From b553a81d47f5fcdab281a71acf905d53e803c8cc Mon Sep 17 00:00:00 2001 From: "SPRINX0\\prochazka" Date: Wed, 21 May 2025 14:48:28 +0200 Subject: [PATCH] load cloud folders --- packages/api/.env | 1 + packages/api/src/controllers/cloud.js | 61 +++++++++++++++++- packages/api/src/utility/cloudIntf.js | 36 ++++++++++- packages/web/src/appobj/AppObjectGroup.svelte | 3 +- packages/web/src/appobj/AppObjectList.svelte | 2 + packages/web/src/stores.ts | 9 ++- packages/web/src/utility/metadataLoaders.ts | 12 ++++ .../web/src/widgets/CloudItemsWidget.svelte | 64 +++++++++++++++---- 8 files changed, 170 insertions(+), 18 deletions(-) diff --git a/packages/api/.env b/packages/api/.env index 790defd5d..e36c8d394 100644 --- a/packages/api/.env +++ b/packages/api/.env @@ -1,5 +1,6 @@ DEVMODE=1 SHELL_SCRIPTING=1 +LOCAL_DBGATE_CLOUD=1 # LOCAL_DBGATE_IDENTITY=1 # CLOUD_UPGRADE_FILE=c:\test\upg\upgrade.zip diff --git a/packages/api/src/controllers/cloud.js b/packages/api/src/controllers/cloud.js index df8632247..7541ef023 100644 --- a/packages/api/src/controllers/cloud.js +++ b/packages/api/src/controllers/cloud.js @@ -1,4 +1,11 @@ -const { getPublicCloudFiles, getPublicFileData, refreshPublicFiles } = require('../utility/cloudIntf'); +const { + getPublicCloudFiles, + getPublicFileData, + refreshPublicFiles, + callCloudApiGet, + callCloudApiPost, +} = require('../utility/cloudIntf'); +const socket = require('../utility/socket'); module.exports = { publicFiles_meta: true, @@ -20,4 +27,56 @@ module.exports = { status: 'ok', }; }, + + contentList_meta: true, + async contentList() { + const resp = callCloudApiGet('content-list'); + console.log('contentList', resp); + return resp; + }, + + getContent_meta: true, + async getContent({ folid, cntid }) { + const resp = await callCloudApiGet(`content/${folid}/${cntid}`); + return resp; + }, + + putContent_meta: true, + async putContent({ folid, cntid, content, name, type }) { + await callCloudApiPost(`put-content`, { folid, cntid, content, name, type }); + socket.emitChanged('cloud-content-changed'); + return { + status: 'ok', + }; + }, + + createFolder_meta: true, + async createFolder({ name }) { + await callCloudApiPost(`folders/create`, { name }); + socket.emitChanged('cloud-content-changed'); + return { + status: 'ok', + }; + }, + + grantFolder_meta: true, + async grantFolder({ inviteLink }) { + const m = inviteLink.match(/^dbgate\:\/\/folder\/v1\/([a-zA-Z]+)\?mode=(read|write|admin)$/); + const invite = m[1]; + const mode = m[2]; + + await callCloudApiPost(`folders/grant/${mode}`, { invite }); + socket.emitChanged('cloud-content-changed'); + return { + status: 'ok', + }; + }, + + refreshContent_meta: true, + async refreshContent() { + socket.emitChanged('cloud-content-changed'); + return { + status: 'ok', + }; + }, }; diff --git a/packages/api/src/utility/cloudIntf.js b/packages/api/src/utility/cloudIntf.js index 4a3bd06d4..4398c20c5 100644 --- a/packages/api/src/utility/cloudIntf.js +++ b/packages/api/src/utility/cloudIntf.js @@ -22,7 +22,7 @@ const DBGATE_IDENTITY_URL = process.env.LOCAL_DBGATE_IDENTITY : 'https://identity.dbgate.io'; const DBGATE_CLOUD_URL = process.env.LOCAL_DBGATE_CLOUD - ? 'http://localhost:3109' + ? 'http://localhost:3110' : process.env.DEVWEB || process.env.DEVMODE ? 'https://cloud.dbgate.udolni.net' : 'https://cloud.dbgate.io'; @@ -130,7 +130,7 @@ async function getCloudSigninHeaders() { 'x-cloud-login': value, }; } - return {}; + return null; } async function updateCloudFiles() { @@ -209,6 +209,36 @@ async function refreshPublicFiles() { } } +async function callCloudApiGet(endpoint) { + const signinHeaders = await getCloudSigninHeaders(); + if (!signinHeaders) { + return null; + } + + const resp = await axios.default.get(`${DBGATE_CLOUD_URL}/${endpoint}`, { + headers: { + ...getLicenseHttpHeaders(), + ...signinHeaders, + }, + }); + return resp.data; +} + +async function callCloudApiPost(endpoint, body) { + const signinHeaders = await getCloudSigninHeaders(); + if (!signinHeaders) { + return null; + } + + const resp = await axios.default.post(`${DBGATE_CLOUD_URL}/${endpoint}`, body, { + headers: { + ...getLicenseHttpHeaders(), + ...signinHeaders, + }, + }); + return resp.data; +} + module.exports = { createDbGateIdentitySession, startCloudTokenChecking, @@ -216,4 +246,6 @@ module.exports = { getPublicCloudFiles, getPublicFileData, refreshPublicFiles, + callCloudApiGet, + callCloudApiPost, }; diff --git a/packages/web/src/appobj/AppObjectGroup.svelte b/packages/web/src/appobj/AppObjectGroup.svelte index 3cd425706..cdcc4b78c 100644 --- a/packages/web/src/appobj/AppObjectGroup.svelte +++ b/packages/web/src/appobj/AppObjectGroup.svelte @@ -12,6 +12,7 @@ export let groupFunc; export let items; export let groupIconFunc = plusExpandIcon; + export let mapGroupTitle = undefined; export let module; export let checkedObjectsStore = null; export let disableContextMenu = false; @@ -63,7 +64,7 @@ - {group} + {mapGroupTitle ? mapGroupTitle(group) : group} {items && `(${countText})`} diff --git a/packages/web/src/appobj/AppObjectList.svelte b/packages/web/src/appobj/AppObjectList.svelte index cbf6d1c9e..ad6c2395b 100644 --- a/packages/web/src/appobj/AppObjectList.svelte +++ b/packages/web/src/appobj/AppObjectList.svelte @@ -26,6 +26,7 @@ export let groupIconFunc = plusExpandIcon; export let groupFunc = undefined; + export let mapGroupTitle = undefined; export let onDropOnGroup = undefined; export let emptyGroupNames = []; export let isExpandedBySearch = false; @@ -127,6 +128,7 @@ {subItemsComponent} {checkedObjectsStore} {groupFunc} + {mapGroupTitle} {disableContextMenu} {filter} {passProps} diff --git a/packages/web/src/stores.ts b/packages/web/src/stores.ts index 60f4e1465..c0857d36e 100644 --- a/packages/web/src/stores.ts +++ b/packages/web/src/stores.ts @@ -182,9 +182,12 @@ export const focusedConnectionOrDatabase = writable<{ conid: string; database?: export const focusedTreeDbKey = writable<{ key: string; root: string; type: string; text: string }>(null); -export const cloudSigninToken = getElectron() - ? writableSettingsValue(null, 'cloudSigninToken') - : writableWithStorage(null, 'cloudSigninToken'); +export const cloudSigninToken = writableSettingsValue(null, 'cloudSigninToken'); +export const cloudEncryptKeysByFolder = writableSettingsValue({}, 'cloudEncryptKeysByFolder'); + +// export const cloudSigninToken = getElectron() +// ? writableSettingsValue(null, 'cloudSigninToken') +// : writableWithStorage(null, 'cloudSigninToken'); export const DEFAULT_OBJECT_SEARCH_SETTINGS = { pureName: true, diff --git a/packages/web/src/utility/metadataLoaders.ts b/packages/web/src/utility/metadataLoaders.ts index fd3fd2a21..d334efc08 100644 --- a/packages/web/src/utility/metadataLoaders.ts +++ b/packages/web/src/utility/metadataLoaders.ts @@ -171,6 +171,11 @@ const publicCloudFilesLoader = () => ({ params: {}, reloadTrigger: { key: `public-cloud-changed` }, }); +const cloudContentListLoader = () => ({ + url: 'cloud/content-list', + params: {}, + reloadTrigger: { key: `cloud-content-changed` }, +}); async function getCore(loader, args) { const { url, params, reloadTrigger, transform, onLoaded, errorValue } = loader(args); @@ -469,3 +474,10 @@ export function getPublicCloudFiles(args) { export function usePublicCloudFiles(args = {}) { return useCore(publicCloudFilesLoader, args); } + +export function getCloudContentList(args) { + return getCore(cloudContentListLoader, args); +} +export function useCloudContentList(args = {}) { + return useCore(cloudContentListLoader, args); +} diff --git a/packages/web/src/widgets/CloudItemsWidget.svelte b/packages/web/src/widgets/CloudItemsWidget.svelte index 1c848a3b3..439a0376c 100644 --- a/packages/web/src/widgets/CloudItemsWidget.svelte +++ b/packages/web/src/widgets/CloudItemsWidget.svelte @@ -6,7 +6,7 @@ import AppObjectList from '../appobj/AppObjectList.svelte'; import * as cloudFileAppObject from '../appobj/CloudFileAppObject.svelte'; - import { usePublicCloudFiles } from '../utility/metadataLoaders'; + import { useCloudContentList, usePublicCloudFiles } from '../utility/metadataLoaders'; import { _t } from '../translations'; import WidgetsInnerContainer from './WidgetsInnerContainer.svelte'; @@ -17,27 +17,69 @@ import FontIcon from '../icons/FontIcon.svelte'; import { apiCall } from '../utility/api'; import { cloudSigninToken } from '../stores'; + import _ from 'lodash'; - let filter = ''; + let publicFilter = ''; + let cloudFilter = ''; $: publicFiles = usePublicCloudFiles(); + $: cloudContentList = useCloudContentList(); + + $: emptyCloudContent = ($cloudContentList || []).filter(x => !x.items?.length).map(x => x.folid); + $: cloudContentFlat = ($cloudContentList || []).flatMap(fld => fld.items ?? []).map(x => x.folid); + $: contentGroupTitleMap = _.fromPairs(($cloudContentList || []).map(x => [x.folid, x.name])); async function handleRefreshPublic() { await apiCall('cloud/refresh-public-files'); } + + async function handleRefreshContent() { + await apiCall('cloud/refresh-content'); + } - - XXX - - - + - - - + + + + + + + + data.folid} + mapGroupTitle={folid => contentGroupTitleMap[folid]} + filter={publicFilter} + /> + + + + + + + + + @@ -46,7 +88,7 @@ list={$publicFiles || []} module={cloudFileAppObject} groupFunc={data => data.folder || undefined} - {filter} + filter={publicFilter} />