summaryrefslogtreecommitdiff
path: root/animism-align/frontend/common
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2020-07-22 14:05:15 +0200
committerJules Laplace <julescarbon@gmail.com>2020-07-22 14:05:15 +0200
commitef78bc6a084f92b4794e987b5832240d85b6479e (patch)
treeb314b630800db6aa60f28ef0b115625e6ca176db /animism-align/frontend/common
parent85d4cb9addf9ca887d3440b2786665d67d9917c4 (diff)
refactor app using babel module-resolver
Diffstat (limited to 'animism-align/frontend/common')
-rw-r--r--animism-align/frontend/common/app.css354
-rw-r--r--animism-align/frontend/common/copyToClipboardButton.component.js24
-rw-r--r--animism-align/frontend/common/fonts.css55
-rw-r--r--animism-align/frontend/common/form.component.js222
-rw-r--r--animism-align/frontend/common/form.css327
-rw-r--r--animism-align/frontend/common/imageCrop.component.js41
-rw-r--r--animism-align/frontend/common/index.js31
-rw-r--r--animism-align/frontend/common/loader.css125
-rw-r--r--animism-align/frontend/common/menubutton.component.js133
-rw-r--r--animism-align/frontend/common/miscellaneous.component.js82
-rw-r--r--animism-align/frontend/common/miscellaneous.css18
-rw-r--r--animism-align/frontend/common/modal.component.js9
-rw-r--r--animism-align/frontend/common/modal.css20
-rw-r--r--animism-align/frontend/common/slider.component.js115
-rw-r--r--animism-align/frontend/common/table.component.js128
-rw-r--r--animism-align/frontend/common/table.css96
-rw-r--r--animism-align/frontend/common/tableIndex.component.js129
-rw-r--r--animism-align/frontend/common/upload.css26
-rw-r--r--animism-align/frontend/common/upload.helpers.js192
-rw-r--r--animism-align/frontend/common/uploadImage.component.js74
20 files changed, 0 insertions, 2201 deletions
diff --git a/animism-align/frontend/common/app.css b/animism-align/frontend/common/app.css
deleted file mode 100644
index 362b933..0000000
--- a/animism-align/frontend/common/app.css
+++ /dev/null
@@ -1,354 +0,0 @@
-* { box-sizing: border-box; }
-html, body {
- margin: 0;
- padding: 0;
- width: 100%;
- height: 100%;
-}
-body {
- background: #000;
- color: #ddd;
- overflow: hidden;
- font-family: 'Roboto', sans-serif;
- font-size: 0.875rem;
- height: 100%;
- width: 100%;
-}
-.gray {
- color: #888;
-}
-
-/* layout */
-
-.container {
- height: 100%;
- width: 100%;
-}
-.app {
- /*display: flex;*/
- height: 100%;
- width: 100%;
-}
-.app > div {
- display: flex;
- flex-direction: column;
- height: 100%;
- width: 100%;
-}
-.app .body {
- display: flex;
- flex-direction: row;
- flex-grow: 1;
- position: relative;
- height: 100%;
- width: 100%;
-}
-
-.row {
- display: flex;
- flex-direction: row;
- justify-content: flex-start;
- align-items: flex-start;
-}
-.row > div {
- margin-right: 1.5rem;
-}
-.row > div:last-child {
- margin-right: 0;
-}
-
-
-.row.menubar {
- background: #324;
- padding: 0.5rem;
- justify-content: flex-end;
- margin-bottom: 1rem;
-}
-.menubar > :first-child {
- flex: 1;
-}
-
-/* lists */
-
-ul {
- margin: 0.75rem 0;
-}
-li {
- line-height: 1.5;
-}
-
-/* headings */
-
-h1 {
- color: #eee;
- margin-bottom: 1.25rem;
- font-size: 1.5rem;
- font-weight: normal;
-}
-div:first-child > h1:first-child,
-.menuButtons + div > h1:first-child {
- margin-top: 0;
-}
-h2 {
- color: #eee;
- font-size: 1.25rem;
- font-weight: normal;
-}
-h3 {
- color: #eee;
- margin-top: 0;
- margin-bottom: 1.25rem;
- font-size: 1.0rem;
- font-weight: normal;
-}
-p {
- margin: 1.25rem 0;
- line-height: 1.5;
-}
-.byline {
- color: #888;
- font-size: 0.75rem;
- margin-top: 0.25rem;
- margin-bottom: 1.25rem;
-}
-
-/* links */
-
-b {
- color: #fff;
-}
-a {
- text-decoration: underline;
- color: #8df;
-}
-
-/* menu button */
-
-.menuButtons {
- width: 3.5rem;
- min-height: 18rem;
- padding: 0 1.0rem 0 1.0rem;
-}
-.menuButton {
- position: relative;
- text-align: center;
- text-transform: uppercase;
- font-size: 0.625rem;
- color: #ddd;
- text-decoration: none;
- cursor: pointer;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- width: 2.5rem;
- margin-bottom: 0.75rem;
-}
-.menuButton .icon {
- background-color: #101;
- width: 2.5rem;
- height: 2.5rem;
- border: 1px solid;
- border-color: #888;
- margin-bottom: 0.3rem;
- display: flex;
- justify-content: center;
- align-items: center;
- transition: border-color 0.1s;
- border-radius: 0.125rem;
-}
-.menuButton svg {
- width: 80%;
- fill: #888;
-}
-.menuButton:hover .icon {
- background-color: #000;
- border-color: #fff;
-}
-.menuButton:hover svg {
- fill: #fff;
-}
-
-.menuButton.small {
- width: 2.0rem;
- margin-bottom: 0;
- margin-right: 0.1875rem;
-}
-.menuButton.small .icon {
- border: 0;
- border-color: #888;
- margin-bottom: 0;
- width: 2.0rem;
- height: 2.0rem;
- border-radius: 0.0625rem;
-}
-.menuButton.small svg {
- fill: #888;
- width: 1.75rem;
- height: 1.75rem;
-}
-.menuButton.small .icon:hover {
- border-color: #11f;
- background-color: #11f;
-}
-.menuButton.small:hover svg {
- fill: #fff;
-}
-.results.th .menuButton.small {
- width: 1.5rem;
-}
-.results.th .menuButton.small .icon {
- width: 1.5rem;
- height: 1.5rem;
-}
-.results.th .menuButton.small svg {
- width: 1.25rem;
- height: 1.25rem;
-}
-
-.menuButton.small.active .icon {
- border-color: #11f;
- background-color: #11f;
-}
-.menuButton.small.active svg {
- fill: #fff;
-}
-.menuButton.small.active:hover .icon {
- border-color: #fff;
- background-color: #11f;
-}
-.menuButton.small.active:hover svg {
- fill: #fff;
-}
-
-/* rows - like a table */
-
-.rows {
- width: 100%;
-}
-.rows .row {
- width: 100%;
-}
-.rows .row:nth-of-type(2n+1) {
- background: #f8f8f8;
-}
-.rows .row:nth-of-type(2n+2) {
- background: #eeeeee;
-}
-.rows .row:hover {
- background: #d8d8d8;
-}
-.rows .row > div,
-.rows .row a > div {
- padding: 0.75rem;
- overflow: hidden;
- text-overflow: ellipsis;
- margin: 0;
-}
-.rows .row div.title {
- width: 10rem;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-.rows .row div.string,
-.rows .row div.str {
- min-width: 6rem;
-}
-.rows .row div.bool {
- width: 4rem;
- overflow: visible;
- text-align: center;
-}
-.rows .row div.color {
- width: 4rem;
- overflow: visible;
- text-align: center;
-}
-.rows .row div.date {
- min-width: 10rem;
-}
-.rows .row div.int,
-.rows .row div.float {
- text-align: right;
- min-width: 6rem;
-}
-.rows .row.heading div.int,
-.rows .row.heading div.float {
- text-align: center;
-}
-.rows .row div.text {
- flex: 1;
- max-width: 20rem;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-.rows .row.heading div {
- text-transform: capitalize;
- font-weight: bold;
- background: #f8f8f8;
-}
-.rows .row.heading:hover {
- background: #f8f8f8;
-}
-
-/* misc ui */
-
-pre, code, .license {
- font-family: Menlo, monospace;
- font-size: 0.75rem;
- line-height: 2;
-}
-.swatch {
- display: inline-block;
- width: 0.75rem;
- height: 0.75rem;
- border: 1px solid #333;
-}
-.dot {
- display: inline-block;
- width: 0.5rem;
- height: 0.5rem;
- border-radius: 50%;
-}
-.light {
- color: #888;
-}
-.pill {
- display: inline-block;
- padding: 0.125rem;
- width: 2.5rem;
- text-align: center;
- border-radius: 0.5rem;
- font-size: 0.75rem;
- text-transform: uppercase;
- font-weight: bold;
-}
-.pill.yes {
- background: #11f;
- color: #fff;
-}
-.pill.no {
- color: #ccc;
- border: 1px solid;
-}
-
-/* columns (of tags) */
-
-.form .columnCells {
- padding-top: 0.25rem
-}
-.columnCells .column {
- margin-top: 0.25rem;
-}
-.columnCells .column > div {
- max-width: 100%;
- padding: 0 0.375rem 0.375rem 0;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-.columnCells .selected {
- color: #11f;
-} \ No newline at end of file
diff --git a/animism-align/frontend/common/copyToClipboardButton.component.js b/animism-align/frontend/common/copyToClipboardButton.component.js
deleted file mode 100644
index cfe7103..0000000
--- a/animism-align/frontend/common/copyToClipboardButton.component.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React, { Component } from 'react';
-import { writeToClipboard } from '../util'
-
-export default class CopyToClipboardButton extends Component {
- state = {
- copied: false,
- }
-
- handleClick() {
- writeToClipboard(this.props.data)
- this.setState({ copied: true })
- }
-
- render() {
- return (
- <button
- className={this.state.copied ? 'copyButton copied' : 'copyButton'}
- onClick={this.handleClick.bind(this)}
- >
- {this.state.copied ? 'Copied!' : 'Copy'}
- </button>
- )
- }
-}
diff --git a/animism-align/frontend/common/fonts.css b/animism-align/frontend/common/fonts.css
deleted file mode 100644
index c782885..0000000
--- a/animism-align/frontend/common/fonts.css
+++ /dev/null
@@ -1,55 +0,0 @@
-@font-face {
- font-family: 'Roboto';
- src: url('/static/fonts/Roboto-Bold.ttf') format('truetype');
- font-weight: bold;
-}
-@font-face {
- font-family: 'Roboto';
- src: url('/static/fonts/Roboto-BoldItalic.ttf') format('truetype');
- font-weight: bold;
- font-style: italic;
-}
-/*
-@font-face {
- font-family: 'Roboto';
- src: url('/static/fonts/Roboto-Light.ttf') format('truetype');
- font-weight: 100;
-}
-@font-face {
- font-family: 'Roboto';
- src: url('/static/fonts/Roboto-LightItalic.ttf') format('truetype');
- font-weight: 100;
-}
-*/
-@font-face {
- font-family: 'Roboto';
- src: url('/static/fonts/Roboto-Medium.ttf') format('truetype');
- font-weight: 300;
-}
-@font-face {
- font-family: 'Roboto';
- src: url('/static/fonts/Roboto-MediumItalic.ttf') format('truetype');
- font-style: italic;
- font-weight: 300;
-}
-@font-face {
- font-family: 'Roboto';
- src: url('/static/fonts/Roboto-Regular.ttf') format('truetype');
-}
-@font-face {
- font-family: 'Roboto';
- src: url('/static/fonts/Roboto-Italic.ttf') format('truetype');
- font-style: italic;
-}
-/*
-@font-face {
- font-family: 'Roboto';
- src: url('/static/fonts/Roboto-Thin.ttf') format('truetype');
- font-weight: 100;
-}
-@font-face {
- font-family: 'Roboto';
- src: url('/static/fonts/Roboto-ThinItalic.ttf') format('truetype');
- font-weight: 100;
-}
-*/ \ No newline at end of file
diff --git a/animism-align/frontend/common/form.component.js b/animism-align/frontend/common/form.component.js
deleted file mode 100644
index c38a299..0000000
--- a/animism-align/frontend/common/form.component.js
+++ /dev/null
@@ -1,222 +0,0 @@
-import React, { Component } from 'react';
-import { courtesyS } from '../util'
-
-export const TextInput = props => (
- <label className={props.error ? 'error' : 'text'}>
- {props.title && <span>{props.title}</span>}
- <input
- type="text"
- required={props.required}
- onChange={props.onChange}
- onBlur={props.onBlur}
- name={props.name}
- value={props.data[props.name] || ""}
- placeholder={props.placeholder}
- autoComplete={props.autoComplete}
- />
- </label>
-)
-
-export const LabelDescription = props => (
- <label className={props.className ? 'text description ' + props.className : 'text description'}>
- <span>{props.title}</span>
- <span>{props.children}</span>
- </label>
-)
-
-export const NumberInput = props => (
- <label className={props.error ? 'error' : 'text'}>
- <span>{props.title}</span>
- <input
- type="number"
- required={props.required}
- onChange={props.onChange}
- name={props.name}
- value={props.data[props.name]}
- min={props.min}
- max={props.max}
- step={props.step || 1}
- />
- </label>
-)
-
-export const ColorInput = props => (
- <label className={props.error ? 'error color' : 'text color'}>
- <span>{props.title}</span>
- <input
- type="color"
- required={props.required}
- onChange={props.onChange}
- name={props.name}
- value={props.data[props.name]}
- />
- <input
- type="text"
- required={props.required}
- onChange={props.onChange}
- name={props.name}
- value={props.data[props.name]}
- />
- </label>
-)
-
-export const TextArea = props => (
- <label className={props.error ? 'textarea error' : 'textarea'}>
- {props.title && <span>{props.title}</span>}
- <textarea
- onChange={props.onChange}
- name={props.name}
- placeholder={props.placeholder}
- value={props.data[props.name]}
- />
- </label>
-)
-
-export const Checkbox = props => (
- <label className="checkbox">
- <input
- type="checkbox"
- name={props.name}
- value={1}
- checked={props.checked}
- onChange={(e) => props.onChange(props.name, e.target.checked)}
- />
- <span>{props.label}</span>
- </label>
-)
-
-export const Radio = props => {
- return (
- <label className="radio">
- <input
- type="radio"
- name={props.name}
- value={props.value}
- checked={props.value === props.currentValue}
- onChange={() => props.onChange(props.name, props.value)}
- />
- <span>{props.label}</span>
- </label>
- )
-}
-
-export class Select extends Component {
- state = {
- focused: false,
- }
-
- render() {
- const { name, selected, options, defaultOption, title, loading, onChange, className } = this.props
- if (loading) {
- return <label className='select'><div>Loading...</div></label>
- }
- const { focused } = this.state
- return (
- <label>
- {title && <span>{title}</span>}
- <div className={(focused ? 'select focus' : 'select') + " " + (className || "")}>
- <div>{(options.find(opt => String(opt.name) === String(selected)) || {label: defaultOption}).label}</div>
- <select
- onFocus={() => this.setState({ focused: true })}
- onBlur={() => this.setState({ focused: false })}
- onChange={e => {
- onChange(name, e.target.value)
- // this.setState({ focused: false })
- }}
- value={selected || "__default__"}
- >
- {!selected && defaultOption && <option value="__default__">{defaultOption}</option>}
- {options.map((option, i) => (
- <option
- key={option.name}
- value={option.name}
- disabled={option.disabled}
- >{option.label}</option>
- ))}
- </select>
- </div>
- </label>
- )
- }
-}
-
-export class FileInputField extends Component {
- state = {
- count: 0,
- }
-
- handleChange(files) {
- const { multiple, onChange } = this.props
- if (!files) {
- this.setState({ count: 0 })
- } else {
- this.setState({ count: multiple ? files.length : 0 })
- }
- onChange(files)
- }
-
- render() {
- const { error, title, label, required, multiple, mime, name } = this.props
- return (
- <label className={error ? 'error' : 'text fileInput'}>
- <span>{title}</span>
- <div className="row">
- <button>
- {label || (multiple ? "Choose files" : "Choose file")}
- <FileInput
- mime={mime}
- multiple={multiple}
- onChange={this.handleChange.bind(this)}
- />
- </button>
- {!!this.state.count && <span>{courtesyS(this.state.count, "file")}{" selected"}</span>}
- </div>
- </label>
- )
- }
-}
-
-export class FileInput extends Component {
- handleChange(e) {
- let { multiple, mime } = this.props
- if (!mime) {
- mime = "image/"
- }
- const files = e.dataTransfer ? e.dataTransfer.files : e.target.files
- let i
- let file, selectedFiles = []
- for (i = 0; i < files.length; i++) {
- file = files[i]
- if (file && file.type.indexOf(mime) === 0) {
- if (multiple) {
- selectedFiles.push(file)
- } else {
- break
- }
- }
- }
- if (multiple && selectedFiles.length) {
- this.props.onChange(selectedFiles)
- } else if (!multiple && file) {
- this.props.onChange(file)
- } else {
- this.props.onChange()
- }
- }
-
- render() {
- return (
- <input type="file" multiple={!!this.props.multiple} onChange={this.handleChange.bind(this)} />
- )
- }
-}
-
-export const SubmitButton = (props) => (
- <label>
- <span></span>
- <button
- className={props.className ? "submit " + props.className : "submit"}
- onClick={props.onClick}
- >{props.title}</button>
- </label>
-)
diff --git a/animism-align/frontend/common/form.css b/animism-align/frontend/common/form.css
deleted file mode 100644
index bbee27e..0000000
--- a/animism-align/frontend/common/form.css
+++ /dev/null
@@ -1,327 +0,0 @@
-/* label */
-
-label {
- display: flex;
- min-width: 10rem;
- flex-direction: row;
- justify-content: flex-start;
- align-items: center;
- cursor: pointer;
-}
-
-.label {
- display: flex;
- min-width: 10rem;
- flex-direction: row;
- justify-content: flex-start;
- align-items: flex-start;
- cursor: pointer;
-}
-
-/* form (stock forms) */
-
-form label,
-form .label {
- width: 100%;
- margin-bottom: 0.5rem;
-}
-form label span,
-form .label > span {
- display: inline-block;
- min-width: 8rem;
- padding: 0.5rem 0;
-}
-form label.textarea {
- align-items: flex-start;
-}
-form input[type="checkbox"] {
- margin: -0.0625rem 0.625rem 0 8rem;
-}
-
-/* form errors */
-
-form .error span {
- color: #f11;
-}
-form .error input[type=text],
-form .error input[type=number],
-form .error input[type=password] {
- border-color: #f11;
-}
-
-/* form field descriptions */
-
-form label.description {
- cursor: normal;
- font-size: small;
- color: #ddd;
-}
-form label.description span {
- padding-top: 0;
-}
-
-/* text input */
-
-input[type=text],
-input[type=number],
-input[type=password] {
- padding: 0.5rem;
- border: 1px solid #ddd;
- color: #fff;
- background: #111;
- font-family: 'Roboto', sans-serif;
- font-size: 0.875rem;
- width: 15rem;
- border-radius: 0.125rem;
-}
-
-input[type=text]:focus,
-input[type=number]:focus,
-input[type=password]:focus {
- border: 1px solid #84f;
- background: #000;
-}
-
-textarea {
- width: 20rem;
- height: 10rem;
- padding: 0.5rem;
- border: 1px solid #ddd;
- font-family: 'Roboto', sans-serif;
- background: #111;
- color: #fff;
- font-size: 0.875rem;
- line-height: 1.3;
- border-radius: 0.125rem;
-}
-textarea:focus {
- border: 1px solid #84f;
- background: #000;
-}
-
-/* checkbox */
-
-input[type=checkbox] {
- position: relative;
- display: block;
- width: 0.75rem;
- height: 0.75rem;
- margin-right: 0.625rem;
- cursor: pointer;
- outline: 0;
-}
-input[type=checkbox] + span {
- font-size: 0.825rem;
- text-transform: uppercase;
- color: #ddd;
-}
-input[type=checkbox]:hover + span {
- color: #fff;
-}
-input[type=checkbox]:focus + span {
- color: #fff;
-}
-input[type="checkbox"]:checked + span {
- color: #fff;
-}
-input[type="checkbox"]:focus:checked + span {
- color: #fff;
-}
-
-input[type="checkbox"]:after {
- position: relative;
- display: block;
- left: 0;
- width: 0.75rem;
- height: 0.75rem;
- border: 0.0625rem solid #ddd;
- content: "";
- background-color: #fff;
- background-repeat: no-repeat;
- background-position: center;
- cursor: pointer;
- transition: background-color 0.1s;
- border-radius: 0.125rem;
-}
-input[type=checkbox]:focus:after {
- border-color: #84f;
-}
-input[type="checkbox"]:checked:after {
- border-color: #84f;
- background-color: #84f;
- background-image: url(/static/img/check.svg);
- background-size: cover;
-}
-
-/* select */
-
-.select {
- position: relative;
- width: 9rem;
- min-width: auto;
- background: #111;
- border-radius: 0.125rem;
- border: 1px solid #ddd;
- padding: 0.5rem;
- overflow: hidden;
- text-overflow: ellipsis;
- margin-right: 1.25rem;
- cursor: pointer;
-}
-.select select {
- position: absolute;
- top: 0; left: 0;
- width: 100%; height: 100%;
- opacity: 0;
- cursor: pointer;
-}
-.select:after {
- content: '';
- position: absolute;
- top: 50%;
- right: 0.375rem;
- transform: translateY(-0.125rem);
- width: 0;
- height: 0;
- border-left: 0.375rem solid transparent;
- border-right: 0.375rem solid transparent;
- border-top: 0.375rem solid #ddd;
-}
-.select.focus {
- border-color: #84f;
- background: #000;
-}
-.select.focus:after {
- border-top-color: #84f;
-}
-.select:hover {
- background-color: #000;
-}
-.select div {
- width: calc(100% - 1.025rem);
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.select.wide {
- width: 20rem;
-}
-
-/* button */
-
-button {
- position: relative;
- background: #333;
- border-radius: 0.125rem;
- color: #ddd;
- border: 1px solid;
- padding: 0.5rem;
- overflow: hidden;
- text-overflow: ellipsis;
- font-family: 'Roboto', sans-serif;
- font-size: 0.875rem;
- cursor: pointer;
- /*text-transform: uppercase;*/
- transition: all 0.1s;
-}
-button:hover {
- background-color: #000;
- border-color: #fff;
-}
-button.process {
- padding-left: 1.5rem;
-}
-button.process:after {
- content: '';
- position: absolute;
- top: 50%;
- left: 0.625rem;
- transform: translateY(-0.375rem);
- width: 0;
- height: 0;
- border-top: 0.375rem solid transparent;
- border-bottom: 0.375rem solid transparent;
- border-left: 0.375rem solid #888;
-}
-button.process:focus:after {
- border-left-color: #84f;
-}
-button:focus {
- background: #000;
- border-color: #fff;
- color: #fff;
- outline: 0;
-}
-button:disabled {
- background: #eee;
- color: #888;
- border-color: #bbb;
- pointer-events: none;
-}
-button:disabled:after {
- border-left-color: #aaa;
-}
-.buttons button {
- margin-right: 0.75rem;
-}
-.buttons button:last-child {
- margin-right: 0;
-}
-button.submit {
- border-color: #d8f;
- color: #fff;
- background: #111;
-}
-button.submit:focus,
-button.submit:hover {
- border-color: #fff;
- color: #fff;
- background: #222;
-}
-button.submit.destroy {
- background-color: rgba(16,16,16,0.5);
- border-color: #b11;
- color: #d11;
-}
-button.submit.destroy:focus,
-button.submit.destroy:hover {
- background: #000;
- border-color: #f33;
- color: #f33;
-}
-
-/* file upload, should always be inside a container */
-
-input[type=file] {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- opacity: 0;
- cursor: pointer;
-}
-::-webkit-file-upload-button { cursor: pointer; }
-.fileInput > .row {
- align-items: center;
-}
-.fileInput > .row > span {
- padding-left: 1rem;
-}
-
-/* copy button */
-
-.copyButton {
- border-color: transparent;
- color: #84f;
- font-size: 0.675rem;
- padding: 0.25rem;
- margin-left: 0.25rem;
-}
-.desktop .copyButton:hover {
- border-color: #84f;
-}
-.copyButton.copied {
- color: #84f;
-} \ No newline at end of file
diff --git a/animism-align/frontend/common/imageCrop.component.js b/animism-align/frontend/common/imageCrop.component.js
deleted file mode 100644
index 9cae850..0000000
--- a/animism-align/frontend/common/imageCrop.component.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import React, { Component } from 'react';
-import { cropImage } from '../util'
-
-export default class ImageCrop extends Component {
- state = {
- cropURL: null
- }
-
- componentDidMount() {
- const { url, crop } = this.props
- this.crop(url, crop)
- }
-
- componentDidUpdate(prevProps) {
- const { url, crop } = this.props
- if (this.props.crop !== prevProps.crop) {
- cropImage(url, crop).then(canvas =>{
- const cropURL = canvas.toDataURL('image/jpeg', 0.8)
- this.setState({ cropURL })
- })
- }
- }
-
- crop(url, crop) {
- cropImage(url, crop).then(canvas =>{
- const cropURL = canvas.toDataURL('image/jpeg', 0.8)
- this.setState({ cropURL })
- })
- }
-
-
- render() {
- const { cropURL } = this.state
- if (!cropURL) {
- return null
- }
- return (
- <img src={cropURL} className='preview' />
- )
- }
-}
diff --git a/animism-align/frontend/common/index.js b/animism-align/frontend/common/index.js
deleted file mode 100644
index 0678a93..0000000
--- a/animism-align/frontend/common/index.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// export { default as Header } from './header.component'
-export {
- MenuButton, SmallMenuButton, MenuRoute,
-} from './menubutton.component'
-export {
- Select, Checkbox, Radio, FileInput, FileInputField,
- TextInput, NumberInput, TextArea, SubmitButton,
- LabelDescription, ColorInput,
-} from './form.component'
-export {
- Loader, Swatch, Dot, Columns, Statistic, Detections, Progress
-} from './miscellaneous.component'
-export { default as TableIndex } from './tableIndex.component'
-export {
- TableObject, TableArray, TableTuples,
- TableRow, TableCell
-} from './table.component'
-export { default as CopyToClipboardButton } from './copyToClipboardButton.component'
-export { default as ImageCrop } from './imageCrop.component'
-export { Modal } from './modal.component'
-export { default as UploadImage } from './uploadImage.component'
-export { default as Slider } from './slider.component'
-
-import './fonts.css'
-import './app.css'
-import './form.css'
-import './loader.css'
-import './table.css'
-import './modal.css'
-import './miscellaneous.css'
-import './upload.css'
diff --git a/animism-align/frontend/common/loader.css b/animism-align/frontend/common/loader.css
deleted file mode 100644
index f047e8e..0000000
--- a/animism-align/frontend/common/loader.css
+++ /dev/null
@@ -1,125 +0,0 @@
-
-@keyframes L_circle_rotate {
- 0% {
- transform: rotate(0deg);
- }
- 100% {
- transform: rotate(360deg);
- }
-}
-@keyframes L_stroke_rotate {
- 0% {
- transform: rotate(0deg);
- }
- 100% {
- transform: rotate(1080deg);
- }
-}
-@keyframes L_stroke_fix {
- 0% {
- transform: rotate(0deg);
- }
- 50% {
- transform: rotate(135deg);
- }
- 100% {
- transform: rotate(270deg);
- }
-}
-@keyframes L_stroke_left_grow {
- 0% {
- transform: rotate(-5deg);
- }
- 50% {
- transform: rotate(-140deg);
- }
- 100% {
- transform: rotate(-5deg);
- }
-}
-@keyframes L_stroke_right_grow {
- 0% {
- transform: rotate(5deg);
- }
- 50% {
- transform: rotate(140deg);
- }
- 100% {
- transform: rotate(5deg);
- }
-}
-.circular-loader .stroke::before, .circular-loader .stroke-right::before, .circular-loader .stroke-left::before {
- content: "";
- display: block;
-}
-
-.circular-loader, .circular-loader .stroke, .circular-loader .stroke::before, .circular-loader .stroke-right, .circular-loader .stroke-right::before, .circular-loader .stroke-left, .circular-loader .stroke-left::before {
- width: 2em;
- height: 2em;
- box-sizing: border-box;
- border-radius: 50%;
-}
-
-.circular-loader .stroke::before, .circular-loader .stroke-right::before, .circular-loader .stroke-left::before {
- border-style: solid;
- border-width: 0.21429em;
- border-color: #778;
-}
-
-.circular-loader .stroke-right, .circular-loader .stroke-left::before {
- position: absolute;
- clip: rect(0 2em 2em 1em);
-}
-.circular-loader .stroke-right::before, .circular-loader .stroke-left {
- position: absolute;
- clip: rect(0 1em 2em 0);
-}
-.circular-loader .stroke::before {
- position: absolute;
- clip: rect(0 1.05em 1em 0.95em);
-}
-
-/**/
-.circular-loader {
- animation: L_circle_rotate 1568.23529ms linear infinite both;
-}
-.circular-loader .stroke::before,
-.circular-loader .stroke-right, .circular-loader .stroke-left {
- animation: L_stroke_fix 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
-}
-.circular-loader .stroke {
- animation: L_stroke_rotate 5332ms steps(4) infinite both;
-}
-.circular-loader .stroke-right::before {
- animation: L_stroke_right_grow 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
-}
-.circular-loader .stroke-left::before {
- animation: L_stroke_left_grow 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
-}
-@keyframes color_K {
- 0%, 15% {
- border-color: #44444f;
- }
- 25%, 40% {
- border-color: #bbbbc7;
- }
- 50%, 65% {
- border-color: #66666f;
- }
- 75%, 90% {
- border-color: #ccccd4;
- }
- 100% {
- border-color: #44444f;
- }
-}
-.circular-loader.color .stroke::before {
- animation: L_stroke_fix 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, color_K 5332ms linear infinite both;
-}
-.circular-loader.color .stroke-right::before {
- animation: L_stroke_right_grow 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, color_K 5332ms linear infinite both;
-}
-.circular-loader.color .stroke-left::before {
- animation: L_stroke_left_grow 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, color_K 5332ms linear infinite both;
-}
-
diff --git a/animism-align/frontend/common/menubutton.component.js b/animism-align/frontend/common/menubutton.component.js
deleted file mode 100644
index a4eea39..0000000
--- a/animism-align/frontend/common/menubutton.component.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import React, { Component } from 'react'
-import { Route, Link } from 'react-router-dom'
-import { history } from '../store'
-
-const icons = {
- upload: {
- title: 'Upload',
- image: '/static/img/add.svg',
- // svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>,
- // svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M9,16V10H5L12,3L19,10H15V16H9M5,20V18H19V20H5Z" /></svg>
- // svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9,10V16H15V10H19L12,3L5,10H9M12,5.8L14.2,8H13V14H11V8H9.8L12,5.8M19,18H5V20H19V18Z" /></svg>
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0,0h24v24H0V0z"/><path d="M19,12v7H5v-7H3v7c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-7H19z M11,6.83L8.41,9.41L7,8l5-5l5,5l-1.41,1.41L13,6.83v9.67h-2 V6.83z"/></svg>,
- },
- new: {
- title: 'New',
- image: '/static/img/add.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>,
- // svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M9,16V10H5L12,3L19,10H15V16H9M5,20V18H19V20H5Z" /></svg>,
- // svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9,10V16H15V10H19L12,3L5,10H9M12,5.8L14.2,8H13V14H11V8H9.8L12,5.8M19,18H5V20H19V18Z" /></svg>
- },
- save: {
- title: 'Export',
- image: '/static/img/save.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M19 12v7H5v-7H3v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-7h-2zm-6 .67l2.59-2.58L17 11.5l-5 5-5-5 1.41-1.41L11 12.67V3h2v9.67z"/></svg>,
- },
- saved: {
- title: 'Saved',
- image: '/static/img/folder.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M9.17 6l2 2H20v10H4V6h5.17M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg>,
- },
- recent: {
- title: 'Recent',
- image: '/static/img/history.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.25 2.52.77-1.28-3.52-2.09V8z"/></svg>,
- },
- random: {
- title: 'Random',
- image: '/static/img/random.svg',
- // svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z"/></svg>,
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/><circle cx="7.5" cy="16.5" r="1.5"/><circle cx="7.5" cy="7.5" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="16.5" cy="16.5" r="1.5"/><circle cx="16.5" cy="7.5" r="1.5"/></svg>
- },
- menu: {
- title: 'Menu',
- image: '/static/img/menu.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></svg>,
- },
- list: {
- title: 'List',
- image: '/static/img/view_list.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path opacity=".87" fill="none" d="M0 0h24v24H0V0z"/><path d="M3 5v14h17V5H3zm4 2v2H5V7h2zm-2 6v-2h2v2H5zm0 2h2v2H5v-2zm13 2H9v-2h9v2zm0-4H9v-2h9v2zm0-4H9V7h9v2z"/></svg>,
- },
- edit: {
- title: 'Edit',
- image: '/static/img/edit.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M14.06 9.02l.92.92L5.92 19H5v-.92l9.06-9.06M17.66 3c-.25 0-.51.1-.7.29l-1.83 1.83 3.75 3.75 1.83-1.83c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.2-.2-.45-.29-.71-.29zm-3.6 3.19L3 17.25V21h3.75L17.81 9.94l-3.75-3.75z"/></svg>
- },
- delete: {
- title: 'Delete',
- image: '/static/img/delete.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7z"/></svg>
- },
- back: {
- title: 'Back',
- image: '/static/img/back.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path opacity=".87" fill="none" d="M0 0h24v24H0V0z"/><path d="M17.51 3.87L15.73 2.1 5.84 12l9.9 9.9 1.77-1.77L9.38 12l8.13-8.13z"/></svg>,
- },
- image_search: {
- title: 'Search',
- image: '/static/img/image_search.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M18 13v7H4V6h5.02c.05-.71.22-1.38.48-2H4c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-5l-2-2zm-1.5 5h-11l2.75-3.53 1.96 2.36 2.75-3.54zm2.8-9.11c.44-.7.7-1.51.7-2.39C20 4.01 17.99 2 15.5 2S11 4.01 11 6.5s2.01 4.5 4.49 4.5c.88 0 1.7-.26 2.39-.7L21 13.42 22.42 12 19.3 8.89zM15.5 9C14.12 9 13 7.88 13 6.5S14.12 4 15.5 4 18 5.12 18 6.5 16.88 9 15.5 9z"/><path fill="none" d="M0 0h24v24H0z"/></svg>,
- },
- search: {
- title: 'Search',
- image: '/static/img/search.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/><path d="M0 0h24v24H0z" fill="none"/></svg>,
- },
- open_in_new: {
- title: 'Open',
- image: '/static/img/open_in_new.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></svg>,
- },
- test: {
- title: 'Test',
- image: '/static/img/fastfood.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.06 22.99h1.66c.84 0 1.53-.64 1.63-1.46L23 5.05h-5V1h-1.97v4.05h-4.97l.3 2.34c1.71.47 3.31 1.32 4.27 2.26 1.44 1.42 2.43 2.89 2.43 5.29v8.05zM1 21.99V21h15.03v.99c0 .55-.45 1-1.01 1H2.01c-.56 0-1.01-.45-1.01-1zm15.03-7c0-8-15.03-8-15.03 0h15.03zM1.02 17h15v2h-15z"/><path fill="none" d="M0 0h24v24H0z"/></svg>
- },
- copy: {
- title: 'Copy',
- image: '/static/img/copy.svg',
- svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>,
- },
- // export: {
- // title: 'Export',
- // image: '/static/img/export.svg',
- // svg: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0,0h24v24H0V0z"/><path d="M19,12v7H5v-7H3v7c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-7H19z M11,6.83L8.41,9.41L7,8l5-5l5,5l-1.41,1.41L13,6.83v9.67h-2 V6.83z"/></svg>,
- // },
-}
-
-const goBack = () => history.goBack()
-
-export const MenuButton = ({ name, href, onClick, label, children, className }) => {
- const { svg, title } = icons[name]
- if (name === 'back') {
- onClick = goBack
- }
- if (href) {
- return (
- <Link to={href} className={className || 'menuButton'}>
- <div className='icon'>{svg}</div>
- {label === false ? "" : title}
- {children}
- </Link>
- )
- } else {
- return (
- <div className={className || 'menuButton'} onClick={onClick}>
- <div className='icon'>{svg}</div>
- {label === false ? "" : title}
- {children}
- </div>
- )
- }
-}
-
-export const SmallMenuButton = (props) => (
- <MenuButton {...props} label={false} className={props.active ? 'menuButton small active' : 'menuButton small'} />
-)
-
-export const MenuRoute = ({ component: Component, props, ...rest }) => (
- <Route {...rest} render={routeProps => (
- <Component {...routeProps} {...props} />
- )}/>
-)
diff --git a/animism-align/frontend/common/miscellaneous.component.js b/animism-align/frontend/common/miscellaneous.component.js
deleted file mode 100644
index 4eb23f1..0000000
--- a/animism-align/frontend/common/miscellaneous.component.js
+++ /dev/null
@@ -1,82 +0,0 @@
-import React, { Component } from 'react';
-import { Link } from 'react-router-dom'
-import { clamp, percent } from '../util'
-
-export const Loader = () => (
- <div>
- <div className='circular-loader color'>
- <div className="stroke">
- <div className="stroke-left"></div>
- <div className="stroke-right"></div>
- </div>
- </div>
- </div>
-)
-
-export const Swatch = ({ color }) => (
- <div
- className='swatch'
- style={{ backgroundColor: color ? 'rgb(' + color.join(',') + ')' : 'transparent' }}
- />
-)
-
-export const Dot = ({ color }) => (
- <div
- className='dot'
- style={{ backgroundColor: color }}
- />
-)
-
-export const Columns = ({ count, margin, width, object, children, className }) => {
- if (!object || !object.length) object = children
- if (!object || !object.length) return null
- margin = margin || 380
- width = width || 250
- count = count || Math.floor((window.innerWidth - margin) / width)
- let columns = []
- let len = object.length
- let j = 0
- for (let i = 0; i < count; i++) {
- let column_len = len * (i + 1) / count
- let column = []
- for (; j < column_len; j++) {
- column.push(<div key={j}>{object[j]}</div>)
- }
- columns.push(<div key={"col_" + i + "_" + j} className='column' style={{ width }}>{column}</div>)
- if (j >= len) break
- }
- return (
- <div className={'row columnCells ' + className}>
- {columns}
- </div>
- )
-}
-
-export const Statistic = ({ name, value, link }) => (
- <div className='statistic row'>
- <div className='title'>{link ? <Link to={link}>{name}</Link> : name}</div>
- <div className='int'>{value}</div>
- </div>
-)
-
-export const Detections = ({ detections, labels }) => (
- (detections || []).map(({ label, rect }, i) => (
- <div
- className='rect'
- key={i}
- style={{
- left: percent(clamp(rect.x1)),
- width: percent(clamp(rect.x2 - rect.x1, 0, Math.min(1.0, 1.0 - rect.x1))),
- top: percent(clamp(rect.y1)),
- height: percent(clamp(rect.y2 - rect.y1, 0, Math.min(1.0, 1.0 - rect.y1))),
- }}>
- {labels && <span>{label.replace(/_/g, ' ')}</span>}
- </div>
- )
-))
-
-export const Progress = ({ current, total }) => (
- <div className='progress'>
- <div className='bar' style={{ width: Math.round(100 * current / total) + '%' }} />
- </div>
-)
diff --git a/animism-align/frontend/common/miscellaneous.css b/animism-align/frontend/common/miscellaneous.css
deleted file mode 100644
index 32c3e7b..0000000
--- a/animism-align/frontend/common/miscellaneous.css
+++ /dev/null
@@ -1,18 +0,0 @@
-
-/* Progress bar */
-
-.progress {
- background: #f8f8f8;
- margin: 0.25rem 0;
- height: 0.25rem;
- width: 20rem;
- position: relative;
- box-shadow: 0 1px 3px rgba(0,0,0,0.2);
- margin-bottom: 0.2rem;
-}
-.progress .bar {
- position: absolute;
- top: 0; left: 0;
- height: 100%;
- background: #11f;
-}
diff --git a/animism-align/frontend/common/modal.component.js b/animism-align/frontend/common/modal.component.js
deleted file mode 100644
index 75c479c..0000000
--- a/animism-align/frontend/common/modal.component.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import React, { Component } from 'react'
-
-export const Modal = ({ visible, children }) => (
- <div className={visible ? "modal visible" : "modal"}>
- <div>
- {children}
- </div>
- </div>
-)
diff --git a/animism-align/frontend/common/modal.css b/animism-align/frontend/common/modal.css
deleted file mode 100644
index 5e95a09..0000000
--- a/animism-align/frontend/common/modal.css
+++ /dev/null
@@ -1,20 +0,0 @@
-.modal {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: 100;
- background: rgba(0,0,0,0.2);
- display: none;
-}
-.modal.visible {
- display: flex;
- justify-content: center;
- align-items: center;
-}
-.modal > div {
- background: #fff;
- padding: 1rem;
- box-shadow: 0 2px 4px rgba(0,0,0,0.5);
-}
diff --git a/animism-align/frontend/common/slider.component.js b/animism-align/frontend/common/slider.component.js
deleted file mode 100644
index 7e42b4d..0000000
--- a/animism-align/frontend/common/slider.component.js
+++ /dev/null
@@ -1,115 +0,0 @@
-import React, { Component } from 'react'
-import { default as throttle } from 'lodash.throttle'
-
-const SLIDER_THROTTLE_TIME = 1000 / 30
-
-export default class Slider extends Component {
- state = {
- value: 0
- }
-
- constructor(props){
- super(props)
- this.timeout = 0
- this.handleInput = this.handleInput.bind(this)
- this.handleRange = this.handleRange.bind(this)
- this.onChange = throttle(props.onChange, SLIDER_THROTTLE_TIME)
- }
- componentDidMount() {
- let { value } = this.props
- if (this.props.type === 'int') {
- value = parseInt(value)
- }
- this.setState({ value })
- }
- componentDidUpdate(prevProps) {
- let { value } = this.props
- if (prevProps.value !== value) {
- if (this.props.type === 'int') {
- value = parseInt(value)
- }
- this.setState({ value })
- }
- }
- handleInput(e){
- let { name } = this.props
- let new_value = e.target.value
- if (new_value === '') {
- new_value = this.props.defaultValue || (this.props.max - this.props.min) / 2
- }
- else if (this.props.type === 'int') {
- new_value = parseInt(new_value)
- }
- else if (this.props.type === 'odd') {
- new_value = parseInt(Math.floor(new_value / 2) * 2 + 1)
- }
- else {
- new_value = parseFloat(new_value)
- }
- if (this.state.value !== new_value) {
- this.setState({ value: new_value })
- this.props.onChange(new_value)
- }
- }
- handleRange(e){
- let { value: new_value } = e.target
- if (this.props.type === 'int') {
- new_value = parseInt(new_value)
- }
- else if (this.props.type === 'odd') {
- new_value = parseInt(Math.floor(new_value / 2) * 2 + 1)
- }
- else if (this.props.type === 'list') {
- new_value = this.props.options[new_value] || this.props.options[0]
- }
- else {
- new_value = parseFloat(new_value)
- }
- this.setState({ value: new_value })
- this.onChange(this.props.name, new_value)
- }
- render(){
- let { name, title } = this.props
- let value = this.state.value
- if (typeof value === 'undefined') {
- value = this.props.min
- }
- let text_value = value
- let step;
- let min = this.props.min || 0
- let max = this.props.max || 0
- if (this.props.type === 'int') {
- step = 1
- } else if (this.props.type === 'list') {
- min = 0
- max = this.props.options.length - 1
- step = 1
- value = this.props.options.indexOf(value)
- } else {
- step = (this.props.max - this.props.min) / 100
- text_value = parseFloat(value).toFixed(2)
- }
- return (
- <label className={this.props.error ? 'slider error' : 'slider'}>
- <span>{title}</span>
- <input
- type='number'
- min={min}
- max={max}
- step={step}
- value={text_value}
- onChange={this.handleInput}
- onBlur={this.handleInput}
- />
- <input
- type='range'
- min={min}
- max={max}
- step={step}
- value={value}
- onChange={this.handleRange}
- />
- </label>
- )
- }
-}
diff --git a/animism-align/frontend/common/table.component.js b/animism-align/frontend/common/table.component.js
deleted file mode 100644
index 8a74a79..0000000
--- a/animism-align/frontend/common/table.component.js
+++ /dev/null
@@ -1,128 +0,0 @@
-import React from 'react'
-
-import { formatName } from '../util'
-
-const __HR__ = '__HR__'
-
-export function TableObject({ tag, object, order, summary }) {
- if (!object) return null
- if (object === 'loading') {
- return <div className='tableObject loading'>{tag}{': Loading'}</div>
- }
- if (object.err) {
- return <div className='tableObject error'>{tag}{' Error: '}{object.err}</div>
- }
- let objects = Object.keys(object)
- if (order) {
- const grouped = objects.reduce((a, b) => {
- const index = order.indexOf(b)
- if (index !== -1) {
- a.order.push([index, b])
- } else {
- a.alpha.push(b)
- }
- return a
- }, { order: [], alpha: [] })
- objects = grouped.order
- .sort((a, b) => a[0] - b[0])
- .map(([i, s]) => s)
- if (!summary) {
- objects = objects
- // .concat([__HR__])
- .concat(grouped.alpha.sort())
- }
- } else {
- objects = objects.sort()
- }
- return (
- <div>
- {tag && <h3 className='tt'>{tag}</h3>}
- <table className={'tableObject ' + tag}>
- <tbody>
- {objects.map((key, i) => (
- <TableRow key={key + '_' + i} name={key} value={object[key]} />
- ))}
- </tbody>
- </table>
- </div>
- )
-}
-
-export function TableArray({ tag, list }) {
- if (!list) return null
- return (
- <div>
- {tag && <h3>{tag}</h3>}
- <table className={'tableArray ' + tag}>
- <tbody>
- {list.map((value, i) => (
- <tr key={tag + '_' + i}>
- <TableCell value={value} />
- </tr>
- ))}
- </tbody>
- </table>
- </div>
- )
-}
-
-export function TableTuples({ tag, list }) {
- if (!list) return null
- return (
- <div>
- {tag && <h3>{tag}</h3>}
- <table className={'tableTuples ' + tag}>
- <tbody>
- {list.map(([key, ...values], i) => (
- <tr key={tag + '_' + i}>
- <th>{formatName(key)}</th>
- {values.map((value, j) => (
- <TableCell key={i + '_' + j} value={value} />
- ))}
- </tr>
- ))}
- </tbody>
- </table>
- </div>
- )
-}
-
-export function TableRow({ name, value }) {
- if (name === __HR__) {
- return (
- <tr>
- <th className='tr'>
- <hr />
- </th>
- </tr>
- )
- }
- return (
- <tr>
- <th>{formatName(name)}</th>
- <TableCell name={name} value={value} />
- </tr>
- )
-}
-
-export function TableCell({ value }) {
- if (value && typeof value === 'object') {
- if (value._raw) {
- value = value.value
- } else if (value.length) {
- value = <TableArray nested tag={''} list={value} />
- } else {
- value = <TableObject nested tag={''} object={value} />
- }
- }
- if (typeof value === 'boolean') {
- return <td>{value ? <Pill type='yes' /> : <Pill type='no' />}</td>
- }
- return (
- <td>{value}</td>
- )
-}
-
-export const Pill = ({ color, type }) => (
- <div className={'pill ' + type} style={{ backgroundColor: color }}>{type}</div>
-) \ No newline at end of file
diff --git a/animism-align/frontend/common/table.css b/animism-align/frontend/common/table.css
deleted file mode 100644
index 4752e21..0000000
--- a/animism-align/frontend/common/table.css
+++ /dev/null
@@ -1,96 +0,0 @@
-/* tables on metadata pages */
-
-h3.tt {
- margin: 1.5rem 0 0.25rem 0;
- font-size: 1.25rem;
-}
-table {
- border: 0;
- margin: 0;
- padding: 0;
- border-spacing: 0;
- line-height: 1.5;
- color: #666;
-}
-.tableObject td,
-.tableObject th {
- padding: 0.1875rem;
- vertical-align: top;
-}
-.tableObject hr {
- width: 100%;
- color: transparent;
- border: 0;
- border-bottom: 1px solid #bbb;
- align: left;
- margin: 3px 0;
- padding: 0;
-}
-.tableObject th,
-.tableTuples th {
- min-width: 8rem;
- text-align: left;
- text-transform: capitalize;
- padding-left: 0;
- padding-right: 0.625rem;
- font-weight: 300;
- color: #333;
-}
-.tableTuples td {
- text-align: right;
-}
-.tableObject td {
- font-weight: normal;
- color: #000;
-}
-.tableObject .tableObject {
- border: 0.0625rem solid #ddd;
-}
-.tableArray {
- border: 0.0625rem solid #ddd;
- border-spacing: 0;
-}
-.tableArray td {
- border-bottom: 0.0625rem solid #ddd;
-}
-
-.rows .tableRow {
- flex-wrap: wrap;
-}
-.rows .row > div.galleryRow {
- padding: 0 0.75rem 0.75rem 0.75rem;
-}
-.rows .row > div.galleryRow > div {
- display: flex;
- flex-direction: row;
- max-height: 100px;
- flex-wrap: wrap;
- max-width: 100%;
- overflow: hidden;
-}
-.galleryRow .thumbnail {
- height: 100px;
- margin-right: 0.75rem;
-}
-/*
-.gray {
- font-size: 12px;
- color: #888;
- display: block;
-}
-.sha256.heading {
- margin: 20px 0 0px;
-}
-.gray span {
- padding-right: 5px;
-}
-.gray {
- margin-bottom: 10px;
-}
-.gray a {
- color: #666;
-}
-*/
-.tableIndex {
- width: 100%;
-} \ No newline at end of file
diff --git a/animism-align/frontend/common/tableIndex.component.js b/animism-align/frontend/common/tableIndex.component.js
deleted file mode 100644
index a34a9e9..0000000
--- a/animism-align/frontend/common/tableIndex.component.js
+++ /dev/null
@@ -1,129 +0,0 @@
-import React, { Component } from 'react'
-import { Link } from 'react-router-dom'
-import { connect } from 'react-redux'
-
-import { formatDateTime } from '../util'
-import { Loader, Swatch, Dot } from '../common'
-
-/*
- <TableIndex
- title="Collections"
- actions={actions.collection}
- data={data.collection.index}
- fields={[
- { name: 'title', type: 'title', link: row => '/collection/' + row.id + '/show/' },
- { name: 'username', type: 'string' },
- { name: 'date', type: 'date' },
- { name: 'notes', type: 'text' },
- ]}
- />
-*/
-
-export default class TableIndex extends Component {
- componentDidMount() {
- this.props.actions && this.props.actions.index()
- }
-
- render() {
- const { data, els, title, fields, noHeadings, notFoundMessage } = this.props
- if (data.loading) {
- return <Loader />
- }
- if (!els && (!data.lookup || !data.order.length)) {
- return (
- <div>
- <h1>{title}</h1>
- <p className='gray'>
- {notFoundMessage || ("No " + title)}
- </p>
- </div>
- )
- }
- return (
- <div className='tableIndex'>
- <h1>{title}</h1>
- <div className='rows'>
- {!noHeadings && <RowHeadings fields={fields} />}
- {els
- ? els.map(el => <Row key={el.id} row={el} fields={fields} />)
- : data.order.map(id => <Row key={id} row={data.lookup[id]} fields={fields} />)
- }
- </div>
- </div>
- )
- }
-}
-
-const RowHeadings = ({fields}) => {
- return (
- <div className='row heading'>
- {fields.map(field => {
- if (field.type === 'gallery') return
- let css = {}
- if (field.width) {
- css = { width: field.width, maxWidth: 'none', flex: 'none', }
- }
- if (field.flex) {
- css.flex = field.flex
- }
- return <div key={field.name} className={field.type} style={css}>{(field.title || field.name).replace(/_/g, ' ')}</div>
- })}
- </div>
- )
-}
-
-const Row = ({ row, fields }) => {
- return (
- <div className='row tableRow'>
- {fields.map(field => {
- let value = field.valueFn ? field.valueFn(row) : row[field.name]
- let css = {}
- if (field.type === 'date' && (row.updated_at || row.created_at || value)) {
- // value = (value || "").split('.')[0]
- value = formatDateTime(row.updated_at || row.created_at || value)
- } else if (field.type === 'text') {
- value = String(value || "").trim().split('\n')[0].replace(/^#+/, '').substr(0, 100)
- } else if (field.type === 'color') {
- value = <Swatch color={value} />
- } else if (field.type === 'bool') {
- value = <Dot color={value ? '#11f' : '#fff'} />
- } else if (field.type === 'str') {
- value = String(value || "").replace(/_/g, ' ')
- } else if (field.type === 'gallery') {
- return <GalleryRow key={field.name} media={value} />
- }
- if (field.width) {
- css = { width: field.width, maxWidth: 'none', flex: 'none', }
- }
- if (field.flex) {
- css.flex = field.flex
- }
- let className
- if (field.style) {
- className = field.type + ' ' + field.style
- } else {
- className = field.type
- }
- value = <div title={value} key={field.name} className={className} style={css}>{value}</div>
- if (field.link) {
- return <Link key={field.name} to={field.link(row)}>{value}</Link>
- }
- return value
- })}
- </div>
- )
-}
-
-const GalleryRow = ({ media }) => {
- return (
- <div className='galleryRow'>
- <div>
- {media.map(img => (
- <Link to={"/media/id/" + img.id + "/"} key={img.url}>
- <img src={img.url} className='thumbnail' />
- </Link>
- ))}
- </div>
- </div>
- )
-}
diff --git a/animism-align/frontend/common/upload.css b/animism-align/frontend/common/upload.css
deleted file mode 100644
index 719f98c..0000000
--- a/animism-align/frontend/common/upload.css
+++ /dev/null
@@ -1,26 +0,0 @@
-/* drag-and-drop */
-
-.dragCurtain {
- display: none;
- pointer-events: none;
- justify-content: center;
- align-items: center;
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: rgba(0,0,0,0.5);
- z-index: 1;
-}
-.dragCurtain div {
- color: #11f;
- background: white;
- border: 2px solid #11f;
- padding: 2rem;
- font-size: 1.5rem;
- font-weight: bold;
-}
-.dragging .dragCurtain {
- display: flex;
-}
diff --git a/animism-align/frontend/common/upload.helpers.js b/animism-align/frontend/common/upload.helpers.js
deleted file mode 100644
index 60d5b82..0000000
--- a/animism-align/frontend/common/upload.helpers.js
+++ /dev/null
@@ -1,192 +0,0 @@
-import ExifReader from 'exifreader'
-
-function base64ToUint8Array(string, start, finish) {
- start = start || 0
- finish = finish || string.length
- // atob that shit
- const binary = atob(string)
- const buffer = new Uint8Array(binary.length)
- for (let i = start; i < finish; i++) {
- buffer[i] = binary.charCodeAt(i)
- }
- return buffer
-}
-
-function getOrientation(uri) {
- // Split off the base64 data
- const base64String = uri.split(',')[1]
- // Read off first 128KB, which is all we need to
- // get the EXIF data
- const arr = base64ToUint8Array(base64String, 0, 2 ** 17)
- try {
- const tags = ExifReader.load(arr.buffer)
- // console.log(tags)
- if (typeof tags.Orientation == 'number') {
- return tags.Orientation
- }
- return tags.Orientation.value
- } catch (err) {
- return 1
- }
-}
-
-function applyRotation(canvas, ctx, deg) {
- const radians = deg * (Math.PI / 180)
- if (deg === 90) {
- ctx.translate(canvas.width, 0)
- } else if (deg === 180) {
- ctx.translate(canvas.width, canvas.height)
- } else if (deg === 270) {
- ctx.translate(0, canvas.height)
- }
- ctx.rotate(radians)
-}
-
-/**
- * Mapping from EXIF orientation values to data
- * regarding the rotation and mirroring necessary to
- * render the canvas correctly
- * Derived from:
- * http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/
- */
-const orientationToTransform = {
- 1: { rotation: 0, mirror: false },
- 2: { rotation: 0, mirror: true },
- 3: { rotation: 180, mirror: false },
- 4: { rotation: 180, mirror: true },
- 5: { rotation: 90, mirror: true },
- 6: { rotation: 90, mirror: false },
- 7: { rotation: 270, mirror: true },
- 8: { rotation: 270, mirror: false }
-}
-
-function applyOrientationCorrection(canvas, ctx, uri) {
- const orientation = getOrientation(uri)
- // Only apply transform if there is some non-normal orientation
- if (orientation && orientation !== 1) {
- console.log(orientation)
- const transform = orientationToTransform[orientation]
- const { rotation } = transform
- const flipAspect = rotation === 90 || rotation === 270
- if (flipAspect) {
- // Fancy schmancy swap algo
- canvas.width = canvas.height + canvas.width
- canvas.height = canvas.width - canvas.height
- canvas.width -= canvas.height
- }
- if (rotation > 0) {
- applyRotation(canvas, ctx, rotation)
- }
- }
-}
-
-function getScale(width, height, viewportWidth, viewportHeight, fillViewport) {
- function fitHorizontal() {
- return viewportWidth / width
- }
- function fitVertical() {
- return viewportHeight / height
- }
- fillViewport = !!fillViewport
- const landscape = (width / height) > (viewportWidth / viewportHeight)
- if (landscape) {
- if (fillViewport) {
- return fitVertical()
- }
- if (width > viewportWidth) {
- return fitHorizontal()
- }
- } else {
- if (fillViewport) {
- return fitHorizontal()
- }
- if (height > viewportHeight) {
- return fitVertical()
- }
- }
- return 1
-}
-
-function getImageProperties(img) {
- // img is an image
- if ('naturalWidth' in img) {
- const { naturalWidth, naturalHeight } = img
- const jpeg = !!img.src.match(/data:image\/jpeg|\.jpeg$|\.jpg$/i)
- const hasDataURI = !!img.src.match(/^data:/)
- return { naturalWidth, naturalHeight, jpeg, hasDataURI }
- }
- // img is a canvas
- return {
- naturalWidth: img.width,
- naturalHeight: img.height,
- jpeg: false,
- hasDataURI: false,
- }
-}
-
-export function renderToCanvas(img, options) {
- if (!img) return null
- options = options || {}
-
- // Canvas max size for any side
- const maxSide = options.maxSide || 0
- const canvas = document.createElement('canvas')
- const ctx = canvas.getContext('2d')
- const initialScale = options.scale || 1
- /*
- // constrain
- // Scale to needed to constrain canvas to max size
- let scale = getScale(img.naturalWidth * initialScale, img.naturalHeight * initialScale, maxSide, maxSide, true)
- // console.log(scale)
- // Still need to apply the user defined scale
- scale *= initialScale
- canvas.width = Math.round(img.naturalWidth * scale)
- canvas.height = Math.round(img.naturalHeight * scale)
- */
- const { naturalWidth, naturalHeight, jpeg, hasDataURI } = getImageProperties(img)
- if (maxSide > 0) {
- if (naturalWidth > naturalHeight) {
- canvas.width = Math.min(maxSide, naturalWidth)
- canvas.height = naturalHeight * canvas.width / naturalWidth
- } else {
- canvas.height = Math.min(maxSide, naturalHeight)
- canvas.width = naturalWidth * canvas.height / naturalHeight
- }
- } else {
- canvas.width = naturalWidth
- canvas.height = naturalHeight
- }
- const { correctOrientation } = options
-
- ctx.save()
-
- // Can only correct orientation on JPEGs represented as dataURIs
- // for the time being
- if (correctOrientation && jpeg && hasDataURI) {
- applyOrientationCorrection(canvas, ctx, img.src)
- }
- // Resize image if too large
- // if (scale !== 1) {
- // ctx.scale(scale, scale)
- // }
-
- ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
- ctx.restore()
-
- return canvas
-}
-
-export function renderThumbnail(img, options) {
- const resized = renderToCanvas(img, {
- correctOrientation: true,
- ...options,
- })
- // const canvas = document.createElement('canvas') // document.querySelector('#user_photo_canvas')
- // const ctx = canvas.getContext('2d')
- // ctx.fillStyle = 'black'
- // ctx.fillRect(0, 0, MAX_SIDE, MAX_SIDE)
- // const xOffset = (MAX_SIDE - resized.width) / 2
- // const yOffset = (MAX_SIDE - resized.height) / 2
- // ctx.drawImage(resized, xOffset, yOffset, resized.width, resized.height)
- return resized
-}
diff --git a/animism-align/frontend/common/uploadImage.component.js b/animism-align/frontend/common/uploadImage.component.js
deleted file mode 100644
index f712d6c..0000000
--- a/animism-align/frontend/common/uploadImage.component.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import React, { Component } from 'react'
-
-import { renderThumbnail } from './upload.helpers'
-
-export default class UploadImageComponent extends Component {
- constructor(props) {
- super(props)
- document.body.addEventListener("dragover", this.dragOver.bind(this))
- document.body.addEventListener("dragleave", this.dragLeave.bind(this))
- document.body.addEventListener("drop", this.upload.bind(this))
- }
-
- dragOver(e) {
- e.stopPropagation()
- e.preventDefault()
- document.body.className = 'dragging'
- }
-
- dragLeave(e) {
- e.stopPropagation()
- e.preventDefault()
- document.body.className = ''
- }
-
- upload(e) {
- e.preventDefault()
- document.body.className = ''
- const files = e.dataTransfer ? e.dataTransfer.files : e.target.files
- let i
- let file
- for (i = 0; i < files.length; i++) {
- file = files[i]
- if (file && file.type.match('image.*')) break
- }
- if (!file) {
- console.log('No file specified')
- return
- }
- const fr = new FileReader()
- fr.onload = fileReaderEvent => {
- fr.onload = null
- const img = new Image()
- img.onload = () => {
- img.onload = null
- this.resizeAndUpload(file, img)
- }
- img.src = fileReaderEvent.target.result
- }
- fr.readAsDataURL(file)
- }
-
- resizeAndUpload(file, img) {
- const canvas = renderThumbnail(img, this.props)
- canvas.toBlob(blob => {
- this.props.onUpload({ file, img, canvas, blob, freshen: true })
- }, 'image/jpeg', this.props.quality || 80)
- }
-
- render() {
- return (
- <div className='uploadButton'>
- <input
- type="file"
- accept="image/*"
- onChange={this.upload.bind(this)}
- required={this.props.required}
- />
- <div className='dragCurtain'>
- <div className='dragLabel'>Drop image here</div>
- </div>
- </div>
- )
- }
-}