{
render() {
return
+ transitionEnterTimeout={500} transitionLeaveTimeout={500}>
{this.props.uiStore.messages.map(this.renderMessage)}
;
}
private renderMessage = (message: UiMessage, index: number) => {
- const { header, content, type } = message;
+ const {header, content, type} = message;
return this.dismiss(index)} />;
+ header={header} content={content}
+ success={type === UiMessage.Type.Success}
+ info={type === UiMessage.Type.Info} warning={type === UiMessage.Type.Warning}
+ error={type === UiMessage.Type.Error} onDismiss={() => this.dismiss(index)}/>;
}
private dismiss(index: number) {
diff --git a/app/script/components/ProgramTable.tsx b/app/script/components/ProgramTable.tsx
index 7d89d22..531d50c 100644
--- a/app/script/components/ProgramTable.tsx
+++ b/app/script/components/ProgramTable.tsx
@@ -1,7 +1,7 @@
-import * as React from "react";
import {observer} from "mobx-react";
-import {Program, Schedule} from "../sprinklers";
+import * as React from "react";
import {Table} from "semantic-ui-react";
+import {Program, Schedule} from "../sprinklers";
@observer
export class ScheduleView extends React.PureComponent<{ schedule: Schedule }, {}> {
diff --git a/app/script/components/RunSectionForm.tsx b/app/script/components/RunSectionForm.tsx
index 8b69b6e..6ff15c9 100644
--- a/app/script/components/RunSectionForm.tsx
+++ b/app/script/components/RunSectionForm.tsx
@@ -1,10 +1,10 @@
-import * as React from "react";
-import {SyntheticEvent} from "react";
import {computed} from "mobx";
import {observer} from "mobx-react";
-import {Duration, Section} from "../sprinklers";
-import {Segment, Header, Form, DropdownProps, DropdownItemProps} from "semantic-ui-react";
+import * as React from "react";
+import {SyntheticEvent} from "react";
+import {DropdownItemProps, DropdownProps, Form, Header, Segment} from "semantic-ui-react";
import {DurationInput} from ".";
+import {Duration, Section} from "../sprinklers";
@observer
export default class RunSectionForm extends React.Component<{
diff --git a/app/script/components/SectionTable.tsx b/app/script/components/SectionTable.tsx
index a7bdb70..37ccefa 100644
--- a/app/script/components/SectionTable.tsx
+++ b/app/script/components/SectionTable.tsx
@@ -1,10 +1,10 @@
-import * as React from "react";
-import {observer} from "mobx-react";
import * as classNames from "classnames";
+import {observer} from "mobx-react";
+import * as React from "react";
import {Table} from "semantic-ui-react";
-import FontAwesome = require("react-fontawesome");
import {Section} from "../sprinklers";
+import FontAwesome = require("react-fontawesome");
/* tslint:disable:object-literal-sort-keys */
diff --git a/app/script/index.tsx b/app/script/index.tsx
index 8527c91..1bc91cb 100644
--- a/app/script/index.tsx
+++ b/app/script/index.tsx
@@ -1,9 +1,9 @@
import * as React from "react";
import * as ReactDOM from "react-dom";
-import { AppContainer } from "react-hot-loader";
+import {AppContainer} from "react-hot-loader";
import App from "./components/App";
-import { MqttApiClient } from "./mqtt";
+import {MqttApiClient} from "./mqtt";
import {Message, UiStore} from "./ui";
const client = new MqttApiClient();
@@ -15,14 +15,14 @@ uiStore.addMessage(new Message("asdf", "boo!", Message.Type.Error));
const rootElem = document.getElementById("app");
ReactDOM.render(
-
+
, rootElem);
if (module.hot) {
module.hot.accept("./components/App", () => {
const NextApp = require("./components/App").default;
ReactDOM.render(
-
+
, rootElem);
});
}
diff --git a/app/script/mqtt.ts b/app/script/mqtt.ts
index 3999184..ecda84f 100644
--- a/app/script/mqtt.ts
+++ b/app/script/mqtt.ts
@@ -1,21 +1,22 @@
-import "paho-mqtt";
-import MQTT = Paho.MQTT;
-
import {EventEmitter} from "events";
+import "paho-mqtt";
import {
- SprinklersDevice, ISprinklersApi, Section, Program, Schedule, ITimeOfDay, Duration, SectionRunner, ISectionRun,
+ Duration,
+ ISectionRun,
+ ISprinklersApi,
+ ITimeOfDay,
+ Program,
+ Schedule,
+ Section,
+ SectionRunner,
+ SprinklersDevice,
} from "./sprinklers";
import {checkedIndexOf} from "./utils";
+import MQTT = Paho.MQTT;
export class MqttApiClient extends EventEmitter implements ISprinklersApi {
- private static newClientId() {
- return "sprinklers3-MqttApiClient-" + Math.round(Math.random() * 1000);
- }
-
client: MQTT.Client;
-
connected: boolean;
-
devices: { [prefix: string]: MqttSprinklersDevice } = {};
constructor() {
@@ -26,6 +27,10 @@ export class MqttApiClient extends EventEmitter implements ISprinklersApi {
// (this.client as any).trace = (m => console.log(m));
}
+ private static newClientId() {
+ return "sprinklers3-MqttApiClient-" + Math.round(Math.random() * 1000);
+ }
+
start() {
console.log("connecting to mqtt with client id %s", this.client.clientId);
this.client.connect({
@@ -106,6 +111,22 @@ class MqttSprinklersDevice extends SprinklersDevice {
this.sectionRunner = new MqttSectionRunner(this);
}
+ get id(): string {
+ return this.prefix;
+ }
+
+ private get subscriptions() {
+ return [
+ `${this.prefix}/connected`,
+ `${this.prefix}/sections`,
+ `${this.prefix}/sections/+/#`,
+ `${this.prefix}/programs`,
+ `${this.prefix}/programs/+/#`,
+ `${this.prefix}/responses/+`,
+ `${this.prefix}/section_runner`,
+ ];
+ }
+
doSubscribe() {
const c = this.apiClient.client;
this.subscriptions
@@ -184,10 +205,6 @@ class MqttSprinklersDevice extends SprinklersDevice {
console.warn(`MqttSprinklersDevice recieved invalid topic: ${topic}`);
}
- get id(): string {
- return this.prefix;
- }
-
runSection(section: Section | number, duration: Duration) {
const sectionNum = checkedIndexOf(section, this.sections, "Section");
const payload: IRunSectionJSON = {
@@ -202,7 +219,7 @@ class MqttSprinklersDevice extends SprinklersDevice {
}
cancelSectionRunById(id: number) {
- return this.makeRequest(`section_runner/cancel_id`, { id });
+ return this.makeRequest(`section_runner/cancel_id`, {id});
}
//noinspection JSMethodCanBeStatic
@@ -228,23 +245,12 @@ class MqttSprinklersDevice extends SprinklersDevice {
});
}
-
- private get subscriptions() {
- return [
- `${this.prefix}/connected`,
- `${this.prefix}/sections`,
- `${this.prefix}/sections/+/#`,
- `${this.prefix}/programs`,
- `${this.prefix}/programs/+/#`,
- `${this.prefix}/responses/+`,
- `${this.prefix}/section_runner`,
- ];
- }
}
interface IResponseData {
reqTopic: string;
error?: string;
+
[key: string]: any;
}
diff --git a/app/script/sprinklers.ts b/app/script/sprinklers.ts
index d71be62..403d733 100644
--- a/app/script/sprinklers.ts
+++ b/app/script/sprinklers.ts
@@ -1,4 +1,4 @@
-import { observable, IObservableArray } from "mobx";
+import {IObservableArray, observable} from "mobx";
export abstract class Section {
device: SprinklersDevice;
@@ -41,10 +41,6 @@ export class Schedule {
}
export class Duration {
- static fromSeconds(seconds: number): Duration {
- return new Duration(Math.floor(seconds / 60), seconds % 60);
- }
-
minutes: number = 0;
seconds: number = 0;
@@ -53,6 +49,10 @@ export class Duration {
this.seconds = seconds;
}
+ static fromSeconds(seconds: number): Duration {
+ return new Duration(Math.floor(seconds / 60), seconds % 60);
+ }
+
toSeconds(): number {
return this.minutes * 60 + this.seconds;
}
@@ -162,17 +162,18 @@ export abstract class SprinklersDevice {
@observable
sectionRunner: SectionRunner;
+ abstract get id(): string;
+
abstract runSection(section: number | Section, duration: Duration): Promise<{}>;
abstract runProgram(program: number | Program): Promise<{}>;
abstract cancelSectionRunById(id: number): Promise<{}>;
-
- abstract get id(): string;
}
export interface ISprinklersApi {
start();
+
getDevice(id: string): SprinklersDevice;
removeDevice(id: string);
diff --git a/tslint.json b/tslint.json
index 0b61947..c05a219 100644
--- a/tslint.json
+++ b/tslint.json
@@ -11,15 +11,22 @@
"max-classes-per-file": [
false
],
- "ordered-imports": false,
+ "ordered-imports": true,
"variable-name": [
"allow-leading-underscore"
],
- "no-namespace": [
- "allow-declarations"
- ],
+ "no-namespace": false,
"interface-name": false,
- "member-access": [ true, "no-public" ]
+ "member-access": [
+ true,
+ "no-public"
+ ],
+ "member-ordering": [
+ true,
+ {
+ "order": "fields-first"
+ }
+ ]
},
"rulesDirectory": []
-}
\ No newline at end of file
+}