ACS-8256: Move "menu buttons" to Insights where it belongs (#9849)

This commit is contained in:
Denys Vuika
2024-07-01 11:01:26 -04:00
committed by GitHub
parent 80ff96a317
commit 5fa3afe3a5
17 changed files with 41 additions and 223 deletions

View File

@@ -7,6 +7,10 @@
"extends": [
"plugin:@nrwl/nx/angular"
],
"parserOptions": {
"project": ["lib/insights/tsconfig.lib.json", "lib/insights/tsconfig.spec.json"],
"createDefaultProgram": true
},
"rules": {
"no-underscore-dangle": ["error", { "allowAfterThis": true }],
"@angular-eslint/no-output-native": "off",
@@ -74,6 +78,10 @@
{
"files": ["*.html"],
"extends": ["plugin:@nrwl/nx/angular-template"],
"parserOptions": {
"project": ["lib/insights/tsconfig.lib.json", "lib/insights/tsconfig.spec.json"],
"createDefaultProgram": true
},
"rules": {
"@angular-eslint/template/no-autofocus": "error",
"@angular-eslint/template/no-positive-tabindex": "error"

View File

@@ -0,0 +1,55 @@
---
Title: Buttons Menu Component
Added: v2.4.0
Status: Active
Last reviewed: 2024-06-21
---
# Buttons Menu Component
Displays buttons on a responsive menu.
![adf-buttons-menu-desktop](images/adf-buttons-menu-desktop.png)
## Basic Usage
Place the buttons for the menu inside this component's HTML tags.
They must use the following structure:
```html
<adf-buttons-action-menu>
<button mat-menu-item (click)="showSettings()">
<mat-icon>settings</mat-icon><span>Settings</span>
</button>
<button mat-menu-item (click)="delete()">
<mat-icon>delete</mat-icon><span>Delete</span>
</button>
</adf-buttons-action-menu>
```
Note that the buttons themselves also have an icon (supplied as a `<mat-icon`)
and a label (supplied as a `<span>`).
They also make use of the Angular material directive `mat-menu-item`.
```html
<button mat-menu-item (click)="event()">
<mat-icon> icon </mat-icon>
<span> label </span>
</button>
```
## Details
This component is fully responsive, and it will display one of two different layouts
depending on the screen size:
**Desktop View**
![adf-buttons-menu-desktop](images/adf-buttons-menu-desktop.png)
**Mobile View**
![adf-buttons-menu-mobile](images/adf-buttons-menu-mobile.png)
The component has a property called `isMenuEmpty` that you can access from code. If this is
set to true then the component will not show an empty menu with no buttons defined.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { AdfDateFnsAdapter, ButtonsMenuModule, DownloadService, ToolbarComponent, ToolbarTitleComponent } from '@alfresco/adf-core';
import { AdfDateFnsAdapter, DownloadService, ToolbarComponent, ToolbarTitleComponent } from '@alfresco/adf-core';
import {
AfterContentChecked,
Component,
@@ -45,6 +45,7 @@ import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { WIDGET_DIRECTIVES } from './widgets';
import { MatButtonModule } from '@angular/material/button';
import { ButtonsMenuComponent } from './buttons-menu/buttons-menu.component';
const FORMAT_DATE_ACTIVITI = 'YYYY-MM-DD';
@@ -113,15 +114,15 @@ export interface ReportFormValues {
MatIconModule,
ReactiveFormsModule,
ToolbarComponent,
ToolbarTitleComponent,
MatFormFieldModule,
MatInputModule,
MatMenuModule,
ToolbarTitleComponent,
...WIDGET_DIRECTIVES,
MatDialogModule,
FormsModule,
MatButtonModule,
ButtonsMenuModule
ButtonsMenuComponent
],
templateUrl: './analytics-report-parameters.component.html',
styleUrls: ['./analytics-report-parameters.component.scss'],

View File

@@ -0,0 +1,20 @@
<div id="adf-buttons-menu" class="adf-buttons-menu" *ngIf="!isMenuEmpty">
<div *ngIf="isMobile()">
<button mat-icon-button [matMenuTriggerFor]="editReportMenu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #editReportMenu="matMenu" class="adf-buttons-menu-mobile">
<ng-content *ngTemplateOutlet="desktop">
</ng-content>
</mat-menu>
</div>
<div *ngIf="!isMobile()" class="adf-buttons-menu-desktop">
<ng-content *ngTemplateOutlet="desktop">
</ng-content>
</div>
</div>
<ng-template #desktop>
<ng-content></ng-content>
</ng-template>

View File

@@ -0,0 +1,30 @@
.adf-buttons-menu {
margin-right: 10px;
& div {
display: flex;
}
&-mobile {
margin-right: 10px;
}
&-desktop {
display: flex;
button {
color: black;
padding: 0;
}
button > span {
display: none;
}
/* stylelint-disable selector-class-pattern */
button > .mat-icon {
color: black;
margin: 0 10px;
}
}
}

View File

@@ -0,0 +1,118 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { Component } from '@angular/core';
import { ButtonsMenuComponent } from '@alfresco/adf-insights';
import { CommonModule } from '@angular/common';
import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';
@Component({
selector: 'adf-custom-container',
standalone: true,
imports: [CommonModule, ButtonsMenuComponent, MatMenuModule, MatIconModule],
template: `
<adf-buttons-action-menu>
<button mat-menu-item (click)="assignValue()"><mat-icon>settings</mat-icon><span>Button</span></button>
</adf-buttons-action-menu>
`
})
export class CustomContainerComponent {
value: number;
assignValue() {
this.value = 1;
}
}
@Component({
selector: 'adf-custom-empty-container',
template: `<adf-buttons-action-menu></adf-buttons-action-menu>`
})
export class CustomEmptyContainerComponent {}
describe('ButtonsMenuComponent', () => {
describe('When Buttons are injected', () => {
let fixture: ComponentFixture<CustomContainerComponent>;
let component: CustomContainerComponent;
let element: HTMLElement;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ButtonsMenuComponent, CustomContainerComponent]
});
fixture = TestBed.createComponent(CustomContainerComponent);
element = fixture.debugElement.nativeElement;
component = fixture.componentInstance;
});
afterEach(() => {
fixture.destroy();
});
it('should render buttons menu when at least one button is declared', async () => {
fixture.detectChanges();
await fixture.whenStable();
const buttonsMenuElement = element.querySelector('#adf-buttons-menu');
expect(buttonsMenuElement).toBeDefined();
});
it('should trigger event when a specific button is clicked', async () => {
expect(component.value).toBeUndefined();
fixture.detectChanges();
await fixture.whenStable();
const button = element.querySelector('button');
button.click();
fixture.detectChanges();
await fixture.whenStable();
expect(component.value).toBe(1);
});
});
describe('When no buttons are injected', () => {
let fixture: ComponentFixture<CustomEmptyContainerComponent>;
let element: HTMLElement;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ButtonsMenuComponent],
declarations: [CustomEmptyContainerComponent]
});
fixture = TestBed.createComponent(CustomEmptyContainerComponent);
element = fixture.nativeElement;
});
afterEach(() => {
fixture.destroy();
TestBed.resetTestingModule();
});
it('should hide buttons menu if buttons input is empty', async () => {
fixture.detectChanges();
await fixture.whenStable();
const buttonsMenuElement = element.querySelector('#adf-buttons-menu');
expect(buttonsMenuElement).toBeNull();
});
});
});

