diff --git a/docs/docassets/images/adf-buttons-menu-desktop.png b/docs/docassets/images/adf-buttons-menu-desktop.png new file mode 100644 index 0000000000..9e6c42c611 Binary files /dev/null and b/docs/docassets/images/adf-buttons-menu-desktop.png differ diff --git a/docs/docassets/images/adf-buttons-menu-mobile.png b/docs/docassets/images/adf-buttons-menu-mobile.png new file mode 100644 index 0000000000..b1cffe225d Binary files /dev/null and b/docs/docassets/images/adf-buttons-menu-mobile.png differ diff --git a/docs/insights/buttons-menu.component.md b/docs/insights/buttons-menu.component.md new file mode 100644 index 0000000000..567532148d --- /dev/null +++ b/docs/insights/buttons-menu.component.md @@ -0,0 +1,90 @@ +--- +Added: v2.4.0 +Status: Active +--- +# Buttons Menu Component + +Displays buttons on a responsive menu. + +## Basic Usage + +This component shows buttons on a responsive menu that changes depending on the device's screen. + +```html + + +``` +You will need to declare all the buttons that you want to have inside your menu in the parent component. + +```ts +buttons: MenuButton[] = []; + + setButtons() { + this.buttons = [ + new MenuButton({ + label: 'Settings', + icon: 'settings', + handler: this.settings.bind(this) + }), + new MenuButton({ + label: 'Delete', + icon: 'delete', + handler: this.deleteItem.bind(this, this.reportId), + id: 'delete-button' + }), + new MenuButton({ + label: 'Export', + icon: 'file_download', + handler: this.exportItem.bind(this), + id: 'export-button', + isVisible: this.isItemValid.bind(this) + }), + new MenuButton({ + label: 'Save', + icon: 'save', + handler: this.saveItem.bind(this), + id: 'save-button', + isVisible: this.isItemValid.bind(this) + }) + ]; +``` + +## Properties + +####Buttons Menu Component + +| Name | Type | Description | +| --- | --- | -- | +| buttons | `MenuButton []` | The array that contains all the buttons for the menu | + +####Button Model + +| Name | Type | Description | +| --- | --- | -- | +| label | `string` | Label to display for the button. | +| icon | `string` | Icon to display for the button. | +| handler | `function` | Callback for the event handler once the button is clicked. | +| styles | `string` | Classes to apply to the button. | +| id | `string` | Id of the button. | +| isVisible | `function` | Variable to define if button is visible or hidden. This function must return a boolean parameter. For instance, if it returns true the button will be visible. If it returns false the button will be hiden. | + + +## Details + +This component uses [Angular Material](https://material.angular.io/) to style the menu. + +Desktop view of the menu +![adf-buttons-menu-desktop](../docassets/images/adf-buttons-menu-desktop.png) + +Mobile view of the menu +![adf-buttons-menu-mobile](../docassets/images/adf-buttons-menu-mobile.png) + +Menu Button Model + +## See also + +- [Menu Button Model](./menu-button.model.md) + + + diff --git a/lib/core/buttons-menu/buttons-menu.component.html b/lib/core/buttons-menu/buttons-menu.component.html new file mode 100644 index 0000000000..ce3030d75b --- /dev/null +++ b/lib/core/buttons-menu/buttons-menu.component.html @@ -0,0 +1,27 @@ +
+ + + +
+
+ + + + + + +
+ + + + + + + + diff --git a/lib/core/buttons-menu/buttons-menu.component.spec.ts b/lib/core/buttons-menu/buttons-menu.component.spec.ts new file mode 100644 index 0000000000..3957c999f6 --- /dev/null +++ b/lib/core/buttons-menu/buttons-menu.component.spec.ts @@ -0,0 +1,94 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * 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, async } from '@angular/core/testing'; +import { ButtonsMenuComponent } from './buttons-menu.component'; +import { MenuButton } from './menu-button.model'; +import { MaterialModule } from '../material.module'; +import { CoreTestingModule } from '../testing/core.testing.module'; + +/*tslint:disable:ban*/ + +fdescribe('ButtonsMenuComponent', () => { + + let fixture; + let buttonsMenuComponent: ButtonsMenuComponent; + let element: HTMLElement; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + MaterialModule, + CoreTestingModule + ] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ButtonsMenuComponent); + element = fixture.nativeElement; + buttonsMenuComponent = fixture.debugElement.componentInstance; + }); + + afterEach(() => { + fixture.destroy(); + TestBed.resetTestingModule(); + }); + + it('should hide buttons menu div if buttons input is empty', async(() => { + buttonsMenuComponent.buttons = []; + fixture.detectChanges(); + fixture.whenStable().then(() => { + const buttonsMenuElement = element.querySelector('#adf-buttons-menu'); + expect(buttonsMenuElement).toBeNull(); + }); + })); + + it('should render buttons menu when there is at least one button declared in the buttons array', async(() => { + const button = new MenuButton({ + label: 'button', + icon: 'button', + id: 'clickMe' + }); + buttonsMenuComponent.buttons = [button]; + fixture.detectChanges(); + fixture.whenStable().then(() => { + const buttonsMenuElement = element.querySelector('#adf-buttons-menu'); + expect(buttonsMenuElement).not.toBeNull(); + expect(buttonsMenuElement).toBeDefined(); + }); + })); + + it('should call the handler function when button is clicked', async(() => { + const button = new MenuButton({ + label: 'button', + icon: 'button', + id: 'clickMe' + }); + button.handler = jasmine.createSpy('handler'); + buttonsMenuComponent.buttons = [button]; + fixture.detectChanges(); + fixture.whenStable().then(() => { + const buttonsMenuElement: HTMLButtonElement = element.querySelector('#clickMe'); + expect(buttonsMenuElement).not.toBeNull(); + expect(buttonsMenuElement).toBeDefined(); + buttonsMenuElement.click(); + fixture.detectChanges(); + expect(button.handler).toHaveBeenCalled(); + }); + })); +}); diff --git a/lib/core/buttons-menu/buttons-menu.component.ts b/lib/core/buttons-menu/buttons-menu.component.ts new file mode 100644 index 0000000000..69b188351f --- /dev/null +++ b/lib/core/buttons-menu/buttons-menu.component.ts @@ -0,0 +1,38 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * 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. + */ + +/* tslint:disable:component-selector no-access-missing-member no-input-rename */ + +import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { MenuButton } from './menu-button.model'; + +@Component({ + selector: 'adf-buttons-action-menu', + templateUrl: './buttons-menu.component.html' +}) + +export class ButtonsMenuComponent implements OnChanges { + @Input() buttons: MenuButton[]; + + ngOnChanges(changes: SimpleChanges) { + this.buttons = changes['buttons'].currentValue; + } + + hasButtons() { + return this.buttons.length > 0 ? true : false; + } +} diff --git a/lib/core/buttons-menu/buttons-menu.module.ts b/lib/core/buttons-menu/buttons-menu.module.ts new file mode 100644 index 0000000000..dc350c7a79 --- /dev/null +++ b/lib/core/buttons-menu/buttons-menu.module.ts @@ -0,0 +1,39 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * 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 { MaterialModule } from '../material.module'; +import { ButtonsMenuComponent } from './buttons-menu.component'; +import { FlexLayoutModule } from '@angular/flex-layout'; + +@NgModule({ + imports: [ + CommonModule, + MaterialModule, + TranslateModule, + FlexLayoutModule + ], + declarations: [ + ButtonsMenuComponent + ], + exports: [ + ButtonsMenuComponent + ] +}) +export class ButtonsMenuModule {} diff --git a/lib/core/buttons-menu/index.ts b/lib/core/buttons-menu/index.ts new file mode 100644 index 0000000000..4c6ac1d58f --- /dev/null +++ b/lib/core/buttons-menu/index.ts @@ -0,0 +1,18 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * 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'; diff --git a/lib/core/buttons-menu/menu-button.model.ts b/lib/core/buttons-menu/menu-button.model.ts new file mode 100644 index 0000000000..be28776fd8 --- /dev/null +++ b/lib/core/buttons-menu/menu-button.model.ts @@ -0,0 +1,37 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * 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 type VisibiltyFunction = (obj?: any) => boolean; +const defaultValidation = () => true; + +export class MenuButton { + label: string; + icon: string; + handler: any; + styles: string; + id: string; + isVisible: VisibiltyFunction; + + constructor(obj?: any) { + this.label = obj.label; + this.icon = obj.icon; + this.handler = obj.handler; + this.styles = obj.styles || null; + this.id = obj.id || null; + this.isVisible = obj.isVisible ? obj.isVisible : defaultValidation; + } +} diff --git a/lib/core/buttons-menu/public-api.ts b/lib/core/buttons-menu/public-api.ts new file mode 100644 index 0000000000..e50687749e --- /dev/null +++ b/lib/core/buttons-menu/public-api.ts @@ -0,0 +1,20 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * 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 './menu-button.model'; +export * from './buttons-menu.module'; diff --git a/lib/core/core.module.ts b/lib/core/core.module.ts index 25fb75d15d..ed078e7d5c 100644 --- a/lib/core/core.module.ts +++ b/lib/core/core.module.ts @@ -40,6 +40,7 @@ import { FormModule } from './form/form.module'; import { SidenavLayoutModule } from './sidenav-layout/sidenav-layout.module'; import { SideBarActionModule } from './sidebar/sidebar-action.module'; import { CommentsModule } from './comments/comments.module'; +import { ButtonsMenuModule } from './buttons-menu/buttons-menu.module'; import { DirectiveModule } from './directives/directive.module'; import { PipeModule } from './pipes/pipe.module'; @@ -151,6 +152,7 @@ export function providers() { InfoDrawerModule, DataColumnModule, DataTableModule, + ButtonsMenuModule, TranslateModule.forChild({ loader: { provide: TranslateLoader, @@ -185,7 +187,8 @@ export function providers() { InfoDrawerModule, DataColumnModule, DataTableModule, - TranslateModule + TranslateModule, + ButtonsMenuModule ] }) export class CoreModuleLazy { @@ -218,6 +221,7 @@ export class CoreModuleLazy { InfoDrawerModule, DataColumnModule, DataTableModule, + ButtonsMenuModule, TranslateModule.forRoot({ loader: { provide: TranslateLoader, @@ -252,7 +256,8 @@ export class CoreModuleLazy { InfoDrawerModule, DataColumnModule, DataTableModule, - TranslateModule + TranslateModule, + ButtonsMenuModule ], providers: [ ...providers(), diff --git a/lib/core/index.ts b/lib/core/index.ts index 4e29a0a168..f48f9ee3b9 100644 --- a/lib/core/index.ts +++ b/lib/core/index.ts @@ -33,6 +33,7 @@ export * from './app-config/index'; export * from './form/index'; export * from './sidenav-layout/index'; export * from './comments/index'; +export * from './buttons-menu/index'; export * from './pipes/index'; export * from './services/index'; diff --git a/lib/core/styles/prebuilt/_all-theme.scss b/lib/core/styles/prebuilt/_all-theme.scss index 43320b0716..2c556a5cc0 100644 --- a/lib/core/styles/prebuilt/_all-theme.scss +++ b/lib/core/styles/prebuilt/_all-theme.scss @@ -1,9 +1,11 @@ @import '../../../content-services/styles/index'; @import '../../../process-services/styles/index'; @import '../../../core/styles/index'; +@import '../../../insights/styles/index'; @mixin alfresco-material-theme($theme) { @include adf-content-services-theme($theme); @include adf-process-services-theme($theme); @include adf-core-theme($theme); + @include adf-insights-theme($theme); } diff --git a/lib/insights/analytics-process/analytics-process.module.ts b/lib/insights/analytics-process/analytics-process.module.ts index 5743dc267c..8d5aafa947 100644 --- a/lib/insights/analytics-process/analytics-process.module.ts +++ b/lib/insights/analytics-process/analytics-process.module.ts @@ -24,7 +24,7 @@ import { MaterialModule } from '../material.module'; import { ChartsModule } from 'ng2-charts'; -import { ToolbarModule } from '@alfresco/adf-core'; +import { ToolbarModule, ButtonsMenuModule } from '@alfresco/adf-core'; import { AnalyticsGeneratorComponent } from './components/analytics-generator.component'; import { AnalyticsReportHeatMapComponent } from './components/analytics-report-heat-map.component'; import { AnalyticsReportListComponent } from './components/analytics-report-list.component'; @@ -37,7 +37,10 @@ import { DropdownWidgetAanalyticsComponent } from './components/widgets/dropdown import { DurationWidgetComponent } from './components/widgets/duration/duration.widget'; import { NumberWidgetAanlyticsComponent } from './components/widgets/number/number.widget'; + import { AnalyticsService } from './services/analytics.service'; +import { FlexLayoutModule } from '@angular/flex-layout'; + @NgModule({ imports: [ @@ -48,7 +51,9 @@ import { AnalyticsService } from './services/analytics.service'; DiagramsModule, MaterialModule, TranslateModule, - ToolbarModule + ToolbarModule, + FlexLayoutModule, + ButtonsMenuModule ], declarations: [ AnalyticsComponent, diff --git a/lib/insights/analytics-process/components/analytics-report-list.component.scss b/lib/insights/analytics-process/components/analytics-report-list.component.scss index 64ba5b08b8..a8ac7f72f1 100644 --- a/lib/insights/analytics-process/components/analytics-report-list.component.scss +++ b/lib/insights/analytics-process/components/analytics-report-list.component.scss @@ -1,5 +1,8 @@ @mixin adf-analytics-report-list-theme($theme) { $primary: map-get($theme, primary); + $accent: map-get($theme, accent ); + $background: map-get($theme, background); + $foreground: map-get($theme, foreground); .adf-analytics-report-list { @@ -43,7 +46,7 @@ position: relative; min-height: 200px; overflow: hidden; - background-color: #269abc; + background-color: mat-color($background, background); display: flex; flex-direction: column; cursor: pointer; @@ -56,7 +59,7 @@ &-icon { font-size: 70px; - color: #168aac; + color: mat-color($accent); width: 1em; height: 1em; display: inline-block; @@ -79,16 +82,16 @@ } &-actions { - border-top: 1px solid rgba(0,0,0,.1); + border-top: 1px solid mat-color($foreground, divider); padding: 8px; box-sizing: border-box; height: 40px; &-icon { - color: #e9f1f3; + color: mat-color($primary, 50); &:hover { - color: #b7dfea; + color: mat-color($primary, 100); } } } diff --git a/lib/insights/analytics-process/components/analytics-report-parameters.component.html b/lib/insights/analytics-process/components/analytics-report-parameters.component.html index 9560b5dad9..b3182455ad 100644 --- a/lib/insights/analytics-process/components/analytics-report-parameters.component.html +++ b/lib/insights/analytics-process/components/analytics-report-parameters.component.html @@ -24,27 +24,10 @@ mode_edit

{{reportParameters.name}}

- -
- - - - - - -
+ + +
@@ -136,4 +119,4 @@
- + \ No newline at end of file diff --git a/lib/insights/analytics-process/components/analytics-report-parameters.component.scss b/lib/insights/analytics-process/components/analytics-report-parameters.component.scss index ba732908a9..ffee75fe9b 100644 --- a/lib/insights/analytics-process/components/analytics-report-parameters.component.scss +++ b/lib/insights/analytics-process/components/analytics-report-parameters.component.scss @@ -1,103 +1,110 @@ -.dropdown-widget { - width: 100%; -} +@mixin adf-analytics-report-parameters-theme($theme) { + $primary: map-get($theme, primary); + $accent: map-get($theme, accent); + $warn: map-get($theme, warn); + $foreground: map-get($theme, foreground); + $background: map-get($theme, background); -.dropdown-widget__select { - width: 100%; -} - -.dropdown-widget__invalid .dropdown-widget__select { - border-color: #d50000; -} - -.dropdown-widget__invalid .dropdown-widget__label { - color: #d50000; -} - -.dropdown-widget__invalid .dropdown-widget__label:after { - background-color: #d50000; -} - -.adf-edit-report-title { - float: left; - font-size: 20px!important; - padding-top: 19px; -} - -.adf-report-icon { - float: left; - padding: 5px 5px 0 0; - visibility: hidden; -} - -.adf-report-title-container { - cursor: pointer; - width: 100%; - margin-bottom: 12px; - - :hover .adf-report-icon { - color: rgb(68, 138, 255); - visibility: visible; - } - -} - -.adf-report-title { - padding-top: 10px; -} - -.adf-full-width-input { - width: 100%; -} - -.is-hide { - height: 0; - overflow: hidden; - transition: height 0.5s; -} - -.adf-report-report-container { - border-bottom: solid 1px rgb(212, 212, 212); - padding-top: 10px; - - .mat-toolbar { - border: 0 !important; - padding: 0 !important; - } -} - -.report-container-setting { - padding-left: 10px; -} - -.option_button_details { - padding-top: 20px; -} - -.export-message { - background-color: lightgray; -} - -.save-export-input { - width: 100%; -} - -.delete-parameter { - position: absolute; - margin-left: 60%; - padding-top: 5px; -} - -.hide { - display: none; -} - -.adf-report-dialog { - .mat-form-field { + .dropdown-widget { width: 100%; } - .mat-dialog-actions { - justify-content: flex-end; + .dropdown-widget__select { + width: 100%; + } + + .dropdown-widget__invalid .dropdown-widget__select { + border-color: mat-color($warn); + } + + .dropdown-widget__invalid .dropdown-widget__label { + color: mat-color($warn); + } + + .dropdown-widget__invalid .dropdown-widget__label:after { + background-color: mat-color($warn); + } + + .adf-edit-report-title { + float: left; + font-size: 20px!important; + padding-top: 19px; + } + + .adf-report-icon { + float: left; + padding: 5px 5px 0 0; + visibility: hidden; + } + + .adf-report-title-container { + cursor: pointer; + width: 100%; + margin-bottom: 12px; + + :hover .adf-report-icon { + color: mat-color($primary); + visibility: visible; + } + } + + .adf-report-title { + padding-top: 10px; + } + + .adf-full-width-input { + width: 100%; + } + + .is-hide { + height: 0; + overflow: hidden; + transition: height 0.5s; + } + + .adf-report-report-container { + border-bottom: solid 1px mat-color($foreground, divider); + padding-top: 10px; + + .mat-toolbar { + border: 0 !important; + padding: 0 !important; + } + } + + .report-container-setting { + padding-left: 10px; + } + + .option_button_details { + padding-top: 20px; + } + + .export-message { + background-color: mat-color($background, background); + } + + .save-export-input { + width: 100%; + } + + .delete-parameter { + position: absolute; + margin-left: 60%; + padding-top: 5px; + } + + .hide { + display: none; + } + + .adf-report-dialog { + .mat-form-field { + width: 100%; + } + + .mat-dialog-actions { + justify-content: flex-end; + } } } diff --git a/lib/insights/analytics-process/components/analytics-report-parameters.component.spec.ts b/lib/insights/analytics-process/components/analytics-report-parameters.component.spec.ts index 80703423d4..baeec7e4df 100644 --- a/lib/insights/analytics-process/components/analytics-report-parameters.component.spec.ts +++ b/lib/insights/analytics-process/components/analytics-report-parameters.component.spec.ts @@ -30,6 +30,7 @@ describe('AnalyticsReportParametersComponent', () => { let component: AnalyticsReportParametersComponent; let fixture: ComponentFixture; let element: HTMLElement; + let validForm = false; setupTestBed({ imports: [InsightsTestingModule] @@ -39,6 +40,9 @@ describe('AnalyticsReportParametersComponent', () => { fixture = TestBed.createComponent(AnalyticsReportParametersComponent); component = fixture.componentInstance; element = fixture.nativeElement; + spyOn(component, 'isFormValid').and.callFake(() => { + return validForm; + }); fixture.detectChanges(); }); @@ -393,7 +397,7 @@ describe('AnalyticsReportParametersComponent', () => { }); describe('When the form is rendered correctly', () => { - let validForm: boolean = true; + let values: any = { dateRange: { startDate: '2016-09-01', endDate: '2016-10-05' @@ -435,18 +439,10 @@ describe('AnalyticsReportParametersComponent', () => { fixture.whenStable().then(() => { component.toggleParameters(); - component.reportId = '1'; - spyOn(component, 'isFormValid').and.callFake(() => { - return validForm; - }); fixture.detectChanges(); }); })); - afterEach(() => { - validForm = true; - }); - it('Should be able to change the report title', (done) => { let title: HTMLElement = element.querySelector('h4'); @@ -546,50 +542,77 @@ describe('AnalyticsReportParametersComponent', () => { }); })); - it('Should raise an event for report deleted', async(() => { - let deleteButton: HTMLButtonElement = element.querySelector('#delete-button'); - expect(deleteButton).toBeDefined(); - expect(deleteButton).not.toBeNull(); - - component.deleteReportSuccess.subscribe((reportId) => { - expect(reportId).not.toBeNull(); + it('should render adf-buttons-menu component', async(() => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + const buttonsMenuComponent = element.querySelector('adf-buttons-action-menu'); + expect(buttonsMenuComponent).not.toBeNull(); + expect(buttonsMenuComponent).toBeDefined(); }); + })); - deleteButton.click(); + it('should render delete button', async(() => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + const buttonsMenuComponent = element.querySelector('#delete-button'); + expect(buttonsMenuComponent).not.toBeNull(); + expect(buttonsMenuComponent).toBeDefined(); + }); + })); - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json' + it('Should raise an event for report deleted', async(() => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + let deleteButton = fixture.debugElement.nativeElement.querySelector('#delete-button'); + expect(deleteButton).toBeDefined(); + expect(deleteButton).not.toBeNull(); + component.deleteReportSuccess.subscribe((reportId) => { + expect(reportId).not.toBeNull(); + }); + deleteButton.click(); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'json' + }); }); })); it('Should hide export button if the form is not valid', async(() => { - let exportButton: HTMLButtonElement = element.querySelector('#export-button'); - expect(exportButton).toBeDefined(); - expect(exportButton).not.toBeNull(); - validForm = false; - + validForm = true; fixture.detectChanges(); - fixture.whenStable().then(() => { fixture.detectChanges(); - exportButton = element.querySelector('#export-button'); - expect(exportButton).toBeNull(); + let exportButton = fixture.debugElement.nativeElement.querySelector('#export-button'); + expect(exportButton).toBeDefined(); + expect(exportButton).not.toBeNull(); + + validForm = false; + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + exportButton = fixture.debugElement.nativeElement.querySelector('#export-button'); + expect(exportButton).toBeNull(); + }); }); + })); it('Should hide save button if the form is not valid', async(() => { - let saveButton: HTMLButtonElement = element.querySelector('#save-button'); - expect(saveButton).toBeDefined(); - expect(saveButton).not.toBeNull(); - validForm = false; - + validForm = true; fixture.detectChanges(); - fixture.whenStable().then(() => { fixture.detectChanges(); - saveButton = element.querySelector('#save-button'); - expect(saveButton).toBeNull(); + let saveButton = fixture.debugElement.nativeElement.querySelector('#save-button'); + expect(saveButton).toBeDefined(); + expect(saveButton).not.toBeNull(); + + validForm = false; + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + saveButton = fixture.debugElement.nativeElement.querySelector('#save-button'); + expect(saveButton).toBeNull(); + }); }); })); @@ -615,6 +638,5 @@ describe('AnalyticsReportParametersComponent', () => { }); })); }); - }); }); diff --git a/lib/insights/analytics-process/components/analytics-report-parameters.component.ts b/lib/insights/analytics-process/components/analytics-report-parameters.component.ts index 73873adb19..7439e57c2c 100644 --- a/lib/insights/analytics-process/components/analytics-report-parameters.component.ts +++ b/lib/insights/analytics-process/components/analytics-report-parameters.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { ContentService, LogService } from '@alfresco/adf-core'; +import { ContentService, LogService, MenuButton } from '@alfresco/adf-core'; import { AfterContentChecked, Component, @@ -38,6 +38,8 @@ import { ReportParametersModel } from '../../diagram/models/report/reportParamet import { ReportQuery } from '../../diagram/models/report/reportQuery.model'; import { AnalyticsService } from '../services/analytics.service'; + + // @deprecated 2.3.0 analytics-report-parameters tag removed @Component({ selector: 'adf-analytics-report-parameters, analytics-report-parameters', @@ -95,6 +97,8 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On reportName: string; + buttons: MenuButton[] = []; + private dropDownSub; private reportParamsSub; private paramOpts; @@ -107,6 +111,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On private logService: LogService, private contentService: ContentService, private dialog: MatDialog) { + } ngOnInit() { @@ -130,9 +135,12 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On if (this.reportForm) { this.reportForm.reset(); } + let reportId = changes['reportId']; if (reportId && reportId.currentValue) { + this.reportId = reportId.currentValue; this.getReportParams(reportId.currentValue); + this.setButtons(); } let appId = changes['appId']; @@ -145,7 +153,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On let formBuilderGroup: any = {}; parameters.forEach((param: ReportParameterDetailsModel) => { switch (param.type) { - case 'dateRange' : + case 'dateRange': formBuilderGroup.dateRange = new FormGroup({}, Validators.required); break; case 'processDefinition': @@ -348,10 +356,6 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On return this.action === 'Save'; } - isFormValid() { - return this.reportForm && this.reportForm.dirty && this.reportForm.valid; - } - doExport(paramQuery: ReportQuery) { this.analyticsService.exportReportToCsv(this.reportId, paramQuery).subscribe( (data: any) => { @@ -385,4 +389,38 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On isParametersHide() { return this.hideParameters; } + + isFormValid() { + return this.reportForm && this.reportForm.dirty && this.reportForm.valid; + } + + setButtons() { + this.buttons = [ + new MenuButton({ + label: 'ANALYTICS.MESSAGES.ICON-SETTING', + icon: 'settings', + handler: this.toggleParameters.bind(this) + }), + new MenuButton({ + label: 'ANALYTICS.MESSAGES.ICON-DELETE', + icon: 'delete', + handler: this.deleteReport.bind(this, this.reportId), + id: 'delete-button' + }), + new MenuButton({ + label: 'ANALYTICS.MESSAGES.ICON-EXPORT-CSV', + icon: 'file_download', + handler: this.showDialog.bind(this, 'Export'), + id: 'export-button', + isVisible: this.isFormValid.bind(this) + }), + new MenuButton({ + label: 'ANALYTICS.MESSAGES.ICON-SAVE', + icon: 'save', + handler: this.showDialog.bind(this, 'Save'), + id: 'save-button', + isVisible: this.isFormValid.bind(this) + }) + ]; + } } diff --git a/lib/insights/material.module.ts b/lib/insights/material.module.ts index daac2a4345..966f50cf82 100644 --- a/lib/insights/material.module.ts +++ b/lib/insights/material.module.ts @@ -21,7 +21,7 @@ import { MatChipsModule, MatDatepickerModule, MatDialogModule, MatGridListModule, MatIconModule, MatInputModule, MatListModule, MatNativeDateModule, MatOptionModule, MatProgressSpinnerModule, MatRadioModule, MatRippleModule, MatSelectModule, MatSlideToggleModule, MatTableModule, MatTabsModule, - MatTooltipModule + MatTooltipModule, MatMenuModule } from '@angular/material'; export function modules() { @@ -30,7 +30,7 @@ export function modules() { MatCheckboxModule, MatDatepickerModule, MatGridListModule, MatIconModule, MatInputModule, MatListModule, MatOptionModule, MatRadioModule, MatSelectModule, MatSlideToggleModule, MatTableModule, MatTabsModule, MatProgressSpinnerModule, MatNativeDateModule, MatRippleModule, MatTooltipModule, - MatChipsModule + MatChipsModule, MatMenuModule ]; } diff --git a/lib/insights/styles/_index.scss b/lib/insights/styles/_index.scss index 4a534b15c2..e915e57fcb 100644 --- a/lib/insights/styles/_index.scss +++ b/lib/insights/styles/_index.scss @@ -1,5 +1,5 @@ @import '../diagram/components/tooltip/diagram-tooltip.component'; - +@import '../analytics-process/components/analytics-report-parameters.component'; @import '../analytics-process/components/analytics-report-list.component'; @import '../analytics-process/components/widgets/date-range/date-range.widget'; @@ -7,4 +7,5 @@ @include adf-diagram-tooltip-theme($theme); @include adf-analytics-report-list-theme($theme); @include adf-analytics-date-range-widget-theme($theme); + @include adf-analytics-report-parameters-theme($theme); }