Create WP Redux store

[MAILPOET-2676]
This commit is contained in:
Amine Ben hammou
2020-03-04 22:58:17 +01:00
committed by amine-mp
parent 408437af70
commit 1d6a7f6fde
10 changed files with 201 additions and 6 deletions

View File

@@ -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 = () => (
<>
<h1 className="title">Settings</h1>
<pre><code>{JSON.stringify((window as any).mailpoet_settings)}</code></pre>
</>
);
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>
<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);
}

View 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' };
}

View 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 }) {
// ...
}

View 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;
}
};
}

View 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: {},
});

View File

@@ -0,0 +1,11 @@
import { State, Settings } from './types';
export default function makeDefaultState(data: Settings): State {
return {
save: {
inProgress: false,
error: null,
},
data,
};
}

View 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;
}

View 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
View File

@@ -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",

View File

@@ -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",