From 0db418895177d5d78d7bdebf3ec568365f0653f3 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Fri, 6 May 2022 14:14:26 -0700 Subject: [PATCH] feat: improve UI overrides --- CONTRIBUTING.md | 50 +++++++++++++++++++ .../src/components/UiOverride/index.tsx | 32 ++++++++++++ superset-frontend/src/preamble.ts | 3 ++ .../src/setup/setupUiOverrides.ts | 32 ++++++++++++ superset-frontend/src/setup/upgradeButton.tsx | 5 ++ .../src/views/components/MenuRight.tsx | 9 ++++ 6 files changed, 131 insertions(+) create mode 100644 superset-frontend/src/components/UiOverride/index.tsx create mode 100644 superset-frontend/src/setup/setupUiOverrides.ts create mode 100644 superset-frontend/src/setup/upgradeButton.tsx diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 738f018873433..a4a2f030ff8be 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1304,6 +1304,56 @@ The following configuration settings are available for async queries (see config More information on the async query feature can be found in [SIP-39](https://github.com/apache/superset/issues/9190). +## UI Overrides +For whatever reason, people may want to customize any area of the +frontend. Some common use cases: + +* Alter the nav (menu) bar, adding or removing items +* Inject a "well" or info bubble +* Point to internal, more specific documentation instead of the Superset docs +* Altering a modal +* Replace a page +* ... + +How to add an injection point / overridable section in the existing code? + +### Before +```jsx +
+ +
+``` + +### After +```jsx +import UiOverride from 'src/components/UiOverride'; + +
+ Override Me! + } + /> +
+``` + +How to define your overrides in your repo/environment? + +`superset-frontend/src/setup/setupUiOverrides.ts` +```js +import { getUiOverrideRegistry } from '@superset-ui/core'; +import UpgradeButton from './upgradeButton'; + +const uiOverrideRegistry = getUiOverrideRegistry(); +export default function setupUiOverrides() { + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Call `uiOverrideRegistry.set` to override things in your environment + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + uiOverrideRegistry.set('navbar.rightSection.leftOf', UpgradeButton); + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +} +``` ## Chart Parameters Chart parameters are stored as a JSON encoded string the `slices.params` column and are often referenced throughout the code as form-data. Currently the form-data is neither versioned nor typed as thus is somewhat free-formed. Note in the future there may be merit in using something like [JSON Schema](https://json-schema.org/) to both annotate and validate the JSON object in addition to using a Mypy `TypedDict` (introduced in Python 3.8) for typing the form-data in the backend. This section serves as a potential primer for that work. diff --git a/superset-frontend/src/components/UiOverride/index.tsx b/superset-frontend/src/components/UiOverride/index.tsx new file mode 100644 index 0000000000000..8984596dddc8e --- /dev/null +++ b/superset-frontend/src/components/UiOverride/index.tsx @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; + +import { getUiOverrideRegistry } from '@superset-ui/core'; + +const uiOverrideRegistry = getUiOverrideRegistry(); + +export interface uiOverrideProps { + name: string; + default?: null; +} +export default function UIOverride(props: uiOverrideProps) { + const val = uiOverrideRegistry.get(props.name) || props.default; + return val; +} diff --git a/superset-frontend/src/preamble.ts b/superset-frontend/src/preamble.ts index ab6d696f5b727..b63d0aa851be8 100644 --- a/superset-frontend/src/preamble.ts +++ b/superset-frontend/src/preamble.ts @@ -27,6 +27,7 @@ import setupColors from './setup/setupColors'; import setupFormatters from './setup/setupFormatters'; import setupDashboardComponents from './setup/setupDasboardComponents'; import { BootstrapUser, User } from './types/bootstrapTypes'; +import setupUiOverrides from 'src/setup/setupUiOverrides'; if (process.env.WEBPACK_MODE === 'development') { setHotLoaderConfig({ logLevel: 'debug', trackTailUpdates: false }); @@ -96,3 +97,5 @@ if (bootstrapData.user?.isActive) { }); }); } + +setupUiOverrides(); diff --git a/superset-frontend/src/setup/setupUiOverrides.ts b/superset-frontend/src/setup/setupUiOverrides.ts new file mode 100644 index 0000000000000..bdfb11e72ff11 --- /dev/null +++ b/superset-frontend/src/setup/setupUiOverrides.ts @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// For individual deployments to add custom overrides + +import { getUiOverrideRegistry } from '@superset-ui/core'; +import UpgradeButton from './upgradeButton'; + +const uiOverrideRegistry = getUiOverrideRegistry(); +export default function setupUiOverrides() { + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // Call `uiOverrideRegistry.set` to override things in your environment + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + uiOverrideRegistry.set('navbar.rightSection.leftOf', UpgradeButton); + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +} diff --git a/superset-frontend/src/setup/upgradeButton.tsx b/superset-frontend/src/setup/upgradeButton.tsx new file mode 100644 index 0000000000000..df27dcf067030 --- /dev/null +++ b/superset-frontend/src/setup/upgradeButton.tsx @@ -0,0 +1,5 @@ +import React from 'react'; +import Button from 'src/components/Button'; + +const btn = ; +export default btn; diff --git a/superset-frontend/src/views/components/MenuRight.tsx b/superset-frontend/src/views/components/MenuRight.tsx index 1c46f6bcf079d..e414af961661b 100644 --- a/superset-frontend/src/views/components/MenuRight.tsx +++ b/superset-frontend/src/views/components/MenuRight.tsx @@ -25,10 +25,12 @@ import { css, SupersetTheme, SupersetClient, + getUiOverrideRegistry, } from '@superset-ui/core'; import { Tooltip } from 'src/components/Tooltip'; import { Link } from 'react-router-dom'; import Icons from 'src/components/Icons'; +import UiOverride from 'src/components/UiOverride'; import findPermission, { isUserAdmin } from 'src/dashboard/util/findPermission'; import { useSelector } from 'react-redux'; import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes'; @@ -246,6 +248,13 @@ const RightMenu = ({ return ( + + } + /> {canDatabase && (