mirror of
https://gitlab.nic.cz/turris/reforis/foris-js.git
synced 2024-12-26 00:21:36 +01:00
Merge branch 'ws-unsubscription' into 'dev'
Add WS unsubscribtion. See merge request turris/reforis/foris-js!53
This commit is contained in:
commit
61d10e91e0
|
@ -20,14 +20,16 @@ import { useForisModule, useForm } from "../hooks";
|
||||||
import { STATES as SUBMIT_BUTTON_STATES, SubmitButton } from "./SubmitButton";
|
import { STATES as SUBMIT_BUTTON_STATES, SubmitButton } from "./SubmitButton";
|
||||||
|
|
||||||
ForisForm.propTypes = {
|
ForisForm.propTypes = {
|
||||||
/** WebSocket object see `scr/common/WebSockets.js`. */
|
/** Optional WebSocket object. See `scr/common/WebSockets.js`.
|
||||||
|
* `forisConfig.wsModule` should be specified when it's passed.
|
||||||
|
* */
|
||||||
ws: PropTypes.object,
|
ws: PropTypes.object,
|
||||||
/** Foris configuration object. See usage in main components. */
|
/** Foris configuration object. See usage in main components. */
|
||||||
forisConfig: PropTypes.shape({
|
forisConfig: PropTypes.shape({
|
||||||
/** reForis Flask aplication API endpoint from `src/common/API.js`. */
|
/** reForis Flask aplication API endpoint from `src/common/API.js`. */
|
||||||
endpoint: PropTypes.string.isRequired,
|
endpoint: PropTypes.string.isRequired,
|
||||||
/** `foris-controller` module name to be used via WebSockets.
|
/** `foris-controller` module name to be used via WebSockets.
|
||||||
* If it's not passed then WebSockets aren't used
|
* It can be use only with `ws` prop.
|
||||||
* */
|
* */
|
||||||
wsModule: PropTypes.string,
|
wsModule: PropTypes.string,
|
||||||
/** `foris-controller` action name to be used via WebSockets.
|
/** `foris-controller` action name to be used via WebSockets.
|
||||||
|
@ -49,6 +51,17 @@ ForisForm.propTypes = {
|
||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
/** Optional override of form submit callback */
|
/** Optional override of form submit callback */
|
||||||
onSubmitOverridden: PropTypes.func,
|
onSubmitOverridden: PropTypes.func,
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/no-unused-prop-types
|
||||||
|
customWSProp(props) {
|
||||||
|
const wsModuleIsSpecified = !!(props.forisConfig && props.forisConfig.wsModule);
|
||||||
|
if (props.ws && !wsModuleIsSpecified) {
|
||||||
|
return new Error("forisConfig.wsModule should be specified when ws object is passed.");
|
||||||
|
}
|
||||||
|
if (!props.ws && wsModuleIsSpecified) {
|
||||||
|
return new Error("forisConfig.wsModule is specified without passing ws object.");
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
ForisForm.defaultProps = {
|
ForisForm.defaultProps = {
|
||||||
|
|
|
@ -61,9 +61,36 @@ export class WebSockets {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(params) {
|
subscribe(module) {
|
||||||
this.waitForConnection(() => {
|
this.waitForConnection(() => {
|
||||||
this.send("subscribe", params);
|
this.send("subscribe", module);
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
unbind(module, action, callback) {
|
||||||
|
const callbacks = this.callbacks[module][action];
|
||||||
|
|
||||||
|
const index = callbacks.indexOf(callback);
|
||||||
|
if (index !== -1) {
|
||||||
|
callbacks.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbacks.length === 0) {
|
||||||
|
delete this.callbacks[module][action];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(this.callbacks[module]).length === 0) {
|
||||||
|
this.unsubscribe(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsubscribe(module) {
|
||||||
|
this.waitForConnection(() => {
|
||||||
|
this.send("unsubscribe", module);
|
||||||
|
delete this.callbacks[module];
|
||||||
});
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -82,15 +109,15 @@ export class WebSockets {
|
||||||
let chain;
|
let chain;
|
||||||
try {
|
try {
|
||||||
chain = this.callbacks[json.module][json.action];
|
chain = this.callbacks[json.module][json.action];
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
if (e instanceof TypeError) {
|
if (error instanceof TypeError) {
|
||||||
console.log(`Callback for this message wasn't found:${e.data}`);
|
console.log(`Callback for this message wasn't found:${error.data}`);
|
||||||
} else throw e;
|
} else throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof chain === "undefined") return;
|
if (typeof chain === "undefined") return;
|
||||||
|
|
||||||
for (let i = 0; i < chain.length; i++) chain[i](json);
|
chain.forEach((callback) => callback(json));
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
|
|
@ -11,12 +11,21 @@ export function useWSForisModule(ws, module, action = "update_settings") {
|
||||||
const [data, setData] = useState(null);
|
const [data, setData] = useState(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ws && module) {
|
// Sometimes we want to disable this hook if WS is not passed. We can't make conditional
|
||||||
ws.subscribe(module)
|
// hooks, but we can disable it here. It's used especially in ForisForm when a module
|
||||||
.bind(module, action, (msg) => {
|
// doesn't present any WS endpoint.
|
||||||
setData(msg.data);
|
if (!ws) return;
|
||||||
});
|
|
||||||
|
function callback(msg) {
|
||||||
|
setData(msg.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ws.subscribe(module)
|
||||||
|
.bind(module, action, callback);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
ws.unbind(module, action, callback);
|
||||||
|
};
|
||||||
}, [action, module, ws]);
|
}, [action, module, ws]);
|
||||||
|
|
||||||
return [data];
|
return [data];
|
||||||
|
|
Loading…
Reference in New Issue
Block a user