forked from enviPath/enviPy
Current Dev State
This commit is contained in:
174
static/js/ketcher2/script/ui/dialog/template-lib.jsx
Normal file
174
static/js/ketcher2/script/ui/dialog/template-lib.jsx
Normal file
@ -0,0 +1,174 @@
|
||||
/****************************************************************************
|
||||
* 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 { escapeRegExp, chunk, flow, filter as _filter, reduce, omit } from 'lodash/fp';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import { h, Component } from 'preact';
|
||||
import { connect } from 'preact-redux';
|
||||
/** @jsx h */
|
||||
|
||||
import sdf from '../../chem/sdf';
|
||||
|
||||
import VisibleView from '../component/visibleview';
|
||||
import StructRender from '../component/structrender';
|
||||
import Dialog from '../component/dialog';
|
||||
import SaveButton from '../component/savebutton';
|
||||
import Input from '../component/input';
|
||||
import SelectList from '../component/select';
|
||||
|
||||
import { changeFilter, changeGroup, selectTmpl, editTmpl } from '../state/templates';
|
||||
import { onAction } from "../state/";
|
||||
|
||||
const GREEK_SIMBOLS = {
|
||||
'Alpha': 'A', 'alpha': 'α',
|
||||
'Beta': 'B', 'beta': 'β',
|
||||
'Gamma': 'Г', 'gamma': 'γ'
|
||||
};
|
||||
|
||||
function tmplName(tmpl, i) {
|
||||
console.assert(tmpl.props && tmpl.props.group, "No group");
|
||||
return tmpl.struct.name || `${tmpl.props.group} template ${i + 1}`;
|
||||
}
|
||||
|
||||
function partition(n, array) {
|
||||
console.warn('partition', n);
|
||||
return chunk(n)(array);
|
||||
}
|
||||
|
||||
const greekRe = new RegExp('\\b' + Object.keys(GREEK_SIMBOLS).join('\\b|\\b') + '\\b', 'g');
|
||||
function greekify(str) {
|
||||
return str.replace(greekRe, sym => GREEK_SIMBOLS[sym]);
|
||||
}
|
||||
|
||||
const filterLibSelector = createSelector(
|
||||
(props) => props.lib,
|
||||
(props) => props.filter,
|
||||
filterLib
|
||||
);
|
||||
|
||||
function filterLib(lib, filter) {
|
||||
console.warn('Filter', filter);
|
||||
let re = new RegExp(escapeRegExp(greekify(filter)), 'i');
|
||||
return flow(
|
||||
_filter(item => !filter || re.test(greekify(item.struct.name)) || re.test(greekify(item.props.group))),
|
||||
reduce((res, item) => {
|
||||
!res[item.props.group] ? res[item.props.group] = [item] : res[item.props.group].push(item);
|
||||
return res;
|
||||
}, {})
|
||||
)(lib)
|
||||
}
|
||||
|
||||
const libRowsSelector = createSelector(
|
||||
(props) => props.lib,
|
||||
(props) => props.group,
|
||||
(props) => props.COLS,
|
||||
libRows
|
||||
);
|
||||
|
||||
function libRows(lib, group, COLS) {
|
||||
console.warn("Group", group);
|
||||
return partition(COLS, lib[group])
|
||||
}
|
||||
|
||||
function RenderTmpl({ tmpl, ...props }) {
|
||||
return tmpl.props && tmpl.props.prerender ?
|
||||
( <svg {...props}><use xlinkHref={tmpl.props.prerender}/></svg> ) :
|
||||
( <StructRender struct={tmpl.struct} options={{ autoScaleMargin: 15 }} {...props}/> );
|
||||
}
|
||||
|
||||
class TemplateLib extends Component {
|
||||
select(tmpl) {
|
||||
if (tmpl === this.props.selected)
|
||||
this.props.onOk(this.result());
|
||||
else
|
||||
this.props.onSelect(tmpl);
|
||||
}
|
||||
|
||||
result() {
|
||||
const tmpl = this.props.selected;
|
||||
console.assert(!tmpl || tmpl.props, 'Incorrect SDF parse');
|
||||
return tmpl ? {
|
||||
struct: tmpl.struct,
|
||||
aid: parseInt(tmpl.props.atomid) || null,
|
||||
bid: parseInt(tmpl.props.bondid) || null
|
||||
} : null;
|
||||
}
|
||||
|
||||
renderRow(row, index, COLS) {
|
||||
return (
|
||||
<div className="tr" key={index}>{ row.map((tmpl, i) => (
|
||||
<div className={tmpl === this.props.selected ? 'td selected' : 'td'}
|
||||
title={greekify(tmplName(tmpl, index * COLS + i))}>
|
||||
<RenderTmpl tmpl={tmpl} className="struct" onClick={() => this.select(tmpl)}/>
|
||||
<button className="attach-button" onClick={() => this.props.onAttach(tmpl)}>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
))}</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const COLS = 3;
|
||||
let { group, filter, onFilter, onChangeGroup, ...props } = this.props;
|
||||
const lib = filterLibSelector(this.props);
|
||||
group = lib[group] ? group : Object.keys(lib)[0];
|
||||
|
||||
return (
|
||||
<Dialog title="Template Library"
|
||||
className="template-lib" params={props}
|
||||
result={() => this.result()}
|
||||
buttons={[
|
||||
<SaveButton className="save"
|
||||
data={ sdf.stringify(this.props.lib) }
|
||||
filename={'ketcher-tmpls.sdf'}>
|
||||
Save To SDF…
|
||||
</SaveButton>,
|
||||
"OK", "Cancel"]}>
|
||||
<label>
|
||||
<Input type="search" placeholder="Filter"
|
||||
value={ filter } onChange={value => onFilter(value)}/>
|
||||
</label>
|
||||
<Input className="groups" component={SelectList}
|
||||
splitIndexes={[Object.keys(lib).indexOf('User Templates')]}
|
||||
value={ group } onChange={g => onChangeGroup(g)}
|
||||
schema={{
|
||||
enum: Object.keys(lib),
|
||||
enumNames: Object.keys(lib).map(g => greekify(g))
|
||||
}}/>
|
||||
<VisibleView data={libRowsSelector({ lib, group, COLS })}
|
||||
rowHeight={120} className="table">
|
||||
{ (row, i) => this.renderRow(row, i, COLS) }
|
||||
</VisibleView>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(
|
||||
store => ({ ...omit(['attach'], store.templates) }),
|
||||
(dispatch, props) => ({
|
||||
onFilter: filter => dispatch(changeFilter(filter)),
|
||||
onSelect: tmpl => dispatch(selectTmpl(tmpl)),
|
||||
onChangeGroup: group => dispatch(changeGroup(group)),
|
||||
onAttach: tmpl => dispatch(editTmpl(tmpl)),
|
||||
onOk: res => {
|
||||
dispatch(onAction({ tool: 'template', opts: res }));
|
||||
props.onOk(res);
|
||||
}
|
||||
})
|
||||
)(TemplateLib);
|
||||
Reference in New Issue
Block a user