diff --git a/src/backend/src/modules/selfhosted/DevCreditService.js b/src/backend/src/modules/selfhosted/DevCreditService.js
index 8e2978946..07b286542 100644
--- a/src/backend/src/modules/selfhosted/DevCreditService.js
+++ b/src/backend/src/modules/selfhosted/DevCreditService.js
@@ -44,12 +44,25 @@ class PermissiveCreditService extends BaseService {
const username = event.actor.type.user.username;
event.available = this.consume_user_credit_(
username, event.cost);
+ if ( ! this.config.simulated_credit ) return;
+
+ // Update usage settings tab in UI
+ svc_event.emit('outer.gui.usage.update', {
+ user_id_list: [event.actor.type.user.id],
+ response: {
+ id: 'dev-credit',
+ used: this.config.simulated_credit -
+ this.get_user_credit_(username),
+ available: this.config.simulated_credit,
+ },
+ });
});
svc_event.on('usages.query', (_, event) => {
const username = event.actor.type.user.username;
if ( ! this.config.simulated_credit ) {
event.usages.push({
+ id: 'dev-credit',
name: `Unlimited Credit`,
used: 0,
available: 1,
@@ -57,6 +70,7 @@ class PermissiveCreditService extends BaseService {
return;
}
event.usages.push({
+ id: 'dev-credit',
name: `Simulated Credit (${this.config.simulated_credit})`,
used: this.config.simulated_credit -
this.get_user_credit_(username),
diff --git a/src/gui/src/UI/Settings/UITabUsage.js b/src/gui/src/UI/Settings/UITabUsage.js
index 31effde0d..68f26d649 100644
--- a/src/gui/src/UI/Settings/UITabUsage.js
+++ b/src/gui/src/UI/Settings/UITabUsage.js
@@ -41,6 +41,7 @@ export default {
`;
},
init: ($el_window) => {
+ const sanitize_id = id => (''+id).replace(/[^A-Za-z0-9-]/g, '');
$.ajax({
url: window.api_origin + "/drivers/usage",
type: 'GET',
@@ -79,18 +80,46 @@ export default {
name = `File Conversions`;
h += `
-
+
${html_encode(name)}:
-
${Number(entry.used)} used of ${Number(entry.available)}
+
${i18n('used_of', entry)}
${Number(entry.usage_percentage)}%
`;
});
+
+ const divContent = $('.settings-content[data-settings="usage"]');
// Append driver usage bars to the container
- $('.settings-content[data-settings="usage"]').append(`
${h}
`);
+ divContent.append(`
${h}
`);
+
+ const update_usage = event => {
+ if ( ! event.usage_percentage ) {
+ event.usage_percentage = (event.used / event.available * 100).toFixed(0);
+ }
+ const el_divContent = divContent[0];
+ el_divContent
+ .querySelector(`[data-id=${sanitize_id(event.id)}] .usage-progbar`)
+ .style.width = '' + Number(event.usage_percentage) + '%';
+ el_divContent
+ .querySelector(`[data-id=${sanitize_id(event.id)}] .usage-progbar span`)
+ .innerText = '' + Number(event.usage_percentage) + '%';
+ const used_of_str = i18n('used_of', event);
+ el_divContent
+ .querySelector(`[data-id=${sanitize_id(event.id)}] > span`)
+ .innerText = used_of_str;
+ };
+
+ divContent.on('remove', () => {
+ socket.off('usage.update', update_usage);
+ });
+ socket.on('usage.update', update_usage);
}
});
diff --git a/src/gui/src/i18n/i18n.js b/src/gui/src/i18n/i18n.js
index d1aee9b15..9dd8e095e 100644
--- a/src/gui/src/i18n/i18n.js
+++ b/src/gui/src/i18n/i18n.js
@@ -27,15 +27,22 @@ const variables = {
privacy: "https://puter.com/privacy"
};
-function ReplacePlaceholders(str) {
- str = str.replace(/{{link=(.*?)}}(.*?){{\/link}}/g, (_, key, text) => `
${text}`);
- str = str.replace(/{{(.*?)}}/g, (_, key) => variables[key]);
+function ReplacePlaceholders(str, arg_variables = {}) {
+ const all_variables = { ...variables, ...arg_variables };
+ str = str.replace(/{{link=(.*?)}}(.*?){{\/link}}/g, (_, key, text) => `
${text}`);
+ str = str.replace(/{{(.*?)}}/g, (_, key) => all_variables[key]);
return str;
}
window.i18n = function (key, replacements = [], encode_html = true) {
+ let arg_variables = {};
if(Array.isArray(replacements) === false){
- replacements = [replacements];
+ if ( typeof replacements === 'object' ) {
+ arg_variables = replacements;
+ replacements = [];
+ } else {
+ replacements = [replacements];
+ }
}
let language = translations[window.locale] ?? translations['en'];
@@ -44,7 +51,7 @@ window.i18n = function (key, replacements = [], encode_html = true) {
if (!str) {
str = key;
}
- str = ReplacePlaceholders(str);
+ str = ReplacePlaceholders(str, arg_variables);
if ( encode_html ) {
str = html_encode(str);
// html_encode doesn't render line breaks
diff --git a/src/gui/src/i18n/translations/en.js b/src/gui/src/i18n/translations/en.js
index 924fd89e5..88f33b709 100644
--- a/src/gui/src/i18n/translations/en.js
+++ b/src/gui/src/i18n/translations/en.js
@@ -309,6 +309,7 @@ const en = {
unzipping: "Unzipping %strong%",
upload: 'Upload',
upload_here: 'Upload here',
+ used_of: '{{used}} used of {{available}}',
usage: 'Usage',
username: "Username",
username_changed: 'Username updated successfully.',