mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-23 03:22:19 +03:00
Rank order (#2150)
Signed-off-by: Dvinyanin Alexandr <dvinyanin.alexandr@gmail.com>
This commit is contained in:
parent
cade773b95
commit
1e21c85379
@ -6,6 +6,9 @@ HR:
|
|||||||
|
|
||||||
- Allow to change assignee in Kanban
|
- Allow to change assignee in Kanban
|
||||||
|
|
||||||
|
Tracker:
|
||||||
|
- Manual issues ordering
|
||||||
|
|
||||||
## 0.6.29
|
## 0.6.29
|
||||||
|
|
||||||
Platform:
|
Platform:
|
||||||
|
@ -494,7 +494,7 @@ export function createModel (builder: Builder): void {
|
|||||||
id: issuesId,
|
id: issuesId,
|
||||||
label: tracker.string.Issues,
|
label: tracker.string.Issues,
|
||||||
icon: tracker.icon.Issues,
|
icon: tracker.icon.Issues,
|
||||||
component: tracker.component.IssuesView,
|
component: tracker.component.Issues,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
title: tracker.string.Issues
|
title: tracker.string.Issues
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
export let states: TypeState[] = []
|
export let states: TypeState[] = []
|
||||||
export let query: DocumentQuery<Item> = {}
|
export let query: DocumentQuery<Item> = {}
|
||||||
export let fieldName: string
|
export let fieldName: string
|
||||||
export let rankFieldName: string
|
export let rankFieldName: string | undefined
|
||||||
export let selection: number | undefined = undefined
|
export let selection: number | undefined = undefined
|
||||||
export let checked: Doc[] = []
|
export let checked: Doc[] = []
|
||||||
|
|
||||||
@ -57,7 +57,10 @@
|
|||||||
dragItem?: Item // required for svelte to properly recalculate state.
|
dragItem?: Item // required for svelte to properly recalculate state.
|
||||||
): ExtItem[] {
|
): ExtItem[] {
|
||||||
const stateCards = objects.filter((it) => (it as any)[fieldName] === state._id)
|
const stateCards = objects.filter((it) => (it as any)[fieldName] === state._id)
|
||||||
stateCards.sort((a, b) => (a as any)[rankFieldName]?.localeCompare((b as any)[rankFieldName]))
|
if (rankFieldName !== undefined) {
|
||||||
|
const sortField = rankFieldName
|
||||||
|
stateCards.sort((a, b) => (a as any)[sortField]?.localeCompare((b as any)[sortField]))
|
||||||
|
}
|
||||||
return stateCards.map((it, idx, arr) => ({
|
return stateCards.map((it, idx, arr) => ({
|
||||||
it,
|
it,
|
||||||
prev: arr[idx - 1],
|
prev: arr[idx - 1],
|
||||||
@ -96,14 +99,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dragCardRank = (dragCard as any)[rankFieldName]
|
if (rankFieldName !== undefined && dragCardInitialRank !== (dragCard as any)[rankFieldName]) {
|
||||||
if (dragCardInitialRank !== (dragCard as any)[rankFieldName]) {
|
const dragCardRank = (dragCard as any)[rankFieldName]
|
||||||
updates = {
|
updates = {
|
||||||
...updates,
|
...updates,
|
||||||
[rankFieldName]: dragCardRank
|
[rankFieldName]: dragCardRank
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Object.keys(updates).length > 0) {
|
if (Object.keys(updates).length > 0) {
|
||||||
await updateItem(dragCard, updates)
|
await updateItem(dragCard, updates)
|
||||||
}
|
}
|
||||||
@ -113,7 +115,7 @@
|
|||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
let dragCard: Item | undefined
|
let dragCard: Item | undefined
|
||||||
let dragCardInitialRank: string
|
let dragCardInitialRank: string | undefined
|
||||||
let dragCardInitialState: StateType
|
let dragCardInitialState: StateType
|
||||||
|
|
||||||
let isDragging = false
|
let isDragging = false
|
||||||
@ -144,23 +146,26 @@
|
|||||||
if (card !== undefined && card[fieldName] !== state._id) {
|
if (card !== undefined && card[fieldName] !== state._id) {
|
||||||
card[fieldName] = state._id
|
card[fieldName] = state._id
|
||||||
const objs = getStateObjects(objects, state)
|
const objs = getStateObjects(objects, state)
|
||||||
card[rankFieldName] = calcRank(objs[objs.length - 1]?.it, undefined)
|
if (rankFieldName !== undefined) card[rankFieldName] = calcRank(objs[objs.length - 1]?.it, undefined)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function cardDragOver (evt: CardDragEvent, object: ExtItem): void {
|
function cardDragOver (evt: CardDragEvent, object: ExtItem): void {
|
||||||
if (dragCard !== undefined) {
|
if (dragCard !== undefined) {
|
||||||
;(dragCard as any)[rankFieldName] = doCalcRank(object, evt)
|
;(dragCard as any)[fieldName] = (dragCard as any)[fieldName]
|
||||||
|
if (rankFieldName !== undefined) {
|
||||||
|
;(dragCard as any)[rankFieldName] = doCalcRank(object, evt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function cardDrop (evt: CardDragEvent, object: ExtItem): void {
|
function cardDrop (evt: CardDragEvent, object: ExtItem): void {
|
||||||
if (dragCard !== undefined) {
|
if (dragCard !== undefined && rankFieldName !== undefined) {
|
||||||
;(dragCard as any)[rankFieldName] = doCalcRank(object, evt)
|
;(dragCard as any)[rankFieldName] = doCalcRank(object, evt)
|
||||||
}
|
}
|
||||||
isDragging = false
|
isDragging = false
|
||||||
}
|
}
|
||||||
function onDragStart (object: ExtItem, state: TypeState): void {
|
function onDragStart (object: ExtItem, state: TypeState): void {
|
||||||
dragCardInitialState = state._id
|
dragCardInitialState = state._id
|
||||||
dragCardInitialRank = (object.it as any)[rankFieldName]
|
dragCardInitialRank = rankFieldName === undefined ? undefined : (object.it as any)[rankFieldName]
|
||||||
dragCard = object.it
|
dragCard = object.it
|
||||||
isDragging = true
|
isDragging = true
|
||||||
dispatch('obj-focus', object.it)
|
dispatch('obj-focus', object.it)
|
||||||
|
@ -106,6 +106,7 @@
|
|||||||
"NoAssignee": "No assignee",
|
"NoAssignee": "No assignee",
|
||||||
"LastUpdated": "Last updated",
|
"LastUpdated": "Last updated",
|
||||||
"DueDate": "Due date",
|
"DueDate": "Due date",
|
||||||
|
"Manual": "Manual",
|
||||||
"All": "All",
|
"All": "All",
|
||||||
"PastWeek": "Past week",
|
"PastWeek": "Past week",
|
||||||
"PastMonth": "Past month",
|
"PastMonth": "Past month",
|
||||||
|
@ -106,6 +106,7 @@
|
|||||||
"NoAssignee": "Нет исполнителя",
|
"NoAssignee": "Нет исполнителя",
|
||||||
"LastUpdated": "Последнее обновление",
|
"LastUpdated": "Последнее обновление",
|
||||||
"DueDate": "Срок",
|
"DueDate": "Срок",
|
||||||
|
"Manual": "Пользовательский",
|
||||||
"All": "Все",
|
"All": "Все",
|
||||||
"PastWeek": "Предыдущая неделя",
|
"PastWeek": "Предыдущая неделя",
|
||||||
"PastMonth": "Предыдущий месяц",
|
"PastMonth": "Предыдущий месяц",
|
||||||
|
@ -25,7 +25,10 @@
|
|||||||
let query: DocumentQuery<Issue>
|
let query: DocumentQuery<Issue>
|
||||||
$: statusQuery.query(
|
$: statusQuery.query(
|
||||||
tracker.class.IssueStatus,
|
tracker.class.IssueStatus,
|
||||||
{ category: { $in: [tracker.issueStatusCategory.Unstarted, tracker.issueStatusCategory.Started] } },
|
{
|
||||||
|
category: { $in: [tracker.issueStatusCategory.Unstarted, tracker.issueStatusCategory.Started] },
|
||||||
|
space: currentSpace
|
||||||
|
},
|
||||||
(result) => {
|
(result) => {
|
||||||
query = { status: { $in: result.map(({ _id }) => _id) }, space: currentSpace }
|
query = { status: { $in: result.map(({ _id }) => _id) }, space: currentSpace }
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,13 @@
|
|||||||
|
|
||||||
const statusQuery = createQuery()
|
const statusQuery = createQuery()
|
||||||
let query: DocumentQuery<Issue> = {}
|
let query: DocumentQuery<Issue> = {}
|
||||||
$: statusQuery.query(tracker.class.IssueStatus, { category: tracker.issueStatusCategory.Backlog }, (result) => {
|
$: statusQuery.query(
|
||||||
query = { status: { $in: result.map(({ _id }) => _id) }, space: currentSpace }
|
tracker.class.IssueStatus,
|
||||||
})
|
{ category: tracker.issueStatusCategory.Backlog, space: currentSpace },
|
||||||
|
(result) => {
|
||||||
|
query = { status: { $in: result.map(({ _id }) => _id) }, space: currentSpace }
|
||||||
|
}
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<IssuesView {query} title={tracker.string.BacklogIssues} />
|
<IssuesView {query} title={tracker.string.BacklogIssues} />
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
<!--
|
||||||
|
// 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 { Ref } from '@anticrm/core'
|
||||||
|
import { Team } from '@anticrm/tracker'
|
||||||
|
import tracker from '../../plugin'
|
||||||
|
import IssuesView from './IssuesView.svelte'
|
||||||
|
|
||||||
|
export let currentSpace: Ref<Team>
|
||||||
|
|
||||||
|
$: query = { space: currentSpace }
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<IssuesView {query} title={tracker.string.ActiveIssues} />
|
@ -14,18 +14,18 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import contact from '@anticrm/contact'
|
import contact from '@anticrm/contact'
|
||||||
import { Class, Doc, DocumentQuery, FindOptions, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
import { Class, Doc, DocumentQuery, Lookup, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
||||||
import { Kanban, TypeState } from '@anticrm/kanban'
|
import { Kanban } from '@anticrm/kanban'
|
||||||
import notification from '@anticrm/notification'
|
import notification from '@anticrm/notification'
|
||||||
import { createQuery, getClient } from '@anticrm/presentation'
|
import { createQuery, getClient } from '@anticrm/presentation'
|
||||||
import { Issue, IssuesGrouping, IssueStatus, Team, ViewOptions } from '@anticrm/tracker'
|
import { Issue, IssuesGrouping, IssuesOrdering, IssueStatus, Team, ViewOptions } from '@anticrm/tracker'
|
||||||
import { Button, Component, Icon, IconAdd, showPanel, showPopup, Tooltip } from '@anticrm/ui'
|
import { Button, Component, Icon, IconAdd, showPanel, showPopup, Tooltip } from '@anticrm/ui'
|
||||||
import { focusStore, ListSelectionProvider, SelectDirection, selectionStore } from '@anticrm/view-resources'
|
import { focusStore, ListSelectionProvider, SelectDirection, selectionStore } from '@anticrm/view-resources'
|
||||||
import ActionContext from '@anticrm/view-resources/src/components/ActionContext.svelte'
|
import ActionContext from '@anticrm/view-resources/src/components/ActionContext.svelte'
|
||||||
import Menu from '@anticrm/view-resources/src/components/Menu.svelte'
|
import Menu from '@anticrm/view-resources/src/components/Menu.svelte'
|
||||||
import { onMount } from 'svelte'
|
import { onMount } from 'svelte'
|
||||||
import tracker from '../../plugin'
|
import tracker from '../../plugin'
|
||||||
import { getKanbanStatuses } from '../../utils'
|
import { getKanbanStatuses, issuesSortOrderMap } from '../../utils'
|
||||||
import CreateIssue from '../CreateIssue.svelte'
|
import CreateIssue from '../CreateIssue.svelte'
|
||||||
import ProjectEditor from '../projects/ProjectEditor.svelte'
|
import ProjectEditor from '../projects/ProjectEditor.svelte'
|
||||||
import AssigneePresenter from './AssigneePresenter.svelte'
|
import AssigneePresenter from './AssigneePresenter.svelte'
|
||||||
@ -40,7 +40,9 @@
|
|||||||
export let query: DocumentQuery<Issue> = {}
|
export let query: DocumentQuery<Issue> = {}
|
||||||
|
|
||||||
$: currentSpace = typeof query.space === 'string' ? query.space : tracker.team.DefaultTeam
|
$: currentSpace = typeof query.space === 'string' ? query.space : tracker.team.DefaultTeam
|
||||||
$: ({ groupBy, shouldShowEmptyGroups, shouldShowSubIssues } = viewOptions)
|
$: ({ groupBy, orderBy, shouldShowEmptyGroups, shouldShowSubIssues } = viewOptions)
|
||||||
|
$: sort = { [orderBy]: issuesSortOrderMap[orderBy] }
|
||||||
|
$: rankFieldName = orderBy === IssuesOrdering.Manual ? orderBy : undefined
|
||||||
$: resultQuery = {
|
$: resultQuery = {
|
||||||
...(shouldShowSubIssues ? {} : { attachedTo: tracker.ids.NoParent }),
|
...(shouldShowSubIssues ? {} : { attachedTo: tracker.ids.NoParent }),
|
||||||
space: currentSpace,
|
space: currentSpace,
|
||||||
@ -57,17 +59,10 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
let issueStatuses: WithLookup<IssueStatus>[] | undefined
|
let issueStatuses: WithLookup<IssueStatus>[] | undefined
|
||||||
let states: TypeState[] | undefined
|
|
||||||
$: statusesQuery.query(
|
$: statusesQuery.query(
|
||||||
tracker.class.IssueStatus,
|
tracker.class.IssueStatus,
|
||||||
{ attachedTo: currentSpace },
|
{ attachedTo: currentSpace },
|
||||||
(is) => {
|
(is) => {
|
||||||
states = is.map((status) => ({
|
|
||||||
_id: status._id,
|
|
||||||
title: status.name,
|
|
||||||
color: status.color ?? status.$lookup?.category?.color ?? 0,
|
|
||||||
icon: status.$lookup?.category?.icon ?? undefined
|
|
||||||
}))
|
|
||||||
issueStatuses = is
|
issueStatuses = is
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -80,13 +75,11 @@
|
|||||||
return object as WithLookup<Issue>
|
return object as WithLookup<Issue>
|
||||||
}
|
}
|
||||||
|
|
||||||
const options: FindOptions<Issue> = {
|
const lookup: Lookup<Issue> = {
|
||||||
lookup: {
|
assignee: contact.class.Employee,
|
||||||
assignee: contact.class.Employee,
|
space: tracker.class.Team,
|
||||||
space: tracker.class.Team,
|
_id: {
|
||||||
_id: {
|
subIssues: tracker.class.Issue
|
||||||
subIssues: tracker.class.Issue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,10 +117,10 @@
|
|||||||
_class={tracker.class.Issue}
|
_class={tracker.class.Issue}
|
||||||
search=""
|
search=""
|
||||||
{states}
|
{states}
|
||||||
{options}
|
options={{ sort, lookup }}
|
||||||
query={resultQuery}
|
query={resultQuery}
|
||||||
fieldName={groupBy}
|
fieldName={groupBy}
|
||||||
rankFieldName={'rank'}
|
{rankFieldName}
|
||||||
on:content={(evt) => {
|
on:content={(evt) => {
|
||||||
listProvider.update(evt.detail)
|
listProvider.update(evt.detail)
|
||||||
}}
|
}}
|
||||||
|
@ -18,6 +18,7 @@ import { Resources } from '@anticrm/platform'
|
|||||||
import { ObjectSearchResult } from '@anticrm/presentation'
|
import { ObjectSearchResult } from '@anticrm/presentation'
|
||||||
import { Issue, Team } from '@anticrm/tracker'
|
import { Issue, Team } from '@anticrm/tracker'
|
||||||
import Inbox from './components/inbox/Inbox.svelte'
|
import Inbox from './components/inbox/Inbox.svelte'
|
||||||
|
import Issues from './components/issues/Issues.svelte'
|
||||||
import Active from './components/issues/Active.svelte'
|
import Active from './components/issues/Active.svelte'
|
||||||
import AssigneePresenter from './components/issues/AssigneePresenter.svelte'
|
import AssigneePresenter from './components/issues/AssigneePresenter.svelte'
|
||||||
import Backlog from './components/issues/Backlog.svelte'
|
import Backlog from './components/issues/Backlog.svelte'
|
||||||
@ -111,6 +112,7 @@ export async function queryIssue<D extends Issue> (
|
|||||||
export default async (): Promise<Resources> => ({
|
export default async (): Promise<Resources> => ({
|
||||||
component: {
|
component: {
|
||||||
NopeComponent,
|
NopeComponent,
|
||||||
|
Issues,
|
||||||
Active,
|
Active,
|
||||||
Backlog,
|
Backlog,
|
||||||
Inbox,
|
Inbox,
|
||||||
|
@ -122,6 +122,7 @@ export default mergeIds(trackerId, tracker, {
|
|||||||
NoAssignee: '' as IntlString,
|
NoAssignee: '' as IntlString,
|
||||||
LastUpdated: '' as IntlString,
|
LastUpdated: '' as IntlString,
|
||||||
DueDate: '' as IntlString,
|
DueDate: '' as IntlString,
|
||||||
|
Manual: '' as IntlString,
|
||||||
All: '' as IntlString,
|
All: '' as IntlString,
|
||||||
PastWeek: '' as IntlString,
|
PastWeek: '' as IntlString,
|
||||||
PastMonth: '' as IntlString,
|
PastMonth: '' as IntlString,
|
||||||
@ -179,6 +180,7 @@ export default mergeIds(trackerId, tracker, {
|
|||||||
Inbox: '' as AnyComponent,
|
Inbox: '' as AnyComponent,
|
||||||
MyIssues: '' as AnyComponent,
|
MyIssues: '' as AnyComponent,
|
||||||
Views: '' as AnyComponent,
|
Views: '' as AnyComponent,
|
||||||
|
Issues: '' as AnyComponent,
|
||||||
Active: '' as AnyComponent,
|
Active: '' as AnyComponent,
|
||||||
Backlog: '' as AnyComponent,
|
Backlog: '' as AnyComponent,
|
||||||
Projects: '' as AnyComponent,
|
Projects: '' as AnyComponent,
|
||||||
|
@ -43,7 +43,8 @@ export const issuesOrderByOptions: Record<IssuesOrdering, IntlString> = {
|
|||||||
[IssuesOrdering.Status]: tracker.string.Status,
|
[IssuesOrdering.Status]: tracker.string.Status,
|
||||||
[IssuesOrdering.Priority]: tracker.string.Priority,
|
[IssuesOrdering.Priority]: tracker.string.Priority,
|
||||||
[IssuesOrdering.LastUpdated]: tracker.string.LastUpdated,
|
[IssuesOrdering.LastUpdated]: tracker.string.LastUpdated,
|
||||||
[IssuesOrdering.DueDate]: tracker.string.DueDate
|
[IssuesOrdering.DueDate]: tracker.string.DueDate,
|
||||||
|
[IssuesOrdering.Manual]: tracker.string.Manual
|
||||||
}
|
}
|
||||||
|
|
||||||
export const issuesDateModificationPeriodOptions: Record<IssuesDateModificationPeriod, IntlString> = {
|
export const issuesDateModificationPeriodOptions: Record<IssuesDateModificationPeriod, IntlString> = {
|
||||||
|
@ -54,7 +54,7 @@ export interface Selection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type IssuesGroupByKeys = keyof Pick<Issue, 'status' | 'priority' | 'assignee' | 'project'>
|
export type IssuesGroupByKeys = keyof Pick<Issue, 'status' | 'priority' | 'assignee' | 'project'>
|
||||||
export type IssuesOrderByKeys = keyof Pick<Issue, 'status' | 'priority' | 'modifiedOn' | 'dueDate'>
|
export type IssuesOrderByKeys = keyof Pick<Issue, 'status' | 'priority' | 'modifiedOn' | 'dueDate' | 'rank'>
|
||||||
|
|
||||||
export const issuesGroupKeyMap: Record<IssuesGrouping, IssuesGroupByKeys | undefined> = {
|
export const issuesGroupKeyMap: Record<IssuesGrouping, IssuesGroupByKeys | undefined> = {
|
||||||
[IssuesGrouping.Status]: 'status',
|
[IssuesGrouping.Status]: 'status',
|
||||||
@ -68,14 +68,16 @@ export const issuesOrderKeyMap: Record<IssuesOrdering, IssuesOrderByKeys> = {
|
|||||||
[IssuesOrdering.Status]: 'status',
|
[IssuesOrdering.Status]: 'status',
|
||||||
[IssuesOrdering.Priority]: 'priority',
|
[IssuesOrdering.Priority]: 'priority',
|
||||||
[IssuesOrdering.LastUpdated]: 'modifiedOn',
|
[IssuesOrdering.LastUpdated]: 'modifiedOn',
|
||||||
[IssuesOrdering.DueDate]: 'dueDate'
|
[IssuesOrdering.DueDate]: 'dueDate',
|
||||||
|
[IssuesOrdering.Manual]: 'rank'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const issuesSortOrderMap: Record<IssuesOrderByKeys, SortingOrder> = {
|
export const issuesSortOrderMap: Record<IssuesOrderByKeys, SortingOrder> = {
|
||||||
status: SortingOrder.Ascending,
|
status: SortingOrder.Ascending,
|
||||||
priority: SortingOrder.Ascending,
|
priority: SortingOrder.Ascending,
|
||||||
modifiedOn: SortingOrder.Descending,
|
modifiedOn: SortingOrder.Descending,
|
||||||
dueDate: SortingOrder.Descending
|
dueDate: SortingOrder.Descending,
|
||||||
|
rank: SortingOrder.Ascending
|
||||||
}
|
}
|
||||||
|
|
||||||
export const issuesGroupEditorMap: Record<'status' | 'priority' | 'project', AnyComponent | undefined> = {
|
export const issuesGroupEditorMap: Record<'status' | 'priority' | 'project', AnyComponent | undefined> = {
|
||||||
|
@ -82,8 +82,9 @@ export enum IssuesGrouping {
|
|||||||
export enum IssuesOrdering {
|
export enum IssuesOrdering {
|
||||||
Status = 'status',
|
Status = 'status',
|
||||||
Priority = 'priority',
|
Priority = 'priority',
|
||||||
LastUpdated = 'lastUpdated',
|
LastUpdated = 'modifiedOn',
|
||||||
DueDate = 'dueDate'
|
DueDate = 'dueDate',
|
||||||
|
Manual = 'rank'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user