import { Injectable, Logger } from '@nestjs/common'; import { Dashboards as DashboardsDb } from '../couchdb-datasources/dashboards'; import * as DashboardModel from '../models/dashboard'; import nano from 'nano'; import { randomUUID } from 'crypto'; import { createAppError } from '../utils/result'; @Injectable() export class DashboardsService { private logger = new Logger(DashboardsService.name); constructor(private db: DashboardsDb) {} async create(): Promise { const id = randomUUID(); this.logger.debug(`Create new dashboard with id - ${id}`); if (await this.isExists(id)) { const err = createAppError('ALREADY_EXISTS'); this.logger.error(`Error - ${JSON.stringify(err)}`); throw err; } const ds = await this.db.getDatasource(); const doc: nano.MaybeDocument & DashboardModel.Dashboard = { _id: id, id: id, data: null, }; await ds.insert(doc); return await ds.get(id); } async loadRawData( id: string, ): Promise { this.logger.debug(`Load raw data, dashboard id - ${id}`); const ds = await this.db.getDatasource(); if (!(await this.isExists(id))) throw createAppError('NOT_EXISTS'); const res = await ds.get(id); return res; } async load(id: string): Promise { this.logger.debug(`Load dashboard id - ${id}`); const rawData = await this.loadRawData(id); return rawData?.data || { widgets: [] }; } async isExists(id: string): Promise { const ds = await this.db.getDatasource(); try { await ds.get(id); return true; } catch (ex) { return false; } } async save(id: string, data: DashboardModel.Data): Promise { this.logger.debug( `Save dashboard id - ${id}, data - ${JSON.stringify(data)}`, ); const ds = await this.db.getDatasource(); const prevValue = await this.loadRawData(id); const newValue = { _id: prevValue._id, _rev: prevValue._rev, id: prevValue.id, data: data, }; await ds.insert(newValue); return; } async publicList(limit: number): Promise<{ id: string; title: string }[]> { const ds = await this.db.getDatasource(); const data = await ds.find({ selector: { 'data.title': { $exists: true, }, }, fields: ['id', 'data.title'], limit: limit, }); if (!data.docs) throw createAppError('DASHBOARDS_NOT_FOUND'); return data.docs.map((d) => ({ id: d.id, title: d.data.title })); } async findDashboardsByWidgetType( widgetType: string, ): Promise { const ds = await this.db.getDatasource(); const data = await ds.find({ selector: { 'data.widgets': { $elemMatch: { type: widgetType, }, }, }, }); if (!data.docs) throw createAppError('DASHBOARDS_NOT_FOUND'); return data.docs; } }