Skip to content

Commit

Permalink
feat: UI override registry (#19671)
Browse files Browse the repository at this point in the history
* typed registry

* remove unintentional change

* lint

* fix
  • Loading branch information
suddjian committed Apr 14, 2022
1 parent 9425dd2 commit 4927685
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 7 deletions.
1 change: 1 addition & 0 deletions superset-frontend/packages/superset-ui-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ export * from './chart';
export * from './chart-composition';
export * from './components';
export * from './math-expression';
export * from './ui-overrides';
Original file line number Diff line number Diff line change
Expand Up @@ -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().
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
@@ -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, {});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* 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.
*/

export * from './UiOverrideRegistry';
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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 { 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');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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;
Expand Down Expand Up @@ -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>
Expand All @@ -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>
Expand Down

0 comments on commit 4927685

Please sign in to comment.