Improved the performance of the permission editor. (Spliting tasks in smaller pices)

This commit is contained in:
WolverinDEV 2018-12-02 18:55:08 +01:00
parent bbdae986b8
commit 86eb36b1e4
4 changed files with 388 additions and 300 deletions

View file

@ -73,7 +73,7 @@
align-items: center;
border: grey solid;
border-width: 0px 0px 1px 0px;
border-width: 0 0 1px 0;
background-color: lightgreen;
}
@ -287,9 +287,12 @@ footer .container {
display: flex;
justify-content: stretch;
/*
overflow: auto;
overflow-x: visible;
*/
overflow: hidden;
overflow-y: auto;
background: white;
border: 2px solid lightgray;

View file

@ -820,7 +820,7 @@
</div>
</div>
{{else}}
<div class="entry group">
<div class="entry group tab-show-partitional">
<div class="title"><div class="arrow down"></div><a>{{>name}}</a></div>
<div class="group-entries">
{{for entries tmpl="tmpl_permission_entry"/}}

View file

@ -3,20 +3,12 @@
/// <reference path="../../client.ts" />
namespace Modals {
export function spawnPermissionEdit() : Modal {
const connectModal = createModal({
header: function() {
return "Server Permissions";
},
body: function () {
let properties: any = {};
let start, end;
start = Date.now();
{
let groups = globalClient.permissions.groupedPermissions();
async function build_permission_editor() : Promise<JQuery[]> {
let root_entry: any = {};
root_entry.entries = [];
{ /* lets build the stuff (~5ms) */
let groups = globalClient.permissions.groupedPermissions();
let entry_stack: any[] = [root_entry];
let insert_group = (group: GroupedPermissions) => {
@ -40,31 +32,74 @@ namespace Modals {
}
};
groups.forEach(entry => insert_group(entry));
}
root_entry.permissions = root_entry.entries;
properties["permissions_group_server"] = $("#tmpl_permission_explorer").renderTag(root_entry);
properties["permissions_group_channel"] = properties["permissions_group_server"].clone();
properties["permissions_channel"] = properties["permissions_group_server"].clone();
properties["permissions_client"] = properties["permissions_group_server"].clone();
properties["permissions_client_channel"] = properties["permissions_group_server"].clone();
const start = Date.now();
console.log("begin render");
const rendered = $("#tmpl_permission_explorer").renderTag(root_entry);
console.log("end (%o)", Date.now() - start);
const result: JQuery[] = [];
for(let i = 0; i < 4; i++)
await new Promise(resolve => setTimeout(() => {
const start = Date.now();
console.log("begin");
result.push(rendered.clone());
console.log("end (%o)", Date.now() - start);
resolve();
}, 5));
result.push(rendered);
return result;
}
end = Date.now();
console.log("Generate: %s", end - start);
start = end;
export function spawnPermissionEdit() : Modal {
const connectModal = createModal({
header: function() {
return "Server Permissions";
},
body: function () {
let properties: any = {};
const tags: JQuery[] = [$.spawn("div"), $.spawn("div"), $.spawn("div"), $.spawn("div"), $.spawn("div")];
properties["permissions_group_server"] = tags[0];
properties["permissions_group_channel"] = tags[1];
properties["permissions_channel"] = tags[2];
properties["permissions_client"] = tags[3];
properties["permissions_client_channel"] = tags[4];
let tag = $.spawn("div").append($("#tmpl_server_permissions").renderTag(properties)).tabify(false);
end = Date.now();
console.log("Tab: %s", end - start);
start = end;
setTimeout(() => {
console.log("HEAVY 1");
build_permission_editor().then(result => {
console.log("Result!");
for(let i = 0; i < 5; i++)
tags[i].replaceWith(result[i]);
setTimeout(() => {
console.log("HEAVY 2");
const task_queue: (() => Promise<any>)[] = [];
task_queue.push(apply_server_groups.bind(undefined, tag.find(".layout-group-server")));
task_queue.push(apply_channel_groups.bind(undefined, tag.find(".layout-group-channel")));
task_queue.push(apply_channel_permission.bind(undefined, tag.find(".layout-channel")));
task_queue.push(apply_client_permission.bind(undefined, tag.find(".layout-client")));
task_queue.push(apply_client_channel_permission.bind(undefined, tag.find(".layout-client-channel")));
const task_invokder = () => {
if(task_queue.length == 0) return;
task_queue.pop_front()().then(() => setTimeout(task_invokder, 0));
};
setTimeout(task_invokder, 5);
}, 1000);
});
}, 1000);
apply_server_groups(tag.find(".layout-group-server"));
apply_channel_groups(tag.find(".layout-group-channel"));
apply_channel_permission(tag.find(".layout-channel"));
apply_client_permission(tag.find(".layout-client"));
apply_client_channel_permission(tag.find(".layout-client-channel"));
end = Date.now();
console.log("Listeners: %s", end - start);
start = end;
return tag;
},
footer: function () {
@ -91,10 +126,23 @@ namespace Modals {
return connectModal;
}
function display_permissions(permission_tag: JQuery, permissions: PermissionValue[]) {
async function display_permissions(permission_tag: JQuery, permissions: PermissionValue[]) {
permission_tag.find(".permission").addClass("unset").find(".permission-grant input").val("");
for(let perm of permissions) {
const permission_chunks: PermissionValue[][] = [];
while(permissions.length > 0) {
permission_chunks.push(permissions.slice(0, 20));
permissions = permissions.slice(20);
}
await new Promise(resolve => {
const process_chunk = () => {
if(permission_chunks.length == 0) {
resolve();
return;
}
for(let perm of permission_chunks.pop_front()) {
let tag = permission_tag.find("." + perm.type.name);
if(perm.value != undefined) {
tag.removeClass("unset");
@ -112,14 +160,21 @@ namespace Modals {
tag.find(".permission-grant input").val(perm.granted_value);
}
}
setTimeout(process_chunk, 0);
};
setTimeout(process_chunk, 0);
});
permission_tag.find(".filter-input").trigger('change');
}
function make_permission_editor(tag: JQuery, default_number: number, cb_edit: (type: PermissionInfo, value?: number, skip?: boolean, negate?: boolean) => Promise<boolean>, cb_grant_edit: (type: PermissionInfo, value?: number) => Promise<boolean>) {
async function make_permission_editor(tag: JQuery, default_number: number, cb_edit: (type: PermissionInfo, value?: number, skip?: boolean, negate?: boolean) => Promise<boolean>, cb_grant_edit: (type: PermissionInfo, value?: number) => Promise<boolean>) {
tag = tag.hasClass("permission-explorer") ? tag : tag.find(".permission-explorer");
const list = tag.find(".list");
//list.css("max-height", document.body.clientHeight * .7)
await new Promise(resolve => setTimeout(() => {
list.find(".arrow").each((idx, _entry) => {
let entry = $(_entry);
let entries = entry.parentsUntil(".group").first().parent().find("> .group-entries");
@ -133,6 +188,10 @@ namespace Modals {
});
});
resolve();
}, 0));
await new Promise(resolve => setTimeout(() => {
tag.find(".filter-input, .filter-granted").on('keyup change', event => {
let filter_mask = tag.find(".filter-input").val() as string;
let req_granted = tag.find('.filter-granted').prop("checked");
@ -162,6 +221,9 @@ namespace Modals {
});
});
resolve();
}, 0));
const expend_all = (parent) => {
(parent || list).find(".arrow").addClass("right").removeClass("down").trigger('click');
};
@ -169,6 +231,8 @@ namespace Modals {
(parent || list).find(".arrow").removeClass("right").addClass("down").trigger('click');
};
await new Promise(resolve => setTimeout(() => {
list.on('contextmenu', event => {
if (event.isDefaultPrevented()) return;
event.preventDefault();
@ -186,6 +250,10 @@ namespace Modals {
});
});
resolve();
}, 0));
await new Promise(resolve => setTimeout(() => {
tag.find(".title").each((idx, _entry) => {
let entry = $(_entry);
entry.on('click', () => {
@ -221,6 +289,10 @@ namespace Modals {
});
});
resolve();
}, 0));
await new Promise(resolve => setTimeout(() => {
tag.find(".permission").each((idx, _entry) => {
let entry = $(_entry);
@ -359,6 +431,9 @@ namespace Modals {
});
});
});
resolve();
}, 0));
}
function build_channel_tree(channel_list: JQuery, update_button: JQuery) {
@ -382,12 +457,12 @@ namespace Modals {
setTimeout(() => channel_list.find('.channel').first().trigger('click'), 0);
}
function apply_client_channel_permission(tag: JQuery) {
async function apply_client_channel_permission(tag: JQuery) {
let permission_tag = tag.find(".permission-explorer");
let channel_list = tag.find(".list-channel .entries");
permission_tag.addClass("disabled");
make_permission_editor(permission_tag, 75, (type, value, skip, negate) => {
await make_permission_editor(permission_tag, 75, (type, value, skip, negate) => {
let cldbid = parseInt(tag.find(".client-dbid").val() as string);
if(isNaN(cldbid)) return Promise.reject("invalid cldbid");
@ -484,11 +559,11 @@ namespace Modals {
});
}
function apply_client_permission(tag: JQuery) {
async function apply_client_permission(tag: JQuery) {
let permission_tag = tag.find(".permission-explorer");
permission_tag.addClass("disabled");
make_permission_editor(permission_tag, 75, (type, value, skip, negate) => {
await make_permission_editor(permission_tag, 75, (type, value, skip, negate) => {
let cldbid = parseInt(tag.find(".client-dbid").val() as string);
if(isNaN(cldbid)) return Promise.reject("invalid cldbid");
if(value != undefined) {
@ -559,11 +634,11 @@ namespace Modals {
});
}
function apply_channel_permission(tag: JQuery) {
async function apply_channel_permission(tag: JQuery) {
let channel_list = tag.find(".list-channel .entries");
let permission_tag = tag.find(".permission-explorer");
make_permission_editor(tag, 75, (type, value, skip, negate) => {
await make_permission_editor(tag, 75, (type, value, skip, negate) => {
let channel_id: number = parseInt(channel_list.find(".selected").attr("channel-id"));
let channel = globalClient.channelTree.findChannel(channel_id);
if(!channel) {
@ -636,11 +711,11 @@ namespace Modals {
});
}
function apply_channel_groups(tag: JQuery) {
async function apply_channel_groups(tag: JQuery) {
let group_list = tag.find(".list-group-channel .entries");
let permission_tag = tag.find(".permission-explorer");
make_permission_editor(tag, 75, (type, value, skip, negate) => {
await make_permission_editor(tag, 75, (type, value, skip, negate) => {
let group_id: number = parseInt(group_list.find(".selected").attr("group-id"));
let group = globalClient.groups.channelGroup(group_id);
if(!group) {
@ -737,11 +812,11 @@ namespace Modals {
setTimeout(() => group_list.find('.group').first().trigger('click'), 0);
}
function apply_server_groups(tag: JQuery) {
async function apply_server_groups(tag: JQuery) {
let group_list = tag.find(".list-group-server .entries");
let permission_tag = tag.find(".permission-explorer");
make_permission_editor(tag, 75, (type, value, skip, negate) => {
await make_permission_editor(tag, 75, (type, value, skip, negate) => {
let group_id: number = parseInt(group_list.find(".selected").attr("group-id"));
let group = globalClient.groups.serverGroup(group_id);
if(!group) {

View file

@ -37,32 +37,42 @@ var TabFunctions = {
let silentContent = $.spawn("div");
silentContent.addClass("tab-content-invisible");
template.find("x-entry").each(function () {
let hentry = $.spawn("div");
hentry.addClass("entry");
template.find("x-entry").each( (_, _entry) => {
const entry = $(_entry);
let tag_header = $.spawn("div").addClass("entry");
if(copy)
hentry.append($(this).find("x-tag").clone(true, true));
tag_header.append(entry.find("x-tag").clone(true, true));
else
hentry.append($(this).find("x-tag"));
tag_header.append(entry.find("x-tag"));
const tag_content = copy ? entry.find("x-content").clone(true, true) : entry.find("x-content");
content.append(tag_content.hide());
tag_header.on("click", () => {
if(tag_header.hasClass("selected")) return;
const _this = $(this);
const _entryContent = copy ? _this.find("x-content").clone(true, true) : _this.find("x-content");
silentContent.append(_entryContent);
hentry.on("click", function () {
if(hentry.hasClass("selected")) return;
tag.find(".tab-header .selected").removeClass("selected");
hentry.addClass("selected");
tag_header.addClass("selected");
content.children().appendTo(silentContent);
console.log(silentContent);
content.empty();
content.append(_entryContent);
//console.log(_this.find("x-content"));
//content.append(_this.find("x-content"));
content.find("> x-content").hide();
/* don't show many nodes at once */
let entries = tag_content.find(".tab-show-partitional");
entries.hide();
const show_next = index => {
console.log("Show " + index);
if(index >= entries.length) return;
entries.eq(index).show();
setTimeout(show_next.bind(undefined, index + 1), 0);
};
show_next(0);
tag_content.show();
});
console.log(this);
header.append(hentry);
header.append(tag_header);
});
header.find(".entry").first().trigger("click");