diff --git a/dev/client-resources/src/__tests__/client.test.ts b/dev/client-resources/src/__tests__/client.test.ts index 6e1379be4a..8c38d0b10e 100644 --- a/dev/client-resources/src/__tests__/client.test.ts +++ b/dev/client-resources/src/__tests__/client.test.ts @@ -36,6 +36,7 @@ describe('client', () => { name: 'xxx', description: 'desc', private: false, + archived: false, members: [] }) const txes = await client.findAll(core.class.Space, { name: 'xxx' }) diff --git a/dev/generator/src/recruit.ts b/dev/generator/src/recruit.ts index 675a2ad4fe..7a61f1fc21 100644 --- a/dev/generator/src/recruit.ts +++ b/dev/generator/src/recruit.ts @@ -75,6 +75,7 @@ export async function generateContacts (transactorUrl: string, dbName: string, o location: faker.address.city(), company: faker.company.companyName(), members: accountIds, + archived: false, private: false } const vacancyId = (options.random ? `vacancy-${generateId()}-${i}` : `vacancy-genid-${i}`) as Ref diff --git a/models/all/src/migration.ts b/models/all/src/migration.ts index e49deae781..047f977fef 100644 --- a/models/all/src/migration.ts +++ b/models/all/src/migration.ts @@ -16,6 +16,7 @@ import { MigrateOperation } from '@anticrm/model' // Import migrate operations. +import { coreOperation } from '@anticrm/model-core' import { taskOperation } from '@anticrm/model-task' import { attachmentOperation } from '@anticrm/model-attachment' import { leadOperation } from '@anticrm/model-lead' @@ -23,6 +24,7 @@ import { recruitOperation } from '@anticrm/model-recruit' import { viewOperation } from '@anticrm/model-view' export const migrateOperations: MigrateOperation[] = [ + coreOperation, taskOperation, attachmentOperation, leadOperation, diff --git a/models/chunter/src/index.ts b/models/chunter/src/index.ts index 5ebb86bd29..a1e046103c 100644 --- a/models/chunter/src/index.ts +++ b/models/chunter/src/index.ts @@ -95,12 +95,14 @@ export function createModel (builder: Builder): void { name: 'general', description: 'General Channel', private: false, + archived: false, members: [] }, chunter.space.General) builder.createDoc(chunter.class.Channel, core.space.Model, { name: 'random', description: 'Random Talks', private: false, + archived: false, members: [] }, chunter.space.Random) diff --git a/models/contact/src/index.ts b/models/contact/src/index.ts index 845a1cddb4..1db3f67e1a 100644 --- a/models/contact/src/index.ts +++ b/models/contact/src/index.ts @@ -251,6 +251,7 @@ export function createModel (builder: Builder): void { name: 'Employees', description: 'Employees', private: false, + archived: false, members: [] }, contact.space.Employee diff --git a/models/core/src/index.ts b/models/core/src/index.ts index 1b984299af..374afa6c61 100644 --- a/models/core/src/index.ts +++ b/models/core/src/index.ts @@ -23,6 +23,7 @@ export * from './core' export * from './security' export * from './tx' export { core as default } +export { coreOperation } from './migration' export function createModel (builder: Builder): void { builder.createModel( diff --git a/models/core/src/migration.ts b/models/core/src/migration.ts new file mode 100644 index 0000000000..597bf77edc --- /dev/null +++ b/models/core/src/migration.ts @@ -0,0 +1,36 @@ +// +// Copyright © 2020, 2021 Anticrm Platform Contributors. +// +// 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 { TxOperations } from '@anticrm/core' +import { + MigrateOperation, + MigrationClient, + MigrationUpgradeClient +} from '@anticrm/model' + +import core from './component' + +export const coreOperation: MigrateOperation = { + async migrate (client: MigrationClient): Promise {}, + async upgrade (client: MigrationUpgradeClient): Promise { + const ops = new TxOperations(client, core.account.System) + const targetSpaces = (await client.findAll(core.class.Space, {})) + .filter((space) => space.archived == null) + + await Promise.all(targetSpaces.map( + (space) => ops.updateDoc(space._class, space.space, space._id, { archived: false }) + )).catch((e) => console.error(e)) + } +} diff --git a/models/core/src/security.ts b/models/core/src/security.ts index 70871bcac1..99f27079ce 100644 --- a/models/core/src/security.ts +++ b/models/core/src/security.ts @@ -33,6 +33,9 @@ export class TSpace extends TDoc implements Space { @Prop(TypeBoolean(), 'Private' as IntlString) private!: boolean + @Prop(TypeBoolean(), 'Archived' as IntlString) + archived!: boolean + members!: Arr> } diff --git a/models/lead/src/index.ts b/models/lead/src/index.ts index 952fdacbb5..f4958d8dc5 100644 --- a/models/lead/src/index.ts +++ b/models/lead/src/index.ts @@ -91,6 +91,7 @@ export function createModel (builder: Builder): void { name: 'Funnel', description: 'Default funnel', private: false, + archived: false, members: [] }, lead.space.DefaultFunnel @@ -157,6 +158,7 @@ export function createModel (builder: Builder): void { description: 'Manage funnel statuses', members: [], private: false, + archived: false, icon: lead.component.TemplatesIcon }, lead.space.FunnelTemplates diff --git a/models/recruit/src/index.ts b/models/recruit/src/index.ts index 4ddafaf06c..659ed03155 100644 --- a/models/recruit/src/index.ts +++ b/models/recruit/src/index.ts @@ -141,7 +141,8 @@ export function createModel (builder: Builder): void { name: 'public', description: 'Public Candidates', private: false, - members: [] + members: [], + archived: false }, recruit.space.CandidatesPublic ) @@ -262,6 +263,7 @@ export function createModel (builder: Builder): void { description: 'Manage vacancy statuses', members: [], private: false, + archived: false, icon: recruit.component.TemplatesIcon }, recruit.space.VacancyTemplates diff --git a/models/setting/package.json b/models/setting/package.json index 8f067cca5c..f4b4f4d0a8 100644 --- a/models/setting/package.json +++ b/models/setting/package.json @@ -33,6 +33,7 @@ "@anticrm/platform": "~0.6.5", "@anticrm/model-core": "~0.6.0", "@anticrm/model-view": "~0.6.0", - "@anticrm/model-workbench": "~0.6.1" + "@anticrm/model-workbench": "~0.6.1", + "@anticrm/task": "~0.6.0" } } diff --git a/models/setting/src/index.ts b/models/setting/src/index.ts index 48dc387645..db8b9a7779 100644 --- a/models/setting/src/index.ts +++ b/models/setting/src/index.ts @@ -19,6 +19,7 @@ import core, { TDoc } from '@anticrm/model-core' import setting from '@anticrm/setting' import type { Integration, IntegrationType, Handler } from '@anticrm/setting' import type { IntlString } from '@anticrm/platform' +import task from '@anticrm/task' import workbench from '@anticrm/model-workbench' import { AnyComponent } from '@anticrm/ui' @@ -64,7 +65,7 @@ export function createModel (builder: Builder): void { { id: 'statuses', label: setting.string.ManageStatuses, - icon: setting.icon.Statuses, + icon: task.icon.ManageStatuses, component: setting.component.ManageStatuses }, { diff --git a/models/task/src/index.ts b/models/task/src/index.ts index 789437859f..55e0f99629 100644 --- a/models/task/src/index.ts +++ b/models/task/src/index.ts @@ -323,6 +323,7 @@ export function createModel (builder: Builder): void { name: 'public', description: 'Public tasks', private: false, + archived: false, members: [] }, task.space.TasksPublic @@ -336,6 +337,7 @@ export function createModel (builder: Builder): void { description: 'Manage project statuses', members: [], private: false, + archived: false, icon: task.component.TemplatesIcon }, task.space.ProjectTemplates @@ -368,9 +370,50 @@ export function createModel (builder: Builder): void { task.action.EditStatuses ) + builder.createDoc( + view.class.Action, + core.space.Model, + { + label: 'Archive' as IntlString, + icon: view.icon.Archive, + action: task.actionImpl.ArchiveSpace + }, + task.action.ArchiveSpace + ) + + builder.createDoc( + view.class.Action, + core.space.Model, + { + label: 'Unarchive' as IntlString, + icon: view.icon.Archive, + action: task.actionImpl.UnarchiveSpace + }, + task.action.UnarchiveSpace + ) + builder.createDoc(view.class.ActionTarget, core.space.Model, { target: task.class.SpaceWithStates, - action: task.action.EditStatuses + action: task.action.EditStatuses, + query: { + archived: false + } + }) + + builder.createDoc(view.class.ActionTarget, core.space.Model, { + target: task.class.SpaceWithStates, + action: task.action.ArchiveSpace, + query: { + archived: false + } + }) + + builder.createDoc(view.class.ActionTarget, core.space.Model, { + target: task.class.SpaceWithStates, + action: task.action.UnarchiveSpace, + query: { + archived: true + } }) builder.mixin(task.class.State, core.class.Class, view.mixin.AttributeEditor, { @@ -399,7 +442,8 @@ export function createModel (builder: Builder): void { name: 'Sequences', description: 'Internal space to store sequence numbers', members: [], - private: false + private: false, + archived: false }, task.space.Sequence ) diff --git a/models/task/src/plugin.ts b/models/task/src/plugin.ts index 024b4dce73..71585bfe44 100644 --- a/models/task/src/plugin.ts +++ b/models/task/src/plugin.ts @@ -30,13 +30,17 @@ export default mergeIds(taskId, task, { CreateTask: '' as Ref, EditStatuses: '' as Ref, TodoItemMarkDone: '' as Ref, - TodoItemMarkUnDone: '' as Ref + TodoItemMarkUnDone: '' as Ref, + ArchiveSpace: '' as Ref, + UnarchiveSpace: '' as Ref }, actionImpl: { CreateTask: '' as Resource<(object: Doc) => Promise>, EditStatuses: '' as Resource<(object: Doc) => Promise>, TodoItemMarkDone: '' as Resource<(object: Doc) => Promise>, - TodoItemMarkUnDone: '' as Resource<(object: Doc) => Promise> + TodoItemMarkUnDone: '' as Resource<(object: Doc) => Promise>, + ArchiveSpace: '' as Resource<(object: Doc) => Promise>, + UnarchiveSpace: '' as Resource<(object: Doc) => Promise> }, component: { ProjectView: '' as AnyComponent, diff --git a/models/telegram/src/index.ts b/models/telegram/src/index.ts index 0a19ef8f83..56525e125d 100644 --- a/models/telegram/src/index.ts +++ b/models/telegram/src/index.ts @@ -87,6 +87,7 @@ export function createModel (builder: Builder): void { name: 'Telegram', description: 'Space for all telegram messages', private: false, + archived: false, members: [] }, telegram.space.Telegram diff --git a/packages/core/src/__tests__/client.test.ts b/packages/core/src/__tests__/client.test.ts index 1f6f822b4c..ce52b1df02 100644 --- a/packages/core/src/__tests__/client.test.ts +++ b/packages/core/src/__tests__/client.test.ts @@ -31,12 +31,13 @@ describe('client', () => { private: false, name: 'NewSpace', description: '', + archived: false, members: [] }) const result2 = await client.findAll(klass, {}) expect(result2).toHaveLength(3) - await client.createDoc(klass, core.space.Model, { private: false, name: 'NewSpace', description: '', members: [] }) + await client.createDoc(klass, core.space.Model, { private: false, name: 'NewSpace', description: '', members: [], archived: false }) const result3 = await client.findAll(klass, {}) expect(result3).toHaveLength(4) }) diff --git a/packages/core/src/__tests__/memdb.test.ts b/packages/core/src/__tests__/memdb.test.ts index 8332cc5013..dc1fbd4dcb 100644 --- a/packages/core/src/__tests__/memdb.test.ts +++ b/packages/core/src/__tests__/memdb.test.ts @@ -65,12 +65,13 @@ describe('memdb', () => { private: false, name: 'NewSpace', description: '', - members: [] + members: [], + archived: false }) const result2 = await client.findAll(core.class.Space, {}) expect(result2).toHaveLength(3) - await client.createDoc(core.class.Space, core.space.Model, { private: false, name: 'NewSpace', description: '', members: [] }) + await client.createDoc(core.class.Space, core.space.Model, { private: false, name: 'NewSpace', description: '', members: [], archived: false }) const result3 = await client.findAll(core.class.Space, {}) expect(result3).toHaveLength(4) }) @@ -180,7 +181,8 @@ describe('memdb', () => { name: 'name', description: 'desc', private: false, - members: [] + members: [], + archived: false }) const account = await model.createDoc(core.class.Account, core.space.Model, { email: 'email' }) await model.updateDoc(core.class.Space, core.space.Model, space, { $push: { members: account } }) diff --git a/packages/core/src/__tests__/minmodel.ts b/packages/core/src/__tests__/minmodel.ts index 9a898385a6..fb60de11b3 100644 --- a/packages/core/src/__tests__/minmodel.ts +++ b/packages/core/src/__tests__/minmodel.ts @@ -107,7 +107,8 @@ export function genMinModel (): TxCUD[] { name: 'Sp1', description: '', private: false, - members: [] + members: [], + archived: false }) ) @@ -116,7 +117,8 @@ export function genMinModel (): TxCUD[] { name: 'Sp2', description: '', private: false, - members: [] + members: [], + archived: false }) ) return txes diff --git a/packages/core/src/classes.ts b/packages/core/src/classes.ts index 7e818023b6..0f68d35b74 100644 --- a/packages/core/src/classes.ts +++ b/packages/core/src/classes.ts @@ -211,6 +211,7 @@ export interface Space extends Doc { description: string private: boolean members: Arr> + archived: boolean } /** diff --git a/packages/query/src/__tests__/minmodel.ts b/packages/query/src/__tests__/minmodel.ts index 1cfa3ab798..07906a99c1 100644 --- a/packages/query/src/__tests__/minmodel.ts +++ b/packages/query/src/__tests__/minmodel.ts @@ -97,7 +97,8 @@ export function genMinModel (): TxCUD[] { name: 'Sp1', description: '', private: false, - members: [u1, u2] + members: [u1, u2], + archived: false }) ) @@ -106,7 +107,8 @@ export function genMinModel (): TxCUD[] { name: 'Sp2', description: '', private: false, - members: [u1] + members: [u1], + archived: false }) ) return txes diff --git a/packages/query/src/__tests__/query.test.ts b/packages/query/src/__tests__/query.test.ts index 4e9a0cf67e..e0b6d5e96e 100644 --- a/packages/query/src/__tests__/query.test.ts +++ b/packages/query/src/__tests__/query.test.ts @@ -97,6 +97,7 @@ describe('query', () => { name: '#0', description: '', members: [], + archived: false, x: 0 }) await factory.createDoc(core.class.Space, core.space.Model, { @@ -104,6 +105,7 @@ describe('query', () => { name: '#1', description: '', members: [], + archived: false, x: 1 }) await factory.createDoc(core.class.Space, core.space.Model, { @@ -111,6 +113,7 @@ describe('query', () => { name: '#2', description: '', members: [], + archived: false, x: 2 }) await factory.createDoc(core.class.Space, core.space.Model, { @@ -118,6 +121,7 @@ describe('query', () => { name: '#3', description: '', members: [], + archived: false, x: 3 }) await pp @@ -144,18 +148,21 @@ describe('query', () => { private: false, name: '#1', description: '', + archived: false, members: [] }) await factory.createDoc(core.class.Space, core.space.Model, { private: false, name: '#2', description: '', + archived: false, members: [] }) await factory.createDoc(core.class.Space, core.space.Model, { private: false, name: '#3', description: '', + archived: false, members: [] }) }) @@ -180,6 +187,7 @@ describe('query', () => { private: false, name: '#1', description: '', + archived: false, members: [] }) await factory.createDoc(core.class.Space, core.space.Model, { @@ -187,6 +195,7 @@ describe('query', () => { private: false, name: '#2', description: '', + archived: false, members: [] }) await factory.createDoc(core.class.Space, core.space.Model, { @@ -194,6 +203,7 @@ describe('query', () => { private: false, name: '#3', description: '', + archived: false, members: [] }) await pp @@ -244,6 +254,7 @@ describe('query', () => { private: true, name: i.toString(), description: '', + archived: false, members: [] }) } diff --git a/packages/query/src/index.ts b/packages/query/src/index.ts index 4a5e7ba6bc..aca74ad35b 100644 --- a/packages/query/src/index.ts +++ b/packages/query/src/index.ts @@ -229,7 +229,7 @@ export class LiveQuery extends TxProcessor implements Client { // Check if query is partially matched. private matchQuery (q: Query, tx: TxUpdateDoc): boolean { - if (!this.client.getHierarchy().isDerived(q._class, tx.objectClass)) { + if (!this.client.getHierarchy().isDerived(tx.objectClass, q._class)) { return false } diff --git a/packages/ui/src/components/Menu.svelte b/packages/ui/src/components/Menu.svelte index c7cc7aa3bd..35e1ea68fc 100644 --- a/packages/ui/src/components/Menu.svelte +++ b/packages/ui/src/components/Menu.svelte @@ -23,8 +23,9 @@ export let actions: { label: IntlString icon?: Asset | AnySvelteComponent - action: () => void | Promise + action: (ctx?: any) => void | Promise }[] = [] + export let ctx: any = undefined const dispatch = createEventDispatcher() @@ -33,7 +34,7 @@ {#each actions as action}