Skip to content

Commit

Permalink
Feature: Use existing conflict dialogue
Browse files Browse the repository at this point in the history
  • Loading branch information
pKallert committed Dec 16, 2024
1 parent c1fe4f5 commit 7a22dc2
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 209 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
use Neos\Neos\Domain\Service\WorkspacePublishingService;
use Neos\Neos\Ui\Application\Shared\ConflictsOccurred;
use Neos\Neos\Ui\Application\Shared\PublishSucceeded;
use Neos\Neos\Ui\Application\Shared\PartialPublishFailed;
use Neos\Neos\Ui\Controller\TranslationTrait;
use Neos\Neos\Ui\Infrastructure\ContentRepository\ConflictsFactory;

Expand Down Expand Up @@ -80,14 +79,21 @@ public function handle(
);

return new ConflictsOccurred(
conflicts: $conflictsFactory->fromWorkspaceRebaseFailed($e)
conflicts: $conflictsFactory->fromWorkspaceRebaseFailed($e),
isPartialPublish: false
);
} catch (PartialWorkspaceRebaseFailed $e) {
$workspace = $this->contentRepositoryRegistry->get($command->contentRepositoryId)->findWorkspaceByName(
$command->workspaceName
$conflictsFactory = new ConflictsFactory(
contentRepository: $this->contentRepositoryRegistry
->get($command->contentRepositoryId),
nodeLabelGenerator: $this->nodeLabelGenerator,
workspaceName: $command->workspaceName,
preferredDimensionSpacePoint: $command->preferredDimensionSpacePoint
);
return new PartialPublishFailed(
baseWorkspaceName: $workspace?->baseWorkspaceName?->value

return new ConflictsOccurred(
conflicts: $conflictsFactory->fromPartialWorkspaceRebaseFailed($e),
isPartialPublish: true
);
} catch (NodeAggregateCurrentlyDoesNotExist $e) {
throw new \RuntimeException(
Expand Down
3 changes: 2 additions & 1 deletion Classes/Application/Shared/ConflictsOccurred.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
final readonly class ConflictsOccurred implements \JsonSerializable
{
public function __construct(
public readonly Conflicts $conflicts
public readonly Conflicts $conflicts,
public readonly bool $isPartialPublish = true
) {
}

Expand Down
36 changes: 0 additions & 36 deletions Classes/Application/Shared/PartialPublishFailed.php

This file was deleted.

18 changes: 18 additions & 0 deletions Classes/Infrastructure/ContentRepository/ConflictsFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasTagged;
use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasUntagged;
use Neos\ContentRepository\Core\Feature\WorkspaceRebase\ConflictingEvent;
use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Exception\PartialWorkspaceRebaseFailed;
use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Exception\WorkspaceRebaseFailed;
use Neos\ContentRepository\Core\NodeType\NodeTypeManager;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphInterface;
Expand Down Expand Up @@ -87,6 +88,23 @@ public function fromWorkspaceRebaseFailed(
return new Conflicts(...$conflictsByKey);
}

public function fromPartialWorkspaceRebaseFailed(
PartialWorkspaceRebaseFailed $partialWorkspaceRebaseFailed
): Conflicts {
/** @var array<string,Conflict> */
$conflictsByKey = [];

foreach ($partialWorkspaceRebaseFailed->conflictingEvents as $conflictingEvent) {
$conflict = $this->createConflict($conflictingEvent);
if (!array_key_exists($conflict->key, $conflictsByKey)) {
// deduplicate if the conflict affects the same node
$conflictsByKey[$conflict->key] = $conflict;
}
}

return new Conflicts(...$conflictsByKey);
}

private function createConflict(
ConflictingEvent $conflictingEvent
): Conflict {
Expand Down
20 changes: 20 additions & 0 deletions Resources/Private/Translations/en/SyncWorkspaceDialog.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
<trans-unit id="resolutionStrategy.selection.option.DISCARD_ALL.description" xml:space="preserve">
<source>This will discard all changes in your workspace, including those on other sites.</source>
</trans-unit>
<trans-unit id="resolutionStrategy.selection.option.PUBLISH_ALL.label" xml:space="preserve">
<source>Publish all changes to workspace "{workspaceName}"</source>
</trans-unit>
<trans-unit id="resolutionStrategy.selection.option.PUBLISH_ALL.description" xml:space="preserve">
<source>This will publish all changes in your workspace, including those on other sites.</source>
</trans-unit>
<trans-unit id="resolutionStrategy.selection.cancel" xml:space="preserve">
<source>Cancel Synchronization</source>
</trans-unit>
Expand All @@ -58,12 +64,26 @@

Do you wish to proceed? Be careful: This cannot be undone!</source>
</trans-unit>
<trans-unit id="resolutionStrategy.PUBLISH_ALL.confirmation.title" xml:space="preserve">
<source>Publish all changes in workspace "{workspaceName}"</source>
</trans-unit>
<trans-unit id="resolutionStrategy.PUBLISH_ALL.confirmation.message" xml:space="preserve">
<source>You are about to publish all changes in workspace "{workspaceName}". This includes all changes on other sites.

Do you wish to proceed? Be careful: This cannot be undone!</source>
</trans-unit>
<trans-unit id="resolutionStrategy.DISCARD_ALL.confirmation.cancel" xml:space="preserve">
<source>No, cancel</source>
</trans-unit>
<trans-unit id="resolutionStrategy.DISCARD_ALL.confirmation.confirm" xml:space="preserve">
<source>Yes, discard everything</source>
</trans-unit>
<trans-unit id="resolutionStrategy.PUBLISH_ALL.confirmation.cancel" xml:space="preserve">
<source>No, cancel</source>
</trans-unit>
<trans-unit id="resolutionStrategy.PUBLISH_ALL.confirmation.confirm" xml:space="preserve">
<source>Yes, publish everything</source>
</trans-unit>
<trans-unit id="resolutionStrategy.FORCE.confirmation.conflicts.label" xml:space="preserve">
<source>You are about to drop the following changes:</source>
</trans-unit>
Expand Down
17 changes: 0 additions & 17 deletions packages/neos-ui-redux-store/src/CR/Publishing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export enum PublishingPhase {
START,
ONGOING,
CONFLICTS,
PARTIALLYFAILED,
SUCCESS,
ERROR
}
Expand All @@ -38,7 +37,6 @@ export type State = null | {
| { phase: PublishingPhase.START }
| { phase: PublishingPhase.ONGOING }
| { phase: PublishingPhase.CONFLICTS }
| { phase: PublishingPhase.PARTIALLYFAILED }
| {
phase: PublishingPhase.ERROR;
error: null | AnyError;
Expand All @@ -58,9 +56,7 @@ export enum actionTypes {
CONFLICTS_OCCURRED = '@neos/neos-ui/CR/Publishing/CONFLICTS_OCCURRED',
CONFLICTS_RESOLVED = '@neos/neos-ui/CR/Publishing/CONFLICTS_RESOLVED',
FAILED = '@neos/neos-ui/CR/Publishing/FAILED',
PARTIALLYFAILED = '@neos/neos-ui/CR/Publishing/PARTIALLYFAILED',
RETRIED = '@neos/neos-ui/CR/Publishing/RETRIED',
RETRIEDWITHSTATE = '@neos/neos-ui/CR/Publishing/RETRIEDWITHSTATE',
SUCEEDED = '@neos/neos-ui/CR/Publishing/SUCEEDED',
ACKNOWLEDGED = '@neos/neos-ui/CR/Publishing/ACKNOWLEDGED',
FINISHED = '@neos/neos-ui/CR/Publishing/FINISHED'
Expand Down Expand Up @@ -98,11 +94,6 @@ const resolveConflicts = () => createAction(actionTypes.CONFLICTS_RESOLVED);
const fail = (error: null | AnyError) =>
createAction(actionTypes.FAILED, {error});

/**
* Signal that the ongoing publish/discard workflow has partially failed
*/
const partialFail = () => createAction(actionTypes.PARTIALLYFAILED);

/**
* Attempt to retry a failed publish/discard workflow
*/
Expand Down Expand Up @@ -134,7 +125,6 @@ export const actions = {
conflicts,
resolveConflicts,
fail,
partialFail,
retry,
succeed,
acknowledge,
Expand Down Expand Up @@ -193,13 +183,6 @@ export const reducer = (state: State = defaultState, action: Action): State => {
error: action.payload.error
}
};
case actionTypes.PARTIALLYFAILED:
return {
...state,
process: {
phase: PublishingPhase.PARTIALLYFAILED
}
};
case actionTypes.RETRIED:
return {
...state,
Expand Down
9 changes: 5 additions & 4 deletions packages/neos-ui-redux-store/src/CR/Syncing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export enum SyncingPhase {

export enum ResolutionStrategy {
FORCE,
DISCARD_ALL
DISCARD_ALL,
PUBLISH_ALL
}

export enum ReasonForConflict {
Expand Down Expand Up @@ -106,8 +107,8 @@ const confirm = () => createAction(actionTypes.CONFIRMED);
/**
* Signal that conflicts occurred during the ongoing syncing (rebasing) workflow
*/
const resolve = (conflicts: Conflict[]) =>
createAction(actionTypes.CONFLICTS_DETECTED, {conflicts});
const resolve = (conflicts: Conflict[], strategy: ResolutionStrategy) =>
createAction(actionTypes.CONFLICTS_DETECTED, {conflicts, strategy});

/**
* Initiates the process of resolving a conflict that occurred
Expand Down Expand Up @@ -192,7 +193,7 @@ export const reducer = (state: State = defaultState, action: Action): State => {
process: {
phase: SyncingPhase.CONFLICT,
conflicts: action.payload.conflicts,
strategy: null
strategy: action.payload.strategy
}
};
}
Expand Down
6 changes: 3 additions & 3 deletions packages/neos-ui-sagas/src/Publish/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ type PublishingResponse =
}
| {
partialPublishFail: {
numberOfAffectedChanges: number;
conflicts: Conflict[];
}
}
| { conflicts: Conflict[] }
| { conflicts: Conflict[], isPartialPublish: boolean }
| { error: AnyError };

export function * watchPublishing({routes}: {routes: Routes}) {
Expand Down Expand Up @@ -109,7 +109,7 @@ export function * watchPublishing({routes}: {routes: Routes}) {
} else if ('conflicts' in result) {
yield put(actions.CR.Publishing.conflicts());
const conflictsWereResolved: boolean =
yield * resolveConflicts(result.conflicts);
yield * resolveConflicts(result.conflicts, result.isPartialPublish);

if (conflictsWereResolved) {
yield put(actions.CR.Publishing.resolveConflicts());
Expand Down
47 changes: 43 additions & 4 deletions packages/neos-ui-sagas/src/Sync/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const handleWindowBeforeUnload = (event: BeforeUnloadEvent) => {

type SyncWorkspaceResult =
| { success: true }
| { conflicts: Conflict[] }
| { conflicts: Conflict[], isPartialPublish: false }
| { error: AnyError };

export function * watchSyncing({routes}: {routes: Routes}) {
Expand Down Expand Up @@ -75,7 +75,7 @@ export const makeSyncPersonalWorkspace = (deps: {
yield * refreshAfterSyncing();
yield put(actions.CR.Syncing.succeed());
} else if ('conflicts' in result) {
yield * resolveConflicts(result.conflicts);
yield * resolveConflicts(result.conflicts, result.isPartialPublish);
} else {
yield put(actions.CR.Syncing.fail(result.error));
}
Expand All @@ -93,10 +93,12 @@ export const makeResolveConflicts = (deps: {
syncPersonalWorkspace: ReturnType<typeof makeSyncPersonalWorkspace>
}) => {
const discardAll = makeDiscardAll(deps);
const publishAll = makePublishAll(deps);

function * resolveConflicts(conflicts: Conflict[]): any {
function * resolveConflicts(conflicts: Conflict[], isPartialPublish: boolean): any {
while (true) {
yield put(actions.CR.Syncing.resolve(conflicts));
const defaultResolutionStrategy = isPartialPublish ? ResolutionStrategy.PUBLISH_ALL : ResolutionStrategy.FORCE
yield put(actions.CR.Syncing.resolve(conflicts, defaultResolutionStrategy));

const {started}: {
cancelled: null | ReturnType<typeof actions.CR.Syncing.cancel>;
Expand All @@ -122,6 +124,11 @@ export const makeResolveConflicts = (deps: {
yield * discardAll();
return true;
}

if (strategy === ResolutionStrategy.PUBLISH_ALL) {
yield * publishAll();
return true;
}
}

return false;
Expand Down Expand Up @@ -187,6 +194,38 @@ const makeDiscardAll = (deps: {
return discardAll;
}

const makePublishAll = (deps: {
syncPersonalWorkspace: ReturnType<typeof makeSyncPersonalWorkspace>;
}) => {
function * publishAll() {
yield put(actions.CR.Publishing.start(
PublishingMode.PUBLISH,
PublishingScope.ALL
));

const {cancelled, failed}: {
cancelled: null | ReturnType<typeof actions.CR.Publishing.cancel>;
failed: null | ReturnType<typeof actions.CR.Publishing.fail>;
finished: null | ReturnType<typeof actions.CR.Publishing.finish>;
} = yield race({
cancelled: take(actionTypes.CR.Publishing.CANCELLED),
failed: take(actionTypes.CR.Publishing.FAILED),
finished: take(actionTypes.CR.Publishing.FINISHED)
});

if (cancelled) {
yield put(actions.CR.Syncing.cancelResolution());
} else if (failed) {
yield put(actions.CR.Syncing.finish());
} else {
yield put(actions.CR.Syncing.confirmResolution());
yield * deps.syncPersonalWorkspace(false);
}
}

return publishAll;
}

const makeRefreshAfterSyncing = (deps: {
routes: Routes
}) => {
Expand Down
Loading

0 comments on commit 7a22dc2

Please sign in to comment.