@milaboratories/uikit 2.2.60 → 2.2.62
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 +12 -0
- package/dist/pl-uikit.js +3869 -3798
- package/dist/pl-uikit.js.map +1 -1
- package/dist/pl-uikit.umd.cjs +6 -6
- package/dist/pl-uikit.umd.cjs.map +1 -1
- package/dist/src/components/PlFileDialog/Remote.vue.d.ts +1 -1
- package/dist/src/components/PlFileDialog/utils.test.d.ts +1 -0
- package/dist/src/components/PlLogView/PlLogView.vue.d.ts +8 -0
- package/dist/src/components/PlLogView/useLogHandle.d.ts +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/components/PlFileDialog/Local.vue +5 -5
- package/src/components/PlFileDialog/Remote.vue +5 -5
- package/src/components/PlFileDialog/utils.test.ts +51 -0
- package/src/components/PlFileDialog/utils.ts +27 -12
- package/src/components/PlLogView/PlLogView.vue +13 -2
- package/src/components/PlLogView/useLogHandle.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/uikit",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.62",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/pl-uikit.umd.js",
|
|
6
6
|
"module": "dist/pl-uikit.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@vueuse/core": "~12.4.0",
|
|
27
27
|
"jsdom": "^25.0.1",
|
|
28
28
|
"resize-observer-polyfill": "^1.5.1",
|
|
29
|
-
"@vitejs/plugin-vue": "^5.2.
|
|
29
|
+
"@vitejs/plugin-vue": "^5.2.3",
|
|
30
30
|
"tsc-alias": "^1.8.11",
|
|
31
31
|
"vitest": "^2.1.8",
|
|
32
32
|
"vite": "^5.4.11",
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"yarpm": "^1.2.0",
|
|
35
35
|
"svgo": "^3.3.2",
|
|
36
36
|
"@types/d3": "^7.4.3",
|
|
37
|
-
"@milaboratories/eslint-config": "^1.0.1",
|
|
38
37
|
"@milaboratories/helpers": "^1.6.11",
|
|
39
|
-
"@
|
|
38
|
+
"@milaboratories/eslint-config": "^1.0.4",
|
|
39
|
+
"@platforma-sdk/model": "^1.27.10"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"dev": "vite",
|
|
@@ -3,7 +3,7 @@ import style from './pl-file-dialog.module.scss';
|
|
|
3
3
|
import type { ImportedFiles } from '@/types';
|
|
4
4
|
import { PlIcon24 } from '../PlIcon24';
|
|
5
5
|
import { computed, reactive } from 'vue';
|
|
6
|
-
import type
|
|
6
|
+
import { getRawPlatformaInstance, type OpenDialogFilter } from '@platforma-sdk/model';
|
|
7
7
|
import { normalizeExtensions } from './utils';
|
|
8
8
|
|
|
9
9
|
const props = defineProps<{
|
|
@@ -19,10 +19,10 @@ const data = reactive({
|
|
|
19
19
|
const label = computed(() => (props.multi ? 'Drag & Drop files here or click to add' : 'Drag & Drop file here or click to add'));
|
|
20
20
|
|
|
21
21
|
const onDrop = async (ev: DragEvent) => {
|
|
22
|
-
const fileToImportHandle =
|
|
22
|
+
const fileToImportHandle = getRawPlatformaInstance()?.lsDriver?.fileToImportHandle;
|
|
23
23
|
|
|
24
24
|
if (!fileToImportHandle) {
|
|
25
|
-
return console.error('API
|
|
25
|
+
return console.error('API getPlatformaRawInstance().lsDriver.fileToImportHandle is not available');
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const extensions = normalizeExtensions(props.extensions);
|
|
@@ -54,7 +54,7 @@ const openNativeDialog = async () => {
|
|
|
54
54
|
: [];
|
|
55
55
|
|
|
56
56
|
if (props.multi) {
|
|
57
|
-
|
|
57
|
+
getRawPlatformaInstance()?.lsDriver
|
|
58
58
|
.showOpenMultipleFilesDialog({
|
|
59
59
|
title: 'Select files to import',
|
|
60
60
|
filters,
|
|
@@ -68,7 +68,7 @@ const openNativeDialog = async () => {
|
|
|
68
68
|
})
|
|
69
69
|
.catch((err) => (data.error = err));
|
|
70
70
|
} else {
|
|
71
|
-
|
|
71
|
+
getRawPlatformaInstance()?.lsDriver
|
|
72
72
|
.showOpenSingleFileDialog({
|
|
73
73
|
title: 'Select file to import',
|
|
74
74
|
filters,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { useEventListener } from '@/composition/useEventListener';
|
|
3
3
|
import type { ImportedFiles } from '@/types';
|
|
4
4
|
import { between, notEmpty, tapIf } from '@milaboratories/helpers';
|
|
5
|
-
import type
|
|
5
|
+
import { getRawPlatformaInstance, type StorageHandle } from '@platforma-sdk/model';
|
|
6
6
|
import { computed, onMounted, reactive, toRef, watch } from 'vue';
|
|
7
7
|
import { PlDropdown } from '../PlDropdown';
|
|
8
8
|
import { PlIcon16 } from '../PlIcon16';
|
|
@@ -58,7 +58,7 @@ const lookup = computed(() => {
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
const query = (storageHandle: StorageHandle, dirPath: string) => {
|
|
61
|
-
if (!
|
|
61
|
+
if (!getRawPlatformaInstance()) {
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -68,7 +68,7 @@ const query = (storageHandle: StorageHandle, dirPath: string) => {
|
|
|
68
68
|
|
|
69
69
|
data.currentLoadingPath = dirPath;
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
getRawPlatformaInstance().lsDriver
|
|
72
72
|
.listFiles(storageHandle, dirPath)
|
|
73
73
|
.then((res) => {
|
|
74
74
|
if (dirPath !== data.dirPath) {
|
|
@@ -186,11 +186,11 @@ const deselectAll = () => changeAll(false);
|
|
|
186
186
|
const loadAvailableStorages = () => {
|
|
187
187
|
resetData();
|
|
188
188
|
deselectAll();
|
|
189
|
-
if (!
|
|
189
|
+
if (!getRawPlatformaInstance()) {
|
|
190
190
|
console.warn('platforma API is not found');
|
|
191
191
|
return;
|
|
192
192
|
}
|
|
193
|
-
|
|
193
|
+
getRawPlatformaInstance().lsDriver
|
|
194
194
|
.getStorageList()
|
|
195
195
|
.then((storageEntries) => {
|
|
196
196
|
// local storage is always returned by the ML, so we need to remove it from remote dialog manually
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { getFilePathBreadcrumbs } from './utils';
|
|
3
|
+
|
|
4
|
+
describe('getFilePathBreadcrumbs', () => {
|
|
5
|
+
test.each([
|
|
6
|
+
{
|
|
7
|
+
name: 'root path "/"',
|
|
8
|
+
path: '/',
|
|
9
|
+
expected: [
|
|
10
|
+
{ index: 0, name: 'Root', path: '' },
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: 'empty path ""',
|
|
15
|
+
path: '',
|
|
16
|
+
expected: [
|
|
17
|
+
{ index: 0, name: 'Root', path: '' },
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'single-level path "/folder"',
|
|
22
|
+
path: '/folder',
|
|
23
|
+
expected: [
|
|
24
|
+
{ index: 0, name: 'Root', path: '' },
|
|
25
|
+
{ index: 1, name: 'folder', path: '/folder' },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'multi-level path "/folder/subfolder/file.txt"',
|
|
30
|
+
path: '/folder/subfolder/file.txt',
|
|
31
|
+
expected: [
|
|
32
|
+
{ index: 0, name: 'Root', path: '' },
|
|
33
|
+
{ index: 1, name: 'folder', path: '/folder' },
|
|
34
|
+
{ index: 2, name: 'subfolder', path: '/folder/subfolder' },
|
|
35
|
+
{ index: 3, name: 'file.txt', path: '/folder/subfolder/file.txt' },
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'path without leading slash "folder/file.txt"',
|
|
40
|
+
path: 'folder/file.txt',
|
|
41
|
+
expected: [
|
|
42
|
+
{ index: 0, name: 'Root', path: '' },
|
|
43
|
+
{ index: 1, name: 'folder', path: 'folder' },
|
|
44
|
+
{ index: 2, name: 'file.txt', path: 'folder/file.txt' },
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
])('should handle $name', ({ path, expected }) => {
|
|
48
|
+
const result = getFilePathBreadcrumbs(path);
|
|
49
|
+
expect(result).toEqual(expected);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -1,27 +1,42 @@
|
|
|
1
|
-
import { trimCharsLeft } from '@milaboratories/helpers';
|
|
1
|
+
import { trimChars, trimCharsLeft } from '@milaboratories/helpers';
|
|
2
2
|
import type { ImportFileHandle } from '@platforma-sdk/model';
|
|
3
3
|
|
|
4
4
|
export function normalizeExtensions(extensions: string[] | undefined) {
|
|
5
5
|
return extensions ? extensions.map((it) => '.' + trimCharsLeft(it, ['.'])) : undefined;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
// NOTE: works only with '/' separator on *nix systems.
|
|
8
9
|
export function getFilePathBreadcrumbs(filePath: string) {
|
|
9
|
-
|
|
10
|
+
// FIXME: separator probably should be got from ls driver from backend.
|
|
11
|
+
// or else this component won't work with remote storages on Windows.
|
|
12
|
+
const sep = '/';
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
// If file path starts with '/',
|
|
15
|
+
// the storage was set up with absolute paths,
|
|
16
|
+
// and we need to add the separator to the results.
|
|
17
|
+
const isAbsolute = filePath.startsWith(sep);
|
|
18
|
+
const chunks = trimChars(filePath, [sep]).split(sep);
|
|
19
|
+
|
|
20
|
+
const stack: { index: number; path: string; name: string }[] = [
|
|
21
|
+
{
|
|
22
|
+
index: 0,
|
|
23
|
+
name: 'Root',
|
|
24
|
+
path: '',
|
|
25
|
+
},
|
|
26
|
+
];
|
|
14
27
|
|
|
15
|
-
|
|
28
|
+
if (chunks.length === 1 && chunks[0] === '') {
|
|
29
|
+
return stack;
|
|
30
|
+
}
|
|
16
31
|
|
|
17
32
|
for (let i = 0; i < chunks.length; i++) {
|
|
33
|
+
const pathPrefix = isAbsolute ? sep : '';
|
|
34
|
+
const p = pathPrefix + chunks.slice(0, i + 1).join(sep);
|
|
35
|
+
|
|
18
36
|
stack.push({
|
|
19
|
-
index: i,
|
|
20
|
-
name:
|
|
21
|
-
path:
|
|
22
|
-
.slice(0, i + 1)
|
|
23
|
-
.filter((c) => c !== '')
|
|
24
|
-
.join('/'),
|
|
37
|
+
index: i + 1,
|
|
38
|
+
name: chunks[i],
|
|
39
|
+
path: p,
|
|
25
40
|
});
|
|
26
41
|
}
|
|
27
42
|
|
|
@@ -31,6 +31,10 @@ const props = defineProps<{
|
|
|
31
31
|
* String contents
|
|
32
32
|
*/
|
|
33
33
|
value?: string;
|
|
34
|
+
/**
|
|
35
|
+
* The content to copy (Note: it takes precedence over value property)
|
|
36
|
+
*/
|
|
37
|
+
valueToCopy?: string;
|
|
34
38
|
/**
|
|
35
39
|
* AnyLogHandle
|
|
36
40
|
*/
|
|
@@ -85,8 +89,15 @@ const onClickCopy = () => {
|
|
|
85
89
|
copyActive.value = false;
|
|
86
90
|
}, 1200);
|
|
87
91
|
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
let toCopy: string | undefined = undefined;
|
|
93
|
+
if (props.valueToCopy) {
|
|
94
|
+
toCopy = props.valueToCopy;
|
|
95
|
+
} else if (computedValue.value && typeof computedValue.value === 'string') {
|
|
96
|
+
toCopy = computedValue.value;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (toCopy !== undefined) {
|
|
100
|
+
navigator.clipboard.writeText(toCopy);
|
|
90
101
|
}
|
|
91
102
|
};
|
|
92
103
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { reactive, type Reactive, ref, watch } from 'vue';
|
|
2
2
|
import { useTimeoutPoll, whenever } from '@vueuse/core';
|
|
3
|
-
import type
|
|
3
|
+
import { getRawPlatformaInstance, type AnyLogHandle, type Platforma } from '@platforma-sdk/model';
|
|
4
4
|
|
|
5
5
|
type LogState = {
|
|
6
6
|
logHandle: AnyLogHandle;
|
|
@@ -32,7 +32,7 @@ export function useLogHandle(
|
|
|
32
32
|
|
|
33
33
|
if (currentLogState === undefined) return;
|
|
34
34
|
|
|
35
|
-
const platforma = props.mockPlatforma ??
|
|
35
|
+
const platforma = props.mockPlatforma ?? getRawPlatformaInstance();
|
|
36
36
|
|
|
37
37
|
if (!platforma) {
|
|
38
38
|
console.warn('Platforma API is not available');
|