import React, { useCallback } from "react";
import { AIIcon, EntityCollection, FireCMSPlugin, InternalUserManagement, useAuthController, useNavigationController, useTranslation } from "@firecms/core";
import { CollectionsConfigController, mergeCollections, useCollectionEditorController } from "@firecms/collection_editor";
import { AddIcon, ArticleIcon, Button, Card, cls, HistoryIcon, Typography } from "@firecms/ui";
import { ProjectConfig } from "./useBuildProjectConfig";
import { TextSearchInfoDialog } from "../components/subscriptions/TextSearchInfoDialog";
import { FireCMSAppConfig, FireCMSBackend } from "../types";
import { RootCollectionSuggestions } from "../components/RootCollectionSuggestions";
import { PermissionErrorView } from "../components/PermissionErrorView";
import { AutoSetUpCollectionsButton } from "../components/AutoSetUpCollectionsButton";
import { EnableEntityHistoryView } from "../components/EnableEntityHistoryView";
import { CollectionsSetupLoadingLabel } from "../components/CollectionsSetupLoadingLabel";
import { RootCollectionInfo } from "../api/projects";
export function useSaasPlugin({
projectConfig,
collectionConfigController,
appConfig,
userManagement,
introMode,
fireCMSBackend,
onAnalyticsEvent,
historyDefaultEnabled,
rootPathSuggestions
}: {
projectConfig: ProjectConfig;
appConfig?: FireCMSAppConfig;
userManagement: InternalUserManagement;
collectionConfigController: CollectionsConfigController;
introMode?: "new_project" | "existing_project";
fireCMSBackend: FireCMSBackend;
onAnalyticsEvent?: (event: string, data?: object) => void;
historyDefaultEnabled?: boolean;
rootPathSuggestions?: RootCollectionInfo[];
}): FireCMSPlugin {
const hasOwnTextSearchImplementation = Boolean(appConfig?.textSearchControllerBuilder);
const additionalChildrenStart = <>
>;
const additionalChildrenEnd = <>
>;
const modifyCollection = useCallback((collection: EntityCollection) => {
if (collection.history === false && !historyDefaultEnabled) {
return {
...collection,
entityViews: [
...(collection.entityViews ?? []),
{
key: "__history",
name: "History",
tabComponent: ,
Builder: EnableEntityHistoryView,
position: "start"
}
],
} satisfies EntityCollection;
}
return collection;
}, []);
const injectCollections = useCallback(
(collections: EntityCollection[]) => mergeCollections(
collections,
(collectionConfigController.collections ?? []).map(modifyCollection),
appConfig?.modifyCollection
),
[collectionConfigController.collections]);
return {
key: "saas",
homePage: {
additionalChildrenStart,
additionalChildrenEnd,
},
userManagement,
collection: {
injectCollections: projectConfig.isTrialOver ? undefined : injectCollections,
modifyCollection
},
collectionView: {
CollectionError: useCallback(({ path, collection, parentCollectionIds, error }: {
path: string;
collection: EntityCollection;
parentCollectionIds?: string[];
error: Error;
}) => {
return ;
}, [projectConfig.projectId, fireCMSBackend.projectsApi, onAnalyticsEvent]),
blockSearch: ({
context,
path,
collection,
parentCollectionIds
}) => {
return !(projectConfig.typesenseSearchConfig?.enabled || (projectConfig.localTextSearchEnabled && collection.textSearchEnabled));
},
showTextSearchBar: ({
context,
path,
collection
}) => {
if (collection.textSearchEnabled === false) {
return false;
}
return true;
},
onTextSearchClick: ({
context,
path,
collection,
parentCollectionIds
}) => {
const canSearch = projectConfig.typesenseSearchConfig?.enabled || (projectConfig.localTextSearchEnabled && collection.textSearchEnabled);
if (!canSearch) {
if (parentCollectionIds === undefined) {
console.warn("Enabling text search: Parent collection ids are undefined")
} else {
context.dialogsController.open({
key: "text_search_info",
Component: (props) =>
});
}
}
return Promise.resolve(false);
}
}
}
}
export function IntroWidget({
introMode,
fireCMSBackend,
projectConfig,
onAnalyticsEvent
}: {
introMode?: "new_project" | "existing_project";
fireCMSBackend: FireCMSBackend;
projectConfig: ProjectConfig;
onAnalyticsEvent?: (event: string, data?: object) => void;
}) {
const navigation = useNavigationController();
const collectionEditorController = useCollectionEditorController();
const authController = useAuthController();
const { t } = useTranslation();
if (!navigation.topLevelNavigation)
throw Error("Navigation not ready in FireCMSHomePage");
if (!navigation.initialised) {
return null;
}
const hasCollections = navigation.initialised &&
(navigation.collections ?? []).length > 0;
if (hasCollections) {
return null;
}
const canCreateCollections = collectionEditorController.configPermissions
? collectionEditorController.configPermissions({
user: authController.user
}).createCollections
: true;
const subtitle = introMode === "existing_project"
? t("admin_panel_ready_bring_data")
: t("admin_panel_ready_get_started");
return (
{t("welcome_to_firecms")}
{subtitle}
{introMode === "existing_project" && (
}
title={t("auto_detect_collections")}
description={t("auto_detect_collections_desc")}
>
onAnalyticsEvent?.("intro_cols_setup_click")}
onSuccess={() => onAnalyticsEvent?.("intro_cols_setup_success")}
onNoCollections={() => onAnalyticsEvent?.("intro_cols_setup_no_cols")}
onError={() => onAnalyticsEvent?.("intro_cols_setup_error")}
/>
)}
}
title={t("create_a_collection")}
description={t("create_collection_desc")}
>
{
onAnalyticsEvent?.("intro_create_collection_click");
collectionEditorController.createCollection({
parentCollectionIds: [],
redirect: true,
sourceClick: "intro_widget"
});
}}
>
{t("new_collection")}
}
title={t("read_the_docs")}
description={t("read_the_docs_desc")}
>
onAnalyticsEvent?.("intro_docs_click")}
>
{t("explore_docs")}
{t("want_to_customize_with_code")}{" "}
npx create-firecms-app
{" "}
{t("to_scaffold_a_local_project")}
);
}
function IntroCard({
icon,
title,
description,
children
}: {
icon: React.ReactNode;
title: string;
description: string;
children: React.ReactNode;
}) {
return (
{icon}
{title}
{description}
{children}
);
}
// save locally that the alert was dismissed
function saveHistoryAlertDismissed() {
localStorage.setItem("firecms_saas_alert_history_dismissed", "true");
}
function isHistoryAlertDismissed(): boolean {
return localStorage.getItem("firecms_saas_alert_history_dismissed") === "true";
}