Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { PluginCustomObjectRenderers } from "../pluginCustomObjectRenderers";

const DefaultCustomObjectRenderersPlugin: PluginCustomObjectRenderers = {
init: () => {
},
get: () => {
return null;
}
}

export default DefaultCustomObjectRenderersPlugin;
8 changes: 8 additions & 0 deletions webui/src/extendable/plugins/pluginCustomObjectRenderers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from "react";
import { RendererComponent } from "../../pages/repositories/repository/fileRenderers/types";
import { ConfigType } from "../../lib/hooks/configProvider";

export interface PluginCustomObjectRenderers {
init: (config?: ConfigType) => void;
get: (contentType?: string, fileExtension?: string) => React.FC<RendererComponent> | null;
}
13 changes: 12 additions & 1 deletion webui/src/extendable/plugins/pluginManager.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import { PluginRepoCreationForm } from "./pluginRepoCreationForm";
import DefaultRepoCreationFormPlugin from "./impls/DefaultRepoCreationFormPlugin";
import { PluginCustomObjectRenderers } from "./pluginCustomObjectRenderers";
import DefaultCustomObjectRenderersPlugin from "./impls/DefaultCustomObjectRenderers";

export class PluginManager {
private _repoCreationForm: PluginRepoCreationForm = DefaultRepoCreationFormPlugin;
private _customObjectRenderers: PluginCustomObjectRenderers = DefaultCustomObjectRenderersPlugin;

overridePluginRepoCreationForm(pluginRepoCreationForm: PluginRepoCreationForm): void {
this._repoCreationForm = pluginRepoCreationForm;
}

get repoCreationForm(): PluginRepoCreationForm | null {
get repoCreationForm(): PluginRepoCreationForm {
return this._repoCreationForm;
}

overridePluginCustomObjectRenderers(pluginCustomObjectRenderers: PluginCustomObjectRenderers): void {
this._customObjectRenderers = pluginCustomObjectRenderers;
}

get customObjectRenderers(): PluginCustomObjectRenderers {
return this._customObjectRenderers;
}
}
17 changes: 15 additions & 2 deletions webui/src/lib/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,18 @@ class Objects {
return response.text()
}

async getRange(repoId, ref, path, start, end, presign = false) {
const query = qs({ path, presign });
const response = await apiRequest(`/repositories/${encodeURIComponent(repoId)}/refs/${encodeURIComponent(ref)}/objects?` + query,
{method: 'GET'},
{'Range': `bytes=${start}-${end}`}
);
if (response.status !== 200 && response.status !== 206) {
throw new Error(await extractError(response));
}
return response.text();
}

async head(repoId, ref, path) {
const query = qs({path});
const response = await apiRequest(`/repositories/${encodeURIComponent(repoId)}/refs/${encodeURIComponent(ref)}/objects?` + query, {
Expand Down Expand Up @@ -878,7 +890,7 @@ class Commits {
}

async commit(repoId, branchId, message, metadata = {}) {
const response = await apiRequest(`/repositories/${repoId}/branches/${branchId}/commits`, {
const response = await apiRequest(`/repositories/${encodeURIComponent(repoId)}/branches/${encodeURIComponent(branchId)}/commits`, {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related, but should be done.

method: 'POST',
body: JSON.stringify({message, metadata}),
});
Expand Down Expand Up @@ -1096,8 +1108,9 @@ class Config {
case 200: {
const cfg = await response.json();
const storages = buildStoragesConfigs(cfg);
const uiConfig = cfg['ui_config'];
const versionConfig = cfg['version_config'];
return {storages, versionConfig};
return {storages, uiConfig, versionConfig};
}
case 409:
throw new Error('Conflict');
Expand Down
29 changes: 24 additions & 5 deletions webui/src/lib/hooks/configProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { createContext, FC, useContext, useEffect, useState, } from "reac

import { config } from "../api";
import useUser from "./user";
import { usePluginManager } from "../../extendable/plugins/pluginsContext";

type ConfigContextType = {
error: Error | null;
Expand All @@ -10,9 +11,10 @@ type ConfigContextType = {
};

type ConfigType = {
storages: StorageConfigType[] | null;
storages?: StorageConfigType[];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also aligning style, to use the ? style.

uiConfig?: UIConfigType;
versionConfig?: VersionConfig;
}
};

type StorageConfigType = {
blockstore_namespace_ValidityRegex: string | null;
Expand All @@ -25,7 +27,19 @@ type StorageConfigType = {
pre_sign_support_ui: boolean;
};

type UIConfigType = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
type UIConfigType = {
type UIConfig = {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I'll also align StorageConfigType.

custom_viewers?: Array<CustomViewerConfig>;
};

type CustomViewerConfig = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change
type CustomViewerConfig = {
type CustomViewer = {

name: string;
url: string;
content_types?: Array<string>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we sometimes use use snake case and sometimes pascal case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The snake case is what's returned from the API as is,
The pascal case is constructed in the js code.
Since the ConfigType is built in the js (see getConfig()),
I kept it as pascal case.
If it's critical I can align, but this has some internal sense.

extensions?: Array<string>;
};

type VersionConfig = {
upgrade_recommended?: boolean;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related, but used in the code, so added here.

upgrade_url?: string;
version_context?: string;
version?: string;
Expand All @@ -42,13 +56,16 @@ const configContext = createContext<ConfigContextType>(configInitialState);
const useConfigContext = () => useContext(configContext);

const ConfigProvider: FC<{children: React.ReactNode}> = ({children}) => {
const pluginManager = usePluginManager();
const {user} = useUser();
const [storageConfig, setConfig] = useState<ConfigContextType>(configInitialState);

useEffect(() => {
config.getConfig()
.then(configData =>
setConfig({config: configData, loading: false, error: null}))
.then(configData => {
pluginManager.customObjectRenderers?.init(configData);
setConfig({config: configData, loading: false, error: null});
})
.catch((error) =>
setConfig({config: null, loading: false, error}));
}, [user]);
Expand All @@ -60,4 +77,6 @@ const ConfigProvider: FC<{children: React.ReactNode}> = ({children}) => {
);
};

export { ConfigProvider, useConfigContext };
export type { ConfigType, CustomViewerConfig };

export { ConfigProvider, useConfigContext };
24 changes: 16 additions & 8 deletions webui/src/pages/repositories/repository/fileRenderers/index.tsx
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I usually avoid file reformatting, but this one was just a little unformatted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {FC} from "react";
import React, { FC } from "react";
import SyntaxHighlighter from "react-syntax-highlighter";
import {FileType, RendererComponent} from "./types";
import {DuckDBRenderer} from "./data";
import { FileType, RendererComponent } from "./types";
import { DuckDBRenderer } from "./data";
import {
GeoJSONRenderer,
ImageRenderer,
Expand All @@ -13,19 +13,20 @@ import {
TextRenderer,
UnsupportedFileType
} from "./simple";
import { usePluginManager } from "../../../../extendable/plugins/pluginsContext";


const MAX_FILE_SIZE = 20971520; // 20MiB


export const Renderers: {[fileType in FileType] : FC<RendererComponent> } = {
export const Renderers: { [fileType in FileType]: FC<RendererComponent> } = {
[FileType.DATA]: props => (
<DuckDBRenderer {...props}/>
),
[FileType.MARKDOWN]: props => (
<TextDownloader {...props} onReady={text =>
<MarkdownRenderer {...props} text={text}/>
} />
}/>
),
[FileType.IPYNB]: props => (
<TextDownloader {...props} onReady={text =>
Expand All @@ -52,11 +53,11 @@ export const Renderers: {[fileType in FileType] : FC<RendererComponent> } = {
[FileType.GEOJSON]: props => (
<TextDownloader {...props} onReady={text =>
<GeoJSONRenderer {...props} text={text}/>
} />
}/>
),
}

export const guessLanguage = (extension: string | null, contentType: string | null) => {
export const guessLanguage = (extension: string | null, contentType: string | null) => {
switch (extension) {
case 'py':
extension = 'python'
Expand Down Expand Up @@ -178,7 +179,14 @@ export function guessType(contentType: string | null, fileExtension: string | nu
}

export const ObjectRenderer: FC<RendererComponent> = (props: RendererComponent) => {
const fileType = guessType(props.contentType, props.fileExtension)
const pluginManager = usePluginManager();

const customRenderer = pluginManager.customObjectRenderers.get(props.contentType, props.fileExtension)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The signature of get is for contentType and fileExtension is string, while their type is string | null
FWIU you should change the signature or pass undefined in case of null (i.e (props.contentType ?? undefined, props.fileExtension ?? undefined)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, apparently even IntelliJ noted about this...

Updated -
It required some more null/undefined changes in other files...

if (customRenderer) {
return customRenderer(props)
}

const fileType = guessType(props.contentType, props.fileExtension)
if (fileType !== FileType.DATA && props.sizeBytes > MAX_FILE_SIZE)
return Renderers[FileType.TOO_LARGE](props)
return Renderers[fileType](props)
Expand Down
Loading