Add new scan pointers for mb/fb
This commit is contained in:
parent
ab6e097a4f
commit
136d21276c
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1766,6 +1766,10 @@
|
||||||
value: { command: "]" }
|
value: { command: "]" }
|
||||||
action: @systemMethod:nextArea
|
action: @systemMethod:nextArea
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
value: { command: "D" }
|
||||||
|
action: @menu:messageAreaSetNewScanDate
|
||||||
|
}
|
||||||
{
|
{
|
||||||
value: 1
|
value: 1
|
||||||
action: @menu:messageArea
|
action: @menu:messageArea
|
||||||
|
@ -1803,6 +1807,47 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
messageAreaSetNewScanDate: {
|
||||||
|
module: set_newscan_date
|
||||||
|
desc: Message Base
|
||||||
|
art: SETMNSDATE
|
||||||
|
config: {
|
||||||
|
target: message
|
||||||
|
scanDateFormat: YYYYMMDD
|
||||||
|
}
|
||||||
|
form: {
|
||||||
|
0: {
|
||||||
|
mci: {
|
||||||
|
ME1: {
|
||||||
|
focus: true
|
||||||
|
submit: true
|
||||||
|
argName: scanDate
|
||||||
|
maskPattern: "####/##/##"
|
||||||
|
}
|
||||||
|
SM2: {
|
||||||
|
argName: targetSelection
|
||||||
|
submit: false
|
||||||
|
justify: right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
submit: {
|
||||||
|
*: [
|
||||||
|
{
|
||||||
|
value: { scanDate: null }
|
||||||
|
action: @method:scanDateSubmit
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
actionKeys: [
|
||||||
|
{
|
||||||
|
keys: [ "escape", "q", "shift + q" ]
|
||||||
|
action: @systemMethod:prevMenu
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
messageAreaChangeCurrentArea: {
|
messageAreaChangeCurrentArea: {
|
||||||
// :TODO: rename this art to ACHANGE
|
// :TODO: rename this art to ACHANGE
|
||||||
art: CHANGE
|
art: CHANGE
|
||||||
|
@ -2493,9 +2538,49 @@
|
||||||
value: { menuOption: "S" }
|
value: { menuOption: "S" }
|
||||||
action: @menu:fileBaseSearch
|
action: @menu:fileBaseSearch
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
value: { menuOption: "P" }
|
||||||
|
action: @menu:fileBaseSetNewScanDate
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileBaseSetNewScanDate: {
|
||||||
|
module: set_newscan_date
|
||||||
|
desc: File Base
|
||||||
|
art: SETFNSDATE
|
||||||
|
config: {
|
||||||
|
target: file
|
||||||
|
scanDateFormat: YYYYMMDD
|
||||||
|
}
|
||||||
|
form: {
|
||||||
|
0: {
|
||||||
|
mci: {
|
||||||
|
ME1: {
|
||||||
|
focus: true
|
||||||
|
submit: true
|
||||||
|
argName: scanDate
|
||||||
|
maskPattern: "####/##/##"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
submit: {
|
||||||
|
*: [
|
||||||
|
{
|
||||||
|
value: { scanDate: null }
|
||||||
|
action: @method:scanDateSubmit
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
actionKeys: [
|
||||||
|
{
|
||||||
|
keys: [ "escape", "q", "shift + q" ]
|
||||||
|
action: @systemMethod:prevMenu
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fileBaseListEntries: {
|
fileBaseListEntries: {
|
||||||
module: file_area_list
|
module: file_area_list
|
||||||
desc: Browsing Files
|
desc: Browsing Files
|
||||||
|
|
|
@ -349,8 +349,8 @@ function FTNMessageScanTossModule() {
|
||||||
message.meta.FtnKludge.FMPT = localAddress.point;
|
message.meta.FtnKludge.FMPT = localAddress.point;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_.get(message, 'meta.FtnProperty.ftn_dest_point', 0) > 0) {
|
if(_.isNumber(options.destAddress.point) && options.destAddress.point > 0) {
|
||||||
message.meta.FtnKludge.TOPT = message.meta.FtnProperty.ftn_dest_point;
|
message.meta.FtnKludge.TOPT = options.destAddress.point;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We need to set some destination info for EchoMail
|
// We need to set some destination info for EchoMail
|
||||||
|
@ -1954,8 +1954,7 @@ function FTNMessageScanTossModule() {
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// :TODO: fill out the rest of the consts here
|
// :TODO: fill out the rest of the consts here
|
||||||
// :TODO: this statement is crazy ugly
|
// :TODO: this statement is crazy ugly -- use JOIN / NOT EXISTS for state_flags & 0x02
|
||||||
// :TODO: this should really check for extenral "flavor" and not-already-exported state_flags0
|
|
||||||
const getNewUuidsSql =
|
const getNewUuidsSql =
|
||||||
`SELECT message_id, message_uuid
|
`SELECT message_id, message_uuid
|
||||||
FROM message m
|
FROM message m
|
||||||
|
|
|
@ -0,0 +1,261 @@
|
||||||
|
/* jslint node: true */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// ENiGMA½
|
||||||
|
const MenuModule = require('./menu_module.js').MenuModule;
|
||||||
|
const ViewController = require('./view_controller.js').ViewController;
|
||||||
|
const Errors = require('./enig_error.js').Errors;
|
||||||
|
const FileEntry = require('./file_entry.js');
|
||||||
|
const FileBaseFilters = require('./file_base_filter.js');
|
||||||
|
const { getAvailableFileAreaTags } = require('./file_base_area.js');
|
||||||
|
const {
|
||||||
|
getSortedAvailMessageConferences,
|
||||||
|
getSortedAvailMessageAreasByConfTag,
|
||||||
|
updateMessageAreaLastReadId,
|
||||||
|
getMessageIdNewerThanTimestampByArea
|
||||||
|
} = require('./message_area.js');
|
||||||
|
const stringFormat = require('./string_format.js');
|
||||||
|
|
||||||
|
// deps
|
||||||
|
const async = require('async');
|
||||||
|
const moment = require('moment');
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
exports.moduleInfo = {
|
||||||
|
name : 'Set New Scan Date',
|
||||||
|
desc : 'Sets new scan date for applicable scans',
|
||||||
|
author : 'NuSkooler',
|
||||||
|
};
|
||||||
|
|
||||||
|
const MciViewIds = {
|
||||||
|
main : {
|
||||||
|
scanDate : 1,
|
||||||
|
targetSelection : 2,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// :TODO: for messages, we could insert "conf - all areas" into targets, and allow such
|
||||||
|
|
||||||
|
exports.getModule = class SetNewScanDate extends MenuModule {
|
||||||
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
|
||||||
|
const config = this.menuConfig.config;
|
||||||
|
|
||||||
|
this.target = config.target || 'message';
|
||||||
|
this.scanDateFormat = config.scanDateFormat || 'YYYYMMDD';
|
||||||
|
|
||||||
|
this.menuMethods = {
|
||||||
|
scanDateSubmit : (formData, extraArgs, cb) => {
|
||||||
|
let scanDate = _.get(formData, 'value.scanDate');
|
||||||
|
if(!scanDate) {
|
||||||
|
return cb(Errors.MissingParam('"scanDate" missing from form data'));
|
||||||
|
}
|
||||||
|
|
||||||
|
scanDate = moment(scanDate, this.scanDateFormat);
|
||||||
|
if(!scanDate.isValid()) {
|
||||||
|
return cb(Errors.Invalid(`"${_.get(formData, 'value.scanDate')}" is not a valid date`));
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetSelection = _.get(formData, 'value.targetSelection'); // may be undefined if N/A
|
||||||
|
|
||||||
|
this[`setNewScanDateFor${_.capitalize(this.target)}Base`](targetSelection, scanDate, () => {
|
||||||
|
return this.prevMenu(cb);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
setNewScanDateForMessageBase(targetSelection, scanDate, cb) {
|
||||||
|
const target = this.targetSelections[targetSelection];
|
||||||
|
if(!target) {
|
||||||
|
return cb(Errors.UnexpectedState('Unable to get target in which to set new scan'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// selected area, or all of 'em
|
||||||
|
let updateAreaTags;
|
||||||
|
if('' === target.area.areaTag) {
|
||||||
|
updateAreaTags = this.targetSelections
|
||||||
|
.map( targetSelection => targetSelection.area.areaTag )
|
||||||
|
.filter( areaTag => areaTag ); // remove the blank 'all' entry
|
||||||
|
} else {
|
||||||
|
updateAreaTags = [ target.area.areaTag ];
|
||||||
|
}
|
||||||
|
|
||||||
|
async.each(updateAreaTags, (areaTag, nextAreaTag) => {
|
||||||
|
getMessageIdNewerThanTimestampByArea(areaTag, scanDate, (err, messageId) => {
|
||||||
|
if(err) {
|
||||||
|
return nextAreaTag(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!messageId) {
|
||||||
|
return nextAreaTag(null); // nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
messageId = Math.max(messageId - 1, 0);
|
||||||
|
|
||||||
|
return updateMessageAreaLastReadId(
|
||||||
|
this.client.user.userId,
|
||||||
|
areaTag,
|
||||||
|
messageId,
|
||||||
|
true, // allowOlder
|
||||||
|
nextAreaTag
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, err => {
|
||||||
|
return cb(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setNewScanDateForFileBase(targetSelection, scanDate, cb) {
|
||||||
|
//
|
||||||
|
// ENiGMA doesn't currently have the concept of per-area
|
||||||
|
// scan pointers for users, so we use all areas avail
|
||||||
|
// to the user.
|
||||||
|
//
|
||||||
|
const filterCriteria = {
|
||||||
|
areaTag : getAvailableFileAreaTags(this.client),
|
||||||
|
newerThanTimestamp : scanDate,
|
||||||
|
limit : 1,
|
||||||
|
orderBy : 'upload_timestamp',
|
||||||
|
order : 'ascending',
|
||||||
|
};
|
||||||
|
|
||||||
|
FileEntry.findFiles(filterCriteria, (err, fileIds) => {
|
||||||
|
if(err) {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!fileIds || 0 === fileIds.length) {
|
||||||
|
// nothing to do
|
||||||
|
return cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pointerFileId = Math.max(fileIds[0] - 1, 0);
|
||||||
|
|
||||||
|
return FileBaseFilters.setFileBaseLastViewedFileIdForUser(
|
||||||
|
this.client.user,
|
||||||
|
pointerFileId,
|
||||||
|
true, // allowOlder
|
||||||
|
cb
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadAvailMessageBaseSelections(cb) {
|
||||||
|
//
|
||||||
|
// Create an array of objects with conf/area information per entry,
|
||||||
|
// sorted naturally or via the 'sort' member in config
|
||||||
|
//
|
||||||
|
const selections = [];
|
||||||
|
getSortedAvailMessageConferences(this.client).forEach(conf => {
|
||||||
|
getSortedAvailMessageAreasByConfTag(conf.confTag, { client : this.client } ).forEach(area => {
|
||||||
|
selections.push({
|
||||||
|
conf : {
|
||||||
|
confTag : conf.confTag,
|
||||||
|
name : conf.conf.name,
|
||||||
|
desc : conf.conf.desc,
|
||||||
|
},
|
||||||
|
area : {
|
||||||
|
areaTag : area.areaTag,
|
||||||
|
name : area.area.name,
|
||||||
|
desc : area.area.desc,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
selections.unshift({
|
||||||
|
conf : {
|
||||||
|
confTag : '',
|
||||||
|
name : 'All conferences',
|
||||||
|
desc : 'All conferences',
|
||||||
|
},
|
||||||
|
area : {
|
||||||
|
areaTag : '',
|
||||||
|
name : 'All areas',
|
||||||
|
desc : 'All areas',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find current conf/area & move it directly under "All"
|
||||||
|
const currConfTag = this.client.user.properties.message_conf_tag;
|
||||||
|
const currAreaTag = this.client.user.properties.message_area_tag;
|
||||||
|
if(currConfTag && currAreaTag) {
|
||||||
|
const confAreaIndex = selections.findIndex( confArea => {
|
||||||
|
return confArea.conf.confTag === currConfTag && confArea.area.areaTag === currAreaTag;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(confAreaIndex > -1) {
|
||||||
|
selections.splice(1, 0, selections.splice(confAreaIndex, 1)[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.targetSelections = selections;
|
||||||
|
|
||||||
|
return cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
mciReady(mciData, cb) {
|
||||||
|
super.mciReady(mciData, err => {
|
||||||
|
if(err) {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
const self = this;
|
||||||
|
const vc = self.addViewController( 'main', new ViewController( { client : this.client } ) );
|
||||||
|
|
||||||
|
async.series(
|
||||||
|
[
|
||||||
|
function validateConfig(callback) {
|
||||||
|
if(![ 'message', 'file' ].includes(self.target)) {
|
||||||
|
return callback(Errors.Invalid(`Invalid "target" in config: ${self.target}`));
|
||||||
|
}
|
||||||
|
// :TOD0: validate scanDateFormat
|
||||||
|
return callback(null);
|
||||||
|
},
|
||||||
|
function loadFromConfig(callback) {
|
||||||
|
return vc.loadFromMenuConfig( { callingMenu : self, mciMap : mciData.menu }, callback);
|
||||||
|
},
|
||||||
|
function loadAvailSelections(callback) {
|
||||||
|
switch(self.target) {
|
||||||
|
case 'message' :
|
||||||
|
return self.loadAvailMessageBaseSelections(callback);
|
||||||
|
|
||||||
|
default :
|
||||||
|
return callback(null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function populateForm(callback) {
|
||||||
|
const today = moment();
|
||||||
|
|
||||||
|
const scanDateView = vc.getView(MciViewIds.main.scanDate);
|
||||||
|
|
||||||
|
// :TODO: MaskTextEditView needs some love: If setText() with input that matches the mask, we should ignore the non-mask chars! Hack in place for now
|
||||||
|
const scanDateFormat = self.scanDateFormat.replace(/[\/\-. ]/g, '');
|
||||||
|
scanDateView.setText(today.format(scanDateFormat));
|
||||||
|
|
||||||
|
if('message' === self.target) {
|
||||||
|
const messageSelectionsFormat = self.menuConfig.config.messageSelectionsFormat || '{conf.name} - {area.name}';
|
||||||
|
const messageSelectionFocusFormat = self.menuConfig.config.messageSelectionFocusFormat || messageSelectionsFormat;
|
||||||
|
|
||||||
|
const targetSelectionView = vc.getView(MciViewIds.main.targetSelection);
|
||||||
|
|
||||||
|
targetSelectionView.setItems(self.targetSelections.map(targetSelection => stringFormat(messageSelectionFocusFormat, targetSelection)));
|
||||||
|
targetSelectionView.setFocusItems(self.targetSelections.map(targetSelection => stringFormat(messageSelectionFocusFormat, targetSelection)));
|
||||||
|
|
||||||
|
targetSelectionView.setFocusItemIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.viewControllers.main.resetInitialFocus();
|
||||||
|
//vc.switchFocus(MciViewIds.main.scanDate);
|
||||||
|
return callback(null);
|
||||||
|
}
|
||||||
|
],
|
||||||
|
err => {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue