// // Copyright © 2020, 2021 Anticrm Platform Contributors. // Copyright © 2021 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. // import { Ref, SortingOrder } from '@anticrm/core' import type { Asset, IntlString } from '@anticrm/platform' import { IssuePriority, IssueStatus, Team, IssuesGrouping, IssuesOrdering, Issue, IssuesDateModificationPeriod } from '@anticrm/tracker' import { AnyComponent, getMillisecondsInMonth, MILLISECONDS_IN_WEEK } from '@anticrm/ui' import { LexoDecimal, LexoNumeralSystem36, LexoRank } from 'lexorank' import LexoRankBucket from 'lexorank/lib/lexoRank/lexoRankBucket' import tracker from './plugin' export interface NavigationItem { id: string label: IntlString icon: Asset component: AnyComponent componentProps?: Record top: boolean } export interface Selection { currentTeam?: Ref currentSpecial?: string } /** * @public */ export const genRanks = (count: number): Generator => (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() } export const issueStatuses: Record = { [IssueStatus.Backlog]: { icon: tracker.icon.StatusBacklog, label: tracker.string.Backlog }, [IssueStatus.Todo]: { icon: tracker.icon.StatusTodo, label: tracker.string.Todo }, [IssueStatus.InProgress]: { icon: tracker.icon.StatusInProgress, label: tracker.string.InProgress }, [IssueStatus.Done]: { icon: tracker.icon.StatusDone, label: tracker.string.Done }, [IssueStatus.Canceled]: { icon: tracker.icon.StatusCanceled, label: tracker.string.Canceled } } export const issuePriorities: Record = { [IssuePriority.NoPriority]: { icon: tracker.icon.PriorityNoPriority, label: tracker.string.NoPriority }, [IssuePriority.Urgent]: { icon: tracker.icon.PriorityUrgent, label: tracker.string.Urgent }, [IssuePriority.High]: { icon: tracker.icon.PriorityHigh, label: tracker.string.High }, [IssuePriority.Medium]: { icon: tracker.icon.PriorityMedium, label: tracker.string.Medium }, [IssuePriority.Low]: { icon: tracker.icon.PriorityLow, label: tracker.string.Low } } export const issuesGroupByOptions: Record = { [IssuesGrouping.Status]: tracker.string.Status, [IssuesGrouping.Assignee]: tracker.string.Assignee, [IssuesGrouping.Priority]: tracker.string.Priority, [IssuesGrouping.NoGrouping]: tracker.string.NoGrouping } export const issuesOrderByOptions: Record = { [IssuesOrdering.Status]: tracker.string.Status, [IssuesOrdering.Priority]: tracker.string.Priority, [IssuesOrdering.LastUpdated]: tracker.string.LastUpdated, [IssuesOrdering.DueDate]: tracker.string.DueDate } export const issuesDateModificationPeriodOptions: Record = { [IssuesDateModificationPeriod.All]: tracker.string.All, [IssuesDateModificationPeriod.PastWeek]: tracker.string.PastWeek, [IssuesDateModificationPeriod.PastMonth]: tracker.string.PastMonth } export type IssuesGroupByKeys = keyof Pick export type IssuesOrderByKeys = keyof Pick export const issuesGroupKeyMap: Record = { [IssuesGrouping.Status]: 'status', [IssuesGrouping.Priority]: 'priority', [IssuesGrouping.Assignee]: 'assignee', [IssuesGrouping.NoGrouping]: undefined } export const issuesOrderKeyMap: Record = { [IssuesOrdering.Status]: 'status', [IssuesOrdering.Priority]: 'priority', [IssuesOrdering.LastUpdated]: 'modifiedOn', [IssuesOrdering.DueDate]: 'dueDate' } export const issuesSortOrderMap: Record = { status: SortingOrder.Ascending, priority: SortingOrder.Ascending, modifiedOn: SortingOrder.Descending, dueDate: SortingOrder.Descending } export const issuesGroupPresenterMap: Record = { status: tracker.component.StatusPresenter, priority: tracker.component.PriorityPresenter, assignee: tracker.component.AssigneePresenter } export const defaultIssueCategories: Partial | undefined>> = { status: [IssueStatus.InProgress, IssueStatus.Todo, IssueStatus.Backlog, IssueStatus.Done, IssueStatus.Canceled], priority: [IssuePriority.NoPriority, IssuePriority.Urgent, IssuePriority.High, IssuePriority.Medium, IssuePriority.Low] } export const getIssuesModificationDatePeriodTime = ( period: IssuesDateModificationPeriod | null ): number => { const today = new Date(Date.now()) switch (period) { case IssuesDateModificationPeriod.PastWeek: { return today.getTime() - MILLISECONDS_IN_WEEK } case IssuesDateModificationPeriod.PastMonth: { return today.getTime() - getMillisecondsInMonth(today) } default: { return 0 } } }