mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 10:19:51 -06:00
Merge pull request #365 from Ashutosh-Bhadauriya/feat/add-attribute-archive
Feature: Add ability to archive attributes
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import LoadingSpinner from "@/components/shared/LoadingSpinner";
|
||||
import { useAttributeClasses } from "@/lib/attributeClasses/attributeClasses";
|
||||
import { Button, ErrorComponent } from "@formbricks/ui";
|
||||
import { Badge, Button, ErrorComponent, Switch } from "@formbricks/ui";
|
||||
import { QuestionMarkCircleIcon, TagIcon } from "@heroicons/react/24/solid";
|
||||
import { useState } from "react";
|
||||
import AttributeDetailModal from "./AttributeDetailModal";
|
||||
@@ -16,6 +16,7 @@ export default function AttributeClassesList({ environmentId }: { environmentId:
|
||||
const [isAttributeDetailModalOpen, setAttributeDetailModalOpen] = useState(false);
|
||||
const [isUploadCSVModalOpen, setUploadCSVModalOpen] = useState(false);
|
||||
const [activeAttributeClass, setActiveAttributeClass] = useState("" as any);
|
||||
const [showArchived, setShowArchived] = useState(false);
|
||||
|
||||
if (isLoadingAttributeClasses) {
|
||||
return <LoadingSpinner />;
|
||||
@@ -30,9 +31,24 @@ export default function AttributeClassesList({ environmentId }: { environmentId:
|
||||
setAttributeDetailModalOpen(true);
|
||||
};
|
||||
|
||||
const toggleShowArchived = () => {
|
||||
setShowArchived(!showArchived);
|
||||
};
|
||||
|
||||
const displayedAttributeClasses = showArchived ? attributeClasses : attributeClasses.filter(ac => !ac.archived);
|
||||
const hasArchived = attributeClasses.some(ac => ac.archived);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-6 text-right">
|
||||
<div className="mb-6 text-right flex items-center justify-end">
|
||||
{hasArchived && <div className="flex items-center text-sm font-medium">
|
||||
Show archived
|
||||
<Switch
|
||||
className="mx-3"
|
||||
checked={showArchived}
|
||||
onCheckedChange={toggleShowArchived}
|
||||
/>
|
||||
</div>}
|
||||
<Button
|
||||
variant="secondary"
|
||||
href="http://formbricks.com/docs/attributes/custom-attributes"
|
||||
@@ -48,7 +64,7 @@ export default function AttributeClassesList({ environmentId }: { environmentId:
|
||||
<div className="text-center">Last Updated</div>
|
||||
</div>
|
||||
<div className="grid-cols-7">
|
||||
{attributeClasses.map((attributeClass) => (
|
||||
{displayedAttributeClasses.map((attributeClass) => (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
handleOpenAttributeDetailModalClick(e, attributeClass);
|
||||
@@ -62,7 +78,11 @@ export default function AttributeClassesList({ environmentId }: { environmentId:
|
||||
<TagIcon className="h-8 w-8 flex-shrink-0 text-slate-500" />
|
||||
</div>
|
||||
<div className="ml-4 text-left">
|
||||
<div className="font-medium text-slate-900">{attributeClass.name}</div>
|
||||
<div className="font-medium text-slate-900">{attributeClass.name}
|
||||
<span className="ml-2">
|
||||
{attributeClass.archived && <Badge text="Archived" type="gray" size="tiny" />}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-xs text-slate-400">{attributeClass.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useAttributeClassMutation } from "@/lib/attributeClasses/mutateAttribut
|
||||
import { Button, Input, Label } from "@formbricks/ui";
|
||||
import type { AttributeClass } from "@prisma/client";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { ArchiveBoxArrowDownIcon, ArchiveBoxXMarkIcon } from "@heroicons/react/24/solid";
|
||||
|
||||
interface AttributeSettingsTabProps {
|
||||
environmentId: string;
|
||||
@@ -31,6 +32,12 @@ export default function AttributeSettingsTab({
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleArchiveToggle = async () => {
|
||||
const data = { archived: !attributeClass.archived };
|
||||
await triggerAttributeClassMutate(data);
|
||||
mutateAttributeClasses();
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form className="space-y-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
@@ -67,13 +74,22 @@ export default function AttributeSettingsTab({
|
||||
) : null}
|
||||
</div>
|
||||
<div className="flex justify-between border-t border-slate-200 pt-6">
|
||||
<div>
|
||||
<div className="flex items-center">
|
||||
<Button
|
||||
variant="secondary"
|
||||
href="https://formbricks.com/docs/getting-started/identify-users"
|
||||
target="_blank">
|
||||
Read Docs
|
||||
</Button>
|
||||
{attributeClass.type !== "automatic" && (
|
||||
<Button className="ml-3" variant="secondary" onClick={handleArchiveToggle}>
|
||||
{attributeClass.archived ? (
|
||||
<> <ArchiveBoxXMarkIcon className="h-4 mr-2 text-slate-600" /><span>Unarchive</span></>
|
||||
) : (
|
||||
<> <ArchiveBoxArrowDownIcon className="h-4 mr-2 text-slate-600" /><span>Archive</span></>
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{attributeClass.type !== "automatic" && (
|
||||
<div className="flex space-x-2">
|
||||
|
||||
@@ -36,7 +36,7 @@ export default function EventClassesList({ environmentId }) {
|
||||
<>
|
||||
<div className="mb-6 text-right">
|
||||
<Button
|
||||
variant="primary"
|
||||
variant="darkCTA"
|
||||
onClick={() => {
|
||||
setAddEventModalOpen(true);
|
||||
}}>
|
||||
|
||||
@@ -38,7 +38,7 @@ export default function PersonDetails({ environmentId, personId }: PersonDetails
|
||||
const otherAttributes = useMemo(
|
||||
() =>
|
||||
person?.attributes?.filter(
|
||||
(attribute) => attribute.attributeClass.name !== "email" && attribute.attributeClass.name !== "userId"
|
||||
(attribute) => attribute.attributeClass.name !== "email" && attribute.attributeClass.name !== "userId" && !attribute.attributeClass.archived
|
||||
) as any[],
|
||||
[person]
|
||||
);
|
||||
|
||||
@@ -158,7 +158,7 @@ export default function WhoToSendCard({ environmentId, localSurvey, setLocalSurv
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{attributeClasses.map((attributeClass) => (
|
||||
{attributeClasses.filter(attributeClass => !attributeClass.archived).map((attributeClass) => (
|
||||
<SelectItem value={attributeClass.id}>{attributeClass.name}</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
|
||||
@@ -73,6 +73,7 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse)
|
||||
select: {
|
||||
name: true,
|
||||
description: true,
|
||||
archived: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "AttributeClass" ADD COLUMN "archived" BOOLEAN NOT NULL DEFAULT false;
|
||||
@@ -64,6 +64,7 @@ model AttributeClass {
|
||||
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
||||
name String
|
||||
description String?
|
||||
archived Boolean @default(false)
|
||||
type AttributeType
|
||||
environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade)
|
||||
environmentId String
|
||||
|
||||
Reference in New Issue
Block a user