mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-31 17:38:28 +00:00
[ACA-1379] Search Results Actions and Bulk Actions (#406)
* download actions and effects * download multiple search results * remove inline toolbar * base page and toolbar for the Search results * toolbar actions * update search settings * toggle favorites from search results * manage versions dialog * folder navigation * sidebar integration * remove obsolete style
This commit is contained in:
@@ -2,6 +2,65 @@
|
||||
<div class="inner-layout__header">
|
||||
<adf-breadcrumb root="APP.BROWSE.SEARCH.TITLE">
|
||||
</adf-breadcrumb>
|
||||
<adf-toolbar class="inline" *ngIf="hasSelection">
|
||||
<button
|
||||
color="primary"
|
||||
mat-icon-button
|
||||
*ngIf="selectedFile"
|
||||
title="{{ 'APP.ACTIONS.VIEW' | translate }}"
|
||||
(click)="showPreview(selectedFile)">
|
||||
<mat-icon>open_in_browser</mat-icon>
|
||||
</button>
|
||||
|
||||
<button
|
||||
color="primary"
|
||||
mat-icon-button
|
||||
title="{{ 'APP.ACTIONS.DOWNLOAD' | translate }}"
|
||||
[acaDownloadNodes]="selectedNodes">
|
||||
<mat-icon>get_app</mat-icon>
|
||||
</button>
|
||||
|
||||
<button mat-icon-button
|
||||
[color]="infoDrawerOpened ? 'accent' : 'primary'"
|
||||
title="{{ 'APP.ACTIONS.DETAILS' | translate }}"
|
||||
(click)="toggleSidebar()">
|
||||
<mat-icon>info_outline</mat-icon>
|
||||
</button>
|
||||
|
||||
<button
|
||||
color="primary"
|
||||
mat-icon-button
|
||||
title="{{ 'APP.ACTIONS.MORE' | translate }}"
|
||||
[matMenuTriggerFor]="actionsMenu">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
|
||||
<mat-menu #actionsMenu="matMenu" [overlapTrigger]="false">
|
||||
<button
|
||||
mat-menu-item
|
||||
#selection="adfFavorite"
|
||||
[adf-node-favorite]="selectedNodes">
|
||||
<mat-icon color="primary" *ngIf="selection.hasFavorites()">star</mat-icon>
|
||||
<mat-icon *ngIf="!selection.hasFavorites()">star_border</mat-icon>
|
||||
<span>{{ 'APP.ACTIONS.FAVORITE' | translate }}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
mat-menu-item
|
||||
[acaCopyNode]="selectedNodes">
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
<span>{{ 'APP.ACTIONS.COPY' | translate }}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
mat-menu-item
|
||||
*ngIf="selectedFile"
|
||||
[acaNodeVersions]="selectedFile">
|
||||
<mat-icon>history</mat-icon>
|
||||
<span>{{ 'APP.ACTIONS.VERSIONS' | translate }}</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
</adf-toolbar>
|
||||
</div>
|
||||
|
||||
<div class="adf-search-results__facets">
|
||||
@@ -11,77 +70,87 @@
|
||||
<div class="inner-layout__content">
|
||||
<adf-search
|
||||
#search
|
||||
[searchTerm]="searchedWord"
|
||||
[maxResults]="maxItems"
|
||||
[skipResults]="skipCount"
|
||||
(resultLoaded)="onSearchResultLoaded($event)">
|
||||
</adf-search>
|
||||
|
||||
<div class="adf-search-results">
|
||||
<adf-search-filter #searchFilter></adf-search-filter>
|
||||
<div class="inner-layout__panel">
|
||||
<div class="adf-search-results">
|
||||
<adf-search-filter #searchFilter></adf-search-filter>
|
||||
|
||||
<div class="adf-search-results__content">
|
||||
<div class="adf-search-results__content-header" *ngIf="data?.list.entries.length">
|
||||
<div class="adf-search-results--info-text">{{ 'APP.BROWSE.SEARCH.FOUND_RESULTS' | translate: { number: totalResults } }}</div>
|
||||
<adf-search-sorting-picker></adf-search-sorting-picker>
|
||||
<div class="adf-search-results__content">
|
||||
<div class="adf-search-results__content-header" *ngIf="data?.list.entries.length">
|
||||
<div class="adf-search-results--info-text">{{ 'APP.BROWSE.SEARCH.FOUND_RESULTS' | translate: { number: totalResults } }}</div>
|
||||
<adf-search-sorting-picker></adf-search-sorting-picker>
|
||||
</div>
|
||||
|
||||
<adf-document-list
|
||||
#documentList
|
||||
[showHeader]="false"
|
||||
[selectionMode]="'multiple'"
|
||||
[sortingMode]="'server'"
|
||||
[sorting]="sorting"
|
||||
[node]="data"
|
||||
(node-dblclick)="onNodeDoubleClick($event.detail?.node?.entry)"
|
||||
(ready)="onDocumentListReady($event, documentList)"
|
||||
(node-select)="onNodeSelect($event, documentList)"
|
||||
(node-unselect)="onNodeUnselect($event, documentList)">
|
||||
|
||||
<data-columns>
|
||||
<data-column
|
||||
[key]="'$thumbnail'"
|
||||
[type]="'image'"
|
||||
[sr-title]="'ADF-DOCUMENT-LIST.LAYOUT.THUMBNAIL'"
|
||||
[sortable]="false">
|
||||
</data-column>
|
||||
<data-column
|
||||
[key]="'name'"
|
||||
[type]="'text'"
|
||||
[title]="'ADF-DOCUMENT-LIST.LAYOUT.NAME'"
|
||||
[class]="'full-width ellipsis-cell'"
|
||||
[sortable]="false">
|
||||
</data-column>
|
||||
<data-column
|
||||
[key]="'content.sizeInBytes'"
|
||||
[type]="'fileSize'"
|
||||
[title]="'ADF-DOCUMENT-LIST.LAYOUT.SIZE'"
|
||||
[sortable]="false">
|
||||
</data-column>
|
||||
<data-column
|
||||
[key]="'modifiedAt'"
|
||||
[type]="'date'"
|
||||
[title]="'ADF-DOCUMENT-LIST.LAYOUT.MODIFIED_ON'"
|
||||
[format]="'timeAgo'"
|
||||
[sortable]="false">
|
||||
</data-column>
|
||||
<data-column
|
||||
[key]="'modifiedByUser.displayName'"
|
||||
[type]="'text'"
|
||||
[title]="'ADF-DOCUMENT-LIST.LAYOUT.MODIFIED_BY'"
|
||||
[sortable]="false">
|
||||
</data-column>
|
||||
</data-columns>
|
||||
|
||||
<empty-folder-content>
|
||||
<ng-template>
|
||||
<div class="empty-search__block">
|
||||
<p class="empty-search__text">Your search returned 0 results</p>
|
||||
</div>
|
||||
</ng-template>
|
||||
</empty-folder-content>
|
||||
</adf-document-list>
|
||||
|
||||
<adf-pagination *ngIf="!documentList.isEmpty()"
|
||||
[target]="documentList"
|
||||
(change)="onPaginationChanged($event)">
|
||||
</adf-pagination>
|
||||
</div>
|
||||
|
||||
<adf-document-list
|
||||
#documentList
|
||||
[showHeader]="false"
|
||||
[sortingMode]="'server'"
|
||||
[sorting]="sorting"
|
||||
[node]="data"
|
||||
(node-dblclick)="onNodeDoubleClick($event.detail?.node?.entry)">
|
||||
|
||||
<data-columns>
|
||||
<data-column
|
||||
[key]="'$thumbnail'"
|
||||
[type]="'image'"
|
||||
[sr-title]="'ADF-DOCUMENT-LIST.LAYOUT.THUMBNAIL'"
|
||||
[sortable]="false">
|
||||
</data-column>
|
||||
<data-column
|
||||
[key]="'name'"
|
||||
[type]="'text'"
|
||||
[title]="'ADF-DOCUMENT-LIST.LAYOUT.NAME'"
|
||||
[class]="'full-width ellipsis-cell'"
|
||||
[sortable]="false">
|
||||
</data-column>
|
||||
<data-column
|
||||
[key]="'content.sizeInBytes'"
|
||||
[type]="'fileSize'"
|
||||
[title]="'ADF-DOCUMENT-LIST.LAYOUT.SIZE'"
|
||||
[sortable]="false">
|
||||
</data-column>
|
||||
<data-column
|
||||
[key]="'modifiedAt'"
|
||||
[type]="'date'"
|
||||
[title]="'ADF-DOCUMENT-LIST.LAYOUT.MODIFIED_ON'"
|
||||
[format]="'timeAgo'"
|
||||
[sortable]="false">
|
||||
</data-column>
|
||||
<data-column
|
||||
[key]="'modifiedByUser.displayName'"
|
||||
[type]="'text'"
|
||||
[title]="'ADF-DOCUMENT-LIST.LAYOUT.MODIFIED_BY'"
|
||||
[sortable]="false">
|
||||
</data-column>
|
||||
</data-columns>
|
||||
|
||||
<empty-folder-content>
|
||||
<ng-template>
|
||||
<div class="empty-search__block">
|
||||
<p class="empty-search__text">Your search returned 0 results</p>
|
||||
</div>
|
||||
</ng-template>
|
||||
</empty-folder-content>
|
||||
</adf-document-list>
|
||||
|
||||
<adf-pagination *ngIf="!documentList.isEmpty()"
|
||||
[target]="documentList"
|
||||
(change)="onPaginationChanged($event)">
|
||||
</adf-pagination>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inner-layout__side-panel" *ngIf="infoDrawerOpened">
|
||||
<aca-info-drawer [node]="lastSelectedNode"></aca-info-drawer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -23,23 +23,28 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Component, OnInit, Optional, ViewChild } from '@angular/core';
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { MinimalNodeEntryEntity, NodePaging, Pagination } from 'alfresco-js-api';
|
||||
import { Router, ActivatedRoute, Params } from '@angular/router';
|
||||
import { SearchQueryBuilderService, SearchComponent as AdfSearchComponent } from '@alfresco/adf-content-services';
|
||||
import { SearchConfigurationService } from '@alfresco/adf-core';
|
||||
import { SearchQueryBuilderService, SearchComponent as AdfSearchComponent, NodePermissionService } from '@alfresco/adf-content-services';
|
||||
import { SearchConfigurationService, UserPreferencesService, SearchService } from '@alfresco/adf-core';
|
||||
import { PageComponent } from '../page.component';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppStore } from '../../store/states/app.state';
|
||||
import { NavigateToLocationAction } from '../../store/actions';
|
||||
|
||||
@Component({
|
||||
selector: 'app-search',
|
||||
templateUrl: './search.component.html',
|
||||
styleUrls: ['./search.component.scss']
|
||||
styleUrls: ['./search.component.scss'],
|
||||
providers: [SearchService]
|
||||
})
|
||||
export class SearchComponent implements OnInit {
|
||||
export class SearchComponent extends PageComponent implements OnInit {
|
||||
|
||||
@ViewChild('search')
|
||||
search: AdfSearchComponent;
|
||||
|
||||
searchedWord: string;
|
||||
queryParamName = 'q';
|
||||
data: NodePaging;
|
||||
totalResults = 0;
|
||||
@@ -48,10 +53,15 @@ export class SearchComponent implements OnInit {
|
||||
sorting = ['name', 'asc'];
|
||||
|
||||
constructor(
|
||||
public router: Router,
|
||||
public permission: NodePermissionService,
|
||||
private queryBuilder: SearchQueryBuilderService,
|
||||
private searchConfiguration: SearchConfigurationService,
|
||||
@Optional() private route: ActivatedRoute) {
|
||||
store: Store<AppStore>,
|
||||
router: Router,
|
||||
preferences: UserPreferencesService,
|
||||
route: ActivatedRoute) {
|
||||
super(preferences, router, route, store);
|
||||
|
||||
queryBuilder.paging = {
|
||||
skipCount: 0,
|
||||
maxItems: 25
|
||||
@@ -59,6 +69,8 @@ export class SearchComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
|
||||
this.sorting = this.getSorting();
|
||||
|
||||
this.queryBuilder.updated.subscribe(() => {
|
||||
@@ -67,9 +79,9 @@ export class SearchComponent implements OnInit {
|
||||
|
||||
if (this.route) {
|
||||
this.route.params.forEach((params: Params) => {
|
||||
const searchedWord = params.hasOwnProperty(this.queryParamName) ? params[this.queryParamName] : null;
|
||||
if (searchedWord) {
|
||||
const queryBody = this.searchConfiguration.generateQueryBody(searchedWord, 0, 100);
|
||||
this.searchedWord = params.hasOwnProperty(this.queryParamName) ? params[this.queryParamName] : null;
|
||||
if (this.searchedWord) {
|
||||
const queryBody = this.searchConfiguration.generateQueryBody(this.searchedWord, 0, 100);
|
||||
|
||||
this.queryBuilder.userQuery = queryBody.query.query;
|
||||
this.queryBuilder.update();
|
||||
@@ -112,6 +124,10 @@ export class SearchComponent implements OnInit {
|
||||
}
|
||||
|
||||
onNodeDoubleClick(node: MinimalNodeEntryEntity) {
|
||||
if (node && node.isFolder) {
|
||||
this.store.dispatch(new NavigateToLocationAction(node));
|
||||
}
|
||||
|
||||
if (node && PageComponent.isLockedNode(node)) {
|
||||
event.preventDefault();
|
||||
|
||||
|
Reference in New Issue
Block a user