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';
|
||||
|
||||
var async = require('async');
|
||||
const db = require('../database');
|
||||
const plugins = require('../plugins');
|
||||
const Meta = require('../meta');
|
||||
const pubsub = require('../pubsub');
|
||||
|
||||
var db = require('../database');
|
||||
var plugins = require('../plugins');
|
||||
var Meta = require('../meta');
|
||||
var pubsub = require('../pubsub');
|
||||
const Settings = module.exports;
|
||||
|
||||
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) {
|
||||
callback(err, settings || {});
|
||||
});
|
||||
|
||||
await Promise.all(sortedLists.map(async function (list) {
|
||||
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) {
|
||||
db.getObjectField('settings:' + hash, field, callback);
|
||||
Settings.getOne = async function (hash, field) {
|
||||
const data = await Settings.get(hash);
|
||||
return data[field];
|
||||
};
|
||||
|
||||
Settings.set = function (hash, values, quiet, callback) {
|
||||
if (!callback && typeof quiet === 'function') {
|
||||
callback = quiet;
|
||||
quiet = false;
|
||||
} else {
|
||||
quiet = quiet || false;
|
||||
Settings.set = async function (hash, values, quiet) {
|
||||
quiet = quiet || false;
|
||||
|
||||
const sortedLists = [];
|
||||
|
||||
for (const key in values) {
|
||||
if (values.hasOwnProperty(key)) {
|
||||
if (Array.isArray(values[key]) && typeof values[key][0] !== 'string') {
|
||||
sortedLists.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.setObject('settings:' + hash, values, next);
|
||||
},
|
||||
function (next) {
|
||||
plugins.fireHook('action:settings.set', {
|
||||
plugin: hash,
|
||||
settings: values,
|
||||
if (sortedLists.length) {
|
||||
await db.delete('settings:' + hash + ':sorted-lists');
|
||||
await db.setAdd('settings:' + hash + ':sorted-lists', sortedLists);
|
||||
|
||||
await Promise.all(sortedLists.map(async function (list) {
|
||||
await db.delete('settings:' + hash + ':sorted-list:' + list);
|
||||
await Promise.all(values[list].map(async function (data, order) {
|
||||
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();
|
||||
},
|
||||
], callback);
|
||||
});
|
||||
|
||||
await Promise.all(ops);
|
||||
}
|
||||
|
||||
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) {
|
||||
var data = {};
|
||||
Settings.setOne = async function (hash, field, value) {
|
||||
const data = {};
|
||||
data[field] = value;
|
||||
Settings.set(hash, data, callback);
|
||||
await Settings.set(hash, data);
|
||||
};
|
||||
|
||||
Settings.setOnEmpty = function (hash, values, callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
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];
|
||||
}
|
||||
});
|
||||
Settings.setOnEmpty = async function (hash, values) {
|
||||
const settings = await Settings.get(hash) || {};
|
||||
const empty = {};
|
||||
|
||||
if (Object.keys(empty).length) {
|
||||
Settings.set(hash, empty, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
], callback);
|
||||
Object.keys(values).forEach(function (key) {
|
||||
if (!settings.hasOwnProperty(key)) {
|
||||
empty[key] = values[key];
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (Object.keys(empty).length) {
|
||||
await Settings.set(hash, empty);
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue