Skip to content
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<osf-sub-header
[title]="'project.analytics.kpi.forks' | translate"
[showButton]="true"
[showButton]="!hasNoPermissions()"
[buttonLabel]="'project.overview.actions.forkProjectLabel' | translate"
(buttonClick)="handleForkResource()"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import { IS_SMALL } from '@osf/shared/helpers';
import { ToolbarResource } from '@osf/shared/models';
import { Duplicate } from '@osf/shared/models/duplicates';
import { CustomDialogService } from '@osf/shared/services';
import { ClearDuplicates, DuplicatesSelectors, GetAllDuplicates } from '@osf/shared/stores';
import { ClearDuplicates, CurrentResourceSelectors, DuplicatesSelectors, GetAllDuplicates } from '@osf/shared/stores';

@Component({
selector: 'osf-view-duplicates',
Expand Down Expand Up @@ -76,6 +76,7 @@ export class ViewDuplicatesComponent {
duplicates = select(DuplicatesSelectors.getDuplicates);
isDuplicatesLoading = select(DuplicatesSelectors.getDuplicatesLoading);
totalDuplicates = select(DuplicatesSelectors.getDuplicatesTotalCount);
hasNoPermissions = select(CurrentResourceSelectors.hasNoPermissions);

readonly pageSize = 10;
readonly UserPermissions = UserPermissions;
Expand Down
4 changes: 2 additions & 2 deletions src/app/features/metadata/metadata.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@
[resourceType]="resourceType()"
/>

@if (showRegistrationDoi()) {
@if (isRegistrationType()) {
<osf-metadata-registration-doi [identifiers]="metadata()?.identifiers!"></osf-metadata-registration-doi>
}

<osf-metadata-tags
[tags]="metadata()?.tags || []"
(tagsChanged)="onTagsChanged($event)"
[readonly]="!hasWriteAccess()"
[readonly]="isRegistrationType() ? !hasAdminAccess() : !hasWriteAccess()"
></osf-metadata-tags>

<osf-metadata-subjects
Expand Down
2 changes: 1 addition & 1 deletion src/app/features/metadata/metadata.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export class MetadataComponent implements OnInit {
);
});

showRegistrationDoi = computed(() => this.resourceType() === ResourceType.Registration);
isRegistrationType = computed(() => this.resourceType() === ResourceType.Registration);

bibliographicContributors = computed(() => this.contributors().filter((contributor) => contributor.isBibliographic));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,87 +37,89 @@
}
}

<div class="flex ml-auto">
<div class="flex flex-1 flex-column-reverse gap-3 justify-content-end sm:gap-3 sm:flex-row-reverse lg:flex-row">
@if (resource.storage && !isCollectionsRoute()) {
<p class="font-bold mr-2 ml-0 mt-2 sm:ml-2 sm:mt-0 sm:align-self-center storage">
{{ +resource.storage.storageUsage | fileSize }}
</p>
}

