953 lines
35 KiB
Common Lisp
953 lines
35 KiB
Common Lisp
(text "{% extends \"root.html\" %} {% block head %}")
|
|
(title
|
|
(text "Community settings - {{ config.name }}"))
|
|
|
|
(text "{% endblock %} {% block body %} {{ macros::nav() }}")
|
|
(main
|
|
("class" "flex flex-col gap-2")
|
|
(div
|
|
("class" "pillmenu")
|
|
(a
|
|
("href" "#/general")
|
|
("data-tab-button" "general")
|
|
("class" "active")
|
|
(text "{{ icon \"settings\" }}")
|
|
(span
|
|
(text "{{ text \"settings:tab.general\" }}")))
|
|
(a
|
|
("href" "#/images")
|
|
("data-tab-button" "images")
|
|
(text "{{ icon \"image\" }}")
|
|
(span
|
|
(text "{{ text \"settings:tab.images\" }}")))
|
|
(a
|
|
("href" "#/members")
|
|
("data-tab-button" "members")
|
|
(text "{{ icon \"users-round\" }}")
|
|
(span
|
|
(text "{{ text \"communities:tab.members\" }}")))
|
|
(text "{% if can_manage_channels -%}")
|
|
(a
|
|
("href" "#/channels")
|
|
("data-tab-button" "channels")
|
|
(text "{{ icon \"rss\" }}")
|
|
(span
|
|
(text "{{ text \"communities:tab.channels\" }}")))
|
|
(text "{%- endif %} {% if can_manage_emojis -%}")
|
|
(a
|
|
("href" "#/emojis")
|
|
("data-tab-button" "emojis")
|
|
(text "{{ icon \"smile\" }}")
|
|
(span
|
|
(text "{{ text \"communities:tab.emojis\" }}")))
|
|
(text "{%- endif %}"))
|
|
(div
|
|
("class" "w-full flex flex-col gap-2")
|
|
("data-tab" "general")
|
|
(div
|
|
("id" "manage_fields")
|
|
("class" "card lowered flex flex-col gap-2")
|
|
(div
|
|
("class" "card-nest")
|
|
("ui_ident" "read_access")
|
|
(div
|
|
("class" "card small")
|
|
(b
|
|
(text "Read access")))
|
|
(div
|
|
("class" "card")
|
|
(select
|
|
("onchange" "save_access(event, 'read')")
|
|
(option
|
|
("value" "Everybody")
|
|
("selected" "{% if community.read_access == 'Everybody' -%}true{% else %}false{%- endif %}")
|
|
(text "Everybody"))
|
|
(option
|
|
("value" "Joined")
|
|
("selected" "{% if community.read_access == 'Joined' -%}true{% else %}false{%- endif %}")
|
|
(text "Joined")))))
|
|
(div
|
|
("class" "card-nest")
|
|
("ui_ident" "join_access")
|
|
(div
|
|
("class" "card small")
|
|
(b
|
|
(text "Join access")))
|
|
(div
|
|
("class" "card")
|
|
(select
|
|
("onchange" "save_access(event, 'join')")
|
|
(option
|
|
("value" "Everybody")
|
|
("selected" "{% if community.join_access == 'Everybody' -%}true{% else %}false{%- endif %}")
|
|
(text "Everybody"))
|
|
(option
|
|
("value" "Request")
|
|
("selected" "{% if community.join_access == 'Request' -%}true{% else %}false{%- endif %}")
|
|
(text "Request"))
|
|
(option
|
|
("value" "Nobody")
|
|
("selected" "{% if community.join_access == 'Nobody' -%}true{% else %}false{%- endif %}")
|
|
(text "Nobody")))))
|
|
(div
|
|
("class" "card-nest")
|
|
("ui_ident" "write_access")
|
|
(div
|
|
("class" "card small")
|
|
(b
|
|
(text "Post permission")))
|
|
(div
|
|
("class" "card")
|
|
(select
|
|
("onchange" "save_access(event, 'write')")
|
|
(option
|
|
("value" "Everybody")
|
|
("selected" "{% if community.write_access == 'Everybody' -%}true{% else %}false{%- endif %}")
|
|
(text "Everybody"))
|
|
(option
|
|
("value" "Joined")
|
|
("selected" "{% if community.write_access == 'Joined' -%}true{% else %}false{%- endif %}")
|
|
(text "Joined"))
|
|
(option
|
|
("value" "Owner")
|
|
("selected" "{% if community.write_access == 'Owner' -%}true{% else %}false{%- endif %}")
|
|
(text "Owner only")))))
|
|
(div
|
|
("class" "card-nest")
|
|
("ui_ident" "change_title")
|
|
(div
|
|
("class" "card small")
|
|
(b
|
|
(text "{{ text \"communities:label.change_title\" }}")))
|
|
(form
|
|
("class" "card flex flex-col gap-2")
|
|
("onsubmit" "change_title(event)")
|
|
(div
|
|
("class" "flex flex-col gap-1")
|
|
(label
|
|
("for" "new_title")
|
|
(text "{{ text \"communities:label.new_title\" }}"))
|
|
(input
|
|
("type" "text")
|
|
("name" "new_title")
|
|
("id" "new_title")
|
|
("placeholder" "new_title")
|
|
("required" "")
|
|
("minlength" "2")))
|
|
(button
|
|
("class" "primary")
|
|
(text "{{ icon \"check\" }}")
|
|
(span
|
|
(text "{{ text \"general:action.save\" }}"))))))
|
|
(div
|
|
("class" "card-nest")
|
|
("ui_ident" "danger_zone")
|
|
(div
|
|
("class" "card small flex gap-1 items-center red")
|
|
(text "{{ icon \"skull\" }}")
|
|
(b
|
|
(text "{{ text \"communities:label.danger_zone\" }}")))
|
|
(div
|
|
("class" "card flex flex-wrap gap-2")
|
|
(button
|
|
("class" "red lowered")
|
|
("onclick" "delete_community()")
|
|
(text "{{ icon \"trash\" }}")
|
|
(span
|
|
(text "{{ text \"communities:label.delete_community\" }}")))))
|
|
(div
|
|
("class" "flex gap-2 flex-wrap")
|
|
(button
|
|
("onclick" "save_context()")
|
|
(text "{{ icon \"check\" }}")
|
|
(span
|
|
(text "{{ text \"general:action.save\" }}")))
|
|
(a
|
|
("href" "/community/{{ community.title }}")
|
|
("class" "button secondary")
|
|
(text "{{ icon \"arrow-left\" }}")
|
|
(span
|
|
(text "{{ text \"general:action.back\" }}")))))
|
|
(div
|
|
("class" "card lowered w-full hidden flex flex-col gap-2")
|
|
("data-tab" "images")
|
|
(div
|
|
("class" "card-nest")
|
|
("ui_ident" "change_avatar")
|
|
(div
|
|
("class" "card small")
|
|
(b
|
|
(text "{{ text \"settings:label.change_avatar\" }}")))
|
|
(form
|
|
("class" "card flex gap-2 flex-row flex-wrap items-center")
|
|
("method" "post")
|
|
("enctype" "multipart/form-data")
|
|
("onsubmit" "upload_avatar(event)")
|
|
(input
|
|
("id" "avatar_file")
|
|
("name" "file")
|
|
("type" "file")
|
|
("accept" "image/png,image/jpeg,image/avif,image/webp,image/gif")
|
|
("class" "w-content"))
|
|
(button
|
|
("class" "primary")
|
|
(text "{{ icon \"check\" }}"))))
|
|
(div
|
|
("class" "card-nest")
|
|
("ui_ident" "change_banner")
|
|
(div
|
|
("class" "card small")
|
|
(b
|
|
(text "{{ text \"settings:label.change_banner\" }}")))
|
|
(form
|
|
("class" "card flex flex-col gap-2")
|
|
("method" "post")
|
|
("enctype" "multipart/form-data")
|
|
("onsubmit" "upload_banner(event)")
|
|
(div
|
|
("class" "flex gap-2 flex-row flex-wrap items-center")
|
|
(input
|
|
("id" "banner_file")
|
|
("name" "file")
|
|
("type" "file")
|
|
("accept" "image/png,image/jpeg,image/avif,image/webp")
|
|
("class" "w-content"))
|
|
(button
|
|
("class" "primary")
|
|
(text "{{ icon \"check\" }}")))
|
|
(span
|
|
("class" "fade")
|
|
(text "Use an image of 1100x350px for the best results.")))))
|
|
(div
|
|
("class" "card lowered w-full hidden flex flex-col gap-2")
|
|
("data-tab" "members")
|
|
(div
|
|
("class" "card-nest")
|
|
(div
|
|
("class" "card small")
|
|
(b
|
|
(text "{{ text \"communities:label.select_member\" }}")))
|
|
(form
|
|
("class" "card flex-col gap-2")
|
|
("onsubmit" "select_user_from_form(event)")
|
|
(div
|
|
("class" "flex flex-col gap-1")
|
|
(div
|
|
("class" "flex flex-col gap-1")
|
|
(label
|
|
("for" "uid")
|
|
(text "{{ text \"communities:label.user_id\" }}"))
|
|
(input
|
|
("type" "number")
|
|
("name" "uid")
|
|
("id" "uid")
|
|
("placeholder" "user id")
|
|
("required" "")
|
|
("minlength" "18")))
|
|
(button
|
|
("class" "primary")
|
|
(text "{{ text \"communities:action.select\" }}")))))
|
|
(div
|
|
("class" "card flex flex-col gap-2 w-full")
|
|
("id" "membership_info"))
|
|
|
|
(div
|
|
("class" "card-nest w-full")
|
|
(div
|
|
("class" "card small flex items-center justify-between gap-2")
|
|
(div
|
|
("class" "flex items-center gap-2")
|
|
(text "{{ icon \"blocks\" }}")
|
|
(span
|
|
(text "{{ text \"mod_panel:label.permissions_level_builder\" }}")))
|
|
(button
|
|
("class" "small lowered")
|
|
("onclick" "update_user_role(document.getElementById('uid').value, document.getElementById('role').value)")
|
|
(text "{{ icon \"check\" }}")
|
|
(span
|
|
(text "{{ text \"general:action.save\" }}"))))
|
|
(div
|
|
("class" "card flex flex-col gap-2")
|
|
("id" "permission_builder"))))
|
|
(text "{% if can_manage_channels -%}")
|
|
(div
|
|
("class" "card lowered w-full hidden flex flex-col gap-2")
|
|
("data-tab" "channels")
|
|
(div
|
|
("class" "card-nest")
|
|
(div
|
|
("class" "card small")
|
|
(b
|
|
(text "{{ text \"communities:action.create_channel\" }}")))
|
|
(form
|
|
("class" "card flex flex-col gap-2")
|
|
("onsubmit" "create_channel_from_form(event)")
|
|
(div
|
|
("class" "flex flex-col gap-1")
|
|
(label
|
|
("for" "title")
|
|
(text "{{ text \"communities:label.name\" }}"))
|
|
(input
|
|
("type" "text")
|
|
("name" "title")
|
|
("id" "title")
|
|
("placeholder" "name")
|
|
("required" "")
|
|
("minlength" "2")
|
|
("maxlength" "32")))
|
|
(button
|
|
("class" "primary")
|
|
(text "{{ text \"communities:action.create\" }}"))))
|
|
(text "{% for channel in channels %}")
|
|
(div
|
|
("class" "card-nest")
|
|
(div
|
|
("class" "card small")
|
|
(b
|
|
(text "{{ channel.position }} "))
|
|
(text "{{ channel.title }}"))
|
|
(div
|
|
("class" "card flex gap-2")
|
|
(button
|
|
("class" "red lowered small")
|
|
("onclick" "delete_channel('{{ channel.id }}')")
|
|
(text "{{ text \"general:action.delete\" }}"))
|
|
(button
|
|
("class" "lowered small")
|
|
("onclick" "update_channel_position('{{ channel.id }}')")
|
|
(text "{{ text \"chats:action.move\" }}"))
|
|
(button
|
|
("class" "lowered small")
|
|
("onclick" "update_channel_title('{{ channel.id }}')")
|
|
(text "{{ text \"chats:action.rename\" }}"))))
|
|
(text "{% endfor %}"))
|
|
(script
|
|
(text "globalThis.delete_channel = async (id) => {
|
|
if (
|
|
!(await trigger(\"atto::confirm\", [
|
|
\"Are you sure you would like to do this?\",
|
|
]))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
fetch(`/api/v1/channels/${id}`, {
|
|
method: \"DELETE\",
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};
|
|
|
|
globalThis.update_channel_position = async (id) => {
|
|
await trigger(\"atto::debounce\", [\"channels::move\"]);
|
|
|
|
const position = Number.parseInt(
|
|
await trigger(\"atto::prompt\", [
|
|
\"New channel position (number):\",
|
|
]),
|
|
);
|
|
|
|
if (!position && position !== 0) {
|
|
return alert(\"Must be a number!\");
|
|
}
|
|
|
|
fetch(`/api/v1/channels/${id}/move`, {
|
|
method: \"POST\",
|
|
headers: {
|
|
\"Content-Type\": \"application/json\",
|
|
},
|
|
body: JSON.stringify({
|
|
position,
|
|
}),
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};
|
|
|
|
globalThis.update_channel_title = async (id) => {
|
|
await trigger(\"atto::debounce\", [\"channels::update_title\"]);
|
|
const title = await trigger(\"atto::prompt\", [\"New channel title:\"]);
|
|
|
|
if (!title) {
|
|
return;
|
|
}
|
|
|
|
fetch(`/api/v1/channels/${id}/title`, {
|
|
method: \"POST\",
|
|
headers: {
|
|
\"Content-Type\": \"application/json\",
|
|
},
|
|
body: JSON.stringify({
|
|
title,
|
|
}),
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};
|
|
|
|
async function create_channel_from_form(e) {
|
|
e.preventDefault();
|
|
await trigger(\"atto::debounce\", [\"channels::create\"]);
|
|
|
|
fetch(\"/api/v1/channels\", {
|
|
method: \"POST\",
|
|
headers: {
|
|
\"Content-Type\": \"application/json\",
|
|
},
|
|
body: JSON.stringify({
|
|
title: e.target.title.value,
|
|
community: \"{{ community.id }}\",
|
|
}),
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
|
|
if (res.ok) {
|
|
window.location.reload();
|
|
}
|
|
});
|
|
}"))
|
|
(text "{%- endif %} {% if can_manage_emojis -%}")
|
|
(div
|
|
("class" "card lowered w-full hidden flex flex-col gap-2")
|
|
("data-tab" "emojis")
|
|
(text "{{ components::supporter_ad(body=\"Become a supporter to upload GIF animated emojis!\") }}")
|
|
(div
|
|
("class" "card-nest")
|
|
("ui_ident" "change_banner")
|
|
(div
|
|
("class" "card small flex items-center gap-2")
|
|
(text "{{ icon \"upload\" }}")
|
|
(b
|
|
(text "{{ text \"communities:label.upload\" }}")))
|
|
(form
|
|
("class" "card flex flex-col gap-2")
|
|
("onsubmit" "upload_emoji(event)")
|
|
(div
|
|
("class" "flex flex-col gap-1")
|
|
(label
|
|
("for" "name")
|
|
(text "{{ text \"communities:label.name\" }}"))
|
|
(input
|
|
("type" "text")
|
|
("name" "name")
|
|
("id" "name")
|
|
("placeholder" "name")
|
|
("required" "")
|
|
("minlength" "2")
|
|
("maxlength" "32")))
|
|
(div
|
|
("class" "flex flex-col gap-1")
|
|
(label
|
|
("for" "file")
|
|
(text "{{ text \"communities:label.file\" }}"))
|
|
(input
|
|
("id" "banner_file")
|
|
("name" "file")
|
|
("type" "file")
|
|
("accept" "image/png,image/jpeg,image/avif,image/webp")
|
|
("class" "w-full")))
|
|
(button
|
|
(text "{{ text \"communities:action.create\" }}"))
|
|
(span
|
|
("class" "fade")
|
|
(text "Emojis can be a maximum of 256 KiB, or 512x512px (width x
|
|
height)."))))
|
|
(text "{% for emoji in emojis %}")
|
|
(div
|
|
("class" "card secondary flex flex-wrap gap-2 items-center justify-between")
|
|
(div
|
|
("class" "flex gap-2 items-center")
|
|
(img
|
|
("src" "/api/v1/communities/{{ community.id }}/emojis/{{ emoji.name }}")
|
|
("alt" "{{ emoji.name }}")
|
|
("class" "emoji")
|
|
("loading" "lazy"))
|
|
(b
|
|
(text "{{ emoji.name }}")))
|
|
(div
|
|
("class" "flex gap-2")
|
|
(button
|
|
("class" "lowered small")
|
|
("onclick" "rename_emoji('{{ emoji.id }}')")
|
|
(text "{{ icon \"pencil\" }}")
|
|
(span
|
|
(text "{{ text \"chats:action.rename\" }}")))
|
|
(button
|
|
("class" "lowered small red")
|
|
("onclick" "remove_emoji('{{ emoji.id }}')")
|
|
(text "{{ icon \"x\" }}")
|
|
(span
|
|
(text "{{ text \"stacks:label.remove\" }}")))))
|
|
(text "{% endfor %}"))
|
|
(script
|
|
(text "globalThis.upload_emoji = (e) => {
|
|
e.preventDefault();
|
|
e.target.querySelector(\"button\").style.display = \"none\";
|
|
|
|
fetch(
|
|
`/api/v1/communities/{{ community.id }}/emojis/${e.target.name.value}`,
|
|
{
|
|
method: \"POST\",
|
|
body: e.target.file.files[0],
|
|
},
|
|
)
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
|
|
e.target.querySelector(\"button\").removeAttribute(\"style\");
|
|
});
|
|
|
|
alert(\"Emoji upload in progress. Please wait!\");
|
|
};
|
|
|
|
globalThis.rename_emoji = async (id) => {
|
|
const name = await trigger(\"atto::prompt\", [\"New emoji name:\"]);
|
|
|
|
if (!name) {
|
|
return;
|
|
}
|
|
|
|
fetch(`/api/v1/emojis_id/${id}/name`, {
|
|
method: \"POST\",
|
|
headers: {
|
|
\"Content-Type\": \"application/json\",
|
|
},
|
|
body: JSON.stringify({
|
|
name,
|
|
}),
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};
|
|
|
|
globalThis.remove_emoji = async (id) => {
|
|
if (
|
|
!(await trigger(\"atto::confirm\", [
|
|
\"Are you sure you would like to do this? This action is permanent.\",
|
|
]))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
fetch(`/api/v1/emojis_id/${id}`, {
|
|
method: \"DELETE\",
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};"))
|
|
(text "{%- endif %}"))
|
|
|
|
(script
|
|
(text "setTimeout(async () => {
|
|
const element = document.getElementById(\"membership_info\");
|
|
const ui = await ns(\"ui\");
|
|
|
|
const uid = new URLSearchParams(window.location.search).get(\"uid\");
|
|
if (uid) {
|
|
document.getElementById(\"uid\").value = uid;
|
|
}
|
|
|
|
globalThis.update_user_role = async (uid, new_role) => {
|
|
if (
|
|
!(await trigger(\"atto::confirm\", [
|
|
\"Are you sure you would like to do this?\",
|
|
]))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
fetch(
|
|
`/api/v1/communities/{{ community.id }}/memberships/${uid}/role`,
|
|
{
|
|
method: \"POST\",
|
|
headers: {
|
|
\"Content-Type\": \"application/json\",
|
|
},
|
|
body: JSON.stringify({
|
|
role: Number.parseInt(new_role),
|
|
}),
|
|
},
|
|
)
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};
|
|
|
|
globalThis.kick_user = async (uid, new_role) => {
|
|
if (
|
|
!(await trigger(\"atto::confirm\", [
|
|
\"Are you sure you would like to do this?\",
|
|
]))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
fetch(`/api/v1/communities/{{ community.id }}/memberships/${uid}`, {
|
|
method: \"DELETE\",
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};
|
|
|
|
globalThis.transfer_ownership = async (uid) => {
|
|
if (
|
|
!(await trigger(\"atto::confirm\", [
|
|
\"Are you sure you would like to do this?\\n\\nThis action is PERMANENT!\",
|
|
]))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
fetch(`/api/v1/communities/{{ community.id }}/transfer_ownership`, {
|
|
method: \"POST\",
|
|
headers: {
|
|
\"Content-Type\": \"application/json\",
|
|
},
|
|
body: JSON.stringify({
|
|
user: uid,
|
|
}),
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};
|
|
|
|
globalThis.select_user_from_form = (e) => {
|
|
e.preventDefault();
|
|
fetch(
|
|
`/api/v1/communities/{{ community.id }}/memberships/${e.target.uid.value}`,
|
|
)
|
|
.then((res) => res.json())
|
|
.then(async (res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
|
|
if (!res.ok) {
|
|
return;
|
|
}
|
|
|
|
// permissions manager
|
|
const get_permissions_html = await trigger(
|
|
\"ui::generate_permissions_ui\",
|
|
[
|
|
{
|
|
// https://trisuaso.github.io/tetratto/tetratto/model/communities_permissions/struct.CommunityPermission.html
|
|
DEFAULT: 1 << 0,
|
|
ADMINISTRATOR: 1 << 1,
|
|
MEMBER: 1 << 2,
|
|
MANAGE_POSTS: 1 << 3,
|
|
MANAGE_ROLES: 1 << 4,
|
|
BANNED: 1 << 5,
|
|
REQUESTED: 1 << 6,
|
|
MANAGE_PINS: 1 << 7,
|
|
MANAGE_COMMUNITY: 1 << 8,
|
|
MANAGE_QUESTIONS: 1 << 9,
|
|
MANAGE_CHANNELS: 1 << 10,
|
|
MANAGE_MESSAGES: 1 << 11,
|
|
MANAGE_EMOJIS: 1 << 12,
|
|
},
|
|
],
|
|
);
|
|
|
|
// ...
|
|
element.innerHTML = `<div class=\"flex gap-2 flex-wrap\" ui_ident=\"actions\">
|
|
<a target=\"_blank\" class=\"button\" href=\"/api/v1/auth/user/find/${e.target.uid.value}\">Open user profile</a>
|
|
${res.payload.role !== 33 ? `<button class=\"red lowered\" onclick=\"update_user_role('${e.target.uid.value}', 33)\">Ban</button>` : `<button class=\"lowered\" onclick=\"update_user_role('${e.target.uid.value}', 5)\">Unban</button>`}
|
|
${res.payload.role !== 65 ? `<button class=\"red lowered\" onclick=\"update_user_role('${e.target.uid.value}', 65)\">Send to review</button>` : `<button class=\"green lowered\" onclick=\"update_user_role('${e.target.uid.value}', 5)\">Accept join request</button>`}
|
|
<button class=\"red lowered\" onclick=\"kick_user('${e.target.uid.value}')\">Kick</button>
|
|
<button class=\"red lowered\" onclick=\"transfer_ownership('${e.target.uid.value}')\">Transfer ownership</button>
|
|
</div>`;
|
|
|
|
document.getElementById(\"permission_builder\").innerHTML =
|
|
get_permissions_html(res.payload.role, \"permission_builder\");
|
|
|
|
ui.refresh_container(element, [\"actions\", \"permissions\"]);
|
|
ui.generate_settings_ui(
|
|
element,
|
|
[
|
|
[
|
|
[\"role\", \"Permission level\"],
|
|
res.payload.role,
|
|
\"input\",
|
|
],
|
|
],
|
|
null,
|
|
{
|
|
role: (new_role) => {
|
|
const [matching, _] =
|
|
all_matching_permissions(new_role);
|
|
|
|
document.getElementById(
|
|
\"permissions\",
|
|
).innerHTML = get_permissions_html(
|
|
rebuild_role(matching),
|
|
\"permissions\",
|
|
);
|
|
|
|
return update_user_role(
|
|
e.target.uid.value,
|
|
new_role,
|
|
);
|
|
},
|
|
},
|
|
);
|
|
});
|
|
};
|
|
}, 250);"))
|
|
|
|
(script
|
|
("type" "application/json")
|
|
("id" "settings_json")
|
|
(text "{{ community.context|json_encode()|safe }}"))
|
|
|
|
(script
|
|
(text "setTimeout(async () => {
|
|
const ui = await ns(\"ui\");
|
|
const settings = JSON.parse(
|
|
document.getElementById(\"settings_json\").innerHTML,
|
|
);
|
|
|
|
globalThis.upload_avatar = (e) => {
|
|
e.preventDefault();
|
|
e.target.querySelector(\"button\").style.display = \"none\";
|
|
|
|
fetch(\"/api/v1/communities/{{ community.id }}/upload/avatar\", {
|
|
method: \"POST\",
|
|
body: e.target.file.files[0],
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
|
|
e.target.querySelector(\"button\").removeAttribute(\"style\");
|
|
});
|
|
|
|
alert(\"Avatar upload in progress. Please wait!\");
|
|
};
|
|
|
|
globalThis.upload_banner = (e) => {
|
|
e.preventDefault();
|
|
e.target.querySelector(\"button\").style.display = \"none\";
|
|
|
|
fetch(\"/api/v1/communities/{{ community.id }}/upload/banner\", {
|
|
method: \"POST\",
|
|
body: e.target.file.files[0],
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
|
|
e.target.querySelector(\"button\").removeAttribute(\"style\");
|
|
});
|
|
|
|
alert(\"Banner upload in progress. Please wait!\");
|
|
};
|
|
|
|
globalThis.save_context = () => {
|
|
fetch(\"/api/v1/communities/{{ community.id }}/context\", {
|
|
method: \"POST\",
|
|
headers: {
|
|
\"Content-Type\": \"application/json\",
|
|
},
|
|
body: JSON.stringify({
|
|
context: settings,
|
|
}),
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};
|
|
|
|
globalThis.save_access = (event, mode) => {
|
|
const selected = event.target.selectedOptions[0];
|
|
fetch(`/api/v1/communities/{{ community.id }}/access/${mode}`, {
|
|
method: \"POST\",
|
|
headers: {
|
|
\"Content-Type\": \"application/json\",
|
|
},
|
|
body: JSON.stringify({
|
|
access: selected.value,
|
|
}),
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};
|
|
|
|
globalThis.change_title = async (e) => {
|
|
e.preventDefault();
|
|
|
|
if (
|
|
!(await trigger(\"atto::confirm\", [
|
|
\"Are you sure you would like to do this?\",
|
|
]))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
fetch(\"/api/v1/communities/{{ community.id }}/title\", {
|
|
method: \"POST\",
|
|
headers: {
|
|
\"Content-Type\": \"application/json\",
|
|
},
|
|
body: JSON.stringify({
|
|
title: e.target.new_title.value,
|
|
}),
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};
|
|
|
|
globalThis.delete_community = async () => {
|
|
if (
|
|
!(await trigger(\"atto::confirm\", [
|
|
\"Are you sure you would like to do this? This action is permanent.\",
|
|
]))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
fetch(`/api/v1/communities/{{ community.id }}`, {
|
|
method: \"DELETE\",
|
|
})
|
|
.then((res) => res.json())
|
|
.then((res) => {
|
|
trigger(\"atto::toast\", [
|
|
res.ok ? \"success\" : \"error\",
|
|
res.message,
|
|
]);
|
|
});
|
|
};
|
|
|
|
ui.refresh_container(document.getElementById(\"manage_fields\"), [
|
|
\"read_access\",
|
|
\"join_access\",
|
|
\"write_access\",
|
|
\"change_title\",
|
|
\"change_avatar\",
|
|
\"change_banner\",
|
|
]);
|
|
|
|
const settings_fields = [
|
|
[
|
|
[\"display_name\", \"Display title\"],
|
|
\"{{ community.context.display_name }}\",
|
|
\"input\",
|
|
],
|
|
[
|
|
[\"description\", \"Description\"],
|
|
settings.description,
|
|
\"textarea\",
|
|
],
|
|
[
|
|
[\"is_nsfw\", \"Mark as NSFW\"],
|
|
\"{{ community.context.is_nsfw }}\",
|
|
\"checkbox\",
|
|
]
|
|
];
|
|
|
|
// {% if not community.is_forge %}
|
|
settings_fields.push([
|
|
[
|
|
\"enable_questions\",
|
|
\"Allow users to ask questions in this community\",
|
|
],
|
|
\"{{ community.context.enable_questions }}\",
|
|
\"checkbox\",
|
|
]);
|
|
|
|
settings_fields.push([
|
|
[
|
|
\"enable_titles\",
|
|
\"Allow users to attach a title to their posts\",
|
|
],
|
|
\"{{ community.context.enable_titles }}\",
|
|
\"checkbox\",
|
|
]);
|
|
|
|
settings_fields.push([
|
|
[
|
|
\"require_titles\",
|
|
\"Require users to attach a title to their posts\",
|
|
],
|
|
\"{{ community.context.require_titles }}\",
|
|
\"checkbox\",
|
|
]);
|
|
// {% endif %}
|
|
|
|
ui.generate_settings_ui(
|
|
document.getElementById(\"manage_fields\"),
|
|
settings_fields,
|
|
settings,
|
|
);
|
|
}, 250);"))
|
|
|
|
(text "{% endblock %}")
|