revamp invites and certificates screen

master
Corne Oppelaar 8 years ago
parent 72482e4f92
commit 414f17476f

@ -134,7 +134,10 @@ body {
padding: 15px; padding: 15px;
margin-top: 20px; } margin-top: 20px; }
.certificate-create { .invite-create {
float: right; }
.certificate-create, .invite-create button {
font-size: 16px; font-size: 16px;
font-weight: normal; font-weight: normal;
background: #53257e; background: #53257e;
@ -142,49 +145,72 @@ body {
padding: 5px; padding: 5px;
float: right; float: right;
text-decoration: none; text-decoration: none;
cursor: pointer; } cursor: pointer;
font-family: 'Karla', sans-serif; }
.panel-content > h1 { .panel-content > h1,
.panel-content > .title > h1 {
margin: 0 0 25px; } margin: 0 0 25px; }
.panel-content > h1 + .undertone { .panel-content > h1 + .undertone,
.panel-content > .title > h1 + .undertone {
margin-top: -25px; margin-top: -25px;
color: #999999; color: #999999;
margin-bottom: 25px; } margin-bottom: 25px; }
.certificate-list { .certificate-list, .invites {
margin: 0; margin: 0;
list-style: none; list-style: none;
padding: 0; } padding: 0; }
.certificate-list li { .certificate-list li, .invites li {
border-left: 3px #e3b2a6 solid; border-left: 3px #e3b2a6 solid;
padding-left: 5px; padding-left: 5px;
margin-bottom: 10px; margin-bottom: 10px;
position: relative; } position: relative; }
.certificate-list li .text .expiry { .certificate-list li .text .expiry, .invites li .text .expiry {
font-size: 14px; font-size: 14px;
color: #999999; } color: #999999; }
.certificate-list li .actions { .certificate-list li .revoke-q, .invites li .revoke-q {
display: none; }
.certificate-list li .actions, .certificate-list li .revoke-q, .invites li .actions, .invites li .revoke-q {
position: absolute; position: absolute;
right: 0; right: 0;
bottom: 0; } bottom: 0; }
.certificate-list li .actions span { .certificate-list li .actions span, .certificate-list li .revoke-q span, .invites li .actions span, .invites li .revoke-q span {
transition: .2s; transition: .2s;
cursor: pointer; cursor: pointer;
padding: 5px; padding: 5px;
float: left; float: left;
display: block; } display: block; }
.certificate-list li .actions span a { .certificate-list li .actions span a, .certificate-list li .revoke-q span a, .invites li .actions span a, .invites li .revoke-q span a {
color: black; color: black;
text-decoration: none; text-decoration: none;
display: block; display: block;
margin: -5px; margin: -5px;
padding: 5px; } padding: 5px; }
.certificate-list li .actions .certificate-delete:hover { .certificate-list li .actions .certificate-delete:hover,
.certificate-list li .actions .yes:hover, .certificate-list li .revoke-q .certificate-delete:hover,
.certificate-list li .revoke-q .yes:hover, .invites li .actions .certificate-delete:hover,
.invites li .actions .yes:hover, .invites li .revoke-q .certificate-delete:hover,
.invites li .revoke-q .yes:hover {
background: #dc6a6a; } background: #dc6a6a; }
.certificate-list li .actions .certificate-download:hover, .certificate-list li .actions .certificate-download:hover,
.certificate-list li .actions .certificate-download-key:hover { .certificate-list li .actions .certificate-download-key:hover,
.certificate-list li .actions .no:hover,
.certificate-list li .actions .copy:hover, .certificate-list li .revoke-q .certificate-download:hover,
.certificate-list li .revoke-q .certificate-download-key:hover,
.certificate-list li .revoke-q .no:hover,
.certificate-list li .revoke-q .copy:hover, .invites li .actions .certificate-download:hover,
.invites li .actions .certificate-download-key:hover,
.invites li .actions .no:hover,
.invites li .actions .copy:hover, .invites li .revoke-q .certificate-download:hover,
.invites li .revoke-q .certificate-download-key:hover,
.invites li .revoke-q .no:hover,
.invites li .revoke-q .copy:hover {
background: #aca4bc; } background: #aca4bc; }
.certificate-list li .actions .no, .certificate-list li .revoke-q .no, .invites li .actions .no, .invites li .revoke-q .no {
width: 65px;
text-align: center; }
ul.topnav { ul.topnav {
list-style-type: none; list-style-type: none;

File diff suppressed because one or more lines are too long

@ -88,16 +88,18 @@ body {
* Third section of the main page, containing the link to the Github page. * Third section of the main page, containing the link to the Github page.
*/ */
.footer-page { .footer-page {
@extend .flexpage; @extend .flexpage;
flex: 1; flex: 1;
background-color: #e2f2f0; background-color: #e2f2f0;
flex-direction: column; flex-direction: column;
-webkit-flex-direction: column; -webkit-flex-direction: column;
min-height: 20vh; min-height: 20vh;
@include break-small { @include break-small {
height: 100%; height: 100%;
} }
} }
/** /**
@ -106,10 +108,11 @@ body {
.login-page { .login-page {
@extend .flexpage; @extend .flexpage;
background: linear-gradient(#070a15, #252b46); background: linear-gradient(#070a15, #252b46);
flex-direction: column; flex-direction: column;
-webkit-flex-direction: column; -webkit-flex-direction: column;
} }
.login-page-form { .login-page-form {
background-color: #fff; background-color: #fff;
@ -145,7 +148,11 @@ body {
margin-top: 20px; margin-top: 20px;
} }
.certificate-create { .invite-create {
float:right;
}
.certificate-create, .invite-create button {
font-size: 16px; font-size: 16px;
font-weight: normal; font-weight: normal;
background: hsl(271, 55%, 32%); background: hsl(271, 55%, 32%);
@ -154,19 +161,22 @@ body {
float: right; float: right;
text-decoration:none; text-decoration:none;
cursor: pointer; cursor: pointer;
font-family: 'Karla', sans-serif;
} }
.panel-content > h1 { .panel-content > h1,
.panel-content > .title > h1 {
margin: 0 0 25px; margin: 0 0 25px;
} }
.panel-content > h1 + .undertone { .panel-content > h1 + .undertone,
.panel-content > .title > h1 + .undertone {
margin-top: -25px; margin-top: -25px;
color: #999999; color: #999999;
margin-bottom: 25px; margin-bottom: 25px;
} }
.certificate-list { .certificate-list, .invites {
margin: 0; margin: 0;
list-style: none; list-style: none;
padding: 0; padding: 0;
@ -184,7 +194,11 @@ body {
} }
} }
.actions { .revoke-q {
display: none;
}
.actions, .revoke-q {
position: absolute; position: absolute;
right: 0; right: 0;
bottom: 0; bottom: 0;
@ -205,13 +219,25 @@ body {
} }
} }
.certificate-delete:hover { .certificate-delete,
background: hsl(0, 62%, 64%); .yes {
&:hover {
background: hsl(0, 62%, 64%);
}
}
.certificate-download,
.certificate-download-key,
.no,
.copy {
&:hover {
background: #aca4bc;
}
} }
.certificate-download:hover, .no {
.certificate-download-key:hover { width: 65px;
background: #aca4bc; text-align: center;
} }
} }
} }

@ -1,5 +1,32 @@
$(function () { $(function () {
var errorDiv = $('<div>').addClass('error-message');
function error(msg) {
$('.title').after(errorDiv.text(msg));
}
$('.actions .certificate-delete').click(function () { $('.actions .certificate-delete').click(function () {
$(this).parents('li').first().find('.certificate-revoke').addClass('show') $(this).parents('.actions').hide().parents('li').first().find('.revoke-q').show();
});
$('.revoke-q .no').click(function () {
$(this).parents('.revoke-q').hide().parents('li').first().find('.actions').show();
});
$('.revoke-q .yes').click(function () {
var _this=this;
$.post('/panel/certificates/revoke', {
name: $(_this).data('name')
}, function (data) {
if (data.success) {
$(_this)
.parents('li')
.first()
.remove();
} else {
error(data.error);
}
});
}); });
}); });

@ -58,6 +58,7 @@ $(function () {
zip.file(commonName + '.key', keyPem); zip.file(commonName + '.key', keyPem);
for(var file in data.zip) { for(var file in data.zip) {
if (!data.zip.hasOwnProperty(file)) continue;
zip.file(file, data.zip[file]); zip.file(file, data.zip[file]);
} }

@ -2,20 +2,20 @@ $(function () {
var clipboard = new Clipboard('.copy'); var clipboard = new Clipboard('.copy');
clipboard.on('success', function(e) { clipboard.on('success', function(e) {
$(e.trigger).text('Copied!') $(e.trigger).text('copied!');
setTimeout( setTimeout(
function () { function () {
$(e.trigger).text('Copy'); $(e.trigger).text('copy');
}, },
2000 2000
); );
}); });
clipboard.on('error', function(e) { clipboard.on('error', function(e) {
$(e.trigger).text('Couldn\t copy :(') $(e.trigger).text('couldn\t copy :(');
setTimeout( setTimeout(
function () { function () {
$(e.trigger).text('Copy'); $(e.trigger).text('copy');
}, },
2000 2000
); );

@ -24,7 +24,6 @@ class Revoke extends Session
{ {
$user = $this->getUser(); $user = $this->getUser();
$name = $this->post('name'); $name = $this->post('name');
$password = $this->post('password');
$cert = CertificateQuery::create() $cert = CertificateQuery::create()
->filterByName($name) ->filterByName($name)
@ -38,13 +37,6 @@ class Revoke extends Session
]); ]);
} }
if (!password_verify($password, $user->getPassword())) {
return $this->json([
'success' => false,
'error' => 'Invalid password'
]);
}
/** /**
* @var CA $ca * @var CA $ca
*/ */

@ -4,11 +4,11 @@ namespace Eater\Glim\Handler\Panel;
use Aura\Session\Segment; use Aura\Session\Segment;
use Eater\Glim\Handler\Panel;
use Eater\Glim\Handler\Session; use Eater\Glim\Handler\Session;
class Invites extends Session class Invites extends Panel
{ {
protected $shouldHaveUser = true;
public function handle() public function handle()
{ {

@ -4,8 +4,12 @@
{% if user.getActiveCertificates()|length < user.getMaxKeys() %} {% if user.getActiveCertificates()|length < user.getMaxKeys() %}
<a href="/panel/certificates/new" class="certificate-create">create</a> <a href="/panel/certificates/new" class="certificate-create">create</a>
{% endif %} {% endif %}
<h1>Certificates</h1>
<div class="undertone">You used {{ user.getActiveCertificates()|length }} of your {{ user.getMaxKeys() }} certificates</div> <div class="title">
<h1>Certificates</h1>
<div class="undertone">You used {{ user.getActiveCertificates()|length }} of your {{ user.getMaxKeys() }} certificates</div>
</div>
<ul class="certificate-list"> <ul class="certificate-list">
{% for certificate in user.getActiveCertificates() %} {% for certificate in user.getActiveCertificates() %}
<li> <li>
@ -24,9 +28,18 @@
</span> </span>
<span class="certificate-delete">revoke</span> <span class="certificate-delete">revoke</span>
</div> </div>
<div class="revoke-q">
<span class="q">Are you sure you want to revoke this certificate?</span>
<span data-name="{{ certificate.getName() }}" class="yes">
<a>yes</a>
</span>
<span class="no">
<a>no</a>
</span>
</div>
</li> </li>
{% else %} {% else %}
<li>You don't have any certificates :( why not <a href="/panel/certificates/new">create</a> one?</li> <li>You don't have any certificates :( why not <a href="/panel/certificates/new">create</a> one?</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endblock %} {% endblock %}

@ -1,55 +1,40 @@
{% extends "base_bootstrap.html.twig" %} {% extends "panel.html.twig" %}
{% block head %} {% block head %}
{{ parent() }} {{ parent() }}
<script src="/js/clipboard.min.js"></script> <script src="/js/clipboard.min.js"></script>
<script src="/js/invites.js"></script> <script src="/js/pages/invites.js"></script>
{% endblock %} {% endblock %}
{% block content %} {% block panel_contents %}
<div class="container"> {% if user.getActiveCertificates()|length < user.getMaxKeys() %}
<div class="row"> <form class="invite-create" action="/panel/invites/create" method="post">
<h2 id="certificates">Invites <small>You used {{ used_invites }} from your {{ max_invites == -1 ? 'infinite' : max_invites }} invites</small></h2> <button type="submit">create</button>
</div> </form>
{% if error %} {% endif %}
<div class="row">
<div class="alert alert-warning" role="alert"> <div class="title">
{{ error }} <h1>Invites</h1>
</div> <div class="undertone">You used {{ used_invites }} from your {{ max_invites == -1 ? 'infinite' : max_invites }} invites</div>
</div>
{% endif %}
<div class="row">
<table class="table">
<thead>
<tr>
<th>Invite</th>
<th>
{% if max_invites > used_invites or max_invites == -1 %}
<form action="/panel/invites/create" method="post">
<button class="btn btn-default pull-right" type="submit">Create new invite</button>
</form>
{% endif %}
</th>
</tr>
</thead>
<tbody>
{% for invite in invites %}
<tr>
<td>
<kbd>{{ invite.getInvite() }}</kbd>
</td>
<td>
<button class="btn btn-default copy pull-right" data-clipboard-text="{{ invite.getInvite() }}">Copy</button>
</td>
</tr>
{% else %}
<tr>
<td colspan="2">You don't have any invites :(</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div> </div>
<ul class="invites">
{% for invite in invites %}
<li>
<div class="text">
<kbd>{{ invite.getInvite() }}</kbd>
</div>
<div class="actions">
<span>
<a class="copy" data-clipboard-text="{{ invite.getInvite() }}">copy</a>
</span>
</div>
</li>
{% else %}
<li>
You don't have any invites
</li>
{% endfor %}
</ul>
{% endblock %} {% endblock %}

Loading…
Cancel
Save