mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 19:11:33 +03:00
EZQMS-602: Moved Rank
type to core (utilities stay in its own package) (#5019)
This commit is contained in:
parent
23a3c8e94f
commit
b2d3256df0
@ -363,3 +363,7 @@ export class TTypeCollaborativeDoc extends TType {}
|
|||||||
@UX(core.string.CollaborativeDocVersion)
|
@UX(core.string.CollaborativeDocVersion)
|
||||||
@Model(core.class.TypeCollaborativeDocVersion, core.class.Type)
|
@Model(core.class.TypeCollaborativeDocVersion, core.class.Type)
|
||||||
export class TTypeCollaborativeDocVersion extends TType {}
|
export class TTypeCollaborativeDocVersion extends TType {}
|
||||||
|
|
||||||
|
@UX(core.string.Rank)
|
||||||
|
@Model(core.class.TypeRank, core.class.Type)
|
||||||
|
export class TTypeRank extends TType {}
|
||||||
|
@ -60,6 +60,7 @@ import {
|
|||||||
TTypeIntlString,
|
TTypeIntlString,
|
||||||
TTypeMarkup,
|
TTypeMarkup,
|
||||||
TTypeNumber,
|
TTypeNumber,
|
||||||
|
TTypeRank,
|
||||||
TTypeRecord,
|
TTypeRecord,
|
||||||
TTypeRelatedDocument,
|
TTypeRelatedDocument,
|
||||||
TTypeString,
|
TTypeString,
|
||||||
@ -122,6 +123,7 @@ export function createModel (builder: Builder): void {
|
|||||||
TTypeNumber,
|
TTypeNumber,
|
||||||
TTypeBoolean,
|
TTypeBoolean,
|
||||||
TTypeString,
|
TTypeString,
|
||||||
|
TTypeRank,
|
||||||
TTypeRecord,
|
TTypeRecord,
|
||||||
TTypeAttachment,
|
TTypeAttachment,
|
||||||
TTypeHyperlink,
|
TTypeHyperlink,
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
"CreatedDate": "Created date",
|
"CreatedDate": "Created date",
|
||||||
"Status": "Status",
|
"Status": "Status",
|
||||||
"StatusCategory": "Status category",
|
"StatusCategory": "Status category",
|
||||||
"Account": "Account"
|
"Account": "Account",
|
||||||
|
"Rank": "Rank"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
"CreatedDate": "Fecha de creación",
|
"CreatedDate": "Fecha de creación",
|
||||||
"Status": "Estado",
|
"Status": "Estado",
|
||||||
"StatusCategory": "Categoría de estado",
|
"StatusCategory": "Categoría de estado",
|
||||||
"Account": "Cuenta"
|
"Account": "Cuenta",
|
||||||
|
"Rank": "Rango"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
"CreatedDate": "Data de criação",
|
"CreatedDate": "Data de criação",
|
||||||
"Status": "Estado",
|
"Status": "Estado",
|
||||||
"StatusCategory": "Categoria de estado",
|
"StatusCategory": "Categoria de estado",
|
||||||
"Account": "Conta"
|
"Account": "Conta",
|
||||||
|
"Rank": "Ranking"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
"CreatedDate": "Дата создания",
|
"CreatedDate": "Дата создания",
|
||||||
"Status": "Статус",
|
"Status": "Статус",
|
||||||
"StatusCategory": "Категория статуса",
|
"StatusCategory": "Категория статуса",
|
||||||
"Account": "Аккаунт"
|
"Account": "Аккаунт",
|
||||||
|
"Rank": "Ранг"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,13 @@ export type Hyperlink = string
|
|||||||
*/
|
*/
|
||||||
export type CollectionSize<T> = T[]['length']
|
export type CollectionSize<T> = T[]['length']
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* String representation of {@link https://www.npmjs.com/package/lexorank LexoRank} type
|
||||||
|
*/
|
||||||
|
export type Rank = string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
//
|
//
|
||||||
import type { IntlString, Plugin, StatusCode } from '@hcengineering/platform'
|
import type { IntlString, Plugin, StatusCode } from '@hcengineering/platform'
|
||||||
import { plugin } from '@hcengineering/platform'
|
import { plugin } from '@hcengineering/platform'
|
||||||
import { Mixin, Version } from '.'
|
import { Mixin, type Rank, Version } from '.'
|
||||||
import type {
|
import type {
|
||||||
Account,
|
Account,
|
||||||
AnyAttribute,
|
AnyAttribute,
|
||||||
@ -101,6 +101,7 @@ export default plugin(coreId, {
|
|||||||
TypeHyperlink: '' as Ref<Class<Type<Hyperlink>>>,
|
TypeHyperlink: '' as Ref<Class<Type<Hyperlink>>>,
|
||||||
TypeNumber: '' as Ref<Class<Type<number>>>,
|
TypeNumber: '' as Ref<Class<Type<number>>>,
|
||||||
TypeMarkup: '' as Ref<Class<Type<string>>>,
|
TypeMarkup: '' as Ref<Class<Type<string>>>,
|
||||||
|
TypeRank: '' as Ref<Class<Type<Rank>>>,
|
||||||
TypeRecord: '' as Ref<Class<Type<Record<any, any>>>>,
|
TypeRecord: '' as Ref<Class<Type<Record<any, any>>>>,
|
||||||
TypeBoolean: '' as Ref<Class<Type<boolean>>>,
|
TypeBoolean: '' as Ref<Class<Type<boolean>>>,
|
||||||
TypeTimestamp: '' as Ref<Class<Type<Timestamp>>>,
|
TypeTimestamp: '' as Ref<Class<Type<Timestamp>>>,
|
||||||
@ -187,6 +188,7 @@ export default plugin(coreId, {
|
|||||||
CreatedDate: '' as IntlString,
|
CreatedDate: '' as IntlString,
|
||||||
Status: '' as IntlString,
|
Status: '' as IntlString,
|
||||||
Account: '' as IntlString,
|
Account: '' as IntlString,
|
||||||
StatusCategory: '' as IntlString
|
StatusCategory: '' as IntlString,
|
||||||
|
Rank: '' as IntlString
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
DocumentQuery,
|
DocumentQuery,
|
||||||
DocumentUpdate,
|
DocumentUpdate,
|
||||||
FindOptions,
|
FindOptions,
|
||||||
|
type Rank,
|
||||||
RateLimiter,
|
RateLimiter,
|
||||||
Ref,
|
Ref,
|
||||||
Space
|
Space
|
||||||
@ -99,7 +100,7 @@
|
|||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
let dragCard: Item | undefined
|
let dragCard: Item | undefined
|
||||||
let dragCardInitialRank: string | undefined
|
let dragCardInitialRank: Rank | undefined
|
||||||
let dragCardInitialState: CategoryType
|
let dragCardInitialState: CategoryType
|
||||||
let dragCardInitialPosition: number | undefined
|
let dragCardInitialPosition: number | undefined
|
||||||
let dragCardState: CategoryType | undefined
|
let dragCardState: CategoryType | undefined
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { type Doc } from '@hcengineering/core'
|
import { type Doc, type Rank } from '@hcengineering/core'
|
||||||
import { type Asset } from '@hcengineering/platform'
|
import { type Asset } from '@hcengineering/platform'
|
||||||
import type { Rank } from '@hcengineering/rank'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
|
@ -35,6 +35,7 @@ import core, {
|
|||||||
MixinUpdate,
|
MixinUpdate,
|
||||||
Obj,
|
Obj,
|
||||||
PropertyType,
|
PropertyType,
|
||||||
|
Rank,
|
||||||
Ref,
|
Ref,
|
||||||
RefTo,
|
RefTo,
|
||||||
Space,
|
Space,
|
||||||
@ -501,3 +502,10 @@ export function TypeCollaborativeDoc (): Type<CollaborativeDoc> {
|
|||||||
export function TypeCollaborativeDocVersion (): Type<CollaborativeDoc> {
|
export function TypeCollaborativeDocVersion (): Type<CollaborativeDoc> {
|
||||||
return { _class: core.class.TypeCollaborativeDocVersion, label: core.string.CollaborativeDocVersion }
|
return { _class: core.class.TypeCollaborativeDocVersion, label: core.string.CollaborativeDocVersion }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export function TypeRank (): Type<Rank> {
|
||||||
|
return { _class: core.class.TypeRank, label: core.string.Rank }
|
||||||
|
}
|
||||||
|
@ -1,145 +0,0 @@
|
|||||||
<!--
|
|
||||||
// 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.
|
|
||||||
-->
|
|
||||||
<script lang="ts">
|
|
||||||
import { flip } from 'svelte/animate'
|
|
||||||
|
|
||||||
import { Doc, DocData, Ref } from '@hcengineering/core'
|
|
||||||
|
|
||||||
import { IconMoreV } from '@hcengineering/ui'
|
|
||||||
import { getClient } from '../utils'
|
|
||||||
|
|
||||||
type DocWithRank = Doc & { rank: string }
|
|
||||||
type DraftDoc = DocData<Doc> & { _id: Ref<Doc> }
|
|
||||||
type DraftDocWithRank = DocData<DocWithRank> & { _id: Ref<Doc> }
|
|
||||||
type ListType = Doc[] | DocWithRank[] | DraftDoc[] | DraftDocWithRank[]
|
|
||||||
|
|
||||||
export let objects: ListType
|
|
||||||
export let handleMove: ((fromIndex: number, toIndex: number) => void) | undefined = undefined
|
|
||||||
export let calcRank: (doc: DocWithRank, next: DocWithRank) => string
|
|
||||||
export let showContextMenu: ((evt: MouseEvent, doc: Doc) => void) | undefined = undefined
|
|
||||||
export let isDraft = false
|
|
||||||
export let editable = true
|
|
||||||
|
|
||||||
const client = getClient()
|
|
||||||
|
|
||||||
let draggingIndex: number | null = null
|
|
||||||
let hoveringIndex: number | null = null
|
|
||||||
let dragOverIndex: number = -1
|
|
||||||
|
|
||||||
function resetDrag () {
|
|
||||||
draggingIndex = null
|
|
||||||
hoveringIndex = null
|
|
||||||
dragOverIndex = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDragStart (ev: DragEvent, index: number) {
|
|
||||||
if (ev.dataTransfer) {
|
|
||||||
ev.dataTransfer.effectAllowed = 'move'
|
|
||||||
ev.dataTransfer.dropEffect = 'move'
|
|
||||||
draggingIndex = index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkHasRank (objects: ListType): objects is DocWithRank[] {
|
|
||||||
return 'rank' in objects[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkIsNotDraft (object: Doc | DocWithRank | DraftDoc | DraftDocWithRank): object is Doc | DocWithRank {
|
|
||||||
return !('_class' in object) && !isDraft
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleDrop (ev: DragEvent, toIndex: number) {
|
|
||||||
if (ev.dataTransfer && draggingIndex !== null && toIndex !== draggingIndex) {
|
|
||||||
ev.dataTransfer.dropEffect = 'move'
|
|
||||||
|
|
||||||
if (handleMove) {
|
|
||||||
handleMove(draggingIndex, toIndex)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!checkHasRank(objects)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const [prev, next] = [
|
|
||||||
objects[draggingIndex < toIndex ? toIndex : toIndex - 1],
|
|
||||||
objects[draggingIndex < toIndex ? toIndex + 1 : toIndex]
|
|
||||||
]
|
|
||||||
const object = objects[draggingIndex]
|
|
||||||
|
|
||||||
const newRank = calcRank(prev, next)
|
|
||||||
if (isDraft) {
|
|
||||||
object.rank = newRank
|
|
||||||
} else {
|
|
||||||
await client.update(object, { rank: newRank })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resetDrag()
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="antiAccordion">
|
|
||||||
{#each objects as object, index (object._id)}
|
|
||||||
<div class="description pb-1" animate:flip={{ duration: 400 }}>
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
||||||
<div
|
|
||||||
class:is-dragging={index === draggingIndex}
|
|
||||||
class:is-dragged-over-up={draggingIndex !== null && index < draggingIndex && index === hoveringIndex}
|
|
||||||
class:is-dragged-over-down={draggingIndex !== null && index > draggingIndex && index === hoveringIndex}
|
|
||||||
class:drag-over-highlight={index === dragOverIndex}
|
|
||||||
draggable={editable}
|
|
||||||
on:contextmenu={(ev) => checkIsNotDraft(object) && showContextMenu?.(ev, object)}
|
|
||||||
on:dragstart={(ev) => {
|
|
||||||
handleDragStart(ev, index)
|
|
||||||
}}
|
|
||||||
on:dragover|preventDefault={() => {
|
|
||||||
dragOverIndex = index
|
|
||||||
return false
|
|
||||||
}}
|
|
||||||
on:dragenter={() => (hoveringIndex = index)}
|
|
||||||
on:drop|preventDefault={(ev) => handleDrop(ev, index)}
|
|
||||||
on:dragend={resetDrag}
|
|
||||||
>
|
|
||||||
<div class="draggable-container">
|
|
||||||
<div class="caption mb-0 flex flex-grow flex-row-center">
|
|
||||||
<div class="draggable-mark fs-title content-dark-color whitespace-nowrap mr-2">
|
|
||||||
<IconMoreV size={'small'} />
|
|
||||||
</div>
|
|
||||||
<div class="fs-title content-dark-color whitespace-nowrap mr-2">
|
|
||||||
{`${index + 1}.`}
|
|
||||||
</div>
|
|
||||||
<slot name="object" {index} />
|
|
||||||
</div>
|
|
||||||
<slot name="object-footer" {index} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.drag-over-highlight {
|
|
||||||
opacity: 0.2;
|
|
||||||
}
|
|
||||||
.description {
|
|
||||||
.draggable-container {
|
|
||||||
cursor: grabbing;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.draggable-mark {
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -36,7 +36,6 @@ export { default as SpacesMultiPopup } from './components/SpacesMultiPopup.svelt
|
|||||||
export { default as ObjectSearchPopup } from './components/ObjectSearchPopup.svelte'
|
export { default as ObjectSearchPopup } from './components/ObjectSearchPopup.svelte'
|
||||||
export { default as IndexedDocumentPreview } from './components/IndexedDocumentPreview.svelte'
|
export { default as IndexedDocumentPreview } from './components/IndexedDocumentPreview.svelte'
|
||||||
export { default as IndexedDocumentCompare } from './components/IndexedDocumentCompare.svelte'
|
export { default as IndexedDocumentCompare } from './components/IndexedDocumentCompare.svelte'
|
||||||
export { default as DraggableList } from './components/DraggableList.svelte'
|
|
||||||
export { default as NavLink } from './components/NavLink.svelte'
|
export { default as NavLink } from './components/NavLink.svelte'
|
||||||
export { default as IconForward } from './components/icons/Forward.svelte'
|
export { default as IconForward } from './components/icons/Forward.svelte'
|
||||||
export { default as Breadcrumbs } from './components/breadcrumbs/Breadcrumbs.svelte'
|
export { default as Breadcrumbs } from './components/breadcrumbs/Breadcrumbs.svelte'
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@hcengineering/core": "^0.6.28",
|
||||||
"lexorank": "~1.0.4"
|
"lexorank": "~1.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,4 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
/**
|
export { type Rank } from '@hcengineering/core'
|
||||||
* @public
|
|
||||||
*
|
|
||||||
* String representation of {@link https://www.npmjs.com/package/lexorank LexoRank} type
|
|
||||||
*/
|
|
||||||
export type Rank = string
|
|
||||||
|
@ -76,14 +76,14 @@
|
|||||||
|
|
||||||
const selection = listProvider.selection
|
const selection = listProvider.selection
|
||||||
|
|
||||||
let resultQuery: DocumentQuery<DocWithRank>
|
let resultQuery: DocumentQuery<Card>
|
||||||
|
|
||||||
$: resultQuery = { ...query, isArchived: { $nin: [true] }, space }
|
$: resultQuery = { ...query, isArchived: { $nin: [true] }, space }
|
||||||
|
|
||||||
const cardQuery = createQuery()
|
const cardQuery = createQuery()
|
||||||
let cards: DocWithRank[] = []
|
let cards: Card[] = []
|
||||||
|
|
||||||
$: cardQuery.query<DocWithRank>(
|
$: cardQuery.query<Card>(
|
||||||
_class,
|
_class,
|
||||||
getCategoryQueryNoLookup(resultQuery),
|
getCategoryQueryNoLookup(resultQuery),
|
||||||
(result) => {
|
(result) => {
|
||||||
|
@ -20,6 +20,7 @@ import {
|
|||||||
Class,
|
Class,
|
||||||
Doc,
|
Doc,
|
||||||
Mixin,
|
Mixin,
|
||||||
|
type Rank,
|
||||||
Ref,
|
Ref,
|
||||||
Space,
|
Space,
|
||||||
Status,
|
Status,
|
||||||
@ -29,7 +30,6 @@ import {
|
|||||||
import { NotificationType } from '@hcengineering/notification'
|
import { NotificationType } from '@hcengineering/notification'
|
||||||
import type { Asset, IntlString, Plugin, Resource } from '@hcengineering/platform'
|
import type { Asset, IntlString, Plugin, Resource } from '@hcengineering/platform'
|
||||||
import { plugin } from '@hcengineering/platform'
|
import { plugin } from '@hcengineering/platform'
|
||||||
import type { Rank } from '@hcengineering/rank'
|
|
||||||
import type { AnyComponent, ComponentExtensionId } from '@hcengineering/ui'
|
import type { AnyComponent, ComponentExtensionId } from '@hcengineering/ui'
|
||||||
import { Action, IconProps, ViewletDescriptor } from '@hcengineering/view'
|
import { Action, IconProps, ViewletDescriptor } from '@hcengineering/view'
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ export interface Project extends Space {
|
|||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export interface Task extends AttachedDoc, DocWithRank {
|
export interface Task extends AttachedDoc {
|
||||||
kind: Ref<TaskType>
|
kind: Ref<TaskType>
|
||||||
status: Ref<Status>
|
status: Ref<Status>
|
||||||
isDone?: boolean
|
isDone?: boolean
|
||||||
@ -59,6 +59,7 @@ export interface Task extends AttachedDoc, DocWithRank {
|
|||||||
attachments?: number
|
attachments?: number
|
||||||
labels?: number
|
labels?: number
|
||||||
identifier: string
|
identifier: string
|
||||||
|
rank: Rank
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,16 +26,17 @@ import core, {
|
|||||||
TxOperations,
|
TxOperations,
|
||||||
generateId,
|
generateId,
|
||||||
type AnyAttribute,
|
type AnyAttribute,
|
||||||
|
type Rank,
|
||||||
type RefTo
|
type RefTo
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import { PlatformError, getEmbeddedLabel, unknownStatus } from '@hcengineering/platform'
|
import { PlatformError, getEmbeddedLabel, unknownStatus } from '@hcengineering/platform'
|
||||||
import task, { Project, ProjectStatus, ProjectType, Task, TaskType } from '.'
|
import task, { Project, ProjectStatus, ProjectType, Task, TaskType } from '.'
|
||||||
import { makeRank, type Rank } from '@hcengineering/rank'
|
import { makeRank } from '@hcengineering/rank'
|
||||||
|
|
||||||
export { genRanks, makeRank } from '@hcengineering/rank'
|
export { genRanks, makeRank } from '@hcengineering/rank'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @deprecated Prefer {@link makeRank}
|
||||||
*
|
*
|
||||||
* TODO: Drop after everything migrates to {@link makeRank}
|
* TODO: Drop after everything migrates to {@link makeRank}
|
||||||
*/
|
*/
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import core, { AttachedData, FindOptions, Ref, SortingOrder } from '@hcengineering/core'
|
import core, { AttachedData, FindOptions, type Rank, Ref, SortingOrder } from '@hcengineering/core'
|
||||||
import { ObjectPopup, getClient } from '@hcengineering/presentation'
|
import { ObjectPopup, getClient } from '@hcengineering/presentation'
|
||||||
import { makeRank } from '@hcengineering/task'
|
import { makeRank } from '@hcengineering/task'
|
||||||
import { Issue, IssueDraft } from '@hcengineering/tracker'
|
import { Issue, IssueDraft } from '@hcengineering/tracker'
|
||||||
@ -42,7 +42,7 @@
|
|||||||
parentIssue?._id !== docValue.attachedTo &&
|
parentIssue?._id !== docValue.attachedTo &&
|
||||||
parentIssue?._id !== docValue._id
|
parentIssue?._id !== docValue._id
|
||||||
) {
|
) {
|
||||||
let rank: string | null = null
|
let rank: Rank | null = null
|
||||||
|
|
||||||
if (parentIssue) {
|
if (parentIssue) {
|
||||||
const lastAttachedIssue = await client.findOne<Issue>(
|
const lastAttachedIssue = await client.findOne<Issue>(
|
||||||
|
Loading…
Reference in New Issue
Block a user