diff --git a/server/src/models/analytic_unit_cache_model.ts b/server/src/models/analytic_unit_cache_model.ts index 2a7e28a..9bef173 100644 --- a/server/src/models/analytic_unit_cache_model.ts +++ b/server/src/models/analytic_unit_cache_model.ts @@ -82,6 +82,11 @@ export async function create(id: AnalyticUnitId): Promise { return db.insertOne(cache.toObject()); } +// TODO: SerializedCache type +export async function insertMany(caches: any[]): Promise { + return db.insertMany(caches); +} + export async function setData(id: AnalyticUnitId, data: any) { return db.updateOne(id, { data }); } diff --git a/server/src/models/analytic_units/db.ts b/server/src/models/analytic_units/db.ts index e5a8f6f..c588fda 100644 --- a/server/src/models/analytic_units/db.ts +++ b/server/src/models/analytic_units/db.ts @@ -1,6 +1,6 @@ import { createAnalyticUnitFromObject } from './utils'; import { AnalyticUnit } from './analytic_unit_model'; -import { AnalyticUnitId, FindManyQuery } from './types'; +import { AnalyticUnitId, FindManyQuery, SerializedAnalyticUnit } from './types'; import { Collection, makeDBQ, SortingOrder } from '../../services/data_service'; import { Metric } from 'grafana-datasource-kit'; @@ -41,6 +41,10 @@ export async function create(unit: AnalyticUnit): Promise { return db.insertOne(obj); } +export async function insertMany(analyticUnits: SerializedAnalyticUnit[]): Promise { + return db.insertMany(analyticUnits); +} + export async function remove(id: AnalyticUnitId): Promise { // TODO: remove it`s segments // TODO: remove it`s cache diff --git a/server/src/models/analytic_units/index.ts b/server/src/models/analytic_units/index.ts index 5530817..2b73da0 100644 --- a/server/src/models/analytic_units/index.ts +++ b/server/src/models/analytic_units/index.ts @@ -13,6 +13,7 @@ import { create, remove, update, + insertMany, setStatus, setDetectionTime, setAlert, @@ -26,6 +27,6 @@ export { AnalyticUnitId, AnalyticUnitStatus, Bound, DetectorType, ANALYTIC_UNIT_TYPES, createAnalyticUnitFromObject, Condition, findById, findMany, - create, remove, update, + create, remove, update, insertMany, setStatus, setDetectionTime, setAlert, setMetric }; diff --git a/server/src/models/detection_model.ts b/server/src/models/detection_model.ts index d12bfb1..5b4e76f 100644 --- a/server/src/models/detection_model.ts +++ b/server/src/models/detection_model.ts @@ -109,7 +109,7 @@ export async function findMany(id: AnalyticUnitId, query?: FindManyQuery): Promi // TODO: maybe it could have a better name export async function findByAnalyticUnitIds(analyticUnitIds: AnalyticUnitId[]): Promise { const spans = await db.findMany({ analyticUnitId: { $in: analyticUnitIds } }); - + if(spans === null) { return []; } @@ -162,6 +162,11 @@ export async function insertSpan(span: DetectionSpan): Promise { return db.insertOne(spanToInsert); } +// TODO: SerializedDetectionSpan type +export async function insertMany(detectionSpans: any[]): Promise { + return db.insertMany(detectionSpans); +} + export function clearSpans(analyticUnitId: AnalyticUnitId) { return db.removeMany({ analyticUnitId }); } diff --git a/server/src/models/panel_model.ts b/server/src/models/panel_model.ts new file mode 100644 index 0000000..3317256 --- /dev/null +++ b/server/src/models/panel_model.ts @@ -0,0 +1,17 @@ +import * as AnalyticUnit from './analytic_units'; +import * as AnalyticUnitCache from '../models/analytic_unit_cache_model'; +import * as DetectionSpan from '../models/detection_model'; +import * as Segment from '../models/segment_model'; + +export type PanelTemplate = { + analyticUnits: AnalyticUnit.SerializedAnalyticUnit[], + caches: AnalyticUnitCache.AnalyticUnitCache[], + detectionSpans: DetectionSpan.DetectionSpan[], + segments: Segment.Segment[] +} + +export type TemplateVariables = { + grafanaUrl: string, + panelId: string, + datasourceUrl: string +}; diff --git a/server/src/models/segment_model.ts b/server/src/models/segment_model.ts index c1bf8c9..15e4b96 100644 --- a/server/src/models/segment_model.ts +++ b/server/src/models/segment_model.ts @@ -232,6 +232,11 @@ export async function mergeAndInsertSegments(segments: Segment[]): Promise<{ }; } +// TODO: SerializedSegment type +export async function insertMany(segments: any[]): Promise { + return db.insertMany(segments); +} + export async function setSegmentsDeleted(ids: SegmentId[]) { return db.updateMany(ids, { deleted: true, labeled: false }); } diff --git a/server/src/routes/panel_router.ts b/server/src/routes/panel_router.ts index a867107..e20514f 100644 --- a/server/src/routes/panel_router.ts +++ b/server/src/routes/panel_router.ts @@ -1,18 +1,54 @@ -import { exportPanel } from '../services/export_service'; +import { PanelTemplate, TemplateVariables } from '../models/panel_model'; +import { exportPanel, importPanel } from '../services/export_service'; import * as Router from 'koa-router'; -async function getPanelTemplate(ctx: Router.IRouterContext) { +async function exportPanelTemplate(ctx: Router.IRouterContext) { let panelId = ctx.request.query.panelId; if(panelId === undefined) { throw new Error('Cannot export analytic units with undefined panelId'); } - const json = await exportPanel(panelId); - ctx.response.body = json; + const panelTemplate = await exportPanel(panelId); + ctx.response.body = panelTemplate; +} + +async function importPanelTemplate(ctx: Router.IRouterContext) { + const { panelTemplate, templateVariables } = ctx.request.body as { + panelTemplate: PanelTemplate, + templateVariables: TemplateVariables + }; + + // TODO: move to model + if(panelTemplate.analyticUnits === undefined) { + throw new Error('Cannot import analytic units with undefined analyticUnits'); + } + if(panelTemplate.caches === undefined) { + throw new Error('Cannot import analytic units with undefined caches'); + } + if(panelTemplate.detectionSpans === undefined) { + throw new Error('Cannot import analytic units with undefined detectionSpans'); + } + if(panelTemplate.segments === undefined) { + throw new Error('Cannot import analytic units with undefined segments'); + } + + if(templateVariables.grafanaUrl === undefined) { + throw new Error('Cannot make analytic unit from template with undefined grafanaUrl'); + } + if(templateVariables.panelId === undefined) { + throw new Error('Cannot make analytic unit from template with undefined panelId'); + } + if(templateVariables.datasourceUrl === undefined) { + throw new Error('Cannot make analytic unit from template with undefined datasourceUrl'); + } + + await importPanel(panelTemplate, templateVariables); + ctx.response.status = 200; } export var router = new Router(); -router.get('/template', getPanelTemplate); +router.get('/template', exportPanelTemplate); +router.post('/template', importPanelTemplate); diff --git a/server/src/services/export_service.ts b/server/src/services/export_service.ts index d8264c8..2449228 100644 --- a/server/src/services/export_service.ts +++ b/server/src/services/export_service.ts @@ -1,15 +1,12 @@ +import { PanelTemplate, TemplateVariables } from '../models/panel_model'; + import * as AnalyticUnit from '../models/analytic_units'; import * as AnalyticUnitCache from '../models/analytic_unit_cache_model'; import * as DetectionSpan from '../models/detection_model'; import * as Segment from '../models/segment_model'; -export async function exportPanel(panelId: string): Promise<{ - analyticUnitTemplates: any[], - caches: AnalyticUnitCache.AnalyticUnitCache[], - detectionSpans: DetectionSpan.DetectionSpan[], - segments: Segment.Segment[] -}> { +export async function exportPanel(panelId: string): Promise { const analyticUnits = await AnalyticUnit.findMany({ panelId }); const analyticUnitIds = analyticUnits.map(analyticUnit => analyticUnit.id); const analyticUnitTemplates = analyticUnits.map(analyticUnit => analyticUnit.toTemplate()); @@ -21,9 +18,24 @@ export async function exportPanel(panelId: string): Promise<{ ]); return { - analyticUnitTemplates, + analyticUnits: analyticUnitTemplates, caches, detectionSpans, segments }; } + +export async function importPanel( + panelTemplate: PanelTemplate, + variables: TemplateVariables +): Promise { + panelTemplate.analyticUnits.forEach(analyticUnit => { + analyticUnit.grafanaUrl = variables.grafanaUrl; + analyticUnit.panelId = variables.panelId; + analyticUnit.metric.datasource.url = variables.datasourceUrl; + }); + await AnalyticUnit.insertMany(panelTemplate.analyticUnits); + await AnalyticUnitCache.insertMany(panelTemplate.caches); + await Segment.insertMany(panelTemplate.segments); + await DetectionSpan.insertMany(panelTemplate.detectionSpans); +}