diff --git a/Neos.Neos/Classes/Domain/Model/WorkspaceRoleAssignments.php b/Neos.Neos/Classes/Domain/Model/WorkspaceRoleAssignments.php index c10d1e0ba6e..87b33bc0d3b 100644 --- a/Neos.Neos/Classes/Domain/Model/WorkspaceRoleAssignments.php +++ b/Neos.Neos/Classes/Domain/Model/WorkspaceRoleAssignments.php @@ -82,21 +82,6 @@ public static function createForSharedWorkspace(UserId $userId): self ); } - /** - * Default role assignment to be specified at creation via {@see WorkspaceService::createSharedWorkspace()} - * - * The specified user is manager - */ - public static function createForPrivateWorkspace(UserId $userId): self - { - return new self( - WorkspaceRoleAssignment::createForUser( - $userId, - WorkspaceRole::MANAGER, - ) - ); - } - public function isEmpty(): bool { return $this->assignments === []; diff --git a/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php b/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php index d4eeb5dad6a..795e643a96b 100644 --- a/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php +++ b/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php @@ -46,12 +46,15 @@ use Neos\Media\Domain\Model\AssetInterface; use Neos\Media\Domain\Model\ImageInterface; use Neos\Neos\Controller\Module\AbstractModuleController; +use Neos\Neos\Domain\Model\User; +use Neos\Neos\Domain\Model\UserId; use Neos\Neos\Domain\Model\WorkspaceClassification; use Neos\Neos\Domain\Model\WorkspaceDescription; use Neos\Neos\Domain\Model\WorkspaceRole; use Neos\Neos\Domain\Model\WorkspaceRoleAssignment; use Neos\Neos\Domain\Model\WorkspaceRoleAssignments; use Neos\Neos\Domain\Model\WorkspaceRoleSubject; +use Neos\Neos\Domain\Model\WorkspaceRoleSubjectType; use Neos\Neos\Domain\Model\WorkspaceTitle; use Neos\Neos\Domain\NodeLabel\NodeLabelGeneratorInterface; use Neos\Neos\Domain\Repository\SiteRepository; @@ -67,6 +70,7 @@ use Neos\Neos\Security\Authorization\ContentRepositoryAuthorizationService; use Neos\Neos\Utility\NodeTypeWithFallbackProvider; use Neos\Workspace\Ui\ViewModel\ChangeItem; +use Neos\Workspace\Ui\ViewModel\ConfirmDeleteWorkspaceRoleAssignmentFormData; use Neos\Workspace\Ui\ViewModel\ContentChangeItem; use Neos\Workspace\Ui\ViewModel\ContentChangeItems; use Neos\Workspace\Ui\ViewModel\ContentChangeProperties; @@ -75,10 +79,13 @@ use Neos\Workspace\Ui\ViewModel\ContentChanges\ImageContentChange; use Neos\Workspace\Ui\ViewModel\ContentChanges\TagContentChange; use Neos\Workspace\Ui\ViewModel\ContentChanges\TextContentChange; +use Neos\Workspace\Ui\ViewModel\CreateWorkspaceRoleAssignmentFormData; use Neos\Workspace\Ui\ViewModel\DocumentChangeItem; use Neos\Workspace\Ui\ViewModel\DocumentItem; use Neos\Workspace\Ui\ViewModel\EditWorkspaceFormData; +use Neos\Workspace\Ui\ViewModel\EditWorkspaceRoleAssignmentsFormData; use Neos\Workspace\Ui\ViewModel\PendingChanges; +use Neos\Workspace\Ui\ViewModel\RoleAssignmentListItem; use Neos\Workspace\Ui\ViewModel\Sorting; use Neos\Workspace\Ui\ViewModel\WorkspaceListItem; use Neos\Workspace\Ui\ViewModel\WorkspaceListItems; @@ -228,7 +235,6 @@ public function createAction( WorkspaceTitle $title, WorkspaceName $baseWorkspace, WorkspaceDescription $description, - string $visibility = 'shared', ): void { $currentUser = $this->userService->getCurrentUser(); if ($currentUser === null) { @@ -238,12 +244,6 @@ public function createAction( $contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId; $workspaceName = $this->workspaceService->getUniqueWorkspaceName($contentRepositoryId, $title->value); - $assignments = match($visibility) { - 'shared' => WorkspaceRoleAssignments::createForSharedWorkspace($currentUser->getId()), - 'private' => WorkspaceRoleAssignments::createForPrivateWorkspace($currentUser->getId()), - default => throw new \RuntimeException(sprintf('Invalid visibility %s given', $visibility), 1736343542) - }; - try { $this->workspaceService->createSharedWorkspace( $contentRepositoryId, @@ -251,7 +251,9 @@ public function createAction( $title, $description, $baseWorkspace, - $assignments + WorkspaceRoleAssignments::createForSharedWorkspace( + $currentUser->getId() + ) ); } catch (WorkspaceAlreadyExists $exception) { $this->addFlashMessage( @@ -299,15 +301,6 @@ public function editAction(WorkspaceName $workspaceName): void } $workspaceMetadata = $this->workspaceService->getWorkspaceMetadata($contentRepositoryId, $workspace->workspaceName); - $workspaceRoleAssignments = $this->workspaceService->getWorkspaceRoleAssignments($contentRepositoryId, $workspace->workspaceName); - $isShared = false; - if ($workspaceMetadata->classification === WorkspaceClassification::SHARED) { - foreach ($workspaceRoleAssignments as $roleAssignment) { - if ($roleAssignment->role === WorkspaceRole::COLLABORATOR) { - $isShared = true; - } - } - } $editWorkspaceDto = new EditWorkspaceFormData( workspaceName: $workspace->workspaceName, @@ -316,7 +309,6 @@ public function editAction(WorkspaceName $workspaceName): void workspaceHasChanges: $this->computePendingChanges($workspace, $contentRepository)->total > 0, baseWorkspaceName: $workspace->baseWorkspaceName, baseWorkspaceOptions: $this->prepareBaseWorkspaceOptions($contentRepository, $workspaceName), - isShared: $isShared, ); $this->view->assign('editWorkspaceFormData', $editWorkspaceDto); @@ -329,14 +321,12 @@ public function editAction(WorkspaceName $workspaceName): void * @param WorkspaceName $workspaceName The name of the workspace that is being updated * @param WorkspaceTitle $title Human friendly title of the workspace, for example "Christmas Campaign" * @param WorkspaceDescription $description A description explaining the purpose of the new workspace - * @param string $visibility Allow other editors to collaborate on this workspace if set to "shared" * @param WorkspaceName|null $baseWorkspace The base workspace to rebase this workspace onto if modified */ public function updateAction( WorkspaceName $workspaceName, WorkspaceTitle $title, WorkspaceDescription $description, - string $visibility, WorkspaceName|null $baseWorkspace = null, ): void { $currentUser = $this->userService->getCurrentUser(); @@ -379,29 +369,6 @@ public function updateAction( $description, ); - $workspaceRoleAssignments = $this->workspaceService->getWorkspaceRoleAssignments($contentRepositoryId, $workspaceName); - $sharedRoleAssignment = WorkspaceRoleAssignment::createForGroup( - 'Neos.Neos:AbstractEditor', - WorkspaceRole::COLLABORATOR, - ); - - match($visibility) { - 'shared' => !$workspaceRoleAssignments->contains($sharedRoleAssignment) && $this->workspaceService->assignWorkspaceRole( - $contentRepositoryId, - $workspaceName, - WorkspaceRoleAssignment::createForGroup( - 'Neos.Neos:AbstractEditor', - WorkspaceRole::COLLABORATOR, - ) - ), - 'private' => $workspaceRoleAssignments->contains($sharedRoleAssignment) && $this->workspaceService->unassignWorkspaceRole( - $contentRepositoryId, - $workspaceName, - WorkspaceRoleSubject::createForGroup('Neos.Neos:AbstractEditor'), - ), - default => throw new \RuntimeException(sprintf('Invalid visibility %s given', $visibility), 1736339457) - }; - if ($baseWorkspace !== null && $workspace->baseWorkspaceName?->equals($baseWorkspace) === false) { // Update Base Workspace $this->workspacePublishingService->changeBaseWorkspace( @@ -504,6 +471,182 @@ public function deleteAction(WorkspaceName $workspaceName): void } } + + public function editWorkspaceRoleAssignmentsAction(WorkspaceName $workspaceName): void + { + $contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId; + $workspaceMetadata = $this->workspaceService->getWorkspaceMetadata($contentRepositoryId, $workspaceName); + + // TODO: Render a form to edit role assignments + // TODO can current user see/edit role assignments? + $roleAssignmentsVisible = true; + $roleAssignmentsEditable = true; + + /** @var array $workspaceUserRoleAssignments */ + $workspaceUserRoleAssignments = []; + /** @var array $workspaceGroupRoleAssignments */ + $workspaceGroupRoleAssignments = []; + + foreach ($this->workspaceService->getWorkspaceRoleAssignments($contentRepositoryId, $workspaceName) as $workspaceRoleAssignment) { + $subjectLabel = match ($workspaceRoleAssignment->subject->type) { + WorkspaceRoleSubjectType::USER => $this->userService->findUserById(UserId::fromString($workspaceRoleAssignment->subject->value))?->getLabel() ?? $workspaceRoleAssignment->subject->value, + WorkspaceRoleSubjectType::GROUP => $this->policyService->getRole($workspaceRoleAssignment->subject->value)->getLabel() ?? $workspaceRoleAssignment->subject->value, + }; + + $roleLabel = $workspaceRoleAssignment->role->value; + switch ($workspaceRoleAssignment->subject->type) { + case WorkspaceRoleSubjectType::USER: + $workspaceUserRoleAssignments[] = new RoleAssignmentListItem( + subjectValue: $workspaceRoleAssignment->subject->value, + subjectLabel: $subjectLabel, + subjectTypeValue: $workspaceRoleAssignment->subject->type->value, + roleLabel: $roleLabel, + subjectType: $workspaceRoleAssignment->subject->type->value, + ); + break; + case WorkspaceRoleSubjectType::GROUP: + $workspaceGroupRoleAssignments[] = new RoleAssignmentListItem( + subjectValue: $workspaceRoleAssignment->subject->value, + subjectLabel: $subjectLabel, + subjectTypeValue: $workspaceRoleAssignment->subject->type->value, + roleLabel: $roleLabel, + subjectType: $workspaceRoleAssignment->subject->type->value, + ); + break; + } + } + + + + $editWorkspaceRoleAssignmentsFormData = new EditWorkspaceRoleAssignmentsFormData( + workspaceName: $workspaceName, + workspaceTitle: $workspaceMetadata->title, + roleAssignmentsEditable: $roleAssignmentsEditable, + userRoleAssignments: $workspaceUserRoleAssignments, + groupRoleAssignments: $workspaceGroupRoleAssignments, + ); + + $this->view->assign('editWorkspaceRoleAssignmentsFormData', $editWorkspaceRoleAssignmentsFormData); + } + + public function createUserWorkspaceRoleAssignmentAction(WorkspaceName $workspaceName): void + { + $contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId; + $workspaceMetadata = $this->workspaceService->getWorkspaceMetadata($contentRepositoryId, $workspaceName); + + $userOptions = []; + foreach ($this->userService->getUsers()->toArray() as $user) { + $userOptions[$user->getId()->value] = $user->getLabel(); + } + + $workspaceRoles = WorkspaceRole::cases(); + /** @var array $roleOptions where key is the Id and value is the translated label of the Role */ + $roleOptions = []; + foreach ($workspaceRoles as $workspaceRole) { + $roleOptions[$workspaceRole->value] = $this->getModuleLabel("workspaces.workspace.workspaceRoleAssignment.role.label.$workspaceRole->value"); + } + + $this->view->assign('createWorkspaceRoleAssignmentFormData', new CreateWorkspaceRoleAssignmentFormData( + workspaceName: $workspaceName, + workspaceTitle: $workspaceMetadata->title, + options: $userOptions, + roleOptions: $roleOptions, + )); + } + public function createGroupWorkspaceRoleAssignmentAction(WorkspaceName $workspaceName): void + { + $contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId; + $workspaceMetadata = $this->workspaceService->getWorkspaceMetadata($contentRepositoryId, $workspaceName); + + $rolesInSystem = $this->policyService->getRoles(); + $groupOptions = []; + foreach ($rolesInSystem as $role) { + $groupOptions[$role->getIdentifier()] = $role->getLabel(); + } + + $workspaceRoles = WorkspaceRole::cases(); + /** @var array $roleOptions where key is the Id and value is the translated label of the Role */ + $roleOptions = []; + foreach ($workspaceRoles as $workspaceRole) { + $roleOptions[$workspaceRole->value] = $this->getModuleLabel("workspaces.workspace.workspaceRoleAssignment.role.label.$workspaceRole->value"); + } + $this->view->assign('createWorkspaceRoleAssignmentFormData', new CreateWorkspaceRoleAssignmentFormData( + workspaceName: $workspaceName, + workspaceTitle: $workspaceMetadata->title, + options: $groupOptions, + roleOptions: $roleOptions, + )); + } + + public function addWorkspaceRoleAssignmentAction( + WorkspaceName $workspaceName, + string $subject, + string $subjectType, + string $role, + ): void + { + // TODO: Validate if user can add role assignment to workspace + + $subjectType = WorkspaceRoleSubjectType::from($subjectType); + $subject = WorkspaceRoleSubject::create($subjectType, $subject); + $role = WorkspaceRole::from($role); + + if ($subjectType === WorkspaceRoleSubjectType::USER) { + $this->addUserRoleAssignment($workspaceName, $subject, $role); + } elseif ($subjectType === WorkspaceRoleSubjectType::GROUP) { + $this->addGroupRoleAssignment($workspaceName, $subject, $role); + } else { + $this->addFlashMessage( + $this->getModuleLabel('workspaces.roleAssignmentCouldNotBeAdded'), + '', + Message::SEVERITY_ERROR + ); + $this->throwStatus(400, 'Invalid subject type'); + } + //WorkspaceName $workspaceName): + $this->forward('editWorkspaceRoleAssignments', null, null, ['workspaceName' => $workspaceName->value]); + } + + public function confirmDeleteWorkspaceRoleAssignmentAction(WorkspaceName $workspaceName, string $subjectValue, string $subjectType): void + { + $contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId; + $workspaceMetadata = $this->workspaceService->getWorkspaceMetadata($contentRepositoryId, $workspaceName); + + $confirmDeleteWorkspaceRoleAssignmentFormData = new ConfirmDeleteWorkspaceRoleAssignmentFormData( + workspaceName: $workspaceName, + workspaceTitle: $workspaceMetadata->title, + subjectValue: $subjectValue, + subjectType: $subjectType, + ); + + $this->view->assign('confirmDeleteWorkspaceRoleAssignmentFormData', $confirmDeleteWorkspaceRoleAssignmentFormData); + } + + public function deleteWorkspaceRoleAssignmentAction(WorkspaceName $workspaceName, string $subjectValue, string $subjectType): void + { + $contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId; + try { + $this->workspaceService->unassignWorkspaceRole( + $contentRepositoryId, + $workspaceName, + WorkspaceRoleSubject::create( + WorkspaceRoleSubjectType::from($subjectType), + $subjectValue + ) + ); + } catch (\Exception $e) { + // TODO: error handling + $this->addFlashMessage( + $this->getModuleLabel('workspaces.roleAssignmentCouldNotBeDeleted'), + '', + Message::SEVERITY_ERROR + ); + $this->throwStatus(500, 'Role assignment could not be deleted'); + } + + $this->redirect('editWorkspaceRoleAssignments', null, null, ['workspaceName' => $workspaceName->value]); + } + /** * Publish a single document node */ @@ -1326,11 +1469,38 @@ protected function getWorkspaceListItems( } return WorkspaceListItems::fromArray($workspaceListItems); } - protected function getChangesFromWorkspace(Workspace $selectedWorkspace,ContentRepository $contentRepository ): Changes{ return $contentRepository->projectionState(ChangeFinder::class) ->findByContentStreamId( $selectedWorkspace->currentContentStreamId ); } + + private function addUserRoleAssignment(WorkspaceName $workspaceName, WorkspaceRoleSubject $subject, WorkspaceRole $role): void + { + if ($this->userService->findUserById(UserId::fromString($subject->value)) === null) { + $this->addFlashMessage( + $this->getModuleLabel('workspaces.roleAssignmentCouldNotBeAdded'), + '', + Message::SEVERITY_ERROR + ); + $this->throwStatus(400, 'Invalid user'); + } + + $this->workspaceService->assignWorkspaceRole( + SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId, + $workspaceName, + WorkspaceRoleAssignment::createForUser(UserId::fromString($subject->value), $role) + ); + } + + private function addGroupRoleAssignment(WorkspaceName $workspaceName, WorkspaceRoleSubject $subject, WorkspaceRole $role): void + { + // TODO check if group exists? + $this->workspaceService->assignWorkspaceRole( + SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId, + $workspaceName, + WorkspaceRoleAssignment::createForGroup($subject->value, $role) + ); + } } diff --git a/Neos.Workspace.Ui/Classes/ViewModel/ConfirmDeleteWorkspaceRoleAssignmentFormData.php b/Neos.Workspace.Ui/Classes/ViewModel/ConfirmDeleteWorkspaceRoleAssignmentFormData.php new file mode 100644 index 00000000000..96dd037be88 --- /dev/null +++ b/Neos.Workspace.Ui/Classes/ViewModel/ConfirmDeleteWorkspaceRoleAssignmentFormData.php @@ -0,0 +1,31 @@ + + */ + public array $roleOptions + ) + { + } +} diff --git a/Neos.Workspace.Ui/Classes/ViewModel/EditWorkspaceFormData.php b/Neos.Workspace.Ui/Classes/ViewModel/EditWorkspaceFormData.php index 471e9840538..d38db3c85ea 100644 --- a/Neos.Workspace.Ui/Classes/ViewModel/EditWorkspaceFormData.php +++ b/Neos.Workspace.Ui/Classes/ViewModel/EditWorkspaceFormData.php @@ -35,7 +35,6 @@ public function __construct( public bool $workspaceHasChanges, public WorkspaceName $baseWorkspaceName, public array $baseWorkspaceOptions, - public bool $isShared, ) { } } diff --git a/Neos.Workspace.Ui/Classes/ViewModel/EditWorkspaceRoleAssignmentsFormData.php b/Neos.Workspace.Ui/Classes/ViewModel/EditWorkspaceRoleAssignmentsFormData.php new file mode 100644 index 00000000000..ee745d85eef --- /dev/null +++ b/Neos.Workspace.Ui/Classes/ViewModel/EditWorkspaceRoleAssignmentsFormData.php @@ -0,0 +1,42 @@ + $roleAssignments + */ + public function __construct( + public WorkspaceName $workspaceName, + public WorkspaceTitle $workspaceTitle, + public bool $roleAssignmentsEditable, + public array $userRoleAssignments, + public array $groupRoleAssignments, + ) { + } +} diff --git a/Neos.Workspace.Ui/Classes/ViewModel/RoleAssignmentListItem.php b/Neos.Workspace.Ui/Classes/ViewModel/RoleAssignmentListItem.php new file mode 100644 index 00000000000..3d827a94e9e --- /dev/null +++ b/Neos.Workspace.Ui/Classes/ViewModel/RoleAssignmentListItem.php @@ -0,0 +1,39 @@ +classification === WorkspaceClassification::PERSONAL->value; } + // todo remove this old shared vs private mapping! public function isPrivate(): bool { - if ($this->classification !== WorkspaceClassification::SHARED->value) { - return false; - } foreach ($this->roleAssignments as $roleAssignment) { if ($roleAssignment->role === WorkspaceRole::COLLABORATOR) { return false; @@ -59,6 +57,7 @@ public function isPrivate(): bool return true; } + // todo remove this old shared vs private mapping! public function isShared(): bool { foreach ($this->roleAssignments as $roleAssignment) { diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/ConfirmDeleteWorkspaceRoleAssignments.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/ConfirmDeleteWorkspaceRoleAssignments.fusion new file mode 100644 index 00000000000..5f4ab4babf5 --- /dev/null +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/ConfirmDeleteWorkspaceRoleAssignments.fusion @@ -0,0 +1,13 @@ +Neos.Workspace.Ui.WorkspaceController.confirmDeleteWorkspaceRoleAssignment = Neos.Fusion:Component { + /// \Neos\Workspace\Ui\ViewModel\ConfirmDeleteWorkspaceRoleAssignmentFormData + confirmDeleteWorkspaceRoleAssignmentFormData = ${confirmDeleteWorkspaceRoleAssignmentFormData} + + renderer = afx` + + ` +} diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/CreateGroupWorkspaceRoleAssignment.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/CreateGroupWorkspaceRoleAssignment.fusion new file mode 100644 index 00000000000..f56bc219634 --- /dev/null +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/CreateGroupWorkspaceRoleAssignment.fusion @@ -0,0 +1,12 @@ +Neos.Workspace.Ui.WorkspaceController.createGroupWorkspaceRoleAssignment = Neos.Fusion:Component { + createWorkspaceRoleAssignmentFormData = ${createWorkspaceRoleAssignmentFormData} + + renderer = afx` + + ` +} diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/CreateUserWorkspaceRoleAssignment.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/CreateUserWorkspaceRoleAssignment.fusion new file mode 100644 index 00000000000..8e6b36c0baf --- /dev/null +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/CreateUserWorkspaceRoleAssignment.fusion @@ -0,0 +1,13 @@ +Neos.Workspace.Ui.WorkspaceController.createUserWorkspaceRoleAssignment = Neos.Fusion:Component { + createWorkspaceRoleAssignmentFormData = ${createWorkspaceRoleAssignmentFormData} + + renderer = afx` + + ` +} diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/Edit.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/Edit.fusion index 805d829c88f..dc7e0f072b6 100644 --- a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/Edit.fusion +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/Edit.fusion @@ -10,7 +10,12 @@ Neos.Workspace.Ui.WorkspaceController.edit = Neos.Fusion:Component { baseWorkspaceName={props.editWorkspaceFormData.baseWorkspaceName.value} workspaceHasChanges={props.editWorkspaceFormData.workspaceHasChanges} baseWorkspaceOptions={props.editWorkspaceFormData.baseWorkspaceOptions} - isShared={props.editWorkspaceFormData.isShared} + + roleAssignmentsVisible={props.editWorkspaceFormData.roleAssignmentsVisible} + roleAssignmentsEditable={props.editWorkspaceFormData.roleAssignmentsEditable} + roleAssignments={props.editWorkspaceFormData.roleAssignments} + roleAssignmentUserOptions={props.editWorkspaceFormData.roleAssignmentUserOptions} + roleAssignmentGroupOptions={props.editWorkspaceFormData.roleAssignmentGroupOptions} /> ` } diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/EditWorkspaceRoleAssignments.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/EditWorkspaceRoleAssignments.fusion new file mode 100644 index 00000000000..7ca4e90f00c --- /dev/null +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Actions/EditWorkspaceRoleAssignments.fusion @@ -0,0 +1,21 @@ +Neos.Workspace.Ui.WorkspaceController.editWorkspaceRoleAssignments = Neos.Fusion:Component { + /// \Neos\Workspace\Ui\ViewModel\EditWorkspaceRoleAssignmentsFormData + editWorkspaceRoleAssignmentsFormData = ${editWorkspaceRoleAssignmentsFormData} + + renderer = afx` + + ` +} diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Components/WorkspaceRoleAssigmentTable.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Components/WorkspaceRoleAssigmentTable.fusion new file mode 100644 index 00000000000..cd2070f06d1 --- /dev/null +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Components/WorkspaceRoleAssigmentTable.fusion @@ -0,0 +1,38 @@ +## +# Renders a Workspace Role Assignment list +# +prototype(Neos.Workspace.Ui:Component.WorkspaceRoleAssignmentTable) < prototype(Neos.Fusion:Component) { + /// string + workspaceName = null + /// array + roleAssignments=${[]} + + @private { + i18n = ${I18n.id('').source('Main').package('Neos.Workspace.Ui')} + confirmDeleteWorkspaceRoleAssignmentPopoverId = 'confirm-delete-workspace-role-assignment-popover' + + } + + renderer = afx` + + + + + + + + + + + + + +
{private.i18n.id('workspaces.workspace.workspaceRoleAssignment.subject')}{private.i18n.id('workspaces.workspace.workspaceRoleAssignment.role')} + {private.i18n.id('workspaces.workspace.workspaceRoleAssignment.actions')} +
+ ` +} diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Components/WorkspaceRoleAssignmentTableRow.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Components/WorkspaceRoleAssignmentTableRow.fusion new file mode 100644 index 00000000000..02de1db1a03 --- /dev/null +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Components/WorkspaceRoleAssignmentTableRow.fusion @@ -0,0 +1,44 @@ +## +# Renders a single WorkspaceRoleAssignment list item +# +prototype(Neos.Workspace.Ui:Component.WorkspaceRoleAssignmentTableRow) < prototype(Neos.Fusion:Component) { + /// string + workspaceName = null + /// bool + roleAssignmentsEditable = false + /// Neos\Workspace\Ui\ViewModel\RoleAssignmentListItem + roleAssignmentFormData = null + + @private { + i18n = ${I18n.id('').source('Main').package('Neos.Workspace.Ui')} + confirmDeleteWorkspaceRoleAssignmentPopoverId = 'confirm-delete-workspace-role-assignment-popover' + confirmDeleteWorkspaceRoleAssignmentUri = Neos.Fusion:ActionUri { + action = 'confirmDeleteWorkspaceRoleAssignment' + format = 'htmx' + arguments { + workspaceName = ${props.workspaceName} + subjectValue = ${props.roleAssignmentFormData.subjectValue} + subjectType = ${props.roleAssignmentFormData.subjectType} + } + } + } + + renderer = afx` + + {props.roleAssignmentFormData.subjectLabel} + {private.i18n.id('workspaces.workspace.workspaceRoleAssignment.role.label.' + props.roleAssignmentFormData.roleLabel)} + + + + + ` +} diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Components/WorkspaceTableRow.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Components/WorkspaceTableRow.fusion index 158120cd877..ef045463188 100644 --- a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Components/WorkspaceTableRow.fusion +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Components/WorkspaceTableRow.fusion @@ -52,6 +52,13 @@ prototype(Neos.Workspace.Ui:Component.WorkspaceTableRow) < prototype(Neos.Fusion workspaceName = ${props.workspaceListItem.name} } } + editWorkspaceRoleAssignmentsUri = Neos.Fusion:ActionUri { + action = 'editWorkspaceRoleAssignments' + format = 'htmx' + arguments { + workspaceName = ${props.workspaceListItem.name} + } + } deleteWorkspaceUri = Neos.Fusion:ActionUri { action = 'delete' format = 'htmx' @@ -70,6 +77,7 @@ prototype(Neos.Workspace.Ui:Component.WorkspaceTableRow) < prototype(Neos.Fusion rebaseWorkspacePopoverId = 'workspace-rebase-modal' deleteWorkspacePopoverId = 'workspace-delete-modal' editWorkspacePopoverId = 'workspace-edit-modal' + editWorkspaceRoleAssignmentsPopoverId = 'workspace-edit-role-assignments-modal' } renderer = afx` @@ -130,6 +138,15 @@ prototype(Neos.Workspace.Ui:Component.WorkspaceTableRow) < prototype(Neos.Fusion attributes.hx-swap='innerHTML' attributes.hx-on--after-request={'document.getElementById("' + private.editWorkspacePopoverId + '").showPopover()'} /> + +
+ +
+ {private.i18n.id('workspaces.createWorkspaceRoleAssignment').arguments([props.workspaceTitle])} +
+
+
+ + +
+ + ` +} diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Modals/Create.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Modals/Create.fusion index 6ca1a371958..8d985f8a968 100644 --- a/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Modals/Create.fusion +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Features/Workspace/Modals/Create.fusion @@ -81,32 +81,6 @@ prototype(Neos.Workspace.Ui:Component.Modal.Create) < prototype(Neos.Fusion:Comp - - - - {private.i18n.id('workspaces.workspace.visibility.shared')} - -

- {private.i18n.id('workspaces.workspace.visibility.shared.help')} -

-
- - {private.i18n.id('workspaces.workspace.visibility.private')} - -

- {private.i18n.id('workspaces.workspace.visibility.private.help')} -

-