chore: Removes no-use-before-define warnings (#20298)
This commit is contained in:
parent
8345eb4644
commit
cb2ffa530f
|
|
@ -23,6 +23,63 @@ export type Params = {
|
|||
debug?: boolean;
|
||||
};
|
||||
|
||||
// Each message we send on the channel specifies an action we want the other side to cooperate with.
|
||||
enum Actions {
|
||||
GET = 'get',
|
||||
REPLY = 'reply',
|
||||
EMIT = 'emit',
|
||||
ERROR = 'error',
|
||||
}
|
||||
|
||||
type Method<A extends {}, R> = (args: A) => R | Promise<R>;
|
||||
|
||||
// helper types/functions for making sure wires don't get crossed
|
||||
|
||||
interface Message {
|
||||
switchboardAction: Actions;
|
||||
}
|
||||
|
||||
interface GetMessage<T = any> extends Message {
|
||||
switchboardAction: Actions.GET;
|
||||
method: string;
|
||||
messageId: string;
|
||||
args: T;
|
||||
}
|
||||
|
||||
function isGet(message: Message): message is GetMessage {
|
||||
return message.switchboardAction === Actions.GET;
|
||||
}
|
||||
|
||||
interface ReplyMessage<T = any> extends Message {
|
||||
switchboardAction: Actions.REPLY;
|
||||
messageId: string;
|
||||
result: T;
|
||||
}
|
||||
|
||||
function isReply(message: Message): message is ReplyMessage {
|
||||
return message.switchboardAction === Actions.REPLY;
|
||||
}
|
||||
|
||||
interface EmitMessage<T = any> extends Message {
|
||||
switchboardAction: Actions.EMIT;
|
||||
method: string;
|
||||
args: T;
|
||||
}
|
||||
|
||||
function isEmit(message: Message): message is EmitMessage {
|
||||
return message.switchboardAction === Actions.EMIT;
|
||||
}
|
||||
|
||||
interface ErrorMessage extends Message {
|
||||
switchboardAction: Actions.ERROR;
|
||||
messageId: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
function isError(message: Message): message is ErrorMessage {
|
||||
return message.switchboardAction === Actions.ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility for communications between an iframe and its parent, used by the Superset embedded SDK.
|
||||
* This builds useful patterns on top of the basic functionality offered by MessageChannel.
|
||||
|
|
@ -185,60 +242,3 @@ export class Switchboard {
|
|||
return `m_${this.name}_${this.incrementor++}`;
|
||||
}
|
||||
}
|
||||
|
||||
type Method<A extends {}, R> = (args: A) => R | Promise<R>;
|
||||
|
||||
// Each message we send on the channel specifies an action we want the other side to cooperate with.
|
||||
enum Actions {
|
||||
GET = 'get',
|
||||
REPLY = 'reply',
|
||||
EMIT = 'emit',
|
||||
ERROR = 'error',
|
||||
}
|
||||
|
||||
// helper types/functions for making sure wires don't get crossed
|
||||
|
||||
interface Message {
|
||||
switchboardAction: Actions;
|
||||
}
|
||||
|
||||
interface GetMessage<T = any> extends Message {
|
||||
switchboardAction: Actions.GET;
|
||||
method: string;
|
||||
messageId: string;
|
||||
args: T;
|
||||
}
|
||||
|
||||
function isGet(message: Message): message is GetMessage {
|
||||
return message.switchboardAction === Actions.GET;
|
||||
}
|
||||
|
||||
interface ReplyMessage<T = any> extends Message {
|
||||
switchboardAction: Actions.REPLY;
|
||||
messageId: string;
|
||||
result: T;
|
||||
}
|
||||
|
||||
function isReply(message: Message): message is ReplyMessage {
|
||||
return message.switchboardAction === Actions.REPLY;
|
||||
}
|
||||
|
||||
interface EmitMessage<T = any> extends Message {
|
||||
switchboardAction: Actions.EMIT;
|
||||
method: string;
|
||||
args: T;
|
||||
}
|
||||
|
||||
function isEmit(message: Message): message is EmitMessage {
|
||||
return message.switchboardAction === Actions.EMIT;
|
||||
}
|
||||
|
||||
interface ErrorMessage extends Message {
|
||||
switchboardAction: Actions.ERROR;
|
||||
messageId: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
function isError(message: Message): message is ErrorMessage {
|
||||
return message.switchboardAction === Actions.ERROR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,12 +25,6 @@ import { FrameComponentProps } from 'src/explore/components/controls/DateFilterC
|
|||
import DateFunctionTooltip from './DateFunctionTooltip';
|
||||
|
||||
export function AdvancedFrame(props: FrameComponentProps) {
|
||||
const advancedRange = getAdvancedRange(props.value || '');
|
||||
const [since, until] = advancedRange.split(SEPARATOR);
|
||||
if (advancedRange !== props.value) {
|
||||
props.onChange(getAdvancedRange(props.value || ''));
|
||||
}
|
||||
|
||||
function getAdvancedRange(value: string): string {
|
||||
if (value.includes(SEPARATOR)) {
|
||||
return value;
|
||||
|
|
@ -44,6 +38,12 @@ export function AdvancedFrame(props: FrameComponentProps) {
|
|||
return SEPARATOR;
|
||||
}
|
||||
|
||||
const advancedRange = getAdvancedRange(props.value || '');
|
||||
const [since, until] = advancedRange.split(SEPARATOR);
|
||||
if (advancedRange !== props.value) {
|
||||
props.onChange(getAdvancedRange(props.value || ''));
|
||||
}
|
||||
|
||||
function onChange(control: 'since' | 'until', value: string) {
|
||||
if (control === 'since') {
|
||||
props.onChange(`${value}${SEPARATOR}${until}`);
|
||||
|
|
|
|||
|
|
@ -67,46 +67,6 @@ let listenersByJobId: Record<string, ListenerFn>;
|
|||
let retriesByJobId: Record<string, number>;
|
||||
let lastReceivedEventId: string | null | undefined;
|
||||
|
||||
export const init = (appConfig?: AppConfig) => {
|
||||
if (!isFeatureEnabled(FeatureFlag.GLOBAL_ASYNC_QUERIES)) return;
|
||||
if (pollingTimeoutId) clearTimeout(pollingTimeoutId);
|
||||
|
||||
listenersByJobId = {};
|
||||
retriesByJobId = {};
|
||||
lastReceivedEventId = null;
|
||||
|
||||
if (appConfig) {
|
||||
config = appConfig;
|
||||
} else {
|
||||
// load bootstrap data from DOM
|
||||
const appContainer = document.getElementById('app');
|
||||
if (appContainer) {
|
||||
const bootstrapData = JSON.parse(
|
||||
appContainer?.getAttribute('data-bootstrap') || '{}',
|
||||
);
|
||||
config = bootstrapData?.common?.conf;
|
||||
} else {
|
||||
config = {};
|
||||
logging.warn('asyncEvent: app config data not found');
|
||||
}
|
||||
}
|
||||
transport = config.GLOBAL_ASYNC_QUERIES_TRANSPORT || TRANSPORT_POLLING;
|
||||
pollingDelayMs = config.GLOBAL_ASYNC_QUERIES_POLLING_DELAY || 500;
|
||||
|
||||
try {
|
||||
lastReceivedEventId = localStorage.getItem(LOCALSTORAGE_KEY);
|
||||
} catch (err) {
|
||||
logging.warn('Failed to fetch last event Id from localStorage');
|
||||
}
|
||||
|
||||
if (transport === TRANSPORT_POLLING) {
|
||||
loadEventsFromApi();
|
||||
}
|
||||
if (transport === TRANSPORT_WS) {
|
||||
wsConnect();
|
||||
}
|
||||
};
|
||||
|
||||
const addListener = (id: string, fn: any) => {
|
||||
listenersByJobId[id] = fn;
|
||||
};
|
||||
|
|
@ -116,6 +76,24 @@ const removeListener = (id: string) => {
|
|||
delete listenersByJobId[id];
|
||||
};
|
||||
|
||||
const fetchCachedData = async (
|
||||
asyncEvent: AsyncEvent,
|
||||
): Promise<CachedDataResponse> => {
|
||||
let status = 'success';
|
||||
let data;
|
||||
try {
|
||||
const { json } = await SupersetClient.get({
|
||||
endpoint: String(asyncEvent.result_url),
|
||||
});
|
||||
data = 'result' in json ? json.result : json;
|
||||
} catch (response) {
|
||||
status = 'error';
|
||||
data = await getClientErrorObject(response);
|
||||
}
|
||||
|
||||
return { status, data };
|
||||
};
|
||||
|
||||
export const waitForAsyncData = async (asyncResponse: AsyncEvent) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const jobId = asyncResponse.job_id;
|
||||
|
|
@ -153,24 +131,6 @@ const fetchEvents = makeApi<
|
|||
endpoint: POLLING_URL,
|
||||
});
|
||||
|
||||
const fetchCachedData = async (
|
||||
asyncEvent: AsyncEvent,
|
||||
): Promise<CachedDataResponse> => {
|
||||
let status = 'success';
|
||||
let data;
|
||||
try {
|
||||
const { json } = await SupersetClient.get({
|
||||
endpoint: String(asyncEvent.result_url),
|
||||
});
|
||||
data = 'result' in json ? json.result : json;
|
||||
} catch (response) {
|
||||
status = 'error';
|
||||
data = await getClientErrorObject(response);
|
||||
}
|
||||
|
||||
return { status, data };
|
||||
};
|
||||
|
||||
const setLastId = (asyncEvent: AsyncEvent) => {
|
||||
lastReceivedEventId = asyncEvent.id;
|
||||
try {
|
||||
|
|
@ -180,22 +140,6 @@ const setLastId = (asyncEvent: AsyncEvent) => {
|
|||
}
|
||||
};
|
||||
|
||||
const loadEventsFromApi = async () => {
|
||||
const eventArgs = lastReceivedEventId ? { last_id: lastReceivedEventId } : {};
|
||||
if (Object.keys(listenersByJobId).length) {
|
||||
try {
|
||||
const { result: events } = await fetchEvents(eventArgs);
|
||||
if (events && events.length) await processEvents(events);
|
||||
} catch (err) {
|
||||
logging.warn(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (transport === TRANSPORT_POLLING) {
|
||||
pollingTimeoutId = window.setTimeout(loadEventsFromApi, pollingDelayMs);
|
||||
}
|
||||
};
|
||||
|
||||
export const processEvents = async (events: AsyncEvent[]) => {
|
||||
events.forEach((asyncEvent: AsyncEvent) => {
|
||||
const jobId = asyncEvent.job_id;
|
||||
|
|
@ -222,6 +166,22 @@ export const processEvents = async (events: AsyncEvent[]) => {
|
|||
});
|
||||
};
|
||||
|
||||
const loadEventsFromApi = async () => {
|
||||
const eventArgs = lastReceivedEventId ? { last_id: lastReceivedEventId } : {};
|
||||
if (Object.keys(listenersByJobId).length) {
|
||||
try {
|
||||
const { result: events } = await fetchEvents(eventArgs);
|
||||
if (events && events.length) await processEvents(events);
|
||||
} catch (err) {
|
||||
logging.warn(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (transport === TRANSPORT_POLLING) {
|
||||
pollingTimeoutId = window.setTimeout(loadEventsFromApi, pollingDelayMs);
|
||||
}
|
||||
};
|
||||
|
||||
const wsConnectMaxRetries = 6;
|
||||
const wsConnectErrorDelay = 2500;
|
||||
let wsConnectRetries = 0;
|
||||
|
|
@ -267,4 +227,44 @@ const wsConnect = (): void => {
|
|||
});
|
||||
};
|
||||
|
||||
export const init = (appConfig?: AppConfig) => {
|
||||
if (!isFeatureEnabled(FeatureFlag.GLOBAL_ASYNC_QUERIES)) return;
|
||||
if (pollingTimeoutId) clearTimeout(pollingTimeoutId);
|
||||
|
||||
listenersByJobId = {};
|
||||
retriesByJobId = {};
|
||||
lastReceivedEventId = null;
|
||||
|
||||
if (appConfig) {
|
||||
config = appConfig;
|
||||
} else {
|
||||
// load bootstrap data from DOM
|
||||
const appContainer = document.getElementById('app');
|
||||
if (appContainer) {
|
||||
const bootstrapData = JSON.parse(
|
||||
appContainer?.getAttribute('data-bootstrap') || '{}',
|
||||
);
|
||||
config = bootstrapData?.common?.conf;
|
||||
} else {
|
||||
config = {};
|
||||
logging.warn('asyncEvent: app config data not found');
|
||||
}
|
||||
}
|
||||
transport = config.GLOBAL_ASYNC_QUERIES_TRANSPORT || TRANSPORT_POLLING;
|
||||
pollingDelayMs = config.GLOBAL_ASYNC_QUERIES_POLLING_DELAY || 500;
|
||||
|
||||
try {
|
||||
lastReceivedEventId = localStorage.getItem(LOCALSTORAGE_KEY);
|
||||
} catch (err) {
|
||||
logging.warn('Failed to fetch last event Id from localStorage');
|
||||
}
|
||||
|
||||
if (transport === TRANSPORT_POLLING) {
|
||||
loadEventsFromApi();
|
||||
}
|
||||
if (transport === TRANSPORT_WS) {
|
||||
wsConnect();
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
|
|
|
|||
|
|
@ -66,20 +66,6 @@ export type LocalStorageValues = {
|
|||
explore__data_table_original_formatted_time_columns: Record<string, string[]>;
|
||||
};
|
||||
|
||||
export function getItem<K extends LocalStorageKeys>(
|
||||
key: K,
|
||||
defaultValue: LocalStorageValues[K],
|
||||
): LocalStorageValues[K] {
|
||||
return dangerouslyGetItemDoNotUse(key, defaultValue);
|
||||
}
|
||||
|
||||
export function setItem<K extends LocalStorageKeys>(
|
||||
key: K,
|
||||
value: LocalStorageValues[K],
|
||||
): void {
|
||||
dangerouslySetItemDoNotUse(key, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function should not be used directly, as it doesn't provide any type safety or any
|
||||
* guarantees that the globally namespaced localstorage key is correct.
|
||||
|
|
@ -116,3 +102,17 @@ export function dangerouslySetItemDoNotUse(key: string, value: any): void {
|
|||
// Catch in case localStorage is unavailable
|
||||
}
|
||||
}
|
||||
|
||||
export function getItem<K extends LocalStorageKeys>(
|
||||
key: K,
|
||||
defaultValue: LocalStorageValues[K],
|
||||
): LocalStorageValues[K] {
|
||||
return dangerouslyGetItemDoNotUse(key, defaultValue);
|
||||
}
|
||||
|
||||
export function setItem<K extends LocalStorageKeys>(
|
||||
key: K,
|
||||
value: LocalStorageValues[K],
|
||||
): void {
|
||||
dangerouslySetItemDoNotUse(key, value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -230,6 +230,14 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
|
|||
),
|
||||
);
|
||||
|
||||
const handleBulkDatasetExport = (datasetsToExport: Dataset[]) => {
|
||||
const ids = datasetsToExport.map(({ id }) => id);
|
||||
handleResourceExport('dataset', ids, () => {
|
||||
setPreparingExport(false);
|
||||
});
|
||||
setPreparingExport(true);
|
||||
};
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
{
|
||||
|
|
@ -617,14 +625,6 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
|
|||
);
|
||||
};
|
||||
|
||||
const handleBulkDatasetExport = (datasetsToExport: Dataset[]) => {
|
||||
const ids = datasetsToExport.map(({ id }) => id);
|
||||
handleResourceExport('dataset', ids, () => {
|
||||
setPreparingExport(false);
|
||||
});
|
||||
setPreparingExport(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SubMenu {...menuData} />
|
||||
|
|
|
|||
|
|
@ -106,21 +106,6 @@ function ChartTable({
|
|||
const [preparingExport, setPreparingExport] = useState<boolean>(false);
|
||||
const [loaded, setLoaded] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (loaded || chartFilter === 'Favorite') {
|
||||
getData(chartFilter);
|
||||
}
|
||||
setLoaded(true);
|
||||
}, [chartFilter]);
|
||||
|
||||
const handleBulkChartExport = (chartsToExport: Chart[]) => {
|
||||
const ids = chartsToExport.map(({ id }) => id);
|
||||
handleResourceExport('chart', ids, () => {
|
||||
setPreparingExport(false);
|
||||
});
|
||||
setPreparingExport(true);
|
||||
};
|
||||
|
||||
const getFilters = (filterName: string) => {
|
||||
const filters = [];
|
||||
|
||||
|
|
@ -159,6 +144,21 @@ function ChartTable({
|
|||
filters: getFilters(filter),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (loaded || chartFilter === 'Favorite') {
|
||||
getData(chartFilter);
|
||||
}
|
||||
setLoaded(true);
|
||||
}, [chartFilter]);
|
||||
|
||||
const handleBulkChartExport = (chartsToExport: Chart[]) => {
|
||||
const ids = chartsToExport.map(({ id }) => id);
|
||||
handleResourceExport('chart', ids, () => {
|
||||
setPreparingExport(false);
|
||||
});
|
||||
setPreparingExport(true);
|
||||
};
|
||||
|
||||
const menuTabs = [
|
||||
{
|
||||
name: 'Favorite',
|
||||
|
|
|
|||
|
|
@ -96,6 +96,43 @@ function DashboardTable({
|
|||
const [preparingExport, setPreparingExport] = useState<boolean>(false);
|
||||
const [loaded, setLoaded] = useState<boolean>(false);
|
||||
|
||||
const getFilters = (filterName: string) => {
|
||||
const filters = [];
|
||||
if (filterName === 'Mine') {
|
||||
filters.push({
|
||||
id: 'owners',
|
||||
operator: 'rel_m_m',
|
||||
value: `${user?.userId}`,
|
||||
});
|
||||
} else if (filterName === 'Favorite') {
|
||||
filters.push({
|
||||
id: 'id',
|
||||
operator: 'dashboard_is_favorite',
|
||||
value: true,
|
||||
});
|
||||
} else if (filterName === 'Examples') {
|
||||
filters.push({
|
||||
id: 'created_by',
|
||||
operator: 'rel_o_m',
|
||||
value: 0,
|
||||
});
|
||||
}
|
||||
return filters;
|
||||
};
|
||||
|
||||
const getData = (filter: string) =>
|
||||
fetchData({
|
||||
pageIndex: 0,
|
||||
pageSize: PAGE_SIZE,
|
||||
sortBy: [
|
||||
{
|
||||
id: 'changed_on_delta_humanized',
|
||||
desc: true,
|
||||
},
|
||||
],
|
||||
filters: getFilters(filter),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (loaded || dashboardFilter === 'Favorite') {
|
||||
getData(dashboardFilter);
|
||||
|
|
@ -132,30 +169,6 @@ function DashboardTable({
|
|||
),
|
||||
);
|
||||
|
||||
const getFilters = (filterName: string) => {
|
||||
const filters = [];
|
||||
if (filterName === 'Mine') {
|
||||
filters.push({
|
||||
id: 'owners',
|
||||
operator: 'rel_m_m',
|
||||
value: `${user?.userId}`,
|
||||
});
|
||||
} else if (filterName === 'Favorite') {
|
||||
filters.push({
|
||||
id: 'id',
|
||||
operator: 'dashboard_is_favorite',
|
||||
value: true,
|
||||
});
|
||||
} else if (filterName === 'Examples') {
|
||||
filters.push({
|
||||
id: 'created_by',
|
||||
operator: 'rel_o_m',
|
||||
value: 0,
|
||||
});
|
||||
}
|
||||
return filters;
|
||||
};
|
||||
|
||||
const menuTabs = [
|
||||
{
|
||||
name: 'Favorite',
|
||||
|
|
@ -192,19 +205,6 @@ function DashboardTable({
|
|||
});
|
||||
}
|
||||
|
||||
const getData = (filter: string) =>
|
||||
fetchData({
|
||||
pageIndex: 0,
|
||||
pageSize: PAGE_SIZE,
|
||||
sortBy: [
|
||||
{
|
||||
id: 'changed_on_delta_humanized',
|
||||
desc: true,
|
||||
},
|
||||
],
|
||||
filters: getFilters(filter),
|
||||
});
|
||||
|
||||
if (loading) return <LoadingCards cover={showThumbnails} />;
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
Loading…
Reference in New Issue