diff --git a/src/model.ts b/src/model.ts index f2a713db4f..88bafaf477 100644 --- a/src/model.ts +++ b/src/model.ts @@ -448,6 +448,14 @@ export class Model extends EventBus implements CommandDispatcher { this.status = Status.Ready; } + /** + * Check if a command can be dispatched, and returns a DispatchResult object with the possible + * reasons the dispatch failed. + */ + canDispatch: CommandDispatcher["canDispatch"] = (type: string, payload?: any) => { + return this.checkDispatchAllowed({ ...payload, type }); + }; + /** * The dispatch method is the only entry point to manipulate data in the model. * This is through this method that commands are dispatched most of the time diff --git a/src/types/commands.ts b/src/types/commands.ts index b6dcb84266..5c557e08e4 100644 --- a/src/types/commands.ts +++ b/src/types/commands.ts @@ -1160,6 +1160,10 @@ export interface CommandDispatcher { type: T, r: Omit ): DispatchResult; + canDispatch>( + type: T, + r: Omit + ): DispatchResult; } export interface CoreCommandDispatcher { @@ -1170,6 +1174,10 @@ export interface CoreCommandDispatcher { type: T, r: Omit ): DispatchResult; + canDispatch>( + type: T, + r: Omit + ): DispatchResult; } export type CommandTypes = Command["type"]; diff --git a/tests/model.test.ts b/tests/model.test.ts index e44a92adb3..81075265ef 100644 --- a/tests/model.test.ts +++ b/tests/model.test.ts @@ -111,6 +111,31 @@ describe("Model", () => { featurePluginRegistry.remove("myUIPlugin"); }); + test("canDispatch method is exposed and works", () => { + class MyCorePlugin extends CorePlugin { + allowDispatch(cmd: CoreCommand) { + if (cmd.type === "CREATE_SHEET") { + return CommandResult.CancelledForUnknownReason; + } + return CommandResult.Success; + } + } + corePluginRegistry.add("myCorePlugin", MyCorePlugin); + const model = new Model(); + expect(model.canDispatch("CREATE_SHEET", { sheetId: "42", position: 1 })).toBeCancelledBecause( + CommandResult.CancelledForUnknownReason + ); + expect(model.dispatch("CREATE_SHEET", { sheetId: "42", position: 1 })).toBeCancelledBecause( + CommandResult.CancelledForUnknownReason + ); + + expect(model.canDispatch("UPDATE_CELL", { sheetId: "42", col: 0, row: 0, content: "hey" })) + .toBeSuccessfullyDispatched; + expect(model.dispatch("UPDATE_CELL", { sheetId: "42", col: 0, row: 0, content: "hey" })) + .toBeSuccessfullyDispatched; + corePluginRegistry.remove("myCorePlugin"); + }); + test("Can open a model in readonly mode", () => { const model = new Model({}, { mode: "readonly" }); expect(model.getters.isReadonly()).toBe(true);