Files
enviPy-bayer/static/js/ketcher2/script/ui/state/index.js
2025-06-23 20:13:54 +02:00

168 lines
3.9 KiB
JavaScript

/****************************************************************************
* Copyright 2017 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
import { pick } from 'lodash/fp';
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk'
import { logger } from 'redux-logger';
import * as structFormat from '../structformat';
import { formsState, formReducer } from './form';
import { optionsState, optionsReducer } from './options';
import { initTmplState, templatesReducer } from './templates';
import action from './action';
import toolbar from './toolbar';
function modal(state = null, action) {
const { type, data } = action;
if (type === 'UPDATE_FORM') {
const formState = formReducer(state.form, action, state.name);
return { ...state, form: formState }
}
switch (type) {
case 'MODAL_CLOSE':
return null;
case 'MODAL_OPEN':
return {
name: data.name,
form: formsState[data.name] || null,
prop: data.prop || null
};
default:
return state;
}
}
const shared = combineReducers({
actionState: action,
toolbar,
modal,
server: (store=null) => store,
editor: (store=null) => store,
options: optionsReducer,
templates: templatesReducer
});
export function onAction(action) {
if (action && action.dialog)
return {
type: 'MODAL_OPEN',
data: { name: action.dialog }
};
if (action && action.thunk)
return action.thunk;
return {
type: 'ACTION',
action
};
}
export function openDialog(dispatch, dialogName, props) {
return new Promise((resolve, reject) => {
dispatch({
type: 'MODAL_OPEN',
data: {
name: dialogName,
prop: {
...props,
onResult: resolve,
onCancel: reject
}
}
})
});
}
export function load(structStr, options) {
return (dispatch, getState) => {
const state = getState();
const editor = state.editor;
const server = state.server;
options = options || {};
// TODO: check if structStr is parsed already
//utils.loading('show');
const parsed = structFormat.fromString(structStr,
options, server);
parsed.catch(function (err) {
//utils.loading('hide');
alert("Can't parse molecule!");
});
return parsed.then(function (struct) {
//utils.loading('hide');
console.assert(struct, 'No molecule to update');
if (options.rescale)
struct.rescale(); // TODO: move out parsing?
if (options.fragment && !struct.isBlank())
dispatch(onAction({ tool: 'paste', opts: struct }));
else
editor.struct(struct);
return struct;
}, function (err) {
alert(err);
});
}
}
function root(state, action) {
switch (action.type) {
case 'INIT':
global._ui_editor = action.editor;
case 'UPDATE':
let {type, ...data} = action;
if (data)
state = { ...state, ...data };
}
const sh = shared(state, {
...action,
...pick(['editor', 'server', 'options'], state)
});
return (sh === state.shared) ? state : {
...state, ...sh
};
}
export default function(options, server) {
// TODO: redux localStorage here
const initState = {
actionState: null,
options: Object.assign(optionsState, { app: options }),
server: server || Promise.reject("Standalone mode!"),
editor: null,
modal: null,
templates: initTmplState
};
const middleware = [ thunk ];
if (process.env.NODE_ENV !== 'production')
middleware.push(logger);
return createStore(root, initState, applyMiddleware(...middleware));
};