@knime/hub-features 1.27.0 → 1.29.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 +32 -0
- package/package.json +4 -4
- package/src/analytics/analytics.ts +39 -13
- package/src/analytics/schema/cloudhome-event-functions.ts +245 -0
- package/src/analytics/schema/code-generator.js +17 -8
- package/src/analytics/schema/{event-functions.ts → editor-event-functions.ts} +7 -9
- package/src/analytics/schema/schema.d.ts +133 -7
- package/src/analytics/schema/schema.json +833 -157
- package/src/analytics/types.ts +4 -1
- package/src/httpClient/constants.ts +1 -0
- package/src/{common/ofetchClient.ts → httpClient/createHttpClient.ts} +6 -5
- package/src/httpClient/index.ts +2 -0
- package/src/index.ts +1 -0
- package/src/useDownloadArtifact/useDownloadArtifact.ts +2 -2
- package/src/useFileUpload/useFileUpload.ts +2 -2
- package/src/common/constants.ts +0 -1
- package/src/components/versions/components/CreateVersionForm.vue +0 -155
- package/src/components/versions/components/CurrentState.vue +0 -258
- package/src/components/versions/components/LabelList.vue +0 -253
- package/src/components/versions/components/ManageVersions.vue +0 -191
- package/src/components/versions/components/NoVersionItem.vue +0 -23
- package/src/components/versions/components/VersionHistory.vue +0 -138
- package/src/components/versions/components/VersionItem.vue +0 -278
- package/src/components/versions/components/VersionLimitInfo.vue +0 -37
- package/src/components/versions/composables/useVersionsApi.ts +0 -254
- package/src/components/versions/constants.ts +0 -3
- package/src/components/versions/index.ts +0 -7
- package/src/components/versions/types.ts +0 -77
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { type Ref, computed, onMounted, ref } from "vue";
|
|
3
|
-
import { useEventBus } from "@vueuse/core";
|
|
4
|
-
import { autoUpdate, offset, useFloating } from "@floating-ui/vue";
|
|
5
|
-
import { isEqual } from "lodash-es"; // eslint-disable-line depend/ban-dependencies
|
|
6
|
-
|
|
7
|
-
import { FunctionButton } from "@knime/components";
|
|
8
|
-
import { truncateString } from "@knime/utils";
|
|
9
|
-
|
|
10
|
-
import Popover from "../../Popover.vue";
|
|
11
|
-
import type { AssignedLabel } from "../types";
|
|
12
|
-
|
|
13
|
-
type PopoverElement = HTMLElement & {
|
|
14
|
-
closeMenu: () => void;
|
|
15
|
-
openMenu: () => void;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const LABEL_LENGTH = 25;
|
|
19
|
-
|
|
20
|
-
const props = withDefaults(
|
|
21
|
-
defineProps<{
|
|
22
|
-
labels: Array<AssignedLabel>;
|
|
23
|
-
defaultLabelCount?: number;
|
|
24
|
-
}>(),
|
|
25
|
-
{ defaultLabelCount: 3 },
|
|
26
|
-
);
|
|
27
|
-
const emit = defineEmits(["labelOver", "labelLeave"]);
|
|
28
|
-
|
|
29
|
-
const eventBus = useEventBus("versionLabels");
|
|
30
|
-
const eventBusKey = "versionLabelShowPopover";
|
|
31
|
-
|
|
32
|
-
const showAll = ref(false);
|
|
33
|
-
const activeLabel: Ref<AssignedLabel | null> = ref(null);
|
|
34
|
-
|
|
35
|
-
const popover: Ref<PopoverElement | null> = ref(null);
|
|
36
|
-
const floatingPanel: Ref<HTMLElement | null> = ref(null);
|
|
37
|
-
const floatingAnchor: Ref<HTMLElement | null> = ref(null);
|
|
38
|
-
// 40px is the offset of the arrow on the popover plus the top padding
|
|
39
|
-
// this is necessary to compensate for the offset calculation
|
|
40
|
-
const defaultCrossAxisOffset = -46;
|
|
41
|
-
const defaultMainAxisOffset = 75;
|
|
42
|
-
|
|
43
|
-
const createMiddleware = () => [
|
|
44
|
-
offset({
|
|
45
|
-
crossAxis: defaultCrossAxisOffset,
|
|
46
|
-
mainAxis: defaultMainAxisOffset,
|
|
47
|
-
}),
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
const { floatingStyles } = useFloating(floatingAnchor, floatingPanel, {
|
|
51
|
-
whileElementsMounted: autoUpdate,
|
|
52
|
-
placement: "left-start",
|
|
53
|
-
strategy: "fixed",
|
|
54
|
-
middleware: createMiddleware(),
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const popoverTopOffset = ref(0);
|
|
58
|
-
const popoverFloatingStyles = computed(() => {
|
|
59
|
-
const parsedTop = parseInt(floatingStyles.value.top.replace("px", ""), 10);
|
|
60
|
-
const compensatedTop = `${parsedTop + popoverTopOffset.value}px`;
|
|
61
|
-
|
|
62
|
-
return {
|
|
63
|
-
...floatingStyles.value,
|
|
64
|
-
top: compensatedTop,
|
|
65
|
-
};
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const isShowMoreVisible = computed(
|
|
69
|
-
() => props.labels.length > props.defaultLabelCount && !showAll.value,
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
const showMoreButtonText = computed(
|
|
73
|
-
() => `+${props.labels.length - props.defaultLabelCount}`,
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
const filteredLabels = computed(() =>
|
|
77
|
-
showAll.value ? props.labels : props.labels.slice(0, props.defaultLabelCount),
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
const calculateDistanceToUpperBorder = (labelElement: HTMLElement) => {
|
|
81
|
-
const labelRect = labelElement.getBoundingClientRect();
|
|
82
|
-
const floatingAnchorRect = floatingAnchor.value!.getBoundingClientRect();
|
|
83
|
-
|
|
84
|
-
return Math.round(labelRect.top - floatingAnchorRect.top);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const isActiveLabel = (label: AssignedLabel) =>
|
|
88
|
-
isEqual(activeLabel.value, label);
|
|
89
|
-
|
|
90
|
-
const togglePopover = (label: AssignedLabel, labelElement: HTMLElement) => {
|
|
91
|
-
if (isActiveLabel(label)) {
|
|
92
|
-
activeLabel.value = null;
|
|
93
|
-
popover.value?.closeMenu();
|
|
94
|
-
} else {
|
|
95
|
-
eventBus.emit(eventBusKey);
|
|
96
|
-
popoverTopOffset.value = calculateDistanceToUpperBorder(labelElement);
|
|
97
|
-
|
|
98
|
-
activeLabel.value = label;
|
|
99
|
-
popover.value?.openMenu();
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const showMore = () => {
|
|
104
|
-
showAll.value = !showAll.value;
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const mouseOver = () => emit("labelOver");
|
|
108
|
-
const mouseLeave = () => emit("labelLeave");
|
|
109
|
-
|
|
110
|
-
onMounted(() => {
|
|
111
|
-
eventBus.on((event: unknown) => {
|
|
112
|
-
if (event === eventBusKey) {
|
|
113
|
-
popover.value?.closeMenu();
|
|
114
|
-
activeLabel.value = null;
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
</script>
|
|
119
|
-
|
|
120
|
-
<template>
|
|
121
|
-
<template v-if="labels.length > 0">
|
|
122
|
-
<div class="label-list-with-popover">
|
|
123
|
-
<div ref="floatingAnchor" class="label-list">
|
|
124
|
-
<FunctionButton
|
|
125
|
-
v-for="label in filteredLabels"
|
|
126
|
-
:key="label.labelId"
|
|
127
|
-
compact
|
|
128
|
-
class="with-border"
|
|
129
|
-
:active="isActiveLabel(label)"
|
|
130
|
-
@mouseover="mouseOver"
|
|
131
|
-
@mouseleave="mouseLeave"
|
|
132
|
-
@click.stop="togglePopover(label, $event.currentTarget)"
|
|
133
|
-
@keydown.esc.stop="popover?.closeMenu()"
|
|
134
|
-
>
|
|
135
|
-
{{ truncateString(label.label.name, LABEL_LENGTH) }}
|
|
136
|
-
</FunctionButton>
|
|
137
|
-
|
|
138
|
-
<FunctionButton
|
|
139
|
-
v-if="isShowMoreVisible"
|
|
140
|
-
compact
|
|
141
|
-
class="with-border"
|
|
142
|
-
@mouseover="mouseOver"
|
|
143
|
-
@mouseleave="mouseLeave"
|
|
144
|
-
@click.stop="showMore"
|
|
145
|
-
>{{ showMoreButtonText }}</FunctionButton
|
|
146
|
-
>
|
|
147
|
-
</div>
|
|
148
|
-
|
|
149
|
-
<div
|
|
150
|
-
ref="floatingPanel"
|
|
151
|
-
class="floating-panel"
|
|
152
|
-
:style="popoverFloatingStyles"
|
|
153
|
-
@click.stop
|
|
154
|
-
@mouseover="mouseOver"
|
|
155
|
-
@mouseleave="mouseLeave"
|
|
156
|
-
>
|
|
157
|
-
<Popover
|
|
158
|
-
ref="popover"
|
|
159
|
-
:use-button="false"
|
|
160
|
-
:button-with-border="false"
|
|
161
|
-
arrow-position="right"
|
|
162
|
-
@close="activeLabel = null"
|
|
163
|
-
>
|
|
164
|
-
<template #content>
|
|
165
|
-
<h6 class="headline">
|
|
166
|
-
{{ activeLabel?.label.name }}
|
|
167
|
-
</h6>
|
|
168
|
-
<div class="panel">
|
|
169
|
-
<div class="description">
|
|
170
|
-
{{ activeLabel?.label.description }}
|
|
171
|
-
</div>
|
|
172
|
-
<div class="message">{{ activeLabel?.message }}</div>
|
|
173
|
-
</div>
|
|
174
|
-
</template>
|
|
175
|
-
</Popover>
|
|
176
|
-
</div>
|
|
177
|
-
</div>
|
|
178
|
-
</template>
|
|
179
|
-
</template>
|
|
180
|
-
|
|
181
|
-
<style lang="postcss" scoped>
|
|
182
|
-
.label-list-with-popover {
|
|
183
|
-
position: relative;
|
|
184
|
-
|
|
185
|
-
& .label-list {
|
|
186
|
-
position: relative;
|
|
187
|
-
display: flex;
|
|
188
|
-
flex-flow: row wrap;
|
|
189
|
-
gap: var(--space-4);
|
|
190
|
-
align-items: center;
|
|
191
|
-
padding: var(--space-6) 0;
|
|
192
|
-
|
|
193
|
-
& .function-button {
|
|
194
|
-
&.with-border {
|
|
195
|
-
padding: 2px var(--space-8);
|
|
196
|
-
border: 1px solid var(--knime-silver-sand);
|
|
197
|
-
|
|
198
|
-
&.active {
|
|
199
|
-
border-color: var(--theme-button-function-background-color-active);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
&:empty {
|
|
205
|
-
display: none;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
& .floating-panel {
|
|
210
|
-
z-index: 3;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/* the position is set back because it interferes with the position calculation of floating UI */
|
|
215
|
-
.popover.expanded :deep(.content) {
|
|
216
|
-
position: initial;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
.headline,
|
|
220
|
-
.panel {
|
|
221
|
-
line-height: 1.5;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
.headline {
|
|
225
|
-
padding-right: 18px;
|
|
226
|
-
margin: 0;
|
|
227
|
-
margin: 0 0 var(--space-8);
|
|
228
|
-
font-size: 16px;
|
|
229
|
-
font-weight: 700;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
.panel {
|
|
233
|
-
& .description {
|
|
234
|
-
margin-bottom: var(--space-6);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
& .message,
|
|
238
|
-
& .description {
|
|
239
|
-
font-size: 13px;
|
|
240
|
-
font-weight: 300;
|
|
241
|
-
|
|
242
|
-
&:empty {
|
|
243
|
-
display: none;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
@media only screen and (width <= 900px) {
|
|
249
|
-
.label-list-with-popover {
|
|
250
|
-
display: none;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
</style>
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { useEventBus } from "@vueuse/core";
|
|
3
|
-
import { throttle } from "lodash-es"; // eslint-disable-line depend/ban-dependencies
|
|
4
|
-
|
|
5
|
-
import { FunctionButton } from "@knime/components";
|
|
6
|
-
import CloseIcon from "@knime/styles/img/icons/close.svg";
|
|
7
|
-
import HistoryIcon from "@knime/styles/img/icons/history.svg";
|
|
8
|
-
|
|
9
|
-
import { CURRENT_STATE_VERSION } from "../constants";
|
|
10
|
-
import type {
|
|
11
|
-
ItemSavepoint,
|
|
12
|
-
NamedItemVersion,
|
|
13
|
-
VersionLimit,
|
|
14
|
-
WithAvatar,
|
|
15
|
-
WithLabels,
|
|
16
|
-
} from "../types";
|
|
17
|
-
|
|
18
|
-
import CurrentState from "./CurrentState.vue";
|
|
19
|
-
import VersionHistory from "./VersionHistory.vue";
|
|
20
|
-
import VersionLimitInfo from "./VersionLimitInfo.vue";
|
|
21
|
-
|
|
22
|
-
type ManageVersionsProps = {
|
|
23
|
-
hasUnversionedChanges: boolean;
|
|
24
|
-
unversionedSavepoint?: (ItemSavepoint & WithAvatar & WithLabels) | null;
|
|
25
|
-
currentVersion: NamedItemVersion["version"] | null;
|
|
26
|
-
versionHistory: Array<NamedItemVersion & WithAvatar & WithLabels>;
|
|
27
|
-
loading: boolean;
|
|
28
|
-
hasLoadedAllVersions: boolean;
|
|
29
|
-
hasAdminRights: boolean;
|
|
30
|
-
hasEditCapability: boolean;
|
|
31
|
-
versionLimit?: VersionLimit;
|
|
32
|
-
upgradeUrl?: string;
|
|
33
|
-
isPrivate?: boolean;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
defineProps<ManageVersionsProps>();
|
|
37
|
-
|
|
38
|
-
defineEmits<{
|
|
39
|
-
close: [];
|
|
40
|
-
loadAll: [];
|
|
41
|
-
create: [];
|
|
42
|
-
delete: [version: NamedItemVersion["version"]];
|
|
43
|
-
restore: [version: NamedItemVersion["version"]];
|
|
44
|
-
select: [version: NamedItemVersion["version"]];
|
|
45
|
-
discardCurrentState: [];
|
|
46
|
-
}>();
|
|
47
|
-
|
|
48
|
-
const labelsEventBus = useEventBus("versionLabels");
|
|
49
|
-
|
|
50
|
-
const closeLabelPopovers = throttle(() => {
|
|
51
|
-
labelsEventBus.emit("versionLabelShowPopover");
|
|
52
|
-
// eslint-disable-next-line no-magic-numbers
|
|
53
|
-
}, 10000); // Arbitrary delay to reduce overhead, is automatically reset @scrollend
|
|
54
|
-
</script>
|
|
55
|
-
|
|
56
|
-
<template>
|
|
57
|
-
<div class="manage-versions-container">
|
|
58
|
-
<FunctionButton class="close" @click="$emit('close')">
|
|
59
|
-
<CloseIcon />
|
|
60
|
-
</FunctionButton>
|
|
61
|
-
|
|
62
|
-
<div class="manage-versions">
|
|
63
|
-
<div class="header">
|
|
64
|
-
<HistoryIcon class="history-icon" /><!--
|
|
65
|
-
-->
|
|
66
|
-
<h4>Version history</h4>
|
|
67
|
-
<div
|
|
68
|
-
v-if="hasUnversionedChanges && unversionedSavepoint"
|
|
69
|
-
class="changes"
|
|
70
|
-
>
|
|
71
|
-
<CurrentState
|
|
72
|
-
:has-edit-capability="hasEditCapability"
|
|
73
|
-
:has-previous-version="versionHistory.length > 0"
|
|
74
|
-
:is-selected="currentVersion === CURRENT_STATE_VERSION"
|
|
75
|
-
:current-state-savepoint="unversionedSavepoint"
|
|
76
|
-
:is-version-limit-exceeded="
|
|
77
|
-
versionLimit?.limit !== undefined &&
|
|
78
|
-
versionLimit.currentUsage >= versionLimit.limit
|
|
79
|
-
"
|
|
80
|
-
@select="$emit('select', CURRENT_STATE_VERSION)"
|
|
81
|
-
@create-version="$emit('create')"
|
|
82
|
-
@discard="$emit('discardCurrentState')"
|
|
83
|
-
/>
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
<div
|
|
87
|
-
class="overflow-container"
|
|
88
|
-
@scroll="closeLabelPopovers"
|
|
89
|
-
@scrollend="closeLabelPopovers.cancel"
|
|
90
|
-
>
|
|
91
|
-
<div class="versions">
|
|
92
|
-
<VersionHistory
|
|
93
|
-
:selected-version="currentVersion"
|
|
94
|
-
:version-history
|
|
95
|
-
:loading
|
|
96
|
-
:has-unversioned-changes
|
|
97
|
-
:has-loaded-all-versions
|
|
98
|
-
:has-admin-rights
|
|
99
|
-
:has-edit-capability
|
|
100
|
-
@delete="$emit('delete', $event)"
|
|
101
|
-
@restore="$emit('restore', $event)"
|
|
102
|
-
@load-all="$emit('loadAll')"
|
|
103
|
-
@select="$emit('select', $event ?? CURRENT_STATE_VERSION)"
|
|
104
|
-
/>
|
|
105
|
-
<VersionLimitInfo
|
|
106
|
-
v-if="versionLimit?.limit !== undefined"
|
|
107
|
-
class="version-limit-info"
|
|
108
|
-
:version-limit="{
|
|
109
|
-
limit: versionLimit.limit,
|
|
110
|
-
currentUsage: versionLimit.currentUsage,
|
|
111
|
-
}"
|
|
112
|
-
:upgrade-url
|
|
113
|
-
:is-private
|
|
114
|
-
/>
|
|
115
|
-
</div>
|
|
116
|
-
</div>
|
|
117
|
-
</div>
|
|
118
|
-
</div>
|
|
119
|
-
</template>
|
|
120
|
-
|
|
121
|
-
<style lang="postcss" scoped>
|
|
122
|
-
@import url("@knime/styles/css/mixins.css");
|
|
123
|
-
|
|
124
|
-
.manage-versions-container {
|
|
125
|
-
position: relative;
|
|
126
|
-
display: flex;
|
|
127
|
-
flex-direction: column;
|
|
128
|
-
align-items: flex-start;
|
|
129
|
-
justify-content: flex-start;
|
|
130
|
-
height: 100%;
|
|
131
|
-
overscroll-behavior: none;
|
|
132
|
-
background-color: var(--knime-gray-light-semi);
|
|
133
|
-
isolation: isolate;
|
|
134
|
-
|
|
135
|
-
& .close {
|
|
136
|
-
position: absolute;
|
|
137
|
-
top: 6px;
|
|
138
|
-
right: 6px;
|
|
139
|
-
z-index: 3;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
& .manage-versions {
|
|
143
|
-
display: flex;
|
|
144
|
-
flex-direction: column;
|
|
145
|
-
width: 100%;
|
|
146
|
-
height: 100%;
|
|
147
|
-
|
|
148
|
-
& .header {
|
|
149
|
-
z-index: 2;
|
|
150
|
-
padding: 32px 30px 30px;
|
|
151
|
-
background-color: var(--knime-white);
|
|
152
|
-
|
|
153
|
-
& h4 {
|
|
154
|
-
display: inline;
|
|
155
|
-
margin: 0;
|
|
156
|
-
font-size: 22px;
|
|
157
|
-
line-height: 26px;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
& .history-icon {
|
|
161
|
-
@mixin svg-icon-size 24;
|
|
162
|
-
|
|
163
|
-
position: relative;
|
|
164
|
-
top: 1px;
|
|
165
|
-
margin-right: 9px;
|
|
166
|
-
vertical-align: sub;
|
|
167
|
-
stroke: var(--knime-masala);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
& .overflow-container {
|
|
172
|
-
overflow-y: auto;
|
|
173
|
-
|
|
174
|
-
& .versions {
|
|
175
|
-
width: 100%;
|
|
176
|
-
padding: 30px;
|
|
177
|
-
|
|
178
|
-
& .version-limit-info {
|
|
179
|
-
margin-top: 30px;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
& .changes {
|
|
185
|
-
width: 100%;
|
|
186
|
-
padding-top: 30px;
|
|
187
|
-
background-color: var(--knime-white);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
</style>
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="no-versions-item">No version created yet</div>
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<style lang="postcss" scoped>
|
|
6
|
-
.no-versions-item {
|
|
7
|
-
padding-top: 4px;
|
|
8
|
-
font-size: 12px;
|
|
9
|
-
font-weight: 300;
|
|
10
|
-
line-height: 15px;
|
|
11
|
-
|
|
12
|
-
&::after {
|
|
13
|
-
position: absolute;
|
|
14
|
-
top: 11px;
|
|
15
|
-
left: -4px;
|
|
16
|
-
width: 6px;
|
|
17
|
-
height: 6px;
|
|
18
|
-
content: "";
|
|
19
|
-
background-color: var(--knime-masala);
|
|
20
|
-
border-radius: 100%;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
</style>
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { IdleReadyButton } from "@knime/components";
|
|
3
|
-
|
|
4
|
-
import type { NamedItemVersion, WithAvatar, WithLabels } from "../types";
|
|
5
|
-
|
|
6
|
-
import NoVersionItem from "./NoVersionItem.vue";
|
|
7
|
-
import VersionItem from "./VersionItem.vue";
|
|
8
|
-
|
|
9
|
-
defineProps<{
|
|
10
|
-
selectedVersion: NamedItemVersion["version"] | null;
|
|
11
|
-
versionHistory: Array<NamedItemVersion & WithAvatar & WithLabels>;
|
|
12
|
-
hasLoadedAllVersions: boolean;
|
|
13
|
-
loading: boolean;
|
|
14
|
-
hasUnversionedChanges: boolean;
|
|
15
|
-
hasAdminRights: boolean;
|
|
16
|
-
hasEditCapability: boolean;
|
|
17
|
-
}>();
|
|
18
|
-
|
|
19
|
-
defineEmits<{
|
|
20
|
-
loadAll: [];
|
|
21
|
-
delete: [version: NamedItemVersion["version"]];
|
|
22
|
-
restore: [version: NamedItemVersion["version"]];
|
|
23
|
-
select: [version: NamedItemVersion["version"] | null];
|
|
24
|
-
}>();
|
|
25
|
-
</script>
|
|
26
|
-
|
|
27
|
-
<template>
|
|
28
|
-
<div class="version-history-container">
|
|
29
|
-
<div :class="['versions', { 'no-changes': !hasUnversionedChanges }]">
|
|
30
|
-
<VersionItem
|
|
31
|
-
v-for="itemVersion in versionHistory"
|
|
32
|
-
:key="itemVersion.version"
|
|
33
|
-
:is-selected="itemVersion.version === selectedVersion"
|
|
34
|
-
:version="itemVersion"
|
|
35
|
-
:has-admin-rights="hasAdminRights"
|
|
36
|
-
:has-edit-capability="hasEditCapability"
|
|
37
|
-
class="version-item"
|
|
38
|
-
@delete="$emit('delete', itemVersion.version)"
|
|
39
|
-
@restore="$emit('restore', itemVersion.version)"
|
|
40
|
-
@select="$emit('select', $event ? itemVersion.version : null)"
|
|
41
|
-
/>
|
|
42
|
-
<NoVersionItem v-if="!loading && versionHistory.length === 0" />
|
|
43
|
-
</div>
|
|
44
|
-
<IdleReadyButton
|
|
45
|
-
v-if="!hasLoadedAllVersions"
|
|
46
|
-
:with-border="false"
|
|
47
|
-
with-down-icon
|
|
48
|
-
:idle="loading"
|
|
49
|
-
ready-text=" Load all "
|
|
50
|
-
@click="$emit('loadAll')"
|
|
51
|
-
/>
|
|
52
|
-
</div>
|
|
53
|
-
</template>
|
|
54
|
-
|
|
55
|
-
<style lang="postcss" scoped>
|
|
56
|
-
@import url("@knime/styles/css/mixins.css");
|
|
57
|
-
|
|
58
|
-
.version-history-container {
|
|
59
|
-
height: 100%;
|
|
60
|
-
|
|
61
|
-
& .header {
|
|
62
|
-
display: flex;
|
|
63
|
-
align-items: center;
|
|
64
|
-
width: 440px;
|
|
65
|
-
height: 24px;
|
|
66
|
-
margin-bottom: 10px;
|
|
67
|
-
|
|
68
|
-
& .title {
|
|
69
|
-
display: inline;
|
|
70
|
-
margin: 0;
|
|
71
|
-
font-size: 16px;
|
|
72
|
-
font-weight: 700;
|
|
73
|
-
line-height: 19px;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
@media only screen and (width <= 900px) {
|
|
77
|
-
width: calc(100vw - 60px);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
& .versions {
|
|
82
|
-
position: relative;
|
|
83
|
-
display: flex;
|
|
84
|
-
flex-direction: column;
|
|
85
|
-
gap: 10px;
|
|
86
|
-
|
|
87
|
-
/*
|
|
88
|
-
Explicit min-height to ensure submenu is never cut off.
|
|
89
|
-
Height is equal to 2 versions.
|
|
90
|
-
*/
|
|
91
|
-
min-height: 50px;
|
|
92
|
-
padding: 0 0 10px 20px;
|
|
93
|
-
margin-left: 10px;
|
|
94
|
-
scrollbar-width: none; /* Hide scrollbar for Firefox */
|
|
95
|
-
-ms-overflow-style: none; /* Hide scrollbar for IE and Edge */
|
|
96
|
-
|
|
97
|
-
&::before {
|
|
98
|
-
position: absolute;
|
|
99
|
-
top: -30px;
|
|
100
|
-
left: -2px;
|
|
101
|
-
width: 2px;
|
|
102
|
-
height: calc(100% + 35px);
|
|
103
|
-
content: "";
|
|
104
|
-
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 5'%3E%3Ccircle cx='1' cy='1' r='.5' fill='%236E6E6E'/%3E%3C/svg%3E");
|
|
105
|
-
background-repeat: repeat-y;
|
|
106
|
-
background-size: 5px;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
&.no-changes::before {
|
|
110
|
-
top: -15px;
|
|
111
|
-
height: calc(100% + 20px);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
& .empty-versions {
|
|
116
|
-
padding: 7px;
|
|
117
|
-
font-size: 11px;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/* Hide scrollbar for now */
|
|
121
|
-
& .versions::-webkit-scrollbar {
|
|
122
|
-
display: none;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
@media only screen and (width <= 900px) {
|
|
126
|
-
width: 100vw;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
svg {
|
|
131
|
-
@mixin svg-icon-size 18;
|
|
132
|
-
|
|
133
|
-
display: inline-block;
|
|
134
|
-
margin-right: 5px;
|
|
135
|
-
vertical-align: middle;
|
|
136
|
-
stroke: var(--knime-masala);
|
|
137
|
-
}
|
|
138
|
-
</style>
|