mirror of
https://github.com/fosrl/pangolin.git
synced 2026-08-29 23:41:31 +02:00
various visual changes
This commit is contained in:
@@ -41,6 +41,7 @@ import {
|
|||||||
FormMessage
|
FormMessage
|
||||||
} from "@app/components/ui/form";
|
} from "@app/components/ui/form";
|
||||||
import { Input } from "@app/components/ui/input";
|
import { Input } from "@app/components/ui/input";
|
||||||
|
import { Label } from "@app/components/ui/label";
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
PopoverContent,
|
PopoverContent,
|
||||||
@@ -1172,52 +1173,55 @@ export default function Page() {
|
|||||||
|
|
||||||
{isNative ? (
|
{isNative ? (
|
||||||
<SettingsFormCell span="half">
|
<SettingsFormCell span="half">
|
||||||
<Popover
|
<div className="grid gap-2">
|
||||||
open={
|
<Label>{t("sites")}</Label>
|
||||||
nativeSiteOpen
|
<Popover
|
||||||
}
|
open={
|
||||||
onOpenChange={
|
nativeSiteOpen
|
||||||
setNativeSiteOpen
|
}
|
||||||
}
|
onOpenChange={
|
||||||
>
|
setNativeSiteOpen
|
||||||
<PopoverTrigger
|
}
|
||||||
asChild
|
|
||||||
>
|
>
|
||||||
<Button
|
<PopoverTrigger
|
||||||
variant="outline"
|
asChild
|
||||||
role="combobox"
|
|
||||||
className="w-full justify-between font-normal"
|
|
||||||
>
|
>
|
||||||
<span className="truncate">
|
<Button
|
||||||
{nativeSelectedSite?.name ??
|
variant="outline"
|
||||||
t(
|
role="combobox"
|
||||||
"siteSelect"
|
className="w-full justify-between font-normal"
|
||||||
)}
|
>
|
||||||
</span>
|
<span className="truncate">
|
||||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
{nativeSelectedSite?.name ??
|
||||||
</Button>
|
t(
|
||||||
</PopoverTrigger>
|
"siteSelect"
|
||||||
<PopoverContent className="w-[var(--radix-popover-trigger-width)] p-0">
|
)}
|
||||||
<SitesSelector
|
</span>
|
||||||
orgId={
|
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
orgId as string
|
</Button>
|
||||||
}
|
</PopoverTrigger>
|
||||||
selectedSite={
|
<PopoverContent className="w-[var(--radix-popover-trigger-width)] p-0">
|
||||||
nativeSelectedSite
|
<SitesSelector
|
||||||
}
|
orgId={
|
||||||
onSelectSite={(
|
orgId as string
|
||||||
site
|
}
|
||||||
) => {
|
selectedSite={
|
||||||
setNativeSelectedSite(
|
nativeSelectedSite
|
||||||
|
}
|
||||||
|
onSelectSite={(
|
||||||
site
|
site
|
||||||
);
|
) => {
|
||||||
setNativeSiteOpen(
|
setNativeSelectedSite(
|
||||||
false
|
site
|
||||||
);
|
);
|
||||||
}}
|
setNativeSiteOpen(
|
||||||
/>
|
false
|
||||||
</PopoverContent>
|
);
|
||||||
</Popover>
|
}}
|
||||||
|
/>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
</SettingsFormCell>
|
</SettingsFormCell>
|
||||||
) : standardDaemonLocation !==
|
) : standardDaemonLocation !==
|
||||||
"site" ||
|
"site" ||
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export default function AuthPageBrandingForm({
|
|||||||
orgSubtitle: branding?.orgSubtitle ?? `Log in to {{orgName}}`,
|
orgSubtitle: branding?.orgSubtitle ?? `Log in to {{orgName}}`,
|
||||||
resourceTitle:
|
resourceTitle:
|
||||||
branding?.resourceTitle ??
|
branding?.resourceTitle ??
|
||||||
`Authenticate to access {{resourceName}}`,
|
`Authenticate to Access {{resourceName}}`,
|
||||||
resourceSubtitle:
|
resourceSubtitle:
|
||||||
branding?.resourceSubtitle ??
|
branding?.resourceSubtitle ??
|
||||||
`Choose your preferred authentication method for {{resourceName}}`,
|
`Choose your preferred authentication method for {{resourceName}}`,
|
||||||
|
|||||||
@@ -12,11 +12,9 @@ import {
|
|||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
import { useOrgContext } from "@app/hooks/useOrgContext";
|
import { useOrgContext } from "@app/hooks/useOrgContext";
|
||||||
import { usePaidStatus } from "@app/hooks/usePaidStatus";
|
import { usePaidStatus } from "@app/hooks/usePaidStatus";
|
||||||
import { getUserDisplayName } from "@app/lib/getUserDisplayName";
|
|
||||||
import { orgQueries } from "@app/lib/queries";
|
import { orgQueries } from "@app/lib/queries";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { UserType } from "@server/types/UserTypes";
|
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import {
|
import {
|
||||||
@@ -67,12 +65,6 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) {
|
|||||||
env.server.maxmind_asn_path && env.server.maxmind_asn_path.length > 0
|
env.server.maxmind_asn_path && env.server.maxmind_asn_path.length > 0
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: orgRoles = [], isLoading: isLoadingOrgRoles } = useQuery(
|
|
||||||
orgQueries.roles({ orgId: org.org.orgId })
|
|
||||||
);
|
|
||||||
const { data: orgUsers = [], isLoading: isLoadingOrgUsers } = useQuery(
|
|
||||||
orgQueries.users({ orgId: org.org.orgId })
|
|
||||||
);
|
|
||||||
const { data: orgIdps = [], isLoading: isLoadingOrgIdps } = useQuery(
|
const { data: orgIdps = [], isLoading: isLoadingOrgIdps } = useQuery(
|
||||||
orgQueries.identityProviders({
|
orgQueries.identityProviders({
|
||||||
orgId: org.org.orgId,
|
orgId: org.org.orgId,
|
||||||
@@ -163,26 +155,6 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const allRoles = useMemo(
|
|
||||||
() =>
|
|
||||||
orgRoles
|
|
||||||
.map((role) => ({
|
|
||||||
id: role.roleId.toString(),
|
|
||||||
text: role.name
|
|
||||||
}))
|
|
||||||
.filter((role) => role.text !== "Admin"),
|
|
||||||
[orgRoles]
|
|
||||||
);
|
|
||||||
|
|
||||||
const allUsers = useMemo(
|
|
||||||
() =>
|
|
||||||
orgUsers.map((user) => ({
|
|
||||||
id: user.id.toString(),
|
|
||||||
text: `${getUserDisplayName({ email: user.email, username: user.username })}${user.type !== UserType.Internal ? ` (${user.idpName})` : ""}`
|
|
||||||
})),
|
|
||||||
[orgUsers]
|
|
||||||
);
|
|
||||||
|
|
||||||
const allIdps = useMemo(() => {
|
const allIdps = useMemo(() => {
|
||||||
if (build === "saas") {
|
if (build === "saas") {
|
||||||
if (isPaidUser(tierMatrix.orgOidc)) {
|
if (isPaidUser(tierMatrix.orgOidc)) {
|
||||||
@@ -197,7 +169,7 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) {
|
|||||||
return [];
|
return [];
|
||||||
}, [orgIdps, isPaidUser]);
|
}, [orgIdps, isPaidUser]);
|
||||||
|
|
||||||
if (isLoadingOrgRoles || isLoadingOrgUsers || isLoadingOrgIdps) {
|
if (isLoadingOrgIdps) {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,8 +224,6 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) {
|
|||||||
form={form}
|
form={form}
|
||||||
orgId={org.org.orgId}
|
orgId={org.org.orgId}
|
||||||
allIdps={allIdps}
|
allIdps={allIdps}
|
||||||
allRoles={allRoles}
|
|
||||||
allUsers={allUsers}
|
|
||||||
emailEnabled={env.email.emailEnabled}
|
emailEnabled={env.email.emailEnabled}
|
||||||
/>
|
/>
|
||||||
<PolicyAccessRulesSection
|
<PolicyAccessRulesSection
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ type PolicyAuthStackSectionCreateProps = {
|
|||||||
form: UseFormReturn<PolicyFormValues, any, any>;
|
form: UseFormReturn<PolicyFormValues, any, any>;
|
||||||
orgId: string;
|
orgId: string;
|
||||||
allIdps: { id: number; text: string }[];
|
allIdps: { id: number; text: string }[];
|
||||||
allRoles: { id: string; text: string }[];
|
|
||||||
allUsers: { id: string; text: string }[];
|
|
||||||
emailEnabled: boolean;
|
emailEnabled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import {
|
|||||||
SettingsSubsectionTitle,
|
SettingsSubsectionTitle,
|
||||||
SettingsSectionTitle
|
SettingsSectionTitle
|
||||||
} from "@app/components/Settings";
|
} from "@app/components/Settings";
|
||||||
import { TagInput } from "@app/components/tags/tag-input";
|
import { RolesSelector } from "@app/components/roles-selector";
|
||||||
|
import { UsersSelector } from "@app/components/users-selector";
|
||||||
import { FormField } from "@app/components/ui/form";
|
import { FormField } from "@app/components/ui/form";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
@@ -38,27 +39,18 @@ export type PolicyAuthStackSectionCreateProps = {
|
|||||||
form: UseFormReturn<PolicyFormValues, any, any>;
|
form: UseFormReturn<PolicyFormValues, any, any>;
|
||||||
orgId: string;
|
orgId: string;
|
||||||
allIdps: { id: number; text: string }[];
|
allIdps: { id: number; text: string }[];
|
||||||
allRoles: { id: string; text: string }[];
|
|
||||||
allUsers: { id: string; text: string }[];
|
|
||||||
emailEnabled: boolean;
|
emailEnabled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function PolicyAuthStackSectionCreate({
|
export function PolicyAuthStackSectionCreate({
|
||||||
form: parentForm,
|
form: parentForm,
|
||||||
|
orgId,
|
||||||
allIdps,
|
allIdps,
|
||||||
allRoles,
|
|
||||||
allUsers,
|
|
||||||
emailEnabled
|
emailEnabled
|
||||||
}: PolicyAuthStackSectionCreateProps) {
|
}: PolicyAuthStackSectionCreateProps) {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const [editingMethod, setEditingMethod] =
|
const [editingMethod, setEditingMethod] =
|
||||||
useState<PolicyAuthMethodId | null>(null);
|
useState<PolicyAuthMethodId | null>(null);
|
||||||
const [activeRolesTagIndex, setActiveRolesTagIndex] = useState<
|
|
||||||
number | null
|
|
||||||
>(null);
|
|
||||||
const [activeUsersTagIndex, setActiveUsersTagIndex] = useState<
|
|
||||||
number | null
|
|
||||||
>(null);
|
|
||||||
|
|
||||||
const sso = useWatch({ control: parentForm.control, name: "sso" });
|
const sso = useWatch({ control: parentForm.control, name: "sso" });
|
||||||
const skipToIdpId = useWatch({
|
const skipToIdpId = useWatch({
|
||||||
@@ -126,47 +118,38 @@ export function PolicyAuthStackSectionCreate({
|
|||||||
}
|
}
|
||||||
allIdps={allIdps}
|
allIdps={allIdps}
|
||||||
rolesEditor={
|
rolesEditor={
|
||||||
<FormField<PolicyFormValues, "roles">
|
<FormField
|
||||||
control={parentForm.control}
|
control={parentForm.control}
|
||||||
name="roles"
|
name="roles"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<TagInput
|
<RolesSelector
|
||||||
{...field}
|
orgId={orgId}
|
||||||
activeTagIndex={activeRolesTagIndex}
|
selectedRoles={field.value}
|
||||||
setActiveTagIndex={
|
onSelectRoles={(selected) =>
|
||||||
setActiveRolesTagIndex
|
parentForm.setValue(
|
||||||
|
"roles",
|
||||||
|
selected
|
||||||
|
)
|
||||||
}
|
}
|
||||||
placeholder={t("accessRoleSelect2")}
|
restrictAdminRole
|
||||||
tags={field.value ?? []}
|
|
||||||
setTags={(newRoles) =>
|
|
||||||
field.onChange(newRoles)
|
|
||||||
}
|
|
||||||
autocompleteOptions={allRoles}
|
|
||||||
allowDuplicates={false}
|
|
||||||
size="sm"
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
usersEditor={
|
usersEditor={
|
||||||
<FormField<PolicyFormValues, "users">
|
<FormField
|
||||||
control={parentForm.control}
|
control={parentForm.control}
|
||||||
name="users"
|
name="users"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<TagInput
|
<UsersSelector
|
||||||
{...field}
|
orgId={orgId}
|
||||||
activeTagIndex={activeUsersTagIndex}
|
selectedUsers={field.value}
|
||||||
setActiveTagIndex={
|
onSelectUsers={(selected) =>
|
||||||
setActiveUsersTagIndex
|
parentForm.setValue(
|
||||||
|
"users",
|
||||||
|
selected
|
||||||
|
)
|
||||||
}
|
}
|
||||||
placeholder={t("accessUserSelect")}
|
|
||||||
tags={field.value ?? []}
|
|
||||||
setTags={(newUsers) =>
|
|
||||||
field.onChange(newUsers)
|
|
||||||
}
|
|
||||||
autocompleteOptions={allUsers}
|
|
||||||
allowDuplicates={false}
|
|
||||||
size="sm"
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|||||||
import { cn } from "@app/lib/cn";
|
import { cn } from "@app/lib/cn";
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
"cursor-pointer inline-flex items-center justify-center whitespace-nowrap text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50",
|
"cursor-pointer inline-flex items-center justify-center whitespace-nowrap text-sm font-normal ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50",
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
|
|||||||
@@ -351,10 +351,6 @@ export function ControlledDataTable<TData, TValue>({
|
|||||||
dataTableFilterDropdownContentClassName
|
dataTableFilterDropdownContentClassName
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<DropdownMenuLabel>
|
|
||||||
{filter.label}
|
|
||||||
</DropdownMenuLabel>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
{filter.options.map(
|
{filter.options.map(
|
||||||
(option) => {
|
(option) => {
|
||||||
const isChecked =
|
const isChecked =
|
||||||
@@ -484,13 +480,6 @@ export function ControlledDataTable<TData, TValue>({
|
|||||||
align="end"
|
align="end"
|
||||||
className="w-48"
|
className="w-48"
|
||||||
>
|
>
|
||||||
<DropdownMenuLabel>
|
|
||||||
{t(
|
|
||||||
"toggleColumns"
|
|
||||||
) ||
|
|
||||||
"Toggle columns"}
|
|
||||||
</DropdownMenuLabel>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
{table
|
{table
|
||||||
.getAllColumns()
|
.getAllColumns()
|
||||||
.filter(
|
.filter(
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ const TableHead = React.forwardRef<
|
|||||||
<th
|
<th
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-10 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
"h-10 text-left align-middle font-medium text-muted-foreground [&_button]:font-medium [&:has([role=checkbox])]:pr-0",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
Reference in New Issue
Block a user