update tslint config with noUnusedLocals and clean up code accordingly

This commit is contained in:
Matthias Nannt
2023-01-30 14:40:12 +01:00
parent bfe4ad0f87
commit d2b10d6502
27 changed files with 52 additions and 304 deletions

View File

@@ -21,7 +21,7 @@ import {
UserGroupIcon,
XMarkIcon,
} from "@heroicons/react/24/outline";
import { Fragment, useEffect, useState } from "react";
import { Fragment, useState } from "react";
const navigation = [
{ name: "Home", href: "#", icon: HomeIcon, current: true },

View File

@@ -4,7 +4,6 @@ import LoadingSpinner from "@/components/LoadingSpinner";
import { useCustomer } from "@/lib/customers";
import { MergeWithSchema } from "@/lib/submissions";
import { convertDateTimeString, onlyUnique, parseUserAgent } from "@/lib/utils";
import { useWorkspace } from "@/lib/workspaces";
import { BackIcon } from "@formbricks/ui";
import { InboxIcon } from "@heroicons/react/24/outline";
import clsx from "clsx";

View File

@@ -9,6 +9,7 @@ import clsx from "clsx";
import Link from "next/link";
import { Fragment, useState } from "react";
import NewFormModal from "@/components/forms/NewFormModal";
import LoadingSpinner from "../LoadingSpinner";
export default function FormsList({ workspaceId }) {
const { forms, mutateForms, isLoadingForms } = useForms(workspaceId);
@@ -30,6 +31,10 @@ export default function FormsList({ workspaceId }) {
}
};
if (isLoadingForms) {
return <LoadingSpinner />;
}
return (
<>
<div className="h-full">

View File

@@ -11,7 +11,6 @@ import { useRouter } from "next/router";
import Prism from "prismjs";
import { useEffect, useMemo, useState } from "react";
import { AiFillApi } from "react-icons/ai";
import { FaReact, FaVuejs } from "react-icons/fa";
import { toast } from "react-toastify";
require("prismjs/components/prism-javascript");

View File

@@ -3,12 +3,10 @@
import EmptyPageFiller from "@/components/EmptyPageFiller";
import LoadingSpinner from "@/components/LoadingSpinner";
import { useSubmissions } from "@/lib/submissions";
import { BugIcon, ComplimentIcon, FormIcon, IdeaIcon } from "@formbricks/ui";
import { Dialog, Transition } from "@headlessui/react";
import { InboxIcon, XMarkIcon } from "@heroicons/react/24/outline";
import clsx from "clsx";
import { useRouter } from "next/router";
import { Fragment, useEffect, useMemo, useState } from "react";
import { Fragment, useEffect, useState } from "react";
import FilterNavigation from "../shared/FilterNavigation";
import FeedbackTimeline from "./FeedbackTimeline";
@@ -21,97 +19,19 @@ const subCategories = [
export default function FeedbackResults() {
const router = useRouter();
const { submissions, isLoadingSubmissions, isErrorSubmissions, mutateSubmissions } = useSubmissions(
const { submissions, isLoadingSubmissions, isErrorSubmissions } = useSubmissions(
router.query.workspaceId?.toString(),
router.query.formId?.toString()
);
const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
const [currentFilter, setCurrentFilter] = useState("all");
const [filteredSubmissions, setFilteredSubmissions] = useState([]);
useEffect(() => {
if (!submissions) return;
let newSubmissions = [];
if (currentFilter === "all") {
newSubmissions = submissions.filter((submission) => !submission.archived);
} else if (currentFilter === "archive") {
newSubmissions = submissions.filter((submission) => submission.archived);
} else {
newSubmissions = submissions.filter((submission) => submission.data.feedbackType === currentFilter);
}
setFilteredSubmissions(newSubmissions);
}, [currentFilter, submissions]);
useEffect(() => {
if (!isLoadingSubmissions) {
setFilteredSubmissions(submissions.filter((submission) => !submission.archived));
}
}, [isLoadingSubmissions, submissions]);
const navigation = useMemo(() => {
if (!submissions) return [];
const feedbackCounts = {
bug: 0,
compliment: 0,
idea: 0,
archive: 0,
};
for (const submission of submissions) {
if (submission.archived) {
feedbackCounts.archive++;
} else {
feedbackCounts[submission.data.feedbackType]++;
}
}
return [
{
id: "all",
name: "All",
href: "#",
icon: FormIcon,
current: true,
count: submissions.length - feedbackCounts.archive,
color: "bg-indigo-400",
},
{
id: "bug",
name: "Bug",
href: "#",
icon: BugIcon,
current: false,
color: "bg-red-400",
count: feedbackCounts.bug,
},
{
id: "compliment",
name: "Love",
href: "#",
icon: ComplimentIcon,
current: false,
count: feedbackCounts.compliment,
color: "bg-green-400",
},
{
id: "idea",
name: "Idea",
href: "#",
icon: IdeaIcon,
current: false,
count: feedbackCounts.idea,
color: "bg-yellow-400",
},
{
id: "archive",
name: "Archive",
href: "#",
icon: IdeaIcon,
current: false,
count: feedbackCounts.archive,
color: "bg-gray-300",
},
];
}, [submissions]);
if (isLoadingSubmissions) {
return (
<div className="flex h-full w-full items-center justify-center">
@@ -194,7 +114,7 @@ export default function FeedbackResults() {
<InboxIcon className="stroke-thin mx-auto h-24 w-24 text-slate-300" />
</EmptyPageFiller>
) : (
<FeedbackTimeline submissions={filteredSubmissions} setSubmissions={setFilteredSubmissions} />
<FeedbackTimeline submissions={filteredSubmissions} />
)}
</div>
</div>

View File

@@ -8,7 +8,7 @@ import Link from "next/link";
import { useRouter } from "next/router";
import { toast } from "react-toastify";
export default function FeedbackTimeline({ submissions, setSubmissions }) {
export default function FeedbackTimeline({ submissions }) {
const router = useRouter();
const { submissions: allSubmissions, mutateSubmissions } = useSubmissions(

View File

@@ -1,5 +1,4 @@
import { Button } from "@formbricks/ui";
import Link from "next/link";
import { useRouter } from "next/router";
import Prism from "prismjs";
import { useEffect } from "react";

View File

@@ -4,7 +4,6 @@ import EmptyPageFiller from "@/components/EmptyPageFiller";
import LoadingSpinner from "@/components/LoadingSpinner";
import { useForm } from "@/lib/forms";
import { deletePipeline, persistPipeline, usePipelines } from "@/lib/pipelines";
import { useWorkspace } from "@/lib/workspaces";
import { Button } from "@formbricks/ui";
import { Switch } from "@headlessui/react";
import { BoltIcon, Cog6ToothIcon, TrashIcon } from "@heroicons/react/20/solid";
@@ -89,9 +88,6 @@ export default function PipelinesOverview({}) {
router.query.formId?.toString(),
router.query.workspaceId?.toString()
);
const { workspace, isLoadingWorkspace, isErrorWorkspace } = useWorkspace(
router.query.workspaceId?.toString()
);
const { pipelines, isLoadingPipelines, isErrorPipelines, mutatePipelines } = usePipelines(
router.query.formId?.toString(),
router.query.workspaceId?.toString()
@@ -128,7 +124,7 @@ export default function PipelinesOverview({}) {
}
};
if (isLoadingForm || isLoadingWorkspace || isLoadingPipelines) {
if (isLoadingForm || isLoadingPipelines) {
return (
<div className="flex h-full w-full items-center justify-center">
<LoadingSpinner />
@@ -136,7 +132,7 @@ export default function PipelinesOverview({}) {
);
}
if (isErrorForm || isErrorWorkspace || isErrorPipelines) {
if (isErrorForm || isErrorPipelines) {
return <div>Error loading ressources. Maybe you don&lsquo;t have enough access rights</div>;
}
return (

View File

@@ -4,7 +4,6 @@ import LoadingSpinner from "@/components/LoadingSpinner";
import TabNavigation from "@/components/TabNavigation";
import { useForm } from "@/lib/forms";
import {
BoltIcon,
ChartPieIcon,
InformationCircleIcon,
RectangleStackIcon,

View File

@@ -11,7 +11,7 @@ import PMFTimeline from "./PMFTimeline";
export default function PMFResults() {
const router = useRouter();
const { submissions, isLoadingSubmissions, isErrorSubmissions, mutateSubmissions } = useSubmissions(
const { submissions, isLoadingSubmissions, isErrorSubmissions } = useSubmissions(
router.query.workspaceId?.toString(),
router.query.formId?.toString()
);
@@ -47,7 +47,7 @@ export default function PMFResults() {
<InboxIcon className="stroke-thin mx-auto h-24 w-24 text-slate-300" />
</EmptyPageFiller>
) : (
<PMFTimeline submissions={filteredSubmissions} setSubmissions={setFilteredSubmissions} />
<PMFTimeline submissions={filteredSubmissions} />
)}
</div>
</div>

View File

@@ -10,7 +10,7 @@ import Link from "next/link";
import { useRouter } from "next/router";
import { toast } from "react-toastify";
export default function PMFTimeline({ submissions, setSubmissions }) {
export default function PMFTimeline({ submissions }) {
const router = useRouter();
const {

View File

@@ -15,7 +15,7 @@ export default function SegmentResults() {
router.query.formId?.toString(),
router.query.workspaceId?.toString()
);
const { submissions, isLoadingSubmissions, isErrorSubmissions, mutateSubmissions } = useSubmissions(
const { submissions, isLoadingSubmissions, isErrorSubmissions } = useSubmissions(
router.query.workspaceId?.toString(),
router.query.formId?.toString()
);

View File

@@ -1,5 +1,4 @@
import { Button } from "@formbricks/ui";
import Link from "next/link";
import { useRouter } from "next/router";
import Prism from "prismjs";
import { useEffect } from "react";

View File

@@ -1,89 +1,23 @@
"use client";
import EmptyPageFiller from "@/components/EmptyPageFiller";
import LoadingSpinner from "@/components/LoadingSpinner";
import { useSubmissions } from "@/lib/submissions";
import {
ArchiveIcon,
ComplimentIcon,
IdeaIcon,
VeryDisappointedIcon,
SomewhatDisappointedIcon,
NotDisappointedIcon,
} from "@formbricks/ui";
import Image from "next/image";
import PMFThumb from "@/images/pmfthumb.webp";
import PMFThumb2 from "@/images/pmfthumb-2.webp";
import Link from "next/link";
import { InboxIcon } from "@heroicons/react/24/outline";
import PMFThumb from "@/images/pmfthumb.webp";
import { useSubmissions } from "@/lib/submissions";
import clsx from "clsx";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { Fragment, useEffect, useMemo, useState } from "react";
import FeedbackTimeline from "./PMFTimeline";
import { Button } from "@formbricks/ui";
import sq from "date-fns/esm/locale/sq/index.js";
const subCategories = [
{ name: "Somewhat disappointed", href: "#" },
{ name: "Very disappointed", href: "#" },
{ name: "Not disappointed", href: "#" },
];
import { useState } from "react";
import FilterNavigation from "../shared/FilterNavigation";
export default function SegmentResults() {
const router = useRouter();
const { submissions, isLoadingSubmissions, isErrorSubmissions, mutateSubmissions } = useSubmissions(
const [filteredSubmissions, setFilteredSubmissions] = useState([]);
const { submissions, isLoadingSubmissions, isErrorSubmissions } = useSubmissions(
router.query.workspaceId?.toString(),
router.query.formId?.toString()
);
const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
const [currentFilter, setCurrentFilter] = useState("all");
const [filteredSubmissions, setFilteredSubmissions] = useState([]);
useEffect(() => {
if (!submissions) return;
let newSubmissions = [];
if (currentFilter === "all") {
newSubmissions = submissions.filter((submission) => !submission.archived);
} else if (currentFilter === "archive") {
newSubmissions = submissions.filter((submission) => submission.archived);
} else {
newSubmissions = submissions.filter((submission) => submission.data.feedbackType === currentFilter);
}
setFilteredSubmissions(newSubmissions);
}, [currentFilter, submissions]);
useEffect(() => {
if (!isLoadingSubmissions) {
setFilteredSubmissions(submissions.filter((submission) => !submission.archived));
}
}, [isLoadingSubmissions, submissions]);
const completed = [
{
segment: "Founder",
},
{
segment: "Entrepreneur",
},
{
segment: "Product Manager",
},
{
segment: "Engineer",
},
];
const submissionz = [
{
question: "What is the main benefit you receive from our service?",
},
{
question: "How can we improve our service for you?",
},
{
question: "What type of people would benefit most from using our service?",
},
];
const q1responses = [
{
@@ -106,109 +40,20 @@ export default function SegmentResults() {
},
];
const q2responses = [
{
response:
"A think it would be awesome if your app could do this because I keep having this problem! I would use it everyday and tell all my friends.",
feeling: "somewhat disapp.",
segment: "Founder",
},
{
response:
"B think it would be awesome if your app could do this because I keep having this problem! I would use it everyday and tell all my friends.",
feeling: "somewhat disapp.",
segment: "Entrepreneur",
},
{
response:
"C think it would be awesome if your app could do this because I keep having this problem! I would use it everyday and tell all my friends.",
feeling: "somewhat disapp.",
segment: "Product Manager",
},
];
if (isLoadingSubmissions) return <LoadingSpinner />;
if (isErrorSubmissions)
return <div>Error loading ressources. Maybe you don&lsquo;t have enough access rights</div>;
return (
<div>
{/* Mobile filter dialog */}
{/* <Transition.Root show={mobileFiltersOpen} as={Fragment}>
<Dialog as="div" className="relative z-40 lg:hidden" onClose={setMobileFiltersOpen}>
<Transition.Child
as={Fragment}
enter="transition-opacity ease-linear duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0">
<div className="fixed inset-0 bg-black bg-opacity-25" />
</Transition.Child>
<div className="fixed inset-0 z-40 flex">
<Transition.Child
as={Fragment}
enter="transition ease-in-out duration-300 transform"
enterFrom="translate-x-full"
enterTo="translate-x-0"
leave="transition ease-in-out duration-300 transform"
leaveFrom="translate-x-0"
leaveTo="translate-x-full">
<Dialog.Panel className="relative ml-auto flex h-full w-full max-w-xs flex-col overflow-y-auto bg-white py-4 pb-12 shadow-xl">
<div className="flex items-center justify-between px-4">
<h2 className="text-lg font-medium text-gray-900">Filters</h2>
<button
type="button"
className="-mr-2 flex h-10 w-10 items-center justify-center rounded-md bg-white p-2 text-gray-400"
onClick={() => setMobileFiltersOpen(false)}>
<span className="sr-only">Close menu</span>
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
{/* Filters
<form className="mt-4 border-t border-gray-200">
<h3 className="sr-only">Categories</h3>
<ul role="list" className="px-2 py-3 font-medium text-gray-900">
{subCategories.map((category) => (
<li key={category.name}>
<a href={category.href} className="block px-2 py-3">
{category.name}
</a>
</li>
))}
</ul>
\
</form>
</Dialog.Panel>
</Transition.Child>
</div>
</Dialog>
</Transition.Root> */}
<div>
<section aria-labelledby="filters" className="pt-6 pb-24">
<div className="grid grid-cols-1 gap-x-16 gap-y-10 lg:grid-cols-4">
<div>
{/* Segments */}
<form className="mb-4 hidden lg:block">
<h3 className="sr-only">Segment</h3>
<div className="flex py-2 text-sm font-bold">
<h4 className="text-slate-600">Segment</h4>
</div>
{completed.map((item) => (
<button
type="button"
key={item.segment}
className={clsx(
item.segment === currentFilter
? "bg-gray-100 text-gray-900"
: "text-gray-600 hover:bg-gray-100 hover:text-gray-900",
"group flex w-full items-center rounded-md px-3 py-2 text-sm font-medium"
)}>
<div className="-ml-1 mr-3 h-2 w-2 flex-shrink-0 rounded-full" />
<span className="truncate">{item.segment}</span>
</button>
))}
</form>
<FilterNavigation submissions={submissions} setFilteredSubmissions={setFilteredSubmissions} />
<div className="mb-2 flex py-2 text-sm font-bold">
<h4 className="text-slate-600">Tutorials</h4>
</div>
@@ -293,7 +138,7 @@ export default function SegmentResults() {
<div>Feeling</div>
<div>Segment</div>
</div>
{q2responses.map((r) => (
{filteredSubmissions.map((r) => (
<div className="grid grid-cols-5 gap-2 px-4 pt-2 pb-4">
<div className="col-span-3">{r.response}</div>
<div>

View File

@@ -20,7 +20,7 @@ export default function SummaryPage() {
const { workspace, isLoadingWorkspace, isErrorWorkspace } = useWorkspace(
router.query.workspaceId?.toString()
);
const { submissions, isLoadingSubmissions, mutateSubmissions } = useSubmissions(
const { submissions, isLoadingSubmissions } = useSubmissions(
router.query.workspaceId?.toString(),
router.query.formId?.toString()
);

View File

@@ -9,7 +9,7 @@ interface Props {
}
export default function LayoutAuth({ title = "Formbricks HQ", children }: Props) {
const { data: session, status } = useSession();
const { data: session } = useSession();
const router = useRouter();
if (session) {

View File

@@ -38,7 +38,7 @@ export default function LayoutWrapperCustomForm({ children }) {
return (
<>
<Disclosure as="header" className="bg-white shadow">
{({ open }) => (
{({}) => (
<>
<div className="px-2 sm:px-4 lg:divide-y lg:divide-gray-200 lg:px-8">
<nav className="hidden lg:flex lg:space-x-8 lg:py-2" aria-label="Global">

View File

@@ -1,19 +1,17 @@
"use client";
import LoadingSpinner from "@/components/LoadingSpinner";
import { useForms } from "@/lib/forms";
import { useWorkspace } from "@/lib/workspaces";
import { InformationCircleIcon } from "@heroicons/react/20/solid";
import { useRouter } from "next/router";
export default function SettingsPage() {
const router = useRouter();
const { forms, isLoadingForms, isErrorForms } = useForms(router.query.workspaceId?.toString());
const { workspace, isLoadingWorkspace, isErrorWorkspace } = useWorkspace(
router.query.workspaceId?.toString()
);
if (isLoadingForms || isLoadingWorkspace) {
if (isLoadingWorkspace) {
return (
<div className="flex h-full w-full items-center justify-center">
<LoadingSpinner />
@@ -21,7 +19,7 @@ export default function SettingsPage() {
);
}
if (isErrorForms || isErrorWorkspace) {
if (isErrorWorkspace) {
return <div>Error loading ressources. Maybe you don&lsquo;t have enough access rights</div>;
}
return (

View File

@@ -16,7 +16,7 @@ export const hasOwnership = async (model, session, id) => {
},
},
});
if (entity.user.email === session.user.email) {
if (entity.user.email === session.email) {
return true;
} else {
return false;

View File

@@ -126,7 +126,7 @@ export const authOptions: NextAuthOptions = {
}),
],
callbacks: {
async jwt({ token, user, account }) {
async jwt({ token }) {
const existingUser = await prisma.user.findFirst({
where: { email: token.email! },
select: {
@@ -144,7 +144,7 @@ export const authOptions: NextAuthOptions = {
...token,
};
},
async session({ session, token, user }) {
async session({ session, token }) {
// @ts-ignore
session.user.id = token.id;
session.user.name = token.name;

View File

@@ -1,13 +1,10 @@
import type { NextApiResponse, NextApiRequest } from "next";
import { getSession } from "next-auth/react";
import { hasOwnership } from "@/lib/apiHelper";
import { getSessionOrUser, hasOwnership } from "@/lib/apiHelper";
import { prisma } from "@formbricks/database";
import { unstable_getServerSession } from "next-auth";
import { authOptions } from "@/pages/api/auth/[...nextauth]";
import type { NextApiRequest, NextApiResponse } from "next";
export default async function handle(req: NextApiRequest, res: NextApiResponse) {
// Check Authentication
const session = await unstable_getServerSession(req, res, authOptions);
const session = await getSessionOrUser(req, res);
if (!session) {
return res.status(401).json({ message: "Not authenticated" });
}

View File

@@ -1,13 +1,11 @@
import { hashApiKey } from "@/lib/apiHelper";
import { authOptions } from "@/pages/api/auth/[...nextauth]";
import { getSessionOrUser, hashApiKey } from "@/lib/apiHelper";
import { prisma } from "@formbricks/database";
import { randomBytes } from "crypto";
import type { NextApiRequest, NextApiResponse } from "next";
import { unstable_getServerSession } from "next-auth";
export default async function handle(req: NextApiRequest, res: NextApiResponse) {
// Check Authentication
const session = await unstable_getServerSession(req, res, authOptions);
const session = await getSessionOrUser(req, res);
if (!session) {
return res.status(401).json({ message: "Not authenticated" });
}
@@ -17,7 +15,7 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse)
if (req.method === "GET") {
const apiKeys = await prisma.apiKey.findMany({
where: {
user: { email: session.user.email },
user: { email: session.email },
},
});
return res.json(apiKeys);
@@ -35,7 +33,7 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse)
data: {
...apiKey,
hashedKey: hashApiKey(key),
user: { connect: { email: session?.user?.email } },
user: { connect: { email: session?.email } },
},
});
res.json({ ...result, apiKey: key });

View File

@@ -1,8 +1,6 @@
import { getSessionOrUser, hashApiKey } from "@/lib/apiHelper";
import { getSessionOrUser } from "@/lib/apiHelper";
import { prisma } from "@formbricks/database";
import { randomBytes } from "crypto";
import type { NextApiRequest, NextApiResponse } from "next";
import { unstable_getServerSession } from "next-auth";
export default async function handle(req: NextApiRequest, res: NextApiResponse) {
// Check Authentication

View File

@@ -1,5 +1,4 @@
import { getSessionOrUser } from "@/lib/apiHelper";
import { capturePosthogEvent } from "@/lib/posthog";
import { prisma } from "@formbricks/database";
import type { NextApiRequest, NextApiResponse } from "next";

View File

@@ -186,7 +186,7 @@ function close() {
containerElement.removeAttribute("data-success");
}
function resetForm(e: Event) {
function resetForm() {
document.getElementById("formbricks__type-switch")!.innerHTML = "";
containerElement.removeAttribute("data-feedback-type");
}

View File

@@ -214,12 +214,9 @@ async function sendWarmupRequest() {
if (!config.formId) {
throw new Error("Missing formId");
}
const response = await fetch(
`${stripLastBackslash(config.formbricksUrl)}/api/capture/forms/${config.formId}/submissions`,
{
method: "OPTIONS",
}
);
await fetch(`${stripLastBackslash(config.formbricksUrl)}/api/capture/forms/${config.formId}/submissions`, {
method: "OPTIONS",
});
return;
}

View File

@@ -10,8 +10,8 @@
"inlineSources": false,
"isolatedModules": true,
"moduleResolution": "node",
"noUnusedLocals": false,
"noUnusedParameters": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"preserveWatchOutput": true,
"skipLibCheck": true,
"strict": true