diff --git a/js/actions/edition_list_actions.js b/js/actions/edition_list_actions.js
index 83b9abfe..ca653323 100644
--- a/js/actions/edition_list_actions.js
+++ b/js/actions/edition_list_actions.js
@@ -35,4 +35,4 @@ class EditionListActions {
}
}
-export default alt.createActions(EditionListActions);
\ No newline at end of file
+export default alt.createActions(EditionListActions);
diff --git a/js/components/ascribe_media/media_player.js b/js/components/ascribe_media/media_player.js
new file mode 100644
index 00000000..55188568
--- /dev/null
+++ b/js/components/ascribe_media/media_player.js
@@ -0,0 +1,132 @@
+'use strict';
+
+import React from 'react';
+import InjectInHeadMixin from '../../mixins/inject_in_head_mixin';
+import Panel from 'react-bootstrap/lib/Panel';
+
+/**
+ * This is the component that implements display-specific functionality.
+ *
+ * ResourceViewer handles the following mimetypes:
+ * - image
+ * - video
+ * - audio
+ * - pdf
+ * - other
+ */
+
+
+let Other = React.createClass({
+ propTypes: {
+ url: React.PropTypes.string.isRequired
+ },
+
+ render() {
+ let ext = this.props.url.split('.').pop();
+
+ return (
+
+
+ .{ext}
+
+
+ );
+ }
+});
+
+let Image = React.createClass({
+ propTypes: {
+ url: React.PropTypes.string.isRequired,
+ preview: React.PropTypes.string.isRequired
+ },
+
+ mixins: [InjectInHeadMixin],
+
+ componentDidMount() {
+ this.inject('http://code.jquery.com/jquery-2.1.4.min.js')
+ .then(() =>
+ Promise.all([
+ this.inject('node_modules/shmui/shmui.css'),
+ this.inject('node_modules/shmui/jquery.shmui.js')
+ ]).then(() => { window.jQuery('.shmui-ascribe').shmui(); }));
+ },
+
+ render() {
+ return (
+
+ );
+ }
+});
+
+let Video = React.createClass({
+ propTypes: {
+ preview: React.PropTypes.string.isRequired,
+ url: React.PropTypes.string.isRequired,
+ extraData: React.PropTypes.array.isRequired
+ },
+
+ mixins: [InjectInHeadMixin],
+
+ getInitialState() {
+ return { ready: false };
+ },
+
+ componentDidMount() {
+ this.inject('http://code.jquery.com/jquery-2.1.4.min.js')
+ .then(() =>
+ Promise.all([
+ this.inject('https://cdnjs.cloudflare.com/ajax/libs/mediaelement/2.17.0/mediaelement-and-player.min.js'),
+ this.inject('https://cdnjs.cloudflare.com/ajax/libs/mediaelement/2.17.0/mediaelementplayer.min.css')
+ ]).then(this.ready));
+ },
+
+ ready() {
+ this.setState({ready: true});
+ },
+
+ render() {
+ if (this.state.ready) {
+ return (
+
+ );
+ } else {
+ return (
+
+ );
+ }
+ }
+});
+
+
+let resourceMap = {
+ 'image': Image,
+ 'video': Video,
+ 'other': Other
+};
+
+let MediaPlayer = React.createClass({
+ propTypes: {
+ mimetype: React.PropTypes.oneOf(['image', 'video', 'audio', 'pdf', 'other']).isRequired,
+ preview: React.PropTypes.string.isRequired,
+ url: React.PropTypes.string.isRequired,
+ extraData: React.PropTypes.array
+ },
+
+ render() {
+ let Component = resourceMap[this.props.mimetype] || Other;
+
+ return (
+
+
+
+ );
+ }
+});
+
+export default MediaPlayer;
diff --git a/js/components/ascribe_media/resource_viewer.js b/js/components/ascribe_media/resource_viewer.js
deleted file mode 100644
index 012228c6..00000000
--- a/js/components/ascribe_media/resource_viewer.js
+++ /dev/null
@@ -1,42 +0,0 @@
-'use strict';
-
-import React from 'react';
-import InjectInHeadMixin from '../../mixins/inject_in_head_mixin';
-
-/**
- * This is the component that implements display-specific functionality.
- *
- * ResourceViewer handles the following mimetypes:
- * - image
- * - video
- * - audio
- * - pdf
- * - other
- */
-
-let resourceMap = {
- 'image': 1
-};
-
-let ResourceViewer = React.createClass({
- propTypes: {
- thumbnail: React.PropTypes.string.isRequired,
- mimetype: React.PropTypes.oneOf(['image', 'video', 'audio', 'pdf', 'other']).isRequired
- },
-
- mixins: [InjectInHeadMixin],
-
- componentDidMount() {
- //this.inject('http://antani.com');
- },
-
- render() {
- return (
-
- resourceviewer {this.props.thumbnail} {this.props.mimetype}
-
- );
- }
-});
-
-export default ResourceViewer;
diff --git a/js/components/edition.js b/js/components/edition.js
index 9094e20b..9bfe8f41 100644
--- a/js/components/edition.js
+++ b/js/components/edition.js
@@ -1,8 +1,12 @@
'use strict';
import React from 'react';
+import MediaPlayer from './ascribe_media/media_player';
-import ResourceViewer from './ascribe_media/resource_viewer';
+import Row from 'react-bootstrap/lib/Row';
+import Col from 'react-bootstrap/lib/Col';
+import Button from 'react-bootstrap/lib/Button';
+import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import EditionActions from '../actions/edition_actions';
import AclButton from './acl_button';
@@ -19,20 +23,30 @@ let Edition = React.createClass({
render() {
let thumbnail = this.props.edition.thumbnail;
let mimetype = this.props.edition.digital_work.mime;
+ let extraData = null;
+
+ if (this.props.edition.digital_work.encoding_urls) {
+ extraData = this.props.edition.digital_work.encoding_urls.map(e => { return { url: e.url, type: e.label } });
+ }
return (
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
);
}
});
diff --git a/js/components/edition_container.js b/js/components/edition_container.js
index 09009248..af2ccfa6 100644
--- a/js/components/edition_container.js
+++ b/js/components/edition_container.js
@@ -39,9 +39,8 @@ let EditionContainer = React.createClass({
render() {
if('title' in this.state.edition) {
return (
-
+
);
} else {
return (
diff --git a/js/mixins/inject_in_head_mixin.js b/js/mixins/inject_in_head_mixin.js
index 42e3b6dc..b537246b 100644
--- a/js/mixins/inject_in_head_mixin.js
+++ b/js/mixins/inject_in_head_mixin.js
@@ -2,11 +2,11 @@
let mapAttr = {
link: 'href',
- source: 'src'
+ script: 'src'
};
-let mapExt = {
- js: 'source',
+let mapTag = {
+ js: 'script',
css: 'link'
};
@@ -24,35 +24,46 @@ let InjectInHeadMixin = {
return document.querySelector(query);
},
- injectTag(tag, src){
- if (InjectInHeadMixin.isPresent(tag, src)) {
- return;
- }
+ injectTag(tag, src) {
+ let promise = new Promise((resolve, reject) => {
+ if (InjectInHeadMixin.isPresent(tag, src)) {
+ resolve();
+ } else {
+ let attr = mapAttr[tag];
+ let element = document.createElement(tag);
+ if (tag === 'script') {
+ element.onload = () => resolve();
+ element.onerror = () => reject();
+ } else {
+ resolve();
+ }
+ document.head.appendChild(element);
+ element[attr] = src;
+ if (tag === 'link') {
+ element.rel = 'stylesheet';
+ }
+ }
+ });
- let attr = mapAttr[tag];
- let element = document.createElement(tag);
- document.head.appendChild(element);
- element[attr] = src;
+ return promise;
},
injectStylesheet(src) {
- this.injectTag('link', src);
+ return InjectInHeadMixin.injectTag('link', src);
},
injectScript(src) {
- this.injectTag('source', src);
+ return InjectInHeadMixin.injectTag('source', src);
},
inject(src) {
let ext = src.split('.').pop();
- try {
- let tag = mapAttr(src);
- } catch (e) {
- throw new Error(`Cannot inject ${src} in the DOM, cannot guess the tag name from extension ${ext}. Valid extensions are "js" and "css".`);
+ let tag = mapTag[ext];
+ if (!tag) {
+ throw new Error(`Cannot inject ${src} in the DOM, cannot guess the tag name from extension "${ext}". Valid extensions are "js" and "css".`);
}
- // ES6Lint says tag is not defined, pls fix
- // - Tim
- InjectInHeadMixin.injectTag(tag, src);
+
+ return InjectInHeadMixin.injectTag(tag, src);
}
};
diff --git a/package.json b/package.json
index 5de03b4e..2e9d596b 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,9 @@
"object-assign": "^2.0.0",
"react": "^0.13.2",
"react-bootstrap": "~0.22.6",
+ "react-datepicker": "~0.8.0",
"react-router": "^0.13.3",
+ "shmui": "^0.1.0",
"uglifyjs": "^2.4.10",
"react-datepicker": "~0.8.0"
},
diff --git a/sass/ascribe_media_player.scss b/sass/ascribe_media_player.scss
new file mode 100644
index 00000000..9dada7f6
--- /dev/null
+++ b/sass/ascribe_media_player.scss
@@ -0,0 +1,18 @@
+.ascribe-media-player {
+ margin-bottom: 1em;
+ video {
+ width: 100%;
+ height: 100%;
+ }
+
+ img {
+ width: 100%;
+ height: 100%;
+ }
+
+ .media-other {
+ font-size: 500%;
+ color: #cccccc;
+ }
+}
+
diff --git a/sass/main.scss b/sass/main.scss
index 1ff12fc5..cc9e3203 100644
--- a/sass/main.scss
+++ b/sass/main.scss
@@ -9,6 +9,7 @@
@import 'ascribe_accordion_list';
@import 'ascribe_piece_list_bulk_modal';
@import 'ascribe_piece_list_toolbar';
+@import 'ascribe_media_player';
@import 'offset_right';
.hidden {