refactor load/save state, add favicon

This commit is contained in:
Adam Brown 2016-12-17 00:26:04 -05:00
parent 720f123977
commit d66292047f
16 changed files with 169 additions and 7147 deletions

View File

@ -1516,12 +1516,25 @@ throw new Error(message);}catch(x){}}};}module.exports=warning;
/***/ function(module, exports, __webpack_require__) {
"use strict";
'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.save=exports.showDifference=exports.showFinal=exports.showOriginal=exports.setMarkdownFormat=exports.setPlaintextFormat=exports.clearInput=exports.updateFinalInput=exports.updateOriginalInput=undefined;var _isomorphicFetch=__webpack_require__(1214);var _isomorphicFetch2=_interopRequireDefault(_isomorphicFetch);var _v=__webpack_require__(566);var _v2=_interopRequireDefault(_v);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}var updateOriginalInput=exports.updateOriginalInput=function updateOriginalInput(text){return function(dispatch,getState){dispatch({type:'UPDATE_ORIGINAL_INPUT',data:text});if(getState().input.original.length>0)dispatch({type:'SAVE_STATUS_DIRTY'});else dispatch({type:'SAVE_STATUS_EMPTY'});};};var updateFinalInput=exports.updateFinalInput=function updateFinalInput(text){return function(dispatch,getState){dispatch({type:'UPDATE_FINAL_INPUT',data:text});if(getState().input.final.length>0)dispatch({type:'SAVE_STATUS_DIRTY'});else dispatch({type:'SAVE_STATUS_EMPTY'});};};var clearInput=exports.clearInput=function clearInput(){return function(dispatch){dispatch({type:'CLEAR_INPUT'});dispatch({type:'SAVE_STATUS_EMPTY'});};};var setPlaintextFormat=exports.setPlaintextFormat=function setPlaintextFormat(){return{type:'SET_PLAINTEXT_FORMAT'};};var setMarkdownFormat=exports.setMarkdownFormat=function setMarkdownFormat(){return{type:'SET_MARKDOWN_FORMAT'};};var showOriginal=exports.showOriginal=function showOriginal(){return{type:'SHOW_ORIGINAL'};};var showFinal=exports.showFinal=function showFinal(){return{type:'SHOW_FINAL'};};var showDifference=exports.showDifference=function showDifference(){return{type:'SHOW_DIFFERENCE'};};//saves the current input fields to the server
//creates and returns a new id for the
'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.save=exports.edit=exports.reset=exports.compare=exports.showDifference=exports.showFinal=exports.showOriginal=exports.setMarkdownFormat=exports.setPlaintextFormat=exports.clearInput=exports.updateFinalInput=exports.updateOriginalInput=undefined;var _isomorphicFetch=__webpack_require__(1214);var _isomorphicFetch2=_interopRequireDefault(_isomorphicFetch);var _v=__webpack_require__(566);var _v2=_interopRequireDefault(_v);var _reactRouter=__webpack_require__(84);var _constants=__webpack_require__(570);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}//All state transitions in the app happen in these methods
//this includes redux state changes, asyncronous data requests, and browser location changes
var updateOriginalInput=exports.updateOriginalInput=function updateOriginalInput(text){return function(dispatch,getState){dispatch({type:'UPDATE_ORIGINAL_INPUT',data:text});if(getState().input.original.length>0)dispatch({type:'STATUS_SET',data:_constants.Status.DIRTY});else dispatch({type:'STATUS_SET',data:_constants.Status.EMPTY});};};var updateFinalInput=exports.updateFinalInput=function updateFinalInput(text){return function(dispatch,getState){dispatch({type:'UPDATE_FINAL_INPUT',data:text});if(getState().input.final.length>0)dispatch({type:'STATUS_SET',data:_constants.Status.DIRTY});else dispatch({type:'STATUS_SET',data:_constants.Status.EMPTY});};};var clearInput=exports.clearInput=function clearInput(){return function(dispatch){dispatch({type:'CLEAR_INPUT'});dispatch({type:'STATUS_SET',data:_constants.Status.EMPTY});};};var setPlaintextFormat=exports.setPlaintextFormat=function setPlaintextFormat(){return{type:'SET_PLAINTEXT_FORMAT'};};var setMarkdownFormat=exports.setMarkdownFormat=function setMarkdownFormat(){return{type:'SET_MARKDOWN_FORMAT'};};var showOriginal=exports.showOriginal=function showOriginal(){return{type:'SHOW_ORIGINAL'};};var showFinal=exports.showFinal=function showFinal(){return{type:'SHOW_FINAL'};};var showDifference=exports.showDifference=function showDifference(){return{type:'SHOW_DIFFERENCE'};};//if the input is dirty, saves it to the server
//creates a new uuid for the same,
//then changes the browser location to a comparison view with that id
var compare=exports.compare=function compare(){return function(dispatch,getState){//!!! could test that the input is dirty before triggering a save
//if the input is empty, the compare should do nothing
//if the input is clean, the compare should not save and keep using the same id
//start saving the input to the server
var id=dispatch(save());//we can use the id created by the save method to build a path
var comparePath='/'+id;_reactRouter.browserHistory.replace(comparePath);};};//clear the input and return to the edit page
var reset=exports.reset=function reset(){return function(dispatch,getState){dispatch(clearInput());_reactRouter.browserHistory.push('/');};};//switch to the edit view
var edit=exports.edit=function edit(){return function(dispatch,getState){_reactRouter.browserHistory.push('/');};};//saves the current input fields to the server
//creates and returns a new id for the comparison
//should this method ensure that the initial state is valid? ('DIRTY')
var save=exports.save=function save(){return function(dispatch,getState){//generate an id
var id=(0,_v2.default)();//set waiting state
dispatch({type:'SAVE_STATUS_WAITING'});var endpointUri='/api/compare/'+id;var fetchOptions={method:'POST',body:JSON.stringify({a:getState().input.original,b:getState().input.final}),headers:{"Content-Type":"application/json"}};//dispatch post request
(0,_isomorphicFetch2.default)(endpointUri,fetchOptions).then(function(response){dispatch({type:'SAVE_STATUS_SAVED'});}).catch(function(error){dispatch({type:'SAVE_STATUS_FAILED',error:error});});//return the id after the request has been sent
dispatch({type:'STATUS_SET',data:_constants.Status.SAVING});var endpointUri='/api/compare/'+id;var fetchOptions={method:'POST',body:JSON.stringify({a:getState().input.original,b:getState().input.final}),headers:{"Content-Type":"application/json"}};//dispatch post request
(0,_isomorphicFetch2.default)(endpointUri,fetchOptions).then(function(response){dispatch({type:'STATUS_SET',data:_constants.Status.CLEAN});}).catch(function(error){dispatch({type:'STATUS_SET',data:_constants.Status.DIRTY});dispatch({type:'STATUS_SET_ERROR',data:_constants.StatusError.SAVE_ERROR,error:error});});//return the id after the request has been sent
return id;};};/*
const load = (id) =>
(dispatch, getState) => {
@ -9782,14 +9795,14 @@ if(buf){for(var ii=0;ii<16;++ii){buf[i+ii]=rnds[ii];}}return buf||bytesToUuid(rn
/***/ function(module, exports, __webpack_require__) {
"use strict";
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _react=__webpack_require__(0);var _react2=_interopRequireDefault(_react);var _reactRedux=__webpack_require__(69);var _semanticUiReact=__webpack_require__(80);var _reactRouter=__webpack_require__(84);var _actions=__webpack_require__(70);var Actions=_interopRequireWildcard(_actions);var _SaveStatus=__webpack_require__(1180);var _SaveStatus2=_interopRequireDefault(_SaveStatus);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}var mapStateToProps=function mapStateToProps(state){return{};};var mapDispatchToProps=function mapDispatchToProps(dispatch){return{onClear:function onClear(){dispatch(Actions.clearInput());dispatch(Actions.clearCompare());}};};var SiteHeader=function SiteHeader(props){return _react2.default.createElement(_semanticUiReact.Segment,{basic:true},_react2.default.createElement(_semanticUiReact.Segment,{basic:true,padded:true,textAlign:'center',as:'header',id:'masthead'},_react2.default.createElement(_semanticUiReact.Header,null,_react2.default.createElement(_reactRouter.Link,{onClick:props.onClear,to:'/'},'dubdiff'))),_react2.default.createElement(_semanticUiReact.Rail,{internal:true,position:'right'},_react2.default.createElement(_semanticUiReact.Segment,{basic:true,padded:true},_react2.default.createElement(_SaveStatus2.default,null))));};exports.default=(0,_reactRedux.connect)(mapStateToProps,mapDispatchToProps)(SiteHeader);
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _react=__webpack_require__(0);var _react2=_interopRequireDefault(_react);var _reactRedux=__webpack_require__(69);var _semanticUiReact=__webpack_require__(80);var _reactRouter=__webpack_require__(84);var _actions=__webpack_require__(70);var Actions=_interopRequireWildcard(_actions);var _SaveStatus=__webpack_require__(1180);var _SaveStatus2=_interopRequireDefault(_SaveStatus);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}var mapStateToProps=function mapStateToProps(state){return{};};var mapDispatchToProps=function mapDispatchToProps(dispatch){return{onReset:function onReset(){console.log(Actions.reset());dispatch(Actions.reset());}};};var SiteHeader=function SiteHeader(props){return _react2.default.createElement(_semanticUiReact.Segment,{basic:true},_react2.default.createElement(_semanticUiReact.Segment,{basic:true,padded:true,textAlign:'center',as:'header',id:'masthead'},_react2.default.createElement(_semanticUiReact.Header,null,_react2.default.createElement(_reactRouter.Link,{onClick:props.onReset},'dubdiff'))),_react2.default.createElement(_semanticUiReact.Rail,{internal:true,position:'right'},_react2.default.createElement(_semanticUiReact.Segment,{basic:true,padded:true},_react2.default.createElement(_SaveStatus2.default,null))));};exports.default=(0,_reactRedux.connect)(mapStateToProps,mapDispatchToProps)(SiteHeader);
/***/ },
/* 570 */
/***/ function(module, exports) {
"use strict";
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var Format=exports.Format={PLAINTEXT:'PLAINTEXT',MARKDOWN:'MARKDOWN'};var Show=exports.Show={ORIGINAL:'ORIGINAL',FINAL:'FINAL',DIFFERENCE:'DIFFERENCE'};
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var Format=exports.Format={PLAINTEXT:'PLAINTEXT',MARKDOWN:'MARKDOWN'};var Show=exports.Show={ORIGINAL:'ORIGINAL',FINAL:'FINAL',DIFFERENCE:'DIFFERENCE'};var Status=exports.Status={INIT:'INIT',LOADING:'LOADING',EMPTY:'EMPTY',CLEAN:'CLEAN',DIRTY:'DIRTY',SAVING:'SAVING'};var StatusError=exports.StatusError={LOADING_ERROR:'LOAD_ERROR',SAVING_ERROR:'SAVE_ERROR'};
/***/ },
/* 571 */
@ -9878,20 +9891,28 @@ function(acc,x,i){return test(x)?acc.concat([i]):acc;},//start with the empty ar
/***/ function(module, exports, __webpack_require__) {
"use strict";
'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.input=input;exports.format=format;exports.show=show;exports.saveStatus=saveStatus;var _constants=__webpack_require__(570);function input(state,action){switch(action.type){case'UPDATE_ORIGINAL_INPUT':return Object.assign({},state,{original:action.data});case'UPDATE_FINAL_INPUT':return Object.assign({},state,{final:action.data});case'CLEAR_INPUT':return{original:'',final:''};default:return state||{original:'',final:''};}}function format(state,action){switch(action.type){case'SET_PLAINTEXT_FORMAT':return _constants.Format.PLAINTEXT;case'SET_MARKDOWN_FORMAT':return _constants.Format.MARKDOWN;default:return state||_constants.Format.PLAINTEXT;}}function show(state,action){switch(action.type){case'SHOW_ORIGINAL':return _constants.Show.ORIGINAL;case'SHOW_FINAL':return _constants.Show.FINAL;case'SHOW_DIFFERENCE':return _constants.Show.DIFFERENCE;default:return state||_constants.Show.DIFFERENCE;}}function saveStatus(state,action){switch(action.type){case'SAVE_STATUS_DIRTY':return{dirty:true};case'SAVE_STATUS_EMPTY':return{dirty:false,empty:true};case'SAVE_STATUS_SAVED':return{dirty:false,saved:true};case'SAVE_STATUS_FAILED':return Object.assign({},state,{waiting:false,failed:true,error:action.error});case'SAVE_STATUS_WAITING':return Object.assign({},state,{waiting:true,failed:false,error:null});default:return state||{empty:true,dirty:false};}}/*
export function loadStatus (state, action) {
'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.input=input;exports.format=format;exports.show=show;exports.status=status;var _constants=__webpack_require__(570);function input(state,action){switch(action.type){case'UPDATE_ORIGINAL_INPUT':return Object.assign({},state,{original:action.data});case'UPDATE_FINAL_INPUT':return Object.assign({},state,{final:action.data});case'CLEAR_INPUT':return{original:'',final:''};default:return state||{original:'',final:''};}}function format(state,action){switch(action.type){case'SET_PLAINTEXT_FORMAT':return _constants.Format.PLAINTEXT;case'SET_MARKDOWN_FORMAT':return _constants.Format.MARKDOWN;default:return state||_constants.Format.PLAINTEXT;}}function show(state,action){switch(action.type){case'SHOW_ORIGINAL':return _constants.Show.ORIGINAL;case'SHOW_FINAL':return _constants.Show.FINAL;case'SHOW_DIFFERENCE':return _constants.Show.DIFFERENCE;default:return state||_constants.Show.DIFFERENCE;}}/*
export function saveStatus (state, action) {
switch (action.type) {
case 'LOAD_STATUS_WAITING':
return {waiting: true}
case 'LOAD_STATUS_FAILED':
return {failed: true, error: action.error }
case 'LOAD_STATUS_LOADED':
return {loaded: true}
case 'SAVE_STATUS_DIRTY':
return {dirty: true}
case 'SAVE_STATUS_EMPTY':
return {dirty: false, empty: true}
case 'SAVE_STATUS_SAVED':
return {dirty: false, saved: true}
case 'SAVE_STATUS_FAILED' :
return Object.assign({}, state, {waiting: false, failed: true, error: action.error})
case 'SAVE_STATUS_WAITING' :
return Object.assign({}, state, {waiting: true, failed: false, error: null})
default:
return state || {waiting: false}
return state || {empty: true, dirty:false}
}
}
*/
*///tracks status of the app, especially with respect to loaded and saved user data
function status(state,action){//the status or error type is valid if it is in the list of Status or StatusError types
var isValidStatus=function isValidStatus(type){return _constants.Status[type]==type;};var isValidError=function isValidError(type){return _constants.StatusError[type]==type;};//the error is cleared when status changes
if(action.type=='STATUS_SET'&&isValidStatus(action.data))return{type:action.data,error:null,hasError:false,errorType:null};//the error is set in addition to the status
else if(action.type=='STATUS_SET_ERROR'&&isValidError(action.data))return Object.assign({},state,{error:action.error,hasError:true,errorType:action.data});else return{type:_constants.Status.EMPTY,hasError:false,error:null};}
/***/ },
/* 575 */
@ -20807,7 +20828,7 @@ module.exports=wrappy;function wrappy(fn,cb){if(fn&&cb)return wrappy(fn)(cb);if(
/***/ function(module, exports, __webpack_require__) {
"use strict";
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};}();var _react=__webpack_require__(0);var _react2=_interopRequireDefault(_react);var _reactRedux=__webpack_require__(69);var _reactRouter=__webpack_require__(84);var _semanticUiReact=__webpack_require__(80);var _actions=__webpack_require__(70);var Actions=_interopRequireWildcard(_actions);var _selectors=__webpack_require__(196);var Selectors=_interopRequireWildcard(_selectors);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call&&(typeof call==="object"||typeof call==="function")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass);}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;}var mapStateToProps=function mapStateToProps(state){return{isMarkdownFormat:Selectors.isMarkdownFormat(state),isShowOriginal:Selectors.isShowOriginal(state),isShowFinal:Selectors.isShowFinal(state),isShowDifference:Selectors.isShowDifference(state)};};var mapDispatchToProps=function mapDispatchToProps(dispatch){return{onSetPlaintextFormat:function onSetPlaintextFormat(){return dispatch(Actions.setPlaintextFormat());},onSetMarkdownFormat:function onSetMarkdownFormat(){return dispatch(Actions.setMarkdownFormat());},onShowOriginal:function onShowOriginal(){return dispatch(Actions.showOriginal());},onShowFinal:function onShowFinal(){return dispatch(Actions.showFinal());},onShowDifference:function onShowDifference(){return dispatch(Actions.showDifference());},onEdit:function onEdit(){}};};var CompareControls=function(_React$Component){_inherits(CompareControls,_React$Component);function CompareControls(){_classCallCheck(this,CompareControls);return _possibleConstructorReturn(this,(CompareControls.__proto__||Object.getPrototypeOf(CompareControls)).apply(this,arguments));}_createClass(CompareControls,[{key:'onClickEdit',value:function onClickEdit(){this.props.onEdit();}},{key:'onClickMarkdownFormat',value:function onClickMarkdownFormat(){if(this.props.isMarkdownFormat)this.props.onSetPlaintextFormat();else this.props.onSetMarkdownFormat();}},{key:'render',value:function render(){return _react2.default.createElement(_semanticUiReact.Segment.Group,null,_react2.default.createElement(_semanticUiReact.Segment,null,_react2.default.createElement(_reactRouter.Link,{to:'/'},_react2.default.createElement(_semanticUiReact.Button,{fluid:true,onClick:this.onClickEdit.bind(this)},'Edit'))),_react2.default.createElement(_semanticUiReact.Segment,null,_react2.default.createElement(_semanticUiReact.Button,{fluid:true,onClick:this.props.onShowOriginal,active:this.props.isShowOriginal},'Original'),_react2.default.createElement(_semanticUiReact.Button,{fluid:true,onClick:this.props.onShowFinal,active:this.props.isShowFinal},'Final'),_react2.default.createElement(_semanticUiReact.Button,{fluid:true,onClick:this.props.onShowDifference,active:this.props.isShowDifference},'Difference')),_react2.default.createElement(_semanticUiReact.Segment,null,_react2.default.createElement(_semanticUiReact.Button,{fluid:true,active:this.props.isMarkdownFormat,type:'submit',onClick:this.onClickMarkdownFormat.bind(this)},this.props.isMarkdownFormat?_react2.default.createElement(_semanticUiReact.Icon,{name:'checkmark'}):_react2.default.createElement('span',null),'\xA0As Markdown')));}}]);return CompareControls;}(_react2.default.Component);exports.default=(0,_reactRedux.connect)(mapStateToProps,mapDispatchToProps)(CompareControls);
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};}();var _react=__webpack_require__(0);var _react2=_interopRequireDefault(_react);var _reactRedux=__webpack_require__(69);var _reactRouter=__webpack_require__(84);var _semanticUiReact=__webpack_require__(80);var _actions=__webpack_require__(70);var Actions=_interopRequireWildcard(_actions);var _selectors=__webpack_require__(196);var Selectors=_interopRequireWildcard(_selectors);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call&&(typeof call==="object"||typeof call==="function")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass);}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;}var mapStateToProps=function mapStateToProps(state){return{isMarkdownFormat:Selectors.isMarkdownFormat(state),isShowOriginal:Selectors.isShowOriginal(state),isShowFinal:Selectors.isShowFinal(state),isShowDifference:Selectors.isShowDifference(state)};};var mapDispatchToProps=function mapDispatchToProps(dispatch){return{onSetPlaintextFormat:function onSetPlaintextFormat(){return dispatch(Actions.setPlaintextFormat());},onSetMarkdownFormat:function onSetMarkdownFormat(){return dispatch(Actions.setMarkdownFormat());},onShowOriginal:function onShowOriginal(){return dispatch(Actions.showOriginal());},onShowFinal:function onShowFinal(){return dispatch(Actions.showFinal());},onShowDifference:function onShowDifference(){return dispatch(Actions.showDifference());},onEdit:function onEdit(){return dispatch(Actions.edit());}};};var CompareControls=function(_React$Component){_inherits(CompareControls,_React$Component);function CompareControls(){_classCallCheck(this,CompareControls);return _possibleConstructorReturn(this,(CompareControls.__proto__||Object.getPrototypeOf(CompareControls)).apply(this,arguments));}_createClass(CompareControls,[{key:'onClickMarkdownFormat',value:function onClickMarkdownFormat(){if(this.props.isMarkdownFormat)this.props.onSetPlaintextFormat();else this.props.onSetMarkdownFormat();}},{key:'render',value:function render(){return _react2.default.createElement(_semanticUiReact.Segment.Group,null,_react2.default.createElement(_semanticUiReact.Segment,null,_react2.default.createElement(_semanticUiReact.Button,{fluid:true,onClick:this.props.onEdit},'Edit')),_react2.default.createElement(_semanticUiReact.Segment,null,_react2.default.createElement(_semanticUiReact.Button,{fluid:true,onClick:this.props.onShowOriginal,active:this.props.isShowOriginal},'Original'),_react2.default.createElement(_semanticUiReact.Button,{fluid:true,onClick:this.props.onShowFinal,active:this.props.isShowFinal},'Final'),_react2.default.createElement(_semanticUiReact.Button,{fluid:true,onClick:this.props.onShowDifference,active:this.props.isShowDifference},'Difference')),_react2.default.createElement(_semanticUiReact.Segment,null,_react2.default.createElement(_semanticUiReact.Button,{fluid:true,active:this.props.isMarkdownFormat,type:'submit',onClick:this.onClickMarkdownFormat.bind(this)},this.props.isMarkdownFormat?_react2.default.createElement(_semanticUiReact.Icon,{name:'checkmark'}):_react2.default.createElement('span',null),'\xA0As Markdown')));}}]);return CompareControls;}(_react2.default.Component);exports.default=(0,_reactRedux.connect)(mapStateToProps,mapDispatchToProps)(CompareControls);
/***/ },
/* 1178 */
@ -20821,10 +20842,8 @@ module.exports=wrappy;function wrappy(fn,cb){if(fn&&cb)return wrappy(fn)(cb);if(
/***/ function(module, exports, __webpack_require__) {
"use strict";
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};}();var _react=__webpack_require__(0);var _react2=_interopRequireDefault(_react);var _reactRedux=__webpack_require__(69);var _reactRouter=__webpack_require__(84);var _semanticUiReact=__webpack_require__(80);var _actions=__webpack_require__(70);var Actions=_interopRequireWildcard(_actions);var _selectors=__webpack_require__(196);var Selectors=_interopRequireWildcard(_selectors);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call&&(typeof call==="object"||typeof call==="function")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass);}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;}var mapStateToProps=function mapStateToProps(state){return{format:state.format,isMarkdownFormat:Selectors.isMarkdownFormat(state),saveStatus:state.saveStatus};};var mapDispatchToProps=function mapDispatchToProps(dispatch){return{onSetPlaintextFormat:function onSetPlaintextFormat(format){return dispatch(Actions.setPlaintextFormat());},onSetMarkdownFormat:function onSetMarkdownFormat(format){return dispatch(Actions.setMarkdownFormat());},//returns an id for the record to be saved
startSaveAsync:function startSaveAsync(){return dispatch(Actions.save());}};};var MainControls=function(_React$Component){_inherits(MainControls,_React$Component);function MainControls(){_classCallCheck(this,MainControls);return _possibleConstructorReturn(this,(MainControls.__proto__||Object.getPrototypeOf(MainControls)).apply(this,arguments));}_createClass(MainControls,[{key:'onClickCompare',value:function onClickCompare(){//start saving the input to the server
var id=this.props.startSaveAsync();//we can use the id created by the save method to build a path
var comparePath='/'+id;_reactRouter.browserHistory.replace(comparePath);return false;}},{key:'onClickMarkdownFormat',value:function onClickMarkdownFormat(){if(this.props.isMarkdownFormat)this.props.onSetPlaintextFormat();else this.props.onSetMarkdownFormat();}},{key:'render',value:function render(){return _react2.default.createElement(_semanticUiReact.Segment.Group,null,_react2.default.createElement(_semanticUiReact.Segment,null,_react2.default.createElement(_semanticUiReact.Button,{fluid:true,onClick:this.onClickCompare.bind(this)},'Compare')),_react2.default.createElement(_semanticUiReact.Segment,null,_react2.default.createElement(_semanticUiReact.Button,{fluid:true,active:this.props.isMarkdownFormat,type:'submit',onClick:this.onClickMarkdownFormat.bind(this)},this.props.isMarkdownFormat?_react2.default.createElement(_semanticUiReact.Icon,{name:'checkmark'}):_react2.default.createElement('span',null),'\xA0As Markdown')));}}]);return MainControls;}(_react2.default.Component);exports.default=(0,_reactRedux.connect)(mapStateToProps,mapDispatchToProps)(MainControls);/*
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};}();var _react=__webpack_require__(0);var _react2=_interopRequireDefault(_react);var _reactRedux=__webpack_require__(69);var _semanticUiReact=__webpack_require__(80);var _actions=__webpack_require__(70);var Actions=_interopRequireWildcard(_actions);var _selectors=__webpack_require__(196);var Selectors=_interopRequireWildcard(_selectors);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call&&(typeof call==="object"||typeof call==="function")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass);}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;}var mapStateToProps=function mapStateToProps(state){return{format:state.format,isMarkdownFormat:Selectors.isMarkdownFormat(state),saveStatus:state.saveStatus};};var mapDispatchToProps=function mapDispatchToProps(dispatch){return{onSetPlaintextFormat:function onSetPlaintextFormat(format){return dispatch(Actions.setPlaintextFormat());},onSetMarkdownFormat:function onSetMarkdownFormat(format){return dispatch(Actions.setMarkdownFormat());},//returns an id for the record to be saved
onCompare:function onCompare(){return dispatch(Actions.compare());}};};var MainControls=function(_React$Component){_inherits(MainControls,_React$Component);function MainControls(){_classCallCheck(this,MainControls);return _possibleConstructorReturn(this,(MainControls.__proto__||Object.getPrototypeOf(MainControls)).apply(this,arguments));}_createClass(MainControls,[{key:'onClickMarkdownFormat',value:function onClickMarkdownFormat(){if(this.props.isMarkdownFormat)this.props.onSetPlaintextFormat();else this.props.onSetMarkdownFormat();}},{key:'render',value:function render(){return _react2.default.createElement(_semanticUiReact.Segment.Group,null,_react2.default.createElement(_semanticUiReact.Segment,null,_react2.default.createElement(_semanticUiReact.Button,{fluid:true,onClick:this.props.onCompare},'Compare')),_react2.default.createElement(_semanticUiReact.Segment,null,_react2.default.createElement(_semanticUiReact.Button,{fluid:true,active:this.props.isMarkdownFormat,type:'submit',onClick:this.onClickMarkdownFormat.bind(this)},this.props.isMarkdownFormat?_react2.default.createElement(_semanticUiReact.Icon,{name:'checkmark'}):_react2.default.createElement('span',null),'\xA0As Markdown')));}}]);return MainControls;}(_react2.default.Component);exports.default=(0,_reactRedux.connect)(mapStateToProps,mapDispatchToProps)(MainControls);/*
<a type="button" onClick={this.onClickCompare.bind(this)} className="btn btn-block btn-primary">compare</a>*/
/***/ },
@ -20832,8 +20851,7 @@ var comparePath='/'+id;_reactRouter.browserHistory.replace(comparePath);return f
/***/ function(module, exports, __webpack_require__) {
"use strict";
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _react=__webpack_require__(0);var _react2=_interopRequireDefault(_react);var _reactRedux=__webpack_require__(69);var _semanticUiReact=__webpack_require__(80);var _reactRouter=__webpack_require__(84);var _actions=__webpack_require__(70);var Actions=_interopRequireWildcard(_actions);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}var mapStateToProps=function mapStateToProps(state){return{saveStatus:state.saveStatus};};var mapDispatchToProps=function mapDispatchToProps(dispatch){return{retrySave:function retrySave(){return dispatch(Actions.save());}};};var onRetrySaveClick=function onRetrySaveClick(props){//we can use the id created by the save method to build a path
var id=props.retrySave();var comparePath='/'+id;_reactRouter.browserHistory.replace(comparePath);return false;};var SaveStatus=function SaveStatus(props){if(props.saveStatus.waiting)return _react2.default.createElement(_semanticUiReact.Message,{size:'tiny',floating:true,compact:true,icon:true},_react2.default.createElement(_semanticUiReact.Icon,{name:'circle notched',loading:true}),_react2.default.createElement(_semanticUiReact.Message.Content,null,_react2.default.createElement(_semanticUiReact.Message.Header,null,'Saving diff')));else if(props.saveStatus.failed)return _react2.default.createElement(_semanticUiReact.Message,{size:'tiny',floating:true,compact:true,icon:true},_react2.default.createElement(_semanticUiReact.Icon,{name:'exclamation'}),_react2.default.createElement(_semanticUiReact.Message.Content,null,_react2.default.createElement(_semanticUiReact.Message.Header,null,'Error saving diff'),'The server returned ',props.saveStatus.error.message,'.',_react2.default.createElement(_semanticUiReact.Button,{onClick:function onClick(){return onRetrySaveClick(props);}},'Retry')));else return _react2.default.createElement('div',null);};exports.default=(0,_reactRedux.connect)(mapStateToProps,mapDispatchToProps)(SaveStatus);
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _react=__webpack_require__(0);var _react2=_interopRequireDefault(_react);var _reactRedux=__webpack_require__(69);var _semanticUiReact=__webpack_require__(80);var _reactRouter=__webpack_require__(84);var _actions=__webpack_require__(70);var Actions=_interopRequireWildcard(_actions);var _constants=__webpack_require__(570);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}var mapStateToProps=function mapStateToProps(state){return{status:state.status};};var mapDispatchToProps=function mapDispatchToProps(dispatch){return{onSave:function onSave(){return dispatch(Actions.save());}};};var SaveStatus=function SaveStatus(props){console.log(props.status);if(props.status.type==_constants.Status.SAVING)return _react2.default.createElement(_semanticUiReact.Message,{size:'tiny',floating:true,compact:true,icon:true},_react2.default.createElement(_semanticUiReact.Icon,{name:'circle notched',loading:true}),_react2.default.createElement(_semanticUiReact.Message.Content,null,_react2.default.createElement(_semanticUiReact.Message.Header,null,'Saving diff')));if(props.status.type==_constants.Status.LOADING)return _react2.default.createElement(_semanticUiReact.Message,{size:'tiny',floating:true,compact:true,icon:true},_react2.default.createElement(_semanticUiReact.Icon,{name:'circle notched',loading:true}),_react2.default.createElement(_semanticUiReact.Message.Content,null,_react2.default.createElement(_semanticUiReact.Message.Header,null,'Loading diff')));else if(props.status.hasError&&props.status.errorType==_constants.StatusError.SAVE_ERROR)return _react2.default.createElement(_semanticUiReact.Message,{size:'tiny',floating:true,compact:true,icon:true},_react2.default.createElement(_semanticUiReact.Icon,{name:'exclamation'}),_react2.default.createElement(_semanticUiReact.Message.Content,null,_react2.default.createElement(_semanticUiReact.Message.Header,null,'Error saving diff'),props.status.error.message,_react2.default.createElement(_semanticUiReact.Button,{onClick:props.onSave},'Retry')));else if(props.status.hasError&&props.status.errorType==_constants.StatusError.LOAD_ERROR)return _react2.default.createElement(_semanticUiReact.Message,{size:'tiny',floating:true,compact:true,icon:true},_react2.default.createElement(_semanticUiReact.Icon,{name:'exclamation'}),_react2.default.createElement(_semanticUiReact.Message.Content,null,_react2.default.createElement(_semanticUiReact.Message.Header,null,'Error loading diff'),'Server returned ',props.status.error));else return _react2.default.createElement('div',null);};exports.default=(0,_reactRedux.connect)(mapStateToProps,mapDispatchToProps)(SaveStatus);
/***/ },
/* 1181 */
@ -23326,15 +23344,11 @@ module.exports = [
/***/ function(module, exports, __webpack_require__) {
"use strict";
'use strict';var _react=__webpack_require__(0);var _react2=_interopRequireDefault(_react);var _reactDom=__webpack_require__(303);var _reactDom2=_interopRequireDefault(_reactDom);var _redux=__webpack_require__(304);var Redux=_interopRequireWildcard(_redux);var _reactRedux=__webpack_require__(69);var _reactRouter=__webpack_require__(84);var _reduxThunk=__webpack_require__(572);var _reduxThunk2=_interopRequireDefault(_reduxThunk);var _reducers=__webpack_require__(574);var reducers=_interopRequireWildcard(_reducers);var _routes=__webpack_require__(575);var _routes2=_interopRequireDefault(_routes);var _actions=__webpack_require__(70);var Actions=_interopRequireWildcard(_actions);var _LocalStorage=__webpack_require__(1216);var _LocalStorage2=_interopRequireDefault(_LocalStorage);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}//the localStore implementation is naive
//initial state should be rehydrated from the server
//then additional state transformations should be applied based on localStore contents
// (or not? maybe localStore is not needed)
'use strict';var _react=__webpack_require__(0);var _react2=_interopRequireDefault(_react);var _reactDom=__webpack_require__(303);var _reactDom2=_interopRequireDefault(_reactDom);var _redux=__webpack_require__(304);var Redux=_interopRequireWildcard(_redux);var _reactRedux=__webpack_require__(69);var _reactRouter=__webpack_require__(84);var _reduxThunk=__webpack_require__(572);var _reduxThunk2=_interopRequireDefault(_reduxThunk);var _reducers=__webpack_require__(574);var reducers=_interopRequireWildcard(_reducers);var _routes=__webpack_require__(575);var _routes2=_interopRequireDefault(_routes);var _actions=__webpack_require__(70);var Actions=_interopRequireWildcard(_actions);var _LocalStorage=__webpack_require__(1216);var _LocalStorage2=_interopRequireDefault(_LocalStorage);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}//initial state is rehydrated from the server
//import createBrowserHistory from 'history/lib/createBrowserHistory'
var initialState=window.__INITIAL_STATE__;//create the list of middlewares
var middlewares=[_reduxThunk2.default];//create the redux store
var initialState=window.__INITIAL_STATE__;//create the redux store
//initial state is retrieved from localStore
var store=Redux.createStore(Redux.combineReducers(reducers),initialState,window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__(Redux.applyMiddleware.apply(Redux,middlewares)):Redux.applyMiddleware.apply(Redux,middlewares));function render(){_reactDom2.default.render(_react2.default.createElement(_reactRedux.Provider,{store:store},_react2.default.createElement(_LocalStorage2.default,null,_react2.default.createElement(_reactRouter.Router,{history:_reactRouter.browserHistory},_routes2.default))),document.getElementById('root'));}render();
var store=Redux.createStore(Redux.combineReducers(reducers),initialState,Redux.compose(Redux.applyMiddleware(_reduxThunk2.default),window.devToolsExtension?window.devToolsExtension():function(f){return f;}));function render(){_reactDom2.default.render(_react2.default.createElement(_reactRedux.Provider,{store:store},_react2.default.createElement(_LocalStorage2.default,null,_react2.default.createElement(_reactRouter.Router,{history:_reactRouter.browserHistory},_routes2.default))),document.getElementById('root'));}render();
/***/ },
/* 1214 */

