Start to build data conservation policy settings

This commit is contained in:
Pierre HUBERT 2021-02-16 18:00:26 +01:00
parent 562293a2e0
commit bb81512f2c
9 changed files with 13888 additions and 19 deletions

13655
assets/3rdparty/vueJS/vue-3.0.5.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
/**
* Server configuration
*
* @author Pierre Hubert
*/
let _serverConfigCache = null;
class ServerConfig {
static async ensureLoaded() {
if (!_serverConfigCache)
_serverConfigCache = await api("server/config");
}
/**
* @returns {StaticServerConfig}
*/
static get conf() {
return _serverConfigCache;
}
}

View File

@ -4,7 +4,7 @@
* @author Pierre HUBERT
*/
ComunicWeb.common.page = {
const Page = {
/**
* Save the current page url
@ -542,5 +542,26 @@ ComunicWeb.common.page = {
if(!ComunicWeb.common.network.getRequest(templateURL, true, afterTemplateDownload))
//An error occured
return false;
},
/**
* Load an HTML template
*
* @param {String} name The name of the template to load
*/
loadHTMLTemplate: async function(name) {
let tpl = await (await fetch(ComunicWeb.__config.templatesURL + name)).text();
for(let entry of [...tpl.matchAll("tr\\(\"[^\"]+\"\\)")])
{
entry = entry[0]
const start = entry.indexOf("\"") + 1
const end = entry.lastIndexOf("\"");
tpl = tpl.replace(entry, tr(entry.substring(start, end)))
}
return tpl;
}
};
ComunicWeb.common.page = Page;

View File

@ -186,6 +186,15 @@ const SettingsInterface = {
emojiID: id
}, true);
},
/**
* Get data conservation policy
*
* @returns {Promise<DataConservationPolicy>}
*/
getDataConservationPolicy: async function() {
return await api("settings/get_data_conservation_policy", null, true);
}
}
ComunicWeb.components.settings.interface = SettingsInterface;

View File

@ -4,7 +4,7 @@
* @author Pierre HUBERT
*/
ComunicWeb.pages.settings.sections.privacy = {
const SettingsPrivacySection = {
/**
* Open settings section
@ -12,16 +12,27 @@ ComunicWeb.pages.settings.sections.privacy = {
* @param {object} args Additionnal arguments
* @param {HTMLElement} target The target for the page
*/
open: function(args, target){
open: async function(args, target){
//Information box
try {
// Information box
this.showInfoBox(target);
// Data conservation policy
await this.showDataConservationPolicy(target);
//Export data box
this.showExportDataBox(target);
//Delete account box
this.showDeleteAccountBox(target);
}
catch(e) {
console.error(e);
target.appendChild(ComunicWeb.common.messages.createCalloutElem("Failed to load page", "The page failed to load !", "danger"));
}
},
@ -49,7 +60,7 @@ ComunicWeb.pages.settings.sections.privacy = {
appendTo: boxHead,
type: "h3",
class: "box-title",
innerHTML: "About our policy"
innerHTML: tr("About our policy")
});
//Create box body
@ -67,6 +78,93 @@ ComunicWeb.pages.settings.sections.privacy = {
})
},
/**
* Show data conservation policy
*
* @param {HTMLElement} target
*/
showDataConservationPolicy: async function(target) {
// Load template
const tpl = await Page.loadHTMLTemplate("pages/settings/privacy/ConservationPolicy.html");
const el = document.createElement("div")
el.innerHTML = tpl;
target.appendChild(el)
// Load user settings
const settings = await SettingsInterface.getDataConservationPolicy();
// Load server policy
await ServerConfig.ensureLoaded();
const serverPolicy = ServerConfig.conf;
// Use Vue
const oneDay = 60 * 60 * 24;
const lifetimeOptions = [
{label: tr("Never"), value: 0},
{label: tr("7 days"), value: oneDay * 7},
{label: tr("15 days"), value: oneDay * 15},
{label: tr("1 month"), value: oneDay * 30},
{label: tr("3 months"), value: oneDay * 30 * 3},
{label: tr("6 months"), value: oneDay * 30 * 6},
{label: tr("1 year"), value: oneDay * 365},
{label: tr("5 years"), value: oneDay * 365 * 5},
{label: tr("10 years"), value: oneDay * 365 * 10},
{label: tr("50 years"), value: oneDay * 365 * 50}
];
let findOptionIndex = (value) => {
if (!value) return lifetimeOptions[0].value;
return [...lifetimeOptions].reverse().find(v => v.value <= value).value
}
const DataConservationPolicyVueApp = {
data() {
return {
options: lifetimeOptions,
settings: [
{
title: tr("Automatically delete unread notification after"),
key: "notification_lifetime",
value: findOptionIndex(settings.notification_lifetime),
},
{
title: tr("Automatically delete your comments after"),
key: "comments_lifetime",
value: findOptionIndex(settings.comments_lifetime)
},
{
title: tr("Automatically delete your posts after"),
key: "posts_lifetime",
value: findOptionIndex(settings.posts_lifetime)
},
{
title: tr("Automatically delete your conversation messages after"),
key: "conversation_messages_lifetime",
value: findOptionIndex(settings.conversation_messages_lifetime)
},
{
title: tr("Automatically delete your likes after"),
key: "likes_lifetime",
value: findOptionIndex(settings.likes_lifetime)
},
{
title: tr("Automatically delete your account if you have been inactive for"),
key: "inactive_account_lifetime",
value: findOptionIndex(settings.inactive_account_lifetime)
}
]
}
}
}
Vue.createApp(DataConservationPolicyVueApp).mount(el);
},
/**
* Show export personnal data box
*
@ -91,7 +189,7 @@ ComunicWeb.pages.settings.sections.privacy = {
appendTo: boxHead,
type: "h3",
class: "box-title",
innerHTML: "Export account data"
innerHTML: tr("Export account data")
});
//Create box body
@ -105,7 +203,7 @@ ComunicWeb.pages.settings.sections.privacy = {
createElem2({
appendTo: boxBody,
type: "p",
innerHTML: "You can export all the data of your account from here."
innerHTML: tr("You can export all the data of your account from here.")
});
//Add delete account button
@ -113,10 +211,10 @@ ComunicWeb.pages.settings.sections.privacy = {
appendTo: boxBody,
type: "div",
class: "btn btn-primary",
innerHTML: "Export account data"
innerHTML: tr("Export account data")
});
exportAccountDataBtn.addEventListener("click", function(e){
exportAccountDataBtn.addEventListener("click", (e) => {
//Request account deletion
ComunicWeb.components.settings.helper.requestAccountDataExport();
@ -163,8 +261,7 @@ ComunicWeb.pages.settings.sections.privacy = {
createElem2({
appendTo: boxBody,
type: "p",
innerHTML: "You can decide here to delete your account. <br /><b>Warning! Warning! Warning! This operation CAN NOT BE REVERTED !!!! All your data (post, conversation " +
"messages, comments...) will be permanently deleted ! You will not be able to recover from this operation !</b>"
innerHTML: tr("You can decide here to delete your account. <br /><b>Warning! Warning! Warning! This operation CAN NOT BE REVERTED !!!! All your data (post, conversation messages, comments...) will be permanently deleted ! You will not be able to recover from this operation !</b>")
});
//Add delete account button
@ -172,7 +269,7 @@ ComunicWeb.pages.settings.sections.privacy = {
appendTo: boxBody,
type: "div",
class: "btn btn-danger",
innerHTML: "Delete your account"
innerHTML: tr("Delete your account")
});
deleteAccountBtn.addEventListener("click", function(e){
@ -184,3 +281,5 @@ ComunicWeb.pages.settings.sections.privacy = {
},
}
ComunicWeb.pages.settings.sections.privacy = SettingsPrivacySection;

18
assets/js/typings/ServerConfig.d.ts vendored Normal file
View File

@ -0,0 +1,18 @@
/**
* Server configuration typings
*
* @author Pierre Hubert
*/
declare interface DataConservationPolicySettings {
min_inactive_account_lifetime: number,
min_notification_lifetime: number,
min_comments_lifetime: number,
min_posts_lifetime: number,
min_conversation_messages_lifetime: number,
min_likes_lifetime: number0
}
declare interface StaticServerConfig {
data_conservation_policy: DataConservationPolicySettings;
}

