mirror of
https://github.com/documenso/documenso
synced 2026-04-21 13:27:18 +00:00
fix: brand logo caching (#2699)
This commit is contained in:
parent
bc82b2e70e
commit
5082226e08
5 changed files with 52 additions and 16 deletions
|
|
@ -98,7 +98,7 @@ export function BrandingPreferencesForm({
|
|||
? `${NEXT_PUBLIC_WEBAPP_URL()}/api/branding/logo/team/${team?.id}`
|
||||
: `${NEXT_PUBLIC_WEBAPP_URL()}/api/branding/logo/organisation/${organisation?.id}`;
|
||||
|
||||
setPreviewUrl(logoUrl);
|
||||
setPreviewUrl(logoUrl + '?v=' + Date.now());
|
||||
setHasLoadedPreview(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -173,7 +173,7 @@ export function BrandingPreferencesForm({
|
|||
/>
|
||||
|
||||
<div className="relative flex w-full flex-col gap-y-4">
|
||||
{!isBrandingEnabled && <div className="bg-background/60 absolute inset-0 z-[9998]" />}
|
||||
{!isBrandingEnabled && <div className="absolute inset-0 z-[9998] bg-background/60" />}
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
|
|
@ -185,7 +185,7 @@ export function BrandingPreferencesForm({
|
|||
</FormLabel>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="border-border bg-background relative h-48 w-full overflow-hidden rounded-lg border">
|
||||
<div className="relative h-48 w-full overflow-hidden rounded-lg border border-border bg-background">
|
||||
{previewUrl ? (
|
||||
<img
|
||||
src={previewUrl}
|
||||
|
|
@ -193,12 +193,12 @@ export function BrandingPreferencesForm({
|
|||
className="h-full w-full object-contain p-4"
|
||||
/>
|
||||
) : (
|
||||
<div className="bg-muted/20 dark:bg-muted text-muted-foreground relative flex h-full w-full items-center justify-center text-sm">
|
||||
<div className="relative flex h-full w-full items-center justify-center bg-muted/20 text-sm text-muted-foreground dark:bg-muted">
|
||||
<Trans>Please upload a logo</Trans>
|
||||
|
||||
{!hasLoadedPreview && (
|
||||
<div className="bg-muted dark:bg-muted absolute inset-0 z-[999] flex items-center justify-center">
|
||||
<Loader className="text-muted-foreground h-8 w-8 animate-spin" />
|
||||
<div className="absolute inset-0 z-[999] flex items-center justify-center bg-muted dark:bg-muted">
|
||||
<Loader className="h-8 w-8 animate-spin text-muted-foreground" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -243,7 +243,7 @@ export function BrandingPreferencesForm({
|
|||
type="button"
|
||||
variant="link"
|
||||
size="sm"
|
||||
className="text-destructive text-xs"
|
||||
className="text-xs text-destructive"
|
||||
onClick={() => {
|
||||
setPreviewUrl('');
|
||||
onChange(null);
|
||||
|
|
|
|||
|
|
@ -48,12 +48,17 @@ export default function OrganisationSettingsBrandingPage() {
|
|||
try {
|
||||
const { brandingEnabled, brandingLogo, brandingUrl, brandingCompanyDetails } = data;
|
||||
|
||||
let uploadedBrandingLogo: string | undefined = '';
|
||||
let uploadedBrandingLogo: string | undefined = undefined;
|
||||
|
||||
if (brandingLogo) {
|
||||
uploadedBrandingLogo = JSON.stringify(await putFile(brandingLogo));
|
||||
}
|
||||
|
||||
// Empty the branding logo if the user unsets it.
|
||||
if (brandingLogo === null) {
|
||||
uploadedBrandingLogo = '';
|
||||
}
|
||||
|
||||
await updateOrganisationSettings({
|
||||
organisationId: organisation.id,
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -34,12 +34,13 @@ export default function TeamsSettingsPage() {
|
|||
try {
|
||||
const { brandingEnabled, brandingLogo, brandingUrl, brandingCompanyDetails } = data;
|
||||
|
||||
let uploadedBrandingLogo = teamWithSettings?.teamSettings?.brandingLogo;
|
||||
let uploadedBrandingLogo: string | undefined = undefined;
|
||||
|
||||
if (brandingLogo) {
|
||||
uploadedBrandingLogo = JSON.stringify(await putFile(brandingLogo));
|
||||
}
|
||||
|
||||
// Empty the branding logo if the user unsets it.
|
||||
if (brandingLogo === null) {
|
||||
uploadedBrandingLogo = '';
|
||||
}
|
||||
|
|
@ -48,7 +49,7 @@ export default function TeamsSettingsPage() {
|
|||
teamId: team.id,
|
||||
data: {
|
||||
brandingEnabled,
|
||||
brandingLogo: uploadedBrandingLogo || null,
|
||||
brandingLogo: uploadedBrandingLogo,
|
||||
brandingUrl: brandingUrl || null,
|
||||
brandingCompanyDetails: brandingCompanyDetails || null,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import { sha256 } from '@documenso/lib/universal/crypto';
|
||||
import { getFileServerSide } from '@documenso/lib/universal/upload/get-file.server';
|
||||
import { loadLogo } from '@documenso/lib/utils/images/logo';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import type { Route } from './+types/branding.logo.organisation.$orgId';
|
||||
|
||||
export async function loader({ params }: Route.LoaderArgs) {
|
||||
const CACHE_CONTROL = 'public, max-age=0, stale-while-revalidate=86400';
|
||||
|
||||
export async function loader({ params, request }: Route.LoaderArgs) {
|
||||
const organisationId = params.orgId;
|
||||
|
||||
if (!organisationId) {
|
||||
|
|
@ -48,6 +51,18 @@ export async function loader({ params }: Route.LoaderArgs) {
|
|||
);
|
||||
}
|
||||
|
||||
const etag = `"${Buffer.from(sha256(settings.brandingLogo)).toString('hex')}"`;
|
||||
|
||||
if (request.headers.get('If-None-Match') === etag) {
|
||||
return new Response(null, {
|
||||
status: 304,
|
||||
headers: {
|
||||
ETag: etag,
|
||||
'Cache-Control': CACHE_CONTROL,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const file = await getFileServerSide(JSON.parse(settings.brandingLogo)).catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
|
|
@ -68,8 +83,8 @@ export async function loader({ params }: Route.LoaderArgs) {
|
|||
headers: {
|
||||
'Content-Type': contentType,
|
||||
'Content-Length': content.length.toString(),
|
||||
// Stale while revalidate for 1 hours to 24 hours
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=86400',
|
||||
'Cache-Control': CACHE_CONTROL,
|
||||
ETag: etag,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import { getTeamSettings } from '@documenso/lib/server-only/team/get-team-settings';
|
||||
import { sha256 } from '@documenso/lib/universal/crypto';
|
||||
import { getFileServerSide } from '@documenso/lib/universal/upload/get-file.server';
|
||||
import { loadLogo } from '@documenso/lib/utils/images/logo';
|
||||
|
||||
import type { Route } from './+types/branding.logo.team.$teamId';
|
||||
|
||||
export async function loader({ params }: Route.LoaderArgs) {
|
||||
const CACHE_CONTROL = 'public, max-age=0, stale-while-revalidate=86400';
|
||||
|
||||
export async function loader({ params, request }: Route.LoaderArgs) {
|
||||
const teamId = Number(params.teamId);
|
||||
|
||||
if (teamId === 0 || Number.isNaN(teamId)) {
|
||||
|
|
@ -41,6 +44,18 @@ export async function loader({ params }: Route.LoaderArgs) {
|
|||
);
|
||||
}
|
||||
|
||||
const etag = `"${Buffer.from(sha256(settings.brandingLogo)).toString('hex')}"`;
|
||||
|
||||
if (request.headers.get('If-None-Match') === etag) {
|
||||
return new Response(null, {
|
||||
status: 304,
|
||||
headers: {
|
||||
ETag: etag,
|
||||
'Cache-Control': CACHE_CONTROL,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const file = await getFileServerSide(JSON.parse(settings.brandingLogo)).catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
|
|
@ -61,8 +76,8 @@ export async function loader({ params }: Route.LoaderArgs) {
|
|||
headers: {
|
||||
'Content-Type': contentType,
|
||||
'Content-Length': content.length.toString(),
|
||||
// Stale while revalidate for 1 hours to 24 hours
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=86400',
|
||||
'Cache-Control': CACHE_CONTROL,
|
||||
ETag: etag,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue