Browse Source

Lots of good improvements

update-deps
Alex Mikhalev 7 years ago
parent
commit
adffea950a
  1. 5
      .vscode/tasks.json
  2. 2
      app/components/App.tsx
  3. 24
      app/components/DeviceView.tsx
  4. 7
      app/components/DurationInput.tsx
  5. 9
      app/components/RunSectionForm.tsx
  6. 2
      app/components/SectionTable.tsx
  7. 11
      app/state/StateBase.ts
  8. 33
      app/state/index.ts
  9. 14
      app/state/web.ts
  10. 4
      app/styles/app.css
  11. 14
      common/sprinklers/SprinklersDevice.ts
  12. 7
      common/sprinklers/mqtt/index.ts

5
.vscode/tasks.json vendored

@ -48,6 +48,11 @@ @@ -48,6 +48,11 @@
"type": "npm",
"script": "start:dev-server",
"problemMatcher": []
},
{
"type": "npm",
"script": "start:nodemon",
"problemMatcher": []
}
]
}

2
app/components/App.tsx

@ -13,7 +13,7 @@ import "semantic-ui-css/semantic.css"; @@ -13,7 +13,7 @@ import "semantic-ui-css/semantic.css";
class App extends React.Component {
render() {
return (
<Container>
<Container className="app">
{/* <MessageTest /> */}
<DevicesView />
<MessagesView />

24
app/components/DeviceView.tsx

@ -1,25 +1,25 @@ @@ -1,25 +1,25 @@
import * as classNames from "classnames";
import { observer } from "mobx-react";
import * as React from "react";
import { Header, Icon, Item } from "semantic-ui-react";
import { Grid, Header, Icon, Item } from "semantic-ui-react";
import { injectState, MqttApiState } from "@app/state";
import { SprinklersDevice } from "@common/sprinklers";
import { ProgramTable, RunSectionForm, SectionRunnerView, SectionTable } from ".";
const ConnectionState = ({ connected }: { connected: boolean }) => {
function ConnectionState({ connected, className }: { connected: boolean, className?: string }) {
const classes = classNames({
"device--connectionState": true,
"device--connectionState-connected": connected,
"device--connectionState-disconnected": !connected,
});
}, className);
return (
<span className={classes}>
<div className={classes}>
<Icon name={connected ? "linkify" : "unlinkify"} />&nbsp;
{connected ? "Connected" : "Disconnected"}
</span>
</div>
);
};
}
interface DeviceViewProps {
deviceId: string;
@ -44,14 +44,20 @@ class DeviceView extends React.Component<DeviceViewProps> { @@ -44,14 +44,20 @@ class DeviceView extends React.Component<DeviceViewProps> {
<Item.Image src={require("@app/images/raspberry_pi.png")} />
<Item.Content>
<Header as="h1">
<span>Device </span><kbd>{id}</kbd>
<div>Device <kbd>{id}</kbd></div>
<ConnectionState connected={connected} />
</Header>
<Item.Meta>
Raspberry Pi Grinklers Instance
</Item.Meta>
<SectionTable sections={sections} />
<RunSectionForm sections={sections} />
<Grid>
<Grid.Column mobile={16} largeScreen={8}>
<SectionTable sections={sections} />
</Grid.Column>
<Grid.Column mobile={16} largeScreen={8}>
<RunSectionForm sections={sections} />
</Grid.Column>
</Grid>
<ProgramTable programs={programs} />
<SectionRunnerView sectionRunner={sectionRunner} sections={sections} />
</Item.Content>

7
app/components/DurationInput.tsx

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
import * as classNames from "classnames";
import * as React from "react";
import { Input, InputProps } from "semantic-ui-react";
@ -5,13 +6,15 @@ import { Duration } from "@common/Duration"; @@ -5,13 +6,15 @@ import { Duration } from "@common/Duration";
export default class DurationInput extends React.Component<{
duration: Duration,
onDurationChange: (newDuration: Duration) => void;
onDurationChange: (newDuration: Duration) => void,
className?: string,
}> {
render() {
const duration = this.props.duration;
const className = classNames("field", "durationInput", this.props.className);
// const editing = this.props.onDurationChange != null;
return (
<div className="field durationInput">
<div className={className}>
<label>Duration</label>
<div className="fields">
<Input

9
app/components/RunSectionForm.tsx

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import { computed } from "mobx";
import { observer } from "mobx-react";
import * as React from "react";
import { DropdownItemProps, DropdownProps, Form, Header, Segment } from "semantic-ui-react";
import { DropdownItemProps, DropdownProps, Form, Grid, Header, Segment } from "semantic-ui-react";
import { Duration } from "@common/Duration";
import log from "@common/logger";
@ -29,7 +29,7 @@ export default class RunSectionForm extends React.Component<{ @@ -29,7 +29,7 @@ export default class RunSectionForm extends React.Component<{
<Segment>
<Header>Run Section</Header>
<Form>
<Form.Group>
<Form.Group className="doubling stackable three column ui grid">
<Form.Select
label="Section"
placeholder="Section"
@ -37,7 +37,10 @@ export default class RunSectionForm extends React.Component<{ @@ -37,7 +37,10 @@ export default class RunSectionForm extends React.Component<{
value={section}
onChange={this.onSectionChange}
/>
<DurationInput duration={duration} onDurationChange={this.onDurationChange} />
<DurationInput
duration={duration}
onDurationChange={this.onDurationChange}
/>
{/*Label must be &nbsp; to align it properly*/}
<Form.Button
label="&nbsp;"

2
app/components/SectionTable.tsx

@ -34,7 +34,7 @@ export default class SectionTable extends React.Component<{ sections: Section[] @@ -34,7 +34,7 @@ export default class SectionTable extends React.Component<{ sections: Section[]
render() {
const rows = this.props.sections.map(SectionTable.renderRow);
return (
<Table celled striped>
<Table celled striped unstackable>
<Table.Header>
<Table.Row>
<Table.HeaderCell colSpan="3">Sections</Table.HeaderCell>

11
app/state/StateBase.ts

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
import { ISprinklersApi } from "@common/sprinklers";
import { UiMessage, UiStore } from "./ui";
export default abstract class StateBase {
abstract readonly sprinklersApi: ISprinklersApi;
uiStore = new UiStore();
start() {
this.sprinklersApi.start();
}
}

33
app/state/index.ts

@ -1,32 +1,3 @@ @@ -1,32 +1,3 @@
import { ISprinklersApi } from "@common/sprinklers";
import { MqttApiClient } from "@common/sprinklers/mqtt";
import { WebApiClient } from "./websocket";
import { UiMessage, UiStore } from "./ui";
export { UiMessage, UiStore };
export { UiMessage, UiStore } from "./ui";
export * from "./inject";
export abstract class StateBase {
abstract readonly sprinklersApi: ISprinklersApi;
uiStore = new UiStore();
constructor() {
this.uiStore.addMessage({ header: "asdf", content: "boo!", error: true });
}
start() {
this.sprinklersApi.start();
}
}
const isDev = process.env.NODE_ENV === "development";
export class MqttApiState extends StateBase {
sprinklersApi = new MqttApiClient(`ws://${location.hostname}:1884`);
}
export class WebApiState extends StateBase {
sprinklersApi = new WebApiClient(isDev ?
`ws://${location.hostname}:8080` :
`ws://${location.host}`);
}
export { default as StateBase } from "./StateBase";

14
app/state/web.ts

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
import { MqttApiClient } from "@common/sprinklers/mqtt";
import StateBase from "./StateBase";
import { WebApiClient } from "./websocket";
const isDev = process.env.NODE_ENV === "development";
const websocketPort = isDev ? 8080 : location.port;
export class MqttApiState extends StateBase {
sprinklersApi = new MqttApiClient(`ws://${location.hostname}:1884`);
}
export class WebApiState extends StateBase {
sprinklersApi = new WebApiClient(`ws://${location.hostname}:${websocketPort}`);
}

4
app/styles/app.css

@ -1,3 +1,7 @@ @@ -1,3 +1,7 @@
.app {
margin-top: 1em;
}
.device--connectionState {
margin-left: .75em;
font-size: .75em;

14
common/sprinklers/SprinklersDevice.ts

@ -10,6 +10,10 @@ export abstract class SprinklersDevice { @@ -10,6 +10,10 @@ export abstract class SprinklersDevice {
@observable programs: Program[] = [];
@observable sectionRunner: SectionRunner;
sectionConstructor: typeof Section = Section;
sectionRunnerConstructor: typeof SectionRunner = SectionRunner;
programConstructor: typeof Program = Program;
constructor() {
this.sectionRunner = new (this.sectionRunnerConstructor)(this);
}
@ -45,16 +49,6 @@ export abstract class SprinklersDevice { @@ -45,16 +49,6 @@ export abstract class SprinklersDevice {
return this.makeRequest({ ...opts, type: "pauseSectionRunner" });
}
get sectionConstructor(): typeof Section {
return Section;
}
get sectionRunnerConstructor(): typeof SectionRunner {
return SectionRunner;
}
get programConstructor(): typeof Program {
return Program;
}
toString(): string {
return `SprinklersDevice{id="${this.id}", connected=${this.connected}, ` +
`sections=[${this.sections}], ` +

7
common/sprinklers/mqtt/index.ts

@ -132,6 +132,9 @@ class MqttSprinklersDevice extends s.SprinklersDevice { @@ -132,6 +132,9 @@ class MqttSprinklersDevice extends s.SprinklersDevice {
constructor(apiClient: MqttApiClient, prefix: string) {
super();
this.sectionConstructor = MqttSection;
this.sectionRunnerConstructor = MqttSectionRunner;
this.programConstructor = MqttProgram;
this.apiClient = apiClient;
this.prefix = prefix;
this.sectionRunner = new MqttSectionRunner(this);
@ -141,10 +144,6 @@ class MqttSprinklersDevice extends s.SprinklersDevice { @@ -141,10 +144,6 @@ class MqttSprinklersDevice extends s.SprinklersDevice {
return this.prefix;
}
get sectionConstructor() { return MqttSection; }
get sectionRunnerConstructor() { return MqttSectionRunner; }
get programConstructor() { return MqttProgram; }
doSubscribe() {
const topics = subscriptions.map((filter) => this.prefix + filter);
this.apiClient.client.subscribe(topics, { qos: 1 });

Loading…
Cancel
Save