diff --git a/packages/presentation/src/components/ObjectPopup.svelte b/packages/presentation/src/components/ObjectPopup.svelte index 6459629798..0336c98c05 100644 --- a/packages/presentation/src/components/ObjectPopup.svelte +++ b/packages/presentation/src/components/ObjectPopup.svelte @@ -58,6 +58,8 @@ let search: string = '' let objects: Doc[] = [] + $: selectedElements = new Set(selectedObjects) + const dispatch = createEventDispatcher() const query = createQuery() $: query.query( @@ -73,15 +75,18 @@ { ...(options ?? {}), limit: 200 } ) - const isSelected = (person: Doc): boolean => { - if (selectedObjects.filter((p) => p === person._id).length > 0) return true - return false - } const checkSelected = (person: Doc, objects: Doc[]): void => { - selectedObjects = isSelected(person) - ? selectedObjects.filter((p) => p !== person._id) - : [...selectedObjects, person._id] + if (selectedElements.has(person._id)) { + selectedElements.delete(person._id) + } else { + selectedElements.add(person._id) + } + + selectedObjects = Array.from(selectedElements) + dispatch('update', selectedObjects) + + selectedElements = selectedElements } const client = getClient() @@ -168,7 +173,7 @@ > {#if multiSelect}
- +
{/if} diff --git a/packages/ui/src/components/Button.svelte b/packages/ui/src/components/Button.svelte index f44e7e6c2d..457e7e0a2a 100644 --- a/packages/ui/src/components/Button.svelte +++ b/packages/ui/src/components/Button.svelte @@ -231,6 +231,16 @@ background-color: var(--button-disabled-color); border-color: transparent; } + + &.selected { + background-color: var(--button-bg-hover); + border-color: var(--button-border-hover); + color: var(--caption-color); + + .btn-icon { + color: var(--accent-color); + } + } } &.no-border { font-weight: 400; @@ -275,10 +285,10 @@ } &.link-bordered { padding: 0 0.375rem; - color: var(--acctent-color); + color: var(--accent-color); border-color: var(--button-border-color); &:hover { - color: var(--acctent-color); + color: var(--accent-color); border-color: var(--button-border-hover); .btn-icon { color: var(--accent-color); diff --git a/plugins/activity-assets/src/tsdoc-metadata.json b/plugins/activity-assets/src/tsdoc-metadata.json index 1de76b30c9..83b5aaf730 100644 --- a/plugins/activity-assets/src/tsdoc-metadata.json +++ b/plugins/activity-assets/src/tsdoc-metadata.json @@ -1,11 +1,11 @@ -// This file is read by tools that parse documentation comments conforming to the TSDoc standard. -// It should be published with your NPM package. It should not be tracked by Git. -{ - "tsdocVersion": "0.12", - "toolPackages": [ - { - "packageName": "@microsoft/api-extractor", - "packageVersion": "7.23.0" - } - ] -} +// This file is read by tools that parse documentation comments conforming to the TSDoc standard. +// It should be published with your NPM package. It should not be tracked by Git. +{ + "tsdocVersion": "0.12", + "toolPackages": [ + { + "packageName": "@microsoft/api-extractor", + "packageVersion": "7.23.0" + } + ] +} diff --git a/plugins/contact-resources/src/components/EmployeePresenter.svelte b/plugins/contact-resources/src/components/EmployeePresenter.svelte index 16852001ce..03eb214baf 100644 --- a/plugins/contact-resources/src/components/EmployeePresenter.svelte +++ b/plugins/contact-resources/src/components/EmployeePresenter.svelte @@ -8,10 +8,12 @@ export let value: WithLookup export let shouldShowAvatar: boolean = true + export let shouldShowName: boolean = true + export let onEmployeeEdit: ((event: MouseEvent) => void) | undefined = undefined let container: HTMLElement - function onEdit () { + const onEdit = () => { showPopup( EmployeePreviewPopup, { @@ -20,11 +22,13 @@ container ) } + + $: handlePersonEdit = onEmployeeEdit ?? onEdit
-
- +
+
{#if value.$lookup?.statuses?.length}
diff --git a/plugins/contact-resources/src/components/PersonContent.svelte b/plugins/contact-resources/src/components/PersonContent.svelte index 2932bc5523..df15f1b029 100644 --- a/plugins/contact-resources/src/components/PersonContent.svelte +++ b/plugins/contact-resources/src/components/PersonContent.svelte @@ -100,7 +100,7 @@ } } .eContentPresenterIcon { - margin-right: 0.5rem; + margin-right: 0.25rem; color: var(--theme-content-dark-color); } .eContentPresenterLabel { diff --git a/plugins/tracker-assets/assets/icons.svg b/plugins/tracker-assets/assets/icons.svg index 33ee43b95e..e6d6bb4a7c 100644 --- a/plugins/tracker-assets/assets/icons.svg +++ b/plugins/tracker-assets/assets/icons.svg @@ -94,4 +94,20 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/tracker-assets/lang/en.json b/plugins/tracker-assets/lang/en.json index 869fe2f834..d3843e428c 100644 --- a/plugins/tracker-assets/lang/en.json +++ b/plugins/tracker-assets/lang/en.json @@ -17,6 +17,10 @@ "Backlog": "Backlog", "Board": "Board", "Projects": "Projects", + "AllProjects": "All", + "BacklogProjects": "Backlog", + "ActiveProjects": "Active", + "ClosedProjects": "Closed", "NewProject": "New project", "CreateProject": "Create project", "ProjectNamePlaceholder": "Project name", @@ -101,6 +105,10 @@ "AddToProject": "Add to project\u2026", "MoveToProject": "Move to project\u2026", "NoProject": "No project", + "ProjectLeadTitle": "Project lead", + "ProjectMembersTitle": "Project members", + "ProjectLeadSearchPlaceholder": "Set project lead\u2026", + "ProjectMembersSearchPlaceholder": "Change project members\u2026", "GotoIssues": "Go to issues", "GotoActive": "Go to active issues", diff --git a/plugins/tracker-assets/src/index.ts b/plugins/tracker-assets/src/index.ts index 6a629be462..722d58e518 100644 --- a/plugins/tracker-assets/src/index.ts +++ b/plugins/tracker-assets/src/index.ts @@ -45,7 +45,11 @@ loadMetadata(tracker.icon, { PriorityUrgent: `${icons}#priority-urgent`, PriorityHigh: `${icons}#priority-high`, PriorityMedium: `${icons}#priority-medium`, - PriorityLow: `${icons}#priority-low` + PriorityLow: `${icons}#priority-low`, + + ProjectsList: `${icons}#list`, + ProjectsTimeline: `${icons}#timeline`, + ProjectMembers: `${icons}#projectMembers` }) addStringsLoader(trackerId, async (lang: string) => await import(`../lang/${lang}.json`)) diff --git a/plugins/tracker-resources/src/components/CommonTrackerDatePresenter.svelte b/plugins/tracker-resources/src/components/CommonTrackerDatePresenter.svelte new file mode 100644 index 0000000000..b0e6eef18a --- /dev/null +++ b/plugins/tracker-resources/src/components/CommonTrackerDatePresenter.svelte @@ -0,0 +1,72 @@ + + + +{#if shouldRender} + {#if formattedDate} + + + + {:else} + + {/if} +{/if} diff --git a/plugins/tracker-resources/src/components/issues/DueDatePopup.svelte b/plugins/tracker-resources/src/components/DueDatePopup.svelte similarity index 98% rename from plugins/tracker-resources/src/components/issues/DueDatePopup.svelte rename to plugins/tracker-resources/src/components/DueDatePopup.svelte index 2807086745..c151428198 100644 --- a/plugins/tracker-resources/src/components/issues/DueDatePopup.svelte +++ b/plugins/tracker-resources/src/components/DueDatePopup.svelte @@ -14,7 +14,7 @@ --> -{#if shouldRenderPresenter} - - - -{/if} + diff --git a/plugins/tracker-resources/src/components/projects/IconPresenter.svelte b/plugins/tracker-resources/src/components/projects/IconPresenter.svelte new file mode 100644 index 0000000000..3bcf174255 --- /dev/null +++ b/plugins/tracker-resources/src/components/projects/IconPresenter.svelte @@ -0,0 +1,23 @@ + + + +
- { - newStatus !== undefined && (object.status = newStatus) - }} - /> + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- - - diff --git a/plugins/tracker-resources/src/components/projects/ProjectsList.svelte b/plugins/tracker-resources/src/components/projects/ProjectsList.svelte new file mode 100644 index 0000000000..92ae7ad0b2 --- /dev/null +++ b/plugins/tracker-resources/src/components/projects/ProjectsList.svelte @@ -0,0 +1,246 @@ + + + +{#await buildModel({ client, _class, keys: itemsConfig, lookup: options.lookup }) then itemModels} +
+ {#if projects} + {#each projects as docObject (docObject._id)} +
x === docObject)]} + class="listGrid" + class:mListGridChecked={selectedObjectIdsSet.has(docObject._id)} + class:mListGridFixed={selectedRowIndex === projects.findIndex((x) => x === docObject)} + class:mListGridSelected={selectedRowIndex === projects.findIndex((x) => x === docObject)} + on:focus={() => {}} + on:mouseover={() => handleRowFocused(docObject)} + > +
+ {#each itemModels as attributeModel, attributeModelIndex} + {#if attributeModelIndex === 0} +
+ +
+ { + onObjectChecked([docObject], event.detail) + }} + /> +
+
+
+ +
+
+ {:else if attributeModelIndex === 1} +
+ +
+
+ {:else} +
+ +
+ {/if} + {/each} +
+
+ {/each} + {:else if loadingProps !== undefined} + {#each Array(getLoadingElementsLength(loadingProps, options)) as _, rowIndex} +
+
+
+ +
+ +
+
+
+
+ {/each} + {/if} +
+{/await} + + diff --git a/plugins/tracker-resources/src/components/projects/ProjectsListBrowser.svelte b/plugins/tracker-resources/src/components/projects/ProjectsListBrowser.svelte new file mode 100644 index 0000000000..5eaae64f7f --- /dev/null +++ b/plugins/tracker-resources/src/components/projects/ProjectsListBrowser.svelte @@ -0,0 +1,72 @@ + + + + + + { + listProvider.updateFocus(event.detail ?? undefined) + }} + on:check={(event) => { + listProvider.updateSelection(event.detail.docs, event.detail.value) + }} +/> diff --git a/plugins/tracker-resources/src/components/projects/TargetDatePresenter.svelte b/plugins/tracker-resources/src/components/projects/TargetDatePresenter.svelte new file mode 100644 index 0000000000..8e768e4983 --- /dev/null +++ b/plugins/tracker-resources/src/components/projects/TargetDatePresenter.svelte @@ -0,0 +1,31 @@ + + + + diff --git a/plugins/tracker-resources/src/index.ts b/plugins/tracker-resources/src/index.ts index bd6e6946c3..d7eb3371ae 100644 --- a/plugins/tracker-resources/src/index.ts +++ b/plugins/tracker-resources/src/index.ts @@ -37,6 +37,11 @@ import StatusEditor from './components/issues/StatusEditor.svelte' import DueDatePresenter from './components/issues/DueDatePresenter.svelte' import AssigneePresenter from './components/issues/AssigneePresenter.svelte' import ViewOptionsPopup from './components/issues/ViewOptionsPopup.svelte' +import IconPresenter from './components/projects/IconPresenter.svelte' +import LeadPresenter from './components/projects/LeadPresenter.svelte' +import TargetDatePresenter from './components/projects/TargetDatePresenter.svelte' +import ProjectMembersPresenter from './components/projects/ProjectMembersPresenter.svelte' +import ProjectStatusPresenter from './components/projects/ProjectStatusPresenter.svelte' import ModificationDatePresenter from './components/issues/ModificationDatePresenter.svelte' import EditIssue from './components/issues/edit/EditIssue.svelte' @@ -67,6 +72,11 @@ export default async (): Promise => ({ DueDatePresenter, EditIssue, NewIssueHeader, - ViewOptionsPopup + ViewOptionsPopup, + IconPresenter, + LeadPresenter, + TargetDatePresenter, + ProjectMembersPresenter, + ProjectStatusPresenter } }) diff --git a/plugins/tracker-resources/src/plugin.ts b/plugins/tracker-resources/src/plugin.ts index 042b23c1a5..adda2e92f6 100644 --- a/plugins/tracker-resources/src/plugin.ts +++ b/plugins/tracker-resources/src/plugin.ts @@ -36,6 +36,10 @@ export default mergeIds(trackerId, tracker, { Board: '' as IntlString, Project: '' as IntlString, Projects: '' as IntlString, + AllProjects: '' as IntlString, + BacklogProjects: '' as IntlString, + ActiveProjects: '' as IntlString, + ClosedProjects: '' as IntlString, NewProject: '' as IntlString, CreateProject: '' as IntlString, ProjectNamePlaceholder: '' as IntlString, @@ -119,6 +123,10 @@ export default mergeIds(trackerId, tracker, { AddToProject: '' as IntlString, MoveToProject: '' as IntlString, NoProject: '' as IntlString, + ProjectLeadTitle: '' as IntlString, + ProjectMembersTitle: '' as IntlString, + ProjectLeadSearchPlaceholder: '' as IntlString, + ProjectMembersSearchPlaceholder: '' as IntlString, IssueTitlePlaceholder: '' as IntlString, IssueDescriptionPlaceholder: '' as IntlString, @@ -160,6 +168,11 @@ export default mergeIds(trackerId, tracker, { DueDatePresenter: '' as AnyComponent, EditIssue: '' as AnyComponent, CreateTeam: '' as AnyComponent, - NewIssueHeader: '' as AnyComponent + NewIssueHeader: '' as AnyComponent, + IconPresenter: '' as AnyComponent, + LeadPresenter: '' as AnyComponent, + TargetDatePresenter: '' as AnyComponent, + ProjectMembersPresenter: '' as AnyComponent, + ProjectStatusPresenter: '' as AnyComponent } }) diff --git a/plugins/tracker-resources/src/utils.ts b/plugins/tracker-resources/src/utils.ts index 3787d18c9f..60d1c168cc 100644 --- a/plugins/tracker-resources/src/utils.ts +++ b/plugins/tracker-resources/src/utils.ts @@ -114,8 +114,16 @@ export const getIssuesModificationDatePeriodTime = (period: IssuesDateModificati } } +export const defaultProjectStatuses = [ + ProjectStatus.Planned, + ProjectStatus.InProgress, + ProjectStatus.Paused, + ProjectStatus.Completed, + ProjectStatus.Canceled +] + // TODO: update icons -export const projectStatuses: Record = { +export const projectStatusAssets: Record = { [ProjectStatus.Planned]: { icon: tracker.icon.CategoryBacklog, label: tracker.string.Planned }, [ProjectStatus.InProgress]: { icon: tracker.icon.CategoryStarted, label: tracker.string.InProgress }, [ProjectStatus.Paused]: { icon: tracker.icon.CategoryUnstarted, label: tracker.string.Paused }, diff --git a/plugins/tracker/src/index.ts b/plugins/tracker/src/index.ts index 1c31dd29b9..e1aac1592b 100644 --- a/plugins/tracker/src/index.ts +++ b/plugins/tracker/src/index.ts @@ -226,6 +226,10 @@ export default plugin(trackerId, { PriorityUrgent: '' as Asset, PriorityHigh: '' as Asset, PriorityMedium: '' as Asset, - PriorityLow: '' as Asset + PriorityLow: '' as Asset, + + ProjectsList: '' as Asset, + ProjectsTimeline: '' as Asset, + ProjectMembers: '' as Asset } })