Skip to content

Commit 4cd7b48

Browse files
authored
Merge pull request #457 from fractal-analytics-platform/further-v2-changes
More V2 features
2 parents 8a7b140 + d138d92 commit 4cd7b48

22 files changed

+739
-300
lines changed

CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Unreleased
44

55
* Supported fractal-server API V2:
6-
* added menu switch to support legacy and current API (\#434);
6+
* added menu switch to support legacy and current API (\#434, \#457);
77
* Dataset V2 CRUD with attribute and type filters (\#434);
88
* new Dataset page with image list and filters (\#434);
99
* updated Single Task form to handle parallel and non parallel fields (\#434);
@@ -13,9 +13,11 @@
1313
* added admin "Tasks V1/V2 compatibility" page (\#450);
1414
* supported adding V1 task in V2 workflow (\#450);
1515
* removed read only property from V2 datasets (\#450);
16-
* added input filters tab in workflow task page (\#452);
16+
* added input filters tab in workflow task page (\#452, \#457);
1717
* added searchable dropdowns for image filters (\#452);
1818
* moved editing of dataset inside dataset page (\#452);
19+
* supported editing of single dataset images (\#457);
20+
* used switches to represent boolean flags (\#457);
1921

2022
# 0.10.2
2123

__tests__/v1/JSchema.test.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
1-
import { describe, it, expect } from 'vitest';
1+
import { describe, it, expect, vi } from 'vitest';
22
import { fireEvent, render, screen } from '@testing-library/svelte';
3+
import { readable } from 'svelte/store';
34

45
import JSchema from '../../src/lib/components/v1/workflow/JSchema.svelte';
56

7+
// Mocking the page store
8+
vi.mock('$app/stores', () => {
9+
return {
10+
page: readable({
11+
url: { pathname: '/v1/projects/1/workflows/1' }
12+
})
13+
};
14+
});
15+
616
describe('JSchema', () => {
717
it('Required NumberProperty with title', async () => {
818
const result = renderSchemaWithSingleProperty(

__tests__/v2/FiltersCreationForm.test.js renamed to __tests__/v2/AttributesTypesForm.test.js

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { describe, it, expect } from 'vitest';
22
import { fireEvent, render } from '@testing-library/svelte';
33

4-
import FiltersCreationForm from '../../src/lib/components/v2/projects/datasets/FiltersCreationForm.svelte';
4+
import AttributesTypesForm from '../../src/lib/components/v2/projects/datasets/AttributesTypesForm.svelte';
55
import { tick } from 'svelte';
66

7-
describe('FiltersCreationForm', () => {
7+
describe('AttributesTypesForm', () => {
88
it('init with existing filters', async () => {
9-
const result = render(FiltersCreationForm);
9+
const result = render(AttributesTypesForm);
1010
result.component.init(
1111
{
1212
key1: 'value1',
@@ -29,7 +29,7 @@ describe('FiltersCreationForm', () => {
2929
});
3030

3131
it('add and remove attribute filter', async () => {
32-
const result = render(FiltersCreationForm);
32+
const result = render(AttributesTypesForm);
3333
expect(result.queryAllByPlaceholderText('Key').length).eq(0);
3434
await fireEvent.click(result.getByRole('button', { name: 'Add attribute filter' }));
3535
expect(result.queryAllByPlaceholderText('Key').length).eq(1);
@@ -38,7 +38,7 @@ describe('FiltersCreationForm', () => {
3838
});
3939

4040
it('add and remove type filter', async () => {
41-
const result = render(FiltersCreationForm);
41+
const result = render(AttributesTypesForm);
4242
expect(result.queryAllByPlaceholderText('Key').length).eq(0);
4343
await fireEvent.click(result.getByRole('button', { name: 'Add type filter' }));
4444
expect(result.queryAllByPlaceholderText('Key').length).eq(1);
@@ -47,7 +47,7 @@ describe('FiltersCreationForm', () => {
4747
});
4848

4949
it('validate missing attribute filter key', async () => {
50-
const result = render(FiltersCreationForm);
50+
const result = render(AttributesTypesForm);
5151
result.component.init({}, {});
5252
await fireEvent.click(result.getByRole('button', { name: 'Add attribute filter' }));
5353
expect(result.component.validateFields()).false;
@@ -56,7 +56,7 @@ describe('FiltersCreationForm', () => {
5656
});
5757

5858
it('validate missing attribute filter value', async () => {
59-
const result = render(FiltersCreationForm);
59+
const result = render(AttributesTypesForm);
6060
result.component.init({}, {});
6161
await fireEvent.click(result.getByRole('button', { name: 'Add attribute filter' }));
6262
await fireEvent.input(result.getByPlaceholderText('Key'), { target: { value: 'my-key' } });
@@ -66,7 +66,7 @@ describe('FiltersCreationForm', () => {
6666
});
6767

6868
it('validate invalid number', async () => {
69-
const result = render(FiltersCreationForm);
69+
const result = render(AttributesTypesForm);
7070
await fireEvent.click(result.getByRole('button', { name: 'Add attribute filter' }));
7171
await fireEvent.input(result.getByPlaceholderText('Key'), { target: { value: 'my-key' } });
7272
await fireEvent.change(result.getByLabelText('Type'), { target: { value: 'number' } });
@@ -76,17 +76,47 @@ describe('FiltersCreationForm', () => {
7676
expect(result.getByText('Invalid number')).toBeDefined();
7777
});
7878

79-
it('switch to boolean attribute', async () => {
80-
const result = render(FiltersCreationForm);
79+
it('switch to number attribute from string containing a numeric value (number is preserved)', async () => {
80+
const result = render(AttributesTypesForm);
8181
await fireEvent.click(result.getByRole('button', { name: 'Add attribute filter' }));
8282
await fireEvent.input(result.getByPlaceholderText('Key'), { target: { value: 'my-key' } });
83+
await fireEvent.input(result.getByPlaceholderText('Value'), { target: { value: '42' } });
84+
await fireEvent.change(result.getByLabelText('Type'), { target: { value: 'number' } });
85+
expect(result.getByPlaceholderText('Value').value).eq('42');
86+
expect(result.component.validateFields()).true;
87+
});
88+
89+
it('switch to number attribute from string containing text (number is reset)', async () => {
90+
const result = render(AttributesTypesForm);
91+
await fireEvent.click(result.getByRole('button', { name: 'Add attribute filter' }));
92+
await fireEvent.input(result.getByPlaceholderText('Key'), { target: { value: 'my-key' } });
93+
await fireEvent.input(result.getByPlaceholderText('Value'), { target: { value: 'foo' } });
94+
await fireEvent.change(result.getByLabelText('Type'), { target: { value: 'number' } });
95+
expect(result.getByPlaceholderText('Value').value).eq('');
96+
expect(result.component.validateFields()).false;
97+
});
98+
99+
it('switch to boolean attribute, default to false', async () => {
100+
const result = render(AttributesTypesForm);
101+
await fireEvent.click(result.getByRole('button', { name: 'Add attribute filter' }));
102+
await fireEvent.input(result.getByPlaceholderText('Key'), { target: { value: 'my-key' } });
103+
await fireEvent.change(result.getByLabelText('Type'), { target: { value: 'boolean' } });
104+
expect(result.getByLabelText('Value').value).eq('false');
105+
expect(result.component.validateFields()).true;
106+
});
107+
108+
it('switch to boolean attribute from string equals to "true", true is set', async () => {
109+
const result = render(AttributesTypesForm);
110+
await fireEvent.click(result.getByRole('button', { name: 'Add attribute filter' }));
111+
await fireEvent.input(result.getByPlaceholderText('Key'), { target: { value: 'my-key' } });
112+
await fireEvent.input(result.getByPlaceholderText('Value'), { target: { value: 'true' } });
83113
await fireEvent.change(result.getByLabelText('Type'), { target: { value: 'boolean' } });
84114
expect(result.getByLabelText('Value').value).eq('true');
85115
expect(result.component.validateFields()).true;
86116
});
87117

88118
it('validate duplicated attribute key', async () => {
89-
const result = render(FiltersCreationForm);
119+
const result = render(AttributesTypesForm);
90120
await fireEvent.click(result.getByRole('button', { name: 'Add attribute filter' }));
91121
await fireEvent.input(result.getByPlaceholderText('Key'), { target: { value: 'my-key' } });
92122
await fireEvent.input(result.getByPlaceholderText('Value'), { target: { value: 'foo' } });
@@ -103,7 +133,7 @@ describe('FiltersCreationForm', () => {
103133
});
104134

105135
it('validate missing type filter key', async () => {
106-
const result = render(FiltersCreationForm);
136+
const result = render(AttributesTypesForm);
107137
result.component.init({}, {});
108138
await fireEvent.click(result.getByRole('button', { name: 'Add type filter' }));
109139
expect(result.component.validateFields()).false;
@@ -112,7 +142,7 @@ describe('FiltersCreationForm', () => {
112142
});
113143

114144
it('validate duplicated type filter key', async () => {
115-
const result = render(FiltersCreationForm);
145+
const result = render(AttributesTypesForm);
116146
result.component.init({}, {});
117147
await fireEvent.click(result.getByRole('button', { name: 'Add type filter' }));
118148
await fireEvent.input(result.getByPlaceholderText('Key'), { target: { value: 'my-key' } });

playwright.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export default defineConfig({
4747

4848
webServer: [
4949
{
50-
command: './tests/start-test-server.sh 2.0.0a8',
50+
command: './tests/start-test-server.sh 2.0.0a10',
5151
port: 8000,
5252
waitForPort: true,
5353
stdout: 'pipe',

src/lib/common/selected_api_version.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import { goto } from "$app/navigation";
22

3-
export const versionsLabels = {
4-
v1: 'legacy',
5-
v2: 'current'
6-
};
7-
83
/**
94
* Save the selected API version in the cookie and reload the page.
105
* This function is called from the Svelte frontend.
Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script>
22
import { getContext } from 'svelte';
33
import PropertyDescription from '$lib/components/common/jschema/PropertyDescription.svelte';
4+
import { page } from '$app/stores';
45
56
const schemaManager = getContext('schemaManager');
67
@@ -14,21 +15,36 @@
1415

1516
<div class="d-flex align-items-center p-2">
1617
<div class="property-metadata d-flex flex-row align-self-center w-50">
17-
<span class={schemaProperty.isRequired() ? 'fw-bold' : ''}>{schemaProperty.title || 'Boolean argument'}</span>
18+
<span class={schemaProperty.isRequired() ? 'fw-bold' : ''}>
19+
{schemaProperty.title || 'Boolean argument'}
20+
</span>
1821
<PropertyDescription description={schemaProperty.description} />
1922
</div>
2023
<div class="property-input ms-auto w-25">
21-
<div class="form-check">
22-
<input
23-
id="property-{schemaProperty.key}"
24-
type="checkbox"
25-
bind:checked={schemaProperty.value}
26-
on:change={handleValueChange}
27-
class="form-check-input"
28-
/>
29-
<label class="form-check-label" for="property-{schemaProperty.key}">
30-
{schemaProperty.value}
31-
</label>
32-
</div>
24+
{#if $page.url.pathname.startsWith('/v1')}
25+
<div class="form-check">
26+
<input
27+
id="property-{schemaProperty.key}"
28+
type="checkbox"
29+
bind:checked={schemaProperty.value}
30+
on:change={handleValueChange}
31+
class="form-check-input"
32+
/>
33+
<label class="form-check-label" for="property-{schemaProperty.key}">
34+
{schemaProperty.value}
35+
</label>
36+
</div>
37+
{:else}
38+
<div class="form-check form-switch">
39+
<input
40+
id="property-{schemaProperty.key}"
41+
class="form-check-input"
42+
type="checkbox"
43+
bind:checked={schemaProperty.value}
44+
on:change={handleValueChange}
45+
role="switch"
46+
/>
47+
</div>
48+
{/if}
3349
</div>
3450
</div>

src/lib/components/v2/projects/datasets/AddImageModal.svelte

Lines changed: 0 additions & 91 deletions
This file was deleted.

0 commit comments

Comments
 (0)