enigma-bbs/core/file_area_filter_edit.js

372 lines
12 KiB
JavaScript

/* jslint node: true */
'use strict';
// ENiGMA½
const MenuModule = require('./menu_module.js').MenuModule;
const ViewController = require('./view_controller.js').ViewController;
const getSortedAvailableFileAreas =
require('./file_base_area.js').getSortedAvailableFileAreas;
const FileBaseFilters = require('./file_base_filter.js');
const stringFormat = require('./string_format.js');
const UserProps = require('./user_property.js');
// deps
const async = require('async');
exports.moduleInfo = {
name: 'File Area Filter Editor',
desc: 'Module for adding, deleting, and modifying file base filters',
author: 'NuSkooler',
};
const MciViewIds = {
editor: {
searchTerms: 1,
tags: 2,
area: 3,
sort: 4,
order: 5,
filterName: 6,
navMenu: 7,
// :TODO: use the customs new standard thing - filter obj can have active/selected, etc.
selectedFilterInfo: 10, // { ...filter object ... }
activeFilterInfo: 11, // { ...filter object ... }
error: 12, // validation errors
},
};
exports.getModule = class FileAreaFilterEdit extends MenuModule {
constructor(options) {
super(options);
this.filtersArray = new FileBaseFilters(this.client).toArray(); // ordered, such that we can index into them
this.currentFilterIndex = 0; // into |filtersArray|
//
// Lexical sort + keep currently active filter (if any) as the first item in |filtersArray|
//
const activeFilter = FileBaseFilters.getActiveFilter(this.client);
this.filtersArray.sort((filterA, filterB) => {
if (activeFilter) {
if (filterA.uuid === activeFilter.uuid) {
return -1;
}
if (filterB.uuid === activeFilter.uuid) {
return 1;
}
}
return filterA.name.localeCompare(filterB.name, {
sensitivity: false,
numeric: true,
});
});
this.menuMethods = {
saveFilter: (formData, extraArgs, cb) => {
return this.saveCurrentFilter(formData, cb);
},
prevFilter: (formData, extraArgs, cb) => {
this.currentFilterIndex -= 1;
if (this.currentFilterIndex < 0) {
this.currentFilterIndex = this.filtersArray.length - 1;
}
this.loadDataForFilter(this.currentFilterIndex);
return cb(null);
},
nextFilter: (formData, extraArgs, cb) => {
this.currentFilterIndex += 1;
if (this.currentFilterIndex >= this.filtersArray.length) {
this.currentFilterIndex = 0;
}
this.loadDataForFilter(this.currentFilterIndex);
return cb(null);
},
makeFilterActive: (formData, extraArgs, cb) => {
const filters = new FileBaseFilters(this.client);
filters.setActive(this.filtersArray[this.currentFilterIndex].uuid);
this.updateActiveLabel();
return cb(null);
},
newFilter: (formData, extraArgs, cb) => {
this.currentFilterIndex = this.filtersArray.length; // next avail slot
this.clearForm(MciViewIds.editor.searchTerms);
return cb(null);
},
deleteFilter: (formData, extraArgs, cb) => {
const selectedFilter = this.filtersArray[this.currentFilterIndex];
const filterUuid = selectedFilter.uuid;
// cannot delete built-in/system filters
if (true === selectedFilter.system) {
this.showError('Cannot delete built in filters!');
return cb(null);
}
this.filtersArray.splice(this.currentFilterIndex, 1); // remove selected entry
// remove from stored properties
const filters = new FileBaseFilters(this.client);
filters.remove(filterUuid);
filters.persist(() => {
//
// If the item was also the active filter, we need to make a new one active
//
if (
filterUuid ===
this.client.user.properties[UserProps.FileBaseFilterActiveUuid]
) {
const newActive = this.filtersArray[this.currentFilterIndex];
if (newActive) {
filters.setActive(newActive.uuid);
} else {
// nothing to set active to
this.client.user.removeProperty(
'file_base_filter_active_uuid'
);
}
}
// update UI
this.updateActiveLabel();
if (this.filtersArray.length > 0) {
this.loadDataForFilter(this.currentFilterIndex);
} else {
this.clearForm();
}
return cb(null);
});
},
viewValidationListener: (err, cb) => {
const errorView = this.viewControllers.editor.getView(
MciViewIds.editor.error
);
let newFocusId;
if (errorView) {
if (err) {
errorView.setText(err.message);
err.view.clearText(); // clear out the invalid data
} else {
errorView.clearText();
}
}
return cb(newFocusId);
},
};
}
showError(errMsg) {
const errorView = this.viewControllers.editor.getView(MciViewIds.editor.error);
if (errorView) {
if (errMsg) {
errorView.setText(errMsg);
} else {
errorView.clearText();
}
}
}
mciReady(mciData, cb) {
super.mciReady(mciData, err => {
if (err) {
return cb(err);
}
const self = this;
const vc = self.addViewController(
'editor',
new ViewController({ client: this.client })
);
async.series(
[
function loadFromConfig(callback) {
return vc.loadFromMenuConfig(
{ callingMenu: self, mciMap: mciData.menu },
callback
);
},
function populateAreas(callback) {
self.availAreas = [{ name: '-ALL-' }].concat(
getSortedAvailableFileAreas(self.client) || []
);
const areasView = vc.getView(MciViewIds.editor.area);
if (areasView) {
areasView.setItems(self.availAreas.map(a => a.name));
}
self.updateActiveLabel();
self.loadDataForFilter(self.currentFilterIndex);
self.viewControllers.editor.resetInitialFocus();
return callback(null);
},
],
err => {
return cb(err);
}
);
});
}
getCurrentFilter() {
return this.filtersArray[this.currentFilterIndex];
}
setText(mciId, text) {
const view = this.viewControllers.editor.getView(mciId);
if (view) {
view.setText(text);
}
}
updateActiveLabel() {
const activeFilter = FileBaseFilters.getActiveFilter(this.client);
if (activeFilter) {
const activeFormat = this.menuConfig.config.activeFormat || '{name}';
this.setText(
MciViewIds.editor.activeFilterInfo,
stringFormat(activeFormat, activeFilter)
);
}
}
setFocusItemIndex(mciId, index) {
const view = this.viewControllers.editor.getView(mciId);
if (view) {
view.setFocusItemIndex(index);
}
}
clearForm(newFocusId) {
[
MciViewIds.editor.searchTerms,
MciViewIds.editor.tags,
MciViewIds.editor.filterName,
].forEach(mciId => {
this.setText(mciId, '');
});
[MciViewIds.editor.area, MciViewIds.editor.order, MciViewIds.editor.sort].forEach(
mciId => {
this.setFocusItemIndex(mciId, 0);
}
);
if (newFocusId) {
this.viewControllers.editor.switchFocus(newFocusId);
} else {
this.viewControllers.editor.resetInitialFocus();
}
}
getSelectedAreaTag(index) {
if (0 === index) {
return ''; // -ALL-
}
const area = this.availAreas[index];
if (!area) {
return '';
}
return area.areaTag;
}
getOrderBy(index) {
return FileBaseFilters.OrderByValues[index] || FileBaseFilters.OrderByValues[0];
}
setAreaIndexFromCurrentFilter() {
let index;
const filter = this.getCurrentFilter();
if (filter) {
// special treatment: areaTag saved as blank ("") if -ALL-
index =
(filter.areaTag &&
this.availAreas.findIndex(area => filter.areaTag === area.areaTag)) ||
0;
} else {
index = 0;
}
this.setFocusItemIndex(MciViewIds.editor.area, index);
}
setOrderByFromCurrentFilter() {
let index;
const filter = this.getCurrentFilter();
if (filter) {
index =
FileBaseFilters.OrderByValues.findIndex(ob => filter.order === ob) || 0;
} else {
index = 0;
}
this.setFocusItemIndex(MciViewIds.editor.order, index);
}
setSortByFromCurrentFilter() {
let index;
const filter = this.getCurrentFilter();
if (filter) {
index = FileBaseFilters.SortByValues.findIndex(sb => filter.sort === sb) || 0;
} else {
index = 0;
}
this.setFocusItemIndex(MciViewIds.editor.sort, index);
}
getSortBy(index) {
return FileBaseFilters.SortByValues[index] || FileBaseFilters.SortByValues[0];
}
setFilterValuesFromFormData(filter, formData) {
filter.name = formData.value.name;
filter.areaTag = this.getSelectedAreaTag(formData.value.areaIndex);
filter.terms = formData.value.searchTerms;
filter.tags = formData.value.tags;
filter.order = this.getOrderBy(formData.value.orderByIndex);
filter.sort = this.getSortBy(formData.value.sortByIndex);
}
saveCurrentFilter(formData, cb) {
const filters = new FileBaseFilters(this.client);
const selectedFilter = this.filtersArray[this.currentFilterIndex];
if (selectedFilter) {
// *update* currently selected filter
this.setFilterValuesFromFormData(selectedFilter, formData);
filters.replace(selectedFilter.uuid, selectedFilter);
} else {
// add a new entry; note that UUID will be generated
const newFilter = {};
this.setFilterValuesFromFormData(newFilter, formData);
// set current to what we just saved
newFilter.uuid = filters.add(newFilter);
// add to our array (at current index position)
this.filtersArray[this.currentFilterIndex] = newFilter;
}
return filters.persist(cb);
}
loadDataForFilter(filterIndex) {
const filter = this.filtersArray[filterIndex];
if (filter) {
this.setText(MciViewIds.editor.searchTerms, filter.terms);
this.setText(MciViewIds.editor.tags, filter.tags);
this.setText(MciViewIds.editor.filterName, filter.name);
this.setAreaIndexFromCurrentFilter();
this.setSortByFromCurrentFilter();
this.setOrderByFromCurrentFilter();
}
}
};