|
200 | 200 | </label> |
201 | 201 | </div> |
202 | 202 | <div v-if="state.viewMode === 'system-admin'" class="policy-workbench__crud-create"> |
203 | | - <label class="policy-workbench__create-inline"> |
204 | | - <span>{{ t('libresign', 'Create in') }}</span> |
205 | | - <select class="policy-workbench__create-select" :value="newRuleScope" @change="setNewRuleScope(($event.target as HTMLSelectElement).value as 'system' | 'group' | 'user', true)"> |
206 | | - <option value="system">{{ t('libresign', 'Instance') }}</option> |
207 | | - <option value="group">{{ t('libresign', 'Group') }}</option> |
208 | | - <option value="user">{{ t('libresign', 'User') }}</option> |
209 | | - </select> |
210 | | - </label> |
211 | | - <NcButton variant="primary" size="small" :disabled="isCreateRuleDisabled" :title="createRuleDisabledReason || undefined" @click="startCreateRule()"> |
| 203 | + <NcButton variant="primary" size="small" :disabled="!hasCreatableScope" :title="createRuleDisabledReason || undefined" @click="requestCreateRule()"> |
212 | 204 | {{ t('libresign', 'Create rule') }} |
213 | 205 | </NcButton> |
214 | 206 | <p v-if="createRuleDisabledReason" class="policy-workbench__table-note policy-workbench__table-note--align-right"> |
|
341 | 333 | </div> |
342 | 334 | </NcDialog> |
343 | 335 |
|
| 336 | + <NcDialog |
| 337 | + v-if="showCreateScopeDialog" |
| 338 | + :name="t('libresign', 'What do you want to create?')" |
| 339 | + size="normal" |
| 340 | + :can-close="true" |
| 341 | + @closing="cancelCreateScopeDialog"> |
| 342 | + <div class="policy-workbench__create-scope-dialog"> |
| 343 | + <p>{{ t('libresign', 'Choose the level where the new rule should be created.') }}</p> |
| 344 | + <div class="policy-workbench__create-scope-actions"> |
| 345 | + <NcButton variant="secondary" :disabled="scopeCreateDisabledReason('system').length > 0" @click="startCreateRuleForScope('system')"> |
| 346 | + {{ t('libresign', 'Instance') }} |
| 347 | + </NcButton> |
| 348 | + <NcButton variant="secondary" :disabled="scopeCreateDisabledReason('group').length > 0" @click="startCreateRuleForScope('group')"> |
| 349 | + {{ t('libresign', 'Group') }} |
| 350 | + </NcButton> |
| 351 | + <NcButton variant="secondary" :disabled="scopeCreateDisabledReason('user').length > 0" @click="startCreateRuleForScope('user')"> |
| 352 | + {{ t('libresign', 'User') }} |
| 353 | + </NcButton> |
| 354 | + </div> |
| 355 | + <ul class="policy-workbench__create-scope-notes"> |
| 356 | + <li v-if="scopeCreateDisabledReason('group')">{{ t('libresign', 'Group') }}: {{ scopeCreateDisabledReason('group') }}</li> |
| 357 | + <li v-if="scopeCreateDisabledReason('user')">{{ t('libresign', 'User') }}: {{ scopeCreateDisabledReason('user') }}</li> |
| 358 | + </ul> |
| 359 | + </div> |
| 360 | + </NcDialog> |
| 361 | + |
344 | 362 | <NcDialog |
345 | 363 | v-if="pendingDiscardAction" |
346 | 364 | :name="t('libresign', 'Discard unsaved changes?')" |
@@ -399,14 +417,14 @@ const saveStatus = ref<'idle' | 'saving' | 'saved'>('idle') |
399 | 417 | const saveFeedbackTimeout = ref<number | null>(null) |
400 | 418 | const pendingRemoval = ref<{ ruleId: string, scope: 'system' | 'group' | 'user', targetLabel: string, help: string } | null>(null) |
401 | 419 | const pendingDiscardAction = ref<'cancel-editor' | 'close-setting' | null>(null) |
| 420 | +const showCreateScopeDialog = ref(false) |
402 | 421 | const isRemovingRule = ref(false) |
403 | 422 | const removalFeedback = ref<string | null>(null) |
404 | 423 | const removalFeedbackTimeout = ref<number | null>(null) |
405 | 424 | const lastPress = ref<{ surface: 'cards' | 'list', key: string, x: number, y: number } | null>(null) |
406 | 425 | const recentSelectionGesture = ref<{ surface: 'cards' | 'list', key: string, at: number } | null>(null) |
407 | 426 | const crudSearch = ref('') |
408 | 427 | const crudScopeFilter = ref<'all' | 'system' | 'group' | 'user'>('all') |
409 | | -const newRuleScope = ref<'system' | 'group' | 'user'>('group') |
410 | 428 | const crudPage = ref(1) |
411 | 429 | const CRUD_PAGE_SIZE = 20 |
412 | 430 |
|
@@ -549,19 +567,30 @@ const editorHelp = computed(() => { |
549 | 567 | return t('libresign', 'A user override is the most specific layer and takes priority over inherited defaults.') |
550 | 568 | }) |
551 | 569 |
|
552 | | -const createRuleDisabledReason = computed(() => { |
553 | | - if (newRuleScope.value === 'group') { |
| 570 | +function scopeCreateDisabledReason(scope: 'system' | 'group' | 'user') { |
| 571 | + if (scope === 'group') { |
554 | 572 | return state.createGroupOverrideDisabledReason || '' |
555 | 573 | } |
556 | 574 |
|
557 | | - if (newRuleScope.value === 'user') { |
| 575 | + if (scope === 'user') { |
558 | 576 | return state.createUserOverrideDisabledReason || '' |
559 | 577 | } |
560 | 578 |
|
561 | 579 | return '' |
| 580 | +} |
| 581 | +
|
| 582 | +const hasCreatableScope = computed(() => { |
| 583 | + return ['system', 'group', 'user'] |
| 584 | + .some((scope) => scopeCreateDisabledReason(scope as 'system' | 'group' | 'user').length === 0) |
562 | 585 | }) |
563 | 586 |
|
564 | | -const isCreateRuleDisabled = computed(() => createRuleDisabledReason.value.length > 0) |
| 587 | +const createRuleDisabledReason = computed(() => { |
| 588 | + if (!hasCreatableScope.value) { |
| 589 | + return t('libresign', 'A higher-level rule is blocking new exceptions in all scopes.') |
| 590 | + } |
| 591 | +
|
| 592 | + return '' |
| 593 | +}) |
565 | 594 |
|
566 | 595 | const pendingRemovalMessage = computed(() => { |
567 | 596 | if (!pendingRemoval.value) { |
@@ -651,20 +680,25 @@ function setCrudScopeFilter(value: 'all' | 'system' | 'group' | 'user', selected |
651 | 680 | crudPage.value = 1 |
652 | 681 | } |
653 | 682 |
|
654 | | -function setNewRuleScope(value: 'system' | 'group' | 'user', selected: boolean) { |
655 | | - if (!selected) { |
| 683 | +function requestCreateRule() { |
| 684 | + if (!hasCreatableScope.value) { |
656 | 685 | return |
657 | 686 | } |
658 | 687 |
|
659 | | - newRuleScope.value = value |
| 688 | + showCreateScopeDialog.value = true |
| 689 | +} |
| 690 | +
|
| 691 | +function cancelCreateScopeDialog() { |
| 692 | + showCreateScopeDialog.value = false |
660 | 693 | } |
661 | 694 |
|
662 | | -function startCreateRule() { |
663 | | - if (isCreateRuleDisabled.value) { |
| 695 | +function startCreateRuleForScope(scope: 'system' | 'group' | 'user') { |
| 696 | + if (scopeCreateDisabledReason(scope).length > 0) { |
664 | 697 | return |
665 | 698 | } |
666 | 699 |
|
667 | | - state.startEditor({ scope: newRuleScope.value }) |
| 700 | + showCreateScopeDialog.value = false |
| 701 | + state.startEditor({ scope }) |
668 | 702 | } |
669 | 703 |
|
670 | 704 | function onSettingsFilterChange(value: string | number) { |
@@ -932,6 +966,7 @@ onBeforeUnmount(() => { |
932 | 966 | } |
933 | 967 |
|
934 | 968 | pendingDiscardAction.value = null |
| 969 | + showCreateScopeDialog.value = false |
935 | 970 | }) |
936 | 971 | </script> |
937 | 972 |
|
@@ -1900,22 +1935,31 @@ onBeforeUnmount(() => { |
1900 | 1935 | } |
1901 | 1936 | } |
1902 | 1937 |
|
1903 | | - &__create-inline { |
1904 | | - display: inline-flex; |
1905 | | - align-items: center; |
1906 | | - gap: 0.45rem; |
| 1938 | + &__create-scope-dialog { |
| 1939 | + display: flex; |
| 1940 | + flex-direction: column; |
| 1941 | + gap: 0.75rem; |
| 1942 | +
|
| 1943 | + p { |
| 1944 | + margin: 0; |
| 1945 | + } |
| 1946 | + } |
| 1947 | +
|
| 1948 | + &__create-scope-actions { |
| 1949 | + display: flex; |
| 1950 | + gap: 0.5rem; |
| 1951 | + flex-wrap: wrap; |
| 1952 | + } |
| 1953 | +
|
| 1954 | + &__create-scope-notes { |
| 1955 | + margin: 0; |
| 1956 | + padding-inline-start: 1.1rem; |
1907 | 1957 | font-size: 0.84rem; |
1908 | 1958 | color: var(--color-text-maxcontrast); |
1909 | | - } |
1910 | 1959 |
|
1911 | | - &__create-select { |
1912 | | - height: 2rem; |
1913 | | - min-width: 8.5rem; |
1914 | | - padding: 0 0.5rem; |
1915 | | - border: 1px solid color-mix(in srgb, var(--color-border-maxcontrast) 68%, transparent); |
1916 | | - border-radius: 8px; |
1917 | | - background: var(--color-main-background); |
1918 | | - color: var(--color-main-text); |
| 1960 | + li { |
| 1961 | + margin: 0; |
| 1962 | + } |
1919 | 1963 | } |
1920 | 1964 |
|
1921 | 1965 | &__table-empty-state { |
|
0 commit comments