Skip to content

Commit 7d3fafc

Browse files
Infinite-NullInfinite-NulladamsilversteinMamadukajorostoyanov
authored
Edit Widgets: save lock control via actions (WordPress#69984)
Co-authored-by: Infinite-Null <ankitkumarshah@git.wordpress.org> Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: jorostoyanov <stoyanovgs@git.wordpress.org>
1 parent 1fea5e7 commit 7d3fafc

File tree

7 files changed

+205
-9
lines changed

7 files changed

+205
-9
lines changed

docs/reference-guides/data/data-core-edit-widgets.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,18 @@ _Returns_
136136

137137
- `boolean`: True if any widget area is currently being saved. False otherwise.
138138

139+
### isWidgetSavingLocked
140+
141+
Returns whether widget saving is locked.
142+
143+
_Parameters_
144+
145+
- _state_ `Object`: Global application state.
146+
147+
_Returns_
148+
149+
- `boolean`: Is locked.
150+
139151
<!-- END TOKEN(Autogenerated selectors|../../../packages/edit-widgets/src/store/selectors.js) -->
140152

141153
## Actions
@@ -150,6 +162,18 @@ _Returns_
150162

151163
- `Object`: Action creator.
152164

165+
### lockWidgetSaving
166+
167+
Returns an action object used to signal that widget saving is locked.
168+
169+
_Parameters_
170+
171+
- _lockName_ `string`: The lock name.
172+
173+
_Returns_
174+
175+
- `Object`: Action object
176+
153177
### moveBlockToWidgetArea
154178

155179
Action that handles moving a block between widget areas
@@ -270,4 +294,16 @@ _Returns_
270294

271295
- `Object`: Action.
272296

297+
### unlockWidgetSaving
298+
299+
Returns an action object used to signal that widget saving is unlocked.
300+
301+
_Parameters_
302+
303+
- _lockName_ `string`: The lock name.
304+
305+
_Returns_
306+
307+
- `Object`: Action object
308+
273309
<!-- END TOKEN(Autogenerated actions|../../../packages/edit-widgets/src/store/actions.js) -->

packages/edit-widgets/src/components/save-button/index.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,26 @@ import { useDispatch, useSelect } from '@wordpress/data';
1111
import { store as editWidgetsStore } from '../../store';
1212

1313
function SaveButton() {
14-
const { hasEditedWidgetAreaIds, isSaving } = useSelect( ( select ) => {
15-
const { getEditedWidgetAreas, isSavingWidgetAreas } =
16-
select( editWidgetsStore );
14+
const { hasEditedWidgetAreaIds, isSaving, isWidgetSaveLocked } = useSelect(
15+
( select ) => {
16+
const {
17+
getEditedWidgetAreas,
18+
isSavingWidgetAreas,
19+
isWidgetSavingLocked,
20+
} = select( editWidgetsStore );
1721

18-
return {
19-
hasEditedWidgetAreaIds: getEditedWidgetAreas()?.length > 0,
20-
isSaving: isSavingWidgetAreas(),
21-
};
22-
}, [] );
22+
return {
23+
hasEditedWidgetAreaIds: getEditedWidgetAreas()?.length > 0,
24+
isSaving: isSavingWidgetAreas(),
25+
isWidgetSaveLocked: isWidgetSavingLocked(),
26+
};
27+
},
28+
[]
29+
);
2330
const { saveEditedWidgetAreas } = useDispatch( editWidgetsStore );
2431

25-
const isDisabled = isSaving || ! hasEditedWidgetAreaIds;
32+
const isDisabled =
33+
isWidgetSaveLocked || isSaving || ! hasEditedWidgetAreaIds;
2634

2735
return (
2836
<Button

packages/edit-widgets/src/store/actions.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,3 +431,31 @@ export const moveBlockToWidgetArea =
431431
destinationIndex
432432
);
433433
};
434+
435+
/**
436+
* Returns an action object used to signal that widget saving is unlocked.
437+
*
438+
* @param {string} lockName The lock name.
439+
*
440+
* @return {Object} Action object
441+
*/
442+
export function unlockWidgetSaving( lockName ) {
443+
return {
444+
type: 'UNLOCK_WIDGET_SAVING',
445+
lockName,
446+
};
447+
}
448+
449+
/**
450+
* Returns an action object used to signal that widget saving is locked.
451+
*
452+
* @param {string} lockName The lock name.
453+
*
454+
* @return {Object} Action object
455+
*/
456+
export function lockWidgetSaving( lockName ) {
457+
return {
458+
type: 'LOCK_WIDGET_SAVING',
459+
lockName,
460+
};
461+
}

packages/edit-widgets/src/store/reducer.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,36 @@ export function inserterSidebarToggleRef( state = { current: null } ) {
9090
return state;
9191
}
9292

93+
/**
94+
* Widget saving lock.
95+
*
96+
* When widget saving is locked, the widget cannot be updated.
97+
*
98+
* @param {Object} state Current state.
99+
* @param {Object} action Dispatched action.
100+
*
101+
* @return {Object} Updated state.
102+
*/
103+
export function widgetSavingLock( state = {}, action ) {
104+
switch ( action.type ) {
105+
case 'LOCK_WIDGET_SAVING':
106+
return { ...state, [ action.lockName ]: true };
107+
108+
case 'UNLOCK_WIDGET_SAVING': {
109+
const { [ action.lockName ]: removedLockName, ...restState } =
110+
state;
111+
return restState;
112+
}
113+
}
114+
115+
return state;
116+
}
117+
93118
export default combineReducers( {
94119
blockInserterPanel,
95120
inserterSidebarToggleRef,
96121
listViewPanel,
97122
listViewToggleRef,
98123
widgetAreasOpenState,
124+
widgetSavingLock,
99125
} );

packages/edit-widgets/src/store/selectors.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,14 @@ export const canInsertBlockInWidgetArea = createRegistrySelector(
311311
export function isListViewOpened( state ) {
312312
return state.listViewPanel;
313313
}
314+
315+
/**
316+
* Returns whether widget saving is locked.
317+
*
318+
* @param {Object} state Global application state.
319+
*
320+
* @return {boolean} Is locked.
321+
*/
322+
export function isWidgetSavingLocked( state ) {
323+
return Object.keys( state.widgetSavingLock ).length > 0;
324+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import deepFreeze from 'deep-freeze';
5+
6+
/**
7+
* Internal dependencies
8+
*/
9+
import { widgetSavingLock } from '../reducer';
10+
11+
describe( 'state', () => {
12+
describe( 'widgetSavingLock', () => {
13+
it( 'returns empty object by default', () => {
14+
const state = widgetSavingLock( undefined, {} );
15+
16+
expect( state ).toEqual( {} );
17+
} );
18+
19+
it( 'returns correct widget saving locks when locks added and removed', () => {
20+
let state = widgetSavingLock( undefined, {
21+
type: 'LOCK_WIDGET_SAVING',
22+
lockName: 'test-lock',
23+
} );
24+
25+
expect( state ).toEqual( {
26+
'test-lock': true,
27+
} );
28+
29+
state = widgetSavingLock( deepFreeze( state ), {
30+
type: 'LOCK_WIDGET_SAVING',
31+
lockName: 'test-lock-2',
32+
} );
33+
34+
expect( state ).toEqual( {
35+
'test-lock': true,
36+
'test-lock-2': true,
37+
} );
38+
39+
state = widgetSavingLock( deepFreeze( state ), {
40+
type: 'UNLOCK_WIDGET_SAVING',
41+
lockName: 'test-lock',
42+
} );
43+
44+
expect( state ).toEqual( {
45+
'test-lock-2': true,
46+
} );
47+
48+
state = widgetSavingLock( deepFreeze( state ), {
49+
type: 'UNLOCK_WIDGET_SAVING',
50+
lockName: 'test-lock-2',
51+
} );
52+
53+
expect( state ).toEqual( {} );
54+
} );
55+
} );
56+
} );
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Internal dependencies
3+
*/
4+
import * as _selectors from '../selectors';
5+
6+
const selectors = { ..._selectors };
7+
const { isWidgetSavingLocked } = selectors;
8+
9+
describe( 'selectors', () => {
10+
describe( 'isWidgetSavingLocked', () => {
11+
it( 'should return true if the post has widgetSavingLocks', () => {
12+
const state = {
13+
widgetSavingLock: { example: true },
14+
currentWidget: {},
15+
saving: {},
16+
};
17+
18+
expect( isWidgetSavingLocked( state ) ).toBe( true );
19+
} );
20+
21+
it( 'should return false if the post has no widgetSavingLocks', () => {
22+
const state = {
23+
widgetSavingLock: {},
24+
currentWidget: {},
25+
saving: {},
26+
};
27+
28+
expect( isWidgetSavingLocked( state ) ).toBe( false );
29+
} );
30+
} );
31+
} );

0 commit comments

Comments
 (0)