mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-09-17 14:21:14 +00:00
added header and search layout changes
This commit is contained in:
committed by
Yasa-Nataliya
parent
d4cf1eddcc
commit
5b39510106
@@ -132,44 +132,6 @@
|
||||
}
|
||||
],
|
||||
"create": [
|
||||
{
|
||||
"id": "app.create.uploadFile",
|
||||
"order": 100,
|
||||
"icon": "file_upload",
|
||||
"title": "APP.NEW_MENU.MENU_ITEMS.UPLOAD_FILE",
|
||||
"description": "APP.NEW_MENU.TOOLTIPS.UPLOAD_FILES",
|
||||
"description-disabled": "APP.NEW_MENU.TOOLTIPS.UPLOAD_FILES_NOT_ALLOWED",
|
||||
"actions": {
|
||||
"click": "UPLOAD_FILES"
|
||||
},
|
||||
"rules": {
|
||||
"enabled": "app.navigation.folder.canUpload",
|
||||
"visible": "app.isContentServiceEnabled"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "app.create.uploadFolder",
|
||||
"order": 200,
|
||||
"icon": "file_upload",
|
||||
"title": "APP.NEW_MENU.MENU_ITEMS.UPLOAD_FOLDER",
|
||||
"description": "APP.NEW_MENU.TOOLTIPS.UPLOAD_FOLDERS",
|
||||
"description-disabled": "APP.NEW_MENU.TOOLTIPS.UPLOAD_FOLDERS_NOT_ALLOWED",
|
||||
"actions": {
|
||||
"click": "UPLOAD_FOLDER"
|
||||
},
|
||||
"rules": {
|
||||
"enabled": "app.navigation.folder.canUpload",
|
||||
"visible": "app.isContentServiceEnabled"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "app.create.separator.1",
|
||||
"type": "separator",
|
||||
"order": 300,
|
||||
"rules": {
|
||||
"visible": "app.isContentServiceEnabled"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "app.create.folder",
|
||||
"order": 400,
|
||||
@@ -198,14 +160,6 @@
|
||||
"visible": "app.isContentServiceEnabled"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "app.create.separator.2",
|
||||
"type": "separator",
|
||||
"order": 650,
|
||||
"rules": {
|
||||
"visible": "app.isContentServiceEnabled"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "app.create.fileFromTemplate",
|
||||
"order": 700,
|
||||
@@ -237,6 +191,38 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"upload": [
|
||||
{
|
||||
"id": "app.create.uploadFile",
|
||||
"order": 100,
|
||||
"icon": "file_upload",
|
||||
"title": "APP.NEW_MENU.MENU_ITEMS.UPLOAD_FILE",
|
||||
"description": "APP.NEW_MENU.TOOLTIPS.UPLOAD_FILES",
|
||||
"description-disabled": "APP.NEW_MENU.TOOLTIPS.UPLOAD_FILES_NOT_ALLOWED",
|
||||
"actions": {
|
||||
"click": "UPLOAD_FILES"
|
||||
},
|
||||
"rules": {
|
||||
"enabled": "app.navigation.folder.canUpload",
|
||||
"visible": "app.isContentServiceEnabled"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "app.create.uploadFolder",
|
||||
"order": 200,
|
||||
"icon": "file_upload",
|
||||
"title": "APP.NEW_MENU.MENU_ITEMS.UPLOAD_FOLDER",
|
||||
"description": "APP.NEW_MENU.TOOLTIPS.UPLOAD_FOLDERS",
|
||||
"description-disabled": "APP.NEW_MENU.TOOLTIPS.UPLOAD_FOLDERS_NOT_ALLOWED",
|
||||
"actions": {
|
||||
"click": "UPLOAD_FOLDER"
|
||||
},
|
||||
"rules": {
|
||||
"enabled": "app.navigation.folder.canUpload",
|
||||
"visible": "app.isContentServiceEnabled"
|
||||
}
|
||||
}
|
||||
],
|
||||
"navbar": [
|
||||
{
|
||||
"id": "app.navbar.primary",
|
||||
|
@@ -103,6 +103,12 @@
|
||||
"CREATE_LIBRARY": "Create a new File Library"
|
||||
}
|
||||
},
|
||||
"HEADER": {
|
||||
"BUTTONS": {
|
||||
"CREATE": "Create",
|
||||
"UPLOAD": "Upload"
|
||||
}
|
||||
},
|
||||
"BROWSE": {
|
||||
"FILE": {
|
||||
"TITLE": "Files",
|
||||
|
@@ -122,6 +122,7 @@ import { AcaFolderRulesModule } from '@alfresco/aca-folder-rules';
|
||||
import { TagsColumnComponent } from './components/dl-custom-components/tags-column/tags-column.component';
|
||||
import { UserInfoComponent } from './components/common/user-info/user-info.component';
|
||||
import { CustomIconsModule } from './extensions/custom-icons.module';
|
||||
import { AppHeaderActionsModule } from './components/header-actions/header-actions.module';
|
||||
|
||||
registerLocaleData(localeFr);
|
||||
registerLocaleData(localeDe);
|
||||
@@ -163,6 +164,7 @@ registerLocaleData(localeSv);
|
||||
AppCreateMenuModule,
|
||||
DocumentListCustomComponentsModule,
|
||||
AppSearchInputModule,
|
||||
AppHeaderActionsModule,
|
||||
AppSearchResultsModule,
|
||||
AppHeaderModule,
|
||||
AppNodeVersionModule,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<aca-page-layout>
|
||||
<aca-page-layout-header>
|
||||
<adf-breadcrumb root="APP.BROWSE.LIBRARIES.MENU.FAVORITE_LIBRARIES.TITLE"> </adf-breadcrumb>
|
||||
|
||||
<aca-header-actions></aca-header-actions>
|
||||
<adf-toolbar class="adf-toolbar--inline">
|
||||
<ng-container *ngFor="let entry of actions; trackBy: trackByActionId">
|
||||
<aca-toolbar-action [actionRef]="entry"></aca-toolbar-action>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<aca-page-layout>
|
||||
<aca-page-layout-header>
|
||||
<adf-breadcrumb root="APP.BROWSE.FAVORITES.TITLE"> </adf-breadcrumb>
|
||||
|
||||
<aca-header-actions></aca-header-actions>
|
||||
<adf-toolbar class="adf-toolbar--inline">
|
||||
<ng-container *ngFor="let entry of actions; trackBy: trackByActionId">
|
||||
<aca-toolbar-action [actionRef]="entry"></aca-toolbar-action>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<aca-page-layout [hasError]="!isValidPath">
|
||||
<aca-page-layout-header>
|
||||
<adf-breadcrumb [root]="title" [folderNode]="node" [maxItems]="isSmallScreen ? 1 : 0" (navigate)="onBreadcrumbNavigate($event)"> </adf-breadcrumb>
|
||||
|
||||
<aca-header-actions></aca-header-actions>
|
||||
<adf-toolbar class="adf-toolbar--inline">
|
||||
<ng-container *ngFor="let entry of actions; trackBy: trackByActionId">
|
||||
<aca-toolbar-action [actionRef]="entry"></aca-toolbar-action>
|
||||
|
@@ -0,0 +1,33 @@
|
||||
<div>
|
||||
<div class="adf-toolbar--spacer adf-toolbar-divider"></div>
|
||||
<span class="action-bar">
|
||||
<button class="aca-mat-button aca-create-button" mat-stroked-button data-automation-id="create-button"
|
||||
*ngIf="canShowCreateButton()"
|
||||
[matMenuTriggerFor]="createMenu">
|
||||
{{ 'APP.HEADER.BUTTONS.CREATE' | translate }}
|
||||
</button>
|
||||
<mat-menu #createMenu="matMenu" role="menu" class="app-create-menu__root-menu app-create-menu__sub-menu"
|
||||
[overlapTrigger]="false" yPosition="below">
|
||||
<div *ngFor="let action of createActions; trackBy: trackByActionId">
|
||||
<app-toolbar-menu-item [actionRef]="action"></app-toolbar-menu-item>
|
||||
</div>
|
||||
</mat-menu>
|
||||
|
||||
<button class="aca-mat-button aca-upload-button" mat-stroked-button data-automation-id="upload-button"
|
||||
*ngIf="canShowUploadButton()" [matMenuTriggerFor]="uploadMenu">
|
||||
{{ 'APP.HEADER.BUTTONS.UPLOAD' | translate }}
|
||||
</button>
|
||||
<mat-menu #uploadMenu="matMenu" role="menu" class="app-upload-menu__root-menu app-upload-menu__sub-menu"
|
||||
[overlapTrigger]="false" yPosition="below">
|
||||
<div *ngFor="let action of uploadActions; trackBy: trackByActionId">
|
||||
<app-toolbar-menu-item [actionRef]="action"></app-toolbar-menu-item>
|
||||
</div>
|
||||
</mat-menu>
|
||||
|
||||
<app-main-action *ngIf="isTasksRoute() || isProcessesRoute()"></app-main-action>
|
||||
|
||||
<adf-toolbar-divider *ngIf="canShowSearchSeparator()">
|
||||
</adf-toolbar-divider>
|
||||
<aca-search-input class="app-search-input"></aca-search-input>
|
||||
</span>
|
||||
</div>
|
@@ -0,0 +1,80 @@
|
||||
.aca-page-layout-header {
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// flex: 0 0 65px;
|
||||
// flex-basis: 96px;
|
||||
// background: var(--theme-page-layout-header-background-color);
|
||||
// border-bottom: 1px solid var(--theme-border-color, rgba(0, 0, 0, 0.07));
|
||||
// padding: 0 24px;
|
||||
|
||||
.adf-breadcrumb-item {
|
||||
font-size: 20px !important;
|
||||
font-weight: 400 !important;
|
||||
letter-spacing: 0.15px !important;
|
||||
}
|
||||
|
||||
.app-search-input {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.action-bar {
|
||||
display: flex;
|
||||
flex: auto;
|
||||
height: 32px;
|
||||
margin-left: 24px;
|
||||
|
||||
adf-toolbar-divider {
|
||||
width: 24px !important;
|
||||
height: 32px !important;
|
||||
margin: 4px 0 0 12px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.aca-mat-button {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
letter-spacing: 0.25px;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.aca-create-button {
|
||||
width: 71px !important;
|
||||
min-width: 71px;
|
||||
height: 32px;
|
||||
background-color: var(--theme-create-button-background-color);
|
||||
color: var(--theme-create-button-text-color);
|
||||
text-overflow: ellipsis;
|
||||
display: flex;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.aca-upload-button {
|
||||
width: 73px !important;
|
||||
min-width: 73px;
|
||||
height: 32px;
|
||||
background-color: var(--theme-upload-button-background-color);
|
||||
color: var(--theme-upload-button-text-color);
|
||||
text-overflow: ellipsis;
|
||||
display: flex;
|
||||
padding: 0;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
// .aca-process-button {
|
||||
// width: 130px !important;
|
||||
// min-width: 130px;
|
||||
// height: 32px;
|
||||
// background-color: var(--theme-upload-button-background-color);
|
||||
// color: var(--theme-upload-button-text-color);
|
||||
// text-overflow: ellipsis;
|
||||
// display: flex;
|
||||
// padding: 0;
|
||||
// margin-left: 12px;
|
||||
// }
|
||||
}
|
@@ -0,0 +1,109 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { HeaderActionsComponent } from './header-actions.component';
|
||||
import { HarnessLoader } from '@angular/cdk/testing';
|
||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||
import { MatButtonHarness } from '@angular/material/button/testing';
|
||||
import { MatMenuHarness } from '@angular/material/menu/testing';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
describe('HeaderActionsComponent', () => {
|
||||
let component: HeaderActionsComponent;
|
||||
let fixture: ComponentFixture<HeaderActionsComponent>;
|
||||
let loader: HarnessLoader;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [AppTestingModule, NoopAnimationsModule, MatButtonModule, MatMenuModule],
|
||||
declarations: [HeaderActionsComponent]
|
||||
});
|
||||
|
||||
fixture = TestBed.createComponent(HeaderActionsComponent);
|
||||
component = fixture.componentInstance;
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
});
|
||||
|
||||
it('total number of buttons in header should be 2 if route is personal-files', async () => {
|
||||
spyOn(component, 'isPersonalFilesRoute').and.returnValue(true);
|
||||
const buttons = await loader.getAllHarnesses(MatButtonHarness);
|
||||
const createButton = await loader.getAllHarnesses(MatButtonHarness.with({text: 'APP.HEADER.BUTTONS.CREATE'}));
|
||||
const uploadButton = await loader.getAllHarnesses(MatButtonHarness.with({text: 'APP.HEADER.BUTTONS.UPLOAD'}));
|
||||
|
||||
expect(buttons.length).toBe(2);
|
||||
expect(createButton.length).toBe(1);
|
||||
expect(uploadButton.length).toBe(1);
|
||||
});
|
||||
|
||||
it('total number of buttons in header should be 1 if route is libraries', async () => {
|
||||
spyOn(component, 'isLibrariesRoute').and.returnValue(true);
|
||||
const buttons = await loader.getAllHarnesses(MatButtonHarness);
|
||||
const createButton = await loader.getAllHarnesses(MatButtonHarness.with({text: 'APP.HEADER.BUTTONS.CREATE'}));
|
||||
|
||||
expect(buttons.length).toBe(1);
|
||||
expect(createButton.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should open and close the create menu', async () => {
|
||||
spyOn(component, 'isPersonalFilesRoute').and.returnValue(true);
|
||||
const createMenu = await loader.getHarness(MatMenuHarness.with({ triggerText: 'APP.HEADER.BUTTONS.CREATE' }));
|
||||
|
||||
expect(await createMenu.isOpen()).toBe(false);
|
||||
await createMenu.open();
|
||||
expect(await createMenu.isOpen()).toBe(true);
|
||||
|
||||
await createMenu.close();
|
||||
expect(await createMenu.isOpen()).toBe(false);
|
||||
});
|
||||
|
||||
it('should open and close the upload menu', async () => {
|
||||
spyOn(component, 'isPersonalFilesRoute').and.returnValue(true);
|
||||
const uploadMenu = await loader.getHarness(MatMenuHarness.with({ triggerText: 'APP.HEADER.BUTTONS.UPLOAD' }));
|
||||
|
||||
expect(await uploadMenu.isOpen()).toBe(false);
|
||||
await uploadMenu.open();
|
||||
expect(await uploadMenu.isOpen()).toBe(true);
|
||||
|
||||
await uploadMenu.close();
|
||||
expect(await uploadMenu.isOpen()).toBe(false);
|
||||
});
|
||||
|
||||
it('should load create menu on click of create button', async () => {
|
||||
spyOn(component, 'isPersonalFilesRoute').and.returnValue(true);
|
||||
|
||||
const buttons = await loader.getHarness(MatButtonHarness.with({ selector: '.aca-create-button' }));
|
||||
buttons.click();
|
||||
|
||||
const createMenu = fixture.debugElement.queryAll(By.css('.app-create-menu__root-menu app-create-menu__sub-menu'));
|
||||
expect(createMenu).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should load upload menu on click of upload button', async () => {
|
||||
spyOn(component, 'isPersonalFilesRoute').and.returnValue(true);
|
||||
|
||||
const buttons = await loader.getHarness(MatButtonHarness.with({ selector: '.aca-upload-button' }));
|
||||
buttons.click();
|
||||
|
||||
const uploadMenu = fixture.debugElement.queryAll(By.css('.app-upload-menu__root-menu app-upload-menu__sub-menu'));
|
||||
expect(uploadMenu).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,96 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
*
|
||||
* This file is part of the Alfresco Example Content Application.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { ContentManagementService } from '../../services/content-management.service';
|
||||
import { AppExtensionService, PageComponent } from '@alfresco/aca-shared';
|
||||
import { SetCurrentFolderAction, AppStore } from '@alfresco/aca-shared/store';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-header-actions',
|
||||
templateUrl: './header-actions.component.html',
|
||||
styleUrls: ['./header-actions.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class HeaderActionsComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
constructor(private router: Router, store: Store<AppStore>, content: ContentManagementService, extensions: AppExtensionService) {
|
||||
super(store, extensions, content);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.store.dispatch(new SetCurrentFolderAction(null));
|
||||
super.ngOnDestroy();
|
||||
}
|
||||
|
||||
isPersonalFilesRoute(): boolean {
|
||||
return this.router.url.includes('/personal-files');
|
||||
}
|
||||
|
||||
isFavoriteLibrariesRoute(): boolean {
|
||||
return this.router.url.includes('/favorite/libraries');
|
||||
}
|
||||
|
||||
isLibrariesRoute(): boolean {
|
||||
return this.router.url.includes('/libraries');
|
||||
}
|
||||
|
||||
canShowCreateButton(): boolean {
|
||||
if (this.isPersonalFilesRoute() || this.isFavoriteLibrariesRoute() || this.isLibrariesRoute()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
canShowUploadButton(): boolean {
|
||||
if (this.isPersonalFilesRoute()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
canShowSearchSeparator(): boolean {
|
||||
if (this.isPersonalFilesRoute() || this.isFavoriteLibrariesRoute() || this.isLibrariesRoute()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
isTasksRoute(): boolean {
|
||||
return this.router.url.includes('/tasks');
|
||||
}
|
||||
|
||||
isProcessesRoute(): boolean {
|
||||
return this.router.url.includes('/processes');
|
||||
}
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
*
|
||||
* This file is part of the Alfresco Example Content Application.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CoreModule } from '@alfresco/adf-core';
|
||||
import { ContentModule } from '@alfresco/adf-content-services';
|
||||
import { AppCommonModule } from '../common/common.module';
|
||||
import { AppToolbarModule } from '../toolbar/toolbar.module';
|
||||
import { DirectivesModule } from '../../directives/directives.module';
|
||||
import { ContextMenuModule } from '../context-menu/context-menu.module';
|
||||
import { AppLayoutModule } from '../layout/layout.module';
|
||||
import { AppSearchInputModule } from '../search/search-input.module';
|
||||
import { HeaderActionsComponent } from './header-actions.component';
|
||||
import { MainActionModule } from '../main-action/main-action.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
CoreModule.forChild(),
|
||||
ContentModule.forChild(),
|
||||
DirectivesModule,
|
||||
AppCommonModule,
|
||||
AppToolbarModule,
|
||||
ContextMenuModule,
|
||||
AppLayoutModule,
|
||||
AppSearchInputModule,
|
||||
MainActionModule
|
||||
],
|
||||
declarations: [HeaderActionsComponent],
|
||||
exports: [HeaderActionsComponent]
|
||||
})
|
||||
export class AppHeaderActionsModule {}
|
@@ -1,7 +1,7 @@
|
||||
<aca-page-layout>
|
||||
<aca-page-layout-header>
|
||||
<adf-breadcrumb root="APP.BROWSE.LIBRARIES.MENU.MY_LIBRARIES.TITLE"> </adf-breadcrumb>
|
||||
|
||||
<aca-header-actions></aca-header-actions>
|
||||
<adf-toolbar class="adf-toolbar--inline">
|
||||
<ng-container *ngFor="let entry of actions; trackBy: trackByActionId">
|
||||
<aca-toolbar-action [actionRef]="entry"></aca-toolbar-action>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<aca-page-layout>
|
||||
<aca-page-layout-header>
|
||||
<adf-breadcrumb root="APP.BROWSE.RECENT.TITLE"> </adf-breadcrumb>
|
||||
|
||||
<aca-header-actions></aca-header-actions>
|
||||
<adf-toolbar class="adf-toolbar--inline">
|
||||
<ng-container *ngFor="let entry of actions; trackBy: trackByActionId">
|
||||
<aca-toolbar-action [actionRef]="entry"></aca-toolbar-action>
|
||||
|
@@ -6,6 +6,7 @@ $top-margin: 12px;
|
||||
font-size: 16px;
|
||||
padding-left: 15px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 12px !important;
|
||||
|
||||
.mat-form-field {
|
||||
font-size: 16px;
|
||||
|
@@ -0,0 +1,66 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
*
|
||||
* This file is part of the Alfresco Example Content Application.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { CoreModule } from '@alfresco/adf-core';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { SearchInputService } from './search-input.service';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
describe('SearchInputService', () => {
|
||||
let service: SearchInputService;
|
||||
let router: Router;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot(), CoreModule.forRoot()]
|
||||
});
|
||||
service = TestBed.inject(SearchInputService);
|
||||
router = TestBed.inject(Router);
|
||||
});
|
||||
|
||||
it('should not navigate to saved route when exitSearch function is called if saved route is null', () => {
|
||||
const routerNavigate = spyOn(router, 'navigate');
|
||||
service.savedRoute = '';
|
||||
service.exitSearch();
|
||||
|
||||
expect(routerNavigate).not.toHaveBeenCalledWith([service.savedRoute]);
|
||||
});
|
||||
|
||||
it('should navigate to saved route when exitSearch function is called', () => {
|
||||
const routerNavigate = spyOn(router, 'navigate');
|
||||
service.savedRoute = '/personal-files';
|
||||
service.exitSearch();
|
||||
|
||||
expect(routerNavigate).toHaveBeenCalledWith([service.savedRoute]);
|
||||
});
|
||||
|
||||
it('should navigate to Search when navigateToSearch function is called', () => {
|
||||
const routerNavigate = spyOn(router, 'navigate');
|
||||
service.navigateToSearch();
|
||||
|
||||
expect(routerNavigate).toHaveBeenCalledWith(['/search']);
|
||||
});
|
||||
});
|
@@ -0,0 +1,55 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
*
|
||||
* This file is part of the Alfresco Example Content Application.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SearchInputService {
|
||||
savedRoute = '';
|
||||
|
||||
constructor(private router: Router) {}
|
||||
|
||||
isSearchRoute(): boolean {
|
||||
return this.router.url.includes('/search');
|
||||
}
|
||||
|
||||
saveRoute(route: string) {
|
||||
this.savedRoute = route;
|
||||
}
|
||||
|
||||
exitSearch() {
|
||||
if (this.savedRoute.length > 0) {
|
||||
this.router.navigate([this.savedRoute]);
|
||||
}
|
||||
}
|
||||
|
||||
navigateToSearch() {
|
||||
this.saveRoute(this.router.url);
|
||||
this.router.navigate(['/search']);
|
||||
}
|
||||
}
|
@@ -1,13 +1,14 @@
|
||||
<div
|
||||
<div *ngIf="searchInputService.isSearchRoute()"
|
||||
class="app-search-container searchMenuTrigger"
|
||||
[matMenuTriggerFor]="searchOptionsMenu"
|
||||
(menuOpened)="onMenuOpened()"
|
||||
(menuClosed)="syncInputValues()"
|
||||
>
|
||||
|
||||
<button mat-icon-button class="app-search-button" (click)="searchByOption()" [title]="'SEARCH.BUTTON.TOOLTIP' | translate">
|
||||
<mat-icon [attr.aria-label]="'SEARCH.BUTTON.ARIA-LABEL' | translate">search</mat-icon>
|
||||
</button>
|
||||
<mat-form-field class="app-input-form-field" [floatLabel]="'never'">
|
||||
<mat-form-field class="app-input-form-field" [floatLabel]="'never'">
|
||||
<input
|
||||
matInput
|
||||
[attr.aria-label]="'SEARCH.INPUT.ARIA-LABEL' | translate"
|
||||
@@ -20,9 +21,20 @@
|
||||
<div matSuffix class="app-suffix-search-icon-wrapper">
|
||||
<mat-icon>arrow_drop_down</mat-icon>
|
||||
</div>
|
||||
|
||||
<button mat-icon-button matSuffix class="app-suffix-search-icon-wrapper app-close-icon" (click)="exitSearch()" (keypressk)="exitSearch()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!searchInputService.isSearchRoute()"
|
||||
class="app-search-container">
|
||||
<button mat-icon-button class="app-search-button" (click)="navigateToSearch()" [title]="'SEARCH.BUTTON.TOOLTIP' | translate">
|
||||
<mat-icon [attr.aria-label]="'SEARCH.BUTTON.ARIA-LABEL' | translate">search</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<mat-menu #searchOptionsMenu="matMenu" [overlapTrigger]="true" class="app-search-options-menu">
|
||||
<div (keydown.tab)="$event.stopPropagation()" (keydown.shift.tab)="$event.stopPropagation()">
|
||||
<div cdkTrapFocus>
|
||||
|
@@ -1,13 +1,33 @@
|
||||
$search-width: 594px;
|
||||
$search-height: 40px;
|
||||
$search-height: 32px;
|
||||
$search-background: #f5f6f5;
|
||||
$search-border-radius: 4px;
|
||||
$top-margin: 12px;
|
||||
|
||||
.app-search-container {
|
||||
color: var(--theme-foreground-text-color);
|
||||
max-width: 100%;
|
||||
margin: 0 !important;
|
||||
|
||||
.app-search-button {
|
||||
width: 32px !important;
|
||||
height: 32px !important;
|
||||
margin-left: 0 !important;
|
||||
padding-left: 0 !important;
|
||||
margin-top: -4px !important;
|
||||
}
|
||||
|
||||
.app-input-form-field {
|
||||
|
||||
.app-close-icon {
|
||||
height: 6px;
|
||||
|
||||
.mat-icon {
|
||||
font-size: 18px !important;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-input-element {
|
||||
caret-color: var(--theme-text-color);
|
||||
|
||||
@@ -54,6 +74,8 @@ mat-checkbox {
|
||||
background-color: $search-background;
|
||||
border-radius: $search-border-radius;
|
||||
height: $search-height;
|
||||
margin-bottom: 0 !important;
|
||||
padding-bottom: 26px !important;
|
||||
}
|
||||
|
||||
.app-search-container {
|
||||
|
@@ -32,12 +32,14 @@ import { SearchByTermAction, SearchActionTypes, SnackbarErrorAction, SnackbarAct
|
||||
import { AppHookService } from '@alfresco/aca-shared';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { SearchQueryBuilderService } from '@alfresco/adf-content-services';
|
||||
import { SearchInputService } from '../search-input.service';
|
||||
|
||||
describe('SearchInputComponent', () => {
|
||||
let fixture: ComponentFixture<SearchInputComponent>;
|
||||
let component: SearchInputComponent;
|
||||
let actions$: Actions;
|
||||
let appHookService: AppHookService;
|
||||
let searchInputService: SearchInputService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
@@ -50,12 +52,21 @@ describe('SearchInputComponent', () => {
|
||||
actions$ = TestBed.inject(Actions);
|
||||
fixture = TestBed.createComponent(SearchInputComponent);
|
||||
appHookService = TestBed.inject(AppHookService);
|
||||
searchInputService = TestBed.inject(SearchInputService);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should change flag on library400Error event', () => {
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should change flag on library400Error event', async () => {
|
||||
spyOn(searchInputService, 'isSearchRoute').and.returnValue(true);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(component.has400LibraryError).toBe(false);
|
||||
|
||||
appHookService.library400Error.next();
|
||||
|
||||
expect(component.has400LibraryError).toBe(true);
|
||||
@@ -65,9 +76,14 @@ describe('SearchInputComponent', () => {
|
||||
expect(component.hasLibraryConstraint()).toBe(false);
|
||||
});
|
||||
|
||||
it('should have library constraint on 400 error received', () => {
|
||||
it('should have library constraint on 400 error received', async () => {
|
||||
spyOn(searchInputService, 'isSearchRoute').and.returnValue(true);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
const libItem = component.searchOptions.find((item) => item.key.toLowerCase().indexOf('libraries') > 0);
|
||||
libItem.value = true;
|
||||
|
||||
appHookService.library400Error.next();
|
||||
|
||||
expect(component.hasLibraryConstraint()).toBe(true);
|
||||
@@ -193,4 +209,44 @@ describe('SearchInputComponent', () => {
|
||||
expect(component.isContentChecked()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('navigateToSearch()', () => {
|
||||
it('should navigate to search on click of search icon', async () => {
|
||||
spyOn(searchInputService, 'isSearchRoute').and.returnValue(false);
|
||||
spyOn(component, 'navigateToSearch').and.callThrough();
|
||||
spyOn(searchInputService, 'navigateToSearch').and.callThrough();
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
const searchIcon = fixture.debugElement.nativeElement.querySelector('.app-search-button');
|
||||
searchIcon.click();
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(component.navigateToSearch).toHaveBeenCalled();
|
||||
expect(searchInputService.navigateToSearch).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('exitSearch()', () => {
|
||||
it('should exit search on click of close icon', async () => {
|
||||
spyOn(searchInputService, 'isSearchRoute').and.returnValue(true);
|
||||
spyOn(component, 'exitSearch').and.callThrough();
|
||||
spyOn(searchInputService, 'exitSearch').and.callThrough();
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
const closeIcon = fixture.debugElement.nativeElement.querySelector('.app-close-icon');
|
||||
closeIcon.click();
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(component.exitSearch).toHaveBeenCalled();
|
||||
expect(searchInputService.exitSearch).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -34,6 +34,7 @@ import { Store } from '@ngrx/store';
|
||||
import { Subject } from 'rxjs';
|
||||
import { filter, takeUntil } from 'rxjs/operators';
|
||||
import { SearchInputControlComponent } from '../search-input-control/search-input-control.component';
|
||||
import { SearchInputService } from '../search-input.service';
|
||||
import { SearchLibrariesQueryBuilderService } from '../search-libraries-results/search-libraries-query-builder.service';
|
||||
|
||||
@Component({
|
||||
@@ -85,26 +86,37 @@ export class SearchInputComponent implements OnInit, OnDestroy {
|
||||
private config: AppConfigService,
|
||||
private router: Router,
|
||||
private store: Store<AppStore>,
|
||||
private appHookService: AppHookService
|
||||
private appHookService: AppHookService,
|
||||
public searchInputService: SearchInputService
|
||||
) {
|
||||
this.searchOnChange = this.config.get<boolean>('search.aca:triggeredOnChange', true);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.showInputValue();
|
||||
if (this.searchInputService.isSearchRoute()) {
|
||||
this.showInputValue();
|
||||
|
||||
this.router.events
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.pipe(filter((e) => e instanceof RouterEvent))
|
||||
.subscribe((event) => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
this.showInputValue();
|
||||
}
|
||||
this.router.events
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.pipe(filter((e) => e instanceof RouterEvent))
|
||||
.subscribe((event) => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
this.showInputValue();
|
||||
}
|
||||
});
|
||||
|
||||
this.appHookService.library400Error.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
||||
this.has400LibraryError = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.appHookService.library400Error.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
||||
this.has400LibraryError = true;
|
||||
});
|
||||
navigateToSearch() {
|
||||
this.searchInputService.navigateToSearch();
|
||||
}
|
||||
|
||||
exitSearch() {
|
||||
this.searchInputService.exitSearch();
|
||||
}
|
||||
|
||||
showInputValue() {
|
||||
@@ -140,7 +152,6 @@ export class SearchInputComponent implements OnInit, OnDestroy {
|
||||
} else {
|
||||
this.store.dispatch(new SnackbarErrorAction('APP.BROWSE.SEARCH.EMPTY_SEARCH'));
|
||||
}
|
||||
this.trigger.closeMenu();
|
||||
}
|
||||
|
||||
onSearchChange(searchTerm: string) {
|
||||
|
@@ -39,6 +39,8 @@ import { AppLayoutModule } from '../layout/layout.module';
|
||||
import { ContextMenuModule } from '../context-menu/context-menu.module';
|
||||
import { SearchActionMenuComponent } from './search-action-menu/search-action-menu.component';
|
||||
import { DocumentListCustomComponentsModule } from '../dl-custom-components/document-list-custom-components.module';
|
||||
import { AppSearchInputModule } from './search-input.module';
|
||||
import { AppHeaderActionsModule } from '../header-actions/header-actions.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -52,7 +54,9 @@ import { DocumentListCustomComponentsModule } from '../dl-custom-components/docu
|
||||
AppLayoutModule,
|
||||
ContextMenuModule,
|
||||
LockedByModule,
|
||||
DocumentListCustomComponentsModule
|
||||
DocumentListCustomComponentsModule,
|
||||
AppSearchInputModule,
|
||||
AppHeaderActionsModule
|
||||
],
|
||||
declarations: [SearchResultsComponent, SearchLibrariesResultsComponent, SearchResultsRowComponent, SearchActionMenuComponent],
|
||||
exports: [SearchResultsComponent, SearchLibrariesResultsComponent, SearchResultsRowComponent, SearchActionMenuComponent]
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<aca-page-layout>
|
||||
<aca-page-layout-header>
|
||||
<adf-breadcrumb root="APP.BROWSE.SEARCH.TITLE"> </adf-breadcrumb>
|
||||
<adf-toolbar class="adf-toolbar--inline">
|
||||
<aca-search-input></aca-search-input>
|
||||
<adf-toolbar class="adf-toolbar--inline adf-toolbar-search-results">
|
||||
<ng-container *ngFor="let entry of actions; trackBy: trackByActionId">
|
||||
<aca-toolbar-action [actionRef]="entry"></aca-toolbar-action>
|
||||
</ng-container>
|
||||
|
@@ -3,6 +3,13 @@
|
||||
$adf-chip-background: #efefef;
|
||||
$contrast-gray: #646569;
|
||||
|
||||
.adf-toolbar-search-results {
|
||||
position: fixed;
|
||||
right: 24px;
|
||||
height: 32px;
|
||||
margin-bottom: 32px !important;
|
||||
}
|
||||
|
||||
.adf-search-results {
|
||||
@include flex-row;
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<aca-page-layout>
|
||||
<aca-page-layout-header>
|
||||
<adf-breadcrumb root="APP.BROWSE.SHARED.TITLE"></adf-breadcrumb>
|
||||
|
||||
<aca-header-actions></aca-header-actions>
|
||||
<adf-toolbar class="adf-toolbar--inline">
|
||||
<ng-container *ngFor="let entry of actions; trackBy: trackByActionId">
|
||||
<aca-toolbar-action [actionRef]="entry"></aca-toolbar-action>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<aca-page-layout>
|
||||
<aca-page-layout-header>
|
||||
<adf-breadcrumb root="APP.BROWSE.TRASHCAN.TITLE"> </adf-breadcrumb>
|
||||
|
||||
<aca-header-actions></aca-header-actions>
|
||||
<adf-toolbar class="adf-toolbar--inline">
|
||||
<ng-container *ngFor="let entry of actions; trackBy: trackByActionId">
|
||||
<aca-toolbar-action [actionRef]="entry"></aca-toolbar-action>
|
||||
|
@@ -33,6 +33,8 @@ import { AppToolbarModule } from '../toolbar/toolbar.module';
|
||||
import { DirectivesModule } from '../../directives/directives.module';
|
||||
import { ContextMenuModule } from '../context-menu/context-menu.module';
|
||||
import { AppLayoutModule } from '../layout/layout.module';
|
||||
import { AppSearchInputModule } from '../search/search-input.module';
|
||||
import { AppHeaderActionsModule } from '../header-actions/header-actions.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -43,7 +45,9 @@ import { AppLayoutModule } from '../layout/layout.module';
|
||||
AppCommonModule,
|
||||
AppToolbarModule,
|
||||
ContextMenuModule,
|
||||
AppLayoutModule
|
||||
AppLayoutModule,
|
||||
AppSearchInputModule,
|
||||
AppHeaderActionsModule
|
||||
],
|
||||
declarations: [TrashcanComponent],
|
||||
exports: [TrashcanComponent]
|
||||
|
@@ -51,6 +51,9 @@ $selected-text-color: #212121;
|
||||
$selected-background-color: rgba(31, 116, 219, 0.24);
|
||||
$action-button-text-color: rgba(33, 35, 40, 0.7);
|
||||
$tooltip-background-color: #ffffff;
|
||||
$create-button-text-color: #212121;
|
||||
$upload-button-background-color: #2A7DE1;
|
||||
$page-layout-header-background-color: #ffffff;
|
||||
|
||||
$defaults: (
|
||||
--theme-primary-color: mat.get-color-from-palette($primary),
|
||||
@@ -95,6 +98,11 @@ $defaults: (
|
||||
--theme-action-button-text-color: $action-button-text-color,
|
||||
--theme-header-border-color: $grey-background,
|
||||
--theme-tooltip-background-color: $tooltip-background-color,
|
||||
--theme-page-layout-header-background-color: $page-layout-header-background-color,
|
||||
--theme-create-button-background-color: $grey-text-background,
|
||||
--theme-create-button-text-color: $create-button-text-color,
|
||||
--theme-upload-button-background-color: $upload-button-background-color,
|
||||
--theme-upload-button-text-color: $pagination-background-color,
|
||||
);
|
||||
|
||||
// propagates SCSS variables into the CSS variables scope
|
||||
|
@@ -25,7 +25,7 @@
|
||||
|
||||
import { DocumentListComponent, ShareDataRow } from '@alfresco/adf-content-services';
|
||||
import { ShowHeaderMode } from '@alfresco/adf-core';
|
||||
import { ContentActionRef, DocumentListPresetRef, SelectionState } from '@alfresco/adf-extensions';
|
||||
import { ContentActionRef, ContentActionType, DocumentListPresetRef, SelectionState } from '@alfresco/adf-extensions';
|
||||
import { OnDestroy, OnInit, OnChanges, ViewChild, SimpleChanges, Directive } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity, NodePaging } from '@alfresco/js-api';
|
||||
@@ -68,12 +68,32 @@ export abstract class PageComponent implements OnInit, OnDestroy, OnChanges {
|
||||
nodeResult: NodePaging;
|
||||
showHeader = ShowHeaderMode.Data;
|
||||
filterSorting = 'name-asc';
|
||||
createActions: Array<ContentActionRef> = [];
|
||||
uploadActions: Array<ContentActionRef> = [];
|
||||
mainAction$: Observable<ContentActionRef>;
|
||||
actionTypes = ContentActionType;
|
||||
|
||||
protected subscriptions: Subscription[] = [];
|
||||
|
||||
protected constructor(protected store: Store<AppStore>, protected extensions: AppExtensionService, protected content: DocumentBasePageService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.mainAction$ = this.extensions.getMainAction().pipe(takeUntil(this.onDestroy$));
|
||||
|
||||
this.extensions
|
||||
.getCreateActions()
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((actions) => {
|
||||
this.createActions = actions;
|
||||
});
|
||||
|
||||
this.extensions
|
||||
.getUploadActions()
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((actions) => {
|
||||
this.uploadActions = actions;
|
||||
});
|
||||
|
||||
this.sharedPreviewUrl$ = this.store.select(getSharedUrl);
|
||||
this.infoDrawerOpened$ = this.store.select(isInfoDrawerOpened).pipe(map((infoDrawerState) => !this.isOutletPreviewUrl() && infoDrawerState));
|
||||
|
||||
@@ -124,6 +144,10 @@ export abstract class PageComponent implements OnInit, OnDestroy, OnChanges {
|
||||
this.store.dispatch(new SetSelectedNodesAction([]));
|
||||
}
|
||||
|
||||
runAction(action: string): void {
|
||||
this.extensions.runActionById(action);
|
||||
}
|
||||
|
||||
showPreview(node: MinimalNodeEntity, extras?: ViewNodeExtras) {
|
||||
if (node && node.entry) {
|
||||
let id: string;
|
||||
|
@@ -7,8 +7,8 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 0 0 65px;
|
||||
flex-basis: 48px;
|
||||
background: var(--theme-background-color);
|
||||
flex-basis: 96px;
|
||||
background: var(--theme-page-layout-header-background-color);
|
||||
border-bottom: 1px solid var(--theme-border-color, rgba(0, 0, 0, 0.07));
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
@@ -79,6 +79,7 @@ export class AppExtensionService implements RuleContext {
|
||||
private _contextMenuActions = new BehaviorSubject<Array<ContentActionRef>>([]);
|
||||
private _openWithActions = new BehaviorSubject<Array<ContentActionRef>>([]);
|
||||
private _createActions = new BehaviorSubject<Array<ContentActionRef>>([]);
|
||||
private _uploadActions = new BehaviorSubject<Array<ContentActionRef>>([]);
|
||||
private _mainActions = new BehaviorSubject<ContentActionRef>(null);
|
||||
private _sidebarActions = new BehaviorSubject<Array<ContentActionRef>>([]);
|
||||
|
||||
@@ -158,6 +159,7 @@ export class AppExtensionService implements RuleContext {
|
||||
this._contextMenuActions.next(this.loader.getContentActions(config, 'features.contextMenu'));
|
||||
this._openWithActions.next(this.loader.getContentActions(config, 'features.viewer.openWith'));
|
||||
this._createActions.next(this.loader.getElements<ContentActionRef>(config, 'features.create'));
|
||||
this._uploadActions.next(this.loader.getElements<ContentActionRef>(config, 'features.upload'));
|
||||
this._mainActions.next(this.loader.getFeatures(config).mainAction);
|
||||
|
||||
this.navbar = this.loadNavBar(config);
|
||||
@@ -366,6 +368,18 @@ export class AppExtensionService implements RuleContext {
|
||||
);
|
||||
}
|
||||
|
||||
getUploadActions(): Observable<Array<ContentActionRef>> {
|
||||
return this._uploadActions.pipe(
|
||||
map((uploadActions) =>
|
||||
uploadActions
|
||||
.filter((action) => this.filterVisible(action))
|
||||
.map((action) => this.copyAction(action))
|
||||
.map((action) => this.buildMenu(action))
|
||||
.map((action) => this.setActionDisabledFromRule(action))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getMainAction(): Observable<ContentActionRef> {
|
||||
return this._mainActions.pipe(
|
||||
filter((mainAction) => mainAction && this.filterVisible(mainAction)),
|
||||
|
Reference in New Issue
Block a user