Removed Semantic UI React

This commit is contained in:
John Lyon-Smith
2018-02-25 17:51:52 -08:00
parent c60bfcedf8
commit 0571196a7f
68 changed files with 981 additions and 1343 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "deighton-ar",
"version": "1.0.0",
"version": "0.1.0",
"description": "Deighton AR Training System",
"main": "index.js",
"repository": {

56
version.json5 Normal file
View File

@@ -0,0 +1,56 @@
{
filenames: [
"package.json",
"website/src/version.js",
"scratch/version.tag.txt",
"scratch/version.desc.txt"
],
buildFormat: "full",
tags: {
major: 0,
minor: 1,
patch: 0,
build: 20180225,
revision: 0,
tz: "America/Los_Angeles",
startYear: "2017"
},
fileTypes: [
{
name: "Node Package",
glob: "**/package.json",
update: {
search: "^(?<begin> *\"version\" *: *\")\\d+\\.\\d+\\.\\d+(?<end>\" *, *)$",
replace: "${begin}${major}.${minor}.${patch}${end}"
}
},
{
name: "Javascript File",
glob: "**/version.js",
updates: [
{
search: "^(?<begin>\\s*static\\s*version\\s*=\\s*')\\d+\\.\\d+\\.\\d+(?<end>'\\s*)$",
replace: "${begin}${major}.${minor}.${patch}${end}"
},
{
search: "^(?<begin>\\s*static\\s*fullVersion\\s*=\\s*')\\d+\\.\\d+\\.\\d+-\\d+\\.\\d+(?<end>'\\s*)$",
replace: "${begin}${major}.${minor}.${patch}-${build}.${revision}${end}"
},
{
search: "^(?<begin>\\s*static\\s*startYear\\s*=\\s*')\\d+(?<end>'\\s*)$",
replace: "${begin}${startYear}${end}"
}
]
},
{
name: "Commit tag file",
glob: "**/*.tag.txt",
write: "v${major}.${minor}.${patch}"
},
{
name: "Commit tag description file",
glob: "**/*.desc.txt",
write: "Version ${major}.${minor}.${patch}-${build}.${revision}"
}
]
}

View File

@@ -1,4 +1,4 @@
'use strict';
feslint'use strict';
const autoprefixer = require('autoprefixer');
const path = require('path');
@@ -137,7 +137,7 @@ module.exports = {
// smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match.
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.svg$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
@@ -146,7 +146,7 @@ module.exports = {
},
// Process JS with Babel.
{
test: /\.(js|jsx|mjs)$/,
test: /\.(js|jsx|mjs)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
@@ -163,37 +163,35 @@ module.exports = {
// In production, we use a plugin to extract that CSS to a file, but
// in development "style" loader enables hot editing of CSS.
{
test: /\.(sass|scss)$/,
test: /\.(sass|scss)$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{ loader: require.resolve('sass-loader'), },
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
{
loader: require.resolve('sass-loader'),
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},

View File

@@ -142,7 +142,7 @@ module.exports = {
// "url" loader works just like "file" loader but it also embeds
// assets smaller than specified size as data URLs to avoid requests.
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.svg$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,

View File

@@ -4,11 +4,6 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/react": {
"version": "15.6.7",
"resolved": "https://registry.npmjs.org/@types/react/-/react-15.6.7.tgz",
"integrity": "sha512-HMfRuwiTp7/MfjPOsVlvlduouJH3haDzjc0oXqZy3ZMn3OTl3i4gGgbxsqzA/u9gNyl/oKkwOrU2oVR6vG5SAw=="
},
"abab": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz",
@@ -94,15 +89,6 @@
"integrity": "sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg==",
"dev": true
},
"adler-32": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.1.0.tgz",
"integrity": "sha1-A1UaXH8O371PyPoSpoFJeOq2UcM=",
"requires": {
"exit-on-epipe": "1.0.1",
"printj": "1.1.0"
}
},
"after": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
@@ -147,12 +133,6 @@
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
"dev": true
},
"anser": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/anser/-/anser-1.4.1.tgz",
"integrity": "sha1-w2QYY6lizr75Qeoshwbyy08HFr0=",
"dev": true
},
"ansi-align": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-1.1.0.tgz",
@@ -233,15 +213,6 @@
"sprintf-js": "1.0.3"
}
},
"aria-query": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-0.5.0.tgz",
"integrity": "sha1-heMVLNjMW6sY2+1hzZxPzlT6ecM=",
"dev": true,
"requires": {
"ast-types-flow": "0.0.7"
}
},
"arr-diff": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
@@ -384,12 +355,6 @@
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
"dev": true
},
"ast-types-flow": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
"integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=",
"dev": true
},
"async": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
@@ -459,15 +424,6 @@
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=",
"dev": true
},
"axobject-query": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-0.1.0.tgz",
"integrity": "sha1-YvWdvFnJ+SQnWco0mWDnov48NsA=",
"dev": true,
"requires": {
"ast-types-flow": "0.0.7"
}
},
"babel-code-frame": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
@@ -2114,15 +2070,6 @@
"lazy-cache": "1.0.4"
}
},
"cfb": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.0.0.tgz",
"integrity": "sha512-nDzEYhfR9kqwcRrnAPQnPbisPorodhkJTkMS2QG12y9kHNXnF+8ByWFLyqxbVfry1jWuXlT1PCK11+MOS8uGKg==",
"requires": {
"commander": "2.11.0",
"printj": "1.1.0"
}
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
@@ -2290,11 +2237,6 @@
}
}
},
"classnames": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.5.tgz",
"integrity": "sha1-+zgB1FNGdknvNgPH1hoCvRKb3m0="
},
"clean-css": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.9.tgz",
@@ -2402,16 +2344,6 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"dev": true
},
"codepage": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.11.0.tgz",
"integrity": "sha1-EHYJW58DtcoE9Dhz+hpid0IoXeI=",
"requires": {
"commander": "2.11.0",
"exit-on-epipe": "1.0.1",
"voc": "1.0.0"
}
},
"collection-visit": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
@@ -2486,7 +2418,8 @@
"commander": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
"integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ=="
"integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
"dev": true
},
"commondir": {
"version": "1.0.1",
@@ -2684,15 +2617,6 @@
}
}
},
"crc-32": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.1.1.tgz",
"integrity": "sha1-XXOdXkxuNSrYME1zIj1IP+Va240=",
"requires": {
"exit-on-epipe": "1.0.1",
"printj": "1.1.0"
}
},
"create-ecdh": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz",
@@ -3056,12 +2980,6 @@
"es5-ext": "0.10.35"
}
},
"damerau-levenshtein": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz",
"integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=",
"dev": true
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -3265,15 +3183,6 @@
"buffer-indexof": "1.1.1"
}
},
"doctrine": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz",
"integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=",
"requires": {
"esutils": "1.1.6",
"isarray": "0.0.1"
}
},
"dom-converter": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz",
@@ -3422,12 +3331,6 @@
"minimalistic-crypto-utils": "1.0.1"
}
},
"emoji-regex": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.5.1.tgz",
"integrity": "sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ==",
"dev": true
},
"emojis-list": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
@@ -3745,12 +3648,6 @@
}
}
},
"eslint-config-react-app": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-1.0.5.tgz",
"integrity": "sha1-mDN1l7wBzCKZH8vdoHRR87RRFxg=",
"dev": true
},
"eslint-config-standard": {
"version": "10.2.1",
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz",
@@ -3813,15 +3710,6 @@
"integrity": "sha1-eSAqDjV1fdkngJGbIzbx+i/lPB4=",
"dev": true
},
"eslint-plugin-flowtype": {
"version": "2.33.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.33.0.tgz",
"integrity": "sha1-sng4FO0t3PcplTuPZf9zyQyr7ks=",
"dev": true,
"requires": {
"lodash": "4.17.4"
}
},
"eslint-plugin-import": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz",
@@ -3864,21 +3752,6 @@
}
}
},
"eslint-plugin-jsx-a11y": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-5.0.3.tgz",
"integrity": "sha1-SpOfduwSUBBSiCMzG/lIzFczgLY=",
"dev": true,
"requires": {
"aria-query": "0.5.0",
"array-includes": "3.0.3",
"ast-types-flow": "0.0.7",
"axobject-query": "0.1.0",
"damerau-levenshtein": "1.0.4",
"emoji-regex": "6.5.1",
"jsx-ast-utils": "1.4.1"
}
},
"eslint-plugin-node": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz",
@@ -3987,11 +3860,6 @@
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
"dev": true
},
"esutils": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz",
"integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U="
},
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -4058,11 +3926,6 @@
"integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=",
"dev": true
},
"exit-on-epipe": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
"integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw=="
},
"expand-brackets": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
@@ -4428,14 +4291,6 @@
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
"dev": true
},
"frac": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.0.tgz",
"integrity": "sha1-3EN+nGpka2CxJ9gqxJAkZERcweM=",
"requires": {
"voc": "1.0.0"
}
},
"fragment-cache": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -5550,11 +5405,6 @@
"integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
"dev": true
},
"get-comments": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-comments/-/get-comments-1.0.1.tgz",
"integrity": "sha1-GWdZEBu7xPrPEwYMqu3Uhw3uVb4="
},
"get-stdin": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
@@ -6261,14 +6111,6 @@
"integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==",
"dev": true
},
"immutability-helper": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-2.5.0.tgz",
"integrity": "sha512-hbOOUruoaBQ04LH1QvUcycfM36y7xlmCKlIQXXyEiry/KeqBUNqq5BsV+KVzhYfgxk4RdFkDuhKaqhHKpjs7XA==",
"requires": {
"invariant": "2.2.2"
}
},
"import-local": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz",
@@ -7235,11 +7077,6 @@
"pretty-format": "20.0.3"
}
},
"jquery": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz",
"integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c="
},
"js-base64": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.3.2.tgz",
@@ -7516,7 +7353,8 @@
"lodash": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
"dev": true
},
"lodash._reinterpolate": {
"version": "3.0.0",
@@ -7930,11 +7768,6 @@
"minimist": "0.0.8"
}
},
"moment": {
"version": "2.19.2",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.19.2.tgz",
"integrity": "sha512-Rf6jiHPEfxp9+dlzxPTmRHbvoFXsh2L/U8hOupUMpnuecHQmI6cF6lUbJl3QqKPko1u6ujO+FxtcajLVfLpAtA=="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -8704,11 +8537,6 @@
"integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==",
"dev": true
},
"papaparse": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-4.3.6.tgz",
"integrity": "sha1-lWbtoOyrE6/LdApiOBxpn0hssUU="
},
"param-case": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
@@ -10307,11 +10135,6 @@
"ansi-styles": "3.2.0"
}
},
"printj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/printj/-/printj-1.1.0.tgz",
"integrity": "sha512-NbiNBOQ0GioHyeD3ni8wZB7ZmfU7mxIrqhWR5XSreX3rUVvk5UOwpzxOnWqrLdCtoBbdQ40sEwC+nXxxjlUo0A=="
},
"private": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@@ -10553,21 +10376,6 @@
}
}
},
"rc-datepicker": {
"version": "5.0.10",
"resolved": "https://registry.npmjs.org/rc-datepicker/-/rc-datepicker-5.0.10.tgz",
"integrity": "sha1-+4o3rs9K6zuWQ8Fwom4qFfGam5Y=",
"requires": {
"@types/react": "15.6.7",
"classnames": "2.2.5",
"lodash": "4.17.4",
"moment": "2.19.2",
"react-flexview": "1.0.13",
"revenge": "0.4.5",
"tcomb": "3.2.24",
"tcomb-react": "0.9.3"
}
},
"react": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-16.2.0.tgz",
@@ -10579,19 +10387,6 @@
"prop-types": "15.6.0"
}
},
"react-data-grid": {
"version": "2.0.74",
"resolved": "https://registry.npmjs.org/react-data-grid/-/react-data-grid-2.0.74.tgz",
"integrity": "sha1-csbkrK8sCO4lfbWZmmRY4XfeC5Q="
},
"react-data-grid-addons": {
"version": "2.0.74",
"resolved": "https://registry.npmjs.org/react-data-grid-addons/-/react-data-grid-addons-2.0.74.tgz",
"integrity": "sha1-mLDTQeG/k13dIyeAc43VBH4fW+o=",
"requires": {
"react-data-grid": "2.0.74"
}
},
"react-dev-utils": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-5.0.0.tgz",
@@ -10802,262 +10597,6 @@
"prop-types": "15.6.0"
}
},
"react-error-overlay": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-1.0.10.tgz",
"integrity": "sha512-/fzpqRGPWlpDvvBwLN7vjE4FAI81ajbWowkrycY8P5RGqE49WIUMIdFjTS5htqJfzxcM599k/x1lCayaq+4qEw==",
"dev": true,
"requires": {
"anser": "1.4.1",
"babel-code-frame": "6.22.0",
"babel-runtime": "6.23.0",
"react-dev-utils": "3.1.1",
"settle-promise": "1.0.0",
"source-map": "0.5.6"
},
"dependencies": {
"address": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/address/-/address-1.0.2.tgz",
"integrity": "sha1-SACB6CtYe6MZRZ/vUS9Rb+A9WK8=",
"dev": true
},
"ansi-escapes": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz",
"integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=",
"dev": true
},
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
"babel-code-frame": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz",
"integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=",
"dev": true,
"requires": {
"chalk": "1.1.3",
"esutils": "2.0.2",
"js-tokens": "3.0.2"
}
},
"cli-cursor": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
"integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
"dev": true,
"requires": {
"restore-cursor": "2.0.0"
}
},
"detect-port-alt": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.3.tgz",
"integrity": "sha1-pNLwYddXoDTs83xRQmCph1DysTE=",
"dev": true,
"requires": {
"address": "1.0.2",
"debug": "2.6.9"
}
},
"esutils": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
"dev": true
},
"figures": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
"integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
"dev": true,
"requires": {
"escape-string-regexp": "1.0.5"
}
},
"filesize": {
"version": "3.5.10",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-3.5.10.tgz",
"integrity": "sha1-/I+iPdtO+eXgq24eZPZ5okpWdh8=",
"dev": true
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"inquirer": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.1.tgz",
"integrity": "sha512-QgW3eiPN8gpj/K5vVpHADJJgrrF0ho/dZGylikGX7iqAdRgC9FVKYKWFLx6hZDBFcOLEoSqINYrVPeFAeG/PdA==",
"dev": true,
"requires": {
"ansi-escapes": "2.0.0",
"chalk": "2.3.1",
"cli-cursor": "2.1.0",
"cli-width": "2.2.0",
"external-editor": "2.1.0",
"figures": "2.0.0",
"lodash": "4.17.4",
"mute-stream": "0.0.7",
"run-async": "2.3.0",
"rx-lite": "4.0.8",
"rx-lite-aggregates": "4.0.8",
"string-width": "2.1.1",
"strip-ansi": "4.0.0",
"through": "2.3.8"
},
"dependencies": {
"chalk": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz",
"integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==",
"dev": true,
"requires": {
"ansi-styles": "3.2.0",
"escape-string-regexp": "1.0.5",
"supports-color": "5.2.0"
}
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"dev": true,
"requires": {
"ansi-regex": "3.0.0"
}
}
}
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"mute-stream": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
"dev": true
},
"onetime": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
"integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
"dev": true,
"requires": {
"mimic-fn": "1.2.0"
}
},
"react-dev-utils": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-3.1.1.tgz",
"integrity": "sha512-xuScoO3RqgGrD15WMtmJf2MoHFu/G886lk8z3vvj87Afxm74UdAyDqtxkCBXvyjUXGRo774HQI7NsSoT9oNXQQ==",
"dev": true,
"requires": {
"address": "1.0.2",
"anser": "1.4.1",
"babel-code-frame": "6.22.0",
"chalk": "1.1.3",
"cross-spawn": "5.1.0",
"detect-port-alt": "1.1.3",
"escape-string-regexp": "1.0.5",
"filesize": "3.5.10",
"global-modules": "1.0.0",
"gzip-size": "3.0.0",
"html-entities": "1.2.1",
"inquirer": "3.2.1",
"is-root": "1.0.0",
"opn": "5.1.0",
"recursive-readdir": "2.2.1",
"shell-quote": "1.6.1",
"sockjs-client": "1.1.4",
"strip-ansi": "3.0.1",
"text-table": "0.2.0"
}
},
"restore-cursor": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
"integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
"dev": true,
"requires": {
"onetime": "2.0.1",
"signal-exit": "3.0.2"
}
},
"run-async": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
"integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
"dev": true,
"requires": {
"is-promise": "2.1.0"
}
},
"rx-lite": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
"integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
"dev": true
},
"source-map": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
"integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
"dev": true
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"dev": true,
"requires": {
"is-fullwidth-code-point": "2.0.0",
"strip-ansi": "4.0.0"
},
"dependencies": {
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"dev": true,
"requires": {
"ansi-regex": "3.0.0"
}
}
}
},
"supports-color": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz",
"integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==",
"dev": true,
"requires": {
"has-flag": "3.0.0"
}
}
}
},
"react-flexview": {
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/react-flexview/-/react-flexview-1.0.13.tgz",
"integrity": "sha1-UKKSbg0d/BdcT4VHHDnK+eqwuxY=",
"requires": {
"@types/react": "15.6.7",
"classnames": "2.2.5",
"lodash": "4.17.4",
"sass-flex-mixins": "0.1.0",
"tcomb-react": "0.9.3"
}
},
"react-router": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-4.2.0.tgz",
@@ -11267,7 +10806,8 @@
"regenerator-runtime": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz",
"integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A=="
"integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==",
"dev": true
},
"regenerator-transform": {
"version": "0.10.1",
@@ -11537,16 +11077,6 @@
"onetime": "1.1.0"
}
},
"revenge": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/revenge/-/revenge-0.4.5.tgz",
"integrity": "sha1-ChS/qNQ/qaaqQKvIEV8StNmI1UI=",
"requires": {
"debug": "2.6.9",
"lodash": "4.17.4",
"tcomb": "3.2.24"
}
},
"right-align": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
@@ -11645,11 +11175,6 @@
}
}
},
"sass-flex-mixins": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/sass-flex-mixins/-/sass-flex-mixins-0.1.0.tgz",
"integrity": "sha1-vRuMvQsIBpK1fKJY9AOjVdVTAI8="
},
"sass-graph": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
@@ -11767,50 +11292,6 @@
"node-forge": "0.7.1"
}
},
"semantic-ui-css": {
"version": "2.2.12",
"resolved": "https://registry.npmjs.org/semantic-ui-css/-/semantic-ui-css-2.2.12.tgz",
"integrity": "sha512-RrA3k6hya+kEMDmVLT38SBTDQD8FgdnFi16eMPuQ1N1xUOoBxKzr+HZASb7Zo3xlMvkYqEWvPIp58Wjl6Zcsfg==",
"requires": {
"jquery": "3.2.1"
}
},
"semantic-ui-react": {
"version": "0.70.0",
"resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-0.70.0.tgz",
"integrity": "sha512-5cuVW4zDvL6EVeETdOI5iDu+c7UKe7LOgvsOvjQ6prEEWbWnRY03mA693yOM3T2QvD+zfPWqsOR5gJsOvaEmew==",
"requires": {
"babel-runtime": "6.26.0",
"classnames": "2.2.5",
"debug": "2.6.9",
"lodash": "4.17.4",
"prop-types": "15.5.8"
},
"dependencies": {
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"requires": {
"core-js": "2.5.1",
"regenerator-runtime": "0.11.0"
}
},
"core-js": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz",
"integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs="
},
"prop-types": {
"version": "15.5.8",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.8.tgz",
"integrity": "sha1-a3suFBCDvjjIWVqlH8VXdccZk5Q=",
"requires": {
"fbjs": "0.8.16"
}
}
}
},
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
@@ -11932,12 +11413,6 @@
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
"dev": true
},
"settle-promise": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/settle-promise/-/settle-promise-1.0.0.tgz",
"integrity": "sha1-aXrbWLgh84fOJ1fAbvyd5fDuM9g=",
"dev": true
},
"sha.js": {
"version": "2.4.9",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz",
@@ -12388,14 +11863,6 @@
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
"ssf": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.10.1.tgz",
"integrity": "sha1-8j2CtjeS71YIkInBzQyEjpEc26Y=",
"requires": {
"frac": "1.1.0"
}
},
"sshpk": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
@@ -12775,39 +12242,6 @@
"inherits": "2.0.3"
}
},
"tcomb": {
"version": "3.2.24",
"resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.24.tgz",
"integrity": "sha512-N9IrL2iIyS/f4+WHYZaMh04ZqDL8yEit9cVdnn+fOuL6jbKo1fusNswHOjSo/kbYwLUKRS1OlQmAkyeNxyEUhA=="
},
"tcomb-doc": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/tcomb-doc/-/tcomb-doc-0.5.2.tgz",
"integrity": "sha1-1YplOjAH42SRJ4ZAEMVYp79mbR4=",
"requires": {
"tcomb": "3.2.24"
}
},
"tcomb-react": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/tcomb-react/-/tcomb-react-0.9.3.tgz",
"integrity": "sha1-RHE+HS6ML/dEuO1leb93rtI7Dvw=",
"requires": {
"doctrine": "0.7.2",
"get-comments": "1.0.1",
"react": "16.2.0",
"tcomb-doc": "0.5.2",
"tcomb-validation": "3.4.1"
}
},
"tcomb-validation": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz",
"integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==",
"requires": {
"tcomb": "3.2.24"
}
},
"test-exclude": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.1.1.tgz",
@@ -13553,11 +12987,6 @@
"indexof": "0.0.1"
}
},
"voc": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/voc/-/voc-1.0.0.tgz",
"integrity": "sha512-mQwxWlK+zosxxDTqiFb9ZQBNgd794scgkhVwca7h9sEhvA52f3VzbOK+TOWeS8eSrFXnfuKrxElSPc5oLAetfw=="
},
"walker": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",
@@ -14435,20 +13864,6 @@
"os-homedir": "1.0.2"
}
},
"xlsx": {
"version": "0.11.9",
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.11.9.tgz",
"integrity": "sha1-TA7H/j9entSxQdsvG82RVzSNd2U=",
"requires": {
"adler-32": "1.1.0",
"cfb": "1.0.0",
"codepage": "1.11.0",
"commander": "2.11.0",
"crc-32": "1.1.1",
"exit-on-epipe": "1.0.1",
"ssf": "0.10.1"
}
},
"xml-char-classes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz",

