mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 10:19:51 -06:00
refactor: introduce ContactsPageLayout component for improved structure
- Replace PageContentWrapper and PageHeader with a new ContactsPageLayout component in Contacts, Attributes, and Segments pages. - Simplify the layout structure and enhance code readability. - Remove unused imports and comments in safe-identifier.ts.
This commit is contained in:
@@ -2,8 +2,6 @@
|
||||
* Validates that a string is a safe identifier.
|
||||
* Safe identifiers can only contain lowercase letters, numbers, and underscores.
|
||||
* They cannot start with a number.
|
||||
*
|
||||
* This matches the validation used for survey variable names (see formbricks#5342).
|
||||
*/
|
||||
export const isSafeIdentifier = (value: string): boolean => {
|
||||
// Must start with a lowercase letter
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import { IS_FORMBRICKS_CLOUD } from "@/lib/constants";
|
||||
import { getLocale } from "@/lingodotdev/language";
|
||||
import { getTranslate } from "@/lingodotdev/server";
|
||||
import { ContactsSecondaryNavigation } from "@/modules/ee/contacts/components/contacts-secondary-navigation";
|
||||
import { ContactsPageLayout } from "@/modules/ee/contacts/components/contacts-page-layout";
|
||||
import { getContactAttributeKeys } from "@/modules/ee/contacts/lib/contact-attribute-keys";
|
||||
import { getIsContactsEnabled } from "@/modules/ee/license-check/lib/utils";
|
||||
import { getEnvironmentAuth } from "@/modules/environments/lib/utils";
|
||||
import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper";
|
||||
import { PageHeader } from "@/modules/ui/components/page-header";
|
||||
import { UpgradePrompt } from "@/modules/ui/components/upgrade-prompt";
|
||||
import { AttributesTable } from "./components/attributes-table";
|
||||
import { CreateAttributeModal } from "./components/create-attribute-modal";
|
||||
|
||||
@@ -17,7 +12,6 @@ export const AttributesPage = async ({
|
||||
params: Promise<{ environmentId: string }>;
|
||||
}) => {
|
||||
const params = await paramsProps;
|
||||
const t = await getTranslate();
|
||||
const locale = await getLocale();
|
||||
|
||||
const [{ isReadOnly }, contactAttributeKeys] = await Promise.all([
|
||||
@@ -28,46 +22,19 @@ export const AttributesPage = async ({
|
||||
const isContactsEnabled = await getIsContactsEnabled();
|
||||
|
||||
return (
|
||||
<PageContentWrapper>
|
||||
<PageHeader
|
||||
pageTitle="Contacts"
|
||||
cta={
|
||||
isContactsEnabled && !isReadOnly ? (
|
||||
<CreateAttributeModal environmentId={params.environmentId} />
|
||||
) : undefined
|
||||
}>
|
||||
<ContactsSecondaryNavigation activeId="attributes" environmentId={params.environmentId} />
|
||||
</PageHeader>
|
||||
|
||||
{isContactsEnabled ? (
|
||||
<AttributesTable
|
||||
contactAttributeKeys={contactAttributeKeys}
|
||||
isReadOnly={isReadOnly}
|
||||
environmentId={params.environmentId}
|
||||
locale={locale}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex items-center justify-center">
|
||||
<UpgradePrompt
|
||||
title={t("environments.contacts.unlock_contacts_title")}
|
||||
description={t("environments.contacts.unlock_contacts_description")}
|
||||
buttons={[
|
||||
{
|
||||
text: IS_FORMBRICKS_CLOUD ? t("common.start_free_trial") : t("common.request_trial_license"),
|
||||
href: IS_FORMBRICKS_CLOUD
|
||||
? `/environments/${params.environmentId}/settings/billing`
|
||||
: "https://formbricks.com/upgrade-self-hosting-license",
|
||||
},
|
||||
{
|
||||
text: t("common.learn_more"),
|
||||
href: IS_FORMBRICKS_CLOUD
|
||||
? `/environments/${params.environmentId}/settings/billing`
|
||||
: "https://formbricks.com/learn-more-self-hosting-license",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</PageContentWrapper>
|
||||
<ContactsPageLayout
|
||||
pageTitle="Contacts"
|
||||
activeId="attributes"
|
||||
environmentId={params.environmentId}
|
||||
isContactsEnabled={isContactsEnabled}
|
||||
isReadOnly={isReadOnly}
|
||||
cta={<CreateAttributeModal environmentId={params.environmentId} />}>
|
||||
<AttributesTable
|
||||
contactAttributeKeys={contactAttributeKeys}
|
||||
isReadOnly={isReadOnly}
|
||||
environmentId={params.environmentId}
|
||||
locale={locale}
|
||||
/>
|
||||
</ContactsPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { ReactNode } from "react";
|
||||
import { IS_FORMBRICKS_CLOUD } from "@/lib/constants";
|
||||
import { getTranslate } from "@/lingodotdev/server";
|
||||
import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper";
|
||||
import { PageHeader } from "@/modules/ui/components/page-header";
|
||||
import { UpgradePrompt } from "@/modules/ui/components/upgrade-prompt";
|
||||
import { ContactsSecondaryNavigation } from "./contacts-secondary-navigation";
|
||||
|
||||
interface ContactsPageLayoutProps {
|
||||
pageTitle: string;
|
||||
activeId: string;
|
||||
environmentId: string;
|
||||
isContactsEnabled: boolean;
|
||||
isReadOnly: boolean;
|
||||
cta?: ReactNode;
|
||||
children: ReactNode;
|
||||
upgradePromptTitle?: string;
|
||||
upgradePromptDescription?: string;
|
||||
}
|
||||
|
||||
export const ContactsPageLayout = async ({
|
||||
pageTitle,
|
||||
activeId,
|
||||
environmentId,
|
||||
isContactsEnabled,
|
||||
isReadOnly,
|
||||
cta,
|
||||
children,
|
||||
upgradePromptTitle,
|
||||
upgradePromptDescription,
|
||||
}: ContactsPageLayoutProps) => {
|
||||
const t = await getTranslate();
|
||||
|
||||
return (
|
||||
<PageContentWrapper>
|
||||
<PageHeader pageTitle={pageTitle} cta={isContactsEnabled && !isReadOnly ? cta : undefined}>
|
||||
<ContactsSecondaryNavigation activeId={activeId} environmentId={environmentId} />
|
||||
</PageHeader>
|
||||
|
||||
{isContactsEnabled ? (
|
||||
children
|
||||
) : (
|
||||
<div className="flex items-center justify-center">
|
||||
<UpgradePrompt
|
||||
title={upgradePromptTitle ?? t("environments.contacts.unlock_contacts_title")}
|
||||
description={upgradePromptDescription ?? t("environments.contacts.unlock_contacts_description")}
|
||||
buttons={[
|
||||
{
|
||||
text: IS_FORMBRICKS_CLOUD ? t("common.start_free_trial") : t("common.request_trial_license"),
|
||||
href: IS_FORMBRICKS_CLOUD
|
||||
? `/environments/${environmentId}/settings/billing`
|
||||
: "https://formbricks.com/upgrade-self-hosting-license",
|
||||
},
|
||||
{
|
||||
text: t("common.learn_more"),
|
||||
href: IS_FORMBRICKS_CLOUD
|
||||
? `/environments/${environmentId}/settings/billing`
|
||||
: "https://formbricks.com/learn-more-self-hosting-license",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</PageContentWrapper>
|
||||
);
|
||||
};
|
||||
@@ -1,15 +1,12 @@
|
||||
import { IS_FORMBRICKS_CLOUD, ITEMS_PER_PAGE } from "@/lib/constants";
|
||||
import { ITEMS_PER_PAGE } from "@/lib/constants";
|
||||
import { getTranslate } from "@/lingodotdev/server";
|
||||
import { ContactsPageLayout } from "@/modules/ee/contacts/components/contacts-page-layout";
|
||||
import { UploadContactsCSVButton } from "@/modules/ee/contacts/components/upload-contacts-button";
|
||||
import { getContactAttributeKeys } from "@/modules/ee/contacts/lib/contact-attribute-keys";
|
||||
import { getContacts } from "@/modules/ee/contacts/lib/contacts";
|
||||
import { getIsContactsEnabled, getIsQuotasEnabled } from "@/modules/ee/license-check/lib/utils";
|
||||
import { getEnvironmentAuth } from "@/modules/environments/lib/utils";
|
||||
import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper";
|
||||
import { PageHeader } from "@/modules/ui/components/page-header";
|
||||
import { UpgradePrompt } from "@/modules/ui/components/upgrade-prompt";
|
||||
import { ContactDataView } from "./components/contact-data-view";
|
||||
import { ContactsSecondaryNavigation } from "./components/contacts-secondary-navigation";
|
||||
|
||||
export const ContactsPage = async ({
|
||||
params: paramsProps,
|
||||
@@ -34,46 +31,23 @@ export const ContactsPage = async ({
|
||||
);
|
||||
|
||||
return (
|
||||
<PageContentWrapper>
|
||||
<PageHeader
|
||||
pageTitle={t("common.contacts")}
|
||||
cta={isContactsEnabled && !isReadOnly ? AddContactsButton : undefined}>
|
||||
<ContactsSecondaryNavigation activeId="contacts" environmentId={params.environmentId} />
|
||||
</PageHeader>
|
||||
|
||||
{isContactsEnabled ? (
|
||||
<ContactDataView
|
||||
key={initialContacts.length + contactAttributeKeys.length}
|
||||
environment={environment}
|
||||
itemsPerPage={ITEMS_PER_PAGE}
|
||||
contactAttributeKeys={contactAttributeKeys}
|
||||
isReadOnly={isReadOnly}
|
||||
initialContacts={initialContacts}
|
||||
hasMore={initialContacts.length >= ITEMS_PER_PAGE}
|
||||
isQuotasAllowed={isQuotasAllowed}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex items-center justify-center">
|
||||
<UpgradePrompt
|
||||
title={t("environments.contacts.unlock_contacts_title")}
|
||||
description={t("environments.contacts.unlock_contacts_description")}
|
||||
buttons={[
|
||||
{
|
||||
text: IS_FORMBRICKS_CLOUD ? t("common.start_free_trial") : t("common.request_trial_license"),
|
||||
href: IS_FORMBRICKS_CLOUD
|
||||
? `/environments/${params.environmentId}/settings/billing`
|
||||
: "https://formbricks.com/upgrade-self-hosting-license",
|
||||
},
|
||||
{
|
||||
text: t("common.learn_more"),
|
||||
href: IS_FORMBRICKS_CLOUD
|
||||
? `/environments/${params.environmentId}/settings/billing`
|
||||
: "https://formbricks.com/learn-more-self-hosting-license",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</PageContentWrapper>
|
||||
<ContactsPageLayout
|
||||
pageTitle={t("common.contacts")}
|
||||
activeId="contacts"
|
||||
environmentId={params.environmentId}
|
||||
isContactsEnabled={isContactsEnabled}
|
||||
isReadOnly={isReadOnly}
|
||||
cta={AddContactsButton}>
|
||||
<ContactDataView
|
||||
key={initialContacts.length + contactAttributeKeys.length}
|
||||
environment={environment}
|
||||
itemsPerPage={ITEMS_PER_PAGE}
|
||||
contactAttributeKeys={contactAttributeKeys}
|
||||
isReadOnly={isReadOnly}
|
||||
initialContacts={initialContacts}
|
||||
hasMore={initialContacts.length >= ITEMS_PER_PAGE}
|
||||
isQuotasAllowed={isQuotasAllowed}
|
||||
/>
|
||||
</ContactsPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { IS_FORMBRICKS_CLOUD } from "@/lib/constants";
|
||||
import { getTranslate } from "@/lingodotdev/server";
|
||||
import { ContactsSecondaryNavigation } from "@/modules/ee/contacts/components/contacts-secondary-navigation";
|
||||
import { ContactsPageLayout } from "@/modules/ee/contacts/components/contacts-page-layout";
|
||||
import { getContactAttributeKeys } from "@/modules/ee/contacts/lib/contact-attribute-keys";
|
||||
import { SegmentTable } from "@/modules/ee/contacts/segments/components/segment-table";
|
||||
import { getSegments } from "@/modules/ee/contacts/segments/lib/segments";
|
||||
import { getIsContactsEnabled } from "@/modules/ee/license-check/lib/utils";
|
||||
import { getEnvironmentAuth } from "@/modules/environments/lib/utils";
|
||||
import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper";
|
||||
import { PageHeader } from "@/modules/ui/components/page-header";
|
||||
import { UpgradePrompt } from "@/modules/ui/components/upgrade-prompt";
|
||||
import { CreateSegmentModal } from "./components/create-segment-modal";
|
||||
|
||||
export const SegmentsPage = async ({
|
||||
@@ -35,50 +31,27 @@ export const SegmentsPage = async ({
|
||||
const filteredSegments = segments.filter((segment) => !segment.isPrivate);
|
||||
|
||||
return (
|
||||
<PageContentWrapper>
|
||||
<PageHeader
|
||||
pageTitle="Contacts"
|
||||
cta={
|
||||
isContactsEnabled && !isReadOnly ? (
|
||||
<CreateSegmentModal
|
||||
environmentId={params.environmentId}
|
||||
contactAttributeKeys={contactAttributeKeys}
|
||||
segments={filteredSegments}
|
||||
/>
|
||||
) : undefined
|
||||
}>
|
||||
<ContactsSecondaryNavigation activeId="segments" environmentId={params.environmentId} />
|
||||
</PageHeader>
|
||||
|
||||
{isContactsEnabled ? (
|
||||
<SegmentTable
|
||||
segments={filteredSegments}
|
||||
<ContactsPageLayout
|
||||
pageTitle="Contacts"
|
||||
activeId="segments"
|
||||
environmentId={params.environmentId}
|
||||
isContactsEnabled={isContactsEnabled}
|
||||
isReadOnly={isReadOnly}
|
||||
cta={
|
||||
<CreateSegmentModal
|
||||
environmentId={params.environmentId}
|
||||
contactAttributeKeys={contactAttributeKeys}
|
||||
isContactsEnabled={isContactsEnabled}
|
||||
isReadOnly={isReadOnly}
|
||||
segments={filteredSegments}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex items-center justify-center">
|
||||
<UpgradePrompt
|
||||
title={t("environments.segments.unlock_segments_title")}
|
||||
description={t("environments.segments.unlock_segments_description")}
|
||||
buttons={[
|
||||
{
|
||||
text: IS_FORMBRICKS_CLOUD ? t("common.start_free_trial") : t("common.request_trial_license"),
|
||||
href: IS_FORMBRICKS_CLOUD
|
||||
? `/environments/${params.environmentId}/settings/billing`
|
||||
: "https://formbricks.com/upgrade-self-hosting-license",
|
||||
},
|
||||
{
|
||||
text: t("common.learn_more"),
|
||||
href: IS_FORMBRICKS_CLOUD
|
||||
? `/environments/${params.environmentId}/settings/billing`
|
||||
: "https://formbricks.com/learn-more-self-hosting-license",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</PageContentWrapper>
|
||||
}
|
||||
upgradePromptTitle={t("environments.segments.unlock_segments_title")}
|
||||
upgradePromptDescription={t("environments.segments.unlock_segments_description")}>
|
||||
<SegmentTable
|
||||
segments={filteredSegments}
|
||||
contactAttributeKeys={contactAttributeKeys}
|
||||
isContactsEnabled={isContactsEnabled}
|
||||
isReadOnly={isReadOnly}
|
||||
/>
|
||||
</ContactsPageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user