Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Async callback refactoring #1313

Merged
merged 10 commits into from
Oct 27, 2024
3 changes: 2 additions & 1 deletion src/Laravel/src/Components/Fragment.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ protected function prepareBeforeRender(): void

$this->xDataMethod('fragment', $this->getAsyncUrl());
$this->customAttributes([
AlpineJs::eventBlade(JsEvent::FRAGMENT_UPDATED, $this->getName()) => 'fragmentUpdate',
AlpineJs::eventBlade(JsEvent::FRAGMENT_UPDATED, $this->getName())
=> 'fragmentUpdate(`' . $this->getAsyncEvents() . '`,' .json_encode($this->getAsyncCallback()). ')',
]);
}
}
4 changes: 2 additions & 2 deletions src/Support/src/AlpineJs.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ public static function asyncUrlDataAttributes(
return array_filter([
'data-async-events' => self::prepareEvents($events),
'data-async-selector' => $selector,
'data-async-callback' => $callback?->getSuccess() ,
'data-async-before-function' => $callback?->getBefore(),
'data-async-callback' => $callback?->customResponse(),
lee-to marked this conversation as resolved.
Show resolved Hide resolved
'data-async-before-function' => $callback?->beforeRequest(),
'data-async-method' => $method->value,
]);
}
Expand Down
49 changes: 38 additions & 11 deletions src/Support/src/DTOs/AsyncCallback.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,62 @@
namespace MoonShine\Support\DTOs;

use Illuminate\Contracts\Support\Arrayable;
use JsonSerializable;

