Add loading button in UI

This commit is contained in:
Gabriel Dutra
2020-07-06 16:53:48 -03:00
parent 9c0450c84e
commit c0e4dfb966
4 changed files with 84 additions and 14 deletions

View File

@@ -2,6 +2,8 @@ import React, { useState, useMemo, useEffect, useCallback } from "react";
import { slice, without, filter, includes } from "lodash";
import PropTypes from "prop-types";
import { useDebouncedCallback } from "use-debounce";
import Button from "antd/lib/button";
import Icon from "antd/lib/icon";
import Input from "antd/lib/input";
import Select from "antd/lib/select";
import { SchemaList, applyFilterOnSchema } from "@/components/queries/SchemaBrowser";
@@ -32,6 +34,8 @@ export default function DatabricksSchemaBrowser({
loadingSchema,
currentDatabaseName,
setCurrentDatabase,
refreshSchema,
refreshingSchema,
} = useDatabricksSchema(dataSource, options, onOptionsUpdate);
const [filterString, setFilterString] = useState("");
const [databaseFilterString, setDatabaseFilterString] = useState("");
@@ -118,7 +122,7 @@ export default function DatabricksSchemaBrowser({
}
/>
</div>
<div className="schema-list-wrapper">
<div className="schema-list-wrapper" data-refreshing={refreshingSchema || null}>
<SchemaList
loading={loadingDatabases || loadingSchema}
schema={filteredSchema}
@@ -126,6 +130,13 @@ export default function DatabricksSchemaBrowser({
onTableExpand={toggleTable}
onItemSelect={onItemSelect}
/>
{!(loadingSchema || loadingDatabases) && (
<div className="load-button">
<Button type="link" onClick={refreshSchema}>
<Icon type="sync" spin={refreshingSchema} />
</Button>
</div>
)}
</div>
</div>
);

View File

@@ -32,11 +32,43 @@
}
.schema-list-wrapper {
position: relative;
height: 100%;
border: 1px solid #eaeaea;
border-top: 0;
border-radius: 0 0 4px 4px;
margin-bottom: 20px;
.schema-browser {
.table-name,
.table-open {
padding-right: 57px;
.copy-to-editor {
right: 25px;
}
}
}
.load-button {
opacity: 0;
position: absolute;
top: 0;
right: 0;
transition: opacity 0.2s ease-in-out;
.ant-btn {
color: #595959;
padding: 0 10px;
}
}
&:hover,
&[data-refreshing] {
.load-button {
opacity: 1;
}
}
}
}

View File

@@ -3,25 +3,25 @@ import { useEffect, useState, useMemo, useCallback, useRef } from "react";
import notification from "@/services/notification";
import DatabricksDataSource from "@/services/databricks-data-source";
function getDatabases(dataSource) {
function getDatabases(dataSource, refresh = false) {
if (!dataSource) {
return Promise.resolve([]);
}
return DatabricksDataSource.getDatabases(dataSource).catch(() => {
return DatabricksDataSource.getDatabases(dataSource, refresh).catch(() => {
notification.error("Failed to load Database list", "Please try again later.");
return Promise.resolve([]);
});
}
function getSchema(dataSource, databaseName) {
function getSchema(dataSource, databaseName, refresh = false) {
if (!dataSource || !databaseName) {
return Promise.resolve([]);
}
return DatabricksDataSource.getDatabaseTables(dataSource, databaseName).catch(() => {
return DatabricksDataSource.getDatabaseTables(dataSource, databaseName, refresh).catch(() => {
notification.error("Failed to load Schema", "Please try again later.");
return Promise.resolve([]);
return Promise.reject();
});
}
@@ -31,9 +31,21 @@ export default function useDatabricksSchema(dataSource, options = null, onOption
const [currentDatabaseName, setCurrentDatabaseName] = useState();
const [schemas, setSchemas] = useState({});
const [loadingSchema, setLoadingSchema] = useState(false);
const [refreshingSchema, setRefreshingSchema] = useState(false);
const schema = useMemo(() => get(schemas, currentDatabaseName, []), [schemas, currentDatabaseName]);
const refreshSchema = useCallback(() => {
if (!refreshingSchema) {
setRefreshingSchema(true);
getSchema(dataSource, currentDatabaseName, true)
.then(schema => {
setSchemas(currentSchemas => ({ ...currentSchemas, [currentDatabaseName]: schema }));
})
.finally(() => setRefreshingSchema(false));
}
}, [dataSource, currentDatabaseName, refreshingSchema]);
const schemasRef = useRef();
schemasRef.current = schemas;
useEffect(() => {
@@ -41,6 +53,7 @@ export default function useDatabricksSchema(dataSource, options = null, onOption
if (currentDatabaseName && !has(schemasRef.current, currentDatabaseName)) {
setLoadingSchema(true);
getSchema(dataSource, currentDatabaseName)
.catch(() => Promise.resolve([]))
.then(data => {
if (!isCancelled) {
setSchemas(currentSchemas => ({
@@ -114,5 +127,7 @@ export default function useDatabricksSchema(dataSource, options = null, onOption
loadingSchema,
currentDatabaseName,
setCurrentDatabase,
refreshSchema,
refreshingSchema,
};
}

View File

@@ -5,12 +5,24 @@ import { fetchDataFromJob } from "@/services/query-result";
export default {
...DataSource,
getDatabases: ({ id }) =>
axios
.get(`api/databricks/databases/${id}`)
.then(data => (has(data, "job.id") ? fetchDataFromJob(data.job.id, 300).catch(() => []) : Promise.resolve([]))),
getDatabaseTables: (data, databaseName) =>
axios
.get(`api/databricks/databases/${data.id}/${databaseName}/tables`)
.then(data => (has(data, "job.id") ? fetchDataFromJob(data.job.id, 300).catch(() => []) : Promise.resolve([]))),
getDatabases: ({ id }, refresh = false) => {
const params = {};
if (refresh) {
params.refresh = true;
}
return axios
.get(`api/databricks/databases/${id}`, { params })
.then(data => (has(data, "job.id") ? fetchDataFromJob(data.job.id, 300).catch(() => []) : Promise.resolve([])));
},
getDatabaseTables: (data, databaseName, refresh = false) => {
const params = {};
if (refresh) {
params.refresh = true;
}
return axios
.get(`api/databricks/databases/${data.id}/${databaseName}/tables`, { params })
.then(data => (has(data, "job.id") ? fetchDataFromJob(data.job.id, 300).catch(() => []) : Promise.resolve([])));
},
};