diff --git a/.env-sample b/.env-sample index 64d4c94c2..975f32677 100644 --- a/.env-sample +++ b/.env-sample @@ -21,6 +21,8 @@ CACHE_PROVIDER=memory CACHE_DEFAULT_TTL=21600 # redis connection string - e.g redis://user:password@redis-service.com:6379/ CACHE_REDIS_CONNECTION_STRING= +# redis graph expiry timer in seconds +REDIS_GRAPH_TTL=3600 CACHE_GRAPHQL=true diff --git a/API Documentation/Core.swagger_collection.yaml b/API Documentation/Core.swagger_collection.yaml index 8b89c836c..939697e9c 100644 --- a/API Documentation/Core.swagger_collection.yaml +++ b/API Documentation/Core.swagger_collection.yaml @@ -220,6 +220,219 @@ paths: schema: $ref: '#/components/schemas/Generic200Response' deprecated: false + '/containers/{container_id}/data_source_templates': + get: + tags: + - Containers + summary: List Data Source Templates + description: List all Data Source Templates for the container. + operationId: RetrieveContainer + parameters: + - name: container_id + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + value: + type: array + items: + type: object + properties: + id: + type: string + name: + type: string + encrypted: + type: boolean + authorized: + type: boolean + custom_fields: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + encrypt: + type: boolean + required: + type: boolean + redirect_address: + type: string + isError: + type: boolean + x-examples: + Example 1: + value: + - id: 98eb71e9-2556-4309-824b-068be12650c9 + name: P6 + encrypted: true + authorized: false + custom_fields: + - name: encrypted + value: OVTPjwWPZNdAvkkxZseu448ZrrdpjLshMmJZ2BF5HYRobkmb91ZWZimOVwU6VeGT6hc1PABdvMXVHi0nRl7cfw== + encrypt: true + required: true + - name: no value + encrypt: false + required: false + - name: unencrypted + value: unencrypted + redirect_address: 'localhost:8181' + - id: 87da60d8-1445-3298-713a-957ad01549b8 + name: Jazz + encrypted: true + authorized: false + redirect_address: 'localhost:8282' + isError: false + examples: + Example 1: + value: + value: + - id: 98eb71e9-2556-4309-824b-068be12650c9 + name: P6 + encrypted: true + authorized: false + custom_fields: + - name: encrypted + value: OVTPjwWPZNdAvkkxZseu448ZrrdpjLshMmJZ2BF5HYRobkmb91ZWZimOVwU6VeGT6hc1PABdvMXVHi0nRl7cfw== + encrypt: true + required: true + - name: no value + encrypt: false + required: false + - name: unencrypted + value: unencrypted + redirect_address: 'localhost:8181' + - id: 87da60d8-1445-3298-713a-957ad01549b8 + name: Jazz + encrypted: true + authorized: false + redirect_address: 'localhost:8282' + isError: false + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + deprecated: false + parameters: + - schema: + type: string + name: container_id + in: path + required: true + post: + summary: Save Data Source Templates + operationId: post-containers-container_id-data_source_templates + description: Add a new Data Source Template to the container or create a new Data Source Template. + requestBody: + content: + application/json: + schema: + type: array + items: + type: object + properties: + id: + type: string + name: + type: string + redirect_address: + type: string + custom_fields: + type: array + items: + type: object + properties: + name: + type: string + encrypt: + type: boolean + required: + type: boolean + value: + type: string + x-examples: + Example 1: + - id: 98eb71e9-2556-4309-824b-068be12650c9 + name: P6 + redirect_address: 'localhost:8181' + custom_fields: + - name: encrypted + encrypt: true + required: true + value: encrypted + - name: no value + required: false + encrypt: false + - name: unencrypted + value: unencrypted + - id: 87da60d8-1445-3298-713a-957ad01549b8 + name: Jazz + redirect_address: 'localhost:8282' + examples: + Example 1: + value: + - id: 98eb71e9-2556-4309-824b-068be12650c9 + name: P6 + redirect_address: 'localhost:8181' + custom_fields: + - name: encrypted + encrypt: true + required: true + value: encrypted + - name: no value + required: false + encrypt: false + - name: unencrypted + value: unencrypted + - id: 87da60d8-1445-3298-713a-957ad01549b8 + name: Jazz + redirect_address: 'localhost:8282' + '/containers/{container_id}/data_source_templates/{template_id}': + delete: + tags: + - Containers + summary: Delete Data Source Template + description: Deletes a Data Source Template based on its UUID as supplied in the route. + operationId: ArchiveContainer + parameters: + - name: container_id + in: path + required: true + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/Generic200Response' + deprecated: false + parameters: + - schema: + type: string + name: container_id + in: path + required: true + - schema: + type: string + name: template_id + in: path + required: true '/containers/{container_id}/active': post: tags: diff --git a/AdminWebApp/src/api/client.ts b/AdminWebApp/src/api/client.ts index 812990bb7..921164dad 100644 --- a/AdminWebApp/src/api/client.ts +++ b/AdminWebApp/src/api/client.ts @@ -34,6 +34,7 @@ import { TagT, TimeseriesRange, TimeseriesRowCount, + DataSourceTemplateT, } from '@/api/types'; import {RetrieveJWT} from '@/auth/authentication_service'; import {UserT} from '@/auth/types'; @@ -705,6 +706,18 @@ export class Client { return this.post(`/containers/${containerID}/graphs/nodes/edges`, {node_ids: nodeIDS}, query); } + listDataSourceTemplates(containerID: string): Promise { + return this.get(`/containers/${containerID}/data_source_templates`); + } + + saveDataSourceTemplates(containerID: string, templates: any[]): Promise { + return this.post(`/containers/${containerID}/data_source_templates`, templates); + } + + deleteDataSourceTemplate(containerID: string, templateID: string): Promise { + return this.delete(`/containers/${containerID}/data_source_templates/${templateID}`); + } + listDataSources(containerID: string, archived = false, timeseries = false): Promise { // we hardcoded the sortBy to insure we're always getting archived data sources at the bottom of the list return this.get(`/containers/${containerID}/import/datasources`, {archived, sortBy: 'archived', timeseries}); diff --git a/AdminWebApp/src/api/types.ts b/AdminWebApp/src/api/types.ts index f3fae3cc6..f6fffaf7c 100644 --- a/AdminWebApp/src/api/types.ts +++ b/AdminWebApp/src/api/types.ts @@ -94,12 +94,12 @@ export type MetatypeKeyT = { data_type: 'number' | 'number64' | 'float' | 'float64' | 'date' | 'string' | 'boolean' | 'enumeration' | 'file'; archived: boolean; validation: - | { - regex: string; - min: number; - max: number; - } - | undefined; + | { + regex: string; + min: number; + max: number; + } + | undefined; options: string[] | undefined; default_value: string | boolean | number | any[] | undefined; created_at?: string; @@ -237,7 +237,13 @@ export type DataSourceT = { adapter_type: string | undefined; active: boolean; archived?: boolean; - config: StandardDataSourceConfig | HttpDataSourceConfig | AvevaDataSourceConfig | TimeseriesDataSourceConfig | P6DataSourceConfig | undefined; + config: StandardDataSourceConfig + | HttpDataSourceConfig + | AvevaDataSourceConfig + | TimeseriesDataSourceConfig + | P6DataSourceConfig + | CustomDataSourceConfig + | undefined; created_at?: string; modified_at?: string; created_by?: string; @@ -343,6 +349,31 @@ export type P6DataSourceConfig = { raw_retention_enabled?: boolean; }; +export type CustomDataSourceConfig = { + kind: 'custom'; + template: DataSourceTemplateT; + stop_nodes?: string[]; + value_nodes?: string[]; + data_retention_days?: number; + raw_retention_enabled?: boolean; +}; + +export type DataSourceTemplateT = { + id?: string; + name: string; + custom_fields?: CustomTemplateFieldT[]; + redirect_address: string; + authorized?: boolean; + saveable?: boolean; +}; + +export type CustomTemplateFieldT = { + name: string; + value?: string; + encrypt?: boolean; + required?: boolean; +}; + export type EventActionT = { id?: string; container_id?: string; @@ -504,6 +535,7 @@ export type TypeMappingTransformationT = { created_at_key?: string; created_at_format_string?: string; tags?: TypeMappingTransformationTagT[]; + merge?: boolean; }; export type TypeMappingTransformationPayloadT = { @@ -805,3 +837,18 @@ export function DefaultTimeseriesDataSourceConfig(): TimeseriesDataSourceConfig fast_load_enabled: true, }; } + +export function DefaultCustomDataSourceConfig(): CustomDataSourceConfig { + return { + kind: 'custom', + template: DefaultDataSourceTemplate() + }; +} + +export function DefaultDataSourceTemplate(): DataSourceTemplateT { + return { + name: '', + custom_fields: [], + redirect_address: '' + } +} \ No newline at end of file diff --git a/AdminWebApp/src/components/dataSources/CustomAdapterActions.vue b/AdminWebApp/src/components/dataSources/CustomAdapterActions.vue deleted file mode 100644 index e69de29bb..000000000 diff --git a/AdminWebApp/src/components/dataSources/DataSourceActions.vue b/AdminWebApp/src/components/dataSources/DataSourceActions.vue index 6d658f253..24386fea8 100644 --- a/AdminWebApp/src/components/dataSources/DataSourceActions.vue +++ b/AdminWebApp/src/components/dataSources/DataSourceActions.vue @@ -38,7 +38,7 @@ disabled /> - + + + +