mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 17:33:14 +01:00
Merge remote-tracking branch 'remotes/origin/master' into AD-43-in-piece_detail-add-generic-field-
Conflicts: gulpfile.js added notifications cleaned up proptypes
This commit is contained in:
commit
30ee436f4c
51
gulpfile.js
51
gulpfile.js
@ -18,6 +18,11 @@ var concat = require('gulp-concat');
|
||||
var _ = require('lodash');
|
||||
var eslint = require('gulp-eslint');
|
||||
var jest = require('jest-cli');
|
||||
var argv = require('yargs').argv;
|
||||
var server = require('./server.js').app;
|
||||
var minifyCss = require('gulp-minify-css');
|
||||
var uglify = require('gulp-uglify');
|
||||
|
||||
|
||||
var config = {
|
||||
bootstrapDir: './node_modules/bootstrap-sass',
|
||||
@ -41,11 +46,14 @@ var config = {
|
||||
}
|
||||
};
|
||||
|
||||
gulp.task('build', function() {
|
||||
gulp.task('build', ['js:build', 'sass:build', 'copy'], function() {
|
||||
});
|
||||
|
||||
gulp.task('js:build', function() {
|
||||
bundle(false);
|
||||
});
|
||||
|
||||
gulp.task('serve', ['browser-sync', 'sass', 'sass:watch', 'copy'], function() {
|
||||
gulp.task('serve', ['browser-sync', 'run-server', 'lint:watch', 'sass:build', 'sass:watch', 'copy'], function() {
|
||||
bundle(true);
|
||||
});
|
||||
|
||||
@ -59,27 +67,30 @@ gulp.task('jest:watch', function(done) {
|
||||
gulp.watch([ config.jestOptions.rootDir + "/**/*.js" ], [ 'jest' ]);
|
||||
});
|
||||
|
||||
gulp.task('run-server', function() {
|
||||
server.listen(4000);
|
||||
});
|
||||
|
||||
gulp.task('browser-sync', function() {
|
||||
browserSync({
|
||||
server: {
|
||||
baseDir: '.'
|
||||
},
|
||||
port: process.env.PORT || 3000
|
||||
files: ['build/css/*.css', 'build/js/*.js'],
|
||||
proxy: 'http://localhost:4000',
|
||||
port: 3000
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('sass', function () {
|
||||
gulp.task('sass:build', function () {
|
||||
gulp.src('./sass/**/main.scss')
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(gulpif(!argv.production, sourcemaps.init()))
|
||||
.pipe(sass({
|
||||
includePaths: [
|
||||
config.bootstrapDir + '/assets/stylesheets'
|
||||
]
|
||||
})
|
||||
.on('error', sass.logError))
|
||||
.pipe(sourcemaps.write('./maps'))
|
||||
}).on('error', sass.logError))
|
||||
.pipe(gulpif(!argv.production, sourcemaps.write('./maps')))
|
||||
.pipe(gulpif(argv.production, minifyCss()))
|
||||
.pipe(gulp.dest('./build/css'))
|
||||
.pipe(browserSync.stream());;
|
||||
.pipe(browserSync.stream());
|
||||
});
|
||||
|
||||
gulp.task('sass:watch', function () {
|
||||
@ -87,13 +98,13 @@ gulp.task('sass:watch', function () {
|
||||
});
|
||||
|
||||
gulp.task('copy', function () {
|
||||
var files = [
|
||||
var staticAssets = [
|
||||
'./fonts/**/*',
|
||||
'./img/**/*'
|
||||
];
|
||||
|
||||
gulp.src(files, {base: './'})
|
||||
.pipe(gulp.dest('build'));
|
||||
gulp.src(staticAssets, {base: './'})
|
||||
.pipe(gulp.dest('./build'));
|
||||
|
||||
gulp.src(config.bootstrapDir + '/assets/fonts/**/*')
|
||||
.pipe(gulp.dest('./build/fonts'));
|
||||
@ -117,6 +128,7 @@ gulp.task('lint:watch', function () {
|
||||
|
||||
function bundle(watch) {
|
||||
var bro;
|
||||
|
||||
if (watch) {
|
||||
bro = watchify(browserify('./js/app.js',
|
||||
// Assigning debug to have sourcemaps
|
||||
@ -141,11 +153,12 @@ function bundle(watch) {
|
||||
.on('error', notify.onError('Error: <%= error.message %>'))
|
||||
.pipe(source('app.js'))
|
||||
.pipe(buffer())
|
||||
.pipe(sourcemaps.init({
|
||||
.pipe(gulpif(!argv.production, sourcemaps.init({
|
||||
loadMaps: true
|
||||
})) // loads map from browserify file
|
||||
.pipe(sourcemaps.write()) // writes .map file
|
||||
.pipe(gulp.dest('./build'))
|
||||
}))) // loads map from browserify file
|
||||
.pipe(gulpif(!argv.production, sourcemaps.write())) // writes .map file
|
||||
.pipe(gulpif(argv.production, uglify({mangle: false})))
|
||||
.pipe(gulp.dest('./build/js'))
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
|
@ -6,11 +6,10 @@
|
||||
<title>ascribe</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="//brick.a.ssl.fastly.net/Source+Sans+Pro:400,600,700,900">
|
||||
<link rel="stylesheet" href="build/css/main.css">
|
||||
<link rel="stylesheet" href="/static/css/main.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="main" class="container"></div>
|
||||
<div id="modal" class="container"></div>
|
||||
<script src="build/app.js"></script>
|
||||
<script src="/static/js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
16
js/actions/global_notification_actions.js
Normal file
16
js/actions/global_notification_actions.js
Normal file
@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
|
||||
|
||||
class GlobalNotificationActions {
|
||||
constructor() {
|
||||
this.generateActions(
|
||||
'appendGlobalNotification',
|
||||
'shiftGlobalNotification',
|
||||
'emulateEmptyStore'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default alt.createActions(GlobalNotificationActions);
|
@ -26,7 +26,7 @@ fetch.defaults({
|
||||
}
|
||||
});
|
||||
|
||||
Router.run(routes, Router.HashLocation, (AscribeApp) => {
|
||||
Router.run(routes, Router.HistoryLocation, (AscribeApp) => {
|
||||
React.render(
|
||||
<AscribeApp />,
|
||||
document.getElementById('main')
|
||||
|
@ -3,6 +3,7 @@
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
import Header from '../components/header';
|
||||
import GlobalNotification from './global_notification';
|
||||
|
||||
let Link = Router.Link;
|
||||
let RouteHandler = Router.RouteHandler;
|
||||
@ -14,6 +15,8 @@ let AscribeApp = React.createClass({
|
||||
<div>
|
||||
<Header />
|
||||
<RouteHandler />
|
||||
<GlobalNotification />
|
||||
<div id="modal" className="container"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
43
js/components/ascribe_forms/form_piece_extradata.js
Normal file
43
js/components/ascribe_forms/form_piece_extradata.js
Normal file
@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import apiUrls from '../../constants/api_urls';
|
||||
import FormMixin from '../../mixins/form_mixin';
|
||||
|
||||
import InputTextAreaToggable from './input_textarea_toggable';
|
||||
|
||||
|
||||
let PersonalNoteForm = React.createClass({
|
||||
mixins: [FormMixin],
|
||||
|
||||
url() {
|
||||
return apiUrls.note_notes;
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
return {
|
||||
bitcoin_id: this.getBitcoinIds().join(),
|
||||
note: this.refs.personalNote.state.value
|
||||
};
|
||||
},
|
||||
|
||||
renderForm() {
|
||||
|
||||
return (
|
||||
<form id="personal_note_content" role="form" key="personal_note_content">
|
||||
<InputTextAreaToggable
|
||||
ref="personalNote"
|
||||
className="form-control"
|
||||
defaultValue={this.props.editions[0].note_from_user}
|
||||
rows={3}
|
||||
editable={true}
|
||||
required=""
|
||||
onSubmit={this.submit}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default PersonalNoteForm;
|
@ -46,8 +46,8 @@ let Image = React.createClass({
|
||||
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')
|
||||
this.inject('/static/thirdparty/shmui/shmui.css'),
|
||||
this.inject('/static/thirdparty/shmui/jquery.shmui.js')
|
||||
]).then(() => { window.jQuery('.shmui-ascribe').shmui(); }));
|
||||
},
|
||||
|
||||
|
@ -1,45 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import LoanForm from '../ascribe_forms/form_loan';
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
|
||||
let LoanModalButton = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<OverlayTrigger delay={500} placement="left"
|
||||
overlay={<Tooltip>Loan your artwork for a limited period of time</Tooltip>}>
|
||||
<ModalTrigger modal={<LoanModal edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}/>}>
|
||||
<div className="btn btn-ascribe-inv">
|
||||
LOAN
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let LoanModal = React.createClass({
|
||||
mixins: [ModalMixin],
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal {...this.props} title="Loan artwork">
|
||||
<div className="modal-body">
|
||||
<LoanForm edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default LoanModalButton;
|
@ -1,44 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
import ShareForm from '../ascribe_forms/form_share_email';
|
||||
|
||||
let ShareModalButton = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<OverlayTrigger delay={500} placement="left" overlay={<Tooltip>Share the artwork</Tooltip>}>
|
||||
<ModalTrigger modal={<ShareModal edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}/>}>
|
||||
<div className="btn btn-ascribe-inv btn-glyph-ascribe">
|
||||
<span className="glyph-ascribe-share2"></span>
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let ShareModal = React.createClass({
|
||||
mixins: [ModalMixin],
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal {...this.props} title="Share artwork">
|
||||
<div className="modal-body">
|
||||
<ShareForm edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default ShareModalButton;
|
@ -1,45 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import UnConsignForm from '../ascribe_forms/form_unconsign';
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
|
||||
let UnConsignModalButton = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<OverlayTrigger delay={500} placement="left"
|
||||
overlay={<Tooltip>Unconsign this artwork</Tooltip>}>
|
||||
<ModalTrigger modal={<UnConsignModal edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}/>}>
|
||||
<div className="btn btn-ascribe-inv">
|
||||
UNCONSIGN
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let UnConsignModal = React.createClass({
|
||||
mixins: [ModalMixin],
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal {...this.props} title="Consign artwork">
|
||||
<div className="modal-body">
|
||||
<UnConsignForm edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default UnConsignModalButton;
|
@ -1,45 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import UnConsignRequestForm from '../ascribe_forms/form_unconsign_request';
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
|
||||
let UnConsignRequestModalButton = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<OverlayTrigger delay={500} placement="left"
|
||||
overlay={<Tooltip>Request to unconsign the artwork</Tooltip>}>
|
||||
<ModalTrigger modal={<UnConsignRequestModal edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}/>}>
|
||||
<div className="btn btn-ascribe-inv">
|
||||
UNCONSIGN REQUEST
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let UnConsignRequestModal = React.createClass({
|
||||
mixins: [ModalMixin],
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal {...this.props} title="Request to unconsign artwork">
|
||||
<div className="modal-body">
|
||||
<UnConsignRequestForm edition={this.props.edition}
|
||||
currentUser={this.props.currentUser}
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default UnConsignRequestModalButton;
|
@ -13,6 +13,7 @@ import UserActions from '../../actions/user_actions';
|
||||
import PieceListBulkModalSelectedEditionsWidget from './piece_list_bulk_modal_selected_editions_widget';
|
||||
import AclButtonList from '../ascribe_buttons/acl_button_list';
|
||||
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
let PieceListBulkModal = React.createClass({
|
||||
propTypes: {
|
||||
@ -92,7 +93,7 @@ let PieceListBulkModal = React.createClass({
|
||||
.forEach((pieceId) => {
|
||||
EditionListActions.fetchEditionList(pieceId, this.state.orderBy, this.state.orderAsc);
|
||||
});
|
||||
|
||||
GlobalNotificationActions.updateGlobalNotification({message: 'Transfer successful'});
|
||||
EditionListActions.clearAllEditionSelections();
|
||||
},
|
||||
|
||||
|
73
js/components/global_notification.js
Normal file
73
js/components/global_notification.js
Normal file
@ -0,0 +1,73 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import GlobalNotificationStore from '../stores/global_notification_store';
|
||||
|
||||
import Row from 'react-bootstrap/lib/Row';
|
||||
import Col from 'react-bootstrap/lib/Col';
|
||||
|
||||
let GlobalNotification = React.createClass({
|
||||
|
||||
componentDidMount() {
|
||||
GlobalNotificationStore.listen(this.onChange);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
GlobalNotificationStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
getInititalState() {
|
||||
return this.extractFirstElem(GlobalNotificationStore.getState().notificationQue);
|
||||
},
|
||||
|
||||
extractFirstElem(l) {
|
||||
return l.length > 0 ? l[0] : null;
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
let notification = this.extractFirstElem(state.notificationQue);
|
||||
|
||||
if(notification) {
|
||||
this.setState(notification);
|
||||
} else {
|
||||
this.replaceState(null);
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
let notificationClass = 'ascribe-global-notification ';
|
||||
let message = this.state && this.state.message ? this.state.message : null;
|
||||
|
||||
if(message) {
|
||||
let colors = {
|
||||
warning: '#f0ad4e',
|
||||
success: '#5cb85c',
|
||||
info: 'rgba(2, 182, 163, 1)',
|
||||
danger: '#d9534f'
|
||||
};
|
||||
|
||||
let text = (<div style={{color: colors[this.state.type]}}>{message ? message : null}</div>);
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Col>
|
||||
<div className={notificationClass + 'ascribe-global-notification-on'}>
|
||||
{text}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Row>
|
||||
<Col>
|
||||
<div className={notificationClass + 'ascribe-global-notification-off'} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default GlobalNotification;
|
@ -38,7 +38,7 @@ let Header = React.createClass({
|
||||
return (
|
||||
<Navbar>
|
||||
<Nav>
|
||||
<a className="navbar-brand" href="#">
|
||||
<a className="navbar-brand" href="/">
|
||||
<span>ascribe </span>
|
||||
<span className="glyph-ascribe-spool-chunked ascribe-color"></span>
|
||||
</a>
|
||||
|
19
js/models/global_notification_model.js
Normal file
19
js/models/global_notification_model.js
Normal file
@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
export default class GlobalNotificationModel {
|
||||
constructor(message, type = 'info', dismissAfter = 3500) {
|
||||
if(message) {
|
||||
this.message = message;
|
||||
} else {
|
||||
throw new Error('A notifications message must be defined.');
|
||||
}
|
||||
|
||||
if(type === 'info' || type === 'success' || type === 'warning' || type === 'danger') {
|
||||
this.type = type;
|
||||
} else {
|
||||
throw new Error('A notification\'s type either has to be info, success, warning, danger. Not: ' + type);
|
||||
}
|
||||
|
||||
this.dismissAfter = dismissAfter;
|
||||
}
|
||||
}
|
40
js/stores/global_notification_store.js
Normal file
40
js/stores/global_notification_store.js
Normal file
@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
|
||||
import GlobalNotificationActions from '../actions/global_notification_actions';
|
||||
|
||||
class GlobalNotificationStore {
|
||||
constructor() {
|
||||
this.notificationQue = [];
|
||||
|
||||
this.bindActions(GlobalNotificationActions);
|
||||
}
|
||||
|
||||
onAppendGlobalNotification(newNotification) {
|
||||
let notificationDelay = 0;
|
||||
for(let i = 0; i < this.notificationQue.length; i++) {
|
||||
notificationDelay += this.notificationQue[i].dismissAfter;
|
||||
}
|
||||
|
||||
this.notificationQue.push(newNotification);
|
||||
setTimeout(GlobalNotificationActions.emulateEmptyStore, notificationDelay + newNotification.dismissAfter);
|
||||
}
|
||||
|
||||
onEmulateEmptyStore() {
|
||||
let actualNotificitionQue = this.notificationQue.slice();
|
||||
|
||||
this.notificationQue = [];
|
||||
|
||||
setTimeout(() => {
|
||||
this.notificationQue = actualNotificitionQue.slice();
|
||||
GlobalNotificationActions.shiftGlobalNotification();
|
||||
}, 400);
|
||||
}
|
||||
|
||||
onShiftGlobalNotification() {
|
||||
this.notificationQue.shift();
|
||||
}
|
||||
}
|
||||
|
||||
export default alt.createStore(GlobalNotificationStore);
|
@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
import PieceAction from '../actions/piece_actions';
|
||||
import PieceActions from '../actions/piece_actions';
|
||||
|
||||
|
||||
class PieceStore {
|
||||
constructor() {
|
||||
this.piece = {};
|
||||
this.bindActions(PieceAction);
|
||||
this.bindActions(PieceActions);
|
||||
}
|
||||
|
||||
onUpdatePiece(piece) {
|
||||
|
50
package.json
50
package.json
@ -3,47 +3,71 @@
|
||||
"version": "0.0.1",
|
||||
"description": "Das neue web client for Ascribe",
|
||||
"main": "js/app.js",
|
||||
"engines": {
|
||||
"node": "0.10.x"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint ./js",
|
||||
"postinstall": "npm run build",
|
||||
"build": "gulp build --production",
|
||||
"start": "node server.js"
|
||||
},
|
||||
"author": "Ascribe",
|
||||
"license": "Copyright",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^3.1.11",
|
||||
"babel-jest": "^5.2.0",
|
||||
"jest-cli": "^0.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"alt": "^0.16.5",
|
||||
"babelify": "^6.1.2",
|
||||
"bootstrap-sass": "^3.3.4",
|
||||
"browser-sync": "^2.7.5",
|
||||
"browserify": "^9.0.8",
|
||||
"browser-sync": "^2.7.5",
|
||||
"classnames": "^1.2.2",
|
||||
"compression": "^1.4.4",
|
||||
"envify": "^3.4.0",
|
||||
"es6-promise": "^2.1.1",
|
||||
"eslint": "^0.22.1",
|
||||
"eslint-plugin-react": "^2.5.0",
|
||||
"express": "^4.12.4",
|
||||
"gulp": "^3.8.11",
|
||||
"gulp-concat": "^2.5.2",
|
||||
"gulp-eslint": "^0.13.2",
|
||||
"gulp-if": "^1.2.5",
|
||||
"gulp-minify-css": "^1.1.6",
|
||||
"gulp-notify": "^2.2.0",
|
||||
"gulp-sass": "^2.0.1",
|
||||
"gulp-sourcemaps": "^1.5.2",
|
||||
"gulp-uglify": "^1.2.0",
|
||||
"gulp-util": "^3.0.4",
|
||||
"harmonize": "^1.4.2",
|
||||
"isomorphic-fetch": "^2.0.2",
|
||||
"jest-cli": "^0.4.0",
|
||||
"lodash": "^3.9.3",
|
||||
"react-textarea-autosize": "^2.2.3",
|
||||
"reactify": "^1.1.0",
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0",
|
||||
"watchify": "^3.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"alt": "^0.16.5",
|
||||
"classnames": "^1.2.2",
|
||||
"es6-promise": "^2.1.1",
|
||||
"isomorphic-fetch": "^2.0.2",
|
||||
"object-assign": "^2.0.0",
|
||||
"react": "^0.13.2",
|
||||
"react-bootstrap": "~0.22.6",
|
||||
"react-datepicker": "~0.8.0",
|
||||
"reactify": "^1.1.0",
|
||||
"react-router": "^0.13.3",
|
||||
"react-textarea-autosize": "^2.2.3",
|
||||
"shmui": "^0.1.0",
|
||||
"uglifyjs": "^2.4.10"
|
||||
"uglifyjs": "^2.4.10",
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0",
|
||||
"watchify": "^3.1.2",
|
||||
"yargs": "^3.10.0"
|
||||
},
|
||||
"jest": {
|
||||
"scriptPreprocessor": "node_modules/babel-jest",
|
||||
"unmockedModulePathPatterns": [
|
||||
"<rootDir>/node_modules/react",
|
||||
"<rootDir>/node_modules/alt",
|
||||
"<rootDir>/js/alt.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
@font-face {
|
||||
font-family: 'ascribe';
|
||||
src:url('../../fonts/ascribe.eot?-oi6ttk');
|
||||
src:url('../../fonts/ascribe.eot?#iefix-oi6ttk') format('embedded-opentype'),
|
||||
url('../../fonts/ascribe.woff?-oi6ttk') format('woff'),
|
||||
url('../../fonts/ascribe.ttf?-oi6ttk') format('truetype'),
|
||||
url('../../fonts/ascribe.svg?-oi6ttk#ascribe') format('svg');
|
||||
src:url('/static/fonts/ascribe.eot?-oi6ttk');
|
||||
src:url('/static/fonts/ascribe.eot?#iefix-oi6ttk') format('embedded-opentype'),
|
||||
url('/static/fonts/ascribe.woff?-oi6ttk') format('woff'),
|
||||
url('/static/fonts/ascribe.ttf?-oi6ttk') format('truetype'),
|
||||
url('/static/fonts/ascribe.svg?-oi6ttk#ascribe') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
29
sass/ascribe-global-notification.scss
Normal file
29
sass/ascribe-global-notification.scss
Normal file
@ -0,0 +1,29 @@
|
||||
.ascribe-global-notification {
|
||||
position: fixed;
|
||||
|
||||
background-color: #212121;
|
||||
width: 100%;
|
||||
height:3.5em;
|
||||
left:0;
|
||||
display:table;
|
||||
|
||||
transition: .2s bottom cubic-bezier(0.77, 0, 0.175, 1);
|
||||
}
|
||||
|
||||
.ascribe-global-notification-off {
|
||||
bottom: -3.5em;
|
||||
}
|
||||
|
||||
.ascribe-global-notification-on {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.ascribe-global-notification > div {
|
||||
display:table-cell;
|
||||
vertical-align: middle;
|
||||
color: $ascribe-color-full;
|
||||
font-size: 1.25em;
|
||||
font-family: 'Source Sans Pro';
|
||||
text-align: right;
|
||||
padding-right: 3em;
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
$ascribe-color: rgba(2, 182, 163, 0.5);
|
||||
$ascribe-color-dark: rgba(2, 182, 163, 0.8);
|
||||
$ascribe-color-full: rgba(2, 182, 163, 1);
|
@ -12,6 +12,7 @@
|
||||
@import 'ascribe_edition';
|
||||
@import 'ascribe_textarea';
|
||||
@import 'ascribe_media_player';
|
||||
@import 'ascribe-global-notification';
|
||||
@import 'offset_right';
|
||||
|
||||
.hidden {
|
||||
|
21
server.js
Normal file
21
server.js
Normal file
@ -0,0 +1,21 @@
|
||||
var express = require('express');
|
||||
var compression = require('compression')
|
||||
|
||||
var app = express();
|
||||
|
||||
app.use(compression());
|
||||
|
||||
app.use('/static/js', express.static(__dirname + '/build/js'));
|
||||
app.use('/static/css', express.static(__dirname + '/build/css'));
|
||||
app.use('/static/fonts', express.static(__dirname + '/build/fonts'));
|
||||
app.use('/static/thirdparty/', express.static(__dirname + '/node_modules'));
|
||||
|
||||
app.get(/.*/, function(req, res) {
|
||||
res.sendFile(__dirname + '/index.html');
|
||||
});
|
||||
|
||||
if (require.main === module) {
|
||||
app.listen(process.env.PORT || 4000);
|
||||
}
|
||||
|
||||
module.exports.app = app;
|
Loading…
Reference in New Issue
Block a user