From 1e0e5de097df378e2f3139acb7f1ffa2ff29a69e Mon Sep 17 00:00:00 2001 From: Denis Bykhov Date: Fri, 10 May 2024 16:54:34 +0500 Subject: [PATCH] Space actions (#5574) Signed-off-by: Denis Bykhov --- models/view/src/index.ts | 30 ++++++++++++++++++ models/view/src/plugin.ts | 6 +++- plugins/tracker-resources/src/index.ts | 2 +- plugins/view-assets/assets/icons.svg | 8 +++++ plugins/view-assets/lang/en.json | 4 ++- plugins/view-assets/lang/es.json | 4 ++- plugins/view-assets/lang/pt.json | 4 ++- plugins/view-assets/lang/ru.json | 4 ++- plugins/view-assets/src/index.ts | 4 ++- plugins/view-resources/src/actionImpl.ts | 31 ++++++++++++++++++- plugins/view-resources/src/index.ts | 13 ++++++-- .../view-resources/src/visibilityTester.ts | 20 ++++++++++++ plugins/view/src/index.ts | 10 ++++-- 13 files changed, 128 insertions(+), 12 deletions(-) diff --git a/models/view/src/index.ts b/models/view/src/index.ts index 6a6edb2c00..b690ba2538 100644 --- a/models/view/src/index.ts +++ b/models/view/src/index.ts @@ -650,6 +650,36 @@ export function createModel (builder: Builder): void { view.action.Archive ) + createAction( + builder, + { + action: view.actionImpl.Join, + label: view.string.Join, + icon: view.icon.Join, + category: view.category.General, + input: 'focus', + target: core.class.Space, + visibilityTester: view.function.CanJoinSpace, + context: { mode: ['context', 'browser'], group: 'tools' } + }, + view.action.Join + ) + + createAction( + builder, + { + action: view.actionImpl.Leave, + label: view.string.Leave, + icon: view.icon.Leave, + category: view.category.General, + input: 'focus', + target: core.class.Space, + visibilityTester: view.function.CanLeaveSpace, + context: { mode: ['context', 'browser'], group: 'tools' } + }, + view.action.Leave + ) + // Keyboard actions. createAction( builder, diff --git a/models/view/src/plugin.ts b/models/view/src/plugin.ts index 9c3643ba7c..70ec3889c6 100644 --- a/models/view/src/plugin.ts +++ b/models/view/src/plugin.ts @@ -24,6 +24,8 @@ export default mergeIds(viewId, view, { actionImpl: { Delete: '' as ViewAction, Archive: '' as ViewAction, + Join: '' as ViewAction, + Leave: '' as ViewAction, Move: '' as ViewAction, MoveLeft: '' as ViewAction, MoveRight: '' as ViewAction, @@ -128,7 +130,9 @@ export default mergeIds(viewId, view, { CanDeleteObject: '' as Resource<(doc?: Doc | Doc[]) => Promise>, CanEditSpace: '' as Resource<(doc?: Doc | Doc[]) => Promise>, CanArchiveSpace: '' as Resource<(doc?: Doc | Doc[]) => Promise>, - CanDeleteSpace: '' as Resource<(doc?: Doc | Doc[]) => Promise> + CanDeleteSpace: '' as Resource<(doc?: Doc | Doc[]) => Promise>, + CanJoinSpace: '' as Resource<(doc?: Doc | Doc[]) => Promise>, + CanLeaveSpace: '' as Resource<(doc?: Doc | Doc[]) => Promise> }, pipeline: { PresentationMiddleware: '' as Ref, diff --git a/plugins/tracker-resources/src/index.ts b/plugins/tracker-resources/src/index.ts index 52bcec0c39..d419ae2223 100644 --- a/plugins/tracker-resources/src/index.ts +++ b/plugins/tracker-resources/src/index.ts @@ -542,7 +542,7 @@ export default async (): Promise => ({ ) => await getAllStates(query, onUpdate, queryId, attr, false), GetVisibleFilters: getVisibleFilters, IssueChatTitleProvider: getIssueChatTitle, - IsProjectJoined: async (project: Project) => !project.private || project.members.includes(getCurrentAccount()._id), + IsProjectJoined: async (project: Project) => project.members.includes(getCurrentAccount()._id), GetIssueStatusCategories: getIssueStatusCategories }, actionImpl: { diff --git a/plugins/view-assets/assets/icons.svg b/plugins/view-assets/assets/icons.svg index b7c8f8d6b9..e601db4e8e 100644 --- a/plugins/view-assets/assets/icons.svg +++ b/plugins/view-assets/assets/icons.svg @@ -147,4 +147,12 @@ + + + + + + + + diff --git a/plugins/view-assets/lang/en.json b/plugins/view-assets/lang/en.json index 5d694bd15c..e5e3fb253d 100644 --- a/plugins/view-assets/lang/en.json +++ b/plugins/view-assets/lang/en.json @@ -121,6 +121,8 @@ "Pin": "Pin", "Unpin": "Unpin", "Archived": "Archived", - "MoreActions": "More actions" + "MoreActions": "More actions", + "Leave": "Leave", + "Join": "Join" } } diff --git a/plugins/view-assets/lang/es.json b/plugins/view-assets/lang/es.json index eaaf4c4a2a..f11d416886 100644 --- a/plugins/view-assets/lang/es.json +++ b/plugins/view-assets/lang/es.json @@ -114,6 +114,8 @@ "ToViewCommands": "para ver los comandos disponibles", "UnArchive": "Desarchivar", "Pin": "Fijar", - "Unpin": "Desfijar" + "Unpin": "Desfijar", + "Leave": "Salir", + "Join": "Unirse" } } \ No newline at end of file diff --git a/plugins/view-assets/lang/pt.json b/plugins/view-assets/lang/pt.json index 5c0e9a554b..670d351676 100644 --- a/plugins/view-assets/lang/pt.json +++ b/plugins/view-assets/lang/pt.json @@ -114,6 +114,8 @@ "ToViewCommands": "para ver os comandos disponíveis", "UnArchive": "Desarquivar", "Pin": "Fixar", - "Unpin": "Desafixar" + "Unpin": "Desafixar", + "Leave": "Sair", + "Join": "Ingressar" } } \ No newline at end of file diff --git a/plugins/view-assets/lang/ru.json b/plugins/view-assets/lang/ru.json index 5aafa1a0fc..99f004897d 100644 --- a/plugins/view-assets/lang/ru.json +++ b/plugins/view-assets/lang/ru.json @@ -118,6 +118,8 @@ "Pin": "Закрепить", "Unpin": "Открепить", "Archived": "Архивированные", - "MoreActions": "Больше действий" + "MoreActions": "Больше действий", + "Leave": "Покинуть", + "Join": "Присоединиться" } } diff --git a/plugins/view-assets/src/index.ts b/plugins/view-assets/src/index.ts index beb6fe1a50..f6688c23f7 100644 --- a/plugins/view-assets/src/index.ts +++ b/plugins/view-assets/src/index.ts @@ -51,5 +51,7 @@ loadMetadata(view.icon, { Table2: `${icons}#table2`, CodeBlock: `${icons}#code-block`, SeparatorLine: `${icons}#separator-line`, - Circle: `${icons}#circle` + Circle: `${icons}#circle`, + Join: `${icons}#join`, + Leave: `${icons}#leave` }) diff --git a/plugins/view-resources/src/actionImpl.ts b/plugins/view-resources/src/actionImpl.ts index 9639b7cf14..3c5a77b14b 100644 --- a/plugins/view-resources/src/actionImpl.ts +++ b/plugins/view-resources/src/actionImpl.ts @@ -5,7 +5,8 @@ import { Hierarchy, type Ref, type Space, - type TxResult + type TxResult, + getCurrentAccount } from '@hcengineering/core' import { type Asset, type IntlString, type Resource, getResource } from '@hcengineering/platform' import { MessageBox, getClient, updateAttribute, type ContextStore, contextStore } from '@hcengineering/presentation' @@ -121,6 +122,32 @@ function Archive (object: Space | Space[]): void { ) } +async function Leave (object: Space | Space[]): Promise { + const client = getClient() + const promises: Array> = [] + const objs = Array.isArray(object) ? object : [object] + const me = getCurrentAccount()._id + for (const obj of objs) { + if (obj.members.includes(me)) { + promises.push(client.update(obj, { $pull: { members: me } })) + } + } + await Promise.all(promises) +} + +async function Join (object: Space | Space[]): Promise { + const client = getClient() + const promises: Array> = [] + const objs = Array.isArray(object) ? object : [object] + const me = getCurrentAccount()._id + for (const obj of objs) { + if (!obj.members.includes(me)) { + promises.push(client.update(obj, { $push: { members: me } })) + } + } + await Promise.all(promises) +} + async function Move (docs: Doc | Doc[]): Promise { showPopup(MoveView, { selected: docs }) } @@ -507,6 +534,8 @@ export const actionImpl = { CopyTextToClipboard, Delete, Archive, + Join, + Leave, Move, MoveUp, MoveDown, diff --git a/plugins/view-resources/src/index.ts b/plugins/view-resources/src/index.ts index a26d009d40..945fe1f7be 100644 --- a/plugins/view-resources/src/index.ts +++ b/plugins/view-resources/src/index.ts @@ -120,7 +120,14 @@ import { import { IndexedDocumentPreview } from '@hcengineering/presentation' import { AggregationMiddleware, AnalyticsMiddleware } from './middleware' import { showEmptyGroups } from './viewOptions' -import { canArchiveSpace, canDeleteObject, canDeleteSpace, canEditSpace } from './visibilityTester' +import { + canArchiveSpace, + canDeleteObject, + canDeleteSpace, + canEditSpace, + canJoinSpace, + canLeaveSpace +} from './visibilityTester' export { canArchiveSpace, canDeleteObject, canDeleteSpace, canEditSpace } from './visibilityTester' export { getActions, getContextActions, invokeAction, showMenu } from './actions' export { default as ActionButton } from './components/ActionButton.svelte' @@ -307,6 +314,8 @@ export default async (): Promise => ({ CanDeleteObject: canDeleteObject, CanEditSpace: canEditSpace, CanArchiveSpace: canArchiveSpace, - CanDeleteSpace: canDeleteSpace + CanDeleteSpace: canDeleteSpace, + CanJoinSpace: canJoinSpace, + CanLeaveSpace: canLeaveSpace } }) diff --git a/plugins/view-resources/src/visibilityTester.ts b/plugins/view-resources/src/visibilityTester.ts index b70b80d09a..e020bacaf8 100644 --- a/plugins/view-resources/src/visibilityTester.ts +++ b/plugins/view-resources/src/visibilityTester.ts @@ -108,3 +108,23 @@ export async function canDeleteSpace (doc?: Doc | Doc[]): Promise { return false } + +export async function canJoinSpace (doc?: Doc | Doc[]): Promise { + if (doc === undefined || Array.isArray(doc)) { + return false + } + + const space = doc as Space + + return !space.members?.includes(getCurrentAccount()._id) +} + +export async function canLeaveSpace (doc?: Doc | Doc[]): Promise { + if (doc === undefined || Array.isArray(doc)) { + return false + } + + const space = doc as Space + + return space.members?.includes(getCurrentAccount()._id) +} diff --git a/plugins/view/src/index.ts b/plugins/view/src/index.ts index e537a06baa..758977c809 100644 --- a/plugins/view/src/index.ts +++ b/plugins/view/src/index.ts @@ -121,6 +121,8 @@ const view = plugin(viewId, { action: { Delete: '' as Ref, Archive: '' as Ref, + Join: '' as Ref, + Leave: '' as Ref, Move: '' as Ref, MoveLeft: '' as Ref, MoveRight: '' as Ref, @@ -199,7 +201,9 @@ const view = plugin(viewId, { Archived: '' as IntlString, MoreActions: '' as IntlString, Pin: '' as IntlString, - Unpin: '' as IntlString + Unpin: '' as IntlString, + Join: '' as IntlString, + Leave: '' as IntlString }, icon: { Table: '' as Asset, @@ -235,7 +239,9 @@ const view = plugin(viewId, { Table2: '' as Asset, CodeBlock: '' as Asset, SeparatorLine: '' as Asset, - Circle: '' as Asset + Circle: '' as Asset, + Join: '' as Asset, + Leave: '' as Asset }, category: { General: '' as Ref,