mirror of
https://github.com/hex248/sprint.git
synced 2026-02-07 18:23:03 +00:00
frontend implementation of iconURL
This commit is contained in:
@@ -3,6 +3,7 @@ import type { ReactNode } from "react";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { useAuthenticatedSession } from "@/components/session-provider";
|
import { useAuthenticatedSession } from "@/components/session-provider";
|
||||||
|
import ThemeToggle from "@/components/theme-toggle";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
||||||
import { Field } from "@/components/ui/field";
|
import { Field } from "@/components/ui/field";
|
||||||
@@ -13,7 +14,6 @@ import { UploadAvatar } from "@/components/upload-avatar";
|
|||||||
import { useUpdateUser } from "@/lib/query/hooks";
|
import { useUpdateUser } from "@/lib/query/hooks";
|
||||||
import { parseError } from "@/lib/server";
|
import { parseError } from "@/lib/server";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import ThemeToggle from "./theme-toggle";
|
|
||||||
|
|
||||||
function Account({ trigger }: { trigger?: ReactNode }) {
|
function Account({ trigger }: { trigger?: ReactNode }) {
|
||||||
const { user: currentUser, setUser } = useAuthenticatedSession();
|
const { user: currentUser, setUser } = useAuthenticatedSession();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { Field } from "@/components/ui/field";
|
import { Field } from "@/components/ui/field";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { UploadOrgIcon } from "@/components/upload-org-icon";
|
||||||
import { useCreateOrganisation, useUpdateOrganisation } from "@/lib/query/hooks";
|
import { useCreateOrganisation, useUpdateOrganisation } from "@/lib/query/hooks";
|
||||||
import { parseError } from "@/lib/server";
|
import { parseError } from "@/lib/server";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
@@ -59,6 +60,7 @@ export function OrganisationForm({
|
|||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [slug, setSlug] = useState("");
|
const [slug, setSlug] = useState("");
|
||||||
const [description, setDescription] = useState("");
|
const [description, setDescription] = useState("");
|
||||||
|
const [iconURL, setIconURL] = useState<string | null>(null);
|
||||||
const [slugManuallyEdited, setSlugManuallyEdited] = useState(false);
|
const [slugManuallyEdited, setSlugManuallyEdited] = useState(false);
|
||||||
const [submitAttempted, setSubmitAttempted] = useState(false);
|
const [submitAttempted, setSubmitAttempted] = useState(false);
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
@@ -71,6 +73,7 @@ export function OrganisationForm({
|
|||||||
setName(existingOrganisation.name);
|
setName(existingOrganisation.name);
|
||||||
setSlug(existingOrganisation.slug);
|
setSlug(existingOrganisation.slug);
|
||||||
setDescription(existingOrganisation.description ?? "");
|
setDescription(existingOrganisation.description ?? "");
|
||||||
|
setIconURL(existingOrganisation.iconURL ?? null);
|
||||||
setSlugManuallyEdited(true);
|
setSlugManuallyEdited(true);
|
||||||
}
|
}
|
||||||
}, [isEdit, existingOrganisation, open]);
|
}, [isEdit, existingOrganisation, open]);
|
||||||
@@ -79,6 +82,7 @@ export function OrganisationForm({
|
|||||||
setName("");
|
setName("");
|
||||||
setSlug("");
|
setSlug("");
|
||||||
setDescription("");
|
setDescription("");
|
||||||
|
setIconURL(null);
|
||||||
setSlugManuallyEdited(false);
|
setSlugManuallyEdited(false);
|
||||||
setSubmitAttempted(false);
|
setSubmitAttempted(false);
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
@@ -161,6 +165,16 @@ export function OrganisationForm({
|
|||||||
|
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<div className="grid mt-2">
|
<div className="grid mt-2">
|
||||||
|
{isEdit && existingOrganisation && (
|
||||||
|
<UploadOrgIcon
|
||||||
|
name={name || existingOrganisation.name}
|
||||||
|
slug={slug || existingOrganisation.slug}
|
||||||
|
iconURL={iconURL}
|
||||||
|
organisationId={existingOrganisation.id}
|
||||||
|
onIconUploaded={setIconURL}
|
||||||
|
className="mb-4"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Field
|
<Field
|
||||||
label="Name"
|
label="Name"
|
||||||
value={name}
|
value={name}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useQueryClient } from "@tanstack/react-query";
|
|||||||
import { type ReactNode, useCallback, useEffect, useMemo, useState } from "react";
|
import { type ReactNode, useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { AddMember } from "@/components/add-member";
|
import { AddMember } from "@/components/add-member";
|
||||||
|
import OrgIcon from "@/components/org-icon";
|
||||||
import { OrganisationForm } from "@/components/organisation-form";
|
import { OrganisationForm } from "@/components/organisation-form";
|
||||||
import { OrganisationSelect } from "@/components/organisation-select";
|
import { OrganisationSelect } from "@/components/organisation-select";
|
||||||
import { ProjectForm } from "@/components/project-form";
|
import { ProjectForm } from "@/components/project-form";
|
||||||
@@ -44,7 +45,6 @@ import {
|
|||||||
import { queryKeys } from "@/lib/query/keys";
|
import { queryKeys } from "@/lib/query/keys";
|
||||||
import { issue } from "@/lib/server";
|
import { issue } from "@/lib/server";
|
||||||
import { capitalise } from "@/lib/utils";
|
import { capitalise } from "@/lib/utils";
|
||||||
import OrgIcon from "./org-icon";
|
|
||||||
|
|
||||||
function Organisations({ trigger }: { trigger?: ReactNode }) {
|
function Organisations({ trigger }: { trigger?: ReactNode }) {
|
||||||
const { user } = useAuthenticatedSession();
|
const { user } = useAuthenticatedSession();
|
||||||
@@ -490,6 +490,7 @@ function Organisations({ trigger }: { trigger?: ReactNode }) {
|
|||||||
<OrgIcon
|
<OrgIcon
|
||||||
name={selectedOrganisation.Organisation.name}
|
name={selectedOrganisation.Organisation.name}
|
||||||
slug={selectedOrganisation.Organisation.slug}
|
slug={selectedOrganisation.Organisation.slug}
|
||||||
|
iconURL={selectedOrganisation.Organisation.iconURL}
|
||||||
size={16}
|
size={16}
|
||||||
textClass="text-2xl"
|
textClass="text-2xl"
|
||||||
className="rounded-lg"
|
className="rounded-lg"
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ export { members } from "@/lib/server/organisation/members";
|
|||||||
export { removeMember } from "@/lib/server/organisation/removeMember";
|
export { removeMember } from "@/lib/server/organisation/removeMember";
|
||||||
export { update } from "@/lib/server/organisation/update";
|
export { update } from "@/lib/server/organisation/update";
|
||||||
export { updateMemberRole } from "@/lib/server/organisation/updateMemberRole";
|
export { updateMemberRole } from "@/lib/server/organisation/updateMemberRole";
|
||||||
|
export { uploadIcon } from "@/lib/server/organisation/uploadIcon";
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
import { useEffect, useMemo, useRef } from "react";
|
import { useEffect, useMemo, useRef } from "react";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
import Account from "@/components/account";
|
import Account from "@/components/account";
|
||||||
import { IssueForm } from "@/components/issue-form";
|
|
||||||
import { IssueDetailPane } from "@/components/issue-detail-pane";
|
import { IssueDetailPane } from "@/components/issue-detail-pane";
|
||||||
|
import { IssueForm } from "@/components/issue-form";
|
||||||
import { IssuesTable } from "@/components/issues-table";
|
import { IssuesTable } from "@/components/issues-table";
|
||||||
import LogOutButton from "@/components/log-out-button";
|
import LogOutButton from "@/components/log-out-button";
|
||||||
import OrgIcon from "@/components/org-icon";
|
import OrgIcon from "@/components/org-icon";
|
||||||
@@ -198,6 +198,11 @@ export default function App() {
|
|||||||
(org) => org.Organisation.id === selectedOrganisationId,
|
(org) => org.Organisation.id === selectedOrganisationId,
|
||||||
)?.Organisation.slug || ""
|
)?.Organisation.slug || ""
|
||||||
}
|
}
|
||||||
|
iconURL={
|
||||||
|
organisations.find(
|
||||||
|
(org) => org.Organisation.id === selectedOrganisationId,
|
||||||
|
)?.Organisation.iconURL || undefined
|
||||||
|
}
|
||||||
size={7}
|
size={7}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ export const OrgUpdateRequestSchema = z.object({
|
|||||||
.max(ORG_SLUG_MAX_LENGTH)
|
.max(ORG_SLUG_MAX_LENGTH)
|
||||||
.regex(/^[a-z0-9-]+$/)
|
.regex(/^[a-z0-9-]+$/)
|
||||||
.optional(),
|
.optional(),
|
||||||
|
iconURL: z.string().url().max(512).nullable().optional(),
|
||||||
statuses: z
|
statuses: z
|
||||||
.record(z.string())
|
.record(z.string())
|
||||||
.refine((obj) => Object.keys(obj).length > 0, "Statuses must have at least one entry")
|
.refine((obj) => Object.keys(obj).length > 0, "Statuses must have at least one entry")
|
||||||
|
|||||||
Reference in New Issue
Block a user