Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {Aggregation} from '@enonic/lib-admin-ui/aggregation/Aggregation';
import {Bucket} from '@enonic/lib-admin-ui/aggregation/Bucket';
import {BucketAggregation} from '@enonic/lib-admin-ui/aggregation/BucketAggregation';
import {AuthContext} from '@enonic/lib-admin-ui/auth/AuthContext';
import {i18n} from '@enonic/lib-admin-ui/util/Messages';
import {ContentAggregation} from './ContentAggregation';
import {GetPrincipalsByKeysRequest} from '../../security/GetPrincipalsByKeysRequest';
Expand All @@ -20,17 +21,19 @@ export class AggregationsDisplayNamesResolver {
private contentTypes: Map<string, string>;
private readonly currentUserId?: string;

constructor(currentUserId?: string) {
this.currentUserId = currentUserId;
constructor() {
this.currentUserId = AuthContext.get().getUser().getKey().toString();
}

updateAggregationsDisplayNames(aggregations: Aggregation[], userId: string): Q.Promise<void> {
updateAggregationsDisplayNames(aggregations: BucketAggregation[]): Q.Promise<void> {
this.updateWorkflowAggregations(aggregations);

const updatePromises: Q.Promise<void>[] = [];
updatePromises.push(this.updateLanguageAggregations(aggregations));
updatePromises.push(this.updateContentTypeAggregations(aggregations));

aggregations.filter((aggr) => this.isPrincipalAggregation(aggr.getName())).forEach((principalAggr: BucketAggregation) => {
updatePromises.push(this.updateUnknownPrincipals(principalAggr).then(() => this.updateKnownPrincipals(principalAggr)));
});

return Q.all(updatePromises).thenResolve(null);
}
Expand Down Expand Up @@ -142,4 +145,8 @@ export class AggregationsDisplayNamesResolver {
return this.updateContentTypeAggregation(aggregation);
});
}

private isPrincipalAggregation(name: string): boolean {
return name === ContentAggregation.OWNER.toString() || name === ContentAggregation.MODIFIED_BY.toString();
}
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
import Q from 'q';
import {i18n} from '@enonic/lib-admin-ui/util/Messages';
import {Router} from '../../Router';
import {ContentServerEventsHandler} from '../../event/ContentServerEventsHandler';
import {ContentSummaryAndCompareStatus} from '../../content/ContentSummaryAndCompareStatus';
import {ContentQuery} from '../../content/ContentQuery';
import {AggregationGroupView} from '@enonic/lib-admin-ui/aggregation/AggregationGroupView';
import {Aggregation} from '@enonic/lib-admin-ui/aggregation/Aggregation';
import {BrowseFilterPanel} from '@enonic/lib-admin-ui/app/browse/filter/BrowseFilterPanel';
import {BucketAggregation} from '@enonic/lib-admin-ui/aggregation/BucketAggregation';
import {AggregationSelection} from '@enonic/lib-admin-ui/aggregation/AggregationSelection';
import {Bucket} from '@enonic/lib-admin-ui/aggregation/Bucket';
import {BucketAggregationView} from '@enonic/lib-admin-ui/aggregation/BucketAggregationView';
import {BucketAggregation} from '@enonic/lib-admin-ui/aggregation/BucketAggregation';
import {BrowseFilterPanel} from '@enonic/lib-admin-ui/app/browse/filter/BrowseFilterPanel';
import {TextSearchField} from '@enonic/lib-admin-ui/app/browse/filter/TextSearchField';
import {AuthContext} from '@enonic/lib-admin-ui/auth/AuthContext';
import {DivEl} from '@enonic/lib-admin-ui/dom/DivEl';
import {Element} from '@enonic/lib-admin-ui/dom/Element';
import {SearchInputValues} from '@enonic/lib-admin-ui/query/SearchInputValues';
import {i18n} from '@enonic/lib-admin-ui/util/Messages';
import {cn} from '@enonic/ui';
import Q from 'q';
import {
$contentFilterState,
deselectAllFilterBuckets,
getFilterSelection,
getFilterValue,
hasFilterSet,
hasFilterValueSet,
resetContentFilter, setContentFilterSelection
} from '../../../v6/features/store/contentFilter.store';
import {ContentId} from '../../content/ContentId';
import {ContentQuery} from '../../content/ContentQuery';
import {ContentSummary} from '../../content/ContentSummary';
import {ContentSummaryAndCompareStatus} from '../../content/ContentSummaryAndCompareStatus';
import {ContentServerChangeItem} from '../../event/ContentServerChangeItem';
import {ContentServerEventsHandler} from '../../event/ContentServerEventsHandler';
import {ProjectContext} from '../../project/ProjectContext';
import {ContentSummary} from '../../content/ContentSummary';
import {ContentId} from '../../content/ContentId';
import {DependenciesSection} from './DependenciesSection';
import {ContentAggregation} from './ContentAggregation';
import {Router} from '../../Router';
import {ContentBrowseFilterComponent} from '../../ui2/filter/ContentBrowseFilterComponent';
import {Branch} from '../../versioning/Branch';
import {AggregationsDisplayNamesResolver} from './AggregationsDisplayNamesResolver';
import {ContentAggregationsFetcher} from './ContentAggregationsFetcher';
import {FilterableAggregationGroupView} from './FilterableAggregationGroupView';
import {AggregationsQueryResult} from './AggregationsQueryResult';
import {Element} from '@enonic/lib-admin-ui/dom/Element';
import {DivEl} from '@enonic/lib-admin-ui/dom/DivEl';
import {ContentExportElement} from './ContentExportElement';
import {ContentAggregation} from './ContentAggregation';
import {ContentAggregationsFetcher} from './ContentAggregationsFetcher';
import {ContentDependency} from './ContentDependency';
import {TextSearchField} from '@enonic/lib-admin-ui/app/browse/filter/TextSearchField';
import {Branch} from '../../versioning/Branch';
import {AuthContext} from '@enonic/lib-admin-ui/auth/AuthContext';
import {cn} from '@enonic/ui';
import {ContentExportElement} from './ContentExportElement';
import {DependenciesSection} from './DependenciesSection'

export class ContentBrowseFilterPanel<T extends ContentSummaryAndCompareStatus = ContentSummaryAndCompareStatus>
extends BrowseFilterPanel<T> {
Expand All @@ -41,15 +50,26 @@ export class ContentBrowseFilterPanel<T extends ContentSummaryAndCompareStatus =
private elementsContainer: Element;
private exportElement?: ContentExportElement;
private targetBranch: Branch = Branch.DRAFT;
private filterComponent: ContentBrowseFilterComponent;

constructor() {
super();

this.addClass(cn('content-browse-filter-panel bg-surface-primary text-main'));
this.addClass(cn('content-browse-filter-panel bg-surface-neutral text-main'));
this.aggregationsFetcher = this.createAggregationFetcher();
this.displayNamesResolver = new AggregationsDisplayNamesResolver();
this.dependenciesSection = new DependenciesSection();

this.filterComponent = new ContentBrowseFilterComponent({
bucketAggregations: [],
filterableAggregations: this.getFilterableAggregations(),
exportOptions: this.getExportOptions(),
});

this.appendChild(this.filterComponent);

this.handleEvents();
this.getAndUpdateAggregations();
this.initElementsAndListeners();
}

protected createAggregationFetcher(): ContentAggregationsFetcher {
Expand All @@ -72,19 +92,15 @@ export class ContentBrowseFilterPanel<T extends ContentSummaryAndCompareStatus =
});
}

