Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function buildCommandConfig(): void

public function execute(mixed $instanceId, array $data = []): array
{
return $this->link('https://facebook.com');
return $this->link('https://facebook.com', openInNewTab: true);
}

public function authorizeFor(mixed $instanceId): bool
Expand Down
20 changes: 10 additions & 10 deletions docs/guide/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,18 @@ Here is the full list of available methods:

### Command return types

Finally, let's review the return possibilities: after a Command has been executed, the code must return something to tell to the front what to do next. There are height of them:
Finally, let's review the return possibilities: after a Command has been executed, the code must return something to tell to the front what to do next. There are eight of them:

- `return $this->info('some text', reload: true)`: displays the entered text in a modal. The second argument, optional (default is `false`), is a boolean to also mark Sharp to reload the page.
- `return $this->info(string $message, bool $reload = false)`: displays the entered text in a modal. The second argument allows reloading the page first.
- `return $this->reload()`: reload the current page (with context).
- `return $this->refresh(1)`*: refresh only the instance with an id on `1`. We can pass an id array also to refresh more than one instance.
- `return $this->view('view.name', ['some'=>'params'])`: display a view right in Sharp; useful for page previews.
- `return $this->html('...')`: display an HTML content.
- `return $this->link('/path/to/redirect')`: redirect to the given path.
- `return $this->download('path', 'diskName')`: the browser will download the specified file.
- `return $this->streamDownload('path', 'name')`: the browser will stream the specified file.

\* `refresh()` is only useful in an Entity List case (in a Dashboard or a Show Page, it will be treated as a `reload()`). In order to make it work properly, you have to slightly adapt the `getListData()` of your Entity List implementation, making use of `$this->queryParams->specificIds()`:
- `return $this->refresh(mixed $ids)`*: refresh only instance(s) with an id in `$ids`, which can be either a single id or an array.
- `return $this->view(string $bladeView, array $params = [])`: display a view right in Sharp; useful for page previews.
- `return $this->html(string $htmlContent)`: display an HTML content.
- `return $this->link(string $link, bool $openInNewTab = false)`: redirect to the given path. The second argument, optional (default is `false`), is a boolean to open the link in a new tab.
- `return $this->download(string $filePath, ?string $fileName = null, ?string $diskName = null)`: the browser will download the specified file.
- `return $this->streamDownload(string $fileContent, string $fileName)`: the browser will stream the specified file.

\* `refresh()` is only useful in an Entity List case (in a Dashboard or a Show Page, it will be treated as a `reload()`). To make it work properly, you have to slightly adapt the `getListData()` of your Entity List implementation, making use of `$this->queryParams->specificIds()`:

