diff --git a/models/core/src/core.ts b/models/core/src/core.ts index 10b9aa527d7..8ea36d341b2 100644 --- a/models/core/src/core.ts +++ b/models/core/src/core.ts @@ -27,6 +27,7 @@ import { type Collection, type Configuration, type ConfigurationElement, + type CustomSequence, type Doc, type Domain, DOMAIN_BLOB, @@ -257,6 +258,12 @@ export class TTypeIntlString extends TType {} @Model(core.class.TypeNumber, core.class.Type) export class TTypeNumber extends TType {} +@UX(core.string.Id) +@Model(core.class.TypeIdentifier, core.class.Type) +export class TTypeIdentifier extends TType { + of!: Ref +} + @UX(core.string.BlobSize) @Model(core.class.TypeFileSize, core.class.Type) export class TTypeFileSize extends TType {} @@ -397,6 +404,11 @@ export class TSequence extends TDoc implements Sequence { sequence!: number } +@Model(core.class.CustomSequence, core.class.Sequence) +export class TCustomSequence extends TSequence implements CustomSequence { + prefix!: string +} + @Model(core.class.ClassCollaborators, core.class.Doc, DOMAIN_MODEL) export class TClassCollaborators extends TDoc implements ClassCollaborators { attachedTo!: Ref> diff --git a/models/core/src/index.ts b/models/core/src/index.ts index a138a1bf6d8..c49249021a6 100644 --- a/models/core/src/index.ts +++ b/models/core/src/index.ts @@ -63,6 +63,7 @@ import { TTypePersonId, TTypeAccountUuid, TTypeNumber, + TTypeIdentifier, TTypeRank, TTypeRecord, TTypeRelatedDocument, @@ -70,6 +71,7 @@ import { TTypeTimestamp, TVersion, TSequence, + TCustomSequence, TClassCollaborators, TCollaborator } from './core' @@ -135,6 +137,7 @@ export function createModel (builder: Builder): void { TTypeFileSize, TTypeTimestamp, TTypeNumber, + TTypeIdentifier, TTypeBoolean, TTypeString, TTypeRank, @@ -155,6 +158,7 @@ export function createModel (builder: Builder): void { TIndexConfiguration, TStatus, TSequence, + TCustomSequence, TDomainStatusPlaceholder, TStatusCategory, TMigrationState, diff --git a/models/setting/src/index.ts b/models/setting/src/index.ts index 60ee4a92073..5fd1b7675aa 100644 --- a/models/setting/src/index.ts +++ b/models/setting/src/index.ts @@ -460,6 +460,10 @@ export function createModel (builder: Builder): void { editor: setting.component.NumberTypeEditor }) + builder.mixin(core.class.TypeIdentifier, core.class.Class, view.mixin.ObjectEditor, { + editor: setting.component.IdentifierTypeEditor + }) + builder.mixin(core.class.RefTo, core.class.Class, view.mixin.ObjectEditor, { editor: setting.component.RefEditor }) diff --git a/models/setting/src/plugin.ts b/models/setting/src/plugin.ts index a9550a6b9b8..542f090832b 100644 --- a/models/setting/src/plugin.ts +++ b/models/setting/src/plugin.ts @@ -37,6 +37,7 @@ export default mergeIds(settingId, setting, { HyperlinkTypeEditor: '' as AnyComponent, BooleanTypeEditor: '' as AnyComponent, NumberTypeEditor: '' as AnyComponent, + IdentifierTypeEditor: '' as AnyComponent, DateTypeEditor: '' as AnyComponent, RefEditor: '' as AnyComponent, AssociationEditor: '' as AnyComponent, diff --git a/models/view/src/index.ts b/models/view/src/index.ts index 5ca2d0d41f7..03e890e10ab 100644 --- a/models/view/src/index.ts +++ b/models/view/src/index.ts @@ -506,6 +506,7 @@ export function createModel (builder: Builder): void { ) classPresenter(builder, core.class.TypeIntlString, view.component.IntlStringPresenter) classPresenter(builder, core.class.TypeNumber, view.component.NumberPresenter, view.component.NumberEditor) + classPresenter(builder, core.class.TypeIdentifier, view.component.IdPresenter, view.component.IdPresenter) classPresenter( builder, core.class.TypeMarkup, diff --git a/plugins/client-resources/package.json b/plugins/client-resources/package.json index 357ca77d62b..2aa14e3c142 100644 --- a/plugins/client-resources/package.json +++ b/plugins/client-resources/package.json @@ -42,7 +42,7 @@ "@hcengineering/client": "^0.7.3", "@hcengineering/communication-sdk-types": "^0.7.5", "@hcengineering/communication-types": "^0.7.7", - "@hcengineering/core": "^0.7.8", + "@hcengineering/core": "^0.7.10", "@hcengineering/platform": "^0.7.5", "@hcengineering/rpc": "^0.7.3", "snappyjs": "^0.7.0" diff --git a/plugins/client/package.json b/plugins/client/package.json index 75df538d374..439165d62e7 100644 --- a/plugins/client/package.json +++ b/plugins/client/package.json @@ -38,7 +38,7 @@ }, "dependencies": { "@hcengineering/platform": "^0.7.5", - "@hcengineering/core": "^0.7.8" + "@hcengineering/core": "^0.7.10" }, "repository": "https://github.com/hcengineering/platform", "publishConfig": { diff --git a/plugins/setting-assets/lang/cs.json b/plugins/setting-assets/lang/cs.json index 47517f5d935..7b657da7c6d 100644 --- a/plugins/setting-assets/lang/cs.json +++ b/plugins/setting-assets/lang/cs.json @@ -202,6 +202,7 @@ "DangerZone": "Nebezpečná zóna", "ApiAccess": "Přístup k API", "ApiToken": "API token", - "GenerateApiToken": "Vygenerovat API token" + "GenerateApiToken": "Vygenerovat API token", + "IdentifierExists": "Identifikátor již existuje" } } diff --git a/plugins/setting-assets/lang/de.json b/plugins/setting-assets/lang/de.json index f71506cfba6..f7f118945a9 100644 --- a/plugins/setting-assets/lang/de.json +++ b/plugins/setting-assets/lang/de.json @@ -204,6 +204,7 @@ "DangerZone": "Gefahrenzone", "ApiAccess": "API-Zugriff", "ApiToken": "API-Token", - "GenerateApiToken": "API-Token generieren" + "GenerateApiToken": "API-Token generieren", + "IdentifierExists": "Bezeichner existiert bereits" } } diff --git a/plugins/setting-assets/lang/en.json b/plugins/setting-assets/lang/en.json index e2d5ff25ced..3ccfc631eb1 100644 --- a/plugins/setting-assets/lang/en.json +++ b/plugins/setting-assets/lang/en.json @@ -204,6 +204,7 @@ "DangerZone": "Danger zone", "ApiAccess": "API access", "ApiToken": "API token", - "GenerateApiToken": "Generate API token" + "GenerateApiToken": "Generate API token", + "IdentifierExists": "Identifier already exists" } } diff --git a/plugins/setting-assets/lang/es.json b/plugins/setting-assets/lang/es.json index 41ab01b2354..b638c8e3fd8 100644 --- a/plugins/setting-assets/lang/es.json +++ b/plugins/setting-assets/lang/es.json @@ -195,6 +195,7 @@ "DangerZone": "Zona de peligro", "ApiAccess": "Acceso API", "ApiToken": "Token API", - "GenerateApiToken": "Generar token API" + "GenerateApiToken": "Generar token API", + "IdentifierExists": "El identificador ya existe" } } diff --git a/plugins/setting-assets/lang/fr.json b/plugins/setting-assets/lang/fr.json index 2a738bd64a9..340ddebaa61 100644 --- a/plugins/setting-assets/lang/fr.json +++ b/plugins/setting-assets/lang/fr.json @@ -204,6 +204,7 @@ "DangerZone": "Zone dangereuse", "ApiAccess": "Accès API", "ApiToken": "Token API", - "GenerateApiToken": "Générer un token API" + "GenerateApiToken": "Générer un token API", + "IdentifierExists": "Identifiant déjà utilisé" } } diff --git a/plugins/setting-assets/lang/it.json b/plugins/setting-assets/lang/it.json index d2382c5d8c5..6b3cf9f9f27 100644 --- a/plugins/setting-assets/lang/it.json +++ b/plugins/setting-assets/lang/it.json @@ -204,6 +204,7 @@ "DangerZone": "Zona pericolosa", "ApiAccess": "Accesso API", "ApiToken": "Token API", - "GenerateApiToken": "Genera token API" + "GenerateApiToken": "Genera token API", + "IdentifierExists": "Identificatore già esistente" } } diff --git a/plugins/setting-assets/lang/ja.json b/plugins/setting-assets/lang/ja.json index bea50ca974e..b82de4d9329 100644 --- a/plugins/setting-assets/lang/ja.json +++ b/plugins/setting-assets/lang/ja.json @@ -204,6 +204,7 @@ "DangerZone": "危険ゾーン", "ApiAccess": "APIアクセス", "ApiToken": "APIトークン", - "GenerateApiToken": "APIトークンを生成" + "GenerateApiToken": "APIトークンを生成", + "IdentifierExists": "識別子は既に存在します" } } diff --git a/plugins/setting-assets/lang/pt.json b/plugins/setting-assets/lang/pt.json index fb671c09c87..efedf23ce1c 100644 --- a/plugins/setting-assets/lang/pt.json +++ b/plugins/setting-assets/lang/pt.json @@ -195,6 +195,7 @@ "DangerZone": "Zona de perigo", "ApiAccess": "Acesso à API", "ApiToken": "Token de API", - "GenerateApiToken": "Gerar token de API" + "GenerateApiToken": "Gerar token de API", + "IdentifierExists": "Identificador já existe" } } diff --git a/plugins/setting-assets/lang/ru.json b/plugins/setting-assets/lang/ru.json index f72c2058c8b..7e28be88a4c 100644 --- a/plugins/setting-assets/lang/ru.json +++ b/plugins/setting-assets/lang/ru.json @@ -9,6 +9,7 @@ "MinValue": "Минимальное значение", "MaxValue": "Максимальное значение", "IntegerOnly": "Только целые числа", + "IdentifierExists": "\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442", "AccountSettings": "Настройки аккаунта", "Categories": "Категории", "Delete": "Удалить", diff --git a/plugins/setting-assets/lang/tr.json b/plugins/setting-assets/lang/tr.json index b05bfca09f4..0cb758f09f7 100644 --- a/plugins/setting-assets/lang/tr.json +++ b/plugins/setting-assets/lang/tr.json @@ -204,6 +204,7 @@ "DangerZone": "Tehlike bölgesi", "ApiAccess": "API erişimi", "ApiToken": "API token", - "GenerateApiToken": "API token oluştur" + "GenerateApiToken": "API token oluştur", + "IdentifierExists": "Tanımlayıcı zaten mevcut" } } diff --git a/plugins/setting-assets/lang/zh.json b/plugins/setting-assets/lang/zh.json index f1565044223..9fbb73a2115 100644 --- a/plugins/setting-assets/lang/zh.json +++ b/plugins/setting-assets/lang/zh.json @@ -204,6 +204,7 @@ "DangerZone": "危险区域", "ApiAccess": "API访问", "ApiToken": "API令牌", - "GenerateApiToken": "生成API令牌" + "GenerateApiToken": "生成API令牌", + "IdentifierExists": "标识符已存在" } } diff --git a/plugins/setting-resources/src/components/typeEditors/IdentifierTypeEditor.svelte b/plugins/setting-resources/src/components/typeEditors/IdentifierTypeEditor.svelte new file mode 100644 index 00000000000..c61e095d19d --- /dev/null +++ b/plugins/setting-resources/src/components/typeEditors/IdentifierTypeEditor.svelte @@ -0,0 +1,85 @@ + + + + + +
+ + {#if editable && identifiers.has(identifier.toUpperCase())} +
+
+ {/if} +
+ + diff --git a/plugins/setting-resources/src/index.ts b/plugins/setting-resources/src/index.ts index 8151e4b97ac..8bed918682e 100644 --- a/plugins/setting-resources/src/index.ts +++ b/plugins/setting-resources/src/index.ts @@ -55,6 +55,7 @@ import EnumTypeEditor from './components/typeEditors/EnumTypeEditor.svelte' import HyperlinkTypeEditor from './components/typeEditors/HyperlinkTypeEditor.svelte' import NumberTypeEditor from './components/typeEditors/NumberTypeEditor.svelte' import RefEditor from './components/typeEditors/RefEditor.svelte' +import IdentifierTypeEditor from './components/typeEditors/IdentifierTypeEditor.svelte' import RelationSetting from './components/RelationSetting.svelte' import RoleAssignmentEditor from './components/typeEditors/RoleAssignmentEditor.svelte' import StringTypeEditor from './components/typeEditors/StringTypeEditor.svelte' @@ -122,6 +123,7 @@ export default async (): Promise => ({ HyperlinkTypeEditor, BooleanTypeEditor, NumberTypeEditor, + IdentifierTypeEditor, RefEditor, RelationSetting, DateTypeEditor, diff --git a/plugins/setting-resources/src/plugin.ts b/plugins/setting-resources/src/plugin.ts index 0a5b53a1b67..8e3e5769539 100644 --- a/plugins/setting-resources/src/plugin.ts +++ b/plugins/setting-resources/src/plugin.ts @@ -147,6 +147,7 @@ export default mergeIds(settingId, setting, { ReleasePrimarySocialId: '' as IntlString, ReleasePrimarySocialIdConfirm: '' as IntlString, Login: '' as IntlString, - Primary: '' as IntlString + Primary: '' as IntlString, + IdentifierExists: '' as IntlString } }) diff --git a/plugins/view-resources/src/components/IdPresenter.svelte b/plugins/view-resources/src/components/IdPresenter.svelte new file mode 100644 index 00000000000..cc8ad0a29c4 --- /dev/null +++ b/plugins/view-resources/src/components/IdPresenter.svelte @@ -0,0 +1,33 @@ + + + + + {value ?? ''} + diff --git a/plugins/view-resources/src/index.ts b/plugins/view-resources/src/index.ts index fa37305b875..3c2571c8d47 100644 --- a/plugins/view-resources/src/index.ts +++ b/plugins/view-resources/src/index.ts @@ -63,6 +63,7 @@ import ObjectMention from './components/ObjectMention.svelte' import ObjectPresenter from './components/ObjectPresenter.svelte' import PersonArrayEditor from './components/PersonArrayEditor.svelte' import PersonIdPresenter from './components/PersonIdPresenter.svelte' +import IdPresenter from './components/IdPresenter.svelte' import ReadOnlyNotification from './components/ReadOnlyNotification.svelte' import RolePresenter from './components/RolePresenter.svelte' import SearchSelector from './components/SearchSelector.svelte' @@ -274,6 +275,7 @@ export default async (): Promise => ({ TimestampFilter, TableBrowser, SpacePresenter, + IdPresenter, StringEditor, StringPresenter, HyperlinkPresenter, diff --git a/plugins/view-resources/src/plugin.ts b/plugins/view-resources/src/plugin.ts index e35d4df94c1..f265ff83187 100644 --- a/plugins/view-resources/src/plugin.ts +++ b/plugins/view-resources/src/plugin.ts @@ -33,7 +33,8 @@ export default mergeIds(viewId, view, { SpaceTypeSelector: '' as AnyComponent, MasterDetailBrowser: '' as AnyComponent, NumberEditor: '' as AnyComponent, - NumberPresenter: '' as AnyComponent + NumberPresenter: '' as AnyComponent, + IdPresenter: '' as AnyComponent }, string: { Contains: '' as IntlString, diff --git a/server/server-pipeline/src/pipeline.ts b/server/server-pipeline/src/pipeline.ts index 55692b04a5a..71d1c7809eb 100644 --- a/server/server-pipeline/src/pipeline.ts +++ b/server/server-pipeline/src/pipeline.ts @@ -36,6 +36,7 @@ import { MarkDerivedEntryMiddleware, ModelMiddleware, ModifiedMiddleware, + IdentifierMiddleware, NormalizeTxMiddleware, PluginConfigurationMiddleware, PrivateMiddleware, @@ -154,6 +155,7 @@ export function createServerPipeline ( : []), UserStatusMiddleware.create, ApplyTxMiddleware.create, // Extract apply + IdentifierMiddleware.create, // After ApplyTx to ensure that it pass TxMiddleware.create, // Store tx into transaction domain ...(opt.disableTriggers === true ? [] : [TriggersMiddleware.create]), ...(opt.fulltextUrl !== undefined