mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat(organization): add logo support for organizations
This commit is contained in:
@@ -35,14 +35,16 @@ export function AddOrganization({ organizationId }: Props) {
|
|||||||
: api.organization.create.useMutation();
|
: api.organization.create.useMutation();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
|
const [logo, setLogo] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (organization) {
|
if (organization) {
|
||||||
setName(organization.name);
|
setName(organization.name);
|
||||||
|
setLogo(organization.logo || "");
|
||||||
}
|
}
|
||||||
}, [organization]);
|
}, [organization]);
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
await mutateAsync({ name, organizationId: organizationId ?? "" })
|
await mutateAsync({ name, logo, organizationId: organizationId ?? "" })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
toast.success(
|
toast.success(
|
||||||
@@ -91,7 +93,7 @@ export function AddOrganization({ organizationId }: Props) {
|
|||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
{organizationId
|
{organizationId
|
||||||
? "Update the organization name"
|
? "Update the organization name and logo"
|
||||||
: "Create a new organization to manage your projects."}
|
: "Create a new organization to manage your projects."}
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
@@ -107,6 +109,18 @@ export function AddOrganization({ organizationId }: Props) {
|
|||||||
className="col-span-3"
|
className="col-span-3"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="grid grid-cols-4 items-center gap-4">
|
||||||
|
<Label htmlFor="logo" className="text-right">
|
||||||
|
Logo URL
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
id="logo"
|
||||||
|
value={logo}
|
||||||
|
onChange={(e) => setLogo(e.target.value)}
|
||||||
|
placeholder="https://example.com/logo.png"
|
||||||
|
className="col-span-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button type="submit" onClick={handleSubmit} isLoading={isLoading}>
|
<Button type="submit" onClick={handleSubmit} isLoading={isLoading}>
|
||||||
|
|||||||
@@ -562,6 +562,7 @@ function SidebarLogo() {
|
|||||||
"transition-all",
|
"transition-all",
|
||||||
state === "collapsed" ? "size-4" : "size-5",
|
state === "collapsed" ? "size-4" : "size-5",
|
||||||
)}
|
)}
|
||||||
|
logoUrl={activeOrganization?.logo}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -607,6 +608,7 @@ function SidebarLogo() {
|
|||||||
"transition-all",
|
"transition-all",
|
||||||
state === "collapsed" ? "size-6" : "size-10",
|
state === "collapsed" ? "size-6" : "size-10",
|
||||||
)}
|
)}
|
||||||
|
logoUrl={org.logo ?? undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
|||||||
@@ -1,8 +1,20 @@
|
|||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
logoUrl?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Logo = ({ className = "size-14" }: Props) => {
|
export const Logo = ({ className = "size-14", logoUrl }: Props) => {
|
||||||
|
if (logoUrl) {
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={logoUrl}
|
||||||
|
alt="Organization Logo"
|
||||||
|
className={className}
|
||||||
|
style={{ objectFit: "contain" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export const organizationRouter = createTRPCRouter({
|
|||||||
.input(
|
.input(
|
||||||
z.object({
|
z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
|
logo: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
@@ -81,6 +82,7 @@ export const organizationRouter = createTRPCRouter({
|
|||||||
z.object({
|
z.object({
|
||||||
organizationId: z.string(),
|
organizationId: z.string(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
|
logo: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
@@ -92,7 +94,10 @@ export const organizationRouter = createTRPCRouter({
|
|||||||
}
|
}
|
||||||
const result = await db
|
const result = await db
|
||||||
.update(organization)
|
.update(organization)
|
||||||
.set({ name: input.name })
|
.set({
|
||||||
|
name: input.name,
|
||||||
|
logo: input.logo,
|
||||||
|
})
|
||||||
.where(eq(organization.id, input.organizationId))
|
.where(eq(organization.id, input.organizationId))
|
||||||
.returning();
|
.returning();
|
||||||
return result[0];
|
return result[0];
|
||||||
|
|||||||
Reference in New Issue
Block a user