Skip to content

Commit

Permalink
[IMP] model: add canDispatch method
Browse files Browse the repository at this point in the history
Add the method `canDispatch` in the model, that will run the given commands
against the `allowDispatch` of the handlers, and return the result.

This will be useful to dynamically display errors in side panels, without
waiting for user confirmation.

Part of task 3271348

Part-of: #2331
  • Loading branch information
hokolomopo committed Apr 12, 2023
1 parent ca3b3d9 commit 18dcf13
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,14 @@ export class Model extends EventBus<any> 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
Expand Down
8 changes: 8 additions & 0 deletions src/types/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,10 @@ export interface CommandDispatcher {
type: T,
r: Omit<C, "type">
): DispatchResult;
canDispatch<T extends CommandTypes, C extends Extract<Command, { type: T }>>(
type: T,
r: Omit<C, "type">
): DispatchResult;
}

export interface CoreCommandDispatcher {
Expand All @@ -1170,6 +1174,10 @@ export interface CoreCommandDispatcher {
type: T,
r: Omit<C, "type">
): DispatchResult;
canDispatch<T extends CoreCommandTypes, C extends Extract<CoreCommand, { type: T }>>(
type: T,
r: Omit<C, "type">
): DispatchResult;
}

export type CommandTypes = Command["type"];
Expand Down
25 changes: 25 additions & 0 deletions tests/model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 18dcf13

Please sign in to comment.