Skip to content

Commit

Permalink
add sequence import button
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielburnworth committed Aug 28, 2021
1 parent 30b149c commit 39f8868
Show file tree
Hide file tree
Showing 92 changed files with 789 additions and 562 deletions.
24 changes: 11 additions & 13 deletions frontend/__test_support__/fake_sequence_step_data.ts
@@ -1,7 +1,7 @@
import {
HardwareFlags, FarmwareData, StepParams,
} from "../sequences/interfaces";
import { WritePin } from "farmbot";
import { SequenceBodyItem } from "farmbot";
import { fakeSequence } from "./fake_state/resources";
import { emptyState } from "../resources/reducer";

Expand All @@ -22,16 +22,14 @@ export const fakeFarmwareData = (): FarmwareData => ({
cameraCalibrated: true,
});

export const fakeStepParams = (): StepParams => {
const step: WritePin = {
kind: "write_pin",
args: { pin_number: 3, pin_value: 2, pin_mode: 1 }
export const fakeStepParams =
<T extends SequenceBodyItem>(step: T): StepParams<T> => {
return {
currentSequence: fakeSequence(),
currentStep: step,
dispatch: jest.fn(),
readOnly: false,
index: 0,
resources: emptyState().index,
};
};
return {
currentSequence: fakeSequence(),
currentStep: step,
dispatch: jest.fn(),
index: 0,
resources: emptyState().index,
};
};
2 changes: 2 additions & 0 deletions frontend/api/api.ts
Expand Up @@ -111,6 +111,8 @@ export class API {
get regimensPath() { return `${this.baseUrl}/api/regimens/`; }
/** /api/sequences/ */
get sequencesPath() { return `${this.baseUrl}/api/sequences/`; }
/** /api/sequence_versions/ */
get sequenceVersionsPath() { return `${this.baseUrl}/api/sequence_versions/`; }
/** /api/tools/ */
get toolsPath() { return `${this.baseUrl}/api/tools/`; }
/** /api/images/ */
Expand Down
26 changes: 26 additions & 0 deletions frontend/constants.ts
Expand Up @@ -1033,6 +1033,32 @@ export namespace Content {
export const IS_PINNED =
trim(`This sequence is pinned.`);

export const PUBLISH_SEQUENCE =
trim(`Publishing this sequence will create a public version released
under the MIT License. Once published, anyone may find and use the
sequence free of charge for tasks including but not limited to:
importing the sequence into their FarmBot account to view and use it as
they deem fit, upgrading their copy to other published versions, making
changes to their copy, publishing, distributing, and even selling their
copy. You can publish new versions of this sequence at any time, which
other users may choose to upgrade to. You may also unpublish the
sequence and/or delete it from your account at any time to disable the
share link. However, these actions will not affect existing imports
owned by other user accounts. By publishing this sequence, you will be
releasing it under the MIT License.`);

export const IMPORT_SEQUENCE =
trim(`Importing this sequence will allow you to use it with your
FarmBot and make changes. If the original author of the sequence
publishes a new version, you will have the option to upgrade your copy.`);

export const IMPORTED_SEQUENCE =
trim(`This sequence was imported from a publicly shared sequence. If
the original author publishes a new version, you may upgrade your copy.
Upgrading will overwrite your copy with the contents of the new version.
It is recommended you check your FarmBot continues operating as expected
after any upgrades.`);

// Regimens
export const NO_REGIMEN_SELECTED =
trim(`Click one in the Regimens panel to edit, or click "+" to create
Expand Down
18 changes: 18 additions & 0 deletions frontend/css/global.scss
Expand Up @@ -1263,6 +1263,10 @@ ul {
}
}

.publish-button {
float: right;
}

.sequence-settings-menu {
.bp3-popover-wrapper {
display: inline;
Expand All @@ -1274,6 +1278,20 @@ ul {
}
}

.sequence-share-menu {
text-align: center;
max-width: 300px;
a {
display: block;
}
button {
display: block;
margin: auto;
float: none;
margin-top: 1rem;
}
}

.logs-page {
.row {
@media screen and (max-width: 974px) {
Expand Down
61 changes: 61 additions & 0 deletions frontend/css/sequences.scss
Expand Up @@ -79,6 +79,12 @@
hr {
margin: 0.5rem 0;
}
&.preview {
.filter-search,
input {
pointer-events: none;
}
}
}

.locals-list {
Expand Down Expand Up @@ -170,13 +176,31 @@
overflow-x: hidden;
}

.sequence {
&.preview {
.padding {
height: 25rem;
}
}
}

.sequence-steps {
margin-right: 25px;
margin-left: 10px;
.sequence-step {
&.hovered {
box-shadow: 0px 0px 15px #ff7700;
}
&.read-only {
margin-top: 1rem;
margin-bottom: 1rem;
.bp3-control,
.filter-search,
textarea,
input {
pointer-events: none;
}
}
}
}

Expand Down Expand Up @@ -562,3 +586,40 @@
}
}
}

.imported-banner,
.import-banner {
margin: 0 -15px 1rem -15px;
padding: 1rem 1.5rem 1rem 2rem;
background: transparentize($orange, 0.4);
button {
margin-right: 1rem;
}
label {
display: inline-block;
}
.bp3-popover-wrapper {
display: inline-block;
margin-left: 1rem;
}
}

.imported-banner {
background: transparentize($blue, 0.4);
}

.transparent-button {
text-transform: uppercase;
font-size: 1rem;
border: 1px solid;
padding: 0.4rem 1.2rem;
font-weight: bold;
letter-spacing: 1px;
border-radius: 4px;
color: $dark_gray;
background: none;
float: right;
&:hover {
background: rgba(255, 255, 255, 0.2);
}
}
8 changes: 8 additions & 0 deletions frontend/route_config.tsx
Expand Up @@ -361,6 +361,14 @@ export const UNBOUND_ROUTES = [
getChild: () => import("./sequences/panel/editor"),
childKey: "DesignerSequenceEditor"
}),
route({
children: true,
$: "/designer/sequence_versions/:sequence_version_id",
getModule,
key,
getChild: () => import("./sequences/panel/preview"),
childKey: "DesignerSequencePreview"
}),
route({
children: true,
$: "/designer/regimens",
Expand Down
53 changes: 49 additions & 4 deletions frontend/sequences/__tests__/actions_test.ts
Expand Up @@ -19,6 +19,8 @@ import {
copySequence, editCurrentSequence, selectSequence, pushStep, pinSequenceToggle,
publishSequence,
upgradeSequence,
installSequence,
unpublishSequence,
} from "../actions";
import { fakeSequence } from "../../__test_support__/fake_state/resources";
import { init, edit, overwrite } from "../../api/crud";
Expand Down Expand Up @@ -132,7 +134,8 @@ describe("publishSequence()", () => {
API.setBaseUrl("");

it("publishes sequence", async () => {
await publishSequence(123);
mockPost = Promise.resolve();
await publishSequence(123)();
expect(axios.post).toHaveBeenCalledWith(
"http://localhost/api/sequences/123/publish");
expect(success).toHaveBeenCalledWith("Sequence published.");
Expand All @@ -141,20 +144,62 @@ describe("publishSequence()", () => {

it("errors while publishing sequence", async () => {
mockPost = Promise.reject();
await publishSequence(123);
await publishSequence(123)();
expect(axios.post).toHaveBeenCalledWith(
"http://localhost/api/sequences/123/publish");
expect(success).not.toHaveBeenCalled();
expect(error).toHaveBeenCalledWith("Publish error.");
});
});

describe("unpublishSequence()", () => {
API.setBaseUrl("");

it("unpublishes sequence", async () => {
mockPost = Promise.resolve();
await unpublishSequence(123)();
expect(axios.post).toHaveBeenCalledWith(
"http://localhost/api/sequences/123/unpublish");
expect(success).toHaveBeenCalledWith("Sequence unpublished.");
expect(error).not.toHaveBeenCalled();
});

it("errors while unpublishing sequence", async () => {
mockPost = Promise.reject();
await unpublishSequence(123)();
expect(axios.post).toHaveBeenCalledWith(
"http://localhost/api/sequences/123/unpublish");
expect(success).not.toHaveBeenCalled();
expect(error).toHaveBeenCalledWith("Unpublish error.");
});
});

describe("installSequence()", () => {
it("installs sequence", async () => {
mockPost = Promise.resolve();
await installSequence(123)();
expect(axios.post).toHaveBeenCalledWith(
"http://localhost/api/sequences/123/install");
expect(success).toHaveBeenCalledWith("Sequence installed.");
expect(error).not.toHaveBeenCalled();
});

it("errors while installing sequence", async () => {
mockPost = Promise.reject();
await installSequence(123)();
expect(axios.post).toHaveBeenCalledWith(
"http://localhost/api/sequences/123/install");
expect(success).not.toHaveBeenCalled();
expect(error).toHaveBeenCalledWith("Install error.");
});
});

describe("upgradeSequence()", () => {
API.setBaseUrl("");

it("upgrades sequence", async () => {
mockPost = Promise.resolve();
await upgradeSequence(123, 1);
await upgradeSequence(123, 1)();
expect(axios.post).toHaveBeenCalledWith(
"http://localhost/api/sequences/123/upgrade/1");
expect(success).toHaveBeenCalledWith("Sequence upgraded.");
Expand All @@ -163,7 +208,7 @@ describe("upgradeSequence()", () => {

it("errors while publishing sequence", async () => {
mockPost = Promise.reject();
await upgradeSequence(123, 1);
await upgradeSequence(123, 1)();
expect(axios.post).toHaveBeenCalledWith(
"http://localhost/api/sequences/123/upgrade/1");
expect(success).not.toHaveBeenCalled();
Expand Down
14 changes: 14 additions & 0 deletions frontend/sequences/__tests__/all_steps_test.tsx
Expand Up @@ -11,6 +11,7 @@ describe("<AllSteps/>", () => {
sequence: fakeSequence(),
onDrop: jest.fn(),
dispatch: jest.fn(),
readOnly: false,
resources: fakeResourceIndex(),
});

Expand All @@ -34,6 +35,19 @@ describe("<AllSteps/>", () => {
.map(stepClass => expect(wrapper.html()).toContain(stepClass));
});

it("renders read-only steps", () => {
const p = fakeProps();
p.readOnly = true;
p.sequence.body.body = [
{ kind: "move_relative", args: { x: 0, y: 0, z: 0, speed: 100 } },
{ kind: "read_pin", args: { pin_number: 0, pin_mode: 0, label: "---" } },
{ kind: "write_pin", args: { pin_number: 0, pin_value: 0, pin_mode: 0 } },
];
p.sequence.body.body.map(step => maybeTagStep(step));
const wrapper = shallow(<AllSteps {...p} />);
expect(wrapper.find(".read-only").length).toEqual(3);
});

it("calls onDrop", () => {
const p = fakeProps();
p.sequence.body.body = [{ kind: "wait", args: { milliseconds: 0 } }];
Expand Down

0 comments on commit 39f8868

Please sign in to comment.