BIN
dist/favicon-16x16.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
dist/favicon-32x32.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
dist/favicon-96x96.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
dist/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

10
dist/index.html vendored
View File

@ -1,10 +0,0 @@
<html>
<head>
<title>Dubdiff 2</title>
</head>
<body>
<div id="root">If you see this then something is wrong.</div>
<script src="dist/browser-bundle.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css"></link>
<link href="dist/main.css" rel="stylesheet"> </body>
</html>

7020
dist/old-dubdiff.css vendored

File diff suppressed because it is too large Load Diff

View File

@ -18,32 +18,22 @@ import LocalStorage from './LocalStorage'
//the localStore implementation is naive
//initial state should be rehydrated from the server
//then additional state transformations should be applied based on localStore contents
// (or not? maybe localStore is not needed)
//initial state is rehydrated from the server
const initialState = window.__INITIAL_STATE__
//create the list of middlewares
let middlewares = [thunk]
//create the redux store
//initial state is retrieved from localStore
const store = Redux.createStore(
Redux.combineReducers(reducers),
initialState,
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__(Redux.applyMiddleware(...middlewares)):
Redux.applyMiddleware(...middlewares)
Redux.compose(
Redux.applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : f => f
)
)
function render() {
ReactDOM.render(
<Provider store={store}>

View File

@ -1,27 +1,33 @@
import fetch from 'isomorphic-fetch'
import uuid from 'uuid/v4'
import {browserHistory} from 'react-router'
import {Status, StatusError} from './constants'
//All state transitions in the app happen in these methods
//this includes redux state changes, asyncronous data requests, and browser location changes
export const updateOriginalInput = (text) =>
(dispatch, getState) => {
dispatch({ type: 'UPDATE_ORIGINAL_INPUT', data:text})
dispatch({type: 'UPDATE_ORIGINAL_INPUT', data:text})
if (getState().input.original.length>0)
dispatch({type: 'SAVE_STATUS_DIRTY'})
dispatch({type: 'STATUS_SET', data:Status.DIRTY})
else
dispatch({type: 'SAVE_STATUS_EMPTY'})
dispatch({type: 'STATUS_SET', data:Status.EMPTY})
}
export const updateFinalInput = (text) =>
(dispatch, getState) => {
dispatch({ type: 'UPDATE_FINAL_INPUT', data:text})
if (getState().input.final.length>0)
dispatch({type: 'SAVE_STATUS_DIRTY'})
dispatch({type: 'STATUS_SET', data:Status.DIRTY})
else
dispatch({type: 'SAVE_STATUS_EMPTY'})
dispatch({type: 'STATUS_SET', data:Status.EMPTY})
}
export const clearInput = () =>
(dispatch) => {
dispatch({ type: 'CLEAR_INPUT'})
dispatch({ type: 'SAVE_STATUS_EMPTY'})
dispatch({type: 'CLEAR_INPUT'})
dispatch({type: 'STATUS_SET', data:Status.EMPTY})
}
export const setPlaintextFormat = () => ({ type: 'SET_PLAINTEXT_FORMAT'})
@ -31,8 +37,42 @@ export const showFinal = () => ({ type: 'SHOW_FINAL'})
export const showDifference = () => ({ type: 'SHOW_DIFFERENCE'})
//if the input is dirty, saves it to the server
//creates a new uuid for the same,
//then changes the browser location to a comparison view with that id
export const compare = () =>
(dispatch, getState) => {
//!!! could test that the input is dirty before triggering a save
//if the input is empty, the compare should do nothing
//if the input is clean, the compare should not save and keep using the same id
//start saving the input to the server
const id = dispatch(save())
//we can use the id created by the save method to build a path
const comparePath = `/${id}`
browserHistory.replace(comparePath)
}
//clear the input and return to the edit page
export const reset = () =>
(dispatch, getState) => {
dispatch(clearInput())
browserHistory.push('/')
}
//switch to the edit view
export const edit = () =>
(dispatch, getState) => {
browserHistory.push('/')
}
//saves the current input fields to the server
//creates and returns a new id for the
//creates and returns a new id for the comparison
//should this method ensure that the initial state is valid? ('DIRTY')
export const save = () =>
(dispatch, getState) => {
@ -40,7 +80,7 @@ export const save = () =>
const id = uuid()
//set waiting state
dispatch( {type: 'SAVE_STATUS_WAITING'})
dispatch( {type: 'STATUS_SET', data:Status.SAVING})
const endpointUri = `/api/compare/${id}`
const fetchOptions = {
@ -58,10 +98,11 @@ export const save = () =>
//dispatch post request
fetch(endpointUri, fetchOptions)
.then(response => {
dispatch( {type: 'SAVE_STATUS_SAVED'})
dispatch({type: 'STATUS_SET', data: Status.CLEAN})
})
.catch(error => {
dispatch( {type: 'SAVE_STATUS_FAILED', error})
dispatch({type: 'STATUS_SET', data: Status.DIRTY})
dispatch({type: 'STATUS_SET_ERROR', data: StatusError.SAVE_ERROR, error})
})
//return the id after the request has been sent

View File

@ -21,16 +21,11 @@ const mapDispatchToProps = dispatch => ({
onShowOriginal: () => dispatch(Actions.showOriginal()),
onShowFinal: () => dispatch(Actions.showFinal()),
onShowDifference: () => dispatch(Actions.showDifference()),
onEdit: () => {
}
onEdit: () => dispatch(Actions.edit())
})
class CompareControls extends React.Component {
onClickEdit() {
this.props.onEdit()
}
onClickMarkdownFormat() {
if (this.props.isMarkdownFormat)
this.props.onSetPlaintextFormat()
@ -43,7 +38,7 @@ class CompareControls extends React.Component {
return (
<Segment.Group>
<Segment>
<Link to="/"><Button fluid onClick={this.onClickEdit.bind(this)}>Edit</Button></Link>
<Button fluid onClick={this.props.onEdit}>Edit</Button>
</Segment>
<Segment >

View File

@ -12,10 +12,7 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = dispatch => ({
onClear: () => {
dispatch(Actions.clearInput())
dispatch(Actions.clearCompare())
},
onReset: () => { console.log(Actions.reset()); dispatch(Actions.reset())},
})
const SiteHeader = (props) => (
@ -24,7 +21,7 @@ const SiteHeader = (props) => (
<Segment basic >
<Segment basic padded textAlign="center" as="header" id='masthead'>
<Header><Link onClick={props.onClear} to="/">dubdiff</Link></Header>
<Header><Link onClick={props.onReset}>dubdiff</Link></Header>
</Segment>
<Rail internal position="right">

View File

@ -1,6 +1,5 @@
import React from 'react'
import {connect} from 'react-redux'
import {browserHistory} from 'react-router'
import {Button, Icon, Segment} from 'semantic-ui-react'
@ -19,24 +18,11 @@ const mapDispatchToProps = dispatch => ({
onSetMarkdownFormat: (format) => dispatch(Actions.setMarkdownFormat()),
//returns an id for the record to be saved
startSaveAsync: () => {
return dispatch(Actions.save())
}
onCompare: () => dispatch(Actions.compare())
})
class MainControls extends React.Component {
onClickCompare() {
//start saving the input to the server
const id = this.props.startSaveAsync()
//we can use the id created by the save method to build a path
const comparePath = `/${id}`
browserHistory.replace(comparePath)
return false
}
onClickMarkdownFormat() {
if (this.props.isMarkdownFormat)
this.props.onSetPlaintextFormat()
@ -49,7 +35,7 @@ class MainControls extends React.Component {
return (
<Segment.Group>
<Segment >
<Button fluid onClick={this.onClickCompare.bind(this)}>Compare</Button>
<Button fluid onClick={this.props.onCompare}>Compare</Button>
</Segment>
<Segment >

View File

@ -5,27 +5,20 @@ import { Message, Icon, Button} from 'semantic-ui-react'
import { browserHistory} from 'react-router'
import * as Actions from '../actions'
import {Status, StatusError} from '../constants'
const mapStateToProps = (state) => ({
saveStatus: state.saveStatus
status: state.status
})
const mapDispatchToProps = dispatch => ({
retrySave: () => dispatch(Actions.save())
onSave: () => dispatch(Actions.save())
})
const onRetrySaveClick = (props) => {
//we can use the id created by the save method to build a path
const id = props.retrySave()
const comparePath = `/${id}`
browserHistory.replace(comparePath)
return false
}
const SaveStatus = (props) => {
if (props.saveStatus.waiting) return (
console.log(props.status)
if (props.status.type == Status.SAVING) return (
<Message size='tiny' floating compact icon>
<Icon name='circle notched' loading />
<Message.Content>
@ -33,16 +26,32 @@ const SaveStatus = (props) => {
</Message.Content>
</Message>
)
else if (props.saveStatus.failed) return (
if (props.status.type == Status.LOADING) return (
<Message size='tiny' floating compact icon>
<Icon name='circle notched' loading />
<Message.Content>
<Message.Header>Loading diff</Message.Header>
</Message.Content>
</Message>
)
else if (props.status.hasError && props.status.errorType == StatusError.SAVE_ERROR) return (
<Message size='tiny' floating compact icon>
<Icon name='exclamation' />
<Message.Content>
<Message.Header>Error saving diff</Message.Header>
The server returned {props.saveStatus.error.message}.
<Button onClick={()=>onRetrySaveClick(props)}>Retry</Button>
{props.status.error.message}
<Button onClick={props.onSave}>Retry</Button>
</Message.Content>
</Message>
</Message>
)
else if (props.status.hasError && props.status.errorType == StatusError.LOAD_ERROR) return (
<Message size='tiny' floating compact icon>
<Icon name='exclamation' />
<Message.Content>
<Message.Header>Error loading diff</Message.Header>
Server returned {props.status.error}
</Message.Content>
</Message>
)
else return ( <div></div> )

View File

@ -8,3 +8,17 @@ export const Show = {
FINAL:'FINAL',
DIFFERENCE:'DIFFERENCE'
}
export const Status = {
INIT: 'INIT',
LOADING: 'LOADING',
EMPTY: 'EMPTY',
CLEAN: 'CLEAN',
DIRTY: 'DIRTY',
SAVING: 'SAVING'
}
export const StatusError = {
LOADING_ERROR: 'LOAD_ERROR',
SAVING_ERROR: 'SAVE_ERROR'
}

View File

@ -1,4 +1,4 @@
import {Format, Show} from './constants'
import {Format, Show, Status, StatusError} from './constants'
export function input (state, action ) {
@ -39,7 +39,7 @@ export function show (state, action) {
}
}
/*
export function saveStatus (state, action) {
switch (action.type) {
case 'SAVE_STATUS_DIRTY':
@ -56,17 +56,20 @@ export function saveStatus (state, action) {
return state || {empty: true, dirty:false}
}
}
/*
export function loadStatus (state, action) {
switch (action.type) {
case 'LOAD_STATUS_WAITING':
return {waiting: true}
case 'LOAD_STATUS_FAILED':
return {failed: true, error: action.error }
case 'LOAD_STATUS_LOADED':
return {loaded: true}
default:
return state || {waiting: false}
}
*/
//tracks status of the app, especially with respect to loaded and saved user data
export function status (state, action) {
//the status or error type is valid if it is in the list of Status or StatusError types
const isValidStatus = (type) => Status[type] == type
const isValidError = (type) => StatusError[type] == type
//the error is cleared when status changes
if (action.type == 'STATUS_SET' && isValidStatus(action.data))
return {type:action.data, error: null, hasError: false, errorType: null}
//the error is set in addition to the status
else if (action.type == 'STATUS_SET_ERROR' && isValidError(action.data))
return Object.assign({}, state, {error: action.error, hasError: true, errorType:action.data})
else
return {type:Status.EMPTY, hasError: false, error:null}
}
*/

View File

@ -51,7 +51,10 @@ const pageTemplate = (body) => {
<link rel="stylesheet" href="dist/main.css"/>
<!-- Favicon -->
<!--<link rel="shortcut icon" href="/assets/favicon.ico">-->
<link rel="icon" type="image/png" sizes="32x32" href="dist/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="dist/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png">
</head>
<body>