Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Expand Up @@ -42,7 +42,6 @@ import { getFormattedErrorMessage } from "@/lib/utils/helper";
import { useSignOut } from "@/modules/auth/hooks/use-sign-out";
import { TrialAlert } from "@/modules/ee/billing/components/trial-alert";
import { TRIAL_BASE_RESPONSE_LIMIT, TrialBannerNew } from "@/modules/ee/billing/components/trial-banner-new";
import { CreateOrganizationModal } from "@/modules/organization/components/CreateOrganizationModal";
import { ProfileAvatar } from "@/modules/ui/components/avatars";
import { Badge } from "@/modules/ui/components/badge";
import { Button } from "@/modules/ui/components/button";
Expand Down Expand Up @@ -70,7 +69,6 @@ interface NavigationProps {
isDevelopment: boolean;
membershipRole?: TOrganizationRole;
publicDomain: string;
isMultiOrgEnabled: boolean;
organizationWorkspacesLimit: number;
isLicenseActive: boolean;
isAccessControlAllowed: boolean;
Expand All @@ -86,7 +84,6 @@ export const MainNavigation = ({
isFormbricksCloud,
isDevelopment,
publicDomain,
isMultiOrgEnabled,
organizationWorkspacesLimit,
isLicenseActive,
isAccessControlAllowed,
Expand Down Expand Up @@ -232,7 +229,6 @@ export const MainNavigation = ({
const [workspaceLoadError, setWorkspaceLoadError] = useState<string | null>(null);
const [organizationLoadError, setOrganizationLoadError] = useState<string | null>(null);
const [openCreateWorkspaceModal, setOpenCreateWorkspaceModal] = useState(false);
const [openCreateOrganizationModal, setOpenCreateOrganizationModal] = useState(false);
const [openWorkspaceLimitModal, setOpenWorkspaceLimitModal] = useState(false);

const renderSwitcherError = (error: string, onRetry: () => void, retryLabel: string) => (
Expand Down Expand Up @@ -456,6 +452,7 @@ export const MainNavigation = ({

const switcherIconClasses =
"flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-slate-100 text-slate-600";
const mainNavIconClassName = "h-4 w-4 shrink-0";
const isInitialWorkspacesLoading =
isWorkspaceDropdownOpen && !hasInitializedWorkspaces && !workspaceLoadError;

Expand Down Expand Up @@ -546,7 +543,7 @@ export const MainNavigation = ({
disabled={item.disabled}
disabledMessage={item.disabled ? disabledNavigationMessage : undefined}
linkText={item.name}>
<item.icon strokeWidth={1.5} />
<item.icon className={mainNavIconClassName} strokeWidth={1.5} />
</NavigationLink>
)
)}
Expand All @@ -566,7 +563,7 @@ export const MainNavigation = ({
settingsNavigationItem.disabled ? disabledNavigationMessage : undefined
}
linkText={settingsNavigationItem.name}>
<settingsNavigationItem.icon strokeWidth={1.5} />
<settingsNavigationItem.icon className={mainNavIconClassName} strokeWidth={1.5} />
</NavigationLink>
</ul>
</li>
Expand Down Expand Up @@ -750,27 +747,17 @@ export const MainNavigation = ({
t("common.try_again")
)}
{!isLoadingOrganizations && !organizationLoadError && (
<>
<DropdownMenuGroup className="max-h-[300px] overflow-y-auto">
{organizations.map((org) => (
<DropdownMenuCheckboxItem
key={org.id}
checked={org.id === organization.id}
onClick={() => handleOrganizationChange(org.id)}
className="cursor-pointer">
{org.name}
</DropdownMenuCheckboxItem>
))}
</DropdownMenuGroup>
{isMultiOrgEnabled && (
<DropdownMenuGroup className="max-h-[300px] overflow-y-auto">
{organizations.map((org) => (
<DropdownMenuCheckboxItem
onClick={() => setOpenCreateOrganizationModal(true)}
className="w-full cursor-pointer justify-between">
<span>{t("common.create_new_organization")}</span>
<PlusIcon className="ml-2 size-4" strokeWidth={1.5} />
key={org.id}
checked={org.id === organization.id}
onClick={() => handleOrganizationChange(org.id)}
className="cursor-pointer">
{org.name}
</DropdownMenuCheckboxItem>
)}
</>
))}
</DropdownMenuGroup>
)}
<DropdownMenuSeparator />
<DropdownMenuCheckboxItem
Expand Down Expand Up @@ -871,12 +858,6 @@ export const MainNavigation = ({
isAccessControlAllowed={isAccessControlAllowed}
/>
)}
{openCreateOrganizationModal && (
<CreateOrganizationModal
open={openCreateOrganizationModal}
setOpen={setOpenCreateOrganizationModal}
/>
)}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ const SettingsNavLink = ({
};

const SectionHeader = ({
icon,
label,
isCollapsed,
isTextVisible,
Expand All @@ -167,8 +166,7 @@ const SectionHeader = ({
currentId,
onSwitcherChange,
onSwitcherOpen,
}: {
icon: React.ReactNode;
}: Readonly<{
label: string;
isCollapsed: boolean;
isTextVisible: boolean;
Expand All @@ -178,18 +176,17 @@ const SectionHeader = ({
currentId?: string;
onSwitcherChange?: (id: string) => void;
onSwitcherOpen?: () => void;
}) => {
}>) => {
if (isCollapsed) {
return <div className="mb-1 mt-3 flex justify-center px-2 text-slate-400">{icon}</div>;
return null;
}

return (
<div
className={cn(
"mb-1 mt-4 flex min-w-0 items-center gap-2 px-3",
"mb-1 mt-4 flex min-w-0 items-center gap-2 px-4",
isTextVisible ? "opacity-0" : "opacity-100"
)}>
<span className="text-slate-500">{icon}</span>
<span className="shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-500">{label}</span>
{switcherName && switcherItems && onSwitcherChange && (
<DropdownMenu onOpenChange={(open) => open && onSwitcherOpen?.()}>
Expand Down Expand Up @@ -408,7 +405,6 @@ export const SettingsSidebarContent = ({
<div className="flex flex-col overflow-y-auto">
<div>
<SectionHeader
icon={<FoldersIcon className="size-4" />}
label={t("common.workspace")}
isCollapsed={isCollapsed}
isTextVisible={isTextVisible}
Expand All @@ -424,7 +420,6 @@ export const SettingsSidebarContent = ({

<div>
<SectionHeader
icon={<Building2Icon className="size-4" />}
label={t("common.organization")}
isCollapsed={isCollapsed}
isTextVisible={isTextVisible}
Expand All @@ -439,12 +434,7 @@ export const SettingsSidebarContent = ({
</div>

<div>
<SectionHeader
icon={<UserCircleIcon className="size-4" />}
label={t("common.account")}
isCollapsed={isCollapsed}
isTextVisible={isTextVisible}
/>
<SectionHeader label={t("common.account")} isCollapsed={isCollapsed} isTextVisible={isTextVisible} />
{renderSection(accountItems)}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ export const WorkspaceLayout = async ({ layoutData, children }: WorkspaceLayoutP
isDevelopment={IS_DEVELOPMENT}
membershipRole={membership.role}
publicDomain={publicDomain}
isMultiOrgEnabled={isMultiOrgEnabled}
organizationWorkspacesLimit={organizationWorkspacesLimit}
isLicenseActive={active}
isAccessControlAllowed={isAccessControlAllowed}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
"use client";

import * as Sentry from "@sentry/nextjs";
import {
Building2Icon,
ChevronDownIcon,
ChevronRightIcon,
Loader2,
PlusIcon,
SettingsIcon,
} from "lucide-react";
import { Building2Icon, ChevronDownIcon, ChevronRightIcon, Loader2, SettingsIcon } from "lucide-react";
import { useRouter } from "next/navigation";
import { useEffect, useState, useTransition } from "react";
import { useTranslation } from "react-i18next";
import { logger } from "@formbricks/logger";
import { getOrganizationsForSwitcherAction } from "@/app/(app)/workspaces/[workspaceId]/actions";
import { getFormattedErrorMessage } from "@/lib/utils/helper";
import { CreateOrganizationModal } from "@/modules/organization/components/CreateOrganizationModal";
import { BreadcrumbItem } from "@/modules/ui/components/breadcrumb";
import {
DropdownMenu,
Expand All @@ -42,7 +34,6 @@ export const OrganizationBreadcrumb = ({
}: OrganizationBreadcrumbProps) => {
const { t } = useTranslation();
const [isOrganizationDropdownOpen, setIsOrganizationDropdownOpen] = useState(false);
const [openCreateOrganizationModal, setOpenCreateOrganizationModal] = useState(false);
const router = useRouter();
const [isPending, startTransition] = useTransition();
const [isLoadingOrganizations, setIsLoadingOrganizations] = useState(false);
Expand Down Expand Up @@ -161,27 +152,17 @@ export const OrganizationBreadcrumb = ({
</div>
)}
{!isLoadingOrganizations && !loadError && (
<>
<DropdownMenuGroup className="max-h-[300px] overflow-y-auto">
{organizations.map((org) => (
<DropdownMenuCheckboxItem
key={org.id}
checked={org.id === currentOrganizationId}
onClick={() => handleOrganizationChange(org.id)}
className="cursor-pointer">
{org.name}
</DropdownMenuCheckboxItem>
))}
</DropdownMenuGroup>
{isMultiOrgEnabled && (
<DropdownMenuGroup className="max-h-[300px] overflow-y-auto">
{organizations.map((org) => (
<DropdownMenuCheckboxItem
onClick={() => setOpenCreateOrganizationModal(true)}
key={org.id}
checked={org.id === currentOrganizationId}
onClick={() => handleOrganizationChange(org.id)}
className="cursor-pointer">
<span>{t("common.create_new_organization")}</span>
<PlusIcon className="ml-2 size-4" />
{org.name}
</DropdownMenuCheckboxItem>
)}
</>
))}
</DropdownMenuGroup>
)}
</>
)}
Expand All @@ -198,12 +179,6 @@ export const OrganizationBreadcrumb = ({
)}
</DropdownMenuContent>
</DropdownMenu>
{openCreateOrganizationModal && (
<CreateOrganizationModal
open={openCreateOrganizationModal}
setOpen={setOpenCreateOrganizationModal}
/>
)}
</BreadcrumbItem>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"use client";

import { useState } from "react";
import { useTranslation } from "react-i18next";
import { CreateOrganizationModal } from "@/modules/organization/components/CreateOrganizationModal";
import { Alert, AlertButton, AlertDescription } from "@/modules/ui/components/alert";

export const CreateOrganizationCard = () => {
const { t } = useTranslation();
const [open, setOpen] = useState(false);

return (
<div className="max-w-4xl">
<Alert variant="info" size="small">
<AlertDescription>
{t("workspace.settings.general.create_new_organization_description")}
</AlertDescription>
<AlertButton onClick={() => setOpen(true)}>
{t("workspace.settings.general.create_new_organization")}
</AlertButton>
</Alert>
{open && <CreateOrganizationModal open={open} setOpen={setOpen} />}
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { getWorkspaceAuth } from "@/modules/workspaces/lib/utils";
import packageJson from "@/package.json";
import { SettingsCard } from "../../components/SettingsCard";
import { AISettingsToggle } from "./components/AISettingsToggle";
import { CreateOrganizationCard } from "./components/CreateOrganizationCard";
import { DeleteOrganization } from "./components/DeleteOrganization";
import { EditOrganizationNameForm } from "./components/EditOrganizationNameForm";
import { SecurityListTip } from "./components/SecurityListTip";
Expand Down Expand Up @@ -88,15 +89,18 @@ const Page = async (props: Readonly<{ params: Promise<{ workspaceId: string }> }
enterpriseLicenseRequestFormUrl={ENTERPRISE_LICENSE_REQUEST_FORM_URL}
/>
{isMultiOrgEnabled && (
<SettingsCard
title={t("workspace.settings.general.delete_organization")}
description={t("workspace.settings.general.delete_organization_description")}>
<DeleteOrganization
organization={organization}
isDeleteDisabled={isDeleteDisabled}
isUserOwner={currentUserRole === "owner"}
/>
</SettingsCard>
<>
<SettingsCard
title={t("workspace.settings.general.delete_organization")}
description={t("workspace.settings.general.delete_organization_description")}>
<DeleteOrganization
organization={organization}
isDeleteDisabled={isDeleteDisabled}
isUserOwner={currentUserRole === "owner"}
/>
</SettingsCard>
<CreateOrganizationCard />
</>
)}

<div className="space-y-2">
Expand Down
21 changes: 16 additions & 5 deletions apps/web/modules/analysis/components/RatingSmiley/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface RatingSmileyProps {
range: number;
addColors?: boolean;
baseUrl?: string;
size?: number;
}

const getSmileyColor = (range: number, idx: number) => {
Expand All @@ -31,7 +32,8 @@ const getSmiley = (
range: number,
active: boolean,
addColors: boolean,
baseUrl?: string
baseUrl?: string,
size: number = 24
): JSX.Element => {
const activeColor = "bg-rating-fill";
const inactiveColor = addColors ? getSmileyColor(range, idx) : "bg-fill-none";
Expand All @@ -49,6 +51,8 @@ const getSmiley = (
"grinning-squinting",
];

const containerSize = size * 2;

const icon = (
<img
data-testid={faceIcons[iconIdx]}
Expand All @@ -58,14 +62,20 @@ const getSmiley = (
: `/smiley-icons/${faceIcons[iconIdx]}-face.png`
}
alt={faceIcons[iconIdx]}
width={24}
height={24}
width={size}
height={size}
className={`${active ? activeColor : inactiveColor} rounded-full`}
/>
);

return (
<table style={{ width: "48px", height: "48px" }}>
<table
style={{
width: `${containerSize}px`,
height: `${containerSize}px`,
marginLeft: "auto",
marginRight: "auto",
}}>
{" "}
{/* NOSONAR S5256 - Need table layout for email compatibility (gmail) */}
<tr>
Expand All @@ -83,6 +93,7 @@ export const RatingSmiley = ({
range,
addColors = false,
baseUrl,
size,
}: RatingSmileyProps): JSX.Element => {
let iconsIdx: number[] = [];
if (range === 10) iconsIdx = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
Expand All @@ -92,5 +103,5 @@ export const RatingSmiley = ({
else if (range === 4) iconsIdx = [4, 5, 6, 7];
else if (range === 3) iconsIdx = [4, 5, 7];

return getSmiley(iconsIdx[idx], idx, range, active, addColors, baseUrl);
return getSmiley(iconsIdx[idx], idx, range, active, addColors, baseUrl, size);
};
Loading
Loading