diff --git a/foundations/core/packages/core/src/classes.ts b/foundations/core/packages/core/src/classes.ts index 0714ca0bcc..b9c62466d9 100644 --- a/foundations/core/packages/core/src/classes.ts +++ b/foundations/core/packages/core/src/classes.ts @@ -227,6 +227,7 @@ export interface Attribute extends Doc, UXObject { defaultValue?: any automationOnly?: boolean rank?: Rank + required?: boolean // Extra customization properties [key: string]: any diff --git a/models/core/src/core.ts b/models/core/src/core.ts index f0feb13166..d6f4588a90 100644 --- a/models/core/src/core.ts +++ b/models/core/src/core.ts @@ -247,6 +247,7 @@ export class TAttribute extends TDoc implements AnyAttribute { isCustom?: boolean defaultValue?: any automationOnly?: boolean + required?: boolean } @Model(core.class.Type, core.class.Obj, DOMAIN_MODEL) diff --git a/packages/presentation/src/components/AttributeBarEditor.svelte b/packages/presentation/src/components/AttributeBarEditor.svelte index 68d0dec7ba..ebf6621b9d 100644 --- a/packages/presentation/src/components/AttributeBarEditor.svelte +++ b/packages/presentation/src/components/AttributeBarEditor.svelte @@ -14,9 +14,10 @@ // limitations under the License. --> {#if editor} {#if showHeader}
@@ -106,7 +120,7 @@ {maxWidth} {attribute} {attributeKey} - value={getAttribute(client, object, { key: attributeKey, attr: attribute })} + {value} space={object.space} {onChange} {focus} @@ -114,13 +128,13 @@ />
{:else} -
+
{/if} {/if} + + diff --git a/plugins/card-resources/src/components/MarkupProperties.svelte b/plugins/card-resources/src/components/MarkupProperties.svelte index ba5c24cbcf..7d263e467c 100644 --- a/plugins/card-resources/src/components/MarkupProperties.svelte +++ b/plugins/card-resources/src/components/MarkupProperties.svelte @@ -19,6 +19,7 @@ import core, { Blob, Class, Doc, Ref, toRank } from '@hcengineering/core' import { getResource, setPlatformStatus, unknownError } from '@hcengineering/platform' import { getClient, KeyedAttribute, updateAttribute } from '@hcengineering/presentation' + import { isEmptyMarkup } from '@hcengineering/text' import { Label } from '@hcengineering/ui' import { MarkupEditor } from '@hcengineering/view-resources' import { createEventDispatcher } from 'svelte' @@ -75,17 +76,34 @@ {#each keys as key} + {@const val = getValue(doc, key.key)} + {@const isRequiredAndEmpty = (key.attr.required ?? false) && isEmptyMarkup(val)}
- + - { - onChange(value, key) - }} - {readonly} - {attachFile} - /> +
+ { + onChange(value, key) + }} + {readonly} + {attachFile} + /> +
{/each} + + diff --git a/plugins/process-assets/lang/cs.json b/plugins/process-assets/lang/cs.json index 07ec6bf5f3..88a932ad5e 100644 --- a/plugins/process-assets/lang/cs.json +++ b/plugins/process-assets/lang/cs.json @@ -176,7 +176,8 @@ "ExportWithSlots": "Exportovat se sloty", "ExportWithoutSlots": "Exportovat bez slotů", "RequiredSlots": "Požadované sloty", - "Bindings": "Vazby" + "Bindings": "Vazby", + "AskRequired": "zeptat se na prázdná povinná pole" }, "error": { "MethodNotFound": "Metoda nenalezena: {methodId}", diff --git a/plugins/process-assets/lang/de.json b/plugins/process-assets/lang/de.json index c7b1404c3f..3fc9c49bcb 100644 --- a/plugins/process-assets/lang/de.json +++ b/plugins/process-assets/lang/de.json @@ -176,7 +176,8 @@ "ExportWithSlots": "Slot-Export", "ExportWithoutSlots": "Slot-freier Export", "RequiredSlots": "Erforderliche Slots", - "Bindings": "Bindungen" + "Bindings": "Bindungen", + "AskRequiredFields": "Erforderliche Felder erfragen" }, "error": { "MethodNotFound": "Methode nicht gefunden: {methodId}", diff --git a/plugins/process-assets/lang/en.json b/plugins/process-assets/lang/en.json index 52fbfa7f09..77cd0b4ff4 100644 --- a/plugins/process-assets/lang/en.json +++ b/plugins/process-assets/lang/en.json @@ -181,6 +181,7 @@ "TextFromSelect": "Text from select", "SelectFromText": "Select from text", "AskSubclass": "Ask subclass", + "AskRequired": "Ask all required fields", "TextFromIdentifier": "Text from identifier" }, "error": { diff --git a/plugins/process-assets/lang/es.json b/plugins/process-assets/lang/es.json index 686f4125e4..bb5ec675de 100644 --- a/plugins/process-assets/lang/es.json +++ b/plugins/process-assets/lang/es.json @@ -181,7 +181,8 @@ "ExportWithSlots": "Exportar con slots", "ExportWithoutSlots": "Exportar sin slots", "RequiredSlots": "Slots requeridos", - "Bindings": "Bindings" + "Bindings": "Bindings", + "AskRequired": "Preguntar por campos requeridos" }, "error": { "MethodNotFound": "Método no encontrado: {methodId}", diff --git a/plugins/process-assets/lang/fr.json b/plugins/process-assets/lang/fr.json index 3dfca17bcb..8a0a0f32be 100644 --- a/plugins/process-assets/lang/fr.json +++ b/plugins/process-assets/lang/fr.json @@ -181,7 +181,8 @@ "ExportWithSlots": "Exporter avec slots", "ExportWithoutSlots": "Exporter sans slots", "RequiredSlots": "Slots requis", - "Bindings": "Bindings" + "Bindings": "Bindings", + "AskRequired": "Demander les champs requis" }, "error": { "MethodNotFound": "Méthode introuvable : {methodId}", diff --git a/plugins/process-assets/lang/it.json b/plugins/process-assets/lang/it.json index a05b08321e..741eb227b2 100644 --- a/plugins/process-assets/lang/it.json +++ b/plugins/process-assets/lang/it.json @@ -181,7 +181,8 @@ "ExportWithSlots": "Esporta con slot", "ExportWithoutSlots": "Esporta senza slot", "RequiredSlots": "Slot richiesti", - "Bindings": "Binding" + "Bindings": "Binding", + "AskRequired": "Richiedi campi" }, "error": { "MethodNotFound": "Metodo non trovato: {methodId}", diff --git a/plugins/process-assets/lang/ja.json b/plugins/process-assets/lang/ja.json index da2e957b93..365f6f1945 100644 --- a/plugins/process-assets/lang/ja.json +++ b/plugins/process-assets/lang/ja.json @@ -180,7 +180,8 @@ "ExportWithSlots": "スロット付きでエクスポート", "ExportWithoutSlots": "スロットなしでエクスポート", "RequiredSlots": "必須スロット", - "Bindings": "バインディング" + "Bindings": "バインディング", + "AskRequired": "必須フィールドを尋ねる" }, "error": { "MethodNotFound": "メソッドが見つかりません: {methodId}", diff --git a/plugins/process-assets/lang/ko.json b/plugins/process-assets/lang/ko.json index 06a521d6a5..8ed05ea4d2 100644 --- a/plugins/process-assets/lang/ko.json +++ b/plugins/process-assets/lang/ko.json @@ -181,7 +181,8 @@ "ExportWithSlots": "슬롯 포함 내보내기", "ExportWithoutSlots": "슬롯 없이 내보내기", "RequiredSlots": "필수 슬롯", - "Bindings": "바인딩" + "Bindings": "바인딩", + "AskRequired": "필수 필드 질문" }, "error": { "MethodNotFound": "메서드를 찾을 수 없습니다: {methodId}", diff --git a/plugins/process-assets/lang/pl.json b/plugins/process-assets/lang/pl.json index 57b143ccdd..a2a7144bca 100644 --- a/plugins/process-assets/lang/pl.json +++ b/plugins/process-assets/lang/pl.json @@ -181,7 +181,8 @@ "TextFromSelect": "Tekst z wyboru", "SelectFromText": "Wybór z tekstu", "AskSubclass": "Poproś o podklasę", - "TextFromIdentifier": "Tekst z identyfikatora" + "TextFromIdentifier": "Tekst z identyfikatora", + "AskRequired": "Poproś o wymagane pola" }, "error": { "MethodNotFound": "Nie odnaleziono metody: {methodId}", diff --git a/plugins/process-assets/lang/pt-br.json b/plugins/process-assets/lang/pt-br.json index 337d703e96..1639ab36f1 100644 --- a/plugins/process-assets/lang/pt-br.json +++ b/plugins/process-assets/lang/pt-br.json @@ -169,7 +169,8 @@ "ExportWithSlots": "Exportar com slots", "ExportWithoutSlots": "Exportar sem slots", "RequiredSlots": "Slots necessários", - "Bindings": "Vinculações" + "Bindings": "Vinculações", + "AskRequired": "Perguntar por campos requeridos" }, "error": { "MethodNotFound": "Método não encontrado: {methodId}", diff --git a/plugins/process-assets/lang/pt.json b/plugins/process-assets/lang/pt.json index acc487f87d..50555ad95c 100644 --- a/plugins/process-assets/lang/pt.json +++ b/plugins/process-assets/lang/pt.json @@ -181,7 +181,8 @@ "ExportWithSlots": "Exportar com slots", "ExportWithoutSlots": "Exportar sem slots", "RequiredSlots": "Slots necessários", - "Bindings": "Vinculações" + "Bindings": "Vinculações", + "AskRequired": "Perguntar por campos requeridos" }, "error": { "MethodNotFound": "Método não encontrado: {methodId}", diff --git a/plugins/process-assets/lang/ru.json b/plugins/process-assets/lang/ru.json index f72ddc3ed4..e9e2cdcb44 100644 --- a/plugins/process-assets/lang/ru.json +++ b/plugins/process-assets/lang/ru.json @@ -181,6 +181,7 @@ "TextFromSelect": "Текст из выбора", "SelectFromText": "Выбор из текста", "AskSubclass": "Спросить подкласс", + "AskRequired": "Запросить все обязательные поля", "TextFromIdentifier": "Текст из идентификатора" }, "error": { diff --git a/plugins/process-assets/lang/tr.json b/plugins/process-assets/lang/tr.json index 7ec970a7e0..dd6056b583 100644 --- a/plugins/process-assets/lang/tr.json +++ b/plugins/process-assets/lang/tr.json @@ -176,7 +176,8 @@ "ExportWithSlots": "Slotlu dışa aktar", "ExportWithoutSlots": "Slotsuz dışa aktar", "RequiredSlots": "Gerekli slotlar", - "Bindings": "Bağlamalar" + "Bindings": "Bağlamalar", + "AskRequired": "Gerekli alanları sor" }, "error": { "MethodNotFound": "Metod bulunamadı: {methodId}", diff --git a/plugins/process-assets/lang/zh.json b/plugins/process-assets/lang/zh.json index 2f88e9a3da..b1fe7d03d8 100644 --- a/plugins/process-assets/lang/zh.json +++ b/plugins/process-assets/lang/zh.json @@ -181,7 +181,8 @@ "ExportWithSlots": "导出包含槽", "ExportWithoutSlots": "导出不含槽", "RequiredSlots": "必需槽", - "Bindings": "绑定" + "Bindings": "绑定", + "AskRequired": "询问必需字段" }, "error": { "MethodNotFound": "找不到方法:{methodId}", diff --git a/plugins/process-resources/src/components/settings/AddTagEditor.svelte b/plugins/process-resources/src/components/settings/AddTagEditor.svelte index 9daea38c9d..e2186b983b 100644 --- a/plugins/process-resources/src/components/settings/AddTagEditor.svelte +++ b/plugins/process-resources/src/components/settings/AddTagEditor.svelte @@ -14,13 +14,15 @@ -->
@@ -104,6 +137,17 @@
{ - return key !== '_class' && key !== 'targetClass' + return key !== '_class' && key !== 'targetClass' && key !== 'askRequired' && key !== 'requiredFields' }) $: allAttrs = getKeys(targetClass) @@ -116,7 +116,7 @@ function typeChange (_id: Ref>): void { if (_id === undefined) return - const attrKeys = ['_class', 'targetClass', ...getKeys(_id).map((p) => p.name)] + const attrKeys = ['_class', 'targetClass', 'askRequired', 'requiredFields', ...getKeys(_id).map((p) => p.name)] const oldParams = { ...params } params = {} for (const key of attrKeys) { @@ -125,12 +125,22 @@ } } keys = Object.keys(params).filter((key) => { - return key !== '_class' && key !== 'targetClass' + return key !== '_class' && key !== 'targetClass' && key !== 'askRequired' && key !== 'requiredFields' }) if (params.targetClass !== _id) { params._class = _id params.targetClass = _id } + if (params.askRequired) { + params.requiredFields = createContext({ + type: 'userRequest', + id: generateContextId(), + _class: _id, + key: 'requiredFields' + }) + } else { + delete params.requiredFields + } step.params = params if (step.context != null) { step.context._class = _id @@ -158,6 +168,27 @@ dispatch('change', step) } } + + let askRequired = params.askRequired ?? false + $: askRequired = params.askRequired ?? false + + function changeAskRequired (e: CustomEvent): void { + if (e.detail !== undefined) { + params.askRequired = e.detail + if (e.detail) { + params.requiredFields = createContext({ + type: 'userRequest', + id: generateContextId(), + _class: targetClass, + key: 'requiredFields' + }) + } else { + delete params.requiredFields + } + step.params = params + dispatch('change', step) + } + }
@@ -191,6 +222,17 @@
{/if} + + +
+ +
{#key targetClass} diff --git a/plugins/process-resources/src/plugin.ts b/plugins/process-resources/src/plugin.ts index 2660e72719..ebe7e07880 100644 --- a/plugins/process-resources/src/plugin.ts +++ b/plugins/process-resources/src/plugin.ts @@ -286,6 +286,7 @@ export default mergeIds(processId, process, { TextFromSelect: '' as IntlString, SelectFromText: '' as IntlString, AskSubclass: '' as IntlString, + AskRequired: '' as IntlString, RequiredSlots: '' as IntlString, Bindings: '' as IntlString }, diff --git a/plugins/process-resources/src/utils.ts b/plugins/process-resources/src/utils.ts index d990aa49ee..b75623184b 100644 --- a/plugins/process-resources/src/utils.ts +++ b/plugins/process-resources/src/utils.ts @@ -543,10 +543,59 @@ export async function getTransitionUserInput ( skipExisting: boolean = false ): Promise { let changed = false + const client = getClient() + const hierarchy = client.getHierarchy() + for (const action of transition.actions) { if (action == null) continue const inputs: SelectedUserRequest[] = [] + + // Map of: tempInputId -> { attrName, virtualContextId } + const dynamicMappings: Record = {} + + // Check for virtual required attributes + let virtualContext: SelectedUserRequest | undefined + let virtualKey = '' + if (action.params.requiredFields !== undefined) { + virtualContext = parseContext(action.params.requiredFields) as SelectedUserRequest + virtualKey = 'requiredFields' + } else if (action.params.requiredProperties !== undefined) { + virtualContext = parseContext(action.params.requiredProperties) as SelectedUserRequest + virtualKey = 'requiredProperties' + } + + if (virtualContext !== undefined && virtualContext.type === 'userRequest') { + const classId = virtualContext._class + const allAttributes = + virtualKey === 'requiredFields' + ? Array.from(hierarchy.getAllAttributes(classId, core.class.Doc).values()) + : Array.from(hierarchy.getOwnAttributes(classId).values()) + + for (const attr of allAttributes) { + if (virtualKey === 'requiredFields' && attr.name === 'title') continue + if (attr.hidden === true) continue + + const isConfigured = + virtualKey === 'requiredFields' + ? action.params[attr.name] !== undefined + : action.params.props !== undefined && action.params.props[attr.name] !== undefined + + if (attr.required === true && !isConfigured) { + const tempInputId = generateContextId() + dynamicMappings[tempInputId] = { attrName: attr.name, virtualContextId: virtualContext.id } + inputs.push({ + type: 'userRequest', + id: tempInputId, + key: attr.name, + _class: classId + }) + } + } + } + for (const key in action.params) { + if (key === 'requiredFields' || key === 'requiredProperties') continue + const value = (action.params as any)[key] if (typeof value === 'string') { const context = parseContext(value) @@ -564,6 +613,7 @@ export async function getTransitionUserInput ( } } } + if (inputs.length > 0) { const promise = new Promise((resolve, reject) => { showPopup( @@ -580,9 +630,24 @@ export async function getTransitionUserInput ( const isComplete = res?.value !== undefined && inputs.every((input) => res.value[input.id] != null) if (isComplete) { changed = true + const groupedValues: Record> = {} + for (const [key, value] of Object.entries(res.value)) { - userContext[key as ContextId] = value + const mapping = dynamicMappings[key] + if (mapping !== undefined) { + if (groupedValues[mapping.virtualContextId] === undefined) { + groupedValues[mapping.virtualContextId] = {} + } + groupedValues[mapping.virtualContextId][mapping.attrName] = value + } else { + userContext[key as ContextId] = value + } } + + for (const [virtualId, obj] of Object.entries(groupedValues)) { + userContext[virtualId as ContextId] = obj + } + resolve() } else { reject(new PlatformError(new Status(Severity.ERROR, process.error.ResultNotProvided, {}))) diff --git a/plugins/setting-assets/lang/cs.json b/plugins/setting-assets/lang/cs.json index 7f5e99831e..80886f8acb 100644 --- a/plugins/setting-assets/lang/cs.json +++ b/plugins/setting-assets/lang/cs.json @@ -238,6 +238,7 @@ "TwoFactorAuthDisabled": "Dvoufaktorové ověřování je zakázáno", "ShowQRCode": "Zobrazit QR kód", "EnterVerificationCode": "Zadejte ověřovací kód", - "OverrideAttribute": "Přepsat atribut" + "OverrideAttribute": "Přepsat atribut", + "Required": "Požadované" } } diff --git a/plugins/setting-assets/lang/de.json b/plugins/setting-assets/lang/de.json index 2bd045d66b..913c868e6e 100644 --- a/plugins/setting-assets/lang/de.json +++ b/plugins/setting-assets/lang/de.json @@ -240,6 +240,7 @@ "TwoFactorAuthDisabled": "Zweistufige Authentifizierung ist deaktiviert", "ShowQRCode": "QR-Code anzeigen", "EnterVerificationCode": "Verifizierungscode eingeben", - "OverrideAttribute": "Überschreibattribut" + "OverrideAttribute": "Überschreibattribut", + "Required": "Pflichtfeld" } } diff --git a/plugins/setting-assets/lang/en.json b/plugins/setting-assets/lang/en.json index fcba270006..fc68364325 100644 --- a/plugins/setting-assets/lang/en.json +++ b/plugins/setting-assets/lang/en.json @@ -240,6 +240,7 @@ "TwoFactorAuthDisabled": "Two-factor authentication is disabled", "ShowQRCode": "Show QR code", "EnterVerificationCode": "Enter verification code", - "OverrideAttribute": "Override attribute" + "OverrideAttribute": "Override attribute", + "Required": "Required" } } diff --git a/plugins/setting-assets/lang/es.json b/plugins/setting-assets/lang/es.json index 8a47eda1ff..d1873d126b 100644 --- a/plugins/setting-assets/lang/es.json +++ b/plugins/setting-assets/lang/es.json @@ -231,6 +231,7 @@ "TwoFactorAuthDisabled": "La autenticación de dos factores está deshabilitada", "ShowQRCode": "Mostrar código QR", "EnterVerificationCode": "Introducir código de verificación", - "OverrideAttribute": "Sobreescribir atributo" + "OverrideAttribute": "Sobreescribir atributo", + "Required": "Requerido" } } diff --git a/plugins/setting-assets/lang/fr.json b/plugins/setting-assets/lang/fr.json index 109e190ea2..73e77fa3e6 100644 --- a/plugins/setting-assets/lang/fr.json +++ b/plugins/setting-assets/lang/fr.json @@ -240,6 +240,7 @@ "TwoFactorAuthDisabled": "L'authentification à deux facteurs est désactivée", "ShowQRCode": "Afficher le code QR", "EnterVerificationCode": "Entrer le code de vérification", - "OverrideAttribute": "Surcharger l'attribut" + "OverrideAttribute": "Surcharger l'attribut", + "Required": "Requis" } } diff --git a/plugins/setting-assets/lang/it.json b/plugins/setting-assets/lang/it.json index 318976c117..319705e9f5 100644 --- a/plugins/setting-assets/lang/it.json +++ b/plugins/setting-assets/lang/it.json @@ -240,6 +240,7 @@ "TwoFactorAuthDisabled": "L'autenticazione a due fattori è disabilitata", "ShowQRCode": "Mostra codice QR", "EnterVerificationCode": "Inserisci codice di verifica", - "OverrideAttribute": "Sovrascrivi attributo" + "OverrideAttribute": "Sovrascrivi attributo", + "Required": "Richiesto" } } diff --git a/plugins/setting-assets/lang/ja.json b/plugins/setting-assets/lang/ja.json index aae41d43b6..6cac7cc427 100644 --- a/plugins/setting-assets/lang/ja.json +++ b/plugins/setting-assets/lang/ja.json @@ -240,6 +240,7 @@ "TwoFactorAuthDisabled": "二要素認証は無効です", "ShowQRCode": "QRコードを表示", "EnterVerificationCode": "確認コードを入力", - "OverrideAttribute": "属性を上書き" + "OverrideAttribute": "属性を上書き", + "Required": "必須" } } diff --git a/plugins/setting-assets/lang/ko.json b/plugins/setting-assets/lang/ko.json index 313725b921..f673b24756 100644 --- a/plugins/setting-assets/lang/ko.json +++ b/plugins/setting-assets/lang/ko.json @@ -240,6 +240,7 @@ "TwoFactorAuthDisabled": "2단계 인증이 비활성화됨", "ShowQRCode": "QR 코드 표시", "EnterVerificationCode": "인증 코드 입력", - "OverrideAttribute": "속성 재정의" + "OverrideAttribute": "속성 재정의", + "Required": "필수" } } diff --git a/plugins/setting-assets/lang/pl.json b/plugins/setting-assets/lang/pl.json index ade3751d2c..1e0b32e4d7 100644 --- a/plugins/setting-assets/lang/pl.json +++ b/plugins/setting-assets/lang/pl.json @@ -240,6 +240,7 @@ "TwoFactorAuthDisabled": "Uwierzytelnienie dwuskładnikowe jest wyłączone", "ShowQRCode": "Pokaż kod QR", "EnterVerificationCode": "Wpisz kod weryfikacyjny", - "OverrideAttribute": "Nadpisz atrybut" + "OverrideAttribute": "Nadpisz atrybut", + "Required": "Obowiązkowe" } } diff --git a/plugins/setting-assets/lang/pt-br.json b/plugins/setting-assets/lang/pt-br.json index 8c3c88d342..94f98fc645 100644 --- a/plugins/setting-assets/lang/pt-br.json +++ b/plugins/setting-assets/lang/pt-br.json @@ -231,6 +231,7 @@ "TwoFactorAuthDisabled": "Autenticação de dois fatores está desativada", "ShowQRCode": "Mostrar código QR", "EnterVerificationCode": "Inserir código de verificação", - "OverrideAttribute": "Sobrescrever atributo" + "OverrideAttribute": "Sobrescrever atributo", + "Required": "Obrigatório" } } diff --git a/plugins/setting-assets/lang/pt.json b/plugins/setting-assets/lang/pt.json index d948670739..047873476c 100644 --- a/plugins/setting-assets/lang/pt.json +++ b/plugins/setting-assets/lang/pt.json @@ -231,6 +231,7 @@ "TwoFactorAuthDisabled": "Autenticação de dois fatores está desativada", "ShowQRCode": "Mostrar código QR", "EnterVerificationCode": "Inserir código de verificação", - "OverrideAttribute": "Sobrescrever atributo" + "OverrideAttribute": "Sobrescrever atributo", + "Required": "Obrigatório" } } diff --git a/plugins/setting-assets/lang/ru.json b/plugins/setting-assets/lang/ru.json index feb92c1cb1..5ff77cea48 100644 --- a/plugins/setting-assets/lang/ru.json +++ b/plugins/setting-assets/lang/ru.json @@ -240,6 +240,7 @@ "TwoFactorAuthDisabled": "Двухфакторная аутентификация отключена", "ShowQRCode": "Показать QR-код", "EnterVerificationCode": "Введите код подтверждения", - "OverrideAttribute": "Переопределить атрибут" + "OverrideAttribute": "Переопределить атрибут", + "Required": "Обязательный" } } diff --git a/plugins/setting-assets/lang/tr.json b/plugins/setting-assets/lang/tr.json index b624a7d537..2dc39e036c 100644 --- a/plugins/setting-assets/lang/tr.json +++ b/plugins/setting-assets/lang/tr.json @@ -240,6 +240,7 @@ "TwoFactorAuthDisabled": "İki faktörlü kimlik doğrulama devre dışı", "ShowQRCode": "QR kodu göster", "EnterVerificationCode": "Doğrulama kodunu gir", - "OverrideAttribute": "Özniteliği geçersiz kıl" + "OverrideAttribute": "Özniteliği geçersiz kıl", + "Required": "Zorunlu" } -} +} \ No newline at end of file diff --git a/plugins/setting-assets/lang/zh.json b/plugins/setting-assets/lang/zh.json index d0fe93d780..5fd59f4c16 100644 --- a/plugins/setting-assets/lang/zh.json +++ b/plugins/setting-assets/lang/zh.json @@ -240,6 +240,7 @@ "TwoFactorAuthDisabled": "双因素认证已禁用", "ShowQRCode": "显示QR码", "EnterVerificationCode": "输入验证码", - "OverrideAttribute": "覆盖属性" + "OverrideAttribute": "覆盖属性", + "Required": "必须" } } diff --git a/plugins/setting-resources/src/components/CreateAttribute.svelte b/plugins/setting-resources/src/components/CreateAttribute.svelte index 5353dc3939..d07b0c100d 100644 --- a/plugins/setting-resources/src/components/CreateAttribute.svelte +++ b/plugins/setting-resources/src/components/CreateAttribute.svelte @@ -57,6 +57,7 @@ let extra: Record = {} let is: AnyComponent | undefined let readonly: boolean = false + let required: boolean = false const client = getClient() const hierarchy = client.getHierarchy() @@ -72,7 +73,8 @@ type, defaultValue, readonly, - automationOnly: readonly + automationOnly: readonly, + required } if (index !== undefined) { data.index = index @@ -196,6 +198,10 @@
diff --git a/plugins/setting-resources/src/components/EditAttribute.svelte b/plugins/setting-resources/src/components/EditAttribute.svelte index 76647f6965..7a113f6b16 100644 --- a/plugins/setting-resources/src/components/EditAttribute.svelte +++ b/plugins/setting-resources/src/components/EditAttribute.svelte @@ -56,6 +56,7 @@ let defaultValue: any | undefined = attribute.defaultValue let icon: Asset | undefined = attribute.icon let automationOnly = attribute.automationOnly ?? false + let required = attribute.required ?? false let extra: Record = {} let is: AnyComponent | undefined @@ -94,6 +95,9 @@ update.readonly = automationOnly update.automationOnly = automationOnly } + if (required !== attribute.required) { + update.required = required + } for (const [k, v] of Object.entries(extra)) { if (attribute[k] === v) continue update[k] = v @@ -308,6 +312,10 @@