-
-
Notifications
You must be signed in to change notification settings - Fork 405
Adds download/upload attachment archive UIs #1551
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Deployed commit |
I know this is still a draft but I gave it a try. Basic functionality works for me - some quick notes:
The download UI has clearly had some thought put into it, thanks for that! |
Deployed commit |
# Conflicts: # app/client/ui/GristTooltips.ts
1ca1afb
to
714c645
Compare
Deployed commit |
Deployed commit |
Deployed commit |
Deployed commit |
Deployed commit |
Deployed commit |
Deployed commit |
assert.equal(downloadUrl.pathname, idealUrl.pathname, "wrong download link called"); | ||
assert.equal(downloadUrl.search, idealUrl.search, "wrong search parameters in url"); | ||
// Ensures the page isn't modified / navigated away from by the link, as subsequent tests will fail. | ||
await driver.find('.test-external-attachments-info a').click(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you clicking this link here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a bug with the link, where it accidentally changes the current page instead of downloading the .tar file.
This clicks it, because if that bug re-occurred then all tests after this one would break.
Although actually, this might be better handled either as a separate test or with additional checks that the current window's URL hasn't changed.
test/nbrowser/AttachmentsTransfer.ts
Outdated
response.data, | ||
fs.createWriteStream(path.join(tmpDownloadsFolder, fileName)) | ||
); | ||
assert.include(await fse.readdir(tmpDownloadsFolder), 'attachments.tar', "attachments file wasn't downloaded"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you test first that this file is not there, before downloading it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, can add that!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
if (!file) { | ||
return; | ||
} | ||
isUploadingObs.set(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the presence of the comment above, I think it is better to test if the owner is not disposed after promise returns? (Here and below).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean, can you describe the change in more detail?
Are you suggesting we check if the owner is disposed before setting the observable? If so, for my benefit learning GrainJS, what's the reason to do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are doing an async operation. By the time the promise is resolved, someone could move to another page, destroying all observables you are setting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've pushed some guards for this. Is this something that Observables should be handling internally?
It feels like once disposed, they should either error or do nothing if set
is called on them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know if the additional checks are sufficient!
app/client/ui/GristTooltips.ts
Outdated
"If you want to re-import this document, " + | ||
"a separate attachments archive will be needed to restore attachments. " | ||
), | ||
dom('div', cssLink({href: "", target: "_blank"}, t('Learn more.'))), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a stub in common urls?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll go a step further and delete this - this was actually dead code, I just realised. Will double check the rest of the PR too.
app/client/ui/MakeCopyMenu.ts
Outdated
|
||
// Prevents the div from expanding the parent and makes it only use available space instead. | ||
const cssEagerWrap = styled('div', ` | ||
min-width: 100%; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very hacky, didn't know this trick. Wdyt about modern alternative ?
contain: inline-size;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oooh, this is nice. Seems to do the same job in practice. Much cleaner than the hack above too.
Weird that this didn't come up when I was searching for options here!
Pushed this fix.
() => downloadAttachmentsModal(doc, pageModel), | ||
menuIcon('Download'), | ||
t('Download attachments...'), | ||
testId('tb-share-option'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we call this testId in some other way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's convention for everything in this list to have the same test id right now (tb-share-option).
I'm happy to fix that - but it needs to be a separate PR or two, as SaaS uses these test ids too.
@@ -1200,7 +1220,7 @@ export class DocAPIImpl extends BaseAPI implements DocAPI { | |||
|
|||
public async uploadAttachment(value: string | Blob, filename?: string): Promise<number> { | |||
const formData = this.newFormData(); | |||
formData.append('upload', value as Blob, filename); | |||
formData.append('upload', value, filename); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, why we don't need it anymore? (Maybe it was needed in saas build).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FormData
objects natively accept string | Blob
in .append
. I just looked through the Git history, and couldn't see any obvious reason why this was added. Maybe the types accepted by FormData.append
changed?
Seems fine now either way!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will check in saas's version of typescript. I remember I was the one added it as the types were complaining.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, let me know if it complains :)
app/common/UserAPI.ts
Outdated
data: formData, | ||
// On browser, it is important not to set Content-Type so that the browser takes care | ||
// of setting HTTP headers appropriately. Outside browser, requestAxios has logic | ||
// for setting the HTTP headers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have any links to reference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did some digging, and found a link which describes why this is important.
I updated the comment to this:
// On the browser, Content-Type shouldn't be set as it prevents the browser from setting
// Content-Type with the correct boundary expression to delimit form fields.
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects#sending_files_using_a_formdata_object
// Therefore we omit Content-Type, and allow Axios to handle it as it sees fit - which works
// correctly in the browser and in Node.
app/client/lib/uploads.ts
Outdated
* @param {ProgressCB} onProgress - Called periodically during the upload | ||
* @returns {Promise<any>} - Parsed JSON from the endpoint. Uses `any` as no validation is performed. | ||
*/ | ||
export async function uploadFormData( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this used anywhere else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only in 'uploadFiles', which it was extracted from.
It was going to be used elsewhere, but I guess I went a different route.
I'm happy to leave this in though if you are, as it splits up a long function (uploadFiles
), making it more readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine with leaving, maybe just remove the export, to detect dead code more easily in the future.
# Conflicts: # app/client/ui/MakeCopyMenu.ts
Deployed commit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch - looks like I didn't set the condition correctly for documents with no attachments. I've fixed that now! |
Deployed commit |
Deployed commit |
@@ -335,5 +426,24 @@ async function waitForNotPresent(fn: () => WebElementPromise) { | |||
|
|||
const attachmentSection = () => driver.find('.test-admin-panel-item-preferredStorage'); | |||
|
|||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be removed
Context
The API supports:
Neither of these functionalities is exposed via the UI currently.
Proposed solution
This PR adds:
Screenshots will be added in the near future, this is currently in draft to allow previews.
Related issues
#1021
Has this been tested?
Screenshots / Screencasts