mirror of https://github.com/xwiki-labs/cryptpad
Server app prototype to display listed servers from accounts.cryptpad.fr
This commit is contained in:
parent
825820f6bf
commit
ba0a39f00c
|
@ -50,7 +50,8 @@
|
|||
"jszip": "Stuk/jszip#^3.1.5",
|
||||
"requirejs-plugins": "^1.0.3",
|
||||
"dragula.js": "3.7.2",
|
||||
"MathJax": "3.0.5"
|
||||
"MathJax": "3.0.5",
|
||||
"datatables": "^1.10.21"
|
||||
},
|
||||
"resolutions": {
|
||||
"bootstrap": "^v4.0.0",
|
||||
|
|
|
@ -0,0 +1,306 @@
|
|||
@import (reference) '../../customize/src/less2/include/framework.less';
|
||||
@import (reference) '../../customize/src/less2/include/sidebar-layout.less';
|
||||
@import (reference) '../../customize/src/less2/include/avatar.less';
|
||||
@import (reference) "../../customize/src/less2/include/limit-bar.less";
|
||||
|
||||
&.cp-app-accounts {
|
||||
.limit-bar_main();
|
||||
|
||||
.framework_min_main(
|
||||
@bg-color: @colortheme_admin-bg,
|
||||
@warn-color: @colortheme_admin-warn,
|
||||
@color: @colortheme_admin-color
|
||||
);
|
||||
.sidebar-layout_main();
|
||||
|
||||
.cp-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
|
||||
@plan_basic: #DDEFFF;
|
||||
@plan_pro: #E4FFDD;
|
||||
@plan_power: #F6DDFF;
|
||||
@alert-neutral: #EFEFEF;
|
||||
@active-color: #AFFDC2;
|
||||
@inactive-color: #FFD4D4;
|
||||
|
||||
|
||||
#cp-sidebarlayout-rightside {
|
||||
color: @cryptpad_text_col !important;
|
||||
.alert {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.cp-accounts-subscribe-anon, .cp-accounts-subscribe-form, .cp-accounts-subscribe-admin {
|
||||
max-width: 940px;
|
||||
margin: 10px auto 20px !important;
|
||||
}
|
||||
|
||||
.cp-accounts-donate {
|
||||
max-width: 650px;
|
||||
}
|
||||
|
||||
.cp-limit-container {
|
||||
.cp-limit-buttons {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cp-accounts-mysubs-addplan {
|
||||
max-width: 830px;
|
||||
#gift label {
|
||||
margin-bottom: 0;
|
||||
margin-top: 10px;
|
||||
font-weight: unset;
|
||||
}
|
||||
}
|
||||
.cp-accounts-subscribe-form {
|
||||
ul {
|
||||
list-style-position: outside;
|
||||
padding-left: 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.subscription-info {
|
||||
font-size: 14px;
|
||||
}
|
||||
.subscription-terms {
|
||||
font-size: 14px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.active-plan {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.choose-plan {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@media (max-width: @browser_media-medium-screen) {
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.plan {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
width: 300px;
|
||||
min-height: 350px;
|
||||
&:not(:last-child) {
|
||||
margin-right: 20px;
|
||||
@media (max-width: @browser_media-medium-screen) {
|
||||
margin-right: 0;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
.plan-header-text {
|
||||
text-transform: capitalize;
|
||||
font-size: 30px;
|
||||
}
|
||||
.plan-price-area {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
.plan-price-text {
|
||||
font-size: 60px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
ul.plan-details {
|
||||
flex: 1;
|
||||
padding-right: 10px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
.buttons {
|
||||
margin: 10px;
|
||||
button {
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.alert {
|
||||
margin: 0 10px;
|
||||
background: white;
|
||||
border: none;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
.plan-basic {
|
||||
background-color: @plan_basic;
|
||||
}
|
||||
.plan-pro {
|
||||
background-color: @plan_pro;
|
||||
}
|
||||
.plan-power {
|
||||
background-color: @plan_power;
|
||||
}
|
||||
.link-to-stripe {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 10px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
.info-bottom {
|
||||
font-size: 14px;
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.cp-accounts-mysubs-data {
|
||||
.active-subs {
|
||||
.subscription {
|
||||
min-height: 300px;
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.alert {
|
||||
background: white;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
color: inherit;
|
||||
border: none;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
button {
|
||||
flex-shrink: 0;
|
||||
margin-top: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.users {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
& > span {
|
||||
width: 180px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.subscription-container {
|
||||
.subscription {
|
||||
min-height: 175px;
|
||||
width: 300px;
|
||||
&:not(.details) {
|
||||
.creation, .notes, .expired, .cancel, .close-d, .storage {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
&.details {
|
||||
.open-d {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.subscription-container, .active-subs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
|
||||
.subscription {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
margin-right: 20px;
|
||||
padding: 10px;
|
||||
background-color: #eee;
|
||||
position: relative;
|
||||
|
||||
& > span {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
button.open-details {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.open-d, .close-d {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.billing, .shared, .expired {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
button {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
}
|
||||
.billing {
|
||||
.text {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
}
|
||||
|
||||
.plan {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.active, .inactive {
|
||||
position: absolute;
|
||||
padding: 0 5px;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
}
|
||||
.inactive {
|
||||
background-color: @inactive-color;
|
||||
}
|
||||
.active {
|
||||
background-color: @active-color;
|
||||
}
|
||||
|
||||
.benificiary-data {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: white;
|
||||
padding: 5px;
|
||||
.cp-avatar {
|
||||
margin-right: 10px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.name {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.notes {
|
||||
flex: 1;
|
||||
max-height: 60px;
|
||||
}
|
||||
|
||||
.avatar_main(30px);
|
||||
}
|
||||
}
|
||||
}
|
||||
.cp-accounts-mysubs-addplan {
|
||||
.avatar_main(30px);
|
||||
}
|
||||
|
||||
.cp-accounts-subscribe-admin {
|
||||
div.admin {
|
||||
margin-bottom: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.cp-accounts-admin {
|
||||
input[type="text"] {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="cp-app-noscroll">
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||
<script async data-bootload="/servers/app/inner.js" data-main="/common/sframe-boot.js?ver=1.6" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||
<style>
|
||||
.loading-hidden { display: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="cp-toolbar" class="cp-toolbar-container"></div>
|
||||
<div id="cp-sidebarlayout-container" style="display: none;">
|
||||
<div id="cp-sidebarlayout-rightside">
|
||||
<h1 id="cp-servers-title">CryptPad Server List</h1>
|
||||
<p id="cp-servers-desc">
|
||||
Lorem ipso sum. Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.Lorem ipso sum.
|
||||
</p>
|
||||
<table id="servers" class="display" style="width:100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>URL</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Version</th>
|
||||
<th>Registered Users</th>
|
||||
<th>Max connections</th>
|
||||
<th>First Connection</th>
|
||||
<th>Last Connection</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,56 @@
|
|||
// Load #1, load as little as possible because we are in a race to get the loading screen up.
|
||||
define([
|
||||
'jquery',
|
||||
'/bower_components/nthen/index.js',
|
||||
'/customize/application_config.js',
|
||||
'/common/dom-ready.js',
|
||||
'/common/common-interface.js',
|
||||
'/common/sframe-common.js',
|
||||
'/common/toolbar.js',
|
||||
'/bower_components/datatables/media/js/jquery.dataTables.min.js',
|
||||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||
'css!/bower_components/datatables/media/css/dataTables.bootstrap4.min.css',
|
||||
'css!/bower_components/datatables/media/css/jquery.dataTables.min.css',
|
||||
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||
'css!/servers/app/servers.css',
|
||||
'less!/servers/app/app-servers.less',
|
||||
], function ($, nThen, ApiConfig, DomReady, UI, SFCommon, Toolbar, DataTable) {
|
||||
var APP = {}
|
||||
|
||||
// Loaded in load #2
|
||||
nThen(function (waitFor) {
|
||||
DomReady.onReady(waitFor());
|
||||
}).nThen(function (waitFor) {
|
||||
$(waitFor(UI.addLoadingScreen));
|
||||
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||
}).nThen(function (/*waitFor*/) {
|
||||
APP.$container = $('#cp-sidebarlayout-container');
|
||||
APP.$toolbar = $('#cp-toolbar');
|
||||
var displayed = ['pageTitle'];
|
||||
var configTb = {
|
||||
displayed: displayed,
|
||||
$container: APP.$toolbar,
|
||||
sfCommon: common,
|
||||
pageTitle: "CryptPad Servers",
|
||||
metadataMgr: common.getMetadataMgr(),
|
||||
};
|
||||
APP.toolbar = Toolbar.create(configTb);
|
||||
APP.toolbar.$rightside.hide();
|
||||
APP.$container.show();
|
||||
UI.removeLoadingScreen();
|
||||
|
||||
$('#servers').DataTable( {
|
||||
"ajax": ApiConfig.accounts_api + "/api/servers",
|
||||
"columns" : [
|
||||
{ "data" : "url" },
|
||||
{ "data" : "name" },
|
||||
{ "data" : "desc" },
|
||||
{ "data" : "version" },
|
||||
{ "data" : "registeredUsers" },
|
||||
{ "data" : "maxOpenUniqueWebSockets" },
|
||||
{ "data" : "firstConnection" },
|
||||
{ "data" : "lastConnection" }
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,65 @@
|
|||
// Load #1, load as little as possible because we are in a race to get the loading screen up.
|
||||
define([
|
||||
'/bower_components/nthen/index.js',
|
||||
'/api/config',
|
||||
'/common/dom-ready.js',
|
||||
'/common/requireconfig.js',
|
||||
'/common/sframe-common-outer.js',
|
||||
], function (nThen, ApiConfig, DomReady, RequireConfig, SFCommonO) {
|
||||
var requireConfig = RequireConfig();
|
||||
|
||||
// Loaded in load #2
|
||||
nThen(function (waitFor) {
|
||||
DomReady.onReady(waitFor());
|
||||
}).nThen(function (waitFor) {
|
||||
var req = {
|
||||
cfg: requireConfig,
|
||||
req: [ '/common/loading.js' ],
|
||||
pfx: window.location.origin
|
||||
};
|
||||
window.rc = requireConfig;
|
||||
window.apiconf = ApiConfig;
|
||||
document.getElementById('sbox-iframe').setAttribute('src',
|
||||
ApiConfig.httpSafeOrigin + '/servers/app/inner.html?' + requireConfig.urlArgs +
|
||||
'#' + encodeURIComponent(JSON.stringify(req)));
|
||||
|
||||
// This is a cheap trick to avoid loading sframe-channel in parallel with the
|
||||
// loading screen setup.
|
||||
var done = waitFor();
|
||||
var onMsg = function (msg) {
|
||||
var data = JSON.parse(msg.data);
|
||||
if (data.q !== 'READY') { return; }
|
||||
window.removeEventListener('message', onMsg);
|
||||
var _done = done;
|
||||
done = function () { };
|
||||
_done();
|
||||
};
|
||||
window.addEventListener('message', onMsg);
|
||||
}).nThen(function (/*waitFor*/) {
|
||||
var addRpc = function (sframeChan, Cryptpad/*, Utils*/) {
|
||||
sframeChan.on('ACCOUNTS_GET_KEYS', function (data, cb) {
|
||||
Cryptpad.getUserObject(null, function (obj) {
|
||||
cb(obj);
|
||||
});
|
||||
});
|
||||
sframeChan.on('Q_UPDATE_LIMIT', function (data, cb) {
|
||||
Cryptpad.updatePinLimit(function (e) {
|
||||
cb({error: e});
|
||||
});
|
||||
});
|
||||
};
|
||||
var category;
|
||||
if (window.location.hash) {
|
||||
category = window.location.hash.slice(1);
|
||||
window.location.hash = '';
|
||||
}
|
||||
var addData = function (obj) {
|
||||
if (category) { obj.category = category; }
|
||||
};
|
||||
SFCommonO.start({
|
||||
noRealtime: true,
|
||||
addRpc: addRpc,
|
||||
addData: addData
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,192 @@
|
|||
(function () {
|
||||
var LS_LANG = "CRYPTPAD_LANG";
|
||||
|
||||
// add your module to this map so it gets used
|
||||
var map = {
|
||||
'de': 'Deutsch',
|
||||
'es': 'Español',
|
||||
'fr': 'Français',
|
||||
//'it': 'Italiano',
|
||||
};
|
||||
|
||||
var getStoredLanguage = function () { return localStorage.getItem(LS_LANG); };
|
||||
var getBrowserLanguage = function () { return navigator.language || navigator.userLanguage; };
|
||||
var getLanguage = function () {
|
||||
if (window.cryptpadLanguage) { return window.cryptpadLanguage; }
|
||||
if (getStoredLanguage()) { return getStoredLanguage(); }
|
||||
var l = getBrowserLanguage() || '';
|
||||
if (Object.keys(map).indexOf(l) !== -1) {
|
||||
return l;
|
||||
}
|
||||
// Edge returns 'fr-FR' --> transform it to 'fr' and check again
|
||||
return Object.keys(map).indexOf(l.split('-')[0]) !== -1 ? l.split('-')[0] : 'en';
|
||||
};
|
||||
var language = getLanguage();
|
||||
|
||||
var req = ['jquery', 'json!/accounts/resources/translations/messages.json'];
|
||||
if (language && map[language]) { req.push('json!/accounts/resources/translations/messages.' + language + '.json'); }
|
||||
|
||||
define(req, function($, Default, Language) {
|
||||
|
||||
var externalMap = JSON.parse(JSON.stringify(map));
|
||||
|
||||
map.en = 'English';
|
||||
var defaultLanguage = 'en';
|
||||
|
||||
var messages;
|
||||
|
||||
if (!Language || !language || language === defaultLanguage || language === 'default' || !map[language]) {
|
||||
messages = Default;
|
||||
}
|
||||
else {
|
||||
// Add the translated keys to the returned object
|
||||
messages = $.extend(true, {}, Default, Language);
|
||||
}
|
||||
|
||||
messages._languages = map;
|
||||
|
||||
// TODO
|
||||
messages._checkTranslationState = function (cb) {
|
||||
if (typeof(cb) !== "function") { return; }
|
||||
var allMissing = [];
|
||||
var reqs = [];
|
||||
Object.keys(externalMap).forEach(function (code) {
|
||||
reqs.push('/resources/translations/messages.' + code + '.js');
|
||||
});
|
||||
require(reqs, function () {
|
||||
var langs = arguments;
|
||||
Object.keys(externalMap).forEach(function (code, i) {
|
||||
var translation = langs[i];
|
||||
var missing = [];
|
||||
var checkInObject = function (ref, translated, path) {
|
||||
var updated = {};
|
||||
Object.keys(ref).forEach(function (k) {
|
||||
if (/^updated_[0-9]+_/.test(k) && !translated[k]) {
|
||||
var key = k.split('_').slice(2).join('_');
|
||||
// Make sure we don't already have an update for that key. It should not happen
|
||||
// but if it does, keep the latest version
|
||||
if (updated[key]) {
|
||||
var ek = updated[key];
|
||||
if (parseInt(ek.split('_')[1]) > parseInt(k.split('_')[1])) { return; }
|
||||
}
|
||||
updated[key] = k;
|
||||
}
|
||||
});
|
||||
Object.keys(ref).forEach(function (k) {
|
||||
if (/^_/.test(k) || k === 'driveReadme') { return; }
|
||||
var nPath = path.slice();
|
||||
nPath.push(k);
|
||||
if (!translated[k] || updated[k]) {
|
||||
if (updated[k]) {
|
||||
var uPath = path.slice();
|
||||
uPath.unshift('out');
|
||||
missing.push([code, nPath, 2, uPath.join('.') + '.' + updated[k]]);
|
||||
return;
|
||||
}
|
||||
return void missing.push([code, nPath, 1]);
|
||||
}
|
||||
if (typeof ref[k] !== typeof translated[k]) {
|
||||
return void missing.push([code, nPath, 3]);
|
||||
}
|
||||
if (typeof ref[k] === "object" && !Array.isArray(ref[k])) {
|
||||
checkInObject(ref[k], translated[k], nPath);
|
||||
}
|
||||
});
|
||||
Object.keys(translated).forEach(function (k) {
|
||||
if (/^_/.test(k) || k === 'driveReadme') { return; }
|
||||
var nPath = path.slice();
|
||||
nPath.push(k);
|
||||
if (typeof ref[k] === "undefined") {
|
||||
missing.push([code, nPath, 0]);
|
||||
}
|
||||
});
|
||||
};
|
||||
checkInObject(Default, translation, []);
|
||||
// Push the removals at the end
|
||||
missing.sort(function (a, b) {
|
||||
if (a[2] === 0 && b[2] !== 0) { return 1; }
|
||||
if (a[2] !== 0 && b[2] === 0) { return -1; }
|
||||
return 0;
|
||||
});
|
||||
Array.prototype.push.apply(allMissing, missing); // Destructive concat
|
||||
});
|
||||
cb(allMissing);
|
||||
});
|
||||
};
|
||||
|
||||
// Get keys with parameters
|
||||
messages._getKey = function (key, argArray) {
|
||||
if (!messages[key]) { return '?'; }
|
||||
var text = messages[key];
|
||||
if (typeof(text) === 'string') {
|
||||
return text.replace(/\{(\d+)\}/g, function (str, p1) {
|
||||
if (typeof(argArray[p1]) === 'string' || typeof(argArray[p1]) === "number") {
|
||||
return argArray[p1];
|
||||
}
|
||||
console.error("Only strings and numbers can be used in _getKey params!");
|
||||
return '';
|
||||
});
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
// Add handler to the language selector
|
||||
var storeLanguage = function (l) {
|
||||
localStorage.setItem(LS_LANG, l);
|
||||
};
|
||||
messages._initSelector = function ($select) {
|
||||
var selector = $select || $('#language-selector');
|
||||
|
||||
if (!selector.length) { return; }
|
||||
|
||||
var $button = $(selector).find('button .buttonTitle');
|
||||
// Select the current language in the list
|
||||
var option = $(selector).find('[data-value="' + language + '"]');
|
||||
selector.setValue(language || 'English');
|
||||
|
||||
// Listen for language change
|
||||
$(selector).find('a.languageValue').on('click', function () {
|
||||
var newLanguage = $(this).attr('data-value');
|
||||
storeLanguage(newLanguage);
|
||||
if (newLanguage !== language) {
|
||||
setTimeout(function () { window.location.reload(); });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var translateText = function (i, e) {
|
||||
var $el = $(e);
|
||||
var key = $el.data('localization');
|
||||
$el.html(messages[key]);
|
||||
};
|
||||
var translateAppend = function (i, e) {
|
||||
var $el = $(e);
|
||||
var key = $el.data('localization-append');
|
||||
$el.append(messages[key]);
|
||||
};
|
||||
var translateTitle = function (i, e) {
|
||||
var $el = $(this);
|
||||
var key = $el.data('localization-title');
|
||||
$el.attr('title', messages[key]);
|
||||
};
|
||||
var translatePlaceholder = function (i, e) {
|
||||
var $el = $(this);
|
||||
var key = $el.data('localization-placeholder');
|
||||
$el.attr('placeholder', messages[key]);
|
||||
};
|
||||
messages._applyTranslation = function () {
|
||||
$('[data-localization]').each(translateText);
|
||||
$('[data-localization-append]').each(translateAppend);
|
||||
$('#pad-iframe').contents().find('[data-localization]').each(translateText);
|
||||
$('[data-localization-title]').each(translateTitle);
|
||||
$('[data-localization-placeholder]').each(translatePlaceholder);
|
||||
$('#pad-iframe').contents().find('[data-localization-title]').each(translateTitle);
|
||||
};
|
||||
|
||||
messages._getLanguage = function () { return language; };
|
||||
|
||||
return messages;
|
||||
|
||||
});
|
||||
}());
|
|
@ -0,0 +1,360 @@
|
|||
.hide {
|
||||
display:none;
|
||||
}
|
||||
|
||||
div.disabled {
|
||||
opacity: 0.4;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
div.plan, div.renewal {
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
div.plan-selected, div.renewal-selected {
|
||||
border: 1px solid #dde;
|
||||
background: #eef;
|
||||
}
|
||||
#info {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.choose-plan .plan img {
|
||||
width: 100%;
|
||||
}
|
||||
.spinner-div {
|
||||
margin: 20px auto;
|
||||
text-align: center;
|
||||
display: block;
|
||||
}
|
||||
.loading-message {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
/* login form */
|
||||
|
||||
.login-form {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.login-form-entry {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
.support-disabled {
|
||||
opacity: 0.4;
|
||||
background: #eee;
|
||||
}
|
||||
.support-pro-noauth {
|
||||
width: 90%;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
|
||||
.plan-details, .support-details, .donate-details {
|
||||
margin-top: 20px;
|
||||
text-align:left;
|
||||
font-family: lato, Helvetica, sans-serif;
|
||||
font-size: 1.02em;
|
||||
}
|
||||
|
||||
/*End of Plan Style*/
|
||||
|
||||
.choose-renewal {
|
||||
margin: 10px 10%;
|
||||
padding: 20px;
|
||||
flex-flow: column;
|
||||
display: flex;
|
||||
background: #efe;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.renewal-options {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
.cp h3.renewal-description {
|
||||
padding-top: 0;
|
||||
}
|
||||
.renewal-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
.renewal-label input {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
|
||||
.cp button.btn-plan-basic, button.btn-donate5, button.btn-gift {
|
||||
background-color: #00ADEE;
|
||||
border-color: #00ADEE;
|
||||
}
|
||||
.cp button.btn-plan-pro {
|
||||
background-color: #78b336;
|
||||
border-color: #78b336;
|
||||
}
|
||||
.cp button.btn-plan-power, .cp button.btn-donate10 {
|
||||
background-color: #F87217;
|
||||
border-color: #F87217;
|
||||
}
|
||||
.cp button.paybutton:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table.subscription-table {
|
||||
width: 100%;
|
||||
}
|
||||
table.subscription-table .cell-benificiary {
|
||||
max-width: 200px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
table.subscription-table tr.personnal-subscription {
|
||||
background-color: #eef;
|
||||
}
|
||||
table.subscription-table .cell-cancel {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.active-subs div.buttons {
|
||||
text-align: center;
|
||||
}
|
||||
.active-subs div.buttons button {
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.active-subs div.buttons .show-active-only-box {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.cp-contacts-container {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
.cp-contacts-container .cp-contact {
|
||||
padding: 5px;
|
||||
margin-right: 5px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-right: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.cp-contacts-container .cp-contact:hover {
|
||||
background: rgba(0,0,0,0.2);
|
||||
}
|
||||
.cp-contacts-container .cp-avatar {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.cp-contacts-container .cp-name {
|
||||
width: 100px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
.subscription-form div.buttons {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#info .button-container {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
|
||||
#info div.row > div {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
#info div.row {
|
||||
margin-right: 0px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
#info #error {
|
||||
padding: 0 10px 0 10px;
|
||||
}
|
||||
/* TODO(cjd) this is crap */
|
||||
#info > span {
|
||||
padding-left: 15px;
|
||||
}
|
||||
#info a.btn {
|
||||
color: white;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
#heading {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pay-spinner {
|
||||
position: fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
background-color:rgba(0, 0, 0, 0.6);
|
||||
z-index: 999999;
|
||||
color:white;
|
||||
|
||||
min-height: 100%;
|
||||
min-height: 100vh;
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.pay-spinner div {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
#hallOfFameCheck {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
|
||||
.faq-container .faq-questions-q {
|
||||
color: #3a84b6;
|
||||
padding: 0;
|
||||
margin-bottom: 0;
|
||||
margin-top: 5px;
|
||||
cursor: pointer;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.faq-container .faq-questions-q:hover {
|
||||
color: #2e688f;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.faq-container .faq-questions-a {
|
||||
display: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.crypto input {
|
||||
width: 100%;
|
||||
background-color: rgba(0,0,0,0.03);
|
||||
border: 0px;
|
||||
}
|
||||
.crypto table {
|
||||
width: 100%;
|
||||
}
|
||||
.crypto .coin-address {
|
||||
width: 100%;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.cp-admin-tabs-container {
|
||||
height: 50px;
|
||||
margin: 20px 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.cp-admin-tab {
|
||||
height: 100%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
background: #EEF;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
border-top: 1px solid #AAA;
|
||||
border-left: 1px solid #AAA;
|
||||
border-right: 1px solid #AAA;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.cp-admin-tab:hover {
|
||||
background: #DDE;
|
||||
}
|
||||
.cp-admin-tab.active {
|
||||
background: #DDE;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.cp-admin-stats {
|
||||
background-color: #EEE;
|
||||
padding: 20px;
|
||||
margin: 20px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.cp-admin-stats p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.cp div.cp-stats {
|
||||
flex: 1;
|
||||
}
|
||||
.cp div.cp-stats * {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cp-admin-stats .cp-stats-note {
|
||||
font-style: italic;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cp-admin-edit-getform input {
|
||||
margin: 0 10px;
|
||||
}
|
||||
.cp-admin-edit-found th {
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
.cp-admin-edit-found tbody tr:hover {
|
||||
background: #EEE;
|
||||
}
|
||||
.cp-admin-edit-found td {
|
||||
padding: 5px;
|
||||
border: 1px solid #CCC;
|
||||
cursor: pointer;
|
||||
}
|
||||
.cp-admin-edit-getform input {
|
||||
margin: 0 10px;
|
||||
}
|
||||
.cp-admin-edit-form p {
|
||||
background: #AA0000;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
padding: 5px;
|
||||
}
|
||||
.cp-admin-edit-form-content .cp-edit-field {
|
||||
font-weight: bold;
|
||||
}
|
||||
.cp-admin-edit-form-content .cp-edit-note {
|
||||
font-size: 0.9em;
|
||||
font-style: italic;
|
||||
}
|
||||
.cp-admin-edit-form-content input {
|
||||
margin: 0 10px;
|
||||
padding: 0 5px;
|
||||
border: 1px solid #888;
|
||||
}
|
||||
.cp-admin-edit-form-content {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CryptPad</title>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="referrer" content="no-referrer" />
|
||||
<script async data-bootload="app/main.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||
<link href="/customize/src/outer.css?ver=1.1" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="sbox-iframe">
|
Loading…
Reference in New Issue