diff --git a/server/bundles/io.cloudbeaver.server/schema/schema.graphqls b/server/bundles/io.cloudbeaver.server/schema/schema.graphqls
index c71e8d3945..a3dee4ffa5 100644
--- a/server/bundles/io.cloudbeaver.server/schema/schema.graphqls
+++ b/server/bundles/io.cloudbeaver.server/schema/schema.graphqls
@@ -3,13 +3,9 @@ scalar Object
# Date/Time
scalar DateTime
-type Query {
+type Query
-}
-
-type Mutation {
-
-}
+type Mutation
schema {
query: Query
diff --git a/webapp/packages/basic-connection-plugin/src/ConnectionDialog/DBSourceSelector/DBSourceItem.tsx b/webapp/packages/basic-connection-plugin/src/ConnectionDialog/DBSourceSelector/DBSourceItem.tsx
index 3ff3bc57fc..ea4e6d5f58 100644
--- a/webapp/packages/basic-connection-plugin/src/ConnectionDialog/DBSourceSelector/DBSourceItem.tsx
+++ b/webapp/packages/basic-connection-plugin/src/ConnectionDialog/DBSourceSelector/DBSourceItem.tsx
@@ -7,61 +7,11 @@
*/
import { observer } from 'mobx-react';
-import styled, { css } from 'reshadow';
+import { useCallback } from 'react';
import { DBDriver, DBSource } from '@dbeaver/core/app';
-import { StaticImage } from '@dbeaver/core/blocks';
-import { useStyles, composes } from '@dbeaver/core/theming';
+import { ListItem } from '@dbeaver/core/blocks';
-const styles = composes(
- css`
- db-source-name {
- composes: theme-border-color-secondary from global;
- }
- `,
- css`
- StaticImage {
- box-sizing: border-box;
- width: 24px;
- }
- db-source {
- position: relative;
- cursor: pointer;
- display: flex;
- box-sizing: border-box;
- align-items: center;
- padding: 8px 12px;
- }
- db-source-icon {
- display: flex;
- align-items: center;
- box-sizing: border-box;
- padding: 0 12px;
- }
- db-source-name {
- composes: theme-typography--body1 from global;
- box-sizing: border-box;
- font-weight: 500;
- min-width: 250px;
- padding: 0 24px 0 12px;
- border-right: 1px solid;
-
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- db-source-description {
- composes: theme-typography--body2 from global;
- box-sizing: border-box;
- max-width: 460px;
- padding: 0 12px 0 24px;
-
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-`
-);
type DBSourceItemProps = {
dbSource: DBSource;
@@ -70,12 +20,7 @@ type DBSourceItemProps = {
}
export const DBSourceItem = observer(function DBSourceItem({ dbSource, dbDriver, onSelect }: DBSourceItemProps) {
+ const select = useCallback(() => onSelect(dbSource.id), [dbSource]);
- return styled(useStyles(styles))(
- onSelect(dbSource.id)}>
-
- {dbSource.name}
- {dbSource.description}
-
- );
+ return ;
});
diff --git a/webapp/packages/basic-connection-plugin/src/ConnectionDialog/DBSourceSelector/DBSourceSelector.tsx b/webapp/packages/basic-connection-plugin/src/ConnectionDialog/DBSourceSelector/DBSourceSelector.tsx
index 4578a3cc32..95e8d565e4 100644
--- a/webapp/packages/basic-connection-plugin/src/ConnectionDialog/DBSourceSelector/DBSourceSelector.tsx
+++ b/webapp/packages/basic-connection-plugin/src/ConnectionDialog/DBSourceSelector/DBSourceSelector.tsx
@@ -8,52 +8,12 @@
import { observer } from 'mobx-react';
import { useState, useMemo } from 'react';
-import styled, { css, use } from 'reshadow';
import { DBDriver, DBSource } from '@dbeaver/core/app';
-import { StaticImage } from '@dbeaver/core/blocks';
-import { useTranslate } from '@dbeaver/core/localization';
-import { useStyles, composes } from '@dbeaver/core/theming';
+import { ItemList, ItemListSearch } from '@dbeaver/core/blocks';
import { DBSourceItem } from './DBSourceItem';
-const styles = composes(
- css`
- list-item {
- composes: theme-ripple theme-background-surface theme-border-color-secondary from global;
- }
- list-search {
- composes: theme-background-secondary from global;
- }
- `,
- css`
- list {
- box-sizing: border-box;
- border-collapse: collapse;
- }
- list-item {
- border-bottom: 1px solid;
- }
- list-search {
- position: sticky;
- top: 0;
- padding: 8px 24px;
- z-index: 1;
-
- & input {
- padding: 4px 24px;
- padding-left: 32px;
- }
-
- & StaticImage {
- position: absolute;
- top: 15px;
- left: 32px;
- }
- }
- `
-);
-
type DBSourceSelectorProps = {
dbSources: DBSource[];
dbDrivers: Map;
@@ -68,7 +28,6 @@ export const DBSourceSelector = observer(function DBSourceSelector({
onSelect,
}: DBSourceSelectorProps) {
const [search, setSearch] = useState('');
- const translate = useTranslate();
const filteredDBSources = useMemo(() => {
if (!search) {
return dbSources;
@@ -76,26 +35,17 @@ export const DBSourceSelector = observer(function DBSourceSelector({
return dbSources.filter(source => source.name.toUpperCase().includes(search.toUpperCase()));
}, [search, dbSources]);
- return styled(useStyles(styles))(
-
-
-
- setSearch(event.target.value)}
- {...use({ mod: 'surface' })}
- />
-
+ return (
+
+
{filteredDBSources.map(dbSource => (
-
-
-
+
))}
-
+
);
});
diff --git a/webapp/packages/core/assets/locales/en.js b/webapp/packages/core/assets/locales/en.js
index 8a0b9f813b..ba9bf6716e 100644
--- a/webapp/packages/core/assets/locales/en.js
+++ b/webapp/packages/core/assets/locales/en.js
@@ -17,9 +17,6 @@ module.exports = {
customConnection_connectionType_url: 'URL',
customConnection_options: 'Options',
customConnection_properties: 'Driver Properties',
- customConnection_properties_name: 'Name',
- customConnection_properties_value: 'Value',
- customConnection_properties_add: 'Add',
customConnection_custom_host: 'Host',
customConnection_custom_obligatory: '(obligatory)',
customConnection_custom_port: 'Port',
@@ -31,6 +28,11 @@ module.exports = {
customConnection_test: 'Test Connection',
customConnection_create: 'Create',
+ data_transfer_dialog_title: 'Export data',
+ data_transfer_dialog_export: 'Export',
+ data_transfer_dialog_exporting_object: 'Exporting:',
+ data_transfer_dialog_configuration_title: 'Export configuration',
+
ui_stepper_back: 'Back',
ui_processing_loading: 'Loading...',
ui_processing_cancel: 'Cancel',
@@ -39,6 +41,9 @@ module.exports = {
ui_errors_details: 'Details',
ui_search: 'Search...',
ui_data_saving_error: 'Error when saving changes',
+ block_properties_table_name: 'Name',
+ block_properties_table_value: 'Value',
+ block_properties_table_add: 'Add',
app_root_session_expired_title: 'Session expired',
app_root_session_expired_message: 'Session has been expired. Do you want to reload?',
diff --git a/webapp/packages/core/assets/locales/ru.js b/webapp/packages/core/assets/locales/ru.js
index 3471459063..f293429a94 100644
--- a/webapp/packages/core/assets/locales/ru.js
+++ b/webapp/packages/core/assets/locales/ru.js
@@ -16,9 +16,6 @@ module.exports = {
customConnection_connectionType_url: 'URL',
customConnection_options: 'Подключение',
customConnection_properties: 'Параметры драйвера',
- customConnection_properties_name: 'Название',
- customConnection_properties_value: 'Значение',
- customConnection_properties_add: 'Добавить',
customConnection_custom_host: 'Хост',
customConnection_custom_obligatory: '(обязательное)',
customConnection_custom_port: 'Порт',
@@ -30,14 +27,22 @@ module.exports = {
customConnection_test: 'Проверить',
customConnection_create: 'Создать',
+ data_transfer_dialog_title: 'Экспорт данных',
+ data_transfer_dialog_export: 'Экспортировать',
+ data_transfer_dialog_exporting_object: 'Экспортировать:',
+ data_transfer_dialog_configuration_title: 'Настройка экспорта',
+
ui_stepper_back: 'Назад',
ui_processing_loading: 'Загрузка...',
- ui_processing_cancel: 'Отменить...',
+ ui_processing_cancel: 'Отменить',
ui_processing_retry: 'Повторить',
ui_error_message: 'Ошибка:',
ui_errors_details: 'Информация',
ui_search: 'Поиск...',
ui_data_saving_error: 'Ошибка при сохранении изменений',
+ block_properties_name: 'Название',
+ block_properties_value: 'Значение',
+ block_properties_add: 'Добавить',
app_root_session_expired_title: 'Сесстия истекла',
app_root_session_expired_message: 'Сессия истекла. Хотите перезагрузить страницу?',
diff --git a/webapp/packages/core/codegen.yml b/webapp/packages/core/codegen.yml
index 8f32c0907f..e97ca32468 100644
--- a/webapp/packages/core/codegen.yml
+++ b/webapp/packages/core/codegen.yml
@@ -1,8 +1,10 @@
schema:
- ../../../server/bundles/io.cloudbeaver.server/schema/schema.graphqls
- - ../../../server/bundles/io.cloudbeaver.server/schema/service.sql.graphqls
+ - ../../../server/bundles/io.cloudbeaver.server/schema/service.core.graphqls
- ../../../server/bundles/io.cloudbeaver.server/schema/service.navigator.graphqls
+ - ../../../server/bundles/io.cloudbeaver.server/schema/service.sql.graphqls
- ../../../server/bundles/io.cloudbeaver.service.metadata/schema/service.metadata.graphqls
+ - ../../../server/bundles/io.cloudbeaver.service.data.transfer/schema/service.data.transfer.graphqls
documents:
- ./src/**/*.gql
generates:
diff --git a/webapp/packages/core/src/app/shared/ConnectionsManager/ConnectionsManagerService.ts b/webapp/packages/core/src/app/shared/ConnectionsManager/ConnectionsManagerService.ts
index 1eaa86765a..2340cc4b53 100644
--- a/webapp/packages/core/src/app/shared/ConnectionsManager/ConnectionsManagerService.ts
+++ b/webapp/packages/core/src/app/shared/ConnectionsManager/ConnectionsManagerService.ts
@@ -42,8 +42,8 @@ export type ObjectContainer = Pick = new Map();
- dbDrivers = new CachedResource(new Map(), this.refreshDriversAsync.bind(this));
- connectionObjectContainers = new CachedResource(new Map(), this.refreshObjectContainersAsync.bind(this));
+ readonly dbDrivers = new CachedResource(new Map(), this.refreshDriversAsync.bind(this));
+ readonly connectionObjectContainers = new CachedResource(new Map(), this.refreshObjectContainersAsync.bind(this));
@computed get connections(): Connection[] {
return Array.from(this.connectionsMap.values());
diff --git a/webapp/packages/core/src/blocks/IconOrImage.tsx b/webapp/packages/core/src/blocks/IconOrImage.tsx
index 79700bb863..d54738cce6 100644
--- a/webapp/packages/core/src/blocks/IconOrImage.tsx
+++ b/webapp/packages/core/src/blocks/IconOrImage.tsx
@@ -14,9 +14,10 @@ import { StaticImage } from './StaticImage';
export type IconOrImageProps = {
icon: string;
className?: string;
+ viewBox?: string;
};
-export const IconOrImage = function IconOrImage({ icon, className }: IconOrImageProps) {
+export const IconOrImage = function IconOrImage({ icon, className, viewBox }: IconOrImageProps) {
const isStaticIcon = useMemo(
() => icon && icon.startsWith('platform:'),
@@ -27,5 +28,5 @@ export const IconOrImage = function IconOrImage({ icon, className }: IconOrImage
return ;
}
- return ;
+ return ;
};
diff --git a/webapp/packages/core/src/blocks/ItemList/ItemList.tsx b/webapp/packages/core/src/blocks/ItemList/ItemList.tsx
new file mode 100644
index 0000000000..88e02a2c02
--- /dev/null
+++ b/webapp/packages/core/src/blocks/ItemList/ItemList.tsx
@@ -0,0 +1,31 @@
+/*
+ * cloudbeaver - Cloud Database Manager
+ * Copyright (C) 2020 DBeaver Corp and others
+ *
+ * Licensed under the Apache License, Version 2.0.
+ * you may not use this file except in compliance with the License.
+ */
+
+import styled from 'reshadow';
+
+import { useStyles, Style } from '@dbeaver/core/theming';
+
+import { Styles, ITEM_LIST_STYLES_ARRAY } from './styles';
+
+type ItemListProps = React.PropsWithChildren<{
+ className?: string;
+ styles?: Style[];
+}>
+
+export function ItemList({
+ children, className, styles,
+}: ItemListProps) {
+
+ return styled(useStyles(...(styles || ITEM_LIST_STYLES_ARRAY)))(
+
+
+ {children}
+
+
+ );
+}
diff --git a/webapp/packages/core/src/blocks/ItemList/ItemListSearch.tsx b/webapp/packages/core/src/blocks/ItemList/ItemListSearch.tsx
new file mode 100644
index 0000000000..6c6b08f358
--- /dev/null
+++ b/webapp/packages/core/src/blocks/ItemList/ItemListSearch.tsx
@@ -0,0 +1,48 @@
+/*
+ * cloudbeaver - Cloud Database Manager
+ * Copyright (C) 2020 DBeaver Corp and others
+ *
+ * Licensed under the Apache License, Version 2.0.
+ * you may not use this file except in compliance with the License.
+ */
+
+import {
+ useState, useCallback, useContext
+} from 'react';
+import styled, { use } from 'reshadow';
+
+import { StaticImage } from '@dbeaver/core/blocks';
+import { useTranslate } from '@dbeaver/core/localization';
+import { useStyles } from '@dbeaver/core/theming';
+
+import { Styles } from './styles';
+
+type ItemListProps = React.PropsWithChildren<{
+ onSearch?(value: string): void;
+ className?: string;
+}>
+
+export function ItemListSearch({ onSearch, className }: ItemListProps) {
+ const styles = useContext(Styles);
+ const [search, setSearch] = useState('');
+ const translate = useTranslate();
+ const searchHandler = useCallback((event: React.ChangeEvent) => {
+ setSearch(event.target.value);
+ if (onSearch) {
+ onSearch(event.target.value);
+ }
+ }, [onSearch]);
+
+ return styled(useStyles(...(styles || [])))(
+
+
+
+
+ );
+}
diff --git a/webapp/packages/core/src/blocks/ItemList/ListItem.tsx b/webapp/packages/core/src/blocks/ItemList/ListItem.tsx
new file mode 100644
index 0000000000..25c7a1a22a
--- /dev/null
+++ b/webapp/packages/core/src/blocks/ItemList/ListItem.tsx
@@ -0,0 +1,41 @@
+/*
+ * cloudbeaver - Cloud Database Manager
+ * Copyright (C) 2020 DBeaver Corp and others
+ *
+ * Licensed under the Apache License, Version 2.0.
+ * you may not use this file except in compliance with the License.
+ */
+
+import { useContext } from 'react';
+import styled from 'reshadow';
+
+import { StaticImage } from '@dbeaver/core/blocks';
+import { useStyles } from '@dbeaver/core/theming';
+
+import { Styles } from './styles';
+
+type ListItemProps = {
+ name?: string;
+ icon?: string;
+ description?: string;
+ onClick(): void;
+ className?: string;
+}
+
+export function ListItem({
+ name,
+ icon,
+ description,
+ onClick,
+ className,
+}: ListItemProps) {
+ const styles = useContext(Styles);
+
+ return styled(useStyles(...styles))(
+
+
+ {name}
+ {description}
+
+ );
+}
diff --git a/webapp/packages/core/src/blocks/ItemList/index.ts b/webapp/packages/core/src/blocks/ItemList/index.ts
new file mode 100644
index 0000000000..ce304189a8
--- /dev/null
+++ b/webapp/packages/core/src/blocks/ItemList/index.ts
@@ -0,0 +1,4 @@
+export * from './ItemList';
+export * from './ItemListSearch';
+export * from './ListItem';
+export { ITEM_LIST_STYLES } from './styles';
diff --git a/webapp/packages/core/src/blocks/ItemList/styles.ts b/webapp/packages/core/src/blocks/ItemList/styles.ts
new file mode 100644
index 0000000000..367b516f8c
--- /dev/null
+++ b/webapp/packages/core/src/blocks/ItemList/styles.ts
@@ -0,0 +1,98 @@
+/*
+ * cloudbeaver - Cloud Database Manager
+ * Copyright (C) 2020 DBeaver Corp and others
+ *
+ * Licensed under the Apache License, Version 2.0.
+ * you may not use this file except in compliance with the License.
+ */
+
+import { createContext } from 'react';
+import { css } from 'reshadow';
+
+import { composes, Style } from '@dbeaver/core/theming';
+
+export const ITEM_LIST_STYLES = composes(
+ css`
+ list-item {
+ composes: theme-ripple theme-background-surface theme-border-color-secondary from global;
+ }
+ list-search {
+ composes: theme-background-secondary theme-text-on-secondary from global;
+ }
+ list-item-name {
+ composes: theme-border-color-secondary from global;
+ }
+ `,
+ css`
+ item-list {
+ box-sizing: border-box;
+ border-collapse: collapse;
+ z-index: 0;
+ }
+ list-search {
+ position: sticky;
+ top: 0;
+ padding: 8px 24px;
+ z-index: 1;
+
+ & input {
+ padding: 4px 24px;
+ padding-left: 32px;
+ }
+
+ & StaticImage {
+ position: absolute;
+ top: 15px;
+ left: 32px;
+ }
+ }
+ list-item {
+ border-bottom: 1px solid;
+ }
+ list-item {
+ position: relative;
+ cursor: pointer;
+ display: flex;
+ box-sizing: border-box;
+ align-items: center;
+ padding: 8px 12px;
+ }
+ list-item-icon {
+ display: flex;
+ align-items: center;
+ box-sizing: border-box;
+ padding: 0 12px;
+
+ & StaticImage {
+ box-sizing: border-box;
+ width: 24px;
+ }
+ }
+ list-item-name {
+ composes: theme-typography--body1 from global;
+ box-sizing: border-box;
+ font-weight: 500;
+ min-width: 250px;
+ padding: 0 24px 0 12px;
+ border-right: 1px solid;
+
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ list-item-description {
+ composes: theme-typography--body2 from global;
+ box-sizing: border-box;
+ max-width: 460px;
+ padding: 0 12px 0 24px;
+
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ `
+);
+
+export const ITEM_LIST_STYLES_ARRAY = [ITEM_LIST_STYLES];
+
+export const Styles = createContext