```php
class OrderList extends SharpEntityList
Expand Down
16 changes: 9 additions & 7 deletions resources/js/commands/CommandManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,27 @@ export class CommandManager {

get defaultCommandResponseHandlers(): CommandResponseHandlers {
return {
info: async ({ message, reload }, { formModal }) => {
await showAlert(message, {
info: async (data, { formModal }) => {
await showAlert(data.message, {
title: __('sharp::modals.command.info.title'),
});
if(formModal.shouldReopen) {
formModal.reloadAndReopen();
} else if(reload) {
} else if(data.reload) {
await this.handleCommandResponse({ action: 'reload' });
}
},
link: ({ link }, { formModal }) => {
link: (data, { formModal }) => {
if(formModal.shouldReopen) {
formModal.reloadAndReopen();
return;
}
if(isSharpLink(link)) {
router.visit(link);
if(data.openInNewTab) {
window.open(data.link, '_blank');
} else if(isSharpLink(data.link)) {
router.visit(data.link);
} else {
location.href = link;
location.href = data.link;
}
},
reload: (data, { formModal }) => {
Expand Down
12 changes: 6 additions & 6 deletions resources/js/types/generated.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export type CommandFormData = {
pageAlert: PageAlertData | null;
};
export type CommandResponseData =
| { action: "link"; link: string }
| { action: "link"; link: string; openInNewTab: boolean }
| { action: "info"; message: string; reload: boolean }
| { action: "refresh"; items?: Array<{ [key: string]: any }> }
| { action: "reload" }
Expand Down Expand Up @@ -140,9 +140,6 @@ export type EmbedFormData = {
fields: { [key: string]: FormFieldData };
layout: FormLayoutData | null;
};
export type EmbeddedFieldAuthorizationsData = {
view: boolean;
};
export type EntityListAuthorizationsData = {
create: boolean;
reorder: boolean;
Expand Down Expand Up @@ -811,7 +808,7 @@ export type ShowDashboardFieldData = {
dashboardKey: string;
hiddenCommands: Array<string>;
endpointUrl: string;
authorizations: EmbeddedFieldAuthorizationsData;
authorizations: ShowFieldAuthorizationsData;
label: string | null;
hiddenFilters: { [key: string]: any } | null;
};
Expand All @@ -838,10 +835,13 @@ export type ShowEntityListFieldData = {
showSearchField: boolean;
showCount: boolean;
endpointUrl: string;
authorizations: EmbeddedFieldAuthorizationsData;
authorizations: ShowFieldAuthorizationsData;
label: string | null;
hiddenFilters: { [key: string]: any } | null;
};
export type ShowFieldAuthorizationsData = {
view: boolean;
};
export type ShowFieldData =
| ShowDashboardFieldData
| ShowEntityListFieldData
Expand Down
2 changes: 1 addition & 1 deletion src/Data/Commands/CommandResponseData.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

// download & streamDownload actions returns the file directly in the response
#[LiteralTypeScriptType(
'{ action: "'.CommandAction::Link->value.'", link: string } | '.
'{ action: "'.CommandAction::Link->value.'", link: string, openInNewTab: boolean } | '.
'{ action: "'.CommandAction::Info->value.'", message: string, reload: boolean } | '.
'{ action: "'.CommandAction::Refresh->value.'", items?: Array<{ [key: string]: any }> } | '.
'{ action: "'.CommandAction::Reload->value.'" } | '.
Expand Down
3 changes: 2 additions & 1 deletion src/EntityList/Commands/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@ protected function info(string $message, bool $reload = false): array
];
}

protected function link(string $link): array
protected function link(string $link, bool $openInNewTab = false): array
{
return [
'action' => CommandAction::Link->value,
'link' => $link,
'openInNewTab' => $openInNewTab,
];
}

Expand Down
2 changes: 1 addition & 1 deletion src/EntityList/Commands/EntityState.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected function streamDownload(string $fileContent, string $fileName): array
throw new SharpInvalidConfigException('StreamDownload return type is not supported for a state.');
}

protected function link(string $link): array
protected function link(string $link, bool $openInNewTab = false): array
{
throw new SharpInvalidConfigException('Link return type is not supported for a state.');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,68 @@ public function getListData(): array|\Illuminate\Contracts\Support\Arrayable
]);
});

it('allows to call an link entity command', function () {
fakeListFor('person', new class() extends PersonList
{
protected function getEntityCommands(): ?array
{
return [
'cmd' => new class() extends EntityCommand
{
public function label(): ?string
{
return 'entity';
}

public function execute(array $data = []): array
{
return $this->link('https://sharp.code16.fr');
}
},
];
}
});

$this->postJson(route('code16.sharp.api.list.command.entity', ['person', 'cmd']))
->assertOk()
->assertJson([
'action' => 'link',
'link' => 'https://sharp.code16.fr',
'openInNewTab' => false,
]);
});

it('allows to call an link + openInNewTab entity command', function () {
fakeListFor('person', new class() extends PersonList
{
protected function getEntityCommands(): ?array
{
return [
'cmd' => new class() extends EntityCommand
{
public function label(): ?string
{
return 'entity';
}

public function execute(array $data = []): array
{
return $this->link('https://sharp.code16.fr', openInNewTab: true);
}
},
];
}
});

$this->postJson(route('code16.sharp.api.list.command.entity', ['person', 'cmd']))
->assertOk()
->assertJson([
'action' => 'link',
'link' => 'https://sharp.code16.fr',
'openInNewTab' => true,
]);
});

it('allows to call a form entity command and it handles 422', function () {
fakeListFor('person', new class() extends PersonList
{
Expand Down
Loading