mirror of
https://github.com/getredash/redash.git
synced 2025-12-19 17:37:19 -05:00
Add loading button in UI
This commit is contained in:
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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([])));
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user