mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-24 00:07:02 -04:00
Merge pull request #80 from alphagov/api-page-design
API keys and documentation page
This commit is contained in:
58
app/assets/javascripts/apiKey.js
Normal file
58
app/assets/javascripts/apiKey.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
(function(Modules) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
Modules.ApiKey = function() {
|
||||||
|
|
||||||
|
const states = {
|
||||||
|
'initial': `
|
||||||
|
<input type='button' class='api-key-button-show' value='Show API key' />
|
||||||
|
`,
|
||||||
|
'keyVisibleBasic': key => `
|
||||||
|
<span class="api-key-key">${key}</span>
|
||||||
|
`,
|
||||||
|
'keyVisible': key => `
|
||||||
|
<span class="api-key-key">${key}</span>
|
||||||
|
<input type='button' class='api-key-button-copy' value='Copy API key to clipboard' />
|
||||||
|
`,
|
||||||
|
'keyCopied': `
|
||||||
|
<span class="api-key-key">Copied to clipboard</span>
|
||||||
|
<input type='button' class='api-key-button-show' value='Show API key' />
|
||||||
|
`
|
||||||
|
};
|
||||||
|
|
||||||
|
this.copyKey = function(keyElement, callback) {
|
||||||
|
var selection = window.getSelection ? window.getSelection() : document.selection,
|
||||||
|
range = document.createRange();
|
||||||
|
selection.removeAllRanges();
|
||||||
|
range.selectNodeContents(keyElement);
|
||||||
|
selection.addRange(range);
|
||||||
|
document.execCommand('copy');
|
||||||
|
selection.removeAllRanges();
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.start = function(component) {
|
||||||
|
|
||||||
|
const $component = $(component).html(states.initial).attr('aria-live', 'polite'),
|
||||||
|
key = $component.data('key');
|
||||||
|
|
||||||
|
$component
|
||||||
|
.on(
|
||||||
|
'click', '.api-key-button-show', () =>
|
||||||
|
$component.html(
|
||||||
|
document.queryCommandSupported('copy') ?
|
||||||
|
states.keyVisible(key) : states.keyVisibleBasic(key)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.on(
|
||||||
|
'click', '.api-key-button-copy', () =>
|
||||||
|
this.copyKey(
|
||||||
|
$('.api-key-key', component)[0], () =>
|
||||||
|
$component.html(states.keyCopied)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
})(window.GOVUK.Modules);
|
||||||
17
app/assets/stylesheets/components/api-key.scss
Normal file
17
app/assets/stylesheets/components/api-key.scss
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
.api-key {
|
||||||
|
|
||||||
|
&-key {
|
||||||
|
font-family: monospace;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-button-show {
|
||||||
|
@include button($grey-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-button-copy {
|
||||||
|
@include button($grey-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -45,6 +45,7 @@
|
|||||||
@import 'components/management-navigation';
|
@import 'components/management-navigation';
|
||||||
@import 'components/dropdown';
|
@import 'components/dropdown';
|
||||||
@import 'components/email-message';
|
@import 'components/email-message';
|
||||||
|
@import 'components/api-key';
|
||||||
|
|
||||||
@import 'views/job';
|
@import 'views/job';
|
||||||
|
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ main = Blueprint('main', __name__)
|
|||||||
from app.main.views import (
|
from app.main.views import (
|
||||||
index, sign_in, sign_out, register, two_factor, verify, sms, add_service,
|
index, sign_in, sign_out, register, two_factor, verify, sms, add_service,
|
||||||
code_not_received, jobs, dashboard, templates, service_settings, forgot_password,
|
code_not_received, jobs, dashboard, templates, service_settings, forgot_password,
|
||||||
new_password, styleguide, user_profile, choose_service
|
new_password, styleguide, user_profile, choose_service, api_keys
|
||||||
)
|
)
|
||||||
|
|||||||
9
app/main/views/api_keys.py
Normal file
9
app/main/views/api_keys.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from flask import render_template
|
||||||
|
from flask_login import login_required
|
||||||
|
from app.main import main
|
||||||
|
|
||||||
|
|
||||||
|
@main.route("/services/<int:service_id>/api-keys")
|
||||||
|
@login_required
|
||||||
|
def api_keys(service_id):
|
||||||
|
return render_template('views/api-keys.html', service_id=service_id)
|
||||||
@@ -36,9 +36,3 @@ def checkemail(service_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def manageusers(service_id):
|
def manageusers(service_id):
|
||||||
return render_template('views/manage-users.html', service_id=service_id)
|
return render_template('views/manage-users.html', service_id=service_id)
|
||||||
|
|
||||||
|
|
||||||
@main.route("/services/<int:service_id>/api-keys")
|
|
||||||
@login_required
|
|
||||||
def apikeys(service_id):
|
|
||||||
return render_template('views/api-keys.html', service_id=service_id)
|
|
||||||
|
|||||||
5
app/templates/components/api-key.html
Normal file
5
app/templates/components/api-key.html
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{% macro api_key(key) %}
|
||||||
|
<div data-module="api-key" data-key="{{ key }}">
|
||||||
|
<span class="api-key-key">{{ key }}</span>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<li><a href="{{ url_for('.manage_templates', service_id=123) }}">Templates</a></li>
|
<li><a href="{{ url_for('.manage_templates', service_id=123) }}">Templates</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{{ url_for('.apikeys', service_id=123) }}">API keys and documentation</a></li>
|
<li><a href="{{ url_for('.api_keys', service_id=123) }}">API keys and documentation</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{{ url_for('.manageusers', service_id=123) }}">Manage users</a></li>
|
<li><a href="{{ url_for('.manageusers', service_id=123) }}">Manage users</a></li>
|
||||||
|
|||||||
@@ -1,15 +1,52 @@
|
|||||||
{% extends "withnav_template.html" %}
|
{% extends "withnav_template.html" %}
|
||||||
{% from "components/page-footer.html" import page_footer %}
|
{% from "components/page-footer.html" import page_footer %}
|
||||||
|
{% from "components/api-key.html" import api_key %}
|
||||||
|
|
||||||
{% block page_title %}
|
{% block page_title %}
|
||||||
GOV.UK Notify | API keys and documentation
|
GOV.UK Notify | API keys and documentation
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block maincolumn_content %}
|
{% block maincolumn_content %}
|
||||||
|
|
||||||
<h1 class="heading-xlarge">API keys and documentation</h1>
|
<div class="grid-row">
|
||||||
|
<div class="column-two-thirds">
|
||||||
|
|
||||||
<p>Here's where developers can access information about the API and access keys</p>
|
<h1 class="heading-xlarge">
|
||||||
|
API keys and documentation
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<h2 class="heading-medium">
|
||||||
|
How to integrate GOV.UK Notify into your service
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
blah blah blah this is where we tell you how the API works
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="heading-medium">Repositories</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="https://github.com/alphagov/notifications-api">GOV.UK Notify API</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="https://github.com/alphagov/notify-api-client">GOV.UK Notify Python client</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="heading-medium">API key for [service name]</h2>
|
||||||
|
|
||||||
|
{{ api_key('d30512af92e1386d63b90e5973b49a10') }}
|
||||||
|
|
||||||
|
<h2 class="heading-medium">API endpoint</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
https://www.notify.works/api/endpoint
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{ page_footer(
|
{{ page_footer(
|
||||||
back_link=url_for('.dashboard', service_id=service_id),
|
back_link=url_for('.dashboard', service_id=service_id),
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
{% from "components/sms-message.html" import sms_message %}
|
{% from "components/sms-message.html" import sms_message %}
|
||||||
{% from "components/table.html" import mapping_table, list_table, row, field %}
|
{% from "components/table.html" import mapping_table, list_table, row, field %}
|
||||||
{% from "components/textbox.html" import textbox %}
|
{% from "components/textbox.html" import textbox %}
|
||||||
|
{% from "components/api-key.html" import api_key %}
|
||||||
|
|
||||||
{% block page_title %}
|
{% block page_title %}
|
||||||
Styleguide – GOV.UK Notify
|
Styleguide – GOV.UK Notify
|
||||||
@@ -152,4 +153,8 @@
|
|||||||
{{ textbox(form.password) }}
|
{{ textbox(form.password) }}
|
||||||
{{ textbox(form.message, highlight_tags=True) }}
|
{{ textbox(form.message, highlight_tags=True) }}
|
||||||
|
|
||||||
|
<h2 class="heading-large">API key</h2>
|
||||||
|
|
||||||
|
{{ api_key('d30512af92e1386d63b90e5973b49a10') }}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -34,17 +34,19 @@ gulp.task('javascripts', () => gulp
|
|||||||
.src([
|
.src([
|
||||||
paths.npm + 'govuk_frontend_toolkit/javascripts/govuk/modules.js',
|
paths.npm + 'govuk_frontend_toolkit/javascripts/govuk/modules.js',
|
||||||
paths.npm + 'govuk_frontend_toolkit/javascripts/govuk/selection-buttons.js',
|
paths.npm + 'govuk_frontend_toolkit/javascripts/govuk/selection-buttons.js',
|
||||||
paths.src + 'javascripts/highlightTags.js',
|
paths.src + 'javascripts/apiKey.js',
|
||||||
paths.src + 'javascripts/dropdown.js',
|
paths.src + 'javascripts/dropdown.js',
|
||||||
|
paths.src + 'javascripts/highlightTags.js',
|
||||||
paths.src + 'javascripts/main.js'
|
paths.src + 'javascripts/main.js'
|
||||||
])
|
])
|
||||||
.pipe(plugins.babel({
|
.pipe(plugins.babel({
|
||||||
presets: ['es2015']
|
presets: ['es2015']
|
||||||
}))
|
}))
|
||||||
.pipe(plugins.uglify())
|
.pipe(plugins.uglify())
|
||||||
.pipe(plugins.addSrc.prepend(
|
.pipe(plugins.addSrc.prepend([
|
||||||
'./node_modules/jquery/dist/jquery.min.js'
|
paths.npm + 'jquery/dist/jquery.min.js',
|
||||||
))
|
paths.npm + 'query-command-supported/dist/queryCommandSupported.min.js'
|
||||||
|
]))
|
||||||
.pipe(plugins.concat('all.js'))
|
.pipe(plugins.concat('all.js'))
|
||||||
.pipe(gulp.dest(paths.dist + 'javascripts/'))
|
.pipe(gulp.dest(paths.dist + 'javascripts/'))
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
"gulp-load-plugins": "1.1.0",
|
"gulp-load-plugins": "1.1.0",
|
||||||
"gulp-sass": "2.1.1",
|
"gulp-sass": "2.1.1",
|
||||||
"gulp-uglify": "1.5.1",
|
"gulp-uglify": "1.5.1",
|
||||||
"jquery": "1.11.2"
|
"jquery": "1.11.2",
|
||||||
|
"query-command-supported": "1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
tests/app/main/views/test_api_keys.py
Normal file
14
tests/app/main/views/test_api_keys.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
from tests.app.main import create_test_user
|
||||||
|
from flask import url_for
|
||||||
|
|
||||||
|
|
||||||
|
def test_should_show_api_keys_and_documentation_page(notifications_admin,
|
||||||
|
notifications_admin_db,
|
||||||
|
notify_db_session):
|
||||||
|
with notifications_admin.test_request_context():
|
||||||
|
with notifications_admin.test_client() as client:
|
||||||
|
user = create_test_user('active')
|
||||||
|
client.login(user)
|
||||||
|
response = client.get(url_for('.api_keys', service_id=123))
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
Reference in New Issue
Block a user