Move DocWithRank to the task plugin (#689)

Signed-off-by: Ilya Sumbatyants <ilya.sumb@gmail.com>
This commit is contained in:
Ilya Sumbatyants 2021-12-21 16:09:46 +07:00 committed by GitHub
parent 9a24af1788
commit 538c5529a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 109 additions and 85 deletions

View File

@ -1877,13 +1877,13 @@ packages:
/@types/ws/7.4.7:
resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==}
dependencies:
'@types/node': 16.11.14
'@types/node': 17.0.0
dev: false
/@types/ws/8.2.2:
resolution: {integrity: sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==}
dependencies:
'@types/node': 16.11.14
'@types/node': 17.0.0
dev: false
/@types/yargs-parser/20.2.1:
@ -2771,6 +2771,7 @@ packages:
/bindings/1.5.0:
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
requiresBuild: true
dependencies:
file-uri-to-path: 1.0.0
dev: false
@ -4737,6 +4738,7 @@ packages:
/file-uri-to-path/1.0.0:
resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
requiresBuild: true
dev: false
optional: true
@ -6987,6 +6989,7 @@ packages:
/nan/2.15.0:
resolution: {integrity: sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==}
requiresBuild: true
dev: false
optional: true
@ -10586,7 +10589,7 @@ packages:
dev: false
file:projects/core.tgz:
resolution: {integrity: sha512-Xjk/aGZgRnNWYrQpTy8f2H8oQVVIvbkX6MdesJnRH7AjJTI2RtloF+8sUQMSjSahPh7thHwaYyDVlJ37vMXXNQ==, tarball: file:projects/core.tgz}
resolution: {integrity: sha512-1RXdycw5v+KGu+kmqXvnrKAZpNYbc0U/rInLVwKYJ17U/hED4ONAIPEaVDxp+fxgyPHpEo7AQjZe2aD87ogwtg==, tarball: file:projects/core.tgz}
name: '@rush-temp/core'
version: 0.0.0
dependencies:
@ -11265,7 +11268,7 @@ packages:
dev: false
file:projects/model-setting.tgz_typescript@4.5.4:
resolution: {integrity: sha512-U6P3iLbt33/iJI21fs7trAHtpwWzmI/zJn+3qyxjjnFP88i11vmbd1zfb6+GYu5muRCutqNi1pTX/5cDo+NtrA==, tarball: file:projects/model-setting.tgz}
resolution: {integrity: sha512-zwbVN3PDOfDeqGcL36IHQIufdePTd68yLUm83rfIg4v8+uilseid981y/BrAysmxTXAfhVYWlDmtYXvNPS4DMQ==, tarball: file:projects/model-setting.tgz}
id: file:projects/model-setting.tgz
name: '@rush-temp/model-setting'
version: 0.0.0
@ -11948,7 +11951,7 @@ packages:
dev: false
file:projects/task.tgz:
resolution: {integrity: sha512-H61a9iYDCDExaqx08I8pBpSZj2gDyDvF+K+R/QjML1YouYeUa1M1UPpjfz4DHwT7a67TJCasvqJ9nh0/ZNvcDw==, tarball: file:projects/task.tgz}
resolution: {integrity: sha512-hVBsBOFHd4nIZZipEk0yQP/C0/oQLXFcky7Q8cH37+nNFNdq4JN+MGhrfFnwWL7WzjxYEX2MW/UdiRpFszzhjA==, tarball: file:projects/task.tgz}
name: '@rush-temp/task'
version: 0.0.0
dependencies:
@ -11961,6 +11964,7 @@ packages:
eslint-plugin-import: 2.25.3_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
eslint-plugin-promise: 5.2.0_eslint@7.32.0
lexorank: 1.0.4
prettier: 2.5.1
typescript: 4.5.4
transitivePeerDependencies:
@ -12199,7 +12203,7 @@ packages:
dev: false
file:projects/view-resources.tgz_096c09b0b673a57c275d9767a12070b1:
resolution: {integrity: sha512-hpnFAMhZPPs+w9TmZF4XlddOrE2XwPH58k0/CJrj303Lyb8g4IDfN29B/G+sv8npFpAXUIc+w9JhV5IsMxZJJg==, tarball: file:projects/view-resources.tgz}
resolution: {integrity: sha512-oT79PCOUvwaL6QgjuwTNVJJqyE82WDmBx37jF5/c6SpSrYNF14+hN41rrPReKQyhhxkyrBts73IePyHxIn653Q==, tarball: file:projects/view-resources.tgz}
id: file:projects/view-resources.tgz
name: '@rush-temp/view-resources'
version: 0.0.0

