* Fix updating of existing file filter
* Update findFiles() to properly apply filters, sort order / direction, etc. * Properly persist hash tags @ file entry persist * Lots of improvements / additions to MCI for upload/download, etc. stats * Persist processed entries @ upload (WIP, but close!)
This commit is contained in:
parent
e265e3cc97
commit
fb176d3ab3
|
@ -46,6 +46,17 @@ module.exports = class FileBaseFilters {
|
|||
return filterUuid;
|
||||
}
|
||||
|
||||
replace(filterUuid, filterInfo) {
|
||||
const filter = this.get(filterUuid);
|
||||
if(!filter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
filterInfo.tags = this.cleanTags(filterInfo.tags);
|
||||
this.filters[filterUuid] = filterInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
remove(filterUuid) {
|
||||
delete this.filters[filterUuid];
|
||||
}
|
||||
|
|
|
@ -121,7 +121,13 @@ module.exports = class FileEntry {
|
|||
});
|
||||
},
|
||||
function storeHashTags(callback) {
|
||||
return callback(null);
|
||||
const hashTagsArray = Array.from(self.hashTags);
|
||||
async.each(hashTagsArray, (hashTag, next) => {
|
||||
return FileEntry.persistHashTag(self.fileId, hashTag, next);
|
||||
},
|
||||
err => {
|
||||
return callback(err);
|
||||
});
|
||||
}
|
||||
],
|
||||
err => {
|
||||
|
@ -192,6 +198,30 @@ module.exports = class FileEntry {
|
|||
);
|
||||
}
|
||||
|
||||
static persistHashTag(fileId, hashTag, cb) {
|
||||
fileDb.serialize( () => {
|
||||
fileDb.run(
|
||||
`INSERT OR IGNORE INTO hash_tag (hash_tag)
|
||||
VALUES (?);`,
|
||||
[ hashTag ]
|
||||
);
|
||||
|
||||
fileDb.run(
|
||||
`REPLACE INTO file_hash_tag (hash_tag_id, file_id)
|
||||
VALUES (
|
||||
(SELECT hash_tag_id
|
||||
FROM hash_tag
|
||||
WHERE hash_tag = ?),
|
||||
?
|
||||
);`,
|
||||
[ hashTag, fileId ],
|
||||
err => {
|
||||
return cb(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
loadHashTags(cb) {
|
||||
fileDb.each(
|
||||
`SELECT ht.hash_tag_id, ht.hash_tag
|
||||
|
@ -226,20 +256,20 @@ module.exports = class FileEntry {
|
|||
static getWellKnownMetaValues() { return Object.keys(FILE_WELL_KNOWN_META); }
|
||||
|
||||
static findFiles(filter, cb) {
|
||||
// :TODO: build search here - return [ fileid1, fileid2, ... ]
|
||||
// free form
|
||||
// areaTag
|
||||
// tags
|
||||
// order by
|
||||
// sort
|
||||
|
||||
filter = filter || {};
|
||||
|
||||
let sql =
|
||||
`SELECT file_id
|
||||
FROM file`;
|
||||
|
||||
let sql;
|
||||
let sqlWhere = '';
|
||||
let sqlOrderBy;
|
||||
const sqlOrderDir = 'ascending' === filter.order ? 'ASC' : 'DESC';
|
||||
|
||||
function getOrderByWithCast(ob) {
|
||||
if( [ 'dl_count', 'user_rating', 'est_release_year', 'byte_size' ].indexOf(filter.sort) > -1 ) {
|
||||
return `ORDER BY CAST(${ob} AS INTEGER)`;
|
||||
}
|
||||
|
||||
return `ORDER BY ${ob}`;
|
||||
}
|
||||
|
||||
function appendWhereClause(clause) {
|
||||
if(sqlWhere) {
|
||||
|
@ -250,13 +280,38 @@ module.exports = class FileEntry {
|
|||
sqlWhere += clause;
|
||||
}
|
||||
|
||||
if(filter.sort) {
|
||||
if(Object.keys(FILE_WELL_KNOWN_META).indexOf(filter.sort) > -1) { // sorting via a meta value?
|
||||
sql =
|
||||
`SELECT f.file_id
|
||||
FROM file f, file_meta m`;
|
||||
|
||||
appendWhereClause(`f.file_id = m.file_id AND m.meta_name="${filter.sort}"`);
|
||||
|
||||
sqlOrderBy = `${getOrderByWithCast('m.meta_value')} ${sqlOrderDir}`;
|
||||
} else {
|
||||
sql =
|
||||
`SELECT f.file_id, f.${filter.sort}
|
||||
FROM file f`;
|
||||
|
||||
sqlOrderBy = getOrderByWithCast(`f.${filter.sort}`) + sqlOrderDir;
|
||||
}
|
||||
} else {
|
||||
sql =
|
||||
`SELECT f.file_id
|
||||
FROM file`;
|
||||
|
||||
sqlOrderBy = `${getOrderByWithCast('f.file_id')} ${sqlOrderDir}`;
|
||||
}
|
||||
|
||||
|
||||
if(filter.areaTag) {
|
||||
appendWhereClause(`area_tag="${filter.areaTag}"`);
|
||||
appendWhereClause(`f.area_tag="${filter.areaTag}"`);
|
||||
}
|
||||
|
||||
if(filter.terms) {
|
||||
appendWhereClause(
|
||||
`file_id IN (
|
||||
`f.file_id IN (
|
||||
SELECT rowid
|
||||
FROM file_fts
|
||||
WHERE file_fts MATCH "${filter.terms.replace(/"/g,'""')}"
|
||||
|
@ -265,25 +320,24 @@ module.exports = class FileEntry {
|
|||
}
|
||||
|
||||
if(filter.tags) {
|
||||
const tags = filter.tags.split(' '); // filter stores as sep separated values
|
||||
// build list of quoted tags; filter.tags comes in as a space separated values
|
||||
const tags = filter.tags.split(' ').map( tag => `"${tag}"` ).join(',');
|
||||
|
||||
appendWhereClause(
|
||||
`file_id IN (
|
||||
`f.file_id IN (
|
||||
SELECT file_id
|
||||
FROM file_hash_tag
|
||||
WHERE hash_tag_id IN (
|
||||
SELECT hash_tag_id
|
||||
FROM hash_tag
|
||||
WHERE hash_tag IN (${tags.join(',')})
|
||||
WHERE hash_tag IN (${tags})
|
||||
)
|
||||
)`
|
||||
);
|
||||
}
|
||||
|
||||
// :TODO: filter.orderBy
|
||||
// :TODO: filter.sort
|
||||
sql += `${sqlWhere} ${sqlOrderBy};`;
|
||||
|
||||
sql += sqlWhere + ';';
|
||||
const matchingFileIds = [];
|
||||
fileDb.each(sql, (err, fileId) => {
|
||||
if(fileId) {
|
||||
|
|
|
@ -37,6 +37,17 @@ function setNextRandomRumor(cb) {
|
|||
});
|
||||
}
|
||||
|
||||
function getRatio(client, propA, propB) {
|
||||
const a = StatLog.getUserStatNum(client.user, propA);
|
||||
const b = StatLog.getUserStatNum(client.user, propB);
|
||||
const ratio = ~~((a / b) * 100);
|
||||
return `${ratio}%`;
|
||||
}
|
||||
|
||||
function userStatAsString(client, statName, defaultValue) {
|
||||
return (StatLog.getUserStat(client.user, statName) || defaultValue).toString();
|
||||
}
|
||||
|
||||
function getPredefinedMCIValue(client, code) {
|
||||
|
||||
if(!client || !code) {
|
||||
|
@ -69,16 +80,16 @@ function getPredefinedMCIValue(client, code) {
|
|||
UN : function userName() { return client.user.username; },
|
||||
UI : function userId() { return client.user.userId.toString(); },
|
||||
UG : function groups() { return _.values(client.user.groups).join(', '); },
|
||||
UR : function realName() { return client.user.properties.real_name; },
|
||||
LO : function location() { return client.user.properties.location; },
|
||||
UR : function realName() { return userStatAsString(client, 'real_name', ''); },
|
||||
LO : function location() { return userStatAsString(client, 'location', ''); },
|
||||
UA : function age() { return client.user.getAge().toString(); },
|
||||
UB : function birthdate() { return moment(client.user.properties.birthdate).format(client.currentTheme.helpers.getDateFormat()); },
|
||||
US : function sex() { return client.user.properties.sex; },
|
||||
UE : function emailAddres() { return client.user.properties.email_address; },
|
||||
UW : function webAddress() { return client.user.properties.web_address; },
|
||||
UF : function affils() { return client.user.properties.affiliation; },
|
||||
UT : function themeId() { return client.user.properties.theme_id; },
|
||||
UC : function loginCount() { return client.user.properties.login_count.toString(); },
|
||||
BD : function birthdate() { return moment(client.user.properties.birthdate).format(client.currentTheme.helpers.getDateFormat()); }, // iNiQUiTY
|
||||
US : function sex() { return userStatAsString(client, 'sex', ''); },
|
||||
UE : function emailAddres() { return userStatAsString(client, 'email_address', ''); },
|
||||
UW : function webAddress() { return userStatAsString(client, 'web_address', ''); },
|
||||
UF : function affils() { return userStatAsString(client, 'affiliation', ''); },
|
||||
UT : function themeId() { return userStatAsString(client, 'theme_id', ''); },
|
||||
UC : function loginCount() { return userStatAsString(client, 'login_count', 0); },
|
||||
ND : function connectedNode() { return client.node.toString(); },
|
||||
IP : function clientIpAddress() { return client.address().address; },
|
||||
ST : function serverName() { return client.session.serverName; },
|
||||
|
@ -86,26 +97,27 @@ function getPredefinedMCIValue(client, code) {
|
|||
const activeFilter = FileBaseFilters.getActiveFilter(client);
|
||||
return activeFilter ? activeFilter.name : '';
|
||||
},
|
||||
DN : function userNumDownloads() { return StatLog.getUserStat(client.user, 'dl_total_count'); }, // Obv/2
|
||||
DK : function userByteDownload() { // Obv/2
|
||||
const byteSize = parseInt(StatLog.getUserStat(client.user, 'dl_total_bytes')) || 0;
|
||||
return formatByteSize(byteSize, true);
|
||||
DN : function userNumDownloads() { return userStatAsString(client, 'dl_total_count', 0); }, // Obv/2
|
||||
DK : function userByteDownload() { // Obv/2 uses DK=downloaded Kbytes
|
||||
const byteSize = StatLog.getUserStatNum(client.user, 'dl_total_bytes');
|
||||
return formatByteSize(byteSize, true); // true=withAbbr
|
||||
},
|
||||
UP : function userNumUploads() { return userStatAsString(client, 'ul_total_count', 0); }, // Obv/2
|
||||
UK : function userByteUpload() { // Obv/2 uses UK=uploaded Kbytes
|
||||
const byteSize = StatLog.getUserStatNum(client.user, 'ul_total_bytes');
|
||||
return formatByteSize(byteSize, true); // true=withAbbr
|
||||
},
|
||||
NR : function userUpDownRatio() { // Obv/2
|
||||
return getRatio(client, 'ul_total_count', 'dl_total_count');
|
||||
},
|
||||
KR : function userUpDownByteRatio() { // Obv/2 uses KR=upload/download Kbyte ratio
|
||||
return getRatio(client, 'ul_total_bytes', 'dl_total_bytes');
|
||||
},
|
||||
// :TODO: Up/down ratio (count)
|
||||
// :TODO: Up/down ratio (bytes)
|
||||
|
||||
MS : function accountCreated() { return moment(client.user.properties.account_created).format(client.currentTheme.helpers.getDateFormat()); },
|
||||
CS : function currentStatus() { return client.currentStatus; },
|
||||
PS : function userPostCount() {
|
||||
const postCount = client.user.properties.post_count || 0;
|
||||
return postCount.toString();
|
||||
},
|
||||
PC : function userPostCallRatio() {
|
||||
const postCount = client.user.properties.post_count || 0;
|
||||
const callCount = client.user.properties.login_count;
|
||||
const ratio = ~~((postCount / callCount) * 100);
|
||||
return `${ratio}%`;
|
||||
},
|
||||
PS : function userPostCount() { return userStatAsString(client, 'post_count', 0); },
|
||||
PC : function userPostCallRatio() { return getRatio(client, 'post_count', 'login_count'); },
|
||||
|
||||
MD : function currentMenuDescription() {
|
||||
return _.has(client, 'currentMenuModule.menuConfig.desc') ? client.currentMenuModule.menuConfig.desc : '';
|
||||
|
@ -181,6 +193,7 @@ function getPredefinedMCIValue(client, code) {
|
|||
//
|
||||
// :TODO: DD - Today's # of downloads (iNiQUiTY)
|
||||
//
|
||||
// :TODO: System stat log for total ul/dl, total ul/dl bytes
|
||||
|
||||
//
|
||||
// Special handling for XY
|
||||
|
|
|
@ -122,6 +122,10 @@ class StatLog {
|
|||
return user.properties[statName];
|
||||
}
|
||||
|
||||
getUserStatNum(user, statName) {
|
||||
return parseInt(this.getUserStat(user, statName)) || 0;
|
||||
}
|
||||
|
||||
incrementUserStat(user, statName, incrementBy, cb) {
|
||||
incrementBy = incrementBy || 1;
|
||||
|
||||
|
|
|
@ -264,9 +264,11 @@ exports.getModule = class FileAreaFilterEdit extends MenuModule {
|
|||
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 = {};
|
||||
|
|
|
@ -333,12 +333,13 @@ exports.getModule = class FileAreaList extends MenuModule {
|
|||
if(_.isString(self.currentFileEntry.desc)) {
|
||||
const descView = self.viewControllers.browse.getView(MciViewIds.browse.desc);
|
||||
if(descView) {
|
||||
/* :TODO: finish createCleanAnsi() and use here!!!
|
||||
createCleanAnsi(
|
||||
self.currentFileEntry.desc,
|
||||
{ height : self.client.termHeight, width : descView.dimens.width },
|
||||
cleanDesc => {
|
||||
descView.setText(cleanDesc);
|
||||
// :TODO: use cleanDesc -- need to finish createCleanAnsi() !!
|
||||
//descView.setText(cleanDesc);
|
||||
descView.setText( self.currentFileEntry.desc );
|
||||
|
||||
self.updateQueueIndicator();
|
||||
self.populateCustomLabels('browse', 10);
|
||||
|
@ -346,9 +347,6 @@ exports.getModule = class FileAreaList extends MenuModule {
|
|||
return callback(null);
|
||||
}
|
||||
);
|
||||
*/
|
||||
|
||||
descView.setText( self.currentFileEntry.desc );
|
||||
}
|
||||
} else {
|
||||
self.updateQueueIndicator();
|
||||
|
|
|
@ -222,7 +222,10 @@ exports.getModule = class UploadModule extends MenuModule {
|
|||
function prepDetails(scanResults, callback) {
|
||||
async.eachSeries(scanResults.newEntries, (newEntry, nextEntry) => {
|
||||
self.displayFileDetailsPageForEntry(newEntry, (err, newValues) => {
|
||||
if(!err) {
|
||||
if(err) {
|
||||
return nextEntry(err);
|
||||
}
|
||||
|
||||
// if the file entry did *not* have a desc, take the user desc
|
||||
if(!self.fileEntryHasDetectedDesc(newEntry)) {
|
||||
newEntry.desc = newValues.shortDesc.trim();
|
||||
|
@ -235,18 +238,27 @@ exports.getModule = class UploadModule extends MenuModule {
|
|||
if(newValues.tags.length > 0) {
|
||||
newEntry.setHashTags(newValues.tags);
|
||||
}
|
||||
}
|
||||
|
||||
return nextEntry(err);
|
||||
});
|
||||
}, err => {
|
||||
delete self.fileDetailsCurrentEntrySubmitCallback;
|
||||
return callback(err, scanResults);
|
||||
});
|
||||
},
|
||||
function persistNewEntries(scanResults, callback) {
|
||||
// loop over entries again & persist to DB
|
||||
async.eachSeries(scanResults.newEntries, (newEntry, nextEntry) => {
|
||||
newEntry.persist(err => {
|
||||
return nextEntry(err);
|
||||
});
|
||||
}, err => {
|
||||
return callback(err);
|
||||
});
|
||||
}
|
||||
],
|
||||
err => {
|
||||
|
||||
console.log('eh'); // :TODO: remove me :)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue