feat: settings sorted list (#8170)
* feat: settings sorted list see https://github.com/NodeBB/nodebb-plugin-quickstart/pull/9/files for samplev1.18.x
parent
7cc63f7d2c
commit
3c9689a5ac
@ -0,0 +1,125 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
define('settings/sorted-list', ['benchpress', 'jqueryui'], function (benchpress) {
|
||||||
|
var SortedList;
|
||||||
|
var Settings;
|
||||||
|
|
||||||
|
|
||||||
|
SortedList = {
|
||||||
|
types: ['sorted-list'],
|
||||||
|
use: function () {
|
||||||
|
Settings = this;
|
||||||
|
},
|
||||||
|
set: function ($container, values) {
|
||||||
|
var key = $container.attr('data-sorted-list');
|
||||||
|
|
||||||
|
values[key] = [];
|
||||||
|
$container.find('[data-type="item"]').each(function (idx, item) {
|
||||||
|
var itemUUID = $(item).attr('data-sorted-list-uuid');
|
||||||
|
|
||||||
|
var formData = $('[data-sorted-list-object="' + key + '"][data-sorted-list-uuid="' + itemUUID + '"]');
|
||||||
|
values[key].push(Settings.helper.serializeForm(formData));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
get: function ($container) {
|
||||||
|
var $list = $container.find('[data-type="list"]');
|
||||||
|
var key = $container.attr('data-sorted-list');
|
||||||
|
var formTpl = $container.attr('data-form-template');
|
||||||
|
|
||||||
|
benchpress.parse(formTpl, {}, function (formHtml) {
|
||||||
|
var addBtn = $('[data-sorted-list="' + key + '"] [data-type="add"]');
|
||||||
|
|
||||||
|
addBtn.on('click', function () {
|
||||||
|
var modal = bootbox.confirm(formHtml, function (save) {
|
||||||
|
if (save) {
|
||||||
|
var itemUUID = utils.generateUUID();
|
||||||
|
var form = $('<form class="" data-sorted-list-uuid="' + itemUUID + '" data-sorted-list-object="' + key + '" />');
|
||||||
|
form.append(modal.find('form').children());
|
||||||
|
|
||||||
|
$('#content').append(form.hide());
|
||||||
|
|
||||||
|
|
||||||
|
var data = Settings.helper.serializeForm(form);
|
||||||
|
parse($container, itemUUID, data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
var list = ajaxify.data.settings[key];
|
||||||
|
if (Array.isArray(list) && typeof list[0] !== 'string') {
|
||||||
|
list.forEach(function (item) {
|
||||||
|
var itemUUID = utils.generateUUID();
|
||||||
|
var form = $(formHtml).deserialize(item);
|
||||||
|
form.attr('data-sorted-list-uuid', itemUUID);
|
||||||
|
form.attr('data-sorted-list-object', key);
|
||||||
|
$('#content').append(form.hide());
|
||||||
|
|
||||||
|
parse($container, itemUUID, item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$list.sortable().addClass('pointer');
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function setupRemoveButton($container, itemUUID) {
|
||||||
|
var key = $container.attr('data-sorted-list');
|
||||||
|
|
||||||
|
var removeBtn = $('[data-sorted-list="' + key + '"] [data-type="remove"]');
|
||||||
|
removeBtn.on('click', function () {
|
||||||
|
$('[data-sorted-list-uuid="' + itemUUID + '"]').remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupEditButton($container, itemUUID) {
|
||||||
|
var $list = $container.find('[data-type="list"]');
|
||||||
|
var key = $container.attr('data-sorted-list');
|
||||||
|
var itemTpl = $container.attr('data-item-template');
|
||||||
|
var editBtn = $('[data-sorted-list-uuid="' + itemUUID + '"] [data-type="edit"]');
|
||||||
|
|
||||||
|
editBtn.on('click', function () {
|
||||||
|
var form = $('[data-sorted-list-uuid="' + itemUUID + '"][data-sorted-list-object="' + key + '"]').clone(true).show();
|
||||||
|
|
||||||
|
var modal = bootbox.confirm(form, function (save) {
|
||||||
|
if (save) {
|
||||||
|
var form = $('<form class="" data-sorted-list-uuid="' + itemUUID + '" data-sorted-list-object="' + key + '" />');
|
||||||
|
form.append(modal.find('form').children());
|
||||||
|
|
||||||
|
$('#content').find('[data-sorted-list-uuid="' + itemUUID + '"][data-sorted-list-object="' + key + '"]').remove();
|
||||||
|
$('#content').append(form.hide());
|
||||||
|
|
||||||
|
|
||||||
|
var data = Settings.helper.serializeForm(form);
|
||||||
|
|
||||||
|
benchpress.parse(itemTpl, data, function (itemHtml) {
|
||||||
|
itemHtml = $(itemHtml);
|
||||||
|
var oldItem = $list.find('[data-sorted-list-uuid="' + itemUUID + '"]');
|
||||||
|
oldItem.after(itemHtml);
|
||||||
|
oldItem.remove();
|
||||||
|
itemHtml.attr('data-sorted-list-uuid', itemUUID);
|
||||||
|
|
||||||
|
setupRemoveButton($container, itemUUID);
|
||||||
|
setupEditButton($container, itemUUID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse($container, itemUUID, data) {
|
||||||
|
var $list = $container.find('[data-type="list"]');
|
||||||
|
var itemTpl = $container.attr('data-item-template');
|
||||||
|
|
||||||
|
benchpress.parse(itemTpl, data, function (itemHtml) {
|
||||||
|
itemHtml = $(itemHtml);
|
||||||
|
$list.append(itemHtml);
|
||||||
|
itemHtml.attr('data-sorted-list-uuid', itemUUID);
|
||||||
|
|
||||||
|
setupRemoveButton($container, itemUUID);
|
||||||
|
setupEditButton($container, itemUUID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return SortedList;
|
||||||
|
});
|
@ -1,73 +1,109 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('async');
|
const db = require('../database');
|
||||||
|
const plugins = require('../plugins');
|
||||||
|
const Meta = require('../meta');
|
||||||
|
const pubsub = require('../pubsub');
|
||||||
|
|
||||||
var db = require('../database');
|
const Settings = module.exports;
|
||||||
var plugins = require('../plugins');
|
|
||||||
var Meta = require('../meta');
|
|
||||||
var pubsub = require('../pubsub');
|
|
||||||
|
|
||||||
var Settings = module.exports;
|
Settings.get = async function (hash) {
|
||||||
|
const data = await db.getObject('settings:' + hash) || {};
|
||||||
|
const sortedLists = await db.getSetMembers('settings:' + hash + ':sorted-lists');
|
||||||
|
|
||||||
Settings.get = function (hash, callback) {
|
|
||||||
db.getObject('settings:' + hash, function (err, settings) {
|
await Promise.all(sortedLists.map(async function (list) {
|
||||||
callback(err, settings || {});
|
const members = await db.getSortedSetRange('settings:' + hash + ':sorted-list:' + list, 0, -1) || [];
|
||||||
});
|
const keys = [];
|
||||||
|
|
||||||
|
data[list] = [];
|
||||||
|
for (const order of members) {
|
||||||
|
keys.push('settings:' + hash + ':sorted-list:' + list + ':' + order);
|
||||||
|
}
|
||||||
|
|
||||||
|
const objects = await db.getObjects(keys);
|
||||||
|
objects.forEach(function (obj) {
|
||||||
|
data[list].push(obj);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
Settings.getOne = function (hash, field, callback) {
|
Settings.getOne = async function (hash, field) {
|
||||||
db.getObjectField('settings:' + hash, field, callback);
|
const data = await Settings.get(hash);
|
||||||
|
return data[field];
|
||||||
};
|
};
|
||||||
|
|
||||||
Settings.set = function (hash, values, quiet, callback) {
|
Settings.set = async function (hash, values, quiet) {
|
||||||
if (!callback && typeof quiet === 'function') {
|
quiet = quiet || false;
|
||||||
callback = quiet;
|
|
||||||
quiet = false;
|
const sortedLists = [];
|
||||||
} else {
|
|
||||||
quiet = quiet || false;
|
for (const key in values) {
|
||||||
|
if (values.hasOwnProperty(key)) {
|
||||||
|
if (Array.isArray(values[key]) && typeof values[key][0] !== 'string') {
|
||||||
|
sortedLists.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async.waterfall([
|
if (sortedLists.length) {
|
||||||
function (next) {
|
await db.delete('settings:' + hash + ':sorted-lists');
|
||||||
db.setObject('settings:' + hash, values, next);
|
await db.setAdd('settings:' + hash + ':sorted-lists', sortedLists);
|
||||||
},
|
|
||||||
function (next) {
|
await Promise.all(sortedLists.map(async function (list) {
|
||||||
plugins.fireHook('action:settings.set', {
|
await db.delete('settings:' + hash + ':sorted-list:' + list);
|
||||||
plugin: hash,
|
await Promise.all(values[list].map(async function (data, order) {
|
||||||
settings: values,
|
await db.delete('settings:' + hash + ':sorted-list:' + list + ':' + order);
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
|
||||||
|
const ops = [];
|
||||||
|
sortedLists.forEach(function (list) {
|
||||||
|
const arr = values[list];
|
||||||
|
delete values[list];
|
||||||
|
|
||||||
|
arr.forEach(function (data, order) {
|
||||||
|
ops.push(db.sortedSetAdd('settings:' + hash + ':sorted-list:' + list, order, order));
|
||||||
|
ops.push(db.setObject('settings:' + hash + ':sorted-list:' + list + ':' + order, data));
|
||||||
});
|
});
|
||||||
pubsub.publish('action:settings.set.' + hash, values);
|
});
|
||||||
Meta.reloadRequired = !quiet;
|
|
||||||
next();
|
await Promise.all(ops);
|
||||||
},
|
}
|
||||||
], callback);
|
|
||||||
|
if (Object.keys(values).length) {
|
||||||
|
await db.setObject('settings:' + hash, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.fireHook('action:settings.set', {
|
||||||
|
plugin: hash,
|
||||||
|
settings: values,
|
||||||
|
});
|
||||||
|
|
||||||
|
pubsub.publish('action:settings.set.' + hash, values);
|
||||||
|
Meta.reloadRequired = !quiet;
|
||||||
};
|
};
|
||||||
|
|
||||||
Settings.setOne = function (hash, field, value, callback) {
|
Settings.setOne = async function (hash, field, value) {
|
||||||
var data = {};
|
const data = {};
|
||||||
data[field] = value;
|
data[field] = value;
|
||||||
Settings.set(hash, data, callback);
|
await Settings.set(hash, data);
|
||||||
};
|
};
|
||||||
|
|
||||||
Settings.setOnEmpty = function (hash, values, callback) {
|
Settings.setOnEmpty = async function (hash, values) {
|
||||||
async.waterfall([
|
const settings = await Settings.get(hash) || {};
|
||||||
function (next) {
|
const empty = {};
|
||||||
db.getObject('settings:' + hash, next);
|
|
||||||
},
|
|
||||||
function (settings, next) {
|
|
||||||
settings = settings || {};
|
|
||||||
var empty = {};
|
|
||||||
Object.keys(values).forEach(function (key) {
|
|
||||||
if (!settings.hasOwnProperty(key)) {
|
|
||||||
empty[key] = values[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Object.keys(empty).length) {
|
Object.keys(values).forEach(function (key) {
|
||||||
Settings.set(hash, empty, next);
|
if (!settings.hasOwnProperty(key)) {
|
||||||
} else {
|
empty[key] = values[key];
|
||||||
next();
|
}
|
||||||
}
|
});
|
||||||
},
|
|
||||||
], callback);
|
|
||||||
|
if (Object.keys(empty).length) {
|
||||||
|
await Settings.set(hash, empty);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue