Skip to content

[ENG-10944] Files general improvement#983

Open
nsemets wants to merge 18 commits into
CenterForOpenScience:feature/pbs-26-9from
nsemets:fix/files
Open

[ENG-10944] Files general improvement#983
nsemets wants to merge 18 commits into
CenterForOpenScience:feature/pbs-26-9from
nsemets:fix/files

Conversation

@nsemets
Copy link
Copy Markdown
Collaborator

@nsemets nsemets commented May 7, 2026

Summary of Changes

  1. Clean up the code.
  2. Refactored files components.
  3. Updated code coverage for files.
  4. Added interfaces for files models.

@nsemets nsemets marked this pull request as ready for review May 12, 2026 11:29
@nsemets nsemets requested review from adlius and brianjgeiger May 12, 2026 11:31
const messageType = action === 'move' ? 'moveFile' : 'copyFile';
this.toastService.showError(errorMessage ?? `files.dialogs.${messageType}.error`);
moveFiles(): void {
this.isFilesUpdating.set(true);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed that isFilesUpdating is set to true when moveFiles() kicks off, but I don't see it being reset back to false anywhere in the pipe. The finalize at the end only resets the dialog header. So if the request errors out or gets cancelled mid-flight (e.g. component destroyed), I believe the button stays stuck in a loading/disabled state forever. Could we add finalize(() => this.isFilesUpdating.set(false)) to the pipe to cover that ?

Comment on lines +191 to +195
readonly headerTitle = computed(() => {
const fileName = this.file()?.name ?? '';
if (!this.fileVersion) return fileName;
return `${fileName} (${this.translateService.instant('project.wiki.version.title')} ${this.fileVersion})`;
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small heads up on this one, headerTitle is a computed() signal, but it's reading this.fileVersion which is a plain class property, not a signal. While angular's reactive graph only tracks signal reads inside computed, so when onOpenRevision() updates fileVersion, headerTitle won't recompute and the header will stay stale showing the original version. Would it make sense to convert fileVersion to a signal('') and use .set() in onOpenRevision?

@@ -131,9 +115,6 @@ export class FileSelectDestinationComponent implements OnInit {
const rootFolder = this.storageAddons().find((option) => option.folder.id === value);
if (rootFolder) {
this.currentRootFolder.set(rootFolder);
if (rootFolder.folder.provider) {
this.actions.setCurrentProvider(rootFolder.folder.provider);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the SetCurrentProvider dispatch got removed from onStorageChange(). Any code downstream that reads the current provider from the store will now get a stale value from whatever provider was selected before. Was this intentional? If so, happy to understand the reasoning, otherwise I think we need to restore that dispatch when the storage selection changes.

(entryFileClicked)="selectProjectFile($event)"
(setCurrentFolder)="setCurrentFolder($event)"
(fileOpened)="selectProjectFile($event)"
(currentFolderChanged)="setCurrentFolder($event)"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is an issue, you changed naming (currentFolderChanged) which is bound on osf-files-tree but those output names don't exist on the component. In this case, file open and folder navigation will be silently broken in the preprints file. Please verify this here and in other files as well I can see similar behavior in other files as well which might led to breaking up functionality

readonly storage = input.required<FileLabelModel | null>();

readonly totalCount = input<number>(0);
readonly isLoading = input<boolean>();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isLoading is declared as input<boolean>() with no default, so it initializes as undefined. The effect below treats undefined as falsy and immediately flips isLoadingMore to false on first render even if a load is actually in progress at that point. Setting a default of false and tightening the guard to if (this.isLoading() === false) would prevent that false-negative reset

Comment on lines +173 to +176
this.filesService.getFileGuid(file.id).subscribe((file) => {
if (file.guid) {
this.openFile(file.guid);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getFileGuid() subscription here doesn't have any cleanup attached. If the user navigates away while that HTTP request is still in flight, the subscription stays alive and will try to call router.navigate() after the component is destroyed. I think adding .pipe(takeUntilDestroyed(this.destroyRef)) before the .subscribe() should cover it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants