parent
031371652b
commit
94f8e38d5a
@ -0,0 +1,44 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Route, Redirect } from 'react-router-dom';
|
||||
import getPathWithUrlBase from 'Utilities/getPathWithUrlBase';
|
||||
import Switch from 'Components/Router/Switch';
|
||||
import StatusConnector from './Status/StatusConnector';
|
||||
import ScriptConnector from './Script/ScriptConnector';
|
||||
|
||||
class Diagnostic extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Switch>
|
||||
<Route
|
||||
exact={true}
|
||||
path="/diag/status"
|
||||
component={StatusConnector}
|
||||
/>
|
||||
<Route
|
||||
exact={true}
|
||||
path="/diag/script"
|
||||
component={ScriptConnector}
|
||||
/>
|
||||
|
||||
{/* Redirect root to status */}
|
||||
<Route
|
||||
exact={true}
|
||||
path="/diag"
|
||||
render={() => {
|
||||
return (
|
||||
<Redirect
|
||||
to={getPathWithUrlBase('/diag/status')}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Diagnostic;
|
@ -0,0 +1,82 @@
|
||||
import ReactMonacoEditor from 'react-monaco-editor';
|
||||
import shallowEqual from 'shallowequal';
|
||||
|
||||
// All editor features -> 7.56 MiB
|
||||
// import 'monaco-editor/esm/vs/editor/editor.all';
|
||||
|
||||
// Only the needed editor features -> 6.88 MiB
|
||||
import 'monaco-editor/esm/vs/editor/browser/controller/coreCommands';
|
||||
import 'monaco-editor/esm/vs/editor/browser/widget/codeEditorWidget';
|
||||
// import 'monaco-editor/esm/vs/editor/browser/widget/diffEditorWidget';
|
||||
// import 'monaco-editor/esm/vs/editor/browser/widget/diffNavigator';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/bracketMatching/bracketMatching';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/caretOperations/caretOperations';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/caretOperations/transpose';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/clipboard/clipboard';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/codeAction/codeActionContributions';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/codelens/codelensController';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/colorPicker/colorDetector';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/comment/comment';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/contextmenu/contextmenu';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/cursorUndo/cursorUndo';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/dnd/dnd';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/find/findController';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/folding/folding';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/fontZoom/fontZoom';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/format/formatActions';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/goToDefinition/goToDefinitionCommands';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/goToDefinition/goToDefinitionMouse';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/gotoError/gotoError';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/hover/hover';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/inPlaceReplace/inPlaceReplace';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/linesOperations/linesOperations';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/links/links';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/multicursor/multicursor';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/parameterHints/parameterHints';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/referenceSearch/referenceSearch';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/rename/rename';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/smartSelect/smartSelect';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/snippet/snippetController2';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/suggest/suggestController';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/tokenization/tokenization';
|
||||
// import 'monaco-editor/esm/vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/wordHighlighter/wordHighlighter';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/wordOperations/wordOperations';
|
||||
import 'monaco-editor/esm/vs/editor/contrib/wordPartOperations/wordPartOperations';
|
||||
|
||||
// csharp&json language
|
||||
import 'monaco-editor/esm/vs/basic-languages/csharp/csharp';
|
||||
import 'monaco-editor/esm/vs/basic-languages/csharp/csharp.contribution';
|
||||
import 'monaco-editor/esm/vs/language/json/monaco.contribution';
|
||||
import 'monaco-editor/esm/vs/language/json/jsonWorker';
|
||||
import 'monaco-editor/esm/vs/language/json/jsonMode';
|
||||
|
||||
// Create a WebWorker from a blob rather than an url
|
||||
import * as EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker';
|
||||
import * as JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker';
|
||||
|
||||
self.MonacoEnvironment = {
|
||||
getWorker: (moduleId, label) => {
|
||||
if (label === 'editorWorkerService') {
|
||||
return new EditorWorker();
|
||||
}
|
||||
if (label === 'json') {
|
||||
return new JsonWorker();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
class MonacoEditor extends ReactMonacoEditor {
|
||||
|
||||
// ReactMonacoEditor should've been PureComponent
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
if (!shallowEqual(this.props, nextProps)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default MonacoEditor;
|
@ -0,0 +1,93 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { fetchStatus, updateScript, validateScript, executeScript } from 'Store/Actions/diagnosticActions';
|
||||
import ScriptConsole from './ScriptConsole';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import Alert from 'Components/Alert';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.diagnostic,
|
||||
(diag) => {
|
||||
return {
|
||||
isStatusPopulated: diag.status.isPopulated,
|
||||
isScriptConsoleEnabled: diag.status.item.scriptConsoleEnabled,
|
||||
isExecuting: diag.script.isExecuting || false,
|
||||
isDebugging: diag.script.isDebugging || false,
|
||||
isValidating: diag.script.isValidating,
|
||||
code: diag.script.code,
|
||||
result: diag.script.result,
|
||||
validation: diag.script.validation,
|
||||
error: diag.script.error
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
fetchStatus,
|
||||
updateScript,
|
||||
validateScript,
|
||||
executeScript
|
||||
};
|
||||
|
||||
class ScriptConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.isStatusPopulated) {
|
||||
this.props.fetchStatus();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
if (!this.props.isStatusPopulated) {
|
||||
return (
|
||||
<PageContent>
|
||||
<LoadingIndicator />
|
||||
</PageContent>
|
||||
);
|
||||
} else if (!this.props.isScriptConsoleEnabled) {
|
||||
return (
|
||||
<PageContent>
|
||||
<Alert kind={kinds.WARNING}>
|
||||
Diagnostic Scripting is disabled
|
||||
</Alert>
|
||||
</PageContent>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ScriptConsole
|
||||
{...this.props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ScriptConnector.propTypes = {
|
||||
isStatusPopulated: PropTypes.bool.isRequired,
|
||||
isScriptConsoleEnabled: PropTypes.bool,
|
||||
isExecuting: PropTypes.bool.isRequired,
|
||||
isDebugging: PropTypes.bool.isRequired,
|
||||
isValidating: PropTypes.bool.isRequired,
|
||||
code: PropTypes.string,
|
||||
result: PropTypes.object,
|
||||
error: PropTypes.object,
|
||||
validation: PropTypes.object,
|
||||
fetchStatus: PropTypes.func.isRequired,
|
||||
updateScript: PropTypes.func.isRequired,
|
||||
validateScript: PropTypes.func.isRequired,
|
||||
executeScript: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(ScriptConnector);
|
@ -0,0 +1,6 @@
|
||||
.split {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component, lazy, Suspense } from 'react';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import styles from './ScriptConsole.css';
|
||||
|
||||
// Lazy load the Monaco Editor since it's a big bundle
|
||||
const MonacoEditor = lazy(() => import(/* webpackChunkName: "monaco-editor" */ './MonacoEditor'));
|
||||
|
||||
const DefaultOptions = {
|
||||
selectOnLineNumbers: true,
|
||||
scrollBeyondLastLine: false
|
||||
};
|
||||
const DefaultResultOptions = {
|
||||
...DefaultOptions,
|
||||
readOnly: true
|
||||
};
|
||||
|
||||
class ScriptConsole extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
editorDidMount = (editor, monaco) => {
|
||||
console.log('editorDidMount', editor);
|
||||
editor.focus();
|
||||
this.monaco = monaco;
|
||||
this.editor = editor;
|
||||
|
||||
this.updateValidation(this.props.validation);
|
||||
}
|
||||
|
||||
updateValidation(validation) {
|
||||
if (!this.monaco) {
|
||||
return;
|
||||
}
|
||||
|
||||
let diagnostics = [];
|
||||
|
||||
if (validation && validation.errorDiagnostics) {
|
||||
diagnostics = validation.errorDiagnostics;
|
||||
}
|
||||
|
||||
const model = this.editor.getModel();
|
||||
|
||||
this.monaco.editor.setModelMarkers(model, 'editor', diagnostics);
|
||||
}
|
||||
|
||||
onChange = (newValue, e) => {
|
||||
this.props.updateScript({ code: newValue });
|
||||
|
||||
this.validateCode();
|
||||
}
|
||||
|
||||
validateCode = _.debounce(() => {
|
||||
const code = this.props.code;
|
||||
this.props.validateScript({ code });
|
||||
}, 250, { leading: false, trailing: true })
|
||||
|
||||
onExecuteScriptPress = () => {
|
||||
const code = this.props.code;
|
||||
this.props.executeScript({ code });
|
||||
}
|
||||
|
||||
onDebugScriptPress = () => {
|
||||
const code = this.props.code;
|
||||
this.props.executeScript({ code, debug: true });
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
render() {
|
||||
const code = this.props.code;
|
||||
const result = JSON.stringify(this.props.result, null, 2);
|
||||
|
||||
this.updateValidation(this.props.validation);
|
||||
|
||||
return (
|
||||
<PageContent>
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
label="Run"
|
||||
iconName={this.props.isExecuting ? icons.REFRESH : icons.SCRIPT_RUN}
|
||||
isSpinning={this.props.isExecuting}
|
||||
onPress={this.onExecuteScriptPress}
|
||||
/>
|
||||
<PageToolbarButton
|
||||
label="Debug"
|
||||
iconName={this.props.isDebugging ? icons.REFRESH : icons.SCRIPT_DEBUG}
|
||||
isSpinning={this.props.isDebugging}
|
||||
onPress={this.onDebugScriptPress}
|
||||
/>
|
||||
</PageToolbarSection>
|
||||
</PageToolbar>
|
||||
<Suspense fallback={<LoadingIndicator />}>
|
||||
<div className={styles.split}>
|
||||
<MonacoEditor
|
||||
language="csharp"
|
||||
theme="vs-light"
|
||||
width="50%"
|
||||
value={code}
|
||||
options={DefaultOptions}
|
||||
onChange={this.onChange}
|
||||
editorDidMount={this.editorDidMount}
|
||||
/>
|
||||
<MonacoEditor
|
||||
language="json"
|
||||
theme="vs-light"
|
||||
width="50%"
|
||||
value={result}
|
||||
options={DefaultResultOptions}
|
||||
/>
|
||||
</div>
|
||||
</Suspense>
|
||||
</PageContent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ScriptConsole.propTypes = {
|
||||
isExecuting: PropTypes.bool.isRequired,
|
||||
isDebugging: PropTypes.bool.isRequired,
|
||||
isValidating: PropTypes.bool.isRequired,
|
||||
code: PropTypes.string,
|
||||
result: PropTypes.object,
|
||||
error: PropTypes.object,
|
||||
validation: PropTypes.object,
|
||||
updateScript: PropTypes.func.isRequired,
|
||||
validateScript: PropTypes.func.isRequired,
|
||||
executeScript: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default ScriptConsole;
|
@ -0,0 +1,5 @@
|
||||
.descriptionList {
|
||||
composes: descriptionList from '~Components/DescriptionList/DescriptionList.css';
|
||||
|
||||
margin-bottom: 10px;
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||
import styles from './Statistics.css';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
|
||||
import moment from 'moment';
|
||||
|
||||
function formatValue(val, formatter) {
|
||||
if (val === undefined) {
|
||||
return 'n/a';
|
||||
}
|
||||
|
||||
if (formatter) {
|
||||
return formatter(val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
class Statistics extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
process,
|
||||
databaseMain,
|
||||
databaseLog,
|
||||
commandsExecuted
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FieldSet legend="Statistics">
|
||||
<DescriptionList className={styles.descriptionList}>
|
||||
<DescriptionListItem
|
||||
title="Up Time"
|
||||
data={formatValue(process.startTime, (startTime) => formatTimeSpan(moment().diff(startTime)))}
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Processor Time"
|
||||
data={formatValue(process.totalProcessorTime, formatTimeSpan)}
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Memory Working Set"
|
||||
data={formatValue(process.workingSet, formatBytes)}
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Memory Virtual Size"
|
||||
data={formatValue(process.virtualMemorySize, formatBytes)}
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Main Database Size"
|
||||
data={formatValue(databaseMain.size, formatBytes)}
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Logs Database Size"
|
||||
data={formatValue(databaseLog.size, formatBytes)}
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title="Commands Executed"
|
||||
data={formatValue(commandsExecuted, formatBytes)}
|
||||
/>
|
||||
</DescriptionList>
|
||||
</FieldSet>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Statistics.propTypes = {
|
||||
process: PropTypes.object,
|
||||
databaseMain: PropTypes.object,
|
||||
databaseLog: PropTypes.object,
|
||||
commandsExecuted: PropTypes.number
|
||||
};
|
||||
|
||||
Statistics.defaultProps = {
|
||||
process: {},
|
||||
databaseMain: {},
|
||||
databaseLog: {}
|
||||
};
|
||||
|
||||
export default Statistics;
|
@ -0,0 +1,46 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import Statistics from './Statistics/Statistics';
|
||||
|
||||
class Status extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<PageContent title="Diagnostic Status">
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
label="Refresh"
|
||||
iconName={icons.REFRESH}
|
||||
isSpinning={this.props.isStatusFetching}
|
||||
onPress={this.props.onRefreshPress}
|
||||
/>
|
||||
</PageToolbarSection>
|
||||
</PageToolbar>
|
||||
<PageContentBody>
|
||||
<Statistics
|
||||
{...this.props.status}
|
||||
/>
|
||||
</PageContentBody>
|
||||
</PageContent>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Status.propTypes = {
|
||||
status: PropTypes.object.isRequired,
|
||||
isStatusFetching: PropTypes.bool.isRequired,
|
||||
onRefreshPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default Status;
|
@ -0,0 +1,59 @@
|
||||
// @ts-check
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { fetchStatus } from 'Store/Actions/diagnosticActions';
|
||||
import Status from './Status';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.diagnostic.status,
|
||||
(status) => {
|
||||
return {
|
||||
isStatusFetching: status.isFetching,
|
||||
status: status.item
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
fetchStatus
|
||||
};
|
||||
|
||||
class DiagnosticConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
componentDidMount() {
|
||||
this.props.fetchStatus();
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onRefreshPress = () => {
|
||||
this.props.fetchStatus();
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Status
|
||||
onRefreshPress={this.onRefreshPress}
|
||||
{...this.props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DiagnosticConnector.propTypes = {
|
||||
status: PropTypes.object.isRequired,
|
||||
fetchStatus: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(DiagnosticConnector);
|
@ -0,0 +1,185 @@
|
||||
import { createThunk, handleThunks } from 'Store/thunks';
|
||||
import createFetchHandler from './Creators/createFetchHandler';
|
||||
import createHandleActions from './Creators/createHandleActions';
|
||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||
import { set } from './baseActions';
|
||||
|
||||
//
|
||||
// Variables
|
||||
|
||||
export const section = 'diagnostic';
|
||||
const scriptSection = 'diagnostic.script';
|
||||
|
||||
//
|
||||
// State
|
||||
|
||||
const exampleScript = `// Obtain the instance of ISeriesService
|
||||
var seriesService = Resolve<ISeriesService>();
|
||||
|
||||
// Get all series
|
||||
var series = seriesService.GetAllSeries();
|
||||
|
||||
// Find the top 5 highest rated ones
|
||||
var top5 = series.Where(s => s.Ratings.Votes > 6)
|
||||
.OrderByDescending(s => s.Ratings.Value)
|
||||
.Take(5)
|
||||
.Select(s => s.Title);
|
||||
|
||||
return new {
|
||||
Top5 = top5,
|
||||
Count = series.Count()
|
||||
};`;
|
||||
|
||||
export const defaultState = {
|
||||
status: {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
item: {}
|
||||
},
|
||||
|
||||
script: {
|
||||
isExecuting: false,
|
||||
isDebugging: false,
|
||||
isValidating: false,
|
||||
workspaceId: null,
|
||||
code: exampleScript,
|
||||
validation: null,
|
||||
result: null,
|
||||
error: null
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Actions Types
|
||||
|
||||
export const FETCH_STATUS = 'diagnostic/status/fetchStatus';
|
||||
export const UPDATE_SCRIPT = 'diagnostic/script/update';
|
||||
export const VALIDATE_SCRIPT = 'diagnostic/script/validate';
|
||||
export const EXECUTE_SCRIPT = 'diagnostic/script/execute';
|
||||
|
||||
//
|
||||
// Action Creators
|
||||
|
||||
export const fetchStatus = createThunk(FETCH_STATUS);
|
||||
export const updateScript = createThunk(UPDATE_SCRIPT);
|
||||
export const validateScript = createThunk(VALIDATE_SCRIPT);
|
||||
export const executeScript = createThunk(EXECUTE_SCRIPT);
|
||||
|
||||
//
|
||||
// Action Handlers
|
||||
|
||||
export const actionHandlers = handleThunks({
|
||||
[FETCH_STATUS]: createFetchHandler('diagnostic.status', '/diagnostic/status'),
|
||||
|
||||
[UPDATE_SCRIPT]: function(getState, payload, dispatch) {
|
||||
const {
|
||||
code
|
||||
} = payload;
|
||||
|
||||
dispatch(set({
|
||||
section: scriptSection,
|
||||
code
|
||||
}));
|
||||
},
|
||||
|
||||
[VALIDATE_SCRIPT]: function(getState, payload, dispatch) {
|
||||
const {
|
||||
code
|
||||
} = payload;
|
||||
|
||||
dispatch(set({
|
||||
section: scriptSection,
|
||||
code,
|
||||
isValidating: true
|
||||
}));
|
||||
|
||||
let ajaxOptions = null;
|
||||
|
||||
ajaxOptions = {
|
||||
url: '/diagnostic/script/validate',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
dataType: 'json',
|
||||
data: JSON.stringify({
|
||||
code
|
||||
})
|
||||
};
|
||||
|
||||
const promise = createAjaxRequest(ajaxOptions).request;
|
||||
|
||||
promise.done((data) => {
|
||||
dispatch(set({
|
||||
section: scriptSection,
|
||||
isValidating: false,
|
||||
validation: data
|
||||
}));
|
||||
});
|
||||
|
||||
promise.fail((xhr) => {
|
||||
dispatch(set({
|
||||
section: scriptSection,
|
||||
isValidating: false,
|
||||
validation: null,
|
||||
error: xhr
|
||||
}));
|
||||
});
|
||||
},
|
||||
|
||||
[EXECUTE_SCRIPT]: function(getState, payload, dispatch) {
|
||||
const {
|
||||
code,
|
||||
debug
|
||||
} = payload;
|
||||
|
||||
dispatch(set({
|
||||
section: scriptSection,
|
||||
code,
|
||||
isExecuting: !debug,
|
||||
isDebugging: debug
|
||||
}));
|
||||
|
||||
let ajaxOptions = null;
|
||||
|
||||
ajaxOptions = {
|
||||
url: '/diagnostic/script/execute',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
dataType: 'json',
|
||||
data: JSON.stringify({
|
||||
code,
|
||||
debug
|
||||
})
|
||||
};
|
||||
|
||||
const promise = createAjaxRequest(ajaxOptions).request;
|
||||
|
||||
promise.done((data) => {
|
||||
dispatch(set({
|
||||
section: scriptSection,
|
||||
isExecuting: false,
|
||||
isDebugging: false,
|
||||
result: (debug || data.error) ? data : data.returnValue,
|
||||
validation: {
|
||||
errorDiagnostics: data.errorDiagnostics
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
promise.fail((xhr) => {
|
||||
dispatch(set({
|
||||
section: scriptSection,
|
||||
isExecuting: false,
|
||||
isDebugging: false,
|
||||
error: xhr
|
||||
}));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
// Reducers
|
||||
|
||||
export const reducers = createHandleActions({
|
||||
|
||||
}, defaultState, section);
|
Loading…
Reference in new issue