Skip to content

Commit

Permalink
Merge with main
Browse files Browse the repository at this point in the history
  • Loading branch information
EmmaLRussell committed Aug 30, 2023
2 parents 495c263 + fdd2ab9 commit c0ee06c
Show file tree
Hide file tree
Showing 14 changed files with 690 additions and 280 deletions.
392 changes: 212 additions & 180 deletions app/static/src/app/components/WodinPanels.vue

Large diffs are not rendered by default.

80 changes: 40 additions & 40 deletions app/static/src/app/components/options/EditParamSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,6 @@
</select>
</div>
</div>
<div v-if="settingsInternal.variationType !== 'Custom'" class="row mt-2" id="edit-scale-type">
<div class="col-6">
<label class="col-form-label">Scale type</label>
</div>
<div class="col-6">
<select class="form-select" v-model="settingsInternal.scaleType">
<option v-for="scale in scaleValues" :key="scale">{{scale}}</option>
</select>
</div>
<div class="col-6">
</div>
</div>
<div class="row mt-2" id="edit-variation-type">
<div class="col-6">
<label class="col-form-label">Variation type</label>
Expand All @@ -40,6 +28,18 @@
</select>
</div>
</div>
<div v-if="settingsInternal.variationType !== 'Custom'" class="row mt-2" id="edit-scale-type">
<div class="col-6">
<label class="col-form-label">Scale type</label>
</div>
<div class="col-6">
<select class="form-select" v-model="settingsInternal.scaleType">
<option v-for="scale in scaleValues" :key="scale">{{scale}}</option>
</select>
</div>
<div class="col-6">
</div>
</div>
<div v-if="settingsInternal.variationType === 'Percentage'" class="row mt-2" id="edit-percent">
<div class="col-6">
<label class="col-form-label">Variation (%)</label>
Expand All @@ -49,34 +49,33 @@
@update="(n) => settingsInternal.variationPercentage = n"></numeric-input>
</div>
</div>
<template v-if="settingsInternal.variationType === 'Range'">
<div class="row mt-2" id="edit-from">
<div class="col-6">
<label class="col-form-label">From</label>
</div>
<div class="col-6">
<numeric-input :value="settingsInternal.rangeFrom"
@update="(n) => settingsInternal.rangeFrom = n"></numeric-input>
</div>
<div v-if="settingsInternal.variationType === 'Range'" class="row mt-2" id="edit-from">
<div class="col-6">
<label class="col-form-label">From</label>
</div>
<div class="row mt-2 text-muted" id="param-central">
<div class="col-6">
Central value
</div>
<div class="col-6">
{{ centralValue }}
</div>
<div class="col-6">
<numeric-input :value="settingsInternal.rangeFrom"
@update="(n) => settingsInternal.rangeFrom = n"></numeric-input>
</div>
<div class="row mt-2" id="edit-to">
<div class="col-6">
<label class="col-form-label">To</label>
</div>
<div class="col-6">
<numeric-input :value="settingsInternal.rangeTo"
@update="(n) => settingsInternal.rangeTo = n"></numeric-input>
</div>
</div>
<div v-if="['Range', 'Custom'].includes(settingsInternal.variationType)"
class="row mt-2 text-muted" id="param-central">
<div class="col-6">
Central value
</div>
</template>
<div class="col-6">
{{ centralValue }}
</div>
</div>
<div v-if="settingsInternal.variationType === 'Range'" class="row mt-2" id="edit-to">
<div class="col-6">
<label class="col-form-label">To</label>
</div>
<div class="col-6">
<numeric-input :value="settingsInternal.rangeTo"
@update="(n) => settingsInternal.rangeTo = n"></numeric-input>
</div>
</div>
<template v-if="settingsInternal.variationType === 'Custom'">
<div id="edit-values" class="row mt-2">
<div class="col-6">
Expand Down Expand Up @@ -195,13 +194,14 @@ export default defineComponent({
});
const updateCustomValues = (newValues: number[]) => {
// sort and remove duplicates
const cleaned = Array.from(new Set(newValues)).sort((a, b) => a - b);
settingsInternal.customValues = cleaned;
settingsInternal.customValues = newValues;
};
const close = () => { emit("close"); };
const updateSettings = () => {
emit("update", { ...settingsInternal });
// sort custom values
const customValues = settingsInternal.customValues.sort((a, b) => a - b);
emit("update", { ...settingsInternal, customValues });
close();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
</div>
<ul>
<li><strong>Parameter:</strong> {{settings.parameterToVary}}</li>
<li v-if="settings.variationType !== 'Custom'"><strong>Scale Type:</strong> {{ settings.scaleType }}</li>
<li><strong>Variation Type:</strong> {{ settings.variationType }}</li>
<li v-if="settings.variationType !== 'Custom'"><strong>Scale Type:</strong> {{ settings.scaleType }}</li>
<li v-if="settings.variationType === 'Percentage'">
<strong>Variation (%):</strong> {{ settings.variationPercentage }}
</li>
Expand Down
18 changes: 17 additions & 1 deletion app/static/src/app/components/options/TagInput.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<template>
<vue-tags-input style="border-color: #d7dce1;"
v-model="currentTag"
:tags="computedTags"
:placeholder="'...'"
:validate="validate"
:add-tag-on-blur="true"
:add-tag-on-keys="[13, ',', 32, ':']"
@on-error="handleError"
@on-tags-changed="handleTagsChanged"/>
</template>
<script lang="ts">
import {
PropType, computed, defineComponent, watch
PropType, computed, defineComponent, watch, ref
} from "vue";
import VueTagsInput from "vue3-tags-input";
import { useStore } from "vuex";
Expand All @@ -30,6 +32,8 @@ export default defineComponent({
setup(props, { emit }) {
const store = useStore();
const currentTag = ref("");
const paramValues = computed(() => store.state.run.parameterValues);
watch(paramValues, () => {
Expand Down Expand Up @@ -61,6 +65,11 @@ export default defineComponent({
return paramValues.value && tag in paramValues.value;
};
const handleError = () => {
// remove duplicate current tag
currentTag.value = "";
};
const handleTagsChanged = (tags: string[]) => {
const parsedTags = tags.map((tag) => {
if (isNumeric(tag)) {
Expand Down Expand Up @@ -97,7 +106,9 @@ export default defineComponent({
};
return {
currentTag,
computedTags,
handleError,
handleTagsChanged,
validate
};
Expand All @@ -112,4 +123,9 @@ export default defineComponent({
.v3ti-tag .v3ti-remove-tag {
text-decoration: none !important;
}
.v3ti-new-tag--error {
text-decoration: none !important;
color: #000 !important;
}
</style>
138 changes: 125 additions & 13 deletions app/static/tests/e2e/panels.etest.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,180 @@
import { expect, test, Page } from "@playwright/test";
import {
expect,
test,
Page,
Locator
} from "@playwright/test";

test.describe("Wodin App panels tests", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/apps/day1");
});

// playwright default screen size is 1280x720
const windowWidth = 1280;
const widthToleranceLeft = Math.max(windowWidth / 8, 200);
const widthToleranceRight = Math.max(windowWidth / 4, 400);
const leftBoundary = widthToleranceLeft;
const rightBoundary = windowWidth - widthToleranceRight;

const expectBothMode = async (page: Page) => {
await expect(await page.innerText(".wodin-mode-both .wodin-left .wodin-content .nav-tabs .active"))
.toBe("Code");
await expect(await page.locator(".wodin-mode-both .wodin-right .wodin-content .js-plotly-plot")).toBeVisible();
await expect(await page.locator(".wodin-collapse-controls #collapse-left")).toBeVisible();
await expect(await page.locator(".wodin-collapse-controls #collapse-right")).toBeVisible();
await expect(await page.locator(".wodin-collapse-controls #resize-panel-control")).toBeVisible();
await expect(await page.locator(".wodin-left .view-left").isHidden()).toBe(true);
await expect(await page.locator(".wodin-right .view-right").isHidden()).toBe(true);
await expect(await page.locator("#wodin-content-right").isHidden()).toBe(false);
await expect(await page.locator("#wodin-content-left").isHidden()).toBe(false);
};

const expectBothModeLeftHidden = async (page: Page) => {
await expect(await page.innerText(".wodin-mode-both .wodin-left .wodin-content .nav-tabs .active"))
.toBe("Code");
await expect(await page.locator(".wodin-mode-both .wodin-right .wodin-content .js-plotly-plot")).toBeVisible();
await expect(await page.locator(".wodin-collapse-controls #resize-panel-control")).toBeVisible();
await expect(await page.locator(".wodin-left .view-left").isHidden()).toBe(false);
await expect(await page.locator(".wodin-right .view-right").isHidden()).toBe(true);
await expect(await page.locator("#wodin-content-left").isHidden()).toBe(true);
await expect(await page.locator("#wodin-content-right").isHidden()).toBe(false);
};

const expectBothModeRightHidden = async (page: Page) => {
await expect(await page.innerText(".wodin-mode-both .wodin-left .wodin-content .nav-tabs .active"))
.toBe("Code");
await expect(await page.locator(".wodin-mode-both .wodin-right .wodin-content .js-plotly-plot").isHidden())
.toBe(true);
await expect(await page.locator(".wodin-collapse-controls #resize-panel-control")).toBeVisible();
await expect(await page.locator(".wodin-left .view-left").isHidden()).toBe(true);
await expect(await page.locator(".wodin-right .view-right").isHidden()).toBe(false);
await expect(await page.locator("#wodin-content-left").isHidden()).toBe(false);
await expect(await page.locator("#wodin-content-right").isHidden()).toBe(true);
};

const expectRightMode = async (page: Page) => {
await expect(await page.locator(".wodin-mode-right .wodin-right .wodin-content .js-plotly-plot")).toBeVisible();
await expect(await page.locator(".wodin-mode-right .wodin-left .wodin-content").isHidden()).toBe(true);
await expect(await page.locator(".wodin-collapse-controls #collapse-left").isHidden()).toBe(true);
await expect(await page.locator(".wodin-collapse-controls #collapse-right")).toBeVisible();
await expect(await page.locator(".wodin-collapse-controls #resize-panel-control")).toBeVisible();
await expect(await page.locator(".wodin-left .view-left")).toBeVisible();
await expect(await page.locator(".wodin-right .view-right").isHidden()).toBe(true);
};

const expectLeftMode = async (page: Page) => {
await expect(await page.locator(".wodin-mode-left .wodin-right .wodin-content").isHidden()).toBe(true);
await expect(await page.locator(".wodin-mode-left .wodin-left .wodin-content")).toBeVisible();
await expect(await page.locator(".wodin-collapse-controls #collapse-left")).toBeVisible();
await expect(await page.locator(".wodin-collapse-controls #collapse-right").isHidden()).toBe(true);
await expect(await page.locator(".wodin-collapse-controls #resize-panel-control")).toBeVisible();
await expect(await page.locator(".wodin-left .view-left").isHidden()).toBe(true);
await expect(await page.locator(".wodin-right .view-right")).toBeVisible();
};

interface Point {
x: number,
y:number
}

const dragTo = async (page: Page, locatorToDrag: Locator, locatorDragTarget: Point, mouseUp = true) => {
const toDragBox = await locatorToDrag.boundingBox();

await page.mouse.move(
toDragBox!.x + toDragBox!.width / 2,
toDragBox!.y + toDragBox!.height / 2
);
await page.mouse.down();
await page.mouse.move(
locatorDragTarget.x,
locatorDragTarget.y
);
if (mouseUp) {
await page.mouse.up();
}
};

test("can collapse and expand left panel", async ({ page }) => {
await expectBothMode(page);
const panelResizer = page.locator("#resize-panel-control");

await dragTo(page, panelResizer, { x: leftBoundary, y: 0 });
await expectBothMode(page);

await dragTo(page, panelResizer, { x: leftBoundary - 1, y: 0 }, false);
await expectBothModeLeftHidden(page);

// beyond collapse boundary so panel should collapse
await dragTo(page, panelResizer, { x: leftBoundary - 1, y: 0 });
await expectRightMode(page);

await dragTo(page, panelResizer, { x: leftBoundary, y: 0 });
await expectBothMode(page);
});

test("can collapse and expand left panel using edge resizer", async ({ page }) => {
await expectBothMode(page);
const panelResizer = page.locator(".edge-resize");

await dragTo(page, panelResizer, { x: leftBoundary, y: 0 });
await expectBothMode(page);

await page.click("#collapse-left");
await dragTo(page, panelResizer, { x: leftBoundary - 1, y: 0 }, false);
await expectBothModeLeftHidden(page);

// beyond collapse boundary so panel should collapse
await dragTo(page, panelResizer, { x: leftBoundary - 1, y: 0 });
await expectRightMode(page);

await page.click("#collapse-right");
await dragTo(page, panelResizer, { x: leftBoundary, y: 0 });
await expectBothMode(page);
});

test("can collapse and expand right panel", async ({ page }) => {
await expectBothMode(page);
const panelResizer = page.locator("#resize-panel-control");

await dragTo(page, panelResizer, { x: rightBoundary, y: 0 });
await expectBothMode(page);

await dragTo(page, panelResizer, { x: rightBoundary + 1, y: 0 }, false);
await expectBothModeRightHidden(page);

// beyond collapse boundary so panel should collapse
await dragTo(page, panelResizer, { x: rightBoundary + 1, y: 0 });
await expectLeftMode(page);

await dragTo(page, panelResizer, { x: rightBoundary, y: 0 });
await expectBothMode(page);
});

test("can collapse and expand right panel using edge resizer", async ({ page }) => {
await expectBothMode(page);
const panelResizer = page.locator(".edge-resize");

await page.click("#collapse-right");
await dragTo(page, panelResizer, { x: rightBoundary, y: 0 });
await expectBothMode(page);

await dragTo(page, panelResizer, { x: rightBoundary + 1, y: 0 }, false);
await expectBothModeRightHidden(page);

// beyond collapse boundary so panel should collapse
await dragTo(page, panelResizer, { x: rightBoundary + 1, y: 0 });
await expectLeftMode(page);

await page.click("#collapse-left");
await dragTo(page, panelResizer, { x: rightBoundary, y: 0 });
await expectBothMode(page);
});

test("'View Options' shows both panels", async ({ page }) => {
await page.click("#collapse-left");
const panelResizer = page.locator("#resize-panel-control");
await dragTo(page, panelResizer, { x: leftBoundary - 1, y: 0 });
await expectRightMode(page);

await expect(await page.innerText(".view-left")).toBe("View Options");
await page.click(".view-left");
await expectBothMode(page);
});

test("'View Charts' shows both panels", async ({ page }) => {
await page.click("#collapse-right");
const panelResizer = page.locator("#resize-panel-control");
await dragTo(page, panelResizer, { x: rightBoundary + 1, y: 0 });
await expectLeftMode(page);

await expect(await page.innerText(".view-right")).toBe("View Charts");
await page.click(".view-right");
Expand Down
Loading

0 comments on commit c0ee06c

Please sign in to comment.