IPC GUI Update Nr.8 (#771)

* Move fav-icons to img folder

* Renaming vars

* Remove unimplemented code

* Misc

* Add utils.js

* Improve i18n

* Misc

* Add i18n to index.html

* Improve i18n

* Add i18n support for all strings

* Add translation for placeholder and title

* Misc

* [Global] Links in Footer should open in new tab
[Bots] Open steam profile on click on avatar

* Misc
This commit is contained in:
SKANKHUNTER
2018-05-25 22:21:53 +02:00
committed by Łukasz Domeradzki
parent 61fa89bd36
commit 4b57a36749
12 changed files with 444 additions and 523 deletions

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -1,86 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title>ASF | Authentication</title>
<title data-i18n="auth-title">ASF | Authentication</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script> <!--Change to cdnjs once available-->
<link rel="icon" href="../favicon.png" type="image/png">
<link rel="shortcut icon" href="../favicon.ico" type="img/x-icon">
<link rel="icon" href="img/favicon.png" type="image/png">
<link rel="shortcut icon" href="img/favicon.ico" type="img/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-sweetalert/1.0.1/sweetalert.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/2.4.2/css/AdminLTE.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
'use strict';
var tmpIsAuthorized = get('IsAuthorized'),
tmpLastPage = get('CurrentPage'),
redirectPage = 'pages/commands.html';
if (tmpLastPage) {
redirectPage = tmpLastPage;
}
function store(name, val) {
if (typeof Storage !== 'undefined') {
localStorage.setItem(name, val);
} else {
window.alert('Please use a modern browser to properly view ASF GUI!');
}
}
function get(name) {
if (typeof Storage !== 'undefined') {
return localStorage.getItem(name);
} else {
window.alert('Please use a modern browser to properly view ASF GUI!');
}
}
if (tmpIsAuthorized === 'true') {
window.location.replace(redirectPage);
} else {
$.ajax({
url: '/Api/ASF',
type: 'GET',
statusCode: {
401: function () {
store('IsAuthorized', false);
store('IPCPassword', '');
},
403: function () {
store('IsAuthorized', false);
store('IPCPassword', '');
$('.lockscreen-name').remove();
$('.lockscreen-item').remove();
$('.help-block').text('You failed to authenticate properly too many times, try again in an hour.');
},
200: function () {
store('IsAuthorized', true);
window.location.replace(redirectPage);
}
}
});
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.messagestore.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.fallbacks.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.language.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.parser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.bidi.min.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/i18n.js"></script>
</head>
<body class="hold-transition lockscreen">
<div class="lockscreen-wrapper">
<div class="lockscreen-logo">
<a href="index.html"><b>Archi</b>SteamFarm</a>
</div>
<div class="lockscreen-name">IPC password required</div>
<div class="lockscreen-name" data-i18n="auth-ipc-header">IPC password required</div>
<div class="lockscreen-item">
<div class="lockscreen-image">
<img src="favicon.png" alt="User Image">
<img src="img/favicon.png" alt="ASF">
</div>
<form class="lockscreen-credentials">
<div class="input-group">
<input type="password" id="IPCPassword" class="form-control" placeholder="Type your password">
<input type="password" id="IPCPassword" class="form-control" data-i18n="placeholder-auth" placeholder="Type your password...">
<div class="input-group-btn">
<button type="button" id="TryToAuth" class="btn"><i class="fa fa-arrow-right text-muted"></i></button>
@@ -89,7 +45,7 @@
</form>
</div>
<div class="help-block text-center">
Please enter the correct IPC password
<span data-i18n="auth-ipc-text">Please enter the correct IPC password</span>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
@@ -99,6 +55,40 @@
$(function () {
'use strict';
var tmpIsAuthorized = get('IsAuthorized'),
tmpLastPage = get('CurrentPage'),
redirectPage = 'pages/commands.html';
if (tmpLastPage) {
redirectPage = tmpLastPage;
}
if (tmpIsAuthorized === 'true') {
window.location.replace(redirectPage);
} else {
$.ajax({
url: '/Api/ASF',
type: 'GET',
statusCode: {
401: function () {
store('IsAuthorized', false);
store('IPCPassword', '');
},
403: function () {
store('IsAuthorized', false);
store('IPCPassword', '');
$('.lockscreen-name, .lockscreen-item').remove();
var res = $.i18n('auth-ipc-403');
$('.help-block').text(res);
},
200: function () {
store('IsAuthorized', true);
window.location.replace(redirectPage);
}
}
});
}
$(document).keypress(function (e) {
var keyCode = e.keyCode || e.which;
@@ -115,8 +105,8 @@
if (newPwd === '') {
swal({
title: 'Error!',
text: 'You need to enter a valid password!',
title: $.i18n('global-error-title'),
text: $.i18n('global-error-invalid-pw'),
type: 'error'
}, function () { swal.close(); });
return false;
@@ -133,24 +123,23 @@
store('IsAuthorized', false);
swal({
title: 'Error!',
text: 'Your IPC password seems to be wrong, try again!',
title: $.i18n('global-error-title'),
text: $.i18n('auth-ipc-pw-wrong'),
type: 'error'
}, function () { swal.close(); });
},
403: function () {
store('IsAuthorized', false);
$('.lockscreen-name').remove();
$('.lockscreen-item').remove();
$('.help-block').text('You failed to authenticate properly too many times, try again in an hour.');
$('.lockscreen-name, .lockscreen-item').remove();
$('.help-block').text($.i18n('auth-ipc-403'));
},
200: function () {
store('IsAuthorized', true);
store('IPCPassword', newPwd);
swal({
title: 'Success!',
text: 'Your IPC password has been saved.',
title: $.i18n('global-success-title'),
text: $.i18n('auth-ipc-pw-saved'),
type: 'success'
}, function () { window.location.replace(redirectPage); });
}

View File

@@ -1,4 +1,4 @@
//#region Utils
//#region Setup
const tmpIPCPassword = get('IPCPassword');
if (tmpIPCPassword) {
@@ -23,74 +23,54 @@ $.ajaxSetup({
}
}
});
function get(name) {
if (typeof Storage !== 'undefined') {
return localStorage.getItem(name);
} else {
window.alert('Please use a modern browser to properly view ASF GUI!');
}
}
function store(name, val) {
if (typeof Storage !== 'undefined') {
localStorage.setItem(name, val);
} else {
window.alert('Please use a modern browser to properly view ASF GUI!');
}
}
//#endregion Utils
//#endregion Setup
//#region Footer
$('.main-footer').ready(function () {
$.ajax({
url: '/Api/ASF',
type: 'GET',
success: function (data) {
var version = data['Result'].Version,
versionNr = version.Major + '.' + version.Minor + '.' + version.Build + '.' + version.Revision;
$.ajax({
url: '/Api/ASF',
type: 'GET',
success: function (data) {
var ver = data['Result'].Version,
verNr = ver.Major + '.' + ver.Minor + '.' + ver.Build + '.' + ver.Revision;
$('#version').text(versionNr);
$('#changelog').attr('href', 'https://github.com/JustArchi/ArchiSteamFarm/releases/tag/' + versionNr);
}
});
$('#version').text(verNr);
$('#changelog').attr('href', 'https://github.com/JustArchi/ArchiSteamFarm/releases/tag/' + verNr);
}
});
//#endregion Footer
//#region Bot Status Buttons
function displayBotStatus() {
$('.bot-status').ready(function () {
var activeBots = 0,
idleBots = 0,
offlineBots = 0;
var offline = 0,
online = 0,
farming = 0;
$.ajax({
url: '/Api/Bot/ASF',
type: 'GET',
success: function (data) {
var json = data['Result'];
$.ajax({
url: '/Api/Bot/ASF',
type: 'GET',
success: function (data) {
var json = data['Result'];
for (var i = 0; i < json.length; i++) {
var obj = json[i],
KeepRunning = obj.KeepRunning,
TimeRemaining = obj.CardsFarmer.TimeRemaining;
for (var i = 0; i < json.length; i++) {
var obj = json[i],
KeepRunning = obj.KeepRunning,
TimeRemaining = obj.CardsFarmer.TimeRemaining;
if (KeepRunning === false) {
offlineBots++;
if (KeepRunning === false) {
offline++;
} else {
if (TimeRemaining === '00:00:00') {
online++;
} else {
if (TimeRemaining === '00:00:00') {
idleBots++;
} else {
activeBots++;
}
farming++;
}
}
$('#offlineBots').text(offlineBots);
$('#idleBots').text(idleBots);
$('#activeBots').text(activeBots);
}
});
$('#offlineBots').text(offline);
$('#onlineBots').text(online);
$('#farmingBots').text(farming);
}
});
}
@@ -100,12 +80,15 @@ window.setInterval(function () { displayBotStatus(); }, 5000);
//#region ASF Information
function displayRAMUsage() {
$('.info-overview').ready(function () {
$.ajax({
url: '/Api/ASF',
type: 'GET',
success: function (data) { $('#ramUsage').html((data['Result'].MemoryUsage / 1024).toFixed(2) + ' MB'); }
});
$.ajax({
url: '/Api/ASF',
type: 'GET',
success: function (data) {
var mem = data['Result'].MemoryUsage,
memMB = (mem / 1024).toFixed(2);
$('#ramUsage').html(memMB + ' MB');
}
});
}
@@ -113,36 +96,35 @@ displayRAMUsage();
window.setInterval(function () { displayRAMUsage(); }, 10000);
function displayUptime() {
$('.info-overview').ready(function () {
$.ajax({
url: '/Api/ASF',
type: 'GET',
success: function (data) { $('#uptime').html(uptimeToString(data['Result'].ProcessStartTime)); }
});
$.ajax({
url: '/Api/ASF',
type: 'GET',
success: function (data) {
var pst = data['Result'].ProcessStartTime,
start = new Date(pst),
now = new Date(),
diff = now.getTime() - start.getTime();
var d = Math.floor(diff / (1000 * 60 * 60 * 24));
diff -= d * (1000 * 60 * 60 * 24);
var h = Math.floor(diff / (1000 * 60 * 60));
diff -= h * (1000 * 60 * 60);
var m = Math.floor(diff / (1000 * 60));
h = (h < 10 ? '0' : '') + h;
m = (m < 10 ? '0' : '') + m;
up = d + 'd ' + h + 'h ' + m + 'm';
$('#uptime').html(up);
}
});
}
displayUptime();
window.setInterval(function () { displayUptime(); }, 60000);
function uptimeToString(startTime) {
var processStartTime = new Date(startTime),
currentDate = new Date(),
diff = currentDate.getTime() - processStartTime.getTime();
var days = Math.floor(diff / (1000 * 60 * 60 * 24));
diff -= days * (1000 * 60 * 60 * 24);
var hours = Math.floor(diff / (1000 * 60 * 60));
diff -= hours * (1000 * 60 * 60);
var mins = Math.floor(diff / (1000 * 60));
hours = (hours < 10 ? '0' : '') + hours;
mins = (mins < 10 ? '0' : '') + mins;
return days + 'd ' + hours + 'h ' + mins + 'm';
}
//#endregion ASF Information
//#region Commands Page
@@ -151,26 +133,29 @@ function fillCommand(cmd) { $cmdInput.val(cmd + ' '); }
function fillBots(bot) { $cmdInput.val($cmdInput.val() + bot); }
function getDateAndTime() {
var currentdate = new Date();
return ('0' + currentdate.getDate()).slice(-2) + '.'
+ ('0' + (currentdate.getMonth() + 1)).slice(-2) + '.'
+ currentdate.getFullYear() + ' @ '
+ ('0' + currentdate.getHours()).slice(-2) + ':'
+ ('0' + currentdate.getMinutes()).slice(-2) + ':'
+ ('0' + currentdate.getSeconds()).slice(-2);
var date = new Date();
return ('0' + date.getDate()).slice(-2) + '.'
+ ('0' + (date.getMonth() + 1)).slice(-2) + '.'
+ date.getFullYear() + ' @ '
+ ('0' + date.getHours()).slice(-2) + ':'
+ ('0' + date.getMinutes()).slice(-2) + ':'
+ ('0' + date.getSeconds()).slice(-2);
}
function logCommand(state, cmd) {
var tmpAutoClear = get('autoClear');
if (state) {
$('#commandSent').val(getDateAndTime() + ' Command sent: ' + cmd);
$('#commandSent').val($.i18n('commands-sent', getDateAndTime(), cmd));
return;
}
var response = $.i18n('commands-response', getDateAndTime(), cmd);
if (tmpAutoClear === 'false') {
$('.box-content-commands').append('\n' + response + '\n');
} else {
if (tmpAutoClear === 'false') {
$('.box-content-commands').append('\n' + getDateAndTime() + ' Response received: ' + cmd + '\n');
} else {
$('.box-content-commands').text(getDateAndTime() + ' Response received: ' + cmd);
}
$('.box-content-commands').text(response);
}
}
@@ -183,15 +168,16 @@ function sendCommand() {
logCommand(true, command);
var response = $.i18n('commands-waiting', getDateAndTime());
if (tmpAutoClear === 'false') {
if ($('.box-content-commands').text() === '') {
$('.box-content-commands').append(getDateAndTime() + ' Waiting for response...' + '\n');
$('.box-content-commands').append(response + '\n');
} else {
$('.box-content-commands').append('\n' + getDateAndTime() + ' Waiting for response...' + '\n');
$('.box-content-commands').append('\n' + response + '\n');
}
} else {
$('.box-content-commands').text(getDateAndTime() + ' Waiting for response...');
$('.box-content-commands').text(response);
}
$('.box-content-commands').append('<div class="overlay"><i class="fas fa-sync fa-spin" style="color:white"></i></div>');
@@ -214,113 +200,6 @@ function sendCommand() {
//#endregion Commands Page
//#region Global Config Utils
//#region Spicy parsing helper by Mole
//const cachedTypeDefinitions = new Map();
//const cachedStructureDefinitions = new Map();
//function request(method, url, data) {
// return new Promise((resolve, reject) => {
// $.ajax(url, { method, data })
// .done(resolve)
// .fail(reject);
// });
//}
//function extract(key) {
// return obj => obj[key];
//}
//const API = {
// get: (endpoint, data) => request('GET', `/Api/${endpoint}`, data).then(extract('Result')),
// post: (endpoint, data) => request('POST', `/Api/${endpoint}`, data).then(extract('Result'))
//};
//const subtypeRegex = /\[[^\]]+\]/g;
//function resolveSubtypes(type) {
// return type.match(subtypeRegex).map(subtype => subtype.slice(1, subtype.length - 1));
//}
//async function getStructureDefinition(type) {
// if (cachedStructureDefinitions.has(type)) return cachedStructureDefinitions.get(type);
// const structureDefinition = API.get(`Structure/${encodeURIComponent(type)}`);
// cachedStructureDefinitions.set(type, structureDefinition);
// return structureDefinition;
//}
//async function getTypeDefinition(type) {
// if (cachedTypeDefinitions.has(type)) return cachedTypeDefinitions.get(type);
// const typeDefinition = API.get(`Type/${encodeURIComponent(type)}`);
// cachedTypeDefinitions.set(type, typeDefinition);
// return typeDefinition;
//}
//async function resolveType(type) {
// switch (type.split('`')[0]) {
// case 'System.Boolean':
// return { type: 'boolean' };
// case 'System.String':
// return { type: 'string' };
// case 'System.Byte':
// return { type: 'smallNumber' };
// case 'System.UInt32':
// return { type: 'number' };
// case 'System.Collections.Generic.HashSet':
// const [subtype] = resolveSubtypes(type);
// return { type: 'hashSet', values: await resolveType(subtype) };
// case 'System.UInt64':
// return { type: 'bigNumber' };
// case 'System.Collections.Generic.Dictionary':
// const subtypes = resolveSubtypes(type);
// return { type: 'dictionary', key: await resolveType(subtypes[0]), value: await resolveType(subtypes[1]) };
// default: // Complex type
// return unwindType(type);
// }
//}
//async function unwindObject(type, typeDefinition) {
// const resolvedStructure = {
// type: 'object',
// body: {}
// };
// const [structureDefinition, resolvedTypes] = await Promise.all([
// getStructureDefinition(type),
// Promise.all(Object.keys(typeDefinition.Body).map(async param => ({ param, type: await resolveType(typeDefinition.Body[param]) })))
// ]);
// for (const { param, type } of resolvedTypes) {
// const paramName = typeDefinition.Body[param] !== 'System.UInt64' ? param : `s_${param}`;
// resolvedStructure.body[param] = {
// defaultValue: structureDefinition[param],
// paramName,
// ...type
// };
// }
// return resolvedStructure;
//}
//async function unwindType(type) {
// if (type === 'ArchiSteamFarm.BotConfig') getStructureDefinition(type); // Dirty trick, but 30% is 30%
// const typeDefinition = await getTypeDefinition(type);
// switch (typeDefinition.Properties.BaseType) {
// case 'System.Object':
// return unwindObject(type, typeDefinition);
// case 'System.Enum':
// return { type: (typeDefinition.Properties.CustomAttributes || []).includes('System.FlagsAttribute') ? 'flag' : 'enum', values: typeDefinition.Body };
// default:
// const structureDefinition = await getStructureDefinition(type);
// return { type: 'unknown', typeDefinition, structureDefinition };
// }
//}
//#endregion Spicy parsing helper by Mole
function generateConfigHTML(mode) {
var namespace = mode === 'ASF' ? 'ArchiSteamFarm.GlobalConfig' : 'ArchiSteamFarm.BotConfig';
$('.box-content-config').empty(); // Clear page content first
@@ -440,12 +319,12 @@ function loadPageContentEditor(botName) {
$("#saveButton").unbind();
$("#saveButton").click(function (e) {
swal({
title: 'Are you sure?',
text: 'The config will be updated and <' + botName + '> will be restarted!',
title: $.i18n('global-question-title'),
text: $.i18n('editor-update', botName),
type: 'warning',
showCancelButton: true,
confirmButtonClass: 'btn-danger',
confirmButtonText: 'Yes, update config!',
confirmButtonText: $.i18n('editor-update-confirm'),
closeOnConfirm: false,
showLoaderOnConfirm: true
}, function () { prepareConfigForSaving(botName); });
@@ -544,7 +423,7 @@ function loadValuesForBotsDropDown(botName) {
botsDropDownHTML += '<li><a href="javascript:void(0)" onclick="loadPageContentEditor(\'' + currentBotName + '\')">' + currentBotName + '</a></li>';
}
$('.box-title').html('Currently editing: <b>' + botName + '</b>');
$('.box-title').html($.i18n('editor-current-bot', botName));
$('#saveButton').data('BotName', botName);
$('#botsDropDown').html(botsDropDownHTML);
}
@@ -654,14 +533,14 @@ function saveConfig(botName, config) {
contentType: 'application/json',
success: function (data) {
swal({
title: 'Success!',
text: '<' + botName + '> and its config file got updated.',
title: $.i18n('global-success-title'),
text: $.i18n('editor-save-confirm', botName),
type: 'success'
}, function () { location.reload(); });
},
error: function (jqXHR, textStatus, errorThrown) {
swal({
title: 'Error!',
title: $.i18n('global-error-title'),
text: jqXHR.status + ' - ' + errorThrown,
type: 'error'
}, function () { location.reload(); });
@@ -758,7 +637,7 @@ function loadValuesForModeDropDown(mode) {
botsDropDownHTML = '<li><a href="javascript:void(0)" onclick="loadPageContentGenerator(\'ASF\');">ASF</a></li>';
}
$('.box-title').html('Current mode: <b>' + mode + '</b>');
$('.box-title').html($.i18n('generator-current-bot', mode));
$('#modeDropDown').html(botsDropDownHTML);
}
@@ -770,8 +649,8 @@ function prepareConfigForDownload(mode) {
if (botName === '') {
swal({
title: 'Error!',
text: 'You need to enter a name',
title: $.i18n('global-error-title'),
text: $.i18n('generator-name'),
type: 'error'
});
return false;
@@ -962,100 +841,36 @@ $(function () {
}
}
function loadLocales(language) {
var i18n = $.i18n(),
langCode = (language === 'strings') ? 'us' : language.substr(language.length - 2).toLowerCase(),
translationFile;
function loadLanguageHTML() {
var tmpLangCode = get('langCode'),
tmpLangMissing = get('langMissing'),
tmpLangTotal = get('langTotal');
i18n.locale = language;
translationFile = '../locale/' + i18n.locale + '.json';
i18n.load(translationFile, i18n.locale).done(
function () {
var missing = 0,
totalSize = 0;
$.getJSON(translationFile, function (obj) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
totalSize++;
if (obj[prop]) {
$('[data-i18n="' + prop + '"]').i18n();
} else {
missing++;
}
}
}
if (missing > 0) {
var percentage = missing * 100 / totalSize;
$('#languageInfo').html('<div class="alert alert-warning alert-dismissible">'
+ '<button title="Never show again" type="button" class="close" data-dismiss="alert" aria-hidden="true">x</button>'
+ percentage.toFixed(0) + '% of this language is not translated! Help us <a href="https://github.com/JustArchi/ArchiSteamFarm/wiki/Localization">here</a>.'
+ '</div>');
} else {
$('#languageInfo').text('');
}
$('#languages').collapse('hide');
});
}
);
store('language', language);
$('#currentLanguage').attr({
alt: langCode,
src: '../img/flags/' + langCode + '.gif'
alt: tmpLangCode,
src: '../img/flags/' + tmpLangCode + '.gif'
});
if (tmpLangMissing > 0) {
var percentage = (tmpLangMissing * 100 / tmpLangTotal).toFixed(0),
//infoText = $.i18n('global-language-info', percentage); //Fix this
infoText = percentage + "% of this language is not translated!";
$('#languageInfo').html('<div class="alert alert-warning alert-dismissible">'
+ '<button data-i18n="title-global-never" title="Never show again" type="button" class="close" data-dismiss="alert" aria-hidden="true">x</button>'
+ infoText
+ '</div>');
} else {
$('#languageInfo').text('');
}
$('#languages').collapse('hide');
}
const defaultLocale = 'strings';
const nameRegex = /\.\/(\S+)\.json/i;
function getLocale(validLocales) {
const language = navigator.language || navigator.userLanguage; // If the browser doesn't support this, it will not support other page elements as well
if (!language) return defaultLocale; // If the browser doesn't provide the language - return default locale
if (language.length !== 2) return validLocales.includes(language) ? language : defaultLocale; // If the language is in `xx-XX` format, check if it's valid
if (validLocales.includes(`${language}-${language.toUpperCase()}`)) return `${language}-${language.toUpperCase()}`; // If the language is two letter code, check if corresponding 5 letter code is a valid locale
const languageRegex = new RegExp(`${language}\-\\\S\\\S`); // Create a regex to match `xx-**` where `*` is a wildcard
for (const validLocale of validLocales) {
if (languageRegex.test(validLocale)) return validLocale; // Check if the locale matches the regex, if so, return it
}
return defaultLocale; // If no match found, return default locale
}
var availableLanguages = [];
function loadAllLanguages() {
$.ajax({
url: '/Api/WWW/Directory/locale',
type: 'GET',
async: false,
success: function (data) {
var obj = data['Result'];
const languageRegex = new RegExp("strings(.[a-z]{2}-[A-Z]{2})?.json");
availableLanguages = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
var language = obj[prop];
if (languageRegex.test(language))
availableLanguages.push(language.substr(0, language.length - 5));
}
}
}
});
}
function setup() {
function loadLayout() {
var tmpSkin = get('skin'),
tmpLayoutState = get('layoutState'),
tmpNightmodeState = get('nightmodeState'),
tmpLeftSidebarState = get('leftSidebarState'),
tmpLanguage = get('language');
tmpLeftSidebarState = get('leftSidebarState');
if (tmpSkin && $.inArray(tmpSkin, mySkins)) changeSkin(tmpSkin);
if (tmpLeftSidebarState === 'sidebar-collapse') {
@@ -1064,8 +879,7 @@ $(function () {
if (tmpLayoutState) changeBoxed(tmpLayoutState);
if (tmpNightmodeState) changeNightmode(tmpNightmodeState);
var myLocal = (tmpLanguage) ? tmpLanguage : getLocale(availableLanguages);
loadLocales(myLocal);
loadLanguageHTML();
$('[data-skin]').on('click', function (e) {
e.preventDefault();
@@ -1091,6 +905,7 @@ $(function () {
$('.language').on('click', function (e) {
e.preventDefault();
loadLocales($(this).data('locale'));
loadLanguageHTML();
});
}
@@ -1103,7 +918,7 @@ $(function () {
// Boxed Layout
+ '<div class="form-group hidden-xs hidden-sm">'
+ '<label class="control-sidebar-subheading">'
+ '<button title="Toggle boxed layout" type="button" class="btn btn-box-tool pull-right text-grey" id="toggleBoxed"><i id="iconBoxed" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button>'
+ '<button data-i18n="title-global-boxed" title="Toggle boxed layout" type="button" class="btn btn-box-tool pull-right text-grey" id="toggleBoxed"><i id="iconBoxed" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button>'
+ '<i class="far fa-square fa-fw"></i> <span data-i18n="global-boxed">Boxed Layout</span>'
+ '</label>'
+ '<p data-i18n="global-boxed-description">Toggle the boxed layout</p>'
@@ -1111,7 +926,7 @@ $(function () {
// Nightmode
+ '<div class="form-group">'
+ '<label class="control-sidebar-subheading">'
+ '<button title="Toggle nightmode" type="button" class="btn btn-box-tool pull-right text-grey" id="toggleNightmode"><i id="iconNightmode" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button>'
+ '<button data-i18n="title-global-nightmode" title="Toggle nightmode" type="button" class="btn btn-box-tool pull-right text-grey" id="toggleNightmode"><i id="iconNightmode" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button>'
+ '<i class="fas fa-moon fa-fw"></i> <span data-i18n="global-nightmode">Nightmode</span>'
+ '</label>'
+ '<p data-i18n="global-nightmode-description">Toggle the nightmode</p>'
@@ -1153,14 +968,14 @@ $(function () {
var language = availableLanguages[i],
langCode = (language === 'strings') ? 'us' : language.substr(language.length - 2).toLowerCase();
$languagesList.append('<button title="Change language" type="button" class="btn btn-box-tool language" data-locale="' + language + '"><img src="../img/flags/' + langCode + '.gif" alt="' + langCode + '"></button>');
$languagesList.append('<button data-i18n="title-global-language" title="Change language" type="button" class="btn btn-box-tool language" data-locale="' + language + '"><img src="../img/flags/' + langCode + '.gif" alt="' + langCode + '"></button>');
}
$layoutSettings.append('<h4 class="control-sidebar-heading" data-i18n="global-language">Language</h4>'
+ '<div id="languageInfo"></div>'
+ '<div class="form-group">'
+ '<label class="control-sidebar-subheading">'
+ '<button title="Change language" type="button" class="btn btn-box-tool pull-right" data-toggle="collapse" data-target="#languages"><span data-i18n="global-change">Change</span> <i class="fas fa-caret-down"></i></button>'
+ '<button data-i18n="title-global-language" title="Change language" type="button" class="btn btn-box-tool pull-right" data-toggle="collapse" data-target="#languages"><span data-i18n="global-change">Change</span> <i class="fas fa-caret-down"></i></button>'
+ '<img id="currentLanguage" src="../img/flags/us.gif" alt="us">'
+ '</label>'
+ '</div>'
@@ -1170,6 +985,6 @@ $(function () {
$('#control-right-sidebar').after($layoutSettings);
setup();
loadLayout();
});
//#endregion Right Sidebar

View File

@@ -0,0 +1,84 @@
const defaultLocale = 'strings',
nameRegex = /\.\/(\S+)\.json/i;
var availableLanguages = [],
tmpLanguage = get('language'),
myLocal = (tmpLanguage) ? tmpLanguage : getLocale(availableLanguages);
function getLocale(validLocales) {
const language = navigator.language || navigator.userLanguage; // If the browser doesn't support this, it will not support other page elements as well
if (!language) return defaultLocale; // If the browser doesn't provide the language - return default locale
if (language.length !== 2) return validLocales.includes(language) ? language : defaultLocale; // If the language is in `xx-XX` format, check if it's valid
if (validLocales.includes(`${language}-${language.toUpperCase()}`)) return `${language}-${language.toUpperCase()}`; // If the language is two letter code, check if corresponding 5 letter code is a valid locale
const languageRegex = new RegExp(`${language}\-\\\S\\\S`); // Create a regex to match `xx-**` where `*` is a wildcard
for (const validLocale of validLocales) {
if (languageRegex.test(validLocale)) return validLocale; // Check if the locale matches the regex, if so, return it
}
return defaultLocale; // If no match found, return default locale
}
function loadLocales(language) {
var i18n = $.i18n(),
langCode = (language === 'strings') ? 'us' : language.substr(language.length - 2).toLowerCase(),
translationFile,
missing = 0,
totalSize = 0;
i18n.locale = language;
translationFile = '../locale/' + i18n.locale + '.json';
i18n.load(translationFile, i18n.locale).done(
function () {
$.getJSON(translationFile, function (obj) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
totalSize++;
if (obj[prop]) {
if (prop.substring(0, 12) === 'placeholder-') {
$('[data-i18n="' + prop + '"]').attr("placeholder", $.i18n(prop));
} else if (prop.substring(0, 6) === 'title-') {
$('[data-i18n="' + prop + '"]').attr("title", $.i18n(prop));
} else {
$('[data-i18n="' + prop + '"]').i18n();
}
} else {
missing++;
}
}
}
store('langMissing', missing);
store('langTotal', totalSize);
});
}
);
store('language', language);
store('langCode', langCode);
}
function loadAllLanguages() {
$.ajax({
url: '/Api/WWW/Directory/locale',
type: 'GET',
async: false,
success: function (data) {
var obj = data['Result'];
const languageRegex = new RegExp("strings(.[a-z]{2}-[A-Z]{2})?.json");
availableLanguages = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
var language = obj[prop];
if (languageRegex.test(language))
availableLanguages.push(language.substr(0, language.length - 5));
}
}
}
});
}
loadLocales(myLocal);

View File

@@ -0,0 +1,10 @@
if (typeof Storage === 'undefined')
window.alert('Please use a modern browser to properly view ASF GUI!');
function get(name) {
return localStorage.getItem(name);
}
function store(name, val) {
localStorage.setItem(name, val);
}

View File

@@ -1,20 +1,52 @@
{
"auth-ipc-403": "You failed to authenticate properly too many times, try again in an hour.",
"auth-ipc-header": "IPC password required",
"auth-ipc-pw-saved": "Your IPC password has been saved.",
"auth-ipc-pw-wrong": "Your IPC password seems to be wrong, try again!",
"auth-ipc-text": "Please enter the correct IPC password",
"auth-title": "ASF | Authentication",
"bots-confirm-delete": "Yes, delete bot!",
"bots-delete": "Show delete button",
"bots-delete-success": "<$1> and all related files have been deleted.",
"bots-delimeter": "Delimeter",
"bots-hide": "Hide bots",
"bots-hide-offline": "Offline bots",
"bots-hide-online": "Online bots",
"bots-infobox-cards": "Cards Remaining",
"bots-infobox-games": "Games Remaining",
"bots-infobox-time": "Time Remaining",
"bots-in-use": "Bot is currently being used.",
"bots-key": "Show key button",
"bots-paused": "Bot is paused.",
"bots-pause-success": "<$1> has been paused.",
"bots-recover-files": "You will not be able to recover any bot files!",
"bots-redeem-button": "Add keys!",
"bots-redeem-confirm": "$1 {{PLURAL:$1|Key|Keys}} have been added to <$2> background redeemer.",
"bots-redeem-title": "Enter keys!",
"bots-resume-success": "<$1> has been resumed.",
"bots-simple": "Simple farming info",
"bots-start-success": "<$1> has been started.",
"bots-stop-success": "<$1> has been stopped.",
"bots-syntax": "Syntax: gameName{Delimeter}cd-key",
"bots-title": "ASF | Bots",
"command-auto-clear": "Auto clear",
"commands-auto-clear": "Auto clear",
"commands-response": "$1 Response received: $2",
"commands-sent": "$1 Command sent: $2",
"commands-title": "ASF | Commands",
"commands-waiting": "$1 Waiting for response...",
"editor-change": "Change bot",
"editor-current": "Currently editing:",
"editor-current-bot": "Currently editing: <b>$1</b>",
"editor-save": "Save",
"editor-save-confirm": "$1 and its config file got updated.",
"editor-title": "ASF | Config Editor",
"editor-update": "The config will be updated and <$1> will be restarted!",
"editor-update-confirm": "Yes, update config!",
"generator-change": "Change mode",
"generator-current": "Current mode:",
"generator-current-bot": "Current mode: <b>$1</b>",
"generator-download": "Download",
"generator-name": "You need to enter a name!",
"generator-title": "ASF | Config Generator",
"global-bots": "Bots",
"global-boxed": "Boxed Layout",
@@ -25,19 +57,46 @@
"global-config": "Config",
"global-control-panel": "Control Panel",
"global-editor": "Editor",
"global-error-invalid-pw": "You need to enter a valid password!",
"global-error-title": "Error!",
"global-generator": "Generator",
"global-home": "Home",
"global-information": "Information",
"global-language": "Language",
"global-language-info": "$1% of this language is not translated! Help us <a href=\"https://github.com/JustArchi/ArchiSteamFarm/wiki/Localization\">here</a>.",
"global-layout": "Layout",
"global-log": "Log",
"global-navigation": "Toggle navigation",
"global-nightmode": "Nightmode",
"global-nightmode-description": "Toggle the nightmode",
"global-question-title": "Are you sure?",
"global-ram-usage": "RAM Usage",
"global-skins": "Skins",
"global-success-title": "Success!",
"global-uptime": "Uptime",
"global-version": "Version",
"global-wiki": "Wiki",
"log-title": "ASF | Log"
}
"log-event-code": "Event code: $1",
"log-title": "ASF | Log",
"placeholder-auth": "Type your password...",
"placeholder-commands": "Type command...",
"placeholder-generator": "Name",
"title-bots-delete": "Toggle delete button",
"title-bots-delete-this": "Delete this bot",
"title-bots-games": "Add keys to GamesToRedeemInBackground",
"title-bots-key": "Toggle key button",
"title-bots-more": "Show more infos",
"title-bots-offline": "Toggle offline bots",
"title-bots-online": "Toggle online bots",
"title-bots-refresh": "Refresh content",
"title-bots-simple": "Toggle simple farming info",
"title-commands-auto-clear": "Toggle auto clear",
"title-commands-send": "Send command",
"title-commands-show-all-bots": "Show all bots",
"title-commands-show-all-commands": "Show all commands",
"title-global-boxed": "Toggle boxed layout",
"title-global-language": "Change language",
"title-global-never": "Never show again",
"title-global-nightmode": "Toggle nightmode",
"title-log-auto-scroll": "Toggle auto scroll"
}

View File

@@ -6,13 +6,12 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script> <!--Change to cdnjs once available-->
<link rel="icon" href="../favicon.png" type="image/png">
<link rel="shortcut icon" href="../favicon.ico" type="img/x-icon">
<link rel="icon" href="../img/favicon.png" type="image/png">
<link rel="shortcut icon" href="../img/favicon.ico" type="img/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-sweetalert/1.0.1/sweetalert.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/2.4.2/css/AdminLTE.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.css">
<!--<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">--> <!--Implement properly-->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
<link rel="stylesheet" href="../css/_all-skins.min.css">
<link rel="stylesheet" href="../css/app.css">
@@ -54,8 +53,8 @@
<i class="fas fa-users fa-fw"></i> <span data-i18n="global-bots">Bots</span>
<span class="pull-right-container bot-status">
<small class="label pull-right bg-gray" id="offlineBots">0</small>
<small class="label pull-right bg-yellow" id="idleBots">0</small>
<small class="label pull-right bg-olive" id="activeBots">0</small>
<small class="label pull-right bg-yellow" id="onlineBots">0</small>
<small class="label pull-right bg-olive" id="farmingBots">0</small>
</span>
</a>
</li>
@@ -111,30 +110,23 @@
<span data-i18n="bots-hide">Hide bots</span> <span class="fas fa-caret-down"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><button title="Toggle online bots" type="button" class="btn btn-box-tool text-grey" id="chkHideOnlineBots"><i id="iconHideOnlineBots" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button><span data-i18n="bots-hide-online">Online bots</span></li>
<li><button title="Toggle offline bots" type="button" class="btn btn-box-tool text-grey" id="chkHideOfflineBots"><i id="iconHideOfflineBots" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button><span data-i18n="bots-hide-offline">Offline bots</span></li>
<li><button data-i18n="title-bots-online" title="Toggle online bots" type="button" class="btn btn-box-tool text-grey" id="chkHideOnlineBots"><i id="iconHideOnlineBots" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button><span data-i18n="bots-hide-online">Online bots</span></li>
<li><button data-i18n="title-bots-offline" title="Toggle offline bots" type="button" class="btn btn-box-tool text-grey" id="chkHideOfflineBots"><i id="iconHideOfflineBots" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button><span data-i18n="bots-hide-offline">Offline bots</span></li>
</ul>
</div>
<!--Implement properly-->
<!--<button title="Toggle multi select" type="button" class="btn btn-box-tool" id="chkMultiSelect" data-widget="collapse"><i id="iconMultiSelect" class="far fa-square"></i></button>-->
<button title="Refresh content" type="button" class="btn btn-box-tool" id="btnRefreshContent"><i class="fas fa-sync"></i></button>
<button data-i18n="title-bots-refresh" title="Refresh content" type="button" class="btn btn-box-tool" id="btnRefreshContent"><i class="fas fa-sync"></i></button>
<div class="btn-group">
<button type="button" class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown">
<i class="fas fa-wrench"></i>
</button>
<ul class="dropdown-menu" role="menu">
<li><button title="Toggle key button" type="button" class="btn btn-box-tool text-grey" id="chkShowKeyButton"><i id="iconShowKeyButton" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button><span data-i18n="bots-key">Show key button</span></li>
<li><button title="Toggle delete button" type="button" class="btn btn-box-tool text-grey" id="chkShowDeleteButton"><i id="iconShowDeleteButton" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button><span data-i18n="bots-delete">Show delete button</span></li>
<li><button title="Toggle simple farming info" type="button" class="btn btn-box-tool text-grey" id="chkSimpleFarmingInfo"><i id="iconSimpleFarmingInfo" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button><span data-i18n="bots-simple">Simple farming info</span></li>
<li><button data-i18n="title-bots-key" title="Toggle key button" type="button" class="btn btn-box-tool text-grey" id="chkShowKeyButton"><i id="iconShowKeyButton" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button><span data-i18n="bots-key">Show key button</span></li>
<li><button data-i18n="title-bots-delete" title="Toggle delete button" type="button" class="btn btn-box-tool text-grey" id="chkShowDeleteButton"><i id="iconShowDeleteButton" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button><span data-i18n="bots-delete">Show delete button</span></li>
<li><button data-i18n="title-bots-simple" title="Toggle simple farming info" type="button" class="btn btn-box-tool text-grey" id="chkSimpleFarmingInfo"><i id="iconSimpleFarmingInfo" class="fas fa-toggle-on fa-2x fa-rotate-180"></i></button><span data-i18n="bots-simple">Simple farming info</span></li>
</ul>
</div>
</div>
</div>
<!--Implement properly-->
<!--<div class="box-body">
<button title="Select all bots" type="button" class="btn btn-default" id="selectAllBots"><i class="fas fa-th"></i> Select all</button>
<button title="Deselect all bots" type="button" class="btn btn-default" id="deselectAllBots"><i class="fas fa-th"></i> Deselect all</button>
</div>-->
</div>
<div class="row" id="totalBotOverview"></div>
<div class="row" id="botRow"></div>
@@ -145,9 +137,9 @@
<footer class="main-footer">
<div class="pull-right"><strong data-i18n="global-version">Version</strong> <span id="version">0.0.0.0</span></div>
<strong>
<a href="https://github.com/JustArchi/ArchiSteamFarm">GitHub</a> -
<a href="https://github.com/JustArchi/ArchiSteamFarm/wiki"><span data-i18n="global-wiki">Wiki</span></a> -
<a href="https://github.com/JustArchi/ArchiSteamFarm/commits/master" id="changelog"><span data-i18n="global-changelog">Changelog</span></a>
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm">GitHub</a> -
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm/wiki"><span data-i18n="global-wiki">Wiki</span></a> -
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm/commits/master" id="changelog"><span data-i18n="global-changelog">Changelog</span></a>
</strong>
</footer>
@@ -165,7 +157,6 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-sweetalert/1.0.1/sweetalert.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/2.4.2/js/adminlte.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js"></script>
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>--> <!--Implement properly-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/humanize-duration/3.12.1/humanize-duration.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.min.js"></script>
@@ -175,6 +166,8 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.parser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.bidi.min.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/i18n.js"></script>
<script src="../js/app.js"></script>
<script>
$(function () {
@@ -187,7 +180,6 @@
tmpShowDeleteButton = get('showDeleteButton'),
tmpShowKeyButton = get('showKeyButton'),
tmpSimpleFarmingInfo = get('simpleFarmingInfo'),
//tmpMultiSelect = get('multiSelect'), // Implement properly
currentlySelectedBots = [];
$(document).delegate('#gamesToRedeemInBackground', 'keydown', function (e) {
@@ -262,15 +254,6 @@
$('#chkSimpleFarmingInfo').addClass('text-olive');
$('#iconSimpleFarmingInfo').removeClass('fa-rotate-180');
}
// Implement properly
//if (tmpMultiSelect === 'true') {
// $('#iconMultiSelect').removeClass('fa-square');
// $('#iconMultiSelect').addClass('fa-check-square');
// $('#headerBox').removeClass('collapsed-box');
// $('#headerBox').removeClass('expanded-box');
// $('#botRow').selectable();
//}
});
$('#chkSimpleFarmingInfo').click(function () {
@@ -318,35 +301,6 @@
loadPageContent();
});
//Implement properly
//$('#chkMultiSelect').click(function () {
// if ($('#iconMultiSelect').hasClass('fa-square')) {
// $('#iconMultiSelect').removeClass('fa-square');
// $('#iconMultiSelect').addClass('fa-check-square');
// $('#botRow').selectable();
// store('multiSelect', true);
// } else {
// $('#iconMultiSelect').removeClass('fa-check-square');
// $('#iconMultiSelect').addClass('fa-square');
// $('#botRow').selectable('destroy');
// store('multiSelect', false);
// }
// $('#chkMultiSelect').blur();
//});
//$('#selectAllBots').click(function () {
// $(".ui-widget-content").each(function () {
// $(this).addClass('ui-selected');
// });
//});
//$('#deselectAllBots').click(function () {
// $(".ui-selected").each(function () {
// $(this).removeClass('ui-selected');
// });
//});
$('#btnRefreshContent').click(function () {
$('#btnRefreshContent').blur();
loadPageContent();
@@ -409,8 +363,8 @@
totalCardsRemaining = 0,
farmingIsActive = false;
var deleteBotHTML = tmpShowDeleteButton === 'true' ? '<button title="Delete this bot" type="button" class="btn btn-box-tool" data-command="deleteBot"><i class="far fa-trash-alt"></i></button>' : '';
var redeemGamesHTML = tmpShowKeyButton === 'true' ? '<button title="Add keys to GamesToRedeemInBackground" type="button" class="btn btn-box-tool" data-command="redeemGames"><i class="fas fa-key"></i></button>' : '';
var deleteBotHTML = tmpShowDeleteButton === 'true' ? '<button data-i18n="title-bots-delete-this" title="Delete this bot" type="button" class="btn btn-box-tool" data-command="deleteBot"><i class="far fa-trash-alt"></i></button>' : '';
var redeemGamesHTML = tmpShowKeyButton === 'true' ? '<button data-i18n="title-bots-games" title="Add keys to GamesToRedeemInBackground" type="button" class="btn btn-box-tool" data-command="redeemGames"><i class="fas fa-key"></i></button>' : '';
for (var i = 0; i < json.length; i++) {
var obj = json[i],
@@ -422,6 +376,7 @@
Paused = obj.CardsFarmer.Paused,
boxColorHTML = '',
avatarHTML = '',
profileHTML = '',
startOrStopHTML = '',
pauseOrResumeHTML = '',
expandBoxHTML = '',
@@ -437,6 +392,7 @@
if (KeepRunning === false) { // Bot is offline
if (tmpHideOfflineBots === 'true') continue;
profileHTML = '<img src="' + avatarHTML + '">';
boxColorHTML = 'box-gray';
startOrStopHTML = '<button title="Start <' + BotName + '>" type="button" class="btn btn-box-tool bot-stopped" data-command="startBot"><i class="fas fa-power-off"></i></button>';
} else { // Bot is idling
@@ -449,6 +405,10 @@
if (SteamID === 0) { // Bot is not connected to steam
boxColorHTML = 'box-danger';
} else { // Bot is connected to steam
profileHTML = '<a href="https://steamcommunity.com/profiles/' + obj.s_SteamID + '" target="_blank">'
+ '<img src="' + avatarHTML + '">'
+ '</a>';
if (TimeRemaining !== '00:00:00') { // Bot is farming
var GamesToFarm = obj.CardsFarmer.GamesToFarm,
CurrentGamesFarming = obj.CardsFarmer.CurrentGamesFarming,
@@ -473,11 +433,11 @@
totalGamesRemaining += GamesToFarm.length;
expandBoxHTML = '<button title="Show more infos" type="button" class="btn btn-box-tool" data-widget="collapse" id="collapse-trigger"><i class="fas fa-plus"></i></button>'
expandBoxHTML = '<button data-i18n="title-bots-more" title="Show more infos" type="button" class="btn btn-box-tool" data-widget="collapse" id="collapse-trigger"><i class="fas fa-plus"></i></button>'
if (IsPlayingPossible) {
if (Paused) {
allGamesHTML = '<p class="text-center no-margin">Bot is paused.</p>';
allGamesHTML = '<p class="text-center no-margin">' + $.i18n('bots-paused') + '</p>';
} else {
if (tmpSimpleFarmingInfo === 'true') {
allGamesHTML = '<p class="text-center no-margin">' + allGamesFarmingName.join(", ") + '</p>';
@@ -498,7 +458,7 @@
}
}
} else {
allGamesHTML = '<p class="text-center no-margin">Bot is currently being used.</p>';
allGamesHTML = '<p class="text-center no-margin">' + $.i18n('bots-in-use') + '</p>';
}
TimeRemaining = moment.duration(TimeRemaining).asMilliseconds();
@@ -527,7 +487,7 @@
$('#botRow').append('<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">'
+ '<div class="box ' + boxColorHTML + ' collapsed-box" id="bot-box-' + BotName + '">'
+ '<div class="box-header with-border botHeader ui-widget-content">'
+ '<img src="' + avatarHTML + '">'
+ profileHTML
+ '<h3 class="box-title botTitle">' + BotName + '</h3>'
+ '<div class="box-tools pull-right botTools" id="' + BotName + '">'
+ startOrStopHTML
@@ -573,18 +533,22 @@
cmd = $(this).data('command'),
$botBox = $('#bot-box-' + BotName);
if (typeof cmd === 'undefined') {
return;
}
$botBox.append('<div class="overlay bot-box-loading"><i class="fas fa-sync fa-spin"></i></div>');
switch (cmd) {
case 'startBot':
$botBox.append('<div class="overlay bot-box-loading"><i class="fas fa-sync fa-spin"></i></div>');
$.ajax({
url: '/Api/Command/start ' + encodeURIComponent(BotName),
type: 'POST',
success: function (data) {
$('.overlay').remove();
swal({
title: 'Success!',
text: '<' + BotName + '> has been started.',
title: $.i18n('global-success-title'),
text: $.i18n('bots-start-success', BotName),
type: 'success'
}, function () { location.reload(); });
}
@@ -592,16 +556,14 @@
break;
case 'stopBot':
$botBox.append('<div class="overlay bot-box-loading"><i class="fas fa-sync fa-spin"></i></div>');
$.ajax({
url: '/Api/Command/stop ' + encodeURIComponent(BotName),
type: 'POST',
success: function (data) {
$('.overlay').remove();
swal({
title: 'Success!',
text: '<' + BotName + '> has been stopped.',
title: $.i18n('global-success-title'),
text: $.i18n('bots-stop-success', BotName),
type: 'success'
}, function () { location.reload(); });
}
@@ -609,16 +571,14 @@
break;
case 'pauseBot':
$botBox.append('<div class="overlay bot-box-loading"><i class="fas fa-sync fa-spin"></i></div>');
$.ajax({
url: '/Api/Command/pause ' + encodeURIComponent(BotName),
type: 'POST',
success: function (data) {
$('.overlay').remove();
swal({
title: 'Success!',
text: '<' + BotName + '> has been paused.',
title: $.i18n('global-success-title'),
text: $.i18n('bots-pause-success', BotName),
type: 'success'
}, function () { location.reload(); });
}
@@ -626,16 +586,14 @@
break;
case 'resumeBot':
$botBox.append('<div class="overlay bot-box-loading"><i class="fas fa-sync fa-spin"></i></div>');
$.ajax({
url: '/Api/Command/resume ' + encodeURIComponent(BotName),
type: 'POST',
success: function (data) {
$('.overlay').remove();
swal({
title: 'Success!',
text: '<' + BotName + '> has been resumed.',
title: $.i18n('global-success-title'),
text: $.i18n('bots-resume-success', BotName),
type: 'success'
}, function () { location.reload(); });
}
@@ -643,14 +601,13 @@
break;
case 'deleteBot':
$botBox.append('<div class="overlay bot-box-loading"><i class="fas fa-sync fa-spin"></i></div>');
swal({
title: 'Are you sure?',
text: 'You will not be able to recover any bot files!',
title: $.i18n('global-question-title'),
text: $.i18n('bots-recover-files'),
type: 'warning',
showCancelButton: true,
confirmButtonClass: 'btn-danger',
confirmButtonText: 'Yes, delete bot!',
confirmButtonText: $.i18n('bots-confirm-delete'),
closeOnConfirm: false,
showLoaderOnConfirm: true
}, function (isConfirm) {
@@ -661,8 +618,8 @@
success: function (data) {
$('.overlay').remove();
swal({
title: 'Success!',
text: '<' + BotName + '> and all related files have been deleted.',
title: $.i18n('global-success-title'),
text: $.i18n('bots-delete-success', BotName),
type: 'success'
}, function () { location.reload(); });
}
@@ -674,20 +631,19 @@
break;
case 'redeemGames':
$botBox.append('<div class="overlay bot-box-loading"><i class="fas fa-sync fa-spin"></i></div>');
swal({
title: 'Enter keys!',
text: '<p class="lead text-muted" style="display: block;">Syntax: gameName{Delimeter}cd-key</p>'
title: $.i18n('bots-redeem-title'),
text: '<p class="lead text-muted" style="display: block;">' + $.i18n('bots-syntax') + '</p>'
+ '<textarea id="gamesToRedeemInBackground"></textarea>'
+ '<div class="input-group">'
+ '<span class="input-group-addon" id="delimeter-text">Delimeter</span>'
+ '<span class="input-group-addon" id="delimeter-text">' + $.i18n('bots-delimeter') + '</span>'
+ '<input type="text" class="form-control" id="delimeter" value="' + tmpDelimeter + '" aria-describedby="delimeter-text">'
+ '</div>',
html: true,
customClass: 'swal-wide',
showCancelButton: true,
confirmButtonClass: 'btn-success',
confirmButtonText: 'Add keys!',
confirmButtonText: $.i18n('bots-redeem-button'),
closeOnConfirm: false,
showLoaderOnConfirm: true
}, function (isConfirm) {
@@ -725,14 +681,14 @@
gamesAdded = Object.keys(obj).length;
swal({
title: 'Success!',
text: gamesAdded + ' Keys have been added to <' + BotName + '> background redeemer.',
title: $.i18n('global-success-title'),
text: $.i18n('bots-redeem-confirm', gamesAdded, BotName),
type: 'success'
}, function () { location.reload(); });
},
error: function (jqXHR, textStatus, errorThrown) {
swal({
title: 'Error!',
title: $.i18n('global-error-title'),
text: jqXHR.status + ' - ' + errorThrown,
type: 'error'
}, function () { location.reload(); });
@@ -751,7 +707,7 @@
+ '<div class="info-box bot-info-box">'
+ '<span class="info-box-icon bg-purple bots-info-box-icon"><i class="fas fa-gamepad"></i></span>'
+ '<div class="info-box-content bot-info-box-content">'
+ '<span class="info-box-text">Games Remaining</span>'
+ '<span class="info-box-text">' + $.i18n('bots-infobox-games') + '</span>'
+ '<span class="info-box-number" id="totalGamesRemaining"></span>'
+ '</div>'
+ '</div>'
@@ -760,7 +716,7 @@
+ '<div class="info-box bot-info-box">'
+ '<span class="info-box-icon bg-green bots-info-box-icon"><i class="far fa-clock"></i></span>'
+ '<div class="info-box-content bot-info-box-content">'
+ '<span class="info-box-text">Time Remaining</span>'
+ '<span class="info-box-text">' + $.i18n('bots-infobox-time') + '</span>'
+ '<span class="info-box-number" id="totalTimeRemaining"></span>'
+ '</div>'
+ '</div>'
@@ -769,7 +725,7 @@
+ '<div class="info-box bot-info-box">'
+ '<span class="info-box-icon bg-aqua bots-info-box-icon"><i class="far fa-clone"></i></span>'
+ '<div class="info-box-content bot-info-box-content">'
+ '<span class="info-box-text">Cards Remaining</span>'
+ '<span class="info-box-text">' + $.i18n('bots-infobox-cards') + '</span>'
+ '<span class="info-box-number" id="totalCardsRemaining"></span>'
+ '</div>'
+ '</div>'

View File

@@ -6,8 +6,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script> <!--Change to cdnjs once available-->
<link rel="icon" href="../favicon.png" type="image/png">
<link rel="shortcut icon" href="../favicon.ico" type="img/x-icon">
<link rel="icon" href="../img/favicon.png" type="image/png">
<link rel="shortcut icon" href="../img/favicon.ico" type="img/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-sweetalert/1.0.1/sweetalert.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/2.4.2/css/AdminLTE.min.css">
@@ -52,8 +52,8 @@
<i class="fas fa-users fa-fw"></i> <span data-i18n="global-bots">Bots</span>
<span class="pull-right-container bot-status">
<small class="label pull-right bg-gray" id="offlineBots">0</small>
<small class="label pull-right bg-yellow" id="idleBots">0</small>
<small class="label pull-right bg-olive" id="activeBots">0</small>
<small class="label pull-right bg-yellow" id="onlineBots">0</small>
<small class="label pull-right bg-olive" id="farmingBots">0</small>
</span>
</a>
</li>
@@ -109,7 +109,7 @@
<i class="fas fa-wrench"></i>
</button>
<ul class="dropdown-menu" role="menu">
<li><button title="Toggle auto clear" type="button" class="btn btn-box-tool text-olive" id="chkAutoClear"><i id="iconAutoClear" class="fas fa-toggle-on fa-2x"></i></button><span data-i18n="command-auto-clear">Auto clear</span></li>
<li><button data-i18n="title-commands-auto-clear" title="Toggle auto clear" type="button" class="btn btn-box-tool text-olive" id="chkAutoClear"><i id="iconAutoClear" class="fas fa-toggle-on fa-2x"></i></button><span data-i18n="commands-auto-clear">Auto clear</span></li>
</ul>
</div>
</div>
@@ -121,22 +121,22 @@
<div class="box-footer">
<div class="input-group">
<div class="input-group-btn hidden-xs" id="cmdsDropDownBox">
<button title="Show all commands" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<button data-i18n="title-commands-show-all-commands" title="Show all commands" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span data-i18n="global-commands">Commands</span>
<span class="fas fa-caret-down" id="iconCmdsDropDownBox"></span>
</button>
<ul class="dropdown-menu scrollable-menu" id="commandsDropDown"></ul>
</div>
<div class="input-group-btn hidden-xs" id="botsDropDownBox">
<button title="Show all bots" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<button data-i18n="title-commands-show-all-bots" title="Show all bots" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span data-i18n="global-bots">Bots</span>
<span class="fas fa-caret-down" id="iconBotsDropDownBox"></span>
</button>
<ul class="dropdown-menu scrollable-menu" id="botsDropDown"></ul>
</div>
<input id="commandInput" type="text" class="form-control" placeholder="Type command...">
<input id="commandInput" type="text" class="form-control" data-i18n="placeholder-commands" placeholder="Type command...">
<div class="input-group-btn">
<button title="Send command" type="button" class="btn btn-default" id="sendCommand"><i class="far fa-paper-plane"></i></button>
<button data-i18n="title-commands-send" title="Send command" type="button" class="btn btn-default" id="sendCommand"><i class="far fa-paper-plane"></i></button>
</div>
</div>
</div>
@@ -148,9 +148,9 @@
<footer class="main-footer">
<div class="pull-right"><strong data-i18n="global-version">Version</strong> <span id="version">0.0.0.0</span></div>
<strong>
<a href="https://github.com/JustArchi/ArchiSteamFarm">GitHub</a> -
<a href="https://github.com/JustArchi/ArchiSteamFarm/wiki"><span data-i18n="global-wiki">Wiki</span></a> -
<a href="https://github.com/JustArchi/ArchiSteamFarm/commits/master" id="changelog"><span data-i18n="global-changelog">Changelog</span></a>
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm">GitHub</a> -
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm/wiki"><span data-i18n="global-wiki">Wiki</span></a> -
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm/commits/master" id="changelog"><span data-i18n="global-changelog">Changelog</span></a>
</strong>
</footer>
@@ -175,6 +175,8 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.parser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.bidi.min.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/i18n.js"></script>
<script src="../js/app.js"></script>
<script>
$(function () {
@@ -345,7 +347,7 @@
$commandInput.attr('placeholder', myCommands[this.id]); // ToDo: Find a better solution for where to display description
})
.mouseleave(function () {
$commandInput.attr('placeholder', 'Type command...');
$commandInput.attr('placeholder', $.i18n('placeholder-commands'));
});
}
}

View File

@@ -6,8 +6,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script> <!--Change to cdnjs once available-->
<link rel="icon" href="../favicon.png" type="image/png">
<link rel="shortcut icon" href="../favicon.ico" type="img/x-icon">
<link rel="icon" href="../img/favicon.png" type="image/png">
<link rel="shortcut icon" href="../img/favicon.ico" type="img/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-sweetalert/1.0.1/sweetalert.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/2.4.2/css/AdminLTE.min.css">
@@ -52,8 +52,8 @@
<i class="fas fa-users fa-fw"></i> <span data-i18n="global-bots">Bots</span>
<span class="pull-right-container bot-status">
<small class="label pull-right bg-gray" id="offlineBots">0</small>
<small class="label pull-right bg-yellow" id="idleBots">0</small>
<small class="label pull-right bg-olive" id="activeBots">0</small>
<small class="label pull-right bg-yellow" id="onlineBots">0</small>
<small class="label pull-right bg-olive" id="farmingBots">0</small>
</span>
</a>
</li>
@@ -131,9 +131,9 @@
<footer class="main-footer">
<div class="pull-right"><strong data-i18n="global-version">Version</strong> <span id="version">0.0.0.0</span></div>
<strong>
<a href="https://github.com/JustArchi/ArchiSteamFarm">GitHub</a> -
<a href="https://github.com/JustArchi/ArchiSteamFarm/wiki"><span data-i18n="global-wiki">Wiki</span></a> -
<a href="https://github.com/JustArchi/ArchiSteamFarm/commits/master" id="changelog"><span data-i18n="global-changelog">Changelog</span></a>
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm">GitHub</a> -
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm/wiki"><span data-i18n="global-wiki">Wiki</span></a> -
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm/commits/master" id="changelog"><span data-i18n="global-changelog">Changelog</span></a>
</strong>
</footer>
@@ -157,6 +157,8 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.parser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.bidi.min.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/i18n.js"></script>
<script src="../js/app.js"></script>
<script>
$(function () {

View File

@@ -6,8 +6,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script> <!--Change to cdnjs once available-->
<link rel="icon" href="../favicon.png" type="image/png">
<link rel="shortcut icon" href="../favicon.ico" type="img/x-icon">
<link rel="icon" href="../img/favicon.png" type="image/png">
<link rel="shortcut icon" href="../img/favicon.ico" type="img/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-sweetalert/1.0.1/sweetalert.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/2.4.2/css/AdminLTE.min.css">
@@ -52,8 +52,8 @@
<i class="fas fa-users fa-fw"></i> <span data-i18n="global-bots">Bots</span>
<span class="pull-right-container bot-status">
<small class="label pull-right bg-gray" id="offlineBots">0</small>
<small class="label pull-right bg-yellow" id="idleBots">0</small>
<small class="label pull-right bg-olive" id="activeBots">0</small>
<small class="label pull-right bg-yellow" id="onlineBots">0</small>
<small class="label pull-right bg-olive" id="farmingBots">0</small>
</span>
</a>
</li>
@@ -119,7 +119,7 @@
<div class="box-footer">
<div class="input-group pull-right">
<div class="input-group">
<input type="text" class="form-control" placeholder="Name" id="GeneratorName">
<input type="text" class="form-control" data-i18n="placeholder-generator" placeholder="Name" id="GeneratorName">
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="downloadButton">
<i class="fas fa-cloud-download-alt"></i> <span data-i18n="generator-download">Download</span>
@@ -136,9 +136,9 @@
<footer class="main-footer">
<div class="pull-right"><strong data-i18n="global-version">Version</strong> <span id="version">0.0.0.0</span></div>
<strong>
<a href="https://github.com/JustArchi/ArchiSteamFarm">GitHub</a> -
<a href="https://github.com/JustArchi/ArchiSteamFarm/wiki"><span data-i18n="global-wiki">Wiki</span></a> -
<a href="https://github.com/JustArchi/ArchiSteamFarm/commits/master" id="changelog"><span data-i18n="global-changelog">Changelog</span></a>
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm">GitHub</a> -
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm/wiki"><span data-i18n="global-wiki">Wiki</span></a> -
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm/commits/master" id="changelog"><span data-i18n="global-changelog">Changelog</span></a>
</strong>
</footer>
@@ -162,6 +162,8 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.parser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.bidi.min.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/i18n.js"></script>
<script src="../js/app.js"></script>
<script>
$(function () {

View File

@@ -6,8 +6,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script> <!--Change to cdnjs once available-->
<link rel="icon" href="../favicon.png" type="image/png">
<link rel="shortcut icon" href="../favicon.ico" type="img/x-icon">
<link rel="icon" href="../img/favicon.png" type="image/png">
<link rel="shortcut icon" href="../img/favicon.ico" type="img/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-sweetalert/1.0.1/sweetalert.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/2.4.2/css/AdminLTE.min.css">
@@ -52,8 +52,8 @@
<i class="fas fa-users fa-fw"></i> <span data-i18n="global-bots">Bots</span>
<span class="pull-right-container bot-status">
<small class="label pull-right bg-gray" id="offlineBots">0</small>
<small class="label pull-right bg-yellow" id="idleBots">0</small>
<small class="label pull-right bg-olive" id="activeBots">0</small>
<small class="label pull-right bg-yellow" id="onlineBots">0</small>
<small class="label pull-right bg-olive" id="farmingBots">0</small>
</span>
</a>
</li>
@@ -104,7 +104,7 @@
<i class="far fa-file-alt"></i>
<h3 class="box-title" data-i18n="global-log">Log</h3>
<div class="box-tools pull-right">
<button title="Toggle auto scroll" type="button" class="btn btn-box-tool text-olive" id="toggleAutoScroll"><i class="fas fa-toggle-on fa-2x"></i></button>
<button data-i18n="title-log-auto-scroll" title="Toggle auto scroll" type="button" class="btn btn-box-tool text-olive" id="toggleAutoScroll"><i class="fas fa-toggle-on fa-2x"></i></button>
</div>
</div>
<div class="box-body">
@@ -120,9 +120,9 @@
<footer class="main-footer">
<div class="pull-right"><strong data-i18n="global-version">Version</strong> <span id="version">0.0.0.0</span></div>
<strong>
<a href="https://github.com/JustArchi/ArchiSteamFarm">GitHub</a> -
<a href="https://github.com/JustArchi/ArchiSteamFarm/wiki"><span data-i18n="global-wiki">Wiki</span></a> -
<a href="https://github.com/JustArchi/ArchiSteamFarm/commits/master" id="changelog"><span data-i18n="global-changelog">Changelog</span></a>
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm">GitHub</a> -
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm/wiki"><span data-i18n="global-wiki">Wiki</span></a> -
<a target="_blank" href="https://github.com/JustArchi/ArchiSteamFarm/commits/master" id="changelog"><span data-i18n="global-changelog">Changelog</span></a>
</strong>
</footer>
@@ -147,6 +147,8 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.parser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.i18n/1.0.4/jquery.i18n.emitter.bidi.min.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/i18n.js"></script>
<script src="../js/app.js"></script>
<script>
$(function () {
@@ -182,8 +184,8 @@
ws.onclose = function (event) {
if (event.code !== 1000) { // Code 1000 means that the connection was closed normally
swal({
title: 'Error!',
text: 'Event code: ' + event.code,
title: $.i18n('global-error-title'),
text: $.i18n('log-event-code', event.code),
type: 'error'
}, function () { swal.close(); });
}