/* 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'); // 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.file_base_filter_active_uuid) { 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(); } } };