final readonly class AsyncCallback implements Arrayable
final readonly class AsyncCallback implements Arrayable, JsonSerializable
{
public function __construct(
private ?string $success,
private ?string $before,
/**
* Called before a request
*/
private ?string $beforeRequest,

/**
* Replaces the default response handler
*/
private ?string $customResponse,

/**
* Called after standard response processing if $customResponse is not specified
*/
private ?string $afterResponse,
) {
}

public static function with(?string $success = null, ?string $before = null): self
public static function with(
?string $beforeRequest = null,
?string $customResponse = null,
?string $afterResponse = null
): self {
return new self($beforeRequest, $customResponse, $afterResponse);
}

public function beforeRequest(): ?string
{
return new self($success, $before);
return $this->beforeRequest;
}

public function getBefore(): ?string
public function customResponse(): ?string
{
return $this->before;
return $this->customResponse;
}

public function getSuccess(): ?string
public function afterResponse(): ?string
{
return $this->success;
return $this->afterResponse;
}

public function toArray(): array
{
return [
'before' => $this->getBefore(),
'success' => $this->getSuccess(),
'beforeRequest' => $this->beforeRequest(),
'customResponse' => $this->customResponse(),
'afterResponse' => $this->afterResponse(),
];
}

public function jsonSerialize(): array
{
return $this->toArray();
}
}
18 changes: 12 additions & 6 deletions src/UI/resources/js/Components/FormBuilder.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ComponentRequestData} from '../DTOs/ComponentRequestData.js'
import {addInvalidListener, containsAttribute, isTextInput} from '../Support/Forms.js'
import request from '../Request/Core.js'
import request, {afterResponse, initCallback} from '../Request/Core.js'
import {dispatchEvents as de} from '../Support/DispatchEvents.js'
import {getInputs, showWhenChange, showWhenVisibilityChange} from '../Support/ShowWhen.js'
import {formToJSON} from 'axios'
Expand All @@ -24,7 +24,7 @@ export default (name = '', initData = {}, reactive = {}) => ({
if (!t.blockWatch) {
let focused = document.activeElement

componentRequestData.withAfterCallback(function (data) {
componentRequestData.withAfterResponse(function (data) {
for (let [column, html] of Object.entries(data.fields)) {
let selectorWrapper = '.field-' + column + '-wrapper'
let selectorElement = '.field-' + column + '-element'
Expand Down Expand Up @@ -171,7 +171,7 @@ export default (name = '', initData = {}, reactive = {}) => ({
this.$el.submit()
}
},
async(events = '', callbackFunction = '', beforeFunction = '') {
async(events = '', callback = {}) {
const form = this.$el
submitState(form, true)
const t = this
Expand All @@ -189,16 +189,22 @@ export default (name = '', initData = {}, reactive = {}) => ({

let componentRequestData = new ComponentRequestData()

callback = initCallback(callback)

componentRequestData
.withBeforeFunction(beforeFunction)
.withResponseFunction(callbackFunction)
.withBeforeRequest(callback.beforeRequest)
.withCustomResponse(callback.customResponse)
.withEvents(events)
.withAfterCallback(function (data, type) {
.withAfterResponse(function (data, type) {
if (type !== 'error' && t.inModal && t.autoClose) {
t.toggleModal()
}

submitState(form, false, false)

if(callback.afterResponse) {
afterResponse(callback.afterResponse, data, type)
}
})
.withAfterErrorCallback(function () {
submitState(form, false)
Expand Down
19 changes: 14 additions & 5 deletions src/UI/resources/js/Components/Fragment.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import selectorsParams from '../Support/SelectorsParams.js'
import {ComponentRequestData} from '../DTOs/ComponentRequestData.js'
import request from '../Request/Core.js'
import request, {afterResponse, beforeRequest, initCallback} from '../Request/Core.js'
import {getQueryString} from '../Support/Forms.js'

export default (asyncUpdateRoute = '') => ({
Expand All @@ -12,7 +12,7 @@ export default (asyncUpdateRoute = '') => ({
this.loading = false
this.withParams = this.$el?.dataset?.asyncWithParams
},
fragmentUpdate() {
async fragmentUpdate(events, callback = {}) {
if (this.asyncUpdateRoute === '') {
return
}
Expand All @@ -21,6 +21,8 @@ export default (asyncUpdateRoute = '') => ({
return
}

callback = initCallback(callback)

this.loading = true

let body = selectorsParams(this.withParams)
Expand All @@ -38,12 +40,19 @@ export default (asyncUpdateRoute = '') => ({

let componentRequestData = new ComponentRequestData()
componentRequestData
.withAfterCallback(function (data) {
.withEvents(events)
.withBeforeRequest(callback.beforeRequest)
.withBeforeResponse(stopLoading)
.withCustomResponse(callback.customResponse)
.withAfterResponse(function (data) {
t.$root.outerHTML = data

if(callback.afterResponse) {
afterResponse(callback.afterResponse, data)
}
})
.withBeforeCallback(stopLoading)
.withErrorCallback(stopLoading)

request(this, this.asyncUpdateRoute, 'get', body, {}, componentRequestData)
request(t, t.asyncUpdateRoute, 'get', body, {}, componentRequestData)
},
})
69 changes: 35 additions & 34 deletions src/UI/resources/js/DTOs/ComponentRequestData.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ export class ComponentRequestData {
this._events = ''
this._selector = ''

this._beforeFunction = null
this._responseFunction = null
this._beforeRequest = null
this._customResponse = null

this._beforeCallback = null
this._afterCallback = null
this._beforeResponse = null
this._afterResponse = null

// TODO Error request refactoring
this._errorCallback = null
this._afterErrorCallback = null

Expand All @@ -35,58 +36,58 @@ export class ComponentRequestData {
return this
}

get beforeFunction() {
return this._beforeFunction
get beforeRequest() {
return this._beforeRequest
}

hasBeforeFunction() {
return this._beforeFunction !== null && this._beforeFunction
hasBeforeRequest() {
return this._beforeRequest !== null && this._beforeRequest
}

withBeforeFunction(value) {
this._beforeFunction = value
withBeforeRequest(value) {
this._beforeRequest = value

return this
}

get beforeCallback() {
return this._beforeCallback
get beforeResponse() {
return this._beforeResponse
}

hasBeforeCallback() {
return this._beforeCallback !== null && typeof this._beforeCallback === 'function'
hasBeforeResponse() {
return this._beforeResponse !== null && typeof this._beforeResponse === 'function'
}

withBeforeCallback(value) {
this._beforeCallback = value
withBeforeResponse(value) {
this._beforeResponse = value

return this
}

get responseFunction() {
return this._responseFunction
get customResponse() {
return this._customResponse
}

hasResponseFunction() {
return this._responseFunction !== null && this._responseFunction
hasCustomResponse() {
return this._customResponse !== null && this._customResponse
}

withResponseFunction(value) {
this._responseFunction = value
withCustomResponse(value) {
this._customResponse = value

return this
}

get afterCallback() {
return this._afterCallback
get afterResponse() {
return this._afterResponse
}

hasAfterCallback() {
return this._afterCallback !== null && typeof this._afterCallback === 'function'
hasAfterResponse() {
return this._afterResponse !== null && typeof this._afterResponse === 'function'
}

withAfterCallback(value) {
this._afterCallback = value
withAfterResponse(value) {
this._afterResponse = value

return this
}
Expand Down Expand Up @@ -132,17 +133,17 @@ export class ComponentRequestData {
fromDataset(dataset = {}) {
return this.withEvents(dataset.asyncEvents ?? '')
.withSelector(dataset.asyncSelector ?? '')
.withResponseFunction(dataset.asyncCallback ?? null)
.withBeforeFunction(dataset.asyncBeforeFunction ?? null)
.withCustomResponse(dataset.asyncCallback ?? null)
.withBeforeRequest(dataset.asyncBeforeFunction ?? null)
}

fromObject(object = {}) {
return this.withEvents(object.events ?? '')
.withSelector(object.selector ?? '')
.withResponseFunction(object.responseFunction ?? null)
.withBeforeFunction(object.beforeFunction ?? null)
.withBeforeCallback(object.beforeCallback ?? null)
.withAfterCallback(object.afterCallback ?? null)
.withCustomResponse(object.customResponse ?? null)
.withBeforeRequest(object.beforeFunction ?? null)
.withBeforeResponse(object.beforeResponse ?? null)
.withAfterResponse(object.afterResponse ?? null)
.withErrorCallback(object.errorCallback ?? null)
.withAfterErrorCallback(object.afterErrorCallback ?? null)
.withExtraAttributes(object.extraAttributes ?? null)
Expand Down
Loading