mirror of
https://github.com/apache/superset.git
synced 2026-04-24 10:35:01 +00:00
* Generate JWT in Flask app * Refactor chart data API query logic, add JWT validation and async worker * Add redis stream implementation, refactoring * Add chart data cache endpoint, refactor QueryContext caching * Typing, linting, refactoring * pytest fixes and openapi schema update * Enforce caching be configured for async query init * Async query processing for explore_json endpoint * Add /api/v1/async_event endpoint * Async frontend for dashboards [WIP] * Chart async error message support, refactoring * Abstract asyncEvent middleware * Async chart loading for Explore * Pylint fixes * asyncEvent middleware -> TypeScript, JS linting * Chart data API: enforce forced_cache, add tests * Add tests for explore_json endpoints * Add test for chart data cache enpoint (no login) * Consolidate set_and_log_cache and add STORE_CACHE_KEYS_IN_METADATA_DB flag * Add tests for tasks/async_queries and address PR comments * Bypass non-JSON result formats for async queries * Add tests for redux middleware * Remove debug statement Co-authored-by: Ville Brofeldt <33317356+villebro@users.noreply.github.com> * Skip force_cached if no queryObj * SunburstViz: don't modify self.form_data * Fix failing annotation test * Resolve merge/lint issues * Reduce polling delay * Fix new getClientErrorObject reference * Fix flakey unit tests * /api/v1/async_event: increment redis stream ID, add tests * PR feedback: refactoring, configuration * Fixup: remove debugging * Fix typescript errors due to redux upgrade * Update UPDATING.md * Fix failing py tests * asyncEvent_spec.js -> asyncEvent_spec.ts * Refactor flakey Python 3.7 mock assertions * Fix another shared state issue in Py tests * Use 'sub' claim in JWT for user_id * Refactor async middleware config * Fixup: restore FeatureFlag boolean type Co-authored-by: Ville Brofeldt <33317356+villebro@users.noreply.github.com>
140 lines
3.8 KiB
JavaScript
140 lines
3.8 KiB
JavaScript
/**
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
import {
|
|
SupersetClient,
|
|
getTimeFormatter,
|
|
TimeFormats,
|
|
} from '@superset-ui/core';
|
|
import { getClientErrorObject } from './getClientErrorObject';
|
|
|
|
// ATTENTION: If you change any constants, make sure to also change constants.py
|
|
|
|
export const NULL_STRING = '<NULL>';
|
|
|
|
// moment time format strings
|
|
export const SHORT_DATE = 'MMM D, YYYY';
|
|
export const SHORT_TIME = 'h:m a';
|
|
|
|
const DATETIME_FORMATTER = getTimeFormatter(TimeFormats.DATABASE_DATETIME);
|
|
|
|
export function getParamFromQuery(query, param) {
|
|
const vars = query.split('&');
|
|
for (let i = 0; i < vars.length; i += 1) {
|
|
const pair = vars[i].split('=');
|
|
if (decodeURIComponent(pair[0]) === param) {
|
|
return decodeURIComponent(pair[1]);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function storeQuery(query) {
|
|
return SupersetClient.post({
|
|
endpoint: '/kv/store/',
|
|
postPayload: { data: query },
|
|
}).then(response => {
|
|
const baseUrl = window.location.origin + window.location.pathname;
|
|
const url = `${baseUrl}?id=${response.json.id}`;
|
|
return url;
|
|
});
|
|
}
|
|
|
|
export function getParamsFromUrl() {
|
|
const hash = window.location.search;
|
|
const params = hash.split('?')[1].split('&');
|
|
const newParams = {};
|
|
params.forEach(p => {
|
|
const value = p.split('=')[1].replace(/\+/g, ' ');
|
|
const key = p.split('=')[0];
|
|
newParams[key] = value;
|
|
});
|
|
return newParams;
|
|
}
|
|
|
|
export function getShortUrl(longUrl) {
|
|
return SupersetClient.post({
|
|
endpoint: '/r/shortner/',
|
|
postPayload: { data: `/${longUrl}` }, // note: url should contain 2x '/' to redirect properly
|
|
parseMethod: 'text',
|
|
stringify: false, // the url saves with an extra set of string quotes without this
|
|
})
|
|
.then(({ text }) => text)
|
|
.catch(response =>
|
|
getClientErrorObject(response).then(({ error, statusText }) =>
|
|
Promise.reject(error || statusText),
|
|
),
|
|
);
|
|
}
|
|
|
|
export function optionLabel(opt) {
|
|
if (opt === null) {
|
|
return NULL_STRING;
|
|
}
|
|
if (opt === '') {
|
|
return '<empty string>';
|
|
}
|
|
if (opt === true) {
|
|
return '<true>';
|
|
}
|
|
if (opt === false) {
|
|
return '<false>';
|
|
}
|
|
if (typeof opt !== 'string' && opt.toString) {
|
|
return opt.toString();
|
|
}
|
|
return opt;
|
|
}
|
|
|
|
export function optionValue(opt) {
|
|
if (opt === null) {
|
|
return NULL_STRING;
|
|
}
|
|
return opt;
|
|
}
|
|
|
|
export function optionFromValue(opt) {
|
|
// From a list of options, handles special values & labels
|
|
return { value: optionValue(opt), label: optionLabel(opt) };
|
|
}
|
|
|
|
export function prepareCopyToClipboardTabularData(data) {
|
|
let result = '';
|
|
for (let i = 0; i < data.length; i += 1) {
|
|
result += `${Object.values(data[i]).join('\t')}\n`;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
export function applyFormattingToTabularData(data) {
|
|
if (!data || data.length === 0 || !('__timestamp' in data[0])) {
|
|
return data;
|
|
}
|
|
return data.map(row => ({
|
|
...row,
|
|
/* eslint-disable no-underscore-dangle */
|
|
__timestamp:
|
|
row.__timestamp === 0 || row.__timestamp
|
|
? DATETIME_FORMATTER(new Date(row.__timestamp))
|
|
: row.__timestamp,
|
|
/* eslint-enable no-underscore-dangle */
|
|
}));
|
|
}
|
|
|
|
export const noOp = () => undefined;
|