14
assets/js/typings/Settings.d.ts vendored Normal file
View File

@ -0,0 +1,14 @@
/**
* Settings interface
*
* @author Pierre Hubert
*/
declare interface DataConservationPolicy {
inactive_account_lifetime?: number,
notification_lifetime?: number,
comments_lifetime?: number,
posts_lifetime?: number,
conversation_messages_lifetime?: number,
likes_lifetime?: number
}

View File

@ -0,0 +1,27 @@
<div class="box box-primary box-export-account-data-settings">
<div class="box-header">
<h3 class="box-title">tr("Data conservation policy")</h3>
</div>
<div class="box-body">
<p>tr("Here you can decide to automatically delete your old account data.")</p>
<!-- Counters target -->
<div class="form-group" v-for="setting in settings">
<label>{{setting.title}}</label>
<select style="width: 100%;" class="form-control select2" v-model="setting.value">
<option v-for="opt in options" v-bind:value="opt.value">{{ opt.label }}</option>
</select>
</div>
<!-- Password confirmation -->
<div class="form-group">
<label>Please type your password to update your policy</label>
<div class="input-group" style="width: 100%;">
<input class="form-control" type="password" placeholder="Your password">
</div>
</div>
<div class="btn btn-primary">tr("Update settings")</div>
</div>
</div>

View File

@ -90,6 +90,9 @@ class Dev {
//JQuery UI
"3rdparty/adminLTE/plugins/jquery-ui/jquery-ui.min.js",
// Vue JS
"3rdparty/vueJS/vue-3.0.5.js",
//iCheck
"3rdparty/adminLTE/plugins/iCheck/icheck.min.js",
@ -328,6 +331,7 @@ class Dev {
"js/common/formChecker.js",
"js/common/date.js",
"js/common/system.js",
"js/common/ServerConfig.js",
array("path" => "js/common/songPlayer.js", "uglifyjs" => false),
array("path" => "js/common/ws.js", "uglifyjs" => false),