View File

@@ -0,0 +1,44 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, ContentChildren, QueryList, AfterContentInit, ViewEncapsulation } from '@angular/core';
import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { CommonModule } from '@angular/common';
@Component({
selector: 'adf-buttons-action-menu',
standalone: true,
imports: [CommonModule, MatButtonModule, MatMenuModule, MatIconModule],
templateUrl: './buttons-menu.component.html',
styleUrls: ['./buttons-menu.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ButtonsMenuComponent implements AfterContentInit {
@ContentChildren(MatMenuItem) buttons: QueryList<MatMenuItem>;
isMenuEmpty: boolean;
ngAfterContentInit() {
this.isMenuEmpty = this.buttons.length <= 0;
}
isMobile(): boolean {
return !!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}
}

View File

@@ -21,6 +21,7 @@ import { AnalyticsReportListComponent } from './components/analytics-report-list
import { AnalyticsReportParametersComponent } from './components/analytics-report-parameters.component';
import { AnalyticsGeneratorComponent } from './components/analytics-generator.component';
import { AnalyticsReportHeatMapComponent } from './components/analytics-report-heat-map.component';
import { ButtonsMenuComponent } from './components/buttons-menu/buttons-menu.component';
export * from './components/analytics.component';
export * from './components/analytics-report-heat-map.component';
@@ -28,12 +29,14 @@ export * from './components/analytics-generator.component';
export * from './components/analytics-report-list.component';
export * from './components/analytics-report-parameters.component';
export * from './components/analytics.component';
export * from './components/buttons-menu/buttons-menu.component';
export * from './services/analytics.service';
export * from './components/widgets';
export const ANALYTICS_PROCESS_DIRECTIVES = [
...WIDGET_DIRECTIVES,
ButtonsMenuComponent,
AnalyticsComponent,
AnalyticsReportListComponent,
AnalyticsReportParametersComponent,