enigma-bbs/core/file_area_filter_edit.js

341 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();
}
}
};