Ability to delete private (aka inbox) messages

This commit is contained in:
Bryan Ashby 2018-07-04 18:49:03 -06:00
parent 2408d4c5c0
commit 0d55daabe4
1 changed files with 130 additions and 32 deletions

View File

@ -7,6 +7,8 @@ const ViewController = require('./view_controller.js').ViewContro
const messageArea = require('./message_area.js'); const messageArea = require('./message_area.js');
const stringFormat = require('./string_format.js'); const stringFormat = require('./string_format.js');
const MessageAreaConfTempSwitcher = require('./mod_mixins.js').MessageAreaConfTempSwitcher; const MessageAreaConfTempSwitcher = require('./mod_mixins.js').MessageAreaConfTempSwitcher;
const Errors = require('./enig_error.js').Errors;
const Message = require('./message.js');
// deps // deps
const async = require('async'); const async = require('async');
@ -14,7 +16,7 @@ const _ = require('lodash');
const moment = require('moment'); const moment = require('moment');
/* /*
Available listFormat/focusListFormat members (VM1): Available listFormat/focusListFormat members for |msgList|
msgNum : Message number msgNum : Message number
to : To username/handle to : To username/handle
@ -22,22 +24,28 @@ const moment = require('moment');
subj : Subject subj : Subject
ts : Message mod timestamp (format with config.dateTimeFormat) ts : Message mod timestamp (format with config.dateTimeFormat)
newIndicator : New mark/indicator (config.newIndicator) newIndicator : New mark/indicator (config.newIndicator)
MCI codes:
VM1 : Message list
TL2 : Message info 1: { msgNumSelected, msgNumTotal }
*/ */
exports.moduleInfo = { exports.moduleInfo = {
name : 'Message List', name : 'Message List',
desc : 'Module for listing/browsing available messages', desc : 'Module for listing/browsing available messages',
author : 'NuSkooler', author : 'NuSkooler',
}; };
const FormIds = {
allViews : 0,
delPrompt : 1,
};
const MciViewIds = { const MciViewIds = {
msgList : 1, // VM1 allViews : {
msgInfo1 : 2, // TL2 msgList : 1, // VM1 - see above
delPromptXy : 2, // %XY2, e.g: delete confirmation
customRangeStart : 10, // Everything |msgList| has plus { msgNumSelected, msgNumTotal }
},
delPrompt: {
prompt : 1,
}
}; };
exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher(MenuModule) { exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher(MenuModule) {
@ -51,7 +59,7 @@ exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher(
this.menuMethods = { this.menuMethods = {
selectMessage : (formData, extraArgs, cb) => { selectMessage : (formData, extraArgs, cb) => {
if(MciViewIds.msgList === formData.submitId) { if(MciViewIds.allViews.msgList === formData.submitId) {
this.initialFocusIndex = formData.value.message; this.initialFocusIndex = formData.value.message;
const modOpts = { const modOpts = {
@ -91,10 +99,40 @@ exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher(
return cb(null); return cb(null);
} }
}, },
fullExit : (formData, extraArgs, cb) => { fullExit : (formData, extraArgs, cb) => {
this.menuResult = { fullExit : true }; this.menuResult = { fullExit : true };
return this.prevMenu(cb); return this.prevMenu(cb);
},
deleteSelected : (formData, extraArgs, cb) => {
if(MciViewIds.allViews.msgList != formData.submitId) {
return cb(null);
}
const messageIndex = _.get(formData, 'value.message');
return this.promptDeleteMessageConfirm(messageIndex, cb);
},
deleteMessageYes : (formData, extraArgs, cb) => {
const msgListView = this.viewControllers.allViews.getView(MciViewIds.allViews.msgList);
this.enableMessageListIndexUpdates(msgListView);
if(this.selectedMessageForDelete) {
this.selectedMessageForDelete.deleteMessage(this.client.user, err => {
if(err) {
this.client.log.error(`Failed to delete message: ${this.selectedMessageForDelete.messageUuid}`);
} else {
this.client.log.info(`User deleted message: ${this.selectedMessageForDelete.messageUuid}`);
this.config.messageList.splice(msgListView.focusedItemIndex, 1);
this.updateMessageNumbersAfterDelete(msgListView.focusedItemIndex);
msgListView.setItems(this.config.messageList);
}
this.selectedMessageForDelete = null;
msgListView.redraw();
return cb(null);
});
} else {
return cb(null);
}
},
deleteMessageNo : (formData, extraArgs, cb) => {
return cb(null);
} }
}; };
} }
@ -130,6 +168,17 @@ exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher(
super.leave(); super.leave();
} }
populateCustomLabelsForSelected(selectedIndex) {
const formatObj = Object.assign(
{
msgNumSelected : (selectedIndex + 1),
msgNumTotal : this.config.messageList.length,
},
this.config.messageList[selectedIndex] // plus, all the selected message props
);
return this.updateCustomViewTextsWithFilter('allViews', MciViewIds.allViews.customRangeStart, formatObj);
}
mciReady(mciData, cb) { mciReady(mciData, cb) {
super.mciReady(mciData, err => { super.mciReady(mciData, err => {
if(err) { if(err) {
@ -183,7 +232,7 @@ exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher(
function updateMessageListObjects(callback) { function updateMessageListObjects(callback) {
const dateTimeFormat = self.menuConfig.config.dateTimeFormat || self.client.currentTheme.helpers.getDateTimeFormat(); const dateTimeFormat = self.menuConfig.config.dateTimeFormat || self.client.currentTheme.helpers.getDateTimeFormat();
const newIndicator = self.menuConfig.config.newIndicator || '*'; const newIndicator = self.menuConfig.config.newIndicator || '*';
const regIndicator = new Array(newIndicator.length + 1).join(' '); // fill with space to avoid draw issues const regIndicator = ' '.repeat(newIndicator.length); // fill with space to avoid draw issues
let msgNum = 1; let msgNum = 1;
self.config.messageList.forEach( (listItem, index) => { self.config.messageList.forEach( (listItem, index) => {
@ -200,19 +249,10 @@ exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher(
}); });
return callback(null); return callback(null);
}, },
function populateList(callback) { function populateAndDrawViews(callback) {
const msgListView = vc.getView(MciViewIds.msgList); const msgListView = vc.getView(MciViewIds.allViews.msgList);
// :TODO: replace with standard custom info MCI - msgNumSelected, msgNumTotal, areaName, areaDesc, confName, confDesc, ...
const messageInfo1Format = self.menuConfig.config.messageInfo1Format || '{msgNumSelected} / {msgNumTotal}';
msgListView.setItems(self.config.messageList); msgListView.setItems(self.config.messageList);
self.enableMessageListIndexUpdates(msgListView);
msgListView.on('index update', idx => {
self.setViewText(
'allViews',
MciViewIds.msgInfo1,
stringFormat(messageInfo1Format, { msgNumSelected : (idx + 1), msgNumTotal : self.config.messageList.length } ));
});
if(self.initialFocusIndex > 0) { if(self.initialFocusIndex > 0) {
// note: causes redraw() // note: causes redraw()
@ -221,14 +261,7 @@ exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher(
msgListView.redraw(); msgListView.redraw();
} }
return callback(null); self.populateCustomLabelsForSelected(self.initialFocusIndex || 0);
},
function drawOtherViews(callback) {
const messageInfo1Format = self.menuConfig.config.messageInfo1Format || '{msgNumSelected} / {msgNumTotal}';
self.setViewText(
'allViews',
MciViewIds.msgInfo1,
stringFormat(messageInfo1Format, { msgNumSelected : self.initialFocusIndex + 1, msgNumTotal : self.config.messageList.length } ));
return callback(null); return callback(null);
}, },
], ],
@ -255,4 +288,69 @@ exports.getModule = class MessageListModule extends MessageAreaConfTempSwitcher(
getMenuResult() { getMenuResult() {
return this.menuResult; return this.menuResult;
} }
enableMessageListIndexUpdates(msgListView) {
msgListView.on('index update', idx => this.populateCustomLabelsForSelected(idx) );
}
updateMessageNumbersAfterDelete(startIndex) {
// all index -= 1 from this point on.
for(let i = startIndex; i < this.config.messageList.length; ++i) {
const msgItem = this.config.messageList[i];
msgItem.msgNum -= 1;
msgItem.text = `${msgItem.msgNum} - ${msgItem.subject} from ${msgItem.fromUserName}`; // default text
}
}
promptDeleteMessageConfirm(messageIndex, cb) {
const messageInfo = this.config.messageList[messageIndex];
if(!_.isObject(messageInfo)) {
return cb(Errors.Invalid(`Invalid message index: ${messageIndex}`));
}
// :TODO: create static userHasDeleteRights() that takes id || uuid that doesn't require full msg load
this.selectedMessageForDelete = new Message();
this.selectedMessageForDelete.load( { uuid : messageInfo.messageUuid }, err => {
if(err) {
this.selectedMessageForDelete = null;
return cb(err);
}
if(!this.selectedMessageForDelete.userHasDeleteRights(this.client.user)) {
this.selectedMessageForDelete = null;
return cb(Errors.AccessDenied('User does not have rights to delete this message'));
}
// user has rights to delete -- prompt/confirm then proceed
return this.promptConfirmDelete(cb);
});
}
promptConfirmDelete(cb) {
const promptXyView = this.viewControllers.allViews.getView(MciViewIds.allViews.delPromptXy);
if(!promptXyView) {
return cb(Errors.MissingMci(`Missing prompt XY${MciViewIds.allViews.delPromptXy} MCI`));
}
const promptOpts = {
clearAtSubmit : true,
};
if(promptXyView.dimens.width) {
promptOpts.clearWidth = promptXyView.dimens.width;
}
return this.promptForInput(
{
formName : 'delPrompt',
formId : FormIds.delPrompt,
promptName : this.config.deleteMessageFromListPrompt || 'deleteMessageFromListPrompt',
prevFormName : 'allViews',
position : promptXyView.position,
},
promptOpts,
err => {
return cb(err);
}
);
}
}; };