Skip to content

Commit 1d4c381

Browse files
authored
Merge pull request #523 from fractal-analytics-platform/custom-env-collection
Added Custom Python env task collection
2 parents 20f31bf + 55e4803 commit 1d4c381

File tree

9 files changed

+644
-14
lines changed

9 files changed

+644
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
> Starting from this release the Sandbox pages are not included in fractal-web anymore, instead they are static pages published together with the documentation.
66
7+
* Added Custom Python env task collection (\#523);
78
* Fixed issue with ajv formats on sandbox (\#522);
89
* Removed "Clear" button from tuples (\#521);
910
* Added "Reset" button on top-level properties having a default value (\#521);

playwright.config.js

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

5656
webServer: [
5757
{
58-
command: './tests/start-test-server.sh 2.1.0',
58+
command: './tests/start-test-server.sh 2.3.0a1',
5959
port: 8000,
6060
waitForPort: true,
6161
stdout: 'pipe',
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<script>
2+
import { createEventDispatcher } from 'svelte';
3+
4+
/** @type {string} */
5+
export let id;
6+
/** @type {string} */
7+
export let description;
8+
/** @type {string} */
9+
export let accept;
10+
export let required = false;
11+
12+
/** @type {(content: string) => any} */
13+
export let validateFile;
14+
15+
/** @type {(type: string, detail?: any) => boolean} */
16+
const dispatch = createEventDispatcher();
17+
18+
/** @type {FileList|null} */
19+
let files = null;
20+
/** @type {HTMLInputElement|undefined} */
21+
let fileInput = undefined;
22+
let fileError = '';
23+
24+
async function onFileSelected() {
25+
fileError = '';
26+
if (!files || files.length === 0) {
27+
dispatch('change', { value: null });
28+
return;
29+
}
30+
const file = files[0];
31+
await processFile(file);
32+
}
33+
34+
export function clearSelectedFile() {
35+
fileError = '';
36+
files = null;
37+
if (fileInput) {
38+
fileInput.value = '';
39+
}
40+
dispatch('change', { value: null });
41+
}
42+
43+
/**
44+
* @param {DragEvent} ev
45+
*/
46+
async function handleDrop(ev) {
47+
ev.preventDefault();
48+
dragOver = false;
49+
50+
if (!ev.dataTransfer) {
51+
return;
52+
}
53+
54+
if (ev.dataTransfer.files.length > 0) {
55+
files = ev.dataTransfer.files;
56+
/** @type {HTMLInputElement} */ (fileInput).files = files;
57+
await processFile(files[0]);
58+
}
59+
}
60+
61+
/**
62+
* @param {File} file
63+
*/
64+
async function processFile(file) {
65+
fileError = '';
66+
let content = await file.text();
67+
try {
68+
const data = validateFile(content);
69+
dispatch('change', { value: data });
70+
} catch (err) {
71+
fileError = /** @type {Error}*/ (err).message;
72+
dispatch('change', { value: null });
73+
}
74+
}
75+
76+
let dragOver = false;
77+
78+
/**
79+
* @param {DragEvent} ev
80+
*/
81+
function handleDragOver(ev) {
82+
// Prevent default behavior (Prevent file from being opened)
83+
ev.preventDefault();
84+
dragOver = true;
85+
}
86+
87+
function handleDragLeave() {
88+
dragOver = false;
89+
}
90+
</script>
91+
92+
<div
93+
class="dropZone bg-light"
94+
on:drop={handleDrop}
95+
on:dragover={handleDragOver}
96+
on:dragleave={handleDragLeave}
97+
class:dragOver
98+
>
99+
<div class="m-1">
100+
<div class="input-group has-validation">
101+
<label for={id} class="input-group-text">
102+
{description}
103+
</label>
104+
<input
105+
class="form-control"
106+
{accept}
107+
type="file"
108+
name={id}
109+
{id}
110+
bind:this={fileInput}
111+
bind:files
112+
class:is-invalid={fileError}
113+
on:change={onFileSelected}
114+
{required}
115+
/>
116+
{#if files && files.length > 0}
117+
<button class="btn btn-outline-secondary" on:click={clearSelectedFile}> Clear </button>
118+
{/if}
119+
<span class="invalid-feedback">{fileError}</span>
120+
</div>
121+
</div>
122+
<p class="text-center mt-1 mb-1">
123+
<i class="bi bi-file-earmark-arrow-up" /> or drag file here
124+
</p>
125+
</div>
126+
127+
<style>
128+
.dropZone {
129+
outline: 2px dashed #00b3bb;
130+
outline-offset: -8px;
131+
padding: 10px;
132+
border-radius: 3px;
133+
}
134+
135+
.dragOver {
136+
background-color: #c8e5ff !important;
137+
}
138+
</style>

src/lib/components/v2/tasks/AddSingleTask.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
import StandardDismissableAlert from '../../common/StandardDismissableAlert.svelte';
1010
import TypesEditor from './TypesEditor.svelte';
1111
12-
/** @type {(task: import('$lib/types-v2').TaskV2) => void} */
13-
export let addNewTask;
12+
/** @type {(task: import('$lib/types-v2').TaskV2[]) => void} */
13+
export let addNewTasks;
1414
1515
let taskSuccessMessage = '';
1616
@@ -138,7 +138,7 @@
138138
if (response.ok) {
139139
// Add created task to the list
140140
console.log('Task created', result);
141-
addNewTask(result);
141+
addNewTasks([result]);
142142
taskSuccessMessage = 'Task created successfully';
143143
resetFields();
144144
} else {

0 commit comments

Comments
 (0)