commit
e6b154602b
|
@ -1,3 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
|
||||
|
|
|
@ -385,7 +385,8 @@ CREATE TABLE public.farmware_installations (
|
|||
url character varying,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
package character varying(80)
|
||||
package character varying(80),
|
||||
package_error character varying
|
||||
);
|
||||
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ export class Account extends React.Component<Props, State> {
|
|||
const deleteAcct =
|
||||
(password: string) => this.props.dispatch(deleteUser({ password }));
|
||||
|
||||
return <Page className="account">
|
||||
return <Page className="account-page">
|
||||
<Col xs={12} sm={6} smOffset={3}>
|
||||
<Row>
|
||||
<Settings
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
&.green {
|
||||
background-color: $green;
|
||||
box-shadow: 0 2px 0px 0px darken($green, 12%);
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($green, 5%) !important;
|
||||
|
@ -63,6 +64,7 @@
|
|||
&.blue {
|
||||
background-color: $blue;
|
||||
box-shadow: 0 2px 0px 0px darken($blue, 12%);
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($blue, 5%) !important;
|
||||
|
@ -71,6 +73,7 @@
|
|||
&.red {
|
||||
background-color: $red;
|
||||
box-shadow: 0 2px 0px 0px darken($red, 12%);
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($red, 5%) !important;
|
||||
|
@ -83,6 +86,7 @@
|
|||
&.disabled {
|
||||
background: $gray !important;
|
||||
}
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($medium_gray, 5%) !important;
|
||||
|
@ -92,6 +96,7 @@
|
|||
color: $dark_gray;
|
||||
background-color: $yellow;
|
||||
box-shadow: 0 2px 0px 0px darken($yellow, 12%);
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($yellow, 5%) !important;
|
||||
|
@ -101,6 +106,7 @@
|
|||
color: $dark_gray;
|
||||
background-color: $orange;
|
||||
box-shadow: 0 2px 0px 0px darken($orange, 12%);
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($orange, 5%) !important;
|
||||
|
@ -109,6 +115,7 @@
|
|||
&.magenta {
|
||||
background-color: $magenta;
|
||||
box-shadow: 0 2px 0px 0px darken($magenta, 12%);
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($magenta, 5%) !important;
|
||||
|
@ -117,6 +124,7 @@
|
|||
&.cyan {
|
||||
background-color: $cyan;
|
||||
box-shadow: 0 2px 0px 0px darken($cyan, 12%);
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($cyan, 5%) !important;
|
||||
|
@ -125,6 +133,7 @@
|
|||
&.brown {
|
||||
background-color: $brown;
|
||||
box-shadow: 0 2px 0px 0px darken($brown, 12%);
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($brown, 5%) !important;
|
||||
|
@ -133,6 +142,7 @@
|
|||
&.purple {
|
||||
background-color: $purple;
|
||||
box-shadow: 0 2px 0px 0px darken($purple, 12%);
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($purple, 5%) !important;
|
||||
|
@ -141,6 +151,7 @@
|
|||
&.pink {
|
||||
background-color: $pink;
|
||||
box-shadow: 0 2px 0px 0px darken($pink, 12%);
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($pink, 5%) !important;
|
||||
|
@ -159,6 +170,7 @@
|
|||
&.pseudo-disabled {
|
||||
background: $medium_light_gray !important;
|
||||
box-shadow: 0 2px 0px 0px lighten($medium_light_gray, 5%) !important;
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background: $medium_light_gray !important;
|
||||
|
@ -178,6 +190,7 @@
|
|||
&.gray {
|
||||
background-color: $medium_light_gray !important;
|
||||
box-shadow: 0 2px 0px 0px darken($medium_light_gray, 12%);
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: darken($medium_light_gray, 5%) !important;
|
||||
|
|
|
@ -575,9 +575,10 @@ ul {
|
|||
.unavailable {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
width: 100%;
|
||||
opacity: 0.40;
|
||||
pointer-events: none;
|
||||
* {
|
||||
pointer-events: none;
|
||||
}
|
||||
&.banner {
|
||||
&:after {
|
||||
content: "Not available when device is offline.";
|
||||
|
@ -868,6 +869,12 @@ ul {
|
|||
}
|
||||
}
|
||||
|
||||
.account-page {
|
||||
label {
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.release-notes-button {
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
|
@ -966,6 +973,10 @@ ul {
|
|||
}
|
||||
}
|
||||
|
||||
.farmware-name-manual-input {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.checkbox-row {
|
||||
margin-top: 1rem;
|
||||
label {
|
||||
|
@ -1037,7 +1048,8 @@ ul {
|
|||
background: $pink;
|
||||
border: 1px solid $red;
|
||||
border-radius: 5px;
|
||||
label, p {
|
||||
label,
|
||||
p {
|
||||
margin: 0.5rem;
|
||||
color: $red;
|
||||
}
|
||||
|
|
|
@ -89,6 +89,9 @@
|
|||
}
|
||||
|
||||
.farmware-button {
|
||||
div {
|
||||
float: right;
|
||||
}
|
||||
p {
|
||||
float: right;
|
||||
margin-top: 0.75rem;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
height: 9rem;
|
||||
height: 8.9rem;
|
||||
background: $dark_gray;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, .2);
|
||||
}
|
||||
|
@ -43,6 +43,9 @@ nav {
|
|||
padding: 2rem 1rem;
|
||||
letter-spacing: 1.2px;
|
||||
transition: font-weight 0.2s ease;
|
||||
&:focus {
|
||||
font-weight: bold;
|
||||
}
|
||||
&:hover {
|
||||
font-weight: bold;
|
||||
color: $white;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
left: 0;
|
||||
right: 0;
|
||||
z-index: 3;
|
||||
height: 3.25rem;
|
||||
background: $black;
|
||||
opacity: 0.9;
|
||||
.bp3-collapse {
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
}
|
||||
|
||||
.widget-header {
|
||||
height: 3.3rem;
|
||||
background: $dark_gray;
|
||||
letter-spacing: .05rem;
|
||||
padding: .75rem 1rem;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import * as React from "react";
|
||||
import { NetworkState } from "../connectivity/interfaces";
|
||||
import { SyncStatus } from "farmbot";
|
||||
import { t } from "i18next";
|
||||
import { Content } from "../constants";
|
||||
|
||||
/** Properties for the <MustBeOnline/> element. */
|
||||
export interface MBOProps {
|
||||
|
@ -23,6 +25,10 @@ export function MustBeOnline(props: MBOProps) {
|
|||
if ((botUp && netUp) || lockOpen) {
|
||||
return <div> {children} </div>;
|
||||
} else {
|
||||
return <div className={`unavailable ${banner}`}> {children} </div>;
|
||||
return <div
|
||||
className={`unavailable ${banner}`}
|
||||
title={t(Content.NOT_AVAILABLE_WHEN_OFFLINE)}>
|
||||
{children}
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,21 +218,22 @@ export class EditFEForm extends React.Component<EditFEProps, State> {
|
|||
allowedDeclarations={AllowedDeclaration.variable}
|
||||
shouldDisplay={this.props.shouldDisplay} />
|
||||
|
||||
executableSet = (e: DropDownItem) => {
|
||||
if (e.value) {
|
||||
const { executable_type } = this.props.farmEvent.body;
|
||||
if (executable_type === "Regimen" &&
|
||||
executableType(e.headingId) === "Sequence") {
|
||||
executableSet = (ddi: DropDownItem) => {
|
||||
if (ddi.value) {
|
||||
const prev_executable_type = this.props.farmEvent.body.executable_type;
|
||||
const next_executable_type = executableType(ddi.headingId);
|
||||
if (prev_executable_type === "Regimen" &&
|
||||
next_executable_type === "Sequence") {
|
||||
error(t("Cannot change from a Regimen to a Sequence."));
|
||||
history.push("/app/designer/farm_events");
|
||||
} else {
|
||||
const { uuid } =
|
||||
this.props.findExecutable(executable_type, parseInt("" + e.value));
|
||||
const { uuid } = this.props.findExecutable(
|
||||
next_executable_type, parseInt("" + ddi.value));
|
||||
const varData = this.props.resources.sequenceMetas[uuid];
|
||||
const update: State = {
|
||||
fe: {
|
||||
executable_type: executableType(e.headingId),
|
||||
executable_id: (e.value || "").toString(),
|
||||
executable_type: next_executable_type,
|
||||
executable_id: (ddi.value || "").toString(),
|
||||
},
|
||||
specialStatusLocal: SpecialStatus.DIRTY
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@ describe("mapStateToProps()", () => {
|
|||
|
||||
it("sync status unknown", () => {
|
||||
const props = mapStateToProps(fakeState());
|
||||
expect(props.botToMqttStatus).toEqual("up");
|
||||
expect(props.botToMqttStatus).toEqual("down");
|
||||
});
|
||||
|
||||
it("currentImage undefined", () => {
|
||||
|
@ -129,6 +129,15 @@ describe("mapStateToProps()", () => {
|
|||
const props = mapStateToProps(state);
|
||||
expect(props.imageJobs).toEqual([]);
|
||||
});
|
||||
|
||||
it("returns bot status", () => {
|
||||
const state = fakeState();
|
||||
state.bot.hardware.informational_settings.sync_status = "sync_now";
|
||||
state.bot.connectivity["bot.mqtt"] = { state: "up", at: "" };
|
||||
const props = mapStateToProps(state);
|
||||
expect(props.syncStatus).toEqual("sync_now");
|
||||
expect(props.botToMqttStatus).toEqual("up");
|
||||
});
|
||||
});
|
||||
|
||||
describe("saveOrEditFarmwareEnv()", () => {
|
||||
|
|
|
@ -28,11 +28,19 @@ export class CameraCalibration extends
|
|||
|
||||
render() {
|
||||
return <div className="weed-detector">
|
||||
<button
|
||||
onClick={this.props.dispatch(calibrate)}
|
||||
className="fb-button green farmware-button" >
|
||||
{t("Calibrate")}
|
||||
</button>
|
||||
<div className="farmware-button">
|
||||
<MustBeOnline
|
||||
syncStatus={this.props.syncStatus}
|
||||
networkState={this.props.botToMqttStatus}
|
||||
hideBanner={true}
|
||||
lockOpen={process.env.NODE_ENV !== "production"}>
|
||||
<button
|
||||
onClick={this.props.dispatch(calibrate)}
|
||||
className="fb-button green farmware-button" >
|
||||
{t("Calibrate")}
|
||||
</button>
|
||||
</MustBeOnline>
|
||||
</div>
|
||||
<Row>
|
||||
<Col sm={12}>
|
||||
<MustBeOnline
|
||||
|
|
|
@ -23,6 +23,8 @@ describe("<Photos/>", () => {
|
|||
dispatch: jest.fn(),
|
||||
timeOffset: 0,
|
||||
imageJobs: [],
|
||||
botToMqttStatus: "up",
|
||||
syncStatus: "synced",
|
||||
});
|
||||
|
||||
it("shows photo", () => {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { TaggedImage, JobProgress } from "farmbot";
|
||||
import { TaggedImage, JobProgress, SyncStatus } from "farmbot";
|
||||
import { NetworkState } from "../../connectivity/interfaces";
|
||||
|
||||
export interface ImageFlipperProps {
|
||||
onFlip(uuid: string | undefined): void;
|
||||
|
@ -18,4 +19,14 @@ export interface PhotosProps {
|
|||
currentImage: TaggedImage | undefined;
|
||||
timeOffset: number;
|
||||
imageJobs: JobProgress[];
|
||||
botToMqttStatus: NetworkState;
|
||||
syncStatus: SyncStatus | undefined;
|
||||
}
|
||||
|
||||
export interface PhotoButtonsProps {
|
||||
takePhoto: () => void,
|
||||
deletePhoto: () => void,
|
||||
imageJobs: JobProgress[],
|
||||
botToMqttStatus: NetworkState;
|
||||
syncStatus: SyncStatus | undefined;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import moment from "moment";
|
|||
import { t } from "i18next";
|
||||
import { success, error } from "farmbot-toastr";
|
||||
import { ImageFlipper } from "./image_flipper";
|
||||
import { PhotosProps } from "./interfaces";
|
||||
import { PhotosProps, PhotoButtonsProps } from "./interfaces";
|
||||
import { getDevice } from "../../device";
|
||||
import { Content } from "../../constants";
|
||||
import { selectImage } from "./actions";
|
||||
|
@ -12,8 +12,9 @@ import { destroy } from "../../api/crud";
|
|||
import {
|
||||
downloadProgress
|
||||
} from "../../devices/components/fbos_settings/os_update_button";
|
||||
import { JobProgress, TaggedImage } from "farmbot";
|
||||
import { TaggedImage } from "farmbot";
|
||||
import { startCase } from "lodash";
|
||||
import { MustBeOnline } from "../../devices/must_be_online";
|
||||
|
||||
interface MetaInfoProps {
|
||||
/** Default conversion is `attr_name ==> Attr Name`.
|
||||
|
@ -48,18 +49,20 @@ const PhotoMetaData = ({ image }: { image: TaggedImage | undefined }) =>
|
|||
obj={{ image: t("No meta data.") }} />}
|
||||
</div>;
|
||||
|
||||
const PhotoButtons = (props: {
|
||||
takePhoto: () => void,
|
||||
deletePhoto: () => void,
|
||||
imageJobs: JobProgress[]
|
||||
}) => {
|
||||
const PhotoButtons = (props: PhotoButtonsProps) => {
|
||||
const imageUploadJobProgress = downloadProgress(props.imageJobs[0]);
|
||||
return <div className="farmware-button">
|
||||
<button
|
||||
className="fb-button green"
|
||||
onClick={props.takePhoto}>
|
||||
{t("Take Photo")}
|
||||
</button>
|
||||
<MustBeOnline
|
||||
syncStatus={props.syncStatus}
|
||||
networkState={props.botToMqttStatus}
|
||||
hideBanner={true}
|
||||
lockOpen={process.env.NODE_ENV !== "production"}>
|
||||
<button
|
||||
className="fb-button green"
|
||||
onClick={props.takePhoto}>
|
||||
{t("Take Photo")}
|
||||
</button>
|
||||
</MustBeOnline>
|
||||
<button
|
||||
className="fb-button red"
|
||||
onClick={props.deletePhoto}>
|
||||
|
@ -115,6 +118,8 @@ export class Photos extends React.Component<PhotosProps, {}> {
|
|||
render() {
|
||||
return <div className="photos">
|
||||
<PhotoButtons
|
||||
syncStatus={this.props.syncStatus}
|
||||
botToMqttStatus={this.props.botToMqttStatus}
|
||||
takePhoto={this.takePhoto}
|
||||
deletePhoto={this.deletePhoto}
|
||||
imageJobs={this.props.imageJobs} />
|
||||
|
|
|
@ -119,6 +119,8 @@ export class FarmwarePage extends React.Component<FarmwareProps, {}> {
|
|||
case "take_photo":
|
||||
case "photos":
|
||||
return <Photos
|
||||
syncStatus={this.props.syncStatus}
|
||||
botToMqttStatus={this.props.botToMqttStatus}
|
||||
timeOffset={this.props.timeOffset}
|
||||
dispatch={this.props.dispatch}
|
||||
images={this.props.images}
|
||||
|
|
|
@ -112,17 +112,21 @@ export function mapStateToProps(props: Everything): FarmwareProps {
|
|||
.reverse()
|
||||
.value();
|
||||
|
||||
const bot2mqtt = props.bot.connectivity["bot.mqtt"];
|
||||
const botToMqttStatus = bot2mqtt ? bot2mqtt.state : "down";
|
||||
const syncStatus = props.bot.hardware.informational_settings.sync_status;
|
||||
|
||||
return {
|
||||
timeOffset: maybeGetTimeOffset(props.resources.index),
|
||||
currentFarmware,
|
||||
farmwares,
|
||||
botToMqttStatus: "up",
|
||||
botToMqttStatus,
|
||||
env: prepopulateEnv(env),
|
||||
user_env: env,
|
||||
dispatch: props.dispatch,
|
||||
currentImage,
|
||||
images,
|
||||
syncStatus: "synced",
|
||||
syncStatus,
|
||||
webAppConfig: conf ? conf.body : {},
|
||||
firstPartyFarmwareNames,
|
||||
shouldDisplay,
|
||||
|
|
|
@ -56,11 +56,17 @@ export class WeedDetector
|
|||
render() {
|
||||
return <div className="weed-detector">
|
||||
<div className="farmware-button">
|
||||
<button
|
||||
onClick={this.props.dispatch(test)}
|
||||
className="fb-button green">
|
||||
{t("detect weeds")}
|
||||
</button>
|
||||
<MustBeOnline
|
||||
syncStatus={this.props.syncStatus}
|
||||
networkState={this.props.botToMqttStatus}
|
||||
hideBanner={true}
|
||||
lockOpen={process.env.NODE_ENV !== "production"}>
|
||||
<button
|
||||
onClick={this.props.dispatch(test)}
|
||||
className="fb-button green">
|
||||
{t("detect weeds")}
|
||||
</button>
|
||||
</MustBeOnline>
|
||||
<button
|
||||
onClick={this.clearWeeds}
|
||||
className="fb-button red">
|
||||
|
|
|
@ -44,22 +44,23 @@ describe("<TileSendMessage/>", () => {
|
|||
const labels = block.find("label");
|
||||
const buttons = block.find("button");
|
||||
expect(inputs.length).toEqual(6);
|
||||
expect(labels.length).toEqual(5);
|
||||
expect(labels.length).toEqual(6);
|
||||
expect(buttons.length).toEqual(1);
|
||||
expect(inputs.first().props().placeholder).toEqual("Send Message");
|
||||
expect(labels.at(0).text()).toEqual("Message");
|
||||
expect(inputs.at(1).props().value).toEqual("send this message");
|
||||
expect(labels.at(1).text()).toEqual("type");
|
||||
expect(buttons.at(0).text()).toEqual("Info");
|
||||
expect(labels.at(1).text()).toEqual("Ticker Notification");
|
||||
expect(labels.at(2).text()).toEqual("Ticker Notification");
|
||||
expect(inputs.at(2).props().checked).toBeTruthy();
|
||||
expect(inputs.at(2).props().disabled).toBeTruthy();
|
||||
expect(labels.at(2).text()).toEqual("Toast Pop Up");
|
||||
expect(labels.at(3).text()).toEqual("Toast Pop Up");
|
||||
expect(inputs.at(3).props().checked).toBeTruthy();
|
||||
expect(inputs.at(3).props().disabled).toBeFalsy();
|
||||
expect(labels.at(3).text()).toEqual("Email");
|
||||
expect(labels.at(4).text()).toEqual("Email");
|
||||
expect(inputs.at(4).props().checked).toBeFalsy();
|
||||
expect(inputs.at(4).props().disabled).toBeFalsy();
|
||||
expect(labels.at(4).text()).toEqual("Speak");
|
||||
expect(labels.at(5).text()).toEqual("Speak");
|
||||
expect(inputs.at(5).props().checked).toBeFalsy();
|
||||
expect(inputs.at(5).props().disabled).toBeFalsy();
|
||||
});
|
||||
|
|
|
@ -77,7 +77,7 @@ export function TileExecuteScript(props: StepParams) {
|
|||
allowEmpty={true}
|
||||
customNullLabel={"Manual Input"} />
|
||||
{!isInstalled(farmwareName) &&
|
||||
<div>
|
||||
<div className="farmware-name-manual-input">
|
||||
<label>{t("Manual input")}</label>
|
||||
<StepInputBox dispatch={dispatch}
|
||||
index={index}
|
||||
|
|
|
@ -120,6 +120,7 @@ export class RefactoredSendMessage
|
|||
field="message" />
|
||||
<div className="bottom-content">
|
||||
<div className="channel-options">
|
||||
<label>{t("type")}</label>
|
||||
<FBSelect
|
||||
onChange={this.setMsgType}
|
||||
selectedItem={this.currentSelection}
|
||||
|
|
|
@ -28,6 +28,7 @@ export interface BIProps {
|
|||
hidden?: boolean;
|
||||
error?: string;
|
||||
title?: string;
|
||||
autoFocus?: boolean;
|
||||
}
|
||||
|
||||
interface BIState {
|
||||
|
@ -110,6 +111,7 @@ export class BlurableInput extends React.Component<BIProps, Partial<BIState>> {
|
|||
className: (this.props.className || "") + (this.error ? " error" : ""),
|
||||
title: this.props.title || "",
|
||||
placeholder: this.props.placeholder,
|
||||
autoFocus: this.props.autoFocus,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,17 @@ describe("util", () => {
|
|||
raw_encoders: { x: undefined, y: undefined, z: undefined }
|
||||
});
|
||||
});
|
||||
|
||||
it("returns valid location_data object when a partial is provided", () => {
|
||||
const result = Util.validBotLocationData(
|
||||
// tslint:disable-next-line:no-any
|
||||
{ raw_encoders: { x: 123 } } as any);
|
||||
expect(result).toEqual({
|
||||
position: { x: undefined, y: undefined, z: undefined },
|
||||
scaled_encoders: { x: undefined, y: undefined, z: undefined },
|
||||
raw_encoders: { x: 123, y: undefined, z: undefined }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("fancyDebug()", () => {
|
||||
|
|
|
@ -179,14 +179,11 @@ export function scrollToBottom(elementId: string) {
|
|||
|
||||
export function validBotLocationData(
|
||||
botLocationData: BotLocationData | undefined): BotLocationData {
|
||||
if (botLocationData && botLocationData.position && botLocationData.position.x) {
|
||||
return botLocationData;
|
||||
}
|
||||
return {
|
||||
return betterMerge({
|
||||
position: { x: undefined, y: undefined, z: undefined },
|
||||
scaled_encoders: { x: undefined, y: undefined, z: undefined },
|
||||
raw_encoders: { x: undefined, y: undefined, z: undefined },
|
||||
};
|
||||
}, botLocationData);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
"typecheck": "./node_modules/typescript/bin/tsc --noEmit",
|
||||
"tslint": "./node_modules/tslint/bin/tslint --project .",
|
||||
"sass-lint": "./node_modules/sass-lint/bin/sass-lint.js -c .sass-lint.yml -v -q",
|
||||
"sass-check": "./node_modules/sass/sass.js --no-source-map frontend/css/_index.scss sass.log"
|
||||
"sass-check": "./node_modules/sass/sass.js --no-source-map frontend/css/_index.scss sass.log",
|
||||
"linters": "npm run typecheck && npm run tslint && npm run sass-lint && npm run sass-check"
|
||||
},
|
||||
"keywords": [
|
||||
"farmbot"
|
||||
|
|
Loading…
Reference in New Issue