mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-14 12:25:17 +00:00
parent
e7c0f2406a
commit
8c51a4ec2c
@ -56,34 +56,14 @@ module.exports = {
|
||||
{
|
||||
test: /\.svelte$/,
|
||||
use: {
|
||||
loader: 'svelte-loader',
|
||||
loader: 'svelte-loader',
|
||||
options: {
|
||||
compilerOptions: {
|
||||
dev: !prod,
|
||||
},
|
||||
emitCss: true,
|
||||
preprocess: require('svelte-preprocess')({ postcss: true })
|
||||
}
|
||||
// options: {
|
||||
// dev: !prod,
|
||||
// emitCss: true,
|
||||
// hotReload: !prod,
|
||||
// preprocess: require('svelte-preprocess')({
|
||||
// babel: {
|
||||
// presets: [
|
||||
// [
|
||||
// '@babel/preset-env',
|
||||
// {
|
||||
// loose: true,
|
||||
// modules: false,
|
||||
// targets: {
|
||||
// esmodules: true
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
// '@babel/typescript'
|
||||
// ],
|
||||
// plugins: ['@babel/plugin-proposal-optional-chaining']
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
preprocess: require('svelte-preprocess')({ postcss: true })
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -129,6 +129,14 @@ export function createModel (builder: Builder): void {
|
||||
icon: contact.icon.Person,
|
||||
label: recruit.string.Candidates,
|
||||
position: 'bottom'
|
||||
},
|
||||
{
|
||||
id: 'archive',
|
||||
component: workbench.component.Archive,
|
||||
icon: view.icon.Archive,
|
||||
label: workbench.string.Archive,
|
||||
position: 'top',
|
||||
visibleIf: workbench.function.HasArchiveSpaces
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -287,6 +295,22 @@ export function createModel (builder: Builder): void {
|
||||
label: recruit.string.SearchApplication,
|
||||
query: recruit.completion.ApplicationQuery
|
||||
}, recruit.completion.ApplicationCategory)
|
||||
|
||||
builder.createDoc(view.class.ActionTarget, core.space.Model, {
|
||||
target: recruit.class.Vacancy,
|
||||
action: task.action.ArchiveSpace,
|
||||
query: {
|
||||
archived: false
|
||||
}
|
||||
})
|
||||
|
||||
builder.createDoc(view.class.ActionTarget, core.space.Model, {
|
||||
target: recruit.class.Vacancy,
|
||||
action: task.action.UnarchiveSpace,
|
||||
query: {
|
||||
archived: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export { default } from './plugin'
|
||||
|
@ -404,22 +404,6 @@ export function createModel (builder: Builder): void {
|
||||
}
|
||||
})
|
||||
|
||||
builder.createDoc(view.class.ActionTarget, core.space.Model, {
|
||||
target: task.class.SpaceWithStates,
|
||||
action: task.action.ArchiveSpace,
|
||||
query: {
|
||||
archived: false
|
||||
}
|
||||
})
|
||||
|
||||
builder.createDoc(view.class.ActionTarget, core.space.Model, {
|
||||
target: task.class.SpaceWithStates,
|
||||
action: task.action.UnarchiveSpace,
|
||||
query: {
|
||||
archived: true
|
||||
}
|
||||
})
|
||||
|
||||
builder.mixin(task.class.State, core.class.Class, view.mixin.AttributeEditor, {
|
||||
editor: task.component.StateEditor
|
||||
})
|
||||
|
@ -13,12 +13,20 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { mergeIds } from '@anticrm/platform'
|
||||
import { Space } from '@anticrm/core'
|
||||
import { IntlString, mergeIds, Resource } from '@anticrm/platform'
|
||||
import { AnyComponent } from '@anticrm/ui'
|
||||
import workbench, { workbenchId } from '@anticrm/workbench'
|
||||
|
||||
export default mergeIds(workbenchId, workbench, {
|
||||
component: {
|
||||
ApplicationPresenter: '' as AnyComponent
|
||||
ApplicationPresenter: '' as AnyComponent,
|
||||
Archive: '' as AnyComponent
|
||||
},
|
||||
string: {
|
||||
Archive: '' as IntlString
|
||||
},
|
||||
function: {
|
||||
HasArchiveSpaces: '' as Resource<(spaces: Space[]) => boolean>
|
||||
}
|
||||
})
|
||||
|
@ -15,8 +15,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import { ActionIcon, IconMoreH, Label } from '@anticrm/ui'
|
||||
import workbench from '../plugin'
|
||||
import { Label } from '@anticrm/ui'
|
||||
|
||||
export let label: IntlString
|
||||
// export let action: () => Promise<void> | void
|
||||
|
@ -14,78 +14,91 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import core from '@anticrm/core'
|
||||
import type { Space } from '@anticrm/core'
|
||||
import type { NavigatorModel, SpecialNavModel } from '@anticrm/workbench'
|
||||
import { getCurrentLocation, navigate, Scroller } from '@anticrm/ui'
|
||||
import core, { Ref, SortingOrder, Space } from '@anticrm/core'
|
||||
import { getResource } from '@anticrm/platform'
|
||||
import { createQuery } from '@anticrm/presentation'
|
||||
import view from '@anticrm/view'
|
||||
|
||||
import workbench from '../plugin'
|
||||
|
||||
import { Scroller } from '@anticrm/ui'
|
||||
import type { NavigatorModel, SpecialNavModel } from '@anticrm/workbench'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import SpacesNav from './navigator/SpacesNav.svelte'
|
||||
import TreeSeparator from './navigator/TreeSeparator.svelte'
|
||||
import SpecialElement from './navigator/SpecialElement.svelte'
|
||||
import TreeSeparator from './navigator/TreeSeparator.svelte'
|
||||
|
||||
export let model: NavigatorModel | undefined
|
||||
export let currentSpace: Ref<Space> | undefined
|
||||
export let currentSpecial: string | undefined
|
||||
|
||||
const query = createQuery()
|
||||
let archivedSpaces: Space[] = []
|
||||
let spaces: Space[] = []
|
||||
let shownSpaces: Space[] = []
|
||||
$: if (model) {
|
||||
query.query(
|
||||
core.class.Space,
|
||||
{
|
||||
_class: { $in: model.spaces.map(x => x.spaceClass) },
|
||||
archived: true
|
||||
_class: { $in: model.spaces.map(x => x.spaceClass) }
|
||||
},
|
||||
(result) => { archivedSpaces = result })
|
||||
(result) => { spaces = result },
|
||||
{ sort: { name: SortingOrder.Ascending } })
|
||||
}
|
||||
|
||||
let showDivider: Boolean = false
|
||||
let specTopCount: number
|
||||
let specBottomCount: number
|
||||
let spArchCount: number
|
||||
let spModelCount: number
|
||||
$: if (model) {
|
||||
if (model.specials) {
|
||||
specTopCount = getSpecials(model.specials, 'top').length
|
||||
specBottomCount = getSpecials(model.specials, 'bottom').length
|
||||
|
||||
let topSpecials: SpecialNavModel[] = []
|
||||
let bottomSpecials: SpecialNavModel[] = []
|
||||
|
||||
async function update (model: NavigatorModel, spaces: Space[]) {
|
||||
if (model.specials !== undefined) {
|
||||
topSpecials = await getSpecials(model.specials, 'top', spaces)
|
||||
specTopCount = topSpecials.length
|
||||
bottomSpecials = await getSpecials(model.specials, 'bottom', spaces)
|
||||
specBottomCount = bottomSpecials.length
|
||||
}
|
||||
if (model.spaces) spModelCount = model.spaces.length
|
||||
if (archivedSpaces) spArchCount = archivedSpaces.length
|
||||
showDivider = ((specTopCount > 0 || spArchCount > 0) && (specBottomCount > 0 || spModelCount > 0)) ?? false
|
||||
showDivider = (specTopCount > 0) ?? false
|
||||
|
||||
shownSpaces = spaces.filter(sp => !sp.archived)
|
||||
}
|
||||
|
||||
function selectSpecial (id: string): void {
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[2] = id
|
||||
loc.path.length = 3
|
||||
navigate(loc)
|
||||
}
|
||||
function getSpecials (specials: SpecialNavModel[], state: 'top' | 'bottom'): SpecialNavModel[] {
|
||||
return specials.filter(p => (p.position ?? 'top') === state)
|
||||
$: if (model) update(model, spaces)
|
||||
|
||||
async function getSpecials (specials: SpecialNavModel[], state: 'top' | 'bottom', spaces: Space[]): Promise<SpecialNavModel[]> {
|
||||
const result: SpecialNavModel[] = []
|
||||
for (const sp of specials) {
|
||||
if ((sp.position ?? 'top') === state) {
|
||||
if (sp.visibleIf !== undefined) {
|
||||
const f = await getResource(sp.visibleIf)
|
||||
if (f(spaces)) {
|
||||
result.push(sp)
|
||||
}
|
||||
} else {
|
||||
result.push(sp)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
{#if model}
|
||||
<Scroller>
|
||||
{#if model.specials}
|
||||
{#each getSpecials(model.specials, 'top') as special}
|
||||
<SpecialElement label={special.label} icon={special.icon} on:click={() => selectSpecial(special.id)} />
|
||||
{#each topSpecials as special}
|
||||
<SpecialElement label={special.label} icon={special.icon} on:click={() => dispatch('special', special.id)} selected={special.id === currentSpecial} />
|
||||
{/each}
|
||||
{/if}
|
||||
{#if archivedSpaces.length > 0}
|
||||
<SpecialElement label={workbench.string.Archive} icon={view.icon.Archive} on:click={() => selectSpecial('archive')} />
|
||||
{/if}
|
||||
|
||||
{#if showDivider}<TreeSeparator />{/if}
|
||||
|
||||
{#each model.spaces as m (m.label)}
|
||||
<SpacesNav model={m}/>
|
||||
<SpacesNav spaces={shownSpaces} {currentSpace} model={m} on:space/>
|
||||
{/each}
|
||||
{#if model.specials}
|
||||
{#each getSpecials(model.specials, 'bottom') as special}
|
||||
<SpecialElement label={special.label} icon={special.icon} on:click={() => selectSpecial(special.id)} />
|
||||
{#each bottomSpecials as special}
|
||||
<SpecialElement label={special.label} icon={special.icon} on:click={() => dispatch('special', special.id)} selected={special.id === currentSpecial} />
|
||||
{/each}
|
||||
{/if}
|
||||
<div class="antiNav-space" />
|
||||
|
@ -13,15 +13,15 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Client, getCurrentAccount, Ref, Space } from '@anticrm/core'
|
||||
import core from '@anticrm/core'
|
||||
import contact, { Employee, EmployeeAccount } from '@anticrm/contact'
|
||||
import core, { Client, getCurrentAccount, Ref, Space } from '@anticrm/core'
|
||||
import { Avatar, createQuery, setClient } from '@anticrm/presentation'
|
||||
import {
|
||||
AnyComponent,
|
||||
AnySvelteComponent,
|
||||
closeTooltip,
|
||||
AnyComponent, closeTooltip,
|
||||
Component,
|
||||
getCurrentLocation,
|
||||
location,
|
||||
navigate,
|
||||
Popup,
|
||||
showPopup,
|
||||
TooltipInstance
|
||||
@ -33,62 +33,93 @@
|
||||
import ActivityStatus from './ActivityStatus.svelte'
|
||||
import AppItem from './AppItem.svelte'
|
||||
import Applications from './Applications.svelte'
|
||||
import Archive from './Archive.svelte'
|
||||
import TopMenu from './icons/TopMenu.svelte'
|
||||
import NavHeader from './NavHeader.svelte'
|
||||
import Navigator from './Navigator.svelte'
|
||||
import SpaceView from './SpaceView.svelte'
|
||||
import contact, { Employee, EmployeeAccount } from '@anticrm/contact'
|
||||
|
||||
export let client: Client
|
||||
|
||||
setClient(client)
|
||||
|
||||
let currentApp: Ref<Application> | undefined
|
||||
let currentApplication: Application | undefined
|
||||
let currentSpace: Ref<Space> | undefined
|
||||
let ownSpecialComponent: AnySvelteComponent | undefined
|
||||
let currentSpecial: string | undefined
|
||||
let specialComponent: AnyComponent | undefined
|
||||
|
||||
let currentApplication: Application | undefined
|
||||
let currentView: ViewConfiguration | undefined
|
||||
let createItemDialog: AnyComponent | undefined
|
||||
let navigatorModel: NavigatorModel | undefined
|
||||
|
||||
onDestroy(
|
||||
location.subscribe(async (loc) => {
|
||||
currentApp = loc.path[1] as Ref<Application>
|
||||
currentApplication = await client.findOne(workbench.class.Application, { _id: currentApp })
|
||||
navigatorModel = currentApplication?.navigatorModel
|
||||
if (currentApp !== loc.path[1]) {
|
||||
currentApp = loc.path[1] as Ref<Application>
|
||||
currentApplication = await client.findOne(workbench.class.Application, { _id: currentApp })
|
||||
navigatorModel = currentApplication?.navigatorModel
|
||||
}
|
||||
const currentFolder = loc.path[2] as Ref<Space>
|
||||
ownSpecialComponent = getOwnSpecialComponent(currentFolder)
|
||||
|
||||
if (ownSpecialComponent !== undefined) {
|
||||
return
|
||||
|
||||
if (currentSpecial !== currentFolder) {
|
||||
specialComponent = getSpecialComponent(currentFolder)
|
||||
if (specialComponent !== undefined) {
|
||||
currentSpecial = currentFolder
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
specialComponent = getSpecialComponent(currentFolder)
|
||||
|
||||
if (specialComponent !== undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
const space = await client.findOne(core.class.Space, { _id: currentFolder })
|
||||
currentSpace = currentFolder
|
||||
if (space) {
|
||||
const spaceClass = client.getHierarchy().getClass(space._class) // (await client.findAll(core.class.Class, { _id: space._class }))[0]
|
||||
const view = client.getHierarchy().as(spaceClass, workbench.mixin.SpaceView)
|
||||
currentView = view.view
|
||||
createItemDialog = currentView.createItemDialog
|
||||
} else {
|
||||
currentView = undefined
|
||||
createItemDialog = undefined
|
||||
}
|
||||
updateSpace(currentSpace)
|
||||
})
|
||||
)
|
||||
|
||||
function getOwnSpecialComponent (id: string): AnySvelteComponent | undefined {
|
||||
if (id === 'archive') {
|
||||
return Archive
|
||||
async function updateSpace (spaceId?: Ref<Space>): Promise<void> {
|
||||
if (spaceId === currentSpace) {
|
||||
return
|
||||
}
|
||||
if (spaceId === undefined) {
|
||||
return
|
||||
}
|
||||
const space = await client.findOne(core.class.Space, { _id: spaceId })
|
||||
if (space) {
|
||||
currentSpace = spaceId
|
||||
currentSpecial = undefined
|
||||
|
||||
const spaceClass = client.getHierarchy().getClass(space._class) // (await client.findAll(core.class.Class, { _id: space._class }))[0]
|
||||
const view = client.getHierarchy().as(spaceClass, workbench.mixin.SpaceView)
|
||||
currentView = view.view
|
||||
createItemDialog = currentView.createItemDialog
|
||||
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[2] = spaceId
|
||||
loc.path.length = 3
|
||||
navigate(loc)
|
||||
} else {
|
||||
currentView = undefined
|
||||
createItemDialog = undefined
|
||||
}
|
||||
}
|
||||
$: updateSpace(currentSpace)
|
||||
|
||||
function selectSpecial (id: string): void {
|
||||
specialComponent = getSpecialComponent(id)
|
||||
if (specialComponent !== undefined) {
|
||||
currentSpecial = id
|
||||
currentSpace = undefined
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[2] = id
|
||||
loc.path.length = 3
|
||||
navigate(loc)
|
||||
}
|
||||
}
|
||||
|
||||
function selectArchive (): void {
|
||||
currentSpace = undefined
|
||||
currentSpecial = undefined
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[2] = 'archive'
|
||||
loc.path.length = 3
|
||||
navigate(loc)
|
||||
}
|
||||
|
||||
function getSpecialComponent (id: string): AnyComponent | undefined {
|
||||
@ -112,17 +143,28 @@
|
||||
let employee: Employee | undefined
|
||||
const accountQ = createQuery()
|
||||
const employeeQ = createQuery()
|
||||
$: accountQ.query(contact.class.EmployeeAccount, {
|
||||
_id: getCurrentAccount()._id as Ref<EmployeeAccount>
|
||||
}, (res) => {
|
||||
account = res[0]
|
||||
}, { limit: 1 })
|
||||
$: accountQ.query(
|
||||
contact.class.EmployeeAccount,
|
||||
{
|
||||
_id: getCurrentAccount()._id as Ref<EmployeeAccount>
|
||||
},
|
||||
(res) => {
|
||||
account = res[0]
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
|
||||
$: account && employeeQ.query(contact.class.Employee, {
|
||||
_id: account.employee
|
||||
}, (res) => {
|
||||
employee = res[0]
|
||||
}, { limit: 1 })
|
||||
$: account &&
|
||||
employeeQ.query(
|
||||
contact.class.Employee,
|
||||
{
|
||||
_id: account.employee
|
||||
},
|
||||
(res) => {
|
||||
employee = res[0]
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
</script>
|
||||
|
||||
{#if client}
|
||||
@ -145,6 +187,7 @@
|
||||
label={visibileNav ? workbench.string.HideMenu : workbench.string.ShowMenu}
|
||||
selected={!visibileNav}
|
||||
action={toggleNav}
|
||||
notify={false}
|
||||
/>
|
||||
</div>
|
||||
<Applications {apps} active={currentApp} />
|
||||
@ -166,20 +209,23 @@
|
||||
{#if currentApplication}
|
||||
<NavHeader label={currentApplication.label} />
|
||||
{/if}
|
||||
<Navigator model={navigatorModel} />
|
||||
</div>
|
||||
<Navigator
|
||||
{currentSpace}
|
||||
{currentSpecial}
|
||||
model={navigatorModel}
|
||||
on:special={(evt) => selectSpecial(evt.detail)}
|
||||
on:space={(evt) => updateSpace(evt.detail)}
|
||||
on:archive={(evt) => selectArchive()}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="antiPanel-component filled indent">
|
||||
{#if currentApplication && currentApplication.component}
|
||||
<Component is={currentApplication.component} />
|
||||
<Component is={currentApplication.component} />
|
||||
{:else if specialComponent}
|
||||
<Component is={specialComponent} />
|
||||
{:else}
|
||||
{#if ownSpecialComponent}
|
||||
<svelte:component this={ownSpecialComponent} model={navigatorModel} />
|
||||
{:else if specialComponent}
|
||||
<Component is={specialComponent} />
|
||||
{:else}
|
||||
<SpaceView {currentSpace} {currentView} {createItemDialog} />
|
||||
{/if}
|
||||
<SpaceView {currentSpace} {currentView} {createItemDialog} />
|
||||
{/if}
|
||||
</div>
|
||||
<!-- <div class="aside"><Chat thread/></div> -->
|
||||
|
@ -12,30 +12,25 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { SortingOrder } from '@anticrm/core'
|
||||
import type { Doc, Ref, Space } from '@anticrm/core'
|
||||
import core from '@anticrm/core'
|
||||
import { getResource, IntlString } from '@anticrm/platform'
|
||||
import { createQuery, getClient } from '@anticrm/presentation'
|
||||
import { Action, getCurrentLocation, IconAdd, IconEdit, location, navigate, showPopup } from '@anticrm/ui'
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
import { Action, IconAdd, IconEdit, showPopup } from '@anticrm/ui'
|
||||
import { getActions as getContributedActions } from '@anticrm/view-resources'
|
||||
import type { SpacesNavModel } from '@anticrm/workbench'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { classIcon } from '../../utils'
|
||||
import SpacePanel from './SpacePanel.svelte'
|
||||
import TreeItem from './TreeItem.svelte'
|
||||
import TreeNode from './TreeNode.svelte'
|
||||
|
||||
export let model: SpacesNavModel
|
||||
|
||||
export let currentSpace: Ref<Space> | undefined
|
||||
export let spaces: Space[]
|
||||
const client = getClient()
|
||||
const query = createQuery()
|
||||
let spaces: Space[] = []
|
||||
let selected: Ref<Space> | undefined = undefined
|
||||
|
||||
$: query.query(model.spaceClass, { archived: false }, result => { spaces = result }, { sort: { name: SortingOrder.Ascending }})
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const addSpace: Action = {
|
||||
label: model.addSpaceLabel,
|
||||
@ -53,18 +48,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function selectSpace (id: Ref<Space>) {
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[2] = id
|
||||
loc.path.length = 3
|
||||
navigate(loc)
|
||||
dispatch('space', id)
|
||||
}
|
||||
|
||||
onDestroy(location.subscribe(async (loc) => {
|
||||
selected = loc.path[2] as Ref<Space>
|
||||
}))
|
||||
|
||||
async function getActions (space: Space): Promise<Action[]> {
|
||||
const result = [editSpace]
|
||||
|
||||
@ -87,7 +74,16 @@
|
||||
<TreeNode label={model.label} actions={[addSpace]}>
|
||||
{#each spaces as space}
|
||||
{#await getActions(space) then actions}
|
||||
<TreeItem _id={space._id} title={space.name} icon={classIcon(client, space._class)} selected={selected === space._id} {actions} on:click={() => { selectSpace(space._id) }}/>
|
||||
<TreeItem
|
||||
_id={space._id}
|
||||
title={space.name}
|
||||
icon={classIcon(client, space._class)}
|
||||
selected={currentSpace === space._id}
|
||||
{actions}
|
||||
on:click={() => {
|
||||
selectSpace(space._id)
|
||||
}}
|
||||
/>
|
||||
{/await}
|
||||
{/each}
|
||||
</TreeNode>
|
||||
|
@ -22,13 +22,14 @@
|
||||
export let label: IntlString | undefined = undefined
|
||||
export let notifications = 0
|
||||
export let actions: Action[] = []
|
||||
export let selected: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<div
|
||||
class="flex-row-center container"
|
||||
class="flex-row-center container" class:selected={selected}
|
||||
on:click|stopPropagation={() => {
|
||||
dispatch('click')
|
||||
}}
|
||||
@ -88,6 +89,10 @@
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background-color: var(--theme-button-bg-enabled);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--theme-button-bg-enabled);
|
||||
.tool {
|
||||
|
@ -16,15 +16,20 @@
|
||||
import WorkbenchApp from './components/WorkbenchApp.svelte'
|
||||
import ApplicationPresenter from './components/ApplicationPresenter.svelte'
|
||||
import { Resources } from '@anticrm/platform'
|
||||
import Archive from './components/Archive.svelte'
|
||||
import { Space } from '@anticrm/core'
|
||||
|
||||
function hasArchiveSpaces (spaces: Space[]): boolean {
|
||||
return spaces.find(sp => sp.archived) !== undefined
|
||||
}
|
||||
|
||||
/*!
|
||||
* Anticrm Platform™ Workbench Plugin
|
||||
* © 2020 Anticrm Platform Contributors. All Rights Reserved.
|
||||
* Licensed under the Eclipse Public License, Version 2.0
|
||||
*/
|
||||
export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
WorkbenchApp,
|
||||
ApplicationPresenter
|
||||
ApplicationPresenter,
|
||||
Archive
|
||||
},
|
||||
function: {
|
||||
HasArchiveSpaces: hasArchiveSpaces
|
||||
}
|
||||
})
|
||||
|
@ -1,24 +1,22 @@
|
||||
//
|
||||
// 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 type { Ref, Obj, Class } from '@anticrm/core'
|
||||
import type { Class, Client, Obj, Ref } from '@anticrm/core'
|
||||
import type { Asset } from '@anticrm/platform'
|
||||
import type { Client } from '@anticrm/core'
|
||||
import type { EmployeeAccount } from '@anticrm/contact'
|
||||
|
||||
export function classIcon(client: Client, _class: Ref<Class<Obj>>): Asset | undefined {
|
||||
export function classIcon (client: Client, _class: Ref<Class<Obj>>): Asset | undefined {
|
||||
return client.getHierarchy().getClass(_class).icon
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
//
|
||||
|
||||
import type { Class, Doc, Mixin, Obj, Ref, Space } from '@anticrm/core'
|
||||
import type { Asset, IntlString, Metadata, Plugin } from '@anticrm/platform'
|
||||
import type { Asset, IntlString, Metadata, Plugin, Resource } from '@anticrm/platform'
|
||||
import { plugin } from '@anticrm/platform'
|
||||
import type { AnyComponent } from '@anticrm/ui'
|
||||
|
||||
@ -59,6 +59,7 @@ export interface SpecialNavModel {
|
||||
icon: Asset
|
||||
component: AnyComponent
|
||||
position?: 'top'|'bottom' // undefined == 'top
|
||||
visibleIf?: Resource<(spaces: Space[]) => boolean>
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user