Skip to content

Commit f2dd6a5

Browse files
committed
add query services
1 parent b704492 commit f2dd6a5

File tree

4 files changed

+288
-1
lines changed

4 files changed

+288
-1
lines changed

client/packages/lowcoder/src/pages/setting/environments/services/enterprise.service.ts

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import axios from "axios";
22
import { message } from "antd";
33
import { ManagedOrg } from "../types/enterprise.types";
4+
import { Query } from "../types/query.types";
5+
46

57
/**
68
* Fetch workspaces for a specific environment
@@ -185,4 +187,93 @@ export const unconnectManagedDataSource = async (
185187
console.error("Error disconnecting managed data source:", error);
186188
throw error;
187189
}
188-
};
190+
};
191+
192+
193+
194+
195+
export async function getManagedQueries(environmentId: string): Promise<Query[]> {
196+
try {
197+
if (!environmentId) {
198+
throw new Error('Environment ID is required');
199+
}
200+
201+
// Get managed queries from the enterprise endpoint
202+
const response = await axios.get(`/api/plugins/enterprise/qlQuery/list`, {
203+
params: {
204+
environmentId
205+
}
206+
});
207+
208+
if (!response.data || !Array.isArray(response.data)) {
209+
return [];
210+
}
211+
212+
// Map the response to match our Query interface
213+
// Note: You may need to adjust this mapping based on the actual response structure
214+
return response.data.map((item: any) => ({
215+
id: item.id || item.qlQueryId,
216+
gid: item.qlQueryGid,
217+
name: item.qlQueryName,
218+
organizationId: item.orgId,
219+
libraryQueryDSL: item.libraryQueryDSL || {},
220+
createTime: item.createTime,
221+
creatorName: item.creatorName || '',
222+
managed: true // These are managed queries
223+
}));
224+
225+
} catch (error) {
226+
const errorMessage = error instanceof Error ? error.message : 'Failed to fetch managed queries';
227+
message.error(errorMessage);
228+
throw error;
229+
}
230+
}
231+
232+
233+
export async function connectManagedQuery(
234+
environmentId: string,
235+
queryName: string,
236+
queryGid: string
237+
): Promise<boolean> {
238+
try {
239+
if (!environmentId || !queryGid) {
240+
throw new Error('Environment ID and Query GID are required');
241+
}
242+
243+
const response = await axios.post('/api/plugins/enterprise/qlQuery', {
244+
environment_id: environmentId,
245+
ql_query_name: queryName,
246+
ql_query_tags: [],
247+
ql_query_gid: queryGid
248+
});
249+
250+
return response.status === 200;
251+
252+
} catch (error) {
253+
const errorMessage = error instanceof Error ? error.message : 'Failed to connect query';
254+
message.error(errorMessage);
255+
throw error;
256+
}
257+
}
258+
259+
260+
export async function unconnectManagedQuery(queryGid: string): Promise<boolean> {
261+
try {
262+
if (!queryGid) {
263+
throw new Error('Query GID is required');
264+
}
265+
266+
const response = await axios.delete(`/api/plugins/enterprise/qlQuery`, {
267+
params: {
268+
qlQueryGid: queryGid
269+
}
270+
});
271+
272+
return response.status === 200;
273+
274+
} catch (error) {
275+
const errorMessage = error instanceof Error ? error.message : 'Failed to disconnect query';
276+
message.error(errorMessage);
277+
throw error;
278+
}
279+
}

client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Workspace } from "../types/workspace.types";
55
import { UserGroup } from "../types/userGroup.types";
66
import {App} from "../types/app.types";
77
import { DataSourceWithMeta } from '../types/datasource.types';
8+
import { Query, QueryResponse } from "../types/query.types";
89

910

1011
/**
@@ -335,4 +336,88 @@ export async function getWorkspaceDataSources(
335336
message.error(errorMessage);
336337
throw error;
337338
}
339+
}
340+
341+
342+
343+
/**
344+
* Fetch queries for a specific workspace
345+
* @param workspaceId - ID of the workspace (orgId)
346+
* @param apiKey - API key for the environment
347+
* @param apiServiceUrl - API service URL for the environment
348+
* @param options - Additional options (name filter, pagination)
349+
* @returns Promise with an array of queries and metadata
350+
*/
351+
export async function getWorkspaceQueries(
352+
workspaceId: string,
353+
apiKey: string,
354+
apiServiceUrl: string,
355+
options: {
356+
name?: string;
357+
pageNum?: number;
358+
pageSize?: number;
359+
} = {}
360+
): Promise<{ queries: Query[], total: number }> {
361+
try {
362+
// Check if required parameters are provided
363+
if (!workspaceId) {
364+
throw new Error('Workspace ID is required');
365+
}
366+
367+
if (!apiKey) {
368+
throw new Error('API key is required to fetch queries');
369+
}
370+
371+
if (!apiServiceUrl) {
372+
throw new Error('API service URL is required to fetch queries');
373+
}
374+
375+
// Set up headers with the Bearer token format
376+
const headers = {
377+
Authorization: `Bearer ${apiKey}`
378+
};
379+
380+
// Prepare query parameters
381+
const params: any = {
382+
orgId: workspaceId
383+
};
384+
385+
// Add optional parameters if provided
386+
if (options.name) params.name = options.name;
387+
if (options.pageNum !== undefined) params.pageNum = options.pageNum;
388+
if (options.pageSize !== undefined) params.pageSize = options.pageSize;
389+
390+
// Make the API request to get queries
391+
const response = await axios.get<QueryResponse>(`${apiServiceUrl}/api/library-queries/listByOrg`, {
392+
headers,
393+
params
394+
});
395+
396+
// Check if response is valid
397+
if (!response.data || !response.data.success === false) {
398+
return { queries: [], total: 0 };
399+
}
400+
401+
// Map the response to include id field required by DeployableItem
402+
const queries = response.data.data.map(query => ({
403+
...query,
404+
// Map to DeployableItem fields if not already present
405+
id: query.id,
406+
name: query.name,
407+
managed: false // Default to unmanaged
408+
}));
409+
410+
console.log("queries",queries);
411+
412+
return {
413+
queries,
414+
total: response.data.total
415+
};
416+
417+
} catch (error) {
418+
// Handle and transform error
419+
const errorMessage = error instanceof Error ? error.message : 'Failed to fetch queries';
420+
message.error(errorMessage);
421+
throw error;
422+
}
338423
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Get merged queries (both regular and managed) for a workspace
3+
*/
4+
import { getManagedQueries } from './enterprise.service';
5+
import { getWorkspaceQueries } from './environments.service';
6+
import { Query } from '../types/query.types';
7+
export interface MergedQueriesResult {
8+
queries: Query[];
9+
stats: {
10+
total: number;
11+
managed: number;
12+
unmanaged: number;
13+
};
14+
}
15+
16+
export async function getMergedWorkspaceQueries(
17+
workspaceId: string,
18+
environmentId: string,
19+
apiKey: string,
20+
apiServiceUrl: string
21+
): Promise<MergedQueriesResult> {
22+
try {
23+
// Fetch both regular and managed queries
24+
const [regularQueries, managedQueries] = await Promise.all([
25+
getWorkspaceQueries(workspaceId, apiKey, apiServiceUrl),
26+
getManagedQueries(environmentId)
27+
]);
28+
29+
// Create a map of managed queries by GID for quick lookup
30+
const managedQueryGids = new Set(managedQueries.map(query => query.gid));
31+
32+
// Mark regular queries as managed if they exist in managed queries
33+
const mergedQueries = regularQueries.queries.map((query: Query ) => ({
34+
...query,
35+
managed: managedQueryGids.has(query.gid)
36+
}));
37+
38+
// Calculate stats
39+
const total = mergedQueries.length;
40+
const managed = mergedQueries.filter(query => query.managed).length;
41+
42+
return {
43+
queries: mergedQueries,
44+
stats: {
45+
total,
46+
managed,
47+
unmanaged: total - managed
48+
}
49+
};
50+
51+
} catch (error) {
52+
throw error;
53+
}
54+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// types/query.types.ts
2+
import { DeployableItem } from './deployable-item.types';
3+
4+
export interface LibraryQueryDSL {
5+
query: {
6+
compType: string;
7+
comp: {
8+
bodyType: string;
9+
body: string;
10+
httpMethod: string;
11+
path: string;
12+
headers: Array<{ key: string; value: string }>;
13+
params: Array<{ key: string; value: string }>;
14+
bodyFormData: Array<{ key: string; value: string; type: string }>;
15+
};
16+
id: string;
17+
name: string;
18+
order: number;
19+
datasourceId: string;
20+
triggerType: string;
21+
onEvent: any[];
22+
notification: {
23+
showSuccess: boolean;
24+
showFail: boolean;
25+
fail: any[];
26+
};
27+
timeout: string;
28+
confirmationModal: any;
29+
variables: any[];
30+
periodic: boolean;
31+
periodicTime: string;
32+
cancelPrevious: boolean;
33+
depQueryName: string;
34+
delayTime: string;
35+
};
36+
}
37+
38+
export interface Query extends DeployableItem {
39+
id: string;
40+
gid: string;
41+
organizationId: string;
42+
name: string;
43+
libraryQueryDSL: LibraryQueryDSL;
44+
createTime: number;
45+
creatorName: string;
46+
managed?: boolean;
47+
}
48+
49+
export interface QueryResponse {
50+
code: number;
51+
message: string;
52+
data: Query[];
53+
pageNum: number;
54+
pageSize: number;
55+
total: number;
56+
success: boolean;
57+
}

0 commit comments

Comments
 (0)