Skip to content

Commit

Permalink
Improved attribute editor for the versionTag conflicts on a debounced…
Browse files Browse the repository at this point in the history
…Change;
  • Loading branch information
stef-coenen committed Sep 19, 2023
1 parent 1956396 commit 582741f
Show file tree
Hide file tree
Showing 14 changed files with 112 additions and 224 deletions.
6 changes: 3 additions & 3 deletions packages/js-lib/src/core/DriveData/DriveUploadProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const uploadFile = async (
thumbnails?: ThumbnailFile[],
encrypt = true,
onVersionConflict?: () => void
): Promise<UploadResult> => {
): Promise<UploadResult | void> => {
const keyHeader = encrypt ? GenerateKeyHeader() : undefined;
return uploadUsingKeyHeader(
dotYouClient,
Expand All @@ -47,7 +47,7 @@ const uploadUsingKeyHeader = async (
payload: Uint8Array | File | Blob | undefined,
thumbnails?: ThumbnailFile[],
onVersionConflict?: () => void
): Promise<UploadResult> => {
): Promise<UploadResult | void> => {
// Rebuild instructions without the systemFileType
const strippedInstructions: UploadInstructionSet = {
storageOptions: instructions.storageOptions,
Expand Down Expand Up @@ -88,7 +88,7 @@ export const uploadHeader = async (
encryptedKeyHeader: EncryptedKeyHeader | undefined,
instructions: UploadInstructionSet,
metadata: UploadFileMetadata
): Promise<UploadResult> => {
): Promise<UploadResult | void> => {
const keyHeader = encryptedKeyHeader
? await decryptKeyHeader(dotYouClient, encryptedKeyHeader)
: undefined;
Expand Down
9 changes: 7 additions & 2 deletions packages/js-lib/src/core/DriveData/UploadHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { DotYouClient } from '../DotYouClient';

import { TransitInstructionSet } from '../../transit/TransitData/TransitTypes';
import { KeyHeader } from './DriveTypes';
import { UploadFileMetadata, UploadInstructionSet, AppendInstructionSet } from './DriveUploadTypes';
import {
UploadFileMetadata,
UploadInstructionSet,
AppendInstructionSet,
UploadResult,
} from './DriveUploadTypes';
import { encryptWithKeyheader, encryptWithSharedSecret, encryptKeyHeader } from './SecurityHelpers';
import {
jsonStringify64,
Expand Down Expand Up @@ -141,7 +146,7 @@ export const pureUpload = async (
};

return client
.post(url, data, config)
.post<UploadResult>(url, data, config)
.then((response) => {
return response.data;
})
Expand Down
3 changes: 2 additions & 1 deletion packages/js-lib/src/core/MediaData/ImageProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,15 @@ export const uploadImage = async (
accessControlList: acl,
};

const result: UploadResult = await uploadFile(
const result = await uploadFile(
dotYouClient,
instructionSet,
metadata,
imageData,
additionalThumbnails,
encrypt
);
if (!result) throw new Error(`Upload failed`);

return { fileId: result.file.fileId, previewThumbnail, type: 'image' };
};
Expand Down
3 changes: 2 additions & 1 deletion packages/js-lib/src/core/MediaData/VideoProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,15 @@ export const uploadVideo = async (
accessControlList: acl,
};

const result: UploadResult = await uploadFile(
const result = await uploadFile(
dotYouClient,
instructionSet,
metadata,
file,
additionalThumbnails,
encrypt
);
if (!result) throw new Error(`Upload failed`);

return { fileId: result.file.fileId, type: 'video' };
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,9 @@ const processAttribute = async (dotYouClient: DotYouClient, attribute: Attribute

export const saveAttribute = async (
dotYouClient: DotYouClient,
toSaveAttribute: AttributeFile
): Promise<AttributeFile> => {
toSaveAttribute: AttributeFile,
onVersionConflict?: () => void
): Promise<AttributeFile | undefined> => {
// Process Attribute
const attr = await processAttribute(dotYouClient, toSaveAttribute);

Expand Down Expand Up @@ -349,17 +350,20 @@ export const saveAttribute = async (
accessControlList: attr.acl,
};

const result: UploadResult = await uploadFile(
const result = await uploadFile(
dotYouClient,
instructionSet,
metadata,
payloadBytes,
undefined,
encrypt
encrypt,
onVersionConflict
);
if (!result) return;

//update server-side info
attr.fileId = result.file.fileId;
attr.versionTag = result.newVersionTag;
return attr;
};

Expand Down
12 changes: 11 additions & 1 deletion packages/js-lib/src/public/posts/PostDefinitionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,17 @@ export const saveChannelDefinition = async (
accessControlList: definition.acl,
};

return await uploadFile(dotYouClient, instructionSet, metadata, payloadBytes, undefined, encrypt);
const result = await uploadFile(
dotYouClient,
instructionSet,
metadata,
payloadBytes,
undefined,
encrypt
);
if (!result) throw new Error(`Upload failed`);

return result;
};

export const removeChannelDefinition = async (dotYouClient: DotYouClient, channelId: string) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/js-lib/src/public/posts/PostProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,14 +280,15 @@ export const savePost = async <T extends PostContent>(
accessControlList: file.acl,
};

const result: UploadResult = await uploadFile(
const result = await uploadFile(
dotYouClient,
instructionSet,
metadata,
payloadBytes,
undefined,
encrypt
);
if (!result) throw new Error(`Upload failed`);

return result;
};
Expand Down
3 changes: 2 additions & 1 deletion packages/js-lib/src/public/posts/PostReactionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,15 @@ export const saveComment = async (
};

// Use owner/youauth endpoint for reactions if the post to comment on is on the current root identity
const result: UploadResult = await uploadFile(
const result = await uploadFile(
dotYouClient,
instructionSet,
metadata,
payloadBytes,
additionalThumbnails,
encrypt
);
if (!result) throw new Error(`Upload failed`);

return result.globalTransitIdFileIdentifier.globalTransitId;
} else {
Expand Down
2 changes: 0 additions & 2 deletions packages/owner-app/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ const DriveDetails = lazy(() => import('../templates/Drives/DriveDetails/DriveDe
const Settings = lazy(() => import('../templates/Settings/Settings'));

const DemoData = lazy(() => import('../templates/DemoData/DemoData'));
const SocketDemo = lazy(() => import('../templates/DemoData/SocketDemo'));

const SocialFeed = lazy(() =>
import('@youfoundation/feed-app').then((feedApp) => ({ default: feedApp.SocialFeed }))
Expand Down Expand Up @@ -192,7 +191,6 @@ function App() {
<Route path="settings/:sectionId" element={<Settings />}></Route>

<Route path="demo-data" element={<DemoData />}></Route>
<Route path="socket-demo" element={<SocketDemo />}></Route>

{/* Feed: */}
<Route path="feed">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { AclIcon, AclSummary, AclWizard, SaveStatus, Times, t } from '@youfoundation/common-app';
import useAttribute from '../../../hooks/profiles/useAttribute';
import { AttributeVm } from '../../../hooks/profiles/useAttributes';
Expand Down Expand Up @@ -26,77 +26,74 @@ const AttributeEditor = ({
}) => {
const [isNewAttribute, setIsNewAttribute] = useState(false);
const {
save: { mutate: saveAttr, status: saveStatus, error: saveError },
save: { data: updatedAttr, mutate: saveAttr, status: saveStatus, error: saveError },
remove: { mutate: removeAttr },
} = useAttribute({});
const [newAttr, setNewAttr] = useState({ ...attribute });

// Local state of the changes, for when it's a new attribute, as saving is manuel in that case
const [latestAttr, setLatestAttr] = useState<AttributeVm>({
...attribute,
...(updatedAttr || {}),
});

const [isAclEdit, setIsAclEdit] = useState(false);
const [isFadeOut, setIsFadeOut] = useState(false);
const sectionRef = useRef<HTMLElement>(null);

const saveNewData = (dirtyAttr: AttributeVm) => {
// Each save should above everything that might happen, remove the isNew state;
saveAttr({ ...dirtyAttr, data: { ...dirtyAttr.data, isNew: undefined } });
if (onSave) {
onSave();
}
const doSaveAttr = (dirtyAttr: AttributeVm) => {
saveAttr({ ...dirtyAttr });
if (onSave) onSave();
};

const changeHandler = (e: { target: { value: unknown; name: string } }) => {
const dirtyAttr = { ...newAttr };

dirtyAttr.data[e.target.name] = e.target.value;
// usCallback so the changeHandler changes less, so the the debounce is more effective
const changeHandler = useCallback(
(e: { target: { value: unknown; name: string } }) => {
const dirtyAttr = { ...latestAttr };
dirtyAttr.data[e.target.name] = e.target.value;

setNewAttr(dirtyAttr);
if (!isNewAttribute) {
saveNewData(dirtyAttr);
}
};
if (isNewAttribute) setLatestAttr(dirtyAttr);
else doSaveAttr(dirtyAttr);
},
[latestAttr, setLatestAttr]
);

const reorder = async (dir: 1 | -1) => {
const newPriority = reorderAttr && (await reorderAttr(attribute, dir));
if (!newPriority) {
return;
}
const dirtyAttr = { ...newAttr, priority: newPriority };
setNewAttr(dirtyAttr);
saveNewData(dirtyAttr);
if (!newPriority) return;

doSaveAttr({ ...latestAttr, priority: newPriority });
};

useEffect(() => {
if (attribute) {
if (attribute.data?.isNew) {
setIsNewAttribute(true);
if (!attribute.acl || attribute.data?.isNew) {
setIsAclEdit(true);
}

sectionRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' });
setTimeout(() => {
setIsFadeOut(true);
}, 500);
}
if (attribute && attribute.data?.isNew) {
setIsNewAttribute(true);
if (!attribute.acl || attribute.data?.isNew) setIsAclEdit(true);

setNewAttr({ ...attribute });
sectionRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' });
setTimeout(() => setIsFadeOut(true), 500);
}
}, [attribute]);

useEffect(() => {
setLatestAttr({ ...attribute, ...(updatedAttr || {}) });
}, [attribute, updatedAttr]);

return (
<Section
ref={sectionRef}
title={
<>
<span className="flex flex-row">
<button
title={newAttr.acl?.requiredSecurityGroup}
title={latestAttr.acl?.requiredSecurityGroup}
className={`mr-2 inline-block`}
onClick={() => setIsAclEdit(true)}
>
<AclIcon className="h-5 w-5" acl={newAttr.acl} />
<AclIcon className="h-5 w-5" acl={latestAttr.acl} />
</button>
<span onClick={() => setIsAclEdit(true)}>
{title ?? newAttr.typeDefinition.name}{' '}
<small className="block text-xs">{<AclSummary acl={newAttr.acl} />}</small>
{title ?? latestAttr.typeDefinition.name}{' '}
<small className="block text-xs">{<AclSummary acl={latestAttr.acl} />}</small>
</span>
</span>
</>
Expand Down Expand Up @@ -144,7 +141,7 @@ const AttributeEditor = ({
) : null}
</div>
{saveStatus === 'error' && !isNewAttribute ? (
<ActionButton state={saveStatus} type="primary" onClick={() => saveNewData(newAttr)}>
<ActionButton state={saveStatus} type="primary" onClick={() => doSaveAttr(latestAttr)}>
{t('Save')}
</ActionButton>
) : null}
Expand Down Expand Up @@ -199,32 +196,27 @@ const AttributeEditor = ({
>
{isAclEdit ? (
<AclWizard
acl={newAttr.acl}
acl={latestAttr.acl}
onConfirm={(newAcl) => {
setIsAclEdit(false);
const dirtyAttr = { ...latestAttr, acl: newAcl };

const dirtyAttr = { ...newAttr, acl: newAcl };
setNewAttr(dirtyAttr);

if (!isNewAttribute) {
saveNewData(dirtyAttr);
}
if (isNewAttribute) setLatestAttr(dirtyAttr);
else doSaveAttr(dirtyAttr);
}}
onCancel={() => {
if (isNewAttribute && onCancel) {
onCancel();
}
if (isNewAttribute && onCancel) onCancel();
setIsAclEdit(false);
}}
/>
) : (
<>
<AttributeFields attribute={newAttr} onChange={changeHandler} />
<AttributeFields attribute={latestAttr} onChange={changeHandler} />
<SaveStatus className="mt-2 text-right sm:mt-0" state={saveStatus} error={saveError} />
{isNewAttribute ? (
<div className="flex flex-row justify-end pb-2">
<p className="text-slate-500">
{t('Accessible by: ')} <AclSummary acl={newAttr?.acl} maxLength={Infinity} />
{t('Accessible by: ')} <AclSummary acl={latestAttr?.acl} maxLength={Infinity} />
</p>
</div>
) : null}
Expand All @@ -233,7 +225,7 @@ const AttributeEditor = ({
<ActionButton
type="primary"
className="ml-2"
onClick={() => saveNewData(newAttr)}
onClick={() => doSaveAttr(latestAttr)}
state={saveStatus}
>
{t('Save')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const AttributeFields = ({
attribute: AttributeVm;
onChange: (e: { target: { value: unknown; name: string } }) => void;
}) => {
const debouncedChange = useMemo(() => debounce(onChange, 500), [onChange]);
const debouncedChange = useMemo(() => debounce(onChange, 1000), [onChange]);

switch (attribute.type) {
case BuiltInAttributes.Name:
Expand Down
Loading

0 comments on commit 582741f

Please sign in to comment.