diff --git a/models/contact/src/index.ts b/models/contact/src/index.ts index d4deda0daa..d5ae6dcfe1 100644 --- a/models/contact/src/index.ts +++ b/models/contact/src/index.ts @@ -45,7 +45,7 @@ import attachment from '@anticrm/model-attachment' import chunter from '@anticrm/model-chunter' import core, { TAccount, TAttachedDoc, TDoc, TSpace } from '@anticrm/model-core' import presentation from '@anticrm/model-presentation' -import view, { actionTemplates, createAction } from '@anticrm/model-view' +import view, { actionTemplates, createAction, ViewAction } from '@anticrm/model-view' import workbench from '@anticrm/model-workbench' import type { Asset, IntlString } from '@anticrm/platform' import setting from '@anticrm/setting' @@ -58,6 +58,7 @@ export const DOMAIN_CHANNEL = 'channel' as Domain export class TChannelProvider extends TDoc implements ChannelProvider { label!: IntlString icon?: Asset + action?: ViewAction placeholder!: IntlString } @@ -305,7 +306,8 @@ export function createModel (builder: Builder): void { { label: contact.string.LinkedIn, icon: contact.icon.LinkedIn, - placeholder: contact.string.LinkedInPlaceholder + placeholder: contact.string.LinkedInPlaceholder, + action: contact.actionImpl.OpenChannel }, contact.channelProvider.LinkedIn ) @@ -316,7 +318,8 @@ export function createModel (builder: Builder): void { { label: contact.string.Twitter, icon: contact.icon.Twitter, - placeholder: contact.string.AtPlaceHolder + placeholder: contact.string.AtPlaceHolder, + action: contact.actionImpl.OpenChannel }, contact.channelProvider.Twitter ) @@ -327,7 +330,8 @@ export function createModel (builder: Builder): void { { label: contact.string.GitHub, icon: contact.icon.GitHub, - placeholder: contact.string.AtPlaceHolder + placeholder: contact.string.AtPlaceHolder, + action: contact.actionImpl.OpenChannel }, contact.channelProvider.GitHub ) @@ -338,7 +342,8 @@ export function createModel (builder: Builder): void { { label: contact.string.Facebook, icon: contact.icon.Facebook, - placeholder: contact.string.FacebookPlaceholder + placeholder: contact.string.FacebookPlaceholder, + action: contact.actionImpl.OpenChannel }, contact.channelProvider.Facebook ) @@ -349,7 +354,8 @@ export function createModel (builder: Builder): void { { label: contact.string.Homepage, icon: contact.icon.Homepage, - placeholder: contact.string.HomepagePlaceholder + placeholder: contact.string.HomepagePlaceholder, + action: contact.actionImpl.OpenChannel }, contact.channelProvider.Homepage ) diff --git a/models/contact/src/plugin.ts b/models/contact/src/plugin.ts index c76fffa7aa..c9dcf29872 100644 --- a/models/contact/src/plugin.ts +++ b/models/contact/src/plugin.ts @@ -83,6 +83,7 @@ export default mergeIds(contactId, contact, { KickEmployee: '' as Ref }, actionImpl: { - KickEmployee: '' as ViewAction + KickEmployee: '' as ViewAction, + OpenChannel: '' as ViewAction } }) diff --git a/models/recruit/src/index.ts b/models/recruit/src/index.ts index 0ed84278f2..728539c570 100644 --- a/models/recruit/src/index.ts +++ b/models/recruit/src/index.ts @@ -307,6 +307,7 @@ export function createModel (builder: Builder): void { label: recruit.string.Applications }, '$lookup.company', + '$lookup.company.$lookup.channels', 'location', 'description', { diff --git a/models/tracker/src/index.ts b/models/tracker/src/index.ts index 37398116fb..73641929b2 100644 --- a/models/tracker/src/index.ts +++ b/models/tracker/src/index.ts @@ -55,7 +55,8 @@ import { SprintStatus, Team, TimeSpendReport, - trackerId + trackerId, + IssueChildInfo } from '@anticrm/tracker' import { KeyBinding } from '@anticrm/view' import tracker from './plugin' @@ -238,6 +239,8 @@ export class TIssue extends TAttachedDoc implements Issue { @Prop(Collection(tracker.class.TimeSpendReport), tracker.string.TimeSpendReports) reports!: number + + declare childInfo: IssueChildInfo[] } /** diff --git a/packages/core/src/operator.ts b/packages/core/src/operator.ts index 7663e23085..3f22318a19 100644 --- a/packages/core/src/operator.ts +++ b/packages/core/src/operator.ts @@ -32,7 +32,11 @@ function $push (document: Doc, keyval: Record): void { if (typeof val === 'object') { const arr = doc[key] as Array const desc = val as Position - arr.splice(desc.$position, 0, ...desc.$each) + if ('$each' in desc) { + arr.splice(desc.$position ?? 0, 0, ...desc.$each) + } else { + arr.push(val) + } } else { doc[key].push(val) } @@ -48,7 +52,20 @@ function $pull (document: Doc, keyval: Record): void { const arr = doc[key] as Array if (typeof keyval[key] === 'object') { const { $in } = keyval[key] as PullArray - doc[key] = arr.filter((val) => !$in.includes(val)) + + doc[key] = arr.filter((val) => { + if ($in !== undefined) { + return !$in.includes(val) + } else { + // We need to match all fields + for (const [kk, kv] of Object.entries(keyval[key])) { + if (val[kk] !== kv) { + return true + } + } + return false + } + }) } else { doc[key] = arr.filter((val) => val !== keyval[key]) } diff --git a/packages/core/src/tx.ts b/packages/core/src/tx.ts index f092aea13a..9c593222d8 100644 --- a/packages/core/src/tx.ts +++ b/packages/core/src/tx.ts @@ -103,7 +103,7 @@ export interface TxMixin extends TxCUD { * @public */ export type ArrayAsElement = { - [P in keyof T]: T[P] extends Arr ? X | PullArray : never + [P in keyof T]: T[P] extends Arr ? Partial | PullArray : never } /** diff --git a/packages/query/src/index.ts b/packages/query/src/index.ts index 22dbeb5610..ccb9771fb3 100644 --- a/packages/query/src/index.ts +++ b/packages/query/src/index.ts @@ -596,10 +596,12 @@ export class LiveQuery extends TxProcessor implements Client { ;(result as any)[key] = objects[0] const nestedResult = {} const parent = (result as any)[key] - await this.getLookupValue(_class, parent, nested, nestedResult) - Object.assign(parent, { - $lookup: nestedResult - }) + if (parent !== undefined) { + await this.getLookupValue(_class, parent, nested, nestedResult) + Object.assign(parent, { + $lookup: nestedResult + }) + } } else { const objects = await this.findAll(value, { _id: getObjectValue(tkey, doc) }) ;(result as any)[key] = objects[0] diff --git a/plugins/attachment-resources/src/components/AttachmentList.svelte b/plugins/attachment-resources/src/components/AttachmentList.svelte index 1d1d4ad9b2..2a943f8ba1 100644 --- a/plugins/attachment-resources/src/components/AttachmentList.svelte +++ b/plugins/attachment-resources/src/components/AttachmentList.svelte @@ -22,9 +22,9 @@ {#if attachments.length} -
+
{#each attachments as attachment} -
+
{/each} diff --git a/plugins/contact-resources/src/components/ChannelEditor.svelte b/plugins/contact-resources/src/components/ChannelEditor.svelte index 4e56c3f15e..28f72b271b 100644 --- a/plugins/contact-resources/src/components/ChannelEditor.svelte +++ b/plugins/contact-resources/src/components/ChannelEditor.svelte @@ -13,23 +13,22 @@ // limitations under the License. --> {#if value} - + {title} {/if} @@ -56,6 +60,10 @@ color: var(--content-color); cursor: pointer; + &.noPointer { + cursor: default; + } + &:hover { color: var(--caption-color); text-decoration: underline; diff --git a/plugins/tracker-resources/src/components/issues/edit/CreateSubIssue.svelte b/plugins/tracker-resources/src/components/issues/edit/CreateSubIssue.svelte index bfab62901a..3a8b8355e6 100644 --- a/plugins/tracker-resources/src/components/issues/edit/CreateSubIssue.svelte +++ b/plugins/tracker-resources/src/components/issues/edit/CreateSubIssue.svelte @@ -24,6 +24,7 @@ import AssigneeEditor from '../AssigneeEditor.svelte' import StatusEditor from '../StatusEditor.svelte' import PriorityEditor from '../PriorityEditor.svelte' + import EstimationEditor from '../timereport/EstimationEditor.svelte' export let parentIssue: Issue export let issueStatuses: WithLookup[] @@ -55,7 +56,12 @@ dueDate: null, comments: 0, subIssues: 0, - parents: [] + parents: [], + sprint: parentIssue.sprint, + estimation: 0, + reportedTime: 0, + reports: 0, + childInfo: [] } } @@ -209,6 +215,7 @@ labels = labels.filter((it) => it._id !== evt.detail) }} /> +
- +
+ +
{/if} diff --git a/plugins/tracker-resources/src/components/issues/edit/SubIssueList.svelte b/plugins/tracker-resources/src/components/issues/edit/SubIssueList.svelte index af0af20cb3..badb4dc9bc 100644 --- a/plugins/tracker-resources/src/components/issues/edit/SubIssueList.svelte +++ b/plugins/tracker-resources/src/components/issues/edit/SubIssueList.svelte @@ -32,6 +32,7 @@ import DueDateEditor from '../DueDateEditor.svelte' import PriorityEditor from '../PriorityEditor.svelte' import StatusEditor from '../StatusEditor.svelte' + import EstimationEditor from '../timereport/EstimationEditor.svelte' export let issues: Issue[] export let issueStatuses: WithLookup[] @@ -148,6 +149,7 @@
+ {#if issue.dueDate !== null} {/if} diff --git a/plugins/tracker-resources/src/components/issues/timereport/EstimationEditor.svelte b/plugins/tracker-resources/src/components/issues/timereport/EstimationEditor.svelte index e34f84b6fe..464ee20999 100644 --- a/plugins/tracker-resources/src/components/issues/timereport/EstimationEditor.svelte +++ b/plugins/tracker-resources/src/components/issues/timereport/EstimationEditor.svelte @@ -13,15 +13,18 @@ // limitations under the License. --> {#if value} {#if kind === 'list'}
- +
- - {#if value.reportedTime > 0} -
{:else} @@ -122,5 +178,15 @@ color: var(--caption-color) !important; } } + + .showError { + color: var(--error-color) !important; + } + .showWarning { + color: var(--warning-color) !important; + } + .romColor { + color: var(--content-color) !important; + } } diff --git a/plugins/tracker-resources/src/components/issues/timereport/EstimationPopup.svelte b/plugins/tracker-resources/src/components/issues/timereport/EstimationPopup.svelte index 656acad162..f8b5852a96 100644 --- a/plugins/tracker-resources/src/components/issues/timereport/EstimationPopup.svelte +++ b/plugins/tracker-resources/src/components/issues/timereport/EstimationPopup.svelte @@ -16,14 +16,15 @@ + + +
+
{:else if value !== undefined} - {value} + + {value} + {#if childTime !== 0} + / {childTime} + {/if} + {:else} {/if} diff --git a/plugins/tracker-resources/src/components/issues/timereport/ReportsPopup.svelte b/plugins/tracker-resources/src/components/issues/timereport/ReportsPopup.svelte index c042c7e6e1..bafd4645e0 100644 --- a/plugins/tracker-resources/src/components/issues/timereport/ReportsPopup.svelte +++ b/plugins/tracker-resources/src/components/issues/timereport/ReportsPopup.svelte @@ -20,6 +20,7 @@ import { Button, eventToHTMLElement, IconAdd, Scroller, showPopup } from '@anticrm/ui' import { TableBrowser } from '@anticrm/view-resources' import tracker from '../../../plugin' + import IssuePresenter from '../IssuePresenter.svelte' import TimeSpendReportPopup from './TimeSpendReportPopup.svelte' export let issue: Issue @@ -27,7 +28,10 @@ return true } const options: FindOptions = { - lookup: { employee: contact.class.Employee } + lookup: { + attachedTo: tracker.class.Issue, + employee: contact.class.Employee + } } function addReport (event: MouseEvent): void { showPopup( @@ -45,11 +49,23 @@ okAction={() => {}} okLabel={presentation.string.Ok} > + + + it.childId)] } }} + config={[ + '$lookup.attachedTo', + '$lookup.attachedTo.title', + '', + '$lookup.employee', + 'description', + 'date', + 'modifiedOn', + 'modifiedBy' + ]} {options} /> diff --git a/plugins/tracker-resources/src/components/sprints/SprintEditor.svelte b/plugins/tracker-resources/src/components/sprints/SprintEditor.svelte index 17cad3a2a8..bc4a1e9c34 100644 --- a/plugins/tracker-resources/src/components/sprints/SprintEditor.svelte +++ b/plugins/tracker-resources/src/components/sprints/SprintEditor.svelte @@ -55,12 +55,15 @@ ) } - $: totalEstimation = (issues ?? [{ estimation: 0 }]) + $: ids = new Set(issues?.map((it) => it._id) ?? []) + + $: noParents = issues?.filter((it) => !ids.has(it.attachedTo as Ref)) + $: totalEstimation = (noParents ?? [{ estimation: 0 }]) .map((it) => it.estimation) .reduce((it, cur) => { return it + cur }) - $: totalReported = (issues ?? [{ reportedTime: 0 }]) + $: totalReported = (noParents ?? [{ reportedTime: 0 }]) .map((it) => it.reportedTime) .reduce((it, cur) => { return it + cur @@ -108,13 +111,15 @@ {@const now = Date.now()} {#if sprint.startDate < now && now < sprint.targetDate} -