View File

@@ -5,28 +5,18 @@
"dependencies": {
"auto-bind2": "^1.0.2",
"eventemitter3": "^2.0.3",
"immutability-helper": "^2.3.0",
"moment": "^2.18.1",
"papaparse": "^4.3.3",
"prop-types": "^15.5.10",
"radium": "^0.22.0",
"rc-datepicker": "^5.0.7",
"react": "^16.2.0",
"react-data-grid": "^2.0.51",
"react-data-grid-addons": "^2.0.55",
"react-dom": "^16.2.0",
"react-router-dom": "^4.1.1",
"regexp-pattern": "^1.0.4",
"semantic-ui-css": "^2.2.10",
"semantic-ui-react": "^0.70.0",
"socket.io-client": "^2.0.3",
"xlsx": "^0.11.3"
"socket.io-client": "^2.0.3"
},
"devDependencies": {
"autoprefixer": "7.1.0",
"babel-core": "6.24.1",
"babel-eslint": "7.2.3",
"babel-jest": "20.0.3",
"babel-loader": "7.0.0",
"babel-preset-react-app": "^3.0.1",
"babel-runtime": "6.23.0",
@@ -36,14 +26,11 @@
"dotenv": "4.0.0",
"dotenv-expand": "^4.2.0",
"eslint": "3.19.0",
"eslint-config-react-app": "^1.0.5",
"eslint-config-standard": "^10.2.1",
"eslint-config-standard-react": "^5.0.0",
"eslint-loader": "1.7.1",
"eslint-plugin-babel": "^4.1.1",
"eslint-plugin-flowtype": "2.33.0",
"eslint-plugin-import": "2.2.0",
"eslint-plugin-jsx-a11y": "5.0.3",
"eslint-plugin-node": "^5.1.0",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-react": "7.0.1",
@@ -60,7 +47,6 @@
"promise": "7.1.1",
"raf": "^3.4.0",
"react-dev-utils": "^5.0.0",
"react-error-overlay": "^1.0.9",
"sass-loader": "^6.0.6",
"style-loader": "^0.17.0",
"sw-precache-webpack-plugin": "0.9.1",

View File

@@ -4,6 +4,7 @@
<title>Deighton AR</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Hind" rel="stylesheet">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.png">
</head>
<body>

View File

@@ -3,16 +3,18 @@ import { Login, Logout, ResetPassword, ForgotPassword, ConfirmEmail, ProtectedRo
import { Home } from './Home'
import { Profile } from './Profile'
import { Users } from './Users'
import { HolyGrail } from './ui'
import { HolyGrail, Image, Text, Icon } from './ui'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import logoImage from 'images/logo.png'
import { versionInfo } from './version'
export class App extends React.Component {
render() {
return (
<HolyGrail>
<HolyGrail.Header>
<img src={logoImage} style={{ width: '50px', height: '50px', margin: '5px' }} />
<Image source={logoImage} width={50} height={50} margin={5} />
<Icon name='logout' />
</HolyGrail.Header>
<HolyGrail.Body>
<Router basename='/'>
@@ -30,7 +32,7 @@ export class App extends React.Component {
</Router>
</HolyGrail.Body>
<HolyGrail.Footer>
<div style={{ margin: '10px' }}>v1.0.0. Copyright &copy; 2018, Deighton.</div>
<Text margin={10}>{versionInfo.fullVersion} &copy; 2018, Kingston Software Solutions.</Text>
</HolyGrail.Footer>
</HolyGrail>
)

View File

@@ -1,9 +1,7 @@
import React from 'react'
import { api } from '../helpers'
import PropTypes from 'prop-types'
import { Container } from 'semantic-ui-react'
import { MessageDialog, WaitDialog } from '../Dialog'
import './ConfirmEmail.scss'
export class ConfirmEmail extends React.Component {
static propTypes = {
@@ -56,7 +54,7 @@ export class ConfirmEmail extends React.Component {
render() {
return (
<Container className='email-confirm-container'>
<div>
<WaitDialog active={!!this.state.waitDialog}
message={this.state.waitDialog ? this.state.waitDialog.message : ''} />
@@ -64,7 +62,7 @@ export class ConfirmEmail extends React.Component {
title={this.state.messageDialog ? this.state.messageDialog.title : ''}
message={this.state.messageDialog ? this.state.messageDialog.message : ''}
onDismiss={this.handleMessageDialogDismiss} />
</Container>
</div>
)
}
}

View File

@@ -1,11 +0,0 @@
.ui.container.email-confirm-container {
display: flex;
height: 80vh;
flex-direction: column;
align-items: center;
justify-content: center;
}
.ui.container.email-confirm-container button {
margin-top: 1em;
}

View File

@@ -1,8 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import { regExpPattern } from 'regexp-pattern'
import { Container, Header, Form, Message } from 'semantic-ui-react'
import './ForgotPassword.scss'
import { Text, StackLayout } from '../ui'
import { MessageDialog, WaitDialog } from '../Dialog'
import { Validator, ValidatedInput, ValidatedButton } from '../Validated'
import { api } from '../helpers'
@@ -67,16 +66,26 @@ export class ForgotPassword extends React.Component {
render() {
return (
<Container className='forgot-password-container'>
<Header content='Forgotten Password' size='large' />
<Form size='large' onSubmit={this.handleSubmit}>
<ValidatedInput label='Email' name='email'
placeholder='example@xyz.com' validator={this.state.validator}
message='A valid email address' />
<Message info content='The email address of an existing user to send the password reset link to.' />
<ValidatedButton className='submit' name='submit' content='Submit'
primary submit validator={this.state.validator}>Submit</ValidatedButton>
</Form>
<div>
<form onSubmit={this.handleSubmit}>
<StackLayout>
<StackLayout.Item>
<Text size='large'>Forgotten Password</Text>
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='Email' name='email'
placeholder='example@xyz.com' validator={this.state.validator}
message='A valid email address' />
</StackLayout.Item>
<StackLayout.Item>
<Text>The email address of an existing user to send the password reset link to.</Text>
</StackLayout.Item>
<StackLayout.Item>
<ValidatedButton className='submit' name='submit' content='Submit'
primary submit validator={this.state.validator}>Submit</ValidatedButton>
</StackLayout.Item>
</StackLayout>
</form>
<WaitDialog active={!!this.state.waitDialog}
message={this.state.waitDialog ? this.state.waitDialog.message : ''} />
@@ -87,7 +96,7 @@ export class ForgotPassword extends React.Component {
title={this.state.messageDialog ? this.state.messageDialog.title : ''}
message={this.state.messageDialog ? this.state.messageDialog.message : ''}
onDismiss={this.handleMessageDialogDismiss} />
</Container>
</div>
)
}
}

View File

@@ -1,23 +0,0 @@
.ui.container.forgot-password-container {
height: 80vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.ui.container.forgot-password-container .header {
border-bottom: 1px solid #d4d4d5;
width: 40%;
padding-bottom: 0.5em;
margin-bottom: 1em;
}
.ui.container.forgot-password-container form {
width: 40%;
}
.ui.container.forgot-password-container .message {
margin: 2em 0;
font-size: 0.8em;
}

View File

@@ -1,13 +1,11 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Container, Header, Form, Message } from 'semantic-ui-react'
import './Login.scss'
import { regExpPattern } from 'regexp-pattern'
import { api } from '../helpers'
import { Validator, ValidatedInput, ValidatedCheckbox } from '../Validated'
import { Validator, ValidatedInput, ValidatedCheckbox, ValidatedButton } from '../Validated'
import { WaitDialog, MessageDialog } from '../Dialog'
import { Link } from 'react-router-dom'
import { Button } from '../ui'
import { Image, Link, Text, StackLayout } from '../ui'
import headerLogo from 'images/deighton.png'
export class Login extends React.Component {
static propTypes = {
@@ -90,30 +88,40 @@ export class Login extends React.Component {
render() {
return (
<Container id='login' className='password-reset-container'>
<Header size='large'>Login Portal</Header>
<Form onSubmit={this.handleSubmit}>
{/* Add in 'Username' field pass */}
<ValidatedInput label='Email' name='email'
placeholder='example@xyz.com' validator={this.state.validator}
message='Enter the email address associated with your account.' width={16} />
<ValidatedInput password label='Password' name='password'
validator={this.state.validator} message='Enter your password.' width={16} />
<Form.Group widths='equal' className='login-options'>
<Form.Field className='login-password'>
<div>
<form onSubmit={this.handleSubmit}>
<StackLayout>
<StackLayout.Item>
<Image source={headerLogo} width={279} height={73} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='Email' name='email'
placeholder='example@xyz.com' validator={this.state.validator}
message='Enter the email address associated with your account.' width={16} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput password label='Password' name='password'
validator={this.state.validator} message='Enter your password.' width={16} />
</StackLayout.Item>
<StackLayout.Item>
<Link to='/forgot-password'>Forgot your password?</Link>
</Form.Field>
<ValidatedCheckbox label='Remember Me'
name='rememberMe' onChange={this.handleChange} validator={this.state.validator}
message='Should we keep you logged in on this computer?' className='login-checkbox' />
</Form.Group>
{ /* <ValidatedButton className='submit' name='submit' content='Submit'
primary submit validator={this.state.validator} /> */ }
<Button>Login</Button>
<Message info>
Please contact <a href='mailto:support@jamoki.com'>support@jamoki.com</a> to request login credentials.
</Message>
</Form>
</StackLayout.Item>
<StackLayout.Item>
<ValidatedCheckbox label='Remember Me'
name='rememberMe' onChange={this.handleChange} validator={this.state.validator}
message='Should we keep you logged in on this computer?' className='login-checkbox' />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedButton className='submit' name='submit' content='Login'
submit validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<Text>
Please contact <Link to='mailto:support@jamoki.com'>support@jamoki.com</Link> to request login credentials.
</Text>
</StackLayout.Item>
</StackLayout>
</form>
<WaitDialog active={this.state.waitDialog} message='Logging In' />
@@ -121,7 +129,7 @@ export class Login extends React.Component {
title={this.state.messageDialog ? this.state.messageDialog.title : ''}
message={this.state.messageDialog ? this.state.messageDialog.message : ''}
onDismiss={this.handleMessageDialogDismiss} />
</Container>
</div>
)
}
}

View File

@@ -1,3 +0,0 @@
#login .login-options { margin: 1.5em 0 3em 0; }
#login .login-password { text-align: left; }
#login .login-checkbox { text-align: right; }

View File

@@ -1,7 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Container, Header, Form, Message } from 'semantic-ui-react'
import './ResetPassword.scss'
import { Text, StackLayout } from '../ui'
import { Validator, ValidatedInput, ValidatedButton } from '../Validated'
import { MessageDialog, WaitDialog } from '../Dialog'
import { api } from '../helpers'
@@ -62,23 +61,35 @@ export class ResetPassword extends React.Component {
render() {
return (
<Container className='password-reset-container'>
<Header content='Reset Password' size='large' />
<Form size='large' onSubmit={this.handleSubmit}>
<ValidatedInput label='New Password' password name='newPassword'
message='A new password, cannot be blank or the same as your old password'
width={16} validator={this.state.validator} />
<ValidatedInput label='Re-entered New Password' password name='reenteredNewPassword'
message='The new password again, must match and cannot be blank'
width={16} validator={this.state.validator} />
<Message info>
Passwords can contain special characters and are discouraged from being simple or reused from other sites or applications.
<br /><br />
Passwords must be at least 6 characters long.
</Message>
<ValidatedButton className='submit' name='submit' content='Submit'
primary submit validator={this.state.validator} />
</Form>
<div>
<form onSubmit={this.handleSubmit}>
<StackLayout>
<StackLayout.Item>
<Text size='large'>Reset Password</Text>
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='New Password' password name='newPassword'
message='A new password, cannot be blank or the same as your old password'
width={16} validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='Re-entered New Password' password name='reenteredNewPassword'
message='The new password again, must match and cannot be blank'
width={16} validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<Text>
Passwords can contain special characters and should be unique to this application.
<br /><br />
Passwords must be at least 6 characters long.
</Text>
</StackLayout.Item>
<StackLayout.Item>
<ValidatedButton className='submit' name='submit' content='Submit'
submit validator={this.state.validator} />
</StackLayout.Item>
</StackLayout>
</form>
<MessageDialog error open={!!this.state.messageDialog}
title={this.state.messageDialog ? this.state.messageDialog.title : ''}
@@ -87,7 +98,7 @@ export class ResetPassword extends React.Component {
<WaitDialog active={!!this.state.waitDialog}
message={this.state.waitDialog ? this.state.waitDialog.message : ''} />
</Container>
</div>
)
}
}

View File

@@ -1,23 +0,0 @@
.ui.container.password-reset-container {
height: 80vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.ui.container.password-reset-container .header {
border-bottom: 1px solid #d4d4d5;
width: 40%;
padding-bottom: 0.5em;
margin-bottom: 1em;
}
.ui.container.password-reset-container form {
width: 40%;
}
.ui.container.password-reset-container .message {
margin: 2em 0;
font-size: 0.8em;
}

View File

@@ -1,8 +1,8 @@
import React from 'react'
import PropTypes from 'prop-types'
import { autoBind } from 'auto-bind2'
import { Modal, Button, Icon, Header, Grid, Form } from 'semantic-ui-react'
import { ValidatedInput, ValidatedActionsButton, Validator } from '../Validated'
import { Modal, Button, Icon, StackLayout, Text } from '../ui'
import { ValidatedInput, ValidatedButton, Validator } from '../Validated'
import { regExpPattern } from 'regexp-pattern'
export class ChangeEmailDialog extends React.Component {
@@ -57,28 +57,26 @@ export class ChangeEmailDialog extends React.Component {
return (
<Modal dimmer='inverted' open={this.props.open} onClose={this.handleClose}
closeOnDimmerClick={false}>
<Header color='black' icon='edit' content='Change Email' />
<Modal.Content>
<Form className='user-form' id='emailForm' onSubmit={this.handleSubmit}>
<Grid>
<Grid.Column width={16}>
<Form.Group>
<ValidatedInput label='New Email' name='newEmail' width={16}
message='Your new email address, e.g. xyz@abc.com, cannot be blank'
validator={this.state.validator} />
</Form.Group>
</Grid.Column>
</Grid>
</Form>
</Modal.Content>
<Modal.Actions>
<ValidatedActionsButton primary submit form='emailForm' name='submit' validator={this.state.validator}>
<Icon name='checkmark' /> OK
</ValidatedActionsButton>
<Button color='red' onClick={this.handleClick}>
<Icon name='close' /> Cancel
</Button>
</Modal.Actions>
<form className='user-form' id='emailForm' onSubmit={this.handleSubmit}>
<StackLayout>
<StackLayout.Item>
<Text>Change Email</Text>
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='New Email' name='newEmail' width={16}
message='Your new email address, e.g. xyz@abc.com, cannot be blank'
validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedButton primary submit form='emailForm' name='submit' validator={this.state.validator}>
<Icon name='checkmark' /> OK
</ValidatedButton>
<Button color='red' onClick={this.handleClick}>
<Icon name='close' /> Cancel
</Button>
</StackLayout.Item>
</StackLayout>
</form>
</Modal>
)
}

View File

@@ -1,7 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import { autoBind } from 'auto-bind2'
import { Modal, Button, Icon, Header, Grid, Form } from 'semantic-ui-react'
import { Modal, Button, Icon, StackLayout, RowLayout, Text } from '../ui'
import { ValidatedInput, ValidatedActionsButton, Validator } from '../Validated'
export class ChangePasswordDialog extends React.Component {
@@ -64,38 +64,41 @@ export class ChangePasswordDialog extends React.Component {
render() {
return (
<Modal dimmer='inverted' open={this.props.open} onClose={this.handleClose}
closeOnDimmerClick={false}>
<Header color='black' icon='edit' content='Change Password' />
<Modal.Content>
<Form className='user-form' id='passwordForm' onSubmit={this.handleSubmit}>
<Grid stackable>
<Grid.Column width={16}>
<Form.Group>
<ValidatedInput label='Current Password' password name='oldPassword'
message='Your existing password, cannot be blank'
width={8} validator={this.state.validator} />
</Form.Group>
<Form.Group>
<ValidatedInput label='New Password' password name='newPassword'
message='A new password, cannot be blank or the same as your old password'
width={8} validator={this.state.validator} />
<ValidatedInput label='Re-entered New Password' password name='reenteredNewPassword'
message='The new password again, must match and cannot be blank'
width={8} validator={this.state.validator} />
</Form.Group>
</Grid.Column>
</Grid>
</Form>
</Modal.Content>
<Modal.Actions>
<ValidatedActionsButton primary submit form='passwordForm' name='submit' validator={this.state.validator}>
<Icon name='checkmark' /> OK
</ValidatedActionsButton>
<Button color='red' onClick={this.handleClick}>
<Icon name='close' /> Cancel
</Button>
</Modal.Actions>
<Modal dimmer='inverted' open={this.props.open} onClose={this.handleClose} closeOnDimmerClick={false}>
<form id='passwordForm' onSubmit={this.handleSubmit}>
<StackLayout.Item color='black' icon='edit'>
<Text size='large'>Change Password</Text>
</StackLayout.Item>
<StackLayout.Item>
<StackLayout>
<StackLayout.Item>
<ValidatedInput label='Current Password' password name='oldPassword'
message='Your existing password, cannot be blank'
width={8} validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='New Password' password name='newPassword'
message='A new password, cannot be blank or the same as your old password'
width={8} validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='Re-entered New Password' password name='reenteredNewPassword'
message='The new password again, must match and cannot be blank'
width={8} validator={this.state.validator} />
</StackLayout.Item>
</StackLayout>
</StackLayout.Item>
<StackLayout.Item>
<RowLayout>
<ValidatedActionsButton primary submit form='passwordForm' name='submit' validator={this.state.validator}>
<Icon name='checkmark' /> OK
</ValidatedActionsButton>
<Button color='red' onClick={this.handleClick}>
<Icon name='close' /> Cancel
</Button>
</RowLayout>
</StackLayout.Item>
</form>
</Modal>
)
}

View File

@@ -1,11 +1,10 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Modal, Button, Icon, Header } from 'semantic-ui-react'
import { Modal, Button, Icon, StackLayout, Text } from '../ui'
export class MessageDialog extends React.Component {
static propTypes = {
open: PropTypes.bool,
error: PropTypes.bool,
title: PropTypes.string.isRequired,
message: PropTypes.string.isRequired,
onDismiss: PropTypes.func
@@ -13,20 +12,20 @@ export class MessageDialog extends React.Component {
render() {
return (
<Modal dimmer='inverted' open={this.props.open} onClose={this.props.onDismiss}
closeOnDimmerClick={false}>
<Header
color={this.props.error ? 'red' : 'blue'}
icon={this.props.error ? 'warning circle' : 'info circle'}
content={this.props.title} />
<Modal.Content>
<h3>{this.props.message}</h3>
</Modal.Content>
<Modal.Actions>
<Button onClick={this.props.onDismiss}>
<Icon name='checkmark' /> OK
</Button>
</Modal.Actions>
<Modal open={this.props.open} onClose={this.props.onDismiss} closeOnDimmerClick={false}>
<StackLayout>
<StackLayout.Item>
<Text>{this.props.title}</Text>
</StackLayout.Item>
<StackLayout.Item>
<Text>{this.props.message}</Text>
</StackLayout.Item>
<StackLayout.Item>
<Button onClick={this.props.onDismiss}>
<Icon name='checkmark' /> OK
</Button>
</StackLayout.Item>
</StackLayout>
</Modal>
)
}

View File

@@ -1,7 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Dimmer, Button, Progress } from 'semantic-ui-react'
import './ProgressDialog.scss'
import { Dimmer, Button, Progress } from '../ui'
export class ProgressDialog extends React.Component {
static propTypes = {

View File

@@ -1,11 +0,0 @@
.progress-dialog {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
#progress {
width: 60%;
}

View File

@@ -1,6 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Dimmer, Loader } from 'semantic-ui-react'
import { Dimmer, Loader } from '../ui'
export class WaitDialog extends React.Component {
static propTypes = {
@@ -10,9 +10,61 @@ export class WaitDialog extends React.Component {
render() {
return (
<Dimmer inverted page active={this.props.active}>
<div style={style.dimmer}>
<Loader inverted size='massive'>{this.props.message}...</Loader>
</Dimmer>
</div>
)
}
}
import React from 'react';
import PropTypes from 'prop-types';
import { keyframes, css } from 'emotion';
import { onlyUpdateForKeys } from 'recompose';
// This returns an animation
const pulse = keyframes`
0% {transform: scale(1);opacity: 1}
45% {transform: scale(0.1);opacity: 0.7}
80% {transform: scale(1);opacity: 1}
`;
class Loader extends React.Component {
style = i => css`{
background-color: ${this.props.color};
width: ${this.props.size}px;
height: ${this.props.size}px;
margin: ${this.props.margin};
border-radius: 100%;
display: inline-block;
animation: ${pulse} 0.75s ${i * 0.12}s infinite cubic-bezier(.2,.68,.18,1.08);
animation-fill-mode: both;
}`;
render() {
return this.props.loading ?
<div>
<div className={this.style(1)} />
<div className={this.style(2)} />
<div className={this.style(3)} />
</div> : null;
}
}
Loader.propTypes = {
loading: PropTypes.bool,
color: PropTypes.string,
size: PropTypes.number,
margin: PropTypes.string
};
Loader.defaultProps = {
loading: true,
color: '#000000',
size: 15,
margin: '2px'
};
const Component = onlyUpdateForKeys(['loading', 'color', 'size', 'margin'])(Loader);
Component.defaultProps = Loader.defaultProps;
export default Component;

View File

@@ -1,7 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import './YesNoMessageDialog.scss'
import { Modal, Button, Icon, Header } from 'semantic-ui-react'
import { Modal, Button, StackLayout, Text, Icon } from '../ui'
export class YesNoMessageDialog extends React.Component {
static propTypes = {
@@ -17,20 +16,24 @@ export class YesNoMessageDialog extends React.Component {
render() {
return (
<Modal dimmer='inverted' open={this.props.open} onClose={this.onDismiss(false)}
<Modal open={this.props.open} onClose={this.onDismiss(false)}
closeOnDimmerClick={false} className='yes-no-modal'>
<Header color='orange' size='large' icon='warning circle' content={this.props.title} />
<Modal.Content>
<p>{this.props.message}</p>
</Modal.Content>
<Modal.Actions>
<Button negative onClick={this.onDismiss(false)}>
<Icon name='remove' /> No
</Button>
<Button positive onClick={this.onDismiss(true)}>
<Icon name='checkmark' /> Yes
</Button>
</Modal.Actions>
<StackLayout>
<StackLayout.Item color='orange'>
<Text>{this.props.title}</Text>
</StackLayout.Item>
<StackLayout.Item>
<Text>{this.props.message}</Text>
</StackLayout.Item>
<StackLayout.Item>
<Button negative onClick={this.onDismiss(false)}>
<Icon name='remove' /> No
</Button>
<Button positive onClick={this.onDismiss(true)}>
<Icon name='checkmark' /> Yes
</Button>
</StackLayout.Item>
</StackLayout>
</Modal>
)
}

View File

@@ -1,6 +0,0 @@
.yes-no-modal p {
font-size: 1.125em;
line-height: 1.6em;
width: 90%;
margin: auto;
}

View File

@@ -1,106 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Button, Header, Icon } from 'semantic-ui-react'
import { autoBind } from 'auto-bind2'
import './FilePicker.scss'
export class FilePicker extends React.Component {
static propTypes = {
validExtensions: PropTypes.arrayOf(PropTypes.string).isRequired, // Make sure these are lowercase
onFileSelect: PropTypes.func,
content: PropTypes.string,
horizontal: PropTypes.bool
}
constructor(props) {
super(props)
autoBind(this, (name) => (name.startsWith('handle')))
this.state = {
icon: 'none',
value: ''
}
this.counter = 0
}
handleDragEnter(e) {
this.counter++
this.setState({ icon: 'pending' })
}
handleDragLeave(e) {
this.counter--
if (this.counter === 0) {
this.setState({ icon: 'none' })
}
}
handleDragOver(e) {
e.preventDefault()
e.stopPropagation()
}
handleDragDrop(e) {
e.preventDefault()
const files = e.dataTransfer.files
if (files.length > 0) {
const file = files[0]
if (file) {
const fileName = file.name.toLowerCase()
const isValidFile = this.props.validExtensions.some((ext) => (fileName.endsWith(ext)))
this.setState({ icon: isValidFile ? 'valid' : 'invalid' })
this.counter = 0
if (isValidFile && this.props.onFileSelect) {
this.props.onFileSelect(file)
window.setTimeout(function() {
this.setState({ icon: 'none' })
}.bind(this), 1000)
}
}
}
}
handleOnFileChange(e) {
let file = e.currentTarget.files[0]
this.setState({ value: '' })
if (this.props.onFileSelect) {
this.props.onFileSelect(file)
}
}
render() {
return (
<div draggable id={this.props.horizontal ? 'holderHorizontal' : 'holderVertical'}
onDragOver={this.handleDragOver}
onDragEnter={this.handleDragEnter} onDragLeave={this.handleDragLeave}
onDrop={this.handleDragDrop}>
<input id='fileInput' type='file' onChange={this.handleOnFileChange} value={this.state.value} />
<Button as='label' htmlFor='fileInput' size={'medium'} type='browse' name='selectFile'
id='selectFile' content={this.props.content} icon='upload' primary />
{ this.props.horizontal
? (<Icon id='fileIconHorizontal'
name={'file' + ((this.state.icon === 'none' || this.state.icon === 'pending') ? ' outline' : '')}
size='huge'
color={this.state.icon === 'valid' ? 'green' : this.state.icon === 'invalid' ? 'red' : 'grey'}
style={this.state.icon === 'pending' ? { transform: 'scale(1.5)' } : {}} />)
: (<Header as='h3' color='grey' icon>
OR
<Header.Subheader>
Drag-and-drop the file here
</Header.Subheader>
<Icon id='fileIconVertical' className=''
name={'file' + ((this.state.icon === 'none' || this.state.icon === 'pending') ? ' outline' : '')}
size='huge'
color={this.state.icon === 'valid' ? 'green' : this.state.icon === 'invalid' ? 'red' : 'grey'}
style={this.state.icon === 'pending' ? { transform: 'scale(1.5)' } : {}} />
</Header>)
}
</div>
)
}
}

View File

@@ -1,51 +0,0 @@
#holderVertical {
border: 3px dashed lightgray;
text-align: center;
border-radius: 0.5em;
display: flex;
flex-direction: column;
align-items: center;
padding: 0.25em 1.25em;
width: auto;
overflow: hidden;
}
#holderHorizontal {
border: 3px dashed lightgray;
text-align: center;
border-radius: 0.5em;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 0.25em 1.25em;
width: auto;
}
#helpText {
height: 2em;
margin-top: 2em;
margin-bottom: 2em;
color: lightgray;
}
#fileIconVertical {
margin-top: 0.5em;
margin-bottom: 0.5em;
transition: all 0.3s ease;
}
#fileIconHorizontal {
margin-left: 0.3em;
transition: all 0.3s ease;
}
#selectFile {
margin-top: 1.5em;
margin-bottom: 1.5em;
white-space: nowrap;
}
#fileInput {
display: none;
}

View File

@@ -1 +0,0 @@
export { FilePicker } from './FilePicker'

View File

@@ -1,5 +1,4 @@
import React from 'react'
import { Container } from 'semantic-ui-react'
import { ProfileForm } from './ProfileForm'
import { Constants, api } from '../helpers'
import { WaitDialog, MessageDialog, ChangePasswordDialog, ProgressDialog, ChangeEmailDialog } from '../Dialog'
@@ -147,7 +146,7 @@ export class Profile extends React.Component {
render() {
return (
<Container>
<div>
<ProfileForm
user={this.state.user}
onSaved={this.handleSaved}
@@ -171,7 +170,7 @@ export class Profile extends React.Component {
message={this.state.progressDialog ? this.state.progressDialog.message : ''}
percent={this.state.uploadPercent}
onCancel={this.handleUploadCancel} />
</Container>
</div>
)
}
}

View File

@@ -1,11 +1,8 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Grid, Form, Image } from 'semantic-ui-react'
import { StackLayout, Button } from '../ui'
import { regExpPattern } from 'regexp-pattern'
import './ProfileForm.scss'
import { Constants } from '../helpers'
import { FilePicker } from '../FilePicker'
import { Validator, ValidatedInput, ValidatedDropdown, ValidatedButton, ValidatedDatePicker } from '../Validated'
import { Validator, ValidatedInput, ValidatedButton } from '../Validated'
export class ProfileForm extends React.Component {
static propTypes = {
@@ -13,9 +10,7 @@ export class ProfileForm extends React.Component {
onSaved: PropTypes.func.isRequired,
onModifiedChanged: PropTypes.func,
onChangePassword: PropTypes.func,
onChangeEmail: PropTypes.func,
onSelectImage: PropTypes.func,
userImageUrl: PropTypes.string
onChangeEmail: PropTypes.func
}
static validations = {
@@ -99,72 +94,32 @@ export class ProfileForm extends React.Component {
render() {
return (
<Form className='profile-form' onSubmit={this.handleSubmit}>
<Grid stackable>
<Grid.Column width={3}>
<Image id='userImage' shape='circular' size='medium' src={this.props.userImageUrl} centered />
<FilePicker validExtensions={['.jpg', '.jpeg', '.png']} content='Select Image' onFileSelect={this.props.onSelectImage} />
</Grid.Column>
<Grid.Column width={13}>
<Form.Group>
<ValidatedInput label='First Name' name='firstName' width={8}
validator={this.state.validator} />
<ValidatedInput label='Last Name' name='lastName' width={8}
validator={this.state.validator} />
</Form.Group>
<Form.Group>
<ValidatedInput label='Email' name='email' width={8} message='Required. Must be a valid email address.'
validator={this.state.validator} />
<Form.Button fluid content={'Change Email'} label='&nbsp;'
width={4} onClick={this.props.onChangeEmail} />
<Form.Button fluid content={'Change Password'} label='&nbsp;'
width={4} onClick={this.props.onChangePassword} />
</Form.Group>
<Form.Group>
<ValidatedInput label='Zip' name='zip' width={4}
validator={this.state.validator} message='5 Character U.S. Zip Code. Optional.' />
<ValidatedDropdown label='State' name='state' width={6} message='Type or select a U.S. State or Province.'
placeholder='Select State' options={Constants.stateOptions}
validator={this.state.validator} searchable />
<ValidatedInput label='City' name='city' width={6}
validator={this.state.validator} message='U.S. City. Optional.' />
</Form.Group>
<Form.Group>
<ValidatedInput label='Address' name='address1' width={12}
validator={this.state.validator} message='Primary Street Address. Optional.' />
<ValidatedInput label='Apt. #' name='address2' width={4}
validator={this.state.validator} message='Apartment/Unit number. Optional.' />
</Form.Group>
<Form.Group>
<ValidatedInput label='Home Phone' name='homePhone' width={8}
validator={this.state.validator} message='A valid U.S. phone number. IE: (555)123-4567. Optional.' />
<ValidatedInput label='Cell Phone' name='cellPhone' width={8}
validator={this.state.validator} message='A valid U.S. phone number. IE: (555)123-4567. Optional.' />
</Form.Group>
<Form.Group>
<ValidatedDatePicker label='Date of Birth' name='dateOfBirth' width={5}
validator={this.state.validator} message='Select a date.' />
<ValidatedInput label='SSN' name='ssn' width={6}
validator={this.state.validator} message='U.S. Social Security Number. IE: 123-45-6789' />
<ValidatedDatePicker label='Hire Date' name='dateOfHire' width={5}
validator={this.state.validator} message='Select a date.' />
</Form.Group>
<Form.Group>
<Form.Field width={12} />
<ValidatedButton submit primary width={4} size='medium' content='Save' label='&nbsp;' name='save'
validator={this.state.validator} />
</Form.Group>
</Grid.Column>
</Grid>
</Form>
<form className='profile-form' onSubmit={this.handleSubmit}>
<StackLayout stackable>
<StackLayout.Item>
<ValidatedInput label='First Name' name='firstName' width={8}
validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='Last Name' name='lastName' width={8}
validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='Email' name='email' width={8} message='Required. Must be a valid email address.'
validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<Button fluid content={'Change Email'} label='&nbsp;'
width={4} onClick={this.props.onChangeEmail} />
<Button fluid content={'Change Password'} label='&nbsp;'
width={4} onClick={this.props.onChangePassword} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedButton submit primary width={4} size='medium' content='Save' label='&nbsp;' name='save'
validator={this.state.validator} />
</StackLayout.Item>
</StackLayout>
</form>
)
}
}

View File

@@ -1,12 +0,0 @@
.profile-form {
text-align: left;
margin: 3em auto 4em auto;
}
.profile-form > .fields {
margin-bottom: 1.5em !important;
}
#userImage {
margin-bottom: 2em;
}

View File

@@ -2,11 +2,10 @@ import React from 'react'
import PropTypes from 'prop-types'
import { autoBind } from 'auto-bind2'
import { regExpPattern } from 'regexp-pattern'
import { Grid, Form } from 'semantic-ui-react'
import './UserForm.scss'
import { ValidatedEmailIcon } from './ValidatedEmailIcon'
import { Constants, api } from '../helpers'
import { Validator, ValidatedInput, ValidatedButton, ValidatedDropdown, ValidatedDatePicker, ValidatedContainer } from '../Validated'
import { Validator, ValidatedInput, ValidatedButton, ValidatedCheckbox } from '../Validated'
import { StackLayout } from '../ui'
export class UserForm extends React.Component {
static propTypes = {
@@ -144,87 +143,43 @@ export class UserForm extends React.Component {
render() {
return (
<Form className='user-form' onSubmit={this.handleSubmit}>
<Grid stackable>
<Grid.Column width={16}>
<Form.Group>
<ValidatedDropdown label={'Deighton Access & Security Level'} width={6} selection
options={Constants.accessLevels} name='role' message='The user role and security level'
placeholder='' validator={this.state.validator} />
</Form.Group>
<Form.Group>
<ValidatedInput label='First Name' name='firstName'
width={8} validator={this.state.validator} />
<ValidatedInput label='Last Name' name='lastName'
width={8} validator={this.state.validator} />
</Form.Group>
<Form.Group>
<ValidatedInput label='Email' name='email' width={8} message='Must be a valid email address. Required.'
validator={this.state.validator} />
<ValidatedEmailIcon name='emailValidated' validator={this.state.validator} width={4}
onClick={this.handleResendEmail} />
<ValidatedButton width={4} size='medium' content='Change Email' label='&nbsp;' name='changeEmail'
validator={this.state.validator} onClick={this.handleChangeEmail} />
</Form.Group>
<form onSubmit={this.handleSubmit}>
<StackLayout>
<StackLayout.Item>
<ValidatedCheckbox label={'Deighton Access & Security Level'} width={6} selection
options={Constants.accessLevels} name='role' message='The user role and security level'
placeholder='' validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='First Name' name='firstName'
width={8} validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='Last Name' name='lastName'
width={8} validator={this.state.validator} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedInput label='Email' name='email' width={8} message='Must be a valid email address. Required.'
validator={this.state.validator} />
<ValidatedEmailIcon name='emailValidated' validator={this.state.validator} width={4}
onClick={this.handleResendEmail} />
</StackLayout.Item>
<StackLayout.Item>
<ValidatedButton width={4} size='medium' content='Change Email' label='&nbsp;' name='changeEmail'
validator={this.state.validator} onClick={this.handleChangeEmail} />
</StackLayout.Item>
<ValidatedContainer name='standard-fields' validator={this.state.validator}>
<Form.Group>
<ValidatedInput label='Zip' width={4} name='zip' message='5 Character U.S. Zip Code. Optional.'
position='bottom center' validator={this.state.validator} />
<ValidatedDropdown label='State' name='state' width={4}
placeholder='Select State' options={Constants.stateOptions} validator={this.state.validator} searchable />
<ValidatedInput label='City' width={8} type='text' name='city' message='U.S. City. Optional.'
validator={this.state.validator} />
</Form.Group>
<Form.Group>
<ValidatedInput label='Address' width={12} name='address1'
validator={this.state.validator} message='Primary Street Address. Optional.' />
<ValidatedInput label='Apt. #' width={4} name='address2'
validator={this.state.validator} message='Apartment/Unit number. Optional.' />
</Form.Group>
<Form.Group>
<ValidatedInput label='Home Phone' width={8} name='homePhone'
validator={this.state.validator} message='A valid U.S. phone number. IE: (555)123-4567. Optional.' />
<ValidatedInput label='Cell Phone' width={8} name='cellPhone'
validator={this.state.validator} message='A valid U.S. phone number. IE: (555)123-4567. Optional.' />
</Form.Group>
<Form.Group>
<ValidatedDatePicker label='Date of Birth' width={5} name='dateOfBirth'
validator={this.state.validator} />
<ValidatedInput label='SSN' width={6} name='ssn'
validator={this.state.validator} message='U.S. Social Security Number. IE: 123-45-6789' />
<ValidatedDatePicker label='Hire Date' width={5} name='dateOfHire'
validator={this.state.validator} />
</Form.Group>
</ValidatedContainer>
<ValidatedContainer name='broker-fields' validator={this.state.validator}>
<Form.Group>
<ValidatedInput label='# Households' width={5} name='numHouseholds'
message='Number of households in this brokers account' validator={this.state.validator} />
<ValidatedInput label='T-12' width={6} name='t12' message='This brokers T-12 info.'
validator={this.state.validator} />
<ValidatedInput label='AUM' width={5} name='aum'
message='This brokers AUM information.' validator={this.state.validator} />
</Form.Group>
</ValidatedContainer>
<Form.Group>
<ValidatedButton color='red' width={4} size='medium' content='Remove' label='&nbsp;' name='remove'
validator={this.state.validator} onClick={this.props.onRemove} />
<ValidatedButton width={4} size='medium' content='Reset' label='&nbsp;' name='reset'
validator={this.state.validator} onClick={this.handleReset} />
<Form.Field width={this.state.validator._id ? 8 : 12} />
<ValidatedButton primary submit width={4} size='medium'
content={this.state.validator._id ? 'Save' : 'Add'} label='&nbsp;' name='submit'
validator={this.state.validator} />
</Form.Group>
</Grid.Column>
</Grid>
</Form>
<StackLayout.Item>
<ValidatedButton color='red' width={4} size='medium' content='Remove' label='&nbsp;' name='remove'
validator={this.state.validator} onClick={this.props.onRemove} />
<ValidatedButton width={4} size='medium' content='Reset' label='&nbsp;' name='reset'
validator={this.state.validator} onClick={this.handleReset} />
<ValidatedButton primary submit width={4} size='medium'
content={this.state.validator._id ? 'Save' : 'Add'} label='&nbsp;' name='submit'
validator={this.state.validator} />
</StackLayout.Item>
</StackLayout>
</form>
)
}
}

View File

@@ -1,6 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Dropdown, List, Icon, Button, Image } from 'semantic-ui-react'
import { Dropdown, List, Icon, Button, Image } from '../ui'
import { Constants, api } from '../helpers'
import './UserList.scss'

View File

@@ -1,10 +1,10 @@
import React from 'react'
import { Container, Grid } from 'semantic-ui-react'
import { autoBind } from 'auto-bind2'
import { UserList } from './UserList'
import { UserForm } from './UserForm'
import { UserFormPlaceholder } from './UserFormPlaceholder'
import { api } from '../helpers'
import { RowLayout } from '../ui'
import { YesNoMessageDialog, MessageDialog, ChangeEmailDialog, WaitDialog } from '../Dialog'
export class Users extends React.Component {
@@ -237,19 +237,19 @@ export class Users extends React.Component {
render() {
return (
<Container>
<div>
<div>Users</div>
<Grid stackable>
<RowLayout>
{/* User List - Displayed on left hand side. */}
<Grid.Column width={5}>
<RowLayout.Item width={5}>
<UserList users={this.state.users} selectedUser={this.state.selectedUser}
selectionModified={this.state.modified} onUserListClick={this.handleUserListClick}
onAddNewUser={this.handleAddNewUser} />
</Grid.Column>
</RowLayout.Item>
{/* User Info - Displayed on right hand side. */}
<Grid.Column width={11}>
<RowLayout.Item>
{
this.state.selectedUser
? <UserForm user={this.state.selectedUser} onSave={this.handleSave}
@@ -257,8 +257,8 @@ export class Users extends React.Component {
onChangeEmail={this.handleChangeEmail} onResendEmail={this.handleResendEmail} />
: <UserFormPlaceholder />
}
</Grid.Column>
</Grid>
</RowLayout.Item>
</RowLayout>
<ChangeEmailDialog open={!!this.state.changeEmailDialog} onDismiss={this.handleChangeEmailDismiss} />
@@ -275,7 +275,7 @@ export class Users extends React.Component {
onDismiss={this.handleMessageDialogDismiss} />
<WaitDialog active={!!this.state.waitDialog} message={this.state.waitDialog ? this.state.waitDialog.message : ''} />
</Container>
</div>
)
}
}

View File

@@ -1,6 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Form, Icon, Popup, Button } from 'semantic-ui-react'
import { Label, Button, Icon } from '../ui'
import './ValidatedEmailIcon.scss'
// This is a validated component with a value that cannot change itself and is specialized
@@ -27,20 +27,19 @@ export class ValidatedEmailIcon extends React.Component {
render() {
if (this.state.value) {
return (
<Form.Field width={this.props.width}>
<label>&nbsp;</label>
<Popup content='Email Validated' position='bottom center' hoverable trigger={
<div width={this.props.width}>
<Label>&nbsp;
<Icon name='mail' color='green' size='big' className='mail-validated-icon' />
} />
</Form.Field>
</Label>
</div>
)
} else {
return (
<Form.Field width={this.props.width}>
<label>&nbsp;</label>
<div width={this.props.width}>
<Label>&nbsp;</Label>
<Button fluid icon='mail outline' color='red' labelPosition='left'
content='Resend Email' onClick={this.props.onClick} disabled={this.state.disabled} />
</Form.Field>
</div>
)
}
}

View File

@@ -1,6 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Button } from 'semantic-ui-react'
import { Button } from '../ui'
export class ValidatedActionsButton extends React.Component {
static propTypes = {

View File

@@ -1,6 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Form, Button } from 'semantic-ui-react'
import { Button } from '../ui'
export class ValidatedButton extends React.Component {
static propTypes = {
@@ -46,13 +46,15 @@ export class ValidatedButton extends React.Component {
render() {
if (this.state.visible) {
return (
<Form.Field width={this.props.width} disabled={this.state.disabled}>
<div width={this.props.width} disabled={this.state.disabled}>
<label>{this.props.label}</label>
<Button fluid color={this.props.color} primary={this.props.primary}
<Button color={this.props.color} primary={this.props.primary}
type={this.props.submit ? 'submit' : 'button'} onClick={this.props.onClick}
content={this.props.content} size={this.props.size} name={this.props.name}
floated={this.props.floated} />
</Form.Field>
size={this.props.size} name={this.props.name}
floated={this.props.floated}>
{this.props.content}
</Button>
</div>
)
} else {
return null

View File

@@ -1,7 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Form } from 'semantic-ui-react'
import { Checkbox } from '../ui'
import { Checkbox, Label } from '../ui'
// This is an example of a validated component with a value that can change itself, that cannot ever be invalid.
@@ -38,9 +37,10 @@ export class ValidatedCheckbox extends React.Component {
render() {
return (
<Form.Field width={this.props.width} disabled={this.state.disabled} className={this.props.className}>
<Checkbox value={!!this.state.value} name={this.props.name} label={this.props.label} />
</Form.Field>
<Label width={this.props.width} disabled={this.state.disabled} className={this.props.className}>
<Checkbox value={!!this.state.value} name={this.props.name} />
{this.props.label}
</Label>
)
}
}

View File

@@ -1,6 +1,5 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Container } from 'semantic-ui-react'
export class ValidatedContainer extends React.Component {
static propTypes = {
@@ -41,9 +40,9 @@ export class ValidatedContainer extends React.Component {
render() {
if (this.state.visible) {
return (
<Container>
<div>
{this.props.children}
</Container>
</div>
)
} else {
return null

View File

@@ -1,56 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Form, Popup } from 'semantic-ui-react'
import 'moment'
import { DatePickerInput } from 'rc-datepicker'
import 'rc-datepicker/lib/style.css'
export class ValidatedDatePicker extends React.Component {
static propTypes = {
name: PropTypes.string.isRequired,
message: PropTypes.string.isRequired,
label: PropTypes.string,
width: PropTypes.number,
validator: PropTypes.object.isRequired
}
constructor(props) {
super(props)
this.state = props.validator.getField(props.name)
this.handleChange = this.handleChange.bind(this)
this.handleClear = this.handleClear.bind(this)
}
handleChange(e, data) {
const { validator, name } = this.props
const state = validator.getField(name)
if (!state.readOnly && !state.disabled) {
// NOTE: data is a little different for this control - no value property
this.setState(validator.updateValue(name, data))
}
}
handleClear(e) {
this.props.validator.updateValue(this.props.name, '')
this.setState(this.props.validator.getField(this.props.name))
}
componentWillReceiveProps(nextProps) {
if (nextProps.validator !== this.props.validator) {
this.setState(nextProps.validator.getField(nextProps.name))
}
}
render() {
return (
<Form.Field error={!this.state.valid} width={this.props.width} disabled={this.state.disabled}>
<label>{this.props.label}</label>
<Popup content={this.props.message} position='right center' hoverable trigger={
<DatePickerInput value={this.state.value} name={this.props.name} onChange={this.handleChange}
showOnInputClick onClear={this.handleClear} />} />
</Form.Field>
)
}
}

View File

@@ -1,6 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Form, Dropdown, Popup } from 'semantic-ui-react'
import { Dropdown, Text } from '../ui'
export class ValidatedDropdown extends React.Component {
static propTypes = {
@@ -35,13 +35,13 @@ export class ValidatedDropdown extends React.Component {
render() {
return (
<Form.Field error={!this.state.valid} width={this.props.width}>
<div error={!this.state.valid} width={this.props.width}>
<label>{this.props.label}</label>
<Popup content={this.props.message} position='right center' hoverable trigger={
<Dropdown selection fluid disabled={this.state.disabled} readOnly={this.state.readOnly}
placeholder={this.props.placeholder} options={this.props.options}
value={this.state.value} onChange={this.handleChange} search={this.props.searchable} />} />
</Form.Field>
<Dropdown selection disabled={this.state.disabled} readOnly={this.state.readOnly}
placeholder={this.props.placeholder} options={this.props.options}
value={this.state.value} onChange={this.handleChange} search={this.props.searchable} />
<Text>{this.props.message}</Text>
</div>
)
}
}

View File

@@ -1,7 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Form } from 'semantic-ui-react'
import { Input } from '../ui'
import { Input, Label, Text } from '../ui'
// This is an example of a validated component with a value that changes itself
@@ -13,10 +12,7 @@ export class ValidatedInput extends React.Component {
width: PropTypes.number,
validator: PropTypes.object.isRequired,
password: PropTypes.bool,
className: PropTypes.string,
placeholder: PropTypes.string,
icon: PropTypes.string,
iconPosition: PropTypes.string
placeholder: PropTypes.string
}
constructor(props) {
@@ -43,17 +39,17 @@ export class ValidatedInput extends React.Component {
render() {
return (
<Form.Field error={!this.state.valid} width={this.props.width} disabled={this.state.disabled} className={this.props.className}>
<label>{this.props.label}</label>
<Input value={this.state.value}
hidden={this.props.password}
name={this.props.name}
onChange={this.handleChange}
placeholder={this.props.placeholder}
className={this.props.className} icon={this.props.icon}
iconPosition={this.props.iconPosition} />
<label>{this.props.message}</label>
</Form.Field>
<div width={this.props.width} disabled={this.state.disabled}>
<Label>{this.props.label}<br />
<Input value={this.state.value}
password={this.props.password}
name={this.props.name}
onChange={this.handleChange}
placeholder={this.props.placeholder} />
</Label>
<br />
<Text size='small'>{this.props.message}</Text>
</div>
)
}
}

View File

@@ -3,6 +3,5 @@ export { ValidatedInput } from './ValidatedInput'
export { ValidatedButton } from './ValidatedButton'
export { ValidatedActionsButton } from './ValidatedActionsButton'
export { ValidatedDropdown } from './ValidatedDropdown'
export { ValidatedDatePicker } from './ValidatedDatePicker'
export { ValidatedCheckbox } from './ValidatedCheckbox'
export { ValidatedContainer } from './ValidatedContainer'

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 320.002 320.002" style="enable-background:new 0 0 320.002 320.002;" xml:space="preserve">
<g id="XMLID_6_">
<path id="XMLID_7_" d="M51.213,175.001h173.785c8.284,0,15-6.716,15-15c0-8.284-6.716-15-15-15H51.213l19.394-19.394
c5.858-5.858,5.858-15.355,0-21.213c-5.857-5.858-15.355-5.858-21.213,0L4.396,149.393c-0.351,0.351-0.683,0.719-0.997,1.103
c-0.137,0.167-0.256,0.344-0.385,0.515c-0.165,0.22-0.335,0.435-0.488,0.664c-0.14,0.209-0.261,0.426-0.389,0.64
c-0.123,0.206-0.252,0.407-0.365,0.619c-0.118,0.22-0.217,0.446-0.323,0.67c-0.104,0.219-0.213,0.435-0.306,0.659
c-0.09,0.219-0.164,0.442-0.243,0.664c-0.087,0.24-0.179,0.477-0.253,0.722c-0.067,0.222-0.116,0.447-0.172,0.672
c-0.063,0.249-0.133,0.497-0.183,0.751c-0.051,0.259-0.082,0.521-0.119,0.782c-0.032,0.223-0.075,0.443-0.097,0.669
c-0.048,0.484-0.073,0.971-0.074,1.457c0,0.007-0.001,0.015-0.001,0.022c0,0.007,0.001,0.015,0.001,0.022
c0.001,0.487,0.026,0.973,0.074,1.458c0.022,0.223,0.064,0.44,0.095,0.661c0.038,0.264,0.069,0.528,0.121,0.79
c0.05,0.252,0.119,0.496,0.182,0.743c0.057,0.227,0.107,0.456,0.175,0.681c0.073,0.241,0.164,0.474,0.248,0.71
c0.081,0.226,0.155,0.453,0.247,0.675c0.091,0.22,0.198,0.431,0.3,0.646c0.108,0.229,0.21,0.46,0.33,0.685
c0.11,0.205,0.235,0.4,0.354,0.599c0.131,0.221,0.256,0.444,0.4,0.659c0.146,0.219,0.309,0.424,0.466,0.635
c0.136,0.181,0.262,0.368,0.407,0.544c0.299,0.364,0.616,0.713,0.947,1.048c0.016,0.016,0.029,0.034,0.045,0.05l45,45.001
c2.93,2.929,6.768,4.394,10.607,4.394c3.838-0.001,7.678-1.465,10.606-4.393c5.858-5.858,5.858-15.355,0.001-21.213L51.213,175.001
z"/>
<path id="XMLID_8_" d="M305.002,25h-190c-8.284,0-15,6.716-15,15v60c0,8.284,6.716,15,15,15s15-6.716,15-15V55h160v210.001h-160
v-45.001c0-8.284-6.716-15-15-15s-15,6.716-15,15v60.001c0,8.284,6.716,15,15,15h190c8.284,0,15-6.716,15-15V40
C320.002,31.716,313.286,25,305.002,25z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 210 210" style="enable-background:new 0 0 210 210;" xml:space="preserve">
<g id="XMLID_12_">
<path id="XMLID_13_" d="M195,0h-20c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V15
C210,6.716,203.284,0,195,0z"/>
<path id="XMLID_14_" d="M115,0H95c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V15
C130,6.716,123.284,0,115,0z"/>
<path id="XMLID_15_" d="M35,0H15C6.716,0,0,6.716,0,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V15
C50,6.716,43.284,0,35,0z"/>
<path id="XMLID_16_" d="M195,160h-20c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15v-20
C210,166.716,203.284,160,195,160z"/>
<path id="XMLID_17_" d="M115,160H95c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15v-20
C130,166.716,123.284,160,115,160z"/>
<path id="XMLID_18_" d="M35,160H15c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15v-20
C50,166.716,43.284,160,35,160z"/>
<path id="XMLID_19_" d="M195,80h-20c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V95
C210,86.716,203.284,80,195,80z"/>
<path id="XMLID_20_" d="M115,80H95c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V95
C130,86.716,123.284,80,115,80z"/>
<path id="XMLID_21_" d="M35,80H15C6.716,80,0,86.716,0,95v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V95
C50,86.716,43.284,80,35,80z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,9 +1,8 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { App } from './App'
import './index.scss'
ReactDOM.render(
<App />,
<App style={{ minHeight: '100vh', position: 'relative' }} />,
document.getElementById('root')
)

View File

@@ -1,6 +0,0 @@
@import '~semantic-ui-css/semantic.min.css';
body #root {
min-height: 100vh;
position: relative;
}

View File

@@ -1,16 +1,18 @@
import { colorInfo, fontInfo } from './style'
export default {
base: {
borderRadius: '10px',
fontFamily: 'Arial',
color: '#ffffff',
fontFamily: fontInfo.family,
color: '#FFFFFF',
fontSize: '20px',
background: '#3498db',
background: colorInfo.buttonBackgroundHover,
padding: '10px 20px 10px 20px',
textDecoration: 'none',
outline: 'none',
':hover': {
background: '#3cb0fd',
background: colorInfo.buttonBackground,
textDecoration: 'none'
}
}

View File

@@ -1,8 +1,10 @@
import { colorInfo } from './style'
export default {
checkbox: {
cursor: 'pointer',
position: 'relative',
backgroundColor: '#2196F3',
backgroundColor: colorInfo.buttonBackground,
top: 0,
left: 0,
height: 25,

View File

@@ -0,0 +1,19 @@
import Radium from 'radium'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import style from './Input.style'
class Dropdown extends Component {
static propTypes = {
password: PropTypes.bool,
children: PropTypes.node
}
render() {
return (
<input type={this.props.password ? 'password' : 'text'} style={style.base}>{this.props.children}</input>
)
}
}
export default Radium(Dropdown)

View File

@@ -0,0 +1,2 @@
export default {
}

View File

@@ -0,0 +1,28 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
// See https://www.flaticon.com/packs/web-button-compilation for more icons
export default class Icon extends Component {
static propTypes = {
name: PropTypes.string.isRequired,
size: PropTypes.number,
margin: PropTypes.number
}
static defaultProps = {
size: 50,
margin: 5,
name: 'shapes'
}
static svgs = {
logout: require('icons/logout.svg'),
shapes: require('icons/shapes.svg')
}
render() {
return <img style={{ width: this.props.size, height: this.props.size, margin: this.props.margin }}
src={Icon.svgs[this.props.name]} />
}
}

View File

@@ -0,0 +1,20 @@
import Radium from 'radium'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
class Image extends Component {
static propTypes = {
source: PropTypes.string,
width: PropTypes.number,
height: PropTypes.number,
margin: PropTypes.number
}
render() {
return (
<img src={this.props.source} style={{ width: this.props.width, height: this.props.height, margin: this.props.margin }} />
)
}
}
export default Radium(Image)

View File

@@ -5,13 +5,13 @@ import style from './Input.style'
class Input extends Component {
static propTypes = {
hidden: PropTypes.bool,
password: PropTypes.bool,
children: PropTypes.node
}
render() {
return (
<input type={this.props.hidden ? 'password' : 'text'} style={style.base}>{this.props.children}</input>
<input type={this.props.password ? 'password' : 'text'} style={style.base}>{this.props.children}</input>
)
}
}

33
website/src/ui/Label.js Normal file
View File

@@ -0,0 +1,33 @@
import Radium from 'radium'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { fontInfo } from './style'
class Label extends Component {
static propTypes = {
size: PropTypes.string,
color: PropTypes.string,
margin: PropTypes.number,
children: PropTypes.node
}
static defaultProps = {
size: 'medium',
color: 'normal',
margin: 0
}
render() {
return (
<label style={{
display: 'inline-block',
fontSize: fontInfo.size[this.props.size],
color: fontInfo.color[this.props.color],
fontFamily: fontInfo.family,
margin: this.props.margin
}}>{this.props.children}</label>
)
}
}
export default Radium(Label)

30
website/src/ui/Link.js Normal file
View File

@@ -0,0 +1,30 @@
import Radium from 'radium'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { fontInfo } from './style'
class Link extends Component {
static propTypes = {
to: PropTypes.string,
size: PropTypes.string,
margin: PropTypes.number,
children: PropTypes.node
}
static defaultProps = {
size: 'medium',
margin: 0
}
render() {
return (
<a href={this.props.to} style={{
fontSize: fontInfo.size[this.props.size],
fontFamily: fontInfo.family,
margin: this.props.margin
}}>{this.props.children}</a>
)
}
}
export default Radium(Link)

30
website/src/ui/List.js Normal file
View File

@@ -0,0 +1,30 @@
import Radium from 'radium'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { fontInfo } from './style'
class List extends Component {
static propTypes = {
size: PropTypes.string,
margin: PropTypes.number,
children: PropTypes.node
}
static defaultProps = {
size: 'medium',
margin: 0
}
render() {
return (
<span style={{
display: 'inline-block',
fontSize: fontInfo.size[this.props.size],
fontFamily: fontInfo.family,
margin: this.props.margin
}}>{this.props.children}</span>
)
}
}
export default Radium(List)

51
website/src/ui/Loader.js Normal file
View File

@@ -0,0 +1,51 @@
import React from 'react';
import PropTypes from 'prop-types';
import { keyframes, css } from 'emotion';
import { onlyUpdateForKeys } from 'recompose';
// This returns an animation
const pulse = keyframes`
0% {transform: scale(1);opacity: 1}
45% {transform: scale(0.1);opacity: 0.7}
80% {transform: scale(1);opacity: 1}
`;
class Loader extends React.Component {
style = i => css`{
background-color: ${this.props.color};
width: ${this.props.size}px;
height: ${this.props.size}px;
margin: ${this.props.margin};
border-radius: 100%;
display: inline-block;
animation: ${pulse} 0.75s ${i * 0.12}s infinite cubic-bezier(.2,.68,.18,1.08);
animation-fill-mode: both;
}`;
render() {
return this.props.loading ?
<div>
<div className={this.style(1)} />
<div className={this.style(2)} />
<div className={this.style(3)} />
</div> : null;
}
}
Loader.propTypes = {
loading: PropTypes.bool,
color: PropTypes.string,
size: PropTypes.number,
margin: PropTypes.string
};
Loader.defaultProps = {
loading: true,
color: '#000000',
size: 15,
margin: '2px'
};
const Component = onlyUpdateForKeys(['loading', 'color', 'size', 'margin'])(Loader);
Component.defaultProps = Loader.defaultProps;
export default Component;

29
website/src/ui/Modal.js Normal file
View File

@@ -0,0 +1,29 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import style from './Modal.style'
import { reactAutoBind } from 'auto-bind2'
export class Modal extends Component {
static propTypes = {
children: PropTypes.node
}
constructor(props) {
super(props)
reactAutoBind(this)
}
preventPropagation(e) {
e.stopPropagation()
}
render() {
return (
<div style={style.dimmer} onClick={this.preventPropagation}>
<div style={style.modal}>
{this.props.children}
</div>
</div>
)
}
}

View File

@@ -0,0 +1,28 @@
export default {
dimmer: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '100vh',
width: '100vw',
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 100,
background: 'rgba(25, 25, 30, 0.75)'
},
modal: {
zIndex: 101,
background: '#FFFFFF',
margin: 0,
padding: '18px 24px',
width: '80%',
border: '1px solid $border-primary',
borderRadius: 4,
boxShadow: '0 0 25px #000000'
}
}

View File

@@ -0,0 +1,31 @@
import Radium from 'radium'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class RowLayout extends Component {
static propTypes = {
children: PropTypes.node,
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]).isRequired
}
render() {
return (
<div style={{ display: 'flex', minWidth: this.props.width, flexDirection: 'row' }}>{this.props.children}</div>
)
}
}
RowLayout.Item = Radium(class RowLayoutItem extends Component {
static propTypes = {
children: PropTypes.node,
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ])
}
render() {
return (
<div style={[ this.props.width ? { minWidth: this.props.width } : { flexGrow: 1 } ]}>{this.props.children}</div>
)
}
})
export default Radium(RowLayout)

View File

@@ -0,0 +1,31 @@
import Radium from 'radium'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class StackLayout extends Component {
static propTypes = {
children: PropTypes.node,
height: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]).isRequired
}
render() {
return (
<div style={{ display: 'flex', minHeight: this.props.height, flexDirection: 'column' }}>{this.props.children}</div>
)
}
}
StackLayout.Item = Radium(class StackLayoutItem extends Component {
static propTypes = {
children: PropTypes.node,
height: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ])
}
render() {
return (
<div style={[ this.props.height ? { minHeight: this.props.height } : { flexGrow: 1 } ]}>{this.props.children}</div>
)
}
})
export default Radium(StackLayout)

View File

@@ -0,0 +1,30 @@
import Radium from 'radium'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { fontInfo } from './style'
class Text extends Component {
static propTypes = {
size: PropTypes.string,
margin: PropTypes.number,
children: PropTypes.node
}
static defaultProps = {
size: 'medium',
margin: 0
}
render() {
return (
<span style={{
display: 'inline-block',
fontSize: fontInfo.size[this.props.size],
fontFamily: fontInfo.family,
margin: this.props.margin
}}>{this.props.children}</span>
)
}
}
export default Radium(Text)

View File

@@ -1,4 +1,16 @@
export { default as Button } from './Button'
export { default as Checkbox } from './Checkbox'
export { default as Input } from './Input'
export { default as Image } from './Image'
export { default as Text } from './Text'
export { default as Link } from './Link'
export { default as Label } from './Label'
export { default as Icon } from './Icon'
export { default as List } from './List'
export { default as Dropdown } from './Dropdown'
export { default as Modal } from './Modal'
export { default as Dimmer } from './Dimmer'
export { default as Loader } from './Loader'
export { default as HolyGrail } from './HolyGrail'
export { default as RowLayout } from './RowLayout'
export { default as StackLayout } from './StackLayout'

19
website/src/ui/style.js Normal file
View File

@@ -0,0 +1,19 @@
export const colorInfo = {
text: '#000000',
alertText: '#FF0000',
buttonBackground: '#3498DB',
buttonBackgroundHover: '#3CB0FD'
}
export const fontInfo = {
family: 'Hind, sans-serif', // https://fonts.google.com/specimen/Hind?selection.family=Hind
size: {
small: '10pt',
medium: '12pt',
large: '14pt'
},
color: {
'normal': colorInfo.text,
'alert': colorInfo.alertText
}
}

View File

@@ -1,5 +1,5 @@
export class VersionInfo {
static version = '0.0.4'
static fullVersion = '0.0.4-20171018.0'
static startYear = '2017'
export const versionInfo = {
version: '0.1.0',
fullVersion: '0.1.0-20180225.0',
startYear: '2017'
}