Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 26 additions & 12 deletions client/src/components/Banners/Banner.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useRef } from 'react';
import { XIcon } from 'lucide-react';
import { useRecoilState } from 'recoil';
import { Button } from '@librechat/client';
import { useGetBannerQuery } from '~/data-provider';
import store from '~/store';

Expand All @@ -15,34 +16,47 @@ export const Banner = ({ onHeightChange }: { onHeightChange?: (height: number) =
}
}, [banner, hideBannerHint, onHeightChange]);

if (!banner || (banner.bannerId && hideBannerHint.includes(banner.bannerId))) {
if (
!banner ||
(banner.bannerId && !banner.persistable && hideBannerHint.includes(banner.bannerId))
) {
return null;
}

console.log(banner);

const onClick = () => {
if (banner.persistable) {
return;
}

setHideBannerHint([...hideBannerHint, banner.bannerId]);

if (onHeightChange) {
onHeightChange(0); // Reset height when banner is closed
onHeightChange(0);
}
};

return (
<div
ref={bannerRef}
className="sticky top-0 z-20 flex items-center bg-neutral-900 from-gray-700 to-gray-900 px-2 py-1 text-slate-50 dark:bg-gradient-to-r dark:text-white md:relative"
className="sticky top-0 z-20 flex items-center bg-surface-secondary px-2 py-1 text-text-primary dark:bg-gradient-to-r md:relative"
>
<div
className="w-full truncate px-4 text-center text-sm"
className={`text-md w-full truncate text-center ${banner.persistable ? '' : 'px-4'}`}
dangerouslySetInnerHTML={{ __html: banner.message }}
></div>
<button
type="button"
aria-label="Dismiss banner"
className="h-8 w-8 opacity-80 hover:opacity-100"
onClick={onClick}
>
<XIcon className="mx-auto h-4 w-4" />
</button>
{!banner.persistable && (
<Button
size="icon"
variant="ghost"
aria-label="Dismiss banner"
className="size-8"
onClick={onClick}
>
<XIcon className="mx-auto h-4 w-4 text-text-primary" />
</Button>
)}
</div>
);
};
12 changes: 11 additions & 1 deletion config/update-banner.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,17 @@ const connect = require('./connect');
let displayTo = '';
let message = '';
let isPublic = undefined;
let persistable = undefined;
// If we have the right number of arguments, lets use them
if (process.argv.length >= 3) {
displayFrom = process.argv[2];
displayTo = process.argv[3];
message = process.argv[4];
isPublic = process.argv[5] === undefined ? undefined : process.argv[5] === 'true';
persistable = process.argv[6] === undefined ? undefined : process.argv[6] === 'true';
} else {
console.orange(
'Usage: npm run update-banner <displayFrom(Format: yyyy-mm-ddTHH:MM:SSZ)> <displayTo(Format: yyyy-mm-ddTHH:MM:SSZ)> <message> <isPublic(true/false)>',
'Usage: npm run update-banner <displayFrom(Format: yyyy-mm-ddTHH:MM:SSZ)> <displayTo(Format: yyyy-mm-ddTHH:MM:SSZ)> <message> <isPublic(true/false)> <persistable(true/false)>',
);
console.orange('Note: if you do not pass in the arguments, you will be prompted for them.');
console.purple('--------------------------');
Expand Down Expand Up @@ -81,6 +83,11 @@ const connect = require('./connect');
isPublic = isPublicInput.toLowerCase() === 'y' ? true : false;
}

if (persistable === undefined) {
const persistableInput = await askQuestion('Is persistable (cannot be dismissed) (y/N):');
persistable = persistableInput.toLowerCase() === 'y' ? true : false;
}

// Generate the same bannerId for the same message
// This allows us to display only messages that haven't been shown yet
const NAMESPACE = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; // Use an arbitrary namespace UUID
Expand All @@ -101,6 +108,7 @@ const connect = require('./connect');
message,
bannerId,
isPublic,
persistable,
},
{ new: true },
);
Expand All @@ -111,6 +119,7 @@ const connect = require('./connect');
message,
bannerId,
isPublic,
persistable,
});
}
} catch (error) {
Expand All @@ -131,6 +140,7 @@ const connect = require('./connect');
console.purple(`to: ${displayTo || 'not specified'}`);
console.purple(`Banner: ${message}`);
console.purple(`isPublic: ${isPublic}`);
console.purple(`persistable: ${persistable}`);
silentExit(0);
})();

Expand Down
1 change: 1 addition & 0 deletions packages/data-provider/src/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,7 @@ export const tBannerSchema = z.object({
createdAt: z.string(),
updatedAt: z.string(),
isPublic: z.boolean(),
persistable: z.boolean().default(false),
});
export type TBanner = z.infer<typeof tBannerSchema>;

Expand Down
5 changes: 5 additions & 0 deletions packages/data-schemas/src/schema/banner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface IBanner extends Document {
displayTo?: Date;
type: 'banner' | 'popup';
isPublic: boolean;
persistable: boolean;
}

const bannerSchema = new Schema<IBanner>(
Expand Down Expand Up @@ -36,6 +37,10 @@ const bannerSchema = new Schema<IBanner>(
type: Boolean,
default: false,
},
persistable: {
type: Boolean,
default: false,
},
},
{ timestamps: true },
);
Expand Down
1 change: 1 addition & 0 deletions packages/data-schemas/src/types/banner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export interface IBanner extends Document {
displayTo?: Date;
type: 'banner' | 'popup';
isPublic: boolean;
persistable: boolean;
}