diff --git a/packages/presentation/lang/en.json b/packages/presentation/lang/en.json
index dd99f49374..4ef5b5816b 100644
--- a/packages/presentation/lang/en.json
+++ b/packages/presentation/lang/en.json
@@ -28,6 +28,12 @@
"Edit": "Edit",
"SelectAvatar": "Select avatar",
"GravatarsManaged": "Gravatars are managed through",
+ "CategoryCurrentUser": "Current user",
+ "Assigned": "Assigned",
+ "CategoryPreviousAssigned": "Previously assigned",
+ "CategoryProjectLead": "Project lead",
+ "CategoryProjectMembers": "Project members",
+ "CategoryOther": "Other",
"InltPropsValue": "{value}"
}
}
diff --git a/packages/presentation/lang/ru.json b/packages/presentation/lang/ru.json
index 3381d3950b..b92cabd03e 100644
--- a/packages/presentation/lang/ru.json
+++ b/packages/presentation/lang/ru.json
@@ -22,12 +22,18 @@
"NumberSpaces": "{count, plural, =0 {В} =1 {В 1 месте} other {В # местах}}",
"InThis": "В этом {space}",
"NoMatchesInThis": "В этом {space} совпадения не обнаружены",
- "NoMatchesFound": "Не найдено соответсвий",
+ "NoMatchesFound": "Не найдено соответствий",
"NotInThis": "Не в этом {space}",
"Add": "Добавить",
"Edit": "Редактировать",
"SelectAvatar": "Выбрать аватар",
"GravatarsManaged": "Граватары управляются через",
+ "CategoryCurrentUser": "Текущий пользователь",
+ "Assigned": "Назначен",
+ "CategoryPreviousAssigned": "Ранее назначенные",
+ "CategoryProjectLead": "Руководитель проекта",
+ "CategoryProjectMembers": "Участники проекта",
+ "CategoryOther": "Прочие",
"InltPropsValue": "{value}"
}
}
diff --git a/packages/presentation/src/components/AssigneeBox.svelte b/packages/presentation/src/components/AssigneeBox.svelte
new file mode 100644
index 0000000000..d4462e97b8
--- /dev/null
+++ b/packages/presentation/src/components/AssigneeBox.svelte
@@ -0,0 +1,177 @@
+
+
+
+
+
+ {#if $$slots.content}
+
+
+
+ {:else}
+
+ {/if}
+
diff --git a/packages/presentation/src/components/AssigneePopup.svelte b/packages/presentation/src/components/AssigneePopup.svelte
new file mode 100644
index 0000000000..12954fd421
--- /dev/null
+++ b/packages/presentation/src/components/AssigneePopup.svelte
@@ -0,0 +1,285 @@
+
+
+
+
+
+
+
+
diff --git a/packages/presentation/src/index.ts b/packages/presentation/src/index.ts
index 707e27c579..20b8116fab 100644
--- a/packages/presentation/src/index.ts
+++ b/packages/presentation/src/index.ts
@@ -21,6 +21,7 @@ export { default as AttributeBarEditor } from './components/AttributeBarEditor.s
export { default as AttributeEditor } from './components/AttributeEditor.svelte'
export { default as AttributesBar } from './components/AttributesBar.svelte'
export { default as Avatar } from './components/Avatar.svelte'
+export { default as AssigneeBox } from './components/AssigneeBox.svelte'
export { default as Card } from './components/Card.svelte'
export { default as CombineAvatars } from './components/CombineAvatars.svelte'
export { default as EditableAvatar } from './components/EditableAvatar.svelte'
@@ -41,6 +42,7 @@ export { default as EmployeeBox } from './components/EmployeeBox.svelte'
export { default as UsersPopup } from './components/UsersPopup.svelte'
export { default as MembersBox } from './components/MembersBox.svelte'
export { default as IconMembers } from './components/icons/Members.svelte'
+export { default as IconPerson } from './components/icons/Person.svelte'
export { default as IconMembersOutline } from './components/icons/MembersOutline.svelte'
export { default as ObjectSearchPopup } from './components/ObjectSearchPopup.svelte'
export { default as IndexedDocumentPreview } from './components/IndexedDocumentPreview.svelte'
diff --git a/packages/presentation/src/plugin.ts b/packages/presentation/src/plugin.ts
index 4356153cad..09292049f6 100644
--- a/packages/presentation/src/plugin.ts
+++ b/packages/presentation/src/plugin.ts
@@ -57,6 +57,12 @@ export default plugin(presentationId, {
Edit: '' as IntlString,
SelectAvatar: '' as IntlString,
GravatarsManaged: '' as IntlString,
+ CategoryCurrentUser: '' as IntlString,
+ Assigned: '' as IntlString,
+ CategoryPreviousAssigned: '' as IntlString,
+ CategoryProjectLead: '' as IntlString,
+ CategoryProjectMembers: '' as IntlString,
+ CategoryOther: '' as IntlString,
InltPropsValue: '' as IntlString
},
metadata: {
diff --git a/packages/presentation/src/utils.ts b/packages/presentation/src/utils.ts
index a1311ac2c6..a0c6681824 100644
--- a/packages/presentation/src/utils.ts
+++ b/packages/presentation/src/utils.ts
@@ -34,12 +34,13 @@ import core, {
TxResult
} from '@hcengineering/core'
import login from '@hcengineering/login'
-import { getMetadata } from '@hcengineering/platform'
+import { getMetadata, IntlString } from '@hcengineering/platform'
import { LiveQuery as LQ } from '@hcengineering/query'
import { onDestroy } from 'svelte'
import { deepEqual } from 'fast-equals'
import { IconSize, DropdownIntlItem } from '@hcengineering/ui'
import contact, { AvatarType, AvatarProvider } from '@hcengineering/contact'
+import presentation from '..'
let liveQuery: LQ
let client: TxOperations
@@ -272,3 +273,43 @@ export function getAvatarProviderId (avatar?: string | null): Ref = Object.freeze({
+ CurrentUser: presentation.string.CategoryCurrentUser,
+ Assigned: presentation.string.Assigned,
+ PreviouslyAssigned: presentation.string.CategoryPreviousAssigned,
+ ProjectLead: presentation.string.CategoryProjectLead,
+ ProjectMembers: presentation.string.CategoryProjectMembers,
+ Other: presentation.string.CategoryOther
+})
+
+/**
+ * @public
+ */
+export const assigneeCategoryOrder: AssigneeCategory[] = [
+ 'CurrentUser',
+ 'Assigned',
+ 'PreviouslyAssigned',
+ 'ProjectLead',
+ 'ProjectMembers',
+ 'Other'
+]
+
+/**
+ * @public
+ */
+export function getCategorytitle (category: AssigneeCategory | undefined): IntlString {
+ const cat: AssigneeCategory = category ?? 'Other'
+ return assigneeCategoryTitleMap[cat]
+}
diff --git a/plugins/tracker-resources/src/components/issues/AssigneeEditor.svelte b/plugins/tracker-resources/src/components/issues/AssigneeEditor.svelte
index d000639779..6b8bbe71f5 100644
--- a/plugins/tracker-resources/src/components/issues/AssigneeEditor.svelte
+++ b/plugins/tracker-resources/src/components/issues/AssigneeEditor.svelte
@@ -15,11 +15,12 @@
{#if value}
-
import contact from '@hcengineering/contact'
import { Ref } from '@hcengineering/core'
- import { UserBox } from '@hcengineering/presentation'
+ import { AssigneeBox } from '@hcengineering/presentation'
import { Issue, Team } from '@hcengineering/tracker'
import { deviceOptionsStore as deviceInfo, getEventPositionElement, ListView, showPopup } from '@hcengineering/ui'
import { ContextMenu, FixedColumn, ListSelectionProvider } from '@hcengineering/view-resources'
@@ -60,21 +60,19 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/plugins/tracker-resources/src/utils.ts b/plugins/tracker-resources/src/utils.ts
index e36911b07c..ac6b973303 100644
--- a/plugins/tracker-resources/src/utils.ts
+++ b/plugins/tracker-resources/src/utils.ts
@@ -13,7 +13,19 @@
// limitations under the License.
//
-import { Doc, DocumentQuery, Ref, SortingOrder, toIdMap, TxOperations, WithLookup } from '@hcengineering/core'
+import { Employee } from '@hcengineering/contact'
+import core, {
+ AttachedData,
+ Doc,
+ DocumentQuery,
+ Ref,
+ SortingOrder,
+ toIdMap,
+ TxCollectionCUD,
+ TxOperations,
+ TxUpdateDoc,
+ WithLookup
+} from '@hcengineering/core'
import { TypeState } from '@hcengineering/kanban'
import { Asset, IntlString, translate } from '@hcengineering/platform'
import { createQuery } from '@hcengineering/presentation'
@@ -24,6 +36,7 @@ import {
IssuesGrouping,
IssuesOrdering,
IssueStatus,
+ IssueTemplateData,
ProjectStatus,
Sprint,
SprintStatus,
@@ -592,3 +605,25 @@ export function subIssueListProvider (subIssues: Issue[], target: Ref): v
listProvider.updateFocus(selectedIssue)
}
}
+
+export async function getPreviousAssignees (
+ issue: Issue | AttachedData | IssueTemplateData
+): Promise>> {
+ return await new Promise((resolve) => {
+ const query = createQuery(true)
+ query.query(
+ core.class.Tx,
+ {
+ 'tx.objectId': (issue as Issue)._id,
+ 'tx.operations.assignee': { $exists: true }
+ },
+ (res) => {
+ const prevAssignee = res
+ .map((t) => ((t as TxCollectionCUD).tx as TxUpdateDoc).operations.assignee)
+ .filter((p) => !(p == null)) as Array[>
+ resolve(prevAssignee)
+ query.unsubscribe()
+ }
+ )
+ })
+}
]