in superset-frontend/src/views/CRUD/hooks.ts [539:781]
sshPasswordNeeded: getSSHPasswordsNeeded(error.errors),
sshPrivateKeyNeeded: getSSHPrivateKeysNeeded(error.errors),
sshPrivateKeyPasswordNeeded: getSSHPrivateKeyPasswordsNeeded(
error.errors,
),
alreadyExists: getAlreadyExists(error.errors),
});
}
return false;
}),
)
.finally(() => {
updateState({ loading: false });
});
},
[],
);
return { state, importResource };
}
type FavoriteStatusResponse = {
result: Array<{
id: string;
value: boolean;
}>;
};
const favoriteApis = {
chart: makeApi<Array<string | number>, FavoriteStatusResponse>({
requestType: 'rison',
method: 'GET',
endpoint: '/api/v1/chart/favorite_status/',
}),
dashboard: makeApi<Array<string | number>, FavoriteStatusResponse>({
requestType: 'rison',
method: 'GET',
endpoint: '/api/v1/dashboard/favorite_status/',
}),
tag: makeApi<Array<string | number>, FavoriteStatusResponse>({
requestType: 'rison',
method: 'GET',
endpoint: '/api/v1/tag/favorite_status/',
}),
};
export function useFavoriteStatus(
type: 'chart' | 'dashboard' | 'tag',
ids: Array<string | number>,
handleErrorMsg: (message: string) => void,
) {
const [favoriteStatus, setFavoriteStatus] = useState<FavoriteStatus>({});
const updateFavoriteStatus = (update: FavoriteStatus) =>
setFavoriteStatus(currentState => ({ ...currentState, ...update }));
useEffect(() => {
if (!ids.length) {
return;
}
favoriteApis[type](ids).then(
({ result }) => {
const update = result.reduce<Record<string, boolean>>(
(acc, element) => {
acc[element.id] = element.value;
return acc;
},
{},
);
updateFavoriteStatus(update);
},
createErrorHandler(errMsg =>
handleErrorMsg(
t('There was an error fetching the favorite status: %s', errMsg),
),
),
);
}, [ids, type, handleErrorMsg]);
const saveFaveStar = useCallback(
(id: number, isStarred: boolean) => {
const endpoint = `/api/v1/${type}/${id}/favorites/`;
const apiCall = isStarred
? SupersetClient.delete({
endpoint,
})
: SupersetClient.post({ endpoint });
apiCall.then(
() => {
updateFavoriteStatus({
[id]: !isStarred,
});
},
createErrorHandler(errMsg =>
handleErrorMsg(
t('There was an error saving the favorite status: %s', errMsg),
),
),
);
},
[type],
);
return [saveFaveStar, favoriteStatus] as const;
}
export const useChartEditModal = (
setCharts: (charts: Array<Chart>) => void,
charts: Array<Chart>,
) => {
const [sliceCurrentlyEditing, setSliceCurrentlyEditing] =
useState<Slice | null>(null);
function openChartEditModal(chart: Chart) {
setSliceCurrentlyEditing({
slice_id: chart.id,
slice_name: chart.slice_name,
description: chart.description,
cache_timeout: chart.cache_timeout,
certified_by: chart.certified_by,
certification_details: chart.certification_details,
is_managed_externally: chart.is_managed_externally,
});
}
function closeChartEditModal() {
setSliceCurrentlyEditing(null);
}
function handleChartUpdated(edits: Chart) {
// update the chart in our state with the edited info
const newCharts = charts.map((chart: Chart) =>
chart.id === edits.id ? { ...chart, ...edits } : chart,
);
setCharts(newCharts);
}
return {
sliceCurrentlyEditing,
handleChartUpdated,
openChartEditModal,
closeChartEditModal,
};
};
export const copyQueryLink = (
id: number,
addDangerToast: (arg0: string) => void,
addSuccessToast: (arg0: string) => void,
) => {
copyTextToClipboard(() =>
Promise.resolve(
`${window.location.origin}${ensureAppRoot(`/sqllab?savedQueryId=${id}`)}`,
),
)
.then(() => {
addSuccessToast(t('Link Copied!'));
})
.catch(() => {
addDangerToast(t('Sorry, your browser does not support copying.'));
});
};
export const getDatabaseImages = () => SupersetText.DB_IMAGES;
export const getConnectionAlert = () => SupersetText.DB_CONNECTION_ALERTS;
export const getDatabaseDocumentationLinks = () =>
SupersetText.DB_CONNECTION_DOC_LINKS;
export const testDatabaseConnection = (
connection: Partial<DatabaseObject>,
handleErrorMsg: (errorMsg: string) => void,
addSuccessToast: (arg0: string) => void,
) => {
SupersetClient.post({
endpoint: 'api/v1/database/test_connection/',
body: JSON.stringify(connection),
headers: { 'Content-Type': 'application/json' },
}).then(
() => {
addSuccessToast(t('Connection looks good!'));
},
createErrorHandler((errMsg: Record<string, string[] | string> | string) => {
handleErrorMsg(t('ERROR: %s', parsedErrorMessage(errMsg)));
}),
);
};
export function useAvailableDatabases() {
const [availableDbs, setAvailableDbs] = useState<JsonObject | null>(null);
const getAvailable = useCallback(() => {
SupersetClient.get({
endpoint: `/api/v1/database/available/`,
}).then(({ json }) => {
setAvailableDbs(json);
});
}, [setAvailableDbs]);
return [availableDbs, getAvailable] as const;
}
const transformDB = (db: Partial<DatabaseObject> | null) => {
if (db && Array.isArray(db?.catalog)) {
return {
...db,
catalog: Object.assign(
{},
...db.catalog.map((x: { name: string; value: string }) => ({
[x.name]: x.value,
})),
),
};
}
return db;
};
export function useDatabaseValidation() {
const [validationErrors, setValidationErrors] = useState<JsonObject | null>(
null,
);
const getValidation = useCallback(
(database: Partial<DatabaseObject> | null, onCreate = false) => {
if (database?.parameters?.ssh) {
// TODO: /validate_parameters/ and related utils should support ssh tunnel
setValidationErrors(null);
return [];
}
return (
SupersetClient.post({
endpoint: '/api/v1/database/validate_parameters/',
body: JSON.stringify(transformDB(database)),
headers: { 'Content-Type': 'application/json' },
})
.then(() => {
setValidationErrors(null);
})
// eslint-disable-next-line consistent-return
.catch(e => {
if (typeof e.json === 'function') {
return e.json().then(({ errors = [] }: JsonObject) => {