Skip to content

Commit

Permalink
Merge pull request #13 from architecture-building-systems/2553-restru…
Browse files Browse the repository at this point in the history
…cture-databases

2553 restructure databases
  • Loading branch information
reyery committed Feb 17, 2020
2 parents 3fc73e5 + 7023500 commit 38905dd
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 34 deletions.
6 changes: 6 additions & 0 deletions src/renderer/actions/databaseEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ export const fetchDatabaseGlossary = () => async dispatch => {
}
};

export const COPY_SCHEDULE_DATA = 'COPY_SCHEDULE_DATA';
export const copyScheduleData = (name, copy) => ({
type: COPY_SCHEDULE_DATA,
payload: { name, copy }
});

export const UPDATE_DATABASE_VALIDATION = 'UPDATE_DATABASE_VALIDATION';
export const updateDatabaseValidation = validation => ({
type: UPDATE_DATABASE_VALIDATION,
Expand Down
156 changes: 124 additions & 32 deletions src/renderer/components/DatabaseEditor/DatabaseEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,32 @@ import {
resetDatabaseState,
initDatabaseState,
setActiveDatabase,
resetDatabaseChanges
resetDatabaseChanges,
copyScheduleData
} from '../../actions/databaseEditor';
import Table, { TableButtons, useTableUpdateRedux } from './Table';
import { months_short } from '../../constants/months';
import { AsyncError } from '../../utils';
import routes from '../../constants/routes';
import { useChangeRoute } from '../Project/Project';
import Handsontable from 'handsontable';
import NewScheduleModal from './NewScheduleModal';

const useValidateDatabasePath = () => {
const [valid, setValid] = useState(null);
const [error, setError] = useState(null);

const checkDBPathValidity = async () => {
try {
setValid(null);
setError(null);
const resp = await axios.get(
'http://localhost:5050/api/inputs/databases/check'
);
setValid(true);
} catch (err) {
console.log(err);
if (err.response) setError(err.response.data.message);
else setError('Could not read and verify databases.');
setValid(false);
}
};
Expand All @@ -40,7 +45,7 @@ const useValidateDatabasePath = () => {
checkDBPathValidity();
}, []);

return [valid, checkDBPathValidity];
return [valid, error, checkDBPathValidity];
};

const ValidationErrors = ({ databaseName }) => {
Expand Down Expand Up @@ -131,7 +136,7 @@ const SavingDatabaseModal = ({ visible, hideModal, error, success }) => {
};

const DatabaseEditor = () => {
const [valid, checkDBPathValidity] = useValidateDatabasePath();
const [valid, error, checkDBPathValidity] = useValidateDatabasePath();
const goToScript = useChangeRoute(`${routes.TOOLS}/data-initializer`);

if (valid === null)
Expand All @@ -158,7 +163,13 @@ const DatabaseEditor = () => {
<DatabaseContent />
) : (
<div>
<div>Could not find or validate databases. Try assigning one</div>
<div style={{ margin: 20 }}>
<p>
Could not find or validate databases. Try assigning a new
database
</p>
{error !== null && <details>{error}</details>}
</div>
<Button onClick={checkDBPathValidity}>Try Again</Button>
</div>
)}
Expand Down Expand Up @@ -347,43 +358,124 @@ const DatabaseContainer = () => {

return (
<div className="cea-database-editor-database-container">
<Database
name={name}
data={data[category][name]}
schema={schema[category][name]}
/>
{category === 'archetypes' && (
<div style={{ margin: 10 }}>
<Alert
message={
<div>
If you want to add a new <i>archetype</i>, you would need to
include it in all sheets of <b>CONSTRUCTION</b> and create its
schedule in <b>SCHEDULES</b>
</div>
}
type="info"
showIcon
/>
</div>
)}
<div className="cea-database-editor-database">
<h2>{name}</h2>
<ValidationErrors databaseName={name} />
{name === 'SCHEDULES' ? (
<SchedulesDatabase
name={name}
data={data[category][name]}
schema={schema[category][name]}
/>
) : (
<Database
name={name}
data={data[category][name]}
schema={schema[category][name]}
/>
)}
</div>
<SaveDatabaseButton />
</div>
);
};

const Database = ({ name, data, schema }) => {
return (
<div className="cea-database-editor-database">
<h2>{name}</h2>
<ValidationErrors databaseName={name} />
<Tabs className="cea-database-editor-tabs" type="card">
{Object.keys(data).map(sheetName => (
<Tabs.TabPane key={sheetName} tab={sheetName}>
{name !== 'schedules' ? (
<DatabaseTable
databaseName={name}
sheetName={sheetName}
sheetData={data[sheetName]}
schema={schema[sheetName]}
/>
) : (
<SchedulesTable
databaseName={name}
sheetName={sheetName}
sheetData={data[sheetName]}
schema={schema[sheetName]}
/>
)}
<Tabs className="cea-database-editor-tabs" type="card">
{Object.keys(data).map(sheetName => (
<Tabs.TabPane key={sheetName} tab={sheetName}>
<DatabaseTable
databaseName={name}
sheetName={sheetName}
sheetData={data[sheetName]}
schema={schema[sheetName]}
/>
</Tabs.TabPane>
))}
</Tabs>
);
};

const SchedulesDatabase = ({ name, data, schema }) => {
const scheduleNames = Object.keys(data);
const [modalVisible, setModalVisible] = useState(false);
const [selectedKey, setSelected] = useState(scheduleNames[0]);
const [panes, setPanes] = useState(scheduleNames);
const dispatch = useDispatch();

const showModal = () => {
setModalVisible(true);
};

const onEdit = (targetKey, action) => {
if (action === 'remove') {
Modal.confirm({
title: `Do you want to delete ${targetKey} schedule?`,
content: 'This action cannot be undone.',
onOk() {
setSelected(null);
setPanes(oldValue => oldValue.filter(pane => pane != targetKey));
}
});
}
};

const addSchedule = values => {
const { name, copy } = values;
dispatch(copyScheduleData(name, copy));
setPanes(oldValue => [...oldValue, name]);
setSelected(name);
};

return (
<React.Fragment>
<Tabs
className="cea-database-editor-tabs"
type="editable-card"
onEdit={onEdit}
hideAdd
activeKey={selectedKey}
onChange={setSelected}
tabBarExtraContent={
<Button onClick={showModal}>Add new Archetype Schedule</Button>
}
>
{panes.map(pane => (
<Tabs.TabPane key={pane} tab={pane}>
<SchedulesTable
databaseName={name}
sheetName={pane}
sheetData={data[pane]}
schema={schema[pane]}
/>
</Tabs.TabPane>
))}
</Tabs>
</div>
<NewScheduleModal
scheduleNames={scheduleNames}
onSuccess={values => {
addSchedule(values);
}}
visible={modalVisible}
setVisible={setModalVisible}
/>
</React.Fragment>
);
};

Expand Down
84 changes: 84 additions & 0 deletions src/renderer/components/DatabaseEditor/NewScheduleModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React, { useState, useRef } from 'react';
import { Modal, Form, Select } from 'antd';
import { FormItemWrapper } from '../Tools/Parameter';

const NewScheduleModal = ({
scheduleNames,
onSuccess,
visible,
setVisible
}) => {
const formRef = useRef();

const handleOk = () => {
formRef.current.validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
onSuccess(values);
setVisible(false);
}
});
};

const handleCancel = e => {
setVisible(false);
};

return (
<Modal
title="Add new Archetype Schedule"
visible={visible}
width={800}
okText="Add"
onOk={handleOk}
onCancel={handleCancel}
destroyOnClose
>
<NewProjectForm ref={formRef} scheduleNames={scheduleNames} />
</Modal>
);
};

const NewProjectForm = Form.create()(({ form, scheduleNames }) => {
return (
<Form layout="horizontal">
<FormItemWrapper
form={form}
name="name"
initialValue=""
help="Name of new Archetype Schedule"
required={true}
rules={[
{
validator: (rule, value, callback) => {
if (scheduleNames.includes(value)) {
callback('Schedule with name already exists');
} else if (value !== value.toUpperCase()) {
callback('Name must be in uppercase');
} else {
callback();
}
}
}
]}
/>
<FormItemWrapper
form={form}
name="copy"
initialValue={scheduleNames[0]}
help="Copy from existing schedule"
inputComponent={
<Select disabled={!scheduleNames.length}>
{scheduleNames.map(name => (
<Select.Option key={name} value={name}>
{name}
</Select.Option>
))}
</Select>
}
/>
</Form>
);
});

export default NewScheduleModal;
2 changes: 1 addition & 1 deletion src/renderer/components/DatabaseEditor/Table.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const useTableUpdateRedux = (tableRef, database, sheet) => {
// ? colHeaders[prop]
// : prop;
// });
dispatch(updateDatabaseChanges(changes));
dispatch(updateDatabaseChanges({ database, sheet, changes }));
}
}
};
Expand Down
17 changes: 16 additions & 1 deletion src/renderer/reducers/databaseEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
FETCH_DATABASE_DATA_FAILURE,
FETCH_DATABASE_SCHEMA_FAILURE,
FETCH_DATABASE_GLOSSARY_FAILURE,
RESET_DATABASE_CHANGES
RESET_DATABASE_CHANGES,
COPY_SCHEDULE_DATA
} from '../actions/databaseEditor';
import { combineReducers } from 'redux';
import { checkNestedProp, createNestedProp, deleteNestedProp } from '../utils';
Expand Down Expand Up @@ -61,6 +62,20 @@ const databaseData = (state = {}, { type, payload }) => {
return payload;
case RESET_DATABASE_STATE:
return {};
// FIXME: Hardcoded location of schedules database
case COPY_SCHEDULE_DATA:
return {
...state,
archetypes: {
...state.archetypes,
schedules: {
...state.archetypes.schedules,
[payload.name]: {
...state.archetypes.schedules[payload.copy]
}
}
}
};
default:
return state;
}
Expand Down

0 comments on commit 38905dd

Please sign in to comment.