protected initElementsAndListeners() {
if (this.isExportAllowed()) {
this.exportElement = new ContentExportElement().setEnabled(false).setTitle(i18n('action.export')) as ContentExportElement;
}

this.handleEvents();
}

protected handleEvents() {
this.onRendered(() => {
super.appendChild(this.elementsContainer);
});

$contentFilterState.listen(() => {
this.search();
});

this.handleEventsForDependenciesSection();
}

Expand Down Expand Up @@ -127,65 +143,39 @@ export class ContentBrowseFilterPanel<T extends ContentSummaryAndCompareStatus =
});
}

protected createHitsCountContainer(): DivEl {
const hitsCounterAndClearButtonWrapper = super.createHitsCountContainer();
if (this.exportElement) {
hitsCounterAndClearButtonWrapper.appendChild(this.exportElement);
}

return hitsCounterAndClearButtonWrapper;
}

protected getAggregationEnum(): Record<string, string> {
return ContentAggregation;
}

protected getGroupViews(): AggregationGroupView[] {
this.aggregations = new Map<string, AggregationGroupView>();

const aggregationEnum = this.getAggregationEnum();
for (let aggrEnum in aggregationEnum) {
const name: string = aggregationEnum[aggrEnum];
this.aggregations.set(name, this.createGroupView(name));
}
protected getFilterableAggregations(): { name: string; idsToKeepOnTop?: string[] }[] {
const currentUserKey = AuthContext.get().getUser().getKey().toString();

return Array.from(this.aggregations.values());
return [
{
name: ContentAggregation.OWNER.toString(),
idsToKeepOnTop: [currentUserKey]
},
{
name: ContentAggregation.MODIFIED_BY.toString(),
idsToKeepOnTop: [currentUserKey]
},
];
}

protected isPrincipalAggregation(name: string): boolean {
return name === ContentAggregation.OWNER.toString() || name === ContentAggregation.MODIFIED_BY.toString();
}
getExportOptions(): { label?: string; action: () => void } {
this.exportElement = new ContentExportElement().setEnabled(false).setTitle(i18n('action.export')) as ContentExportElement;

protected createGroupView(name: string): AggregationGroupView {
if (this.isPrincipalAggregation(name)) {
const currentUserKey = this.getCurrentUserKeyAsString();
if (!this.displayNamesResolver) {
this.displayNamesResolver = new AggregationsDisplayNamesResolver(currentUserKey);
return {
label: i18n('action.export'),
action: () => {
this.exportElement.handleExportClicked();
}
const aggregationGroupView = new FilterableAggregationGroupView(name, i18n(`field.${name}`));
aggregationGroupView.setIdsToKeepOnToTop([currentUserKey]);
aggregationGroupView.setResolver(this.displayNamesResolver);

return aggregationGroupView;
}

return new AggregationGroupView(name, i18n(`field.${name}`));
}

protected appendExtraSections() {
super.appendExtraSections();
this.dependenciesSection = new DependenciesSection();
this.appendChild(this.dependenciesSection);
};
}

protected isExportAllowed(): boolean {
// add more checks here if needed
return true;
protected isFilterableAggregation(aggregation: BucketAggregation): boolean {
return aggregation.getName() === ContentAggregation.OWNER.toString() || aggregation.getName() ===
ContentAggregation.MODIFIED_BY.toString();
}

private removeDependencyItem() {
this.dependenciesSection.reset();
this.resetConstraints();
this.search();
Router.get().back();
}
Expand All @@ -197,7 +187,6 @@ export class ContentBrowseFilterPanel<T extends ContentSummaryAndCompareStatus =
this.selectBucketByTypeOnLoad(type);
}

this.setConstraintItems(this.dependenciesSection, [item.getId()]);
this.dependenciesSection.setDependencyItem(item);
}

Expand All @@ -220,7 +209,9 @@ export class ContentBrowseFilterPanel<T extends ContentSummaryAndCompareStatus =
}

private selectContentTypeBucket(key: string): void {
(this.aggregations.get(ContentAggregation.CONTENT_TYPE).getAggregationViews()[0] as BucketAggregationView)?.selectBucketViewByKey(key);
const aggregationSelection = new AggregationSelection(ContentAggregation.CONTENT_TYPE);
aggregationSelection.setValues([new Bucket(key, 0)]);
setContentFilterSelection([aggregationSelection]);
}

searchItemById(id: ContentId): void {
Expand Down Expand Up @@ -250,6 +241,39 @@ export class ContentBrowseFilterPanel<T extends ContentSummaryAndCompareStatus =
});
}

