Skip to content

Commit

Permalink
Feature: Add popup for workspace rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
pKallert committed Nov 14, 2023
1 parent 1f893ef commit 234a31a
Show file tree
Hide file tree
Showing 21 changed files with 372 additions and 163 deletions.
32 changes: 32 additions & 0 deletions Classes/Controller/BackendServiceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\PublishIndividualNodesFromWorkspace;
use Neos\ContentRepository\Core\Feature\WorkspacePublication\Dto\NodeIdsToPublishOrDiscard;
use Neos\ContentRepository\Core\Feature\WorkspacePublication\Dto\NodeIdToPublishOrDiscard;
use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Command\RebaseWorkspace;
use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints;
use Neos\ContentRepository\Core\SharedModel\Exception\NodeAggregateCurrentlyDoesNotExist;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
Expand Down Expand Up @@ -618,4 +619,35 @@ public function generateUriPathSegmentAction(string $contextNode, string $text):
$slug = $this->nodeUriPathSegmentGenerator->generateUriPathSegment($contextNode, $text);
$this->view->assign('value', $slug);
}

/**
* Change base workspace of current user workspace
*
* @param string $targetWorkspaceName
* @return void
* @throws \Exception
*/
public function rebaseWorkspaceAction(string $targetWorkspaceName): void
{
$contentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId;
$contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);

$command = RebaseWorkspace::create(WorkspaceName::fromString($targetWorkspaceName));
try {
$contentRepository->handle($command)->block();
} catch (\Exception $exception) {
$error = new Error();
$error->setMessage($error->getMessage());

$this->feedbackCollection->add($error);
$this->view->assign('value', $this->feedbackCollection);
return;
}

$success = new Success();
$success->setMessage(sprintf('Successfully synced User workspace'));
$this->feedbackCollection->add($success);

$this->view->assign('value', $this->feedbackCollection);
}
}
7 changes: 7 additions & 0 deletions Configuration/Routes.Service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
'@action': 'changeBaseWorkspace'
httpMethods: ['POST']

-
name: 'Rebase Workspace'
uriPattern: 'rebase-workspace'
defaults:
'@controller': 'BackendService'
'@action': 'rebaseWorkspace'
httpMethods: ['POST']
-
name: 'Copy nodes to clipboard'
uriPattern: 'copy-nodes'
Expand Down
3 changes: 3 additions & 0 deletions Resources/Private/Fusion/Backend/Root.fusion
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ backend = Neos.Fusion:Template {
changeBaseWorkspace = Neos.Fusion:UriBuilder {
action = 'changeBaseWorkspace'
}
rebaseWorkspace = Neos.Fusion:UriBuilder {
action = 'rebaseWorkspace'
}
copyNodes = Neos.Fusion:UriBuilder {
action = 'copyNodes'
}
Expand Down
17 changes: 17 additions & 0 deletions Resources/Private/Translations/en/Main.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,23 @@
<trans-unit id="deleteXNodes" xml:space="preserve">
<source>Delete {amount} nodes</source>
</trans-unit>
<trans-unit id="syncPersonalWorkSpace" xml:space="preserve">
<source>Synchronize personal workspace</source>
</trans-unit>
<trans-unit id="syncPersonalWorkSpaceConfirm" xml:space="preserve">
<source>Synchronize now</source>
</trans-unit>
<trans-unit id="syncPersonalWorkSpaceMessage" xml:space="preserve">
<source>Your personal workspace is up-to-date with the current workspace.</source>
</trans-unit>
<trans-unit id="syncPersonalWorkSpaceMessageOutdated" xml:space="preserve">
<source>It seems like there are changes in the workspace that are not reflected in your personal workspace.
You should synchronize your personal workspace to avoid conflicts.</source>
</trans-unit>
<trans-unit id="syncPersonalWorkSpaceMessageOutdatedConflict" xml:space="preserve">
<source>It seems like there are changes in the workspace that are not reflected in your personal workspace.
The changes lead to an error state. Please contact your administrator to resolve the problem.</source>
</trans-unit>
<trans-unit id="rangeEditorMinimum" xml:space="preserve">
<source>Minimum</source>
</trans-unit>
Expand Down
2 changes: 1 addition & 1 deletion Resources/Public/Icons/sync.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion Resources/Public/Icons/sync_check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions packages/neos-ui-backend-connector/src/Endpoints/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface Routes {
publish: string;
discard: string;
changeBaseWorkspace: string;
rebaseWorkspace: string;
copyNodes: string;
cutNodes: string;
clearClipboard: string;
Expand Down Expand Up @@ -111,6 +112,21 @@ export default (routes: Routes) => {
})).then(response => fetchWithErrorHandling.parseJson(response))
.catch(reason => fetchWithErrorHandling.generalErrorHandler(reason));

