mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-25 03:36:12 +01:00
📁 feat: Integrate SharePoint File Picker and Download Workflow (#8651)
* feat(sharepoint): integrate SharePoint file picker and download workflow Introduces end‑to‑end SharePoint import support: * Token exchange with Microsoft Graph and scope management (`useSharePointToken`) * Re‑usable hooks: `useSharePointPicker`, `useSharePointDownload`, `useSharePointFileHandling` * FileSearch dropdown now offers **From Local Machine** / **From SharePoint** sources and gracefully falls back when SharePoint is disabled * Agent upload model, `AttachFileMenu`, and `DropdownPopup` extended for SharePoint files and sub‑menus * Blurry overlay with progress indicator and `maxSelectionCount` limit during downloads * Cache‑flush utility (`config/flush-cache.js`) supporting Redis & filesystem, with dry‑run and npm script * Updated `SharePointIcon` (uses `currentColor`) and new i18n keys * Bug fixes: placeholder syntax in progress message, picker event‑listener cleanup * Misc style and performance optimizations * Fix ESLint warnings --------- Co-authored-by: Atef Bellaaj <slalom.bellaaj@external.daimlertruck.com>
This commit is contained in:
parent
b6413b06bc
commit
a955097faf
40 changed files with 2500 additions and 123 deletions
|
|
@ -29,7 +29,8 @@ interface DropdownProps {
|
|||
type MenuProps = Omit<
|
||||
DropdownProps,
|
||||
'trigger' | 'isOpen' | 'setIsOpen' | 'focusLoop' | 'mountByState'
|
||||
>;
|
||||
> &
|
||||
Ariakit.MenuProps;
|
||||
|
||||
const DropdownPopup: React.FC<DropdownProps> = ({
|
||||
trigger,
|
||||
|
|
@ -70,7 +71,9 @@ const Menu: React.FC<MenuProps> = ({
|
|||
finalFocus,
|
||||
unmountOnHide,
|
||||
preserveTabOrder,
|
||||
...props
|
||||
}) => {
|
||||
const menuStore = Ariakit.useMenuStore();
|
||||
const menu = Ariakit.useMenuContext();
|
||||
return (
|
||||
<Ariakit.Menu
|
||||
|
|
@ -83,13 +86,53 @@ const Menu: React.FC<MenuProps> = ({
|
|||
unmountOnHide={unmountOnHide}
|
||||
preserveTabOrder={preserveTabOrder}
|
||||
className={cn('popover-ui z-50', className)}
|
||||
{...props}
|
||||
>
|
||||
{items
|
||||
.filter((item) => item.show !== false)
|
||||
.map((item, index) => {
|
||||
const { subItems } = item;
|
||||
if (item.separate === true) {
|
||||
return <Ariakit.MenuSeparator key={index} className="my-1 h-px bg-white/10" />;
|
||||
}
|
||||
if (subItems && subItems.length > 0) {
|
||||
return (
|
||||
<Ariakit.MenuProvider
|
||||
store={menuStore}
|
||||
key={`${keyPrefix ?? ''}${index}-${item.id ?? ''}-provider`}
|
||||
>
|
||||
<Ariakit.MenuButton
|
||||
className={cn(
|
||||
'group flex w-full cursor-pointer items-center justify-between gap-2 rounded-lg px-3 py-3.5 text-sm text-text-primary outline-none transition-colors duration-200 hover:bg-surface-hover focus:bg-surface-hover md:px-2.5 md:py-2',
|
||||
itemClassName,
|
||||
)}
|
||||
disabled={item.disabled}
|
||||
id={item.id}
|
||||
render={item.render}
|
||||
ref={item.ref}
|
||||
// hideOnClick={item.hideOnClick}
|
||||
>
|
||||
<span className="flex items-center gap-2">
|
||||
{item.icon != null && (
|
||||
<span className={cn('mr-2 size-4', iconClassName)} aria-hidden="true">
|
||||
{item.icon}
|
||||
</span>
|
||||
)}
|
||||
{item.label}
|
||||
</span>
|
||||
<Ariakit.MenuButtonArrow className="stroke-1 text-base opacity-75" />
|
||||
</Ariakit.MenuButton>
|
||||
<Menu
|
||||
items={subItems}
|
||||
menuId={`${menuId}-${index}`}
|
||||
key={`${keyPrefix ?? ''}${index}-${item.id ?? ''}`}
|
||||
gutter={12}
|
||||
portal={true}
|
||||
/>
|
||||
</Ariakit.MenuProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Ariakit.MenuItem
|
||||
key={`${keyPrefix ?? ''}${index}-${item.id ?? ''}`}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue