wip
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
|
||||
const config = {
|
||||
themes: {
|
||||
default: {
|
||||
|
||||
@@ -229,6 +229,8 @@ export const TreeView = <T,>({
|
||||
initialOpenState={initialOpenState}
|
||||
selection={selectedNodeId}
|
||||
disableEdit={true}
|
||||
selectionFollowsFocus={true}
|
||||
disableMultiSelection={true}
|
||||
rowHeight={32}
|
||||
overscanCount={20}
|
||||
padding={25}
|
||||
|
||||
@@ -43,6 +43,7 @@ export const createTreeStore = <T>(
|
||||
}
|
||||
refreshCallback?.(nodeId)
|
||||
.then((data) => {
|
||||
console.log('data', data);
|
||||
state.updateNode(nodeId, { ...node, ...data });
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||
import { Command } from 'cmdk';
|
||||
import { ReactNode, useRef } from 'react';
|
||||
|
||||
@@ -48,7 +49,12 @@ export const QuickSearch = ({
|
||||
return (
|
||||
<>
|
||||
<QuickSearchStyle />
|
||||
<div className="quick-search-container">
|
||||
<div
|
||||
className="quick-search-container"
|
||||
onKeyDown={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<Command label={label} shouldFilter={false} ref={ref}>
|
||||
{showInput && (
|
||||
<QuickSearchInput
|
||||
|
||||
@@ -57,6 +57,9 @@ export const QuickSearchInput = ({
|
||||
/* eslint-disable-next-line jsx-a11y/no-autofocus */
|
||||
autoFocus={true}
|
||||
aria-label={t('Quick search input')}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
value={inputValue}
|
||||
role="combobox"
|
||||
placeholder={placeholder ?? t('Search')}
|
||||
|
||||
@@ -56,6 +56,8 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
|
||||
const { toast } = useToastProvider();
|
||||
const copyDocLink = useCopyDocLink(doc.id);
|
||||
|
||||
|
||||
|
||||
const options: DropdownMenuOption[] = [
|
||||
...(isSmallMobile
|
||||
? [
|
||||
|
||||
+32
-11
@@ -1,9 +1,11 @@
|
||||
import { Button, Modal, ModalSize } from '@openfun/cunningham-react';
|
||||
import { Button, Input, Modal, ModalSize } from '@openfun/cunningham-react';
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Box, Text } from '@/components';
|
||||
import { useTreeStore } from '@/components/common/tree/treeStore';
|
||||
|
||||
import { useUpdateDoc } from '../api';
|
||||
import { Doc } from '../types';
|
||||
|
||||
interface ModalRenameDocProps {
|
||||
@@ -13,7 +15,25 @@ interface ModalRenameDocProps {
|
||||
|
||||
export const ModalRenameDoc = ({ onClose, doc }: ModalRenameDocProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { updateNode } = useTreeStore();
|
||||
const { mutate: updateDoc } = useUpdateDoc();
|
||||
const [title, setTitle] = useState(doc.title);
|
||||
|
||||
const onRename = () => {
|
||||
updateDoc(
|
||||
{
|
||||
id: doc.id,
|
||||
title,
|
||||
},
|
||||
{
|
||||
onSuccess: (doc) => {
|
||||
updateNode(doc.id, doc);
|
||||
onClose();
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
closeOnClickOutside
|
||||
@@ -35,27 +55,28 @@ export const ModalRenameDoc = ({ onClose, doc }: ModalRenameDocProps) => {
|
||||
>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
aria-label={t('Confirm rename')}
|
||||
fullWidth
|
||||
onClick={() => console.log('rename', title)}
|
||||
>
|
||||
<Button aria-label={t('Confirm rename')} fullWidth onClick={onRename}>
|
||||
{t('Rename')}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Box $padding={{ top: 'base' }}>
|
||||
<input
|
||||
<Input
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
defaultValue={title}
|
||||
// label={t('Nom du document')}
|
||||
onKeyDown={(e) => {
|
||||
e.stopPropagation();
|
||||
if (e.key === 'Enter') {
|
||||
onRename();
|
||||
}
|
||||
}}
|
||||
value={title}
|
||||
label={t('Document name')}
|
||||
onChange={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
setTitle(e.target.value);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -43,6 +43,7 @@ export interface Doc {
|
||||
link_reach: LinkReach;
|
||||
link_role: LinkRole;
|
||||
nb_accesses: number;
|
||||
depth: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
numchild: number;
|
||||
|
||||
+20
-8
@@ -9,6 +9,7 @@ import { css } from 'styled-components';
|
||||
|
||||
import { APIError } from '@/api';
|
||||
import { Box } from '@/components';
|
||||
import { useTreeStore } from '@/components/common/tree/treeStore';
|
||||
import { useCunninghamTheme } from '@/cunningham';
|
||||
import { User } from '@/features/auth';
|
||||
import { Doc, Role } from '@/features/docs';
|
||||
@@ -39,6 +40,7 @@ export const DocShareAddMemberList = ({
|
||||
afterInvite,
|
||||
}: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const { refreshNode } = useTreeStore();
|
||||
const { toast } = useToastProvider();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { spacingsTokens, colorsTokens } = useCunninghamTheme();
|
||||
@@ -94,14 +96,24 @@ export const DocShareAddMemberList = ({
|
||||
};
|
||||
|
||||
return isInvitationMode
|
||||
? createInvitation({
|
||||
...payload,
|
||||
email: user.email,
|
||||
})
|
||||
: createDocAccess({
|
||||
...payload,
|
||||
memberId: user.id,
|
||||
});
|
||||
? createInvitation(
|
||||
{
|
||||
...payload,
|
||||
email: user.email,
|
||||
},
|
||||
{
|
||||
onSuccess: () => refreshNode(doc.id),
|
||||
},
|
||||
)
|
||||
: createDocAccess(
|
||||
{
|
||||
...payload,
|
||||
memberId: user.id,
|
||||
},
|
||||
{
|
||||
onSuccess: () => refreshNode(doc.id),
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
const settledPromises = await Promise.allSettled(promises);
|
||||
|
||||
+14
-6
@@ -7,6 +7,7 @@ import {
|
||||
DropdownMenuOption,
|
||||
IconOptions,
|
||||
} from '@/components';
|
||||
import { useTreeStore } from '@/components/common/tree/treeStore';
|
||||
import { useCunninghamTheme } from '@/cunningham';
|
||||
import { Access, Doc, Role } from '@/features/docs/doc-management/';
|
||||
import { useResponsiveStore } from '@/stores';
|
||||
@@ -23,6 +24,7 @@ type Props = {
|
||||
};
|
||||
export const DocShareMemberItem = ({ doc, access }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const { refreshNode } = useTreeStore();
|
||||
const { isLastOwner, isOtherOwner } = useWhoAmI(access);
|
||||
const { toast } = useToastProvider();
|
||||
const { isDesktop } = useResponsiveStore();
|
||||
@@ -48,15 +50,21 @@ export const DocShareMemberItem = ({ doc, access }: Props) => {
|
||||
});
|
||||
|
||||
const onUpdate = (newRole: Role) => {
|
||||
updateDocAccess({
|
||||
docId: doc.id,
|
||||
role: newRole,
|
||||
accessId: access.id,
|
||||
});
|
||||
updateDocAccess(
|
||||
{
|
||||
docId: doc.id,
|
||||
role: newRole,
|
||||
accessId: access.id,
|
||||
},
|
||||
{ onSuccess: () => refreshNode(doc.id) },
|
||||
);
|
||||
};
|
||||
|
||||
const onRemove = () => {
|
||||
removeDocAccess({ accessId: access.id, docId: doc.id });
|
||||
removeDocAccess(
|
||||
{ accessId: access.id, docId: doc.id },
|
||||
{ onSuccess: () => refreshNode(doc.id) },
|
||||
);
|
||||
};
|
||||
|
||||
const moreActions: DropdownMenuOption[] = [
|
||||
|
||||
@@ -153,7 +153,12 @@ export const DocTree = ({ docId }: Props) => {
|
||||
</Box>
|
||||
</Box>
|
||||
</SeparatedSection>
|
||||
<Box $padding={{ all: 'sm' }} $margin={{ top: '-35px' }} $width="100%">
|
||||
<Box
|
||||
$padding={{ all: 'sm' }}
|
||||
$margin={{ top: '-35px' }}
|
||||
$width="100%"
|
||||
tabIndex={-1}
|
||||
>
|
||||
{initialOpenState && treeDataStore.length > 0 && (
|
||||
<TreeView
|
||||
initialOpenState={initialOpenState}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { css } from 'styled-components';
|
||||
|
||||
import { Box, Text } from '@/components';
|
||||
import { Box, Icon, Text } from '@/components';
|
||||
import { useCunninghamTheme } from '@/cunningham';
|
||||
import { Doc } from '@/features/docs/doc-management';
|
||||
|
||||
@@ -13,7 +13,7 @@ const ItemTextCss = css`
|
||||
white-space: initial;
|
||||
display: -webkit-box;
|
||||
line-clamp: 1;
|
||||
width: 100%;
|
||||
/* width: 100%; */
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
`;
|
||||
@@ -39,11 +39,12 @@ export const LightDocItem = ({
|
||||
$align="center"
|
||||
$css={css`
|
||||
.light-doc-item-actions {
|
||||
display: ${showActions ? 'flex' : 'none'};
|
||||
opacity: 0;
|
||||
display: 'flex';
|
||||
}
|
||||
&:hover {
|
||||
.light-doc-item-actions {
|
||||
display: flex;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`}
|
||||
@@ -52,9 +53,24 @@ export const LightDocItem = ({
|
||||
<Logo />
|
||||
</Box>
|
||||
|
||||
<Text $css={ItemTextCss} $size="sm">
|
||||
{doc.title}
|
||||
</Text>
|
||||
<Box
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$css={css`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
`}
|
||||
>
|
||||
<Text $css={ItemTextCss} $size="sm">
|
||||
{doc.title}
|
||||
</Text>
|
||||
{doc.nb_accesses - doc.depth > 1 && (
|
||||
<Icon isFilled iconName="group" $size="16px" $variation="400" />
|
||||
)}
|
||||
</Box>
|
||||
{rightContent && (
|
||||
<Box
|
||||
$direction="row"
|
||||
|
||||
@@ -48,7 +48,6 @@ export const LeftPanel = () => {
|
||||
width: 100%;
|
||||
min-width: 300px;
|
||||
overflow: hidden;
|
||||
border-right: 1px solid ${colors['greyscale-200']};
|
||||
`}
|
||||
>
|
||||
<Box
|
||||
|
||||
@@ -20,9 +20,7 @@ const calculateDefaultSize = (targetWidth: number, isDesktop: boolean) => {
|
||||
return 0;
|
||||
}
|
||||
const windowWidth = window.innerWidth;
|
||||
console.log('windowWidth', windowWidth);
|
||||
return (targetWidth / windowWidth) * 100;
|
||||
// On limite le pourcentage entre 20 et 40 pour éviter des panneaux trop petits ou trop grands
|
||||
};
|
||||
|
||||
export function MainLayout({
|
||||
@@ -83,7 +81,12 @@ export function MainLayout({
|
||||
>
|
||||
<LeftPanel />
|
||||
</Panel>
|
||||
<PanelResizeHandle />
|
||||
<PanelResizeHandle
|
||||
style={{
|
||||
width: '1px',
|
||||
backgroundColor: colors['greyscale-200'],
|
||||
}}
|
||||
/>
|
||||
<Panel>
|
||||
<Box
|
||||
as="main"
|
||||
|
||||
Reference in New Issue
Block a user