View File

@ -1,6 +1,6 @@
import { genRanks, Ref, TxOperations } from '@anticrm/core'
import task, { DoneState, Kanban, SpaceWithStates, State } from '@anticrm/task'
import { Ref, TxOperations } from '@anticrm/core'
import task, { DoneState, genRanks, Kanban, SpaceWithStates, State } from '@anticrm/task'
import { findOrUpdate } from './utils'
export async function createUpdateSpaceKanban (spaceId: Ref<SpaceWithStates>, client: TxOperations): Promise<Ref<State>[]> {

View File

@ -1,7 +1,8 @@
import contact from '@anticrm/contact'
import core, { AttachedData, Data, generateId, genRanks, Ref, TxOperations } from '@anticrm/core'
import core, { AttachedData, Data, generateId, Ref, TxOperations } from '@anticrm/core'
import recruit from '@anticrm/model-recruit'
import { Applicant, Candidate, Vacancy } from '@anticrm/recruit'
import { genRanks } from '@anticrm/task'
import faker from 'faker'
import jpeg, { BufferRet } from 'jpeg-js'
import { Client } from 'minio'

View File

@ -15,7 +15,7 @@
import type { Account, Arr, Ref, Space } from '@anticrm/core'
import { DOMAIN_MODEL } from '@anticrm/core'
import { Implements, Model, Prop, TypeBoolean, TypeString } from '@anticrm/model'
import { Model, Prop, TypeBoolean, TypeString } from '@anticrm/model'
import type { IntlString } from '@anticrm/platform'
import core from './component'
import { TDoc } from './core'
@ -43,8 +43,3 @@ export class TSpace extends TDoc implements Space {
export class TAccount extends TDoc implements Account {
email!: string
}
@Implements(core.interface.DocWithRank)
export class TDocWithRank extends TDoc {
@Prop(TypeString(), 'Rank' as IntlString)
rank!: string
}

View File

@ -20,7 +20,7 @@ import attachment from '@anticrm/model-attachment'
import type { Employee } from '@anticrm/contact'
import contact from '@anticrm/contact'
import { Arr, Class, Doc, Domain, DOMAIN_MODEL, FindOptions, Ref, Space, Timestamp } from '@anticrm/core'
import { Builder, Collection, Mixin, Model, Prop, TypeBoolean, TypeDate, TypeRef, TypeString, UX } from '@anticrm/model'
import { Builder, Collection, Implements, Mixin, Model, Prop, TypeBoolean, TypeDate, TypeRef, TypeString, UX } from '@anticrm/model'
import chunter from '@anticrm/model-chunter'
import core, { TAttachedDoc, TClass, TDoc, TSpace } from '@anticrm/model-core'
import view from '@anticrm/model-view'
@ -54,7 +54,7 @@ export { default } from './plugin'
export const DOMAIN_TASK = 'task' as Domain
export const DOMAIN_STATE = 'state' as Domain
export const DOMAIN_KANBAN = 'kanban' as Domain
@Model(task.class.State, core.class.Doc, DOMAIN_STATE, [core.interface.DocWithRank])
@Model(task.class.State, core.class.Doc, DOMAIN_STATE, [task.interface.DocWithRank])
@UX('State' as IntlString, undefined, undefined, 'title')
export class TState extends TDoc implements State {
@Prop(TypeString(), 'Title' as IntlString)
@ -65,7 +65,7 @@ export class TState extends TDoc implements State {
declare rank: string
}
@Model(task.class.DoneState, core.class.Doc, DOMAIN_STATE, [core.interface.DocWithRank])
@Model(task.class.DoneState, core.class.Doc, DOMAIN_STATE, [task.interface.DocWithRank])
@UX('Done' as IntlString, undefined, undefined, 'title')
export class TDoneState extends TDoc implements DoneState {
@Prop(TypeString(), 'Title' as IntlString)
@ -85,7 +85,7 @@ export class TLostState extends TDoneState implements LostState {}
*
* No domain is specified, since pure Tasks could not exists
*/
@Model(task.class.Task, core.class.AttachedDoc, DOMAIN_TASK, [core.interface.DocWithRank])
@Model(task.class.Task, core.class.AttachedDoc, DOMAIN_TASK, [task.interface.DocWithRank])
export class TTask extends TAttachedDoc implements Task {
@Prop(TypeRef(task.class.State), 'State' as IntlString)
state!: Ref<State>
@ -168,7 +168,7 @@ export class TKanbanTemplateSpace extends TSpace implements KanbanTemplateSpace
icon!: AnyComponent
}
@Model(task.class.StateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN, [core.interface.DocWithRank])
@Model(task.class.StateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN, [task.interface.DocWithRank])
export class TStateTemplate extends TAttachedDoc implements StateTemplate {
@Prop(TypeString(), 'Title' as IntlString)
title!: string
@ -179,7 +179,7 @@ export class TStateTemplate extends TAttachedDoc implements StateTemplate {
declare rank: string
}
@Model(task.class.DoneStateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN, [core.interface.DocWithRank])
@Model(task.class.DoneStateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN, [task.interface.DocWithRank])
export class TDoneStateTemplate extends TAttachedDoc implements DoneStateTemplate {
@Prop(TypeString(), 'Title' as IntlString)
title!: string
@ -211,8 +211,15 @@ export class TSequence extends TDoc implements Sequence {
sequence!: number
}
@Implements(task.interface.DocWithRank)
export class TDocWithRank extends TDoc {
@Prop(TypeString(), 'Rank' as IntlString)
rank!: string
}
export function createModel (builder: Builder): void {
builder.createModel(
TDocWithRank,
TState,
TDoneState,
TWonState,

View File

@ -13,7 +13,7 @@
// limitations under the License.
//
import { AttachedDoc, Class, Client, Doc, DocWithRank, Domain, DOMAIN_TX, genRanks, Ref, Space, TxCUD, TxOperations } from '@anticrm/core'
import { AttachedDoc, Class, Client, Doc, Domain, DOMAIN_TX, Ref, Space, TxCUD, TxOperations } from '@anticrm/core'
import {
MigrateOperation,
MigrateUpdate,
@ -22,7 +22,7 @@ import {
MigrationUpgradeClient
} from '@anticrm/model'
import core from '@anticrm/model-core'
import { createProjectKanban, KanbanTemplate } from '@anticrm/task'
import { createProjectKanban, DocWithRank, genRanks, KanbanTemplate } from '@anticrm/task'
import { DOMAIN_TASK, DOMAIN_STATE, DOMAIN_KANBAN } from '.'
import task from './plugin'

View File

@ -29,7 +29,6 @@
},
"dependencies": {
"@anticrm/platform": "~0.6.5",
"just-clone": "^3.2.1",
"lexorank": "~1.0.4"
"just-clone": "^3.2.1"
}
}

View File

@ -220,10 +220,3 @@ export interface Space extends Doc {
export interface Account extends Doc {
email: string
}
/**
* @public
*/
export interface DocWithRank extends Doc {
rank: string
}

View File

@ -14,7 +14,7 @@
//
import type { Plugin, StatusCode } from '@anticrm/platform'
import { plugin } from '@anticrm/platform'
import type { Account, ArrOf, AnyAttribute, AttachedDoc, DocWithRank, Class, Doc, Interface, Obj, PropertyType, Ref, Space, Timestamp, Type, Collection, RefTo } from './classes'
import type { Account, ArrOf, AnyAttribute, AttachedDoc, Class, Doc, Interface, Obj, PropertyType, Ref, Space, Timestamp, Type, Collection, RefTo } from './classes'
import type { Tx, TxBulkWrite, TxCollectionCUD, TxCreateDoc, TxCUD, TxMixin, TxPutBag, TxRemoveDoc, TxUpdateDoc } from './tx'
/**
@ -50,9 +50,6 @@ export default plugin(coreId, {
Collection: '' as Ref<Class<Collection<AttachedDoc>>>,
Bag: '' as Ref<Class<Type<Record<string, PropertyType>>>>
},
interface: {
DocWithRank: '' as Ref<Interface<DocWithRank>>
},
space: {
Tx: '' as Ref<Space>,
Model: '' as Ref<Space>

View File

@ -13,9 +13,6 @@
// limitations under the License.
//
import { LexoRank, LexoDecimal, LexoNumeralSystem36 } from 'lexorank'
import LexoRankBucket from 'lexorank/lib/lexoRank/lexoRankBucket'
import type { Doc, Ref, Account } from './classes'
function toHex (value: number, chars: number): string {
@ -62,30 +59,3 @@ export function getCurrentAccount (): Account { return currentAccount }
export function setCurrentAccount (account: Account): void {
currentAccount = account
}
/**
* @public
*/
export const genRanks = (count: number): Generator<string, void, unknown> =>
(function * () {
const sys = new LexoNumeralSystem36()
const base = 36
const max = base ** 6
const gap = LexoDecimal.parse(Math.trunc(max / (count + 2)).toString(base), sys)
let cur = LexoDecimal.parse('0', sys)
for (let i = 0; i < count; i++) {
cur = cur.add(gap)
yield new LexoRank(LexoRankBucket.BUCKET_0, cur).toString()
}
})()
/**
* @public
*/
export const calcRank = (prev?: { rank: string }, next?: { rank: string }): string => {
const a = prev?.rank !== undefined ? LexoRank.parse(prev.rank) : LexoRank.min()
const b = next?.rank !== undefined ? LexoRank.parse(next.rank) : LexoRank.max()
return a.between(b).toString()
}

View File

@ -15,7 +15,7 @@
-->
<script lang="ts">
import contact, { Contact } from '@anticrm/contact'
import { calcRank, Data, Ref, SortingOrder, Space } from '@anticrm/core'
import { Data, Ref, SortingOrder, Space } from '@anticrm/core'
import { generateId } from '@anticrm/core'
import { OK, Status } from '@anticrm/platform'
import { Card, getClient, UserBox } from '@anticrm/presentation'
@ -23,7 +23,7 @@
import { EditBox, Grid, Status as StatusControl } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte'
import lead from '../plugin'
import task from '@anticrm/task'
import task, { calcRank } from '@anticrm/task'
export let space: Ref<Space>

View File

@ -15,10 +15,10 @@
//
import type { Contact } from '@anticrm/contact'
import { Class, Data, Doc, genRanks, Ref, Space } from '@anticrm/core'
import { Class, Data, Doc, Ref, Space } from '@anticrm/core'
import type { Asset, Plugin } from '@anticrm/platform'
import { plugin } from '@anticrm/platform'
import task, { DoneState, Kanban, KanbanTemplateSpace, SpaceWithStates, State, Task } from '@anticrm/task'
import task, { DoneState, Kanban, KanbanTemplateSpace, SpaceWithStates, State, Task, genRanks } from '@anticrm/task'
/**
* @public

View File

@ -16,11 +16,10 @@
import type { Employee } from '@anticrm/contact'
import contact from '@anticrm/contact'
import { Account, Class, Client, Doc, generateId, Ref, SortingOrder } from '@anticrm/core'
import { calcRank } from '@anticrm/core'
import { getResource, OK, Resource, Severity, Status } from '@anticrm/platform'
import { Card, getClient, UserBox } from '@anticrm/presentation'
import type { Applicant, Candidate } from '@anticrm/recruit'
import type { SpaceWithStates, State } from '@anticrm/task'
import { calcRank, SpaceWithStates, State } from '@anticrm/task'
import task from '@anticrm/task'
import { Grid, Status as StatusControl } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte'

View File

@ -14,11 +14,11 @@
-->
<script lang="ts">
import contact, { Employee } from '@anticrm/contact'
import { AttachedData, calcRank, Data, Doc, Ref, SortingOrder, Space } from '@anticrm/core'
import { AttachedData, Data, Doc, Ref, SortingOrder, Space } from '@anticrm/core'
import { generateId } from '@anticrm/core'
import { OK, Status } from '@anticrm/platform'
import { Card, getClient, UserBox } from '@anticrm/presentation'
import { Issue, State } from '@anticrm/task'
import { calcRank, Issue, State } from '@anticrm/task'
import { EditBox, Grid, Status as StatusControl } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte'
import task from '../plugin'

View File

@ -14,10 +14,10 @@
// limitations under the License.
-->
<script lang="ts">
import { Ref, Doc, SortingOrder, calcRank } from '@anticrm/core'
import { Ref, SortingOrder } from '@anticrm/core'
import { createQuery, getClient } from '@anticrm/presentation'
import type { Kanban, State, DoneState } from '@anticrm/task'
import task from '@anticrm/task'
import task, { calcRank } from '@anticrm/task'
import StatesEditor from '../state/StatesEditor.svelte'

View File

@ -15,11 +15,11 @@
-->
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import { Ref, Space, SortingOrder, calcRank } from '@anticrm/core'
import { Ref, Space, SortingOrder } from '@anticrm/core'
import core from '@anticrm/core'
import { createQuery, getClient } from '@anticrm/presentation'
import type { State, DoneStateTemplate, KanbanTemplate, StateTemplate } from '@anticrm/task'
import task from '@anticrm/task'
import task, { calcRank } from '@anticrm/task'
import StatesEditor from '../state/StatesEditor.svelte'

View File

@ -15,12 +15,12 @@
-->
<script lang="ts">
import { AttachedDoc, calcRank, Class, Doc, DocumentUpdate, DocWithRank, FindOptions, Ref, SortingOrder } from '@anticrm/core'
import { AttachedDoc, Class, Doc, DocumentUpdate, FindOptions, Ref, SortingOrder } from '@anticrm/core'
import core from '@anticrm/core'
import { getResource } from '@anticrm/platform'
import { createQuery, getClient } from '@anticrm/presentation'
import type { Kanban, SpaceWithStates, State, Task } from '@anticrm/task'
import task, { DoneState, LostState, WonState } from '@anticrm/task'
import type { Kanban, SpaceWithStates, State } from '@anticrm/task'
import task, { DoneState, LostState, WonState, DocWithRank, calcRank } from '@anticrm/task'
import type { AnySvelteComponent } from '@anticrm/ui'
import { AnyComponent, Loading, ScrollBox } from '@anticrm/ui'
import KanbanPanel from './KanbanPanel.svelte'

View File

@ -30,6 +30,7 @@
"@anticrm/core": "~0.6.11",
"@anticrm/contact": "~0.6.2",
"@anticrm/view": "~0.6.0",
"@anticrm/ui": "~0.6.0"
"@anticrm/ui": "~0.6.0",
"lexorank": "~1.0.4"
}
}

View File

@ -14,12 +14,21 @@
//
import type { Employee } from '@anticrm/contact'
import { AttachedDoc, Class, Client, Data, Doc, DocWithRank, genRanks, Mixin, Ref, Space, Timestamp, TxOperations } from '@anticrm/core'
import { AttachedDoc, Class, Client, Data, Doc, Interface, Mixin, Ref, Space, Timestamp, TxOperations } from '@anticrm/core'
import type { Asset, Plugin } from '@anticrm/platform'
import { plugin } from '@anticrm/platform'
import type { AnyComponent } from '@anticrm/ui'
import { ViewletDescriptor } from '@anticrm/view'
import { genRanks } from './utils'
/**
* @public
*/
export interface DocWithRank extends Doc {
rank: string
}
// S T A T E
/**
@ -163,6 +172,9 @@ const task = plugin(taskId, {
mixin: {
KanbanCard: '' as Ref<Mixin<KanbanCard>>
},
interface: {
DocWithRank: '' as Ref<Interface<DocWithRank>>
},
class: {
Issue: '' as Ref<Class<Issue>>,
Project: '' as Ref<Class<Project>>,
@ -332,3 +344,5 @@ export async function createKanban (client: Client & TxOperations, attachedTo: R
attachedTo
})
}
export * from './utils'

44
plugins/task/src/utils.ts Normal file
View File

@ -0,0 +1,44 @@
//
// 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 { LexoRank, LexoDecimal, LexoNumeralSystem36 } from 'lexorank'
import LexoRankBucket from 'lexorank/lib/lexoRank/lexoRankBucket'
/**
* @public
*/
export const genRanks = (count: number): Generator<string, void, unknown> =>
(function * () {
const sys = new LexoNumeralSystem36()
const base = 36
const max = base ** 6
const gap = LexoDecimal.parse(Math.trunc(max / (count + 2)).toString(base), sys)
let cur = LexoDecimal.parse('0', sys)
for (let i = 0; i < count; i++) {
cur = cur.add(gap)
yield new LexoRank(LexoRankBucket.BUCKET_0, cur).toString()
}
})()
/**
* @public
*/
export const calcRank = (prev?: { rank: string }, next?: { rank: string }): string => {
const a = prev?.rank !== undefined ? LexoRank.parse(prev.rank) : LexoRank.min()
const b = next?.rank !== undefined ? LexoRank.parse(next.rank) : LexoRank.max()
return a.between(b).toString()
}

View File

@ -17,11 +17,11 @@
import { Label, Button, Status as StatusControl } from '@anticrm/ui'
import { getClient } from '@anticrm/presentation'
import core, { AttachedDoc, Collection, Doc, Ref, Space, SortingOrder, calcRank, Client, Class } from '@anticrm/core'
import core, { AttachedDoc, Collection, Doc, Ref, Space, SortingOrder, Client, Class } from '@anticrm/core'
import { SpaceSelect } from '@anticrm/presentation'
import { createEventDispatcher } from 'svelte'
import view from '../plugin'
import task, { Task } from '@anticrm/task'
import task, { Task, calcRank } from '@anticrm/task'
import { getResource, OK, Resource, Status, translate } from '@anticrm/platform'
export let object: Doc