341 lines
12 KiB
JavaScript
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();
|
|
}
|
|
}
|
|
};
|