You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by su...@apache.org on 2022/04/14 15:44:43 UTC

[superset] branch master updated: feat: UI override registry (#19671)

This is an automated email from the ASF dual-hosted git repository.

suddjian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 4927685c30 feat: UI override registry (#19671)
4927685c30 is described below

commit 4927685c3059c0207713bceeea7c60f1f3b75ec3
Author: David Aaron Suddjian <18...@users.noreply.github.com>
AuthorDate: Thu Apr 14 08:44:26 2022 -0700

    feat: UI override registry (#19671)
    
    * typed registry
    
    * remove unintentional change
    
    * lint
    
    * fix
---
 .../packages/superset-ui-core/src/index.ts         |  1 +
 .../superset-ui-core/src/models/Registry.ts        |  4 ++
 .../superset-ui-core/src/models/TypedRegistry.ts   | 60 ++++++++++++++++++++++
 .../packages/superset-ui-core/src/models/index.ts  |  1 +
 .../src/ui-overrides/UiOverrideRegistry.ts         | 46 +++++++++++++++++
 .../{models/index.ts => ui-overrides/index.tsx}    |  7 +--
 .../index.ts => test/models/TypedRegistry.test.ts} | 22 +++++---
 .../components/DashboardEmbedControls.tsx          | 27 +++++++---
 8 files changed, 150 insertions(+), 18 deletions(-)

diff --git a/superset-frontend/packages/superset-ui-core/src/index.ts b/superset-frontend/packages/superset-ui-core/src/index.ts
index 23d972fc9a..2a53112f6f 100644
--- a/superset-frontend/packages/superset-ui-core/src/index.ts
+++ b/superset-frontend/packages/superset-ui-core/src/index.ts
@@ -35,3 +35,4 @@ export * from './chart';
 export * from './chart-composition';
 export * from './components';
 export * from './math-expression';
+export * from './ui-overrides';
diff --git a/superset-frontend/packages/superset-ui-core/src/models/Registry.ts b/superset-frontend/packages/superset-ui-core/src/models/Registry.ts
index 7bf7f175cb..90a8065e29 100644
--- a/superset-frontend/packages/superset-ui-core/src/models/Registry.ts
+++ b/superset-frontend/packages/superset-ui-core/src/models/Registry.ts
@@ -59,6 +59,10 @@ export interface RegistryConfig {
 /**
  * Registry class
  *
+ * !!!!!!!!
+ * IF YOU ARE ADDING A NEW REGISTRY TO SUPERSET, CONSIDER USING TypedRegistry
+ * !!!!!!!!
+ *
  * Can use generic to specify type of item in the registry
  * @type V Type of value
  * @type W Type of value returned from loader function when using registerLoader().
diff --git a/superset-frontend/packages/superset-ui-core/src/models/TypedRegistry.ts b/superset-frontend/packages/superset-ui-core/src/models/TypedRegistry.ts
new file mode 100644
index 0000000000..80e32167f5
--- /dev/null
+++ b/superset-frontend/packages/superset-ui-core/src/models/TypedRegistry.ts
@@ -0,0 +1,60 @@
+/**
+ * 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.
+ */
+
+/**
+ * A Registry which serves as a typed key:value store for Superset and for Plugins.
+ *
+ * Differences from the older Registry class:
+ *
+ * 1. The keys and values stored in this class are individually typed by TYPEMAP parameter.
+ *    In the old Registry, all values are of the same type and keys are not enumerated.
+ *    Though you can also use indexed or mapped types in a TYPEMAP.
+ *
+ * 2. This class does not have a separate async get and set methods or use loaders.
+ *    Instead, TYPEMAP should specify async values and loaders explicitly when needed.
+ *    The value can be anything! A string, a class, a function, an async function... anything!
+ *
+ * 3. This class does not implement Policies, that is a separate concern to be handled elsewhere.
+ *
+ *
+ * Removing or altering types in a type map could be a potential breaking change, be careful!
+ *
+ * Listener methods have not been added because there isn't a use case yet.
+ */
+class TypedRegistry<TYPEMAP extends {}> {
+  name = 'TypedRegistry';
+
+  private records: TYPEMAP;
+
+  constructor(initialRecords: TYPEMAP) {
+    this.records = initialRecords;
+  }
+
+  get<K extends keyof TYPEMAP>(key: K): TYPEMAP[K] {
+    // The type construction above means that when you call this function,
+    // you get a really specific type back.
+    return this.records[key];
+  }
+
+  set<K extends keyof TYPEMAP>(key: K, value: TYPEMAP[K]) {
+    this.records[key] = value;
+  }
+}
+
+export default TypedRegistry;
diff --git a/superset-frontend/packages/superset-ui-core/src/models/index.ts b/superset-frontend/packages/superset-ui-core/src/models/index.ts
index 10d46c2a7e..365ed391d3 100644
--- a/superset-frontend/packages/superset-ui-core/src/models/index.ts
+++ b/superset-frontend/packages/superset-ui-core/src/models/index.ts
@@ -21,3 +21,4 @@ export { default as Plugin } from './Plugin';
 export { default as Preset } from './Preset';
 export { default as Registry, OverwritePolicy } from './Registry';
 export { default as RegistryWithDefaultKey } from './RegistryWithDefaultKey';
+export { default as TypedRegistry } from './TypedRegistry';
diff --git a/superset-frontend/packages/superset-ui-core/src/ui-overrides/UiOverrideRegistry.ts b/superset-frontend/packages/superset-ui-core/src/ui-overrides/UiOverrideRegistry.ts
new file mode 100644
index 0000000000..fb74ae1ece
--- /dev/null
+++ b/superset-frontend/packages/superset-ui-core/src/ui-overrides/UiOverrideRegistry.ts
@@ -0,0 +1,46 @@
+/**
+ * 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 { TypedRegistry } from '../models';
+import { makeSingleton } from '../utils';
+
+/** A function (or component) which returns text (or marked-up text) */
+type UiGeneratorText<P = void> = (props: P) => string | React.ReactElement;
+
+/**
+ * This type defines all the UI override options which replace elements of Superset's default UI.
+ * Idea with the keys here is generally to namespace following the form of 'domain.functonality.item'
+ *
+ * When defining a new option here, take care to keep any parameters to functions (or components) minimal.
+ * Any removal or alteration to a parameter will be considered a breaking change.
+ */
+export type UiOverrides = Partial<{
+  'embedded.documentation.description': UiGeneratorText;
+  'embedded.documentation.url': string;
+}>;
+
+/**
+ * A registry containing UI customizations to replace elements of Superset's default UI.
+ */
+class UiOverrideRegistry extends TypedRegistry<UiOverrides> {
+  name = 'UiOverrideRegistry';
+}
+
+export const getUiOverrideRegistry = makeSingleton(UiOverrideRegistry, {});
diff --git a/superset-frontend/packages/superset-ui-core/src/models/index.ts b/superset-frontend/packages/superset-ui-core/src/ui-overrides/index.tsx
similarity index 72%
copy from superset-frontend/packages/superset-ui-core/src/models/index.ts
copy to superset-frontend/packages/superset-ui-core/src/ui-overrides/index.tsx
index 10d46c2a7e..d59afc216f 100644
--- a/superset-frontend/packages/superset-ui-core/src/models/index.ts
+++ b/superset-frontend/packages/superset-ui-core/src/ui-overrides/index.tsx
@@ -16,8 +16,5 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-export { default as ExtensibleFunction } from './ExtensibleFunction';
-export { default as Plugin } from './Plugin';
-export { default as Preset } from './Preset';
-export { default as Registry, OverwritePolicy } from './Registry';
-export { default as RegistryWithDefaultKey } from './RegistryWithDefaultKey';
+
+export * from './UiOverrideRegistry';
diff --git a/superset-frontend/packages/superset-ui-core/src/models/index.ts b/superset-frontend/packages/superset-ui-core/test/models/TypedRegistry.test.ts
similarity index 68%
copy from superset-frontend/packages/superset-ui-core/src/models/index.ts
copy to superset-frontend/packages/superset-ui-core/test/models/TypedRegistry.test.ts
index 10d46c2a7e..7eb0d88f9d 100644
--- a/superset-frontend/packages/superset-ui-core/src/models/index.ts
+++ b/superset-frontend/packages/superset-ui-core/test/models/TypedRegistry.test.ts
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -16,8 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-export { default as ExtensibleFunction } from './ExtensibleFunction';
-export { default as Plugin } from './Plugin';
-export { default as Preset } from './Preset';
-export { default as Registry, OverwritePolicy } from './Registry';
-export { default as RegistryWithDefaultKey } from './RegistryWithDefaultKey';
+
+import { TypedRegistry } from '@superset-ui/core';
+
+describe('TypedRegistry', () => {
+  it('gets a value', () => {
+    const reg = new TypedRegistry({ foo: 'bar' });
+    expect(reg.get('foo')).toBe('bar');
+  });
+
+  it('sets a value', () => {
+    const reg = new TypedRegistry({ foo: 'bar' });
+    reg.set('foo', 'blah');
+    expect(reg.get('foo')).toBe('blah');
+  });
+});
diff --git a/superset-frontend/src/dashboard/components/DashboardEmbedControls.tsx b/superset-frontend/src/dashboard/components/DashboardEmbedControls.tsx
index d20cc24600..a2c44f4902 100644
--- a/superset-frontend/src/dashboard/components/DashboardEmbedControls.tsx
+++ b/superset-frontend/src/dashboard/components/DashboardEmbedControls.tsx
@@ -17,7 +17,13 @@
  * under the License.
  */
 import React, { useCallback, useEffect, useState } from 'react';
-import { makeApi, styled, SupersetApiError, t } from '@superset-ui/core';
+import {
+  makeApi,
+  styled,
+  SupersetApiError,
+  t,
+  getUiOverrideRegistry,
+} from '@superset-ui/core';
 import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
 import Modal from 'src/components/Modal';
 import Loading from 'src/components/Loading';
@@ -27,6 +33,8 @@ import { useToasts } from 'src/components/MessageToasts/withToasts';
 import { FormItem } from 'src/components/Form';
 import { EmbeddedDashboard } from '../types';
 
+const uiOverrideRegistry = getUiOverrideRegistry();
+
 type Props = {
   dashboardId: string;
   show: boolean;
@@ -140,6 +148,13 @@ export const DashboardEmbedControls = ({ dashboardId, onHide }: Props) => {
     return <Loading />;
   }
 
+  const docsDescription = uiOverrideRegistry.get(
+    'embedded.documentation.description',
+  );
+  const docsUrl =
+    uiOverrideRegistry.get('embedded.documentation.url') ??
+    'https://www.npmjs.com/package/@superset-ui/embedded-sdk';
+
   return (
     <>
       <p>
@@ -159,12 +174,10 @@ export const DashboardEmbedControls = ({ dashboardId, onHide }: Props) => {
       </p>
       <p>
         {t('For further instructions, consult the')}{' '}
-        <a
-          href="https://www.npmjs.com/package/@superset-ui/embedded-sdk"
-          target="_blank"
-          rel="noreferrer"
-        >
-          {t('Superset Embedded SDK documentation.')}
+        <a href={docsUrl} target="_blank" rel="noreferrer">
+          {docsDescription
+            ? docsDescription()
+            : t('Superset Embedded SDK documentation.')}
         </a>
       </p>
       <h3>Settings</h3>