import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
HostListener,
Injectable,
OnInit,
QueryList,
ViewChild,
ViewChildren,
} from "@angular/core";
import { MatDialog, MatDialogRef } from "@angular/material/dialog";
import { WidgetframeService } from "../../../widgetframe/widgetframe.service";
import {
deepCopy,
UtilService,
} from "../../../../components/util/util.service";
import { CurrentLocaleService } from "../../../../components/i18n/currentLocale.service";
import { NgUnsubscribe } from "../../../../ng-unsubscribe";
import { filter, flatMap, map, takeUntil } from "rxjs/operators";
import { HalService } from "../../../../components/hal/hal.service";
import * as uriTemplates_ from "uri-templates";
import { NotificationsService } from "../../../../components/notifications/services/notifications.service";
import { combineLatest, Subject } from "rxjs";
import { AppdataStore } from "../../../../components/appdata/appdata.store";
import { CdkFixedSizeVirtualScroll } from "@angular/cdk/scrolling";
import { TranslateService } from "@ngx-translate/core";
import {
DynamicFormTabsContext,
DynamicFormTabsDialog,
} from "../../../dynamic-form/dynamic-form-tabs-dialog/dynamic-form-tabs-dialog.component";
import { DialogService } from "../../../../../shared/components/dialog/dialog.service";
const uriTemplates = uriTemplates_;
@Component({
selector: "nm-searchfavorites-dialog",
templateUrl: "./search-favorites-dialog.component.html",
styleUrls: ["./search-favorites-dialog.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SearchFavoritesDialogComponent implements OnInit, AfterViewInit {
public searchTemplatesUri: string;
public hasCreateRoleBasedTemplate: boolean;
public dialogService: DialogService;
public groupIndex = 0;
public templates;
public filterText;
public userfilterText;
public formData;
public isListSearch;
public selected = [];
public selectedUser = [];
public editingTemplate;
public users = [];
public selectedFavorite;
public infoText: string;
public sending = false;
public loading = false;
public userTranslation: string = "";
public rolesOptions = [];
private unsubscribe = NgUnsubscribe.create();
public allSelected: boolean = false;
private onFavoriteChangeSub = new Subject<void>();
public onFavoriteChange = this.onFavoriteChangeSub.pipe(
takeUntil(this.unsubscribe)
);
private loadFavorites = new Subject<void>();
@ViewChildren("input") inputList: QueryList<HTMLInputElement>;
@ViewChild(CdkFixedSizeVirtualScroll) viewPort: CdkFixedSizeVirtualScroll;
constructor(
public dialogRef: MatDialogRef<SearchFavoritesDialogComponent>,
private widgetframeService: WidgetframeService,
private localeService: CurrentLocaleService,
private halservice: HalService,
private notificationService: NotificationsService,
private appStore: AppdataStore,
private cd: ChangeDetectorRef,
private translateService: TranslateService
) {}
ngOnInit(): void {
this.userTranslation = this.translateService.instant("label.user");
this.dialogRef.afterClosed().subscribe(() => {
this.unsubscribe.destroy();
});
this.halservice
.getActionEvents()
.pipe(
takeUntil(this.unsubscribe),
filter(
(e) =>
e.name == "delete" ||
e.name == "update" ||
e.name == "add-to-dashboard" ||
e.name == "remove-from-dashboard"
)
)
.subscribe((resp) => {
if (resp.response.body) {
this.notificationService.success(
resp.response.body.title,
resp.response.body.message
);
this.loadFavorites.next();
this.onFavoriteChangeSub.next();
this.selected = [];
}
});
this.halservice
.getActionEvents()
.pipe(
takeUntil(this.unsubscribe),
filter((e) => e.name == "select-attribute-profile")
)
.subscribe((resp) => this.handleSelectAttributeProfile(resp));
if (this.searchTemplatesUri) {
combineLatest(
this.localeService.getCurrentLocale(),
this.loadFavorites.asObservable()
)
.pipe(takeUntil(this.unsubscribe))
.subscribe(([locale, load]) => {
const url = UtilService.setUrlParam(
this.searchTemplatesUri,
"locale",
locale
);
this.widgetframeService.getData(url).subscribe((data) => {
this.loading = false;
this.templates = data;
if (this.rolesOptions.length === 0) {
this.loadWorkboxRoles();
}
if (this.selectedFavorite) {
const template = this.templates._embedded.templates.find(
(entry) => entry.identifier === this.selectedFavorite
);
if (template) {
template.checked = true;
}
this.selected = [template];
}
this.cd.markForCheck();
});
});
this.loadFavorites.next();
} else {
console.error("searchTemplatesUri is not defined but needed");
}
}
get data() {
if (!this.templates) {
return [];
}
return this.templates._embedded.templates;
}
edit(template) {
if (this.editingTemplate) {
this.editingTemplate.edit = false;
this.editingTemplate = null;
}
this.editingTemplate = template;
template.edit = true;
template.editText = template.text;
template.chip.value = this.getChipValue(template);
}
@HostListener("document:keydown.escape", ["$event"]) onKeydownHandler(event) {
if (this.editingTemplate) {
this.stopEdit();
} else {
this.dialogRef.close(null);
}
}
saveEdit(template) {
if (!template.editText) {
if (!template.identifier) {
this.data.shift();
this.templates._embedded.templates = [].concat(this.data);
}
this.stopEdit();
return;
}
if (!template.identifier) {
this.createSearchTemplate(template);
} else {
template.text = template.editText;
template.chip.value = this.getChipValue(template);
const payload = {
name: template.editText,
roleId: template.roleId,
attributeProfileId: template.attributeProfileId,
};
this.updateSearchTemplate(template, payload);
}
this.stopEdit();
}
stopEdit() {
if (!this.editingTemplate.identifier) {
this.data.shift();
this.templates._embedded.templates = [].concat(this.data);
}
this.editingTemplate.edit = false;
this.editingTemplate = null;
}
createSearchTemplate(template) {
let action;
let params;
if (this.isListSearch) {
action = this.templates._actions["create-list"];
params = this.formData.listvalue;
} else {
action = this.templates._actions["create-standard"];
params = deepCopy(this.formData.fields);
if (this.formData.attributes) {
params.attributes = this.formData.attributes;
}
if (this.formData.fields && this.formData.fields.category) {
params.publication = this.formData.fields.category.publication;
params.category = this.formData.fields.category.category;
}
}
this.loading = true;
action.payload = {
params,
identifier: template.editText,
roleId: template.roleId,
};
this.halservice
.execute("create-searchfavorite", action)
.subscribe((resp) => {
template.text = template.editText;
if (resp.response.body) {
this.loading = false;
this.notificationService.success(
resp.response.body.title,
resp.response.body.message
);
this.loadFavorites.next();
this.onFavoriteChangeSub.next();
}
});
}
updateSearchTemplate(template, payload) {
const action = template._actions.rename;
action.payload = payload;
this.halservice.execute("save-searchfavorite", action).subscribe((resp) => {
if (resp.response.body) {
this.notificationService.success(
resp.response.body.title,
resp.response.body.message
);
this.onFavoriteChangeSub.next();
}
});
}
getChipValue(template) {
if (template.roleId) {
return this.rolesOptions.find((role) => role.pimRef === template.roleId)
?.name;
} else {
return this.userTranslation;
}
}
addFavorite() {
const template = {
edit: true,
editText: "",
text: "",
};
this.templates._embedded.templates = [template].concat(
this.templates._embedded.templates
);
this.filterText = "";
this.editingTemplate = template;
}
sendTo() {
if (this.users.length === 0) {
this.appStore
.getAppdata()
.pipe(
map((data) => data.portal._links.users.href),
flatMap((url) => this.widgetframeService.getData(url)),
map((data) => data._embedded.users)
)
.subscribe((data) => {
this.users = data;
});
}
this.groupIndex = 1;
}
checkboxChange(template, checked) {
template.checked = checked;
if (checked) {
this.selected.push(template);
} else {
this.selected.splice(this.selected.indexOf(template), 1);
}
this.allSelected = this.selected.length === this.data.length;
}
userCheckboxChange(user, checked) {
user.checked = checked;
if (checked) {
this.selectedUser.push(user);
} else {
this.selected.splice(this.selectedUser.indexOf(user), 1);
}
}
ngAfterViewInit(): void {
this.inputList.changes
.pipe(takeUntil(this.unsubscribe))
.subscribe((data) => {
if (data.first) {
data.first.nativeElement.focus();
}
});
}
acceptSend() {
const action = this.templates._actions["send-to"];
action.payload = this.selectedUser.map((entry) => entry.name);
const tmpl = uriTemplates(action.href);
action.href = tmpl.fill({
source: this.selected.map((entry) => entry.identifier),
});
this.sending = true;
this.halservice.execute("send-searchfavorite", action).subscribe((resp) => {
if (resp.response.body) {
this.notificationService.success(
resp.response.body.title,
resp.response.body.message
);
this.sending = false;
this.groupIndex = 0;
this.selectedUser.forEach((user) => (user.checked = false));
this.selected.forEach((entry) => (entry.checked = false));
this.selectedUser = [];
this.selected = [];
this.cd.markForCheck();
}
});
}
selectAll(event) {
this.allSelected = event.checked;
this.templates._embedded.templates.forEach((template) => {
template.checked = this.allSelected;
});
this.selected = [];
if (this.allSelected) {
this.selected.push(...this.data);
}
}
beforeActionExecute(action) {
if (action.key === "update") {
if (this.isListSearch) {
action.value.payload = this.formData.listvalue;
} else {
const payload = deepCopy(this.formData.fields);
if (payload.category) {
payload.publication = payload.category.publication;
payload.category = payload.category.category;
}
action.value.payload = payload;
if (this.formData.attributes) {
action.value.payload.attributes = this.formData.attributes;
}
if (this.formData.visibleFields) {
action.value.payload.visibleFields = this.formData.visibleFields;
}
}
}
}
back() {
this.groupIndex = 0;
}
displayAction(act, template) {
if (act.key === "update") {
return template.listsearch === this.isListSearch;
}
return act.key !== "rename" && act.key !== "load";
}
displayRole(template) {
return (
(template.roleId || !template.identifier) &&
this.hasCreateRoleBasedTemplate
);
}
disableSendToButton(): boolean {
return (
this.selected.length === 0 ||
this.selected.filter((template) => template.roleId).length > 0
);
}
loadWorkboxRoles() {
this.appStore
.getAppdata()
.pipe(
map((data) => data.portal._links["workbox-roles"].href),
flatMap((url) => this.widgetframeService.getData(url))
)
.subscribe((data) => {
this.rolesOptions = data;
});
}
handleSelectAttributeProfile(resp) {
const templateId = resp?.action?.payload;
const template = this.templates._embedded.templates.find(
(template) => template.identifier === templateId
);
let dialogRef = this.dialogService.open(DynamicFormTabsDialog, {
data: {
identifier: "select-attribute-profile",
title: "placeholder.attribute.profile",
dialogConfig: {
tabs: [
{
type: "form",
fields: [
{
label: "placeholder.attribute.profile",
field: "attributeProfile",
type: "lookup",
lookupOptions: resp?.response?.body?._embedded?.profiles,
identifierField: "pimRef",
descriptionField: "identifier",
lookupAllowEmpty: true,
required: false,
floatingLabel: true,
defaultValue: template?.attributeProfileId,
},
],
},
],
},
},
});
dialogRef.afterClosed().subscribe((data) => {
if (!data) {
return;
}
template.attributeProfileId = data?.values?.attributeProfile;
const payload = {
attributeProfileId: template.attributeProfileId,
};
this.updateSearchTemplate(template, payload);
});
}
}
export function buildStandardSearchUriParameter(data): any {
const form = data[0] ? data[0] : {};
if (form.category) {
if (!form.category.category) {
form.category.category = "";
}
if (!form.category.publication) {
form.category.publication = "";
}
}
const attributes = data[1];
const uriParams = form ? form : {};
let attributeFilters = {};
if (attributes && attributes.length > 0) {
for (let attribute of attributes) {
buildAttributeFilter(attribute, attributeFilters);
}
uriParams["attributes"] = JSON.stringify(attributeFilters);
}
return uriParams;
}
export function buildStandardSearchUri(data, templateUrl): string {
const template = uriTemplates(templateUrl);
return template.fill(buildStandardSearchUriParameter(data));
}
function buildAttributeFilter(attribute, attributeFilters) {
if (attribute.displayRange) {
let from = findValueEncoded(attribute.from);
if (from) {
attributeFilters[attribute.identifier] = from;
}
let to = findValueEncoded(attribute.to);
if (to) {
attributeFilters[attribute.identifier] = to;
}
return;
}
const filter = findValueEncoded(attribute);
if (filter) {
attributeFilters[attribute.identifier] = filter;
}
}
function findValueEncoded(attribute) {
if (attribute.source["0"]) {
if (attribute.source["0"].value) {
return encodeURIComponent(attribute.source["0"].value);
}
}
}