From f043b7a2e142b51ef4845a6814ec31dc771e14c6 Mon Sep 17 00:00:00 2001 From: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> Date: Tue, 19 Apr 2022 21:35:06 +0600 Subject: [PATCH 1/2] ModifyOn should be updated on server for every tx (#1455) Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> --- server/middleware/src/base.ts | 43 +++++++++++++++++++++++++++++++ server/middleware/src/index.ts | 2 ++ server/middleware/src/modified.ts | 43 +++++++++++++++++++++++++++++++ server/middleware/src/private.ts | 22 ++++------------ server/server/src/server.ts | 3 ++- 5 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 server/middleware/src/base.ts create mode 100644 server/middleware/src/modified.ts 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 ] From 5b54ab7c460a1c192ed790a96cbde35fb6ddcb0f Mon Sep 17 00:00:00 2001 From: Alex <41288429+Dvinyanin@users.noreply.github.com> Date: Tue, 19 Apr 2022 22:37:19 +0700 Subject: [PATCH 2/2] Add ArchiveCard action (#1456) Signed-off-by: Dvinyanin Alexandr --- plugins/board-resources/src/index.ts | 7 +++++-- plugins/board-resources/src/utils/CardUtils.ts | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/plugins/board-resources/src/index.ts b/plugins/board-resources/src/index.ts index ac45156a4e..d8abf04e4c 100644 --- a/plugins/board-resources/src/index.ts +++ b/plugins/board-resources/src/index.ts @@ -28,7 +28,7 @@ import KanbanView from './components/KanbanView.svelte' import CardLabelsPicker from './components/popups/CardLabelsPicker.svelte' import MoveView from './components/popups/MoveCard.svelte' import DateRangePicker from './components/popups/DateRangePicker.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 }) @@ -57,7 +57,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) +}