⭐️ Writeable shared links part 1 (#66)
* Minor fixes and implemented writeable shared links (no security) * Go t onode 16 for frontend
This commit is contained in:
@@ -44,7 +44,7 @@ jobs:
|
||||
path: tdrive/frontend/build/
|
||||
|
||||
publish-frontend:
|
||||
# needs: build-frontend
|
||||
# needs: build-frontend
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/qa' || github.ref == 'refs/heads/canary'
|
||||
steps:
|
||||
|
||||
@@ -51,24 +51,6 @@ class CurrentUser extends Observable {
|
||||
return getUser(Login.currentUserId);
|
||||
}
|
||||
|
||||
updateUserStatus = (newStatus: string[]) => {
|
||||
return () => {
|
||||
const { updateStatus } = useCurrentUser();
|
||||
updateStatus(newStatus);
|
||||
};
|
||||
};
|
||||
|
||||
async updateStatusIcon(status: string[]) {
|
||||
const update = {
|
||||
id: Login.currentUserId,
|
||||
status_icon: status,
|
||||
};
|
||||
|
||||
Collections.get('users').updateObject(update);
|
||||
this.updateUserStatus(status);
|
||||
await UserAPIClient.updateUserStatus(`${status[0]} ${status[1]}`);
|
||||
}
|
||||
|
||||
updateTutorialStatus(key: string, set_false?: unknown) {
|
||||
const user = this.get();
|
||||
if (!user) {
|
||||
|
||||
@@ -106,7 +106,9 @@ export const useCurrentCompanyRealtime = () => {
|
||||
* @param user
|
||||
* @returns CompanyType | undefined
|
||||
*/
|
||||
export function useBestCandidateCompany(user: UserType | undefined): CompanyType | undefined {
|
||||
export function useBestCandidateCompany(
|
||||
user: UserType | undefined | null,
|
||||
): CompanyType | undefined {
|
||||
const routerCompanyId = useRouterCompany();
|
||||
const storageCompanyId = (LocalStorage.getItem('default_company_id') as string) || null;
|
||||
|
||||
|
||||
@@ -24,6 +24,10 @@ export const setPublicLinkToken = (token: string | null) => {
|
||||
publicLinkToken = token;
|
||||
};
|
||||
|
||||
export const getPublicLinkToken = () => {
|
||||
return publicLinkToken;
|
||||
};
|
||||
|
||||
export const setTdriveTabToken = (token: string | null) => {
|
||||
tdriveTabToken = token;
|
||||
};
|
||||
|
||||
@@ -6,18 +6,17 @@ import { useRecoilState } from 'recoil';
|
||||
import { CurrentUserState } from '../state/atoms/current-user';
|
||||
import { useRealtimeRoom } from '@features/global/hooks/use-realtime';
|
||||
import Languages from '@features/global/services/languages-service';
|
||||
import { RealtimeApplicationEvent } from '@features/global/types/realtime-types';
|
||||
import { useSetUserList } from './use-user-list';
|
||||
import { getPublicLinkToken } from 'app/features/drive/api-client/api-client';
|
||||
|
||||
export const useCurrentUser = () => {
|
||||
console.log("getting current user");
|
||||
const [user, setUser] = useRecoilState(CurrentUserState);
|
||||
const { set: setUserList } = useSetUserList('useCurrentUser');
|
||||
|
||||
//Depreciated way to get use update from LoginService
|
||||
LoginService.recoilUpdateUser = setUser;
|
||||
useEffect(() => {
|
||||
if (!user) {
|
||||
if (!user && !getPublicLinkToken()) {
|
||||
LoginService.init();
|
||||
LoginService.login({});
|
||||
}
|
||||
@@ -29,17 +28,13 @@ export const useCurrentUser = () => {
|
||||
if (user?.preferences?.locale) Languages.setLanguage(user?.preferences?.locale);
|
||||
}, [user?.preferences?.locale]);
|
||||
|
||||
const updateStatus = async (userStatus: string[]) => {
|
||||
await UserAPIClient.updateUserStatus(`${userStatus[0]} ${userStatus[1]}`);
|
||||
|
||||
await refresh();
|
||||
};
|
||||
|
||||
const refresh = async () => {
|
||||
await LoginService.updateUser();
|
||||
if (!getPublicLinkToken()) {
|
||||
await LoginService.updateUser();
|
||||
}
|
||||
};
|
||||
|
||||
return { user, refresh, updateStatus };
|
||||
return { user, refresh };
|
||||
};
|
||||
|
||||
export const useCurrentUserRealtime = () => {
|
||||
|
||||
@@ -118,7 +118,7 @@ export default memo(
|
||||
return (
|
||||
<UploadZone
|
||||
overClassName={''}
|
||||
className="min-h-full"
|
||||
className="h-full overflow-hidden"
|
||||
disableClick
|
||||
parent={''}
|
||||
multiple={true}
|
||||
@@ -146,7 +146,7 @@ export default memo(
|
||||
|
||||
<div
|
||||
className={
|
||||
'flex flex-col grow h-full overflow-auto ' +
|
||||
'flex flex-col grow h-full overflow-hidden ' +
|
||||
(loading && (!children?.length || loadingParentChange) ? 'opacity-50 ' : '')
|
||||
}
|
||||
>
|
||||
@@ -167,7 +167,7 @@ export default memo(
|
||||
</Menu>
|
||||
</div>
|
||||
|
||||
<div className="grow">
|
||||
<div className="grow overflow-auto">
|
||||
{folders.length > 0 && (
|
||||
<>
|
||||
<Title className="mb-2 block">Folders</Title>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { PropertiesModalAtom } from './modals/properties';
|
||||
import { SelectorModalAtom } from './modals/selector';
|
||||
import { AccessModalAtom } from './modals/update-access';
|
||||
import { VersionsModalAtom } from './modals/versions';
|
||||
import { DriveApiClient } from '@features/drive/api-client/api-client';
|
||||
import { DriveApiClient, getPublicLinkToken } from '@features/drive/api-client/api-client';
|
||||
import { useDriveActions } from '@features/drive/hooks/use-drive-actions';
|
||||
import { getPublicLink } from '@features/drive/hooks/use-drive-item';
|
||||
import { useDrivePreview } from '@features/drive/hooks/use-drive-preview';
|
||||
@@ -71,8 +71,8 @@ export const useOnBuildContextMenu = (children: DriveItem[], initialParentId?: s
|
||||
},
|
||||
{
|
||||
type: 'menu',
|
||||
text: 'Manage access',
|
||||
hide: access === 'read',
|
||||
text: 'Manage access and sharing',
|
||||
hide: access === 'read' || getPublicLinkToken(),
|
||||
onClick: () => setAccessModalState({ open: true, id: item.id }),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -95,7 +95,7 @@ const PathItem = ({
|
||||
href="#"
|
||||
className="text-sm font-medium text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white"
|
||||
onClick={evt => {
|
||||
if (first) {
|
||||
if (first && user?.id) {
|
||||
MenusManager.openMenu(
|
||||
[
|
||||
{ type: 'menu', text: 'Home', onClick: () => onClick('root') },
|
||||
@@ -114,7 +114,7 @@ const PathItem = ({
|
||||
{item?.access_info?.public?.level && item?.access_info?.public?.level !== 'none' && (
|
||||
<PublicIcon className="h-5 w-5 ml-2" />
|
||||
)}
|
||||
{first && (
|
||||
{first && !!user?.id && (
|
||||
<span className="ml-2 -mr-1 text-gray-700">
|
||||
<ChevronDownIcon className="w-4 h-4" />
|
||||
</span>
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ export const PublicLinkManager = ({ id, disabled }: { id: string; disabled?: boo
|
||||
</div>
|
||||
<div className="shrink-0">
|
||||
<AccessLevel
|
||||
hiddenLevels={['manage', 'write']}
|
||||
hiddenLevels={['manage']}
|
||||
disabled={loading || disabled}
|
||||
level={item?.access_info?.public?.level || null}
|
||||
onChange={level => {
|
||||
|
||||
@@ -6,15 +6,20 @@ import Languages from '@features/global/services/languages-service';
|
||||
import { addApiUrlIfNeeded } from '@features/global/utils/URLUtils';
|
||||
import RouterService from '@features/router/services/router-service';
|
||||
import Drive from '@views/client/body/drive';
|
||||
import { Button } from 'app/atoms/button/button';
|
||||
import { Input } from 'app/atoms/input/input-text';
|
||||
import { Base, Subtitle, Title } from 'app/atoms/text';
|
||||
import UploadsViewer from 'app/components/file-uploads/uploads-viewer';
|
||||
import { useDriveItem } from 'app/features/drive/hooks/use-drive-item';
|
||||
import { useDriveUpload } from 'app/features/drive/hooks/use-drive-upload';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import shortUUID from 'short-uuid';
|
||||
import Avatar from '../../../../atoms/avatar';
|
||||
import { setPublicLinkToken } from '../../../../features/drive/api-client/api-client';
|
||||
import useRouterCompany from '../../../../features/router/hooks/use-router-company';
|
||||
import { useDriveItem } from 'app/features/drive/hooks/use-drive-item';
|
||||
import { Base, Subtitle, Title } from 'app/atoms/text';
|
||||
import { Input } from 'app/atoms/input/input-text';
|
||||
import { Button } from 'app/atoms/button/button';
|
||||
import { CreateModalAtom } from './modals/create';
|
||||
import { CreateModalWithUploadZones } from '../../side-bar/actions';
|
||||
|
||||
export default () => {
|
||||
const companyId = useRouterCompany();
|
||||
@@ -71,6 +76,8 @@ export default () => {
|
||||
</AccessChecker>
|
||||
</div>
|
||||
<MenusBodyLayer />
|
||||
<UploadsViewer />
|
||||
<CreateModalWithUploadZones />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -46,7 +46,7 @@ export default React.memo((): JSX.Element => {
|
||||
<FeatureToggles features={activeFeatureNames}>
|
||||
<>
|
||||
<Header openSideMenu={() => setMenuIsOpen(true)} />
|
||||
<div className="grow flex flex-row grid-cols-2 sm:px-2 sm:pb-2">
|
||||
<div className="grow flex flex-row grid-cols-2 sm:px-2 sm:pb-2 overflow-hidden">
|
||||
<div
|
||||
style={
|
||||
menuIsOpen
|
||||
|
||||
@@ -12,72 +12,84 @@ import { ConfirmDeleteModalAtom } from '../body/drive/modals/confirm-delete';
|
||||
import { CreateModal, CreateModalAtom } from '../body/drive/modals/create';
|
||||
import { Button } from '@atoms/button/button';
|
||||
|
||||
export default () => {
|
||||
export const CreateModalWithUploadZones = () => {
|
||||
const companyId = useRouterCompany();
|
||||
const uploadZoneRef = useRef<UploadZone | null>(null);
|
||||
const uploadFolderZoneRef = useRef<UploadZone | null>(null);
|
||||
const setCreationModalState = useSetRecoilState(CreateModalAtom);
|
||||
const { uploadTree, uploadFromUrl } = useDriveUpload();
|
||||
const [parentId, _] = useRecoilState(DriveCurrentFolderAtom('root'));
|
||||
|
||||
return (
|
||||
<>
|
||||
<UploadZone
|
||||
overClassName={'!hidden'}
|
||||
className="hidden"
|
||||
disableClick
|
||||
parent={''}
|
||||
multiple={true}
|
||||
ref={uploadZoneRef}
|
||||
driveCollectionKey={'side-menu'}
|
||||
onAddFiles={async (_, event) => {
|
||||
const tree = await getFilesTree(event);
|
||||
setCreationModalState({ parent_id: '', open: false });
|
||||
uploadTree(tree, {
|
||||
companyId,
|
||||
parentId,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<UploadZone
|
||||
overClassName={'!hidden'}
|
||||
className="hidden"
|
||||
disableClick
|
||||
parent={''}
|
||||
multiple={true}
|
||||
ref={uploadFolderZoneRef}
|
||||
directory={true}
|
||||
driveCollectionKey={'side-menu'}
|
||||
onAddFiles={async (_, event) => {
|
||||
const tree = await getFilesTree(event);
|
||||
setCreationModalState({ parent_id: '', open: false });
|
||||
uploadTree(tree, {
|
||||
companyId,
|
||||
parentId,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<CreateModal
|
||||
selectFolderFromDevice={() => uploadFolderZoneRef.current?.open()}
|
||||
selectFromDevice={() => uploadZoneRef.current?.open()}
|
||||
addFromUrl={(url, name) => {
|
||||
setCreationModalState({ parent_id: '', open: false });
|
||||
uploadFromUrl(url, name, {
|
||||
companyId,
|
||||
parentId,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default () => {
|
||||
const [parentId, _] = useRecoilState(DriveCurrentFolderAtom('root'));
|
||||
const { access, item, inTrash } = useDriveItem(parentId);
|
||||
const { children: trashChildren } = useDriveItem('trash');
|
||||
const uploadZoneRef = useRef<UploadZone | null>(null);
|
||||
const uploadFolderZoneRef = useRef<UploadZone | null>(null);
|
||||
|
||||
const setConfirmDeleteModalState = useSetRecoilState(ConfirmDeleteModalAtom);
|
||||
const setCreationModalState = useSetRecoilState(CreateModalAtom);
|
||||
const { uploadTree, uploadFromUrl } = useDriveUpload();
|
||||
|
||||
const openItemModal = useCallback(() => {
|
||||
if (item?.id) setCreationModalState({ open: true, parent_id: item.id });
|
||||
}, [item?.id, setCreationModalState]);
|
||||
|
||||
return (
|
||||
<div className="-m-4">
|
||||
<div className="-m-4 overflow-hidden">
|
||||
<AnimatedHeight>
|
||||
<div className="p-4">
|
||||
<UploadZone
|
||||
overClassName={'!hidden'}
|
||||
className="hidden"
|
||||
disableClick
|
||||
parent={''}
|
||||
multiple={true}
|
||||
ref={uploadZoneRef}
|
||||
driveCollectionKey={'side-menu'}
|
||||
onAddFiles={async (_, event) => {
|
||||
const tree = await getFilesTree(event);
|
||||
setCreationModalState({ parent_id: '', open: false });
|
||||
uploadTree(tree, {
|
||||
companyId,
|
||||
parentId,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<UploadZone
|
||||
overClassName={'!hidden'}
|
||||
className="hidden"
|
||||
disableClick
|
||||
parent={''}
|
||||
multiple={true}
|
||||
ref={uploadFolderZoneRef}
|
||||
directory={true}
|
||||
driveCollectionKey={'side-menu'}
|
||||
onAddFiles={async (_, event) => {
|
||||
const tree = await getFilesTree(event);
|
||||
setCreationModalState({ parent_id: '', open: false });
|
||||
uploadTree(tree, {
|
||||
companyId,
|
||||
parentId,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<CreateModal
|
||||
selectFolderFromDevice={() => uploadFolderZoneRef.current?.open()}
|
||||
selectFromDevice={() => uploadZoneRef.current?.open()}
|
||||
addFromUrl={(url, name) => {
|
||||
setCreationModalState({ parent_id: '', open: false });
|
||||
uploadFromUrl(url, name, {
|
||||
companyId,
|
||||
parentId,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<CreateModalWithUploadZones />
|
||||
|
||||
{inTrash && access === 'manage' && (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user