frontend: check in html, css, js
This commit is contained in:
parent
5b7b97a4bf
commit
a88dea879b
@ -1,7 +1,15 @@
|
||||
SHELL = bash
|
||||
|
||||
# list of JS files to be built
|
||||
JS_BUILD =
|
||||
JS_BUILD = jquery.js vue.js highlight.js chartist.js login.js signup.js dashboard.js
|
||||
|
||||
jquery.js = jquery.js
|
||||
vue.js = vue.js
|
||||
highlight.js = highlight.js
|
||||
chartist.js = chartist.js
|
||||
login.js = utils.js http.js auth-common.js login.js
|
||||
signup.js = utils.js http.js auth-common.js signup.js
|
||||
dashboard.js = utils.js http.js errors.js self.js dashboard.js dashboard-setting.js dashboard-domain.js dashboard-installation.js dashboard-general.js dashboard-moderation.js dashboard-statistics.js dashboard-import.js dashboard-danger.js
|
||||
|
||||
# for each file in $(JS_BUILD), list its composition
|
||||
|
||||
@ -29,8 +37,6 @@ JS_PROD_BUILD_FILES = $(addprefix $(JS_PROD_BUILD_DIR)/, $(JS_BUILD))
|
||||
JS_MINIFIER = uglifyjs
|
||||
JS_MINIFIER_FLAGS = --compress --mangle
|
||||
|
||||
ENV_JS = env.js
|
||||
|
||||
SASS_SRC_DIR = sass
|
||||
SASS_SRC_FILES = $(wildcard $(SASS_SRC_DIR)/*.scss)
|
||||
CSS_DEVEL_BUILD_DIR = $(DEVEL_BUILD_DIR)/css
|
||||
@ -69,7 +75,7 @@ $(HTML_PROD_BUILD_FILES): $(HTML_PROD_BUILD_DIR)/%.html: $(HTML_DEVEL_BUILD_DIR)
|
||||
devel-js: $(JS_DEVEL_BUILD_FILES)
|
||||
|
||||
.SECONDEXPANSION:
|
||||
$(JS_DEVEL_BUILD_FILES): $(JS_DEVEL_BUILD_DIR)/%.js: $$(addprefix $$(JS_SRC_DIR)/, $$(%.js) $$(ENV_JS))
|
||||
$(JS_DEVEL_BUILD_FILES): $(JS_DEVEL_BUILD_DIR)/%.js: $$(addprefix $$(JS_SRC_DIR)/, $$(%.js))
|
||||
>$@; \
|
||||
for f in $^; do \
|
||||
printf "// %s\n" "$$f" >>$@; \
|
||||
|
1
frontend/account.html
Normal file
1
frontend/account.html
Normal file
@ -0,0 +1 @@
|
||||
|
383
frontend/dashboard.html
Normal file
383
frontend/dashboard.html
Normal file
@ -0,0 +1,383 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="<<<.CdnPrefix>>>/js/jquery.js"></script>
|
||||
<script src="<<<.CdnPrefix>>>/js/vue.js"></script>
|
||||
<script src="<<<.CdnPrefix>>>/js/highlight.js"></script>
|
||||
<script src="<<<.CdnPrefix>>>/js/chartist.js"></script>
|
||||
<script src="<<<.CdnPrefix>>>/js/dashboard.js"></script>
|
||||
<link rel="stylesheet" href="<<<.CdnPrefix>>>/css/chartist.css">
|
||||
<link rel="stylesheet" href="<<<.CdnPrefix>>>/css/dashboard.css">
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700|Source+Sans+Pro:200,300,400,700" rel="stylesheet">
|
||||
<title>Commento: Dashboard</title>
|
||||
</head>
|
||||
|
||||
<div id="navbar" class="navbar">
|
||||
<a href="/" class="navbar-item navbar-logo-text"><img src="/images/logo.svg" class="navbar-logo">Commento</a>
|
||||
<div class="navbar-item float-right">
|
||||
<a href="/logout" class="navbar-item">Logout</a>
|
||||
<a href="/account" class="navbar-item">Account Settings</a>
|
||||
<div id="owner-name">{{name}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.onload = function() {
|
||||
window.selfGet(function() {
|
||||
window.vueConstruct(function() {
|
||||
window.navbarFill();
|
||||
window.domainRefresh();
|
||||
$(document).ready(function(){
|
||||
$("ul.tabs li").click(function(){
|
||||
var tab_id = $(this).attr("data-tab");
|
||||
|
||||
$("ul.tabs li").removeClass("current");
|
||||
$(".content").removeClass("current");
|
||||
|
||||
$(this).addClass("current");
|
||||
$("#"+tab_id).addClass("current");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="global-error" id="global-error"></div>
|
||||
<div class="global-ok" id="global-ok"></div>
|
||||
|
||||
<div id="dashboard" class="dashboard-container">
|
||||
<div class="pane-left">
|
||||
<div class="tree" v-if="domains.length == 0 || domains[0].show == false">
|
||||
<img class="tree-svg" src="/images/tree.svg">
|
||||
It's so quiet in here.
|
||||
</div>
|
||||
|
||||
<div class="pane-setting" v-for="domain in domains" v-on:click="window.domainSelect(domain.domain)" id="{{domain.hex}}" v-bind:class="{selected: domain.selected}" v-if="domain.show">
|
||||
<div class="pane-setting-inside">
|
||||
<div class="setting-title">{{domain.name}}</div>
|
||||
<div class="setting-subtitle">{{domain.domain}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pane-setting" id="domain-add" onclick="window.location.hash='#new-domain-modal'">
|
||||
<div class="pane-setting-inside super-setting">
|
||||
<div class="super-setting-title">+</div>
|
||||
<div class="super-setting-text">New Domain</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pane-middle">
|
||||
<div v-if="showSettings" class="pane-setting" v-for="setting in settings" v-on:click="window.settingSelect(setting.id)" id="{{setting.id}}" v-bind:class="{selected: setting.selected}">
|
||||
<div class="pane-setting-inside">
|
||||
<div class="setting-title">{{setting.text}}</div>
|
||||
<div class="setting-subtitle">{{setting.meaning}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="select-a-domain" v-if="!showSettings">
|
||||
Select a website on the left.
|
||||
</div>
|
||||
</div>
|
||||
<div class="pane-right">
|
||||
|
||||
<!-- Installation -->
|
||||
<div id="installation-view" class="view hidden">
|
||||
<div class="view-inside">
|
||||
<div class="large-view">
|
||||
<div class="tabs-container">
|
||||
<div class="tab">
|
||||
<ul class="tabs">
|
||||
<li class="tab-link original current" data-tab="install-tab-1">Universal Snippet</li>
|
||||
</ul>
|
||||
|
||||
<div id="install-tab-1" class="content original current">
|
||||
<div class="import-text">
|
||||
Copy the following piece of HTML code and paste it where you'd like Commento to load.
|
||||
</div>
|
||||
|
||||
<pre><code id="code-div" class="html"></code></pre>
|
||||
|
||||
<div class="text">
|
||||
And that's it. All your settings, themes, and comments would be automagically loaded. Commento is mobile-responsive too, as it simply fills the container it is put in.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stats -->
|
||||
<div id="statistics-view" class="view hidden">
|
||||
<div class="view-inside">
|
||||
<div class="mid-view center">
|
||||
<div class="center center-title">
|
||||
Analytics
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="number">
|
||||
<div class="digits gray-digits">{{domains[cd].viewsLast30Days.zeros}}</div>
|
||||
<div class="digits">{{domains[cd].viewsLast30Days.num}}</div>
|
||||
<div class="digits dark-gray-digits">{{domains[cd].viewsLast30Days.units}}</div>
|
||||
</div>
|
||||
<div class="text">
|
||||
views in the last 30 days
|
||||
</div>
|
||||
<div class="graph" id="views-graph"></div>
|
||||
</div>
|
||||
|
||||
<div class="stat">
|
||||
<div class="number">
|
||||
<div class="digits gray-digits">{{domains[cd].commentsLast30Days.zeros}}</div>
|
||||
<div class="digits">{{domains[cd].commentsLast30Days.num}}</div>
|
||||
<div class="digits dark-gray-digits">{{domains[cd].commentsLast30Days.units}}</div>
|
||||
</div>
|
||||
<div class="text">
|
||||
comments in the last 30 days
|
||||
</div>
|
||||
<div class="graph" id="comments-graph"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- moderation -->
|
||||
<div id="moderation-view" class="view hidden">
|
||||
<div class="view-inside">
|
||||
<div class="small-view mid-view">
|
||||
<div class="tabs-container">
|
||||
<div class="tab">
|
||||
<ul class="tabs">
|
||||
<li class="tab-link original current" data-tab="mod-tab-1">Moderator List</li>
|
||||
</ul>
|
||||
|
||||
<div id="mod-tab-1" class="content original current">
|
||||
<div class="pitch">
|
||||
Moderators have the power to approve and delete comments. To make someone a moderator, add their email address down below. Once added, shiny new moderation buttons will appear on each comment for that person on each page on this domain.
|
||||
</div>
|
||||
<div class="email-container">
|
||||
<div class="email">
|
||||
<input class="input" type="text" id="new-mod" placeholder="Email">
|
||||
<button id="new-mod-button" class="email-button" onclick="window.moderatorNewHandler()">Add moderator</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mod-emails-container">
|
||||
<div class="content">
|
||||
<div class="mod-email" v-for="email in domains[cd].moderators" v-if="domains[cd].moderators.length > 0">
|
||||
<div class="email">{{email.email}}</div>
|
||||
<div class="delete" v-on:click="window.moderatorDeleteHandler(email.email)">Delete</div>
|
||||
<div class="date">added {{email.timeAgo}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- General Settings -->
|
||||
<div id="general-view" class="view hidden">
|
||||
<div class="view-inside">
|
||||
<div class="small-mid-view">
|
||||
<div class="center center-title">
|
||||
General Settings
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="row">
|
||||
<div class="label">Website Name</div>
|
||||
<input class="input gray-input" id="cur-domain-name" type="text" :placeholder="domains[cd].origName" v-model="domains[cd].name">
|
||||
</div>
|
||||
|
||||
<div class="row no-border round-check">
|
||||
<input type="checkbox" class="switch" v-model="domains[cd].autoSpamFilter" id="spam-filtering">
|
||||
<label for="spam-filtering">Automatic spam filtering</label>
|
||||
<div class="pitch">
|
||||
Commento uses Akismet's advanced spam detection techniques to automatically identify and remove spam comments. We strongly recommended you leave enabled.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-border round-check">
|
||||
<input type="checkbox" class="switch" v-model="domains[cd].requireModeration" id="require-moderation">
|
||||
<label for="require-moderation">Require all comments to be approved manually</label>
|
||||
<div class="pitch">
|
||||
Enabling this would require a moderator to approve every comment. Moderators can manually delete comments even if this is not enabled.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-border round-check">
|
||||
<input type="checkbox" class="switch" v-model="domains[cd].requireIdentification" id="require-identification">
|
||||
<label for="require-identification">Require identification</label>
|
||||
<div class="pitch">
|
||||
Enabling this would require all commenters to authenticate themselves (using their Google account, for example). Disabling would optionally allow anonymous comments.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="new-domain-error" class="modal-error-box"></div>
|
||||
</div>
|
||||
<div class="center">
|
||||
<button id="save-general-button" onclick="window.generalSaveHandler()" class="button">Save Changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import Comments -->
|
||||
<div id="import-view" class="view hidden">
|
||||
<div class="view-inside">
|
||||
<div class="large-view">
|
||||
<div class="tabs-container">
|
||||
<div class="tab">
|
||||
<ul class="tabs">
|
||||
<li class="tab-link original current" data-tab="install-tab-1">Disqus</li>
|
||||
</ul>
|
||||
|
||||
<div id="install-tab-1" class="content original current">
|
||||
<div class="import-text">
|
||||
If you're currently using Disqus and want to import all your comments into Commento, you can do so:
|
||||
<ul>
|
||||
<li>
|
||||
Go to <a href="http://disqus.com/admin/discussions/export/">the admin export section</a> in Disqus and click on <b>Export Comments</b>. This should start the process of exporting your comments.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
After a while, you'll receive an email from Disqus with a link to a compressed archive of all comments and associated data. Copy and paste that link here and start the import process:
|
||||
|
||||
<br><br>
|
||||
|
||||
<div class="email-container">
|
||||
<div class="email">
|
||||
<input class="input" type="text" id="new-mod" placeholder="https://media.disqus.com/uploads/...">
|
||||
<button class="email-button">Import</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="subtext-container">
|
||||
<div class="subtext">
|
||||
<div>Note: it is strongly recommended you do this only once. Multiple imports for the same domain may have unintended effects.</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
We'll automatically download this file, extract it, parse it and import comments into Commento. The URL information will be preserved. By using this service, you grant Commento the permission to download and process your Disqus information.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Danger Zone -->
|
||||
<div id="danger-view" class="view hidden">
|
||||
<div class="view-inside">
|
||||
<div class="mid-view">
|
||||
<div class="tabs-container">
|
||||
<div class="tab">
|
||||
<ul class="tabs">
|
||||
<li class="tab-link original current" data-tab="danger-tab-1">Freeze Comments</li>
|
||||
<li class="tab-link current" data-tab="danger-tab-2">Delete Domain</li>
|
||||
</ul>
|
||||
|
||||
<div id="danger-tab-1" class="content original current">
|
||||
<div class="box" v-if="domains[cd].state == 'frozen'">
|
||||
<div class="box-subtitle">
|
||||
If you desire to re-allow comments again on your website, you can do so. You can, of course, freeze the site again in the future.
|
||||
</div>
|
||||
|
||||
<button onclick="window.location.hash='#unfreeze-domain-modal'" class="button green-button">Unfreeze Domain</button>
|
||||
</div>
|
||||
|
||||
<div class="box" v-if="domains[cd].state != 'frozen'">
|
||||
<div class="box-subtitle">
|
||||
If you desire to temporarily freeze new comments (domain-wide), thereby making it read-only, you can do so. You can choose to unfreeze later; this is temporary.
|
||||
</div>
|
||||
|
||||
<button id="orange-button" onclick="window.location.hash='#freeze-domain-modal'" class="button orange-button">Freeze Domain</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="danger-tab-2" class="content">
|
||||
<div class="box">
|
||||
<div class="box-subtitle">
|
||||
Want to completely remove Commento from your website? This will permanently delete all comments and there is literally no way to retrieve your data once you do this.
|
||||
</div>
|
||||
|
||||
<button id="big-red-button" class="button big-red-button" onclick="window.location.hash='#delete-domain-modal'">Delete Domain</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="freeze-domain-modal" class="modal-window">
|
||||
<div class="inside">
|
||||
<a href="#modal-close" title="Close" class="modal-close"></a>
|
||||
<div class="modal-title">Freeze Domain</div>
|
||||
<div class="modal-subtitle">
|
||||
Are you absolutely sure you want to freeze your domain, thereby making it read-only? You can choose to unfreeze later; this is temporary.
|
||||
</div>
|
||||
<div class="modal-contents">
|
||||
<button id="orange-button" class="button orange-button" onclick="window.domainFreezeHandler()">Freeze Domain</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="unfreeze-domain-modal" class="modal-window">
|
||||
<div class="inside">
|
||||
<a href="#modal-close" title="Close" class="modal-close"></a>
|
||||
<div class="modal-title">Unfreeze Domain</div>
|
||||
<div class="modal-subtitle">
|
||||
Are you absolutely sure you want to unfreeze your domain? This will re-allow new comments. You can choose to freeze again in the future.
|
||||
</div>
|
||||
<div class="modal-contents">
|
||||
<button id="blue-button" class="button green-button" onclick="window.domainUnfreezeHandler()">Unfreeze Domain</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="delete-domain-modal" class="modal-window">
|
||||
<div class="inside">
|
||||
<a href="#modal-close" title="Close" class="modal-close"></a>
|
||||
<div class="modal-title">Delete Domain</div>
|
||||
<div class="modal-subtitle">
|
||||
Are you absolutely sure? This will permanently delete all comments and there is literally no way to retrieve your data once you do this.
|
||||
</div>
|
||||
<div class="modal-contents">
|
||||
<button id="big-red-button" class="button big-red-button" onclick="window.domainDeleteHandler()">Delete Domain</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="new-domain-modal" class="modal-window">
|
||||
<div class="inside">
|
||||
<a href="#modal-close" title="Close" class="modal-close"></a>
|
||||
<div class="modal-title">Add a New Domain</div>
|
||||
<div class="modal-contents">
|
||||
<div class="box">
|
||||
<div class="box-subtitle">
|
||||
Remember to double-check the domain, as only connections from this domain will be accepted. You <b>cannot</b> change this in the future. You can change the name, however.
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="label">Website Name</div>
|
||||
<input class="input gray-input" id="new-domain-name" type="text" placeholder="Billie Joe's Blog">
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="label">Website Domain</div>
|
||||
<input class="input gray-input" id="new-domain-domain" type="text" placeholder="https://blog.billie.com">
|
||||
</div>
|
||||
</div>
|
||||
<div id="new-domain-error" class="modal-error-box"></div>
|
||||
<div class="center">
|
||||
<button id="add-site-button" onclick="window.domainNewHandler()" class="button">Add Domain</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</html>
|
BIN
frontend/images/120x120.png
Normal file
BIN
frontend/images/120x120.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.2 KiB |
7
frontend/images/close.svg
Normal file
7
frontend/images/close.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="22px" height="22px">
|
||||
<g id="Home-(v2)" fill="none" fill-rule="evenodd">
|
||||
<g id="Artboard-3" fill="#CFD7DF">
|
||||
<path id="Close" d="M11 9.55L7.75 6.3A1.02 1.02 0 0 0 6.3 7.75L9.55 11 6.3 14.25a1.02 1.02 0 0 0 1.45 1.45L11 12.45l3.25 3.25a1.02 1.02 0 0 0 1.45-1.45L12.45 11l3.25-3.25a1.02 1.02 0 0 0-1.45-1.45L11 9.55zM11 22a11 11 0 1 1 0-22 11 11 0 0 1 0 22z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 439 B |
10
frontend/images/logo.svg
Normal file
10
frontend/images/logo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 11 KiB |
38
frontend/images/tree.svg
Normal file
38
frontend/images/tree.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 12 KiB |
11
frontend/js/auth-common.js
Normal file
11
frontend/js/auth-common.js
Normal file
@ -0,0 +1,11 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Prefills the email field from the URL parameter.
|
||||
global.prefillEmail = function() {
|
||||
if (paramGet("email") != undefined) {
|
||||
$("#email").val(paramGet("email"));
|
||||
$("#password").click();
|
||||
}
|
||||
};
|
||||
|
||||
} (window, document));
|
10
frontend/js/chartist.js
Normal file
10
frontend/js/chartist.js
Normal file
File diff suppressed because one or more lines are too long
41
frontend/js/dashboard-danger.js
Normal file
41
frontend/js/dashboard-danger.js
Normal file
@ -0,0 +1,41 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Opens the danger zone.
|
||||
global.dangerOpen = function() {
|
||||
$(".view").hide();
|
||||
$("#danger-view").show();
|
||||
};
|
||||
|
||||
|
||||
// Deletes a domain.
|
||||
global.domainDeleteHandler = function() {
|
||||
var data = global.dashboard.$data;
|
||||
|
||||
domainDelete(data.domains[data.cd].domain, function(success) {
|
||||
if (success)
|
||||
document.location = '/dashboard';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Freezes a domain.
|
||||
global.domainFreezeHandler = function() {
|
||||
var data = global.dashboard.$data;
|
||||
|
||||
data.domains[data.cd].state = "frozen"
|
||||
domainUpdate(data.domains[data.cd])
|
||||
document.location.hash = "#modal-close";
|
||||
}
|
||||
|
||||
|
||||
// Unfreezes a domain.
|
||||
global.domainUnfreezeHandler = function() {
|
||||
var data = global.dashboard.$data;
|
||||
|
||||
data.domains[data.cd].state = "unfrozen"
|
||||
domainUpdate(data.domains[data.cd])
|
||||
document.location.hash = "#modal-close";
|
||||
}
|
||||
|
||||
|
||||
} (window, document));
|
144
frontend/js/dashboard-domain.js
Normal file
144
frontend/js/dashboard-domain.js
Normal file
@ -0,0 +1,144 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Selects a domain.
|
||||
global.domainSelect = function(domain) {
|
||||
var data = global.dashboard.$data;
|
||||
var domains = data.domains;
|
||||
|
||||
for (var i = 0; i < domains.length; i++) {
|
||||
if (domains[i].domain == domain) {
|
||||
vs("frozen", domains[i].state == "frozen");
|
||||
domains[i].selected = true;
|
||||
data.cd = i;
|
||||
data.importedComments = domains[i].importedComments;
|
||||
}
|
||||
else
|
||||
domains[i].selected = false;
|
||||
}
|
||||
|
||||
data.showSettings = true;
|
||||
|
||||
settingDeselectAll();
|
||||
$(".view").hide();
|
||||
};
|
||||
|
||||
|
||||
// Deselects all domains.
|
||||
global.domainDeselectAll = function() {
|
||||
var data = global.dashboard.$data;
|
||||
var domains = data.domains;
|
||||
|
||||
for (var i = 0; i < domains.length; i++)
|
||||
domains[i].selected = false;
|
||||
}
|
||||
|
||||
|
||||
// Creates a new domain.
|
||||
global.domainNewHandler = function() {
|
||||
var json = {
|
||||
session: global.cookieGet("session"),
|
||||
name: $("#new-domain-name").val(),
|
||||
domain: $("#new-domain-domain").val(),
|
||||
}
|
||||
|
||||
global.buttonDisable("#add-site-button");
|
||||
global.post(global.origin + "/api/domain/new", json, function(resp) {
|
||||
global.buttonEnable("#add-site-button");
|
||||
|
||||
$("#new-domain-name").val("");
|
||||
$("#new-domain-domain").val("");
|
||||
document.location.hash = "#modal-close";
|
||||
|
||||
if (!resp.success) {
|
||||
global.globalErrorShow(resp.message);
|
||||
return;
|
||||
}
|
||||
|
||||
global.domainRefresh(function() {
|
||||
global.domainSelect(resp.domain);
|
||||
global.domainDeselectAll();
|
||||
global.settingSelect("installation");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Refreshes the list of domains.
|
||||
global.domainRefresh = function(callback) {
|
||||
var json = {
|
||||
session: global.cookieGet("session"),
|
||||
};
|
||||
|
||||
global.post(global.origin + "/api/domain/list", json, function(resp) {
|
||||
if (!resp.success) {
|
||||
global.globalErrorShow(resp.message);
|
||||
return;
|
||||
}
|
||||
|
||||
resp.domains = resp.domains.sort(function(a, b) {
|
||||
var x = a.creationDate; var y = b.creationDate;
|
||||
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
||||
});
|
||||
|
||||
for (var i = 0; i < resp.domains.length; i++) {
|
||||
resp.domains[i].show = true;
|
||||
resp.domains[i].selected = false;
|
||||
|
||||
resp.domains[i].origName = resp.domains[i].name;
|
||||
resp.domains[i].origDomain = resp.domains[i].domain;
|
||||
|
||||
resp.domains[i].viewsLast30Days = global.numberify(0);
|
||||
resp.domains[i].commentsLast30Days = global.numberify(0);
|
||||
|
||||
for (var j = 0; j < resp.domains[i].moderators.length; j++) {
|
||||
resp.domains[i].moderators[j].timeAgo = global.timeSince(
|
||||
Date.parse(resp.domains[i].moderators[j].addDate));
|
||||
}
|
||||
}
|
||||
|
||||
global.vs("domains", resp.domains);
|
||||
|
||||
if (callback !== undefined)
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// Updates a domain with the backend.
|
||||
global.domainUpdate = function(domain, callback) {
|
||||
var json = {
|
||||
session: global.cookieGet("session"),
|
||||
domain: domain,
|
||||
};
|
||||
|
||||
global.post(global.origin + "/api/domain/update", json, function(resp) {
|
||||
if (callback !== undefined)
|
||||
callback(resp.success);
|
||||
|
||||
if (!resp.success) {
|
||||
global.globalErrorShow(resp.message);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Deletes a domain.
|
||||
global.domainDelete = function(domain, callback) {
|
||||
var json = {
|
||||
session: global.cookieGet("session"),
|
||||
domain: domain,
|
||||
};
|
||||
|
||||
global.post(global.origin + "/api/domain/delete", json, function(resp) {
|
||||
if (!resp.success) {
|
||||
global.globalErrorShow(resp.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback !== undefined)
|
||||
callback(resp.success);
|
||||
});
|
||||
}
|
||||
|
||||
} (window, document));
|
19
frontend/js/dashboard-general.js
Normal file
19
frontend/js/dashboard-general.js
Normal file
@ -0,0 +1,19 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Opens the general settings window.
|
||||
global.generalOpen = function() {
|
||||
$(".view").hide();
|
||||
$("#general-view").show();
|
||||
};
|
||||
|
||||
global.generalSaveHandler = function() {
|
||||
var data = global.dashboard.$data;
|
||||
|
||||
global.buttonDisable("#save-general-button");
|
||||
global.domainUpdate(data.domains[data.cd], function() {
|
||||
global.globalOKShow("Settings saved!");
|
||||
global.buttonEnable("#save-general-button");
|
||||
});
|
||||
};
|
||||
|
||||
} (window, document));
|
33
frontend/js/dashboard-import.js
Normal file
33
frontend/js/dashboard-import.js
Normal file
@ -0,0 +1,33 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Opens the import window.
|
||||
global.importOpen = function() {
|
||||
$(".view").hide();
|
||||
$("#import-view").show();
|
||||
}
|
||||
|
||||
|
||||
global.importDisqus = function() {
|
||||
var url = $("#disqus-url").val();
|
||||
var data = global.dashboard.$data;
|
||||
|
||||
var json = {
|
||||
session: global.cookieGet("session"),
|
||||
domain: data.domains[data.cd].domain,
|
||||
url: url,
|
||||
}
|
||||
|
||||
global.buttonDisable("#disqus-import-button");
|
||||
global.post(global.origin + "/api/import/disqus", json, function(resp) {
|
||||
global.buttonEnable("#disqus-import-button");
|
||||
|
||||
if (!resp.success) {
|
||||
global.globalErrorShow(resp.message);
|
||||
return;
|
||||
}
|
||||
|
||||
globalOKShow("Imported " + resp.numImported + " comments!");
|
||||
});
|
||||
}
|
||||
|
||||
} (window, document));
|
22
frontend/js/dashboard-installation.js
Normal file
22
frontend/js/dashboard-installation.js
Normal file
@ -0,0 +1,22 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Opens the installation view.
|
||||
global.installationOpen = function() {
|
||||
var data = global.dashboard.$data;
|
||||
|
||||
var html = '' +
|
||||
'<div id="commento"></div>\n' +
|
||||
'<script src="' + window.cdn + '/js/commento.js"><\/script>\n' +
|
||||
'';
|
||||
|
||||
$("#code-div").text(html);
|
||||
|
||||
$('pre code').each(function(i, block) {
|
||||
hljs.highlightBlock(block);
|
||||
});
|
||||
|
||||
$(".view").hide();
|
||||
$("#installation-view").show();
|
||||
};
|
||||
|
||||
} (window, document));
|
82
frontend/js/dashboard-moderation.js
Normal file
82
frontend/js/dashboard-moderation.js
Normal file
@ -0,0 +1,82 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Opens the moderatiosn settings window.
|
||||
global.moderationOpen = function() {
|
||||
$(".view").hide();
|
||||
$("#moderation-view").show();
|
||||
};
|
||||
|
||||
|
||||
// Adds a moderator.
|
||||
global.moderatorNewHandler = function() {
|
||||
var data = global.dashboard.$data;
|
||||
var email = $("#new-mod").val();
|
||||
|
||||
var json = {
|
||||
session: global.cookieGet("session"),
|
||||
domain: data.domains[data.cd].domain,
|
||||
email: email,
|
||||
}
|
||||
|
||||
var idx = -1;
|
||||
for (var i = 0; i < data.domains[data.cd].moderators.length; i++) {
|
||||
if (data.domains[data.cd].moderators[i].email == email) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx == -1) {
|
||||
data.domains[data.cd].moderators.push({"email": email, "timeAgo": "just now"});
|
||||
global.buttonDisable("#new-mod-button");
|
||||
global.post(global.origin + "/api/domain/moderator/new", json, function(resp) {
|
||||
global.buttonEnable("#new-mod-button");
|
||||
|
||||
if (!resp.success) {
|
||||
global.globalErrorShow(resp.message);
|
||||
return
|
||||
}
|
||||
|
||||
global.globalOKShow("Added a new moderator!");
|
||||
$("#new-mod").val("");
|
||||
$("#new-mod").focus();
|
||||
});
|
||||
}
|
||||
else {
|
||||
global.globalErrorShow("Already a moderator.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Deletes a moderator.
|
||||
global.moderatorDeleteHandler = function(email) {
|
||||
var data = global.dashboard.$data;
|
||||
|
||||
var json = {
|
||||
session: global.cookieGet("session"),
|
||||
domain: data.domains[data.cd].domain,
|
||||
email: email,
|
||||
}
|
||||
|
||||
var idx = -1;
|
||||
for (var i = 0; i < data.domains[data.cd].moderators.length; i++) {
|
||||
if (data.domains[data.cd].moderators[i].email == email) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx != -1) {
|
||||
data.domains[data.cd].moderators.splice(idx, 1);
|
||||
global.post(global.origin + "/api/domain/moderator/delete", json, function(resp) {
|
||||
if (!resp.success) {
|
||||
global.globalErrorShow(resp.message);
|
||||
return
|
||||
}
|
||||
|
||||
globalOKShow("Removed!");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} (window, document));
|
46
frontend/js/dashboard-setting.js
Normal file
46
frontend/js/dashboard-setting.js
Normal file
@ -0,0 +1,46 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Sets the vue.js toggle to select and deselect panes visually.
|
||||
function settingSelectCSS(id) {
|
||||
var data = global.dashboard.$data;
|
||||
var settings = data.settings;
|
||||
|
||||
for (var i = 0; i < settings.length; i++) {
|
||||
if (settings[i].id == id) {
|
||||
settings[i].selected = true;
|
||||
}
|
||||
else {
|
||||
settings[i].selected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Selects a setting.
|
||||
global.settingSelect = function(id) {
|
||||
var data = global.dashboard.$data;
|
||||
var settings = data.settings;
|
||||
|
||||
settingSelectCSS(id);
|
||||
|
||||
$("ul.tabs li").removeClass("current");
|
||||
$(".content").removeClass("current");
|
||||
$(".original").addClass("current");
|
||||
|
||||
for (var i = 0; i < settings.length; i++) {
|
||||
if (id == settings[i].id)
|
||||
settings[i].open();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Deselects all settings.
|
||||
global.settingDeselectAll = function() {
|
||||
var data = global.dashboard.$data;
|
||||
var settings = data.settings;
|
||||
|
||||
for (var i = 0; i < settings.length; i++)
|
||||
settings[i].selected = false;
|
||||
}
|
||||
|
||||
} (window, document));
|
100
frontend/js/dashboard-statistics.js
Normal file
100
frontend/js/dashboard-statistics.js
Normal file
@ -0,0 +1,100 @@
|
||||
(function (global, document) {
|
||||
|
||||
global.numberify = function(x) {
|
||||
if (x == 0)
|
||||
return {"zeros": "000", "num": "", "units": ""}
|
||||
|
||||
if (x < 10)
|
||||
return {"zeros": "00", "num": x, "units": ""}
|
||||
|
||||
if (x < 100)
|
||||
return {"zeros": "0", "num": x, "units": ""}
|
||||
|
||||
if (x < 1000)
|
||||
return {"zeros": "", "num": x, "units": ""}
|
||||
|
||||
var res;
|
||||
|
||||
if (x < 1000000) {
|
||||
res = numberify((x/1000).toFixed(0))
|
||||
res.units = "K"
|
||||
}
|
||||
else if (x < 1000000000) {
|
||||
res = numberify((x/1000000).toFixed(0))
|
||||
res.units = "M"
|
||||
}
|
||||
else if (x < 1000000000000) {
|
||||
res = numberify((x/1000000000).toFixed(0))
|
||||
res.units = "B"
|
||||
}
|
||||
|
||||
if (res.num*10 % 10 == 0)
|
||||
res.num = Math.ceil(res.num);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
global.statisticsOpen = function() {
|
||||
var data = global.dashboard.$data;
|
||||
|
||||
var json = {
|
||||
session: global.cookieGet("session"),
|
||||
domain: data.domains[data.cd].domain,
|
||||
}
|
||||
|
||||
$(".view").hide();
|
||||
post(global.origin + "/api/domain/statistics", json, function(resp) {
|
||||
$("#statistics-view").show();
|
||||
|
||||
if (!resp.success) {
|
||||
globalErrorShow(resp.message);
|
||||
return;
|
||||
}
|
||||
|
||||
var options = {
|
||||
showPoint: false,
|
||||
axisY: {
|
||||
onlyInteger: true,
|
||||
showGrid: false,
|
||||
},
|
||||
axisX: {
|
||||
showGrid: false,
|
||||
},
|
||||
showArea: true,
|
||||
};
|
||||
|
||||
var views;
|
||||
var comments;
|
||||
|
||||
views = resp.viewsLast30Days;
|
||||
// views = [0, 1, 4, 16, 14, 12, 10, 25, 13, 5, 20, 25, 12, 57, 46, 64, 4, 36, 7, 80, 43, 86, 121, 6, 74, 94, 83, 73, 140, 89, 25];
|
||||
|
||||
comments = resp.commentsLast30Days;
|
||||
// comments = [0, 0, 1, 2, 3, 3, 4, 5, 7, 8, 5, 9, 9, 5, 6, 7, 8, 3, 1, 16, 3, 10, 8, 5, 12, 5, 4, 8, 4, 23, 19];
|
||||
|
||||
var labels = new Array();
|
||||
for (var i = 0; i < views.length; i++) {
|
||||
if ((views.length-i) % 7 == 0) {
|
||||
var x = (views.length-i)/7;
|
||||
labels.push(x + " week" + (x > 1 ? "s" : "") + " ago");
|
||||
}
|
||||
else
|
||||
labels.push("");
|
||||
}
|
||||
|
||||
new Chartist.Line("#views-graph", {
|
||||
labels: labels,
|
||||
series: [views],
|
||||
}, options);
|
||||
|
||||
new Chartist.Line("#comments-graph", {
|
||||
labels: labels,
|
||||
series: [comments],
|
||||
}, options);
|
||||
|
||||
data.domains[data.cd].viewsLast30Days = numberify(views.reduce(function(a, b) { return a + b; }, 0));
|
||||
data.domains[data.cd].commentsLast30Days = numberify(comments.reduce(function(a, b) { return a + b; }, 0));
|
||||
});
|
||||
}
|
||||
|
||||
} (window, document));
|
89
frontend/js/dashboard.js
Normal file
89
frontend/js/dashboard.js
Normal file
@ -0,0 +1,89 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Sets a vue.js field. Short for "vue set".
|
||||
function vs(field, value) {
|
||||
Vue.set(global.dashboard, field, value);
|
||||
}
|
||||
|
||||
|
||||
global.vs = vs;
|
||||
|
||||
|
||||
// Sets the owner's name in the navbar.
|
||||
global.navbarFill = function() {
|
||||
$("#owner-name").text(global.owner.name);
|
||||
};
|
||||
|
||||
|
||||
// Constructs the vue.js object
|
||||
global.vueConstruct = function(callback) {
|
||||
var settings = [
|
||||
{
|
||||
"id": "installation",
|
||||
"text": "Installation",
|
||||
"meaning": "Install Commento with HTML",
|
||||
"selected": false,
|
||||
"open": installationOpen,
|
||||
},
|
||||
{
|
||||
"id": "general",
|
||||
"text": "General Settings",
|
||||
"meaning": "Names, domains and the rest",
|
||||
"selected": false,
|
||||
"open": generalOpen,
|
||||
},
|
||||
{
|
||||
"id": "moderation",
|
||||
"text": "Moderation Settings",
|
||||
"meaning": "Approve and delete comments",
|
||||
"selected": false,
|
||||
"open": moderationOpen,
|
||||
},
|
||||
{
|
||||
"id": "statistics",
|
||||
"text": "Statistics",
|
||||
"meaning": "Usage and comment statistics",
|
||||
"selected": false,
|
||||
"open": statisticsOpen,
|
||||
},
|
||||
{
|
||||
"id": "import",
|
||||
"text": "Import Comments",
|
||||
"meaning": "Import from a different service",
|
||||
"selected": false,
|
||||
"open": importOpen,
|
||||
},
|
||||
{
|
||||
"id": "danger",
|
||||
"text": "Danger Zone",
|
||||
"meaning": "Delete or freeze domain",
|
||||
"selected": false,
|
||||
"open": dangerOpen,
|
||||
},
|
||||
];
|
||||
|
||||
var reactiveData = {
|
||||
// list of panes; mutable because selection information is stored within
|
||||
settings: settings,
|
||||
|
||||
// list of domains dynamically loaded; obviously mutable
|
||||
domains: [{show: false, viewsLast30Days: global.numberify(0), commentsLast30Days: global.numberify(0), moderators: []}],
|
||||
|
||||
// whether or not to show the settings column; mutable because we do not
|
||||
// show the column until a domain has been selected
|
||||
showSettings: false,
|
||||
|
||||
// currently selected domain index; obviously mutable
|
||||
cd: 0, // stands for "current domain"
|
||||
};
|
||||
|
||||
global.dashboard = new Vue({
|
||||
el: "#dashboard",
|
||||
data: reactiveData,
|
||||
});
|
||||
|
||||
if (callback !== undefined)
|
||||
callback();
|
||||
};
|
||||
|
||||
} (window, document));
|
31
frontend/js/errors.js
Normal file
31
frontend/js/errors.js
Normal file
@ -0,0 +1,31 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Registers a given ID for a fade out after 5 seconds.
|
||||
global.registerHide = function(id) {
|
||||
var el = $(id);
|
||||
|
||||
setTimeout(function() {
|
||||
$(id).fadeOut("fast");
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
|
||||
// Shows a global message on the given label ID and registers it for hiding.
|
||||
global.showGlobalMessage = function(id, text) {
|
||||
global.textSet(id, text);
|
||||
global.registerHide(id);
|
||||
}
|
||||
|
||||
|
||||
// Shows a global error message.
|
||||
global.globalErrorShow = function(text) {
|
||||
global.showGlobalMessage("#global-error", text);
|
||||
}
|
||||
|
||||
|
||||
// Shows a global success message.
|
||||
global.globalOKShow = function(text) {
|
||||
global.showGlobalMessage("#global-ok", text);
|
||||
}
|
||||
|
||||
} (window, document));
|
3
frontend/js/highlight.js
Normal file
3
frontend/js/highlight.js
Normal file
File diff suppressed because one or more lines are too long
31
frontend/js/http.js
Normal file
31
frontend/js/http.js
Normal file
@ -0,0 +1,31 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Performs a JSON POST request to the given url with the given data and
|
||||
// calls the callback function with the JSON response.
|
||||
global.post = function(url, json, callback) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
data: JSON.stringify(json),
|
||||
success: function(data) {
|
||||
var resp = JSON.parse(data);
|
||||
callback(resp);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Performs a GET request and calls the callback function with the JSON
|
||||
// response.
|
||||
global.get = function(url, callback) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "GET",
|
||||
success: function(data) {
|
||||
var resp = JSON.parse(data);
|
||||
callback(resp);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
} (window, document));
|
4
frontend/js/jquery.js
vendored
Normal file
4
frontend/js/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
73
frontend/js/login.js
Normal file
73
frontend/js/login.js
Normal file
@ -0,0 +1,73 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Shows messages produced from email confirmation attempts.
|
||||
function displayConfirmedEmail() {
|
||||
var confirmed = global.paramGet("confirmed");
|
||||
|
||||
if (confirmed == "true") {
|
||||
$("#msg").html("Successfully confirmed! Login to continue.")
|
||||
}
|
||||
else if (confirmed == "false") {
|
||||
$("#err").html("That link has expired.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Shows messages produced from password reset attempts.
|
||||
function displayChangedPassword() {
|
||||
var changed = paramGet("changed");
|
||||
|
||||
if (changed == "true") {
|
||||
$("#msg").html("Password changed successfully! Login to continue.")
|
||||
}
|
||||
}
|
||||
|
||||
// Shows messages produced from completed signups.
|
||||
function displaySignedUp() {
|
||||
var signedUp = paramGet("signedUp");
|
||||
|
||||
if (signedUp == "true") {
|
||||
$("#msg").html("Registration successful! Login to continue.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Shows email confirmation and password reset messages, if any.
|
||||
global.displayMessages = function() {
|
||||
displayConfirmedEmail();
|
||||
displayChangedPassword();
|
||||
displaySignedUp();
|
||||
};
|
||||
|
||||
|
||||
// Logs the user in and redirects to the dashboard.
|
||||
global.login = function() {
|
||||
var all_ok = global.unfilledMark(["#email", "#password"], function(el) {
|
||||
el.css("border-bottom", "1px solid red");
|
||||
});
|
||||
|
||||
if (!all_ok) {
|
||||
global.textSet("#err", "Please make sure all fields are filled");
|
||||
return;
|
||||
}
|
||||
|
||||
var json = {
|
||||
"email": $("#email").val(),
|
||||
"password": $("#password").val(),
|
||||
};
|
||||
|
||||
global.buttonDisable("#login-button");
|
||||
global.post(global.origin + "/api/owner/login", json, function(resp) {
|
||||
global.buttonEnable("#login-button");
|
||||
|
||||
if (!resp.success) {
|
||||
global.textSet("#err", resp.message);
|
||||
return;
|
||||
}
|
||||
|
||||
global.cookieSet("session", resp.session);
|
||||
document.location = "/dashboard";
|
||||
});
|
||||
};
|
||||
|
||||
} (window, document));
|
20
frontend/js/self.js
Normal file
20
frontend/js/self.js
Normal file
@ -0,0 +1,20 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Get self details.
|
||||
global.selfGet = function(callback) {
|
||||
var json = {
|
||||
"session": global.cookieGet("session"),
|
||||
};
|
||||
|
||||
global.post(global.origin + "/api/owner/self", json, function(resp) {
|
||||
if (!resp.success || !resp.loggedIn) {
|
||||
document.location = "/login";
|
||||
return;
|
||||
}
|
||||
|
||||
global.owner = resp.owner;
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
}(window, document));
|
43
frontend/js/signup.js
Normal file
43
frontend/js/signup.js
Normal file
@ -0,0 +1,43 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Signs up the user and redirects to either the login page or the email
|
||||
// confirmation, depending on whether or not SMTP is configured in the
|
||||
// backend.
|
||||
global.signup = function() {
|
||||
if ($("#password").val() != $("#password2").val()) {
|
||||
global.textSet("#err", "The two passwords don't match");
|
||||
return;
|
||||
}
|
||||
|
||||
var all_ok = unfilledMark(["#email", "#name", "#password", "#password2"], function(el) {
|
||||
el.css("border-bottom", "1px solid red");
|
||||
});
|
||||
|
||||
if (!all_ok) {
|
||||
global.textSet("#err", "Please make sure all fields are filled");
|
||||
return;
|
||||
}
|
||||
|
||||
var json = {
|
||||
"email": $("#email").val(),
|
||||
"name": $("#name").val(),
|
||||
"password": $("#password").val(),
|
||||
};
|
||||
|
||||
global.buttonDisable("#signup-button");
|
||||
post(global.origin + "/api/owner/new", json, function(resp) {
|
||||
global.buttonEnable("#signup-button")
|
||||
|
||||
if (!resp.success) {
|
||||
global.textSet("#err", resp.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (resp.confirmEmail)
|
||||
document.location = "/confirm-email";
|
||||
else
|
||||
document.location = "/login?signedUp=true";
|
||||
});
|
||||
};
|
||||
|
||||
} (window, document));
|
108
frontend/js/utils.js
Normal file
108
frontend/js/utils.js
Normal file
@ -0,0 +1,108 @@
|
||||
(function (global, document) {
|
||||
|
||||
// Gets a GET parameter in the current URL.
|
||||
global.paramGet = function(param) {
|
||||
var pageURL = decodeURIComponent(window.location.search.substring(1));
|
||||
var urlVariables = pageURL.split('&');
|
||||
|
||||
for (var i = 0; i < urlVariables.length; i++) {
|
||||
var paramURL = urlVariables[i].split('=');
|
||||
if (paramURL[0] === param)
|
||||
return paramURL[1] === undefined ? true : paramURL[1];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Sets the disabled attribute in a button.
|
||||
global.buttonDisable = function(id) {
|
||||
var el = $(id);
|
||||
|
||||
el.attr("disabled", true);
|
||||
}
|
||||
|
||||
|
||||
// Unsets the disabled attribute in a button.
|
||||
global.buttonEnable = function(id) {
|
||||
var el = $(id);
|
||||
|
||||
el.attr("disabled", false);
|
||||
}
|
||||
|
||||
// Sets the text on the given label ID.
|
||||
global.textSet = function(id, text) {
|
||||
var el = $(id);
|
||||
|
||||
el.show();
|
||||
el.text(text);
|
||||
}
|
||||
|
||||
|
||||
// Given an array of input IDs, this function calls a callback function with
|
||||
// the first unfilled ID.
|
||||
global.unfilledMark = function(fields, callback) {
|
||||
var all_ok = true;
|
||||
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
var el = $(fields[i]);
|
||||
if (el.val() == "") {
|
||||
callback(el);
|
||||
}
|
||||
}
|
||||
|
||||
return all_ok;
|
||||
}
|
||||
|
||||
|
||||
// Gets the value of a cookie.
|
||||
global.cookieGet = function(name) {
|
||||
var c = "; " + document.cookie;
|
||||
var x = c.split("; " + name + "=");
|
||||
if (x.length == 2)
|
||||
return x.pop().split(";").shift();
|
||||
};
|
||||
|
||||
|
||||
// Sets the value of a cookie.
|
||||
global.cookieSet = function(name, value) {
|
||||
var expires = "";
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (365*24*60*60*1000));
|
||||
expires = "; expires=" + date.toUTCString();
|
||||
|
||||
document.cookie = name + "=" + value + expires + "; path=/";
|
||||
}
|
||||
|
||||
|
||||
// Converts a date in the past to a human-friendly duration relative to now.
|
||||
global.timeSince = function(date) {
|
||||
var seconds = Math.floor((new Date() - date) / 1000);
|
||||
var interval = Math.floor(seconds / 31536000);
|
||||
|
||||
if (interval > 1)
|
||||
return interval + " years ago";
|
||||
|
||||
interval = Math.floor(seconds / 2592000);
|
||||
if (interval > 1)
|
||||
return interval + " months ago";
|
||||
|
||||
interval = Math.floor(seconds / 86400);
|
||||
if (interval > 1)
|
||||
return interval + " days ago";
|
||||
|
||||
interval = Math.floor(seconds / 3600);
|
||||
if (interval > 1)
|
||||
return interval + " hours ago";
|
||||
|
||||
interval = Math.floor(seconds / 60);
|
||||
if (interval > 1)
|
||||
return interval + " minutes ago";
|
||||
|
||||
if (seconds > 5)
|
||||
return Math.floor(seconds) + " seconds ago";
|
||||
else
|
||||
return "just now";
|
||||
}
|
||||
|
||||
} (window, document));
|
6
frontend/js/vue.js
Normal file
6
frontend/js/vue.js
Normal file
File diff suppressed because one or more lines are too long
72
frontend/login.html
Normal file
72
frontend/login.html
Normal file
@ -0,0 +1,72 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1.0">
|
||||
<script src="<<<.CdnPrefix>>>/js/jquery.js"></script>
|
||||
<script src="<<<.CdnPrefix>>>/js/login.js"></script>
|
||||
<link rel="stylesheet" href="<<<.CdnPrefix>>>/css/auth.css">
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700|Source+Sans+Pro:200,300,400,700" rel="stylesheet">
|
||||
<title>Commento: Login</title>
|
||||
</head>
|
||||
|
||||
<div class="navbar">
|
||||
<a href="/" class="navbar-item navbar-logo-text"><img src="/images/logo.png" class="navbar-logo">Commento</a>
|
||||
<a href="/login" class="navbar-item"><b>Login</b></a>
|
||||
<a href="/signup" class="navbar-item">Signup</a>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.onload = function() {
|
||||
window.prefillEmail();
|
||||
window.displayMessages();
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="auth-form-container">
|
||||
<div class="auth-form">
|
||||
<div class="form-title">
|
||||
Login to continue
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="label">Email Address</div>
|
||||
<input class="input" type="text" name="email" id="email" placeholder="example@example.com">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="label">Password</div>
|
||||
<input class="input" type="password" name="password" id="password" placeholder="">
|
||||
</div>
|
||||
|
||||
<div class="err" id="err"></div>
|
||||
<div class="msg" id="msg"></div>
|
||||
|
||||
<button id="button" class="button" onclick="window.login()">Login</button>
|
||||
|
||||
<a class="link" href="/forgot">Trouble logging in? Reset your password.</a>
|
||||
<a class="link" href="/signup">Don't have an account yet? Sign up.</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<div class="footer-inner">
|
||||
<div class="links">
|
||||
<div class="link-group">
|
||||
<div class="header">Your Installation</div>
|
||||
<a class="link" href="/login">Login</a>
|
||||
<a class="link" href="/signup">Signup</a>
|
||||
<a class="link" href="/dashboard">Dashboard</a>
|
||||
</div>
|
||||
<div class="link-group">
|
||||
<div class="header">Documentation</div>
|
||||
<a class="link" href="https://docs.commento.io/">Documentation</a>
|
||||
<a class="link" href="https://gitlab.com/commento">Open Source</a>
|
||||
</div>
|
||||
<div class="link-group">
|
||||
<div class="header">About</div>
|
||||
<a class="link" href="https://commento.io">About Commento</a>
|
||||
<a class="link" href="https://commento.io/help">Help</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</html>
|
147
frontend/sass/auth-main.scss
Normal file
147
frontend/sass/auth-main.scss
Normal file
@ -0,0 +1,147 @@
|
||||
@import "common-main.scss";
|
||||
|
||||
body {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.auth-form-container {
|
||||
position: relative;
|
||||
top: 100px;
|
||||
width: 100%;
|
||||
min-height: calc(100% - 100px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 100px;
|
||||
|
||||
.auth-form {
|
||||
width: 400px;
|
||||
background: white;
|
||||
border-radius: 3px;
|
||||
padding: 24px;
|
||||
margin: 20px;
|
||||
|
||||
.form-title {
|
||||
font-size: 28px;
|
||||
font-weight: 300;
|
||||
text-align: center;
|
||||
padding: 12px;
|
||||
padding-bottom: 36px;
|
||||
}
|
||||
|
||||
.form-subtitle {
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
padding: 12px;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid $gray-1;
|
||||
|
||||
input[type=text],
|
||||
input[type=password] {
|
||||
font-size: 15px;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #32325d;
|
||||
border-bottom: 1px solid $gray-1;
|
||||
margin-right: 20px;
|
||||
background: $gray-0;
|
||||
width: 100%;
|
||||
color: #32325d;
|
||||
border: none;
|
||||
outline: none;
|
||||
line-height: 28px;
|
||||
background: $white;
|
||||
}
|
||||
|
||||
input[type=text]::placeholder,
|
||||
input[type=password]::placeholder {
|
||||
color: $gray-3;
|
||||
}
|
||||
|
||||
.label {
|
||||
display: inline-block;
|
||||
color: $gray-5;
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
@extend .shadow;
|
||||
border: 1px solid $blue-6;
|
||||
border-radius: 3px;
|
||||
line-height: 32px;
|
||||
background: $blue-6;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background: $blue-5;
|
||||
border: 1px solid $blue-5;
|
||||
}
|
||||
|
||||
.button:disabled {
|
||||
background: $blue-4;
|
||||
border: 1px solid $blue-4;
|
||||
cursor: unset;
|
||||
}
|
||||
|
||||
.err, .msg, .link {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.link {
|
||||
font-weight: normal;
|
||||
color: $blue-6;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: $blue-6;
|
||||
}
|
||||
|
||||
.err {
|
||||
color: $red-6;
|
||||
}
|
||||
|
||||
.msg {
|
||||
color: $green-6;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
.auth-form {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cent {
|
||||
font-size: 12px;
|
||||
color: $gray-5;
|
||||
text-align: center;
|
||||
|
||||
.gray {
|
||||
color: $gray-5;
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
border-bottom: 1px solid $gray-3;
|
||||
}
|
||||
}
|
3
frontend/sass/auth.scss
Normal file
3
frontend/sass/auth.scss
Normal file
@ -0,0 +1,3 @@
|
||||
@import "common-main.scss";
|
||||
@import "navbar-main.scss";
|
||||
@import "auth-main.scss";
|
1
frontend/sass/chartist.scss
Normal file
1
frontend/sass/chartist.scss
Normal file
File diff suppressed because one or more lines are too long
314
frontend/sass/colors-main.scss
Normal file
314
frontend/sass/colors-main.scss
Normal file
@ -0,0 +1,314 @@
|
||||
$white: #ffffff;
|
||||
$black: #000000;
|
||||
|
||||
$gray-list: (
|
||||
"0": #f8f9fa,
|
||||
"1": #f1f3f5,
|
||||
"2": #e9ecef,
|
||||
"3": #dee2e6,
|
||||
"4": #ced4da,
|
||||
"5": #adb5bd,
|
||||
"6": #868e96,
|
||||
"7": #495057,
|
||||
"8": #343a40,
|
||||
"9": #212529
|
||||
);
|
||||
|
||||
$gray-0: map-get($gray-list, "0");
|
||||
$gray-1: map-get($gray-list, "1");
|
||||
$gray-2: map-get($gray-list, "2");
|
||||
$gray-3: map-get($gray-list, "3");
|
||||
$gray-4: map-get($gray-list, "4");
|
||||
$gray-5: map-get($gray-list, "5");
|
||||
$gray-6: map-get($gray-list, "6");
|
||||
$gray-7: map-get($gray-list, "7");
|
||||
$gray-8: map-get($gray-list, "8");
|
||||
$gray-9: map-get($gray-list, "9");
|
||||
|
||||
$red-list: (
|
||||
"0": #fff5f5,
|
||||
"1": #ffe3e3,
|
||||
"2": #ffc9c9,
|
||||
"3": #ffa8a8,
|
||||
"4": #ff8787,
|
||||
"5": #ff6b6b,
|
||||
"6": #fa5252,
|
||||
"7": #f03e3e,
|
||||
"8": #e03131,
|
||||
"9": #c92a2a
|
||||
);
|
||||
|
||||
$red-0: map-get($red-list, "0");
|
||||
$red-1: map-get($red-list, "1");
|
||||
$red-2: map-get($red-list, "2");
|
||||
$red-3: map-get($red-list, "3");
|
||||
$red-4: map-get($red-list, "4");
|
||||
$red-5: map-get($red-list, "5");
|
||||
$red-6: map-get($red-list, "6");
|
||||
$red-7: map-get($red-list, "7");
|
||||
$red-8: map-get($red-list, "8");
|
||||
$red-9: map-get($red-list, "9");
|
||||
|
||||
$pink-list: (
|
||||
"0": #fff0f6,
|
||||
"1": #ffdeeb,
|
||||
"2": #fcc2d7,
|
||||
"3": #faa2c1,
|
||||
"4": #f783ac,
|
||||
"5": #f06595,
|
||||
"6": #e64980,
|
||||
"7": #d6336c,
|
||||
"8": #c2255c,
|
||||
"9": #a61e4d
|
||||
);
|
||||
|
||||
$pink-0: map-get($pink-list, "0");
|
||||
$pink-1: map-get($pink-list, "1");
|
||||
$pink-2: map-get($pink-list, "2");
|
||||
$pink-3: map-get($pink-list, "3");
|
||||
$pink-4: map-get($pink-list, "4");
|
||||
$pink-5: map-get($pink-list, "5");
|
||||
$pink-6: map-get($pink-list, "6");
|
||||
$pink-7: map-get($pink-list, "7");
|
||||
$pink-8: map-get($pink-list, "8");
|
||||
$pink-9: map-get($pink-list, "9");
|
||||
|
||||
$grape-list: (
|
||||
"0": #f8f0fc,
|
||||
"1": #f3d9fa,
|
||||
"2": #eebefa,
|
||||
"3": #e599f7,
|
||||
"4": #da77f2,
|
||||
"5": #cc5de8,
|
||||
"6": #be4bdb,
|
||||
"7": #ae3ec9,
|
||||
"8": #9c36b5,
|
||||
"9": #862e9c
|
||||
);
|
||||
|
||||
$grape-0: map-get($grape-list, "0");
|
||||
$grape-1: map-get($grape-list, "1");
|
||||
$grape-2: map-get($grape-list, "2");
|
||||
$grape-3: map-get($grape-list, "3");
|
||||
$grape-4: map-get($grape-list, "4");
|
||||
$grape-5: map-get($grape-list, "5");
|
||||
$grape-6: map-get($grape-list, "6");
|
||||
$grape-7: map-get($grape-list, "7");
|
||||
$grape-8: map-get($grape-list, "8");
|
||||
$grape-9: map-get($grape-list, "9");
|
||||
|
||||
$violet-list: (
|
||||
"0": #f3f0ff,
|
||||
"1": #e5dbff,
|
||||
"2": #d0bfff,
|
||||
"3": #b197fc,
|
||||
"4": #9775fa,
|
||||
"5": #845ef7,
|
||||
"6": #7950f2,
|
||||
"7": #7048e8,
|
||||
"8": #6741d9,
|
||||
"9": #5f3dc4
|
||||
);
|
||||
|
||||
$violet-0: map-get($violet-list, "0");
|
||||
$violet-1: map-get($violet-list, "1");
|
||||
$violet-2: map-get($violet-list, "2");
|
||||
$violet-3: map-get($violet-list, "3");
|
||||
$violet-4: map-get($violet-list, "4");
|
||||
$violet-5: map-get($violet-list, "5");
|
||||
$violet-6: map-get($violet-list, "6");
|
||||
$violet-7: map-get($violet-list, "7");
|
||||
$violet-8: map-get($violet-list, "8");
|
||||
$violet-9: map-get($violet-list, "9");
|
||||
|
||||
$indigo-list: (
|
||||
"0": #edf2ff,
|
||||
"1": #dbe4ff,
|
||||
"2": #bac8ff,
|
||||
"3": #91a7ff,
|
||||
"4": #748ffc,
|
||||
"5": #5c7cfa,
|
||||
"6": #4c6ef5,
|
||||
"7": #4263eb,
|
||||
"8": #3b5bdb,
|
||||
"9": #364fc7
|
||||
);
|
||||
|
||||
$indigo-0: map-get($indigo-list, "0");
|
||||
$indigo-1: map-get($indigo-list, "1");
|
||||
$indigo-2: map-get($indigo-list, "2");
|
||||
$indigo-3: map-get($indigo-list, "3");
|
||||
$indigo-4: map-get($indigo-list, "4");
|
||||
$indigo-5: map-get($indigo-list, "5");
|
||||
$indigo-6: map-get($indigo-list, "6");
|
||||
$indigo-7: map-get($indigo-list, "7");
|
||||
$indigo-8: map-get($indigo-list, "8");
|
||||
$indigo-9: map-get($indigo-list, "9");
|
||||
|
||||
$blue-list: (
|
||||
"0": #e7f5ff,
|
||||
"1": #d0ebff,
|
||||
"2": #a5d8ff,
|
||||
"3": #74c0fc,
|
||||
"4": #4dabf7,
|
||||
"5": #339af0,
|
||||
"6": #228be6,
|
||||
"7": #1c7ed6,
|
||||
"8": #1971c2,
|
||||
"9": #1864ab
|
||||
);
|
||||
|
||||
$blue-0: map-get($blue-list, "0");
|
||||
$blue-1: map-get($blue-list, "1");
|
||||
$blue-2: map-get($blue-list, "2");
|
||||
$blue-3: map-get($blue-list, "3");
|
||||
$blue-4: map-get($blue-list, "4");
|
||||
$blue-5: map-get($blue-list, "5");
|
||||
$blue-6: map-get($blue-list, "6");
|
||||
$blue-7: map-get($blue-list, "7");
|
||||
$blue-8: map-get($blue-list, "8");
|
||||
$blue-9: map-get($blue-list, "9");
|
||||
|
||||
$cyan-list: (
|
||||
"0": #e3fafc,
|
||||
"1": #c5f6fa,
|
||||
"2": #99e9f2,
|
||||
"3": #66d9e8,
|
||||
"4": #3bc9db,
|
||||
"5": #22b8cf,
|
||||
"6": #15aabf,
|
||||
"7": #1098ad,
|
||||
"8": #0c8599,
|
||||
"9": #0b7285
|
||||
);
|
||||
|
||||
$cyan-0: map-get($cyan-list, "0");
|
||||
$cyan-1: map-get($cyan-list, "1");
|
||||
$cyan-2: map-get($cyan-list, "2");
|
||||
$cyan-3: map-get($cyan-list, "3");
|
||||
$cyan-4: map-get($cyan-list, "4");
|
||||
$cyan-5: map-get($cyan-list, "5");
|
||||
$cyan-6: map-get($cyan-list, "6");
|
||||
$cyan-7: map-get($cyan-list, "7");
|
||||
$cyan-8: map-get($cyan-list, "8");
|
||||
$cyan-9: map-get($cyan-list, "9");
|
||||
|
||||
$teal-list: (
|
||||
"0": #e6fcf5,
|
||||
"1": #c3fae8,
|
||||
"2": #96f2d7,
|
||||
"3": #63e6be,
|
||||
"4": #38d9a9,
|
||||
"5": #20c997,
|
||||
"6": #12b886,
|
||||
"7": #0ca678,
|
||||
"8": #099268,
|
||||
"9": #087f5b
|
||||
);
|
||||
|
||||
$teal-0: map-get($teal-list, "0");
|
||||
$teal-1: map-get($teal-list, "1");
|
||||
$teal-2: map-get($teal-list, "2");
|
||||
$teal-3: map-get($teal-list, "3");
|
||||
$teal-4: map-get($teal-list, "4");
|
||||
$teal-5: map-get($teal-list, "5");
|
||||
$teal-6: map-get($teal-list, "6");
|
||||
$teal-7: map-get($teal-list, "7");
|
||||
$teal-8: map-get($teal-list, "8");
|
||||
$teal-9: map-get($teal-list, "9");
|
||||
|
||||
$green-list: (
|
||||
"0": #ebfbee,
|
||||
"1": #d3f9d8,
|
||||
"2": #b2f2bb,
|
||||
"3": #8ce99a,
|
||||
"4": #69db7c,
|
||||
"5": #51cf66,
|
||||
"6": #40c057,
|
||||
"7": #37b24d,
|
||||
"8": #2f9e44,
|
||||
"9": #2b8a3e
|
||||
);
|
||||
|
||||
$green-0: map-get($green-list, "0");
|
||||
$green-1: map-get($green-list, "1");
|
||||
$green-2: map-get($green-list, "2");
|
||||
$green-3: map-get($green-list, "3");
|
||||
$green-4: map-get($green-list, "4");
|
||||
$green-5: map-get($green-list, "5");
|
||||
$green-6: map-get($green-list, "6");
|
||||
$green-7: map-get($green-list, "7");
|
||||
$green-8: map-get($green-list, "8");
|
||||
$green-9: map-get($green-list, "9");
|
||||
|
||||
$lime-list: (
|
||||
"0": #f4fce3,
|
||||
"1": #e9fac8,
|
||||
"2": #d8f5a2,
|
||||
"3": #c0eb75,
|
||||
"4": #a9e34b,
|
||||
"5": #94d82d,
|
||||
"6": #82c91e,
|
||||
"7": #74b816,
|
||||
"8": #66a80f,
|
||||
"9": #5c940d
|
||||
);
|
||||
|
||||
$lime-0: map-get($lime-list, "0");
|
||||
$lime-1: map-get($lime-list, "1");
|
||||
$lime-2: map-get($lime-list, "2");
|
||||
$lime-3: map-get($lime-list, "3");
|
||||
$lime-4: map-get($lime-list, "4");
|
||||
$lime-5: map-get($lime-list, "5");
|
||||
$lime-6: map-get($lime-list, "6");
|
||||
$lime-7: map-get($lime-list, "7");
|
||||
$lime-8: map-get($lime-list, "8");
|
||||
$lime-9: map-get($lime-list, "9");
|
||||
|
||||
$yellow-list: (
|
||||
"0": #fff9db,
|
||||
"1": #fff8c5,
|
||||
"2": #ffec99,
|
||||
"3": #ffe066,
|
||||
"4": #ffd43b,
|
||||
"5": #fcc419,
|
||||
"6": #fab005,
|
||||
"7": #f59f00,
|
||||
"8": #f08c00,
|
||||
"9": #e67700
|
||||
);
|
||||
|
||||
$yellow-0: map-get($yellow-list, "0");
|
||||
$yellow-1: map-get($yellow-list, "1");
|
||||
$yellow-2: map-get($yellow-list, "2");
|
||||
$yellow-3: map-get($yellow-list, "3");
|
||||
$yellow-4: map-get($yellow-list, "4");
|
||||
$yellow-5: map-get($yellow-list, "5");
|
||||
$yellow-6: map-get($yellow-list, "6");
|
||||
$yellow-7: map-get($yellow-list, "7");
|
||||
$yellow-8: map-get($yellow-list, "8");
|
||||
$yellow-9: map-get($yellow-list, "9");
|
||||
|
||||
$orange-list: (
|
||||
"0": #fff4e6,
|
||||
"1": #ffe8cc,
|
||||
"2": #ffd8a8,
|
||||
"3": #ffc078,
|
||||
"4": #ffa94d,
|
||||
"5": #ff922b,
|
||||
"6": #fd7e14,
|
||||
"7": #f76707,
|
||||
"8": #e8590c,
|
||||
"9": #d9480f
|
||||
);
|
||||
|
||||
$orange-0: map-get($orange-list, "0");
|
||||
$orange-1: map-get($orange-list, "1");
|
||||
$orange-2: map-get($orange-list, "2");
|
||||
$orange-3: map-get($orange-list, "3");
|
||||
$orange-4: map-get($orange-list, "4");
|
||||
$orange-5: map-get($orange-list, "5");
|
||||
$orange-6: map-get($orange-list, "6");
|
||||
$orange-7: map-get($orange-list, "7");
|
||||
$orange-8: map-get($orange-list, "8");
|
||||
$orange-9: map-get($orange-list, "9");
|
87
frontend/sass/common-main.scss
Normal file
87
frontend/sass/common-main.scss
Normal file
@ -0,0 +1,87 @@
|
||||
@import "colors-main.scss";
|
||||
|
||||
html {
|
||||
font-family: 'Source Sans Pro', sans-serif;
|
||||
font-size: 14px;
|
||||
color: $gray-7;
|
||||
background: $gray-0;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.shadow {
|
||||
box-shadow: 0 1px 3px rgba(50,50,93,.15), 0 1px 0 rgba(0,0,0,.02);
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: relative;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
margin-top: 72px;
|
||||
|
||||
.copyright {
|
||||
align-items: none;
|
||||
color: $gray-3;
|
||||
background: $white;
|
||||
text-align: center;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.footer-inner {
|
||||
width: 100%;
|
||||
background: $white;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.links {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
.link-group {
|
||||
margin: 40px;
|
||||
|
||||
.header {
|
||||
text-transform: uppercase;
|
||||
font-weight: 700;
|
||||
font-size: 12px;
|
||||
color: $gray-5;
|
||||
}
|
||||
}
|
||||
|
||||
.link {
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
display: block;
|
||||
color: $gray-5;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: $gray-7;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
.link-group {
|
||||
display: block
|
||||
}
|
||||
|
||||
.links {
|
||||
display: block;
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
918
frontend/sass/dashboard-main.scss
Normal file
918
frontend/sass/dashboard-main.scss
Normal file
@ -0,0 +1,918 @@
|
||||
@import "colors-main.scss";
|
||||
@import "common-main.scss";
|
||||
|
||||
.subscription-nag {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: calc(50% - 200px);
|
||||
height: 40px;
|
||||
width: 400px;
|
||||
border-radius: 3px;
|
||||
-webkit-box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
-moz-box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
background: $gray-7;
|
||||
color: $gray-0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
z-index: 10000;
|
||||
animation: shake .5s linear;
|
||||
-webkit-animation: shake .5s linear;
|
||||
animation-delay: 1s;
|
||||
-webkit-animation-delay: 1s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes shake {
|
||||
8%, 41% {
|
||||
-webkit-transform: translateX(-5px);
|
||||
}
|
||||
25%, 58% {
|
||||
-webkit-transform: translateX(5px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translateX(-2px);
|
||||
}
|
||||
92% {
|
||||
-webkit-transform: translateX(2px);
|
||||
}
|
||||
0%, 100% {
|
||||
-webkit-transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.global-error, .global-ok {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
margin: 30px;
|
||||
padding: 5px;
|
||||
border: 1px solid $red-6;
|
||||
background: $red-6;
|
||||
color: white;
|
||||
display: none;
|
||||
z-index: 80000;
|
||||
}
|
||||
|
||||
.global-ok {
|
||||
border: 1px solid $green-7;
|
||||
background: $green-7;
|
||||
}
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tabs-container {
|
||||
ul.tabs {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
list-style: none;
|
||||
border-bottom: 1px solid $gray-4;
|
||||
|
||||
li {
|
||||
background: none;
|
||||
display: inline-block;
|
||||
padding: 10px 15px;
|
||||
cursor: pointer;
|
||||
transition: all 0.1s;
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
|
||||
li.current {
|
||||
border-bottom: 1px solid $blue-6;
|
||||
transition: all 0.1s;
|
||||
}
|
||||
}
|
||||
|
||||
.content{
|
||||
display: none;
|
||||
padding: 25px;
|
||||
|
||||
.pitch {
|
||||
color: $gray-6;
|
||||
margin-bottom: 24px;
|
||||
line-height: 22px;
|
||||
|
||||
a { color: $blue-6; }
|
||||
a:hover { color: $blue-6; }
|
||||
}
|
||||
}
|
||||
|
||||
.content.current{
|
||||
display: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.email-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
|
||||
.email {
|
||||
@extend .shadow;
|
||||
border-radius: 4px;
|
||||
background: $white;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
|
||||
.input {
|
||||
height: 40px;
|
||||
background: $white;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 5px;
|
||||
padding-left: 10px;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.input::placeholder {
|
||||
color: $gray-5;
|
||||
}
|
||||
|
||||
.email-button {
|
||||
height: 40px;
|
||||
min-width: 110px;
|
||||
float: right;
|
||||
background: $white;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0px 10px 0px 10px;
|
||||
border-left: 1px solid $gray-1;
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: $blue-7;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.email-button:hover {
|
||||
color: $blue-6;
|
||||
}
|
||||
|
||||
.email-button:disabled {
|
||||
cursor: default;
|
||||
color: $gray-6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mod-emails-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border-radius: 3px;
|
||||
margin-top: 24px;
|
||||
|
||||
.content {
|
||||
display: block;
|
||||
padding: 0px;
|
||||
border: 1px solid $gray-2;
|
||||
border-top: 0px solid transparent;
|
||||
min-width: 550px;
|
||||
|
||||
.mod-email {
|
||||
display: block;
|
||||
height: 42px;
|
||||
border-top: 1px solid $gray-2;
|
||||
|
||||
.date,
|
||||
.delete,
|
||||
.email {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0px 12px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.email {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.date {
|
||||
float: right;
|
||||
color: $gray-4;
|
||||
}
|
||||
|
||||
.delete {
|
||||
float: right;
|
||||
color: $red-6;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.delete:hover {
|
||||
color: $red-7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.round-check {
|
||||
input[type="checkbox"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input[type="checkbox"] + label {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-left: 35px;
|
||||
margin-bottom: 5px;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
input[type="checkbox"] + label:last-child { margin-bottom: 0; }
|
||||
|
||||
input[type="checkbox"] + label:before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
margin-top: 2px;
|
||||
background: $gray-0;
|
||||
border: 1px solid $gray-3;
|
||||
border-radius: 3px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
transition: all .15s;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:disabled + label:before {
|
||||
background: $gray-0;
|
||||
border: 1px solid $gray-4;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked + label:before {
|
||||
background: $blue-6;
|
||||
border: 1px solid $blue-6;
|
||||
}
|
||||
|
||||
.pitch {
|
||||
font-size: 13px;
|
||||
color: #a0a0a0;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-container {
|
||||
position: relative;
|
||||
top: 72px;
|
||||
width: 100%;
|
||||
height: calc(100% - 94px);
|
||||
|
||||
.pane-left {
|
||||
padding-top: 20px;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
border-right: 1px solid $gray-1;
|
||||
width: 240px;
|
||||
height: 100%;
|
||||
|
||||
.tree {
|
||||
opacity: 0.4;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
.tree-svg {
|
||||
margin-bottom: 20px;
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pane-middle {
|
||||
padding-top: 20px;
|
||||
position: absolute;
|
||||
left: 240px;
|
||||
border-right: 1px solid $gray-1;
|
||||
width: 280px;
|
||||
height: 100%;
|
||||
padding-left: 1px;
|
||||
}
|
||||
|
||||
.pane-right {
|
||||
position: absolute;
|
||||
left: 520px;
|
||||
width: calc(100% - 520px);
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.view {
|
||||
padding: 25px;
|
||||
padding-top: 35px;
|
||||
}
|
||||
|
||||
.view-inside {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tiny-view {
|
||||
font-size: 15px;
|
||||
width: 35%;
|
||||
min-width: 400px;
|
||||
max-width: 450px;
|
||||
}
|
||||
|
||||
.small-view {
|
||||
font-size: 15px;
|
||||
width: 50%;
|
||||
min-width: 400px;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.small-mid-view {
|
||||
font-size: 15px;
|
||||
width: 70%;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.mid-view {
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
.large-view {
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
max-width: 750px;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.select-a-domain {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: $gray-5;
|
||||
}
|
||||
|
||||
.pane-setting {
|
||||
width: 100%;
|
||||
height: 54px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
color: $gray-7;
|
||||
|
||||
.setting-title, .setting-subtitle {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.setting-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.setting-subtitle {
|
||||
color: $gray-5;
|
||||
}
|
||||
|
||||
.super-setting {
|
||||
display: flex;
|
||||
|
||||
.super-setting-title {
|
||||
display: inline;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.super-setting-text {
|
||||
padding-left: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 32px;
|
||||
height: 45px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pane-setting:hover {
|
||||
color: $gray-6;
|
||||
-webkit-box-shadow: inset -2px 0px 0 -1px $gray-4;
|
||||
-moz-box-shadow: inset -2px 0px 0 -1px $gray-4;
|
||||
box-shadow: inset -2px 0px 0 -1px $gray-4;
|
||||
}
|
||||
|
||||
.selected {
|
||||
color: $blue-6;
|
||||
-webkit-box-shadow: inset -2px 0px 0 -1px $blue-6;
|
||||
-moz-box-shadow: inset -2px 0px 0 -1px $blue-6;
|
||||
box-shadow: inset -2px 0px 0 -1px $blue-6;
|
||||
}
|
||||
|
||||
.selected:hover {
|
||||
color: $blue-7;
|
||||
-webkit-box-shadow: inset -2px 0px 0 -1px $blue-6;
|
||||
-moz-box-shadow: inset -2px 0px 0 -1px $blue-6;
|
||||
box-shadow: inset -2px 0px 0 -1px $blue-6;
|
||||
}
|
||||
}
|
||||
|
||||
.import-text {
|
||||
font-size: 15px;
|
||||
color: $gray-6;
|
||||
line-height: 25px;
|
||||
|
||||
a {
|
||||
color: $blue-6;
|
||||
border-bottom: 1px solid $blue-6;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
li::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
border: solid $gray-7;
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(-45deg);
|
||||
margin-left: 12px;
|
||||
margin-right: 12px;
|
||||
margin-bottom: 2px;
|
||||
position: absolute;
|
||||
left: -35px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.subtext-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 8px;
|
||||
padding-bottom: 16px;
|
||||
|
||||
.subtext {
|
||||
max-width: 500px;
|
||||
font-size: 13px;
|
||||
line-height: 17px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.float-right {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.modal-window {
|
||||
position: fixed;
|
||||
background-color: rgba(82, 95, 127, 0.4);
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 999;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
-webkit-transition: all 0.2s;
|
||||
-moz-transition: all 0.2s;
|
||||
transition: all 0.2s;
|
||||
|
||||
.inside {
|
||||
border: 1px solid white;
|
||||
border-radius: 6px;
|
||||
width: 500px;
|
||||
position: relative;
|
||||
margin: 10% auto;
|
||||
background: $gray-0;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.modal-error-box {
|
||||
width: 100%;
|
||||
color: $red-6;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
padding-top: 15px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.modal-subtitle {
|
||||
text-align: center;
|
||||
color: $gray-6;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.modal-contents {
|
||||
padding: 12px;
|
||||
min-height: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-window:target {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
background-image: url(/images/close.svg);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-close:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.box {
|
||||
padding: 6px;
|
||||
margin-bottom: 25px;
|
||||
|
||||
.box-title {
|
||||
padding: 6px;
|
||||
padding-top: 0px;
|
||||
font-size: 19px;
|
||||
}
|
||||
|
||||
.box-subtitle {
|
||||
font-size: 14px;
|
||||
padding: 6px;
|
||||
color: $gray-6;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.gray {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
color: $gray-6;
|
||||
opacity: 0.8;
|
||||
|
||||
a { color: $gray-6; border: none; }
|
||||
a:hover { color: $gray-6; border: none; }
|
||||
}
|
||||
|
||||
.gray:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.row {
|
||||
.gray-input {
|
||||
background: $gray-0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
margin-bottom: 32px;
|
||||
border-bottom: 1px solid $gray-2;
|
||||
|
||||
.label {
|
||||
display: inline-block;
|
||||
color: $gray-5;
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.input {
|
||||
font-size: 15px;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
color: #32325d;
|
||||
border: none;
|
||||
outline: none;
|
||||
line-height: 28px;
|
||||
background: $gray-0;
|
||||
}
|
||||
|
||||
.input::placeholder {
|
||||
color: $gray-4;
|
||||
}
|
||||
}
|
||||
|
||||
.theme {
|
||||
display: block;
|
||||
width: calc(100% - 20px);
|
||||
border: 1px solid white;
|
||||
-webkit-box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
-moz-box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
border-radius: 3px;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 20px;
|
||||
background: white;
|
||||
opacity: 0.5;
|
||||
filter: alpha(opacity=50);
|
||||
transition: all 0.3s;
|
||||
|
||||
.theme-title {
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.theme-subtitle {
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
color: $gray-5;
|
||||
}
|
||||
|
||||
.theme-image {
|
||||
width: calc(100% - 40px);
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.theme:hover {
|
||||
opacity: 0.8;
|
||||
filter: alpha(opacity=80);
|
||||
}
|
||||
|
||||
.selectedtheme {
|
||||
opacity: 1;
|
||||
filter: alpha(opacity=100);
|
||||
}
|
||||
|
||||
.selectedtheme:hover {
|
||||
opacity: 1;
|
||||
filter: alpha(opacity=100);
|
||||
}
|
||||
|
||||
.no-border {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.button {
|
||||
@extend .shadow;
|
||||
height: 40px;
|
||||
min-width: 110px;
|
||||
background: $white;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0px 10px 0px 10px;
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: $blue-7;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
color: $blue-6;
|
||||
}
|
||||
|
||||
.button:disabled {
|
||||
cursor: default;
|
||||
color: $gray-6;
|
||||
}
|
||||
|
||||
.short-button {
|
||||
width: 80px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.stat {
|
||||
-webkit-box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
-moz-box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
margin: 20px;
|
||||
padding: 20px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
width: calc(100% - 80px);
|
||||
background: white;
|
||||
border-radius: 3px;
|
||||
|
||||
.number {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
line-height: 42px;
|
||||
|
||||
.digits {
|
||||
display: table-cell;
|
||||
font-size: 48px;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
.gray-digits {
|
||||
color: $gray-3;
|
||||
}
|
||||
|
||||
.gray-7-digits {
|
||||
color: $gray-7;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
text-transform: uppercase;
|
||||
color: $gray-5;
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.center-title {
|
||||
font-size: 32px;
|
||||
font-weight: 300;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: $gray-6;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
foreignObject {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.all-done {
|
||||
margin-top: 40px;
|
||||
color: $gray-5;
|
||||
font-size :15px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.mod-button {
|
||||
width: fit-content;
|
||||
line-height: 24px;
|
||||
color: $gray-6;
|
||||
background: white;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.mod-button:hover {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.red-button {
|
||||
border: 1px solid $gray-3;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.red-button:hover {
|
||||
border: 1px solid $red-6;
|
||||
}
|
||||
|
||||
.green-button {
|
||||
color: $green-7;
|
||||
}
|
||||
|
||||
.green-button:hover {
|
||||
color: $green-7;
|
||||
}
|
||||
|
||||
.green-button:disabled {
|
||||
color: $gray-6;
|
||||
}
|
||||
|
||||
.orange-button {
|
||||
color: $orange-7;
|
||||
}
|
||||
|
||||
.orange-button:hover {
|
||||
color: $orange-7;
|
||||
}
|
||||
|
||||
.big-red-button {
|
||||
background: $red-6;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.big-red-button:hover {
|
||||
background: $red-5;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.comment {
|
||||
-webkit-box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
-moz-box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
box-shadow: 0 7px 14px 0 rgba(50,50,93,.1), 0 3px 6px 0 rgba(0,0,0,.07);
|
||||
width: calc(100% - 40px);
|
||||
background: white;
|
||||
border: 1px solid white;
|
||||
border-radius: 3px;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
transition: all 1s;
|
||||
|
||||
.comment-inside {
|
||||
.actions {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 300;
|
||||
font-size: 18px;
|
||||
color: $gray-5;
|
||||
margin-bottom: 18px;
|
||||
line-height: 28px;
|
||||
|
||||
.postlink {
|
||||
color: $gray-5;
|
||||
}
|
||||
}
|
||||
|
||||
.profile {
|
||||
.avatar {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
font-size: 22px;
|
||||
float: left;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.names {
|
||||
margin-left: 50px;
|
||||
|
||||
.name {
|
||||
a {
|
||||
color: $gray-7;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.time {
|
||||
color: $gray-4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.move-left {
|
||||
transform: translateX(10000px);
|
||||
}
|
||||
|
||||
.move-right {
|
||||
transform: translateX(10000px);
|
||||
}
|
||||
|
||||
.graph {
|
||||
margin-top: 16px;
|
||||
height: 300px;
|
||||
.ct-series-a .ct-line {
|
||||
stroke: $gray-7;
|
||||
stroke-width: 1px;
|
||||
}
|
||||
|
||||
.ct-series-a .ct-area {
|
||||
fill: $gray-7;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: 'Source Code Pro', monospace;
|
||||
font-size: 13px;
|
||||
}
|
4
frontend/sass/dashboard.scss
Normal file
4
frontend/sass/dashboard.scss
Normal file
@ -0,0 +1,4 @@
|
||||
@import "common-main.scss";
|
||||
@import "navbar-main.scss";
|
||||
@import "dashboard-main.scss";
|
||||
@import "tomorrow.scss";
|
58
frontend/sass/navbar-main.scss
Normal file
58
frontend/sass/navbar-main.scss
Normal file
@ -0,0 +1,58 @@
|
||||
@import "colors-main.scss";
|
||||
|
||||
.navbar {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.navbar-item {
|
||||
width: auto;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
font-size: 16px;
|
||||
color: $gray-5;
|
||||
background: $gray-0;
|
||||
}
|
||||
|
||||
.navbar-logo-text {
|
||||
font-size: 16px;
|
||||
margin-left: 56px;
|
||||
color: $gray-9;
|
||||
}
|
||||
|
||||
.navbar-logo {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
.navbar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.navbar-item {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navbar-logo-text {
|
||||
display: flex;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.banner-container {
|
||||
width: calc(100% - 24px);
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-hamburger {
|
||||
color: $gray-9;
|
||||
}
|
97
frontend/sass/tomorrow.scss
Normal file
97
frontend/sass/tomorrow.scss
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
|
||||
Atom One Light by Daniel Gamage
|
||||
Original One Light Syntax theme from https://github.com/atom/one-light-syntax
|
||||
|
||||
base: #fafafa
|
||||
mono-1: #383a42
|
||||
mono-2: #686b77
|
||||
mono-3: #a0a1a7
|
||||
hue-1: #0184bb
|
||||
hue-2: #4078f2
|
||||
hue-3: #a626a4
|
||||
hue-4: #50a14f
|
||||
hue-5: #e45649
|
||||
hue-5-2: #c91243
|
||||
hue-6: #986801
|
||||
hue-6-2: #c18401
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 1em;
|
||||
color: #383a42;
|
||||
background: #ffffff;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #a0a1a7;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-doctag,
|
||||
.hljs-keyword,
|
||||
.hljs-formula {
|
||||
color: #a626a4;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name,
|
||||
.hljs-selector-tag,
|
||||
.hljs-deletion,
|
||||
.hljs-subst {
|
||||
color: #e45649;
|
||||
}
|
||||
|
||||
.hljs-literal {
|
||||
color: #0184bb;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-regexp,
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-meta-string {
|
||||
color: #50a14f;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title {
|
||||
color: #c18401;
|
||||
}
|
||||
|
||||
.hljs-attr,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-type,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-number {
|
||||
color: #986801;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-link,
|
||||
.hljs-meta,
|
||||
.hljs-selector-id,
|
||||
.hljs-title {
|
||||
color: #4078f2;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
87
frontend/signup.html
Normal file
87
frontend/signup.html
Normal file
@ -0,0 +1,87 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1.0">
|
||||
<script src="<<<.CdnPrefix>>>/js/jquery.js"></script>
|
||||
<script src="<<<.CdnPrefix>>>/js/signup.js"></script>
|
||||
<link rel="stylesheet" href="<<<.CdnPrefix>>>/css/auth.css">
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700|Source+Sans+Pro:200,300,400,700" rel="stylesheet">
|
||||
<title>Commento: Signup</title>
|
||||
</head>
|
||||
|
||||
<div class="navbar">
|
||||
<a href="/" class="navbar-item navbar-logo-text"><img src="/images/logo.svg" class="navbar-logo">Commento</a>
|
||||
<a href="/login" class="navbar-item">Login</a>
|
||||
<a href="/signup" class="navbar-item"><b>Signup</b></a>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.onload = function() {
|
||||
window.prefillEmail();
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="auth-form-container">
|
||||
<div class="auth-form">
|
||||
<div class="form-title">
|
||||
Create an account
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="label">Email Address</div>
|
||||
<input class="input" type="text" name="email" id="email" placeholder="example@example.com">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="label">Full Name</div>
|
||||
<input class="input" type="text" name="name" id="name" placeholder="Billie Joe Armstrong">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="label">Password</div>
|
||||
<input class="input" type="password" name="password" id="password" placeholder="">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="label">Confirm Password</div>
|
||||
<input class="input" type="password" name="password2" id="password2" placeholder="">
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="plan" id="plan" value="">
|
||||
|
||||
<div class="err" id="err"></div>
|
||||
|
||||
<p class="cent">
|
||||
By signing up, you agree to our
|
||||
<a href="/terms" class="gray">Terms and Conditions</a> and
|
||||
<a href="/privacy" class="gray">Privacy Policy</a>
|
||||
</p>
|
||||
|
||||
<button id="signup-button" class="button" onclick="window.signup()">Sign up</button>
|
||||
|
||||
<a class="link" href="/login">Already have an account? Login instead.</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<div class="footer-inner">
|
||||
<div class="links">
|
||||
<div class="link-group">
|
||||
<div class="header">Your Installation</div>
|
||||
<a class="link" href="/login">Login</a>
|
||||
<a class="link" href="/signup">Signup</a>
|
||||
<a class="link" href="/dashboard">Dashboard</a>
|
||||
</div>
|
||||
<div class="link-group">
|
||||
<div class="header">Documentation</div>
|
||||
<a class="link" href="https://docs.commento.io/">Documentation</a>
|
||||
<a class="link" href="https://gitlab.com/commento">Open Source</a>
|
||||
</div>
|
||||
<div class="link-group">
|
||||
<div class="header">About</div>
|
||||
<a class="link" href="https://commento.io">About Commento</a>
|
||||
<a class="link" href="https://commento.io/help">Help</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user