windmill-components 1.22.42 → 1.28.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/AppConnect.svelte +93 -47
- package/components/AppConnect.svelte.d.ts +2 -2
- package/components/ArgInfo.svelte +0 -5
- package/components/ArgInput.svelte +91 -64
- package/components/ArgInput.svelte.d.ts +8 -3
- package/components/Button.svelte +4 -4
- package/components/CenteredPage.svelte +1 -1
- package/components/CollapseLink.svelte +12 -0
- package/components/CollapseLink.svelte.d.ts +19 -0
- package/components/CronInput.svelte +84 -0
- package/components/CronInput.svelte.d.ts +18 -0
- package/components/DisplayResult.svelte +28 -15
- package/components/Editor.svelte +136 -66
- package/components/Editor.svelte.d.ts +2 -0
- package/components/EditorBar.svelte +56 -45
- package/components/FlowBuilder.svelte +155 -70
- package/components/FlowEditor.svelte +79 -200
- package/components/FlowEditor.svelte.d.ts +3 -2
- package/components/FlowJobResult.svelte +1 -1
- package/components/FlowPreview.svelte +18 -24
- package/components/FlowPreviewContent.svelte +68 -0
- package/components/FlowPreviewContent.svelte.d.ts +21 -0
- package/components/FlowStatusViewer.svelte +85 -37
- package/components/FlowStatusViewer.svelte.d.ts +3 -2
- package/components/FlowViewer.svelte +85 -45
- package/components/FlowViewer.svelte.d.ts +2 -1
- package/components/IconedResourceType.svelte +30 -5
- package/components/InputTransformForm.svelte +209 -0
- package/components/InputTransformForm.svelte.d.ts +26 -0
- package/components/InputTransformsViewer.svelte +19 -0
- package/components/InputTransformsViewer.svelte.d.ts +17 -0
- package/components/InviteGlobalUser.svelte +2 -2
- package/components/InviteUser.svelte +2 -2
- package/components/JobStatus.svelte +32 -25
- package/components/Modal.svelte +44 -42
- package/components/ModuleStep.svelte +94 -79
- package/components/ObjectResourceInput.svelte +58 -38
- package/components/ObjectTypeNarrowing.svelte +4 -19
- package/components/Path.svelte +1 -0
- package/components/Path.svelte.d.ts +1 -1
- package/components/RadioButton.svelte +11 -96
- package/components/RadioButton.svelte.d.ts +4 -2
- package/components/ResourceEditor.svelte +4 -5
- package/components/ResourceEditor.svelte.d.ts +2 -2
- package/components/ResourcePicker.svelte +25 -2
- package/components/ResourcePicker.svelte.d.ts +3 -0
- package/components/ResourceTypePicker.svelte +17 -29
- package/components/ResourceTypePicker.svelte.d.ts +1 -0
- package/components/RunForm.svelte +14 -15
- package/components/RunForm.svelte.d.ts +1 -1
- package/components/SchemaEditor.svelte +87 -71
- package/components/SchemaEditor.svelte.d.ts +2 -0
- package/components/SchemaEditorProperty.svelte +11 -0
- package/components/SchemaEditorProperty.svelte.d.ts +17 -0
- package/components/SchemaForm.svelte +21 -127
- package/components/SchemaForm.svelte.d.ts +3 -4
- package/components/SchemaModal.svelte +20 -33
- package/components/SchemaModal.svelte.d.ts +1 -1
- package/components/SchemaViewer.svelte +4 -6
- package/components/ScriptBuilder.svelte +40 -43
- package/components/ScriptEditor.svelte +71 -66
- package/components/ScriptPicker.svelte +10 -12
- package/components/ScriptPicker.svelte.d.ts +1 -1
- package/components/ScriptSchema.svelte +0 -5
- package/components/ShareModal.svelte +1 -1
- package/components/SharedBadge.svelte +12 -10
- package/components/StringTypeNarrowing.svelte +8 -4
- package/components/StringTypeNarrowing.svelte.d.ts +1 -0
- package/components/TableCustom.svelte +7 -9
- package/components/TableSimple.svelte +1 -1
- package/components/Toggle.svelte +8 -10
- package/components/Toggle.svelte.d.ts +5 -11
- package/components/Tooltip.svelte +3 -2
- package/components/VariableEditor.svelte +21 -6
- package/components/flows/CopyFirstStepSchema.svelte +7 -5
- package/components/flows/DynamicInputHelpBox.svelte +1 -1
- package/components/flows/FlowBox.svelte +3 -0
- package/components/flows/FlowBox.svelte.d.ts +23 -0
- package/components/flows/FlowBoxHeader.svelte +9 -0
- package/components/flows/FlowBoxHeader.svelte.d.ts +18 -0
- package/components/flows/FlowInput.svelte +20 -0
- package/components/flows/FlowInput.svelte.d.ts +14 -0
- package/components/flows/FlowInputs.svelte +7 -3
- package/components/flows/FlowModuleHeader.svelte +42 -40
- package/components/flows/FlowModuleHeader.svelte.d.ts +1 -1
- package/components/flows/FlowSettings.svelte +174 -0
- package/components/flows/FlowSettings.svelte.d.ts +21 -0
- package/components/flows/flowStore.d.ts +5 -2
- package/components/flows/flowStore.js +65 -9
- package/components/flows/pickers/FlowScriptPicker.svelte +6 -1
- package/components/flows/pickers/FlowScriptPicker.svelte.d.ts +1 -0
- package/components/flows/utils.d.ts +11 -7
- package/components/flows/utils.js +114 -45
- package/components/icons/AirtableIcon.svelte +17 -0
- package/components/icons/AirtableIcon.svelte.d.ts +17 -0
- package/components/icons/GCloudIcon.svelte +16 -0
- package/components/icons/GCloudIcon.svelte.d.ts +17 -0
- package/components/icons/GItlabIcon.svelte +16 -0
- package/components/icons/GItlabIcon.svelte.d.ts +17 -0
- package/components/icons/GSheetsIcon.svelte +16 -0
- package/components/icons/GSheetsIcon.svelte.d.ts +17 -0
- package/components/icons/GcalIcon.svelte +16 -0
- package/components/icons/GcalIcon.svelte.d.ts +17 -0
- package/components/icons/GdriveIcon.svelte +16 -0
- package/components/icons/GdriveIcon.svelte.d.ts +17 -0
- package/components/icons/GmailIcon.svelte +16 -0
- package/components/icons/GmailIcon.svelte.d.ts +17 -0
- package/components/icons/PostgresIcon.svelte +8 -49
- package/components/icons/Slack.svelte +9 -18
- package/components/icons/TogglIcon.svelte +59 -0
- package/components/icons/TogglIcon.svelte.d.ts +17 -0
- package/components/propertyPicker/ObjectViewer.svelte +35 -37
- package/components/propertyPicker/ObjectViewer.svelte.d.ts +2 -0
- package/components/propertyPicker/OverlayPropertyPicker.svelte +53 -53
- package/components/propertyPicker/OverlayPropertyPicker.svelte.d.ts +5 -2
- package/components/propertyPicker/PropPicker.svelte +13 -15
- package/components/propertyPicker/PropPicker.svelte.d.ts +1 -1
- package/components/propertyPicker/WarningMessage.svelte +14 -41
- package/components/propertyPicker/WarningMessage.svelte.d.ts +11 -8
- package/components/propertyPicker/utils.d.ts +1 -0
- package/components/propertyPicker/utils.js +25 -0
- package/gen/core/OpenAPI.js +1 -1
- package/gen/index.d.ts +11 -2
- package/gen/index.js +1 -2
- package/gen/models/CompletedJob.d.ts +1 -1
- package/gen/models/Flow.d.ts +3 -13
- package/gen/models/FlowMetadata.d.ts +9 -0
- package/gen/models/FlowMetadata.js +4 -0
- package/gen/models/FlowModuleValue.d.ts +5 -22
- package/gen/models/FlowModuleValue.js +1 -15
- package/gen/models/ForloopFlow.d.ts +8 -0
- package/gen/models/ForloopFlow.js +4 -0
- package/gen/models/InputTransform.d.ts +3 -12
- package/gen/models/InputTransform.js +1 -8
- package/gen/models/JavascriptTransform.d.ts +4 -0
- package/gen/models/JavascriptTransform.js +4 -0
- package/gen/models/MainArgSignature.d.ts +1 -1
- package/gen/models/NewSchedule.d.ts +1 -0
- package/gen/models/OpenFlowWPath.d.ts +4 -0
- package/gen/models/OpenFlowWPath.js +4 -0
- package/gen/models/PathFlow.d.ts +4 -0
- package/gen/models/PathFlow.js +4 -0
- package/gen/models/PathScript.d.ts +4 -0
- package/gen/models/PathScript.js +4 -0
- package/gen/models/RawScript.d.ts +12 -0
- package/gen/models/RawScript.js +11 -0
- package/gen/models/Schedule.d.ts +1 -1
- package/gen/models/StaticTransform.d.ts +4 -0
- package/gen/models/StaticTransform.js +4 -0
- package/gen/models/TokenResponse.d.ts +3 -3
- package/gen/models/Usage.d.ts +5 -0
- package/gen/models/Usage.js +4 -0
- package/gen/models/User.d.ts +2 -0
- package/gen/schemas/$AuditLog.d.ts +32 -0
- package/gen/schemas/$AuditLog.js +35 -0
- package/gen/schemas/$CompletedJob.d.ts +98 -0
- package/gen/schemas/$CompletedJob.js +103 -0
- package/gen/schemas/$ContextualVariable.d.ts +16 -0
- package/gen/schemas/$ContextualVariable.js +19 -0
- package/gen/schemas/$CreateResource.d.ts +22 -0
- package/gen/schemas/$CreateResource.js +25 -0
- package/gen/schemas/$CreateVariable.d.ts +26 -0
- package/gen/schemas/$CreateVariable.js +29 -0
- package/gen/schemas/$CreateWorkspace.d.ts +20 -0
- package/gen/schemas/$CreateWorkspace.js +23 -0
- package/gen/schemas/$EditResource.d.ts +13 -0
- package/gen/schemas/$EditResource.js +16 -0
- package/gen/schemas/$EditResourceType.d.ts +10 -0
- package/gen/schemas/$EditResourceType.js +13 -0
- package/gen/schemas/$EditSchedule.d.ts +20 -0
- package/gen/schemas/$EditSchedule.js +23 -0
- package/gen/schemas/$EditVariable.d.ts +16 -0
- package/gen/schemas/$EditVariable.js +19 -0
- package/gen/schemas/$EditWorkspaceUser.d.ts +7 -0
- package/gen/schemas/$EditWorkspaceUser.js +10 -0
- package/gen/schemas/$Flow.d.ts +23 -0
- package/gen/schemas/$Flow.js +26 -0
- package/gen/schemas/$FlowMetadata.d.ts +31 -0
- package/gen/schemas/$FlowMetadata.js +34 -0
- package/gen/schemas/$FlowPreview.d.ts +80 -0
- package/gen/schemas/$FlowPreview.js +83 -0
- package/gen/schemas/$GlobalUserInfo.d.ts +26 -0
- package/gen/schemas/$GlobalUserInfo.js +29 -0
- package/gen/schemas/$Group.d.ts +23 -0
- package/gen/schemas/$Group.js +26 -0
- package/gen/schemas/$Job.d.ts +17 -0
- package/gen/schemas/$Job.js +20 -0
- package/gen/schemas/$ListableVariable.d.ts +35 -0
- package/gen/schemas/$ListableVariable.js +38 -0
- package/gen/schemas/$Login.d.ts +12 -0
- package/gen/schemas/$Login.js +15 -0
- package/gen/schemas/$MainArgSignature.d.ts +50 -0
- package/gen/schemas/$MainArgSignature.js +53 -0
- package/gen/schemas/$NewSchedule.d.ts +30 -0
- package/gen/schemas/$NewSchedule.js +33 -0
- package/gen/schemas/$NewToken.d.ts +11 -0
- package/gen/schemas/$NewToken.js +14 -0
- package/gen/schemas/$NewUser.d.ts +16 -0
- package/gen/schemas/$NewUser.js +19 -0
- package/gen/schemas/$Preview.d.ts +19 -0
- package/gen/schemas/$Preview.js +22 -0
- package/gen/schemas/$QueuedJob.d.ts +139 -0
- package/gen/schemas/$QueuedJob.js +144 -0
- package/gen/schemas/$Resource.d.ts +31 -0
- package/gen/schemas/$Resource.js +34 -0
- package/gen/schemas/$ResourceType.d.ts +17 -0
- package/gen/schemas/$ResourceType.js +20 -0
- package/gen/schemas/$Schedule.d.ts +47 -0
- package/gen/schemas/$Schedule.js +50 -0
- package/gen/schemas/$Script.d.ts +77 -0
- package/gen/schemas/$Script.js +80 -0
- package/gen/schemas/$ScriptArgs.d.ts +6 -0
- package/gen/schemas/$ScriptArgs.js +9 -0
- package/gen/schemas/$SlackToken.d.ts +24 -0
- package/gen/schemas/$SlackToken.js +27 -0
- package/gen/schemas/$TokenResponse.d.ts +23 -0
- package/gen/schemas/$TokenResponse.js +26 -0
- package/gen/schemas/$TruncatedToken.d.ts +25 -0
- package/gen/schemas/$TruncatedToken.js +28 -0
- package/gen/schemas/$Usage.d.ts +13 -0
- package/gen/schemas/$Usage.js +16 -0
- package/gen/schemas/$User.d.ts +42 -0
- package/gen/schemas/$User.js +45 -0
- package/gen/schemas/$UserWorkspaceList.d.ts +28 -0
- package/gen/schemas/$UserWorkspaceList.js +31 -0
- package/gen/schemas/$WorkerPing.d.ts +31 -0
- package/gen/schemas/$WorkerPing.js +34 -0
- package/gen/schemas/$Workspace.d.ts +19 -0
- package/gen/schemas/$Workspace.js +22 -0
- package/gen/schemas/$WorkspaceInvite.d.ts +16 -0
- package/gen/schemas/$WorkspaceInvite.js +19 -0
- package/gen/services/FlowService.d.ts +24 -23
- package/gen/services/FlowService.js +14 -0
- package/gen/services/JobService.d.ts +1 -1
- package/gen/services/ScriptService.d.ts +13 -19
- package/gen/services/ScriptService.js +0 -14
- package/gen/services/WorkspaceService.d.ts +1 -1
- package/gen/services/WorkspaceService.js +1 -1
- package/infer.js +8 -1
- package/package.json +85 -16
- package/script_helpers.d.ts +1 -1
- package/script_helpers.js +11 -13
- package/sql.d.ts +89 -0
- package/sql.js +817 -0
- package/stores.d.ts +0 -1
- package/stores.js +0 -6
- package/utils.d.ts +12 -5
- package/utils.js +55 -9
- package/components/RadioButtonV2.svelte +0 -33
- package/components/RadioButtonV2.svelte.d.ts +0 -20
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
<script context="module">import Modal from './Modal.svelte';
|
|
2
2
|
export const ARG_TYPES = ['integer', 'number', 'string', 'boolean', 'object', 'array'];
|
|
3
|
-
export function modalToSchema(schema) {
|
|
4
|
-
return {
|
|
5
|
-
type: schema.selectedType,
|
|
6
|
-
description: schema.description,
|
|
7
|
-
pattern: schema.pattern,
|
|
8
|
-
default: schema.default,
|
|
9
|
-
enum: schema.enum_,
|
|
10
|
-
items: schema.items
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
3
|
export function schemaToModal(schema, name, required) {
|
|
14
4
|
return {
|
|
15
5
|
name,
|
|
@@ -17,6 +7,8 @@ export function schemaToModal(schema, name, required) {
|
|
|
17
7
|
description: schema.description,
|
|
18
8
|
pattern: schema.pattern,
|
|
19
9
|
default: schema.default,
|
|
10
|
+
contentEncoding: schema.contentEncoding,
|
|
11
|
+
format: schema.format,
|
|
20
12
|
required
|
|
21
13
|
};
|
|
22
14
|
}
|
|
@@ -33,14 +25,17 @@ import { createEventDispatcher } from 'svelte';
|
|
|
33
25
|
import ArgInput from './ArgInput.svelte';
|
|
34
26
|
import StringTypeNarrowing from './StringTypeNarrowing.svelte';
|
|
35
27
|
import Required from './Required.svelte';
|
|
28
|
+
import ObjectTypeNarrowing from './ObjectTypeNarrowing.svelte';
|
|
36
29
|
export let property = DEFAULT_PROPERTY;
|
|
37
30
|
export let error = '';
|
|
38
31
|
export let editing = false;
|
|
39
32
|
export let oldArgName = undefined;
|
|
33
|
+
let resource_type = undefined;
|
|
40
34
|
const dispatch = createEventDispatcher();
|
|
41
35
|
let modal;
|
|
42
36
|
export function openModal() {
|
|
43
37
|
modal.openModal();
|
|
38
|
+
resource_type = property.format?.substring(5);
|
|
44
39
|
}
|
|
45
40
|
export function closeModal() {
|
|
46
41
|
modal.closeModal();
|
|
@@ -54,6 +49,11 @@ function clearModal() {
|
|
|
54
49
|
property.description = DEFAULT_PROPERTY.description;
|
|
55
50
|
property.required = DEFAULT_PROPERTY.required;
|
|
56
51
|
property.selectedType = DEFAULT_PROPERTY.selectedType;
|
|
52
|
+
property.format = undefined;
|
|
53
|
+
resource_type = undefined;
|
|
54
|
+
}
|
|
55
|
+
$: if (property.selectedType == 'object' && resource_type) {
|
|
56
|
+
property.format = resource_type ? `$res:${resource_type}` : undefined;
|
|
57
57
|
}
|
|
58
58
|
</script>
|
|
59
59
|
|
|
@@ -77,12 +77,16 @@ function clearModal() {
|
|
|
77
77
|
/>
|
|
78
78
|
</label>
|
|
79
79
|
<h3 class="font-semibold text-gray-700">Type<Required required={true} /></h3>
|
|
80
|
-
<div class="grid sm:grid-cols-3 md:grid-cols-4 gap-x-2 gap-y-1 items-center mb-2">
|
|
80
|
+
<div class="grid sm:grid-cols-3 md:grid-cols-4 gap-x-2 gap-y-1 items-center mb-2 w-full">
|
|
81
81
|
{#each ARG_TYPES as argType}
|
|
82
82
|
<button
|
|
83
83
|
class={argType == property.selectedType ? 'item-button-selected' : 'item-button'}
|
|
84
84
|
on:click={() => {
|
|
85
85
|
property.selectedType = argType
|
|
86
|
+
property.format = undefined
|
|
87
|
+
property.contentEncoding = undefined
|
|
88
|
+
property.enum_ = undefined
|
|
89
|
+
property.pattern = undefined
|
|
86
90
|
}}>{argType}</button
|
|
87
91
|
>
|
|
88
92
|
{/each}
|
|
@@ -106,13 +110,14 @@ function clearModal() {
|
|
|
106
110
|
pattern={property.pattern}
|
|
107
111
|
/>
|
|
108
112
|
{#if property.selectedType !== 'boolean'}
|
|
109
|
-
<h2 class="mb-2">Advanced</h2>
|
|
113
|
+
<h2 class="mb-2 mt-4">Advanced</h2>
|
|
110
114
|
|
|
111
115
|
{#if property.selectedType == 'string'}
|
|
112
116
|
<StringTypeNarrowing
|
|
113
117
|
bind:format={property.format}
|
|
114
118
|
bind:pattern={property.pattern}
|
|
115
119
|
bind:enum_={property.enum_}
|
|
120
|
+
bind:contentEncoding={property.contentEncoding}
|
|
116
121
|
/>
|
|
117
122
|
{:else if property.selectedType == 'array'}
|
|
118
123
|
<select bind:value={property.items}>
|
|
@@ -120,6 +125,9 @@ function clearModal() {
|
|
|
120
125
|
<option value={{ type: 'string' }}> Items are strings</option>
|
|
121
126
|
<option value={{ type: 'number' }}>Items are numbers</option>
|
|
122
127
|
</select>
|
|
128
|
+
{:else if property.selectedType == 'object'}
|
|
129
|
+
<h3 class="mb-2 font-bold mt-4">Resource type</h3>
|
|
130
|
+
<ObjectTypeNarrowing bind:format={property.format} />
|
|
123
131
|
{:else}
|
|
124
132
|
<p>No advanced configuration for this type</p>
|
|
125
133
|
{/if}
|
|
@@ -137,24 +145,3 @@ function clearModal() {
|
|
|
137
145
|
Save
|
|
138
146
|
</button>
|
|
139
147
|
</Modal>
|
|
140
|
-
|
|
141
|
-
<style>
|
|
142
|
-
.item-button {
|
|
143
|
-
padding-top: 0.25rem;
|
|
144
|
-
padding-bottom: 0.25rem;
|
|
145
|
-
border-width: 1px;
|
|
146
|
-
border-radius: 0.125rem
|
|
147
|
-
}
|
|
148
|
-
.item-button-selected {
|
|
149
|
-
-webkit-text-decoration-line: underline;
|
|
150
|
-
text-decoration-line: underline;
|
|
151
|
-
font-weight: 700;
|
|
152
|
-
padding-top: 0.25rem;
|
|
153
|
-
padding-bottom: 0.25rem;
|
|
154
|
-
border-width: 1px;
|
|
155
|
-
--tw-border-opacity: 1;
|
|
156
|
-
border-color: rgb(59 130 246 / var(--tw-border-opacity));
|
|
157
|
-
--tw-bg-opacity: 1;
|
|
158
|
-
background-color: rgb(239 246 255 / var(--tw-bg-opacity));
|
|
159
|
-
border-radius: 0.125rem
|
|
160
|
-
}</style>
|
|
@@ -14,8 +14,8 @@ export interface ModalSchemaProperty {
|
|
|
14
14
|
items?: {
|
|
15
15
|
type?: 'string' | 'number';
|
|
16
16
|
};
|
|
17
|
+
contentEncoding?: 'base64' | 'binary';
|
|
17
18
|
}
|
|
18
|
-
export declare function modalToSchema(schema: ModalSchemaProperty): SchemaProperty;
|
|
19
19
|
export declare function schemaToModal(schema: SchemaProperty, name: string, required: boolean): ModalSchemaProperty;
|
|
20
20
|
export declare const DEFAULT_PROPERTY: ModalSchemaProperty;
|
|
21
21
|
declare const __propDef: {
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
<script>import { emptySchema } from '../utils';
|
|
2
2
|
import Highlight from 'svelte-highlight';
|
|
3
3
|
import json from 'svelte-highlight/languages/json';
|
|
4
|
-
import github from 'svelte-highlight/styles/github';
|
|
5
4
|
import TableCustom from './TableCustom.svelte';
|
|
6
5
|
export let schema = emptySchema();
|
|
7
6
|
let viewJsonSchema = false;
|
|
8
7
|
</script>
|
|
9
8
|
|
|
10
|
-
<svelte:head>
|
|
11
|
-
{@html github}
|
|
12
|
-
</svelte:head>
|
|
13
|
-
|
|
14
9
|
<div class="w-full">
|
|
15
10
|
<div class="flex flex-col sm:flex-row text-base">
|
|
16
11
|
<button
|
|
@@ -59,7 +54,10 @@ let viewJsonSchema = false;
|
|
|
59
54
|
? JSON.stringify(property.default)
|
|
60
55
|
: ''}</td
|
|
61
56
|
>
|
|
62
|
-
<td
|
|
57
|
+
<td
|
|
58
|
+
>{property.format ?? ''}
|
|
59
|
+
{property.contentEncoding ? `(encoding: ${property.contentEncoding})` : ''}</td
|
|
60
|
+
>
|
|
63
61
|
<td>{schema.required.includes(name) ? 'required' : 'optional'}</td>
|
|
64
62
|
</tr>
|
|
65
63
|
{/each}
|
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
<script>import { ScriptService } from '../gen';
|
|
2
|
-
import { emptySchema, sendUserToast, setQueryWithoutLoad } from '../utils';
|
|
3
|
-
import { onDestroy } from 'svelte';
|
|
4
|
-
import ScriptEditor from './ScriptEditor.svelte';
|
|
5
|
-
import { page } from '$app/stores';
|
|
6
2
|
import { goto } from '$app/navigation';
|
|
7
|
-
import
|
|
8
|
-
import SvelteMarkdown from 'svelte-markdown';
|
|
9
|
-
import { workspaceStore } from '../stores';
|
|
10
|
-
import ScriptSchema from './ScriptSchema.svelte';
|
|
3
|
+
import { page } from '$app/stores';
|
|
11
4
|
import { inferArgs } from '../infer';
|
|
12
|
-
import Required from './Required.svelte';
|
|
13
|
-
import RadioButton from './RadioButton.svelte';
|
|
14
5
|
import { DENO_INIT_CODE, DENO_INIT_CODE_TRIGGER, initialCode } from '../script_helpers';
|
|
6
|
+
import { workspaceStore } from '../stores';
|
|
7
|
+
import { emptySchema, encodeState, sendUserToast, setQueryWithoutLoad } from '../utils';
|
|
8
|
+
import { Breadcrumb, BreadcrumbItem } from 'flowbite-svelte';
|
|
9
|
+
import { onDestroy } from 'svelte';
|
|
10
|
+
import SvelteMarkdown from 'svelte-markdown';
|
|
11
|
+
import Path from './Path.svelte';
|
|
12
|
+
import RadioButton from './RadioButton.svelte';
|
|
13
|
+
import Required from './Required.svelte';
|
|
14
|
+
import ScriptEditor from './ScriptEditor.svelte';
|
|
15
|
+
import ScriptSchema from './ScriptSchema.svelte';
|
|
15
16
|
let editor;
|
|
16
17
|
let scriptSchema;
|
|
17
18
|
$: step = Number($page.url.searchParams.get('step')) || 1;
|
|
18
19
|
export let script;
|
|
19
20
|
export let initialPath = '';
|
|
20
21
|
let pathError = '';
|
|
21
|
-
$:
|
|
22
|
-
setQueryWithoutLoad($page.url, 'state', btoa(JSON.stringify(script)));
|
|
23
|
-
}
|
|
22
|
+
$: setQueryWithoutLoad($page.url, 'state', encodeState(script));
|
|
24
23
|
$: {
|
|
25
24
|
if (script.language == 'python3') {
|
|
26
25
|
script.is_trigger = false;
|
|
@@ -85,34 +84,33 @@ onDestroy(() => {
|
|
|
85
84
|
<div class="flex flex-col h-screen max-w-screen-lg xl:-ml-20 xl:pl-4 w-full -mt-4 pt-4 md:mx-10 ">
|
|
86
85
|
<!-- Nav between steps-->
|
|
87
86
|
<div class="flex flex-col w-full">
|
|
88
|
-
<div class="justify-between flex flex-row drop-shadow-sm w-full">
|
|
87
|
+
<div class="justify-between flex flex-row drop-shadow-sm w-full mt-4">
|
|
89
88
|
<div class="wizard-nav flex flex-row w-full">
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
? '
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
>
|
|
89
|
+
<Breadcrumb>
|
|
90
|
+
<BreadcrumbItem>
|
|
91
|
+
<button on:click={() => changeStep(1)} class={step === 1 ? 'font-bold' : null}>
|
|
92
|
+
Metadata
|
|
93
|
+
</button>
|
|
94
|
+
</BreadcrumbItem>
|
|
95
|
+
<BreadcrumbItem>
|
|
96
|
+
<button
|
|
97
|
+
on:click={() => changeStep(2)}
|
|
98
|
+
class={step === 2 ? 'font-bold' : null}
|
|
99
|
+
disabled={pathError != ''}
|
|
100
|
+
>
|
|
101
|
+
Code
|
|
102
|
+
</button>
|
|
103
|
+
</BreadcrumbItem>
|
|
104
|
+
<BreadcrumbItem>
|
|
105
|
+
<button
|
|
106
|
+
on:click={() => changeStep(3)}
|
|
107
|
+
class={step === 3 ? 'font-bold' : null}
|
|
108
|
+
disabled={pathError != ''}
|
|
109
|
+
>
|
|
110
|
+
UI customisation
|
|
111
|
+
</button>
|
|
112
|
+
</BreadcrumbItem>
|
|
113
|
+
</Breadcrumb>
|
|
116
114
|
</div>
|
|
117
115
|
<div class="flex flex-row-reverse ml-2">
|
|
118
116
|
{#if step != 3}
|
|
@@ -168,7 +166,6 @@ onDestroy(() => {
|
|
|
168
166
|
<div class="max-w-md">
|
|
169
167
|
<RadioButton
|
|
170
168
|
label="Language"
|
|
171
|
-
small={true}
|
|
172
169
|
options={[
|
|
173
170
|
['Typescript (Deno)', 'deno'],
|
|
174
171
|
['Python 3.10', 'python3']
|
|
@@ -196,10 +193,11 @@ onDestroy(() => {
|
|
|
196
193
|
rows="1"
|
|
197
194
|
/>
|
|
198
195
|
</label>
|
|
199
|
-
<label class="block ">
|
|
196
|
+
<label class="block" for="inp">
|
|
200
197
|
<span class="text-gray-700"
|
|
201
198
|
>Description<Required required={false} detail="accept markdown formatting" />
|
|
202
199
|
<textarea
|
|
200
|
+
id="inp"
|
|
203
201
|
bind:value={script.description}
|
|
204
202
|
class="
|
|
205
203
|
mt-1
|
|
@@ -268,7 +266,6 @@ onDestroy(() => {
|
|
|
268
266
|
/* .wizard-nav {
|
|
269
267
|
@apply w-1/2 sm:w-1/4;
|
|
270
268
|
} */
|
|
271
|
-
|
|
272
269
|
.wizard-nav button {
|
|
273
270
|
max-height: 30px;
|
|
274
271
|
}</style>
|
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
<script>import {
|
|
2
|
-
import { emptySchema, displayDate } from '../utils';
|
|
3
|
-
import { fade } from 'svelte/transition';
|
|
4
|
-
import Icon from 'svelte-awesome';
|
|
5
|
-
import { faCheck, faChevronDown, faChevronUp, faExclamationTriangle, faMagic, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons';
|
|
6
|
-
import Editor from './Editor.svelte';
|
|
7
|
-
import Tooltip from './Tooltip.svelte';
|
|
8
|
-
import { onDestroy, onMount } from 'svelte';
|
|
1
|
+
<script>import { CompletedJob, Job, JobService } from '../gen';
|
|
9
2
|
import { userStore, workspaceStore } from '../stores';
|
|
10
|
-
import
|
|
3
|
+
import { displayDate, emptySchema } from '../utils';
|
|
4
|
+
import { faCheck, faChevronDown, faChevronUp, faExclamationTriangle, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons';
|
|
5
|
+
import { onDestroy, onMount } from 'svelte';
|
|
6
|
+
import Icon from 'svelte-awesome';
|
|
11
7
|
import { check } from 'svelte-awesome/icons';
|
|
8
|
+
import { fade } from 'svelte/transition';
|
|
9
|
+
import Editor from './Editor.svelte';
|
|
12
10
|
import Modal from './Modal.svelte';
|
|
11
|
+
import TableCustom from './TableCustom.svelte';
|
|
12
|
+
import Tooltip from './Tooltip.svelte';
|
|
13
13
|
import { inferArgs } from '../infer';
|
|
14
|
-
|
|
14
|
+
import { Highlight } from 'svelte-highlight';
|
|
15
|
+
import { json, python, typescript } from 'svelte-highlight/languages';
|
|
15
16
|
import { VSplitPane } from 'svelte-split-pane';
|
|
16
|
-
import SchemaForm from './SchemaForm.svelte';
|
|
17
17
|
import DisplayResult from './DisplayResult.svelte';
|
|
18
18
|
import EditorBar from './EditorBar.svelte';
|
|
19
|
-
import
|
|
20
|
-
import { json, python, typescript } from 'svelte-highlight/languages';
|
|
19
|
+
import SchemaForm from './SchemaForm.svelte';
|
|
21
20
|
// Exported
|
|
22
21
|
export let schema = emptySchema();
|
|
23
22
|
export let code;
|
|
@@ -48,6 +47,7 @@ $: lastSave = localStorage.getItem(path ?? 'last_save');
|
|
|
48
47
|
export function getEditor() {
|
|
49
48
|
return editor;
|
|
50
49
|
}
|
|
50
|
+
let div = null;
|
|
51
51
|
export async function runPreview() {
|
|
52
52
|
try {
|
|
53
53
|
if (previewIntervalId) {
|
|
@@ -116,6 +116,7 @@ async function loadPreviewJob(id) {
|
|
|
116
116
|
previewIsLoading = false;
|
|
117
117
|
loadPastPreviews();
|
|
118
118
|
}
|
|
119
|
+
div?.scroll({ top: div?.scrollHeight, behavior: 'smooth' });
|
|
119
120
|
}
|
|
120
121
|
catch (err) {
|
|
121
122
|
console.error(err);
|
|
@@ -205,7 +206,7 @@ onDestroy(() => {
|
|
|
205
206
|
<div class="header">
|
|
206
207
|
<EditorBar {editor} {lang} {websocketAlive} />
|
|
207
208
|
</div>
|
|
208
|
-
<div class="flex-1 overflow-hidden">
|
|
209
|
+
<div class="flex-1 overflow-hidden border p-2 rounded">
|
|
209
210
|
<Editor
|
|
210
211
|
{code}
|
|
211
212
|
bind:websocketAlive
|
|
@@ -214,11 +215,16 @@ onDestroy(() => {
|
|
|
214
215
|
runPreview()
|
|
215
216
|
viewPreview = true
|
|
216
217
|
}}
|
|
217
|
-
formatAction={() => {
|
|
218
|
+
formatAction={async () => {
|
|
218
219
|
code = getEditor().getCode()
|
|
220
|
+
await inferSchema()
|
|
219
221
|
localStorage.setItem(path ?? 'last_save', code)
|
|
220
222
|
lastSave = code
|
|
221
223
|
}}
|
|
224
|
+
on:blur={() => {
|
|
225
|
+
code = getEditor().getCode()
|
|
226
|
+
inferSchema()
|
|
227
|
+
}}
|
|
222
228
|
class="h-full"
|
|
223
229
|
deno={lang == 'deno'}
|
|
224
230
|
automaticLayout={true}
|
|
@@ -234,8 +240,8 @@ onDestroy(() => {
|
|
|
234
240
|
viewPreview = !viewPreview
|
|
235
241
|
}}
|
|
236
242
|
>
|
|
237
|
-
<div class="flex flex-row items-baseline">
|
|
238
|
-
<div class="font-base py-0 mr-6">
|
|
243
|
+
<div class="flex flex-row flex-wrap items-baseline">
|
|
244
|
+
<div class="font-base py-0 mr-6 hidden md:block">
|
|
239
245
|
Preview <Tooltip
|
|
240
246
|
><span class="font-normal"
|
|
241
247
|
>Test your script by running a preview, passing inputs as if you were a user</span
|
|
@@ -322,7 +328,7 @@ onDestroy(() => {
|
|
|
322
328
|
}}
|
|
323
329
|
>Run preview
|
|
324
330
|
</button>
|
|
325
|
-
<div class="text-xs text-gray-700 min-w-max mx-2">
|
|
331
|
+
<div class="text-xs text-gray-700 min-w-max hidden md:block mx-2">
|
|
326
332
|
Shortcuts: <Tooltip>
|
|
327
333
|
Cmd/Ctrl+S: autoformat code and overwrite local save <br />
|
|
328
334
|
Cmd/Ctrl+Enter: run preview</Tooltip
|
|
@@ -331,7 +337,7 @@ onDestroy(() => {
|
|
|
331
337
|
</div>
|
|
332
338
|
</div>
|
|
333
339
|
</div>
|
|
334
|
-
<div class="preview flex-1
|
|
340
|
+
<div bind:this={div} class="preview flex-1 p-3">
|
|
335
341
|
{#if previewTab === 'logs'}
|
|
336
342
|
<pre
|
|
337
343
|
class="break-all relative h-full mx-2">{#if previewJob && previewJob.logs}{previewJob.logs}
|
|
@@ -339,21 +345,20 @@ onDestroy(() => {
|
|
|
339
345
|
{:else}No preview is available yet{/if}
|
|
340
346
|
</pre>
|
|
341
347
|
{:else if previewTab === 'input'}
|
|
342
|
-
<div class="break-all relative h-full font-sans">
|
|
343
|
-
<div class="
|
|
344
|
-
<
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
current preview input doesn't match requirements defined in arguments. Are you sure?{/if}
|
|
348
|
+
<div class="break-all relative h-full font-sans -mt-2">
|
|
349
|
+
<div class="items-baseline text-xs text-gray-700 px-2 ml-8 italic hidden md:block">
|
|
350
|
+
<p>
|
|
351
|
+
Move the focus outside of the text editor to recompute the input schema from main
|
|
352
|
+
signature or press Ctrl/Cmd+S
|
|
353
|
+
</p>
|
|
354
|
+
<p class="">
|
|
355
|
+
{#if isValid}
|
|
356
|
+
<Icon data={faCheck} class="text-green-600 mr-1" scale={0.6} /> The current preview input
|
|
357
|
+
matches requirements defined in arguments
|
|
358
|
+
{:else}
|
|
359
|
+
<Icon data={faExclamationTriangle} class="text-yellow-500 mr-1" scale={0.6} />The
|
|
360
|
+
current preview input doesn't match requirements defined in arguments{/if}
|
|
361
|
+
</p>
|
|
357
362
|
</div>
|
|
358
363
|
<div class="sm:px-8">
|
|
359
364
|
<SchemaForm {schema} bind:args bind:isValid />
|
|
@@ -384,7 +389,7 @@ onDestroy(() => {
|
|
|
384
389
|
{:else}No local save{/if}
|
|
385
390
|
</div>
|
|
386
391
|
{:else if previewTab === 'history'}
|
|
387
|
-
<TableCustom
|
|
392
|
+
<TableCustom>
|
|
388
393
|
<tr slot="header-row">
|
|
389
394
|
<th class="text-xs">id</th>
|
|
390
395
|
<th class="text-xs">created at</th>
|
|
@@ -394,11 +399,11 @@ onDestroy(() => {
|
|
|
394
399
|
<th class="text-xs">logs</th>
|
|
395
400
|
</tr>
|
|
396
401
|
<tbody slot="body">
|
|
397
|
-
{#each pastPreviews as { id, created_at, success, result
|
|
402
|
+
{#each pastPreviews as { id, created_at, success, result }}
|
|
398
403
|
<tr class="">
|
|
399
|
-
<td class="text-xs"
|
|
400
|
-
|
|
401
|
-
>
|
|
404
|
+
<td class="text-xs">
|
|
405
|
+
<a class="pr-3" href="/run/{id}" target="_blank">{id.substring(30)}</a>
|
|
406
|
+
</td>
|
|
402
407
|
<td class="text-xs">{displayDate(created_at)}</td>
|
|
403
408
|
<td class="text-xs">
|
|
404
409
|
{#if success}
|
|
@@ -415,9 +420,10 @@ onDestroy(() => {
|
|
|
415
420
|
modalViewerContent = result
|
|
416
421
|
modalViewerMode = 'result'
|
|
417
422
|
modalViewer.openModal()
|
|
418
|
-
}}
|
|
419
|
-
|
|
420
|
-
|
|
423
|
+
}}
|
|
424
|
+
>{JSON.stringify(result).substring(0, 30)}...
|
|
425
|
+
</a>
|
|
426
|
+
</td>
|
|
421
427
|
<td class="text-xs"
|
|
422
428
|
><a
|
|
423
429
|
href="#code"
|
|
@@ -463,30 +469,29 @@ onDestroy(() => {
|
|
|
463
469
|
|
|
464
470
|
<style>
|
|
465
471
|
.header {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
padding-bottom: 0.25rem;
|
|
472
|
-
border-left-width: 1px;
|
|
473
|
-
border-right-width: 1px;
|
|
474
|
-
--tw-bg-opacity: 1;
|
|
475
|
-
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
|
476
|
-
font-size: 0.75rem;
|
|
477
|
-
line-height: 1rem;
|
|
478
|
-
--tw-text-opacity: 1;
|
|
479
|
-
color: rgb(55 65 81 / var(--tw-text-opacity));
|
|
480
|
-
}
|
|
472
|
+
|
|
473
|
+
padding-top: 0.5rem;
|
|
474
|
+
|
|
475
|
+
padding-bottom: 0.5rem
|
|
476
|
+
}
|
|
481
477
|
|
|
482
478
|
.preview {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
479
|
+
|
|
480
|
+
border-width: 1px;
|
|
481
|
+
|
|
482
|
+
overflow: auto;
|
|
483
|
+
|
|
484
|
+
border-left-width: 1px;
|
|
485
|
+
|
|
486
|
+
border-right-width: 1px;
|
|
487
|
+
|
|
488
|
+
--tw-bg-opacity: 1;
|
|
489
|
+
|
|
490
|
+
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
|
491
|
+
|
|
492
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
493
|
+
|
|
494
|
+
font-size: 0.75rem;
|
|
495
|
+
|
|
496
|
+
line-height: 1rem
|
|
492
497
|
}</style>
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
<script>import { ScriptService, FlowService
|
|
1
|
+
<script>import { ScriptService, FlowService } from '../gen';
|
|
2
2
|
import Icon from 'svelte-awesome';
|
|
3
3
|
import { faSearch } from '@fortawesome/free-solid-svg-icons';
|
|
4
4
|
import { hubScripts, workspaceStore } from '../stores';
|
|
5
5
|
import { createEventDispatcher } from 'svelte';
|
|
6
6
|
import ItemPicker from './ItemPicker.svelte';
|
|
7
|
-
import RadioButton from './RadioButton.svelte';
|
|
8
7
|
import Modal from './Modal.svelte';
|
|
9
8
|
import { Highlight } from 'svelte-highlight';
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
9
|
+
import typescript from 'svelte-highlight/languages/typescript';
|
|
10
|
+
import python from 'svelte-highlight/languages/python';
|
|
11
|
+
import { getScriptByPath } from '../utils';
|
|
12
|
+
import RadioButton from './RadioButton.svelte';
|
|
13
13
|
export let scriptPath = undefined;
|
|
14
14
|
export let allowFlow = false;
|
|
15
15
|
export let allowHub = false;
|
|
@@ -42,10 +42,6 @@ $: {
|
|
|
42
42
|
}
|
|
43
43
|
</script>
|
|
44
44
|
|
|
45
|
-
<svelte:head>
|
|
46
|
-
{@html github}
|
|
47
|
-
</svelte:head>
|
|
48
|
-
|
|
49
45
|
<ItemPicker
|
|
50
46
|
bind:this={itemPicker}
|
|
51
47
|
pickCallback={(path, _) => {
|
|
@@ -61,9 +57,11 @@ $: {
|
|
|
61
57
|
/>
|
|
62
58
|
|
|
63
59
|
<div class="flex flex-row items-center space-x-5">
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
<div class="w-80">
|
|
61
|
+
{#if options.length > 1}
|
|
62
|
+
<RadioButton bind:value={itemKind} {options} />
|
|
63
|
+
{/if}
|
|
64
|
+
</div>
|
|
67
65
|
|
|
68
66
|
<input type="text" value={scriptPath ?? 'No path chosen yet'} disabled />
|
|
69
67
|
<button class="default-button text-gray-100" on:click={() => itemPicker.openModal()}
|
|
@@ -4,7 +4,7 @@ declare const __propDef: {
|
|
|
4
4
|
scriptPath?: string | undefined;
|
|
5
5
|
allowFlow?: boolean | undefined;
|
|
6
6
|
allowHub?: boolean | undefined;
|
|
7
|
-
itemKind?: "
|
|
7
|
+
itemKind?: "flow" | "script" | "hub" | undefined;
|
|
8
8
|
isTrigger?: boolean | undefined;
|
|
9
9
|
};
|
|
10
10
|
events: {
|
|
@@ -3,7 +3,6 @@ import SchemaForm from './SchemaForm.svelte';
|
|
|
3
3
|
import Tabs from './Tabs.svelte';
|
|
4
4
|
import Highlight from 'svelte-highlight';
|
|
5
5
|
import json from 'svelte-highlight/languages/json';
|
|
6
|
-
import github from 'svelte-highlight/styles/github';
|
|
7
6
|
import SvelteMarkdown from 'svelte-markdown';
|
|
8
7
|
export let schema;
|
|
9
8
|
export let summary;
|
|
@@ -15,10 +14,6 @@ export function setSchema(newSchema) {
|
|
|
15
14
|
}
|
|
16
15
|
</script>
|
|
17
16
|
|
|
18
|
-
<svelte:head>
|
|
19
|
-
{@html github}
|
|
20
|
-
</svelte:head>
|
|
21
|
-
|
|
22
17
|
<div class="w-full">
|
|
23
18
|
<PageHeader title="UI customisation" />
|
|
24
19
|
<Tabs
|
|
@@ -86,7 +86,7 @@ async function addAcl(owner, write) {
|
|
|
86
86
|
<option>group</option>
|
|
87
87
|
</select>
|
|
88
88
|
</label>
|
|
89
|
-
<label class="block grow mx-2">
|
|
89
|
+
<label class="block grow mx-2" for="inp">
|
|
90
90
|
<span class="text-sm text-gray-700">Owner</span>
|
|
91
91
|
<div class="block mt-1">
|
|
92
92
|
<div class="static z-50">
|
|
@@ -20,13 +20,13 @@ $: {
|
|
|
20
20
|
}
|
|
21
21
|
else {
|
|
22
22
|
let writeGroup = pgroups.find((x) => extraPermsKeys.includes(x) && extraPerms[x]);
|
|
23
|
-
if (
|
|
23
|
+
if (writeGroup) {
|
|
24
24
|
kind = 'write';
|
|
25
25
|
reason = `This item was write shared to the group ${writeGroup} which you are a member of`;
|
|
26
26
|
}
|
|
27
27
|
else {
|
|
28
|
-
let readGroup = pgroups.find((x) => extraPermsKeys.includes(x)
|
|
29
|
-
if (
|
|
28
|
+
let readGroup = pgroups.find((x) => extraPermsKeys.includes(x));
|
|
29
|
+
if (readGroup) {
|
|
30
30
|
kind = 'read';
|
|
31
31
|
reason = `This item was read-only shared to the group ${readGroup} which you are a member of`;
|
|
32
32
|
}
|
|
@@ -45,10 +45,12 @@ $: {
|
|
|
45
45
|
}
|
|
46
46
|
</script>
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
{#if kind == 'read' || kind == 'write'}
|
|
49
|
+
<span class="mr-1">
|
|
50
|
+
{#if kind == 'read'}
|
|
51
|
+
<Badge tooltip={reason}>shared to you (read-only)</Badge>
|
|
52
|
+
{:else if kind == 'write'}
|
|
53
|
+
<Badge tooltip={reason}>shared to you</Badge>
|
|
54
|
+
{/if}
|
|
55
|
+
</span>
|
|
56
|
+
{/if}
|