const rebaseWorkspace = (targetWorkspaceName: WorkspaceName) => fetchWithErrorHandling.withCsrfToken(csrfToken => ({
url: routes.ui.service.rebaseWorkspace,

method: 'POST',
credentials: 'include',
headers: {
'X-Flow-Csrftoken': csrfToken,
'Content-Type': 'application/json'
},
body: JSON.stringify({
targetWorkspaceName
})
})).then(response => fetchWithErrorHandling.parseJson(response))
.catch(reason => fetchWithErrorHandling.generalErrorHandler(reason));

const copyNodes = (nodes: NodeContextPath[]) => fetchWithErrorHandling.withCsrfToken(csrfToken => ({
url: routes.ui.service.copyNodes,

Expand Down Expand Up @@ -660,6 +676,7 @@ export default (routes: Routes) => {
publish,
discard,
changeBaseWorkspace,
rebaseWorkspace,
copyNodes,
cutNodes,
clearClipboard,
Expand Down
2 changes: 2 additions & 0 deletions packages/neos-ui-redux-store/src/CR/Workspaces/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ test(`should export actionTypes`, () => {
expect(typeof (actionTypes.DISCARD_ABORTED)).toBe('string');
expect(typeof (actionTypes.DISCARD_CONFIRMED)).toBe('string');
expect(typeof (actionTypes.CHANGE_BASE_WORKSPACE)).toBe('string');
expect(typeof (actionTypes.REBASE_WORKSPACE)).toBe('string');
});

test(`should export action creators`, () => {
Expand All @@ -19,6 +20,7 @@ test(`should export action creators`, () => {
expect(typeof (actions.abortDiscard)).toBe('function');
expect(typeof (actions.confirmDiscard)).toBe('function');
expect(typeof (actions.changeBaseWorkspace)).toBe('function');
expect(typeof (actions.rebaseWorkspace)).toBe('function');
});

test(`should export a reducer`, () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/neos-ui-redux-store/src/CR/Workspaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ const confirmDiscard = () => createAction(actionTypes.DISCARD_CONFIRMED);
const changeBaseWorkspace = (name: string) => createAction(actionTypes.CHANGE_BASE_WORKSPACE, name);

/**
* Confirm the ongoing discard
* Rebase the user workspace
*/
const rebaseWorkspace = () => createAction(actionTypes.REBASE_WORKSPACE);
const rebaseWorkspace = (name: string) => createAction(actionTypes.REBASE_WORKSPACE, name);

//
// Export the actions
Expand Down
69 changes: 69 additions & 0 deletions packages/neos-ui-redux-store/src/UI/SyncWorkspaceModal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import produce from 'immer';
import {action as createAction, ActionType} from 'typesafe-actions';

import {InitAction} from '../../System';

export interface State extends Readonly<{
isOpen: boolean;
}> {}

export const defaultState: State = {
isOpen: false
};

//
// Export the action types
//
export enum actionTypes {
OPEN = '@neos/neos-ui/UI/SyncWorkspaceModal/OPEN',
CANCEL = '@neos/neos-ui/UI/SyncWorkspaceModal/CANCEL',
APPLY = '@neos/neos-ui/UI/SyncWorkspaceModal/APPLY'
}

/**
* Opens the add node modal.
*/
const open = () => createAction(actionTypes.OPEN);

/**
* Closes the add node modal.
*/
const cancel = () => createAction(actionTypes.CANCEL);

/**
* Closes the add node modal.
*/
const apply = () => createAction(actionTypes.APPLY);

//
// Export the actions
//
export const actions = {
open,
cancel,
apply
};

export type Action = ActionType<typeof actions>;

//
// Export the reducer
//
export const reducer = (state: State = defaultState, action: InitAction | Action) => produce(state, draft => {
switch (action.type) {
case actionTypes.OPEN: {
draft.isOpen = true;
break;
}
case actionTypes.CANCEL: {
draft.isOpen = false;
break;
}
case actionTypes.APPLY: {
draft.isOpen = false;
break;
}
}
});

export const selectors = {};
4 changes: 4 additions & 0 deletions packages/neos-ui-redux-store/src/UI/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import * as InsertionModeModal from './InsertionModeModal';
import * as SelectNodeTypeModal from './SelectNodeTypeModal';
import * as NodeCreationDialog from './NodeCreationDialog';
import * as NodeVariantCreationDialog from './NodeVariantCreationDialog';
import * as SyncWorkspaceModal from './SyncWorkspaceModal';
import * as ContentTree from './ContentTree';

const all = {
Expand All @@ -37,6 +38,7 @@ const all = {
SelectNodeTypeModal,
NodeCreationDialog,
NodeVariantCreationDialog,
SyncWorkspaceModal,
ContentTree
};

Expand Down Expand Up @@ -64,6 +66,7 @@ export interface State {
selectNodeTypeModal: SelectNodeTypeModal.State;
nodeCreationDialog: NodeCreationDialog.State;
nodeVariantCreationDialog: NodeVariantCreationDialog.State;
SyncWorkspaceModal: SyncWorkspaceModal.State;
contentTree: ContentTree.State;
}

Expand Down Expand Up @@ -97,6 +100,7 @@ export const reducer = combineReducers({
selectNodeTypeModal: SelectNodeTypeModal.reducer,
nodeCreationDialog: NodeCreationDialog.reducer,
nodeVariantCreationDialog: NodeVariantCreationDialog.reducer,
SyncWorkspaceModal: SyncWorkspaceModal.reducer,
contentTree: ContentTree.reducer
} as any); // TODO: when we update redux, this shouldn't be necessary https://github.com/reduxjs/redux/issues/2709#issuecomment-357328709

Expand Down
19 changes: 19 additions & 0 deletions packages/neos-ui-sagas/src/Publish/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@ export function * watchChangeBaseWorkspace() {
});
}

export function * watchRebaseWorkspace() {
const {rebaseWorkspace, getWorkspaceInfo} = backend.get().endpoints;
yield takeEvery(actionTypes.CR.Workspaces.REBASE_WORKSPACE, function * change(action) {
yield put(actions.UI.Remote.startSaving());

try {
const feedback = yield call(rebaseWorkspace, action.payload);
yield put(actions.ServerFeedback.handleServerFeedback(feedback));

Check failure on line 52 in packages/neos-ui-sagas/src/Publish/index.js

View workflow job for this annotation

GitHub Actions / Code style

Block must not be padded by blank lines

} catch (error) {
console.error('Failed to sync user workspace', error);
} finally {
const workspaceInfo = yield call(getWorkspaceInfo);
yield put(actions.CR.Workspaces.update(workspaceInfo));
yield put(actions.UI.Remote.finishSaving());
}
});
}

export function * discardIfConfirmed() {
const {discard} = backend.get().endpoints;
yield takeLatest(actionTypes.CR.Workspaces.COMMENCE_DISCARD, function * waitForConfirmation() {
Expand Down
1 change: 1 addition & 0 deletions packages/neos-ui-sagas/src/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ manifest('main.sagas', {}, globalRegistry => {

sagasRegistry.set('neos-ui/CR/Policies/watchNodeInformationChanges', {saga: crPolicies.watchNodeInformationChanges});

sagasRegistry.set('neos-ui/Publish/watchRebaseWorkspace', {saga: publish.watchRebaseWorkspace});
sagasRegistry.set('neos-ui/Publish/watchChangeBaseWorkspace', {saga: publish.watchChangeBaseWorkspace});
sagasRegistry.set('neos-ui/Publish/discardIfConfirmed', {saga: publish.discardIfConfirmed});
sagasRegistry.set('neos-ui/Publish/watchPublish', {saga: publish.watchPublish});
Expand Down
Loading

0 comments on commit 234a31a

Please sign in to comment.