diff --git a/plugins/board-resources/src/index.ts b/plugins/board-resources/src/index.ts index 8f2239870a..465d0b99b5 100644 --- a/plugins/board-resources/src/index.ts +++ b/plugins/board-resources/src/index.ts @@ -30,7 +30,7 @@ import MoveView from './components/popups/MoveCard.svelte' import DateRangePicker from './components/popups/DateRangePicker.svelte' import CardLabelPresenter from './components/presenters/LabelPresenter.svelte' import CardDatePresenter from './components/presenters/DatePresenter.svelte' -import { addCurrentUser, canAddCurrentUser, isArchived, isUnarchived } from './utils/CardUtils' +import { addCurrentUser, canAddCurrentUser, isArchived, isUnarchived, archiveCard, unarchiveCard, deleteCard } from './utils/CardUtils' async function showMoveCardPopup (object: Card): Promise { showPopup(MoveView, { object }) @@ -61,7 +61,10 @@ export default async (): Promise => ({ Join: addCurrentUser, Move: showMoveCardPopup, Dates: showDatePickerPopup, - Labels: showCardLabelsPopup + Labels: showCardLabelsPopup, + Archive: archiveCard, + SendToBoard: unarchiveCard, + Delete: deleteCard }, cardActionSupportedHandler: { Join: canAddCurrentUser, diff --git a/plugins/board-resources/src/utils/CardUtils.ts b/plugins/board-resources/src/utils/CardUtils.ts index 136643f71a..76104e0fe5 100644 --- a/plugins/board-resources/src/utils/CardUtils.ts +++ b/plugins/board-resources/src/utils/CardUtils.ts @@ -9,6 +9,10 @@ export function updateCard (client: Client, card: Card, field: string, value: an client.update(card, { [field]: value }) } +export function deleteCard (card: Card, client: Client): void { + client.remove(card) +} + export function isArchived (card: Card): boolean { return !!card.isArchived } @@ -45,3 +49,11 @@ export function addCurrentUser (card: Card, client: Client): void { members.push(employee) updateCard(client, card, 'members', members) } + +export function archiveCard (card: Card, client: Client): void { + updateCard(client, card, 'isArchived', true) +} + +export function unarchiveCard (card: Card, client: Client): void { + updateCard(client, card, 'isArchived', false) +} diff --git a/server/middleware/src/base.ts b/server/middleware/src/base.ts new file mode 100644 index 0000000000..6794950808 --- /dev/null +++ b/server/middleware/src/base.ts @@ -0,0 +1,43 @@ +// +// Copyright © 2022 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import { Class, Doc, DocumentQuery, FindOptions, Ref, ServerStorage, Tx } from '@anticrm/core' +import { FindAllMiddlewareResult, Middleware, SessionContext, TxMiddlewareResult } from '@anticrm/server-core' + +/** + * @public + */ +export abstract class BaseMiddleware { + constructor (protected readonly storage: ServerStorage, protected readonly next?: Middleware) { + } + + async findAll (ctx: SessionContext, _class: Ref>, query: DocumentQuery, options?: FindOptions): Promise> { + return await this.provideFindAll(ctx, _class, query, options) + } + + protected async provideTx (ctx: SessionContext, tx: Tx): Promise { + if (this.next !== undefined) { + return await this.next.tx(ctx, tx) + } + return [ctx, tx, undefined] + } + + protected async provideFindAll (ctx: SessionContext, _class: Ref>, query: DocumentQuery, options?: FindOptions): Promise> { + if (this.next !== undefined) { + return await this.next.findAll(ctx, _class, query, options) + } + return [ctx, _class, query, options] + } +} diff --git a/server/middleware/src/index.ts b/server/middleware/src/index.ts index 9e3a93bd26..7a3714d979 100644 --- a/server/middleware/src/index.ts +++ b/server/middleware/src/index.ts @@ -13,4 +13,6 @@ // limitations under the License. // +export * from './base' +export * from './modified' export * from './private' diff --git a/server/middleware/src/modified.ts b/server/middleware/src/modified.ts new file mode 100644 index 0000000000..40295ef5eb --- /dev/null +++ b/server/middleware/src/modified.ts @@ -0,0 +1,43 @@ +// +// Copyright © 2022 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import core, { Doc, ServerStorage, Timestamp, Tx, TxCreateDoc } from '@anticrm/core' +import { Middleware, SessionContext, TxMiddlewareResult } from '@anticrm/server-core' +import { BaseMiddleware } from './base' + +/** + * @public + */ +export class ModifiedMiddleware extends BaseMiddleware implements Middleware { + private constructor (storage: ServerStorage, next?: Middleware) { + super(storage, next) + } + + static create (storage: ServerStorage, next?: Middleware): ModifiedMiddleware { + return new ModifiedMiddleware(storage, next) + } + + async tx (ctx: SessionContext, tx: Tx): Promise { + tx.modifiedOn = Date.now() + if (this.storage.hierarchy.isDerived(tx._class, core.class.TxCreateDoc)) { + const createTx = tx as TxCreateDoc + if (createTx.attributes.createOn !== undefined) { + createTx.attributes.createOn = tx.modifiedOn + } + } + const res = await this.provideTx(ctx, tx) + return [res[0], res[1], res[2]] + } +} diff --git a/server/middleware/src/private.ts b/server/middleware/src/private.ts index c3b7b4dba8..ca3d075ac2 100644 --- a/server/middleware/src/private.ts +++ b/server/middleware/src/private.ts @@ -17,14 +17,16 @@ import core, { Tx, Doc, Ref, Class, DocumentQuery, FindOptions, ServerStorage, A import platform, { PlatformError, Severity, Status } from '@anticrm/platform' import { Middleware, SessionContext, TxMiddlewareResult, FindAllMiddlewareResult } from '@anticrm/server-core' import { DOMAIN_PREFERENCE } from '@anticrm/server-preference' +import { BaseMiddleware } from './base' /** * @public */ -export class PrivateMiddleware implements Middleware { +export class PrivateMiddleware extends BaseMiddleware implements Middleware { private readonly targetDomains = [DOMAIN_PREFERENCE] - private constructor (private readonly storage: ServerStorage, private readonly next?: Middleware) { + private constructor (storage: ServerStorage, next?: Middleware) { + super(storage, next) } static create (storage: ServerStorage, next?: Middleware): PrivateMiddleware { @@ -48,14 +50,7 @@ export class PrivateMiddleware implements Middleware { return [res[0], res[1], res[2] ?? target] } - private async provideTx (ctx: SessionContext, tx: Tx): Promise { - if (this.next !== undefined) { - return await this.next.tx(ctx, tx) - } - return [ctx, tx, undefined] - } - - async findAll (ctx: SessionContext, _class: Ref>, query: DocumentQuery, options?: FindOptions): Promise> { + override async findAll (ctx: SessionContext, _class: Ref>, query: DocumentQuery, options?: FindOptions): Promise> { let newQuery = query const domain = this.storage.hierarchy.getDomain(_class) if (this.targetDomains.includes(domain)) { @@ -68,13 +63,6 @@ export class PrivateMiddleware implements Middleware { return await this.provideFindAll(ctx, _class, newQuery, options) } - private async provideFindAll (ctx: SessionContext, _class: Ref>, query: DocumentQuery, options?: FindOptions): Promise> { - if (this.next !== undefined) { - return await this.next.findAll(ctx, _class, query, options) - } - return [ctx, _class, query, options] - } - private async getUser (ctx: SessionContext): Promise> { if (ctx.userEmail === undefined) { throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {})) diff --git a/server/server/src/server.ts b/server/server/src/server.ts index 40e52638ac..0be704598d 100644 --- a/server/server/src/server.ts +++ b/server/server/src/server.ts @@ -27,7 +27,7 @@ import { TxResult } from '@anticrm/core' import { createElasticAdapter } from '@anticrm/elastic' -import { PrivateMiddleware } from '@anticrm/middleware' +import { PrivateMiddleware, ModifiedMiddleware } from '@anticrm/middleware' import { createMongoAdapter, createMongoTxAdapter } from '@anticrm/mongo' import { addLocation } from '@anticrm/platform' import { serverAttachmentId } from '@anticrm/server-attachment' @@ -103,6 +103,7 @@ export function start ( addLocation(serverTelegramId, () => import('@anticrm/server-telegram-resources')) const middlewares: MiddlewareCreator[] = [ + ModifiedMiddleware.create, PrivateMiddleware.create ]