mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-13 13:17:45 +02:00
Card fixes (#8136)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
import activity from '@hcengineering/activity'
|
||||
import { CardEvents, cardId, type Card, type MasterTag, type Tag } from '@hcengineering/card'
|
||||
import { CardEvents, cardId, DOMAIN_CARD, type Card, type MasterTag, type Tag } from '@hcengineering/card'
|
||||
import chunter from '@hcengineering/chunter'
|
||||
import contact from '@hcengineering/contact'
|
||||
import core, {
|
||||
@@ -20,7 +20,6 @@ import core, {
|
||||
DOMAIN_MODEL,
|
||||
IndexKind,
|
||||
type CollectionSize,
|
||||
type Domain,
|
||||
type MarkupBlobRef,
|
||||
type Rank,
|
||||
type Ref
|
||||
@@ -48,8 +47,6 @@ import card from './plugin'
|
||||
|
||||
export { cardId } from '@hcengineering/card'
|
||||
|
||||
const DOMAIN_CARD = 'card' as Domain
|
||||
|
||||
@Model(card.class.MasterTag, core.class.Class)
|
||||
export class TMasterTag extends TClass implements MasterTag {}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ export function createModel (builder: Builder): void {
|
||||
isAsync: true,
|
||||
txMatch: {
|
||||
_class: core.class.TxRemoveDoc,
|
||||
objectClass: card.class.MasterTag
|
||||
objectClass: { $in: [card.class.MasterTag, card.class.Tag] }
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -23,17 +23,17 @@
|
||||
"Archived": "Archivováno",
|
||||
"ClassLabel": "Typ",
|
||||
"ClassPropertyLabel": "Štítek",
|
||||
"String": "Řetězec",
|
||||
"String": "Text",
|
||||
"Markup": "Značení",
|
||||
"Number": "Číslo",
|
||||
"Boolean": "Boolean",
|
||||
"Boolean": "Zaškrtávací políčko",
|
||||
"Timestamp": "Časové razítko",
|
||||
"Date": "Datum",
|
||||
"IntlString": "Mezinárodní řetězec",
|
||||
"Ref": "Odkaz",
|
||||
"Collection": "Kolekce",
|
||||
"Array": "Pole",
|
||||
"Enum": "Výčet",
|
||||
"Array": "Vícenásobný výběr",
|
||||
"Enum": "Výběr",
|
||||
"Members": "Členové",
|
||||
"Hyperlink": "URL",
|
||||
"Collaborative": "Spolupráce",
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
"String": "Text",
|
||||
"Markup": "Formatierter Text",
|
||||
"Number": "Zahl",
|
||||
"Boolean": "Boolesch",
|
||||
"Boolean": "Kontrollkästchen",
|
||||
"Timestamp": "Zeitstempel",
|
||||
"Date": "Datum",
|
||||
"IntlString": "Internationaler Text",
|
||||
"Ref": "Referenz",
|
||||
"Collection": "Sammlung",
|
||||
"Array": "Liste",
|
||||
"Enum": "Aufzählung",
|
||||
"Array": "Mehrfachauswahl",
|
||||
"Enum": "Auswahl",
|
||||
"Members": "Mitglieder",
|
||||
"Hyperlink": "URL",
|
||||
"MarkupBlobRef": "Kollaborativ",
|
||||
|
||||
@@ -23,17 +23,17 @@
|
||||
"Archived": "Archived",
|
||||
"ClassLabel": "Type",
|
||||
"ClassPropertyLabel": "Label",
|
||||
"String": "String",
|
||||
"String": "Text",
|
||||
"Markup": "Markup",
|
||||
"Number": "Number",
|
||||
"Boolean": "Boolean",
|
||||
"Boolean": "Checkbox",
|
||||
"Timestamp": "Timestamp",
|
||||
"Date": "Date",
|
||||
"IntlString": "IntlString",
|
||||
"Ref": "Ref",
|
||||
"Ref": "Reference",
|
||||
"Collection": "Collection",
|
||||
"Array": "Array",
|
||||
"Enum": "Enum",
|
||||
"Array": "Multi-Select",
|
||||
"Enum": "Select",
|
||||
"Members": "Members",
|
||||
"Hyperlink": "URL",
|
||||
"MarkupBlobRef": "Collaborative",
|
||||
|
||||
@@ -16,17 +16,17 @@
|
||||
"Archived": "Archivado",
|
||||
"ClassLabel": "Tipo",
|
||||
"ClassPropertyLabel": "Etiqueta",
|
||||
"String": "Cadena de texto",
|
||||
"String": "Texto",
|
||||
"Markup": "Marcado",
|
||||
"Number": "Número",
|
||||
"Boolean": "Booleano",
|
||||
"Boolean": "Casilla de verificación",
|
||||
"Timestamp": "Marca de tiempo",
|
||||
"Date": "Fecha",
|
||||
"IntlString": "Cadena de texto internacionalizada",
|
||||
"Ref": "Ref.",
|
||||
"Ref": "Referencia",
|
||||
"Collection": "Colección",
|
||||
"Array": "Arreglo",
|
||||
"Enum": "Enum.",
|
||||
"Array": "Selección múltiple",
|
||||
"Enum": "Selección",
|
||||
"Members": "Miembros",
|
||||
"Hyperlink": "Enlace",
|
||||
"MarkupBlobRef": "Colaborativo",
|
||||
|
||||
@@ -23,17 +23,17 @@
|
||||
"Archived": "Archivé",
|
||||
"ClassLabel": "Type",
|
||||
"ClassPropertyLabel": "Label",
|
||||
"String": "Chaîne",
|
||||
"String": "Texte",
|
||||
"Markup": "Balise",
|
||||
"Number": "Nombre",
|
||||
"Boolean": "Booléen",
|
||||
"Boolean": "Case à cocher",
|
||||
"Timestamp": "Horodatage",
|
||||
"Date": "Date",
|
||||
"IntlString": "Chaîne internationale",
|
||||
"Ref": "Réf",
|
||||
"Ref": "Référence",
|
||||
"Collection": "Collection",
|
||||
"Array": "Tableau",
|
||||
"Enum": "Énumération",
|
||||
"Array": "Sélection multiple",
|
||||
"Enum": "Sélection",
|
||||
"Members": "Membres",
|
||||
"Hyperlink": "URL",
|
||||
"MarkupBlobRef": "Collaboratif",
|
||||
|
||||
@@ -23,17 +23,17 @@
|
||||
"Archived": "Archiviato",
|
||||
"ClassLabel": "Tipo",
|
||||
"ClassPropertyLabel": "Etichetta",
|
||||
"String": "Stringa",
|
||||
"String": "Testo",
|
||||
"Markup": "Markup",
|
||||
"Number": "Numero",
|
||||
"Boolean": "Booleano",
|
||||
"Boolean": "Casella di controllo",
|
||||
"Timestamp": "Timestamp",
|
||||
"Date": "Data",
|
||||
"IntlString": "StringaIntl",
|
||||
"Ref": "Riferimento",
|
||||
"Collection": "Collezione",
|
||||
"Array": "Array",
|
||||
"Enum": "Enumeratore",
|
||||
"Array": "Selezione multipla",
|
||||
"Enum": "Selezione",
|
||||
"Members": "Membri",
|
||||
"Hyperlink": "Hyperlink",
|
||||
"Collaborative": "Collaborativo",
|
||||
|
||||
@@ -16,17 +16,17 @@
|
||||
"Archived": "Arquivado",
|
||||
"ClassLabel": "Tipo",
|
||||
"ClassPropertyLabel": "Rótulo",
|
||||
"String": "Cadeia de texto",
|
||||
"String": "Texto",
|
||||
"Markup": "Marcação",
|
||||
"Number": "Número",
|
||||
"Boolean": "Booleano",
|
||||
"Boolean": "Caixa de seleção",
|
||||
"Timestamp": "Marca de data/hora",
|
||||
"Date": "Data",
|
||||
"IntlString": "Cadeia de texto internacionalizada",
|
||||
"Ref": "Ref.",
|
||||
"Ref": "Referência",
|
||||
"Collection": "Coleção",
|
||||
"Array": "Matriz",
|
||||
"Enum": "Enumeração",
|
||||
"Array": "Seleção múltipla",
|
||||
"Enum": "Seleção",
|
||||
"Members": "Membros",
|
||||
"Hyperlink": "URL",
|
||||
"MarkupBlobRef": "Colaborativo",
|
||||
|
||||
@@ -23,17 +23,17 @@
|
||||
"Archived": "Архивный",
|
||||
"ClassLabel": "Тип",
|
||||
"ClassPropertyLabel": "Название",
|
||||
"String": "Строка",
|
||||
"String": "Текст",
|
||||
"Markup": "Разметка",
|
||||
"Number": "Число",
|
||||
"Boolean": "Логическое",
|
||||
"Boolean": "Чекбокс",
|
||||
"Timestamp": "Временная отметка",
|
||||
"Date": "Дата",
|
||||
"IntlString": "Интернационализированная строка",
|
||||
"Ref": "Ссылка",
|
||||
"Collection": "Коллекция",
|
||||
"Array": "Массив",
|
||||
"Enum": "Справочник",
|
||||
"Array": "Множественный выбор",
|
||||
"Enum": "Выбор",
|
||||
"Members": "Участники",
|
||||
"Hyperlink": "URL",
|
||||
"MarkupBlobRef": "Коллаборативный",
|
||||
|
||||
@@ -23,17 +23,17 @@
|
||||
"Archived": "已归档",
|
||||
"ClassLabel": "类型",
|
||||
"ClassPropertyLabel": "标签",
|
||||
"String": "字符串",
|
||||
"String": "文字",
|
||||
"Markup": "标记",
|
||||
"Number": "数字",
|
||||
"Boolean": "布尔值",
|
||||
"Boolean": "复选框",
|
||||
"Timestamp": "时间戳",
|
||||
"Date": "日期",
|
||||
"IntlString": "国际字符串",
|
||||
"Ref": "引用",
|
||||
"Collection": "集合",
|
||||
"Array": "数组",
|
||||
"Enum": "枚举",
|
||||
"Array": "多选",
|
||||
"Enum": "选择",
|
||||
"Members": "成员",
|
||||
"Hyperlink": "URL",
|
||||
"MarkupBlobRef": "协作",
|
||||
|
||||
@@ -45,13 +45,13 @@
|
||||
return
|
||||
}
|
||||
if (multiselect && Array.isArray(selected)) {
|
||||
const index = selected.indexOf(item.id)
|
||||
if (index !== -1) {
|
||||
selected.splice(index, 1)
|
||||
selected = selected
|
||||
const set = new Set(selected)
|
||||
if (set.has(item.id)) {
|
||||
set.delete(item.id)
|
||||
} else {
|
||||
selected = selected === undefined ? [item.id] : [...selected, item.id]
|
||||
set.add(item.id)
|
||||
}
|
||||
selected = Array.from(set)
|
||||
dispatch('update', selected)
|
||||
} else {
|
||||
dispatch('close', item.id)
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
async function handleDelete (): Promise<void> {
|
||||
await deleteMasterTag(masterTag, () => {
|
||||
const loc = getCurrentLocation()
|
||||
if (masterTag.extends !== card.class.MasterTag && masterTag.extends !== undefined) {
|
||||
if (masterTag.extends !== card.class.Card && masterTag.extends !== undefined) {
|
||||
loc.path[4] = masterTag.extends
|
||||
} else {
|
||||
loc.path.length = 3
|
||||
|
||||
@@ -34,12 +34,18 @@
|
||||
const query = createQuery()
|
||||
|
||||
query.query(core.class.Association, {}, (res) => {
|
||||
console.log(res)
|
||||
associations = res
|
||||
})
|
||||
|
||||
function getClassLabel (_class: Ref<Class<Doc>>): IntlString {
|
||||
const _classLabel = hierarchy.getClass(_class)
|
||||
return _classLabel.label
|
||||
try {
|
||||
const _classLabel = hierarchy.getClass(_class)
|
||||
return _classLabel.label
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return core.string.Class
|
||||
}
|
||||
}
|
||||
|
||||
function addRelation (): void {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Class, Mixin, Doc, Ref, MarkupBlobRef, Rank } from '@hcengineering/core'
|
||||
import { Class, Mixin, Doc, Ref, MarkupBlobRef, Rank, Domain } from '@hcengineering/core'
|
||||
import { Asset, IntlString, plugin, Plugin } from '@hcengineering/platform'
|
||||
import type { AnyComponent } from '@hcengineering/ui'
|
||||
|
||||
@@ -42,6 +42,8 @@ export interface MasterTagEditorSection extends Doc {
|
||||
*/
|
||||
export const cardId = 'card' as Plugin
|
||||
|
||||
export const DOMAIN_CARD = 'card' as Domain
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
|
||||
@@ -57,18 +57,22 @@
|
||||
if (added.has(_id) || ignore.has(_id)) continue
|
||||
const _class = hierarchy.getClass(_id)
|
||||
if (_class.label === undefined) continue
|
||||
if (viewlets.has(hierarchy.getBaseClass(_id))) {
|
||||
added.add(_id)
|
||||
const descendants = hierarchy.getDescendants(_id)
|
||||
const toAdd: Class<Doc>[] = []
|
||||
for (const desc of descendants) {
|
||||
if (added.has(desc) || ignore.has(desc)) continue
|
||||
const _class = hierarchy.getClass(desc)
|
||||
if (_class.label === undefined) continue
|
||||
added.add(desc)
|
||||
toAdd.push(_class)
|
||||
try {
|
||||
if (viewlets.has(hierarchy.getBaseClass(_id))) {
|
||||
added.add(_id)
|
||||
const descendants = hierarchy.getDescendants(_id)
|
||||
const toAdd: Class<Doc>[] = []
|
||||
for (const desc of descendants) {
|
||||
if (added.has(desc) || ignore.has(desc)) continue
|
||||
const _class = hierarchy.getClass(desc)
|
||||
if (_class.label === undefined) continue
|
||||
added.add(desc)
|
||||
toAdd.push(_class)
|
||||
}
|
||||
base.set(_id, toAdd)
|
||||
}
|
||||
base.set(_id, toAdd)
|
||||
} catch (err) {
|
||||
ignore.add(_id)
|
||||
}
|
||||
}
|
||||
const result: [DropdownIntlItem, DropdownIntlItem[]][] = []
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
is={getComponent(selected)}
|
||||
props={{
|
||||
type: type?.of,
|
||||
nested: true,
|
||||
editable,
|
||||
kind,
|
||||
size
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
export let type: EnumOf | undefined
|
||||
export let editable: boolean = true
|
||||
export let value: Enum | undefined
|
||||
export let nested: boolean = false
|
||||
export let defaultValue: string | undefined
|
||||
export let kind: ButtonKind = 'no-border'
|
||||
export let size: ButtonSize = 'small'
|
||||
@@ -66,7 +67,9 @@
|
||||
{#if editable}
|
||||
<EnumSelect label={core.string.Enum} bind:value {create} {kind} {size} />
|
||||
{:else if value}
|
||||
{value.name}
|
||||
<div>
|
||||
{value.name}
|
||||
</div>
|
||||
{/if}
|
||||
{#if value}
|
||||
<Button
|
||||
@@ -79,7 +82,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if value && type}
|
||||
{#if value && type && !nested}
|
||||
<div class="hulyModal-content__settingsSet-line">
|
||||
<span class="label">
|
||||
<Label label={setting.string.DefaultValue} />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import core, { Association, Doc, WithLookup } from '@hcengineering/core'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { Button, IconAdd, Label, Section, showPopup } from '@hcengineering/ui'
|
||||
import { Button, IconAdd, Label, Scroller, Section, showPopup } from '@hcengineering/ui'
|
||||
import { showMenu } from '../actions'
|
||||
import view, { Viewlet, ViewletPreference } from '@hcengineering/view'
|
||||
import DocTable from './DocTable.svelte'
|
||||
@@ -116,16 +116,18 @@
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="content">
|
||||
<div class="antiSection-empty solid flex-col mt-3">
|
||||
{#if docs?.length > 0 && config != null}
|
||||
{#if docs?.length > 0 && config != null}
|
||||
<Scroller horizontal>
|
||||
<DocTable objects={docs} {_class} {config} {onContextMenu} />
|
||||
{:else if !readonly}
|
||||
</Scroller>
|
||||
{:else if !readonly}
|
||||
<div class="antiSection-empty solid clear-mins mt-3">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<span class="over-underline content-color" on:click={add}>
|
||||
<Label label={core.string.AddRelation} />
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</Section>
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import core, { AnyAttribute, Tx, TxCreateDoc, TxProcessor, TxRemoveDoc } from '@hcengineering/core'
|
||||
import card, { MasterTag } from '@hcengineering/card'
|
||||
import core, { AnyAttribute, Class, Doc, Ref, Tx, TxCreateDoc, TxProcessor, TxRemoveDoc } from '@hcengineering/core'
|
||||
import card, { DOMAIN_CARD, MasterTag } from '@hcengineering/card'
|
||||
import view from '@hcengineering/view'
|
||||
import { TriggerControl } from '@hcengineering/server-core'
|
||||
|
||||
@@ -86,7 +86,7 @@ async function OnMasterTagRemove (ctx: TxRemoveDoc<MasterTag>[], control: Trigge
|
||||
const res: Tx[] = []
|
||||
// should remove objects if masterTag
|
||||
if (removedTag._class === card.class.MasterTag) {
|
||||
const cards = await control.findAll(control.ctx, removeTx.objectId, {})
|
||||
const cards = await control.lowLevel.rawFindAll(DOMAIN_CARD, { _class: removedTag._id as Ref<Class<Doc>> })
|
||||
for (const card of cards) {
|
||||
res.push(control.txFactory.createTxRemoveDoc(card._class, card.space, card._id))
|
||||
}
|
||||
@@ -96,6 +96,21 @@ async function OnMasterTagRemove (ctx: TxRemoveDoc<MasterTag>[], control: Trigge
|
||||
if (des === removeTx.objectId) continue
|
||||
res.push(control.txFactory.createTxRemoveDoc(card.class.MasterTag, core.space.Model, des))
|
||||
}
|
||||
const removedRelation = new Set()
|
||||
const relationsA = control.modelDb.findAllSync(core.class.Association, {
|
||||
classA: removeTx.objectId
|
||||
})
|
||||
for (const rel of relationsA) {
|
||||
removedRelation.add(rel._id)
|
||||
res.push(control.txFactory.createTxRemoveDoc(core.class.Association, core.space.Model, rel._id))
|
||||
}
|
||||
const relationsB = control.modelDb.findAllSync(core.class.Association, {
|
||||
classB: removeTx.objectId
|
||||
})
|
||||
for (const rel of relationsB) {
|
||||
if (removedRelation.has(rel._id)) continue
|
||||
res.push(control.txFactory.createTxRemoveDoc(core.class.Association, core.space.Model, rel._id))
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -51,13 +51,15 @@ export class TxMiddleware extends BaseMiddleware implements Middleware {
|
||||
async tx (ctx: MeasureContext, txes: Tx[]): Promise<TxMiddlewareResult> {
|
||||
const txToStore: Tx[] = []
|
||||
for (const tx of txes) {
|
||||
if (tx.space !== core.space.DerivedTx && TxProcessor.isExtendsCUD(tx._class)) {
|
||||
const objectClass = (tx as TxCUD<Doc>).objectClass
|
||||
if (
|
||||
objectClass !== core.class.BenchmarkDoc &&
|
||||
this.context.hierarchy.findDomain(objectClass) !== DOMAIN_TRANSIENT
|
||||
) {
|
||||
txToStore.push(tx)
|
||||
if (TxProcessor.isExtendsCUD(tx._class)) {
|
||||
if (tx.space !== core.space.DerivedTx || tx.objectSpace === core.space.Model) {
|
||||
const objectClass = (tx as TxCUD<Doc>).objectClass
|
||||
if (
|
||||
objectClass !== core.class.BenchmarkDoc &&
|
||||
this.context.hierarchy.findDomain(objectClass) !== DOMAIN_TRANSIENT
|
||||
) {
|
||||
txToStore.push(tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@ export class ClassProperties {
|
||||
}
|
||||
|
||||
url = (): Locator => this.page.getByRole('button', { name: 'URL' })
|
||||
string = (): Locator => this.page.getByRole('button', { name: 'String' })
|
||||
boolean = (): Locator => this.page.getByRole('button', { name: 'Boolean' })
|
||||
string = (): Locator => this.page.getByRole('button', { name: 'Text', exact: true })
|
||||
boolean = (): Locator => this.page.getByRole('button', { name: 'Checkbox' })
|
||||
number = (): Locator => this.page.getByRole('button', { name: 'Number' })
|
||||
date = (): Locator => this.page.getByRole('button', { name: 'Date' })
|
||||
ref = (): Locator => this.page.getByRole('button', { name: 'Ref' })
|
||||
array = (): Locator => this.page.getByRole('button', { name: 'Array' })
|
||||
enum = (): Locator => this.page.getByRole('button', { name: 'Enum', exact: true })
|
||||
ref = (): Locator => this.page.getByRole('button', { name: 'Reference' })
|
||||
array = (): Locator => this.page.getByRole('button', { name: 'Multi-Select' })
|
||||
enum = (): Locator => this.page.getByRole('button', { name: 'Select', exact: true })
|
||||
|
||||
addedCustomAttribute = (attribute: string): Locator => this.page.getByRole('button', { name: attribute })
|
||||
inputName = (): Locator => this.page.getByPlaceholder('Name')
|
||||
|
||||
Reference in New Issue
Block a user