Commit 7d14d217 authored by Robert Knight's avatar Robert Knight

Implement new designs for pages for creating, joining and sharing groups

 * Implement new look for the Create, Join and Share groups pages.
   The forms are functional without JS but contain a small amount
   of JS logic for enhancements such as selecting the content of
   the share pane.

 * Merge the 'Login to join' and 'Join' pages into a single
   form. The only difference between the two is that
   when the user is not signed in, the button label
   changes from 'Join <Group Name>' to 'Sign in to join <Group Name>'
   which redirects to the login page.

 * Create a new site.scss file which is intended to
   contain only styling for the website and a site-bundle.js
   bundle which contains JS code used only for the site.

 * Extract out the button styles used by <dropdown-menu-btn> into
   a separate .scss file for re-use

 * Add additional colors used by the new group forms
   to variables.scss. To avoid the problems
   with naming that arise when trying to insert additional
   colors into a list with names like 'light', 'lighter' etc.
   I'm starting to use http://chir.ag/projects/name-that-color for
   memorable names.

 * Start to use a '$color-' prefix for colors, in preparation
   for extracting colors into their own file.

Card 93
parent b2200aea
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="80px" height="61px" viewBox="0 0 80 61" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
<title>Untitled</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<rect id="Rectangle-21" stroke="#979797" stroke-width="2" fill="#FFFFFF" sketch:type="MSShapeGroup" x="2" y="1" width="76" height="50" rx="3"></rect>
<rect id="Rectangle-22" opacity="0.2" fill="#585858" sketch:type="MSShapeGroup" x="10" y="9" width="16" height="2"></rect>
<rect id="Rectangle-22-Copy" opacity="0.2" fill="#585858" sketch:type="MSShapeGroup" x="10" y="15" width="60" height="2"></rect>
<rect id="Rectangle-22-Copy-2" opacity="0.2" fill="#585858" sketch:type="MSShapeGroup" x="10" y="21" width="60" height="2"></rect>
<rect id="Rectangle-22-Copy-3" opacity="0.2" fill="#585858" sketch:type="MSShapeGroup" x="10" y="27" width="60" height="2"></rect>
<rect id="Rectangle-22-Copy-4" opacity="0.2" fill="#585858" sketch:type="MSShapeGroup" x="10" y="33" width="60" height="2"></rect>
<path d="M77.3153812,22.3423094 C78.7980552,21.6009724 80,22.3423094 80,24.0065012 L80,57.9934988 C80,59.6539436 78.6616553,61 77.0099126,61 L2.99008742,61 C1.33870774,61 1.19297385,60.4035131 2.68461881,59.6576906 L77.3153812,22.3423094 Z" id="Rectangle-19" fill="#4F4F4F" sketch:type="MSShapeGroup"></path>
<path d="M0,24.0065012 C0,22.3460564 1.19297385,21.5964869 2.68461881,22.3423094 L77.3153812,59.6576906 C78.7980552,60.3990276 78.6616553,61 77.0099126,61 L2.99008742,61 C1.33870774,61 0,59.6576906 0,57.9934988 L0,24.0065012 Z" id="Rectangle-19-Copy" fill="#585858" sketch:type="MSShapeGroup"></path>
</g>
</svg>
\ No newline at end of file
angular = require('angular')
module.exports = class AppController
this.$inject = [
'$controller', '$document', '$location', '$route', '$scope', '$window',
......
......@@ -5,6 +5,7 @@ require('angular-websocket')
require('angular-jwt')
uuid = require('node-uuid')
clientId = uuid.v4()
socket = null
......
function CreateGroupFormController(element) {
// Create Group form handling
var self = this;
this._submitBtn = element.querySelector('.js-create-group-create-btn');
this._groupNameInput = element.querySelector('.js-group-name-input');
this._infoLink = element.querySelector('.js-group-info-link');
this._infoText = element.querySelector('.js-group-info-text');
function groupNameChanged(event) {
self._submitBtn.disabled = self._groupNameInput.value.trim().length === 0;
}
self._groupNameInput.addEventListener('input', groupNameChanged);
groupNameChanged();
this._infoLink.addEventListener('click', function (event) {
event.preventDefault();
self._infoLink.classList.add('is-hidden');
self._infoText.classList.remove('is-hidden');
});
}
module.exports = CreateGroupFormController;
......@@ -35,6 +35,7 @@ module.exports = function(config) {
// Test deps
'../../../node_modules/angular-mocks/angular-mocks.js',
'../../templates/client/*.html',
{ pattern: '../../groups/templates/*.html.jinja2', included: false },
'test/bootstrap.js',
// Tests
......
function ShareGroupFormController(element) {
var shareLink = element.querySelector('.js-share-link');
shareLink.focus();
shareLink.select();
}
module.exports = ShareGroupFormController;
// groups forms
var CreateGroupFormController = require('./create-group-form');
var ShareGroupFormController = require('./share-group-form');
function setupGroupsController(path) {
if (path === '/groups/new') {
new CreateGroupFormController(document.body);
} else if (document.querySelector('.is-member-of-group')) {
new ShareGroupFormController(document.body);
}
}
document.addEventListener('DOMContentLoaded', function () {
if (document.location.pathname.indexOf('/groups') === 0) {
setupGroupsController(document.location.pathname);
}
});
var fetch = require('isomorphic-fetch');
var swig = require('swig');
var CreateGroupFormController = require('../create-group-form');
function isHidden(elt) {
return elt.classList.contains('is-hidden');
}
// helper to dispatch a native event to an element
function sendEvent(element, eventType) {
// createEvent() used instead of Event constructor
// for PhantomJS compatibility
var event = document.createEvent('Event');
event.initEvent(eventType, true /* bubbles */, true /* cancelable */);
element.dispatchEvent(event);
}
// fetch the text for Karma resource which matches the given regex.
// The resource must have been included in the list of files for the test
// specified in the karma.config.js file
function fetchTemplate(pathRegex) {
var templateUrl = Object.keys(window.__karma__.files).filter(function (path) {
return path.match(pathRegex);
})[0];
return fetch(templateUrl).then(function (response) {
return response.text();
});
}
describe('CreateGroupFormController', function () {
var element;
var template;
before(function () {
return fetchTemplate(/create\.html\.jinja2$/).then(function (text) {
// extract the 'content' block from the template
var contentBlock = text.match(/{% block content %}([^]*){% endblock content %}/)[1];
template = swig.compile(contentBlock);
});
});
beforeEach(function () {
var context = {
form: {
csrf_token: {
render: function() {}
},
name: ''
}
};
element = document.createElement('div');
element.innerHTML = template(context);
});
it('should enable submission if form is valid', function () {
var controller = new CreateGroupFormController(element);
controller._groupNameInput.value = '';
sendEvent(controller._groupNameInput, 'input');
assert.equal(controller._submitBtn.disabled, true);
controller._groupNameInput.value = 'a group name';
sendEvent(controller._groupNameInput, 'input');
assert.equal(controller._submitBtn.disabled, false);
});
it('should toggle info text when explain link is clicked', function () {
var controller = new CreateGroupFormController(element);
assert.equal(isHidden(controller._infoText), true);
sendEvent(controller._infoLink, 'click');
assert.equal(isHidden(controller._infoText), false);
assert.equal(isHidden(controller._infoLink), true);
});
});
......@@ -4,11 +4,13 @@ $base-font-size: 12px;
$base-line-height: 20px;
@import './reset';
@import './elements';
@import './common';
// components
@import './dropdown-menu-btn';
@import './publish-annotation-btn';
@import './share-link';
body {
@extend .noise;
......@@ -27,13 +29,6 @@ body {
margin: 0;
}
svg { -webkit-tap-highlight-color: rgba(255, 255, 255, 0); }
ol {
list-style-type: decimal;
padding-left: 3em;
}
.content {
margin-left: auto;
margin-right: auto;
......@@ -46,7 +41,6 @@ ol {
}
}
.sheet {
border: solid 1px $gray-lighter;
border-radius: 2px;
......@@ -134,32 +128,6 @@ $group-list-width: 270px;
flex-shrink: 1;
}
.share-link-container {
font-size: $body1-font-size;
line-height: $body1-line-height;
margin-top: 1px;
white-space: normal;
}
.share-link-toggle {
color: $gray-light;
}
.share-link-toggle:hover {
text-decoration: underline;
color: $gray-dark;
}
.share-link-field {
padding: 3px;
padding-top: 5px;
padding-bottom: 5px;
margin-top: 12px;
margin-bottom: 8px;
border: 1px solid $gray-lighter;
width: 100%;
}
.new-group-btn {
background-color: $gray-lightest;
......
......@@ -23,7 +23,6 @@
&__label {
// the label occupies the entire space of the button and
// shows a darker state on hover
width: 100%;
height: 100%;
......@@ -43,7 +42,7 @@
}
&:disabled {
color: #929292;
color: $gray-light;
}
}
......
// basic standard styling for elements
ol {
list-style-type: decimal;
padding-left: 3em;
}
svg { -webkit-tap-highlight-color: rgba(255, 255, 255, 0); }
// The group-form block implements the styles used by the forms for
// creating, joining and sharing groups
@at-root {
@mixin flex-center-column {
display: flex;
flex-direction: column;
align-items: center;
}
$border-color: $gray-lighter;
$border: 1px solid $border-color;
.is-hidden {
display: none;
}
.group-form {
@include flex-center-column();
min-height: 280px;
background-color: $white;
border: $border;
color: $color-dove-gray;
padding-bottom: 45px;
margin-top: 75px;
&__form {
@include flex-center-column();
}
&__heading-icon {
margin-top: 40px;
font-size: 24px;
}
&__invite-icon {
margin-top: 40px;
margin-bottom: 35px;
width: 85px;
height: 65px;
}
&__heading {
font-size: $title-font-size;
font-weight: $title-font-weight;
margin-bottom: 40px;
}
.form-field {
@include flex-center-column();
}
&__name-label {
font-size: 18px;
}
&__name-input {
font-size: 28px;
font-weight: bold;
border: none;
text-align: center;
margin-bottom: 40px;
width: 350px;
// TODO - Cyan cursor color
&:placeholder {
color: $color-alto;
}
}
}
.group-form-footer {
@include flex-center-column();
justify-content: center;
border: $border;
border-top: none;
color: $color-dove-gray;
font-size: $body2-font-size;
line-height: $body2-line-height;
min-height: 43px;
background-color: $color-wild-sand;
padding-left: 18px;
padding-right: 18px;
&__explain-link {
color: $color-silver-chalice;
}
&__explain-text {
padding-bottom: 22px;
}
&__heading {
font-weight: bold;
margin-top: 22px;
margin-bottom: 4px;
}
&__list {
padding-left: 18px;
}
}
.group-form-footer-link {
@include flex-center-column();
color: $gray-light;
justify-content: center;
height: 35px;
a {
color: inherit;
}
}
}
// A dark grey button used for the primary action
// in a form
.primary-action-btn {
// note that there is currently some duplication here between
// the styling for this element and <dropdown-menu-btn>
color: $color-seashell;
background-color: $color-dove-gray;
height: 35px;
border: none;
border-radius: 2px;
font-weight: bold;
font-size: $body1-font-size;
&:disabled {
color: $gray-light;
}
&:hover:enabled {
background-color: $color-mine-shaft;
}
}
// form for sharing links
.share-link-container {
font-size: $body1-font-size;
line-height: $body1-line-height;
margin-top: 1px;
white-space: normal;
}
.share-link-toggle {
color: $gray-light;
}
.share-link-toggle:hover {
text-decoration: underline;
color: $gray-dark;
}
.share-link-field {
padding: 3px;
padding-top: 5px;
padding-bottom: 5px;
margin-top: 12px;
margin-bottom: 8px;
border: 1px solid $gray-lighter;
border-radius: 2px;
width: 100%;
}
.share-link-icons {
display: flex;
flex-direction: row;
justify-content: center;
}
.share-link-icon {
color: $color-dove-gray;
display: inline-block;
font-size: 24px;
text-decoration: none;
margin-left: 5px;
margin-right: 5px;
&:hover {
color: $brand-color;
}
}
// shared styling used by both the app and the website
@import './base';
@import './reset';
@import' ./elements';
// shared components
@import './primary-action-btn';
@import './share-link';
// website-specific components
@import './group-form';
body {
@extend .noise;
font-family: $sans-font-family;
}
.content {
margin-left: auto;
margin-right: auto;
}
.content--narrow {
width: 450px;
}
// Colors and shades of gray
// Names courtesy of http://chir.ag/projects/name-that-color
$white: #fff !default;
$black: #000 !default;
......@@ -9,7 +12,14 @@ $gray-light: #969696 !default;
$gray-lighter: #d3d3d3 !default;
$gray-lightest: #f9f9f9 !default;
//COLORS
$color-mine-shaft: #3A3A3A;
$color-dove-gray: #626262;
$color-silver-chalice: #a6a6a6;
$color-alto: #dedede;
$color-seashell: #f1f1f1;
$color-wild-sand: #f5f5f5;
// COLORS
$brand-color: #bd1c2b !default;
$button-text-color: $gray-dark !default;
......@@ -70,6 +80,12 @@ $headings-color: inherit !default;
$body1-font-size: 12px;
$body1-line-height: 1.4em;
$body2-font-size: 14px;
$body2-line-height: 1.4em;
$title-font-size: 20px;
$title-font-weight: bold;
//STANCE COLORS
$positive: #3aab39;
$negative: #d11c2b;
......
......@@ -11,22 +11,22 @@
type="text"
ng-value="viaPageLink"
readonly /></p>
<p class="share-links">
<p class="share-link-icons">
<a href="//twitter.com/intent/tweet?url={{viaPageLink}}"
target="_blank"
title="Tweet link"
class="h-icon-twitter"></a>
class="share-link-icon h-icon-twitter"></a>
<a href="//www.facebook.com/sharer/sharer.php?u={{viaPageLink}}"
target="_blank"
title="Share on Facebook"
class="h-icon-facebook"></a>
class="share-link-icon h-icon-facebook"></a>
<a href="//plus.google.com/share?url={{viaPageLink}}"
target="_blank"
title="Post on Google Plus"
class="h-icon-google-plus"></a>
class="share-link-icon h-icon-google-plus"></a>
<a href="mailto:?subject=Let's%20Annotate&amp;body={{viaPageLink}}"
title="Share via email"
class="h-icon-mail"></a>
class="share-link-icon h-icon-mail"></a>
</p>
</div>
</div>
......
......@@ -35,6 +35,7 @@
"extend": "^2.0.0",
"frame-rpc": "^1.3.1",
"hammerjs": "^2.0.4",
"isomorphic-fetch": "^2.1.1",
"jquery": "1.11.1",
"js-polyfills": "^0.1.11",
"moment": "^2.10.6",
......@@ -64,7 +65,8 @@
"proxyquire": "^1.6.0",
"proxyquire-universal": "^1.0.8",
"proxyquireify": "^3.0.0",
"sinon": "1.16.1"
"sinon": "1.16.1",
"swig": "^1.4.2"
},
"engines": {
"node": "0.10.x"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment