`dashboard/${dashboard.slug}`}
+ itemUrl={dashboard => dashboard.url}
emptyState={
diff --git a/client/app/pages/queries-list/QueriesList.jsx b/client/app/pages/queries-list/QueriesList.jsx
index b5899b6390..e23094b112 100644
--- a/client/app/pages/queries-list/QueriesList.jsx
+++ b/client/app/pages/queries-list/QueriesList.jsx
@@ -11,7 +11,6 @@ import { wrap as itemsList, ControllerType } from "@/components/items-list/Items
import { ResourceItemsSource } from "@/components/items-list/classes/ItemsSource";
import { UrlStateStorage } from "@/components/items-list/classes/StateStorage";
-import LoadingState from "@/components/items-list/components/LoadingState";
import * as Sidebar from "@/components/items-list/components/Sidebar";
import ItemsTable, { Columns } from "@/components/items-list/components/ItemsTable";
@@ -43,12 +42,6 @@ class QueriesList extends React.Component {
title: "Favorites",
icon: () => ,
},
- {
- key: "archive",
- href: "queries/archive",
- title: "Archived",
- icon: () => ,
- },
{
key: "my",
href: "queries/my",
@@ -56,6 +49,12 @@ class QueriesList extends React.Component {
icon: () => ,
isAvailable: () => currentUser.hasPermission("create_query"),
},
+ {
+ key: "archive",
+ href: "queries/archive",
+ title: "Archived",
+ icon: () => ,
+ },
];
listColumns = [
@@ -80,12 +79,18 @@ class QueriesList extends React.Component {
width: null,
}
),
- Columns.custom((text, item) => item.user.name, { title: "Created By" }),
- Columns.dateTime.sortable({ title: "Created At", field: "created_at" }),
- Columns.dateTime.sortable({ title: "Last Executed At", field: "retrieved_at", orderByField: "executed_at" }),
+ Columns.custom((text, item) => item.user.name, { title: "Created By", width: "1%" }),
+ Columns.dateTime.sortable({ title: "Created At", field: "created_at", width: "1%" }),
+ Columns.dateTime.sortable({
+ title: "Last Executed At",
+ field: "retrieved_at",
+ orderByField: "executed_at",
+ width: "1%",
+ }),
Columns.custom.sortable((text, item) => , {
title: "Refresh Schedule",
field: "schedule",
+ width: "1%",
}),
];
@@ -130,34 +135,29 @@ class QueriesList extends React.Component {
/>
- controller.updatePagination({ itemsPerPage })}
- />
- {!controller.isLoaded && }
- {controller.isLoaded && controller.isEmpty && (
+ {controller.isLoaded && controller.isEmpty ? (
- )}
- {controller.isLoaded && !controller.isEmpty && (
+ ) : (
controller.updatePagination({ itemsPerPage })}
page={controller.page}
onChange={page => controller.updatePagination({ page })}
/>
diff --git a/client/app/pages/queries-list/queries-list.css b/client/app/pages/queries-list/queries-list.css
index 8e3f0e291b..619a72c8a8 100644
--- a/client/app/pages/queries-list/queries-list.css
+++ b/client/app/pages/queries-list/queries-list.css
@@ -4,5 +4,13 @@
}
.page-queries-list .page-header-actions {
- min-width: 25%; /* same as sidebar */
+ width: 25%; /* same as sidebar */
+ max-width: 350px; /* same as sidebar */
+}
+
+/* same rule as for sidebar */
+@media (max-width: 990px) {
+ .page-queries-list .page-header-actions {
+ width: auto;
+ }
}
diff --git a/client/app/pages/queries/QuerySource.jsx b/client/app/pages/queries/QuerySource.jsx
index 99646ce796..cffe935153 100644
--- a/client/app/pages/queries/QuerySource.jsx
+++ b/client/app/pages/queries/QuerySource.jsx
@@ -10,6 +10,7 @@ import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSess
import Resizable from "@/components/Resizable";
import Parameters from "@/components/Parameters";
import EditInPlace from "@/components/EditInPlace";
+import DynamicComponent from "@/components/DynamicComponent";
import recordEvent from "@/services/recordEvent";
import { ExecutionStatus } from "@/services/query-result";
import routes from "@/services/routes";
@@ -212,12 +213,14 @@ function QuerySource(props) {
key={`ds-${ds.id}`}
value={ds.id}
data-name={ds.name}
+ title={ds.description && ds.description}
data-test={`SelectDataSource${ds.id}`}>
-
+
{ds.name}
))}
+
)}
diff --git a/client/app/pages/queries/QuerySource.less b/client/app/pages/queries/QuerySource.less
index ed510da58a..2c161517c2 100644
--- a/client/app/pages/queries/QuerySource.less
+++ b/client/app/pages/queries/QuerySource.less
@@ -73,7 +73,7 @@
flex: 0 0 auto;
}
- .ant-tabs-content {
+ .ant-tabs-content-holder {
flex: 1 1 auto;
position: relative;
diff --git a/client/app/pages/queries/QueryView.jsx b/client/app/pages/queries/QueryView.jsx
index 5eed8f6bb4..768a309291 100644
--- a/client/app/pages/queries/QueryView.jsx
+++ b/client/app/pages/queries/QueryView.jsx
@@ -3,7 +3,9 @@ import PropTypes from "prop-types";
import cx from "classnames";
import useMedia from "use-media";
import Button from "antd/lib/button";
-import Icon from "antd/lib/icon";
+
+import FullscreenOutlinedIcon from "@ant-design/icons/FullscreenOutlined";
+import FullscreenExitOutlinedIcon from "@ant-design/icons/FullscreenExitOutlined";
import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession";
import EditInPlace from "@/components/EditInPlace";
@@ -131,7 +133,7 @@ function QueryView(props) {
onStopEditing={() => setAddingDescription(false)}
placeholder="Add description"
ignoreBlanks={false}
- editorProps={{ autosize: { minRows: 2, maxRows: 4 } }}
+ editorProps={{ autoSize: { minRows: 2, maxRows: 4 } }}
defaultEditing={addingDescription}
multiline
/>
@@ -190,7 +192,7 @@ function QueryView(props) {
type="default"
shortcut="alt+f"
onClick={toggleFullscreen}>
-
+ {fullscreen ?
:
}
}
/>
diff --git a/client/app/pages/queries/QueryView.less b/client/app/pages/queries/QueryView.less
index 8fbe15e492..b6cb734d12 100644
--- a/client/app/pages/queries/QueryView.less
+++ b/client/app/pages/queries/QueryView.less
@@ -89,7 +89,7 @@ page-query-view {
flex: 0 0 auto;
}
- .ant-tabs-content {
+ .ant-tabs-content-holder {
flex: 1 1 auto;
position: relative;
diff --git a/client/app/pages/queries/VisualizationEmbed.jsx b/client/app/pages/queries/VisualizationEmbed.jsx
index bb59fc7b85..05cb2b5760 100644
--- a/client/app/pages/queries/VisualizationEmbed.jsx
+++ b/client/app/pages/queries/VisualizationEmbed.jsx
@@ -6,7 +6,6 @@ import { markdown } from "markdown";
import Button from "antd/lib/button";
import Dropdown from "antd/lib/dropdown";
-import Icon from "antd/lib/icon";
import Menu from "antd/lib/menu";
import Tooltip from "antd/lib/tooltip";
import routeWithApiKeySession from "@/components/ApplicationArea/routeWithApiKeySession";
@@ -18,6 +17,9 @@ import QueryResultsLink from "@/components/EditVisualizationButton/QueryResultsL
import VisualizationName from "@/components/visualizations/VisualizationName";
import VisualizationRenderer from "@/components/visualizations/VisualizationRenderer";
+import FileOutlinedIcon from "@ant-design/icons/FileOutlined";
+import FileExcelOutlinedIcon from "@ant-design/icons/FileExcelOutlined";
+
import { VisualizationType } from "@redash/viz/lib";
import HtmlContent from "@redash/viz/lib/components/HtmlContent";
@@ -72,7 +74,7 @@ function VisualizationEmbedFooter({
apiKey={apiKey}
disabled={!queryResults || !queryResults.getData || !queryResults.getData()}
embed>
-
Download as CSV File
+
Download as CSV File
@@ -83,7 +85,7 @@ function VisualizationEmbedFooter({
apiKey={apiKey}
disabled={!queryResults || !queryResults.getData || !queryResults.getData()}
embed>
- Download as TSV File
+ Download as TSV File
@@ -94,7 +96,7 @@ function VisualizationEmbedFooter({
apiKey={apiKey}
disabled={!queryResults || !queryResults.getData || !queryResults.getData()}
embed>
- Download as Excel File
+ Download as Excel File
diff --git a/client/app/pages/queries/components/QueryExecutionMetadata.jsx b/client/app/pages/queries/components/QueryExecutionMetadata.jsx
index 5b8496ba1e..d8e29665f4 100644
--- a/client/app/pages/queries/components/QueryExecutionMetadata.jsx
+++ b/client/app/pages/queries/components/QueryExecutionMetadata.jsx
@@ -55,7 +55,7 @@ export default function QueryExecutionMetadata({
{queryResultData.metadata.data_scanned && (
- Data Scanned
+ Data Scanned
{prettySize(queryResultData.metadata.data_scanned)}
)}
diff --git a/client/app/pages/queries/components/QueryPageHeader.jsx b/client/app/pages/queries/components/QueryPageHeader.jsx
index 50e022a886..ceec749f04 100644
--- a/client/app/pages/queries/components/QueryPageHeader.jsx
+++ b/client/app/pages/queries/components/QueryPageHeader.jsx
@@ -4,7 +4,7 @@ import PropTypes from "prop-types";
import Button from "antd/lib/button";
import Dropdown from "antd/lib/dropdown";
import Menu from "antd/lib/menu";
-import Icon from "antd/lib/icon";
+import EllipsisOutlinedIcon from "@ant-design/icons/EllipsisOutlined";
import useMedia from "use-media";
import EditInPlace from "@/components/EditInPlace";
import FavoritesControl from "@/components/FavoritesControl";
@@ -199,7 +199,7 @@ export default function QueryPageHeader({
{!queryFlags.isNew && (
)}
diff --git a/client/app/pages/queries/components/QuerySourceAlerts.jsx b/client/app/pages/queries/components/QuerySourceAlerts.jsx
index 1b973d535b..75b4729720 100644
--- a/client/app/pages/queries/components/QuerySourceAlerts.jsx
+++ b/client/app/pages/queries/components/QuerySourceAlerts.jsx
@@ -1,7 +1,7 @@
import React from "react";
import PropTypes from "prop-types";
import Card from "antd/lib/card";
-import Icon from "antd/lib/icon";
+import WarningFilledIcon from "@ant-design/icons/WarningFilled";
import Button from "antd/lib/button";
import Typography from "antd/lib/typography";
import { currentUser } from "@/services/auth";
@@ -70,7 +70,7 @@ export default function QuerySourceAlerts({ query, dataSourcesAvailable }) {
-
+
{message}
diff --git a/client/app/pages/queries/components/QueryVisualizationTabs.jsx b/client/app/pages/queries/components/QueryVisualizationTabs.jsx
index 6e6243b2ed..4f63e4abae 100644
--- a/client/app/pages/queries/components/QueryVisualizationTabs.jsx
+++ b/client/app/pages/queries/components/QueryVisualizationTabs.jsx
@@ -17,7 +17,7 @@ function EmptyState({ title, message, refreshButton }) {
-

+
{title}
{message}
@@ -133,7 +133,6 @@ export default function QueryVisualizationTabs({
{orderedVisualizations.map(visualization => (
find(dataSources, { id: query.data_source_id }) || null, [
- query.data_source_id,
- dataSources,
- ]);
+ const dataSource = useMemo(
+ () => find(dataSources, ds => toString(ds.id) === toString(query.data_source_id)) || null,
+ [query.data_source_id, dataSources]
+ );
useEffect(() => {
let cancelDataSourceLoading = false;
diff --git a/client/app/pages/query-snippets/QuerySnippetsList.jsx b/client/app/pages/query-snippets/QuerySnippetsList.jsx
index ff4c8e1c2a..9296f36bd5 100644
--- a/client/app/pages/query-snippets/QuerySnippetsList.jsx
+++ b/client/app/pages/query-snippets/QuerySnippetsList.jsx
@@ -177,8 +177,10 @@ class QuerySnippetsList extends React.Component {
toggleSorting={controller.toggleSorting}
/>
controller.updatePagination({ itemsPerPage })}
page={controller.page}
onChange={page => controller.updatePagination({ page })}
/>
diff --git a/client/app/pages/settings/OrganizationSettings.jsx b/client/app/pages/settings/OrganizationSettings.jsx
index ae1df1f3fd..45e31337c9 100644
--- a/client/app/pages/settings/OrganizationSettings.jsx
+++ b/client/app/pages/settings/OrganizationSettings.jsx
@@ -12,6 +12,7 @@ import recordEvent from "@/services/recordEvent";
import OrgSettings from "@/services/organizationSettings";
import routes from "@/services/routes";
import useImmutableCallback from "@/lib/hooks/useImmutableCallback";
+import { getHorizontalFormProps, getHorizontalFormItemWithoutLabelProps } from "@/styles/formStyle";
import GeneralSettings from "./components/GeneralSettings";
import AuthSettings from "./components/AuthSettings";
@@ -53,36 +54,34 @@ function OrganizationSettings({ onError }) {
setCurrentValues(currentValues => ({ ...currentValues, ...changes }));
}, []);
- const handleSubmit = useCallback(
- event => {
- event.preventDefault();
- if (!isSaving) {
- setIsSaving(true);
- OrgSettings.save(currentValues)
- .then(response => {
- const settings = get(response, "settings");
- setSettings(settings);
- setCurrentValues({ ...settings });
- })
- .catch(handleError)
- .finally(() => setIsSaving(false));
- }
- },
- [isSaving, currentValues, handleError]
- );
+ const handleSubmit = useCallback(() => {
+ if (!isSaving) {
+ setIsSaving(true);
+ OrgSettings.save(currentValues)
+ .then(response => {
+ const settings = get(response, "settings");
+ setSettings(settings);
+ setCurrentValues({ ...settings });
+ })
+ .catch(handleError)
+ .finally(() => setIsSaving(false));
+ }
+ }, [isSaving, currentValues, handleError]);
return (
-
+
{isLoading ? (
) : (
-
+
+
)}
@@ -102,8 +101,8 @@ const OrganizationSettingsPage = wrapSettingsTab(
"Settings.Organization",
{
permission: "admin",
- title: "Settings",
- path: "settings/organization",
+ title: "General",
+ path: "settings/general",
order: 6,
},
OrganizationSettings
@@ -112,8 +111,8 @@ const OrganizationSettingsPage = wrapSettingsTab(
routes.register(
"Settings.Organization",
routeWithUserSession({
- path: "/settings/organization",
- title: "Organization Settings",
+ path: "/settings/general",
+ title: "General Settings",
render: pageProps =>
,
})
);
diff --git a/client/app/pages/settings/components/AuthSettings/PasswordLoginSettings.jsx b/client/app/pages/settings/components/AuthSettings/PasswordLoginSettings.jsx
index 3a287523d5..74d7314136 100644
--- a/client/app/pages/settings/components/AuthSettings/PasswordLoginSettings.jsx
+++ b/client/app/pages/settings/components/AuthSettings/PasswordLoginSettings.jsx
@@ -23,7 +23,7 @@ export default function PasswordLoginSettings(props) {
className="m-t-15 m-b-15"
/>
)}
-
+
SAML
-
+
- Anonymous Usage Data Sharing
- >
+
+ Anonymous Usage Data Sharing
+
+
}>
- onChange({ feature_show_permissions_control: e.target.checked })}>
- Enable experimental multiple owners support
-
-
-
- onChange({ send_email_on_failed_scheduled_queries: e.target.checked })}>
- Email query owners when scheduled queries fail
-
-
-
- onChange({ multi_byte_search_enabled: e.target.checked })}>
- Enable multi-byte (Chinese, Japanese, and Korean) search for query names and descriptions (slower)
-
+
+
+ onChange({ feature_show_permissions_control: e.target.checked })}>
+ Enable experimental multiple owners support
+
+
+
+
+ onChange({ send_email_on_failed_scheduled_queries: e.target.checked })}>
+ Email query owners when scheduled queries fail
+
+
+
+ onChange({ multi_byte_search_enabled: e.target.checked })}>
+ Enable multi-byte (Chinese, Japanese, and Korean) search for query names and descriptions (slower)
+
+
);
diff --git a/client/app/pages/users/UsersList.jsx b/client/app/pages/users/UsersList.jsx
index 09e3aea78b..bae16148a8 100644
--- a/client/app/pages/users/UsersList.jsx
+++ b/client/app/pages/users/UsersList.jsx
@@ -213,12 +213,6 @@ class UsersList extends React.Component {
- controller.updatePagination({ itemsPerPage })}
- />
{!controller.isLoaded && }
@@ -234,8 +228,10 @@ class UsersList extends React.Component {
toggleSorting={controller.toggleSorting}
/>
controller.updatePagination({ itemsPerPage })}
page={controller.page}
onChange={page => controller.updatePagination({ page })}
/>
diff --git a/client/app/pages/users/components/UserInfoForm.jsx b/client/app/pages/users/components/UserInfoForm.jsx
index 5a0b43d971..01e57ea376 100644
--- a/client/app/pages/users/components/UserInfoForm.jsx
+++ b/client/app/pages/users/components/UserInfoForm.jsx
@@ -69,6 +69,7 @@ export default function UserInfoForm(props) {
name: "group_ids",
title: "Groups",
type: "content",
+ required: false,
content: isLoadingGroups ? "Loading..." : ,
},
],
diff --git a/client/app/services/auth.js b/client/app/services/auth.js
index b7a2fe0b03..db5e2af18c 100644
--- a/client/app/services/auth.js
+++ b/client/app/services/auth.js
@@ -30,6 +30,10 @@ export const messages = [];
const logger = debug("redash:auth");
const session = { loaded: false };
+const AuthUrls = {
+ Login: "login",
+};
+
function updateSession(sessionData) {
logger("Updating session to be:", sessionData);
extend(session, sessionData, { loaded: true });
@@ -42,10 +46,13 @@ export const Auth = {
isAuthenticated() {
return session.loaded && session.user.id;
},
+ setLoginUrl(loginUrl) {
+ AuthUrls.Login = loginUrl;
+ },
login() {
const next = encodeURI(location.url);
logger("Calling login with next = %s", next);
- window.location.href = `login?next=${next}`;
+ window.location.href = `${AuthUrls.Login}?next=${next}`;
},
logout() {
logger("Logout.");
diff --git a/client/app/services/axios.js b/client/app/services/axios.js
index 3697050bbe..13de7eab7a 100644
--- a/client/app/services/axios.js
+++ b/client/app/services/axios.js
@@ -1,6 +1,7 @@
import axiosLib from "axios";
import { Auth } from "@/services/auth";
import qs from "query-string";
+import Cookies from "js-cookie";
export const axios = axiosLib.create({
paramsSerializer: params => qs.stringify(params),
@@ -16,5 +17,10 @@ axios.interceptors.request.use(config => {
config.headers.Authorization = `Key ${apiKey}`;
}
+ const csrfToken = Cookies.get("csrf_token");
+ if (csrfToken) {
+ config.headers.common["X-CSRF-TOKEN"] = csrfToken;
+ }
+
return config;
});
diff --git a/client/app/services/dashboard.js b/client/app/services/dashboard.js
index f347048ca0..d2f1806fa6 100644
--- a/client/app/services/dashboard.js
+++ b/client/app/services/dashboard.js
@@ -6,6 +6,8 @@ import { currentUser } from "@/services/auth";
import location from "@/services/location";
import { cloneParameter } from "@/services/parameters";
+export const urlForDashboard = ({ id, slug }) => `dashboards/${id}-${slug}`;
+
export function collectDashboardFilters(dashboard, queryResults, urlParams) {
const filters = {};
_.each(queryResults, queryResult => {
@@ -123,6 +125,11 @@ function calculateNewWidgetPosition(existingWidgets, newWidget) {
export function Dashboard(dashboard) {
_.extend(this, dashboard);
+ Object.defineProperty(this, "url", {
+ get: function() {
+ return urlForDashboard(this);
+ },
+ });
}
function prepareDashboardWidgets(widgets) {
@@ -147,17 +154,23 @@ function transformResponse(data) {
return data;
}
-const saveOrCreateUrl = data => (data.slug ? `api/dashboards/${data.slug}` : "api/dashboards");
+const saveOrCreateUrl = data => (data.id ? `api/dashboards/${data.id}` : "api/dashboards");
const DashboardService = {
- get: ({ slug }) => axios.get(`api/dashboards/${slug}`).then(transformResponse),
+ get: ({ id, slug }) => {
+ const params = {};
+ if (!id) {
+ params.legacy = null;
+ }
+ return axios.get(`api/dashboards/${id || slug}`, { params }).then(transformResponse);
+ },
getByToken: ({ token }) => axios.get(`api/dashboards/public/${token}`).then(transformResponse),
save: data => axios.post(saveOrCreateUrl(data), data).then(transformResponse),
- delete: ({ slug }) => axios.delete(`api/dashboards/${slug}`).then(transformResponse),
+ delete: ({ id }) => axios.delete(`api/dashboards/${id}`).then(transformResponse),
query: params => axios.get("api/dashboards", { params }).then(transformResponse),
recent: params => axios.get("api/dashboards/recent", { params }).then(transformResponse),
favorites: params => axios.get("api/dashboards/favorites", { params }).then(transformResponse),
- favorite: ({ slug }) => axios.post(`api/dashboards/${slug}/favorite`),
- unfavorite: ({ slug }) => axios.delete(`api/dashboards/${slug}/favorite`),
+ favorite: ({ id }) => axios.post(`api/dashboards/${id}/favorite`),
+ unfavorite: ({ id }) => axios.delete(`api/dashboards/${id}/favorite`),
};
_.extend(Dashboard, DashboardService);
diff --git a/client/app/services/data-source.js b/client/app/services/data-source.js
index 0a5c78da2b..312e2944a3 100644
--- a/client/app/services/data-source.js
+++ b/client/app/services/data-source.js
@@ -1,19 +1,25 @@
-import { has } from "lodash";
+import { has, map, isObject } from "lodash";
import { axios } from "@/services/axios";
import { fetchDataFromJob } from "@/services/query-result";
export const SCHEMA_NOT_SUPPORTED = 1;
export const SCHEMA_LOAD_ERROR = 2;
-export const IMG_ROOT = "/static/images/db-logos";
+export const IMG_ROOT = "static/images/db-logos";
+
+function mapSchemaColumnsToObject(columns) {
+ return map(columns, column => (isObject(column) ? column : { name: column }));
+}
const DataSource = {
query: () => axios.get("api/data_sources"),
get: ({ id }) => axios.get(`api/data_sources/${id}`),
+ post: ({ id }) => axios.post(`api/data_sources/${id}`),
types: () => axios.get("api/data_sources/types"),
create: data => axios.post(`api/data_sources`, data),
save: data => axios.post(`api/data_sources/${data.id}`, data),
test: data => axios.post(`api/data_sources/${data.id}/test`),
delete: ({ id }) => axios.delete(`api/data_sources/${id}`),
+ updateSchema: ({ id, data }) => axios.post(`api/data_sources/${id}/schema`, data),
fetchSchema: (data, refresh = false) => {
const params = {};
@@ -21,14 +27,17 @@ const DataSource = {
params.refresh = true;
}
- return axios.get(`api/data_sources/${data.id}/schema`, { params }).then(data => {
- if (has(data, "job")) {
- return fetchDataFromJob(data.job.id).catch(error =>
- error.code === SCHEMA_NOT_SUPPORTED ? [] : Promise.reject(new Error(data.job.error))
- );
- }
- return has(data, "schema") ? data.schema : Promise.reject();
- });
+ return axios
+ .get(`api/data_sources/${data.id}/schema`, { params })
+ .then(data => {
+ if (has(data, "job")) {
+ return fetchDataFromJob(data.job.id).catch(error =>
+ error.code === SCHEMA_NOT_SUPPORTED ? [] : Promise.reject(new Error(data.job.error))
+ );
+ }
+ return has(data, "schema") ? data.schema : Promise.reject();
+ })
+ .then(tables => map(tables, table => ({ ...table, columns: mapSchemaColumnsToObject(table.columns) })));
},
};
diff --git a/client/app/services/databricks-data-source.js b/client/app/services/databricks-data-source.js
index e12b3e8c26..d916b04217 100644
--- a/client/app/services/databricks-data-source.js
+++ b/client/app/services/databricks-data-source.js
@@ -3,14 +3,41 @@ import { axios } from "@/services/axios";
import DataSource from "@/services/data-source";
import { fetchDataFromJob } from "@/services/query-result";
+function fetchDataFromJobOrReturnData(data) {
+ return has(data, "job.id") ? fetchDataFromJob(data.job.id, 1000) : data;
+}
+
+function rejectErrorResponse(data) {
+ return has(data, "error") ? Promise.reject(new Error(data.error.message)) : data;
+}
+
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) =>
+ getDatabases: ({ id }, refresh = false) => {
+ const params = {};
+
+ if (refresh) {
+ params.refresh = true;
+ }
+ return axios
+ .get(`api/databricks/databases/${id}`, { params })
+ .then(fetchDataFromJobOrReturnData)
+ .then(rejectErrorResponse);
+ },
+ getDatabaseTables: (data, databaseName, refresh = false) => {
+ const params = {};
+
+ if (refresh) {
+ params.refresh = true;
+ }
+ return axios
+ .get(`api/databricks/databases/${data.id}/${databaseName}/tables`, { params })
+ .then(fetchDataFromJobOrReturnData)
+ .then(rejectErrorResponse);
+ },
+ getTableColumns: (data, databaseName, tableName) =>
axios
- .get(`api/databricks/databases/${data.id}/${databaseName}/tables`)
- .then(data => (has(data, "job.id") ? fetchDataFromJob(data.job.id, 300).catch(() => []) : Promise.resolve([]))),
+ .get(`api/databricks/databases/${data.id}/${databaseName}/columns/${tableName}`)
+ .then(fetchDataFromJobOrReturnData)
+ .then(rejectErrorResponse),
};
diff --git a/client/app/services/destination.js b/client/app/services/destination.js
index faa8647d21..6100b9d075 100644
--- a/client/app/services/destination.js
+++ b/client/app/services/destination.js
@@ -1,6 +1,6 @@
import { axios } from "@/services/axios";
-export const IMG_ROOT = "/static/images/destinations";
+export const IMG_ROOT = "static/images/destinations";
const Destination = {
query: () => axios.get("api/destinations"),
diff --git a/client/app/services/notification.d.ts b/client/app/services/notification.d.ts
new file mode 100644
index 0000000000..cf2faa42fa
--- /dev/null
+++ b/client/app/services/notification.d.ts
@@ -0,0 +1,10 @@
+import { NotificationApi, ArgsProps } from "antd/lib/notification";
+type simpleFunc = (message: string, description?: string | null, args?: ArgsProps | null) => void;
+declare const notification: NotificationApi & {
+ success: simpleFunc;
+ error: simpleFunc;
+ info: simpleFunc;
+ warning: simpleFunc;
+ warn: simpleFunc;
+};
+export default notification;
diff --git a/client/app/services/routes.js b/client/app/services/routes.js
deleted file mode 100644
index abb008a0a4..0000000000
--- a/client/app/services/routes.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import { isString, isObject, filter, sortBy } from "lodash";
-import pathToRegexp from "path-to-regexp";
-
-function getRouteParamsCount(path) {
- const tokens = pathToRegexp.parse(path);
- return filter(tokens, isObject).length;
-}
-
-class Routes {
- _items = [];
- _sorted = false;
-
- get items() {
- if (!this._sorted) {
- this._items = sortBy(this._items, [
- item => getRouteParamsCount(item.path), // simple definitions first, with more params - last
- item => -item.path.length, // longer first
- item => item.path, // if same type and length - sort alphabetically
- ]);
- this._sorted = true;
- }
- return this._items;
- }
-
- register(id, route) {
- id = isString(id) ? id : null;
- this.unregister(id);
- if (isObject(route)) {
- this._items = [...this._items, { ...route, id }];
- this._sorted = false;
- }
- }
-
- unregister(id) {
- if (isString(id)) {
- // removing item does not break their order (if already sorted)
- this._items = filter(this._items, item => item.id !== id);
- }
- }
-}
-
-export default new Routes();
diff --git a/client/app/services/routes.ts b/client/app/services/routes.ts
new file mode 100644
index 0000000000..eae32f8fcc
--- /dev/null
+++ b/client/app/services/routes.ts
@@ -0,0 +1,63 @@
+import { isString, isObject, filter, sortBy } from "lodash";
+import React from "react";
+import { Context, Route as UniversalRouterRoute } from "universal-router";
+import pathToRegexp from "path-to-regexp";
+
+export interface CurrentRoute {
+ id: string | null;
+ key?: string;
+ title: string;
+ routeParams: P;
+}
+
+export interface RedashRoute
extends UniversalRouterRoute {
+ path: string; // we don't use other UniversalRouterRoute options, path should be available and should be a string
+ key?: string; // generated in Router.jsx
+ title: string;
+ render?: (currentRoute: CurrentRoute) => React.ReactNode;
+ getApiKey?: () => string;
+}
+
+interface RouteItem extends RedashRoute {
+ id: string | null;
+}
+
+function getRouteParamsCount(path: string) {
+ const tokens = pathToRegexp.parse(path);
+ return filter(tokens, isObject).length;
+}
+
+class Routes {
+ _items: RouteItem[] = [];
+ _sorted = false;
+
+ get items(): RouteItem[] {
+ if (!this._sorted) {
+ this._items = sortBy(this._items, [
+ item => getRouteParamsCount(item.path), // simple definitions first, with more params - last
+ item => -item.path.length, // longer first
+ item => item.path, // if same type and length - sort alphabetically
+ ]);
+ this._sorted = true;
+ }
+ return this._items;
+ }
+
+ public register(id: string, route: RedashRoute
) {
+ const idOrNull = isString(id) ? id : null;
+ this.unregister(idOrNull);
+ if (isObject(route)) {
+ this._items = [...this.items, { ...route, id: idOrNull }];
+ this._sorted = false;
+ }
+ }
+
+ public unregister(id: string | null) {
+ if (isString(id)) {
+ // removing item does not break their order (if already sorted)
+ this._items = filter(this.items, item => item.id !== id);
+ }
+ }
+}
+
+export default new Routes();
diff --git a/client/app/services/widget.js b/client/app/services/widget.js
index 2b21e3b390..16dcc4199f 100644
--- a/client/app/services/widget.js
+++ b/client/app/services/widget.js
@@ -143,18 +143,24 @@ class Widget {
if (maxAge === undefined || force) {
maxAge = force ? 0 : undefined;
}
- this.queryResult = this.getQuery().getQueryResult(maxAge);
- this.queryResult
+ const queryResult = this.getQuery().getQueryResult(maxAge);
+ this.queryResult = queryResult;
+
+ queryResult
.toPromise()
.then(result => {
- this.loading = false;
- this.data = result;
+ if (this.queryResult === queryResult) {
+ this.loading = false;
+ this.data = result;
+ }
return result;
})
.catch(error => {
- this.loading = false;
- this.data = error;
+ if (this.queryResult === queryResult) {
+ this.loading = false;
+ this.data = error;
+ }
return error;
});
}
diff --git a/client/app/styles/formStyle.less b/client/app/styles/formStyle.less
new file mode 100644
index 0000000000..884b94a127
--- /dev/null
+++ b/client/app/styles/formStyle.less
@@ -0,0 +1,10 @@
+.ant-form-horizontal--labels-left {
+ .ant-form-item-label {
+ text-align: left;
+ white-space: normal;
+
+ > label::after {
+ content: none; // Do not show ":" next to label when they are aligned on left side
+ }
+ }
+}
diff --git a/client/app/styles/formStyle.ts b/client/app/styles/formStyle.ts
new file mode 100644
index 0000000000..86d4970cd0
--- /dev/null
+++ b/client/app/styles/formStyle.ts
@@ -0,0 +1,18 @@
+import { FormProps } from "antd/lib/form/Form";
+import { FormItemProps } from "antd/lib/form/FormItem";
+import "./formStyle.less";
+
+export function getHorizontalFormProps(): FormProps {
+ return {
+ labelCol: { xs: { span: 24 }, sm: { span: 6 }, lg: { span: 4 } },
+ wrapperCol: { xs: { span: 24 }, sm: { span: 12 }, lg: { span: 10 } },
+ layout: "horizontal",
+ className: "ant-form-horizontal--labels-left",
+ };
+}
+
+export function getHorizontalFormItemWithoutLabelProps(): FormItemProps {
+ return {
+ wrapperCol: { xs: { span: 24 }, sm: { span: 12, offset: 6 }, lg: { span: 12, offset: 4 } },
+ };
+}
diff --git a/client/cypress/cypress.js b/client/cypress/cypress.js
index 9a8611fecf..c71989d288 100644
--- a/client/cypress/cypress.js
+++ b/client/cypress/cypress.js
@@ -1,21 +1,44 @@
/* eslint-disable import/no-extraneous-dependencies, no-console */
+const { find } = require("lodash");
const atob = require("atob");
const { execSync } = require("child_process");
-const { post } = require("request").defaults({ jar: true });
+const { get, post } = require("request").defaults({ jar: true });
const { seedData } = require("./seed-data");
+const fs = require("fs");
+var Cookie = require("request-cookies").Cookie;
-const baseUrl = process.env.CYPRESS_baseUrl || "http://localhost:5000";
+let cypressConfigBaseUrl;
+try {
+ const cypressConfig = JSON.parse(fs.readFileSync("cypress.json"));
+ cypressConfigBaseUrl = cypressConfig.baseUrl;
+} catch (e) {}
+
+const baseUrl = process.env.CYPRESS_baseUrl || cypressConfigBaseUrl || "http://localhost:5000";
function seedDatabase(seedValues) {
- const request = seedValues.shift();
- const data = request.type === "form" ? { formData: request.data } : { json: request.data };
+ get(baseUrl + "/login", (_, { headers }) => {
+ const request = seedValues.shift();
+ const data = request.type === "form" ? { formData: request.data } : { json: request.data };
- post(baseUrl + request.route, data, (err, response) => {
- const result = response ? response.statusCode : err;
- console.log("POST " + request.route + " - " + result);
- if (seedValues.length) {
- seedDatabase(seedValues);
+ if (headers["set-cookie"]) {
+ const cookies = headers["set-cookie"].map(cookie => new Cookie(cookie));
+ const csrfCookie = find(cookies, { key: "csrf_token" });
+ if (csrfCookie) {
+ if (request.type === "form") {
+ data["formData"] = { ...data["formData"], csrf_token: csrfCookie.value };
+ } else {
+ data["headers"] = { "X-CSRFToken": csrfCookie.value };
+ }
+ }
}
+
+ post(baseUrl + request.route, data, (err, response) => {
+ const result = response ? response.statusCode : err;
+ console.log("POST " + request.route + " - " + result);
+ if (seedValues.length) {
+ seedDatabase(seedValues);
+ }
+ });
});
}
diff --git a/client/cypress/integration/alert/create_alert_spec.js b/client/cypress/integration/alert/create_alert_spec.js
index 1eb78f2aa2..092b631cae 100644
--- a/client/cypress/integration/alert/create_alert_spec.js
+++ b/client/cypress/integration/alert/create_alert_spec.js
@@ -1,5 +1,3 @@
-import { createQuery } from "../../support/redash-api";
-
describe("Create Alert", () => {
beforeEach(() => {
cy.login();
@@ -12,7 +10,7 @@ describe("Create Alert", () => {
});
it("selects query and takes a screenshot", () => {
- createQuery({ name: "Create Alert Query" }).then(({ id: queryId }) => {
+ cy.createQuery({ name: "Create Alert Query" }).then(({ id: queryId }) => {
cy.visit("/alerts/new");
cy.getByTestId("QuerySelector")
.click()
diff --git a/client/cypress/integration/alert/edit_alert_spec.js b/client/cypress/integration/alert/edit_alert_spec.js
index 92082edcea..1a03ccf373 100644
--- a/client/cypress/integration/alert/edit_alert_spec.js
+++ b/client/cypress/integration/alert/edit_alert_spec.js
@@ -1,13 +1,11 @@
-import { createAlert, createQuery } from "../../support/redash-api";
-
describe("Edit Alert", () => {
beforeEach(() => {
cy.login();
});
it("renders the page and takes a screenshot", () => {
- createQuery({ query: "select 1 as col_name" })
- .then(({ id: queryId }) => createAlert(queryId, { column: "col_name" }))
+ cy.createQuery({ query: "select 1 as col_name" })
+ .then(({ id: queryId }) => cy.createAlert(queryId, { column: "col_name" }))
.then(({ id: alertId }) => {
cy.visit(`/alerts/${alertId}/edit`);
cy.getByTestId("Criteria").should("exist");
@@ -16,8 +14,8 @@ describe("Edit Alert", () => {
});
it("edits the notification template and takes a screenshot", () => {
- createQuery()
- .then(({ id: queryId }) => createAlert(queryId, { custom_subject: "FOO", custom_body: "BAR" }))
+ cy.createQuery()
+ .then(({ id: queryId }) => cy.createAlert(queryId, { custom_subject: "FOO", custom_body: "BAR" }))
.then(({ id: alertId }) => {
cy.visit(`/alerts/${alertId}/edit`);
cy.getByTestId("AlertCustomTemplate").should("exist");
@@ -33,8 +31,8 @@ describe("Edit Alert", () => {
custom_body: "{{ ALERT_THRESHOLD }}",
};
- createQuery()
- .then(({ id: queryId }) => createAlert(queryId, options))
+ cy.createQuery()
+ .then(({ id: queryId }) => cy.createAlert(queryId, options))
.then(({ id: alertId }) => {
cy.visit(`/alerts/${alertId}/edit`);
cy.get(".alert-template-preview").click();
diff --git a/client/cypress/integration/alert/view_alert_spec.js b/client/cypress/integration/alert/view_alert_spec.js
index 04ccbe7daf..2042050fd7 100644
--- a/client/cypress/integration/alert/view_alert_spec.js
+++ b/client/cypress/integration/alert/view_alert_spec.js
@@ -1,14 +1,13 @@
-import { createAlert, createQuery, createUser, addDestinationSubscription } from "../../support/redash-api";
-
describe("View Alert", () => {
beforeEach(function() {
- cy.login();
- createQuery({ query: "select 1 as col_name" })
- .then(({ id: queryId }) => createAlert(queryId, { column: "col_name" }))
- .then(({ id: alertId }) => {
- this.alertId = alertId;
- this.alertUrl = `/alerts/${alertId}`;
- });
+ cy.login().then(() => {
+ cy.createQuery({ query: "select 1 as col_name" })
+ .then(({ id: queryId }) => cy.createAlert(queryId, { column: "col_name" }))
+ .then(({ id: alertId }) => {
+ this.alertId = alertId;
+ this.alertUrl = `/alerts/${alertId}`;
+ });
+ });
});
it("renders the page and takes a screenshot", function() {
@@ -24,8 +23,8 @@ describe("View Alert", () => {
.should("not.exist");
cy.server();
- cy.route("GET", "api/destinations").as("Destinations");
- cy.route("GET", "api/alerts/*/subscriptions").as("Subscriptions");
+ cy.route("GET", "**/api/destinations").as("Destinations");
+ cy.route("GET", "**/api/alerts/*/subscriptions").as("Subscriptions");
cy.visit(this.alertUrl);
@@ -42,7 +41,7 @@ describe("View Alert", () => {
describe("Alert Destination permissions", () => {
before(() => {
cy.login();
- createUser({
+ cy.createUser({
name: "Example User",
email: "user@redash.io",
password: "password",
@@ -51,11 +50,11 @@ describe("View Alert", () => {
it("hides remove button from non-author", function() {
cy.server();
- cy.route("GET", "api/alerts/*/subscriptions").as("Subscriptions");
+ cy.route("GET", "**/api/alerts/*/subscriptions").as("Subscriptions");
cy.logout()
.then(() => cy.login()) // as admin
- .then(() => addDestinationSubscription(this.alertId, "Test Email Destination"))
+ .then(() => cy.addDestinationSubscription(this.alertId, "Test Email Destination"))
.then(() => {
cy.visit(this.alertUrl);
@@ -83,11 +82,11 @@ describe("View Alert", () => {
it("shows remove button for non-author admin", function() {
cy.server();
- cy.route("GET", "api/alerts/*/subscriptions").as("Subscriptions");
+ cy.route("GET", "**/api/alerts/*/subscriptions").as("Subscriptions");
cy.logout()
.then(() => cy.login("user@redash.io", "password"))
- .then(() => addDestinationSubscription(this.alertId, "Test Email Destination"))
+ .then(() => cy.addDestinationSubscription(this.alertId, "Test Email Destination"))
.then(() => {
cy.visit(this.alertUrl);
diff --git a/client/cypress/integration/dashboard/dashboard_spec.js b/client/cypress/integration/dashboard/dashboard_spec.js
index 489a07ea5f..d819dccb16 100644
--- a/client/cypress/integration/dashboard/dashboard_spec.js
+++ b/client/cypress/integration/dashboard/dashboard_spec.js
@@ -1,6 +1,5 @@
/* global cy, Cypress */
-import { createDashboard, addTextbox } from "../../support/redash-api";
import { getWidgetTestId } from "../../support/dashboard";
const menuWidth = 80;
@@ -16,7 +15,7 @@ describe("Dashboard", () => {
cy.getByTestId("CreateDashboardMenuItem").click();
cy.server();
- cy.route("POST", "api/dashboards").as("NewDashboard");
+ cy.route("POST", "**/api/dashboards").as("NewDashboard");
cy.getByTestId("CreateDashboardDialog").within(() => {
cy.getByTestId("DashboardSaveButton").should("be.disabled");
@@ -25,19 +24,19 @@ describe("Dashboard", () => {
});
cy.wait("@NewDashboard").then(xhr => {
- const slug = Cypress._.get(xhr, "response.body.slug");
- assert.isDefined(slug, "Dashboard api call returns slug");
+ const id = Cypress._.get(xhr, "response.body.id");
+ assert.isDefined(id, "Dashboard api call returns id");
cy.visit("/dashboards");
cy.getByTestId("DashboardLayoutContent").within(() => {
- cy.getByTestId(slug).should("exist");
+ cy.getByTestId(`DashboardId${id}`).should("exist");
});
});
});
it("archives dashboard", () => {
- createDashboard("Foo Bar").then(({ slug }) => {
- cy.visit(`/dashboard/${slug}`);
+ cy.createDashboard("Foo Bar").then(({ id }) => {
+ cy.visit(`/dashboards/${id}`);
cy.getByTestId("DashboardMoreButton").click();
@@ -52,7 +51,22 @@ describe("Dashboard", () => {
cy.visit("/dashboards");
cy.getByTestId("DashboardLayoutContent").within(() => {
- cy.getByTestId(slug).should("not.exist");
+ cy.getByTestId(`DashboardId${id}`).should("not.exist");
+ });
+ });
+ });
+
+ it("is accessible through multiple urls", () => {
+ cy.server();
+ cy.route("GET", "**/api/dashboards/*").as("LoadDashboard");
+ cy.createDashboard("Dashboard multiple urls").then(({ id, slug }) => {
+ [`/dashboards/${id}`, `/dashboards/${id}-anything-here`, `/dashboard/${slug}`].forEach(url => {
+ cy.visit(url);
+ cy.wait("@LoadDashboard");
+ cy.getByTestId(`DashboardId${id}Container`).should("exist");
+
+ // assert it always use the "/dashboards/{id}" path
+ cy.location("pathname").should("contain", `/dashboards/${id}`);
});
});
});
@@ -60,11 +74,11 @@ describe("Dashboard", () => {
context("viewport width is at 800px", () => {
before(function() {
cy.login();
- createDashboard("Foo Bar")
- .then(({ slug, id }) => {
- this.dashboardUrl = `/dashboard/${slug}`;
- this.dashboardEditUrl = `/dashboard/${slug}?edit`;
- return addTextbox(id, "Hello World!").then(getWidgetTestId);
+ cy.createDashboard("Foo Bar")
+ .then(({ id }) => {
+ this.dashboardUrl = `/dashboards/${id}`;
+ this.dashboardEditUrl = `/dashboards/${id}?edit`;
+ return cy.addTextbox(id, "Hello World!").then(getWidgetTestId);
})
.then(elTestId => {
cy.visit(this.dashboardUrl);
@@ -117,8 +131,8 @@ describe("Dashboard", () => {
context("viewport width is at 767px", () => {
before(function() {
cy.login();
- createDashboard("Foo Bar").then(({ slug }) => {
- this.dashboardUrl = `/dashboard/${slug}`;
+ cy.createDashboard("Foo Bar").then(({ id }) => {
+ this.dashboardUrl = `/dashboards/${id}`;
});
});
diff --git a/client/cypress/integration/dashboard/dashboard_tags_spec.js b/client/cypress/integration/dashboard/dashboard_tags_spec.js
index 9d8ef131ae..b1ef579af9 100644
--- a/client/cypress/integration/dashboard/dashboard_tags_spec.js
+++ b/client/cypress/integration/dashboard/dashboard_tags_spec.js
@@ -1,15 +1,14 @@
-import { createDashboard } from "../../support/redash-api";
import { expectTagsToContain, typeInTagsSelectAndSave } from "../../support/tags";
describe("Dashboard Tags", () => {
beforeEach(function() {
cy.login();
- createDashboard("Foo Bar").then(({ slug }) => cy.visit(`/dashboard/${slug}`));
+ cy.createDashboard("Foo Bar").then(({ id }) => cy.visit(`/dashboards/${id}`));
});
it("is possible to add and edit tags", () => {
cy.server();
- cy.route("POST", "api/dashboards/*").as("DashboardSave");
+ cy.route("POST", "**/api/dashboards/*").as("DashboardSave");
cy.getByTestId("TagsControl").contains(".label", "Unpublished");
@@ -17,13 +16,13 @@ describe("Dashboard Tags", () => {
.should("contain", "Add tag")
.click();
- typeInTagsSelectAndSave("tag1{enter}tag2{enter}tag3{enter}{esc}");
+ typeInTagsSelectAndSave("tag1{enter}tag2{enter}tag3{enter}");
cy.wait("@DashboardSave");
expectTagsToContain(["tag1", "tag2", "tag3"]);
cy.getByTestId("EditTagsButton").click();
- typeInTagsSelectAndSave("tag4{enter}{esc}");
+ typeInTagsSelectAndSave("tag4{enter}");
cy.wait("@DashboardSave");
cy.reload();
diff --git a/client/cypress/integration/dashboard/filters_spec.js b/client/cypress/integration/dashboard/filters_spec.js
index 47091c600a..d239332ee6 100644
--- a/client/cypress/integration/dashboard/filters_spec.js
+++ b/client/cypress/integration/dashboard/filters_spec.js
@@ -1,4 +1,3 @@
-import { createDashboard } from "../../support/redash-api";
import { createQueryAndAddWidget, editDashboard } from "../../support/dashboard";
import { expectTableToHaveLength, expectFirstColumnToHaveMembers } from "../../support/visualizations/table";
@@ -24,12 +23,12 @@ describe("Dashboard Filters", () => {
name: "Query Filters",
query: `SELECT stage1 AS "stage1::filter", stage2, value FROM (${SQL}) q`,
};
- createDashboard("Dashboard Filters").then(dashboard => {
+ cy.createDashboard("Dashboard Filters").then(dashboard => {
createQueryAndAddWidget(dashboard.id, queryData)
.as("widget1TestId")
.then(() => createQueryAndAddWidget(dashboard.id, queryData, { position: { col: 4 } }))
.as("widget2TestId")
- .then(() => cy.visit(`/dashboard/${dashboard.slug}`));
+ .then(() => cy.visit(`/dashboards/${dashboard.id}`));
});
});
@@ -40,7 +39,7 @@ describe("Dashboard Filters", () => {
cy.getByTestId("DashboardFilters").within(() => {
cy.getByTestId("FilterName-stage1::filter")
- .find(".ant-select-selection-selected-value")
+ .find(".ant-select-selection-item")
.should("have.text", "a");
});
@@ -53,7 +52,7 @@ describe("Dashboard Filters", () => {
.click();
});
- cy.contains("li.ant-select-dropdown-menu-item:visible", "b").click();
+ cy.contains(".ant-select-item-option-content:visible", "b").click();
cy.getByTestId(this.widget1TestId).within(() => {
expectTableToHaveLength(3);
@@ -75,7 +74,7 @@ describe("Dashboard Filters", () => {
.click();
});
- cy.contains("li.ant-select-dropdown-menu-item:visible", "c").click();
+ cy.contains(".ant-select-item-option-content:visible", "c").click();
[this.widget1TestId, this.widget2TestId].forEach(widgetTestId =>
cy.getByTestId(widgetTestId).within(() => {
diff --git a/client/cypress/integration/dashboard/grid_compliant_widgets_spec.js b/client/cypress/integration/dashboard/grid_compliant_widgets_spec.js
index 31a7361979..19883a0177 100644
--- a/client/cypress/integration/dashboard/grid_compliant_widgets_spec.js
+++ b/client/cypress/integration/dashboard/grid_compliant_widgets_spec.js
@@ -1,6 +1,5 @@
/* global cy */
-import { createDashboard, addTextbox } from "../../support/redash-api";
import { getWidgetTestId, editDashboard, resizeBy } from "../../support/dashboard";
const menuWidth = 80;
@@ -9,10 +8,10 @@ describe("Grid compliant widgets", () => {
beforeEach(function() {
cy.login();
cy.viewport(1215 + menuWidth, 800);
- createDashboard("Foo Bar")
- .then(({ slug, id }) => {
- this.dashboardUrl = `/dashboard/${slug}`;
- return addTextbox(id, "Hello World!").then(getWidgetTestId);
+ cy.createDashboard("Foo Bar")
+ .then(({ id }) => {
+ this.dashboardUrl = `/dashboards/${id}`;
+ return cy.addTextbox(id, "Hello World!").then(getWidgetTestId);
})
.then(elTestId => {
cy.visit(this.dashboardUrl);
@@ -50,7 +49,7 @@ describe("Grid compliant widgets", () => {
it("auto saves after drag", () => {
cy.server();
- cy.route("POST", "api/widgets/*").as("WidgetSave");
+ cy.route("POST", "**/api/widgets/*").as("WidgetSave");
editDashboard();
cy.get("@textboxEl").dragBy(330);
@@ -118,7 +117,7 @@ describe("Grid compliant widgets", () => {
it("auto saves after resize", () => {
cy.server();
- cy.route("POST", "api/widgets/*").as("WidgetSave");
+ cy.route("POST", "**/api/widgets/*").as("WidgetSave");
editDashboard();
resizeBy(cy.get("@textboxEl"), 200);
diff --git a/client/cypress/integration/dashboard/parameter_mapping_spec.js b/client/cypress/integration/dashboard/parameter_mapping_spec.js
index 04dc58a439..2e7195a8bb 100644
--- a/client/cypress/integration/dashboard/parameter_mapping_spec.js
+++ b/client/cypress/integration/dashboard/parameter_mapping_spec.js
@@ -1,13 +1,12 @@
-import { createDashboard } from "../../support/redash-api";
import { createQueryAndAddWidget } from "../../support/dashboard";
describe("Parameter Mapping", () => {
beforeEach(function() {
cy.login();
- createDashboard("Foo Bar")
- .then(({ slug, id }) => {
+ cy.createDashboard("Foo Bar")
+ .then(({ id }) => {
this.dashboardId = id;
- this.dashboardUrl = `/dashboard/${slug}`;
+ this.dashboardUrl = `/dashboards/${id}`;
})
.then(() => {
const queryData = {
diff --git a/client/cypress/integration/dashboard/sharing_spec.js b/client/cypress/integration/dashboard/sharing_spec.js
index adba653603..3ddcab8a1e 100644
--- a/client/cypress/integration/dashboard/sharing_spec.js
+++ b/client/cypress/integration/dashboard/sharing_spec.js
@@ -1,14 +1,13 @@
/* global cy */
-import { createDashboard, createQuery } from "../../support/redash-api";
import { editDashboard, shareDashboard, createQueryAndAddWidget } from "../../support/dashboard";
describe("Dashboard Sharing", () => {
beforeEach(function() {
cy.login();
- createDashboard("Foo Bar").then(({ slug, id }) => {
+ cy.createDashboard("Foo Bar").then(({ id }) => {
this.dashboardId = id;
- this.dashboardUrl = `/dashboard/${slug}`;
+ this.dashboardUrl = `/dashboards/${id}`;
});
});
@@ -23,7 +22,7 @@ describe("Dashboard Sharing", () => {
};
const dashboardUrl = this.dashboardUrl;
- createQuery({ options }).then(({ id: queryId }) => {
+ cy.createQuery({ options }).then(({ id: queryId }) => {
cy.visit(dashboardUrl);
editDashboard();
cy.getByTestId("AddWidgetButton").click();
@@ -148,7 +147,7 @@ describe("Dashboard Sharing", () => {
};
const dashboardUrl = this.dashboardUrl;
- createQuery({ options }).then(({ id: queryId }) => {
+ cy.createQuery({ options }).then(({ id: queryId }) => {
cy.visit(dashboardUrl);
editDashboard();
cy.getByTestId("AddWidgetButton").click();
diff --git a/client/cypress/integration/dashboard/textbox_spec.js b/client/cypress/integration/dashboard/textbox_spec.js
index 7e5beffa54..0c8463587e 100644
--- a/client/cypress/integration/dashboard/textbox_spec.js
+++ b/client/cypress/integration/dashboard/textbox_spec.js
@@ -1,14 +1,13 @@
/* global cy */
-import { createDashboard, addTextbox } from "../../support/redash-api";
import { getWidgetTestId, editDashboard } from "../../support/dashboard";
describe("Textbox", () => {
beforeEach(function() {
cy.login();
- createDashboard("Foo Bar").then(({ slug, id }) => {
+ cy.createDashboard("Foo Bar").then(({ id }) => {
this.dashboardId = id;
- this.dashboardUrl = `/dashboard/${slug}`;
+ this.dashboardUrl = `/dashboards/${id}`;
});
});
@@ -31,7 +30,7 @@ describe("Textbox", () => {
});
it("removes textbox by X button", function() {
- addTextbox(this.dashboardId, "Hello World!")
+ cy.addTextbox(this.dashboardId, "Hello World!")
.then(getWidgetTestId)
.then(elTestId => {
cy.visit(this.dashboardUrl);
@@ -47,7 +46,7 @@ describe("Textbox", () => {
});
it("removes textbox by menu", function() {
- addTextbox(this.dashboardId, "Hello World!")
+ cy.addTextbox(this.dashboardId, "Hello World!")
.then(getWidgetTestId)
.then(elTestId => {
cy.visit(this.dashboardUrl);
@@ -65,11 +64,11 @@ describe("Textbox", () => {
it("allows opening menu after removal", function() {
let elTestId1;
- addTextbox(this.dashboardId, "txb 1")
+ cy.addTextbox(this.dashboardId, "txb 1")
.then(getWidgetTestId)
.then(elTestId => {
elTestId1 = elTestId;
- return addTextbox(this.dashboardId, "txb 2").then(getWidgetTestId);
+ return cy.addTextbox(this.dashboardId, "txb 2").then(getWidgetTestId);
})
.then(elTestId2 => {
cy.visit(this.dashboardUrl);
@@ -99,7 +98,7 @@ describe("Textbox", () => {
});
it("edits textbox", function() {
- addTextbox(this.dashboardId, "Hello World!")
+ cy.addTextbox(this.dashboardId, "Hello World!")
.then(getWidgetTestId)
.then(elTestId => {
cy.visit(this.dashboardUrl);
@@ -133,8 +132,8 @@ describe("Textbox", () => {
const txb2Pos = { col: 1, row: 1, sizeX: 3, sizeY: 4 };
cy.viewport(1215, 800);
- addTextbox(id, "x", { position: txb1Pos })
- .then(() => addTextbox(id, "x", { position: txb2Pos }))
+ cy.addTextbox(id, "x", { position: txb1Pos })
+ .then(() => cy.addTextbox(id, "x", { position: txb2Pos }))
.then(getWidgetTestId)
.then(elTestId => {
cy.visit(this.dashboardUrl);
diff --git a/client/cypress/integration/dashboard/widget_spec.js b/client/cypress/integration/dashboard/widget_spec.js
index 2eff9e4f21..6da0e335cb 100644
--- a/client/cypress/integration/dashboard/widget_spec.js
+++ b/client/cypress/integration/dashboard/widget_spec.js
@@ -1,14 +1,13 @@
/* global cy */
-import { createDashboard, createQuery } from "../../support/redash-api";
import { createQueryAndAddWidget, editDashboard, resizeBy } from "../../support/dashboard";
describe("Widget", () => {
beforeEach(function() {
cy.login();
- createDashboard("Foo Bar").then(({ slug, id }) => {
+ cy.createDashboard("Foo Bar").then(({ id }) => {
this.dashboardId = id;
- this.dashboardUrl = `/dashboard/${slug}`;
+ this.dashboardUrl = `/dashboards/${id}`;
});
});
@@ -19,7 +18,7 @@ describe("Widget", () => {
};
it("adds widget", function() {
- createQuery().then(({ id: queryId }) => {
+ cy.createQuery().then(({ id: queryId }) => {
cy.visit(this.dashboardUrl);
editDashboard();
cy.getByTestId("AddWidgetButton").click();
@@ -104,7 +103,7 @@ describe("Widget", () => {
it("grows when dynamically adding table rows", () => {
// listen to results
cy.server();
- cy.route("GET", "api/query_results/*").as("FreshResults");
+ cy.route("GET", "**/api/query_results/*").as("FreshResults");
// start with 1 table row
cy.get("@paramInput")
@@ -132,7 +131,7 @@ describe("Widget", () => {
it("revokes auto height after manual height adjustment", () => {
// listen to results
cy.server();
- cy.route("GET", "api/query_results/*").as("FreshResults");
+ cy.route("GET", "**/api/query_results/*").as("FreshResults");
editDashboard();
diff --git a/client/cypress/integration/data-source/create_data_source_spec.js b/client/cypress/integration/data-source/create_data_source_spec.js
index d062293285..0453dd5d62 100644
--- a/client/cypress/integration/data-source/create_data_source_spec.js
+++ b/client/cypress/integration/data-source/create_data_source_spec.js
@@ -1,12 +1,25 @@
describe("Create Data Source", () => {
beforeEach(() => {
cy.login();
- cy.visit("/data_sources/new");
+ });
+
+ it("opens the creation dialog when clicking in the create link or button", () => {
+ cy.visit("/data_sources");
+ cy.server();
+ cy.route("**/api/data_sources", []); // force an empty response
+
+ ["CreateDataSourceButton", "CreateDataSourceLink"].forEach(createElementTestId => {
+ cy.getByTestId(createElementTestId).click();
+ cy.getByTestId("CreateSourceDialog").should("exist");
+ cy.getByTestId("CreateSourceCancelButton").click();
+ cy.getByTestId("CreateSourceDialog").should("not.exist");
+ });
});
it("renders the page and takes a screenshot", function() {
+ cy.visit("/data_sources/new");
cy.server();
- cy.route("api/data_sources/types").as("DataSourceTypesRequest");
+ cy.route("**/api/data_sources/types").as("DataSourceTypesRequest");
cy.wait("@DataSourceTypesRequest")
.then(({ response }) => response.body.filter(type => type.deprecated))
@@ -23,6 +36,7 @@ describe("Create Data Source", () => {
});
it("creates a new PostgreSQL data source", () => {
+ cy.visit("/data_sources/new");
cy.getByTestId("SearchSource").type("PostgreSQL");
cy.getByTestId("CreateSourceDialog")
.contains("PostgreSQL")
@@ -33,7 +47,7 @@ describe("Create Data Source", () => {
cy.getByTestId("User").type("postgres");
cy.getByTestId("Password").type("postgres");
cy.getByTestId("Database Name").type("postgres{enter}");
- cy.getByTestId("CreateSourceButton").click();
+ cy.getByTestId("CreateSourceSaveButton").click();
cy.contains("Saved.");
});
diff --git a/client/cypress/integration/destination/create_destination_spec.js b/client/cypress/integration/destination/create_destination_spec.js
index 5a51d336a2..4629ec76c0 100644
--- a/client/cypress/integration/destination/create_destination_spec.js
+++ b/client/cypress/integration/destination/create_destination_spec.js
@@ -1,5 +1,3 @@
-import { createDestination } from "../../support/redash-api";
-
describe("Create Destination", () => {
beforeEach(() => {
cy.login();
@@ -8,7 +6,7 @@ describe("Create Destination", () => {
it("renders the page and takes a screenshot", function() {
cy.visit("/destinations/new");
cy.server();
- cy.route("api/destinations/types").as("DestinationTypesRequest");
+ cy.route("**/api/destinations/types").as("DestinationTypesRequest");
cy.wait("@DestinationTypesRequest")
.then(({ response }) => response.body.filter(type => type.deprecated))
@@ -25,7 +23,7 @@ describe("Create Destination", () => {
});
it("shows a custom error message when destination name is already taken", () => {
- createDestination("Slack Destination", "slack").then(() => {
+ cy.createDestination("Slack Destination", "slack").then(() => {
cy.visit("/destinations/new");
cy.getByTestId("SearchSource").type("Slack");
@@ -34,7 +32,7 @@ describe("Create Destination", () => {
.click();
cy.getByTestId("Name").type("Slack Destination");
- cy.getByTestId("CreateSourceButton").click();
+ cy.getByTestId("CreateSourceSaveButton").click();
cy.contains("Alert Destination with the name Slack Destination already exists.");
});
diff --git a/client/cypress/integration/embed/share_embed_spec.js b/client/cypress/integration/embed/share_embed_spec.js
index e077e19d37..520482979b 100644
--- a/client/cypress/integration/embed/share_embed_spec.js
+++ b/client/cypress/integration/embed/share_embed_spec.js
@@ -1,12 +1,10 @@
-import { createQuery } from "../../support/redash-api";
-
describe("Embedded Queries", () => {
beforeEach(() => {
cy.login();
});
it("can be shared without parameters", () => {
- createQuery({ query: "select name from users order by name" }).then(query => {
+ cy.createQuery({ query: "select name from users order by name" }).then(query => {
cy.visit(`/queries/${query.id}/source`);
cy.getByTestId("ExecuteButton").click();
cy.getByTestId("QueryPageVisualizationTabs", { timeout: 10000 }).should("exist");
diff --git a/client/cypress/integration/query/create_query_spec.js b/client/cypress/integration/query/create_query_spec.js
index 5071977a94..12ea5161af 100644
--- a/client/cypress/integration/query/create_query_spec.js
+++ b/client/cypress/integration/query/create_query_spec.js
@@ -7,7 +7,7 @@ describe("Create Query", () => {
it("executes and saves a query", () => {
cy.clickThrough(`
SelectDataSource
- SelectDataSource1
+ SelectDataSource${Cypress.env("dataSourceId")}
`);
cy.getByTestId("QueryEditor")
@@ -22,6 +22,6 @@ describe("Create Query", () => {
cy.percySnapshot("Edit Query");
cy.getByTestId("SaveButton").click();
- cy.url().should("match", /\/queries\/\d+\/source/);
+ cy.url().should("match", /\/queries\/.+\/source/);
});
});
diff --git a/client/cypress/integration/query/filters_spec.js b/client/cypress/integration/query/filters_spec.js
index 3e2a0b67b1..219743ac40 100644
--- a/client/cypress/integration/query/filters_spec.js
+++ b/client/cypress/integration/query/filters_spec.js
@@ -1,4 +1,3 @@
-import { createQuery } from "../../support/redash-api";
import { expectTableToHaveLength, expectFirstColumnToHaveMembers } from "../../support/visualizations/table";
const SQL = `
@@ -27,13 +26,13 @@ describe("Query Filters", () => {
query: `SELECT stage1 AS "stage1::filter", stage2, value FROM (${SQL}) q`,
};
- createQuery(queryData).then(({ id }) => cy.visit(`/queries/${id}`));
+ cy.createQuery(queryData).then(({ id }) => cy.visit(`/queries/${id}`));
cy.getByTestId("ExecuteButton").click();
});
it("filters rows in a Table Visualization", () => {
cy.getByTestId("FilterName-stage1::filter")
- .find(".ant-select-selection-selected-value")
+ .find(".ant-select-selection-item")
.should("have.text", "a");
expectTableToHaveLength(4);
@@ -43,7 +42,7 @@ describe("Query Filters", () => {
.find(".ant-select")
.click();
- cy.contains("li.ant-select-dropdown-menu-item", "b").click();
+ cy.contains(".ant-select-item-option-content", "b").click();
expectTableToHaveLength(3);
expectFirstColumnToHaveMembers(["b", "b", "b"]);
@@ -57,13 +56,13 @@ describe("Query Filters", () => {
query: `SELECT stage1 AS "stage1::multi-filter", stage2, value FROM (${SQL}) q`,
};
- createQuery(queryData).then(({ id }) => cy.visit(`/queries/${id}`));
+ cy.createQuery(queryData).then(({ id }) => cy.visit(`/queries/${id}`));
cy.getByTestId("ExecuteButton").click();
});
function expectSelectedOptionsToHaveMembers(values) {
cy.getByTestId("FilterName-stage1::multi-filter")
- .find(".ant-select-selection__choice__content")
+ .find(".ant-select-selection-item-content")
.then($selectedOptions => Cypress.$.map($selectedOptions, item => Cypress.$(item).text()))
.then(selectedOptions => expect(selectedOptions).to.have.members(values));
}
@@ -74,9 +73,9 @@ describe("Query Filters", () => {
expectFirstColumnToHaveMembers(["a", "a", "a", "a"]);
cy.getByTestId("FilterName-stage1::multi-filter")
- .find(".ant-select-selection")
+ .find(".ant-select-selector")
.click();
- cy.contains("li.ant-select-dropdown-menu-item", "b").click();
+ cy.contains(".ant-select-item-option-content", "b").click();
cy.getByTestId("FilterName-stage1::multi-filter").click(); // close dropdown
expectSelectedOptionsToHaveMembers(["a", "b"]);
@@ -86,7 +85,7 @@ describe("Query Filters", () => {
// Clear Option
cy.getByTestId("FilterName-stage1::multi-filter")
- .find(".ant-select-selection")
+ .find(".ant-select-selector")
.click();
cy.getByTestId("ClearOption").click();
cy.getByTestId("FilterName-stage1::multi-filter").click(); // close dropdown
@@ -96,7 +95,7 @@ describe("Query Filters", () => {
// Select All Option
cy.getByTestId("FilterName-stage1::multi-filter")
- .find(".ant-select-selection")
+ .find(".ant-select-selector")
.click();
cy.getByTestId("SelectAllOption").click();
cy.getByTestId("FilterName-stage1::multi-filter").click(); // close dropdown
diff --git a/client/cypress/integration/query/parameter_spec.js b/client/cypress/integration/query/parameter_spec.js
index a415e4581a..d297522a47 100644
--- a/client/cypress/integration/query/parameter_spec.js
+++ b/client/cypress/integration/query/parameter_spec.js
@@ -1,5 +1,3 @@
-import { createQuery } from "../../support/redash-api";
-
describe("Parameter", () => {
const expectDirtyStateChange = edit => {
cy.getByTestId("ParameterName-test-parameter")
@@ -31,7 +29,7 @@ describe("Parameter", () => {
},
};
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}`));
+ cy.createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}`));
});
it("updates the results after clicking Apply", () => {
@@ -63,7 +61,7 @@ describe("Parameter", () => {
},
};
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}`));
+ cy.createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}`));
});
it("updates the results after clicking Apply", () => {
@@ -105,7 +103,7 @@ describe("Parameter", () => {
},
};
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
+ cy.createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
});
it("updates the results after selecting a value", () => {
@@ -113,7 +111,7 @@ describe("Parameter", () => {
.find(".ant-select")
.click();
- cy.contains("li.ant-select-dropdown-menu-item", "value2").click();
+ cy.contains(".ant-select-item-option", "value2").click();
cy.getByTestId("ParameterApplyButton").click();
// ensure that query is being executed
@@ -132,12 +130,12 @@ describe("Parameter", () => {
`);
cy.getByTestId("ParameterName-test-parameter")
- .find(".ant-select")
+ .find(".ant-select-selection-search")
.click();
// select all unselected options
- cy.get("li.ant-select-dropdown-menu-item").each($option => {
- if (!$option.hasClass("ant-select-dropdown-menu-item-selected")) {
+ cy.get(".ant-select-item-option").each($option => {
+ if (!$option.hasClass("ant-select-item-option-selected")) {
cy.wrap($option).click();
}
});
@@ -155,7 +153,7 @@ describe("Parameter", () => {
.find(".ant-select")
.click();
- cy.contains("li.ant-select-dropdown-menu-item", "value2").click();
+ cy.contains(".ant-select-item-option", "value2").click();
});
});
});
@@ -167,7 +165,7 @@ describe("Parameter", () => {
name: "Dropdown Query",
query: "",
};
- createQuery(dropdownQueryData, true).then(dropdownQuery => {
+ cy.createQuery(dropdownQueryData, true).then(dropdownQuery => {
const queryData = {
name: "Query Based Dropdown Parameter",
query: "SELECT '{{test-parameter}}' AS parameter",
@@ -178,16 +176,16 @@ describe("Parameter", () => {
},
};
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
+ cy.createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
});
});
it("should show a 'No options available' message when you click", () => {
cy.getByTestId("ParameterName-test-parameter")
- .find(".ant-select:not(.ant-select-disabled) .ant-select-selection")
+ .find(".ant-select:not(.ant-select-disabled) .ant-select-selector")
.click();
- cy.contains("li.ant-select-dropdown-menu-item", "No options available");
+ cy.contains(".ant-select-item-empty", "No options available");
});
});
@@ -199,7 +197,7 @@ describe("Parameter", () => {
SELECT 'value2' AS name, 2 AS value UNION ALL
SELECT 'value3' AS name, 3 AS value`,
};
- createQuery(dropdownQueryData, true).then(dropdownQuery => {
+ cy.createQuery(dropdownQueryData, true).then(dropdownQuery => {
const queryData = {
name: "Query Based Dropdown Parameter",
query: "SELECT '{{test-parameter}}' AS parameter",
@@ -217,7 +215,7 @@ describe("Parameter", () => {
.and("contain", "value2")
.and("contain", "value3");
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
+ cy.createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
});
});
@@ -235,7 +233,7 @@ describe("Parameter", () => {
.click();
// make sure all options are unselected and select all
- cy.get("li.ant-select-dropdown-menu-item").each($option => {
+ cy.get(".ant-select-item-option").each($option => {
expect($option).not.to.have.class("ant-select-dropdown-menu-item-selected");
cy.wrap($option).click();
});
@@ -249,17 +247,17 @@ describe("Parameter", () => {
});
});
- describe("Date Parameter", () => {
- const selectCalendarDate = date => {
- cy.getByTestId("ParameterName-test-parameter")
- .find("input")
- .click();
+ const selectCalendarDate = date => {
+ cy.getByTestId("ParameterName-test-parameter")
+ .find("input")
+ .click();
- cy.get(".ant-calendar-date-panel")
- .contains(".ant-calendar-date", date)
- .click();
- };
+ cy.get(".ant-picker-panel")
+ .contains(".ant-picker-cell-inner", date)
+ .click();
+ };
+ describe("Date Parameter", () => {
beforeEach(() => {
const queryData = {
name: "Date Parameter",
@@ -274,7 +272,7 @@ describe("Parameter", () => {
cy.wrap(now.getTime()).as("now");
cy.clock(now.getTime(), ["Date"]);
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}`));
+ cy.createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}`));
});
afterEach(() => {
@@ -321,7 +319,7 @@ describe("Parameter", () => {
cy.wrap(now.getTime()).as("now");
cy.clock(now.getTime(), ["Date"]);
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}`));
+ cy.createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}`));
});
afterEach(() => {
@@ -334,11 +332,9 @@ describe("Parameter", () => {
.as("Input")
.click();
- cy.get(".ant-calendar-date-panel")
- .contains(".ant-calendar-date", "15")
- .click();
+ selectCalendarDate("15");
- cy.get(".ant-calendar-ok-btn").click();
+ cy.get(".ant-picker-ok button").click();
cy.getByTestId("ParameterApplyButton").click();
@@ -351,7 +347,7 @@ describe("Parameter", () => {
.as("Input")
.click();
- cy.get(".ant-calendar-date-panel")
+ cy.get(".ant-picker-panel")
.contains("Now")
.click();
@@ -378,7 +374,7 @@ describe("Parameter", () => {
.find("input")
.click();
- cy.get(".ant-calendar-date-panel")
+ cy.get(".ant-picker-panel")
.contains("Now")
.click();
});
@@ -392,12 +388,12 @@ describe("Parameter", () => {
.first()
.click();
- cy.get(".ant-calendar-date-panel")
- .contains(".ant-calendar-date", startDate)
+ cy.get(".ant-picker-panel")
+ .contains(".ant-picker-cell-inner", startDate)
.click();
- cy.get(".ant-calendar-date-panel")
- .contains(".ant-calendar-date", endDate)
+ cy.get(".ant-picker-panel")
+ .contains(".ant-picker-cell-inner", endDate)
.click();
};
@@ -415,7 +411,7 @@ describe("Parameter", () => {
cy.wrap(now.getTime()).as("now");
cy.clock(now.getTime(), ["Date"]);
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
+ cy.createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
});
afterEach(() => {
@@ -469,7 +465,7 @@ describe("Parameter", () => {
cy.location("search").should("not.contain", "Redash");
cy.server();
- cy.route("POST", "api/queries/*/results").as("Results");
+ cy.route("POST", "**/api/queries/*/results").as("Results");
apply(cy.get("@Input"));
@@ -489,7 +485,12 @@ describe("Parameter", () => {
},
};
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
+ cy.server();
+ cy.route("GET", "**/api/data_sources/*/schema").as("Schema");
+
+ cy.createQuery(queryData, false)
+ .then(({ id }) => cy.visit(`/queries/${id}/source`))
+ .then(() => cy.wait("@Schema"));
});
it("shows and hides according to parameter dirty state", () => {
@@ -564,7 +565,7 @@ describe("Parameter", () => {
},
};
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
+ cy.createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
cy.get(".parameter-block")
.first()
@@ -586,7 +587,7 @@ describe("Parameter", () => {
it("is possible to rearrange parameters", function() {
cy.server();
- cy.route("POST", "api/queries/*").as("QuerySave");
+ cy.route("POST", "**/api/queries/*").as("QuerySave");
dragParam("param1", this.paramWidth, 1);
cy.wait("@QuerySave");
@@ -610,7 +611,7 @@ describe("Parameter", () => {
},
};
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
+ cy.createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}/source`));
cy.getByTestId("ParameterSettings-parameter").click();
});
diff --git a/client/cypress/integration/query/query_tags_spec.js b/client/cypress/integration/query/query_tags_spec.js
index 48aae533c7..0c8e01099d 100644
--- a/client/cypress/integration/query/query_tags_spec.js
+++ b/client/cypress/integration/query/query_tags_spec.js
@@ -1,4 +1,3 @@
-import { createQuery } from "../../support/redash-api";
import { expectTagsToContain, typeInTagsSelectAndSave } from "../../support/tags";
describe("Query Tags", () => {
@@ -10,12 +9,12 @@ describe("Query Tags", () => {
query: "SELECT 1 as value",
};
- createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}`));
+ cy.createQuery(queryData, false).then(({ id }) => cy.visit(`/queries/${id}`));
});
it("is possible to add and edit tags", () => {
cy.server();
- cy.route("POST", "api/queries/*").as("QuerySave");
+ cy.route("POST", "**/api/queries/*").as("QuerySave");
cy.getByTestId("TagsControl").contains(".label", "Unpublished");
@@ -23,13 +22,13 @@ describe("Query Tags", () => {
.should("contain", "Add tag")
.click();
- typeInTagsSelectAndSave("tag1{enter}tag2{enter}tag3{enter}{esc}");
+ typeInTagsSelectAndSave("tag1{enter}tag2{enter}tag3{enter}");
cy.wait("@QuerySave");
expectTagsToContain(["tag1", "tag2", "tag3"]);
cy.getByTestId("EditTagsButton").click();
- typeInTagsSelectAndSave("tag4{enter}{esc}");
+ typeInTagsSelectAndSave("tag4{enter}");
cy.wait("@QuerySave");
cy.reload();
diff --git a/client/cypress/integration/settings/organization_settings_spec.js b/client/cypress/integration/settings/organization_settings_spec.js
index b8fa7bfb60..85d884634a 100644
--- a/client/cypress/integration/settings/organization_settings_spec.js
+++ b/client/cypress/integration/settings/organization_settings_spec.js
@@ -1,7 +1,7 @@
describe("Settings", () => {
beforeEach(() => {
cy.login();
- cy.visit("/settings/organization");
+ cy.visit("/settings/general");
});
it("renders the page and takes a screenshot", () => {
diff --git a/client/cypress/integration/settings/settings_tabs_spec.js b/client/cypress/integration/settings/settings_tabs_spec.js
index 5c4ace6428..d67886b53c 100644
--- a/client/cypress/integration/settings/settings_tabs_spec.js
+++ b/client/cypress/integration/settings/settings_tabs_spec.js
@@ -1,5 +1,3 @@
-import { createUser } from "../../support/redash-api";
-
describe("Settings Tabs", () => {
const regularUser = {
name: "Example User",
@@ -8,7 +6,7 @@ describe("Settings Tabs", () => {
};
const userTabs = ["Users", "Groups", "Query Snippets", "Account"];
- const adminTabs = ["Data Sources", "Alert Destinations", "Settings"];
+ const adminTabs = ["Data Sources", "Alert Destinations", "General"];
const expectSettingsTabsToBe = expectedTabs =>
cy.getByTestId("SettingsScreenItem").then($list => {
@@ -17,7 +15,7 @@ describe("Settings Tabs", () => {
});
before(() => {
- cy.login().then(() => createUser(regularUser));
+ cy.login().then(() => cy.createUser(regularUser));
});
describe("For admin user", () => {
diff --git a/client/cypress/integration/visualizations/box_plot_spec.js b/client/cypress/integration/visualizations/box_plot_spec.js
index 49fa00c528..84cb9f4634 100644
--- a/client/cypress/integration/visualizations/box_plot_spec.js
+++ b/client/cypress/integration/visualizations/box_plot_spec.js
@@ -1,7 +1,5 @@
/* global cy, Cypress */
-import { createQuery, createVisualization } from "../../support/redash-api";
-
const SQL = `
SELECT 12 AS mn, 4967 AS mx UNION ALL
SELECT 10 AS mn, 19430 AS mx UNION ALL
@@ -42,8 +40,8 @@ describe("Box Plot", () => {
beforeEach(() => {
cy.login();
- createQuery({ query: SQL })
- .then(({ id }) => createVisualization(id, "BOXPLOT", "Boxplot (Deprecated)", {}))
+ cy.createQuery({ query: SQL })
+ .then(({ id }) => cy.createVisualization(id, "BOXPLOT", "Boxplot (Deprecated)", {}))
.then(({ id: visualizationId, query_id: queryId }) => {
cy.visit(`queries/${queryId}/source#${visualizationId}`);
cy.getByTestId("ExecuteButton").click();
diff --git a/client/cypress/integration/visualizations/choropleth_spec.js b/client/cypress/integration/visualizations/choropleth_spec.js
index d9199f8e3f..b8d0003515 100644
--- a/client/cypress/integration/visualizations/choropleth_spec.js
+++ b/client/cypress/integration/visualizations/choropleth_spec.js
@@ -1,7 +1,5 @@
/* global cy */
-import { createQuery } from "../../support/redash-api";
-
const SQL = `
SELECT 'AR' AS "code", 'Argentina' AS "name", 37.62 AS "value" UNION ALL
SELECT 'AU' AS "code", 'Australia' AS "name", 37.62 AS "value" UNION ALL
@@ -34,7 +32,7 @@ describe("Choropleth", () => {
beforeEach(() => {
cy.login();
- createQuery({ query: SQL }).then(({ id }) => {
+ cy.createQuery({ query: SQL }).then(({ id }) => {
cy.visit(`queries/${id}/source`);
cy.getByTestId("ExecuteButton").click();
});
diff --git a/client/cypress/integration/visualizations/cohort_spec.js b/client/cypress/integration/visualizations/cohort_spec.js
index cb42026dca..87e168e82f 100644
--- a/client/cypress/integration/visualizations/cohort_spec.js
+++ b/client/cypress/integration/visualizations/cohort_spec.js
@@ -1,7 +1,5 @@
/* global cy, Cypress */
-import { createQuery } from "../../support/redash-api";
-
const SQL = `
SELECT '2019-01-01' AS "date", 21 AS "bucket", 5 AS "value", 1 AS "stage" UNION ALL
SELECT '2019-01-01' AS "date", 21 AS "bucket", 8 AS "value", 2 AS "stage" UNION ALL
@@ -24,7 +22,7 @@ describe("Cohort", () => {
beforeEach(() => {
cy.login();
- createQuery({ query: SQL }).then(({ id }) => {
+ cy.createQuery({ query: SQL }).then(({ id }) => {
cy.visit(`queries/${id}/source`);
cy.getByTestId("ExecuteButton").click();
});
diff --git a/client/cypress/integration/visualizations/counter_spec.js b/client/cypress/integration/visualizations/counter_spec.js
index b52f8454f4..206e0130f4 100644
--- a/client/cypress/integration/visualizations/counter_spec.js
+++ b/client/cypress/integration/visualizations/counter_spec.js
@@ -1,7 +1,5 @@
/* global cy, Cypress */
-import { createQuery } from "../../support/redash-api";
-
const SQL = `
SELECT 27182.8182846 AS a, 20000 AS b, 'lorem' AS c UNION ALL
SELECT 31415.9265359 AS a, 40000 AS b, 'ipsum' AS c
@@ -12,7 +10,7 @@ describe("Counter", () => {
beforeEach(() => {
cy.login();
- createQuery({ query: SQL }).then(({ id }) => {
+ cy.createQuery({ query: SQL }).then(({ id }) => {
cy.visit(`queries/${id}/source`);
cy.getByTestId("ExecuteButton").click();
});
diff --git a/client/cypress/integration/visualizations/edit_visualization_dialog_spec.js b/client/cypress/integration/visualizations/edit_visualization_dialog_spec.js
index e54b53581b..494bb22290 100644
--- a/client/cypress/integration/visualizations/edit_visualization_dialog_spec.js
+++ b/client/cypress/integration/visualizations/edit_visualization_dialog_spec.js
@@ -1,11 +1,9 @@
/* global cy */
-import { createQuery } from "../../support/redash-api";
-
describe("Edit visualization dialog", () => {
beforeEach(() => {
cy.login();
- createQuery().then(({ id }) => {
+ cy.createQuery().then(({ id }) => {
cy.visit(`queries/${id}/source`);
cy.getByTestId("ExecuteButton").click();
});
diff --git a/client/cypress/integration/visualizations/funnel_spec.js b/client/cypress/integration/visualizations/funnel_spec.js
index 4ccab3ecf2..71e3c16038 100644
--- a/client/cypress/integration/visualizations/funnel_spec.js
+++ b/client/cypress/integration/visualizations/funnel_spec.js
@@ -1,7 +1,5 @@
/* global cy, Cypress */
-import { createQuery } from "../../support/redash-api";
-
const SQL = `
SELECT 'a.01' AS a, 1.758831600227 AS b UNION ALL
SELECT 'a.02' AS a, 613.4456936572 AS b UNION ALL
@@ -25,7 +23,7 @@ describe("Funnel", () => {
beforeEach(() => {
cy.login();
- createQuery({ query: SQL }).then(({ id }) => {
+ cy.createQuery({ query: SQL }).then(({ id }) => {
cy.visit(`queries/${id}/source`);
cy.getByTestId("ExecuteButton").click();
});
diff --git a/client/cypress/integration/visualizations/map_spec.js b/client/cypress/integration/visualizations/map_spec.js
index 693a6eb910..223540752a 100644
--- a/client/cypress/integration/visualizations/map_spec.js
+++ b/client/cypress/integration/visualizations/map_spec.js
@@ -1,7 +1,5 @@
/* global cy */
-import { createQuery, createVisualization } from "../../support/redash-api";
-
const SQL = `
SELECT 'Israel' AS country, 32.0808800 AS lat, 34.7805700 AS lng UNION ALL
SELECT 'Israel' AS country, 31.7690400 AS lat, 35.2163300 AS lng UNION ALL
@@ -22,8 +20,8 @@ describe("Map (Markers)", () => {
const mapTileUrl = "/static/images/fixtures/map-tile.png";
- createQuery({ query: SQL })
- .then(({ id }) => createVisualization(id, "MAP", "Map (Markers)", { mapTileUrl }))
+ cy.createQuery({ query: SQL })
+ .then(({ id }) => cy.createVisualization(id, "MAP", "Map (Markers)", { mapTileUrl }))
.then(({ id: visualizationId, query_id: queryId }) => {
cy.visit(`queries/${queryId}/source#${visualizationId}`);
cy.getByTestId("ExecuteButton").click();
diff --git a/client/cypress/integration/visualizations/pivot_spec.js b/client/cypress/integration/visualizations/pivot_spec.js
index 54d4cf53ab..74e5ab5e62 100644
--- a/client/cypress/integration/visualizations/pivot_spec.js
+++ b/client/cypress/integration/visualizations/pivot_spec.js
@@ -1,10 +1,7 @@
-/* global cy, Cypress */
+/* global cy */
-import { createQuery, createVisualization, createDashboard, addWidget } from "../../support/redash-api";
import { getWidgetTestId } from "../../support/dashboard";
-const { get } = Cypress._;
-
const SQL = `
SELECT 'a' AS stage1, 'a1' AS stage2, 11 AS value UNION ALL
SELECT 'a' AS stage1, 'a2' AS stage2, 12 AS value UNION ALL
@@ -44,7 +41,7 @@ function createPivotThroughUI(visualizationName, options = {}) {
describe("Pivot", () => {
beforeEach(() => {
cy.login();
- createQuery({ name: "Pivot Visualization", query: SQL })
+ cy.createQuery({ name: "Pivot Visualization", query: SQL })
.its("id")
.as("queryId");
});
@@ -68,18 +65,16 @@ describe("Pivot", () => {
const visualizationName = "Pivot";
cy.server();
- cy.route("POST", "api/visualizations").as("SaveVisualization");
+ cy.route("POST", "**/api/visualizations").as("SaveVisualization");
createPivotThroughUI(visualizationName, { hideControls: true });
- cy.wait("@SaveVisualization").then(xhr => {
- const visualizationId = get(xhr, "response.body.id");
- // Added visualization should also have hidden controls
- cy.getByTestId(`QueryPageVisualization${visualizationId}`)
- .find("table")
- .find(".pvtAxisContainer, .pvtRenderer, .pvtVals")
- .should("be.not.visible");
- });
+ cy.wait("@SaveVisualization");
+ // Added visualization should also have hidden controls
+ cy.getByTestId("PivotTableVisualization")
+ .find("table")
+ .find(".pvtAxisContainer, .pvtRenderer, .pvtVals")
+ .should("be.not.visible");
});
it("updates the visualization when results change", function() {
@@ -92,12 +87,12 @@ describe("Pivot", () => {
vals: ["value"],
};
- createVisualization(this.queryId, "PIVOT", "Pivot", options).then(visualization => {
+ cy.createVisualization(this.queryId, "PIVOT", "Pivot", options).then(visualization => {
cy.visit(`queries/${this.queryId}/source#${visualization.id}`);
cy.getByTestId("ExecuteButton").click();
// assert number of rows is 11
- cy.getByTestId(`QueryPageVisualization${visualization.id}`).contains(".pvtGrandTotal", "11");
+ cy.getByTestId("PivotTableVisualization").contains(".pvtGrandTotal", "11");
cy.getByTestId("QueryEditor")
.get(".ace_text-input")
@@ -109,7 +104,7 @@ describe("Pivot", () => {
cy.getByTestId("ExecuteButton").click();
// assert number of rows is 12
- cy.getByTestId(`QueryPageVisualization${visualization.id}`).contains(".pvtGrandTotal", "12");
+ cy.getByTestId("PivotTableVisualization").contains(".pvtGrandTotal", "12");
});
});
@@ -141,14 +136,14 @@ describe("Pivot", () => {
},
];
- createDashboard("Pivot Visualization")
+ cy.createDashboard("Pivot Visualization")
.then(dashboard => {
- this.dashboardUrl = `/dashboard/${dashboard.slug}`;
+ this.dashboardUrl = `/dashboards/${dashboard.id}`;
return cy.all(
pivotTables.map(pivot => () =>
- createVisualization(this.queryId, "PIVOT", pivot.name, pivot.options).then(visualization =>
- addWidget(dashboard.id, visualization.id, { position: pivot.position })
- )
+ cy
+ .createVisualization(this.queryId, "PIVOT", pivot.name, pivot.options)
+ .then(visualization => cy.addWidget(dashboard.id, visualization.id, { position: pivot.position }))
)
);
})
diff --git a/client/cypress/integration/visualizations/sankey_sunburst_spec.js b/client/cypress/integration/visualizations/sankey_sunburst_spec.js
index 5bb8eda9e9..1a5130efbf 100644
--- a/client/cypress/integration/visualizations/sankey_sunburst_spec.js
+++ b/client/cypress/integration/visualizations/sankey_sunburst_spec.js
@@ -1,6 +1,5 @@
/* global cy */
-import { createQuery, createDashboard, createVisualization, addWidget } from "../../support/redash-api";
import { getWidgetTestId } from "../../support/dashboard";
const SQL = `
@@ -24,7 +23,7 @@ describe("Sankey and Sunburst", () => {
describe("Creation through UI", () => {
beforeEach(() => {
- createQuery({ query: SQL }).then(({ id }) => {
+ cy.createQuery({ query: SQL }).then(({ id }) => {
cy.visit(`queries/${id}/source`);
cy.getByTestId("ExecuteButton").click();
});
@@ -98,14 +97,15 @@ describe("Sankey and Sunburst", () => {
];
it("takes a snapshot with Sunburst (1 - 5 stages)", function() {
- createDashboard("Sunburst Visualization").then(dashboard => {
- this.dashboardUrl = `/dashboard/${dashboard.slug}`;
+ cy.createDashboard("Sunburst Visualization").then(dashboard => {
+ this.dashboardUrl = `/dashboards/${dashboard.id}`;
return cy
.all(
STAGES_WIDGETS.map(sunburst => () =>
- createQuery({ name: `Sunburst with ${sunburst.name}`, query: sunburst.query })
- .then(queryData => createVisualization(queryData.id, "SUNBURST_SEQUENCE", "Sunburst", {}))
- .then(visualization => addWidget(dashboard.id, visualization.id, { position: sunburst.position }))
+ cy
+ .createQuery({ name: `Sunburst with ${sunburst.name}`, query: sunburst.query })
+ .then(queryData => cy.createVisualization(queryData.id, "SUNBURST_SEQUENCE", "Sunburst", {}))
+ .then(visualization => cy.addWidget(dashboard.id, visualization.id, { position: sunburst.position }))
)
)
.then(widgets => {
@@ -122,14 +122,15 @@ describe("Sankey and Sunburst", () => {
});
it("takes a snapshot with Sankey (1 - 5 stages)", function() {
- createDashboard("Sankey Visualization").then(dashboard => {
- this.dashboardUrl = `/dashboard/${dashboard.slug}`;
+ cy.createDashboard("Sankey Visualization").then(dashboard => {
+ this.dashboardUrl = `/dashboards/${dashboard.id}`;
return cy
.all(
STAGES_WIDGETS.map(sankey => () =>
- createQuery({ name: `Sankey with ${sankey.name}`, query: sankey.query })
- .then(queryData => createVisualization(queryData.id, "SANKEY", "Sankey", {}))
- .then(visualization => addWidget(dashboard.id, visualization.id, { position: sankey.position }))
+ cy
+ .createQuery({ name: `Sankey with ${sankey.name}`, query: sankey.query })
+ .then(queryData => cy.createVisualization(queryData.id, "SANKEY", "Sankey", {}))
+ .then(visualization => cy.addWidget(dashboard.id, visualization.id, { position: sankey.position }))
)
)
.then(widgets => {
diff --git a/client/cypress/integration/visualizations/table/table_spec.js b/client/cypress/integration/visualizations/table/table_spec.js
index 0104c2ee0e..b0fa8ec61c 100644
--- a/client/cypress/integration/visualizations/table/table_spec.js
+++ b/client/cypress/integration/visualizations/table/table_spec.js
@@ -4,15 +4,15 @@
This test suite relies on Percy (does not validate rendered visualizations)
*/
-import { createQuery, createVisualization } from "../../../support/redash-api";
import * as AllCellTypes from "./.mocks/all-cell-types";
import * as MultiColumnSort from "./.mocks/multi-column-sort";
import * as SearchInData from "./.mocks/search-in-data";
import * as LargeDataset from "./.mocks/large-dataset";
function prepareVisualization(query, type, name, options) {
- return createQuery({ query })
- .then(({ id }) => createVisualization(id, type, name, options))
+ return cy
+ .createQuery({ query })
+ .then(({ id }) => cy.createVisualization(id, type, name, options))
.then(({ id: visualizationId, query_id: queryId }) => {
// use data-only view because we don't need editor features, but it will
// free more space for visualizations. Also, we'll hide schema browser (via shortcut)
@@ -22,7 +22,7 @@ function prepareVisualization(query, type, name, options) {
cy.get("body").type("{alt}D");
// do some pre-checks here to ensure that visualization was created and is visible
- cy.getByTestId(`QueryPageVisualization${visualizationId}`)
+ cy.getByTestId("TableVisualization")
.should("exist")
.find("table")
.should("exist");
@@ -41,13 +41,12 @@ describe("Table", () => {
it("renders all cell types", () => {
const { query, config } = AllCellTypes;
prepareVisualization(query, "TABLE", "All cell types", config).then(() => {
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(500); // add some waiting to avoid an async update error from .jvi-toggle
+
// expand JSON cell
- cy.get(".jvi-item.jvi-root .jvi-toggle")
- .should("exist")
- .click();
- cy.get(".jvi-item.jvi-root .jvi-item .jvi-toggle")
- .should("exist")
- .click({ multiple: true });
+ cy.get(".jvi-item.jvi-root .jvi-toggle").click();
+ cy.get(".jvi-item.jvi-root .jvi-item .jvi-toggle").click({ multiple: true });
cy.percySnapshot("Visualizations - Table (All cell types)", { widths: [viewportWidth] });
});
@@ -63,9 +62,7 @@ describe("Table", () => {
});
it("sorts data by a single column", function() {
- const { visualizationId } = this;
-
- cy.getByTestId(`QueryPageVisualization${visualizationId}`)
+ cy.getByTestId("TableVisualization")
.find("table th")
.contains("c")
.should("exist")
@@ -74,16 +71,14 @@ describe("Table", () => {
});
it("sorts data by a multiple columns", function() {
- const { visualizationId } = this;
-
- cy.getByTestId(`QueryPageVisualization${visualizationId}`)
+ cy.getByTestId("TableVisualization")
.find("table th")
.contains("a")
.should("exist")
.click();
cy.get("body").type("{shift}", { release: false });
- cy.getByTestId(`QueryPageVisualization${visualizationId}`)
+ cy.getByTestId("TableVisualization")
.find("table th")
.contains("b")
.should("exist")
@@ -93,9 +88,7 @@ describe("Table", () => {
});
it("sorts data in reverse order", function() {
- const { visualizationId } = this;
-
- cy.getByTestId(`QueryPageVisualization${visualizationId}`)
+ cy.getByTestId("TableVisualization")
.find("table th")
.contains("c")
.should("exist")
@@ -108,7 +101,7 @@ describe("Table", () => {
it("searches in multiple columns", () => {
const { query, config } = SearchInData;
prepareVisualization(query, "TABLE", "Search", config).then(({ visualizationId }) => {
- cy.getByTestId(`QueryPageVisualization${visualizationId}`)
+ cy.getByTestId("TableVisualization")
.find("table input")
.should("exist")
.type("test");
@@ -119,7 +112,7 @@ describe("Table", () => {
it("shows pagination and navigates to third page", () => {
const { query, config } = LargeDataset;
prepareVisualization(query, "TABLE", "With pagination", config).then(({ visualizationId }) => {
- cy.getByTestId(`QueryPageVisualization${visualizationId}`)
+ cy.get(".visualization-renderer")
.find(".ant-table-pagination")
.should("exist")
.find("li")
diff --git a/client/cypress/integration/visualizations/word_cloud_spec.js b/client/cypress/integration/visualizations/word_cloud_spec.js
index 78663f1738..27c029a8e2 100644
--- a/client/cypress/integration/visualizations/word_cloud_spec.js
+++ b/client/cypress/integration/visualizations/word_cloud_spec.js
@@ -1,7 +1,5 @@
/* global cy, Cypress */
-import { createQuery } from "../../support/redash-api";
-
const { map } = Cypress._;
const SQL = `
@@ -64,7 +62,7 @@ describe("Word Cloud", () => {
beforeEach(() => {
cy.login();
- createQuery({ query: SQL }).then(({ id }) => {
+ cy.createQuery({ query: SQL }).then(({ id }) => {
cy.visit(`queries/${id}/source`);
cy.getByTestId("ExecuteButton").click();
});
diff --git a/client/cypress/support/commands.js b/client/cypress/support/commands.js
index 1ac5aef0ec..a9245f3f1c 100644
--- a/client/cypress/support/commands.js
+++ b/client/cypress/support/commands.js
@@ -4,17 +4,36 @@ import "@percy/cypress"; // eslint-disable-line import/no-extraneous-dependencie
const { each } = Cypress._;
-Cypress.Commands.add("login", (email = "admin@redash.io", password = "password") =>
- cy.request({
- url: "/login",
- method: "POST",
- form: true,
- body: {
- email,
- password,
- },
- })
-);
+Cypress.Commands.add("login", (email = "admin@redash.io", password = "password") => {
+ let csrf;
+ cy.visit("/login");
+ cy.getCookie("csrf_token")
+ .then(cookie => {
+ if (cookie) {
+ csrf = cookie.value;
+ } else {
+ cy.visit("/login").then(() => {
+ cy.get('input[name="csrf_token"]')
+ .invoke("val")
+ .then(csrf_token => {
+ csrf = csrf_token;
+ });
+ });
+ }
+ })
+ .then(() => {
+ cy.request({
+ url: "/login",
+ method: "POST",
+ form: true,
+ body: {
+ email,
+ password,
+ csrf_token: csrf,
+ },
+ });
+ });
+});
Cypress.Commands.add("logout", () => cy.visit("/logout"));
Cypress.Commands.add("getByTestId", element => cy.get('[data-test="' + element + '"]'));
diff --git a/client/cypress/support/dashboard/index.js b/client/cypress/support/dashboard/index.js
index 238949bcef..1f92bc249b 100644
--- a/client/cypress/support/dashboard/index.js
+++ b/client/cypress/support/dashboard/index.js
@@ -1,7 +1,5 @@
/* global cy */
-import { createQuery, addWidget } from "../redash-api";
-
const { get } = Cypress._;
const RESIZE_HANDLE_SELECTOR = ".react-resizable-handle";
@@ -10,11 +8,12 @@ export function getWidgetTestId(widget) {
}
export function createQueryAndAddWidget(dashboardId, queryData = {}, widgetOptions = {}) {
- return createQuery(queryData)
+ return cy
+ .createQuery(queryData)
.then(query => {
const visualizationId = get(query, "visualizations.0.id");
assert.isDefined(visualizationId, "Query api call returns at least one visualization with id");
- return addWidget(dashboardId, visualizationId, widgetOptions);
+ return cy.addWidget(dashboardId, visualizationId, widgetOptions);
})
.then(getWidgetTestId);
}
diff --git a/client/cypress/support/index.js b/client/cypress/support/index.js
index f887c29aea..90950663a2 100644
--- a/client/cypress/support/index.js
+++ b/client/cypress/support/index.js
@@ -1 +1,13 @@
+/* global Cypress */
+
import "./commands";
+import "./redash-api/index.js";
+
+Cypress.env("dataSourceId", 1);
+
+Cypress.on("uncaught:exception", err => {
+ // Prevent ResizeObserver error from failing tests
+ if (err && Cypress._.includes(err.message, "ResizeObserver loop limit exceeded")) {
+ return false;
+ }
+});
diff --git a/client/cypress/support/redash-api/index.js b/client/cypress/support/redash-api/index.js
index 647ff620cc..1292f9e1a6 100644
--- a/client/cypress/support/redash-api/index.js
+++ b/client/cypress/support/redash-api/index.js
@@ -2,16 +2,21 @@
const { extend, get, merge, find } = Cypress._;
-export function createDashboard(name) {
- return cy.request("POST", "api/dashboards", { name }).then(({ body }) => body);
-}
+const post = options =>
+ cy
+ .getCookie("csrf_token")
+ .then(csrf => cy.request({ ...options, method: "POST", headers: { "X-CSRF-TOKEN": csrf.value } }));
-export function createQuery(data, shouldPublish = true) {
+Cypress.Commands.add("createDashboard", name => {
+ return post({ url: "api/dashboards", body: { name } }).then(({ body }) => body);
+});
+
+Cypress.Commands.add("createQuery", (data, shouldPublish = true) => {
const merged = extend(
{
name: "Test Query",
query: "select 1",
- data_source_id: 1,
+ data_source_id: Cypress.env("dataSourceId"),
options: {
parameters: [],
},
@@ -21,25 +26,25 @@ export function createQuery(data, shouldPublish = true) {
);
// eslint-disable-next-line cypress/no-assigning-return-values
- let request = cy.request("POST", "/api/queries", merged).then(({ body }) => body);
+ let request = post({ url: "/api/queries", body: merged }).then(({ body }) => body);
if (shouldPublish) {
request = request.then(query =>
- cy.request("POST", `/api/queries/${query.id}`, { is_draft: false }).then(() => query)
+ post({ url: `/api/queries/${query.id}`, body: { is_draft: false } }).then(() => query)
);
}
return request;
-}
+});
-export function createVisualization(queryId, type, name, options) {
+Cypress.Commands.add("createVisualization", (queryId, type, name, options) => {
const data = { query_id: queryId, type, name, options };
- return cy.request("POST", "/api/visualizations", data).then(({ body }) => ({
+ return post({ url: "/api/visualizations", body: data }).then(({ body }) => ({
query_id: queryId,
...body,
}));
-}
+});
-export function addTextbox(dashboardId, text = "text", options = {}) {
+Cypress.Commands.add("addTextbox", (dashboardId, text = "text", options = {}) => {
const defaultOptions = {
position: { col: 0, row: 0, sizeX: 3, sizeY: 3 },
};
@@ -52,14 +57,14 @@ export function addTextbox(dashboardId, text = "text", options = {}) {
options: merge(defaultOptions, options),
};
- return cy.request("POST", "api/widgets", data).then(({ body }) => {
+ return post({ url: "api/widgets", body: data }).then(({ body }) => {
const id = get(body, "id");
assert.isDefined(id, "Widget api call returns widget id");
return body;
});
-}
+});
-export function addWidget(dashboardId, visualizationId, options = {}) {
+Cypress.Commands.add("addWidget", (dashboardId, visualizationId, options = {}) => {
const defaultOptions = {
position: { col: 0, row: 0, sizeX: 3, sizeY: 3 },
};
@@ -71,14 +76,14 @@ export function addWidget(dashboardId, visualizationId, options = {}) {
options: merge(defaultOptions, options),
};
- return cy.request("POST", "api/widgets", data).then(({ body }) => {
+ return post({ url: "api/widgets", body: data }).then(({ body }) => {
const id = get(body, "id");
assert.isDefined(id, "Widget api call returns widget id");
return body;
});
-}
+});
-export function createAlert(queryId, options = {}, name) {
+Cypress.Commands.add("createAlert", (queryId, options = {}, name) => {
const defaultOptions = {
column: "?column?",
op: "greater than",
@@ -92,67 +97,66 @@ export function createAlert(queryId, options = {}, name) {
options: merge(defaultOptions, options),
};
- return cy.request("POST", "api/alerts", data).then(({ body }) => {
+ return post({ url: "api/alerts", body: data }).then(({ body }) => {
const id = get(body, "id");
- assert.isDefined(id, "Alert api call returns alert id");
+ assert.isDefined(id, "Alert api call retu ns alert id");
return body;
});
-}
+});
-export function createUser({ name, email, password }) {
- return cy
- .request({
- method: "POST",
- url: "api/users?no_invite=yes",
- body: { name, email },
- failOnStatusCode: false,
- })
- .then(xhr => {
- const { status, body } = xhr;
- if (status < 200 || status > 400) {
- throw new Error(xhr);
- }
+Cypress.Commands.add("createUser", ({ name, email, password }) => {
+ return post({
+ url: "api/users?no_invite=yes",
+ body: { name, email },
+ failOnStatusCode: false,
+ }).then(xhr => {
+ const { status, body } = xhr;
+ if (status < 200 || status > 400) {
+ throw new Error(xhr);
+ }
- if (status === 400 && body.message === "Email already taken.") {
- // all is good, do nothing
- return;
- }
+ if (status === 400 && body.message === "Email already taken.") {
+ // all is good, do nothing
+ return;
+ }
- const id = get(body, "id");
- assert.isDefined(id, "User api call returns user id");
+ const id = get(body, "id");
+ assert.isDefined(id, "User api call returns user id");
- return cy.request({
- url: body.invite_link,
- method: "POST",
- form: true,
- body: { password },
- });
+ return post({
+ url: body.invite_link,
+ form: true,
+ body: { password },
});
-}
+ });
+});
-export function createDestination(name, type, options = {}) {
- return cy.request({
- method: "POST",
+Cypress.Commands.add("createDestination", (name, type, options = {}) => {
+ return post({
url: "api/destinations",
body: { name, type, options },
failOnStatusCode: false,
});
-}
+});
-export function getDestinations() {
+Cypress.Commands.add("getDestinations", () => {
return cy.request("GET", "api/destinations").then(({ body }) => body);
-}
+});
-export function addDestinationSubscription(alertId, destinationName) {
- return getDestinations()
+Cypress.Commands.add("addDestinationSubscription", (alertId, destinationName) => {
+ return cy
+ .getDestinations()
.then(destinations => {
const destination = find(destinations, { name: destinationName });
if (!destination) {
throw new Error("Destination not found");
}
- return cy.request("POST", `api/alerts/${alertId}/subscriptions`, {
- alert_id: alertId,
- destination_id: destination.id,
+ return post({
+ url: `api/alerts/${alertId}/subscriptions`,
+ body: {
+ alert_id: alertId,
+ destination_id: destination.id,
+ },
});
})
.then(({ body }) => {
@@ -160,4 +164,4 @@ export function addDestinationSubscription(alertId, destinationName) {
assert.isDefined(id, "Subscription api call returns subscription id");
return body;
});
-}
+});
diff --git a/client/cypress/support/tags/index.js b/client/cypress/support/tags/index.js
index 25bcb97574..cef4c429a3 100644
--- a/client/cypress/support/tags/index.js
+++ b/client/cypress/support/tags/index.js
@@ -10,8 +10,9 @@ export function typeInTagsSelectAndSave(text) {
cy.getByTestId("EditTagsDialog").within(() => {
cy.get(".ant-select")
.find("input")
- .type(text);
+ .type(text, { force: true });
+ cy.get(".ant-modal-header").click(); // hide dropdown options
cy.contains("OK").click();
});
}
diff --git a/client/jsconfig.json b/client/jsconfig.json
deleted file mode 100644
index fe68d7ac70..0000000000
--- a/client/jsconfig.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "compilerOptions": {
- "baseUrl": "./",
- "paths": {
- "@/*": ["./app/*"]
- }
- },
- "exclude": ["dist"]
-}
\ No newline at end of file
diff --git a/client/tsconfig.json b/client/tsconfig.json
new file mode 100644
index 0000000000..cee94d6637
--- /dev/null
+++ b/client/tsconfig.json
@@ -0,0 +1,35 @@
+{
+ "compilerOptions": {
+ // Target latest version of ECMAScript.
+ "target": "esnext",
+ // Search under node_modules for non-relative imports.
+ "moduleResolution": "node",
+ // Process & infer types from .js files.
+ "allowJs": true,
+ // Don't emit; allow Babel to transform files.
+ "noEmit": true,
+ // Enable strictest settings like strictNullChecks & noImplicitAny.
+ "strict": true,
+ // Import non-ES modules as default imports.
+ "esModuleInterop": true,
+ "jsx": "react",
+ "allowSyntheticDefaultImports": true,
+ "noUnusedLocals": true,
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "forceConsistentCasingInFileNames": true,
+ "baseUrl": "./",
+ "paths": {
+ "@/*": ["./app/*"]
+ }
+ },
+ "include": [
+ "app/**/*"
+ ],
+ "exclude": [
+ "dist"
+ ]
+}
diff --git a/docker-compose.yml b/docker-compose.yml
index bf56e3af09..82bcd245fb 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,6 +1,6 @@
# This configuration file is for the **development** setup.
# For a production example please refer to getredash/setup repository on GitHub.
-version: "2"
+version: "2.2"
x-redash-service: &redash-service
build:
context: .
@@ -15,6 +15,7 @@ x-redash-environment: &redash-environment
REDASH_RATELIMIT_ENABLED: "false"
REDASH_MAIL_DEFAULT_SENDER: "redash@example.com"
REDASH_MAIL_SERVER: "email"
+ REDASH_ENFORCE_CSRF: "true"
services:
server:
<<: *redash-service
diff --git a/migrations/alembic.ini b/migrations/alembic.ini
index 138c144473..cda6dc822f 100644
--- a/migrations/alembic.ini
+++ b/migrations/alembic.ini
@@ -1,6 +1,7 @@
# A generic, single database configuration.
[alembic]
+script_location = migrations
# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s
diff --git a/migrations/env.py b/migrations/env.py
index 4593816063..1e80c143ae 100755
--- a/migrations/env.py
+++ b/migrations/env.py
@@ -11,16 +11,17 @@
# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)
-logger = logging.getLogger('alembic.env')
+logger = logging.getLogger("alembic.env")
# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
from flask import current_app
-config.set_main_option('sqlalchemy.url',
- current_app.config.get('SQLALCHEMY_DATABASE_URI'))
-target_metadata = current_app.extensions['migrate'].db.metadata
+
+db_url_escaped = current_app.config.get("SQLALCHEMY_DATABASE_URI").replace("%", "%%")
+config.set_main_option("sqlalchemy.url", db_url_escaped)
+target_metadata = current_app.extensions["migrate"].db.metadata
# other values from the config, defined by the needs of env.py,
# can be acquired:
@@ -59,21 +60,25 @@ def run_migrations_online():
# when there are no changes to the schema
# reference: http://alembic.readthedocs.org/en/latest/cookbook.html
def process_revision_directives(context, revision, directives):
- if getattr(config.cmd_opts, 'autogenerate', False):
+ if getattr(config.cmd_opts, "autogenerate", False):
script = directives[0]
if script.upgrade_ops.is_empty():
directives[:] = []
- logger.info('No changes in schema detected.')
+ logger.info("No changes in schema detected.")
- engine = engine_from_config(config.get_section(config.config_ini_section),
- prefix='sqlalchemy.',
- poolclass=pool.NullPool)
+ engine = engine_from_config(
+ config.get_section(config.config_ini_section),
+ prefix="sqlalchemy.",
+ poolclass=pool.NullPool,
+ )
connection = engine.connect()
- context.configure(connection=connection,
- target_metadata=target_metadata,
- process_revision_directives=process_revision_directives,
- **current_app.extensions['migrate'].configure_args)
+ context.configure(
+ connection=connection,
+ target_metadata=target_metadata,
+ process_revision_directives=process_revision_directives,
+ **current_app.extensions["migrate"].configure_args
+ )
try:
with context.begin_transaction():
@@ -81,6 +86,7 @@ def process_revision_directives(context, revision, directives):
finally:
connection.close()
+
if context.is_offline_mode():
run_migrations_offline()
else:
diff --git a/migrations/versions/118aa16f565b_.py b/migrations/versions/118aa16f565b_.py
new file mode 100644
index 0000000000..6265d6eddb
--- /dev/null
+++ b/migrations/versions/118aa16f565b_.py
@@ -0,0 +1,38 @@
+"""empty message
+
+Revision ID: 118aa16f565b
+Revises: cf135a57332e
+Create Date: 2019-02-05 20:16:52.182780
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "118aa16f565b"
+down_revision = "cf135a57332e"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ op.create_table(
+ "tablemetadata_queries_link",
+ sa.Column("table_id", sa.Integer(), nullable=False),
+ sa.Column("query_id", sa.Integer(), nullable=False),
+ sa.ForeignKeyConstraint(["query_id"], ["queries.id"], ondelete="CASCADE"),
+ sa.ForeignKeyConstraint(
+ ["table_id"], ["table_metadata.id"], ondelete="CASCADE"
+ ),
+ sa.PrimaryKeyConstraint("table_id", "query_id"),
+ )
+ op.drop_column(u"table_metadata", "sample_query")
+
+
+def downgrade():
+ op.add_column(
+ u"table_metadata",
+ sa.Column("sample_query", sa.TEXT(), autoincrement=False, nullable=True),
+ )
+ op.drop_table("tablemetadata_queries_link")
diff --git a/migrations/versions/151a4c333e96_.py b/migrations/versions/151a4c333e96_.py
new file mode 100644
index 0000000000..46e3124ee4
--- /dev/null
+++ b/migrations/versions/151a4c333e96_.py
@@ -0,0 +1,24 @@
+"""empty message
+
+Revision ID: 151a4c333e96
+Revises: e5c7a4e2df4d
+Create Date: 2019-03-26 19:32:29.052222
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "151a4c333e96"
+down_revision = "e5c7a4e2df4d"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ pass
+
+
+def downgrade():
+ pass
diff --git a/migrations/versions/280daa582976_.py b/migrations/versions/280daa582976_.py
new file mode 100644
index 0000000000..983efbc862
--- /dev/null
+++ b/migrations/versions/280daa582976_.py
@@ -0,0 +1,59 @@
+"""Add column metadata and table metadata
+
+Revision ID: 280daa582976
+Revises: 151a4c333e96
+Create Date: 2019-01-24 18:23:53.040608
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "280daa582976"
+down_revision = "151a4c333e96"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ op.create_table(
+ "table_metadata",
+ sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
+ sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
+ sa.Column("id", sa.Integer(), nullable=False),
+ sa.Column("org_id", sa.Integer(), nullable=False),
+ sa.Column("data_source_id", sa.Integer(), nullable=False),
+ sa.Column("exists", sa.Boolean(), nullable=False),
+ sa.Column("name", sa.String(length=255), nullable=False),
+ sa.Column("description", sa.String(length=4096), nullable=True),
+ sa.Column("column_metadata", sa.Boolean(), nullable=False),
+ sa.Column("sample_query", sa.Text(), nullable=True),
+ sa.ForeignKeyConstraint(
+ ["data_source_id"], ["data_sources.id"], ondelete="CASCADE"
+ ),
+ sa.ForeignKeyConstraint(["org_id"], ["organizations.id"]),
+ sa.PrimaryKeyConstraint("id"),
+ )
+ op.create_table(
+ "column_metadata",
+ sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
+ sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
+ sa.Column("id", sa.Integer(), nullable=False),
+ sa.Column("org_id", sa.Integer(), nullable=False),
+ sa.Column("table_id", sa.Integer(), nullable=False),
+ sa.Column("name", sa.String(length=255), nullable=False),
+ sa.Column("type", sa.String(length=255), nullable=True),
+ sa.Column("example", sa.String(length=4096), nullable=True),
+ sa.Column("exists", sa.Boolean(), nullable=False),
+ sa.ForeignKeyConstraint(
+ ["table_id"], ["table_metadata.id"], ondelete="CASCADE"
+ ),
+ sa.ForeignKeyConstraint(["org_id"], ["organizations.id"]),
+ sa.PrimaryKeyConstraint("id"),
+ )
+
+
+def downgrade():
+ op.drop_table("column_metadata")
+ op.drop_table("table_metadata")
diff --git a/migrations/versions/6adb92e75691_.py b/migrations/versions/6adb92e75691_.py
new file mode 100644
index 0000000000..c2825e4867
--- /dev/null
+++ b/migrations/versions/6adb92e75691_.py
@@ -0,0 +1,27 @@
+"""Add sample_updated_at column to table_metadata
+
+Revision ID: 6adb92e75691
+Revises: 280daa582976
+Create Date: 2019-04-10 20:13:13.714589
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "6adb92e75691"
+down_revision = "280daa582976"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ op.add_column(
+ "table_metadata",
+ sa.Column("sample_updated_at", sa.DateTime(timezone=True), nullable=True),
+ )
+
+
+def downgrade():
+ op.drop_column("table_metadata", "sample_updated_at")
diff --git a/migrations/versions/ba150362b02e_.py b/migrations/versions/ba150362b02e_.py
new file mode 100644
index 0000000000..636415557a
--- /dev/null
+++ b/migrations/versions/ba150362b02e_.py
@@ -0,0 +1,26 @@
+"""Add description field for data_sources
+
+Revision ID: ba150362b02e
+Revises: 118aa16f565b
+Create Date: 2019-02-05 21:21:08.069390
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "ba150362b02e"
+down_revision = "118aa16f565b"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ op.add_column(
+ "data_sources", sa.Column("description", sa.String(length=4096), nullable=True)
+ )
+
+
+def downgrade():
+ op.drop_column("data_sources", "description")
diff --git a/migrations/versions/cf135a57332e_.py b/migrations/versions/cf135a57332e_.py
new file mode 100644
index 0000000000..01694219e5
--- /dev/null
+++ b/migrations/versions/cf135a57332e_.py
@@ -0,0 +1,32 @@
+"""Add column description and table visibility fields
+
+Revision ID: cf135a57332e
+Revises: 6adb92e75691
+Create Date: 2019-02-05 19:52:48.233070
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "cf135a57332e"
+down_revision = "6adb92e75691"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ op.add_column(
+ "column_metadata",
+ sa.Column("description", sa.String(length=4096), nullable=True),
+ )
+ op.add_column(
+ "table_metadata",
+ sa.Column("visible", sa.Boolean(), nullable=False, server_default="True"),
+ )
+
+
+def downgrade():
+ op.drop_column("table_metadata", "visible")
+ op.drop_column("column_metadata", "description")
diff --git a/migrations/versions/da6767746e76_add_more_db_indexes.py b/migrations/versions/da6767746e76_add_more_db_indexes.py
new file mode 100644
index 0000000000..478aa42435
--- /dev/null
+++ b/migrations/versions/da6767746e76_add_more_db_indexes.py
@@ -0,0 +1,101 @@
+"""Add more db indexes.
+
+Revision ID: da6767746e76
+Revises: ba150362b02e
+Create Date: 2019-12-02 11:48:52.611441
+
+"""
+from alembic import op
+
+
+# revision identifiers, used by Alembic.
+revision = "da6767746e76"
+down_revision = "ba150362b02e"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ op.create_index(
+ op.f("ix_column_metadata_exists"), "column_metadata", ["exists"], unique=False
+ )
+ op.create_index(
+ op.f("ix_column_metadata_name"), "column_metadata", ["name"], unique=False
+ )
+ op.create_index(
+ op.f("ix_column_metadata_table_id"),
+ "column_metadata",
+ ["table_id"],
+ unique=False,
+ )
+ op.create_index(
+ "ix_column_metadata_table_id_exists",
+ "column_metadata",
+ ["table_id", "exists"],
+ unique=False,
+ )
+ op.create_index(
+ "ix_column_metadata_table_id_name_exists",
+ "column_metadata",
+ ["table_id", "exists", "name"],
+ unique=False,
+ )
+ op.create_index(
+ "ix_column_metadata_table_id_pkey",
+ "column_metadata",
+ ["table_id", "id"],
+ unique=False,
+ )
+ op.create_index(
+ op.f("ix_table_metadata_data_source_id"),
+ "table_metadata",
+ ["data_source_id"],
+ unique=False,
+ )
+ op.create_index(
+ "ix_table_metadata_data_source_id_exists",
+ "table_metadata",
+ ["data_source_id", "exists"],
+ unique=False,
+ )
+ op.create_index(
+ "ix_table_metadata_data_source_id_name_exists",
+ "table_metadata",
+ ["data_source_id", "exists", "name"],
+ unique=False,
+ )
+ op.create_index(
+ op.f("ix_table_metadata_exists"), "table_metadata", ["exists"], unique=False
+ )
+ op.create_index(
+ op.f("ix_table_metadata_name"), "table_metadata", ["name"], unique=False
+ )
+ op.create_index(
+ op.f("ix_table_metadata_sample_updated_at"),
+ "table_metadata",
+ ["sample_updated_at"],
+ unique=False,
+ )
+
+
+def downgrade():
+ op.drop_index(
+ op.f("ix_table_metadata_sample_updated_at"), table_name="table_metadata"
+ )
+ op.drop_index(op.f("ix_table_metadata_name"), table_name="table_metadata")
+ op.drop_index(op.f("ix_table_metadata_exists"), table_name="table_metadata")
+ op.drop_index(
+ "ix_table_metadata_data_source_id_name_exists", table_name="table_metadata"
+ )
+ op.drop_index(
+ "ix_table_metadata_data_source_id_exists", table_name="table_metadata"
+ )
+ op.drop_index(op.f("ix_table_metadata_data_source_id"), table_name="table_metadata")
+ op.drop_index("ix_column_metadata_table_id_pkey", table_name="column_metadata")
+ op.drop_index(
+ "ix_column_metadata_table_id_name_exists", table_name="column_metadata"
+ )
+ op.drop_index("ix_column_metadata_table_id_exists", table_name="column_metadata")
+ op.drop_index(op.f("ix_column_metadata_table_id"), table_name="column_metadata")
+ op.drop_index(op.f("ix_column_metadata_name"), table_name="column_metadata")
+ op.drop_index(op.f("ix_column_metadata_exists"), table_name="column_metadata")
diff --git a/package-lock.json b/package-lock.json
index 45566abcc0..31681c4e4f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,37 +17,167 @@
"@ant-design/colors": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.2.2.tgz",
- "integrity": "sha512-YKgNbG2dlzqMhA9NtI3/pbY16m3Yl/EeWBRa+lB1X1YaYxHrxNexiQYCLTWO/uDvAjLFMEDU+zR901waBtMtjQ==",
+ "integrity": "sha1-WtQ9YZ6RHzSI66wwPWBuZqhCOQM=",
"requires": {
"tinycolor2": "^1.4.1"
}
},
- "@ant-design/create-react-context": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@ant-design/create-react-context/-/create-react-context-0.2.5.tgz",
- "integrity": "sha512-1rMAa4qgP2lfl/QBH9i78+Gjxtj9FTMpMyDGZsEBW5Kih72EuUo9958mV8PgpRkh4uwPSQ7vVZWXeyNZXVAFDg==",
- "requires": {
- "gud": "^1.0.0",
- "warning": "^4.0.3"
- }
- },
"@ant-design/css-animation": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@ant-design/css-animation/-/css-animation-1.7.2.tgz",
"integrity": "sha512-bvVOe7A+r7lws58B7r+fgnQDK90cV45AXuvGx6i5CCSX1W/M3AJnHsNggDANBxEtWdNdFWcDd5LorB+RdSIlBw=="
},
"@ant-design/icons": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz",
- "integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w=="
- },
- "@ant-design/icons-react": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@ant-design/icons-react/-/icons-react-2.0.1.tgz",
- "integrity": "sha512-r1QfoltMuruJZqdiKcbPim3d8LNsVPB733U0gZEUSxBLuqilwsW28K2rCTWSMTjmFX7Mfpf+v/wdiFe/XCqThw==",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-4.2.1.tgz",
+ "integrity": "sha512-245ZI40MOr5GGws+sNSiJIRRoEf/J2xvPSMgwRYf3bv8mVGQZ6XTQI/OMeV16KtiSZ3D+mBKXVYSBz2fhigOXQ==",
"requires": {
"@ant-design/colors": "^3.1.0",
- "babel-runtime": "^6.26.0"
+ "@ant-design/icons-svg": "^4.0.0",
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.6",
+ "insert-css": "^2.0.0",
+ "rc-util": "^5.0.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
+ }
+ },
+ "@ant-design/icons-svg": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.1.0.tgz",
+ "integrity": "sha512-Fi03PfuUqRs76aI3UWYpP864lkrfPo0hluwGqh7NJdLhvH4iRDc3jbJqZIvRDLHKbXrvAfPPV3+zjUccfFvWOQ=="
+ },
+ "@ant-design/react-slick": {
+ "version": "0.26.3",
+ "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-0.26.3.tgz",
+ "integrity": "sha512-FhaFfS+oea0P5WvhaM7BC2/P9r4F0yMoewBpDqVkOq+JxEiKRHJ7iBYJsenv2WEymnWeO3eCuMrz/Eez7pHpGg==",
+ "requires": {
+ "@babel/runtime": "^7.10.4",
+ "classnames": "^2.2.5",
+ "json2mq": "^0.2.0",
+ "lodash": "^4.17.15",
+ "resize-observer-polyfill": "^1.5.0"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
+ }
+ },
+ "@babel/cli": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.10.4.tgz",
+ "integrity": "sha512-xX99K4V1BzGJdQANK5cwK+EpF1vP9gvqhn+iWvG+TubCjecplW7RSQimJ2jcCvu6fnK5pY6mZMdu6EWTj32QVA==",
+ "dev": true,
+ "requires": {
+ "chokidar": "^2.1.8",
+ "commander": "^4.0.1",
+ "convert-source-map": "^1.1.0",
+ "fs-readdir-recursive": "^1.1.0",
+ "glob": "^7.0.0",
+ "lodash": "^4.17.13",
+ "make-dir": "^2.1.0",
+ "slash": "^2.0.0",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ },
+ "make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "dev": true,
+ "requires": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "optional": true
+ },
+ "pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
+ "dev": true,
+ "optional": true
+ }
}
},
"@babel/code-frame": {
@@ -59,28 +189,156 @@
"@babel/highlight": "^7.0.0"
}
},
- "@babel/core": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.3.4.tgz",
- "integrity": "sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==",
+ "@babel/compat-data": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.10.4.tgz",
+ "integrity": "sha512-t+rjExOrSVvjQQXNp5zAIYDp00KjdvGl/TpDX5REPr0S9IAIPQMTilcfG6q8c0QFmj9lSTVySV2VTsyggvtNIw==",
"dev": true,
"requires": {
- "@babel/code-frame": "^7.0.0",
- "@babel/generator": "^7.3.4",
- "@babel/helpers": "^7.2.0",
- "@babel/parser": "^7.3.4",
- "@babel/template": "^7.2.2",
- "@babel/traverse": "^7.3.4",
- "@babel/types": "^7.3.4",
- "convert-source-map": "^1.1.0",
+ "browserslist": "^4.12.0",
+ "invariant": "^2.2.4",
+ "semver": "^5.5.0"
+ }
+ },
+ "@babel/core": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.4.tgz",
+ "integrity": "sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.10.4",
+ "@babel/helper-module-transforms": "^7.10.4",
+ "@babel/helpers": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4",
+ "convert-source-map": "^1.7.0",
"debug": "^4.1.0",
- "json5": "^2.1.0",
- "lodash": "^4.17.11",
+ "gensync": "^1.0.0-beta.1",
+ "json5": "^2.1.2",
+ "lodash": "^4.17.13",
"resolve": "^1.3.2",
"semver": "^5.4.1",
"source-map": "^0.5.0"
},
"dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.4.tgz",
+ "integrity": "sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz",
+ "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.4.tgz",
+ "integrity": "sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.10.4",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "convert-source-map": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
+ "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@@ -90,6 +348,18 @@
"ms": "^2.1.1"
}
},
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ },
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -126,22 +396,60 @@
}
},
"@babel/helper-annotate-as-pure": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz",
- "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
+ "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
"dev": true,
"requires": {
- "@babel/types": "^7.0.0"
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
}
},
"@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz",
- "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz",
+ "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==",
"dev": true,
"requires": {
- "@babel/helper-explode-assignable-expression": "^7.1.0",
- "@babel/types": "^7.0.0"
+ "@babel/helper-explode-assignable-expression": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
}
},
"@babel/helper-builder-react-jsx": {
@@ -154,120 +462,577 @@
"esutils": "^2.0.0"
}
},
- "@babel/helper-call-delegate": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz",
- "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==",
+ "@babel/helper-compilation-targets": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz",
+ "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==",
"dev": true,
"requires": {
- "@babel/helper-hoist-variables": "^7.0.0",
- "@babel/traverse": "^7.1.0",
- "@babel/types": "^7.0.0"
+ "@babel/compat-data": "^7.10.4",
+ "browserslist": "^4.12.0",
+ "invariant": "^2.2.4",
+ "levenary": "^1.1.1",
+ "semver": "^5.5.0"
}
},
"@babel/helper-create-class-features-plugin": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.3.4.tgz",
- "integrity": "sha512-uFpzw6L2omjibjxa8VGZsJUPL5wJH0zzGKpoz0ccBkzIa6C8kWNUbiBmQ0rgOKWlHJ6qzmfa6lTiGchiV8SC+g==",
- "dev": true,
- "requires": {
- "@babel/helper-function-name": "^7.1.0",
- "@babel/helper-member-expression-to-functions": "^7.0.0",
- "@babel/helper-optimise-call-expression": "^7.0.0",
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-replace-supers": "^7.3.4",
- "@babel/helper-split-export-declaration": "^7.0.0"
- }
- },
- "@babel/helper-define-map": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz",
- "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==",
- "dev": true,
- "requires": {
- "@babel/helper-function-name": "^7.1.0",
- "@babel/types": "^7.0.0",
- "lodash": "^4.17.10"
- }
- },
- "@babel/helper-explode-assignable-expression": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz",
- "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==",
- "dev": true,
- "requires": {
- "@babel/traverse": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "@babel/helper-function-name": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
- "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.4.tgz",
+ "integrity": "sha512-9raUiOsXPxzzLjCXeosApJItoMnX3uyT4QdM2UldffuGApNrF8e938MwNpDCK9CPoyxrEoCgT+hObJc3mZa6lQ==",
"dev": true,
"requires": {
- "@babel/helper-get-function-arity": "^7.0.0",
- "@babel/template": "^7.1.0",
- "@babel/types": "^7.0.0"
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz",
+ "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
}
},
- "@babel/helper-get-function-arity": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
- "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
+ "@babel/helper-create-regexp-features-plugin": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz",
+ "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==",
"dev": true,
"requires": {
- "@babel/types": "^7.0.0"
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-regex": "^7.10.4",
+ "regexpu-core": "^4.7.0"
}
},
- "@babel/helper-hoist-variables": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz",
- "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==",
+ "@babel/helper-define-map": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.4.tgz",
+ "integrity": "sha512-nIij0oKErfCnLUCWaCaHW0Bmtl2RO9cN7+u2QT8yqTywgALKlyUVOvHDElh+b5DwVC6YB1FOYFOTWcN/+41EDA==",
"dev": true,
"requires": {
- "@babel/types": "^7.0.0"
- }
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/types": "^7.10.4",
+ "lodash": "^4.17.13"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
+ }
},
- "@babel/helper-member-expression-to-functions": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz",
- "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==",
+ "@babel/helper-explode-assignable-expression": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz",
+ "integrity": "sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A==",
+ "dev": true,
+ "requires": {
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.4.tgz",
+ "integrity": "sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz",
+ "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.4.tgz",
+ "integrity": "sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.10.4",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
+ "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
"dev": true,
"requires": {
+ "@babel/helper-get-function-arity": "^7.0.0",
+ "@babel/template": "^7.1.0",
"@babel/types": "^7.0.0"
}
},
- "@babel/helper-module-imports": {
+ "@babel/helper-get-function-arity": {
"version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz",
- "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
+ "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
"dev": true,
"requires": {
"@babel/types": "^7.0.0"
}
},
- "@babel/helper-module-transforms": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.2.2.tgz",
- "integrity": "sha512-YRD7I6Wsv+IHuTPkAmAS4HhY0dkPobgLftHp0cRGZSdrRvmZY8rFvae/GVu3bD00qscuvK3WPHB3YdNpBXUqrA==",
+ "@babel/helper-hoist-variables": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz",
+ "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==",
"dev": true,
"requires": {
- "@babel/helper-module-imports": "^7.0.0",
- "@babel/helper-simple-access": "^7.1.0",
- "@babel/helper-split-export-declaration": "^7.0.0",
- "@babel/template": "^7.2.2",
- "@babel/types": "^7.2.2",
- "lodash": "^4.17.10"
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.4.tgz",
+ "integrity": "sha512-m5j85pK/KZhuSdM/8cHUABQTAslV47OjfIB9Cc7P+PvlAoBzdb79BGNfw8RhT5Mq3p+xGd0ZfAKixbrUZx0C7A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
+ "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.4.tgz",
+ "integrity": "sha512-Er2FQX0oa3nV7eM1o0tNCTx7izmQtwAQsIiaLRWtavAAEcskb0XJ5OjJbVrYXWOTr8om921Scabn4/tzlx7j1Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4",
+ "lodash": "^4.17.13"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz",
+ "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
}
},
"@babel/helper-optimise-call-expression": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz",
- "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+ "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
"dev": true,
"requires": {
- "@babel/types": "^7.0.0"
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
}
},
"@babel/helper-plugin-utils": {
@@ -277,185 +1042,1026 @@
"dev": true
},
"@babel/helper-regex": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0.tgz",
- "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.4.tgz",
+ "integrity": "sha512-inWpnHGgtg5NOF0eyHlC0/74/VkdRITY9dtTpB2PrxKKn+AkVMRiZz/Adrx+Ssg+MLDesi2zohBW6MVq6b4pOQ==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.13"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-remap-async-to-generator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz",
+ "integrity": "sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-wrap-function": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.4.tgz",
+ "integrity": "sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz",
+ "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.4.tgz",
+ "integrity": "sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.10.4",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
+ "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.4.tgz",
+ "integrity": "sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz",
+ "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.4.tgz",
+ "integrity": "sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.10.4",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz",
+ "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz",
+ "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/helper-wrap-function": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz",
+ "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.4.tgz",
+ "integrity": "sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz",
+ "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.4.tgz",
+ "integrity": "sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.10.4",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helpers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz",
+ "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.4.tgz",
+ "integrity": "sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz",
+ "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.4.tgz",
+ "integrity": "sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.10.4",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
+ "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.0",
+ "esutils": "^2.0.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.3.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.4.tgz",
+ "integrity": "sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==",
+ "dev": true
+ },
+ "@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.4.tgz",
+ "integrity": "sha512-MJbxGSmejEFVOANAezdO39SObkURO5o/8b6fSH6D1pi9RZQt+ldppKPXfqgUWpSQ9asM6xaSaSJIaeWMDRP0Zg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-remap-async-to-generator": "^7.10.4",
+ "@babel/plugin-syntax-async-generators": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/plugin-proposal-class-properties": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz",
+ "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==",
"dev": true,
"requires": {
- "lodash": "^4.17.10"
+ "@babel/helper-create-class-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/helper-remap-async-to-generator": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz",
- "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==",
+ "@babel/plugin-proposal-dynamic-import": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz",
+ "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==",
"dev": true,
"requires": {
- "@babel/helper-annotate-as-pure": "^7.0.0",
- "@babel/helper-wrap-function": "^7.1.0",
- "@babel/template": "^7.1.0",
- "@babel/traverse": "^7.1.0",
- "@babel/types": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/helper-replace-supers": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.3.4.tgz",
- "integrity": "sha512-pvObL9WVf2ADs+ePg0jrqlhHoxRXlOa+SHRHzAXIz2xkYuOHfGl+fKxPMaS4Fq+uje8JQPobnertBBvyrWnQ1A==",
+ "@babel/plugin-proposal-json-strings": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz",
+ "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==",
"dev": true,
"requires": {
- "@babel/helper-member-expression-to-functions": "^7.0.0",
- "@babel/helper-optimise-call-expression": "^7.0.0",
- "@babel/traverse": "^7.3.4",
- "@babel/types": "^7.3.4"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/helper-simple-access": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz",
- "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==",
+ "@babel/plugin-proposal-nullish-coalescing-operator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz",
+ "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==",
"dev": true,
"requires": {
- "@babel/template": "^7.1.0",
- "@babel/types": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/helper-split-export-declaration": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz",
- "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==",
+ "@babel/plugin-proposal-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==",
"dev": true,
"requires": {
- "@babel/types": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/helper-wrap-function": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz",
- "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==",
+ "@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.4.tgz",
+ "integrity": "sha512-6vh4SqRuLLarjgeOf4EaROJAHjvu9Gl+/346PbDH9yWbJyfnJ/ah3jmYKYtswEyCoWZiidvVHjHshd4WgjB9BA==",
"dev": true,
"requires": {
- "@babel/helper-function-name": "^7.1.0",
- "@babel/template": "^7.1.0",
- "@babel/traverse": "^7.1.0",
- "@babel/types": "^7.2.0"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+ "@babel/plugin-transform-parameters": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ },
+ "@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ }
}
},
- "@babel/helpers": {
- "version": "7.3.1",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.3.1.tgz",
- "integrity": "sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA==",
+ "@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz",
+ "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==",
"dev": true,
"requires": {
- "@babel/template": "^7.1.2",
- "@babel/traverse": "^7.1.5",
- "@babel/types": "^7.3.0"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/highlight": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
- "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
+ "@babel/plugin-proposal-optional-chaining": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz",
+ "integrity": "sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ==",
"dev": true,
"requires": {
- "chalk": "^2.0.0",
- "esutils": "^2.0.2",
- "js-tokens": "^4.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/parser": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.4.tgz",
- "integrity": "sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==",
- "dev": true
- },
- "@babel/plugin-proposal-async-generator-functions": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz",
- "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==",
+ "@babel/plugin-proposal-private-methods": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz",
+ "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-remap-async-to-generator": "^7.1.0",
- "@babel/plugin-syntax-async-generators": "^7.2.0"
+ "@babel/helper-create-class-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/plugin-proposal-class-properties": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.4.tgz",
- "integrity": "sha512-lUf8D3HLs4yYlAo8zjuneLvfxN7qfKv1Yzbj5vjqaqMJxgJA3Ipwp4VUJ+OrOdz53Wbww6ahwB8UhB2HQyLotA==",
+ "@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz",
+ "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==",
"dev": true,
"requires": {
- "@babel/helper-create-class-features-plugin": "^7.3.4",
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/plugin-proposal-json-strings": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz",
- "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==",
+ "@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-json-strings": "^7.2.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/plugin-proposal-object-rest-spread": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.4.tgz",
- "integrity": "sha512-j7VQmbbkA+qrzNqbKHrBsW3ddFnOeva6wzSe/zB7T+xaxGc+RCpwo44wCmRixAIGRoIpmVgvzFzNJqQcO3/9RA==",
+ "@babel/plugin-syntax-class-properties": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz",
+ "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-object-rest-spread": "^7.2.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/plugin-proposal-optional-catch-binding": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz",
- "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==",
+ "@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-syntax-optional-catch-binding": "^7.2.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/plugin-proposal-unicode-property-regex": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz",
- "integrity": "sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw==",
+ "@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-regex": "^7.0.0",
- "regexpu-core": "^4.2.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/plugin-syntax-async-generators": {
+ "@babel/plugin-syntax-jsx": {
"version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz",
- "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz",
+ "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
- "@babel/plugin-syntax-json-strings": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz",
- "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==",
+ "@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
- "@babel/plugin-syntax-jsx": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz",
- "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==",
+ "@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-syntax-object-rest-spread": {
@@ -468,202 +2074,588 @@
}
},
"@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz",
- "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==",
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/plugin-syntax-top-level-await": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz",
+ "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/plugin-syntax-typescript": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.4.tgz",
+ "integrity": "sha512-oSAEz1YkBCAKr5Yiq8/BNtvSAPwkp/IyUnwZogd8p+F0RuYQQrLeRUzIQhueQTTBy/F+a40uS7OFKxnkRvmvFQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-arrow-functions": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz",
- "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz",
+ "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-async-to-generator": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.3.4.tgz",
- "integrity": "sha512-Y7nCzv2fw/jEZ9f678MuKdMo99MFDJMT/PvD9LisrR5JDFcJH6vYeH6RnjVt3p5tceyGRvTtEN0VOlU+rgHZjA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz",
+ "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==",
"dev": true,
"requires": {
- "@babel/helper-module-imports": "^7.0.0",
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-remap-async-to-generator": "^7.1.0"
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-remap-async-to-generator": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-block-scoped-functions": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz",
- "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz",
+ "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-block-scoping": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.3.4.tgz",
- "integrity": "sha512-blRr2O8IOZLAOJklXLV4WhcEzpYafYQKSGT3+R26lWG41u/FODJuBggehtOwilVAcFu393v3OFj+HmaE6tVjhA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.4.tgz",
+ "integrity": "sha512-J3b5CluMg3hPUii2onJDRiaVbPtKFPLEaV5dOPY5OeAbDi1iU/UbbFFTgwb7WnanaDy7bjU35kc26W3eM5Qa0A==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "lodash": "^4.17.11"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "lodash": "^4.17.13"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-classes": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.3.4.tgz",
- "integrity": "sha512-J9fAvCFBkXEvBimgYxCjvaVDzL6thk0j0dBvCeZmIUDBwyt+nv6HfbImsSrWsYXfDNDivyANgJlFXDUWRTZBuA==",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.0.0",
- "@babel/helper-define-map": "^7.1.0",
- "@babel/helper-function-name": "^7.1.0",
- "@babel/helper-optimise-call-expression": "^7.0.0",
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-replace-supers": "^7.3.4",
- "@babel/helper-split-export-declaration": "^7.0.0",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz",
+ "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-define-map": "^7.10.4",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4",
"globals": "^11.1.0"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz",
+ "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-computed-properties": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz",
- "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz",
+ "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-destructuring": {
- "version": "7.3.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.3.2.tgz",
- "integrity": "sha512-Lrj/u53Ufqxl/sGxyjsJ2XNtNuEjDyjpqdhMNh5aZ+XFOdThL46KBj27Uem4ggoezSYBxKWAil6Hu8HtwqesYw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz",
+ "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-dotall-regex": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz",
- "integrity": "sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz",
+ "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-regex": "^7.0.0",
- "regexpu-core": "^4.1.3"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-duplicate-keys": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz",
- "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz",
+ "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-exponentiation-operator": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz",
- "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz",
+ "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==",
"dev": true,
"requires": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0",
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-for-of": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz",
- "integrity": "sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz",
+ "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-function-name": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz",
- "integrity": "sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz",
+ "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==",
"dev": true,
"requires": {
- "@babel/helper-function-name": "^7.1.0",
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz",
+ "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-literals": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz",
- "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz",
+ "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/plugin-transform-member-expression-literals": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz",
+ "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-modules-amd": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz",
- "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.4.tgz",
+ "integrity": "sha512-3Fw+H3WLUrTlzi3zMiZWp3AR4xadAEMv6XRCYnd5jAlLM61Rn+CRJaZMaNvIpcJpQ3vs1kyifYvEVPFfoSkKOA==",
"dev": true,
"requires": {
- "@babel/helper-module-transforms": "^7.1.0",
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-module-transforms": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-modules-commonjs": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz",
- "integrity": "sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz",
+ "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==",
"dev": true,
"requires": {
- "@babel/helper-module-transforms": "^7.1.0",
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-simple-access": "^7.1.0"
+ "@babel/helper-module-transforms": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-modules-systemjs": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.3.4.tgz",
- "integrity": "sha512-VZ4+jlGOF36S7TjKs8g4ojp4MEI+ebCQZdswWb/T9I4X84j8OtFAyjXjt/M16iIm5RIZn0UMQgg/VgIwo/87vw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.4.tgz",
+ "integrity": "sha512-Tb28LlfxrTiOTGtZFsvkjpyjCl9IoaRI52AEU/VIwOwvDQWtbNJsAqTXzh+5R7i74e/OZHH2c2w2fsOqAfnQYQ==",
"dev": true,
"requires": {
- "@babel/helper-hoist-variables": "^7.0.0",
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-hoist-variables": "^7.10.4",
+ "@babel/helper-module-transforms": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-modules-umd": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz",
- "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz",
+ "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==",
"dev": true,
"requires": {
- "@babel/helper-module-transforms": "^7.1.0",
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-module-transforms": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.3.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz",
- "integrity": "sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz",
+ "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==",
"dev": true,
"requires": {
- "regexp-tree": "^0.1.0"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4"
}
},
"@babel/plugin-transform-new-target": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz",
- "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz",
+ "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-object-assign": {
@@ -676,24 +2668,82 @@
}
},
"@babel/plugin-transform-object-super": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz",
- "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz",
+ "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-replace-supers": "^7.1.0"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-parameters": {
- "version": "7.3.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.3.3.tgz",
- "integrity": "sha512-IrIP25VvXWu/VlBWTpsjGptpomtIkYrN/3aDp4UKm7xK6UxZY88kcJ1UwETbzHAlwN21MnNfwlar0u8y3KpiXw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.4.tgz",
+ "integrity": "sha512-RurVtZ/D5nYfEg0iVERXYKEgDFeesHrHfx8RT05Sq57ucj2eOYAP6eu5fynL4Adju4I/mP/I6SO0DqNWAXjfLQ==",
"dev": true,
"requires": {
- "@babel/helper-call-delegate": "^7.1.0",
- "@babel/helper-get-function-arity": "^7.0.0",
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/plugin-transform-property-literals": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz",
+ "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-react-display-name": {
@@ -737,121 +2787,308 @@
}
},
"@babel/plugin-transform-regenerator": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.3.4.tgz",
- "integrity": "sha512-hvJg8EReQvXT6G9H2MvNPXkv9zK36Vxa1+csAVTpE1J3j0zlHplw76uudEbJxgvqZzAq9Yh45FLD4pk5mKRFQA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz",
+ "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==",
+ "dev": true,
+ "requires": {
+ "regenerator-transform": "^0.14.2"
+ }
+ },
+ "@babel/plugin-transform-reserved-words": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz",
+ "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==",
"dev": true,
"requires": {
- "regenerator-transform": "^0.13.4"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-shorthand-properties": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz",
- "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz",
+ "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-spread": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz",
- "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.4.tgz",
+ "integrity": "sha512-1e/51G/Ni+7uH5gktbWv+eCED9pP8ZpRhZB3jOaI3mmzfvJTWHkuyYTv0Z5PYtyM+Tr2Ccr9kUdQxn60fI5WuQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-sticky-regex": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz",
- "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz",
+ "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-regex": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-regex": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-template-literals": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz",
- "integrity": "sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.4.tgz",
+ "integrity": "sha512-4NErciJkAYe+xI5cqfS8pV/0ntlY5N5Ske/4ImxAVX7mk9Rxt2bwDTGv1Msc2BRJvWQcmYEC+yoMLdX22aE4VQ==",
"dev": true,
"requires": {
- "@babel/helper-annotate-as-pure": "^7.0.0",
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-typeof-symbol": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz",
- "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz",
+ "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/plugin-transform-typescript": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.10.4.tgz",
+ "integrity": "sha512-3WpXIKDJl/MHoAN0fNkSr7iHdUMHZoppXjf2HJ9/ed5Xht5wNIsXllJXdityKOxeA3Z8heYRb1D3p2H5rfCdPw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-typescript": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/plugin-transform-unicode-escapes": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz",
+ "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-unicode-regex": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz",
- "integrity": "sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz",
+ "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/helper-regex": "^7.0.0",
- "regexpu-core": "^4.1.3"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
}
},
"@babel/preset-env": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.3.4.tgz",
- "integrity": "sha512-2mwqfYMK8weA0g0uBKOt4FE3iEodiHy9/CW0b+nWXcbL+pGzLx8ESYc+j9IIxr6LTDHWKgPm71i9smo02bw+gA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.4.tgz",
+ "integrity": "sha512-tcmuQ6vupfMZPrLrc38d0sF2OjLT3/bZ0dry5HchNCQbrokoQi4reXqclvkkAT5b+gWc23meVWpve5P/7+w/zw==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.10.4",
+ "@babel/helper-compilation-targets": "^7.10.4",
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-proposal-async-generator-functions": "^7.10.4",
+ "@babel/plugin-proposal-class-properties": "^7.10.4",
+ "@babel/plugin-proposal-dynamic-import": "^7.10.4",
+ "@babel/plugin-proposal-json-strings": "^7.10.4",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
+ "@babel/plugin-proposal-numeric-separator": "^7.10.4",
+ "@babel/plugin-proposal-object-rest-spread": "^7.10.4",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.10.4",
+ "@babel/plugin-proposal-optional-chaining": "^7.10.4",
+ "@babel/plugin-proposal-private-methods": "^7.10.4",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.10.4",
+ "@babel/plugin-syntax-async-generators": "^7.8.0",
+ "@babel/plugin-syntax-class-properties": "^7.10.4",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.0",
+ "@babel/plugin-syntax-json-strings": "^7.8.0",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.0",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.0",
+ "@babel/plugin-syntax-top-level-await": "^7.10.4",
+ "@babel/plugin-transform-arrow-functions": "^7.10.4",
+ "@babel/plugin-transform-async-to-generator": "^7.10.4",
+ "@babel/plugin-transform-block-scoped-functions": "^7.10.4",
+ "@babel/plugin-transform-block-scoping": "^7.10.4",
+ "@babel/plugin-transform-classes": "^7.10.4",
+ "@babel/plugin-transform-computed-properties": "^7.10.4",
+ "@babel/plugin-transform-destructuring": "^7.10.4",
+ "@babel/plugin-transform-dotall-regex": "^7.10.4",
+ "@babel/plugin-transform-duplicate-keys": "^7.10.4",
+ "@babel/plugin-transform-exponentiation-operator": "^7.10.4",
+ "@babel/plugin-transform-for-of": "^7.10.4",
+ "@babel/plugin-transform-function-name": "^7.10.4",
+ "@babel/plugin-transform-literals": "^7.10.4",
+ "@babel/plugin-transform-member-expression-literals": "^7.10.4",
+ "@babel/plugin-transform-modules-amd": "^7.10.4",
+ "@babel/plugin-transform-modules-commonjs": "^7.10.4",
+ "@babel/plugin-transform-modules-systemjs": "^7.10.4",
+ "@babel/plugin-transform-modules-umd": "^7.10.4",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4",
+ "@babel/plugin-transform-new-target": "^7.10.4",
+ "@babel/plugin-transform-object-super": "^7.10.4",
+ "@babel/plugin-transform-parameters": "^7.10.4",
+ "@babel/plugin-transform-property-literals": "^7.10.4",
+ "@babel/plugin-transform-regenerator": "^7.10.4",
+ "@babel/plugin-transform-reserved-words": "^7.10.4",
+ "@babel/plugin-transform-shorthand-properties": "^7.10.4",
+ "@babel/plugin-transform-spread": "^7.10.4",
+ "@babel/plugin-transform-sticky-regex": "^7.10.4",
+ "@babel/plugin-transform-template-literals": "^7.10.4",
+ "@babel/plugin-transform-typeof-symbol": "^7.10.4",
+ "@babel/plugin-transform-unicode-escapes": "^7.10.4",
+ "@babel/plugin-transform-unicode-regex": "^7.10.4",
+ "@babel/preset-modules": "^0.1.3",
+ "@babel/types": "^7.10.4",
+ "browserslist": "^4.12.0",
+ "core-js-compat": "^3.6.2",
+ "invariant": "^2.2.2",
+ "levenary": "^1.1.1",
+ "semver": "^5.5.0"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ },
+ "@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/preset-modules": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz",
+ "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==",
"dev": true,
"requires": {
- "@babel/helper-module-imports": "^7.0.0",
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-proposal-async-generator-functions": "^7.2.0",
- "@babel/plugin-proposal-json-strings": "^7.2.0",
- "@babel/plugin-proposal-object-rest-spread": "^7.3.4",
- "@babel/plugin-proposal-optional-catch-binding": "^7.2.0",
- "@babel/plugin-proposal-unicode-property-regex": "^7.2.0",
- "@babel/plugin-syntax-async-generators": "^7.2.0",
- "@babel/plugin-syntax-json-strings": "^7.2.0",
- "@babel/plugin-syntax-object-rest-spread": "^7.2.0",
- "@babel/plugin-syntax-optional-catch-binding": "^7.2.0",
- "@babel/plugin-transform-arrow-functions": "^7.2.0",
- "@babel/plugin-transform-async-to-generator": "^7.3.4",
- "@babel/plugin-transform-block-scoped-functions": "^7.2.0",
- "@babel/plugin-transform-block-scoping": "^7.3.4",
- "@babel/plugin-transform-classes": "^7.3.4",
- "@babel/plugin-transform-computed-properties": "^7.2.0",
- "@babel/plugin-transform-destructuring": "^7.2.0",
- "@babel/plugin-transform-dotall-regex": "^7.2.0",
- "@babel/plugin-transform-duplicate-keys": "^7.2.0",
- "@babel/plugin-transform-exponentiation-operator": "^7.2.0",
- "@babel/plugin-transform-for-of": "^7.2.0",
- "@babel/plugin-transform-function-name": "^7.2.0",
- "@babel/plugin-transform-literals": "^7.2.0",
- "@babel/plugin-transform-modules-amd": "^7.2.0",
- "@babel/plugin-transform-modules-commonjs": "^7.2.0",
- "@babel/plugin-transform-modules-systemjs": "^7.3.4",
- "@babel/plugin-transform-modules-umd": "^7.2.0",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.3.0",
- "@babel/plugin-transform-new-target": "^7.0.0",
- "@babel/plugin-transform-object-super": "^7.2.0",
- "@babel/plugin-transform-parameters": "^7.2.0",
- "@babel/plugin-transform-regenerator": "^7.3.4",
- "@babel/plugin-transform-shorthand-properties": "^7.2.0",
- "@babel/plugin-transform-spread": "^7.2.0",
- "@babel/plugin-transform-sticky-regex": "^7.2.0",
- "@babel/plugin-transform-template-literals": "^7.2.0",
- "@babel/plugin-transform-typeof-symbol": "^7.2.0",
- "@babel/plugin-transform-unicode-regex": "^7.2.0",
- "browserslist": "^4.3.4",
- "invariant": "^2.2.2",
- "js-levenshtein": "^1.1.3",
- "semver": "^5.3.0"
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+ "@babel/plugin-transform-dotall-regex": "^7.4.4",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ },
+ "dependencies": {
+ "@babel/types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz",
+ "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "dev": true
+ }
}
},
"@babel/preset-react": {
@@ -867,6 +3104,24 @@
"@babel/plugin-transform-react-jsx-source": "^7.0.0"
}
},
+ "@babel/preset-typescript": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.10.4.tgz",
+ "integrity": "sha512-SdYnvGPv+bLlwkF2VkJnaX/ni1sMNetcGI1+nThF1gyv6Ph8Qucc4ZZAjM5yZcE/AKRXIOTZz7eSRDWOEjPyRQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-transform-typescript": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ }
+ }
+ },
"@babel/runtime": {
"version": "7.7.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.7.tgz",
@@ -1153,18 +3408,40 @@
"@turf/helpers": "6.x"
}
},
+ "@types/classnames": {
+ "version": "2.2.10",
+ "resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.10.tgz",
+ "integrity": "sha512-1UzDldn9GfYYEsWWnn/P4wkTlkZDH7lDb0wBMGbtIQc9zXEQq7FlKBdZUn6OBqD8sKZZ2RQO2mAjGpXiDGoRmQ==",
+ "dev": true
+ },
"@types/eslint-visitor-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
"integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
"dev": true
},
+ "@types/hoist-non-react-statics": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
"@types/json-schema": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz",
"integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==",
"dev": true
},
+ "@types/lodash": {
+ "version": "4.14.157",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.157.tgz",
+ "integrity": "sha512-Ft5BNFmv2pHDgxV5JDsndOWTRJ+56zte0ZpYLowp03tW+K+t8u8YMOzAnpuqPgzX6WO1XpDIUm7u04M8vdDiVQ==",
+ "dev": true
+ },
"@types/node": {
"version": "11.9.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.9.5.tgz",
@@ -1172,31 +3449,26 @@
"dev": true
},
"@types/prop-types": {
- "version": "15.7.0",
- "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.0.tgz",
- "integrity": "sha512-eItQyV43bj4rR3JPV0Skpl1SncRCdziTEK9/v8VwXmV6d/qOUO8/EuWeHBbCZcsfSHfzI5UyMJLCSXtxxznyZg=="
+ "version": "15.7.3",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
+ "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
+ "dev": true
},
"@types/react": {
- "version": "16.8.5",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.5.tgz",
- "integrity": "sha512-8LRySaaSJVLNZb2dbOGvGmzn88cbAfrgDpuWy+6lLgQ0OJFgHHvyuaCX4/7ikqJlpmCPf4uazJAZcfTQRdJqdQ==",
+ "version": "16.9.41",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.41.tgz",
+ "integrity": "sha512-6cFei7F7L4wwuM+IND/Q2cV1koQUvJ8iSV+Gwn0c3kvABZ691g7sp3hfEQHOUBJtccl1gPi+EyNjMIl9nGA0ug==",
+ "dev": true,
"requires": {
"@types/prop-types": "*",
"csstype": "^2.2.0"
}
},
"@types/react-dom": {
- "version": "16.8.2",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.8.2.tgz",
- "integrity": "sha512-MX7n1wq3G/De15RGAAqnmidzhr2Y9O/ClxPxyqaNg96pGyeXUYPSvujgzEVpLo9oIP4Wn1UETl+rxTN02KEpBw==",
- "requires": {
- "@types/react": "*"
- }
- },
- "@types/react-slick": {
- "version": "0.23.4",
- "resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.4.tgz",
- "integrity": "sha512-vXoIy4GUfB7/YgqubR4H7RALo+pRdMYCeLgWwV3MPwl5pggTlEkFBTF19R7u+LJc85uMqC7RfsbkqPLMQ4ab+A==",
+ "version": "16.9.8",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.8.tgz",
+ "integrity": "sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==",
+ "dev": true,
"requires": {
"@types/react": "*"
}
@@ -1516,6 +3788,11 @@
"negotiator": "0.6.1"
}
},
+ "ace-builds": {
+ "version": "1.4.12",
+ "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.4.12.tgz",
+ "integrity": "sha512-G+chJctFPiiLGvs3+/Mly3apXTcfgE45dT5yp12BcWZ1kUs+gm0qd3/fv4gsz6fVag4mM0moHVpjHDIgph6Psg=="
+ },
"acorn": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
@@ -1553,16 +3830,8 @@
"acorn-walk": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz",
- "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==",
- "dev": true
- },
- "add-dom-event-listener": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz",
- "integrity": "sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw==",
- "requires": {
- "object-assign": "4.x"
- }
+ "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==",
+ "dev": true
},
"add-line-numbers": {
"version": "1.0.1",
@@ -1687,70 +3956,77 @@
"integrity": "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8="
},
"antd": {
- "version": "3.26.17",
- "resolved": "https://registry.npmjs.org/antd/-/antd-3.26.17.tgz",
- "integrity": "sha512-P9uSK8SZ/1AvhQCC6aaLEkVrQhjbfZyUnqNV+lDnPqtudnZD2Ycy7Og+/EhuOBsQpYQvVT2aPLMgQWFv8tdJkA==",
- "requires": {
- "@ant-design/create-react-context": "^0.2.4",
- "@ant-design/icons": "~2.1.1",
- "@ant-design/icons-react": "~2.0.1",
- "@types/react-slick": "^0.23.4",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/antd/-/antd-4.4.3.tgz",
+ "integrity": "sha512-DA776Lfl7AOfGC+dWnA+QV4AopkrC/cDiI997S+JIBI85VaC2CiuYPYWYuTPPftpJR87UCx7p6Bgv1DvrdxNTw==",
+ "requires": {
+ "@ant-design/css-animation": "^1.7.2",
+ "@ant-design/icons": "^4.2.1",
+ "@ant-design/react-slick": "~0.26.3",
+ "@babel/runtime": "^7.10.4",
"array-tree-filter": "^2.1.0",
- "babel-runtime": "6.x",
- "classnames": "~2.2.6",
+ "classnames": "^2.2.6",
"copy-to-clipboard": "^3.2.0",
- "css-animation": "^1.5.0",
- "dom-closest": "^0.2.0",
- "enquire.js": "^2.1.6",
- "is-mobile": "^2.1.0",
"lodash": "^4.17.13",
- "moment": "^2.24.0",
- "omit.js": "^1.0.2",
- "prop-types": "^15.7.2",
+ "moment": "^2.25.3",
+ "omit.js": "^2.0.2",
"raf": "^3.4.1",
- "rc-animate": "^2.10.2",
- "rc-calendar": "~9.15.7",
- "rc-cascader": "~0.17.4",
- "rc-checkbox": "~2.1.6",
- "rc-collapse": "~1.11.3",
- "rc-dialog": "~7.6.0",
- "rc-drawer": "~3.1.1",
- "rc-dropdown": "~2.4.1",
- "rc-editor-mention": "^1.1.13",
- "rc-form": "^2.4.10",
- "rc-input-number": "~4.5.0",
- "rc-mentions": "~0.4.0",
- "rc-menu": "~7.5.1",
- "rc-notification": "~3.3.1",
- "rc-pagination": "~1.20.11",
- "rc-progress": "~2.5.0",
- "rc-rate": "~2.5.0",
- "rc-resize-observer": "^0.1.0",
- "rc-select": "~9.2.0",
- "rc-slider": "~8.7.1",
- "rc-steps": "~3.5.0",
- "rc-switch": "~1.9.0",
- "rc-table": "~6.10.5",
- "rc-tabs": "~9.7.0",
- "rc-time-picker": "~3.7.1",
- "rc-tooltip": "~3.7.3",
- "rc-tree": "~2.1.0",
- "rc-tree-select": "~2.9.1",
- "rc-trigger": "^2.6.2",
- "rc-upload": "~2.9.1",
- "rc-util": "^4.16.1",
- "react-lazy-load": "^3.0.13",
- "react-lifecycles-compat": "^3.0.4",
- "react-slick": "~0.25.2",
- "resize-observer-polyfill": "^1.5.1",
- "shallowequal": "^1.1.0",
- "warning": "~4.0.3"
+ "rc-animate": "~3.1.0",
+ "rc-cascader": "~1.3.0",
+ "rc-checkbox": "~2.3.0",
+ "rc-collapse": "~2.0.0",
+ "rc-dialog": "~8.1.0",
+ "rc-drawer": "~4.1.0",
+ "rc-dropdown": "~3.1.2",
+ "rc-field-form": "~1.5.0",
+ "rc-input-number": "~5.1.1",
+ "rc-mentions": "~1.4.0",
+ "rc-menu": "~8.5.0",
+ "rc-notification": "~4.4.0",
+ "rc-pagination": "~2.4.1",
+ "rc-picker": "~1.10.6",
+ "rc-progress": "~3.0.0",
+ "rc-rate": "~2.8.2",
+ "rc-resize-observer": "^0.2.3",
+ "rc-select": "^11.0.10",
+ "rc-slider": "~9.3.0",
+ "rc-steps": "~4.0.1",
+ "rc-switch": "~3.2.0",
+ "rc-table": "~7.8.0",
+ "rc-tabs": "~11.5.0",
+ "rc-textarea": "~0.3.0",
+ "rc-tooltip": "~4.2.0",
+ "rc-tree": "~3.6.0",
+ "rc-tree-select": "~4.0.2",
+ "rc-trigger": "~4.3.0",
+ "rc-upload": "~3.2.0",
+ "rc-util": "^5.0.1",
+ "scroll-into-view-if-needed": "^2.2.25",
+ "warning": "^4.0.3"
},
"dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
"lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
+ },
+ "moment": {
+ "version": "2.27.0",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz",
+ "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ=="
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
}
}
},
@@ -1877,7 +4153,7 @@
"array-tree-filter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
- "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
+ "integrity": "sha1-hzrAD+yDdJ8lWsjdCDgUtPYykZA="
},
"array-union": {
"version": "1.0.2",
@@ -1920,7 +4196,9 @@
"asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
- "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
+ "dev": true,
+ "optional": true
},
"asn1": {
"version": "0.2.4",
@@ -2020,9 +4298,9 @@
"dev": true
},
"async-validator": {
- "version": "1.11.5",
- "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.11.5.tgz",
- "integrity": "sha512-XNtCsMAeAH1pdLMEg1z8/Bb3a8cdCbui9QbJATRFHHHW5kT6+NPI3zSVQUXgikTFITzsg+kYY5NTWhM2Orwt9w=="
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-3.3.0.tgz",
+ "integrity": "sha512-cAHGD9EL8aCqWXjnb44q94MWiDFzUo1tMhvLb2WzcpWqGiKugsjWG9cvl+jPgkPca7asNbsBU3fa0cwkI/P+Xg=="
},
"asynckit": {
"version": "0.4.0",
@@ -2245,6 +4523,15 @@
"babel-runtime": "^6.22.0"
}
},
+ "babel-plugin-dynamic-import-node": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+ "dev": true,
+ "requires": {
+ "object.assign": "^4.1.0"
+ }
+ },
"babel-plugin-istanbul": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.1.tgz",
@@ -2678,11 +4965,6 @@
"typedarray-pool": "^1.1.0"
}
},
- "brace": {
- "version": "0.11.1",
- "resolved": "https://registry.npmjs.org/brace/-/brace-0.11.1.tgz",
- "integrity": "sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg="
- },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -2811,14 +5093,23 @@
}
},
"browserslist": {
- "version": "4.4.2",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.2.tgz",
- "integrity": "sha512-ISS/AIAiHERJ3d45Fz0AVYKkgcy+F/eJHzKEvv1j0wwKGKD9T3BrwKr/5g45L+Y4XIK5PlTqefHciRFcfE1Jxg==",
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.13.0.tgz",
+ "integrity": "sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ==",
"dev": true,
"requires": {
- "caniuse-lite": "^1.0.30000939",
- "electron-to-chromium": "^1.3.113",
- "node-releases": "^1.1.8"
+ "caniuse-lite": "^1.0.30001093",
+ "electron-to-chromium": "^1.3.488",
+ "escalade": "^3.0.1",
+ "node-releases": "^1.1.58"
+ },
+ "dependencies": {
+ "electron-to-chromium": {
+ "version": "1.3.496",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.496.tgz",
+ "integrity": "sha512-TXY4mwoyowwi4Lsrq9vcTUYBThyc1b2hXaTZI13p8/FRhY2CTaq5lK+DVjhYkKiTLsKt569Xes+0J5JsVXFurQ==",
+ "dev": true
+ }
}
},
"bser": {
@@ -3037,9 +5328,9 @@
"dev": true
},
"caniuse-lite": {
- "version": "1.0.30000939",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000939.tgz",
- "integrity": "sha512-oXB23ImDJOgQpGjRv1tCtzAvJr4/OvrHi5SO2vUgB0g0xpdZZoA/BxfImiWfdwoYdUTtQrPsXsvYU/dmCSM8gg==",
+ "version": "1.0.30001097",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001097.tgz",
+ "integrity": "sha512-TeuSleKt/vWXaPkLVFqGDnbweYfq4IaZ6rUugFf3rWY6dlII8StUZ8Ddin0PkADfgYZ4wRqCdO2ORl4Rn5eZIA==",
"dev": true
},
"canvas-fit": {
@@ -3544,25 +5835,12 @@
"integrity": "sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==",
"dev": true
},
- "component-classes": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/component-classes/-/component-classes-1.2.6.tgz",
- "integrity": "sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE=",
- "requires": {
- "component-indexof": "0.0.3"
- }
- },
"component-emitter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
"dev": true
},
- "component-indexof": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/component-indexof/-/component-indexof-0.0.3.tgz",
- "integrity": "sha1-EdCRMSI5648yyPJa6csAL/6NPCQ="
- },
"compressible": {
"version": "2.0.16",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.16.tgz",
@@ -3616,6 +5894,11 @@
"validate.io-positive-integer": "^1.0.0"
}
},
+ "compute-scroll-into-view": {
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.14.tgz",
+ "integrity": "sha512-mKDjINe3tc6hGelUMNDzuhorIUZ7kS7BwyY0r2wQd2HOH2tRuJykiC06iSEX8y1TuhNzvz4GcJnK16mM2J1NMQ=="
+ },
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -3770,7 +6053,7 @@
"copy-to-clipboard": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz",
- "integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==",
+ "integrity": "sha1-EVqhqZmP+rYZb5MHatbaO5E2Yq4=",
"requires": {
"toggle-selection": "^1.0.6"
}
@@ -3861,6 +6144,24 @@
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.4.tgz",
"integrity": "sha512-05qQ5hXShcqGkPZpXEFLIpxayZscVD2kuMBZewxiIPPEagukO4mqgPA9CWhUvFBJfy3ODdK2p9xyHh7FTU9/7A=="
},
+ "core-js-compat": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz",
+ "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.8.5",
+ "semver": "7.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
+ "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
+ "dev": true
+ }
+ }
+ },
"core-js-pure": {
"version": "3.4.7",
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.4.7.tgz",
@@ -3914,16 +6215,6 @@
"sha.js": "^2.4.8"
}
},
- "create-react-class": {
- "version": "15.6.3",
- "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz",
- "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==",
- "requires": {
- "fbjs": "^0.8.9",
- "loose-envify": "^1.3.1",
- "object-assign": "^4.1.1"
- }
- },
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -3956,15 +6247,6 @@
"randomfill": "^1.0.3"
}
},
- "css-animation": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/css-animation/-/css-animation-1.6.1.tgz",
- "integrity": "sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog==",
- "requires": {
- "babel-runtime": "6.x",
- "component-classes": "^1.2.5"
- }
- },
"css-color-names": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
@@ -4181,9 +6463,10 @@
}
},
"csstype": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.2.tgz",
- "integrity": "sha512-Rl7PvTae0pflc1YtxtKbiSqq20Ts6vpIYOD5WBafl4y123DyHUeLrRdQP66sQW8/6gmX8jrYJLXwNeMqYVJcow=="
+ "version": "2.6.11",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.11.tgz",
+ "integrity": "sha512-l8YyEC9NBkSm783PFTvh0FmJy7s5pFKrDp49ZL7zBGX3fWkO+N4EEyan1qqp8cwPLDcD0OSdyY6hAMoxp34JFw==",
+ "dev": true
},
"cubic-hermite": {
"version": "1.0.0",
@@ -4571,9 +6854,9 @@
"dev": true
},
"diff-match-patch": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.4.tgz",
- "integrity": "sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg=="
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz",
+ "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw=="
},
"diff-sequences": {
"version": "24.0.0",
@@ -4644,15 +6927,7 @@
"dom-align": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.0.tgz",
- "integrity": "sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA=="
- },
- "dom-closest": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/dom-closest/-/dom-closest-0.2.0.tgz",
- "integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
- "requires": {
- "dom-matches": ">=1.0.1"
- }
+ "integrity": "sha1-VvtxVt8LkQmYMDZNLUj4iWP1opw="
},
"dom-converter": {
"version": "0.2.0",
@@ -4692,16 +6967,6 @@
}
}
},
- "dom-matches": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/dom-matches/-/dom-matches-2.0.0.tgz",
- "integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
- },
- "dom-scroll-into-view": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-1.2.1.tgz",
- "integrity": "sha1-6PNnMt0ImwIBqI14Fdw/iObWbH4="
- },
"dom-serializer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
@@ -4770,16 +7035,6 @@
"resolved": "https://registry.npmjs.org/double-bits/-/double-bits-1.1.1.tgz",
"integrity": "sha1-WKu6RUlNpND6Nrc60RoobJGEscY="
},
- "draft-js": {
- "version": "0.10.5",
- "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.10.5.tgz",
- "integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==",
- "requires": {
- "fbjs": "^0.8.15",
- "immutable": "~3.7.4",
- "object-assign": "^4.1.0"
- }
- },
"draw-svg-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/draw-svg-path/-/draw-svg-path-1.0.0.tgz",
@@ -4953,14 +7208,6 @@
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
"dev": true
},
- "encoding": {
- "version": "0.1.12",
- "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
- "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
- "requires": {
- "iconv-lite": "~0.4.13"
- }
- },
"end-of-stream": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
@@ -4969,11 +7216,6 @@
"once": "^1.4.0"
}
},
- "enquire.js": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz",
- "integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ="
- },
"entities": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
@@ -5133,6 +7375,12 @@
"es6-symbol": "^3.1.1"
}
},
+ "escalade": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.1.tgz",
+ "integrity": "sha512-DR6NO3h9niOT+MZs7bjxlj2a1k+POu5RN8CLTPX2+i78bRi9eLe7+0zXgUHMnGXWybYcL61E9hGhPKqedy8tQA==",
+ "dev": true
+ },
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -6031,11 +8279,6 @@
"integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==",
"dev": true
},
- "eventlistener": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/eventlistener/-/eventlistener-0.0.1.tgz",
- "integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg="
- },
"events": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
@@ -6406,27 +8649,6 @@
"bser": "^2.0.0"
}
},
- "fbjs": {
- "version": "0.8.17",
- "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
- "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
- "requires": {
- "core-js": "^1.0.0",
- "isomorphic-fetch": "^2.1.1",
- "loose-envify": "^1.0.0",
- "object-assign": "^4.1.0",
- "promise": "^7.1.1",
- "setimmediate": "^1.0.5",
- "ua-parser-js": "^0.7.18"
- },
- "dependencies": {
- "core-js": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
- "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
- }
- }
- },
"figgy-pudding": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
@@ -6785,6 +9007,12 @@
"universalify": "^0.1.0"
}
},
+ "fs-readdir-recursive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
+ "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
+ "dev": true
+ },
"fs-write-stream-atomic": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
@@ -7309,6 +9537,12 @@
"resolved": "https://registry.npmjs.org/gamma/-/gamma-0.1.0.tgz",
"integrity": "sha1-MxVkNAO/J5BsqAqzfDbs6UQO8zA="
},
+ "gensync": {
+ "version": "1.0.0-beta.1",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
+ "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==",
+ "dev": true
+ },
"geojson-vt": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz",
@@ -8116,11 +10350,6 @@
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
"dev": true
},
- "gud": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
- "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
- },
"gzip-size": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-4.1.0.tgz",
@@ -8131,11 +10360,6 @@
"pify": "^3.0.0"
}
},
- "hammerjs": {
- "version": "2.0.8",
- "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
- "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
- },
"handle-thing": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz",
@@ -8607,6 +10831,7 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
@@ -8690,11 +10915,6 @@
"invariant": "^2.2.0"
}
},
- "immutable": {
- "version": "3.7.6",
- "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
- "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
- },
"import-fresh": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
@@ -8894,6 +11114,11 @@
}
}
},
+ "insert-css": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/insert-css/-/insert-css-2.0.0.tgz",
+ "integrity": "sha1-610Ql7dUL0x56jBg067gfQU4gPQ="
+ },
"internal-ip": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.2.0.tgz",
@@ -9217,7 +11442,8 @@
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
- "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true
},
"is-string": {
"version": "1.0.4",
@@ -9287,15 +11513,6 @@
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
"dev": true
},
- "isomorphic-fetch": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
- "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
- "requires": {
- "node-fetch": "^1.0.1",
- "whatwg-fetch": ">=0.10.0"
- }
- },
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -9925,11 +12142,10 @@
"integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==",
"dev": true
},
- "js-levenshtein": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
- "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==",
- "dev": true
+ "js-cookie": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
+ "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
},
"js-tokens": {
"version": "4.0.0",
@@ -10052,12 +12268,20 @@
"dev": true
},
"json5": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz",
- "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
+ "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
"dev": true,
"requires": {
- "minimist": "^1.2.0"
+ "minimist": "^1.2.5"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+ "dev": true
+ }
}
},
"jsonfile": {
@@ -10215,6 +12439,23 @@
"integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=",
"dev": true
},
+ "levenary": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz",
+ "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==",
+ "dev": true,
+ "requires": {
+ "leven": "^3.1.0"
+ },
+ "dependencies": {
+ "leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true
+ }
+ }
+ },
"levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
@@ -10336,11 +12577,6 @@
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
"dev": true
},
- "lodash.debounce": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
- "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
- },
"lodash.escape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
@@ -10375,11 +12611,6 @@
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
"dev": true
},
- "lodash.throttle": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
- "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
- },
"lodash.unescape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz",
@@ -10817,20 +13048,21 @@
}
},
"mini-store": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/mini-store/-/mini-store-2.0.0.tgz",
- "integrity": "sha512-EG0CuwpQmX+XL4QVS0kxNwHW5ftSbhygu1qxQH0pipugjnPkbvkalCdQbEihMwtQY6d3MTN+MS0q+aurs+RfLQ==",
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/mini-store/-/mini-store-3.0.5.tgz",
+ "integrity": "sha512-A7f0+d7TEvjJNY2K+splh2OG3AhmoPoiF3VntlAcJuBzryMumOF9LAVzg8mRJPPbCkz7mlWQg9MCMQPR2auftA==",
"requires": {
- "hoist-non-react-statics": "^2.3.1",
- "prop-types": "^15.6.0",
- "react-lifecycles-compat": "^3.0.4",
+ "hoist-non-react-statics": "^3.3.2",
"shallowequal": "^1.0.2"
},
"dependencies": {
"hoist-non-react-statics": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
- "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "requires": {
+ "react-is": "^16.7.0"
+ }
}
}
},
@@ -11075,11 +13307,6 @@
"resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz",
"integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ=="
},
- "mutationobserver-shim": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/mutationobserver-shim/-/mutationobserver-shim-0.3.5.tgz",
- "integrity": "sha512-YAMuSp4Oi19SYQF04dGnRajyFp4Wyam+jKKWzm5roPcNh1Rip8dnHPxls5F/xBgY0H2gV+3IzWuIvYQPDAvmBQ=="
- },
"mute-stream": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
@@ -11295,15 +13522,6 @@
"lower-case": "^1.1.1"
}
},
- "node-fetch": {
- "version": "1.7.3",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
- "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
- "requires": {
- "encoding": "^0.1.11",
- "is-stream": "^1.0.1"
- }
- },
"node-forge": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
@@ -11422,13 +13640,10 @@
}
},
"node-releases": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.8.tgz",
- "integrity": "sha512-gQm+K9mGCiT/NXHy+V/ZZS1N/LOaGGqRAAJJs3X9Ah1g+CIbRcBgNyoNYQ+SEtcyAtB9KqDruu+fF7nWjsqRaA==",
- "dev": true,
- "requires": {
- "semver": "^5.3.0"
- }
+ "version": "1.1.59",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.59.tgz",
+ "integrity": "sha512-H3JrdUczbdiwxN5FuJPyCHnGHIFqQ0wWxo+9j1kAXAzqNMAHlo+4I/sYYxpyK0irQ73HgdiyzD32oqQDcU2Osw==",
+ "dev": true
},
"nopt": {
"version": "2.1.2",
@@ -11713,12 +13928,9 @@
"dev": true
},
"omit.js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/omit.js/-/omit.js-1.0.2.tgz",
- "integrity": "sha512-/QPc6G2NS+8d4L/cQhbk6Yit1WTB6Us2g84A7A/1+w9d/eRGHyEqC5kkQtHVoHZ5NFWGG7tUGgrhVZwgZanKrQ==",
- "requires": {
- "babel-runtime": "^6.23.0"
- }
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/omit.js/-/omit.js-2.0.2.tgz",
+ "integrity": "sha512-hJmu9D+bNB40YpL9jYebQl4lsTW6yEHRTroJzNLqQJYHm7c+NQnJGfZmIWh8S3q3KoaxV1aLhV6B3+0N0/kyJg=="
},
"on-finished": {
"version": "2.3.0",
@@ -12888,12 +15100,6 @@
}
}
},
- "private": {
- "version": "0.1.8",
- "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
- "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
- "dev": true
- },
"process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@@ -12915,6 +15121,8 @@
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "dev": true,
+ "optional": true,
"requires": {
"asap": "~2.0.3"
}
@@ -13216,511 +15424,735 @@
"dev": true
},
"rc-align": {
- "version": "2.4.5",
- "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-2.4.5.tgz",
- "integrity": "sha512-nv9wYUYdfyfK+qskThf4BQUSIadeI/dCsfaMZfNEoxm9HwOIioQ+LyqmMK6jWHAZQgOzMLaqawhuBXlF63vgjw==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.1.tgz",
+ "integrity": "sha512-RQ5Fhxl0LW+zsxbY8dxAcpXdaHkHH2jzRSSpvBTS7G9LMK3T+WRcn4ovjg/eqAESM6TdTx0hfqWF2S1pO75jxQ==",
"requires": {
- "babel-runtime": "^6.26.0",
+ "@babel/runtime": "^7.10.1",
+ "classnames": "2.x",
"dom-align": "^1.7.0",
- "prop-types": "^15.5.8",
- "rc-util": "^4.0.4"
+ "rc-util": "^5.0.1",
+ "resize-observer-polyfill": "^1.5.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-animate": {
- "version": "2.11.1",
- "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-2.11.1.tgz",
- "integrity": "sha512-1NyuCGFJG/0Y+9RKh5y/i/AalUCA51opyyS/jO2seELpgymZm2u9QV3xwODwEuzkmeQ1BDPxMLmYLcTJedPlkQ==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.0.tgz",
+ "integrity": "sha512-8FsM+3B1H+0AyTyGggY6JyVldHTs1CyYT8CfTmG/nGHHXlecvSLeICJhcKgRLjUiQlctNnRtB1rwz79cvBVmrw==",
"requires": {
- "babel-runtime": "6.x",
+ "@ant-design/css-animation": "^1.7.2",
"classnames": "^2.2.6",
- "css-animation": "^1.3.2",
- "prop-types": "15.x",
"raf": "^3.4.0",
- "rc-util": "^4.15.3",
- "react-lifecycles-compat": "^3.0.4"
- }
- },
- "rc-calendar": {
- "version": "9.15.10",
- "resolved": "https://registry.npmjs.org/rc-calendar/-/rc-calendar-9.15.10.tgz",
- "integrity": "sha512-xh1A3rYejKskAvkjnd9BcHXFbBnAYsHMGHBdtoAkbwp43B6yEieNL0g0Tzz8s1gApDZV2j5vF1jJ9IIpPYFNLw==",
- "requires": {
- "babel-runtime": "6.x",
- "classnames": "2.x",
- "moment": "2.x",
- "prop-types": "^15.5.8",
- "rc-trigger": "^2.2.0",
- "rc-util": "^4.1.1",
- "react-lifecycles-compat": "^3.0.4"
+ "rc-util": "^5.0.1"
}
},
"rc-cascader": {
- "version": "0.17.5",
- "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-0.17.5.tgz",
- "integrity": "sha512-WYMVcxU0+Lj+xLr4YYH0+yXODumvNXDcVEs5i7L1mtpWwYkubPV/zbQpn+jGKFCIW/hOhjkU4J1db8/P/UKE7A==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-1.3.0.tgz",
+ "integrity": "sha512-wayuMo/dSZixvdpiRFZB4Q6A3omKRXQcJ3CxN02+PNiTEcRnK2KDqKUzrx7GwgMsyH5tz90lUZ91lLaEPNFv0A==",
"requires": {
"array-tree-filter": "^2.1.0",
- "prop-types": "^15.5.8",
- "rc-trigger": "^2.2.0",
- "rc-util": "^4.0.4",
- "react-lifecycles-compat": "^3.0.4",
- "shallow-equal": "^1.0.0",
+ "rc-trigger": "^4.0.0",
+ "rc-util": "^5.0.1",
"warning": "^4.0.1"
}
},
"rc-checkbox": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.1.8.tgz",
- "integrity": "sha512-6qOgh0/by0nVNASx6LZnhRTy17Etcgav+IrI7kL9V9kcDZ/g7K14JFlqrtJ3NjDq/Kyn+BPI1st1XvbkhfaJeg==",
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.3.1.tgz",
+ "integrity": "sha512-i290/iTqmZ0WtI2UPIryqT9rW6O99+an4KeZIyZDH3r+Jbb6YdddaWNdzq7g5m9zaNhJvgjf//wJtC4fvve2Tg==",
"requires": {
- "babel-runtime": "^6.23.0",
- "classnames": "2.x",
- "prop-types": "15.x",
- "react-lifecycles-compat": "^3.0.4"
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-collapse": {
- "version": "1.11.8",
- "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-1.11.8.tgz",
- "integrity": "sha512-8EhfPyScTYljkbRuIoHniSwZagD5UPpZ3CToYgoNYWC85L2qCbPYF7+OaC713FOrIkp6NbfNqXsITNxmDAmxog==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-2.0.0.tgz",
+ "integrity": "sha512-R5+Ge1uzwK9G1wZPRPhqQsed4FXTDmU0BKzsqfNBtZdk/wd+yey8ZutmJmSozYc5hQwjPkCvJHV7gOIRZKIlJg==",
"requires": {
+ "@ant-design/css-animation": "^1.7.2",
"classnames": "2.x",
- "css-animation": "1.x",
- "prop-types": "^15.5.6",
- "rc-animate": "2.x",
+ "rc-animate": "3.x",
"react-is": "^16.7.0",
- "react-lifecycles-compat": "^3.0.4",
"shallowequal": "^1.1.0"
}
},
"rc-dialog": {
- "version": "7.6.1",
- "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-7.6.1.tgz",
- "integrity": "sha512-KUKf+2eZ4YL+lnXMG3hR4ZtIhC9glfH27NtTVz3gcoDIPAf3uUvaXVRNoDCiSi+OGKLyIb/b6EoidFh6nQC5Wg==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-8.1.0.tgz",
+ "integrity": "sha512-vMVAtyxpnokh/okFcDQVLO6ymIXfoTKYKtqJ/hMtf+0WcvRn4VgVDBvGyEk5zd94k0RgwEze9o2kGw8SyjivZg==",
"requires": {
- "babel-runtime": "6.x",
- "rc-animate": "2.x",
- "rc-util": "^4.16.1"
+ "rc-animate": "3.x",
+ "rc-util": "^5.0.1"
}
},
"rc-drawer": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-3.1.3.tgz",
- "integrity": "sha512-2z+RdxmzXyZde/1OhVMfDR1e/GBswFeWSZ7FS3Fdd0qhgVdpV1wSzILzzxRaT481ItB5hOV+e8pZT07vdJE8kg==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-4.1.0.tgz",
+ "integrity": "sha512-kjeQFngPjdzAFahNIV0EvEBoIKMOnvUsAxpkSPELoD/1DuR4nLafom5ryma+TIxGwkFJ92W6yjsMi1U9aiOTeQ==",
"requires": {
+ "@babel/runtime": "^7.10.1",
"classnames": "^2.2.6",
- "rc-util": "^4.16.1",
- "react-lifecycles-compat": "^3.0.4"
+ "rc-util": "^5.0.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-dropdown": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-2.4.1.tgz",
- "integrity": "sha512-p0XYn0wrOpAZ2fUGE6YJ6U8JBNc5ASijznZ6dkojdaEfQJAeZtV9KMEewhxkVlxGSbbdXe10ptjBlTEW9vEwEg==",
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-3.1.2.tgz",
+ "integrity": "sha512-s2W5jqvjTid5DxotGO5FlTBaQWeB+Bu7McQgjB8Ot3Wbl72AIKwLf11+lgbV4mA2vWC1H8DKyn6SW9TKLTi0xg==",
"requires": {
- "babel-runtime": "^6.26.0",
+ "@babel/runtime": "^7.10.1",
"classnames": "^2.2.6",
- "prop-types": "^15.5.8",
- "rc-trigger": "^2.5.1",
- "react-lifecycles-compat": "^3.0.2"
- }
- },
- "rc-editor-core": {
- "version": "0.8.10",
- "resolved": "https://registry.npmjs.org/rc-editor-core/-/rc-editor-core-0.8.10.tgz",
- "integrity": "sha512-T3aHpeMCIYA1sdAI7ynHHjXy5fqp83uPlD68ovZ0oClTSc3tbHmyCxXlA+Ti4YgmcpCYv7avF6a+TIbAka53kw==",
- "requires": {
- "babel-runtime": "^6.26.0",
- "classnames": "^2.2.5",
- "draft-js": "^0.10.0",
- "immutable": "^3.7.4",
- "lodash": "^4.16.5",
- "prop-types": "^15.5.8",
- "setimmediate": "^1.0.5"
- }
- },
- "rc-editor-mention": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/rc-editor-mention/-/rc-editor-mention-1.1.13.tgz",
- "integrity": "sha512-3AOmGir91Fi2ogfRRaXLtqlNuIwQpvla7oUnGHS1+3eo7b+fUp5IlKcagqtwUBB5oDNofoySXkLBxzWvSYNp/Q==",
- "requires": {
- "babel-runtime": "^6.23.0",
- "classnames": "^2.2.5",
- "dom-scroll-into-view": "^1.2.0",
- "draft-js": "~0.10.0",
- "immutable": "~3.7.4",
- "prop-types": "^15.5.8",
- "rc-animate": "^2.3.0",
- "rc-editor-core": "~0.8.3"
- }
- },
- "rc-form": {
- "version": "2.4.11",
- "resolved": "https://registry.npmjs.org/rc-form/-/rc-form-2.4.11.tgz",
- "integrity": "sha512-8BL+FNlFLTOY/A5X6tU35GQJLSIpsmqpwn/tFAYQTczXc4dMJ33ggtH248Cum8+LS0jLTsJKG2L4Qp+1CkY+sA==",
- "requires": {
- "async-validator": "~1.11.3",
- "babel-runtime": "6.x",
- "create-react-class": "^15.5.3",
- "dom-scroll-into-view": "1.x",
- "hoist-non-react-statics": "^3.3.0",
- "lodash": "^4.17.4",
- "rc-util": "^4.15.3",
- "warning": "^4.0.3"
+ "rc-trigger": "^4.0.0"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
- "rc-hammerjs": {
- "version": "0.6.9",
- "resolved": "https://registry.npmjs.org/rc-hammerjs/-/rc-hammerjs-0.6.9.tgz",
- "integrity": "sha512-4llgWO3RgLyVbEqUdGsDfzUDqklRlQW5VEhE3x35IvhV+w//VPRG34SBavK3D2mD/UaLKaohgU41V4agiftC8g==",
+ "rc-field-form": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.5.1.tgz",
+ "integrity": "sha512-h/v/5/iYf4DEZvYfxvmkCS6N2PNm2LW2Ha6oDBglWDNA0TcOFCeIWSq8q+r/Pyq/EHA55iGye4ezhKLzOUgvJg==",
"requires": {
- "babel-runtime": "6.x",
- "hammerjs": "^2.0.8",
- "prop-types": "^15.5.9"
+ "@babel/runtime": "^7.8.4",
+ "async-validator": "^3.0.3",
+ "rc-util": "^5.0.0"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-input-number": {
- "version": "4.5.7",
- "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-4.5.7.tgz",
- "integrity": "sha512-99PrQ90sTOKyyj7eu0VzwxY17xQ+bwG1XTQd+bTwFQ+IOUkIw7L4qSAYxt58sVYL+Cw+bu/RAtT2IpT9yC2pCQ==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-5.1.1.tgz",
+ "integrity": "sha512-16ln4rfgMcAYDAdx6MSYgbgoYjLCRXGkOC4G0I8NEiCOcBshuYCTf6tFdnBOVfsq0Zw9kj1qKoIrCEoRRkbGdw==",
"requires": {
- "babel-runtime": "6.x",
"classnames": "^2.2.0",
- "prop-types": "^15.5.7",
- "rc-util": "^4.5.1",
- "rmc-feedback": "^2.0.0"
+ "rc-util": "^5.0.1"
}
},
"rc-mentions": {
- "version": "0.4.2",
- "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-0.4.2.tgz",
- "integrity": "sha512-DTZurQzacLXOfVuiHydGzqkq7cFMHXF18l2jZ9PhWUn2cqvOSY3W4osN0Pq29AOMOBpcxdZCzgc7Lb0r/bgkDw==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.4.0.tgz",
+ "integrity": "sha512-DIcjQZNerCZ50tnDnL6P9mpNmlGc9VFrSjXh55RzkAZOTelf061T7ZbYv0bYeSdohvAwYNr4gt3/Pe79AUsjLw==",
"requires": {
- "@ant-design/create-react-context": "^0.2.4",
+ "@babel/runtime": "^7.10.1",
"classnames": "^2.2.6",
- "rc-menu": "^7.4.22",
- "rc-trigger": "^2.6.2",
- "rc-util": "^4.6.0",
- "react-lifecycles-compat": "^3.0.4"
+ "rc-menu": "^8.0.1",
+ "rc-textarea": "^0.3.0",
+ "rc-trigger": "^4.3.0",
+ "rc-util": "^5.0.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-menu": {
- "version": "7.5.5",
- "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-7.5.5.tgz",
- "integrity": "sha512-4YJXJgrpUGEA1rMftXN7bDhrV5rPB8oBJoHqT+GVXtIWCanfQxEnM3fmhHQhatL59JoAFMZhJaNzhJIk4FUWCQ==",
+ "version": "8.5.0",
+ "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-8.5.0.tgz",
+ "integrity": "sha512-zEf3gKcdEKrI2/GpotOyIuVqrqEEJLLb+bLBTud+5b6Y70xwUH8IZvK6kXdHdqEnJGEZmq5NIy8Ufcr+HOYGxQ==",
"requires": {
+ "@babel/runtime": "^7.10.1",
"classnames": "2.x",
- "dom-scroll-into-view": "1.x",
- "mini-store": "^2.0.0",
- "mutationobserver-shim": "^0.3.2",
- "rc-animate": "^2.10.1",
- "rc-trigger": "^2.3.0",
- "rc-util": "^4.13.0",
+ "mini-store": "^3.0.1",
+ "omit.js": "^2.0.0",
+ "rc-animate": "^3.1.0",
+ "rc-trigger": "^4.2.0",
+ "rc-util": "^5.0.1",
"resize-observer-polyfill": "^1.5.0",
"shallowequal": "^1.1.0"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-notification": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-3.3.1.tgz",
- "integrity": "sha512-U5+f4BmBVfMSf3OHSLyRagsJ74yKwlrQAtbbL5ijoA0F2C60BufwnOcHG18tVprd7iaIjzZt1TKMmQSYSvgrig==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-4.4.0.tgz",
+ "integrity": "sha512-IDeNAFGVeOsy1tv4zNVqMAXB9tianR80ewQbtObaAQfjwAjWfONdqdyjFkEU6nc6UQhSUYA5OcTGb7kwwbnh0g==",
"requires": {
- "babel-runtime": "6.x",
+ "@babel/runtime": "^7.10.1",
"classnames": "2.x",
- "prop-types": "^15.5.8",
- "rc-animate": "2.x",
- "rc-util": "^4.0.4"
+ "rc-animate": "3.x",
+ "rc-util": "^5.0.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-pagination": {
- "version": "1.20.14",
- "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-1.20.14.tgz",
- "integrity": "sha512-sNKwbFrxiqATqcIIShfrFs8BT03n4UUwTAMYae+JhHTmILQmXdvimEnZbVuWcno6G02DAJcLrFpmkn1h2tmEJw==",
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-2.4.4.tgz",
+ "integrity": "sha512-YpLZ/9xIpzmMQLdtyBHc39GbP0354EOAM32a89m9F25o4mQVchcfIly4dv1sCnEHqLcyf0y9diftnVZRBxRwKg==",
"requires": {
- "babel-runtime": "6.x",
- "classnames": "^2.2.6",
- "prop-types": "^15.5.7",
- "react-lifecycles-compat": "^3.0.4"
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
+ }
+ },
+ "rc-picker": {
+ "version": "1.10.7",
+ "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-1.10.7.tgz",
+ "integrity": "sha512-UgMAi//vxYf437fCG4fRlHwcS365wjLju/G0UgRJalrbnDMxUhgZ5XLi9pGY0M9ZWQeCDe9eywr409dITXQXFA==",
+ "requires": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.1",
+ "moment": "^2.24.0",
+ "rc-trigger": "^4.0.0",
+ "rc-util": "^5.0.1",
+ "shallowequal": "^1.1.0"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-progress": {
- "version": "2.5.3",
- "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-2.5.3.tgz",
- "integrity": "sha512-K2fa4CnqGehLZoMrdmBeZ86ONSTVcdk5FlqetbwJ3R/+42XfqhwQVOjWp2MH4P7XSQOMAGcNOy1SFfCP3415sg==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.0.0.tgz",
+ "integrity": "sha512-dQv1KU3o6Vay604FMYMF4S0x4GNXAgXf1tbQ1QoxeIeQt4d5fUeB7Ri82YPu+G+aRvH/AtxYAlEcnxyVZ1/4Hw==",
"requires": {
- "babel-runtime": "6.x",
- "prop-types": "^15.5.8"
+ "classnames": "^2.2.6"
}
},
"rc-rate": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.5.1.tgz",
- "integrity": "sha512-3iJkNJT8xlHklPCdeZtUZmJmRVUbr6AHRlfSsztfYTXVlHrv2TcPn3XkHsH+12j812WVB7gvilS2j3+ffjUHXg==",
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.8.2.tgz",
+ "integrity": "sha512-f9T/D+ZwWQrWHkpidpQbnXpnVMGMC4eSRAkwuu88a8Qv1C/9LNc4AErazoh8tpnZBFqq19F3j0Glv+sDgkfEig==",
"requires": {
+ "@babel/runtime": "^7.10.1",
"classnames": "^2.2.5",
- "prop-types": "^15.5.8",
- "rc-util": "^4.3.0",
- "react-lifecycles-compat": "^3.0.4"
+ "rc-util": "^5.0.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-resize-observer": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-0.1.3.tgz",
- "integrity": "sha512-uzOQEwx83xdQSFOkOAM7x7GHIQKYnrDV4dWxtCxyG1BS1pkfJ4EvDeMfsvAJHSYkQXVBu+sgRHGbRtLG3qiuUg==",
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-0.2.3.tgz",
+ "integrity": "sha512-dEPCGX15eRRnu+TNBIGyEghpzE24fTDW8pHdJPJS/kCR3lafFqBLqKzBgZW6pMUuM70/ZDyFQ0Kynx9kWsXRNw==",
"requires": {
+ "@babel/runtime": "^7.10.1",
"classnames": "^2.2.1",
- "rc-util": "^4.13.0",
+ "rc-util": "^5.0.0",
"resize-observer-polyfill": "^1.5.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-select": {
- "version": "9.2.3",
- "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-9.2.3.tgz",
- "integrity": "sha512-WhswxOMWiNnkXRbxyrj0kiIvyCfo/BaRPaYbsDetSIAU2yEDwKHF798blCP5u86KLOBKBvtxWLFCkSsQw1so5w==",
+ "version": "11.0.11",
+ "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-11.0.11.tgz",
+ "integrity": "sha512-7xW5U6fyjr5j6CG3/Bl0ceUKzpNDOctJiIcK1eyLYq7Va+KFB0kNFMYULHPI41m/TJJIKDCW3N08K3rd2Z2SIA==",
"requires": {
- "babel-runtime": "^6.23.0",
+ "@babel/runtime": "^7.10.1",
"classnames": "2.x",
- "component-classes": "1.x",
- "dom-scroll-into-view": "1.x",
- "prop-types": "^15.5.8",
- "raf": "^3.4.0",
- "rc-animate": "2.x",
- "rc-menu": "^7.3.0",
- "rc-trigger": "^2.5.4",
- "rc-util": "^4.0.4",
- "react-lifecycles-compat": "^3.0.2",
- "warning": "^4.0.2"
+ "rc-animate": "^3.0.0",
+ "rc-trigger": "^4.3.0",
+ "rc-util": "^5.0.1",
+ "rc-virtual-list": "^1.1.2",
+ "warning": "^4.0.3"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-slider": {
- "version": "8.7.1",
- "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-8.7.1.tgz",
- "integrity": "sha512-WMT5mRFUEcrLWwTxsyS8jYmlaMsTVCZIGENLikHsNv+tE8ThU2lCoPfi/xFNUfJFNFSBFP3MwPez9ZsJmNp13g==",
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-9.3.1.tgz",
+ "integrity": "sha512-c52PWPyrfJWh28K6dixAm0906L3/4MUIxqrNQA4TLnC/Z+cBNycWJUZoJerpwSOE1HdM3XDwixCsmtFc/7aWlQ==",
"requires": {
- "babel-runtime": "6.x",
+ "@babel/runtime": "^7.10.1",
"classnames": "^2.2.5",
- "prop-types": "^15.5.4",
- "rc-tooltip": "^3.7.0",
- "rc-util": "^4.0.4",
- "react-lifecycles-compat": "^3.0.4",
- "shallowequal": "^1.1.0",
- "warning": "^4.0.3"
+ "rc-tooltip": "^4.0.0",
+ "rc-util": "^5.0.0",
+ "shallowequal": "^1.1.0"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-steps": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-3.5.0.tgz",
- "integrity": "sha512-2Vkkrpa7PZbg7qPsqTNzVDov4u78cmxofjjnIHiGB9+9rqKS8oTLPzbW2uiWDr3Lk+yGwh8rbpGO1E6VAgBCOg==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-4.0.1.tgz",
+ "integrity": "sha512-6MuqunJDIZexZj7v5EcHiOF6Q7Xg53+mcxELiIROhvXatssfLxDESpRZJ3zLquecxRjq5epYt92X8xBJ653itg==",
"requires": {
- "babel-runtime": "^6.23.0",
+ "@babel/runtime": "^7.10.2",
"classnames": "^2.2.3",
- "lodash": "^4.17.5",
- "prop-types": "^15.5.7"
+ "rc-util": "^5.0.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-switch": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-1.9.0.tgz",
- "integrity": "sha512-Isas+egaK6qSk64jaEw4GgPStY4umYDbT7ZY93bZF1Af+b/JEsKsJdNOU2qG3WI0Z6tXo2DDq0kJCv8Yhu0zww==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-3.2.0.tgz",
+ "integrity": "sha512-WQZnRrWZ+KGh4Cd98FpP1ZgvMmebctoHzKAO2n1Xsry1FQBSGgIw4rQJRxET31VS/dR1LIKb5md/k0UzcXXc0g==",
"requires": {
+ "@babel/runtime": "^7.10.1",
"classnames": "^2.2.1",
- "prop-types": "^15.5.6",
- "react-lifecycles-compat": "^3.0.4"
+ "rc-util": "^5.0.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-table": {
- "version": "6.10.15",
- "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-6.10.15.tgz",
- "integrity": "sha512-LAr0M/gqt+irOjvPNBLApmQ0CUHNOfKsEBhu1uIuB3OlN1ynA9z+sdoTQyNd9+8NSl0MYnQOOfhtLChAY7nU0A==",
+ "version": "7.8.6",
+ "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.8.6.tgz",
+ "integrity": "sha512-rHRStVTO6FYlxs5Bk9S56Vo/Jn7pX3hOtHTHP+Vu++i9SF7DroOReMIi+OJ7RA9n3jVBxyT/9+NESXgTFvPbYA==",
"requires": {
+ "@babel/runtime": "^7.10.1",
"classnames": "^2.2.5",
- "component-classes": "^1.2.6",
- "lodash": "^4.17.5",
- "mini-store": "^2.0.0",
- "prop-types": "^15.5.8",
- "rc-util": "^4.13.0",
- "react-lifecycles-compat": "^3.0.2",
- "shallowequal": "^1.0.2"
+ "raf": "^3.4.1",
+ "rc-resize-observer": "^0.2.0",
+ "rc-util": "^5.0.0",
+ "shallowequal": "^1.1.0"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-tabs": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-9.7.0.tgz",
- "integrity": "sha512-kvmgp8/MfLzFZ06hWHignqomFQ5nF7BqKr5O1FfhE4VKsGrep52YSF/1MvS5oe0NPcI9XGNS2p751C5v6cYDpQ==",
+ "version": "11.5.6",
+ "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-11.5.6.tgz",
+ "integrity": "sha512-Q2wqnt66SFksGXxNARLqGNMYIFH3KSm48+hMc4tq6qhgpsW104dedHcM86NUyqsQcvYWWiceUNu3TSnbe+XZnw==",
"requires": {
- "@ant-design/create-react-context": "^0.2.4",
- "babel-runtime": "6.x",
+ "@babel/runtime": "^7.10.1",
"classnames": "2.x",
- "lodash": "^4.17.5",
- "prop-types": "15.x",
"raf": "^3.4.1",
- "rc-hammerjs": "~0.6.0",
- "rc-util": "^4.0.4",
- "react-lifecycles-compat": "^3.0.4",
- "resize-observer-polyfill": "^1.5.1",
- "warning": "^4.0.3"
+ "rc-dropdown": "^3.1.0",
+ "rc-menu": "^8.2.1",
+ "rc-resize-observer": "^0.2.1",
+ "rc-trigger": "^4.2.1",
+ "rc-util": "^5.0.0"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
- "rc-time-picker": {
- "version": "3.7.3",
- "resolved": "https://registry.npmjs.org/rc-time-picker/-/rc-time-picker-3.7.3.tgz",
- "integrity": "sha512-Lv1Mvzp9fRXhXEnRLO4nW6GLNxUkfAZ3RsiIBsWjGjXXvMNjdr4BX/ayElHAFK0DoJqOhm7c5tjmIYpEOwcUXg==",
+ "rc-textarea": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-0.3.0.tgz",
+ "integrity": "sha512-vrTPkPT6wrO7EI8ouLFZZLXA1pFVrVRCnkmyyf0yRComFbcH1ogmFEGu85CjVT96rQqAiQFOe0QV3nKopZOJow==",
"requires": {
- "classnames": "2.x",
- "moment": "2.x",
- "prop-types": "^15.5.8",
- "raf": "^3.4.1",
- "rc-trigger": "^2.2.0",
- "react-lifecycles-compat": "^3.0.4"
+ "@babel/runtime": "^7.10.1",
+ "classnames": "^2.2.1",
+ "omit.js": "^2.0.0",
+ "rc-resize-observer": "^0.2.3"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-tooltip": {
- "version": "3.7.3",
- "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.3.tgz",
- "integrity": "sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-4.2.1.tgz",
+ "integrity": "sha512-oykuaGsHg7RFvPUaxUpxo7ScEqtH61C66x4JUmjlFlSS8gSx2L8JFtfwM1D68SLBxUqGqJObtxj4TED75gQTiA==",
"requires": {
- "babel-runtime": "6.x",
- "prop-types": "^15.5.8",
- "rc-trigger": "^2.2.2"
+ "rc-trigger": "^4.2.1"
}
},
"rc-tree": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz",
- "integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==",
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-3.6.0.tgz",
+ "integrity": "sha512-2Hy/F+zWuqF5vFlSqpcVXh9Ik2Dl6/tQcRks5EnK8UwXUOgav4+LVORCtdqy4KX7J94vz7d4xfiyWBye/gO1Xg==",
"requires": {
- "@ant-design/create-react-context": "^0.2.4",
+ "@babel/runtime": "^7.10.1",
"classnames": "2.x",
- "prop-types": "^15.5.8",
- "rc-animate": "^2.6.0",
- "rc-util": "^4.5.1",
- "react-lifecycles-compat": "^3.0.4",
- "warning": "^4.0.3"
+ "rc-animate": "^3.1.0",
+ "rc-util": "^5.0.0",
+ "rc-virtual-list": "^1.1.0"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-tree-select": {
- "version": "2.9.4",
- "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-2.9.4.tgz",
- "integrity": "sha512-0HQkXAN4XbfBW20CZYh3G+V+VMrjX42XRtDCpyv6PDUm5vikC0Ob682ZBCVS97Ww2a5Hf6Ajmu0ahWEdIEpwhg==",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-4.0.3.tgz",
+ "integrity": "sha512-C2me2AgNYTSXtuybzde2QC82P5yJEZ5gb3SglEOizKvOJM8bJ0hAk8VLK55Xi+a0PO3QvcLLDnJGXEEEB8E/tA==",
"requires": {
- "classnames": "^2.2.1",
- "dom-scroll-into-view": "^1.2.1",
- "prop-types": "^15.5.8",
- "raf": "^3.4.0",
- "rc-animate": "^2.8.2",
- "rc-tree": "~2.1.0",
- "rc-trigger": "^3.0.0",
- "rc-util": "^4.5.0",
- "react-lifecycles-compat": "^3.0.4",
- "shallowequal": "^1.0.2",
- "warning": "^4.0.1"
+ "@babel/runtime": "^7.10.1",
+ "classnames": "2.x",
+ "rc-select": "^11.0.4",
+ "rc-tree": "^3.6.0",
+ "rc-util": "^5.0.1"
},
"dependencies": {
- "rc-trigger": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-3.0.0.tgz",
- "integrity": "sha512-hQxbbJpo23E2QnYczfq3Ec5J5tVl2mUDhkqxrEsQAqk16HfADQg+iKNWzEYXyERSncdxfnzYuaBgy764mNRzTA==",
- "requires": {
- "babel-runtime": "6.x",
- "classnames": "^2.2.6",
- "prop-types": "15.x",
- "raf": "^3.4.0",
- "rc-align": "^2.4.1",
- "rc-animate": "^3.0.0-rc.1",
- "rc-util": "^4.15.7"
- },
- "dependencies": {
- "rc-animate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.0.0.tgz",
- "integrity": "sha512-+ANeyCei4lWSJHWTcocywdYAy6lpRdBva/7Fs3nBBiAngW/W+Gmx+gQEcsmcgQBqziWUYnR91Bk12ltR3GBHPA==",
- "requires": {
- "@ant-design/css-animation": "^1.7.2",
- "classnames": "^2.2.6",
- "raf": "^3.4.0",
- "rc-util": "^4.15.3"
- }
- }
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
}
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
}
}
},
"rc-trigger": {
- "version": "2.6.5",
- "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-2.6.5.tgz",
- "integrity": "sha512-m6Cts9hLeZWsTvWnuMm7oElhf+03GOjOLfTuU0QmdB9ZrW7jR2IpI5rpNM7i9MvAAlMAmTx5Zr7g3uu/aMvZAw==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-4.3.0.tgz",
+ "integrity": "sha512-jnGNzosXmDdivMBjPCYe/AfOXTpJU2/xQ9XukgoXDQEoZq/9lcI1r7eUIfq70WlWpLxlUEqQktiV3hwyy6Nw9g==",
"requires": {
- "babel-runtime": "6.x",
+ "@babel/runtime": "^7.10.1",
"classnames": "^2.2.6",
- "prop-types": "15.x",
- "rc-align": "^2.4.0",
- "rc-animate": "2.x",
- "rc-util": "^4.4.0",
- "react-lifecycles-compat": "^3.0.4"
+ "raf": "^3.4.1",
+ "rc-align": "^4.0.0",
+ "rc-animate": "^3.0.0",
+ "rc-util": "^5.0.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
+ "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
+ }
}
},
"rc-upload": {
- "version": "2.9.4",
- "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-2.9.4.tgz",
- "integrity": "sha512-WXt0HGxXyzLrPV6iec/96Rbl/6dyrAW8pKuY6wwD7yFYwfU5bjgKjv7vC8KNMJ6wzitFrZjnoiogNL3dF9dj3Q==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-3.2.0.tgz",
+ "integrity": "sha512-/vyOGVxl5QVM3ZE7s+GqYPbCLC/Q/vJq0sjdwnvJw01KvAR5kVOC4jbHEaU56dMss7PFGDfNzc8zO5bWYLDzVQ==",
"requires": {
- "babel-runtime": "6.x",
- "classnames": "^2.2.5",
- "prop-types": "^15.5.7",
- "warning": "4.x"
+ "classnames": "^2.2.5"
}
},
"rc-util": {
- "version": "4.20.7",
- "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.20.7.tgz",
- "integrity": "sha512-wzL7bGTimuUK/SgXlUIxcXYdQ27eAaBd8PTuiKz7ZI/Mbm5R6ZcRTWpeIGG56t+/79oi++kobfKbJrPxMTkKIw==",
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.6.tgz",
+ "integrity": "sha512-uLGxF9WjbpJSjd6iDnIjl8ZeMUglpcuh1DwO26aaXh++yAmlB6eIAJMUwwJCuqJvo4quCvsDPg1VkqHILc4U0A==",
"requires": {
- "add-dom-event-listener": "^1.1.0",
- "prop-types": "^15.5.10",
"react-is": "^16.12.0",
- "react-lifecycles-compat": "^3.0.4",
"shallowequal": "^1.1.0"
},
"dependencies": {
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ "integrity": "sha1-eJcppNw23imZ3BVt1sHZwYzqVqQ="
}
}
},
+ "rc-virtual-list": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-1.1.6.tgz",
+ "integrity": "sha512-u3+izqWL8p8bQy8nYH48qWpiGyxR/ye8D2k0zJlXmfYeL55/xh83YrzHqiDzO78uj0Ewag3nXDA0JTVrYO7ygQ==",
+ "requires": {
+ "classnames": "^2.2.6",
+ "raf": "^3.4.1",
+ "rc-util": "^5.0.0"
+ }
+ },
"react": {
- "version": "16.8.3",
- "resolved": "https://registry.npmjs.org/react/-/react-16.8.3.tgz",
- "integrity": "sha512-3UoSIsEq8yTJuSu0luO1QQWYbgGEILm+eJl2QN/VLDi7hL+EN18M3q3oVZwmVzzBJ3DkM7RMdRwBmZZ+b4IzSA==",
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz",
+ "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
- "prop-types": "^15.6.2",
- "scheduler": "^0.13.3"
+ "prop-types": "^15.6.2"
}
},
"react-ace": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/react-ace/-/react-ace-6.4.0.tgz",
- "integrity": "sha512-woTTgGk9x4GRRWiM4QLNOspjaJAYLX3UZ3J2XRYQvJiN6wyxrFY9x7rdOKc+4Tj+khb/ccPiDj/kll4UeJEDPw==",
+ "version": "9.1.1",
+ "resolved": "https://registry.npmjs.org/react-ace/-/react-ace-9.1.1.tgz",
+ "integrity": "sha512-dL0w6GwtnS1opsOoWhJaF7rF7xCM+NOEOfePmDfiaeU+EyZQ6nRWDBgyzKsuiB3hyXH3G9D6FX37ur/LKUdKjA==",
"requires": {
- "brace": "^0.11.1",
+ "ace-builds": "^1.4.6",
"diff-match-patch": "^1.0.4",
"lodash.get": "^4.4.2",
"lodash.isequal": "^4.5.0",
- "prop-types": "^15.6.2"
+ "prop-types": "^15.7.2"
}
},
"react-dom": {
- "version": "16.8.3",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.3.tgz",
- "integrity": "sha512-ttMem9yJL4/lpItZAQ2NTFAbV7frotHk5DZEHXUOws2rMmrsvh1Na7ThGT0dTzUIl6pqTOi5tYREfL8AEna3lA==",
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz",
+ "integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
- "scheduler": "^0.13.3"
+ "scheduler": "^0.19.1"
+ },
+ "dependencies": {
+ "scheduler": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
+ "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1"
+ }
+ }
}
},
"react-draggable": {
@@ -13749,17 +16181,6 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.3.tgz",
"integrity": "sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA=="
},
- "react-lazy-load": {
- "version": "3.0.13",
- "resolved": "https://registry.npmjs.org/react-lazy-load/-/react-lazy-load-3.0.13.tgz",
- "integrity": "sha1-OwqS0zbUPT8Nc8vm81sXBQsIuCQ=",
- "requires": {
- "eventlistener": "0.0.1",
- "lodash.debounce": "^4.0.0",
- "lodash.throttle": "^4.0.0",
- "prop-types": "^15.5.8"
- }
- },
"react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
@@ -13797,18 +16218,6 @@
"react-draggable": "^4.0.3"
}
},
- "react-slick": {
- "version": "0.25.2",
- "resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.25.2.tgz",
- "integrity": "sha512-8MNH/NFX/R7zF6W/w+FS5VXNyDusF+XDW1OU0SzODEU7wqYB+ZTGAiNJ++zVNAVqCAHdyCybScaUB+FCZOmBBw==",
- "requires": {
- "classnames": "^2.2.5",
- "enquire.js": "^2.1.6",
- "json2mq": "^0.2.0",
- "lodash.debounce": "^4.0.8",
- "resize-observer-polyfill": "^1.5.0"
- }
- },
"react-sortable-hoc": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-1.11.0.tgz",
@@ -14003,9 +16412,9 @@
"integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg=="
},
"regenerate-unicode-properties": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz",
- "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==",
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz",
+ "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==",
"dev": true,
"requires": {
"regenerate": "^1.4.0"
@@ -14017,12 +16426,29 @@
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
},
"regenerator-transform": {
- "version": "0.13.4",
- "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.4.tgz",
- "integrity": "sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==",
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz",
+ "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==",
"dev": true,
"requires": {
- "private": "^0.1.6"
+ "@babel/runtime": "^7.8.4"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.4.tgz",
+ "integrity": "sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw==",
+ "dev": true,
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.5",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
+ "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
+ "dev": true
+ }
}
},
"regex-not": {
@@ -14061,12 +16487,6 @@
"resolved": "https://registry.npmjs.org/regex-regex/-/regex-regex-1.0.0.tgz",
"integrity": "sha1-kEih6uuHD01IDavHb8Qs3MC8OnI="
},
- "regexp-tree": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.5.tgz",
- "integrity": "sha512-nUmxvfJyAODw+0B13hj8CFVAxhe7fDEAgJgaotBu3nnR+IgGgZq59YedJP5VYTlkEfqjuK6TuRpnymKdatLZfQ==",
- "dev": true
- },
"regexp.prototype.flags": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz",
@@ -14161,29 +16581,29 @@
"dev": true
},
"regexpu-core": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz",
- "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==",
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz",
+ "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==",
"dev": true,
"requires": {
"regenerate": "^1.4.0",
- "regenerate-unicode-properties": "^7.0.0",
- "regjsgen": "^0.5.0",
- "regjsparser": "^0.6.0",
+ "regenerate-unicode-properties": "^8.2.0",
+ "regjsgen": "^0.5.1",
+ "regjsparser": "^0.6.4",
"unicode-match-property-ecmascript": "^1.0.4",
- "unicode-match-property-value-ecmascript": "^1.0.2"
+ "unicode-match-property-value-ecmascript": "^1.2.0"
}
},
"regjsgen": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz",
- "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==",
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz",
+ "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==",
"dev": true
},
"regjsparser": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz",
- "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==",
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz",
+ "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==",
"dev": true,
"requires": {
"jsesc": "~0.5.0"
@@ -14358,6 +16778,26 @@
}
}
},
+ "request-cookies": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/request-cookies/-/request-cookies-1.1.0.tgz",
+ "integrity": "sha1-dYHT2bKsXcQ25kWbIWpi48fmjPE=",
+ "dev": true,
+ "requires": {
+ "tough-cookie": "0.12.x"
+ },
+ "dependencies": {
+ "tough-cookie": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz",
+ "integrity": "sha1-giDH4hq9WxPZaAQlS9WoHr8sfWI=",
+ "dev": true,
+ "requires": {
+ "punycode": ">=0.2.0"
+ }
+ }
+ }
+ },
"request-promise-core": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz",
@@ -14399,7 +16839,7 @@
"resize-observer-polyfill": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
- "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+ "integrity": "sha1-DpAg3T0hAkRY1OvSfiPkAmmBBGQ="
},
"resolve": {
"version": "1.10.0",
@@ -14507,15 +16947,6 @@
"inherits": "^2.0.1"
}
},
- "rmc-feedback": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/rmc-feedback/-/rmc-feedback-2.0.0.tgz",
- "integrity": "sha512-5PWOGOW7VXks/l3JzlOU9NIxRpuaSS8d9zA3UULUCuTKnpwBHNvv1jSJzxgbbCQeYzROWUpgKI4za3X4C/mKmQ==",
- "requires": {
- "babel-runtime": "6.x",
- "classnames": "^2.2.5"
- }
- },
"robust-compress": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/robust-compress/-/robust-compress-1.0.0.tgz",
@@ -14672,7 +17103,8 @@
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
},
"sane": {
"version": "3.1.0",
@@ -14707,6 +17139,7 @@
"version": "0.13.3",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.3.tgz",
"integrity": "sha512-UxN5QRYWtpR1egNWzJcVLk8jlegxAugswQc984lD3kU7NuobsO37/sRfbpTdBjtnD5TBNFA2Q2oLV5+UmPSmEQ==",
+ "dev": true,
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
@@ -14723,6 +17156,14 @@
"ajv-keywords": "^3.1.0"
}
},
+ "scroll-into-view-if-needed": {
+ "version": "2.2.25",
+ "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.25.tgz",
+ "integrity": "sha512-C8RKJPq9lK7eubwGpLbUkw3lklcG3Ndjmea2PyauzrA0i4DPlzAmVMGxaZrBFqCrVLfvJmP80IyHnv4jxvg1OQ==",
+ "requires": {
+ "compute-scroll-into-view": "^1.0.14"
+ }
+ },
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -14859,7 +17300,8 @@
"setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
- "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
+ "dev": true
},
"setprototypeof": {
"version": "1.1.0",
@@ -14882,15 +17324,10 @@
"resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz",
"integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA="
},
- "shallow-equal": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
- "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
- },
"shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
- "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
+ "integrity": "sha1-GI1SHelbkIdAT9TctosT3wrk5/g="
},
"sharkdown": {
"version": "0.1.1",
@@ -16970,10 +19407,11 @@
"dup": "^1.0.0"
}
},
- "ua-parser-js": {
- "version": "0.7.21",
- "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz",
- "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ=="
+ "typescript": {
+ "version": "3.9.6",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz",
+ "integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==",
+ "dev": true
},
"uglify-js": {
"version": "2.8.29",
@@ -17013,9 +19451,9 @@
}
},
"unicode-match-property-value-ecmascript": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz",
- "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz",
+ "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==",
"dev": true
},
"unicode-property-aliases-ecmascript": {
@@ -17508,7 +19946,7 @@
"warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
- "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
+ "integrity": "sha1-Fungd+uKhtavfWSqHgX9hbRnjKM=",
"requires": {
"loose-envify": "^1.0.0"
}
@@ -18114,11 +20552,6 @@
"iconv-lite": "0.4.24"
}
},
- "whatwg-fetch": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
- "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
- },
"whatwg-mimetype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
diff --git a/package.json b/package.json
index 9952a28789..bea953f4c1 100644
--- a/package.json
+++ b/package.json
@@ -16,14 +16,17 @@
"webpack-dev-server": "webpack-dev-server",
"analyze": "npm run clean && BUNDLE_ANALYZER=on webpack",
"analyze:build": "npm run clean && NODE_ENV=production BUNDLE_ANALYZER=on webpack",
- "lint": "npm run lint:base -- --ext .js --ext .jsx ./client",
- "lint:fix": "npm run lint:base -- --fix --ext .js --ext .jsx ./client",
+ "lint": "npm run lint:base -- --ext .js --ext .jsx --ext .ts --ext .tsx ./client",
+ "lint:fix": "npm run lint:base -- --fix --ext .js --ext .jsx --ext .ts --ext .tsx ./client",
"lint:base": "eslint --config ./client/.eslintrc.js --ignore-path ./client/.eslintignore",
"lint:ci": "npm run lint -- --max-warnings 0 --format junit --output-file /tmp/test-results/eslint/results.xml",
- "prettier": "prettier --write 'client/app/**/*.{js,jsx}' 'client/cypress/**/*.js'",
- "test": "TZ=Africa/Khartoum jest",
+ "prettier": "prettier --write 'client/app/**/*.{js,jsx,ts,tsx}' 'client/cypress/**/*.{js,jsx,ts,tsx}'",
+ "type-check": "tsc --noEmit --project client/tsconfig.json",
+ "type-check:watch": "npm run type-check -- --watch",
+ "jest": "TZ=Africa/Khartoum jest",
+ "test": "run-s type-check jest",
"test:watch": "jest --watch",
- "cypress:install": "npm install --no-save cypress@~4.5.0 @percy/agent@0.26.2 @percy/cypress@^2.2.0 atob@2.1.2",
+ "cypress:install": "npm install --no-save cypress@~4.12.1 @percy/agent@0.26.2 @percy/cypress@^2.2.0 atob@2.1.2 lodash@^4.17.10 request-cookies@^1.1.0",
"cypress": "node client/cypress/cypress.js",
"postinstall": "(cd viz-lib && npm ci && npm run build:babel)"
},
@@ -42,14 +45,12 @@
},
"homepage": "https://redash.io/",
"dependencies": {
+ "@ant-design/icons": "^4.2.1",
"@redash/viz": "file:viz-lib",
- "@types/prop-types": "^15.5.2",
- "@types/react": "^16.3.13",
- "@types/react-dom": "^16.0.5",
- "antd": "^3.26.17",
+ "ace-builds": "^1.4.12",
+ "antd": "^4.4.3",
"axios": "^0.19.0",
"bootstrap": "^3.3.7",
- "brace": "^0.11.0",
"classnames": "^2.2.6",
"d3": "^3.5.17",
"debug": "^3.1.0",
@@ -57,6 +58,7 @@
"font-awesome": "^4.7.0",
"history": "^4.10.1",
"hoist-non-react-statics": "^3.3.0",
+ "js-cookie": "^2.2.1",
"lodash": "^4.17.10",
"markdown": "0.5.0",
"material-design-iconic-font": "^2.2.0",
@@ -67,9 +69,9 @@
"path-to-regexp": "^3.1.0",
"prop-types": "^15.6.1",
"query-string": "^6.9.0",
- "react": "^16.8.3",
- "react-ace": "^6.1.0",
- "react-dom": "^16.8.3",
+ "react": "^16.13.1",
+ "react-ace": "^9.1.1",
+ "react-dom": "^16.13.1",
"react-grid-layout": "^0.18.2",
"react-resizable": "^1.10.1",
"react-virtualized": "^9.21.2",
@@ -78,11 +80,19 @@
"use-media": "^1.4.0"
},
"devDependencies": {
- "@babel/core": "^7.2.2",
- "@babel/plugin-proposal-class-properties": "^7.3.0",
+ "@babel/cli": "^7.10.4",
+ "@babel/core": "^7.10.4",
+ "@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/plugin-transform-object-assign": "^7.2.0",
- "@babel/preset-env": "^7.3.1",
+ "@babel/preset-env": "^7.10.4",
"@babel/preset-react": "^7.0.0",
+ "@babel/preset-typescript": "^7.10.4",
+ "@types/classnames": "^2.2.10",
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/lodash": "^4.14.157",
+ "@types/prop-types": "^15.7.3",
+ "@types/react": "^16.9.41",
+ "@types/react-dom": "^16.9.8",
"@typescript-eslint/eslint-plugin": "^2.10.0",
"@typescript-eslint/parser": "^2.10.0",
"babel-eslint": "^10.0.3",
@@ -122,6 +132,8 @@
"raw-loader": "^0.5.1",
"react-test-renderer": "^16.5.2",
"request": "^2.88.0",
+ "request-cookies": "^1.1.0",
+ "typescript": "^3.9.6",
"url-loader": "^1.1.2",
"webpack": "^4.20.2",
"webpack-build-notifier": "^0.1.30",
diff --git a/redash/__init__.py b/redash/__init__.py
index 43506ca103..9620d48366 100644
--- a/redash/__init__.py
+++ b/redash/__init__.py
@@ -47,7 +47,7 @@ def setup_logging():
redis_connection = redis.from_url(settings.REDIS_URL)
rq_redis_connection = redis.from_url(settings.RQ_REDIS_URL)
mail = Mail()
-migrate = Migrate()
+migrate = Migrate(compare_type=True)
statsd_client = StatsClient(
host=settings.STATSD_HOST, port=settings.STATSD_PORT, prefix=settings.STATSD_PREFIX
)
diff --git a/redash/app.py b/redash/app.py
index 554dca309f..67eee53bbe 100644
--- a/redash/app.py
+++ b/redash/app.py
@@ -10,7 +10,7 @@ class Redash(Flask):
def __init__(self, *args, **kwargs):
kwargs.update(
{
- "template_folder": settings.STATIC_ASSETS_PATH,
+ "template_folder": settings.FLASK_TEMPLATE_PATH,
"static_folder": settings.STATIC_ASSETS_PATH,
"static_url_path": "/static",
}
diff --git a/redash/authentication/__init__.py b/redash/authentication/__init__.py
index 7aeea8f332..95f61d2d45 100644
--- a/redash/authentication/__init__.py
+++ b/redash/authentication/__init__.py
@@ -251,10 +251,11 @@ def init_app(app):
login_manager.init_app(app)
login_manager.anonymous_user = models.AnonymousUser
- app.register_blueprint(google_oauth.blueprint)
- app.register_blueprint(saml_auth.blueprint)
- app.register_blueprint(remote_user_auth.blueprint)
- app.register_blueprint(ldap_auth.blueprint)
+ from redash.security import csrf
+ for auth in [google_oauth, saml_auth, remote_user_auth, ldap_auth]:
+ blueprint = auth.blueprint
+ csrf.exempt(blueprint)
+ app.register_blueprint(blueprint)
user_logged_in.connect(log_user_logged_in)
login_manager.request_loader(request_loader)
diff --git a/redash/cli/data_sources.py b/redash/cli/data_sources.py
index 4a94bfd12d..fe15075395 100644
--- a/redash/cli/data_sources.py
+++ b/redash/cli/data_sources.py
@@ -4,7 +4,7 @@
from flask.cli import AppGroup
from sqlalchemy.orm.exc import NoResultFound
-from redash import models
+from redash import models, tasks
from redash.query_runner import (
get_configuration_schema_for_query_runner_type,
query_runners,
@@ -202,6 +202,38 @@ def update_attr(obj, attr, new_value):
setattr(obj, attr, new_value)
+@manager.command()
+@click.argument("name")
+@click.option(
+ "--org",
+ "organization",
+ default="default",
+ help="The organization the user belongs to (leave blank for " "'default').",
+)
+@click.option(
+ "--count",
+ "num_tables",
+ default=50,
+ help="number of tables to process data samples for",
+)
+def refresh_samples(name, num_tables=50, organization="default"):
+ """Refresh table samples by data source name."""
+ try:
+ org = models.Organization.get_by_slug(organization)
+ data_source = models.DataSource.query.filter(
+ models.DataSource.name == name, models.DataSource.org == org
+ ).one()
+ print(
+ "Refreshing samples for data source: {} (id={})".format(
+ name, data_source.id
+ )
+ )
+ tasks.refresh_samples(data_source.id, num_tables)
+ except NoResultFound:
+ print("Couldn't find data source named: {}".format(name))
+ exit(1)
+
+
@manager.command()
@click.argument("name")
@click.option("--name", "new_name", default=None, help="new name for the data source")
diff --git a/redash/cli/database.py b/redash/cli/database.py
index ce55b73c6f..777a04637b 100644
--- a/redash/cli/database.py
+++ b/redash/cli/database.py
@@ -8,6 +8,7 @@
from sqlalchemy.sql import select
from sqlalchemy_utils.types.encrypted.encrypted_type import FernetEngine
+from redash import settings
from redash.models.base import Column
from redash.models.types import EncryptedConfiguration
from redash.utils.configuration import ConfigurationContainer
@@ -26,6 +27,19 @@ def _wait_for_db_connection(db):
retried = True
+
+def is_db_empty():
+ from redash.models import db
+
+ table_names = sqlalchemy.inspect(db.get_engine()).get_table_names()
+ return len(table_names) == 0
+
+
+def load_extensions(db):
+ with db.engine.connect() as connection:
+ for extension in settings.dynamic_settings.database_extensions:
+ connection.execute(f'CREATE EXTENSION IF NOT EXISTS "{extension}";')
+
@manager.command()
def create_tables():
@@ -33,12 +47,18 @@ def create_tables():
from redash.models import db
_wait_for_db_connection(db)
- # To create triggers for searchable models, we need to call configure_mappers().
- sqlalchemy.orm.configure_mappers()
- db.create_all()
- # Need to mark current DB as up to date
- stamp()
+ # We need to make sure we run this only if the DB is empty, because otherwise calling
+ # stamp() will stamp it with the latest migration value and migrations won't run.
+ if is_db_empty():
+ load_extensions(db)
+
+ # To create triggers for searchable models, we need to call configure_mappers().
+ sqlalchemy.orm.configure_mappers()
+ db.create_all()
+
+ # Need to mark current DB as up to date
+ stamp()
@manager.command()
diff --git a/redash/handlers/alerts.py b/redash/handlers/alerts.py
index 7929df9c05..6efa7d4652 100644
--- a/redash/handlers/alerts.py
+++ b/redash/handlers/alerts.py
@@ -146,7 +146,6 @@ def post(self, alert_id):
return d
def get(self, alert_id):
- alert_id = int(alert_id)
alert = models.Alert.get_by_id_and_org(alert_id, self.current_org)
require_access(alert, self.current_user, view_only)
diff --git a/redash/handlers/api.py b/redash/handlers/api.py
index 8f7cc1a369..327ff87bea 100644
--- a/redash/handlers/api.py
+++ b/redash/handlers/api.py
@@ -25,10 +25,12 @@
DataSourceSchemaResource,
DataSourceTestResource,
DataSourceTypeListResource,
+ DataSourceToggleStringResource,
)
from redash.handlers.databricks import (
DatabricksDatabaseListResource,
DatabricksSchemaResource,
+ DatabricksTableColumnListResource,
)
from redash.handlers.destinations import (
DestinationListResource,
@@ -127,7 +129,7 @@ def json_representation(data, code, headers=None):
api.add_org_resource(DashboardListResource, "/api/dashboards", endpoint="dashboards")
api.add_org_resource(
- DashboardResource, "/api/dashboards/", endpoint="dashboard"
+ DashboardResource, "/api/dashboards/", endpoint="dashboard"
)
api.add_org_resource(
PublicDashboardResource,
@@ -156,6 +158,10 @@ def json_representation(data, code, headers=None):
DatabricksSchemaResource,
"/api/databricks/databases///tables",
)
+api.add_org_resource(
+ DatabricksTableColumnListResource,
+ "/api/databricks/databases///columns/",
+)
api.add_org_resource(
DataSourcePauseResource, "/api/data_sources//pause"
)
@@ -163,6 +169,10 @@ def json_representation(data, code, headers=None):
api.add_org_resource(
DataSourceResource, "/api/data_sources/", endpoint="data_source"
)
+api.add_resource(
+ DataSourceToggleStringResource, "/api/data_sources//toggle_string"
+)
+
api.add_org_resource(GroupListResource, "/api/groups", endpoint="groups")
api.add_org_resource(GroupResource, "/api/groups/", endpoint="group")
diff --git a/redash/handlers/dashboards.py b/redash/handlers/dashboards.py
index 1575fe2e28..df7a06a497 100644
--- a/redash/handlers/dashboards.py
+++ b/redash/handlers/dashboards.py
@@ -21,6 +21,7 @@
DashboardSerializer,
public_dashboard,
)
+from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm.exc import StaleDataError
@@ -115,11 +116,11 @@ def post(self):
class DashboardResource(BaseResource):
@require_permission("list_dashboards")
- def get(self, dashboard_slug=None):
+ def get(self, dashboard_id=None):
"""
Retrieves a dashboard.
- :qparam string slug: Slug of dashboard to retrieve.
+ :qparam number id: Id of dashboard to retrieve.
.. _dashboard-response-label:
@@ -149,9 +150,12 @@ def get(self, dashboard_slug=None):
:>json string widget.created_at: ISO format timestamp for widget creation
:>json string widget.updated_at: ISO format timestamp for last widget modification
"""
- dashboard = get_object_or_404(
- models.Dashboard.get_by_slug_and_org, dashboard_slug, self.current_org
- )
+ if request.args.get("legacy") is not None:
+ fn = models.Dashboard.get_by_slug_and_org
+ else:
+ fn = models.Dashboard.get_by_id_and_org
+
+ dashboard = get_object_or_404(fn, dashboard_id, self.current_org)
response = DashboardSerializer(
dashboard, with_widgets=True, user=self.current_user
).serialize()
@@ -175,11 +179,11 @@ def get(self, dashboard_slug=None):
return response
@require_permission("edit_dashboard")
- def post(self, dashboard_slug):
+ def post(self, dashboard_id):
"""
Modifies a dashboard.
- :qparam string slug: Slug of dashboard to retrieve.
+ :qparam number id: Id of dashboard to retrieve.
Responds with the updated :ref:`dashboard `.
@@ -188,7 +192,7 @@ def post(self, dashboard_slug):
"""
dashboard_properties = request.get_json(force=True)
# TODO: either convert all requests to use slugs or ids
- dashboard = models.Dashboard.get_by_id_and_org(dashboard_slug, self.current_org)
+ dashboard = models.Dashboard.get_by_id_and_org(dashboard_id, self.current_org)
require_object_modify_permission(dashboard, self.current_user)
@@ -218,7 +222,11 @@ def post(self, dashboard_slug):
try:
models.db.session.commit()
except StaleDataError:
+ models.db.session.rollback()
abort(409)
+ except IntegrityError:
+ models.db.session.rollback()
+ abort(400)
result = DashboardSerializer(
dashboard, with_widgets=True, user=self.current_user
@@ -231,17 +239,15 @@ def post(self, dashboard_slug):
return result
@require_permission("edit_dashboard")
- def delete(self, dashboard_slug):
+ def delete(self, dashboard_id):
"""
Archives a dashboard.
- :qparam string slug: Slug of dashboard to retrieve.
+ :qparam number id: Id of dashboard to retrieve.
Responds with the archived :ref:`dashboard `.
"""
- dashboard = models.Dashboard.get_by_slug_and_org(
- dashboard_slug, self.current_org
- )
+ dashboard = models.Dashboard.get_by_id_and_org(dashboard_id, self.current_org)
dashboard.is_archived = True
dashboard.record_changes(changed_by=self.current_user)
models.db.session.add(dashboard)
diff --git a/redash/handlers/data_sources.py b/redash/handlers/data_sources.py
index e874edcc4a..a18b1b2244 100644
--- a/redash/handlers/data_sources.py
+++ b/redash/handlers/data_sources.py
@@ -19,10 +19,10 @@
query_runners,
NotSupported,
)
+from redash.tasks.queries import refresh_schema
from redash.utils import filter_none
from redash.utils.configuration import ConfigurationContainer, ValidationError
-from redash.tasks.general import test_connection, get_schema
-from redash.serializers import serialize_job
+from redash.tasks.general import test_connection
class DataSourceTypeListResource(BaseResource):
@@ -72,11 +72,16 @@ def post(self, data_source_id):
data_source.type = req["type"]
data_source.name = req["name"]
+ data_source.description = req["description"] if "description" in req else ""
models.db.session.add(data_source)
+ # Refresh the stored schemas when a data source is updated
+ refresh_schema.delay(data_source.id)
+
try:
models.db.session.commit()
except IntegrityError as e:
+ models.db.session.rollback()
if req["name"] in str(e):
abort(
400,
@@ -127,7 +132,7 @@ def get(self):
continue
try:
- d = ds.to_dict()
+ d = ds.to_dict(all=True)
d["view_only"] = all(
project(ds.groups, self.current_user.group_ids).values()
)
@@ -162,11 +167,20 @@ def post(self):
try:
datasource = models.DataSource.create_with_group(
- org=self.current_org, name=req["name"], type=req["type"], options=config
+ org=self.current_org,
+ name=req["name"],
+ type=req["type"],
+ description=req["description"] if "description" in req else "",
+ options=config,
)
models.db.session.commit()
+
+ # Refresh the stored schemas when a new data source is added to the list
+ refresh_schema.delay(datasource.id)
+
except IntegrityError as e:
+ models.db.session.rollback()
if req["name"] in str(e):
abort(
400,
@@ -189,6 +203,16 @@ def post(self):
class DataSourceSchemaResource(BaseResource):
+ @require_admin
+ def post(self, data_source_id):
+ data_source = get_object_or_404(
+ models.DataSource.get_by_id_and_org, data_source_id, self.current_org
+ )
+ new_schema_data = request.get_json(force=True)
+ models.DataSource.save_schema(new_schema_data)
+ # Force update the schema cache to have all changes available right away
+ data_source.schema_cache.populate(forced=True)
+
def get(self, data_source_id):
data_source = get_object_or_404(
models.DataSource.get_by_id_and_org, data_source_id, self.current_org
@@ -196,15 +220,19 @@ def get(self, data_source_id):
require_access(data_source, self.current_user, view_only)
refresh = request.args.get("refresh") is not None
- if not refresh:
- cached_schema = data_source.get_cached_schema()
-
- if cached_schema is not None:
- return {"schema": cached_schema}
+ response = {}
- job = get_schema.delay(data_source.id, refresh)
+ try:
+ response["schema"] = data_source.get_schema(refresh)
+ except NotSupported:
+ response["error"] = {
+ "code": 1,
+ "message": "Data source type does not support retrieving schema",
+ }
+ except Exception:
+ response["error"] = {"code": 2, "message": "Error retrieving schema."}
- return serialize_job(job)
+ return response
class DataSourcePauseResource(BaseResource):
@@ -275,3 +303,15 @@ def post(self, data_source_id):
}
)
return response
+
+
+class DataSourceToggleStringResource(BaseResource):
+ def get(self, data_source_id):
+ data_source = get_object_or_404(
+ models.DataSource.get_by_id_and_org, data_source_id, self.current_org
+ )
+ require_access(data_source.groups, self.current_user, view_only)
+ try:
+ return {"toggle_string": data_source.options.get("toggle_table_string", "")}
+ except Exception:
+ abort(400)
diff --git a/redash/handlers/databricks.py b/redash/handlers/databricks.py
index e5743115c2..0c36bc74be 100644
--- a/redash/handlers/databricks.py
+++ b/redash/handlers/databricks.py
@@ -1,41 +1,97 @@
from flask_restful import abort
-from redash import models
+from flask import request
+from redash import models, redis_connection
from redash.handlers.base import BaseResource, get_object_or_404
from redash.permissions import (
require_access,
view_only,
)
-from redash.tasks.databricks import get_databricks_databases, get_databricks_schema
+from redash.tasks.databricks import (
+ get_databricks_databases,
+ get_databricks_tables,
+ get_database_tables_with_columns,
+ get_databricks_table_columns,
+)
from redash.serializers import serialize_job
+from redash.utils import json_loads, json_dumps
+
+
+def _get_databricks_data_source(data_source_id, user, org):
+ data_source = get_object_or_404(
+ models.DataSource.get_by_id_and_org, data_source_id, org
+ )
+ require_access(data_source, user, view_only)
+
+ if not data_source.type == "databricks":
+ abort(400, message="Resource only available for the Databricks query runner.")
+
+ return data_source
+
+
+def _databases_key(data_source_id):
+ return "databricks:databases:{}".format(data_source_id)
+
+
+def _tables_key(data_source_id, database_name):
+ return "databricks:database_tables:{}:{}".format(data_source_id, database_name)
+
+
+def _get_databases_from_cache(data_source_id):
+ cache = redis_connection.get(_databases_key(data_source_id))
+ return json_loads(cache) if cache else None
+
+
+def _get_tables_from_cache(data_source_id, database_name):
+ cache = redis_connection.get(_tables_key(data_source_id, database_name))
+ return json_loads(cache) if cache else None
class DatabricksDatabaseListResource(BaseResource):
def get(self, data_source_id):
- data_source = get_object_or_404(
- models.DataSource.get_by_id_and_org, data_source_id, self.current_org
+ data_source = _get_databricks_data_source(
+ data_source_id, user=self.current_user, org=self.current_org
)
- require_access(data_source, self.current_user, view_only)
- if not data_source.type == "databricks":
- abort(
- 400, message="Resource only available for the Databricks query runner."
- )
+ refresh = request.args.get("refresh") is not None
+ if not refresh:
+ cached_databases = _get_databases_from_cache(data_source_id)
+
+ if cached_databases is not None:
+ return cached_databases
- job = get_databricks_databases.delay(data_source.id)
+ job = get_databricks_databases.delay(
+ data_source.id, redis_key=_databases_key(data_source_id)
+ )
return serialize_job(job)
class DatabricksSchemaResource(BaseResource):
def get(self, data_source_id, database_name):
- data_source = get_object_or_404(
- models.DataSource.get_by_id_and_org, data_source_id, self.current_org
+ data_source = _get_databricks_data_source(
+ data_source_id, user=self.current_user, org=self.current_org
)
- require_access(data_source, self.current_user, view_only)
- if not data_source.type == "databricks":
- abort(
- 400, message="Resource only available for the Databricks query runner."
- )
+ refresh = request.args.get("refresh") is not None
+ if not refresh:
+ cached_tables = _get_tables_from_cache(data_source_id, database_name)
+
+ if cached_tables is not None:
+ return {"schema": cached_tables, "has_columns": True}
+
+ job = get_databricks_tables.delay(data_source.id, database_name)
+ return serialize_job(job)
+
+ job = get_database_tables_with_columns.delay(
+ data_source.id, database_name, redis_key=_tables_key(data_source_id, database_name)
+ )
+ return serialize_job(job)
+
+
+class DatabricksTableColumnListResource(BaseResource):
+ def get(self, data_source_id, database_name, table_name):
+ data_source = _get_databricks_data_source(
+ data_source_id, user=self.current_user, org=self.current_org
+ )
- job = get_databricks_schema.delay(data_source.id, database_name)
+ job = get_databricks_table_columns.delay(data_source.id, database_name, table_name)
return serialize_job(job)
diff --git a/redash/handlers/favorites.py b/redash/handlers/favorites.py
index 71ac3a20b8..71a0ac3db1 100644
--- a/redash/handlers/favorites.py
+++ b/redash/handlers/favorites.py
@@ -51,7 +51,7 @@ def delete(self, query_id):
class DashboardFavoriteResource(BaseResource):
def post(self, object_id):
dashboard = get_object_or_404(
- models.Dashboard.get_by_slug_and_org, object_id, self.current_org
+ models.Dashboard.get_by_id_and_org, object_id, self.current_org
)
fav = models.Favorite(
org_id=self.current_org.id, object=dashboard, user=self.current_user
@@ -76,7 +76,7 @@ def post(self, object_id):
def delete(self, object_id):
dashboard = get_object_or_404(
- models.Dashboard.get_by_slug_and_org, object_id, self.current_org
+ models.Dashboard.get_by_id_and_org, object_id, self.current_org
)
models.Favorite.query.filter(
models.Favorite.object == dashboard,
diff --git a/redash/handlers/users.py b/redash/handlers/users.py
index bc2e98c534..446a8c5f66 100644
--- a/redash/handlers/users.py
+++ b/redash/handlers/users.py
@@ -157,6 +157,7 @@ def post(self):
models.db.session.add(user)
models.db.session.commit()
except IntegrityError as e:
+ models.db.session.rollback()
if "email" in str(e):
abort(400, message="Email already taken.")
abort(500)
@@ -287,7 +288,7 @@ def post(self, user_id):
message = "Email already taken."
else:
message = "Error updating record"
-
+ models.db.session.rollback()
abort(400, message=message)
self.record_event(
diff --git a/redash/models/__init__.py b/redash/models/__init__.py
index 1bd2fab77f..ed71244b0b 100644
--- a/redash/models/__init__.py
+++ b/redash/models/__init__.py
@@ -5,11 +5,17 @@
import numbers
import pytz
-from sqlalchemy import distinct, or_, and_, UniqueConstraint
+from sqlalchemy import distinct, or_, and_, UniqueConstraint, cast
from sqlalchemy.dialects import postgresql
from sqlalchemy.event import listens_for
from sqlalchemy.ext.hybrid import hybrid_property
-from sqlalchemy.orm import backref, contains_eager, joinedload, subqueryload, load_only
+from sqlalchemy.orm import (
+ backref,
+ contains_eager,
+ joinedload,
+ load_only,
+ relationship,
+)
from sqlalchemy.orm.exc import NoResultFound # noqa: F401
from sqlalchemy import func
from sqlalchemy_utils import generic_relationship
@@ -27,13 +33,9 @@
with_ssh_tunnel,
get_configuration_schema_for_query_runner_type,
get_query_runner,
- TYPE_BOOLEAN,
- TYPE_DATE,
- TYPE_DATETIME,
)
from redash.utils import (
generate_token,
- json_dumps,
json_loads,
mustache_render,
base_url,
@@ -82,6 +84,219 @@ def get(self, query_id):
scheduled_queries_executions = ScheduledQueriesExecutions()
+def cleanup_data_in_table(table_model):
+ ttl_days_ago = utils.utcnow() - datetime.timedelta(
+ days=settings.SCHEMA_METADATA_TTL_DAYS
+ )
+
+ table_model.query.filter(
+ table_model.exists.is_(False), table_model.updated_at < ttl_days_ago
+ ).delete()
+
+ db.session.commit()
+
+
+class SchemaCache:
+ """
+ This caches schema requests in redis and uses a method to
+ serve stale values while the cache is being populated or
+ updated to handle the thundering herd problem.
+ """
+
+ # SCHEMAS_REFRESH_SCHEDULE is in minutes, converting to seconds here:
+ timeout = settings.SCHEMAS_REFRESH_SCHEDULE * 60
+ # keeping the stale cached items for 10 minutes longer
+ # than its timeout to make sure repopulation can work
+ stale_cache_timeout = 60 * 10
+
+ def __init__(self, data_source):
+ self.data_source = data_source
+ self.client = redis_connection
+ self.cache_key = f"data_source:schema:cache:{self.data_source.id}"
+ self.lock_key = f"{self.cache_key}:lock"
+ self.fresh_key = f"{self.cache_key}:fresh"
+
+ def populate(self, schema=None, forced=False):
+ """
+ This is the central method to populate the cache and return
+ either the provided fallback schema or the value loaded
+ from the database.
+
+ It uses Redis locking to make sure the retrieval from the
+ database isn't run many times at once.
+
+ It also sets a separate key that indicates freshness that has
+ a shorter ttl than the actual cache key that contains the
+ schema.
+
+ In the get_schema method it'll check the freshness key first
+ and trigger a repopulation of the cache key if it's stale.
+ """
+ lock = redis_connection.lock(self.lock_key, timeout=self.timeout)
+ acquired = lock.acquire(blocking=False)
+
+ if acquired or forced:
+ try:
+ schema = TableMetadata.load(self.data_source)
+ except Exception:
+ raise
+ else:
+ key_timeout = self.timeout + self.stale_cache_timeout
+ pipeline = redis_connection.pipeline()
+ pipeline.set(self.cache_key, utils.json_dumps(schema), key_timeout)
+ pipeline.set(self.fresh_key, 1, self.timeout)
+ pipeline.execute()
+ finally:
+ if acquired:
+ lock.release()
+
+ return schema or []
+
+
+@generic_repr("id", "name", "data_source_id", "org_id", "exists", "column_metadata")
+class TableMetadata(TimestampMixin, db.Model):
+ id = Column(db.Integer, primary_key=True)
+ org_id = Column(db.Integer, db.ForeignKey("organizations.id"))
+ data_source_id = Column(
+ db.Integer, db.ForeignKey("data_sources.id", ondelete="CASCADE"), index=True
+ )
+ exists = Column(db.Boolean, default=True, index=True)
+ visible = Column(db.Boolean, default=True)
+ name = Column(db.String(255), index=True)
+ description = Column(db.String(4096), nullable=True)
+ column_metadata = Column(db.Boolean, default=False)
+ sample_updated_at = Column(db.DateTime(True), nullable=True, index=True)
+ sample_queries = relationship(
+ "Query", secondary="tablemetadata_queries_link", backref="relevant_tables"
+ )
+ existing_columns = db.relationship(
+ "ColumnMetadata",
+ backref="table",
+ order_by="ColumnMetadata.name",
+ primaryjoin="and_(TableMetadata.id == ColumnMetadata.table_id, ColumnMetadata.exists.is_(True))",
+ )
+
+ __tablename__ = "table_metadata"
+ __table_args__ = (
+ db.Index("ix_table_metadata_data_source_id_exists", "data_source_id", "exists"),
+ db.Index(
+ "ix_table_metadata_data_source_id_name_exists",
+ "data_source_id",
+ "exists",
+ "name",
+ ),
+ )
+
+ def __str__(self):
+ return str(self.name)
+
+ @classmethod
+ def store(cls, data_source, existing_tables_set, table_data):
+ """
+ Insert new or update all existing tables to reflect the provided data.
+ """
+ existing_tables = cls.query.filter(
+ cls.name.in_(existing_tables_set), cls.data_source_id == data_source.id,
+ )
+ table_names = set()
+ for table in existing_tables:
+ table_names.add(table.name)
+ for name, value in table_data[table.name].items():
+ setattr(table, name, value)
+ db.session.add(table)
+
+ # Find the tables that need to be created by subtracting the sets:
+ for table_name in existing_tables_set.difference(table_names):
+ db.session.add(cls(**table_data[table_name]))
+ db.session.commit()
+
+ @classmethod
+ def load(cls, data_source):
+ """
+ When called will fetch all table and column metadata from
+ the database and serialize it with the TableMetadataSerializer.
+ """
+ # due to the unfortunate import time side effects of
+ # Redash's package layout this needs to be done inline
+ from redash.serializers import TableMetadataSerializer
+
+ schema = []
+ tables = (
+ cls.query.filter(
+ cls.data_source_id == data_source.id, cls.exists.is_(True),
+ )
+ .order_by(cls.name)
+ .options(joinedload(cls.existing_columns), joinedload(cls.sample_queries),)
+ )
+
+ for table in tables:
+ schema.append(
+ TableMetadataSerializer(table, with_favorite_state=False).serialize()
+ )
+
+ return schema
+
+
+@generic_repr("id", "name", "type", "table_id", "org_id", "exists")
+class ColumnMetadata(TimestampMixin, db.Model):
+ id = Column(db.Integer, primary_key=True)
+ org_id = Column(db.Integer, db.ForeignKey("organizations.id"))
+ table_id = Column(
+ db.Integer, db.ForeignKey("table_metadata.id", ondelete="CASCADE"), index=True
+ )
+ name = Column(db.String(255), index=True)
+ type = Column(db.String(255), nullable=True)
+ example = Column(db.String(4096), nullable=True)
+ exists = Column(db.Boolean, default=True, index=True)
+ description = Column(db.String(4096), nullable=True)
+
+ __tablename__ = "column_metadata"
+ __table_args__ = (
+ db.Index("ix_column_metadata_table_id_pkey", "table_id", "id"),
+ db.Index("ix_column_metadata_table_id_exists", "table_id", "exists"),
+ db.Index(
+ "ix_column_metadata_table_id_name_exists", "table_id", "exists", "name"
+ ),
+ )
+
+ def __str__(self):
+ return str(self.name)
+
+ @classmethod
+ def store(cls, table, existing_columns_set, column_data):
+ existing_columns = cls.query.filter(
+ cls.name.in_(existing_columns_set), cls.table_id == table.id,
+ ).all()
+
+ column_names = set()
+ for column in existing_columns:
+ column_names.add(column.name)
+ for name, value in column_data[column.name].items():
+ setattr(column, name, value)
+ db.session.add(column)
+
+ # Find the columns that need to be created by subtracting the sets:
+ for column_name in existing_columns_set.difference(column_names):
+ db.session.add(cls(**column_data[column_name]))
+ db.session.commit()
+
+
+class TableMetadataQueriesLink(db.Model):
+ table_id = Column(
+ db.Integer,
+ db.ForeignKey("table_metadata.id", ondelete="CASCADE"),
+ primary_key=True,
+ )
+ query_id = Column(
+ db.Integer, db.ForeignKey("queries.id", ondelete="CASCADE"), primary_key=True
+ )
+
+ __tablename__ = "tablemetadata_queries_link"
+
+ def __str__(self):
+ return str(self.id)
+
+
@generic_repr("id", "name", "type", "org_id", "created_at")
class DataSource(BelongsToOrgMixin, db.Model):
id = primary_key("DataSource")
@@ -98,6 +313,7 @@ class DataSource(BelongsToOrgMixin, db.Model):
)
),
)
+ description = Column(db.String(4096), nullable=True)
queue_name = Column(db.String(255), default="queries")
scheduled_queue_name = Column(db.String(255), default="scheduled_queries")
created_at = Column(db.DateTime(True), default=db.func.now())
@@ -119,6 +335,7 @@ def to_dict(self, all=False, with_permissions_for=None):
"id": self.id,
"name": self.name,
"type": self.type,
+ "description": self.description,
"syntax": self.query_runner.syntax,
"paused": self.paused,
"pause_reason": self.pause_reason,
@@ -171,6 +388,35 @@ def all(cls, org, group_ids=None):
def get_by_id(cls, _id):
return cls.query.filter(cls.id == _id).one()
+ @classmethod
+ def save_schema(cls, schema_info):
+ # There was a change in column data.
+ if "columnId" in schema_info:
+ ColumnMetadata.query.filter(
+ ColumnMetadata.table_id == schema_info["tableId"],
+ ColumnMetadata.id == schema_info["columnId"],
+ ).update(schema_info["schema"])
+ db.session.commit()
+ return
+
+ sample_queries = schema_info["schema"].pop("sample_queries", None)
+ if sample_queries is not None:
+ table_metadata_object = TableMetadata.query.filter(
+ TableMetadata.id == schema_info["tableId"]
+ ).first()
+ table_metadata_object.sample_queries = []
+
+ query_ids = [sample_query["id"] for sample_query in sample_queries.values()]
+ query_objects = Query.query.filter(Query.id.in_(query_ids))
+ table_metadata_object.sample_queries.extend(query_objects)
+ db.session.add(table_metadata_object)
+ db.session.commit()
+
+ TableMetadata.query.filter(TableMetadata.id == schema_info["tableId"]).update(
+ schema_info["schema"]
+ )
+ db.session.commit()
+
def delete(self):
Query.query.filter(Query.data_source == self).update(
dict(data_source_id=None, latest_query_data_id=None)
@@ -178,45 +424,52 @@ def delete(self):
QueryResult.query.filter(QueryResult.data_source == self).delete()
res = db.session.delete(self)
db.session.commit()
-
- redis_connection.delete(self._schema_key)
-
return res
- def get_cached_schema(self):
- cache = redis_connection.get(self._schema_key)
- return json_loads(cache) if cache else None
-
def get_schema(self, refresh=False):
- out_schema = None
- if not refresh:
- out_schema = self.get_cached_schema()
-
- if out_schema is None:
- query_runner = self.query_runner
- schema = query_runner.get_schema(get_stats=refresh)
-
- try:
- out_schema = self._sort_schema(schema)
- except Exception:
- logging.exception(
- "Error sorting schema columns for data_source {}".format(self.id)
- )
- out_schema = schema
- finally:
- redis_connection.set(self._schema_key, json_dumps(out_schema))
-
- return out_schema
-
- def _sort_schema(self, schema):
- return [
- {"name": i["name"], "columns": sorted(i["columns"])}
- for i in sorted(schema, key=lambda x: x["name"])
- ]
+ """
+ Get or set the schema from Redis.
+
+ This will first check for the fresh key and either
+ return the schema value if it's still fresh or
+ repopulate the cache key and return the stale value.
+
+ This will refresh the schema from the data source's API
+ when requested with the refresh parameter, which will also
+ (re)populate the cache.
+ """
+ if refresh:
+ from redash.tasks.queries import refresh_schema
+
+ refresh_schema.delay(self.id)
+
+ # First let's try to find out if there is a cached schema
+ # already and hasn't timed out yet and load it with json.
+ schema = redis_connection.get(self.schema_cache.cache_key)
+ if schema:
+ schema = utils.json_loads(schema)
+ else:
+ # Otherwise we assume the cache key has timed out or was
+ # never populated before.
+ schema = []
+
+ # Now check if there is a fresh key from the last time populating.
+ is_fresh = redis_connection.get(self.schema_cache.fresh_key)
+ if is_fresh:
+ # If the cache value is still fresh, just return it.
+ return schema
+ else:
+ # Otherwise pass the stale value to the populate method
+ # so it can use it as a fallback in case a population
+ # lock is in place already (e.g. another user has already
+ # tried to fetch the schema). If the lock can be created
+ # successfully, it'll actually load the schema using the
+ # load method and set the cache and refresh keys.
+ return self.schema_cache.populate(schema)
@property
- def _schema_key(self):
- return "data_source:schema:{}".format(self.id)
+ def schema_cache(self):
+ return SchemaCache(self)
@property
def _pause_key(self):
@@ -638,6 +891,7 @@ def outdated_queries(cls):
)
.filter(Query.schedule.isnot(None))
.order_by(Query.id)
+ .all()
)
now = utils.utcnow()
@@ -1099,6 +1353,10 @@ class Dashboard(ChangeTrackingMixin, TimestampMixin, BelongsToOrgMixin, db.Model
def __str__(self):
return "%s=%s" % (self.id, self.name)
+ @property
+ def name_as_slug(self):
+ return utils.slugify(self.name)
+
@classmethod
def all(cls, org, group_ids, user_id):
query = (
@@ -1303,6 +1561,7 @@ class ApiKey(TimestampMixin, GFKBase, db.Model):
api_key = Column(db.String(255), index=True, default=lambda: generate_token(40))
active = Column(db.Boolean, default=True)
# 'object' provided by GFKBase
+ object_id = Column(key_type("ApiKey"))
created_by_id = Column(key_type("User"), db.ForeignKey("users.id"), nullable=True)
created_by = db.relationship(User)
diff --git a/redash/models/base.py b/redash/models/base.py
index 027d906670..e2b7e68277 100644
--- a/redash/models/base.py
+++ b/redash/models/base.py
@@ -4,6 +4,7 @@
from sqlalchemy.orm import object_session
from sqlalchemy.pool import NullPool
from sqlalchemy_searchable import make_searchable, vectorizer, SearchQueryMixin
+from sqlalchemy.dialects import postgresql
from redash import settings
from redash.utils import json_dumps
@@ -48,6 +49,11 @@ def integer_vectorizer(column):
return db.func.cast(column, db.Text)
+@vectorizer(postgresql.UUID)
+def uuid_vectorizer(column):
+ return db.func.cast(column, db.Text)
+
+
Column = functools.partial(db.Column, nullable=False)
# AccessPermission and Change use a 'generic foreign key' approach to refer to
diff --git a/redash/models/changes.py b/redash/models/changes.py
index c0d437ee7b..cf8be934d0 100644
--- a/redash/models/changes.py
+++ b/redash/models/changes.py
@@ -9,6 +9,7 @@
class Change(GFKBase, db.Model):
id = primary_key("Change")
# 'object' defined in GFKBase
+ object_id = Column(key_type("Change"))
object_version = Column(db.Integer, default=0)
user_id = Column(key_type("User"), db.ForeignKey("users.id"))
user = db.relationship("User", backref="changes")
diff --git a/redash/query_runner/__init__.py b/redash/query_runner/__init__.py
index 9f92ffe637..4e4cc2cd1f 100644
--- a/redash/query_runner/__init__.py
+++ b/redash/query_runner/__init__.py
@@ -61,6 +61,7 @@ class BaseQueryRunner(object):
deprecated = False
should_annotate_query = True
noop_query = None
+ sample_query = None
def __init__(self, configuration):
self.syntax = "sql"
@@ -181,6 +182,25 @@ def _run_query_internal(self, query):
raise Exception("Failed running query [%s]." % query)
return json_loads(results)["rows"]
+ def get_table_sample(self, table_name):
+ if self.sample_query is None:
+ raise NotImplementedError()
+
+ query = self.sample_query.format(table=table_name)
+
+ results, error = self.run_query(query, None)
+ if error is not None:
+ logger.exception(error)
+ raise NotSupported()
+
+ rows = json_loads(results).get("rows", [])
+ if len(rows) > 0:
+ sample = rows[0]
+ else:
+ sample = {}
+
+ return sample
+
@classmethod
def to_dict(cls):
return {
@@ -232,6 +252,12 @@ def configuration_schema(cls):
"url": {"type": "string", "title": cls.url_title},
"username": {"type": "string", "title": cls.username_title},
"password": {"type": "string", "title": cls.password_title},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"secret": ["password"],
"order": ["url", "username", "password"],
diff --git a/redash/query_runner/athena.py b/redash/query_runner/athena.py
index 35a2ba5dc5..0ae70f8bb4 100644
--- a/redash/query_runner/athena.py
+++ b/redash/query_runner/athena.py
@@ -50,6 +50,10 @@ def format(self, operation, parameters=None):
class Athena(BaseQueryRunner):
noop_query = "SELECT 1"
+ # This takes a 1% random sample from {table}, reducing
+ # the runtime and data scanned for the query
+ sample_query = "SELECT * FROM {table} TABLESAMPLE SYSTEM (1) LIMIT 1"
+
@classmethod
def name(cls):
return "Amazon Athena"
@@ -82,6 +86,13 @@ def configuration_schema(cls):
"title": "Athena cost per Tb scanned (USD)",
"default": 5,
},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
+ "samples": {"type": "boolean", "title": "Show Data Samples"},
},
"required": ["region", "s3_staging_dir"],
"extra_options": ["glue", "cost_per_tb"],
@@ -182,12 +193,17 @@ def __get_schema_from_glue(self):
table_name = "%s.%s" % (database["Name"], table["Name"])
if table_name not in schema:
column = [
- columns["Name"]
- for columns in table["StorageDescriptor"]["Columns"]
+ {"name": column_data["Name"], "type": column_data["Type"]}
+ for column_data in table["StorageDescriptor"]["Columns"]
]
- schema[table_name] = {"name": table_name, "columns": column}
+ schema[table_name] = {
+ "name": table_name,
+ "columns": column,
+ }
for partition in table.get("PartitionKeys", []):
- schema[table_name]["columns"].append(partition["Name"])
+ schema[table_name]["columns"].append(
+ {"name": partition["Name"], "type": partition["Type"]}
+ )
return list(schema.values())
def get_schema(self, get_stats=False):
@@ -196,7 +212,7 @@ def get_schema(self, get_stats=False):
schema = {}
query = """
- SELECT table_schema, table_name, column_name
+ SELECT table_schema, table_name, column_name, data_type
FROM information_schema.columns
WHERE table_schema NOT IN ('information_schema')
"""
@@ -210,7 +226,10 @@ def get_schema(self, get_stats=False):
table_name = "{0}.{1}".format(row["table_schema"], row["table_name"])
if table_name not in schema:
schema[table_name] = {"name": table_name, "columns": []}
- schema[table_name]["columns"].append(row["column_name"])
+ column = row["column_name"]
+ if row.get("data_type") is not None:
+ column = {"name": row["column_name"], "type": row["data_type"]}
+ schema[table_name]["columns"].append(column)
return list(schema.values())
diff --git a/redash/query_runner/axibase_tsd.py b/redash/query_runner/axibase_tsd.py
index ecb1af5cba..bd9bf8df1a 100644
--- a/redash/query_runner/axibase_tsd.py
+++ b/redash/query_runner/axibase_tsd.py
@@ -115,6 +115,12 @@ def configuration_schema(cls):
"type": "boolean",
"title": "Trust SSL Certificate",
},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["username", "password", "hostname", "protocol", "port"],
"secret": ["password"],
diff --git a/redash/query_runner/big_query.py b/redash/query_runner/big_query.py
index 1b29de7ff3..5f7b8352a6 100644
--- a/redash/query_runner/big_query.py
+++ b/redash/query_runner/big_query.py
@@ -1,5 +1,6 @@
import datetime
import logging
+import operator
import sys
import time
from base64 import b64decode
@@ -86,6 +87,7 @@ def _get_query_results(jobs, project_id, location, job_id, start_index):
class BigQuery(BaseQueryRunner):
should_annotate_query = False
noop_query = "SELECT 1"
+ sample_query = "#standardSQL\n SELECT * FROM {table} LIMIT 1"
@classmethod
def enabled(cls):
@@ -117,6 +119,13 @@ def configuration_schema(cls):
"type": "number",
"title": "Maximum Billing Tier",
},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
+ "samples": {"type": "boolean", "title": "Show Data Samples"},
},
"required": ["jsonKeyFile", "projectId"],
"order": [
@@ -255,51 +264,164 @@ def _get_columns_schema_column(self, column):
columns = []
if column["type"] == "RECORD":
for field in column["fields"]:
- columns.append("{}.{}".format(column["name"], field["name"]))
+ field_name = u"{}.{}".format(column["name"], field["name"])
+ columns.append({"name": field_name, "type": field["type"]})
else:
- columns.append(column["name"])
-
+ columns.append({"name": column["name"], "type": column["type"]})
return columns
+ def _columns_and_samples_to_dict(self, schema, samples):
+ samples_dict = {}
+ if not samples:
+ return samples_dict
+
+ # If a sample exists, its shape/length should be analogous to
+ # the schema provided (i.e their lengths should match up)
+ for i, column in enumerate(schema):
+ if column["type"] == "RECORD":
+ if column.get("mode", None) == "REPEATED":
+ # Repeated fields have multiple samples of the same format.
+ # We only need to show the first one as an example.
+ associated_sample = [] if len(samples[i]) == 0 else samples[i][0]
+ else:
+ associated_sample = samples[i] or []
+
+ for j, field in enumerate(column["fields"]):
+ field_name = u"{}.{}".format(column["name"], field["name"])
+ samples_dict[field_name] = None
+ if len(associated_sample) > 0:
+ samples_dict[field_name] = associated_sample[j]
+ else:
+ samples_dict[column["name"]] = samples[i]
+
+ return samples_dict
+
+ def _flatten_samples(self, samples):
+ samples_list = []
+ for field in samples:
+ value = field["v"]
+ if isinstance(value, dict):
+ samples_list.append(self._flatten_samples(value.get("f", [])))
+ elif isinstance(value, list):
+ samples_list.append(self._flatten_samples(value))
+ else:
+ samples_list.append(value)
+
+ return samples_list
+
+ def get_table_sample(self, table_name):
+ if not self.configuration.get("loadSchema", False):
+ return {}
+
+ service = self._get_bigquery_service()
+ project_id = self._get_project_id()
+
+ dataset_id, table_id = table_name.split(".", 1)
+
+ try:
+ # NOTE: the `sample_response` is limited by `maxResults` here.
+ # Without this limit, the response would be very large and require
+ # pagination using `nextPageToken`.
+ sample_response = (
+ service.tabledata()
+ .list(
+ projectId=project_id,
+ datasetId=dataset_id,
+ tableId=table_id,
+ fields="rows",
+ maxResults=1,
+ )
+ .execute()
+ )
+ schema_response = (
+ service.tables()
+ .get(
+ projectId=project_id,
+ datasetId=dataset_id,
+ tableId=table_id,
+ fields="schema,id",
+ )
+ .execute()
+ )
+ table_rows = sample_response.get("rows", [])
+
+ if len(table_rows) == 0:
+ samples = []
+ else:
+ samples = table_rows[0].get("f", [])
+
+ schema = schema_response.get("schema", {}).get("fields", [])
+ columns = self._get_columns_schema(schema_response).get("columns", [])
+
+ flattened_samples = self._flatten_samples(samples)
+ samples_dict = self._columns_and_samples_to_dict(schema, flattened_samples)
+ return samples_dict
+ except HttpError as http_error:
+ logger.exception(
+ "Error communicating with server for sample for table %s: %s",
+ table_name,
+ http_error,
+ )
+
+ # If there is an error getting the sample using the API,
+ # try to do it by running a `select *` with a limit.
+ return super().get_table_sample(table_name)
+
def get_schema(self, get_stats=False):
if not self.configuration.get("loadSchema", False):
return []
service = self._get_bigquery_service()
project_id = self._get_project_id()
- datasets = service.datasets().list(projectId=project_id).execute()
+ # get a list of Big Query datasets
+ datasets_request = service.datasets().list(
+ projectId=project_id,
+ fields="datasets/datasetReference/datasetId,nextPageToken",
+ )
+ datasets = []
+ while datasets_request:
+ # request datasets
+ datasets_response = datasets_request.execute()
+ # store results
+ datasets.extend(datasets_response.get("datasets", []))
+ # try loading next page
+ datasets_request = service.datasets().list_next(
+ datasets_request,
+ datasets_response,
+ )
+
schema = []
- for dataset in datasets.get("datasets", []):
+ # load all tables for all datasets
+ for dataset in datasets:
dataset_id = dataset["datasetReference"]["datasetId"]
- tables = (
- service.tables()
- .list(projectId=project_id, datasetId=dataset_id)
- .execute()
+ tables_request = service.tables().list(
+ projectId=project_id,
+ datasetId=dataset_id,
+ fields="tables/tableReference/tableId,nextPageToken",
)
- while True:
- for table in tables.get("tables", []):
+ while tables_request:
+ # request tables with fields above
+ tables_response = tables_request.execute()
+ for table in tables_response.get("tables", []):
+ # load schema for given table
table_data = (
service.tables()
.get(
projectId=project_id,
datasetId=dataset_id,
tableId=table["tableReference"]["tableId"],
+ fields="id,schema",
)
.execute()
)
+ # build schema data with given table data
table_schema = self._get_columns_schema(table_data)
schema.append(table_schema)
- next_token = tables.get("nextPageToken", None)
- if next_token is None:
- break
-
- tables = (
- service.tables()
- .list(
- projectId=project_id, datasetId=dataset_id, pageToken=next_token
- )
- .execute()
+ # try loading next page of results
+ tables_request = service.tables().list_next(
+ tables_request,
+ tables_response,
)
return schema
diff --git a/redash/query_runner/cass.py b/redash/query_runner/cass.py
index 4a49c0d9b1..94d95d1854 100644
--- a/redash/query_runner/cass.py
+++ b/redash/query_runner/cass.py
@@ -77,6 +77,12 @@ def configuration_schema(cls):
"PROTOCOL_TLSv1_2",
],
},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["keyspace", "host", "useSsl"],
"secret": ["sslCertificateFile"],
diff --git a/redash/query_runner/clickhouse.py b/redash/query_runner/clickhouse.py
index c2a1c6ebb5..cc5f8e4f92 100644
--- a/redash/query_runner/clickhouse.py
+++ b/redash/query_runner/clickhouse.py
@@ -32,6 +32,12 @@ def configuration_schema(cls):
"title": "Verify SSL certificate",
"default": True,
},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"order": ["url", "user", "password", "dbname"],
"required": ["dbname"],
diff --git a/redash/query_runner/databricks.py b/redash/query_runner/databricks.py
index 14ce2abb19..6c107f9450 100644
--- a/redash/query_runner/databricks.py
+++ b/redash/query_runner/databricks.py
@@ -141,12 +141,36 @@ def get_databases(self):
results = json_loads(results)
- return [row["namespace"] for row in results["rows"]]
+ first_column_name = results["columns"][0]["name"]
+ return [row[first_column_name] for row in results["rows"]]
- def get_database_schema(self, database_name):
+ def get_database_tables(self, database_name):
schema = {}
cursor = self._get_cursor()
+ cursor.tables(schema=database_name)
+
+ for table in cursor:
+ table_name = "{}.{}".format(table[1], table[2])
+
+ if table_name not in schema:
+ schema[table_name] = {"name": table_name, "columns": []}
+
+ return list(schema.values())
+
+ def get_database_tables_with_columns(self, database_name):
+ schema = {}
+ cursor = self._get_cursor()
+
+ # load tables first, otherwise tables without columns are not showed
+ cursor.tables(schema=database_name)
+
+ for table in cursor:
+ table_name = "{}.{}".format(table[1], table[2])
+
+ if table_name not in schema:
+ schema[table_name] = {"name": table_name, "columns": []}
+
cursor.columns(schema=database_name)
for column in cursor:
@@ -155,9 +179,14 @@ def get_database_schema(self, database_name):
if table_name not in schema:
schema[table_name] = {"name": table_name, "columns": []}
- schema[table_name]["columns"].append(column[3])
+ schema[table_name]["columns"].append({"name": column[3], "type": column[5]})
return list(schema.values())
+ def get_table_columns(self, database_name, table_name):
+ cursor = self._get_cursor()
+ cursor.columns(schema=database_name, table=table_name)
+ return [{"name": column[3], "type": column[5]} for column in cursor]
+
register(Databricks)
diff --git a/redash/query_runner/dynamodb_sql.py b/redash/query_runner/dynamodb_sql.py
index 965cc8fc2f..fa99c0ee12 100644
--- a/redash/query_runner/dynamodb_sql.py
+++ b/redash/query_runner/dynamodb_sql.py
@@ -44,6 +44,12 @@ def configuration_schema(cls):
"region": {"type": "string", "default": "us-east-1"},
"access_key": {"type": "string"},
"secret_key": {"type": "string"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["access_key", "secret_key"],
"secret": ["secret_key"],
diff --git a/redash/query_runner/elasticsearch.py b/redash/query_runner/elasticsearch.py
index d96dd1e433..5658b5fb50 100644
--- a/redash/query_runner/elasticsearch.py
+++ b/redash/query_runner/elasticsearch.py
@@ -56,6 +56,12 @@ def configuration_schema(cls):
"type": "string",
"title": "Basic Auth Password",
},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"order": ["server", "basic_auth_user", "basic_auth_password"],
"secret": ["basic_auth_password"],
diff --git a/redash/query_runner/google_analytics.py b/redash/query_runner/google_analytics.py
index 9956f5d5f3..fbd6763506 100644
--- a/redash/query_runner/google_analytics.py
+++ b/redash/query_runner/google_analytics.py
@@ -103,7 +103,15 @@ def enabled(cls):
def configuration_schema(cls):
return {
"type": "object",
- "properties": {"jsonKeyFile": {"type": "string", "title": "JSON Key File"}},
+ "properties": {
+ "jsonKeyFile": {"type": "string", "title": "JSON Key File"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
+ },
"required": ["jsonKeyFile"],
"secret": ["jsonKeyFile"],
}
diff --git a/redash/query_runner/google_spreadsheets.py b/redash/query_runner/google_spreadsheets.py
index c9f159c75b..e747e7075b 100644
--- a/redash/query_runner/google_spreadsheets.py
+++ b/redash/query_runner/google_spreadsheets.py
@@ -166,7 +166,15 @@ def enabled(cls):
def configuration_schema(cls):
return {
"type": "object",
- "properties": {"jsonKeyFile": {"type": "string", "title": "JSON Key File"}},
+ "properties": {
+ "jsonKeyFile": {"type": "string", "title": "JSON Key File"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
+ },
"required": ["jsonKeyFile"],
"secret": ["jsonKeyFile"],
}
diff --git a/redash/query_runner/graphite.py b/redash/query_runner/graphite.py
index 3bbf098598..d7285b8637 100644
--- a/redash/query_runner/graphite.py
+++ b/redash/query_runner/graphite.py
@@ -45,6 +45,12 @@ def configuration_schema(cls):
"username": {"type": "string"},
"password": {"type": "string"},
"verify": {"type": "boolean", "title": "Verify SSL certificate"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["url"],
"secret": ["password"],
diff --git a/redash/query_runner/hive_ds.py b/redash/query_runner/hive_ds.py
index 1baab89560..2fa2389759 100644
--- a/redash/query_runner/hive_ds.py
+++ b/redash/query_runner/hive_ds.py
@@ -50,6 +50,12 @@ def configuration_schema(cls):
"port": {"type": "number"},
"database": {"type": "string"},
"username": {"type": "string"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"order": ["host", "port", "database", "username"],
"required": ["host"],
@@ -111,7 +117,6 @@ def _get_connection(self):
database=self.configuration.get("database", "default"),
username=self.configuration.get("username", None),
)
-
return connection
def run_query(self, query, user):
diff --git a/redash/query_runner/impala_ds.py b/redash/query_runner/impala_ds.py
index 9981586142..68596513d6 100644
--- a/redash/query_runner/impala_ds.py
+++ b/redash/query_runner/impala_ds.py
@@ -56,6 +56,12 @@ def configuration_schema(cls):
"ldap_user": {"type": "string"},
"ldap_password": {"type": "string"},
"timeout": {"type": "number"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["host"],
"secret": ["ldap_password"],
diff --git a/redash/query_runner/influx_db.py b/redash/query_runner/influx_db.py
index 6ca3ecb23c..fbd90e1437 100644
--- a/redash/query_runner/influx_db.py
+++ b/redash/query_runner/influx_db.py
@@ -55,7 +55,15 @@ class InfluxDB(BaseQueryRunner):
def configuration_schema(cls):
return {
"type": "object",
- "properties": {"url": {"type": "string"}},
+ "properties": {
+ "url": {"type": "string"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
+ },
"required": ["url"],
}
diff --git a/redash/query_runner/memsql_ds.py b/redash/query_runner/memsql_ds.py
index d1c235608d..dc0bf9d8c8 100644
--- a/redash/query_runner/memsql_ds.py
+++ b/redash/query_runner/memsql_ds.py
@@ -50,6 +50,12 @@ def configuration_schema(cls):
"port": {"type": "number"},
"user": {"type": "string"},
"password": {"type": "string"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["host", "port"],
"secret": ["password"],
diff --git a/redash/query_runner/mongodb.py b/redash/query_runner/mongodb.py
index b89e2b6640..74faaf8e12 100644
--- a/redash/query_runner/mongodb.py
+++ b/redash/query_runner/mongodb.py
@@ -146,6 +146,12 @@ def configuration_schema(cls):
],
"title": "Replica Set Read Preference",
},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["connectionString", "dbName"],
}
diff --git a/redash/query_runner/mssql.py b/redash/query_runner/mssql.py
index 73cd38d3a8..79db424e26 100644
--- a/redash/query_runner/mssql.py
+++ b/redash/query_runner/mssql.py
@@ -50,6 +50,12 @@ def configuration_schema(cls):
"title": "Character Set",
},
"db": {"type": "string", "title": "Database Name"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["db"],
"secret": ["password"],
diff --git a/redash/query_runner/mysql.py b/redash/query_runner/mysql.py
index 61dfde8c1c..5dcb3c9fbf 100644
--- a/redash/query_runner/mysql.py
+++ b/redash/query_runner/mysql.py
@@ -51,6 +51,7 @@ def __init__(self):
class Mysql(BaseSQLQueryRunner):
noop_query = "SELECT 1"
+ sample_query = "SELECT * FROM {table} LIMIT 1"
@classmethod
def configuration_schema(cls):
@@ -66,6 +67,13 @@ def configuration_schema(cls):
"passwd": {"type": "string", "title": "Password"},
"db": {"type": "string", "title": "Database name"},
"port": {"type": "number", "default": 3306},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
+ "samples": {"type": "boolean", "title": "Show Data Samples"},
},
"order": ["host", "port", "user", "passwd", "db"],
"required": ["db"],
@@ -126,7 +134,8 @@ def _get_tables(self, schema):
query = """
SELECT col.table_schema as table_schema,
col.table_name as table_name,
- col.column_name as column_name
+ col.column_name as column_name,
+ col.column_type as data_type
FROM `information_schema`.`columns` col
WHERE col.table_schema NOT IN ('information_schema', 'performance_schema', 'mysql', 'sys');
"""
@@ -147,7 +156,9 @@ def _get_tables(self, schema):
if table_name not in schema:
schema[table_name] = {"name": table_name, "columns": []}
- schema[table_name]["columns"].append(row["column_name"])
+ schema[table_name]["columns"].append(
+ {"name": row["column_name"], "type": row["data_type"]}
+ )
return list(schema.values())
diff --git a/redash/query_runner/oracle.py b/redash/query_runner/oracle.py
index 26d80592a6..4fe41db067 100644
--- a/redash/query_runner/oracle.py
+++ b/redash/query_runner/oracle.py
@@ -59,6 +59,12 @@ def configuration_schema(cls):
"port": {"type": "number"},
"servicename": {"type": "string", "title": "DSN Service Name"},
"encoding": {"type": "string"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["servicename", "user", "password", "host", "port"],
"extra_options": ["encoding"],
diff --git a/redash/query_runner/pg.py b/redash/query_runner/pg.py
index d7be8efc0b..263400ac61 100644
--- a/redash/query_runner/pg.py
+++ b/redash/query_runner/pg.py
@@ -72,9 +72,9 @@ def _wait(conn, timeout=None):
def full_table_name(schema, name):
if "." in name:
- name = u'"{}"'.format(name)
+ name = '"{}"'.format(name)
- return u"{}.{}".format(schema, name)
+ return "{}.{}".format(schema, name)
def build_schema(query_result, schema):
@@ -104,13 +104,17 @@ def build_schema(query_result, schema):
if table_name not in schema:
schema[table_name] = {"name": table_name, "columns": []}
- schema[table_name]["columns"].append(row["column_name"])
+ column = row["column_name"]
+ if row.get("data_type") is not None:
+ column = {"name": row["column_name"], "type": row["data_type"]}
+
+ schema[table_name]["columns"].append(column)
def _create_cert_file(configuration, key, ssl_config):
- file_key = key + 'File'
+ file_key = key + "File"
if file_key in configuration:
- with NamedTemporaryFile(mode='w', delete=False) as cert_file:
+ with NamedTemporaryFile(mode="w", delete=False) as cert_file:
cert_bytes = b64decode(configuration[file_key])
cert_file.write(cert_bytes.decode("utf-8"))
@@ -119,22 +123,23 @@ def _create_cert_file(configuration, key, ssl_config):
def _cleanup_ssl_certs(ssl_config):
for k, v in ssl_config.items():
- if k != 'sslmode':
+ if k != "sslmode":
os.remove(v)
def _get_ssl_config(configuration):
- ssl_config = {'sslmode': configuration.get('sslmode', 'prefer')}
+ ssl_config = {"sslmode": configuration.get("sslmode", "prefer")}
- _create_cert_file(configuration, 'sslrootcert', ssl_config)
- _create_cert_file(configuration, 'sslcert', ssl_config)
- _create_cert_file(configuration, 'sslkey', ssl_config)
+ _create_cert_file(configuration, "sslrootcert", ssl_config)
+ _create_cert_file(configuration, "sslcert", ssl_config)
+ _create_cert_file(configuration, "sslkey", ssl_config)
return ssl_config
class PostgreSQL(BaseSQLQueryRunner):
noop_query = "SELECT 1"
+ sample_query = "SELECT * FROM {table} LIMIT 1"
@classmethod
def configuration_schema(cls):
@@ -159,23 +164,26 @@ def configuration_schema(cls):
{"value": "verify-full", "name": "Verify Full"},
],
},
- "sslrootcertFile": {
- "type": "string",
- "title": "SSL Root Certificate"
- },
- "sslcertFile": {
- "type": "string",
- "title": "SSL Client Certificate"
- },
- "sslkeyFile": {
+ "sslrootcertFile": {"type": "string", "title": "SSL Root Certificate"},
+ "sslcertFile": {"type": "string", "title": "SSL Client Certificate"},
+ "sslkeyFile": {"type": "string", "title": "SSL Client Key"},
+ "toggle_table_string": {
"type": "string",
- "title": "SSL Client Key"
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
},
+ "samples": {"type": "boolean", "title": "Show Data Samples"},
},
"order": ["host", "port", "user", "password"],
"required": ["dbname"],
"secret": ["password"],
- "extra_options": ["sslmode", "sslrootcertFile", "sslcertFile", "sslkeyFile"],
+ "extra_options": [
+ "sslmode",
+ "sslrootcertFile",
+ "sslcertFile",
+ "sslkeyFile",
+ ],
}
@classmethod
@@ -210,7 +218,8 @@ def _get_tables(self, schema):
query = """
SELECT s.nspname as table_schema,
c.relname as table_name,
- a.attname as column_name
+ a.attname as column_name,
+ a.atttypid::regtype::varchar as data_type
FROM pg_class c
JOIN pg_namespace s
ON c.relnamespace = s.oid
@@ -219,13 +228,16 @@ def _get_tables(self, schema):
ON a.attrelid = c.oid
AND a.attnum > 0
AND NOT a.attisdropped
+ JOIN pg_type t
+ ON a.atttypid = t.oid
WHERE c.relkind IN ('m', 'f', 'p')
UNION
SELECT table_schema,
table_name,
- column_name
+ column_name,
+ data_type
FROM information_schema.columns
WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
"""
@@ -243,7 +255,7 @@ def _get_connection(self):
port=self.configuration.get("port"),
dbname=self.configuration.get("dbname"),
async_=True,
- **self.ssl_config
+ **self.ssl_config,
)
return connection
@@ -290,6 +302,7 @@ def run_query(self, query, user):
class Redshift(PostgreSQL):
+ sample_query = "SELECT * FROM {table} LIMIT 1"
@classmethod
def type(cls):
@@ -340,6 +353,13 @@ def configuration_schema(cls):
"title": "Query Group for Scheduled Queries",
"default": "default",
},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
+ "samples": {"type": "boolean", "title": "Show Data Samples"},
},
"order": [
"host",
@@ -382,12 +402,13 @@ def _get_tables(self, schema):
SELECT DISTINCT table_name,
table_schema,
column_name,
+ data_type,
ordinal_position AS pos
FROM svv_columns
WHERE table_schema NOT IN ('pg_internal','pg_catalog','information_schema')
AND table_schema NOT LIKE 'pg_temp_%'
)
- SELECT table_name, table_schema, column_name
+ SELECT table_name, table_schema, column_name, data_type
FROM tables
WHERE
HAS_SCHEMA_PRIVILEGE(table_schema, 'USAGE') AND
@@ -402,8 +423,8 @@ def _get_tables(self, schema):
return list(schema.values())
-class RedshiftIAM(Redshift):
+class RedshiftIAM(Redshift):
@classmethod
def type(cls):
return "redshift_iam"
@@ -418,11 +439,15 @@ def enabled(cls):
def _login_method_selection(self):
if self.configuration.get("rolename"):
- if not self.configuration.get("aws_access_key_id") or not self.configuration.get("aws_secret_access_key"):
+ if not self.configuration.get(
+ "aws_access_key_id"
+ ) or not self.configuration.get("aws_secret_access_key"):
return "ASSUME_ROLE_NO_KEYS"
else:
return "ASSUME_ROLE_KEYS"
- elif self.configuration.get("aws_access_key_id") and self.configuration.get("aws_secret_access_key"):
+ elif self.configuration.get("aws_access_key_id") and self.configuration.get(
+ "aws_secret_access_key"
+ ):
return "KEYS"
elif not self.configuration.get("password"):
return "ROLE"
@@ -435,7 +460,10 @@ def configuration_schema(cls):
"rolename": {"type": "string", "title": "IAM Role Name"},
"aws_region": {"type": "string", "title": "AWS Region"},
"aws_access_key_id": {"type": "string", "title": "AWS Access Key ID"},
- "aws_secret_access_key": {"type": "string", "title": "AWS Secret Access Key"},
+ "aws_secret_access_key": {
+ "type": "string",
+ "title": "AWS Secret Access Key",
+ },
"clusterid": {"type": "string", "title": "Redshift Cluster ID"},
"user": {"type": "string"},
"host": {"type": "string"},
@@ -479,39 +507,47 @@ def _get_connection(self):
login_method = self._login_method_selection()
-
if login_method == "KEYS":
- client = boto3.client("redshift",
- region_name=self.configuration.get("aws_region"),
- aws_access_key_id=self.configuration.get("aws_access_key_id"),
- aws_secret_access_key=self.configuration.get("aws_secret_access_key"))
+ client = boto3.client(
+ "redshift",
+ region_name=self.configuration.get("aws_region"),
+ aws_access_key_id=self.configuration.get("aws_access_key_id"),
+ aws_secret_access_key=self.configuration.get("aws_secret_access_key"),
+ )
elif login_method == "ROLE":
- client = boto3.client("redshift",
- region_name=self.configuration.get("aws_region"))
+ client = boto3.client(
+ "redshift", region_name=self.configuration.get("aws_region")
+ )
else:
if login_method == "ASSUME_ROLE_KEYS":
- assume_client = client = boto3.client('sts',
- region_name=self.configuration.get("aws_region"),
- aws_access_key_id=self.configuration.get("aws_access_key_id"),
- aws_secret_access_key=self.configuration.get(
- "aws_secret_access_key"))
+ assume_client = client = boto3.client(
+ "sts",
+ region_name=self.configuration.get("aws_region"),
+ aws_access_key_id=self.configuration.get("aws_access_key_id"),
+ aws_secret_access_key=self.configuration.get(
+ "aws_secret_access_key"
+ ),
+ )
else:
- assume_client = client = boto3.client('sts',
- region_name=self.configuration.get("aws_region"))
+ assume_client = client = boto3.client(
+ "sts", region_name=self.configuration.get("aws_region")
+ )
role_session = f"redash_{uuid4().hex}"
session_keys = assume_client.assume_role(
- RoleArn=self.configuration.get("rolename"),
- RoleSessionName=role_session)["Credentials"]
- client = boto3.client("redshift",
- region_name=self.configuration.get("aws_region"),
- aws_access_key_id=session_keys["AccessKeyId"],
- aws_secret_access_key=session_keys["SecretAccessKey"],
- aws_session_token=session_keys["SessionToken"]
- )
+ RoleArn=self.configuration.get("rolename"), RoleSessionName=role_session
+ )["Credentials"]
+ client = boto3.client(
+ "redshift",
+ region_name=self.configuration.get("aws_region"),
+ aws_access_key_id=session_keys["AccessKeyId"],
+ aws_secret_access_key=session_keys["SecretAccessKey"],
+ aws_session_token=session_keys["SessionToken"],
+ )
credentials = client.get_cluster_credentials(
DbUser=self.configuration.get("user"),
DbName=self.configuration.get("dbname"),
- ClusterIdentifier=self.configuration.get("clusterid"))
+ ClusterIdentifier=self.configuration.get("clusterid"),
+ )
db_user = credentials["DbUser"]
db_password = credentials["DbPassword"]
connection = psycopg2.connect(
diff --git a/redash/query_runner/presto.py b/redash/query_runner/presto.py
index ac76c5e710..bcca347ae1 100644
--- a/redash/query_runner/presto.py
+++ b/redash/query_runner/presto.py
@@ -33,6 +33,7 @@
class Presto(BaseQueryRunner):
noop_query = "SHOW TABLES"
+ sample_query = "SELECT * FROM {table} TABLESAMPLE SYSTEM (1) LIMIT 1"
@classmethod
def configuration_schema(cls):
@@ -46,6 +47,13 @@ def configuration_schema(cls):
"catalog": {"type": "string"},
"username": {"type": "string"},
"password": {"type": "string"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
+ "samples": {"type": "boolean", "title": "Show Data Samples"},
},
"order": [
"host",
@@ -70,7 +78,7 @@ def type(cls):
def get_schema(self, get_stats=False):
schema = {}
query = """
- SELECT table_schema, table_name, column_name
+ SELECT table_schema, table_name, column_name, data_type
FROM information_schema.columns
WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
"""
@@ -88,7 +96,9 @@ def get_schema(self, get_stats=False):
if table_name not in schema:
schema[table_name] = {"name": table_name, "columns": []}
- schema[table_name]["columns"].append(row["column_name"])
+ schema[table_name]["columns"].append(
+ {"name": row["column_name"], "type": row["data_type"],}
+ )
return list(schema.values())
diff --git a/redash/query_runner/python.py b/redash/query_runner/python.py
index ab3f25a53d..41ea383574 100644
--- a/redash/query_runner/python.py
+++ b/redash/query_runner/python.py
@@ -83,6 +83,12 @@ def configuration_schema(cls):
},
"additionalModulesPaths": {"type": "string"},
"additionalBuiltins": {"type": "string"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
}
diff --git a/redash/query_runner/salesforce.py b/redash/query_runner/salesforce.py
index fb0eeea9bb..3f1bd261f4 100644
--- a/redash/query_runner/salesforce.py
+++ b/redash/query_runner/salesforce.py
@@ -77,6 +77,12 @@ def configuration_schema(cls):
"title": "Salesforce API Version",
"default": DEFAULT_API_VERSION,
},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["username", "password", "token"],
"secret": ["password", "token"],
diff --git a/redash/query_runner/script.py b/redash/query_runner/script.py
index 9adb1851c9..ae2a342442 100644
--- a/redash/query_runner/script.py
+++ b/redash/query_runner/script.py
@@ -45,6 +45,12 @@ def configuration_schema(cls):
"type": "boolean",
"title": "Execute command through the shell",
},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["path"],
}
diff --git a/redash/query_runner/snowflake.py b/redash/query_runner/snowflake.py
index 3e32f572d5..34556457c6 100644
--- a/redash/query_runner/snowflake.py
+++ b/redash/query_runner/snowflake.py
@@ -45,6 +45,12 @@ def configuration_schema(cls):
"warehouse": {"type": "string"},
"database": {"type": "string"},
"region": {"type": "string", "default": "us-west"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"order": ["account", "user", "password", "warehouse", "database", "region"],
"required": ["user", "password", "account", "database", "warehouse"],
diff --git a/redash/query_runner/sqlite.py b/redash/query_runner/sqlite.py
index ffee42bf7f..f88bd06fbb 100644
--- a/redash/query_runner/sqlite.py
+++ b/redash/query_runner/sqlite.py
@@ -14,7 +14,15 @@ class Sqlite(BaseSQLQueryRunner):
def configuration_schema(cls):
return {
"type": "object",
- "properties": {"dbpath": {"type": "string", "title": "Database Path"}},
+ "properties": {
+ "dbpath": {"type": "string", "title": "Database Path"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
+ },
"required": ["dbpath"],
}
diff --git a/redash/query_runner/treasuredata.py b/redash/query_runner/treasuredata.py
index 763b3e3c4a..d0541fc673 100644
--- a/redash/query_runner/treasuredata.py
+++ b/redash/query_runner/treasuredata.py
@@ -52,6 +52,12 @@ def configuration_schema(cls):
"title": "Auto Schema Retrieval",
"default": False,
},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["apikey", "db"],
}
diff --git a/redash/query_runner/vertica.py b/redash/query_runner/vertica.py
index a6989ee7dd..f7a61fe2b4 100644
--- a/redash/query_runner/vertica.py
+++ b/redash/query_runner/vertica.py
@@ -42,6 +42,12 @@ def configuration_schema(cls):
"port": {"type": "number"},
"read_timeout": {"type": "number", "title": "Read Timeout"},
"connection_timeout": {"type": "number", "title": "Connection Timeout"},
+ "toggle_table_string": {
+ "type": "string",
+ "title": "Toggle Table String",
+ "default": "_v",
+ "info": "This string will be used to toggle visibility of tables in the schema browser when editing a query in order to remove non-useful tables from sight.",
+ },
},
"required": ["database"],
"order": [
diff --git a/redash/security.py b/redash/security.py
index dd14441385..3d21c8e463 100644
--- a/redash/security.py
+++ b/redash/security.py
@@ -1,10 +1,15 @@
import functools
+from flask import session, request
+from flask_login import current_user
from flask_talisman import talisman
+from flask_wtf.csrf import CSRFProtect, generate_csrf
+
from redash import settings
talisman = talisman.Talisman()
+csrf = CSRFProtect()
def csp_allows_embeding(fn):
@@ -19,6 +24,32 @@ def decorated(*args, **kwargs):
def init_app(app):
+ csrf.init_app(app)
+ app.config["WTF_CSRF_CHECK_DEFAULT"] = False
+ app.config["WTF_CSRF_SSL_STRICT"] = False
+
+ @app.after_request
+ def inject_csrf_token(response):
+ response.set_cookie("csrf_token", generate_csrf())
+ return response
+
+ if settings.ENFORCE_CSRF:
+ @app.before_request
+ def check_csrf():
+ # BEGIN workaround until https://github.com/lepture/flask-wtf/pull/419 is merged
+ if request.blueprint in csrf._exempt_blueprints:
+ return
+
+ view = app.view_functions.get(request.endpoint)
+ dest = f'{view.__module__}.{view.__name__}'
+
+ if dest in csrf._exempt_views:
+ return
+ # END workaround
+
+ if not current_user.is_authenticated or "user_id" in session:
+ csrf.protect()
+
talisman.init_app(
app,
feature_policy=settings.FEATURE_POLICY,
diff --git a/redash/serializers/__init__.py b/redash/serializers/__init__.py
index b82c1b9f17..6e7e997be9 100644
--- a/redash/serializers/__init__.py
+++ b/redash/serializers/__init__.py
@@ -75,15 +75,13 @@ class Serializer(object):
class QuerySerializer(Serializer):
def __init__(self, object_or_list, **kwargs):
self.object_or_list = object_or_list
+ self.with_favorite_state = kwargs.pop("with_favorite_state", True)
self.options = kwargs
def serialize(self):
if isinstance(self.object_or_list, models.Query):
result = serialize_query(self.object_or_list, **self.options)
- if (
- self.options.get("with_favorite_state", True)
- and not current_user.is_api_user()
- ):
+ if self.with_favorite_state and not current_user.is_api_user():
result["is_favorite"] = models.Favorite.is_favorite(
current_user.id, self.object_or_list
)
@@ -91,7 +89,7 @@ def serialize(self):
result = [
serialize_query(query, **self.options) for query in self.object_or_list
]
- if self.options.get("with_favorite_state", True):
+ if self.with_favorite_state:
favorite_ids = models.Favorite.are_favorites(
current_user.id, self.object_or_list
)
@@ -101,6 +99,80 @@ def serialize(self):
return result
+class ColumnMetadataSerializer(Serializer):
+ def __init__(self, object_or_list):
+ self.object_or_list = object_or_list
+
+ def serialize(self):
+ if isinstance(self.object_or_list, models.ColumnMetadata):
+ result = serialize_column_metadata(self.object_or_list)
+ else:
+ result = [
+ serialize_column_metadata(column_metadata)
+ for column_metadata in self.object_or_list
+ ]
+ return result
+
+
+class TableMetadataSerializer(Serializer):
+ def __init__(self, object_or_list, **kwargs):
+ self.object_or_list = object_or_list
+ self.options = kwargs
+
+ def serialize(self):
+ if isinstance(self.object_or_list, models.TableMetadata):
+ result = serialize_table_metadata(self.object_or_list, self.options)
+ else:
+ result = [
+ serialize_table_metadata(column_metadata, self.options)
+ for column_metadata in self.object_or_list
+ ]
+ return result
+
+
+def serialize_table_metadata(table_metadata, options, include_columns=True):
+ sample_queries_dict = dict(
+ [
+ (v["id"], v)
+ for v in QuerySerializer(
+ table_metadata.sample_queries, **options
+ ).serialize()
+ ]
+ )
+ d = {
+ "id": table_metadata.id,
+ "org_id": table_metadata.org_id,
+ "data_source_id": table_metadata.data_source_id,
+ "exists": table_metadata.exists,
+ "visible": table_metadata.visible,
+ "name": table_metadata.name,
+ "description": table_metadata.description,
+ "column_metadata": table_metadata.column_metadata,
+ "sample_updated_at": table_metadata.sample_updated_at,
+ "sample_queries": sample_queries_dict,
+ }
+ if include_columns:
+ d["columns"] = [
+ ColumnMetadataSerializer(column).serialize()
+ for column in table_metadata.existing_columns
+ ]
+ return d
+
+
+def serialize_column_metadata(column_metadata):
+ d = {
+ "id": column_metadata.id,
+ "org_id": column_metadata.org_id,
+ "table_id": column_metadata.table_id,
+ "name": column_metadata.name,
+ "type": column_metadata.type,
+ "example": column_metadata.example,
+ "exists": column_metadata.exists,
+ "description": column_metadata.description,
+ }
+ return d
+
+
def serialize_query(
query,
with_stats=False,
@@ -245,7 +317,7 @@ def serialize_dashboard(obj, with_widgets=False, user=None, with_favorite_state=
d = {
"id": obj.id,
- "slug": obj.slug,
+ "slug": obj.name_as_slug,
"name": obj.name,
"user_id": obj.user_id,
"user": {
diff --git a/redash/settings/__init__.py b/redash/settings/__init__.py
index 539805d88b..e0033cf97b 100644
--- a/redash/settings/__init__.py
+++ b/redash/settings/__init__.py
@@ -55,7 +55,11 @@
os.environ.get("REDASH_QUERY_RESULTS_CLEANUP_MAX_AGE", "7")
)
-SCHEMAS_REFRESH_SCHEDULE = int(os.environ.get("REDASH_SCHEMAS_REFRESH_SCHEDULE", 30))
+SCHEMAS_REFRESH_SCHEDULE = int(os.environ.get("REDASH_SCHEMAS_REFRESH_SCHEDULE", 360))
+SCHEMAS_REFRESH_QUEUE = os.environ.get("REDASH_SCHEMAS_REFRESH_QUEUE", "schemas")
+SCHEMA_REFRESH_TIME_LIMIT = int(
+ os.environ.get("REDASH_SCHEMA_REFRESH_TIME_LIMIT", 3600)
+)
AUTH_TYPE = os.environ.get("REDASH_AUTH_TYPE", "api_key")
INVITATION_TOKEN_MAX_AGE = int(
@@ -229,7 +233,9 @@
STATIC_ASSETS_PATH = fix_assets_path(
os.environ.get("REDASH_STATIC_ASSETS_PATH", "../client/dist/")
)
-
+FLASK_TEMPLATE_PATH = fix_assets_path(
+ os.environ.get("REDASH_FLASK_TEMPLATE_PATH", STATIC_ASSETS_PATH)
+)
# Time limit (in seconds) for scheduled queries. Set this to -1 to execute without a time limit.
SCHEDULED_QUERY_TIME_LIMIT = int(
os.environ.get("REDASH_SCHEDULED_QUERY_TIME_LIMIT", -1)
@@ -481,6 +487,22 @@ def email_server_is_configured():
os.environ.get("REDASH_SCHEMA_RUN_TABLE_SIZE_CALCULATIONS", "false")
)
+# Frequency of clearing out old schema metadata.
+SCHEMA_METADATA_TTL_DAYS = int(os.environ.get("REDASH_SCHEMA_METADATA_TTL_DAYS", 60))
+
+# Frequency of schema samples updates
+SCHEMA_SAMPLE_UPDATE_FREQUENCY_DAYS = int(
+ os.environ.get("REDASH_SCHEMA_SAMPLE_UPDATE_FREQUENCY_DAYS", 14)
+)
+SCHEMA_SAMPLE_UPDATE_TIMEOUT = int(
+ os.environ.get("REDASH_SCHEMA_SAMPLE_UPDATE_TIMEOUT", SCHEMA_REFRESH_TIME_LIMIT)
+)
+
+# Frequency of schema samples refresh when no samples are stored
+SCHEMA_SAMPLE_REFRESH_FREQUENCY_DAYS = int(
+ os.environ.get("REDASH_SCHEMA_SAMPLE_REFRESH_FREQUENCY_DAYS", 2)
+)
+
# kylin
KYLIN_OFFSET = int(os.environ.get("REDASH_KYLIN_OFFSET", 0))
KYLIN_LIMIT = int(os.environ.get("REDASH_KYLIN_LIMIT", 50000))
@@ -498,3 +520,9 @@ def email_server_is_configured():
REQUESTS_ALLOW_REDIRECTS = parse_boolean(
os.environ.get("REDASH_REQUESTS_ALLOW_REDIRECTS", "false")
)
+
+# Enforces CSRF token validation on API requests.
+# This is turned off by default to avoid breaking any existing deployments but it is highly recommended to turn this toggle on to prevent CSRF attacks.
+ENFORCE_CSRF = parse_boolean(
+ os.environ.get("REDASH_ENFORCE_CSRF", "false")
+)
\ No newline at end of file
diff --git a/redash/settings/dynamic_settings.py b/redash/settings/dynamic_settings.py
index 836153ce36..1f15712238 100644
--- a/redash/settings/dynamic_settings.py
+++ b/redash/settings/dynamic_settings.py
@@ -57,3 +57,7 @@ def database_key_definitions(default):
)
return definitions
+
+# Since you can define custom primary key types using `database_key_definitions`, you may want to load certain extensions when creating the database.
+# To do so, simply add the name of the extension you'd like to load to this list.
+database_extensions = []
\ No newline at end of file
diff --git a/redash/tasks/__init__.py b/redash/tasks/__init__.py
index 98df1d12ff..d43259a4f7 100644
--- a/redash/tasks/__init__.py
+++ b/redash/tasks/__init__.py
@@ -10,8 +10,13 @@
execute_query,
refresh_queries,
refresh_schemas,
+ refresh_schema,
cleanup_query_results,
empty_schedules,
+ remove_ghost_locks,
+ cleanup_schema_metadata,
+ refresh_samples,
+ update_sample,
)
from .alerts import check_alerts_for_query
from .failure_report import send_aggregated_errors
diff --git a/redash/tasks/databricks.py b/redash/tasks/databricks.py
index 53e68d01f5..63849d9766 100644
--- a/redash/tasks/databricks.py
+++ b/redash/tasks/databricks.py
@@ -1,22 +1,59 @@
from rq.registry import FailedJobRegistry
-from redash import models
+from redash import models, redis_connection
from redash.worker import job
from redash.tasks.worker import Queue
+from redash.utils import json_dumps
+
+
+DATABRICKS_REDIS_EXPIRATION_TIME = 3600
+
+
+@job("schemas", queue_class=Queue, at_front=True, timeout=300, ttl=90)
+def get_databricks_databases(data_source_id, redis_key):
+ try:
+ data_source = models.DataSource.get_by_id(data_source_id)
+ databases = data_source.query_runner.get_databases()
+ redis_connection.set(redis_key, json_dumps(databases))
+ redis_connection.expire(redis_key, DATABRICKS_REDIS_EXPIRATION_TIME)
+ return databases
+ except Exception:
+ return {"error": {"code": 2, "message": "Error retrieving database list."}}
@job("schemas", queue_class=Queue, at_front=True, timeout=300, ttl=90)
-def get_databricks_databases(data_source_id):
+def get_database_tables_with_columns(data_source_id, database_name, redis_key):
try:
data_source = models.DataSource.get_by_id(data_source_id)
- return data_source.query_runner.get_databases()
+ tables = data_source.query_runner.get_database_tables_with_columns(
+ database_name
+ )
+ # check for tables since it doesn't return an error when the requested database doesn't exist
+ if tables or redis_connection.exists(redis_key):
+ redis_connection.set(redis_key, json_dumps(tables))
+ redis_connection.expire(
+ redis_key, DATABRICKS_REDIS_EXPIRATION_TIME,
+ )
+ return {"schema": tables, "has_columns": True}
except Exception:
return {"error": {"code": 2, "message": "Error retrieving schema."}}
@job("schemas", queue_class=Queue, at_front=True, timeout=300, ttl=90)
-def get_databricks_schema(data_source_id, database_name):
+def get_databricks_tables(data_source_id, database_name):
try:
data_source = models.DataSource.get_by_id(data_source_id)
- return data_source.query_runner.get_database_schema(database_name)
+ tables = data_source.query_runner.get_database_tables_with_columns(
+ database_name
+ )
+ return {"schema": tables, "has_columns": False}
except Exception:
return {"error": {"code": 2, "message": "Error retrieving schema."}}
+
+
+@job("schemas", queue_class=Queue, at_front=True, timeout=300, ttl=90)
+def get_databricks_table_columns(data_source_id, database_name, table_name):
+ try:
+ data_source = models.DataSource.get_by_id(data_source_id)
+ return data_source.query_runner.get_table_columns(database_name, table_name)
+ except Exception:
+ return {"error": {"code": 2, "message": "Error retrieving table columns."}}
diff --git a/redash/tasks/queries/__init__.py b/redash/tasks/queries/__init__.py
index 7c5d34fb0f..255c9570d7 100644
--- a/redash/tasks/queries/__init__.py
+++ b/redash/tasks/queries/__init__.py
@@ -1,7 +1,10 @@
from .maintenance import (
refresh_queries,
+ refresh_schema,
refresh_schemas,
cleanup_query_results,
empty_schedules,
+ remove_ghost_locks,
)
from .execution import execute_query, enqueue_query
+from .samples import cleanup_schema_metadata, refresh_samples, update_sample
diff --git a/redash/tasks/queries/maintenance.py b/redash/tasks/queries/maintenance.py
index 8f92fcdebe..912f38e95b 100644
--- a/redash/tasks/queries/maintenance.py
+++ b/redash/tasks/queries/maintenance.py
@@ -8,10 +8,13 @@
QueryDetachedFromDataSourceError,
)
from redash.tasks.failure_report import track_failure
+from redash.tasks.queries.samples import refresh_samples
from redash.utils import json_dumps, sentry
from redash.worker import job, get_job_logger
+from redash.monitor import rq_job_ids
from .execution import enqueue_query
+from .samples import truncate_long_string
logger = get_job_logger(__name__)
@@ -134,36 +137,147 @@ def cleanup_query_results():
logger.info("Deleted %d unused query results.", deleted_count)
-@job("schemas")
-def refresh_schema(data_source_id):
+def remove_ghost_locks():
+ """
+ Removes query locks that reference a non existing RQ job.
+ """
+ keys = redis_connection.keys("query_hash_job:*")
+ locks = {k: redis_connection.get(k) for k in keys}
+ jobs = list(rq_job_ids())
+
+ count = 0
+
+ for lock, job_id in locks.items():
+ if job_id not in jobs:
+ redis_connection.delete(lock)
+ count += 1
+
+ logger.info("Locks found: {}, Locks removed: {}".format(len(locks), count))
+
+
+@job(settings.SCHEMAS_REFRESH_QUEUE, timeout=settings.SCHEMA_REFRESH_TIME_LIMIT)
+def refresh_schema(data_source_id, max_type_string_length=250):
ds = models.DataSource.get_by_id(data_source_id)
- logger.info(u"task=refresh_schema state=start ds_id=%s", ds.id)
+ logger.info("task=refresh_schema state=start ds_id=%s", ds.id)
+ lock_key = "data_source:schema:refresh:{}:lock".format(data_source_id)
+ lock = redis_connection.lock(lock_key, timeout=settings.SCHEMA_REFRESH_TIME_LIMIT)
+ acquired = lock.acquire(blocking=False)
start_time = time.time()
- try:
- ds.get_schema(refresh=True)
- logger.info(
- u"task=refresh_schema state=finished ds_id=%s runtime=%.2f",
- ds.id,
- time.time() - start_time,
- )
- statsd_client.incr("refresh_schema.success")
- except JobTimeoutException:
- logger.info(
- u"task=refresh_schema state=timeout ds_id=%s runtime=%.2f",
- ds.id,
- time.time() - start_time,
- )
- statsd_client.incr("refresh_schema.timeout")
- except Exception:
- logger.warning(
- u"Failed refreshing schema for the data source: %s", ds.name, exc_info=1
- )
- statsd_client.incr("refresh_schema.error")
- logger.info(
- u"task=refresh_schema state=failed ds_id=%s runtime=%.2f",
- ds.id,
- time.time() - start_time,
- )
+
+ if acquired:
+ logger.info("task=refresh_schema state=locked ds_id=%s", ds.id)
+ try:
+ # Stores data from the updated schema that tells us which
+ # columns and which tables currently exist
+ existing_tables_set = set()
+ existing_columns_set = set()
+
+ # Stores data that will be inserted into postgres
+ table_data = {}
+ column_data = {}
+
+ new_columns = {}
+
+ for table in ds.query_runner.get_schema(get_stats=True):
+ table_name = table["name"]
+ existing_tables_set.add(table_name)
+ new_columns[table_name] = table["columns"]
+ table_data[table_name] = {
+ "org_id": ds.org_id,
+ "name": table_name,
+ "data_source_id": ds.id,
+ "column_metadata": any(col.get("type", None) for col in table["columns"]),
+ "exists": True,
+ }
+
+ models.TableMetadata.store(ds, existing_tables_set, table_data)
+
+ all_existing_persisted_tables = models.TableMetadata.query.filter(
+ models.TableMetadata.exists.is_(True),
+ models.TableMetadata.data_source_id == ds.id,
+ ).all()
+
+ for table in all_existing_persisted_tables:
+ for column in new_columns.get(table.name, []):
+ column_name = column["name"]
+ existing_columns_set.add(column_name)
+ column_data[column_name] = {
+ "org_id": ds.org_id,
+ "table_id": table.id,
+ "name": column_name,
+ "type": None,
+ "exists": True,
+ }
+
+ if table.column_metadata:
+ column_data[column_name]["type"] = truncate_long_string(
+ column["type"], max_type_string_length
+ )
+
+ models.ColumnMetadata.store(table, existing_columns_set, column_data)
+
+ existing_columns_list = list(existing_columns_set)
+
+ # If a column did not exist, set the 'column_exists' flag to false.
+ models.ColumnMetadata.query.filter(
+ models.ColumnMetadata.exists.is_(True),
+ models.ColumnMetadata.table_id == table.id,
+ ~models.ColumnMetadata.name.in_(existing_columns_list),
+ ).update(
+ {"exists": False, "updated_at": models.db.func.now()},
+ synchronize_session="fetch",
+ )
+
+ # Clear the set for the next round
+ existing_columns_set.clear()
+
+ # If a table did not exist in the get_schema() response above,
+ # set the 'exists' flag to false.
+ existing_tables_list = list(existing_tables_set)
+ models.TableMetadata.query.filter(
+ models.TableMetadata.exists.is_(True),
+ models.TableMetadata.data_source_id == ds.id,
+ ~models.TableMetadata.name.in_(existing_tables_list),
+ ).update(
+ {"exists": False, "updated_at": models.db.func.now()},
+ synchronize_session="fetch",
+ )
+
+ models.db.session.commit()
+
+ logger.info("task=refresh_schema state=caching ds_id=%s", ds.id)
+ ds.schema_cache.populate(forced=True)
+ logger.info("task=refresh_schema state=cached ds_id=%s", ds.id)
+
+ logger.info(
+ "task=refresh_schema state=finished ds_id=%s runtime=%.2f",
+ ds.id,
+ time.time() - start_time,
+ )
+ statsd_client.incr("refresh_schema.success")
+ except JobTimeoutException:
+ logger.info(
+ "task=refresh_schema state=timeout ds_id=%s runtime=%.2f",
+ ds.id,
+ time.time() - start_time,
+ )
+ statsd_client.incr("refresh_schema.timeout")
+ except Exception:
+ raise
+ logger.warning(
+ "Failed refreshing schema for the data source: %s", ds.name, exc_info=1
+ )
+ statsd_client.incr("refresh_schema.error")
+ logger.info(
+ "task=refresh_schema state=failed ds_id=%s runtime=%.2f",
+ ds.id,
+ time.time() - start_time,
+ )
+ finally:
+ lock.release()
+ logger.info("task=refresh_schema state=unlocked ds_id=%s", ds.id)
+ else:
+ logger.info("task=refresh_schema state=alreadylocked ds_id=%s", ds.id)
def refresh_schemas():
@@ -196,6 +310,7 @@ def refresh_schemas():
)
else:
refresh_schema.delay(ds.id)
+ refresh_samples.delay(ds.id, table_sample_limit=50)
logger.info(
u"task=refresh_schemas state=finish total_runtime=%.2f",
diff --git a/redash/tasks/queries/samples.py b/redash/tasks/queries/samples.py
new file mode 100644
index 0000000000..0990739d77
--- /dev/null
+++ b/redash/tasks/queries/samples.py
@@ -0,0 +1,128 @@
+import datetime
+import time
+
+from redash import models, settings, utils
+from redash.query_runner import NotSupported
+from redash.worker import get_job_logger, job
+from sqlalchemy import or_
+from sqlalchemy.orm import load_only
+
+logger = get_job_logger(__name__)
+
+
+def truncate_long_string(original_str, max_length):
+ # Remove null characters so we can save as string to postgres
+ new_str = original_str.replace("\x00", "")
+
+ if new_str and len(new_str) > max_length:
+ new_str = "{}...".format(new_str[:max_length])
+ return new_str
+
+
+@job(settings.SCHEMAS_REFRESH_QUEUE, timeout=settings.SCHEMA_SAMPLE_UPDATE_TIMEOUT)
+def update_sample(data_source_id, table_name, table_id, sample_updated_at):
+ """
+ For a given table, look up a sample row for it and update
+ the "example" fields for it in the column_metadata table.
+ """
+ logger.info(u"task=update_sample state=start table_name=%s", table_name)
+ start_time = time.time()
+ ds = models.DataSource.get_by_id(data_source_id)
+
+ persisted_columns = models.ColumnMetadata.query.filter(
+ models.ColumnMetadata.exists.is_(True),
+ models.ColumnMetadata.table_id == table_id,
+ ).options(load_only("id", "name", "example"))
+
+ update_threshold = utils.utcnow() - datetime.timedelta(
+ days=settings.SCHEMA_SAMPLE_UPDATE_FREQUENCY_DAYS
+ )
+
+ first_column = persisted_columns.first()
+
+ if (
+ first_column
+ and sample_updated_at
+ and first_column.example
+ and sample_updated_at > update_threshold
+ ):
+ # Look at the first example in the persisted columns.
+ # If this is *not* empty AND sample_updated_at is recent, don't update sample
+ logger.info(
+ u"task=update_sample state=abort - recent sample exists table_name=%s",
+ table_name,
+ )
+ return
+
+ sample = None
+ try:
+ sample = ds.query_runner.get_table_sample(table_name)
+ except NotSupported:
+ logger.info(u"Unable to fetch samples for {}".format(table_name))
+
+ if not sample:
+ return
+
+ # If a column exists, add a sample to it.
+ for persisted_column in persisted_columns.all():
+ column_example = sample.get(persisted_column.name, None)
+ column_example = (
+ column_example if isinstance(column_example, str) else str(column_example)
+ ) # noqa: F821
+ persisted_column.example = truncate_long_string(column_example, 4000)
+ models.db.session.add(persisted_column)
+
+ models.db.session.commit()
+ logger.info(
+ u"task=update_sample state=finished table_name=%s runtime=%.2f",
+ table_name,
+ time.time() - start_time,
+ )
+ return sample
+
+
+@job(settings.SCHEMAS_REFRESH_QUEUE, timeout=settings.SCHEMA_REFRESH_TIME_LIMIT)
+def refresh_samples(data_source_id, table_sample_limit):
+ """
+ For a given data source, refresh the data samples stored for each
+ table. This is done for tables with no samples or samples older
+ than DAYS_AGO
+ """
+ logger.info(u"task=refresh_samples state=start ds_id=%s", data_source_id)
+ ds = models.DataSource.get_by_id(data_source_id)
+
+ if not ds.query_runner.configuration.get("samples", False):
+ return
+
+ DAYS_AGO = utils.utcnow() - datetime.timedelta(
+ days=settings.SCHEMA_SAMPLE_REFRESH_FREQUENCY_DAYS
+ )
+
+ # Find all existing tables that have an empty or old sample_updated_at
+ tables_to_sample = (
+ models.TableMetadata.query.filter(
+ models.TableMetadata.exists.is_(True),
+ models.TableMetadata.data_source_id == data_source_id,
+ or_(
+ models.TableMetadata.sample_updated_at.is_(None),
+ models.TableMetadata.sample_updated_at < DAYS_AGO,
+ ),
+ )
+ .limit(table_sample_limit)
+ .all()
+ )
+
+ tasks = []
+ for table in tables_to_sample:
+ tasks.append((ds.id, table.name, table.id, table.sample_updated_at))
+ table.sample_updated_at = models.db.func.now()
+ models.db.session.add(table)
+ models.db.session.commit()
+
+ for task_args in tasks:
+ update_sample.delay(*task_args)
+
+
+def cleanup_schema_metadata():
+ models.cleanup_data_in_table(models.TableMetadata)
+ models.cleanup_data_in_table(models.ColumnMetadata)
diff --git a/redash/tasks/schedule.py b/redash/tasks/schedule.py
index 55d0e96291..15e027942b 100644
--- a/redash/tasks/schedule.py
+++ b/redash/tasks/schedule.py
@@ -11,8 +11,10 @@
from redash.tasks import (
sync_user_details,
refresh_queries,
+ remove_ghost_locks,
empty_schedules,
refresh_schemas,
+ cleanup_schema_metadata,
cleanup_query_results,
purge_failed_jobs,
version_check,
@@ -61,6 +63,11 @@ def schedule(kwargs):
def periodic_job_definitions():
jobs = [
{"func": refresh_queries, "interval": 30, "result_ttl": 600},
+ {
+ "func": remove_ghost_locks,
+ "interval": timedelta(minutes=1),
+ "result_ttl": 600,
+ },
{"func": empty_schedules, "interval": timedelta(minutes=60)},
{
"func": refresh_schemas,
@@ -72,6 +79,7 @@ def periodic_job_definitions():
"func": send_aggregated_errors,
"interval": timedelta(minutes=settings.SEND_FAILURE_EMAIL_INTERVAL),
},
+ {"func": cleanup_schema_metadata, "interval": timedelta(days=3)},
]
if settings.VERSION_CHECK:
diff --git a/redash/tasks/worker.py b/redash/tasks/worker.py
index 19aadabfef..b1597f26ea 100644
--- a/redash/tasks/worker.py
+++ b/redash/tasks/worker.py
@@ -1,9 +1,7 @@
import errno
import os
-import signal
-import time
from redash import statsd_client
-from rq import Worker as BaseWorker, Queue as BaseQueue, get_current_job
+from rq import Worker as BaseWorker, Queue as BaseQueue
from rq.utils import utcnow
from rq.timeouts import UnixSignalDeathPenalty, HorseMonitorTimeoutException
from rq.job import Job as BaseJob, JobStatus
@@ -80,7 +78,7 @@ class HardLimitingWorker(BaseWorker):
job_class = CancellableJob
def stop_executing_job(self, job):
- os.kill(self.horse_pid, signal.SIGINT)
+ self.kill_horse()
self.log.warning("Job %s has been cancelled.", job.id)
def soft_limit_exceeded(self, job):
diff --git a/redash/templates/forgot.html b/redash/templates/forgot.html
index 54ff1bde48..f8ee82e1f4 100644
--- a/redash/templates/forgot.html
+++ b/redash/templates/forgot.html
@@ -9,6 +9,7 @@
{% else %}