@@ -62,27 +62,27 @@ export default function DetailedProvider() {
)}
- {entry.productDescription.map((prod, index) =>
+ {entry.productDescription.map((prod, index) =>
{prod.category}
-
+
{prod.shortDescription}
-
- {prod.section.image ?

:
}
-
-
-
-
-
- {prod.section.description}
-
-
+
+ {prod.section.image ?

:
}
+
+
+
+
+
+ {prod.section.description}
+
+
diff --git a/frontend-web/webclient/app/Providers/Overview.tsx b/frontend-web/webclient/app/Providers/Overview.tsx
index da018b3a00..7d377f1964 100644
--- a/frontend-web/webclient/app/Providers/Overview.tsx
+++ b/frontend-web/webclient/app/Providers/Overview.tsx
@@ -12,8 +12,9 @@ import {CardClass} from "@/ui-components/Card";
import {SidebarTabId} from "@/ui-components/SidebarComponents";
import {ProviderBranding} from "@/UCloud/ProviderBrandingApi";
import {useSelector} from "react-redux";
+import {providerBrandingStore} from "@/ProviderBrandings/AutomaticProviderBranding";
-export function ProviderEntry(props: { provider: ProviderBranding }): React.ReactNode {
+export function ProviderEntry(props: {provider: ProviderBranding}): React.ReactNode {
if (!props.provider.id || !props.provider.title) return null;
return (
@@ -21,11 +22,11 @@ export function ProviderEntry(props: { provider: ProviderBranding }): React.Reac
-
+
-
+
@@ -36,9 +37,9 @@ export function ProviderEntry(props: { provider: ProviderBranding }): React.Reac
);
}
-function useProviderBrandings(): Record
| undefined {
- const data = useSelector((it: ReduxObject) => it.providerBrandings);
- return data.providers;
+export function useProviderBrandings(): Record | undefined {
+ const providers = React.useSyncExternalStore(sub => providerBrandingStore.subscribe(sub), () => providerBrandingStore.getSnapshot());
+ return providers.providers;
}
export default function ProviderOverview() {
@@ -51,20 +52,20 @@ export default function ProviderOverview() {
const main =
{Object.values(providers).map(provider =>
-
+
)}
if (!Client.isLoggedIn) return (<>
-
-
+
+
{main}
>);
- return ();
+ return ();
}
const ProviderCard = injectStyle("provider-card", k => `
diff --git a/frontend-web/webclient/app/Providers/ProviderLogo.tsx b/frontend-web/webclient/app/Providers/ProviderLogo.tsx
index 91c2c2bb47..4f7551373b 100644
--- a/frontend-web/webclient/app/Providers/ProviderLogo.tsx
+++ b/frontend-web/webclient/app/Providers/ProviderLogo.tsx
@@ -1,21 +1,26 @@
import * as React from "react";
import {Image} from "@/ui-components";
-import ProviderInfo from "@/Assets/provider_info.json";
import {classConcat} from "@/Unstyled";
import {injectStyle} from "@/Unstyled";
import {TooltipV2} from "@/ui-components/Tooltip";
import {getProviderTitle} from "@/Providers/ProviderTitle";
+import {providerBrandingStore} from "@/ProviderBrandings/AutomaticProviderBranding";
export function providerLogoPath(providerId: string): string {
- const logo = ProviderInfo.providers.find(p => p.id === providerId)?.logo ?? "";
+ const logo = providerBrandingStore.getProviderProperty(providerId, "logo");
if (logo) return `/Images/${logo}`;
return "";
}
export const ProviderLogo: React.FunctionComponent<{providerId: string; size: number; className?: string;}> = ({providerId, size, className}) => {
- const myInfo = ProviderInfo.providers.find(p => p.id === providerId);
+ const [logo, title] = [
+ providerBrandingStore.getProviderProperty(providerId, "logo"),
+ providerBrandingStore.getProviderProperty(providerId, "title")
+ ];
+
+
return
- {!myInfo ? (providerId[0] ?? "?").toUpperCase() : }
+ {!logo ? (providerId[0] ?? "?").toUpperCase() : }
};
diff --git a/frontend-web/webclient/app/Providers/ProviderTitle.tsx b/frontend-web/webclient/app/Providers/ProviderTitle.tsx
index 301a10cd19..5faaab055f 100644
--- a/frontend-web/webclient/app/Providers/ProviderTitle.tsx
+++ b/frontend-web/webclient/app/Providers/ProviderTitle.tsx
@@ -1,25 +1,16 @@
import * as React from "react";
-import ProviderInfo from "@/Assets/provider_info.json";
import {capitalized} from "@/UtilityFunctions";
-
-interface ProviderInfo {
- id: string;
- title: string;
- logo: string | null;
- shortTitle: string;
-}
+import {providerBrandingStore} from "@/ProviderBrandings/AutomaticProviderBranding";
export const ProviderTitle: React.FunctionComponent<{providerId: string}> = ({providerId}) => {
return <>{getProviderTitle(providerId)}>;
};
export function getProviderTitle(providerId: string): string {
- const providers: ProviderInfo[] = ProviderInfo.providers;
- const myInfo = providers.find(p => p.id === providerId);
- return myInfo?.title ?? capitalized(providerId.replace("_", " ").replace("-", " "));
+ const title = providerBrandingStore.getProviderProperty(providerId, "title");
+ return title ?? capitalized(providerId.replace("_", " ").replace("-", " "));
}
export function getShortProviderTitle(providerId: string): string {
- const providers: ProviderInfo[] = ProviderInfo.providers;
- const myInfo = providers.find(p => p.id === providerId);
- return myInfo?.shortTitle ?? capitalized(providerId.replace("_", " ").replace("-", " "));
+ const shortTitle = providerBrandingStore.getProviderProperty(providerId, "shortTitle");
+ return shortTitle ?? capitalized(providerId.replace("_", " ").replace("-", " "));
}
diff --git a/frontend-web/webclient/app/UCloud/ProviderBrandingApi.tsx b/frontend-web/webclient/app/UCloud/ProviderBrandingApi.tsx
index fa4f51da4e..e7819ea119 100644
--- a/frontend-web/webclient/app/UCloud/ProviderBrandingApi.tsx
+++ b/frontend-web/webclient/app/UCloud/ProviderBrandingApi.tsx
@@ -35,5 +35,4 @@ export class ProviderBrandingApi {
}
}
-const providerBrandingApi = new ProviderBrandingApi();
-export { providerBrandingApi };
\ No newline at end of file
+export const providerBrandingApi = new ProviderBrandingApi();
\ No newline at end of file
diff --git a/frontend-web/webclient/app/Utilities/ReduxUtilities.tsx b/frontend-web/webclient/app/Utilities/ReduxUtilities.tsx
index 7a2d68b4a0..25e6f369dd 100644
--- a/frontend-web/webclient/app/Utilities/ReduxUtilities.tsx
+++ b/frontend-web/webclient/app/Utilities/ReduxUtilities.tsx
@@ -11,7 +11,6 @@ import {popInReducer} from "@/ui-components/PopIn";
import {sidebarReducer} from "@/Applications/Redux/Reducer";
import {EnhancedStore, PayloadAction, ReducersMapObject, configureStore} from "@reduxjs/toolkit";
import {noopCall} from "@/Authentication/DataHook";
-import {providerBrandingReducer} from "@/ProviderBrandings/AutomaticProviderBranding";
import {brandingReducer} from "@/Applications/Branding/AutomaticBranding";
export const CONTEXT_SWITCH = "CONTEXT_SWITCH";
@@ -45,7 +44,6 @@ export const store = confStore(initObject(), {
sidebar: sidebarReducer,
avatar: avatarReducer,
terminal: terminalReducer,
- providerBrandings: providerBrandingReducer,
branding: brandingReducer,
project: ProjectRedux.reducer,
popinChild: popInReducer,
diff --git a/frontend-web/webclient/app/UtilityFunctions.tsx b/frontend-web/webclient/app/UtilityFunctions.tsx
index d472bb667f..c6faa1e6c6 100644
--- a/frontend-web/webclient/app/UtilityFunctions.tsx
+++ b/frontend-web/webclient/app/UtilityFunctions.tsx
@@ -66,16 +66,6 @@ export type ExtensionType =
| "markdown"
| "application";
-export const commonFileExtensions = [
- "app", "application", "md", "markdown", "markdown", "zig", "swift", "kt", "kts", "js", "jsx", "ts", "tsx",
- "java", "py", "python", "tex", "r", "c", "h", "cc", "hh", "c++", "h++", "hpp", "cpp", "cxx", "jai", "hxx",
- "html", "htm", "lhs", "hs", "sql", "sh", "iol", "ol", "col", "bib", "toc", "jar", "exe", "xml", "json",
- "yml", "ini", "sbatch", "code", "png", "gif", "tiff", "eps", "ppm", "svg", "jpg", "jpeg", "image", "txt",
- "doc", "docx", "log", "csv", "tsv", "plist", "out", "err", "text", "pdf", "pdf", "wav", "mp3", "ogg", "aac",
- "pcm", "audio", "mpg", "mp4", "avi", "mov", "wmv", "video", "gz", "zip", "tar", "tgz", "tbz", "bz2", "archive",
- "dat", "binary", "rs",
-];
-
const languages = {
"md": "markdown",
"kt": "kotlin",
diff --git a/frontend-web/webclient/app/ui-components/ResourceBrowser.tsx b/frontend-web/webclient/app/ui-components/ResourceBrowser.tsx
index 861e4d8db9..13a8abed21 100644
--- a/frontend-web/webclient/app/ui-components/ResourceBrowser.tsx
+++ b/frontend-web/webclient/app/ui-components/ResourceBrowser.tsx
@@ -32,7 +32,6 @@ import {createPortal} from "react-dom";
import {ProjectSwitcher, FilterInputClass, projectCache, fetchProjects} from "@/Project/ProjectSwitcher";
import {addProjectListener, removeProjectListener} from "@/Project/ReduxState";
import {ProductType, ProductV2} from "@/Accounting";
-import ProviderInfo from "@/Assets/provider_info.json";
import {ProductSelector} from "@/Products/Selector";
import {Client} from "@/Authentication/HttpClientInstance";
import {divHtml, divText, image} from "@/Utilities/HTMLUtilities";
@@ -50,7 +49,7 @@ import {noopCall} from "@/Authentication/DataHook";
import {injectResourceBrowserStyle, ShortcutClass} from "./ResourceBrowserStyle";
import {ASC, DESC, Filter, FilterCheckbox, FilterInput, FilterOption, FilterWithOptions, MultiOption, MultiOptionFilter, SORT_BY, SORT_DIRECTION} from "./ResourceBrowserFilters";
import {sendInformationNotification} from "@/Notifications";
-import {UFile} from "@/UCloud/UFile";
+import {providerBrandingStore} from "@/ProviderBrandings/AutomaticProviderBranding";
import ReactClient from "react-dom/client";
import {VmActionItem, VmActionSplitButton} from "@/Applications/Jobs/VmActionSplitButton";
@@ -3733,8 +3732,8 @@ export function resourceCreationWithProductSelector(
return {startCreation, cancelCreation, portal};
}
-export function providerIcon(providerId: string, opts?: Partial, logo?: string): HTMLElement {
- const myInfo: {logo: string} | undefined = logo ? {logo} : ProviderInfo.providers.find(p => p.id === providerId);
+export function providerIcon(providerId: string, opts?: Partial, providedLogo?: string): HTMLElement {
+ const logo = providedLogo ?? providerBrandingStore.getProviderProperty(providerId, "logo");
const outer = divHtml("");
outer.className = "provider-icon"
outer.style.background = "var(--secondaryMain)";
@@ -3748,9 +3747,9 @@ export function providerIcon(providerId: string, opts?: Partial
-
>