@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.
Files changed (28) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/package.json +4 -4
  3. package/src/analytics/analytics.ts +39 -13
  4. package/src/analytics/schema/cloudhome-event-functions.ts +245 -0
  5. package/src/analytics/schema/code-generator.js +17 -8
  6. package/src/analytics/schema/{event-functions.ts → editor-event-functions.ts} +7 -9
  7. package/src/analytics/schema/schema.d.ts +133 -7
  8. package/src/analytics/schema/schema.json +833 -157
  9. package/src/analytics/types.ts +4 -1
  10. package/src/httpClient/constants.ts +1 -0
  11. package/src/{common/ofetchClient.ts → httpClient/createHttpClient.ts} +6 -5
  12. package/src/httpClient/index.ts +2 -0
  13. package/src/index.ts +1 -0
  14. package/src/useDownloadArtifact/useDownloadArtifact.ts +2 -2
  15. package/src/useFileUpload/useFileUpload.ts +2 -2
  16. package/src/common/constants.ts +0 -1
  17. package/src/components/versions/components/CreateVersionForm.vue +0 -155
  18. package/src/components/versions/components/CurrentState.vue +0 -258
  19. package/src/components/versions/components/LabelList.vue +0 -253
  20. package/src/components/versions/components/ManageVersions.vue +0 -191
  21. package/src/components/versions/components/NoVersionItem.vue +0 -23
  22. package/src/components/versions/components/VersionHistory.vue +0 -138
  23. package/src/components/versions/components/VersionItem.vue +0 -278
  24. package/src/components/versions/components/VersionLimitInfo.vue +0 -37
  25. package/src/components/versions/composables/useVersionsApi.ts +0 -254
  26. package/src/components/versions/constants.ts +0 -3
  27. package/src/components/versions/index.ts +0 -7
  28. 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="&nbsp; Load all &nbsp;"
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>