@knime/hub-features 1.12.6 → 1.14.0
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/CHANGELOG.md +17 -0
- package/package.json +2 -2
- package/src/components/versions/components/CreateVersionForm.vue +166 -0
- package/src/components/versions/{CurrentState.vue → components/CurrentState.vue} +4 -3
- package/src/components/versions/{LabelList.vue → components/LabelList.vue} +2 -3
- package/src/components/versions/{ManageVersions.vue → components/ManageVersions.vue} +26 -4
- package/src/components/versions/{VersionHistory.vue → components/VersionHistory.vue} +2 -1
- package/src/components/versions/{VersionItem.vue → components/VersionItem.vue} +2 -2
- package/src/components/versions/components/VersionLimitInfo.vue +32 -0
- package/src/components/versions/{useVersionsApi.ts → composables/useVersionsApi.ts} +9 -1
- package/src/components/versions/index.ts +3 -3
- package/src/components/versions/types.ts +5 -0
- package/src/components/versions/CreateVersionForm.vue +0 -150
- /package/src/components/versions/{NoVersionItem.vue → components/NoVersionItem.vue} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @knime/hub-features
|
|
2
2
|
|
|
3
|
+
## 1.14.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- c75b415: Added SideDrawerHeader component
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [c75b415]
|
|
12
|
+
- @knime/components@1.36.0
|
|
13
|
+
|
|
14
|
+
## 1.13.0
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- d04922e: display version limit info in ManageVersions side drawer
|
|
19
|
+
|
|
3
20
|
## 1.12.6
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knime/hub-features",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "Vue components & composables for shared hub features",
|
|
5
5
|
"homepage": "https://knime.github.io/webapps-common/",
|
|
6
6
|
"license": "GPL 3 and Additional Permissions according to Sec. 7 (SEE the file LICENSE)",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"lodash-es": "4.17.21",
|
|
32
32
|
"ofetch": "^1.4.1",
|
|
33
33
|
"typescript": "^5.8.3",
|
|
34
|
-
"@knime/components": "1.
|
|
34
|
+
"@knime/components": "1.36.0",
|
|
35
35
|
"@knime/styles": "1.11.1",
|
|
36
36
|
"@knime/utils": "1.5.5"
|
|
37
37
|
},
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, nextTick, onMounted, ref } from "vue";
|
|
3
|
+
import { useTextareaAutosize } from "@vueuse/core";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Button,
|
|
7
|
+
InputField,
|
|
8
|
+
Label,
|
|
9
|
+
LoadingIcon,
|
|
10
|
+
SideDrawerHeader,
|
|
11
|
+
TextArea,
|
|
12
|
+
} from "@knime/components";
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
isCreationPending?: boolean;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
withDefaults(defineProps<Props>(), { isCreationPending: false });
|
|
19
|
+
|
|
20
|
+
const emit = defineEmits<{
|
|
21
|
+
create: [{ name: string; description: string }];
|
|
22
|
+
cancel: [hasUnsavedChanges: boolean];
|
|
23
|
+
}>();
|
|
24
|
+
|
|
25
|
+
const versionName = ref("");
|
|
26
|
+
const versionDescription = ref("");
|
|
27
|
+
|
|
28
|
+
const descriptionEditor = ref<InstanceType<typeof TextArea> | null>(null);
|
|
29
|
+
|
|
30
|
+
onMounted(() => {
|
|
31
|
+
useTextareaAutosize({
|
|
32
|
+
element: descriptionEditor.value?.$el.getElementsByTagName("textarea")[0],
|
|
33
|
+
input: versionDescription,
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const doValidate = ref(false);
|
|
38
|
+
|
|
39
|
+
const isVersionNameInvalid = computed(() => {
|
|
40
|
+
return doValidate.value && versionName.value.length <= 0;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const hasUnsavedChanges = computed(() => {
|
|
44
|
+
return versionName.value !== "" || versionDescription.value !== "";
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const onCreate = async () => {
|
|
48
|
+
doValidate.value = true;
|
|
49
|
+
await nextTick();
|
|
50
|
+
|
|
51
|
+
if (!isVersionNameInvalid.value) {
|
|
52
|
+
emit("create", {
|
|
53
|
+
name: versionName.value,
|
|
54
|
+
description: versionDescription.value,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<template>
|
|
61
|
+
<div class="create-version-form">
|
|
62
|
+
<SideDrawerHeader
|
|
63
|
+
title="Create Version"
|
|
64
|
+
description="Give your version a name and description. Versions can be used to create a deployment.
|
|
65
|
+
"
|
|
66
|
+
:is-sub-drawer="true"
|
|
67
|
+
@close="$emit('cancel', hasUnsavedChanges)"
|
|
68
|
+
/>
|
|
69
|
+
<div class="form-content">
|
|
70
|
+
<Label text="Version name">
|
|
71
|
+
<InputField
|
|
72
|
+
v-model="versionName"
|
|
73
|
+
type="text"
|
|
74
|
+
required
|
|
75
|
+
:is-valid="!isVersionNameInvalid"
|
|
76
|
+
/>
|
|
77
|
+
<div v-if="isVersionNameInvalid" class="error">
|
|
78
|
+
Please enter at least 1 character.
|
|
79
|
+
</div>
|
|
80
|
+
</Label>
|
|
81
|
+
<Label text="Description">
|
|
82
|
+
<TextArea
|
|
83
|
+
ref="descriptionEditor"
|
|
84
|
+
v-model="versionDescription"
|
|
85
|
+
class="description"
|
|
86
|
+
/>
|
|
87
|
+
</Label>
|
|
88
|
+
<div class="controls">
|
|
89
|
+
<Button
|
|
90
|
+
with-border
|
|
91
|
+
compact
|
|
92
|
+
class="button cancel"
|
|
93
|
+
@click="$emit('cancel', hasUnsavedChanges)"
|
|
94
|
+
>
|
|
95
|
+
<strong>Cancel</strong>
|
|
96
|
+
</Button>
|
|
97
|
+
<Button
|
|
98
|
+
primary
|
|
99
|
+
compact
|
|
100
|
+
class="button create"
|
|
101
|
+
:disabled="isVersionNameInvalid || isCreationPending"
|
|
102
|
+
@click="onCreate"
|
|
103
|
+
>
|
|
104
|
+
<LoadingIcon v-if="isCreationPending" />
|
|
105
|
+
<strong v-if="!isCreationPending">Create</strong>
|
|
106
|
+
</Button>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</template>
|
|
111
|
+
|
|
112
|
+
<style lang="postcss" scoped>
|
|
113
|
+
.create-version-form {
|
|
114
|
+
height: 100%;
|
|
115
|
+
max-height: 100%;
|
|
116
|
+
width: 100%;
|
|
117
|
+
display: flex;
|
|
118
|
+
flex-direction: column;
|
|
119
|
+
|
|
120
|
+
& .form-content {
|
|
121
|
+
display: flex;
|
|
122
|
+
flex-direction: column;
|
|
123
|
+
height: 100%;
|
|
124
|
+
padding: 30px 30px 0;
|
|
125
|
+
gap: 30px;
|
|
126
|
+
overscroll-behavior: none;
|
|
127
|
+
isolation: isolate;
|
|
128
|
+
overflow: auto;
|
|
129
|
+
z-index: 1;
|
|
130
|
+
background-color: var(--knime-gray-ultra-light);
|
|
131
|
+
|
|
132
|
+
& .description {
|
|
133
|
+
width: 100%;
|
|
134
|
+
max-width: unset;
|
|
135
|
+
display: flex;
|
|
136
|
+
|
|
137
|
+
& :deep(textarea) {
|
|
138
|
+
width: 100%;
|
|
139
|
+
box-sizing: content-box;
|
|
140
|
+
max-height: 200px;
|
|
141
|
+
resize: none;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
& .error {
|
|
146
|
+
position: absolute;
|
|
147
|
+
word-break: keep-all;
|
|
148
|
+
margin-top: 6px;
|
|
149
|
+
font-weight: 300;
|
|
150
|
+
font-size: 13px;
|
|
151
|
+
color: var(--theme-color-error);
|
|
152
|
+
line-height: 18px;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
& .controls {
|
|
156
|
+
border-top: 1px solid var(--knime-silver-sand);
|
|
157
|
+
display: flex;
|
|
158
|
+
margin: 0 -30px;
|
|
159
|
+
padding: 10px 20px;
|
|
160
|
+
gap: 10px;
|
|
161
|
+
justify-content: space-between;
|
|
162
|
+
margin-top: auto;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
</style>
|
|
@@ -5,16 +5,17 @@ import { Button, LocalDateTime, SubMenu } from "@knime/components";
|
|
|
5
5
|
import MenuIcon from "@knime/styles/img/icons/menu-options.svg";
|
|
6
6
|
import WrenchIcon from "@knime/styles/img/icons/wrench.svg";
|
|
7
7
|
|
|
8
|
-
import HubAvatar from "
|
|
8
|
+
import HubAvatar from "../../avatars/HubAvatar.vue";
|
|
9
|
+
import type { ItemSavepoint, WithAvatar, WithLabels } from "../types";
|
|
9
10
|
|
|
10
11
|
import LabelList from "./LabelList.vue";
|
|
11
|
-
import type { ItemSavepoint, WithAvatar, WithLabels } from "./types";
|
|
12
12
|
|
|
13
13
|
const props = defineProps<{
|
|
14
14
|
isSelected: boolean;
|
|
15
15
|
hasEditCapability: boolean;
|
|
16
16
|
hasPreviousVersion: boolean;
|
|
17
17
|
currentStateSavepoint: ItemSavepoint & WithAvatar & WithLabels;
|
|
18
|
+
isVersionLimitExceeded?: boolean;
|
|
18
19
|
}>();
|
|
19
20
|
|
|
20
21
|
const emit = defineEmits<{
|
|
@@ -66,7 +67,7 @@ const onMenuItemClick = (_: Event, item: (typeof menuItems.value)[number]) => {
|
|
|
66
67
|
</div>
|
|
67
68
|
<div class="right">
|
|
68
69
|
<Button
|
|
69
|
-
v-if="hasEditCapability"
|
|
70
|
+
v-if="hasEditCapability && !isVersionLimitExceeded"
|
|
70
71
|
with-border
|
|
71
72
|
compact
|
|
72
73
|
class="create-button"
|
|
@@ -7,9 +7,8 @@ import { isEqual } from "lodash-es"; // eslint-disable-line depend/ban-dependenc
|
|
|
7
7
|
import { FunctionButton } from "@knime/components";
|
|
8
8
|
import { truncateString } from "@knime/utils";
|
|
9
9
|
|
|
10
|
-
import Popover from "
|
|
11
|
-
|
|
12
|
-
import type { AssignedLabel } from "./types";
|
|
10
|
+
import Popover from "../../Popover.vue";
|
|
11
|
+
import type { AssignedLabel } from "../types";
|
|
13
12
|
|
|
14
13
|
type PopoverElement = HTMLElement & {
|
|
15
14
|
closeMenu: () => void;
|
|
@@ -6,15 +6,18 @@ import { FunctionButton } from "@knime/components";
|
|
|
6
6
|
import CloseIcon from "@knime/styles/img/icons/close.svg";
|
|
7
7
|
import HistoryIcon from "@knime/styles/img/icons/history.svg";
|
|
8
8
|
|
|
9
|
-
import
|
|
10
|
-
import VersionHistory from "./VersionHistory.vue";
|
|
11
|
-
import { CURRENT_STATE_VERSION } from "./constants";
|
|
9
|
+
import { CURRENT_STATE_VERSION } from "../constants";
|
|
12
10
|
import type {
|
|
13
11
|
ItemSavepoint,
|
|
14
12
|
NamedItemVersion,
|
|
13
|
+
VersionLimit,
|
|
15
14
|
WithAvatar,
|
|
16
15
|
WithLabels,
|
|
17
|
-
} from "
|
|
16
|
+
} from "../types";
|
|
17
|
+
|
|
18
|
+
import CurrentState from "./CurrentState.vue";
|
|
19
|
+
import VersionHistory from "./VersionHistory.vue";
|
|
20
|
+
import VersionLimitInfo from "./VersionLimitInfo.vue";
|
|
18
21
|
|
|
19
22
|
type ManageVersionsProps = {
|
|
20
23
|
hasUnversionedChanges: boolean;
|
|
@@ -25,6 +28,8 @@ type ManageVersionsProps = {
|
|
|
25
28
|
hasLoadedAllVersions: boolean;
|
|
26
29
|
hasAdminRights: boolean;
|
|
27
30
|
hasEditCapability: boolean;
|
|
31
|
+
versionLimit?: VersionLimit;
|
|
32
|
+
upgradeUrl?: string;
|
|
28
33
|
};
|
|
29
34
|
|
|
30
35
|
defineProps<ManageVersionsProps>();
|
|
@@ -67,6 +72,10 @@ const closeLabelPopovers = throttle(() => {
|
|
|
67
72
|
:has-previous-version="versionHistory.length > 0"
|
|
68
73
|
:is-selected="currentVersion === CURRENT_STATE_VERSION"
|
|
69
74
|
:current-state-savepoint="unversionedSavepoint"
|
|
75
|
+
:is-version-limit-exceeded="
|
|
76
|
+
versionLimit?.limit !== undefined &&
|
|
77
|
+
versionLimit.currentUsage >= versionLimit.limit
|
|
78
|
+
"
|
|
70
79
|
@select="$emit('select', CURRENT_STATE_VERSION)"
|
|
71
80
|
@create-version="$emit('create')"
|
|
72
81
|
@discard="$emit('discardCurrentState')"
|
|
@@ -92,6 +101,15 @@ const closeLabelPopovers = throttle(() => {
|
|
|
92
101
|
@load-all="$emit('loadAll')"
|
|
93
102
|
@select="$emit('select', $event ?? CURRENT_STATE_VERSION)"
|
|
94
103
|
/>
|
|
104
|
+
<VersionLimitInfo
|
|
105
|
+
v-if="versionLimit?.limit !== undefined"
|
|
106
|
+
class="version-limit-info"
|
|
107
|
+
:version-limit="{
|
|
108
|
+
limit: versionLimit.limit,
|
|
109
|
+
currentUsage: versionLimit.currentUsage,
|
|
110
|
+
}"
|
|
111
|
+
:upgrade-url
|
|
112
|
+
/>
|
|
95
113
|
</div>
|
|
96
114
|
</div>
|
|
97
115
|
</div>
|
|
@@ -155,6 +173,10 @@ const closeLabelPopovers = throttle(() => {
|
|
|
155
173
|
& .versions {
|
|
156
174
|
width: 100%;
|
|
157
175
|
padding: 30px;
|
|
176
|
+
|
|
177
|
+
& .version-limit-info {
|
|
178
|
+
margin-top: 30px;
|
|
179
|
+
}
|
|
158
180
|
}
|
|
159
181
|
}
|
|
160
182
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { IdleReadyButton } from "@knime/components";
|
|
3
3
|
|
|
4
|
+
import type { NamedItemVersion, WithAvatar, WithLabels } from "../types";
|
|
5
|
+
|
|
4
6
|
import NoVersionItem from "./NoVersionItem.vue";
|
|
5
7
|
import VersionItem from "./VersionItem.vue";
|
|
6
|
-
import type { NamedItemVersion, WithAvatar, WithLabels } from "./types";
|
|
7
8
|
|
|
8
9
|
defineProps<{
|
|
9
10
|
selectedVersion: NamedItemVersion["version"] | null;
|
|
@@ -6,10 +6,10 @@ import { LocalDateTime, SubMenu, Tooltip } from "@knime/components";
|
|
|
6
6
|
import MenuIcon from "@knime/styles/img/icons/menu-options.svg";
|
|
7
7
|
import { truncateString } from "@knime/utils";
|
|
8
8
|
|
|
9
|
-
import HubAvatar from "
|
|
9
|
+
import HubAvatar from "../../avatars/HubAvatar.vue";
|
|
10
|
+
import type { NamedItemVersion, WithAvatar, WithLabels } from "../types";
|
|
10
11
|
|
|
11
12
|
import LabelList from "./LabelList.vue";
|
|
12
|
-
import type { NamedItemVersion, WithAvatar, WithLabels } from "./types";
|
|
13
13
|
|
|
14
14
|
const DESCRIPTION_TRUNCATE_LENGTH = 120;
|
|
15
15
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from "vue";
|
|
3
|
+
|
|
4
|
+
import { InlineMessage } from "@knime/components";
|
|
5
|
+
|
|
6
|
+
import type { VersionLimit } from "../types";
|
|
7
|
+
|
|
8
|
+
const { versionLimit, upgradeUrl = undefined } = defineProps<{
|
|
9
|
+
versionLimit: Required<VersionLimit>;
|
|
10
|
+
upgradeUrl?: string;
|
|
11
|
+
}>();
|
|
12
|
+
|
|
13
|
+
const isLimitReached = computed(
|
|
14
|
+
() => versionLimit.currentUsage >= versionLimit.limit,
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const title = computed(() => {
|
|
18
|
+
if (isLimitReached.value) {
|
|
19
|
+
return `You've reached the maximum of ${versionLimit.limit} versions.`;
|
|
20
|
+
} else {
|
|
21
|
+
return `Using ${versionLimit.currentUsage} of ${versionLimit.limit} versions.`;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<InlineMessage variant="info" :title>
|
|
28
|
+
<template v-if="upgradeUrl"><a :href="upgradeUrl">Upgrade</a></template>
|
|
29
|
+
<template v-else>Upgrade</template>
|
|
30
|
+
to use unlimited versions.
|
|
31
|
+
</InlineMessage>
|
|
32
|
+
</template>
|
|
@@ -8,11 +8,12 @@ import type {
|
|
|
8
8
|
ItemSavepoint,
|
|
9
9
|
NamedItemVersion,
|
|
10
10
|
RepositoryItem,
|
|
11
|
+
VersionLimit,
|
|
11
12
|
WithAvatar,
|
|
12
13
|
WithLabels,
|
|
13
14
|
} from "@knime/hub-features/versions";
|
|
14
15
|
|
|
15
|
-
import { getFetchClient } from "
|
|
16
|
+
import { getFetchClient } from "../../../common/ofetchClient";
|
|
16
17
|
|
|
17
18
|
type UseVersionsApiOptions = {
|
|
18
19
|
customFetchClientOptions?: FetchOptions;
|
|
@@ -51,6 +52,12 @@ export const useVersionsApi = ({
|
|
|
51
52
|
return doHubRequest(`/repository/${itemId}`) as Promise<RepositoryItem>;
|
|
52
53
|
};
|
|
53
54
|
|
|
55
|
+
const fetchVersionLimit = ({ itemId }: { itemId: string }) => {
|
|
56
|
+
return doHubRequest(
|
|
57
|
+
`/repository/limits/${itemId}/item-versions`,
|
|
58
|
+
) as Promise<VersionLimit>;
|
|
59
|
+
};
|
|
60
|
+
|
|
54
61
|
const fetchVersions = ({
|
|
55
62
|
itemId,
|
|
56
63
|
loadAll,
|
|
@@ -214,6 +221,7 @@ export const useVersionsApi = ({
|
|
|
214
221
|
|
|
215
222
|
return {
|
|
216
223
|
fetchVersions,
|
|
224
|
+
fetchVersionLimit,
|
|
217
225
|
fetchResourceLabels,
|
|
218
226
|
fetchItemSavepoints,
|
|
219
227
|
fetchPermissions,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import CreateVersionForm from "./CreateVersionForm.vue";
|
|
2
|
-
import ManageVersions from "./ManageVersions.vue";
|
|
1
|
+
import CreateVersionForm from "./components/CreateVersionForm.vue";
|
|
2
|
+
import ManageVersions from "./components/ManageVersions.vue";
|
|
3
3
|
|
|
4
4
|
export { CreateVersionForm, ManageVersions };
|
|
5
5
|
export type * from "./types";
|
|
6
6
|
export * from "./constants";
|
|
7
|
-
export * from "./useVersionsApi";
|
|
7
|
+
export * from "./composables/useVersionsApi";
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed, nextTick, onMounted, ref } from "vue";
|
|
3
|
-
import { useTextareaAutosize } from "@vueuse/core";
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
Button,
|
|
7
|
-
InputField,
|
|
8
|
-
Label,
|
|
9
|
-
LoadingIcon,
|
|
10
|
-
TextArea,
|
|
11
|
-
} from "@knime/components";
|
|
12
|
-
|
|
13
|
-
type Props = {
|
|
14
|
-
isCreationPending?: boolean;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
withDefaults(defineProps<Props>(), { isCreationPending: false });
|
|
18
|
-
|
|
19
|
-
const emit = defineEmits<{
|
|
20
|
-
create: [{ name: string; description: string }];
|
|
21
|
-
cancel: [hasUnsavedChanges: boolean];
|
|
22
|
-
}>();
|
|
23
|
-
|
|
24
|
-
const versionName = ref("");
|
|
25
|
-
const versionDescription = ref("");
|
|
26
|
-
|
|
27
|
-
const descriptionEditor = ref<InstanceType<typeof TextArea> | null>(null);
|
|
28
|
-
|
|
29
|
-
onMounted(() => {
|
|
30
|
-
useTextareaAutosize({
|
|
31
|
-
element: descriptionEditor.value?.$el.getElementsByTagName("textarea")[0],
|
|
32
|
-
input: versionDescription,
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const doValidate = ref(false);
|
|
37
|
-
|
|
38
|
-
const isVersionNameInvalid = computed(() => {
|
|
39
|
-
return versionName.value.length <= 0 && doValidate.value;
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const hasUnsavedChanges = computed(() => {
|
|
43
|
-
return versionName.value !== "" || versionDescription.value !== "";
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const onCreate = async () => {
|
|
47
|
-
doValidate.value = true;
|
|
48
|
-
await nextTick();
|
|
49
|
-
|
|
50
|
-
if (!isVersionNameInvalid.value) {
|
|
51
|
-
emit("create", {
|
|
52
|
-
name: versionName.value,
|
|
53
|
-
description: versionDescription.value,
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
</script>
|
|
58
|
-
|
|
59
|
-
<template>
|
|
60
|
-
<div class="create-version-form">
|
|
61
|
-
<Label text="Version name">
|
|
62
|
-
<InputField
|
|
63
|
-
v-model="versionName"
|
|
64
|
-
type="text"
|
|
65
|
-
required
|
|
66
|
-
:is-valid="!isVersionNameInvalid"
|
|
67
|
-
/>
|
|
68
|
-
<div v-if="isVersionNameInvalid" class="error">
|
|
69
|
-
Please enter at least 1 character.
|
|
70
|
-
</div>
|
|
71
|
-
</Label>
|
|
72
|
-
<Label text="Description">
|
|
73
|
-
<TextArea
|
|
74
|
-
ref="descriptionEditor"
|
|
75
|
-
v-model="versionDescription"
|
|
76
|
-
class="description"
|
|
77
|
-
/>
|
|
78
|
-
</Label>
|
|
79
|
-
<div class="controls">
|
|
80
|
-
<Button
|
|
81
|
-
with-border
|
|
82
|
-
compact
|
|
83
|
-
class="button cancel"
|
|
84
|
-
@click="$emit('cancel', hasUnsavedChanges)"
|
|
85
|
-
>
|
|
86
|
-
<strong>Cancel</strong>
|
|
87
|
-
</Button>
|
|
88
|
-
<Button
|
|
89
|
-
primary
|
|
90
|
-
compact
|
|
91
|
-
class="button create"
|
|
92
|
-
:disabled="isVersionNameInvalid || isCreationPending"
|
|
93
|
-
@click="onCreate"
|
|
94
|
-
>
|
|
95
|
-
<LoadingIcon v-if="isCreationPending" />
|
|
96
|
-
<strong v-if="!isCreationPending">Create</strong>
|
|
97
|
-
</Button>
|
|
98
|
-
</div>
|
|
99
|
-
</div>
|
|
100
|
-
</template>
|
|
101
|
-
|
|
102
|
-
<style lang="postcss" scoped>
|
|
103
|
-
.create-version-form {
|
|
104
|
-
height: 100%;
|
|
105
|
-
max-height: 100%;
|
|
106
|
-
width: 100%;
|
|
107
|
-
display: flex;
|
|
108
|
-
flex-direction: column;
|
|
109
|
-
padding: 30px 30px 0;
|
|
110
|
-
gap: 30px;
|
|
111
|
-
overscroll-behavior: none;
|
|
112
|
-
isolation: isolate;
|
|
113
|
-
overflow: auto;
|
|
114
|
-
z-index: 1;
|
|
115
|
-
background-color: var(--knime-gray-ultra-light);
|
|
116
|
-
|
|
117
|
-
& .description {
|
|
118
|
-
width: 100%;
|
|
119
|
-
max-width: unset;
|
|
120
|
-
display: flex;
|
|
121
|
-
|
|
122
|
-
& :deep(textarea) {
|
|
123
|
-
width: 100%;
|
|
124
|
-
box-sizing: content-box;
|
|
125
|
-
max-height: 200px;
|
|
126
|
-
resize: none;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
& .error {
|
|
131
|
-
position: absolute;
|
|
132
|
-
word-break: keep-all;
|
|
133
|
-
margin-top: 6px;
|
|
134
|
-
font-weight: 300;
|
|
135
|
-
font-size: 13px;
|
|
136
|
-
color: var(--theme-color-error);
|
|
137
|
-
line-height: 18px;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
& .controls {
|
|
141
|
-
border-top: 1px solid var(--knime-silver-sand);
|
|
142
|
-
display: flex;
|
|
143
|
-
margin: 0 -30px;
|
|
144
|
-
padding: 10px 20px;
|
|
145
|
-
gap: 10px;
|
|
146
|
-
justify-content: space-between;
|
|
147
|
-
margin-top: auto;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
</style>
|
|
File without changes
|