updateAggregations(aggregations: BucketAggregation[]): void {
this.filterComponent.updateAggregations(aggregations);
}

getSearchInputValues(): SearchInputValues {
const searchInputValues: SearchInputValues = new SearchInputValues();

searchInputValues.setAggregationSelections(getFilterSelection());
searchInputValues.setTextSearchFieldValue(getFilterValue());

return searchInputValues;
}

hasFilterSet(): boolean {
return hasFilterSet();
}

hasSearchStringSet(): boolean {
return hasFilterValueSet();
}

resetControls() {
resetContentFilter();
}

deselectAll() {
deselectAllFilterBuckets();
}

updateHitsCounter(hits: number) {
this.filterComponent.updateHitsCounter(hits);
}

protected doSearch(): Q.Promise<void> {
if (!this.isFilteredOrConstrained()) {
return this.resetFacets();
Expand All @@ -276,7 +300,7 @@ export class ContentBrowseFilterPanel<T extends ContentSummaryAndCompareStatus =
this.updateHitsCounter(aggregationsQueryResult.getMetadata().getTotalHits());
this.updateExportState(aggregationsQueryResult);

return this.processAggregations(aggregationsQueryResult.getAggregations()).then(() => {
return this.processAggregations(aggregationsQueryResult.getAggregations() as BucketAggregation[]).then(() => {
return aggregationsQueryResult;
});
});
Expand All @@ -293,16 +317,20 @@ export class ContentBrowseFilterPanel<T extends ContentSummaryAndCompareStatus =
this.exportElement.setEnabled(aggregationsQueryResult.getMetadata().getTotalHits() > 0);
}

private processAggregations(aggregations: Aggregation[]): Q.Promise<void> {
this.toggleAggregationsVisibility(aggregations);
private processAggregations(aggregations: BucketAggregation[]): Q.Promise<void> {
this.sortAggregations(aggregations);

return this.displayNamesResolver.updateAggregationsDisplayNames(aggregations, this.getCurrentUserKeyAsString()).then(() => {
return this.displayNamesResolver.updateAggregationsDisplayNames(aggregations).then(() => {
this.updateAggregations(aggregations);
});
}

private getCurrentUserKeyAsString(): string {
return AuthContext.get().getUser().getKey().toString();
private sortAggregations(aggregations: BucketAggregation[]): void {
const order = Object.values(ContentAggregation).filter(value => typeof value === 'string') as string[];

aggregations.sort(
(a, b) => order.indexOf(a.getName()) - order.indexOf(b.getName())
);
}

private getAggregations(): Q.Promise<AggregationsQueryResult> {
Expand Down Expand Up @@ -335,14 +363,6 @@ export class ContentBrowseFilterPanel<T extends ContentSummaryAndCompareStatus =
return null;
}

private toggleAggregationsVisibility(aggregations: Aggregation[]) {
aggregations.forEach((aggregation: BucketAggregation) => {
const isAggregationNotEmpty: boolean = aggregation.getBuckets().some((bucket: Bucket) => bucket.docCount > 0);
this.aggregations.get(aggregation.getName()).setVisible(isAggregationNotEmpty);
});
}


// doing a trick to avoid changing lib-admin-ui, adding all children except export button to a wrapper
appendChild(child: Element, lazyRender?: boolean): Element {
if (!this.elementsContainer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class ContentExportElement extends SpanEl {
});
}

protected handleExportClicked(): void {
handleExportClicked(): void {
if (!this.exportConfirmationDialog) {
this.exportConfirmationDialog = new ConfirmationDialog()
.setYesCallback(() => {
Expand Down Expand Up @@ -103,7 +103,7 @@ export class ContentExportElement extends SpanEl {
}

this.searchInputValues.aggregationSelections.filter((value) => value.getSelectedBuckets().length).forEach((selected) => {
params[selected.name] = this.aggregationSelectionValueToString(selected);
params[selected.getName()] = this.aggregationSelectionValueToString(selected);
});

return UriHelper.appendUrlParams(this.getReportServicePath(), params);
Expand All @@ -115,7 +115,7 @@ export class ContentExportElement extends SpanEl {
(bucket: DateRangeBucket) => ValueExpr.dateTime(bucket.getFrom()).getValue().getString()).join();
}

return selected.selectedBuckets.map((bucket) => bucket.getKey()).join();
return selected.getSelectedBuckets().map((bucket) => bucket.getKey()).join();
}


Expand Down
Loading