Create WP Redux store
[MAILPOET-2676]
This commit is contained in:
committed by
amine-mp
parent
408437af70
commit
1d6a7f6fde
@@ -1,14 +1,44 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { useSelect, useDispatch } from '@wordpress/data';
|
||||
import { initStore, STORE_NAME } from './store';
|
||||
|
||||
const App = () => (
|
||||
const App = () => {
|
||||
const isSaving = useSelect(
|
||||
(sel) => sel(STORE_NAME).isSaving(),
|
||||
[]
|
||||
);
|
||||
const error = useSelect(
|
||||
(sel) => sel(STORE_NAME).getError(),
|
||||
[]
|
||||
);
|
||||
const settings = useSelect(
|
||||
(sel) => sel(STORE_NAME).getSettings(),
|
||||
[]
|
||||
);
|
||||
const email = useSelect(
|
||||
(sel) => sel(STORE_NAME).getSetting(['sender', 'address']),
|
||||
[]
|
||||
);
|
||||
const actions = useDispatch(STORE_NAME);
|
||||
const setEmail = (event) => {
|
||||
actions.setSetting(['sender', 'address'], event.target.value);
|
||||
};
|
||||
const save = () => {
|
||||
actions.saveSettings(settings);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<h1 className="title">Settings</h1>
|
||||
<pre><code>{JSON.stringify((window as any).mailpoet_settings)}</code></pre>
|
||||
<p>{JSON.stringify({ email, isSaving, error })}</p>
|
||||
<input type="text" value={email} onChange={setEmail} />
|
||||
<button type="button" onClick={save}>Save</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const container = document.getElementById('settings_container');
|
||||
if (container) {
|
||||
initStore((window as any).mailpoet_settings);
|
||||
ReactDOM.render(<App />, container);
|
||||
}
|
||||
|
15
assets/js/src/settings/store/actions.ts
Normal file
15
assets/js/src/settings/store/actions.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Action, Settings } from './types';
|
||||
|
||||
export function setSetting(path: string[], value: any): Action {
|
||||
return { type: 'SET_SETTING', path, value };
|
||||
}
|
||||
|
||||
export function* saveSettings(data: Settings) {
|
||||
yield { type: 'SAVE_STARTED' };
|
||||
const error = yield { type: 'SEND_DATA_TO_API', data };
|
||||
if (error) {
|
||||
return { type: 'SAVE_FAILED', error };
|
||||
}
|
||||
yield { type: 'TRACK_SETTINGS_SAVED', data };
|
||||
return { type: 'SAVE_DONE' };
|
||||
}
|
19
assets/js/src/settings/store/controls.ts
Normal file
19
assets/js/src/settings/store/controls.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import MailPoet from 'mailpoet';
|
||||
|
||||
export async function SEND_DATA_TO_API({ data }) {
|
||||
try {
|
||||
await MailPoet.Ajax.post({
|
||||
api_version: (window as any).mailpoet_api_version,
|
||||
endpoint: 'settings',
|
||||
action: 'set',
|
||||
data,
|
||||
});
|
||||
return false;
|
||||
} catch (res) {
|
||||
return res.errors.map((e) => e.message);
|
||||
}
|
||||
}
|
||||
|
||||
export function TRACK_SETTINGS_SAVED({ data }) {
|
||||
// ...
|
||||
}
|
19
assets/js/src/settings/store/create_reducer.ts
Normal file
19
assets/js/src/settings/store/create_reducer.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import _ from 'lodash';
|
||||
import { State, Action } from './types';
|
||||
|
||||
export default function createReducer(defaultValue: State) {
|
||||
return (state: State = defaultValue, action: Action): State => {
|
||||
switch (action.type) {
|
||||
case 'SET_SETTING':
|
||||
return _.setWith(_.clone(state), ['data', ...action.path], action.value, _.clone);
|
||||
case 'SAVE_STARTED':
|
||||
return { ...state, save: { inProgress: true, error: null } };
|
||||
case 'SAVE_DONE':
|
||||
return { ...state, save: { inProgress: false, error: null } };
|
||||
case 'SAVE_FAILED':
|
||||
return { ...state, save: { inProgress: false, error: action.error } };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
}
|
17
assets/js/src/settings/store/index.ts
Normal file
17
assets/js/src/settings/store/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { registerStore } from '@wordpress/data';
|
||||
import { Settings } from './types';
|
||||
import * as actions from './actions';
|
||||
import * as selectors from './selectors';
|
||||
import * as controls from './controls';
|
||||
import createReducer from './create_reducer';
|
||||
import makeDefaultState from './make_default_state';
|
||||
|
||||
export const STORE_NAME = 'mailpoet-settings';
|
||||
|
||||
export const initStore = (data: Settings) => registerStore(STORE_NAME, {
|
||||
reducer: createReducer(makeDefaultState(data)),
|
||||
actions,
|
||||
selectors,
|
||||
controls,
|
||||
resolvers: {},
|
||||
});
|
11
assets/js/src/settings/store/make_default_state.ts
Normal file
11
assets/js/src/settings/store/make_default_state.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { State, Settings } from './types';
|
||||
|
||||
export default function makeDefaultState(data: Settings): State {
|
||||
return {
|
||||
save: {
|
||||
inProgress: false,
|
||||
error: null,
|
||||
},
|
||||
data,
|
||||
};
|
||||
}
|
22
assets/js/src/settings/store/selectors.ts
Normal file
22
assets/js/src/settings/store/selectors.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import _ from 'lodash';
|
||||
import { State, Settings } from './types';
|
||||
|
||||
export function getSetting(state: State, path: string[]): any {
|
||||
return _.get(state.data, path);
|
||||
}
|
||||
|
||||
export function getSettings(state: State): Settings {
|
||||
return state.data;
|
||||
}
|
||||
|
||||
export function isSaving(state: State): boolean {
|
||||
return state.save.inProgress;
|
||||
}
|
||||
|
||||
export function hasError(state: State): boolean {
|
||||
return state.save.error !== null;
|
||||
}
|
||||
|
||||
export function getError(state: State): any {
|
||||
return state.save.error;
|
||||
}
|
55
assets/js/src/settings/store/types.ts
Normal file
55
assets/js/src/settings/store/types.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
export type Settings = {
|
||||
sender: {
|
||||
name: string
|
||||
address: string
|
||||
}
|
||||
reply_to: {
|
||||
name: string
|
||||
address: string
|
||||
}
|
||||
subscribe: {
|
||||
on_comment: {
|
||||
enabled: boolean
|
||||
label: string
|
||||
segments: string[]
|
||||
}
|
||||
on_register: {
|
||||
enabled: boolean
|
||||
label: string
|
||||
segments: string[]
|
||||
}
|
||||
}
|
||||
subscription: {
|
||||
pages: {
|
||||
manage: string
|
||||
unsubscribe: string
|
||||
confirmation: string
|
||||
captcha: string
|
||||
}
|
||||
segments: string[]
|
||||
}
|
||||
stats_notifications: {
|
||||
enabled: boolean
|
||||
automated: boolean
|
||||
address: string
|
||||
}
|
||||
subscriber_email_notification: {
|
||||
enabled: boolean
|
||||
address: string
|
||||
}
|
||||
// ...
|
||||
}
|
||||
|
||||
export type State = {
|
||||
data: Settings
|
||||
save: {
|
||||
inProgress: boolean
|
||||
error: any
|
||||
}
|
||||
}
|
||||
|
||||
export type Action =
|
||||
| { type: 'SET_SETTING'; value: any; path: string[] }
|
||||
| { type: 'SAVE_STARTED' }
|
||||
| { type: 'SAVE_DONE' }
|
||||
| { type: 'SAVE_FAILED'; error: any }
|
6
package-lock.json
generated
6
package-lock.json
generated
@@ -3968,6 +3968,12 @@
|
||||
"integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/lodash": {
|
||||
"version": "4.14.149",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz",
|
||||
"integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/minimatch": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
|
||||
|
@@ -86,6 +86,7 @@
|
||||
"@babel/preset-react": "^7.8.3",
|
||||
"@babel/preset-typescript": "^7.8.3",
|
||||
"@babel/register": "^7.8.3",
|
||||
"@types/lodash": "^4.14.149",
|
||||
"@types/react": "^16.9.22",
|
||||
"@typescript-eslint/eslint-plugin": "^2.21.0",
|
||||
"@typescript-eslint/parser": "^2.21.0",
|
||||
|
Reference in New Issue
Block a user