diff --git a/src/app/features/files/components/file-browser-info/file-browser-info.component.html b/src/app/features/files/components/file-browser-info/file-browser-info.component.html index f7e045c8b..fd409bd07 100644 --- a/src/app/features/files/components/file-browser-info/file-browser-info.component.html +++ b/src/app/features/files/components/file-browser-info/file-browser-info.component.html @@ -1,4 +1,14 @@
+ @if (isProjectReadOnly()) { +

+ {{ 'files.filesBrowserDialog.note' | translate }} + {{ 'files.filesBrowserDialog.readOnlyWarning' | translate }} + + {{ 'files.filesBrowserDialog.osfProjectTransition' | translate }} + +

+ } + @for (item of filteredInfoItems; track item.titleKey) {

{{ item.titleKey | translate }}

diff --git a/src/app/features/files/components/file-browser-info/file-browser-info.component.spec.ts b/src/app/features/files/components/file-browser-info/file-browser-info.component.spec.ts index f00920808..04f1e63c0 100644 --- a/src/app/features/files/components/file-browser-info/file-browser-info.component.spec.ts +++ b/src/app/features/files/components/file-browser-info/file-browser-info.component.spec.ts @@ -4,10 +4,12 @@ import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { UserSelectors } from '@osf/core/store/user/user.selectors'; import { ResourceType } from '@osf/shared/enums/resource-type.enum'; import { provideOSFCore } from '@testing/osf.testing.provider'; import { provideDynamicDialogRefMock } from '@testing/providers/dynamic-dialog-ref.mock'; +import { provideMockStore } from '@testing/providers/store-provider.mock'; import { FileBrowserInfoComponent } from './file-browser-info.component'; @@ -21,7 +23,14 @@ describe('FileBrowserInfoComponent', () => { TestBed.configureTestingModule({ imports: [FileBrowserInfoComponent], - providers: [provideOSFCore(), provideDynamicDialogRefMock(), MockProvider(DynamicDialogConfig, dialogConfigMock)], + providers: [ + provideOSFCore(), + provideDynamicDialogRefMock(), + MockProvider(DynamicDialogConfig, dialogConfigMock), + provideMockStore({ + signals: [{ selector: UserSelectors.isProjectReadOnly, value: false }], + }), + ], }); fixture = TestBed.createComponent(FileBrowserInfoComponent); diff --git a/src/app/features/files/components/file-browser-info/file-browser-info.component.ts b/src/app/features/files/components/file-browser-info/file-browser-info.component.ts index c628fbe70..9bb0f9704 100644 --- a/src/app/features/files/components/file-browser-info/file-browser-info.component.ts +++ b/src/app/features/files/components/file-browser-info/file-browser-info.component.ts @@ -1,3 +1,5 @@ +import { select } from '@ngxs/store'; + import { TranslatePipe } from '@ngx-translate/core'; import { Button } from 'primeng/button'; @@ -5,24 +7,26 @@ import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { UserSelectors } from '@osf/core/store/user/user.selectors'; import { ResourceType } from '@osf/shared/enums/resource-type.enum'; -import { FILE_BROWSER_INFO_ITEMS } from '../../constants'; +import { FILE_BROWSER_INFO_ITEMS, FILE_BROWSER_READ_ONLY_INFO_ITEMS } from '../../constants'; @Component({ selector: 'osf-file-browser-info', - imports: [Button, TranslatePipe], templateUrl: './file-browser-info.component.html', + imports: [Button, TranslatePipe], styleUrl: './file-browser-info.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) export class FileBrowserInfoComponent { readonly dialogRef = inject(DynamicDialogRef); readonly config = inject(DynamicDialogConfig); + readonly isProjectReadOnly = select(UserSelectors.isProjectReadOnly); readonly resourceType = (this.config.data as ResourceType) ?? ResourceType.Project; - readonly infoItems = FILE_BROWSER_INFO_ITEMS; + readonly infoItems = this.isProjectReadOnly() ? FILE_BROWSER_READ_ONLY_INFO_ITEMS : FILE_BROWSER_INFO_ITEMS; readonly filteredInfoItems = this.infoItems.filter((item) => item.showForResourceTypes.includes(this.resourceType)); } diff --git a/src/app/features/files/constants/file-browser-info.constants.ts b/src/app/features/files/constants/file-browser-info.constants.ts index 1de435ecb..266744cca 100644 --- a/src/app/features/files/constants/file-browser-info.constants.ts +++ b/src/app/features/files/constants/file-browser-info.constants.ts @@ -59,3 +59,31 @@ export const FILE_BROWSER_INFO_ITEMS: FileInfoItem[] = [ showForResourceTypes: [ResourceType.Project, ResourceType.Registration], }, ]; + +export const FILE_BROWSER_READ_ONLY_INFO_ITEMS: FileInfoItem[] = [ + { + titleKey: 'files.filesBrowserDialog.seeAllFiles', + descriptionKey: 'files.filesBrowserDialog.seeAllFilesDescription', + showForResourceTypes: [ResourceType.Project, ResourceType.Registration], + }, + { + titleKey: 'files.filesBrowserDialog.openViewFiles', + descriptionKey: 'files.filesBrowserDialog.openViewFilesDescription', + showForResourceTypes: [ResourceType.Project, ResourceType.Registration], + }, + { + titleKey: 'files.filesBrowserDialog.downloadAllFilesZip', + descriptionKey: 'files.filesBrowserDialog.downloadAllFilesZipDescription', + showForResourceTypes: [ResourceType.Project, ResourceType.Registration], + }, + { + titleKey: 'files.filesBrowserDialog.downloadFolderZip', + descriptionKey: 'files.filesBrowserDialog.downloadFolderZipDescription', + showForResourceTypes: [ResourceType.Project, ResourceType.Registration], + }, + { + titleKey: 'files.filesBrowserDialog.downloadFile', + descriptionKey: 'files.filesBrowserDialog.downloadFileDescription', + showForResourceTypes: [ResourceType.Project, ResourceType.Registration], + }, +]; diff --git a/src/app/features/project/overview/components/toggle-publicity-dialog/toggle-publicity-dialog.component.html b/src/app/features/project/overview/components/toggle-publicity-dialog/toggle-publicity-dialog.component.html index 0c14f5081..ce5a4ec61 100644 --- a/src/app/features/project/overview/components/toggle-publicity-dialog/toggle-publicity-dialog.component.html +++ b/src/app/features/project/overview/components/toggle-publicity-dialog/toggle-publicity-dialog.component.html @@ -10,7 +10,14 @@
  • {{ 'project.overview.dialog.makePrivate.messageItems.removedFromCollections' | translate }}
  • } @else { -

    +

    + @if (isProjectReadOnly()) { + + {{ 'project.overview.dialog.makePublic.warningReadOnly' | translate }} + + } @else { +

    + } } } @else {
    diff --git a/src/app/features/project/overview/components/toggle-publicity-dialog/toggle-publicity-dialog.component.ts b/src/app/features/project/overview/components/toggle-publicity-dialog/toggle-publicity-dialog.component.ts index db91999d4..07e28070d 100644 --- a/src/app/features/project/overview/components/toggle-publicity-dialog/toggle-publicity-dialog.component.ts +++ b/src/app/features/project/overview/components/toggle-publicity-dialog/toggle-publicity-dialog.component.ts @@ -4,6 +4,7 @@ import { TranslatePipe, TranslateService } from '@ngx-translate/core'; import { Button } from 'primeng/button'; import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; +import { Message } from 'primeng/message'; import { ChangeDetectionStrategy, @@ -31,7 +32,7 @@ import { ProjectOverviewSelectors, UpdateProjectPublicStatus } from '../../store @Component({ selector: 'osf-toggle-publicity-dialog', - imports: [Button, TranslatePipe, ComponentsSelectionListComponent, LoadingSpinnerComponent], + imports: [Button, Message, TranslatePipe, ComponentsSelectionListComponent, LoadingSpinnerComponent], templateUrl: './toggle-publicity-dialog.component.html', styleUrl: './toggle-publicity-dialog.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, @@ -56,11 +57,6 @@ export class TogglePublicityDialogComponent { componentsList: WritableSignal = signal([]); isInformationStep = computed(() => this.step() === TogglePublicityStep.Information); - makePublicMessage = computed(() => - this.isProjectReadOnly() - ? 'project.overview.dialog.makePublic.messageReadOnly' - : 'project.overview.dialog.makePublic.message' - ); constructor() { effect(() => { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 7b2257ab0..d2532757d 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -723,8 +723,11 @@ "moreInfo": "For more information please see our", "move": "Move", "moveDescription": "You can move your files from one part of your project or component to another. Select the files that you want to move, and click the vertical ellipses to open the dropdown, then click “move”. Choose a component, provider, or folder and then click “Move”.", + "note": "Note:", "openViewFiles": "Open/View Files and Folders", "openViewFilesDescription": "Click a file name to go to view the file in the OSF. Opens file in a new tab. Click on the folder to open the contents in the files list.", + "osfProjectTransition": "OSF Project Transition", + "readOnlyWarning": "OSF Projects are being transitioned. You can no longer upload, rename, move, or copy files or folders. Existing files and folders remain accessible and downloadable. Read more about the", "renameFolderFile": "Rename a folder or file", "renameFolderFileDescription": "In the files list, select the file that you want to rename and click the vertical ellipses to open the dropdown. Select “Rename”. Note: Some special characters may cause unexpected behavior with certain addons.", "seeAllFiles": "See All Files in a Provider", @@ -1969,8 +1972,9 @@ "makePublic": { "confirmButton": "Make Public", "header": "Make Project Public", - "message": "Please review your projects, components, and add-ons for sensitive or restricted information before making them public.

    Once they are made public, you should assume they will always be public. You can return them to private later, but search engines (including Google's cache) or others may access files, wiki pages, or analytics before you do.", - "messageReadOnly": "Please review your projects, components, and add-ons for sensitive or restricted information before making them public.

    This action is irreversible." + "message": "Please review your projects, components, and add-ons for sensitive or restricted information before making them public.", + "warning": "Once they are made public, you should assume they will always be public. You can return them to private later, but search engines (including Google's cache) or others may access files, wiki pages, or analytics before you do.", + "warningReadOnly": "This action is irreversible." }, "privacySettingsPermissionTooltip": "You must have admin permission on this component to be able to change privacy settings", "toast": {