summaryrefslogtreecommitdiff
path: root/animism-align/frontend/app/views/align/components
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2020-07-27 15:44:29 +0200
committerJules Laplace <julescarbon@gmail.com>2020-07-27 15:44:29 +0200
commit2aad507650fa3263ef81be759ab0531b43e5b7cc (patch)
treeb8299f962ef0e3342cb8978f5e0a4f57a8ee1b30 /animism-align/frontend/app/views/align/components
parenteee3193ecf604eaed30505128b2a1f7bb875d44a (diff)
annotation form for curtain events. refactor utilities
Diffstat (limited to 'animism-align/frontend/app/views/align/components')
-rw-r--r--animism-align/frontend/app/views/align/components/annotations/annotation.form.css55
-rw-r--r--animism-align/frontend/app/views/align/components/annotations/annotation.form.js37
-rw-r--r--animism-align/frontend/app/views/align/components/annotations/annotation.index.css76
-rw-r--r--animism-align/frontend/app/views/align/components/annotations/annotation.index.js6
-rw-r--r--animism-align/frontend/app/views/align/components/annotations/annotationForms/annotationForm.utility.js80
-rw-r--r--animism-align/frontend/app/views/align/components/annotations/annotationForms/index.js11
-rw-r--r--animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.image.js4
-rw-r--r--animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.utility.js (renamed from animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.util.js)14
-rw-r--r--animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.video.js4
-rw-r--r--animism-align/frontend/app/views/align/components/annotations/annotationTypes/index.js5
10 files changed, 267 insertions, 25 deletions
diff --git a/animism-align/frontend/app/views/align/components/annotations/annotation.form.css b/animism-align/frontend/app/views/align/components/annotations/annotation.form.css
new file mode 100644
index 0000000..fdb4abe
--- /dev/null
+++ b/animism-align/frontend/app/views/align/components/annotations/annotation.form.css
@@ -0,0 +1,55 @@
+/* Annotation form */
+
+.annotationForm {
+ width: 401px;
+ padding: 0.5rem;
+ position: absolute;
+ left: 0.25rem;
+ background: #448;
+ box-shadow: 0 0 2px #000, 0 0 4px #000;
+ z-index: 10;
+}
+.annotationForm textarea {
+ width: 100%;
+}
+.annotationForm .row {
+ justify-content: space-between;
+ align-items: center;
+}
+.annotationForm .row > div {
+ display: flex;
+ align-items: center;
+}
+.annotationForm .buttons {
+ margin-bottom: 0.5rem;
+}
+.annotationForm .ts {
+ color: #fff;
+}
+.annotationForm .select.media_id {
+ width: 100%;
+ margin-right: 0;
+}
+.annotationForm .options label span:first-child {
+ display: inline-block;
+ width: 6rem;
+}
+.annotationForm .options .description {
+ font-size: 0.75rem;
+ margin-top: 0.25rem;
+ margin-bottom: 0.5rem;
+}
+.annotationForm .color input[type="text"].number {
+ width: 8rem;
+}
+.annotationForm .color input[type="text"] {
+ width: 8rem;
+}
+.annotationForm .color input[type="color"] {
+ background: transparent;
+ border: 0;
+ height: 1.7rem;
+ padding: 0;
+ margin: 0 0.5rem 0 0;
+ width: 1.4rem;
+}
diff --git a/animism-align/frontend/app/views/align/components/annotations/annotation.form.js b/animism-align/frontend/app/views/align/components/annotations/annotation.form.js
index f4620bc..7882884 100644
--- a/animism-align/frontend/app/views/align/components/annotations/annotation.form.js
+++ b/animism-align/frontend/app/views/align/components/annotations/annotation.form.js
@@ -7,18 +7,16 @@ import actions from 'app/actions'
import { ZOOM_STEPS } from 'app/constants'
import { clamp, timestamp, capitalize } from 'app/utils'
-import { timeToPosition } from 'app/views/align/align.util'
+import { timeToPosition } from 'app/utils/align.utils'
import { Select } from 'app/common'
-import {
- AnnotationFormVideo,
- AnnotationFormImage,
-} from './annotationForms'
+import { annotationFormLookup } from './annotationForms'
const ANNOTATION_TYPES = [
'sentence', 'header', 'paragraph_end',
'video',
'image', 'image_carousel',
+ 'curtain',
].map(name => ({ name, label: capitalize(name.replace('_', ' ')) }))
class AnnotationForm extends Component {
@@ -26,6 +24,7 @@ class AnnotationForm extends Component {
super(props)
this.handleChange = this.handleChange.bind(this)
this.handleSelect = this.handleSelect.bind(this)
+ this.handleSettingsChange = this.handleSettingsChange.bind(this)
this.handleSettingsSelect = this.handleSettingsSelect.bind(this)
this.handleKeyDown = this.handleKeyDown.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
@@ -74,6 +73,10 @@ class AnnotationForm extends Component {
handleSelect(name, value) {
actions.align.updateAnnotationForm(name, value)
}
+ handleSettingsChange(e) {
+ const { name, value } = e.target
+ this.handleSettingsSelect(name, value)
+ }
handleSettingsSelect(name, value) {
if (name.indexOf('_id') !== -1) value = parseInt(value) || 0
actions.align.updateAnnotationSettings(name, value)
@@ -111,7 +114,7 @@ class AnnotationForm extends Component {
}
}
render() {
- const { timeline, annotation, media } = this.props
+ const { timeline, annotation } = this.props
return (
<div
className='annotationForm'
@@ -122,15 +125,7 @@ class AnnotationForm extends Component {
{this.renderButtons()}
{annotation.type === 'sentence' && this.renderTextarea()}
{annotation.type === 'header' && this.renderTextarea()}
- {annotation.type === 'video' &&
- <AnnotationFormVideo annotation={annotation} media={media} handleSettingsSelect={this.handleSettingsSelect} />
- }
- {annotation.type === 'image' &&
- <AnnotationFormImage annotation={annotation} media={media} handleSettingsSelect={this.handleSettingsSelect} />
- }
- {annotation.type === 'image_carousel' &&
- <AnnotationFormImageCarousel annotation={annotation} media={media} handleSettingsSelect={this.handleSettingsSelect} />
- }
+ {(annotation.type in annotationFormLookup) && this.renderElementForm()}
</div>
)
}
@@ -169,6 +164,18 @@ class AnnotationForm extends Component {
</div>
)
}
+ renderElementForm() {
+ const { annotation, media } = this.props
+ const AnnotationFormElement = annotationFormLookup[annotation.type]
+ return (
+ <AnnotationFormElement
+ annotation={annotation}
+ media={media}
+ handleSettingsChange={this.handleSettingsChange}
+ handleSettingsSelect={this.handleSettingsSelect}
+ />
+ )
+ }
}
const mapStateToProps = state => ({
diff --git a/animism-align/frontend/app/views/align/components/annotations/annotation.index.css b/animism-align/frontend/app/views/align/components/annotations/annotation.index.css
new file mode 100644
index 0000000..d39e5de
--- /dev/null
+++ b/animism-align/frontend/app/views/align/components/annotations/annotation.index.css
@@ -0,0 +1,76 @@
+/* Annotation index */
+
+.annotationIndex {
+ width: 800px;
+}
+.annotationIndex .annotation {
+ position: absolute;
+ left: 5px;
+ max-width: 400px;
+ padding: 0.25rem 0.375rem;
+ box-shadow: 0px 0px 3px rgba(0,0,0,1.0);
+ border: 1px solid transparent;
+ border-radius: 2px;
+ font-size: 12px;
+ cursor: pointer;
+ user-select: none;
+ background-color: #768;
+}
+.annotation.selected {
+ border-color: #bbf;
+ box-shadow: 0px 0px 4px rgba(0,0,0,1.0), 0px 0px 2px rgba(0,0,0,1.0);
+ z-index: 1;
+ background-image: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.4));
+}
+.annotationIndex .annotation.media {
+ left: calc(405px + 0.5rem);
+}
+.annotation.sentence.even {
+ background-color: #83b;
+}
+.annotation.sentence.odd {
+ background-color: #537;
+}
+.annotation.header {
+ background-color: #838;
+}
+.annotation.paragraph_end {
+ background-color: #003;
+ border-top: 1px solid #888;
+ width: 100%;
+ padding: 1px;
+}
+.annotationIndex .annotation.utility {
+ left: calc(405px + 0.5rem);
+}
+
+
+/* Condensed layout (first lines) */
+
+.annotationIndex.condensed .annotation.sentence {
+ z-index: 0;
+ white-space: pre;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.annotationIndex.condensed .annotation.header {
+ z-index: 1;
+}
+.annotationIndex.condensed .annotation.paragraph_end {
+ border-top-color: #888;
+}
+
+/* Collapsed layout (borders) */
+
+.annotationIndex.collapsed .annotation.sentence {
+ height: 2px; overflow: hidden; padding: 0; z-index: 0;
+}
+.annotationIndex.collapsed .annotation.sentence.selected {
+ z-index: 1;
+}
+.annotationIndex.collapsed .annotation.header {
+ z-index: 2;
+}
+.annotationIndex.collapsed .annotation.paragraph_end {
+ border-top-color: #333;
+}
diff --git a/animism-align/frontend/app/views/align/components/annotations/annotation.index.js b/animism-align/frontend/app/views/align/components/annotations/annotation.index.js
index aa31268..da1038f 100644
--- a/animism-align/frontend/app/views/align/components/annotations/annotation.index.js
+++ b/animism-align/frontend/app/views/align/components/annotations/annotation.index.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react'
+import React, { PureComponent } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
@@ -6,11 +6,11 @@ import actions from 'app/actions'
import { ZOOM_STEPS, INNER_HEIGHT } from 'app/constants'
import { clamp } from 'app/utils'
-import { positionToTime, timeToPosition } from 'app/views/align/align.util'
+import { positionToTime, timeToPosition } from 'app/utils/align.utils'
import { AnnotationElementLookup } from './annotationTypes'
-class AnnotationIndex extends Component {
+class AnnotationIndex extends PureComponent {
state = {
items: [],
}
diff --git a/animism-align/frontend/app/views/align/components/annotations/annotationForms/annotationForm.utility.js b/animism-align/frontend/app/views/align/components/annotations/annotationForms/annotationForm.utility.js
new file mode 100644
index 0000000..2b6f868
--- /dev/null
+++ b/animism-align/frontend/app/views/align/components/annotations/annotationForms/annotationForm.utility.js
@@ -0,0 +1,80 @@
+import React, { Component } from 'react'
+
+import { timestamp } from 'app/utils'
+import { TextInput, LabelDescription, Select } from 'app/common'
+import { CURTAIN_COLOR_SELECT_OPTIONS } from 'app/constants'
+import { curtainTimings } from 'app/utils/annotation.utils'
+
+export const AnnotationFormCurtain = ({ annotation, handleSettingsChange, handleSettingsSelect }) => {
+ const {
+ fadeInDurationInSeconds, fadeOutDurationInSeconds, durationInSeconds,
+ start_ts, end_ts, fade_in_end_ts, fade_out_start_ts,
+ } = curtainTimings(annotations)
+
+ return (
+ <div className='options'>
+ <TextInput
+ title="Total duration"
+ name="duration"
+ className="number"
+ placeholder="0:00"
+ data={annotation.settings}
+ onChange={handleSettingsChange}
+ autoComplete="off"
+ />
+ <LabelDescription>
+ {durationInSeconds}
+ {' seconds, ends at '}
+ {timestamp(end_ts)}
+ </LabelDescription>
+
+ <TextInput
+ title="Fade in duration"
+ name="fade_in_duration"
+ className="number"
+ placeholder="0:00"
+ data={annotation.settings}
+ onChange={handleSettingsChange}
+ autoComplete="off"
+ />
+ <LabelDescription>
+ {fadeInDurationInSeconds}
+ {' seconds, ends at '}
+ {timestamp(fade_in_end_ts)}
+ </LabelDescription>
+
+ <TextInput
+ title="Fade out duration"
+ name="fade_out_duration"
+ className="number"
+ placeholder="0:00"
+ data={annotation.settings}
+ onChange={handleSettingsChange}
+ autoComplete="off"
+ />
+ <LabelDescription>
+ {fadeOutDurationInSeconds}
+ {' seconds, starts at '}
+ {timestamp(fade_out_start_ts)}
+ </LabelDescription>
+
+ <Select
+ title='Color'
+ name='color'
+ selected={annotation.settings.color}
+ options={CURTAIN_COLOR_SELECT_OPTIONS}
+ defaultOption='Pick a color'
+ onChange={handleSettingsSelect}
+ />
+
+ <TextInput
+ title="Curtain text"
+ name="curtain_text"
+ placeholder="Enter text or leave blank"
+ data={annotation.settings}
+ onChange={handleSettingsChange}
+ autoComplete="off"
+ />
+ </div>
+ )
+}
diff --git a/animism-align/frontend/app/views/align/components/annotations/annotationForms/index.js b/animism-align/frontend/app/views/align/components/annotations/annotationForms/index.js
index 1411efc..29f9def 100644
--- a/animism-align/frontend/app/views/align/components/annotations/annotationForms/index.js
+++ b/animism-align/frontend/app/views/align/components/annotations/annotationForms/index.js
@@ -6,7 +6,12 @@ import {
AnnotationFormImage,
} from './annotationForm.image'
-export {
- AnnotationFormImage,
- AnnotationFormVideo,
+import {
+ AnnotationFormCurtain,
+} from './annotationForm.utility'
+
+export const annotationFormLookup = {
+ image: AnnotationFormImage,
+ video: AnnotationFormVideo,
+ curtain: AnnotationFormCurtain,
}
diff --git a/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.image.js b/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.image.js
index ec4d25e..00c653a 100644
--- a/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.image.js
+++ b/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.image.js
@@ -1,8 +1,8 @@
import React, { Component } from 'react'
-import { thumbnailURL } from 'app/views/align/align.util'
+import { thumbnailURL } from 'app/utils/annotation.utils'
-import { checkAnnotationMediaNotReady, AnnotationMediaLoading } from './annotationTypes.util'
+import { checkAnnotationMediaNotReady, AnnotationMediaLoading } from './annotationTypes.utility'
export const AnnotationImage = ({ y, annotation, media, selected, onClick, onDoubleClick }) => {
const { start_ts, text } = annotation
diff --git a/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.util.js b/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.utility.js
index 17abebd..8bd0b9d 100644
--- a/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.util.js
+++ b/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.utility.js
@@ -1,5 +1,19 @@
import React, { Component } from 'react'
+export const AnnotationCurtain = ({ y, annotation, selected, onClick, onDoubleClick }) => {
+ const className = selected ? 'annotation utility curtain selected' : 'annotation utility curtain'
+ return (
+ <div
+ className={className}
+ style={{ top: y }}
+ onClick={e => onClick(e, annotation)}
+ onDoubleClick={e => onDoubleClick(e, annotation)}
+ >
+ CURTAIN
+ </div>
+ )
+}
+
export const checkAnnotationMediaNotReady = (annotation, media) => {
return (!media) || (!(annotation.settings.media_id in media))
}
diff --git a/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.video.js b/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.video.js
index f51ac71..d2fc4e5 100644
--- a/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.video.js
+++ b/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.video.js
@@ -1,7 +1,7 @@
import React, { Component } from 'react'
-import { thumbnailURL } from 'app/views/align/align.util'
-import { checkAnnotationMediaNotReady, AnnotationMediaLoading } from './annotationTypes.util'
+import { thumbnailURL } from 'app/utils/annotation.utils'
+import { checkAnnotationMediaNotReady, AnnotationMediaLoading } from './annotationTypes.utility'
export const AnnotationVideo = ({ y, annotation, media, selected, onClick, onDoubleClick }) => {
const { start_ts, text } = annotation
diff --git a/animism-align/frontend/app/views/align/components/annotations/annotationTypes/index.js b/animism-align/frontend/app/views/align/components/annotations/annotationTypes/index.js
index 560063b..ee30167 100644
--- a/animism-align/frontend/app/views/align/components/annotations/annotationTypes/index.js
+++ b/animism-align/frontend/app/views/align/components/annotations/annotationTypes/index.js
@@ -13,10 +13,15 @@ import {
AnnotationImage,
} from './annotationTypes.image'
+import {
+ AnnotationCurtain,
+} from './annotationTypes.utility'
+
export const AnnotationElementLookup = {
sentence: React.memo(AnnotationSentence),
header: React.memo(AnnotationHeader),
paragraph_end: React.memo(AnnotationParagraphEnd),
video: React.memo(AnnotationVideo),
image: React.memo(AnnotationImage),
+ curtain: React.memo(AnnotationCurtain),
}