mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-09-17 14:21:29 +00:00
Merge remote-tracking branch 'origin/dev-valbano-ng15-start' into AAE-23572-recreate-js-api-lib-into-a-proper-nx-workspace-lib
This commit is contained in:
@@ -65,8 +65,7 @@
|
||||
"demo-shell/src/styles.scss",
|
||||
"demo-shell/src/custom-style-dev.scss",
|
||||
"node_modules/cropperjs/dist/cropper.min.css",
|
||||
"node_modules/pdfjs-dist/web/pdf_viewer.css",
|
||||
|
||||
"node_modules/pdfjs-dist/web/pdf_viewer.css"
|
||||
],
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": ["lib", "lib/core/src/lib"]
|
||||
|
@@ -1,20 +0,0 @@
|
||||
<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>
|
@@ -1,31 +0,0 @@
|
||||
@import 'styles/mat-selectors';
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
button > #{$material-icons} {
|
||||
color: black;
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,117 +0,0 @@
|
||||
/*!
|
||||
* @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 { MaterialModule } from '../material.module';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-custom-container',
|
||||
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: [TranslateModule.forRoot()],
|
||||
declarations: [CustomContainerComponent],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
});
|
||||
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: [TranslateModule.forRoot(), MaterialModule],
|
||||
declarations: [CustomEmptyContainerComponent],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
});
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
@@ -1,124 +0,0 @@
|
||||
/*!
|
||||
* @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 { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
|
||||
import { ButtonsMenuComponent } from './buttons-menu.component';
|
||||
import { ButtonsMenuModule } from './buttons-menu.module';
|
||||
import { importProvidersFrom } from '@angular/core';
|
||||
import { CoreStoryModule } from '../../..';
|
||||
|
||||
export default {
|
||||
component: ButtonsMenuComponent,
|
||||
title: 'Core/Buttons Menu/Buttons Menu',
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [ButtonsMenuModule]
|
||||
}),
|
||||
applicationConfig({
|
||||
providers: [importProvidersFrom(CoreStoryModule)]
|
||||
})
|
||||
],
|
||||
argTypes: {
|
||||
mobile: {
|
||||
type: { name: 'boolean' },
|
||||
name: 'isMobile',
|
||||
description: 'Determines whether it is displayed on a mobile device',
|
||||
control: {
|
||||
disable: false
|
||||
},
|
||||
table: {
|
||||
category: 'Component methods',
|
||||
type: {
|
||||
summary: '() => boolean'
|
||||
}
|
||||
}
|
||||
},
|
||||
isMenuEmpty: {
|
||||
description: 'Determines whether it has anything to display',
|
||||
table: {
|
||||
category: 'Component properties',
|
||||
type: {
|
||||
summary: 'boolean'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
args: {
|
||||
mobile: true
|
||||
}
|
||||
} as Meta<ButtonsMenuComponent>;
|
||||
|
||||
export const SixButtons: StoryFn = (args) => ({
|
||||
props: {
|
||||
...args,
|
||||
isMenuEmpty: false,
|
||||
isMobile() {
|
||||
return args.mobile;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<adf-buttons-action-menu>
|
||||
<button mat-menu-item>
|
||||
<mat-icon>settings</mat-icon><span> Settings </span>
|
||||
</button>
|
||||
<button mat-menu-item>
|
||||
<mat-icon>home</mat-icon><span> Home </span>
|
||||
</button>
|
||||
<button mat-menu-item>
|
||||
<mat-icon>search</mat-icon><span> Search </span>
|
||||
</button>
|
||||
<button mat-menu-item>
|
||||
<mat-icon>done</mat-icon><span> Done </span>
|
||||
</button>
|
||||
<button mat-menu-item>
|
||||
<mat-icon>delete</mat-icon><span> Delete </span>
|
||||
</button>
|
||||
<button mat-menu-item>
|
||||
<mat-icon>block</mat-icon><span> Block </span>
|
||||
</button>
|
||||
</adf-buttons-action-menu>
|
||||
`
|
||||
});
|
||||
|
||||
export const OneButton: StoryFn = (args) => ({
|
||||
props: {
|
||||
...args,
|
||||
isMenuEmpty: false,
|
||||
isMobile() {
|
||||
return args.mobile;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<adf-buttons-action-menu>
|
||||
<button mat-menu-item>
|
||||
<mat-icon>settings</mat-icon><span> Settings </span>
|
||||
</button>
|
||||
</adf-buttons-action-menu>
|
||||
`
|
||||
});
|
||||
|
||||
export const NoButtons: StoryFn = (args) => ({
|
||||
props: {
|
||||
...args,
|
||||
isMenuEmpty: true,
|
||||
isMobile() {
|
||||
return args.mobile;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<adf-buttons-action-menu></adf-buttons-action-menu>`
|
||||
});
|
@@ -1,41 +0,0 @@
|
||||
/*!
|
||||
* @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 } from '@angular/material/menu';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-buttons-action-menu',
|
||||
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);
|
||||
}
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
/*!
|
||||
* @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 { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { ButtonsMenuComponent } from './buttons-menu.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
TranslateModule
|
||||
],
|
||||
declarations: [ButtonsMenuComponent],
|
||||
exports: [ButtonsMenuComponent, MatIconModule, MatMenuModule, MatButtonModule]
|
||||
})
|
||||
export class ButtonsMenuModule {}
|
@@ -1,18 +0,0 @@
|
||||
/*!
|
||||
* @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.
|
||||
*/
|
||||
|
||||
export * from './public-api';
|
@@ -1,19 +0,0 @@
|
||||
/*!
|
||||
* @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.
|
||||
*/
|
||||
|
||||
export * from './buttons-menu.component';
|
||||
export * from './buttons-menu.module';
|
@@ -30,6 +30,7 @@
|
||||
padding: 6px 0 8px 12px;
|
||||
margin-top: 0;
|
||||
border-radius: 6px;
|
||||
width: 90%;
|
||||
|
||||
#{$mat-select-value} {
|
||||
color: var(--adf-metadata-action-button-clear-color);
|
||||
|
@@ -35,7 +35,6 @@ import { FormBaseModule } from './form/form-base.module';
|
||||
import { SidenavLayoutModule } from './layout/layout.module';
|
||||
import { CommentsModule } from './comments/comments.module';
|
||||
import { CommentListModule } from './comments/comment-list/comment-list.module';
|
||||
import { ButtonsMenuModule } from './buttons-menu/buttons-menu.module';
|
||||
import { TemplateModule } from './templates/template.module';
|
||||
import { ClipboardModule } from './clipboard/clipboard.module';
|
||||
import { NotificationHistoryModule } from './notifications/notification-history.module';
|
||||
@@ -95,7 +94,6 @@ import { DynamicChipListModule } from './dynamic-chip-list';
|
||||
LanguageMenuModule,
|
||||
InfoDrawerModule,
|
||||
DataTableModule,
|
||||
ButtonsMenuModule,
|
||||
TemplateModule,
|
||||
IconModule,
|
||||
SortingPickerModule,
|
||||
@@ -135,7 +133,6 @@ import { DynamicChipListModule } from './dynamic-chip-list';
|
||||
InfoDrawerModule,
|
||||
DataTableModule,
|
||||
TranslateModule,
|
||||
ButtonsMenuModule,
|
||||
TemplateModule,
|
||||
SortingPickerModule,
|
||||
IconModule,
|
||||
|
@@ -185,7 +185,8 @@
|
||||
<label *ngIf="multiselect" [for]="'select-file-' + idx" class="adf-datatable-cell adf-datatable-checkbox-cell adf-datatable-checkbox-single">
|
||||
<mat-checkbox
|
||||
[id]="'select-file-' + idx"
|
||||
[class.adf-datatable-checkbox-selected]="row.isSelected"
|
||||
[class.adf-datatable-checkbox-selected]="row.isSelected"
|
||||
[class.adf-datatable-hover-only]="displayCheckboxesOnHover"
|
||||
[checked]="row.isSelected"
|
||||
[attr.aria-checked]="row.isSelected"
|
||||
role="checkbox"
|
||||
|
@@ -160,17 +160,15 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
.adf-datatable-checkbox-cell {
|
||||
&.adf-datatable-checkbox-single {
|
||||
visibility: visible;
|
||||
}
|
||||
.adf-datatable-hover-only {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.adf-datatable-checkbox-single {
|
||||
.adf-datatable-hover-only {
|
||||
visibility: hidden;
|
||||
|
||||
&:has(.adf-datatable-checkbox-selected) {
|
||||
&.adf-datatable-checkbox-selected {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
@@ -453,6 +451,8 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* stylelint-disable media-feature-range-notation */
|
||||
|
||||
/* mobile phone */
|
||||
@media all and (max-width: 768px) {
|
||||
.adf-desktop-only.adf-ellipsis-cell {
|
||||
@@ -578,6 +578,7 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable selector-class-pattern */
|
||||
.cdk-drag-preview {
|
||||
&.adf-datatable-cell-header {
|
||||
border-radius: 6px;
|
||||
@@ -641,7 +642,7 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
||||
align-items: center;
|
||||
height: inherit;
|
||||
|
||||
.adf-datatable-body[role="rowgroup"] {
|
||||
.adf-datatable-body[role='rowgroup'] {
|
||||
.adf-datatable-row {
|
||||
height: 100%;
|
||||
background-color: var(--adf-theme-background-card-color);
|
||||
|
@@ -1329,6 +1329,36 @@ describe('DataTable', () => {
|
||||
expect(rows[1].getValue('icon')).toBe('directions_car');
|
||||
expect(rows[2].getValue('icon')).toBe('local_shipping');
|
||||
});
|
||||
|
||||
describe('displayCheckboxesOnHover', () => {
|
||||
const getCheckboxes = () =>
|
||||
fixture.debugElement.queryAll(By.css('.adf-datatable-checkbox-single .adf-checkbox-sr-only')).map((row) => row.nativeElement);
|
||||
|
||||
beforeEach(() => {
|
||||
dataTable.data = new ObjectDataTableAdapter([{ name: '1' }, { name: '2' }], [new ObjectDataColumn({ key: 'name' })]);
|
||||
dataTable.multiselect = true;
|
||||
});
|
||||
|
||||
it('should always display checkboxes when displayCheckboxesOnHover is set to false', () => {
|
||||
dataTable.displayCheckboxesOnHover = false;
|
||||
fixture.detectChanges();
|
||||
|
||||
const checkboxes = getCheckboxes();
|
||||
checkboxes.forEach((checkbox) => {
|
||||
expect(checkbox.classList).not.toContain('adf-datatable-hover-only');
|
||||
});
|
||||
});
|
||||
|
||||
it('should display checkboxes on hover when displayCheckboxesOnHover is set to true', () => {
|
||||
dataTable.displayCheckboxesOnHover = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
const checkboxes = getCheckboxes();
|
||||
checkboxes.forEach((checkbox) => {
|
||||
expect(checkbox.classList).toContain('adf-datatable-hover-only');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Accesibility', () => {
|
||||
|
@@ -238,6 +238,12 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
@Input()
|
||||
blurOnResize = true;
|
||||
|
||||
/**
|
||||
* Flag that indicates if selection checkboxes inside row should be displayed on hover only.
|
||||
*/
|
||||
@Input()
|
||||
displayCheckboxesOnHover = false;
|
||||
|
||||
headerFilterTemplate: TemplateRef<any>;
|
||||
noContentTemplate: TemplateRef<any>;
|
||||
noPermissionTemplate: TemplateRef<any>;
|
||||
|
@@ -206,7 +206,7 @@ describe('SearchTextInputComponent', () => {
|
||||
fixture.detectChanges();
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.params).toEqual({ transform: 'translateX(82%)' });
|
||||
expect(component.subscriptAnimationState.params).toEqual({ transform: 'translateX(95%)' });
|
||||
discardPeriodicTasks();
|
||||
}));
|
||||
|
||||
@@ -237,7 +237,7 @@ describe('SearchTextInputComponent', () => {
|
||||
fixture.detectChanges();
|
||||
tick(100);
|
||||
|
||||
expect(component.subscriptAnimationState.params).toEqual({ transform: 'translateX(-82%)' });
|
||||
expect(component.subscriptAnimationState.params).toEqual({ transform: 'translateX(-95%)' });
|
||||
discardPeriodicTasks();
|
||||
}));
|
||||
|
||||
|
@@ -33,14 +33,14 @@
|
||||
<mat-icon>zoom_in</mat-icon>
|
||||
</button>
|
||||
|
||||
<button *ngIf="!readOnly" id="viewer-rotate-button"
|
||||
<button *ngIf="!readOnly && allowedEditActions.rotate" id="viewer-rotate-button"
|
||||
title="{{ 'ADF_VIEWER.ARIA.ROTATE' | translate }}"
|
||||
attr.aria-label="{{ 'ADF_VIEWER.ARIA.ROTATE' | translate }}"
|
||||
mat-icon-button
|
||||
(click)="rotateImage()">
|
||||
<mat-icon>rotate_left</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="!readOnly" id="viewer-crop-button"
|
||||
<button *ngIf="!readOnly && allowedEditActions.crop" id="viewer-crop-button"
|
||||
title="{{ 'ADF_VIEWER.ARIA.CROP' | translate }}"
|
||||
attr.aria-label="{{ 'ADF_VIEWER.ARIA.CROP' | translate }}"
|
||||
mat-icon-button
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
</adf-toolbar>
|
||||
|
||||
<adf-toolbar class="adf-secondary-toolbar" *ngIf="!readOnly && isEditing">
|
||||
<adf-toolbar class="adf-secondary-toolbar" *ngIf="isEditing && !readOnly">
|
||||
<button id="viewer-cancel-button"
|
||||
title="{{ 'ADF_VIEWER.ARIA.CANCEL' | translate }}"
|
||||
attr.aria-label="{{ 'ADF_VIEWER.ARIA.CANCEL' | translate }}"
|
||||
|
@@ -370,4 +370,36 @@ describe('Test Img viewer component ', () => {
|
||||
expect(component.reset).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('allowedEditActions', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ImgViewerComponent);
|
||||
element = fixture.nativeElement;
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should conditionally display rotate and crop buttons based on allowedEditActions', () => {
|
||||
component.readOnly = false;
|
||||
component.allowedEditActions = { rotate: true, crop: true };
|
||||
fixture.detectChanges();
|
||||
|
||||
let rotateButton = element.querySelector('#viewer-rotate-button');
|
||||
let cropButton = element.querySelector('#viewer-crop-button');
|
||||
|
||||
// Check both buttons are visible when allowed
|
||||
expect(rotateButton).not.toBeNull('Rotate button should be visible when allowed');
|
||||
expect(cropButton).not.toBeNull('Crop button should be visible when allowed');
|
||||
|
||||
// Change allowedEditActions to disallow both actions
|
||||
component.allowedEditActions = { rotate: false, crop: false };
|
||||
fixture.detectChanges();
|
||||
|
||||
rotateButton = element.querySelector('#viewer-rotate-button');
|
||||
cropButton = element.querySelector('#viewer-crop-button');
|
||||
|
||||
// Check both buttons are not visible when not allowed
|
||||
expect(rotateButton).toBeNull('Rotate button should not be visible when disallowed');
|
||||
expect(cropButton).toBeNull('Crop button should not be visible when disallowed');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -54,6 +54,12 @@ export class ImgViewerComponent implements AfterViewInit, OnChanges, OnDestroy {
|
||||
@Input()
|
||||
readOnly = true;
|
||||
|
||||
@Input()
|
||||
allowedEditActions: { [key: string]: boolean } = {
|
||||
rotate: true,
|
||||
crop: true
|
||||
};
|
||||
|
||||
@Input()
|
||||
urlFile: string;
|
||||
|
||||
|
@@ -44,6 +44,7 @@
|
||||
<adf-img-viewer [urlFile]="urlFile"
|
||||
[readOnly]="readOnly"
|
||||
[fileName]="internalFileName"
|
||||
[allowedEditActions]="allowedEditActions"
|
||||
[blobFile]="blobFile"
|
||||
(error)="onUnsupportedFile()"
|
||||
(submit)="onSubmitFile($event)"
|
||||
|
@@ -95,6 +95,17 @@ export class ViewerRenderComponent implements OnChanges, OnInit, OnDestroy {
|
||||
@Input()
|
||||
readOnly = true;
|
||||
|
||||
/**
|
||||
* Controls which actions are enabled in the viewer.
|
||||
* Example:
|
||||
* { rotate: true, crop: false } will enable rotation but disable cropping.
|
||||
*/
|
||||
@Input()
|
||||
allowedEditActions: { [key: string]: boolean } = {
|
||||
rotate: true,
|
||||
crop: true
|
||||
};
|
||||
|
||||
/** media subtitles for the media player*/
|
||||
@Input()
|
||||
tracks: Track[] = [];
|
||||
|
@@ -167,6 +167,7 @@
|
||||
[blobFile]="blobFile"
|
||||
[readOnly]="readOnly"
|
||||
(submitFile)="onSubmitFile($event)"
|
||||
[allowedEditActions]="allowedEditActions"
|
||||
[urlFile]="urlFile"
|
||||
(isSaving)="allowNavigate = !$event"
|
||||
[tracks]="tracks"
|
||||
|
@@ -189,6 +189,17 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
|
||||
@Input()
|
||||
readOnly = true;
|
||||
|
||||
/**
|
||||
* Controls which actions are enabled in the viewer.
|
||||
* Example:
|
||||
* { rotate: true, crop: false } will enable rotation but disable cropping.
|
||||
*/
|
||||
@Input()
|
||||
allowedEditActions: { [key: string]: boolean } = {
|
||||
rotate: true,
|
||||
crop: true
|
||||
};
|
||||
|
||||
/** media subtitles for the media player*/
|
||||
@Input()
|
||||
tracks: Track[] = [];
|
||||
|
@@ -32,7 +32,6 @@ export * from './lib/app-config/index';
|
||||
export * from './lib/form/index';
|
||||
export * from './lib/layout/index';
|
||||
export * from './lib/comments/index';
|
||||
export * from './lib/buttons-menu/index';
|
||||
export * from './lib/sorting-picker/index';
|
||||
export * from './lib/templates/index';
|
||||
export * from './lib/pipes/index';
|
||||
|
Reference in New Issue
Block a user