[ACS-10286] Add label and aria expanded to the rule set header (#4834)

* [ACS-10286] Add proper role and aria attributes to rule section header

* [ACS-10286] Add unit tests and main rule set coverage

* [ACS-10286] Rework component to use material expansion panel

* [ACS-10286] CR changes

* [ACS-10286] excluded XAT-907

---------

Co-authored-by: Adam Świderski <adam.tomasz.swiderski@gmail.com>
This commit is contained in:
MichalKinas
2025-10-08 13:18:16 +02:00
committed by GitHub
co-authored by Adam Świderski
parent 4d88927db5
commit 199d31f1cd
6 changed files with 111 additions and 108 deletions
@@ -1,3 +1,4 @@
{ {
"XAT-897": "https://hyland.atlassian.net/browse/ACS-5503" "XAT-897": "https://hyland.atlassian.net/browse/ACS-5503",
"XAT-907": "https://hyland.atlassian.net/browse/ACS-10486"
} }
@@ -126,7 +126,8 @@
"LOADING_RULES": "Loading rules", "LOADING_RULES": "Loading rules",
"TOGGLE_RULE_STATE": "Toggle {{ name }} rule", "TOGGLE_RULE_STATE": "Toggle {{ name }} rule",
"INHERITED_RULES_WILL_BE_RUN_FIRST": "Inherited rules will be run first", "INHERITED_RULES_WILL_BE_RUN_FIRST": "Inherited rules will be run first",
"ALL_LINKED_RULES_ARE_DISABLED": "All rules linked from this rule set are disabled" "ALL_LINKED_RULES_ARE_DISABLED": "All rules linked from this rule set are disabled",
"EDIT_LINK_LABEL": "Link rules from another folder"
}, },
"LINK_RULES_DIALOG": { "LINK_RULES_DIALOG": {
"TITLE": "Select a folder to link rules from", "TITLE": "Select a folder to link rules from",
@@ -172,7 +172,7 @@ describe('ManageRulesSmartComponent', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
expect(folderRuleSetsService.loadRuleSets).toHaveBeenCalledOnceWith(component.nodeId); expect(folderRuleSetsService.loadRuleSets).toHaveBeenCalledOnceWith(component.nodeId);
const ruleGroupingSections = unitTestingUtils.getAllByCSS(`[data-automation-id="rule-list-item"]`); const ruleGroupingSections = unitTestingUtils.getAllByCSS('.aca-rule-list__item');
const deleteRuleBtn = unitTestingUtils.getByCSS('#delete-rule-btn'); const deleteRuleBtn = unitTestingUtils.getByCSS('#delete-rule-btn');
@@ -1,87 +1,83 @@
<div <mat-accordion multi>
*ngIf="inheritedRuleSetGroupingItems.length > 0" @if (inheritedRuleSetGroupingItems.length > 0) {
class="aca-rule-list__item" <mat-expansion-panel [expanded]="true" class="aca-rule-list__item">
data-automation-id="rule-list-item" <mat-expansion-panel-header class="aca-rule-list__item__header">
[ngClass]="{ 'aca-expanded': inheritedRuleSetsExpanded }"> <mat-panel-title>
<span class="aca-rule-list__item__header__title">
{{ 'ACA_FOLDER_RULES.RULE_LIST.INHERITED_RULES' | translate }}
<mat-icon
class="aca-rule-list__item__header__title__icon"
[matTooltip]="'ACA_FOLDER_RULES.RULE_LIST.INHERITED_RULES_WILL_BE_RUN_FIRST' | translate">
info
</mat-icon>
</span>
</mat-panel-title>
</mat-expansion-panel-header>
<aca-rule-list-grouping
[items]="inheritedRuleSetGroupingItems"
[selectedRule]="selectedRule"
(selectRule)="onSelectRule($event)"
(ruleEnabledChanged)="onRuleEnabledChanged($event)"
(loadMoreRules)="onLoadMoreRules($event)"
(loadMoreRuleSets)="onLoadMoreRuleSets()" />
</mat-expansion-panel>
}
@if (mainRuleSetGroupingItems.length > 0 || isMainRuleSetLinked) {
<mat-expansion-panel [expanded]="true" class="aca-rule-list__item">
<mat-expansion-panel-header class="aca-rule-list__item__header">
<mat-panel-title>
<span class="aca-rule-list__item__header__title" data-automation-id="main-rule-set-title">
@if (isMainRuleSetOwned) {
{{ 'ACA_FOLDER_RULES.RULE_LIST.OWNED_RULES' | translate }}
} @else {
{{ 'ACA_FOLDER_RULES.RULE_LIST.LINKED_RULES' | translate }}
}
</span>
<div @if (!isMainRuleSetOwned) {
tabindex="0" <mat-icon
class="aca-rule-list__item__header" class="aca-rule-list__item__header__icon"
matRipple matRippleColor="hsla(0,0%,0%,0.05)" tabindex="0"
(click)="inheritedRuleSetsExpanded = !inheritedRuleSetsExpanded" aria-hidden="false"
(keyup.enter)="inheritedRuleSetsExpanded = !inheritedRuleSetsExpanded"> [attr.aria-label]="'ACA_FOLDER_RULES.RULE_LIST.EDIT_LINK_LABEL' | translate"
[attr.title]="'ACA_FOLDER_RULES.RULE_LIST.EDIT_LINK_LABEL' | translate"
(keydown.enter)="onRuleSetEditLinkClicked($event)"
(keydown.enter)="onRuleSetEditLinkClicked($event)"
(click)="onRuleSetEditLinkClicked($event)">
edit
</mat-icon>
<mat-icon
class="aca-rule-list__item__header__icon"
tabindex="0"
aria-hidden="false"
[attr.aria-label]="'ACA_FOLDER_RULES.CONFIRMATION_DIALOG.DELETE_RULE_SET_LINK.TITLE' | translate"
[attr.title]="'ACA_FOLDER_RULES.CONFIRMATION_DIALOG.DELETE_RULE_SET_LINK.TITLE' | translate"
(keydown.enter)="onRuleSetUnlinkClicked($event)"
(click)="onRuleSetUnlinkClicked($event)">
link_off
</mat-icon>
}
</mat-panel-title>
<span class="aca-rule-list__item__header__title"> </mat-expansion-panel-header>
{{ 'ACA_FOLDER_RULES.RULE_LIST.INHERITED_RULES' | translate }} @if (mainRuleSetGroupingItems.length > 0) {
<mat-icon class="aca-rule-list__item__header__title__icon" [matTooltip]="'ACA_FOLDER_RULES.RULE_LIST.INHERITED_RULES_WILL_BE_RUN_FIRST' | translate"> <aca-rule-list-grouping
info [items]="mainRuleSetGroupingItems"
</mat-icon> [selectedRule]="selectedRule"
</span> [showEnabledToggles]="isMainRuleSetOwned"
<mat-icon class="aca-rule-list__item__header__icon"> (selectRule)="onSelectRule($event)"
{{ inheritedRuleSetsExpanded ? 'expand_more' : 'chevron_right' }} (ruleEnabledChanged)="onRuleEnabledChanged($event)"
</mat-icon> (loadMoreRules)="onLoadMoreRules($event)" />
</div> } @else {
<aca-rule-list-grouping
*ngIf="inheritedRuleSetsExpanded"
[items]="inheritedRuleSetGroupingItems"
[selectedRule]="selectedRule"
(selectRule)="onSelectRule($event)"
(ruleEnabledChanged)="onRuleEnabledChanged($event)"
(loadMoreRules)="onLoadMoreRules($event)"
(loadMoreRuleSets)="onLoadMoreRuleSets()" />
</div>
<div
*ngIf="mainRuleSetGroupingItems.length > 0 || isMainRuleSetLinked"
class="aca-rule-list__item"
data-automation-id="rule-list-item"
[ngClass]="{ 'aca-expanded': mainRuleSetExpanded }">
<div
tabindex="0"
class="aca-rule-list__item__header"
matRipple matRippleColor="hsla(0,0%,0%,0.05)"
(click)="mainRuleSetExpanded = !mainRuleSetExpanded"
(keyup.enter)="mainRuleSetExpanded = !mainRuleSetExpanded">
<span class="aca-rule-list__item__header__title" data-automation-id="main-rule-set-title">
<ng-container *ngIf="isMainRuleSetOwned; else linkedRuleSet">
{{ 'ACA_FOLDER_RULES.RULE_LIST.OWNED_RULES' | translate }}
</ng-container>
<ng-template #linkedRuleSet>
{{ 'ACA_FOLDER_RULES.RULE_LIST.LINKED_RULES' | translate }}
</ng-template>
</span>
<ng-container *ngIf="!isMainRuleSetOwned">
<mat-icon class="aca-rule-list__item__header__icon" (click)="onRuleSetEditLinkClicked($event)">edit</mat-icon>
<mat-icon class="aca-rule-list__item__header__icon" (click)="onRuleSetUnlinkClicked($event)">link_off</mat-icon>
</ng-container>
<mat-icon class="aca-rule-list__item__header__icon">
{{ mainRuleSetExpanded ? 'expand_more' : 'chevron_right' }}
</mat-icon>
</div>
<ng-container *ngIf="mainRuleSetExpanded">
<aca-rule-list-grouping
*ngIf="mainRuleSetGroupingItems.length > 0; else emptyLinkedRuleSet"
[items]="mainRuleSetGroupingItems"
[selectedRule]="selectedRule"
[showEnabledToggles]="isMainRuleSetOwned"
(selectRule)="onSelectRule($event)"
(ruleEnabledChanged)="onRuleEnabledChanged($event)"
(loadMoreRules)="onLoadMoreRules($event)" />
<ng-template #emptyLinkedRuleSet>
<div class="aca-rule-list__item__all-linked-rules-are-disabled"> <div class="aca-rule-list__item__all-linked-rules-are-disabled">
{{ 'ACA_FOLDER_RULES.RULE_LIST.ALL_LINKED_RULES_ARE_DISABLED' | translate }} {{ 'ACA_FOLDER_RULES.RULE_LIST.ALL_LINKED_RULES_ARE_DISABLED' | translate }}
<button *ngIf="mainRuleSet?.owningFolder?.id" mat-stroked-button [routerLink]="['/nodes', mainRuleSet.owningFolder.id, 'rules']"> @if (mainRuleSet?.owningFolder?.id) {
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.SEE_IN_FOLDER' | translate }} <button mat-stroked-button [routerLink]="['/nodes', mainRuleSet.owningFolder.id, 'rules']">
</button> {{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.SEE_IN_FOLDER' | translate }}
</button>
}
</div> </div>
</ng-template> }
</ng-container> </mat-expansion-panel>
}
</div> </mat-accordion>
@@ -1,26 +1,33 @@
/* stylelint-disable selector-class-pattern */
@use '@angular/material' as mat;
.aca-rule-list { .aca-rule-list {
display: flex; @include mat.expansion-overrides(
flex-direction: column; (
overflow-y: auto; container-background-color: var(--theme-background-color),
gap: 8px; header-text-color: var(--theme-text-color),
container-shape: 12px
)
);
&__item { &__item {
display: flex;
flex-direction: column;
border: 1px solid var(--theme-border-color); border: 1px solid var(--theme-border-color);
border-radius: 12px; border-radius: 12px;
overflow: hidden; /* stylelint-disable-next-line declaration-no-important */
box-shadow: none !important;
.mat-expansion-panel-body {
padding: 0;
}
&__header { &__header {
display: flex;
flex-direction: row;
gap: 4px;
align-items: stretch;
cursor: pointer;
color: var(--theme-text-color);
user-select: none;
font-size: 0.9em; font-size: 0.9em;
padding: 0.5em 1em; padding: 0 16px;
&.mat-expanded {
border-bottom: 1px solid var(--theme-border-color);
border-radius: 0;
}
& > * { & > * {
display: flex; display: flex;
@@ -41,12 +48,6 @@
} }
} }
&.aca-expanded {
.aca-rule-list__item__header {
border-bottom: 1px solid var(--theme-border-color);
}
}
&__all-linked-rules-are-disabled { &__all-linked-rules-are-disabled {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -31,6 +31,7 @@ import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatRippleModule } from '@angular/material/core'; import { MatRippleModule } from '@angular/material/core';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatAccordion, MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle } from '@angular/material/expansion';
import { MatTooltipModule } from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip';
import { RuleListGroupingUiComponent } from '../rule-list-grouping/rule-list-grouping.ui-component'; import { RuleListGroupingUiComponent } from '../rule-list-grouping/rule-list-grouping.ui-component';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
@@ -47,7 +48,11 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
MatTooltipModule, MatTooltipModule,
RuleListGroupingUiComponent, RuleListGroupingUiComponent,
RouterModule, RouterModule,
MatButtonModule MatButtonModule,
MatAccordion,
MatExpansionPanel,
MatExpansionPanelHeader,
MatExpansionPanelTitle
], ],
selector: 'aca-rule-list', selector: 'aca-rule-list',
templateUrl: './rule-list.ui-component.html', templateUrl: './rule-list.ui-component.html',
@@ -83,7 +88,6 @@ export class RuleListUiComponent implements OnInit {
ruleSetUnlinkClicked = new EventEmitter<RuleSet>(); ruleSetUnlinkClicked = new EventEmitter<RuleSet>();
mainRuleSet: RuleSet = null; mainRuleSet: RuleSet = null;
inheritedRuleSetsExpanded = true;
mainRuleSetExpanded = true; mainRuleSetExpanded = true;
mainRuleSetGroupingItems: RuleGroupingItem[] = []; mainRuleSetGroupingItems: RuleGroupingItem[] = [];
inheritedRuleSetGroupingItems: RuleGroupingItem[] = []; inheritedRuleSetGroupingItems: RuleGroupingItem[] = [];