Skip to content

Commit

Permalink
UBER-413: Allow extensible navigator model (#3477)
Browse files Browse the repository at this point in the history
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
  • Loading branch information
haiodo authored Jul 4, 2023
1 parent 03b9be5 commit 2869a8e
Show file tree
Hide file tree
Showing 16 changed files with 214 additions and 44 deletions.
1 change: 1 addition & 0 deletions models/board/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ export function createModel (builder: Builder): void {
navigatorModel: {
spaces: [
{
id: 'boards',
label: board.string.MyBoards,
spaceClass: board.class.Board,
addSpaceLabel: board.string.BoardCreateLabel,
Expand Down
2 changes: 2 additions & 0 deletions models/chunter/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,12 +421,14 @@ export function createModel (builder: Builder, options = { addApplication: true
],
spaces: [
{
id: 'channels',
label: chunter.string.Channels,
spaceClass: chunter.class.Channel,
addSpaceLabel: chunter.string.CreateChannel,
createComponent: chunter.component.CreateChannel
},
{
id: 'directMessages',
label: chunter.string.DirectMessages,
spaceClass: chunter.class.DirectMessage,
addSpaceLabel: chunter.string.NewDirectMessage,
Expand Down
1 change: 1 addition & 0 deletions models/lead/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export function createModel (builder: Builder): void {
],
spaces: [
{
id: 'funnels',
label: lead.string.Funnels,
spaceClass: lead.class.Funnel,
addSpaceLabel: lead.string.CreateFunnel,
Expand Down
3 changes: 2 additions & 1 deletion models/tracker/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ export function createModel (builder: Builder): void {
{
key: 'assignee',
presenter: tracker.component.AssigneeEditor,
displayProps: { key: 'assigee', fixed: 'right' },
displayProps: { key: 'assignee', fixed: 'right' },
props: { kind: 'list', shouldShowName: false, avatarSize: 'x-small' }
}
],
Expand Down Expand Up @@ -1084,6 +1084,7 @@ export function createModel (builder: Builder): void {
],
spaces: [
{
id: 'projects',
label: tracker.string.Projects,
spaceClass: tracker.class.Project,
addSpaceLabel: tracker.string.CreateProject,
Expand Down
16 changes: 14 additions & 2 deletions models/workbench/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ import preference, { TPreference } from '@hcengineering/model-preference'
import { createAction } from '@hcengineering/model-view'
import type { Asset, IntlString } from '@hcengineering/platform'
import view, { KeyBinding } from '@hcengineering/view'
import type { Application, HiddenApplication, SpaceView, ViewConfiguration } from '@hcengineering/workbench'
import type {
Application,
ApplicationNavModel,
HiddenApplication,
SpaceView,
ViewConfiguration
} from '@hcengineering/workbench'

import core, { TClass, TDoc } from '@hcengineering/model-core'
import workbench from './plugin'
Expand All @@ -37,6 +43,12 @@ export class TApplication extends TDoc implements Application {
hidden!: boolean
}

@Model(workbench.class.ApplicationNavModel, core.class.Doc, DOMAIN_MODEL)
@UX(workbench.string.Application)
export class TApplicationNavModel extends TDoc implements ApplicationNavModel {
extends!: Ref<Application>
}

@Model(workbench.class.HiddenApplication, preference.class.Preference)
export class THiddenApplication extends TPreference implements HiddenApplication {
@Prop(TypeRef(workbench.class.Application), workbench.string.HiddenApplication)
Expand All @@ -49,7 +61,7 @@ export class TSpaceView extends TClass implements SpaceView {
}

export function createModel (builder: Builder): void {
builder.createModel(TApplication, TSpaceView, THiddenApplication)
builder.createModel(TApplication, TSpaceView, THiddenApplication, TApplicationNavModel)
builder.mixin(workbench.class.Application, core.class.Class, view.mixin.ObjectPresenter, {
presenter: workbench.component.ApplicationPresenter
})
Expand Down
54 changes: 53 additions & 1 deletion packages/core/src/operations.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { deepEqual } from 'fast-equals'
import { DocumentUpdate, Hierarchy, MixinData, MixinUpdate, ModelDb, toFindResult } from '.'
import type {
Account,
Expand All @@ -15,7 +16,7 @@ import type {
import { Client } from './client'
import core from './component'
import type { DocumentQuery, FindOptions, FindResult, TxResult, WithLookup } from './storage'
import { DocumentClassQuery, Tx, TxCUD, TxFactory } from './tx'
import { DocumentClassQuery, Tx, TxCUD, TxFactory, TxProcessor } from './tx'

/**
* @public
Expand Down Expand Up @@ -269,6 +270,57 @@ export class TxOperations implements Omit<Client, 'notify'> {
apply (scope: string): ApplyOperations {
return new ApplyOperations(this, scope)
}

async diffUpdate (doc: Doc, raw: Doc | Data<Doc>, date: Timestamp): Promise<Doc> {
// We need to update fields if they are different.
const documentUpdate: DocumentUpdate<Doc> = {}
for (const [k, v] of Object.entries(raw)) {
if (['_class', '_id', 'modifiedBy', 'modifiedOn', 'space', 'attachedTo', 'attachedToClass'].includes(k)) {
continue
}
const dv = (doc as any)[k]
if (!deepEqual(dv, v) && v != null) {
;(documentUpdate as any)[k] = v
}
}
if (Object.keys(documentUpdate).length > 0) {
await this.update(doc, documentUpdate, false, date, doc.modifiedBy)
TxProcessor.applyUpdate(doc, documentUpdate)
}
return doc
}

async mixinDiffUpdate (
doc: Doc,
raw: Doc | Data<Doc>,
mixin: Ref<Class<Mixin<Doc>>>,
modifiedBy: Ref<Account>,
modifiedOn: Timestamp
): Promise<Doc> {
// We need to update fields if they are different.

if (!this.getHierarchy().hasMixin(doc, mixin)) {
await this.createMixin(doc._id, doc._class, doc.space, mixin, raw as MixinData<Doc, Doc>, modifiedOn, modifiedBy)
TxProcessor.applyUpdate(this.getHierarchy().as(doc, mixin), raw)
return doc
}

const documentUpdate: MixinUpdate<Doc, Doc> = {}
for (const [k, v] of Object.entries(raw)) {
if (['_class', '_id', 'modifiedBy', 'modifiedOn', 'space', 'attachedTo', 'attachedToClass'].includes(k)) {
continue
}
const dv = (doc as any)[k]
if (!deepEqual(dv, v) && v != null) {
;(documentUpdate as any)[k] = v
}
}
if (Object.keys(documentUpdate).length > 0) {
await this.updateMixin(doc._id, doc._class, doc.space, mixin, documentUpdate, modifiedOn, modifiedBy)
TxProcessor.applyUpdate(this.getHierarchy().as(doc, mixin), documentUpdate)
}
return doc
}
}

/**
Expand Down
21 changes: 16 additions & 5 deletions plugins/tracker-resources/src/components/issues/IssuesView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import view, { Viewlet } from '@hcengineering/view'
import {
FilterBar,
SpaceHeader,
ViewletContentView,
ViewletSettingButton,
activeViewlet,
getViewOptions,
Expand All @@ -23,8 +25,7 @@
} from '@hcengineering/view-resources'
import { onDestroy } from 'svelte'
import tracker from '../../plugin'
import IssuesContent from './IssuesContent.svelte'
import IssuesHeader from './IssuesHeader.svelte'
import CreateIssue from '../CreateIssue.svelte'
export let space: Ref<Space> | undefined = undefined
export let query: DocumentQuery<Issue> = {}
Expand Down Expand Up @@ -88,7 +89,8 @@
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
</script>

<IssuesHeader
<SpaceHeader
_class={tracker.class.Issue}
bind:viewlet
bind:search
showLabelSelector={$$slots.label_selector}
Expand Down Expand Up @@ -117,12 +119,21 @@
/>
{/if}
</svelte:fragment>
</IssuesHeader>
</SpaceHeader>
<FilterBar _class={tracker.class.Issue} query={searchQuery} {viewOptions} on:change={(e) => (resultQuery = e.detail)} />
<slot name="afterHeader" />
<div class="popupPanel rowContent">
{#if viewlet}
<IssuesContent {viewlet} query={resultQuery} {space} {viewOptions} />
<ViewletContentView
_class={tracker.class.Issue}
{viewlet}
query={resultQuery}
{space}
{viewOptions}
createItemDialog={CreateIssue}
createItemLabel={tracker.string.AddIssueTooltip}
createItemDialogProps={{ shouldSaveDraft: true }}
/>
{/if}
{#if $$slots.aside !== undefined && asideShown}
<div class="popupPanel-body__aside" class:shown={asideShown}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
themeStore
} from '@hcengineering/ui'
import { NavLink, TreeNode } from '@hcengineering/view-resources'
import { SpacesNavModel } from '@hcengineering/workbench'
import { SpacesNavModel, SpecialNavModel } from '@hcengineering/workbench'
import { SpecialElement } from '@hcengineering/workbench-resources'
import tracker from '../../plugin'
import { getResource } from '@hcengineering/platform'
export let space: Project
export let model: SpacesNavModel
Expand All @@ -38,9 +39,30 @@
const getSpaceCollapsedKey = () => `${getCurrentLocation().path[1]}_${space._id}_collapsed`
$: collapsed = localStorage.getItem(getSpaceCollapsedKey()) === COLLAPSED
let specials: SpecialNavModel[] = []
async function updateSpecials (model: SpacesNavModel, space: Project): Promise<void> {
const newSpecials: SpecialNavModel[] = []
for (const sp of model.specials ?? []) {
let shouldAdd = true
if (sp.visibleIf !== undefined) {
const visibleIf = await getResource(sp.visibleIf)
if (visibleIf !== undefined) {
shouldAdd = await visibleIf([space])
}
}
if (shouldAdd) {
newSpecials.push(sp)
}
}
specials = newSpecials
}
$: updateSpecials(model, space)
</script>

{#if model.specials}
{#if specials}
<TreeNode
{collapsed}
icon={space?.icon === tracker.component.IconWithEmoji ? IconWithEmoji : space?.icon ?? model.icon}
Expand All @@ -56,7 +78,7 @@
actions={() => getActions(space)}
on:click={() => localStorage.setItem(getSpaceCollapsedKey(), collapsed ? '' : COLLAPSED)}
>
{#each model.specials as special}
{#each specials as special}
<NavLink space={space._id} special={special.id}>
<SpecialElement
indent={'ml-2'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import view, { Viewlet } from '@hcengineering/view'
import {
FilterBar,
SpaceHeader,
ViewletSettingButton,
activeViewlet,
getViewOptions,
Expand All @@ -24,7 +25,6 @@
} from '@hcengineering/view-resources'
import { onDestroy } from 'svelte'
import tracker from '../../plugin'
import IssuesHeader from '../issues/IssuesHeader.svelte'
import CreateIssueTemplate from './CreateIssueTemplate.svelte'
import IssueTemplatesContent from './IssueTemplatesContent.svelte'
Expand Down Expand Up @@ -91,7 +91,15 @@
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
</script>

<IssuesHeader {space} {viewlets} {label} bind:viewlet bind:search showLabelSelector={$$slots.label_selector}>
<SpaceHeader
_class={tracker.class.IssueTemplate}
{space}
{viewlets}
{label}
bind:viewlet
bind:search
showLabelSelector={$$slots.label_selector}
>
<svelte:fragment slot="label_selector">
<slot name="label_selector" />
</svelte:fragment>
Expand All @@ -115,7 +123,7 @@
<ViewletSettingButton bind:viewOptions {viewlet} />
{/if}
</svelte:fragment>
</IssuesHeader>
</SpaceHeader>
<slot name="afterHeader" />
<FilterBar
_class={tracker.class.IssueTemplate}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<script lang="ts">
import { Ref, Space } from '@hcengineering/core'
import { Class, Doc, Ref, Space } from '@hcengineering/core'
import { TabList, SearchEdit, IModeSelector, ModeSelector } from '@hcengineering/ui'
import { Viewlet } from '@hcengineering/view'
import { FilterButton, setActiveViewletId } from '@hcengineering/view-resources'
import tracker from '../../plugin'
import { WithLookup } from '@hcengineering/core'
import { setActiveViewletId } from '../utils'
import FilterButton from './filter/FilterButton.svelte'
export let space: Ref<Space> | undefined = undefined
export let _class: Ref<Class<Doc>>
export let viewlet: WithLookup<Viewlet> | undefined
export let viewlets: WithLookup<Viewlet>[] = []
export let label: string
Expand Down Expand Up @@ -65,7 +66,7 @@
<SearchEdit bind:value={search} on:change={() => {}} />
<!-- <ActionIcon icon={IconMoreH} size={'small'} /> -->
<div class="buttons-divider" />
<FilterButton _class={tracker.class.Issue} {space} />
<FilterButton {_class} {space} />
</div>
<div class="ac-header-full medium-gap">
<slot name="extra" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
<script lang="ts">
import { DocumentQuery, Ref, Space, WithLookup } from '@hcengineering/core'
import { Issue } from '@hcengineering/tracker'
import { Component, Loading } from '@hcengineering/ui'
import { Class, Doc, DocumentQuery, Ref, Space, WithLookup } from '@hcengineering/core'
import { AnySvelteComponent, Component, Loading } from '@hcengineering/ui'
import view, { Viewlet, ViewletPreference, ViewOptions } from '@hcengineering/view'
import tracker from '../../plugin'
import CreateIssue from '../CreateIssue.svelte'
import { createQuery } from '@hcengineering/presentation'
import { IntlString } from '@hcengineering/platform'
export let viewlet: WithLookup<Viewlet>
export let query: DocumentQuery<Issue> = {}
export let _class: Ref<Class<Doc>>
export let query: DocumentQuery<Doc> = {}
export let space: Ref<Space> | undefined
export let viewOptions: ViewOptions
export let createItemDialog: AnySvelteComponent | undefined = undefined
export let createItemLabel: IntlString | undefined = undefined
export let createItemDialogProps = { shouldSaveDraft: true }
const preferenceQuery = createQuery()
let preference: ViewletPreference | undefined
let loading = true
Expand All @@ -29,10 +32,6 @@
},
{ limit: 1 }
)
const createItemDialog = CreateIssue
const createItemLabel = tracker.string.AddIssueTooltip
const createItemDialogProps = { shouldSaveDraft: true }
</script>

{#if viewlet?.$lookup?.descriptor?.component}
Expand All @@ -42,7 +41,7 @@
<Component
is={viewlet.$lookup.descriptor.component}
props={{
_class: tracker.class.Issue,
_class,
config: preference?.config ?? viewlet.config,
options: viewlet.options,
createItemDialog,
Expand Down
6 changes: 5 additions & 1 deletion plugins/view-resources/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ import ValueSelector from './components/ValueSelector.svelte'
import ViewletSettingButton from './components/ViewletSettingButton.svelte'
import DateFilterPresenter from './components/filter/DateFilterPresenter.svelte'
import ArrayFilter from './components/filter/ArrayFilter.svelte'
import SpaceHeader from './components/SpaceHeader.svelte'
import ViewletContentView from './components/ViewletContentView.svelte'

import {
afterResult,
Expand Down Expand Up @@ -175,7 +177,9 @@ export {
DocNavLink,
EnumEditor,
StringPresenter,
EditBoxPopup
EditBoxPopup,
SpaceHeader,
ViewletContentView
}

function PositionElementAlignment (e?: Event): PopupAlignment | undefined {
Expand Down
Loading

0 comments on commit 2869a8e

Please sign in to comment.