diff --git a/app/components/ProgramSequenceView.tsx b/app/components/ProgramSequenceView.tsx
index 4903f11..ece2ab3 100644
--- a/app/components/ProgramSequenceView.tsx
+++ b/app/components/ProgramSequenceView.tsx
@@ -1,7 +1,9 @@
import classNames = require("classnames");
import { observer } from "mobx-react";
import * as React from "react";
-import { Form, List } from "semantic-ui-react";
+import * as ReactDOM from "react-dom";
+import { SortableContainer, SortableElement, SortableHandle, SortEnd, arrayMove } from "react-sortable-hoc";
+import { Form, Icon, List } from "semantic-ui-react";
import { DurationView, SectionChooser } from "@app/components/index";
import { Duration } from "@common/Duration";
@@ -9,6 +11,8 @@ import { ProgramItem, Section } from "@common/sprinklersRpc";
import "@app/styles/ProgramSequenceView";
+const Handle = SortableHandle(() => );
+
@observer
class ProgramSequenceItem extends React.Component<{
sequenceItem: ProgramItem, sections: Section[], onChange?: (newItem: ProgramItem) => void,
@@ -21,17 +25,15 @@ class ProgramSequenceItem extends React.Component<{
if (editing) {
return (
-
+
@@ -48,11 +50,12 @@ class ProgramSequenceItem extends React.Component<{
}
render() {
+ const editing = this.props.onChange != null;
return (
-
-
+
+ {editing ? : }
{this.renderContent()}
-
+
);
}
@@ -75,22 +78,65 @@ class ProgramSequenceItem extends React.Component<{
}
}
+const ProgramSequenceItemD = SortableElement(ProgramSequenceItem);
+
+type ItemChangeHandler = (newItem: ProgramItem, index: number) => void;
+
+const ProgramSequenceList = SortableContainer(observer(({ className, list, sections, onChange }: {
+ className: string,
+ list: ProgramItem[],
+ sections: Section[],
+ onChange?: ItemChangeHandler,
+}) => {
+ const listItems = list.map((item, index) => {
+ const onChangeHandler = onChange ? (newItem: ProgramItem) => onChange(newItem, index) : undefined;
+ const key = `item-${index}`;
+ return (
+
+ );
+ });
+ return ;
+}), { withRef: true });
+
@observer
-export default class ProgramSequenceView extends React.Component<{
+class ProgramSequenceView extends React.Component<{
sequence: ProgramItem[], sections: Section[], editing?: boolean,
}> {
render() {
const { sequence, sections } = this.props;
const editing = this.props.editing || false;
const className = classNames("programSequence", { editing });
- const sequenceItems = sequence.map((item, index) => {
- const onChange = editing ? (newItem: ProgramItem) => this.changeItem(newItem, index) : undefined;
- return ;
- });
- return {sequenceItems}
;
+ const onChange = editing ? this.changeItem : undefined;
+ return (
+
+ );
}
- private changeItem = (newItem: ProgramItem, index: number) => {
+ private changeItem: ItemChangeHandler = (newItem, index) => {
this.props.sequence[index] = newItem;
}
+
+ private onSortEnd = ({oldIndex, newIndex}: SortEnd) => {
+ const { sequence: array } = this.props;
+ if (newIndex >= array.length) {
+ return;
+ }
+ array.splice(newIndex, 0, array.splice(oldIndex, 1)[0]);
+ }
}
+
+const ProgramSequenceViewD = SortableContainer(ProgramSequenceView);
+export default ProgramSequenceViewD;
diff --git a/app/styles/DurationView.scss b/app/styles/DurationView.scss
index 0a2d838..b204e80 100644
--- a/app/styles/DurationView.scss
+++ b/app/styles/DurationView.scss
@@ -1,49 +1,42 @@
$durationInput-spacing: 1.0em;
+$durationInput-inputWidth: 4em;
+$durationInput-labelWidth: 2.5em;
-.durationInputs {
- display: flex;
- // max-width: 100%;
+.field .durationInputs {
+ display: flex; // max-width: 100%;
justify-content: start;
flex-wrap: wrap;
margin: -$durationInput-spacing / 2;
- &.inline {
- min-width: 20em;
-
- .ui.input.durationInput {
- >input {
- width: 0 !important;
- }
- }
- }
-}
-
-$durationInput-inputWidth: 4em;
-$durationInput-labelWidth: 2.5em;
-
-.ui.form .field .ui.input.durationInput {
- padding: $durationInput-spacing / 2;
-
- max-width: 100%;
width: auto;
- flex-basis: auto;
- flex-shrink: 0;
- flex-grow: 1;
- > input {
- min-width: $durationInput-inputWidth;
- width: auto;
- flex-basis: $durationInput-inputWidth;
- flex-grow: 1;
- flex-shrink: 0;
+ .ui.input.durationInput>input {
+ width: 0 !important;
}
- > .label {
- min-width: $durationInput-labelWidth;
- width: $durationInput-labelWidth;
- flex: $durationInput-labelWidth;
- flex-grow: 0;
+ .ui.input.durationInput {
+ padding: $durationInput-spacing / 2;
+ max-width: 100%;
+ width: auto !important;
+ flex-basis: auto;
flex-shrink: 0;
- text-align: center;
+ flex-grow: 1;
+
+ >input {
+ min-width: $durationInput-inputWidth;
+ width: auto;
+ flex-basis: $durationInput-inputWidth;
+ flex-grow: 1;
+ flex-shrink: 0;
+ }
+
+ >.label {
+ min-width: $durationInput-labelWidth;
+ width: $durationInput-labelWidth;
+ flex: $durationInput-labelWidth;
+ flex-grow: 0;
+ flex-shrink: 0;
+ text-align: center;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/app/styles/ProgramSequenceView.scss b/app/styles/ProgramSequenceView.scss
index 62d19aa..061f058 100644
--- a/app/styles/ProgramSequenceView.scss
+++ b/app/styles/ProgramSequenceView.scss
@@ -1,3 +1,22 @@
-.programSequence.editing .item .content {
- width: 20em;
+.programSequence {
+ &.editing .programSequence-item .content {
+ // width: 20em;
+ }
+ padding-left: 0;
}
+
+.programSequence-item {
+ list-style-type: none;
+ z-index: 2000;
+ display: flex;
+ margin-bottom: .5em;
+ i.icon {
+ margin: .5rem;
+ }
+ .header {
+ font-weight: bold;
+ }
+ .durationInputs {
+ width: 20em;
+ }
+}
\ No newline at end of file
diff --git a/app/styles/SectionChooser.scss b/app/styles/SectionChooser.scss
index 8f95232..3376746 100644
--- a/app/styles/SectionChooser.scss
+++ b/app/styles/SectionChooser.scss
@@ -1,5 +1,7 @@
.sectionChooser {
.ui.selection.dropdown {
- min-width: 14em;
+ min-width: 10em;
+ max-width: 100%;
+ width: 14em !important;
}
}
diff --git a/package.json b/package.json
index fbeaad1..6b00d33 100644
--- a/package.json
+++ b/package.json
@@ -72,6 +72,7 @@
"@types/react-dom": "16.0.6",
"@types/react-hot-loader": "^4.1.0",
"@types/react-router-dom": "^4.3.0",
+ "@types/react-sortable-hoc": "^0.6.3",
"@types/webpack-env": "^1.13.6",
"@types/ws": "^5.1.2",
"async": "^2.6.1",
@@ -105,6 +106,7 @@
"react-hot-loader": "^4.3.3",
"react-router": "^4.3.1",
"react-router-dom": "^4.3.1",
+ "react-sortable-hoc": "^0.8.3",
"sass-loader": "^7.0.3",
"semantic-ui-css": "^2.3.3",
"semantic-ui-react": "^0.82.1",
diff --git a/yarn.lock b/yarn.lock
index f7d7327..3a7e1ab 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -144,6 +144,12 @@
"@types/history" "*"
"@types/react" "*"
+"@types/react-sortable-hoc@^0.6.3":
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/@types/react-sortable-hoc/-/react-sortable-hoc-0.6.3.tgz#b9d034ab2728691ef3270ede5f4b4fd1cead52bd"
+ dependencies:
+ "@types/react" "*"
+
"@types/react@*", "@types/react@16.4.7":
version "16.4.7"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.4.7.tgz#f33f6d759a7e1833befa15224d68942d178a5a3f"
@@ -641,6 +647,13 @@ babel-code-frame@6.26.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
esutils "^2.0.2"
js-tokens "^3.0.2"
+babel-runtime@^6.11.6:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+ dependencies:
+ core-js "^2.4.0"
+ regenerator-runtime "^0.11.0"
+
backo2@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
@@ -1442,7 +1455,7 @@ core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
-core-js@^2.5.7:
+core-js@^2.4.0, core-js@^2.5.7:
version "2.5.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
@@ -5624,7 +5637,7 @@ promise@^8.0.1:
dependencies:
asap "~2.0.3"
-prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
+prop-types@^15.5.7, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
version "15.6.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
dependencies:
@@ -5858,6 +5871,14 @@ react-router@^4.3.1:
prop-types "^15.6.1"
warning "^4.0.1"
+react-sortable-hoc@^0.8.3:
+ version "0.8.3"
+ resolved "https://registry.yarnpkg.com/react-sortable-hoc/-/react-sortable-hoc-0.8.3.tgz#8537e8ab8d6bad6829885755a0f847817ed78648"
+ dependencies:
+ babel-runtime "^6.11.6"
+ invariant "^2.2.1"
+ prop-types "^15.5.7"
+
react@16.4.1:
version "16.4.1"
resolved "https://registry.yarnpkg.com/react/-/react-16.4.1.tgz#de51ba5764b5dbcd1f9079037b862bd26b82fe32"
@@ -5954,6 +5975,10 @@ regenerate@^1.2.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
+regenerator-runtime@^0.11.0:
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+
regenerator-runtime@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.0.tgz#8052ac952d85b10f3425192cd0c53f45cf65c6cb"