Transfer changes from enterprise codebase
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import { mapValues } from "lodash";
|
||||
import {
|
||||
EmailIcon,
|
||||
ProfileIcon,
|
||||
@@ -40,19 +39,13 @@ import { accountPreferencesPath } from "~/utils/routeHelpers";
|
||||
import useCurrentTeam from "./useCurrentTeam";
|
||||
import usePolicy from "./usePolicy";
|
||||
|
||||
type SettingsGroups = "Account" | "Workspace" | "Integrations";
|
||||
|
||||
export type ConfigItem = {
|
||||
name: string;
|
||||
path: string;
|
||||
icon: React.FC<any>;
|
||||
component: () => JSX.Element;
|
||||
component: React.ComponentType<any>;
|
||||
enabled: boolean;
|
||||
group: SettingsGroups;
|
||||
};
|
||||
|
||||
type ConfigType = {
|
||||
[key in string]: ConfigItem;
|
||||
group: string;
|
||||
};
|
||||
|
||||
const useSettingsConfig = () => {
|
||||
@@ -60,9 +53,9 @@ const useSettingsConfig = () => {
|
||||
const can = usePolicy(team);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const config: ConfigType = React.useMemo(
|
||||
() => ({
|
||||
Profile: {
|
||||
const config = React.useMemo(() => {
|
||||
const items: ConfigItem[] = [
|
||||
{
|
||||
name: t("Profile"),
|
||||
path: "/settings",
|
||||
component: Profile,
|
||||
@@ -70,7 +63,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Account"),
|
||||
icon: ProfileIcon,
|
||||
},
|
||||
Preferences: {
|
||||
{
|
||||
name: t("Preferences"),
|
||||
path: accountPreferencesPath(),
|
||||
component: Preferences,
|
||||
@@ -78,7 +71,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Account"),
|
||||
icon: SettingsIcon,
|
||||
},
|
||||
Notifications: {
|
||||
{
|
||||
name: t("Notifications"),
|
||||
path: "/settings/notifications",
|
||||
component: Notifications,
|
||||
@@ -86,7 +79,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Account"),
|
||||
icon: EmailIcon,
|
||||
},
|
||||
Api: {
|
||||
{
|
||||
name: t("API Tokens"),
|
||||
path: "/settings/tokens",
|
||||
component: ApiKeys,
|
||||
@@ -95,7 +88,7 @@ const useSettingsConfig = () => {
|
||||
icon: CodeIcon,
|
||||
},
|
||||
// Team group
|
||||
Details: {
|
||||
{
|
||||
name: t("Details"),
|
||||
path: "/settings/details",
|
||||
component: Details,
|
||||
@@ -103,7 +96,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Workspace"),
|
||||
icon: TeamIcon,
|
||||
},
|
||||
Security: {
|
||||
{
|
||||
name: t("Security"),
|
||||
path: "/settings/security",
|
||||
component: Security,
|
||||
@@ -111,7 +104,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Workspace"),
|
||||
icon: PadlockIcon,
|
||||
},
|
||||
Features: {
|
||||
{
|
||||
name: t("Features"),
|
||||
path: "/settings/features",
|
||||
component: Features,
|
||||
@@ -119,7 +112,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Workspace"),
|
||||
icon: BeakerIcon,
|
||||
},
|
||||
Members: {
|
||||
{
|
||||
name: t("Members"),
|
||||
path: "/settings/members",
|
||||
component: Members,
|
||||
@@ -127,7 +120,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Workspace"),
|
||||
icon: UserIcon,
|
||||
},
|
||||
Groups: {
|
||||
{
|
||||
name: t("Groups"),
|
||||
path: "/settings/groups",
|
||||
component: Groups,
|
||||
@@ -135,7 +128,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Workspace"),
|
||||
icon: GroupIcon,
|
||||
},
|
||||
Shares: {
|
||||
{
|
||||
name: t("Shared Links"),
|
||||
path: "/settings/shares",
|
||||
component: Shares,
|
||||
@@ -143,7 +136,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Workspace"),
|
||||
icon: LinkIcon,
|
||||
},
|
||||
Import: {
|
||||
{
|
||||
name: t("Import"),
|
||||
path: "/settings/import",
|
||||
component: Import,
|
||||
@@ -151,7 +144,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Workspace"),
|
||||
icon: ImportIcon,
|
||||
},
|
||||
Export: {
|
||||
{
|
||||
name: t("Export"),
|
||||
path: "/settings/export",
|
||||
component: Export,
|
||||
@@ -159,20 +152,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Workspace"),
|
||||
icon: ExportIcon,
|
||||
},
|
||||
// Integrations
|
||||
...mapValues(
|
||||
PluginLoader.plugins,
|
||||
(plugin) =>
|
||||
({
|
||||
name: plugin.config.name,
|
||||
path: integrationSettingsPath(plugin.id),
|
||||
group: t("Integrations"),
|
||||
component: plugin.settings,
|
||||
enabled: !!plugin.settings && can.update,
|
||||
icon: plugin.icon,
|
||||
} as ConfigItem)
|
||||
),
|
||||
SelfHosted: {
|
||||
{
|
||||
name: t("Self Hosted"),
|
||||
path: integrationSettingsPath("self-hosted"),
|
||||
component: SelfHosted,
|
||||
@@ -180,7 +160,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Integrations"),
|
||||
icon: BuildingBlocksIcon,
|
||||
},
|
||||
GoogleAnalytics: {
|
||||
{
|
||||
name: t("Google Analytics"),
|
||||
path: integrationSettingsPath("google-analytics"),
|
||||
component: GoogleAnalytics,
|
||||
@@ -188,7 +168,7 @@ const useSettingsConfig = () => {
|
||||
group: t("Integrations"),
|
||||
icon: GoogleIcon,
|
||||
},
|
||||
Zapier: {
|
||||
{
|
||||
name: "Zapier",
|
||||
path: integrationSettingsPath("zapier"),
|
||||
component: Zapier,
|
||||
@@ -196,21 +176,34 @@ const useSettingsConfig = () => {
|
||||
group: t("Integrations"),
|
||||
icon: ZapierIcon,
|
||||
},
|
||||
}),
|
||||
[t, can.createApiKey, can.update, can.createImport, can.createExport]
|
||||
);
|
||||
];
|
||||
|
||||
const enabledConfigs = React.useMemo(
|
||||
() =>
|
||||
Object.keys(config).reduce(
|
||||
(acc, key: string) =>
|
||||
config[key].enabled ? [...acc, config[key]] : acc,
|
||||
[]
|
||||
),
|
||||
[config]
|
||||
);
|
||||
// Plugins
|
||||
Object.values(PluginLoader.plugins).map((plugin) => {
|
||||
const hasSettings = !!plugin.settings;
|
||||
const enabledInDeployment =
|
||||
!plugin.config.deployments ||
|
||||
plugin.config.deployments.length === 0 ||
|
||||
(plugin.config.deployments.includes("cloud") && isCloudHosted) ||
|
||||
(plugin.config.deployments.includes("enterprise") && !isCloudHosted);
|
||||
|
||||
return enabledConfigs;
|
||||
const item = {
|
||||
name: t(plugin.config.name),
|
||||
path: integrationSettingsPath(plugin.id),
|
||||
group: plugin.id === "collections" ? t("Workspace") : t("Integrations"),
|
||||
component: plugin.settings,
|
||||
enabled: enabledInDeployment && hasSettings && can.update,
|
||||
icon: plugin.icon,
|
||||
} as ConfigItem;
|
||||
|
||||
const insertIndex = items.findIndex((i) => i.group === t("Integrations"));
|
||||
items.splice(insertIndex, 0, item);
|
||||
});
|
||||
|
||||
return items;
|
||||
}, [t, can.createApiKey, can.update, can.createImport, can.createExport]);
|
||||
|
||||
return config.filter((item) => item.enabled);
|
||||
};
|
||||
|
||||
export default useSettingsConfig;
|
||||
|
||||
@@ -239,7 +239,7 @@ function CollectionMenu({
|
||||
{
|
||||
type: "button",
|
||||
title: `${t("Export")}…`,
|
||||
visible: !!(collection && canUserInTeam.createExport),
|
||||
visible: !!(collection && canUserInTeam.createExport && can.export),
|
||||
onClick: handleExport,
|
||||
icon: <ExportIcon />,
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import invariant from "invariant";
|
||||
import { concat, find, last } from "lodash";
|
||||
import { concat, find, last, sortBy } from "lodash";
|
||||
import { computed, action } from "mobx";
|
||||
import {
|
||||
CollectionPermission,
|
||||
@@ -50,9 +50,12 @@ export default class CollectionsStore extends BaseStore<Collection> {
|
||||
@computed
|
||||
get orderedData(): Collection[] {
|
||||
let collections = Array.from(this.data.values());
|
||||
collections = collections.filter((collection) =>
|
||||
collection.deletedAt ? false : true
|
||||
);
|
||||
collections = collections
|
||||
.filter((collection) => !collection.deletedAt)
|
||||
.filter(
|
||||
(collection) =>
|
||||
this.rootStore.policies.abilities(collection.id).readDocument
|
||||
);
|
||||
return collections.sort((a, b) => {
|
||||
if (a.index === b.index) {
|
||||
return a.updatedAt > b.updatedAt ? -1 : 1;
|
||||
@@ -62,6 +65,14 @@ export default class CollectionsStore extends BaseStore<Collection> {
|
||||
});
|
||||
}
|
||||
|
||||
@computed
|
||||
get all(): Collection[] {
|
||||
return sortBy(
|
||||
Array.from(this.data.values()),
|
||||
(collection) => collection.name
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* List of paths to each of the documents, where paths are composed of id and title/name pairs
|
||||
*/
|
||||
|
||||
@@ -6,6 +6,7 @@ interface Plugin {
|
||||
name: string;
|
||||
description: string;
|
||||
requiredEnvVars?: string[];
|
||||
deployments?: string[];
|
||||
};
|
||||
settings: React.FC;
|
||||
icon: React.FC<{ size?: number; fill?: string }>;
|
||||
|
||||
@@ -92,7 +92,7 @@ allow(User, "share", Collection, (user, collection) => {
|
||||
return true;
|
||||
});
|
||||
|
||||
allow(User, "readDocument", Collection, (user, collection) => {
|
||||
allow(User, ["readDocument", "export"], Collection, (user, collection) => {
|
||||
if (!collection || user.teamId !== collection.teamId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -576,7 +576,7 @@ router.post(
|
||||
const collection = await Collection.scope({
|
||||
method: ["withMembership", user.id],
|
||||
}).findByPk(id);
|
||||
authorize(user, "read", collection);
|
||||
authorize(user, "export", collection);
|
||||
|
||||
const fileOperation = await sequelize.transaction(async (transaction) =>
|
||||
collectionExporter({
|
||||
|
||||
@@ -320,8 +320,8 @@
|
||||
"Groups": "Groups",
|
||||
"Shared Links": "Shared Links",
|
||||
"Import": "Import",
|
||||
"Integrations": "Integrations",
|
||||
"Self Hosted": "Self Hosted",
|
||||
"Integrations": "Integrations",
|
||||
"Google Analytics": "Google Analytics",
|
||||
"Revoke token": "Revoke token",
|
||||
"Revoke": "Revoke",
|
||||
|
||||
Reference in New Issue
Block a user