2022-12-01 23:05:46 +01:00

217 lines
7.8 KiB
TypeScript

// (C) Copyright 2015 Moodle Pty 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 { Component, ElementRef, Input, OnInit, Type, ViewChild } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { CoreTag } from '@features/tag/services/tag';
import { CoreSites } from '@services/sites';
import { CoreFormFields, CoreForms } from '@singletons/form';
import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils } from '@services/utils/utils';
import { ModalController } from '@singletons';
import {
AddonModDataField,
AddonModDataData,
AddonModDataTemplateType,
AddonModDataSearchEntriesAdvancedField,
} from '../../services/data';
import { AddonModDataFieldsDelegate } from '../../services/data-fields-delegate';
import { AddonModDataHelper } from '../../services/data-helper';
import { AddonModDataComponentsCompileModule } from '../components-compile.module';
import { AddonModDataSearchDataParams } from '../index';
/**
* Page that displays the search modal.
*/
@Component({
selector: 'addon-mod-data-search-modal',
templateUrl: 'search.html',
styleUrls: ['../../data.scss', '../../data-forms.scss'],
})
export class AddonModDataSearchComponent implements OnInit {
@ViewChild('searchFormEl') formElement!: ElementRef;
@Input() search!: AddonModDataSearchDataParams;
@Input() fields!: Record<number, AddonModDataField>;
@Input() database!: AddonModDataData;
advancedSearch = '';
advancedIndexed: CoreFormFields = {};
extraImports: Type<unknown>[] = [AddonModDataComponentsCompileModule];
searchForm: FormGroup;
jsData?: {
fields: Record<number, AddonModDataField>;
form: FormGroup;
search: CoreFormFields;
};
fieldsArray: AddonModDataField[] = [];
constructor(
protected fb: FormBuilder,
) {
this.searchForm = new FormGroup({});
}
ngOnInit(): void {
this.advancedIndexed = {};
this.search.advanced?.forEach((field) => {
if (field !== undefined) {
this.advancedIndexed[field.name] = field.value
? CoreTextUtils.parseJSON(field.value, '')
: '';
}
});
this.searchForm.addControl('text', this.fb.control(this.search.text || ''));
this.searchForm.addControl('sortBy', this.fb.control(this.search.sortBy || '0'));
this.searchForm.addControl('sortDirection', this.fb.control(this.search.sortDirection || 'DESC'));
this.searchForm.addControl('firstname', this.fb.control(this.advancedIndexed['firstname'] || ''));
this.searchForm.addControl('lastname', this.fb.control(this.advancedIndexed['lastname'] || ''));
this.fieldsArray = CoreUtils.objectToArray(this.fields);
this.advancedSearch = this.renderAdvancedSearchFields();
}
/**
* Displays Advanced Search Fields.
*
* @returns Generated HTML.
*/
protected renderAdvancedSearchFields(): string {
this.jsData = {
fields: this.fields,
form: this.searchForm,
search: this.advancedIndexed,
};
let template = AddonModDataHelper.getTemplate(this.database, AddonModDataTemplateType.SEARCH, this.fieldsArray);
// Replace the fields found on template.
this.fieldsArray.forEach((field) => {
let replace = '[[' + field.name + ']]';
replace = replace.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
const replaceRegex = new RegExp(replace, 'gi');
// Replace field by a generic directive.
const render = '<addon-mod-data-field-plugin mode="search" [field]="fields[' + field.id +
']" [form]="form" [searchFields]="search"></addon-mod-data-field-plugin>';
template = template.replace(replaceRegex, render);
});
// Not pluginable other search elements.
// Replace firstname field by the text input.
let replaceRegex = new RegExp('##firstname##', 'gi');
let render = '<span [formGroup]="form"><ion-input type="text" name="firstname" \
[placeholder]="\'addon.mod_data.authorfirstname\' | translate" formControlName="firstname"></ion-input></span>';
template = template.replace(replaceRegex, render);
// Replace lastname field by the text input.
replaceRegex = new RegExp('##lastname##', 'gi');
render = '<span [formGroup]="form"><ion-input type="text" name="lastname" \
[placeholder]="\'addon.mod_data.authorlastname\' | translate" formControlName="lastname"></ion-input></span>';
template = template.replace(replaceRegex, render);
// Searching by tags is not supported.
replaceRegex = new RegExp('##tags##', 'gi');
const message = CoreTag.areTagsAvailableInSite() ?
'<p class="item-dimmed">{{ \'addon.mod_data.searchbytagsnotsupported\' | translate }}</p>'
: '';
template = template.replace(replaceRegex, message);
return template;
}
/**
* Retrieve the entered data in search in a form.
*
* @param searchedData Array with the entered form values.
* @returns Array with the answers.
*/
getSearchDataFromForm(searchedData: CoreFormFields): AddonModDataSearchEntriesAdvancedField[] {
const advancedSearch: AddonModDataSearchEntriesAdvancedField[] = [];
// Filter and translate fields to each field plugin.
this.fieldsArray.forEach((field) => {
const fieldData = AddonModDataFieldsDelegate.getFieldSearchData(field, searchedData);
fieldData.forEach((data) => {
// WS wants values in Json format.
advancedSearch.push({
name: data.name,
value: JSON.stringify(data.value),
});
});
});
// Not pluginable other search elements.
if (searchedData.firstname) {
// WS wants values in Json format.
advancedSearch.push({
name: 'firstname',
value: JSON.stringify(searchedData.firstname),
});
}
if (searchedData.lastname) {
// WS wants values in Json format.
advancedSearch.push({
name: 'lastname',
value: JSON.stringify(searchedData.lastname),
});
}
return advancedSearch;
}
/**
* Close modal.
*/
closeModal(): void {
CoreForms.triggerFormCancelledEvent(this.formElement, CoreSites.getCurrentSiteId());
ModalController.dismiss();
}
/**
* Done editing.
*
* @param e Event.
*/
searchEntries(e: Event): void {
e.preventDefault();
e.stopPropagation();
const searchedData = this.searchForm.value;
if (this.search.searchingAdvanced) {
this.search.advanced = this.getSearchDataFromForm(searchedData);
this.search.searching = this.search.advanced.length > 0;
} else {
this.search.text = searchedData.text;
this.search.searching = this.search.text.length > 0;
}
this.search.sortBy = searchedData.sortBy;
this.search.sortDirection = searchedData.sortDirection;
CoreForms.triggerFormSubmittedEvent(this.formElement, false, CoreSites.getCurrentSiteId());
ModalController.dismiss(this.search);
}
}