mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-26 04:23:58 +03:00
Filters improve (#2572)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
67e86538bb
commit
f7e220d0f2
@ -35,6 +35,7 @@ import { DOMAIN_MODEL, IndexKind } from '@hcengineering/core'
|
|||||||
import {
|
import {
|
||||||
Builder,
|
Builder,
|
||||||
Collection,
|
Collection,
|
||||||
|
Hidden,
|
||||||
Index,
|
Index,
|
||||||
Model,
|
Model,
|
||||||
Prop,
|
Prop,
|
||||||
@ -76,6 +77,7 @@ export class TChannelProvider extends TDoc implements ChannelProvider {
|
|||||||
export class TContact extends TDoc implements Contact {
|
export class TContact extends TDoc implements Contact {
|
||||||
@Prop(TypeString(), contact.string.Name)
|
@Prop(TypeString(), contact.string.Name)
|
||||||
@Index(IndexKind.FullText)
|
@Index(IndexKind.FullText)
|
||||||
|
@Hidden()
|
||||||
name!: string
|
name!: string
|
||||||
|
|
||||||
avatar?: string | null
|
avatar?: string | null
|
||||||
|
@ -70,17 +70,21 @@ import core from './component'
|
|||||||
export class TObj implements Obj {
|
export class TObj implements Obj {
|
||||||
@Prop(TypeRef(core.class.Class), core.string.ClassLabel)
|
@Prop(TypeRef(core.class.Class), core.string.ClassLabel)
|
||||||
@Index(IndexKind.Indexed)
|
@Index(IndexKind.Indexed)
|
||||||
|
@Hidden()
|
||||||
_class!: Ref<Class<this>>
|
_class!: Ref<Class<this>>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(core.class.Doc, core.class.Obj)
|
@Model(core.class.Doc, core.class.Obj)
|
||||||
|
@UX(core.string.Object)
|
||||||
export class TDoc extends TObj implements Doc {
|
export class TDoc extends TObj implements Doc {
|
||||||
@Prop(TypeRef(core.class.Doc), core.string.Id)
|
@Prop(TypeRef(core.class.Doc), core.string.Id)
|
||||||
|
@Hidden()
|
||||||
// @Index(IndexKind.Indexed) // - automatically indexed by default.
|
// @Index(IndexKind.Indexed) // - automatically indexed by default.
|
||||||
_id!: Ref<this>
|
_id!: Ref<this>
|
||||||
|
|
||||||
@Prop(TypeRef(core.class.Space), core.string.Space)
|
@Prop(TypeRef(core.class.Space), core.string.Space)
|
||||||
@Index(IndexKind.Indexed)
|
@Index(IndexKind.Indexed)
|
||||||
|
@Hidden()
|
||||||
space!: Ref<Space>
|
space!: Ref<Space>
|
||||||
|
|
||||||
@Prop(TypeTimestamp(), core.string.Modified)
|
@Prop(TypeTimestamp(), core.string.Modified)
|
||||||
@ -94,10 +98,12 @@ export class TDoc extends TObj implements Doc {
|
|||||||
export class TAttachedDoc extends TDoc implements AttachedDoc {
|
export class TAttachedDoc extends TDoc implements AttachedDoc {
|
||||||
@Prop(TypeRef(core.class.Doc), core.string.AttachedTo)
|
@Prop(TypeRef(core.class.Doc), core.string.AttachedTo)
|
||||||
@Index(IndexKind.Indexed)
|
@Index(IndexKind.Indexed)
|
||||||
|
@Hidden()
|
||||||
attachedTo!: Ref<Doc>
|
attachedTo!: Ref<Doc>
|
||||||
|
|
||||||
@Prop(TypeRef(core.class.Class), core.string.AttachedToClass)
|
@Prop(TypeRef(core.class.Class), core.string.AttachedToClass)
|
||||||
@Index(IndexKind.Indexed)
|
@Index(IndexKind.Indexed)
|
||||||
|
@Hidden()
|
||||||
attachedToClass!: Ref<Class<Doc>>
|
attachedToClass!: Ref<Class<Doc>>
|
||||||
|
|
||||||
@Prop(TypeString(), core.string.Collection)
|
@Prop(TypeString(), core.string.Collection)
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
import type { Employee, Organization } from '@hcengineering/contact'
|
import type { Employee, Organization } from '@hcengineering/contact'
|
||||||
import { Doc, FindOptions, IndexKind, Lookup, Ref, Timestamp } from '@hcengineering/core'
|
import { Doc, FindOptions, IndexKind, Lookup, Ref, Timestamp } from '@hcengineering/core'
|
||||||
import {
|
import {
|
||||||
ArrOf,
|
|
||||||
Builder,
|
Builder,
|
||||||
Collection,
|
Collection,
|
||||||
Index,
|
Index,
|
||||||
@ -125,7 +124,7 @@ export class TCandidate extends TPerson implements Candidate {
|
|||||||
@Mixin(recruit.mixin.VacancyList, contact.class.Organization)
|
@Mixin(recruit.mixin.VacancyList, contact.class.Organization)
|
||||||
@UX(recruit.string.VacancyList, recruit.icon.RecruitApplication, undefined, 'name')
|
@UX(recruit.string.VacancyList, recruit.icon.RecruitApplication, undefined, 'name')
|
||||||
export class TVacancyList extends TOrganization implements VacancyList {
|
export class TVacancyList extends TOrganization implements VacancyList {
|
||||||
@Prop(ArrOf(TypeRef(recruit.class.Vacancy)), recruit.string.Vacancies)
|
@Prop(Collection(recruit.class.Vacancy), recruit.string.Vacancies)
|
||||||
vacancies!: number
|
vacancies!: number
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +191,7 @@ export function createModel (builder: Builder): void {
|
|||||||
editor: recruit.component.Applications
|
editor: recruit.component.Applications
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.mixin(recruit.class.Vacancy, core.class.Class, view.mixin.ArrayEditor, {
|
builder.mixin(recruit.class.Vacancy, core.class.Class, view.mixin.CollectionEditor, {
|
||||||
editor: recruit.component.VacancyList
|
editor: recruit.component.VacancyList
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -121,6 +121,7 @@ export class TTask extends TAttachedDoc implements Task {
|
|||||||
|
|
||||||
@Prop(TypeString(), task.string.TaskNumber)
|
@Prop(TypeString(), task.string.TaskNumber)
|
||||||
@Index(IndexKind.FullText)
|
@Index(IndexKind.FullText)
|
||||||
|
@Hidden()
|
||||||
number!: number
|
number!: number
|
||||||
|
|
||||||
// @Prop(TypeRef(contact.class.Employee), task.string.TaskAssignee)
|
// @Prop(TypeRef(contact.class.Employee), task.string.TaskAssignee)
|
||||||
|
@ -512,7 +512,7 @@ export function createModel (builder: Builder): void {
|
|||||||
)
|
)
|
||||||
|
|
||||||
builder.mixin(core.class.Space, core.class.Class, view.mixin.AttributePresenter, {
|
builder.mixin(core.class.Space, core.class.Class, view.mixin.AttributePresenter, {
|
||||||
presenter: view.component.SpacePresenter
|
presenter: view.component.SpaceRefPresenter
|
||||||
})
|
})
|
||||||
|
|
||||||
// Selection stuff
|
// Selection stuff
|
||||||
|
@ -64,7 +64,8 @@ export default mergeIds(viewId, view, {
|
|||||||
MarkupEditor: '' as AnyComponent,
|
MarkupEditor: '' as AnyComponent,
|
||||||
MarkupEditorPopup: '' as AnyComponent,
|
MarkupEditorPopup: '' as AnyComponent,
|
||||||
ListView: '' as AnyComponent,
|
ListView: '' as AnyComponent,
|
||||||
IndexedDocumentPreview: '' as AnyComponent
|
IndexedDocumentPreview: '' as AnyComponent,
|
||||||
|
SpaceRefPresenter: '' as AnyComponent
|
||||||
},
|
},
|
||||||
string: {
|
string: {
|
||||||
Table: '' as IntlString,
|
Table: '' as IntlString,
|
||||||
|
@ -150,6 +150,7 @@ export default plugin(coreId, {
|
|||||||
Name: '' as IntlString,
|
Name: '' as IntlString,
|
||||||
Enum: '' as IntlString,
|
Enum: '' as IntlString,
|
||||||
Description: '' as IntlString,
|
Description: '' as IntlString,
|
||||||
Hyperlink: '' as IntlString
|
Hyperlink: '' as IntlString,
|
||||||
|
Object: '' as IntlString
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -394,6 +394,34 @@ export class Hierarchy {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getOwnAttributes (clazz: Ref<Classifier>): Map<string, AnyAttribute> {
|
||||||
|
const result = new Map<string, AnyAttribute>()
|
||||||
|
|
||||||
|
const attributes = this.attributes.get(clazz)
|
||||||
|
if (attributes !== undefined) {
|
||||||
|
for (const [name, attr] of attributes) {
|
||||||
|
result.set(name, attr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
getParentClass (_class: Ref<Class<Obj>>): Ref<Class<Obj>> {
|
||||||
|
const baseDomain = this.getDomain(_class)
|
||||||
|
const ancestors = this.getAncestors(_class)
|
||||||
|
let result: Ref<Class<Obj>> = _class
|
||||||
|
for (const ancestor of ancestors) {
|
||||||
|
try {
|
||||||
|
const domain = this.getClass(ancestor).domain
|
||||||
|
if (domain === baseDomain) {
|
||||||
|
result = ancestor
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
getAttribute (classifier: Ref<Classifier>, name: string): AnyAttribute {
|
getAttribute (classifier: Ref<Classifier>, name: string): AnyAttribute {
|
||||||
const attr = this.findAttribute(classifier, name)
|
const attr = this.findAttribute(classifier, name)
|
||||||
if (attr === undefined) {
|
if (attr === undefined) {
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
"Array": "Array",
|
"Array": "Array",
|
||||||
"Enum": "Enum",
|
"Enum": "Enum",
|
||||||
"Members": "Members",
|
"Members": "Members",
|
||||||
"Hyperlink": "URL"
|
"Hyperlink": "URL",
|
||||||
|
"Object": "Object"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
"Array": "Массив",
|
"Array": "Массив",
|
||||||
"Enum": "Справочник",
|
"Enum": "Справочник",
|
||||||
"Members": "Участники",
|
"Members": "Участники",
|
||||||
"Hyperlink": "URL"
|
"Hyperlink": "URL",
|
||||||
|
"Object": "Объект"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,18 +148,9 @@
|
|||||||
transition-duration: 0.15s;
|
transition-duration: 0.15s;
|
||||||
|
|
||||||
.btn-icon {
|
.btn-icon {
|
||||||
color: var(--content-color);
|
|
||||||
transition: color 0.15s;
|
transition: color 0.15s;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
&:hover {
|
|
||||||
color: var(--accent-color);
|
|
||||||
transition-duration: 0;
|
|
||||||
|
|
||||||
.btn-icon {
|
|
||||||
color: var(--caption-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
color: rgb(var(--caption-color) / 40%);
|
color: rgb(var(--caption-color) / 40%);
|
||||||
|
|
||||||
@ -167,6 +158,14 @@
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&:hover {
|
||||||
|
color: var(--caption-color);
|
||||||
|
transition-duration: 0;
|
||||||
|
|
||||||
|
.btn-icon {
|
||||||
|
color: var(--caption-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.jf-left {
|
&.jf-left {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
import view, { Viewlet, ViewletPreference } from '@hcengineering/view'
|
import view, { Viewlet, ViewletPreference } from '@hcengineering/view'
|
||||||
import {
|
import {
|
||||||
ActionContext,
|
ActionContext,
|
||||||
|
FilterBar,
|
||||||
FilterButton,
|
FilterButton,
|
||||||
getViewOptions,
|
getViewOptions,
|
||||||
setActiveViewletId,
|
setActiveViewletId,
|
||||||
@ -31,10 +32,11 @@
|
|||||||
import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
||||||
|
|
||||||
let search = ''
|
let search = ''
|
||||||
let resultQuery: DocumentQuery<Doc> = {}
|
let searchQuery: DocumentQuery<Doc> = {}
|
||||||
|
let resultQuery: DocumentQuery<Doc> = searchQuery
|
||||||
|
|
||||||
function updateResultQuery (search: string): void {
|
function updateResultQuery (search: string): void {
|
||||||
resultQuery = search === '' ? {} : { $search: search }
|
searchQuery = search === '' ? {} : { $search: search }
|
||||||
}
|
}
|
||||||
|
|
||||||
let viewlet: Viewlet | undefined
|
let viewlet: Viewlet | undefined
|
||||||
@ -109,6 +111,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<FilterBar
|
||||||
|
_class={contact.class.Contact}
|
||||||
|
{viewOptions}
|
||||||
|
query={searchQuery}
|
||||||
|
on:change={(e) => (resultQuery = e.detail)}
|
||||||
|
/>
|
||||||
|
|
||||||
{#if viewlet}
|
{#if viewlet}
|
||||||
{#if loading}
|
{#if loading}
|
||||||
<Loading />
|
<Loading />
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
import { Button, Icon, IconAdd, Label, Loading, SearchEdit, showPopup } from '@hcengineering/ui'
|
import { Button, Icon, IconAdd, Label, Loading, SearchEdit, showPopup } from '@hcengineering/ui'
|
||||||
import view, { BuildModelKey, Viewlet, ViewletPreference } from '@hcengineering/view'
|
import view, { BuildModelKey, Viewlet, ViewletPreference } from '@hcengineering/view'
|
||||||
import {
|
import {
|
||||||
|
FilterBar,
|
||||||
FilterButton,
|
FilterButton,
|
||||||
getViewOptions,
|
getViewOptions,
|
||||||
setActiveViewletId,
|
setActiveViewletId,
|
||||||
@ -30,9 +31,10 @@
|
|||||||
import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
||||||
|
|
||||||
let search: string = ''
|
let search: string = ''
|
||||||
|
let searchQuery: DocumentQuery<Doc> = {}
|
||||||
let resultQuery: DocumentQuery<Doc> = {}
|
let resultQuery: DocumentQuery<Doc> = {}
|
||||||
|
|
||||||
$: resultQuery = search === '' ? {} : { $search: search }
|
$: searchQuery = search === '' ? {} : { $search: search }
|
||||||
|
|
||||||
type ApplicationInfo = { count: number; modifiedOn: number }
|
type ApplicationInfo = { count: number; modifiedOn: number }
|
||||||
let applications: Map<Ref<Vacancy>, ApplicationInfo> = new Map<Ref<Vacancy>, ApplicationInfo>()
|
let applications: Map<Ref<Vacancy>, ApplicationInfo> = new Map<Ref<Vacancy>, ApplicationInfo>()
|
||||||
@ -169,6 +171,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<FilterBar
|
||||||
|
_class={recruit.class.Vacancy}
|
||||||
|
{viewOptions}
|
||||||
|
query={searchQuery}
|
||||||
|
on:change={(e) => (resultQuery = e.detail)}
|
||||||
|
/>
|
||||||
|
|
||||||
{#if descr}
|
{#if descr}
|
||||||
{#if loading}
|
{#if loading}
|
||||||
<Loading />
|
<Loading />
|
||||||
|
@ -123,8 +123,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const filtredKeys = Array.from(keysMap.values())
|
const filtredKeys = Array.from(keysMap.values())
|
||||||
|
|
||||||
const { attributes, collections } = categorizeFields(hierarchy, filtredKeys, collectionArrays, allowedCollections)
|
const { attributes, collections } = categorizeFields(hierarchy, filtredKeys, collectionArrays, allowedCollections)
|
||||||
|
|
||||||
keys = attributes.map((it) => it.key)
|
keys = attributes.map((it) => it.key)
|
||||||
|
|
||||||
const editors: { key: KeyedAttribute; editor: AnyComponent; category: AttributeCategory }[] = []
|
const editors: { key: KeyedAttribute; editor: AnyComponent; category: AttributeCategory }[] = []
|
||||||
@ -171,7 +171,7 @@
|
|||||||
$: getEditorOrDefault(realObjectClass, showAllMixins, _id)
|
$: getEditorOrDefault(realObjectClass, showAllMixins, _id)
|
||||||
|
|
||||||
function getEditorOrDefault (_class: Ref<Class<Doc>>, showAllMixins: boolean, _id: Ref<Doc>): void {
|
function getEditorOrDefault (_class: Ref<Class<Doc>>, showAllMixins: boolean, _id: Ref<Doc>): void {
|
||||||
parentClass = getParentClass(_class)
|
parentClass = hierarchy.getParentClass(_class)
|
||||||
mainEditor = getEditor(_class)
|
mainEditor = getEditor(_class)
|
||||||
updateKeys(showAllMixins)
|
updateKeys(showAllMixins)
|
||||||
}
|
}
|
||||||
@ -210,21 +210,6 @@
|
|||||||
|
|
||||||
$: icon = getIcon(realObjectClass)
|
$: icon = getIcon(realObjectClass)
|
||||||
|
|
||||||
function getParentClass (_class: Ref<Class<Doc>>): Ref<Class<Doc>> {
|
|
||||||
const baseDomain = hierarchy.getDomain(_class)
|
|
||||||
const ancestors = hierarchy.getAncestors(_class)
|
|
||||||
let result: Ref<Class<Doc>> = _class
|
|
||||||
for (const ancestor of ancestors) {
|
|
||||||
try {
|
|
||||||
const domain = hierarchy.getClass(ancestor).domain
|
|
||||||
if (domain === baseDomain) {
|
|
||||||
result = ancestor
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
let title: string = ''
|
let title: string = ''
|
||||||
|
|
||||||
$: if (object !== undefined) {
|
$: if (object !== undefined) {
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
_id: type.of
|
_id: type.of
|
||||||
},
|
},
|
||||||
(res) => {
|
(res) => {
|
||||||
items = res[0].enumValues.map((p) => {
|
items = res[0]?.enumValues?.map((p) => {
|
||||||
return { id: p, label: p }
|
return { id: p, label: p }
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2023 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.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import core, { Ref, Space } from '@hcengineering/core'
|
||||||
|
import { ObjectPresenter } from '..'
|
||||||
|
|
||||||
|
export let value: Ref<Space>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ObjectPresenter objectId={value} _class={core.class.Space} />
|
@ -14,10 +14,17 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import core, { AnyAttribute, ArrOf, Class, Doc, Ref, Type } from '@hcengineering/core'
|
import core, { AnyAttribute, ArrOf, Class, Doc, Ref, Type } from '@hcengineering/core'
|
||||||
import { IntlString } from '@hcengineering/platform'
|
import { Asset, IntlString } from '@hcengineering/platform'
|
||||||
import preferencePlugin from '@hcengineering/preference'
|
import preferencePlugin from '@hcengineering/preference'
|
||||||
import presentation, { Card, createQuery, getAttributePresenterClass, getClient } from '@hcengineering/presentation'
|
import presentation, { Card, createQuery, getAttributePresenterClass, getClient } from '@hcengineering/presentation'
|
||||||
import { Button, getPlatformColorForText, ToggleButton } from '@hcengineering/ui'
|
import {
|
||||||
|
Button,
|
||||||
|
getEventPositionElement,
|
||||||
|
getPlatformColorForText,
|
||||||
|
SelectPopup,
|
||||||
|
showPopup,
|
||||||
|
ToggleButton
|
||||||
|
} from '@hcengineering/ui'
|
||||||
import { BuildModelKey, Viewlet, ViewletPreference } from '@hcengineering/view'
|
import { BuildModelKey, Viewlet, ViewletPreference } from '@hcengineering/view'
|
||||||
import { deepEqual } from 'fast-equals'
|
import { deepEqual } from 'fast-equals'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
@ -55,14 +62,16 @@
|
|||||||
label: IntlString
|
label: IntlString
|
||||||
value: string | BuildModelKey
|
value: string | BuildModelKey
|
||||||
_class: Ref<Class<Doc>>
|
_class: Ref<Class<Doc>>
|
||||||
|
icon: Asset | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
function getObjectConfig (_class: Ref<Class<Doc>>, param: string): AttributeConfig {
|
function getObjectConfig (_class: Ref<Class<Doc>>, param: string): AttributeConfig {
|
||||||
const clazz = client.getHierarchy().getClass(_class)
|
const clazz = hierarchy.getClass(_class)
|
||||||
return {
|
return {
|
||||||
value: param,
|
value: param,
|
||||||
label: clazz.label,
|
label: clazz.label,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
icon: clazz.icon,
|
||||||
_class
|
_class
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,6 +79,7 @@
|
|||||||
function getBaseConfig (viewlet: Viewlet): AttributeConfig[] {
|
function getBaseConfig (viewlet: Viewlet): AttributeConfig[] {
|
||||||
const lookup = buildConfigLookup(hierarchy, viewlet.attachTo, viewlet.config, viewlet.options?.lookup)
|
const lookup = buildConfigLookup(hierarchy, viewlet.attachTo, viewlet.config, viewlet.options?.lookup)
|
||||||
const result: AttributeConfig[] = []
|
const result: AttributeConfig[] = []
|
||||||
|
const clazz = hierarchy.getClass(viewlet.attachTo)
|
||||||
for (const param of viewlet.config) {
|
for (const param of viewlet.config) {
|
||||||
if (typeof param === 'string') {
|
if (typeof param === 'string') {
|
||||||
if (param.length === 0) {
|
if (param.length === 0) {
|
||||||
@ -79,7 +89,8 @@
|
|||||||
value: param,
|
value: param,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
label: getKeyLabel(client, viewlet.attachTo, param, lookup),
|
label: getKeyLabel(client, viewlet.attachTo, param, lookup),
|
||||||
_class: viewlet.attachTo
|
_class: viewlet.attachTo,
|
||||||
|
icon: clazz.icon
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -87,7 +98,8 @@
|
|||||||
value: param,
|
value: param,
|
||||||
label: param.label as IntlString,
|
label: param.label as IntlString,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
_class: viewlet.attachTo
|
_class: viewlet.attachTo,
|
||||||
|
icon: clazz.icon
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,13 +138,15 @@
|
|||||||
parent = pclazz.extends
|
parent = pclazz.extends
|
||||||
}
|
}
|
||||||
if (presenter === undefined) return
|
if (presenter === undefined) return
|
||||||
|
const clazz = hierarchy.getClass(attribute.attributeOf)
|
||||||
|
|
||||||
if (useMixinProxy) {
|
if (useMixinProxy) {
|
||||||
const newValue = {
|
const newValue = {
|
||||||
value: attribute.attributeOf + '.' + attribute.name,
|
value: attribute.attributeOf + '.' + attribute.name,
|
||||||
label: attribute.label,
|
label: attribute.label,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
_class: attribute.attributeOf
|
_class: attribute.attributeOf,
|
||||||
|
icon: clazz.icon
|
||||||
}
|
}
|
||||||
if (!isExist(result, newValue)) {
|
if (!isExist(result, newValue)) {
|
||||||
result.push(newValue)
|
result.push(newValue)
|
||||||
@ -142,7 +156,8 @@
|
|||||||
value,
|
value,
|
||||||
label: attribute.label,
|
label: attribute.label,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
_class: attribute.attributeOf
|
_class: attribute.attributeOf,
|
||||||
|
icon: clazz.icon
|
||||||
}
|
}
|
||||||
if (!isExist(result, newValue)) {
|
if (!isExist(result, newValue)) {
|
||||||
result.push(newValue)
|
result.push(newValue)
|
||||||
@ -169,11 +184,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
hierarchy.getDescendants(viewlet.attachTo).forEach((it) => {
|
hierarchy.getDescendants(viewlet.attachTo).forEach((it) => {
|
||||||
const ancestor = hierarchy.getAncestors(it)[1]
|
hierarchy.getOwnAttributes(it).forEach((attr) => {
|
||||||
hierarchy.getAllAttributes(it, ancestor).forEach((attr) => {
|
processAttribute(attr, result, true)
|
||||||
if (attr.isCustom === true) {
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const ancestors = new Set(hierarchy.getAncestors(viewlet.attachTo))
|
||||||
|
const parent = hierarchy.getParentClass(viewlet.attachTo)
|
||||||
|
const parentMixins = hierarchy
|
||||||
|
.getDescendants(parent)
|
||||||
|
.map((p) => hierarchy.getClass(p))
|
||||||
|
.filter((p) => hierarchy.isMixin(p._id) && p.extends && ancestors.has(p.extends))
|
||||||
|
|
||||||
|
parentMixins.forEach((it) => {
|
||||||
|
hierarchy.getOwnAttributes(it._id).forEach((attr) => {
|
||||||
processAttribute(attr, result, true)
|
processAttribute(attr, result, true)
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -252,6 +277,24 @@
|
|||||||
const color = getPlatformColorForText(attribute._class)
|
const color = getPlatformColorForText(attribute._class)
|
||||||
return `border: 1px solid ${color + (attribute.enabled ? 'ff' : 'cc')};`
|
return `border: 1px solid ${color + (attribute.enabled ? 'ff' : 'cc')};`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function groupByClasses (attributes: AttributeConfig[]): Map<Ref<Class<Doc>>, AttributeConfig[]> {
|
||||||
|
const res = new Map()
|
||||||
|
for (const attribute of attributes) {
|
||||||
|
if (attribute.enabled) continue
|
||||||
|
const arr = res.get(attribute._class) ?? []
|
||||||
|
arr.push(attribute)
|
||||||
|
res.set(attribute._class, arr)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
$: enabled = attributes.filter((p) => p.enabled)
|
||||||
|
$: classes = groupByClasses(attributes)
|
||||||
|
|
||||||
|
function getClassLabel (_class: Ref<Class<Doc>>): IntlString {
|
||||||
|
return hierarchy.getClass(_class).label
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Card
|
<Card
|
||||||
@ -264,7 +307,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div class="flex-row-stretch flex-wrap">
|
<div class="flex-row-stretch flex-wrap">
|
||||||
{#each attributes as attribute, i}
|
{#each enabled as attribute, i}
|
||||||
<div
|
<div
|
||||||
class="m-0-5 border-radius-1 overflow-label"
|
class="m-0-5 border-radius-1 overflow-label"
|
||||||
style={getStyle(attribute)}
|
style={getStyle(attribute)}
|
||||||
@ -281,7 +324,41 @@
|
|||||||
selected = undefined
|
selected = undefined
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ToggleButton backgroundColor={getColor(attribute)} label={attribute.label} bind:value={attribute.enabled} />
|
<ToggleButton
|
||||||
|
backgroundColor={getColor(attribute)}
|
||||||
|
icon={attribute.icon}
|
||||||
|
label={attribute.label}
|
||||||
|
bind:value={attribute.enabled}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div class="flex-row-stretch flex-wrap">
|
||||||
|
{#each Array.from(classes.keys()) as _class}
|
||||||
|
<div class="m-0-5">
|
||||||
|
<Button
|
||||||
|
label={getClassLabel(_class)}
|
||||||
|
on:click={(e) => {
|
||||||
|
showPopup(
|
||||||
|
SelectPopup,
|
||||||
|
{
|
||||||
|
value: classes.get(_class)?.map((it) => ({ id: it.value, label: it.label }))
|
||||||
|
},
|
||||||
|
getEventPositionElement(e),
|
||||||
|
(val) => {
|
||||||
|
console.log('val')
|
||||||
|
console.log(val)
|
||||||
|
if (val !== undefined) {
|
||||||
|
const value = classes.get(_class)?.find((it) => it.value === val)
|
||||||
|
if (value) {
|
||||||
|
value.enabled = true
|
||||||
|
attributes = attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,11 +22,20 @@
|
|||||||
Doc,
|
Doc,
|
||||||
Ref,
|
Ref,
|
||||||
RefTo,
|
RefTo,
|
||||||
Type,
|
Space,
|
||||||
Space
|
Type
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import { getClient } from '@hcengineering/presentation'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
import { closePopup, closeTooltip, Icon, Label, showPopup, Submenu, resizeObserver } from '@hcengineering/ui'
|
import {
|
||||||
|
closePopup,
|
||||||
|
closeTooltip,
|
||||||
|
Icon,
|
||||||
|
Label,
|
||||||
|
resizeObserver,
|
||||||
|
Scroller,
|
||||||
|
showPopup,
|
||||||
|
Submenu
|
||||||
|
} from '@hcengineering/ui'
|
||||||
import { Filter, KeyFilter } from '@hcengineering/view'
|
import { Filter, KeyFilter } from '@hcengineering/view'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import { FilterQuery } from '../../filter'
|
import { FilterQuery } from '../../filter'
|
||||||
@ -86,9 +95,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function buildFilterForAttr (_class: Ref<Class<Doc>>, attribute: AnyAttribute, result: KeyFilter[]): void {
|
function buildFilterForAttr (_class: Ref<Class<Doc>>, attribute: AnyAttribute, result: KeyFilter[]): void {
|
||||||
if (attribute.isCustom !== true) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (attribute.label === undefined || attribute.hidden) {
|
if (attribute.label === undefined || attribute.hidden) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -101,6 +107,7 @@
|
|||||||
result.push(filter)
|
result.push(filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildFilterFor (
|
function buildFilterFor (
|
||||||
_class: Ref<Class<Doc>>,
|
_class: Ref<Class<Doc>>,
|
||||||
allAttributes: Map<string, AnyAttribute>,
|
allAttributes: Map<string, AnyAttribute>,
|
||||||
@ -118,7 +125,7 @@
|
|||||||
|
|
||||||
const desc = hierarchy.getDescendants(_class)
|
const desc = hierarchy.getDescendants(_class)
|
||||||
for (const d of desc) {
|
for (const d of desc) {
|
||||||
const extra = hierarchy.getAllAttributes(d, _class)
|
const extra = hierarchy.getOwnAttributes(d)
|
||||||
for (const [k, v] of extra) {
|
for (const [k, v] of extra) {
|
||||||
if (!allAttributes.has(k)) {
|
if (!allAttributes.has(k)) {
|
||||||
allAttributes.set(k, v)
|
allAttributes.set(k, v)
|
||||||
@ -127,6 +134,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ancestors = new Set(hierarchy.getAncestors(_class))
|
||||||
|
const parent = hierarchy.getParentClass(_class)
|
||||||
|
const parentMixins = hierarchy
|
||||||
|
.getDescendants(parent)
|
||||||
|
.map((p) => hierarchy.getClass(p))
|
||||||
|
.filter((p) => hierarchy.isMixin(p._id) && p.extends && ancestors.has(p.extends))
|
||||||
|
|
||||||
|
for (const d of parentMixins) {
|
||||||
|
const extra = hierarchy.getOwnAttributes(d._id)
|
||||||
|
for (const [k, v] of extra) {
|
||||||
|
if (!allAttributes.has(k)) {
|
||||||
|
allAttributes.set(k, v)
|
||||||
|
buildFilterForAttr(d._id, v, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,8 +231,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
|
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
|
||||||
<div class="scroll">
|
<Scroller>
|
||||||
<div class="box">
|
|
||||||
{#each getTypes(_class) as type, i}
|
{#each getTypes(_class) as type, i}
|
||||||
{#if filter === undefined && type.component === view.component.ObjectFilter && hasNested(type)}
|
{#if filter === undefined && type.component === view.component.ObjectFilter && hasNested(type)}
|
||||||
<Submenu
|
<Submenu
|
||||||
@ -243,8 +266,7 @@
|
|||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</Scroller>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -62,6 +62,7 @@ import TimestampPresenter from './components/TimestampPresenter.svelte'
|
|||||||
import UpDownNavigator from './components/UpDownNavigator.svelte'
|
import UpDownNavigator from './components/UpDownNavigator.svelte'
|
||||||
import ValueSelector from './components/ValueSelector.svelte'
|
import ValueSelector from './components/ValueSelector.svelte'
|
||||||
import ViewletSettingButton from './components/ViewletSettingButton.svelte'
|
import ViewletSettingButton from './components/ViewletSettingButton.svelte'
|
||||||
|
import SpaceRefPresenter from './components/SpaceRefPresenter.svelte'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
afterResult,
|
afterResult,
|
||||||
@ -172,7 +173,8 @@ export default async (): Promise<Resources> => ({
|
|||||||
HTMLEditor,
|
HTMLEditor,
|
||||||
ListView,
|
ListView,
|
||||||
GrowPresenter,
|
GrowPresenter,
|
||||||
IndexedDocumentPreview
|
IndexedDocumentPreview,
|
||||||
|
SpaceRefPresenter
|
||||||
},
|
},
|
||||||
popup: {
|
popup: {
|
||||||
PositionElementAlignment
|
PositionElementAlignment
|
||||||
|
Loading…
Reference in New Issue
Block a user