diff --git a/src/api/api.ts b/src/api/api.ts index 86f9e5e8..15b712c7 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -76,6 +76,9 @@ import type { AccessControlResponse, AccessControlUpdateRequest, AccessControlBulkDeployRequest, + CustomResourceBuildRequest, + MicroDomainDeployRequest, + BulkMicroDomainDeployResult, } from "./apiTypes.ts"; import { RestApi } from "./rest/restApi.ts"; import { isVsCode, VSCodeExtensionApi } from "./rest/vscodeExtensionApi.ts"; @@ -167,6 +170,8 @@ export interface Api { revertToSnapshot(chainId: string, snapshotId: string): Promise; + buildCR(request: CustomResourceBuildRequest): Promise; + getLibraryElementByType(type: string): Promise; getDeployments(chainId: string): Promise; @@ -537,6 +542,21 @@ export interface Api { bulkDeployChainsAccessControl( searchRequest: AccessControlBulkDeployRequest[], ): Promise; + + deployToMicroDomain( + request: BulkMicroDomainDeployResult, + ): Promise; + + deploySnapshotsToMicroDomain( + request: MicroDomainDeployRequest, + ): Promise; + + deleteMicroDomain(name: string): Promise; + + deleteSnapshotFromMicroDomain( + name: string, + snapshotId: string, + ): Promise; } export const api: Api = isVsCode ? new VSCodeExtensionApi() : new RestApi(); diff --git a/src/api/apiTypes.ts b/src/api/apiTypes.ts index 15a3ad4a..84a59c66 100644 --- a/src/api/apiTypes.ts +++ b/src/api/apiTypes.ts @@ -265,6 +265,7 @@ export type Deployment = { snapshotId: string; name: string; domain: string; + domainType: DomainType; createdWhen: number; createdBy: User; runtime?: RuntimeStates; @@ -283,8 +284,14 @@ export type EngineDomain = { replicas: number; namespace: string; version?: string; + type: DomainType; }; +export enum DomainType { + NATIVE = "NATIVE", + MICRO = "MICRO", +} + export type ChainLoggingSettings = { fallbackDefault: ChainLoggingProperties; consulDefault?: ChainLoggingProperties; @@ -1241,6 +1248,37 @@ export type AccessControlProperty = { abacParameters?: AbacParameters; }; +export type CustomResourceBuildRequest = { + options: CustomResourceOptions; + chainIds: string[]; +}; + +export type CustomResourceOptions = { + language?: string; + name?: string; + namespace?: string; + container?: ContainerOptions; + monitoring?: MonitoringOptions; + service?: ServiceOptions; + environment?: Record; + resources?: string[]; + serviceAccount?: string; +}; + +export type MonitoringOptions = { + enabled: boolean; + interval: string; +}; + +export type ServiceOptions = { + enabled: boolean; +}; + +export type ContainerOptions = { + image?: string; + imagePoolPolicy?: "Always" | "Never" | "IfNotPresent"; +}; + export type LiveExchange = { exchangeId: string; deploymentId: string; @@ -1317,6 +1355,24 @@ export type BulkDeploymentRequest = { chainIds: string[]; }; +export type MicroDomainDeployRequest = { + name: string; + snapshotIds: string[]; + mode?: DeployMode; +}; + +export type BulkMicroDomainDeployResult = { + domains: string[]; + chainIds: string[]; + snapshotAction: BulkDeploymentSnapshotAction; + mode?: DeployMode; +}; + +export enum DeployMode { + REWRITE = "REWRITE", + APPEND = "APPEND", +} + export type BulkDeploymentResult = { chainId: string; chainName: string; diff --git a/src/api/rest/restApi.ts b/src/api/rest/restApi.ts index 95987b55..ea39f867 100644 --- a/src/api/rest/restApi.ts +++ b/src/api/rest/restApi.ts @@ -66,19 +66,22 @@ import { Element, SystemOperation, SpecApiFile, + CustomResourceBuildRequest, LiveExchange, ContextSystem, IntegrationSystemType, DiagnosticValidation, BulkDeploymentRequest, BulkDeploymentResult, + MicroDomainDeployRequest, + BulkMicroDomainDeployResult, ImportVariablesResult, VariableImportPreview, UsedProperty, AccessControlSearchRequest, AccessControlResponse, AccessControlUpdateRequest, - AccessControlBulkDeployRequest, + AccessControlBulkDeployRequest } from "../apiTypes.ts"; import { Api } from "../api.ts"; import { getFileFromResponse } from "../../misc/download-utils.ts"; @@ -91,7 +94,7 @@ import type { ApiResponse, SecretResponse, SecretWithVariables, - Variable, + Variable } from "../apiTypes.ts"; export class RestApi implements Api { @@ -104,12 +107,12 @@ export class RestApi implements Api { axios.create({ baseURL: gateway, timeout: 2000, - headers: { "content-type": "application/json" }, + headers: { "content-type": "application/json" } }), { maxRequests: 50, - perMilliseconds: 1000, - }, + perMilliseconds: 1000 + } ); registerRestAxiosInstance(this.instance); @@ -142,9 +145,9 @@ export class RestApi implements Api { } } return Promise.reject( - new RestApiError(message, responseCode, responseBody, error), + new RestApiError(message, responseCode, responseBody, error) ); - }, + } ); } @@ -156,22 +159,22 @@ export class RestApi implements Api { serviceName: string, message: string, errorDate: string, - stacktrace?: string, + stacktrace?: string ): ApiError => { return { responseBody: { serviceName, errorMessage: message, errorDate, - stacktrace, - }, + stacktrace + } }; }; private wrapApiResponse = async ( serviceName: string, fallbackMessage: string, - fn: () => Promise, + fn: () => Promise ): Promise> => { try { const data = await fn(); @@ -193,8 +196,8 @@ export class RestApi implements Api { body.serviceName, body.errorMessage, body.errorDate, - body.stackTrace, - ), + body.stackTrace + ) }; } if (e.message) { @@ -203,8 +206,8 @@ export class RestApi implements Api { error: this.toApiError( serviceName, e.message, - new Date().toISOString(), - ), + new Date().toISOString() + ) }; } } @@ -214,15 +217,15 @@ export class RestApi implements Api { error: this.toApiError( serviceName, fallbackMessage, - new Date().toISOString(), - ), + new Date().toISOString() + ) }; } }; private wrapBoolean = async ( fallbackMessage: string, - fn: () => Promise, + fn: () => Promise ): Promise => { try { await fn(); @@ -236,7 +239,7 @@ export class RestApi implements Api { getChains = async (): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains`, + `${this.v1()}/catalog/chains` ); return response.data; }; @@ -251,30 +254,30 @@ export class RestApi implements Api { "Failed to fetch common variables", async () => { const response = await this.instance.get( - `${prefix}/common-variables`, + `${prefix}/common-variables` ); const rawData = response.data; if (rawData && typeof rawData === "object" && !Array.isArray(rawData)) { return Object.entries(rawData as Record).map( ([key, value]) => ({ key, - value: String(value), - }), + value: String(value) + }) ); } throw new Error("Unexpected response format"); - }, + } ); }; createCommonVariable = async ( - variable: Variable, + variable: Variable ): Promise> => { return this.createCommonVariables({ [variable.key]: variable.value }); }; private createCommonVariables = async ( - variables: Record, + variables: Record ): Promise> => { const serviceName = "Common Variables API"; const prefix = `${this.v1()}/variables-management`; @@ -285,15 +288,15 @@ export class RestApi implements Api { async () => { const response = await this.instance.post( `${prefix}/common-variables`, - variables, + variables ); return response.data; - }, + } ); }; updateCommonVariable = async ( - variable: Variable, + variable: Variable ): Promise> => { const serviceName = "Common Variables API"; const prefix = `${this.v1()}/variables-management`; @@ -305,10 +308,10 @@ export class RestApi implements Api { const response = await this.instance.patch( `${prefix}/common-variables/${variable.key}`, variable.value, - { headers: { "Content-Type": "text/plain" } }, + { headers: { "Content-Type": "text/plain" } } ); return response.data; - }, + } ); }; @@ -329,13 +332,13 @@ export class RestApi implements Api { const response = await this.instance.get( `${prefix}/common-variables/export?${params}`, - { responseType: "blob" }, + { responseType: "blob" } ); return getFileFromResponse(response); }; importVariablesPreview = async ( - formData: FormData, + formData: FormData ): Promise> => { const serviceName = "Common Variables API"; if (!formData) { @@ -344,8 +347,8 @@ export class RestApi implements Api { error: this.toApiError( serviceName, "No file selected or form data is empty.", - new Date().toISOString(), - ), + new Date().toISOString() + ) }; } const path = `${this.v1()}/variables-management/common-variables/preview`; @@ -356,15 +359,15 @@ export class RestApi implements Api { const response = await this.instance.post( path, formData, - { headers: { "Content-Type": "multipart/form-data" } }, + { headers: { "Content-Type": "multipart/form-data" } } ); return response.data; - }, + } ); }; importVariables = async ( - formData: FormData, + formData: FormData ): Promise> => { const serviceName = "Common Variables API"; if (!formData) { @@ -373,8 +376,8 @@ export class RestApi implements Api { error: this.toApiError( serviceName, "No file selected or form data is empty.", - new Date().toISOString(), - ), + new Date().toISOString() + ) }; } const path = `${this.v2()}/common-variables/import`; @@ -382,7 +385,7 @@ export class RestApi implements Api { const response = await this.instance.post( path, formData, - { headers: { "Content-Type": "multipart/form-data" } }, + { headers: { "Content-Type": "multipart/form-data" } } ); return response.data; }); @@ -398,24 +401,24 @@ export class RestApi implements Api { "Failed to fetch secured variables", async () => { const response = await this.instance.get( - `${this.v2()}/secured-variables`, + `${this.v2()}/secured-variables` ); return response.data.map( ({ secretName, variablesNames, defaultSecret }) => ({ secretName, variables: variablesNames.map((key: string) => ({ key, - value: "******", + value: "******" })), - isDefaultSecret: defaultSecret, - }), + isDefaultSecret: defaultSecret + }) ); - }, + } ); }; getSecuredVariablesForSecret = async ( - secretName: string, + secretName: string ): Promise> => { const serviceName = "Secured Variables API"; @@ -424,16 +427,16 @@ export class RestApi implements Api { "Failed to fetch variables for secret", async () => { const response = await this.instance.get( - `${this.v2()}/secured-variables/${secretName}`, + `${this.v2()}/secured-variables/${secretName}` ); return response.data.map((key: string) => ({ key, value: "******" })); - }, + } ); }; createSecuredVariables = async ( secretName: string, - variables: Variable[], + variables: Variable[] ): Promise> => { const serviceName = "Secured Variables API"; const keyRegex = /^[a-zA-Z0-9_-]+$/; @@ -444,8 +447,8 @@ export class RestApi implements Api { error: this.toApiError( serviceName, `Invalid key: ${v.key}`, - new Date().toISOString(), - ), + new Date().toISOString() + ) }; } } @@ -455,16 +458,16 @@ export class RestApi implements Api { async () => { await this.instance.post(`${this.v2()}/secured-variables`, { secretName, - variables: Object.fromEntries(variables.map((v) => [v.key, v.value])), + variables: Object.fromEntries(variables.map((v) => [v.key, v.value])) }); return variables; - }, + } ); }; updateSecuredVariables = async ( secretName: string, - variables: Variable[], + variables: Variable[] ): Promise> => { const serviceName = "Secured Variables API"; return this.wrapApiResponse( @@ -473,16 +476,16 @@ export class RestApi implements Api { async () => { await this.instance.patch(`${this.v2()}/secured-variables`, { secretName, - variables: Object.fromEntries(variables.map((v) => [v.key, v.value])), + variables: Object.fromEntries(variables.map((v) => [v.key, v.value])) }); return variables; - }, + } ); }; deleteSecuredVariables = async ( secretName: string, - keys: string[], + keys: string[] ): Promise> => { const serviceName = "Secured Variables API"; return this.wrapApiResponse( @@ -492,10 +495,10 @@ export class RestApi implements Api { const params = new URLSearchParams(); keys.forEach((key) => params.append("variablesNames", key)); await this.instance.delete( - `${this.v2()}/secured-variables/${secretName}?${params}`, + `${this.v2()}/secured-variables/${secretName}?${params}` ); return true; - }, + } ); }; @@ -507,28 +510,28 @@ export class RestApi implements Api { async () => { await this.instance.post(`${this.v2()}/secret/${secretName}`); return true; - }, + } ); }; downloadHelmChart = async (secretName: string): Promise => { const response = await this.instance.get( `${this.v2()}/secret/template/${secretName}`, - { responseType: "blob" }, + { responseType: "blob" } ); return getFileFromResponse(response); }; getChain = async (id: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/${id}`, + `${this.v1()}/catalog/chains/${id}` ); return response.data; }; findChainByElementId = async (elementId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/find-by-element/${elementId}`, + `${this.v1()}/catalog/chains/find-by-element/${elementId}` ); return response.data; }; @@ -536,7 +539,7 @@ export class RestApi implements Api { updateChain = async (id: string, chain: Partial): Promise => { const response = await this.instance.put( `${this.v1()}/catalog/chains/${id}`, - chain, + chain ); return response.data; }; @@ -544,7 +547,7 @@ export class RestApi implements Api { createChain = async (chain: ChainCreationRequest): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/chains`, - chain, + chain ); return response.data; }; @@ -556,13 +559,13 @@ export class RestApi implements Api { deleteChains = async (chainIds: string[]): Promise => { await this.instance.post( `${this.v1()}/catalog/chains/bulk-delete`, - chainIds, + chainIds ); }; duplicateChain = async (chainId: string): Promise => { const response = await this.instance.post( - `${this.v1()}/catalog/chains/${chainId}/duplicate`, + `${this.v1()}/catalog/chains/${chainId}/duplicate` ); return response.data; }; @@ -572,8 +575,8 @@ export class RestApi implements Api { `${this.v1()}/catalog/chains/${chainId}/copy`, null, { - params: { targetFolderId: folderId }, - }, + params: { targetFolderId: folderId } + } ); return response.data; }; @@ -583,8 +586,8 @@ export class RestApi implements Api { `${this.v1()}/catalog/chains/${chainId}/move`, null, { - params: { targetFolderId: folder }, - }, + params: { targetFolderId: folder } + } ); return response.data; }; @@ -593,67 +596,67 @@ export class RestApi implements Api { const response = await this.instance.get( `${this.v1()}/catalog/export`, { - responseType: "blob", - }, + responseType: "blob" + } ); return getFileFromResponse(response); }; exportChains = async ( chainIds: string[], - exportSubchains: boolean, + exportSubchains: boolean ): Promise => { const response = await this.instance.get( `${this.v1()}/catalog/export/chains`, { params: { chainIds, exportWithSubChains: exportSubchains }, paramsSerializer: { - indexes: null, + indexes: null }, - responseType: "blob", - }, + responseType: "blob" + } ); return getFileFromResponse(response); }; getLibrary = async (): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/library`, + `${this.v1()}/catalog/library` ); return response.data; }; getElementTypes = async (): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/library/elements/types`, + `${this.v1()}/catalog/library/elements/types` ); return response.data; }; getElements = async (chainId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/${chainId}/elements`, + `${this.v1()}/catalog/chains/${chainId}/elements` ); return response.data; }; getElementsByType = async ( chainId: string, - elementType: string, + elementType: string ): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/${chainId}/elements/type/${elementType}`, + `${this.v1()}/catalog/chains/${chainId}/elements/type/${elementType}` ); return response.data; }; createElement = async ( elementRequest: CreateElementRequest, - chainId: string, + chainId: string ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/chains/${chainId}/elements`, - elementRequest, + elementRequest ); return response.data; }; @@ -661,36 +664,36 @@ export class RestApi implements Api { updateElement = async ( elementRequest: PatchElementRequest, chainId: string, - elementId: string, + elementId: string ): Promise => { const response = await this.instance.patch( `${this.v1()}/catalog/chains/${chainId}/elements/${elementId}`, - elementRequest, + elementRequest ); return response.data; }; transferElement = async ( transferElementRequest: TransferElementRequest, - chainId: string, + chainId: string ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/chains/${chainId}/elements/transfer`, - transferElementRequest, + transferElementRequest ); return response.data; }; deleteElements = async ( elementIds: string[], - chainId: string, + chainId: string ): Promise => { const elementsIdsParam = elementIds.join(","); const response = await this.instance.delete( `${this.v1()}/catalog/chains/${chainId}/elements`, { - params: { elementsIds: elementsIdsParam }, - }, + params: { elementsIds: elementsIdsParam } + } ); return response.data; }; @@ -698,7 +701,7 @@ export class RestApi implements Api { modifyHttpTriggerProperties = async ( chainId: string, specificationGroupId: string, - httpTriggerIds: string[], + httpTriggerIds: string[] ): Promise => { await this.instance.put( `${this.v1()}/catalog/chains/${chainId}/elements/properties-modification`, @@ -706,70 +709,70 @@ export class RestApi implements Api { { params: { specificationGroupId: specificationGroupId, - httpTriggerIds: httpTriggerIds, + httpTriggerIds: httpTriggerIds }, paramsSerializer: (params) => - qs.stringify(params, { arrayFormat: "repeat" }), - }, + qs.stringify(params, { arrayFormat: "repeat" }) + } ); }; getConnections = async (chainId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/${chainId}/dependencies`, + `${this.v1()}/catalog/chains/${chainId}/dependencies` ); return response.data; }; createConnection = async ( connectionRequest: ConnectionRequest, - chainId: string, + chainId: string ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/chains/${chainId}/dependencies`, - connectionRequest, + connectionRequest ); return response.data; }; deleteConnections = async ( connectionIds: string[], - chainId: string, + chainId: string ): Promise => { const connectionIdsParam = connectionIds.join(","); const response = await this.instance.delete( `${this.v1()}/catalog/chains/${chainId}/dependencies`, { - params: { dependenciesIds: connectionIdsParam }, - }, + params: { dependenciesIds: connectionIdsParam } + } ); return response.data; }; createSnapshot = async (chainId: string): Promise => { const response = await this.instance.post( - `${this.v1()}/catalog/chains/${chainId}/snapshots`, + `${this.v1()}/catalog/chains/${chainId}/snapshots` ); return response.data; }; getSnapshots = async (chainId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/${chainId}/snapshots`, + `${this.v1()}/catalog/chains/${chainId}/snapshots` ); return response.data; }; getSnapshot = async (snapshotId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/chainId/snapshots/${snapshotId}`, + `${this.v1()}/catalog/chains/chainId/snapshots/${snapshotId}` ); return response.data; }; deleteSnapshot = async (snapshotId: string): Promise => { await this.instance.delete( - `${this.v1()}/catalog/chains/chainId/snapshots/${snapshotId}`, + `${this.v1()}/catalog/chains/chainId/snapshots/${snapshotId}` ); }; @@ -779,10 +782,10 @@ export class RestApi implements Api { revertToSnapshot = async ( chainId: string, - snapshotId: string, + snapshotId: string ): Promise => { const response = await this.instance.post( - `${this.v1()}/catalog/chains/${chainId}/snapshots/${snapshotId}/revert`, + `${this.v1()}/catalog/chains/${chainId}/snapshots/${snapshotId}/revert` ); return response.data; }; @@ -790,126 +793,126 @@ export class RestApi implements Api { updateSnapshot = async ( snapshotId: string, name: string, - labels: EntityLabel[], + labels: EntityLabel[] ): Promise => { const response = await this.instance.put( `${this.v1()}/catalog/chains/chainId/snapshots/${snapshotId}`, { name, - labels, - }, + labels + } ); return response.data; }; getLibraryElementByType = async (type: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/library/${type}`, + `${this.v1()}/catalog/library/${type}` ); return response.data; }; getDeployments = async (chainId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/${chainId}/deployments`, + `${this.v1()}/catalog/chains/${chainId}/deployments` ); return response.data; }; createDeployment = async ( chainId: string, - request: CreateDeploymentRequest, + request: CreateDeploymentRequest ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/chains/${chainId}/deployments`, - request, + request ); return response.data; }; deleteDeployment = async (deploymentId: string): Promise => { await this.instance.delete( - `${this.v1()}/catalog/chains/chainId/deployments/${deploymentId}`, + `${this.v1()}/catalog/chains/chainId/deployments/${deploymentId}` ); }; getDomains = async (): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/domains`, + `${this.v1()}/catalog/domains` ); return response.data; }; getLoggingSettings = async ( - chainId: string, + chainId: string ): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/${chainId}/properties/logging`, + `${this.v1()}/catalog/chains/${chainId}/properties/logging` ); return response.data; }; setLoggingProperties = async ( chainId: string, - properties: ChainLoggingProperties, + properties: ChainLoggingProperties ): Promise => { await this.instance.post( `${this.v1()}/catalog/chains/${chainId}/properties/logging`, - properties, + properties ); }; deleteLoggingSettings = async (chainId: string): Promise => { await this.instance.delete( - `${this.v1()}/catalog/chains/${chainId}/properties/logging`, + `${this.v1()}/catalog/chains/${chainId}/properties/logging` ); }; getMaskedFields = async (chainId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/${chainId}/masking`, + `${this.v1()}/catalog/chains/${chainId}/masking` ); return response.data.fields; }; createMaskedField = async ( chainId: string, - maskedField: Partial>, + maskedField: Partial> ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/chains/${chainId}/masking`, - maskedField, + maskedField ); return response.data; }; deleteMaskedFields = async ( chainId: string, - maskedFieldIds: string[], + maskedFieldIds: string[] ): Promise => { await this.instance.post( `${this.v1()}/catalog/chains/${chainId}/masking/field`, - maskedFieldIds, + maskedFieldIds ); }; deleteMaskedField = async ( chainId: string, - maskedFieldId: string, + maskedFieldId: string ): Promise => { await this.instance.delete( - `${this.v1()}/catalog/chains/${chainId}/masking/field/${maskedFieldId}`, + `${this.v1()}/catalog/chains/${chainId}/masking/field/${maskedFieldId}` ); }; updateMaskedField = async ( chainId: string, maskedFieldId: string, - changes: Partial>, + changes: Partial> ): Promise => { const response = await this.instance.put( `${this.v1()}/catalog/chains/${chainId}/masking/field/${maskedFieldId}`, - changes, + changes ); return response.data; }; @@ -917,7 +920,7 @@ export class RestApi implements Api { getSessions = async ( chainId: string | undefined, filters: SessionFilterAndSearchRequest, - paginationOptions: PaginationOptions, + paginationOptions: PaginationOptions ): Promise => { const prefix = `${this.v1()}/sessions-management/sessions`; const url = chainId ? `${prefix}/chains/${chainId}` : prefix; @@ -931,7 +934,7 @@ export class RestApi implements Api { const response = await this.instance.post( url, filters, - { params }, + { params } ); return response.data; }; @@ -939,12 +942,12 @@ export class RestApi implements Api { deleteSessions = async (sessionIds: string[]): Promise => { await this.instance.post( `${this.v1()}/sessions-management/sessions/bulk-delete`, - sessionIds, + sessionIds ); }; deleteSessionsByChainId = async ( - chainId: string | undefined, + chainId: string | undefined ): Promise => { const prefix = `${this.v1()}/sessions-management/sessions`; const url = chainId ? `${prefix}/chains/${chainId}` : prefix; @@ -955,7 +958,7 @@ export class RestApi implements Api { const response = await this.instance.post( `${this.v1()}/sessions-management/sessions/export`, sessionIds, - { responseType: "blob" }, + { responseType: "blob" } ); return getFileFromResponse(response); }; @@ -969,86 +972,86 @@ export class RestApi implements Api { const response = await this.instance.post( `${this.v1()}/sessions-management/sessions/import`, formData, - { headers }, + { headers } ); return response.data; }; retryFromLastCheckpoint = async ( chainId: string, - sessionId: string, + sessionId: string ): Promise => { await this.instance.post( `${this.v1()}/engine/chains/${chainId}/sessions/${sessionId}/retry`, - null, + null ); }; getSession = async (sessionId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/sessions-management/sessions/${sessionId}`, + `${this.v1()}/sessions-management/sessions/${sessionId}` ); return response.data; }; getCheckpointSessions = async ( - sessionIds: string[], + sessionIds: string[] ): Promise => { const response = await this.instance.get( `${this.v1()}/engine/sessions`, { params: { ids: sessionIds }, paramsSerializer: { - indexes: null, - }, - }, + indexes: null + } + } ); return response.data; }; retrySessionFromLastCheckpoint = async ( chainId: string, - sessionId: string, + sessionId: string ): Promise => { return this.instance.post( `${this.v1()}/engine/chains/${chainId}/sessions/${sessionId}/retry`, - null, + null ); }; getFolder = async (folderId: string): Promise => { const response = await this.instance.get( - `${this.v2()}/folders/${folderId}`, + `${this.v2()}/folders/${folderId}` ); return response.data; }; getRootFolders = async ( filter: string, - openedFolderId: string, + openedFolderId: string ): Promise => { const response = await this.instance.get( `${this.v1()}/catalog/folders/`, { params: { filter: filter, - openedFolderId: openedFolderId, - }, - }, + openedFolderId: openedFolderId + } + } ); return response.data; }; getPathToFolder = async (folderId: string): Promise => { const response = await this.instance.get( - `${this.v2()}/folders/${folderId}/path`, + `${this.v2()}/folders/${folderId}/path` ); return response.data; }; getPathToFolderByName = async (folderName: string): Promise => { const response = await this.instance.get( - `${this.v2()}/folders/path?name=${folderName}`, + `${this.v2()}/folders/path?name=${folderName}` ); return response.data; }; @@ -1056,18 +1059,18 @@ export class RestApi implements Api { createFolder = async (request: CreateFolderRequest): Promise => { const response = await this.instance.post( `${this.v2()}/folders`, - request, + request ); return response.data; }; updateFolder = async ( folderId: string, - changes: UpdateFolderRequest, + changes: UpdateFolderRequest ): Promise => { const response = await this.instance.put( `${this.v2()}/folders/${folderId}`, - changes, + changes ); return response.data; }; @@ -1081,62 +1084,62 @@ export class RestApi implements Api { }; listFolder = async ( - request: ListFolderRequest, + request: ListFolderRequest ): Promise<(FolderItem | ChainItem)[]> => { const response = await this.instance.post<(FolderItem | ChainItem)[]>( `${this.v2()}/folders/list`, - request, + request ); return response.data; }; moveFolder = async ( folderId: string, - targetFolderId?: string, + targetFolderId?: string ): Promise => { const request: MoveFolderRequest = { id: folderId, - targetId: targetFolderId, + targetId: targetFolderId }; const response = await this.instance.post( `${this.v2()}/folders/move`, - request, + request ); return response.data; }; getNestedChains = async (folderId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/folders/${folderId}/chains`, + `${this.v1()}/catalog/folders/${folderId}/chains` ); return response.data; }; getServicesUsedByChains = async ( - chainIds: string[], + chainIds: string[] ): Promise => { const response = await this.instance.get( `${this.v1()}/catalog/chains/used-systems`, { params: { chainIds }, paramsSerializer: { - indexes: null, - }, - }, + indexes: null + } + } ); return response.data; }; getChainsUsedByService = async (systemId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/systems/${systemId}`, + `${this.v1()}/catalog/chains/systems/${systemId}` ); return response.data; }; exportServices = async ( serviceIds: string[], - modelIds: string[], + modelIds: string[] ): Promise => { const formData: FormData = new FormData(); if (serviceIds?.length) { @@ -1151,17 +1154,17 @@ export class RestApi implements Api { { headers: { "Content-Type": "multipart/form-data", - accept: "*/*", + accept: "*/*" }, - responseType: "blob", - }, + responseType: "blob" + } ); return getFileFromResponse(response); }; exportSpecifications = async ( specificationIds: string[], - specificationGroupId: string[], + specificationGroupId: string[] ): Promise => { const params: Record = {}; if (specificationIds?.length) { @@ -1175,10 +1178,10 @@ export class RestApi implements Api { { params, headers: { - accept: "*/*", + accept: "*/*" }, - responseType: "blob", - }, + responseType: "blob" + } ); return getFileFromResponse(response); }; @@ -1190,7 +1193,7 @@ export class RestApi implements Api { httpTriggerIds: string[], externalRoutes: boolean, specificationType: ApiSpecificationType, - format: ApiSpecificationFormat, + format: ApiSpecificationFormat ): Promise => { const params: Record = {}; if (deploymentIds?.length) { @@ -1211,10 +1214,10 @@ export class RestApi implements Api { { params: { ...params, externalRoutes, specificationType, format }, headers: { - accept: "*/*", + accept: "*/*" }, - responseType: "blob", - }, + responseType: "blob" + } ); const contentType = ( @@ -1231,7 +1234,7 @@ export class RestApi implements Api { if (e instanceof RestApiError) throw e; throw new RestApiError( "Failed to generate API specification", - response.status, + response.status ); } } @@ -1240,13 +1243,13 @@ export class RestApi implements Api { getServices = async ( modelType: string, - withSpec: boolean, + withSpec: boolean ): Promise => { const response = await this.instance.get( `${this.v1()}/systems-catalog/systems`, { - params: { modelType, withSpec }, - }, + params: { modelType, withSpec } + } ); return response.data; }; @@ -1254,18 +1257,18 @@ export class RestApi implements Api { createService = async (system: SystemRequest): Promise => { const response = await this.instance.post( `${this.v1()}/systems-catalog/systems`, - system, + system ); return response.data; }; createEnvironment = async ( systemId: string, - envRequest: EnvironmentRequest, + envRequest: EnvironmentRequest ): Promise => { const response = await this.instance.post( `${this.v1()}/systems-catalog/systems/${systemId}/environments`, - envRequest, + envRequest ); return response.data; }; @@ -1273,27 +1276,27 @@ export class RestApi implements Api { updateEnvironment = async ( systemId: string, environmentId: string, - envRequest: EnvironmentRequest, + envRequest: EnvironmentRequest ): Promise => { const response = await this.instance.put( `${this.v1()}/systems-catalog/systems/${systemId}/environments/${environmentId}`, - envRequest, + envRequest ); return response.data; }; deleteEnvironment = async ( systemId: string, - environmentId: string, + environmentId: string ): Promise => { await this.instance.delete( - `${this.v1()}/systems-catalog/systems/${systemId}/environments/${environmentId}`, + `${this.v1()}/systems-catalog/systems/${systemId}/environments/${environmentId}` ); }; deleteService = async (serviceId: string): Promise => { await this.instance.delete( - `${this.v1()}/systems-catalog/systems/${serviceId}`, + `${this.v1()}/systems-catalog/systems/${serviceId}` ); }; @@ -1306,9 +1309,9 @@ export class RestApi implements Api { { headers: { "Content-Type": "multipart/form-data", - accept: "*/*", - }, - }, + accept: "*/*" + } + } ); return response.data; }; @@ -1316,7 +1319,7 @@ export class RestApi implements Api { commitImport = async ( file: File, request?: ImportRequest, - validateByHash?: boolean, + validateByHash?: boolean ): Promise => { const formData: FormData = new FormData(); formData.append("file", file, file.name); @@ -1332,16 +1335,16 @@ export class RestApi implements Api { { headers: { "Content-Type": "multipart/form-data", - accept: "*/*", - }, - }, + accept: "*/*" + } + } ); return response.data; }; getImportStatus = async (importId: string): Promise => { const response = await this.instance.get( - `${this.v3()}/import/${importId}`, + `${this.v3()}/import/${importId}` ); return response.data; }; @@ -1351,95 +1354,95 @@ export class RestApi implements Api { `${this.v1()}/catalog/events`, { params: { - lastEventId: lastEventId, - }, - }, + lastEventId: lastEventId + } + } ); return response.data; }; getDeploymentsByEngine = async ( domain: string, - engineHost: string, + engineHost: string ): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/domains/${domain}/engines/${engineHost}/deployments`, + `${this.v1()}/catalog/domains/${domain}/engines/${engineHost}/deployments` ); return response.data; }; getEnginesByDomain = async (domain: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/domains/${domain}/engines`, + `${this.v1()}/catalog/domains/${domain}/engines` ); return response.data; }; loadCatalogActionsLog = async ( - searchRequest: ActionLogSearchRequest, + searchRequest: ActionLogSearchRequest ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/actions-log`, - searchRequest, + searchRequest ); return response.data; }; exportCatalogActionsLog = async ( - params: LogExportRequestParams, + params: LogExportRequestParams ): Promise => { const response = await this.instance.get( `${this.v1()}/catalog/actions-log/export`, { responseType: "blob", - params, - }, + params + } ); return response.data; }; getContextServices = async (): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/context-system`, + `${this.v1()}/catalog/context-system` ); const result = response.data; response.data.map( - (system) => (system.type = IntegrationSystemType.CONTEXT), + (system) => (system.type = IntegrationSystemType.CONTEXT) ); return result; }; getContextService = async (id: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/context-system/${id}`, + `${this.v1()}/catalog/context-system/${id}` ); return response.data; }; createContextService = async ( - system: Pick, + system: Pick ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/context-system`, - system, + system ); return response.data; }; updateContextService = async ( id: string, - data: Partial, + data: Partial ): Promise => { const response = await this.instance.put( `${this.v1()}/catalog/context-system/${id}`, - data, + data ); return response.data; }; deleteContextService = async (serviceId: string): Promise => { await this.instance.delete( - `${this.v1()}/catalog/context-system/${serviceId}`, + `${this.v1()}/catalog/context-system/${serviceId}` ); }; @@ -1454,108 +1457,108 @@ export class RestApi implements Api { { headers: { "Content-Type": "multipart/form-data", - accept: "*/*", + accept: "*/*" }, - responseType: "blob", - }, + responseType: "blob" + } ); return getFileFromResponse(response); }; getService = async (id: string): Promise => { const response = await this.instance.get( - `${this.v1()}/systems-catalog/systems/${id}`, + `${this.v1()}/systems-catalog/systems/${id}` ); return response.data; }; updateService = async ( id: string, - data: Partial, + data: Partial ): Promise => { const response = await this.instance.put( `${this.v1()}/systems-catalog/systems/${id}`, - data, + data ); return response.data; }; getEnvironment = async ( systemId: string, - environmentId: string, + environmentId: string ): Promise => { const response = await this.instance.get( - `/api/v1/${getAppName()}/systems-catalog/systems/${systemId}/environments/${environmentId}`, + `/api/v1/${getAppName()}/systems-catalog/systems/${systemId}/environments/${environmentId}` ); return response.data; }; getEnvironments = async (systemId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/systems-catalog/systems/${systemId}/environments`, + `${this.v1()}/systems-catalog/systems/${systemId}/environments` ); return response.data; }; getApiSpecifications = async ( - systemId: string, + systemId: string ): Promise => { const response = await this.instance.get( `${this.v1()}/systems-catalog/specificationGroups`, { params: { - systemId: systemId, - }, - }, + systemId: systemId + } + } ); return response.data; }; getLatestApiSpecification = async ( - systemId: string, + systemId: string ): Promise => { const response = await this.instance.get( `${this.v1()}/systems-catalog/models/latest`, { params: { - systemId: systemId, - }, - }, + systemId: systemId + } + } ); return response.data; }; updateApiSpecificationGroup = async ( id: string, - data: Partial, + data: Partial ): Promise => { const response = await this.instance.patch( `${this.v1()}/systems-catalog/specificationGroups/${id}`, - data, + data ); return response.data; }; deleteSpecificationGroup = async (id: string): Promise => { await this.instance.delete( - `${this.v1()}/systems-catalog/specificationGroups/${id}`, + `${this.v1()}/systems-catalog/specificationGroups/${id}` ); }; updateSpecificationModel = async ( id: string, - data: Partial, + data: Partial ): Promise => { const response = await this.instance.patch( `${this.v1()}/systems-catalog/models/${id}`, - data, + data ); return response.data; }; getSpecificationModelSource = async (id: string): Promise => { const response = await this.instance.get( - `${this.v1()}/systems-catalog/models/${id}/source`, + `${this.v1()}/systems-catalog/models/${id}/source` ); return response.data; }; @@ -1566,16 +1569,16 @@ export class RestApi implements Api { getSpecificationModel = async ( systemId?: string, - specificationGroupId?: string, + specificationGroupId?: string ): Promise => { const response = await this.instance.get( `${this.v1()}/systems-catalog/models`, { params: { systemId: systemId, - specificationGroupId: specificationGroupId, - }, - }, + specificationGroupId: specificationGroupId + } + } ); return response.data; }; @@ -1585,15 +1588,15 @@ export class RestApi implements Api { `${this.v1()}/systems-catalog/models/deprecated`, modelId, { - headers: { "Content-Type": "text/plain" }, - }, + headers: { "Content-Type": "text/plain" } + } ); return response.data; }; getOperations = async ( modelId: string, - paginationOptions: PaginationOptions = {}, + paginationOptions: PaginationOptions = {} ): Promise => { const params: Record = { modelId }; @@ -1606,14 +1609,14 @@ export class RestApi implements Api { const response = await this.instance.get( `${this.v1()}/systems-catalog/operations`, - { params }, + { params } ); return response.data; }; getOperationInfo = async (operationId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/systems-catalog/operations/${encodeURIComponent(operationId)}/info`, + `${this.v1()}/systems-catalog/operations/${encodeURIComponent(operationId)}/info` ); return response.data; }; @@ -1625,7 +1628,7 @@ export class RestApi implements Api { deployLabel?: string, packageName?: string, packageVersion?: string, - packagePartOf?: string, + packagePartOf?: string ): Promise => { const formData = new FormData(); formData.append("file", file); @@ -1652,29 +1655,29 @@ export class RestApi implements Api { { headers: { ...headers, - "Content-Type": "multipart/form-data", - }, - }, + "Content-Type": "multipart/form-data" + } + } ); return response.data; }; importSpecification = async ( specificationGroupId: string, - files: File[], + files: File[] ): Promise => { const formData = new FormData(); files.forEach((file) => formData.append("files", file)); const params: Record = { - specificationGroupId: specificationGroupId, + specificationGroupId: specificationGroupId }; const response = await this.instance.post( `${this.v1()}/systems-catalog/import`, formData, { params, - headers: { "Content-Type": "multipart/form-data" }, - }, + headers: { "Content-Type": "multipart/form-data" } + } ); return response.data; }; @@ -1683,13 +1686,13 @@ export class RestApi implements Api { systemId: string, name: string, files: File[], - protocol?: string, + protocol?: string ): Promise => { const formData: FormData = new FormData(); files.forEach((file) => formData.append("files", file, file.name)); const params: Record = { systemId: systemId, - name: name, + name: name }; if (protocol) params.protocol = protocol; const response = await this.instance.post( @@ -1697,51 +1700,51 @@ export class RestApi implements Api { formData, { params, - headers: { "Content-Type": "multipart/form-data" }, - }, + headers: { "Content-Type": "multipart/form-data" } + } ); return response.data; }; getImportSpecificationResult = async ( - importId: string, + importId: string ): Promise => { const response = await this.instance.get( - `${this.v1()}/systems-catalog/import/${importId}`, + `${this.v1()}/systems-catalog/import/${importId}` ); return response.data; }; getDetailedDesignTemplates = async ( - includeContent: boolean, + includeContent: boolean ): Promise => { const response = await this.instance.get( `${this.v1()}/catalog/detailed-design/templates`, { params: { - includeContent, - }, - }, + includeContent + } + } ); return response.data; }; getDetailedDesignTemplate = async ( - templateId: string, + templateId: string ): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/detailed-design/templates/${templateId}`, + `${this.v1()}/catalog/detailed-design/templates/${templateId}` ); return response.data; }; createOrUpdateDetailedDesignTemplate = async ( name: string, - content: string, + content: string ): Promise => { const response = await this.instance.put( `${this.v1()}/catalog/detailed-design/templates`, - { name, content }, + { name, content } ); return response.data; }; @@ -1751,36 +1754,36 @@ export class RestApi implements Api { `${this.v1()}/catalog/detailed-design/templates`, { params: { - ids, - }, - }, + ids + } + } ); }; getChainDetailedDesign = async ( chainId: string, - templateId: string, + templateId: string ): Promise => { const response = await this.instance.get( `${this.v1()}/catalog/detailed-design/chains/${chainId}`, { params: { - templateId, - }, - }, + templateId + } + } ); return response.data; }; getChainSequenceDiagram = async ( chainId: string, - diagramModes: DiagramMode[], + diagramModes: DiagramMode[] ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/design-generator/chains/${chainId}`, { - diagramModes, - }, + diagramModes + } ); return response.data; }; @@ -1788,13 +1791,13 @@ export class RestApi implements Api { getSnapshotSequenceDiagram = async ( chainId: string, snapshotId: string, - diagramModes: DiagramMode[], + diagramModes: DiagramMode[] ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/design-generator/chains/${chainId}/snapshots/${snapshotId}`, { - diagramModes, - }, + diagramModes + } ); return response.data; }; @@ -1806,28 +1809,28 @@ export class RestApi implements Api { readSpecificationFileContent = (): Promise => { return Promise.reject( new Error( - "Method readSpecificationFileContent not implemented in RestApi", - ), + "Method readSpecificationFileContent not implemented in RestApi" + ) ); }; groupElements = async ( chainId: string, - elementIds: string[], + elementIds: string[] ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/chains/${chainId}/elements/groups`, - elementIds, + elementIds ); return response.data; }; ungroupElements = async ( chainId: string, - groupId: string, + groupId: string ): Promise => { const response = await this.instance.delete( - `${this.v1()}/catalog/chains/${chainId}/elements/groups/${groupId}`, + `${this.v1()}/catalog/chains/${chainId}/elements/groups/${groupId}` ); return response.data; }; @@ -1837,9 +1840,9 @@ export class RestApi implements Api { `${this.v1()}/catalog/live-exchanges`, { params: { - limit: limit, - }, - }, + limit: limit + } + } ); return response.status === 204 ? [] : response.data; }; @@ -1847,10 +1850,10 @@ export class RestApi implements Api { terminateExchange = async ( podIp: string, deploymentId: string, - exchangeId: string, + exchangeId: string ): Promise => { await this.instance.delete( - `${this.v1()}/catalog/live-exchanges/${podIp}/${deploymentId}/${exchangeId}`, + `${this.v1()}/catalog/live-exchanges/${podIp}/${deploymentId}/${exchangeId}` ); }; @@ -1860,20 +1863,28 @@ export class RestApi implements Api { getValidations = async ( filters: EntityFilterModel[], - searchString: string, + searchString: string ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/diagnostic/validations`, - { searchString, filters }, + { searchString, filters } + ); + return response.data; + }; + + buildCR = async (request: CustomResourceBuildRequest): Promise => { + const response = await this.instance.post( + `${this.v1()}/catalog/cr`, + request ); return response.data; }; getValidation = async ( - validationId: string, + validationId: string ): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/diagnostic/validations/${validationId}`, + `${this.v1()}/catalog/diagnostic/validations/${validationId}` ); return response.data; }; @@ -1883,58 +1894,93 @@ export class RestApi implements Api { `${this.v1()}/catalog/diagnostic/validations`, undefined, { - params: { validationIds: ids }, - }, + params: { validationIds: ids } + } ); }; bulkDeploy = async ( - request: BulkDeploymentRequest, + request: BulkDeploymentRequest ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/chains/deployments/bulk`, - request, + request ); return response.data; }; getUsedProperties = async (chainId: string): Promise => { const response = await this.instance.get( - `${this.v1()}/catalog/chains/${chainId}/elements/properties/used`, + `${this.v1()}/catalog/chains/${chainId}/elements/properties/used` ); return response.data; }; loadHttpTriggerAccessControl = async ( - searchRequest: AccessControlSearchRequest, + searchRequest: AccessControlSearchRequest ): Promise => { const response = await this.instance.post( `${this.v1()}/catalog/chains/roles`, - searchRequest, + searchRequest ); return response.data; }; updateHttpTriggerAccessControl = async ( - searchRequest: AccessControlUpdateRequest[], + searchRequest: AccessControlUpdateRequest[] ): Promise => { const response = await this.instance.put( `${this.v1()}/catalog/chains/roles`, - searchRequest, + searchRequest ); return response.data; }; bulkDeployChainsAccessControl = async ( - searchRequest: AccessControlBulkDeployRequest[], + searchRequest: AccessControlBulkDeployRequest[] ): Promise => { const response = await this.instance.put( `${this.v1()}/catalog/chains/roles/redeploy`, - searchRequest, + searchRequest ); return response.data; }; + + deployToMicroDomain = async ( + request: BulkMicroDomainDeployResult + ): Promise => { + const response = await this.instance.post( + `${this.v1()}/catalog/cr/deploy-chains`, + request + ); + return response.data; + }; + + deploySnapshotsToMicroDomain = async ( + request: MicroDomainDeployRequest + ): Promise => { + const response = await this.instance.post( + `${this.v1()}/catalog/cr/deploy`, + request + ); + return response.data; + }; + + deleteMicroDomain = async (name: string): Promise => { + await this.instance.delete( + `${this.v1()}/catalog/cr/${name}` + ); + }; + + deleteSnapshotFromMicroDomain = async ( + name: string, + chainId: string + ): Promise => { + await this.instance.delete( + `${this.v1()}/catalog/cr/${name}/${chainId}` + ); + }; } diff --git a/src/api/rest/vscodeExtensionApi.ts b/src/api/rest/vscodeExtensionApi.ts index aea6111c..c968d41e 100644 --- a/src/api/rest/vscodeExtensionApi.ts +++ b/src/api/rest/vscodeExtensionApi.ts @@ -918,6 +918,10 @@ export class VSCodeExtensionApi implements Api { throw new Error("Method moveFolder not implemented."); } + buildCR(): Promise { + throw new Error("Method buildCR not implemented."); + } + getSpecApiFiles = async (): Promise => { return ( (await this.sendMessageToExtension("getSpecApiFiles")).payload @@ -1070,6 +1074,18 @@ export class VSCodeExtensionApi implements Api { getUsedProperties(_chainId: string): Promise { throw new Error("Method loadHttpTriggerAccessControl not implemented."); } + deployToMicroDomain(): Promise { + throw new Error("Method deployToMicroDomain not implemented."); + } + deploySnapshotsToMicroDomain(): Promise { + throw new Error("Method deploySnapshotsToMicroDomain not implemented."); + } + deleteMicroDomain(): Promise { + throw new Error("Method deleteMicroDomain not implemented."); + } + deleteSnapshotFromMicroDomain(): Promise { + throw new Error("Method deleteSnapshotFromMicroDomain not implemented."); + } } interface VSCodeApi { diff --git a/src/components/SelectDomains.tsx b/src/components/SelectDomains.tsx new file mode 100644 index 00000000..9c506d08 --- /dev/null +++ b/src/components/SelectDomains.tsx @@ -0,0 +1,65 @@ +import React, { useCallback } from "react"; +import { Select, Space, Tag } from "antd"; +import { useDomains } from "../hooks/useDomains.tsx"; +import { LabelInValueType } from "rc-select/lib/Select"; +import type { FlattenOptionData } from "rc-select/lib/interface"; +import { DomainType, EngineDomain } from "../api/apiTypes.ts"; + +export type Domain = { + name: string; + type: DomainType; +}; + +export type SelectDomainsProperties = { + value?: Domain[]; + onChange?: (value: Domain[]) => void; +}; + +function getDomainType( + domainId: string, + domains: EngineDomain[], +): DomainType { + return ( + domains.find((domain) => domainId === domain.id)?.type ?? DomainType.MICRO + ); +} + +export const SelectDomains: React.FC = ({ + value, + onChange, +}) => { + const { isLoading: isDomainsLoading, domains } = useDomains(); + + const renderOption = useCallback( + (props: LabelInValueType | FlattenOptionData) => { + const domainType = getDomainType(props.value?.toString() ?? "", domains); + return domainType === DomainType.MICRO ? ( + + micro + {props.value} + + ) : ( + props.label + ); + }, + [domains], + ); + + return ( + + ); +}; diff --git a/src/components/admin_tools/domains/DomainsTable.tsx b/src/components/admin_tools/domains/DomainsTable.tsx index 96b9f360..80141fd6 100644 --- a/src/components/admin_tools/domains/DomainsTable.tsx +++ b/src/components/admin_tools/domains/DomainsTable.tsx @@ -1,10 +1,13 @@ -import React from "react"; -import { Table, Button, Typography } from "antd"; +import React, { useCallback, useEffect, useState } from "react"; +import { Table, Button, Typography, Space, Tag } from "antd"; import type { ColumnsType } from "antd/es/table"; import { EngineTable } from "./EngineTable"; import { useEngines } from "./hooks/useEngines"; import tableStyles from "./Tables.module.css"; -import { EngineDomain } from "../../../api/apiTypes.ts"; +import { DomainType, EngineDomain } from "../../../api/apiTypes.ts"; +import { OverridableIcon } from "../../../icons/IconProvider.tsx"; +import { useNotificationService } from "../../../hooks/useNotificationService.tsx"; +import { api } from "../../../api/api.ts"; interface Props { domains: EngineDomain[]; @@ -33,11 +36,49 @@ const EnginesForDomain: React.FC<{ domain: EngineDomain }> = ({ domain }) => { }; const DomainsTable: React.FC = ({ domains, isLoading = false }) => { + const notificationsService = useNotificationService(); + const [tableData, setTableData] = useState([]); + + useEffect(() => { + setTableData(domains); + }, [domains]); + + const deleteMicroDomain = useCallback( + async (name: string) => { + try { + await api.deleteMicroDomain(name); + setTableData((items) => items.filter((domain) => domain.name !== name)); + } catch (e) { + notificationsService.requestFailed( + `Failed to delete micro domain ${name}`, + e, + ); + } + }, + [notificationsService], + ); + const columns: ColumnsType = [ { title: Domain, dataIndex: "name", key: "name", + render: (_: unknown, domain: EngineDomain) => { + return domain.type === DomainType.MICRO ? ( + + {domain.name} + micro +