<div class="flex gap-2 justify-content-start">
@if (showViewOnlyLinks() && canEdit()) {
<p-button
class="flex"
[pTooltip]="'project.overview.tooltips.viewOnlyLinks' | translate"
tooltipPosition="bottom"
[routerLink]="'../contributors'"
[ariaLabel]="'project.overview.tooltips.viewOnlyLinks' | translate"
>
<span class="font-bold">{{ resource.viewOnlyLinksCount }}</span>
<i class="fas fa-link text-2xl"></i>
</p-button>
@if (!hasNoPermissions()) {
<div class="flex ml-auto">
<div class="flex flex-1 flex-column-reverse gap-3 justify-content-end sm:gap-3 sm:flex-row-reverse lg:flex-row">
@if (resource.storage && !isCollectionsRoute()) {
<p class="font-bold mr-2 ml-0 mt-2 sm:ml-2 sm:mt-0 sm:align-self-center storage">
{{ +resource.storage.storageUsage | fileSize }}
</p>
}

@if (resource.resourceType === ResourceType.Project && !hasViewOnly()) {
<p-button
class="flex"
(click)="forkActionMenu.toggle($event)"
[pTooltip]="'project.overview.tooltips.duplicate' | translate"
tooltipPosition="bottom"
[ariaLabel]="'project.overview.tooltips.duplicate' | translate"
>
<span class="font-bold">{{ resource.forksCount }}</span>
<i class="fas fa-clone text-2xl"></i>
<p-menu appendTo="body" #forkActionMenu [model]="forkActionItems" popup>
<ng-template #item let-item>
<a class="p-menu-item-link">
{{ item.label | translate }}
</a>
</ng-template>
</p-menu>
</p-button>
}
<div class="flex gap-2 justify-content-start">
@if (showViewOnlyLinks() && canEdit()) {
<p-button
class="flex"
[pTooltip]="'project.overview.tooltips.viewOnlyLinks' | translate"
tooltipPosition="bottom"
[routerLink]="'../contributors'"
[ariaLabel]="'project.overview.tooltips.viewOnlyLinks' | translate"
>
<span class="font-bold">{{ resource.viewOnlyLinksCount }}</span>
<i class="fas fa-link text-2xl"></i>
</p-button>
}

@if (!hasViewOnly()) {
<p-button
[pTooltip]="'project.overview.tooltips.bookmarks' | translate"
tooltipPosition="bottom"
class="flex"
(onClick)="toggleBookmark()"
[loading]="isBookmarksLoading() || isBookmarksSubmitting()"
[ariaLabel]="'project.overview.tooltips.bookmarks' | translate"
>
@if (!isBookmarksLoading() && !isBookmarksSubmitting()) {
<i class="text-2xl" [ngClass]="isBookmarked() ? 'fas fa-bookmark' : 'far fa-bookmark'"></i>
}
</p-button>
}
@if (resource.resourceType === ResourceType.Project && !hasViewOnly()) {
<p-button
class="flex"
(click)="forkActionMenu.toggle($event)"
[pTooltip]="'project.overview.tooltips.duplicate' | translate"
tooltipPosition="bottom"
[ariaLabel]="'project.overview.tooltips.duplicate' | translate"
>
<span class="font-bold">{{ resource.forksCount }}</span>
<i class="fas fa-clone text-2xl"></i>
<p-menu appendTo="body" #forkActionMenu [model]="forkActionItems" popup>
<ng-template #item let-item>
<a class="p-menu-item-link">
{{ item.label | translate }}
</a>
</ng-template>
</p-menu>
</p-button>
}

@if (resource.isPublic && !hasViewOnly()) {
<p-button
class="flex"
(onClick)="socialsActionMenu.toggle($event)"
[pTooltip]="'project.overview.tooltips.share' | translate"
tooltipPosition="bottom"
[ariaLabel]="'project.overview.tooltips.share' | translate"
>
<span class="font-bold">{{ socialsActionItems().length }}</span>
<i class="fas fa-share-nodes text-2xl"></i>
<p-menu appendTo="body" #socialsActionMenu [model]="socialsActionItems()" popup>
<ng-template #item let-item>
<a class="p-menu-item-link" [href]="item.url" target="_blank" rel="noopener noreferrer">
<div class="social-link flex align-items-center justify-content-center">
<osf-icon [iconClass]="`${item.icon} fa-sm`"></osf-icon>
</div>
{{ item.label | translate }}
</a>
</ng-template>
</p-menu>
</p-button>
}
@if (!hasViewOnly()) {
<p-button
[pTooltip]="'project.overview.tooltips.bookmarks' | translate"
tooltipPosition="bottom"
class="flex"
(onClick)="toggleBookmark()"
[loading]="isBookmarksLoading() || isBookmarksSubmitting()"
[ariaLabel]="'project.overview.tooltips.bookmarks' | translate"
>
@if (!isBookmarksLoading() && !isBookmarksSubmitting()) {
<i class="text-2xl" [ngClass]="isBookmarked() ? 'fas fa-bookmark' : 'far fa-bookmark'"></i>
}
</p-button>
}

@if (resource.isPublic && !hasViewOnly()) {
<p-button
class="flex"
(onClick)="socialsActionMenu.toggle($event)"
[pTooltip]="'project.overview.tooltips.share' | translate"
tooltipPosition="bottom"
[ariaLabel]="'project.overview.tooltips.share' | translate"
>
<span class="font-bold">{{ socialsActionItems().length }}</span>
<i class="fas fa-share-nodes text-2xl"></i>
<p-menu appendTo="body" #socialsActionMenu [model]="socialsActionItems()" popup>
<ng-template #item let-item>
<a class="p-menu-item-link" [href]="item.url" target="_blank" rel="noopener noreferrer">
<div class="social-link flex align-items-center justify-content-center">
<osf-icon [iconClass]="`${item.icon} fa-sm`"></osf-icon>
</div>
{{ item.label | translate }}
</a>
</ng-template>
</p-menu>
</p-button>
}
</div>
</div>
</div>
</div>
}
</div>
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export class OverviewToolbarComponent {
bookmarksCollectionId = select(BookmarksSelectors.getBookmarksCollectionId);
bookmarkedProjects = select(MyResourcesSelectors.getBookmarks);
duplicatedProject = select(ProjectOverviewSelectors.getDuplicatedProject);
hasNoPermissions = select(ProjectOverviewSelectors.hasNoPermissions);
socialsActionItems = computed(() => {
const shareableContent = this.createShareableContent();
return shareableContent ? this.buildSocialActionItems(shareableContent) : [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@ <h3 class="text-xl pb-4">{{ 'myProjects.settings.projectAffiliation' | translate
<p>{{ affiliation.name }}</p>
</div>

<p-button
class="danger-icon-btn"
icon="fas fa-trash"
severity="danger"
text
[ariaLabel]="'common.buttons.delete' | translate"
(onClick)="removeAffiliation(affiliation)"
></p-button>
@if (canEdit()) {
<p-button
class="danger-icon-btn"
icon="fas fa-trash"
severity="danger"
text
[ariaLabel]="'common.buttons.delete' | translate"
(onClick)="removeAffiliation(affiliation)"
></p-button>
}
</div>
}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Institution } from '@osf/shared/models';
export class SettingsProjectAffiliationComponent {
affiliations = input<Institution[]>([]);
removed = output<Institution>();
canEdit = input<boolean>(false);

removeAffiliation(affiliation: Institution) {
this.removed.emit(affiliation);
Expand Down
5 changes: 3 additions & 2 deletions src/app/features/project/settings/settings.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<osf-loading-spinner />
} @else {
<div class="flex flex-column flex-1 gap-4 w-full bg-white py-4 px-3 md:px-5 xl:px-4">
@if (canWrite()) {
@if (hasWriteAccess()) {
<osf-settings-project-form-card
(submitForm)="submitForm($event)"
(deleteProject)="deleteProject()"
Expand All @@ -17,7 +17,7 @@
[locationText]="'myProjects.settings.storageLocationMessage' | translate"
></osf-settings-storage-location-card>

@if (isAdmin()) {
@if (hasAdminAccess()) {
<osf-settings-view-only-links-card
id="view-only-links"
[tableData]="viewOnlyLinks()"
Expand Down Expand Up @@ -48,6 +48,7 @@
/>

<osf-settings-project-affiliation
[canEdit]="hasWriteAccess()"
[affiliations]="projectDetails().affiliatedInstitutions"
(removed)="removeAffiliation($event)"
></osf-settings-project-affiliation>
Expand Down
6 changes: 3 additions & 3 deletions src/app/features/project/settings/settings.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ export class SettingsComponent implements OnInit {
title = signal('');

userPermissions = computed(() => this.projectDetails()?.currentUserPermissions || []);
isAdmin = computed(() => this.userPermissions().includes(UserPermissions.Admin));
canWrite = computed(() => this.userPermissions().includes(UserPermissions.Write));
hasAdminAccess = computed(() => this.userPermissions().includes(UserPermissions.Admin));
hasWriteAccess = computed(() => this.userPermissions().includes(UserPermissions.Write));

constructor() {
this.setupEffects();
Expand Down Expand Up @@ -255,7 +255,7 @@ export class SettingsComponent implements OnInit {
effect(() => {
const id = this.projectId();

if (id && this.isAdmin()) {
if (id && this.hasAdminAccess()) {
this.actions.getViewOnlyLinks(id, ResourceType.Project);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@

<div class="flex gap-2 align-items-baseline">
<strong>{{ 'common.labels.contributors' | translate }}:</strong>
<osf-contributors-list [contributors]="registrationData().contributors"></osf-contributors-list>
<osf-contributors-list
[contributors]="registrationData().contributors"
[anonymous]="!registrationData().contributors.length"
></osf-contributors-list>
</div>

<div class="flex gap-2 align-items-baseline">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ export class RegistryComponentsMapper {
registrationSupplement: apiComponent.attributes.registration_supplement,
tags: apiComponent.attributes.tags,
isPublic: apiComponent.attributes.public,
contributors: ContributorsMapper.getContributors(apiComponent.embeds.bibliographic_contributors.data) || [],
contributors: ContributorsMapper.getContributors(apiComponent.embeds?.bibliographic_contributors?.data || []),
};
}

static fromApiResponseArray(apiComponents: RegistryComponentJsonApi[]): RegistryComponentModel[] {
return apiComponents.map(this.fromApiResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ export class CurrentResourceSelectors {

@Selector([CurrentResourceState])
static hasWriteAccess(state: CurrentResourceStateModel): boolean {
return state.resourceDetails.data?.currentUserPermissions?.includes(UserPermissions.Write) || false;
return state.currentResource.data?.permissions?.includes(UserPermissions.Write) || false;
}

@Selector([CurrentResourceState])
static hasAdminAccess(state: CurrentResourceStateModel): boolean {
return state.resourceDetails.data?.currentUserPermissions?.includes(UserPermissions.Admin) || false;
return state.currentResource.data?.permissions?.includes(UserPermissions.Admin) || false;
}

@Selector([CurrentResourceState])
static hasNoPermissions(state: CurrentResourceStateModel): boolean {
return !state.resourceDetails.data?.currentUserPermissions?.length;
return !state.currentResource.data?.permissions?.length;
}

@Selector([CurrentResourceState])
Expand Down
Loading