import { Service, Inject } from 'typedi'; import winston from 'winston'; import { CrontabView, CrontabViewModel } from '../data/cronView'; import { initPosition, maxPosition, minPosition, stepPosition, } from '../data/env'; import { FindOptions } from 'sequelize'; @Service() export default class CronViewService { constructor(@Inject('logger') private logger: winston.Logger) {} public async create(payload: CrontabView): Promise { let position = initPosition; const views = await this.list(); if (views && views.length > 0 && views[views.length - 1].position) { position = views[views.length - 1].position as number; } position = position / 2; const tab = new CrontabView({ ...payload, position }); const doc = await this.insert(tab); await this.checkPosition(tab.position!); return doc; } public async insert(payload: CrontabView): Promise { return await CrontabViewModel.create(payload, { returning: true }); } public async update(payload: CrontabView): Promise { const doc = await this.getDb({ id: payload.id }); const tab = new CrontabView({ ...doc, ...payload }); const newDoc = await this.updateDb(tab); return newDoc; } public async updateDb(payload: CrontabView): Promise { await CrontabViewModel.update(payload, { where: { id: payload.id } }); return await this.getDb({ id: payload.id }); } public async remove(ids: number[]) { await CrontabViewModel.destroy({ where: { id: ids } }); } public async list(): Promise { try { const result = await CrontabViewModel.findAll({ where: {}, order: [['position', 'DESC']], }); return result; } catch (error) { throw error; } } public async getDb( query: FindOptions['where'], ): Promise { const doc: any = await CrontabViewModel.findOne({ where: { ...query } }); if (!doc) { throw new Error(`CronView ${JSON.stringify(query)} not found`); } return doc.get({ plain: true }); } public async disabled(ids: number[]) { await CrontabViewModel.update({ isDisabled: 1 }, { where: { id: ids } }); } public async enabled(ids: number[]) { await CrontabViewModel.update({ isDisabled: 0 }, { where: { id: ids } }); } private async checkPosition(position: number) { const precisionPosition = parseFloat(position.toPrecision(16)); if (precisionPosition < minPosition || precisionPosition > maxPosition) { const envs = await this.list(); let position = initPosition; for (const env of envs) { position = position - stepPosition; await this.updateDb({ id: env.id, position }); } } } private getPrecisionPosition(position: number): number { return parseFloat(position.toPrecision(16)); } public async move({ id, fromIndex, toIndex, }: { fromIndex: number; toIndex: number; id: number; }): Promise { let targetPosition: number; const isUpward = fromIndex > toIndex; const views = await this.list(); if (toIndex === 0 || toIndex === views.length - 1) { targetPosition = isUpward ? views[0].position! * 2 : views[toIndex].position! / 2; } else { targetPosition = isUpward ? (views[toIndex].position! + views[toIndex - 1].position!) / 2 : (views[toIndex].position! + views[toIndex + 1].position!) / 2; } const newDoc = await this.update({ id, position: this.getPrecisionPosition(targetPosition), }); await this.checkPosition(targetPosition); return newDoc; } }