Last active
November 9, 2022 20:48
-
-
Save Neophen/88cfa24fcbc3b7695851d12abee74554 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Providers; | |
use App\Support\Utils\OctaModal; | |
use App\Support\Utils\OctaResponse; | |
use Illuminate\Support\Facades\Cache; | |
use Illuminate\Support\Facades\Session; | |
use Illuminate\Support\ServiceProvider; | |
use Inertia\Inertia; | |
class AppServiceProvider extends ServiceProvider | |
{ | |
public function boot() | |
{ | |
$this->registerInertia(); | |
} | |
public function registerInertia() | |
{ | |
Inertia::version(function () { | |
return md5_file(public_path('mix-manifest.json')); | |
}); | |
Inertia::share([ | |
OctaModal::key => fn () => Session::has(OctaModal::key) ? Cache::pull(Session::get(OctaModal::key)) : null, | |
OctaResponse::key => fn () => Session::has(OctaResponse::key) ? Cache::pull(Session::get(OctaResponse::key)) : null, | |
'flash' => fn () => [ | |
'success' => Session::get('success'), | |
'error' => Session::get('error'), | |
], | |
'errors' => fn () => Session::get('errors') | |
? Session::get('errors') | |
->getBag('default') | |
->getMessages() | |
: (object) [], | |
]); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div | |
class="fixed inset-0 z-10 bg-black bg-opacity-75" | |
:class="{ | |
block: hasModals, | |
hidden: !hasModals, | |
}" | |
> | |
<StackModalForm | |
v-for="(modal, i) in modals" | |
:key="modal.id" | |
:config="modal.config" | |
:show="modal.show" | |
:isActive="i == modals.length - 1" | |
@close="removeModal(modal.id)" | |
@success="removeModal(modal.id)" | |
/> | |
</div> | |
</template> | |
<script> | |
import { ref, watch } from "@vue/composition-api"; | |
import StackModalForm from "./Form/StackModalForm.vue"; | |
import { injectNotifications } from "../../../common/composables"; | |
export default { | |
name: "Modals", | |
components: { | |
StackModalForm, | |
}, | |
setup(props, { root }) { | |
const notifications = injectNotifications(); | |
const modals = ref([]); | |
const hasModals = ref(false); | |
const addModal = (modal = null) => { | |
if (!modal) return; | |
modals.value.push({ | |
id: modal.id, | |
show: true, | |
config: modal, | |
}); | |
hasModals.value = true; | |
}; | |
const removeModal = (id) => { | |
const hideModal = (modal) => | |
modal.id !== id ? modal : { ...modal, show: false }; | |
modals.value = modals.value.map(hideModal); | |
setTimeout(() => { | |
modals.value = modals.value.filter((x) => x.id !== id); | |
if (modals.value.length === 0) { | |
hasModals.value = false; | |
} | |
}, 250); | |
}; | |
watch(() => root.$page.octa_modal, addModal); | |
watch( | |
() => root.$page.octa_response_item, | |
(item) => { | |
if (!item) return; | |
notifications.emit(item.id, item.item); | |
}, | |
); | |
return { | |
modals, | |
removeModal, | |
addModal, | |
hasModals, | |
}; | |
}, | |
}; | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Support\Utils; | |
use App\Support\ModalActionEnum; | |
use Illuminate\Support\Facades\Cache; | |
use Illuminate\Support\Str; | |
class OctaModal | |
{ | |
public const key = "octa_modal"; | |
private $uuid; | |
private ModalActionEnum $type; | |
private $title; | |
private $confirm; | |
private $fieldset; | |
private $submit; | |
public static function create() | |
{ | |
return new OctaModal(ModalActionEnum::post(), "Create"); | |
} | |
public static function update() | |
{ | |
return new OctaModal(ModalActionEnum::put(), "Update"); | |
} | |
public function __construct(ModalActionEnum $type, string $confirm) | |
{ | |
do { | |
$uuid = Str::uuid()->__toString() . "-" . auth()->id(); | |
} while (Cache::has($uuid)); | |
$this->uuid = $uuid; | |
$this->type = $type; | |
$this->confirm = $confirm; | |
} | |
public function title(string $title): OctaModal | |
{ | |
$this->title = $title; | |
return $this; | |
} | |
public function confirm(string $confirm): OctaModal | |
{ | |
$this->confirm = $confirm; | |
return $this; | |
} | |
public function route(...$routeParams): OctaModal | |
{ | |
$this->submit = route(...$routeParams); | |
return $this; | |
} | |
public function fieldset($fieldset): OctaModal | |
{ | |
$this->fieldset = $fieldset; | |
return $this; | |
} | |
public function get() | |
{ | |
Cache::put($this->uuid, [ | |
"id" => $this->uuid, | |
"title" => $this->title, | |
"confirm" => $this->confirm, | |
"type" => $this->type, | |
"fieldset" => $this->fieldset, | |
"submit" => $this->submit, | |
]); | |
return redirect()->back()->with(self::key, $this->uuid); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Support\Utils; | |
use Illuminate\Support\Facades\Cache; | |
use Illuminate\Support\Facades\Session; | |
use Illuminate\Support\Str; | |
class OctaResponse | |
{ | |
public const key = "octa_response_item"; | |
private $uuid; | |
private $id; | |
private $item; | |
private $success; | |
public static function make(string $success) | |
{ | |
return new OctaResponse($success); | |
} | |
public function __construct(string $success) | |
{ | |
do { | |
$uuid = Str::uuid()->__toString() . "-" . auth()->id(); | |
} while (Cache::has($uuid)); | |
$this->uuid = $uuid; | |
$this->success = $success; | |
} | |
public function id(string $id): OctaResponse | |
{ | |
$this->id = $id; | |
return $this; | |
} | |
public function item($item): OctaResponse | |
{ | |
$this->item = $item; | |
return $this; | |
} | |
public function get() | |
{ | |
if ($this->id) { | |
Cache::put($this->uuid, [ | |
"id" => $this->id, | |
"item" => $this->item, | |
]); | |
Session::flash(self::key, $this->uuid); | |
} | |
return redirect()->back()->with('success', $this->success); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Admin\Controllers\Posts; | |
use App\Fieldsets\PostFieldset; | |
use App\Policies\PostsAreaPolicy; | |
use App\Support\Utils\OctaModal; | |
class PostCreateController | |
{ | |
public function __invoke() | |
{ | |
if (!gateAllows(PostsAreaPolicy::EDIT)) { | |
return redirect()->back()->with('error', PostsAreaPolicy::EDIT_ERROR); | |
}; | |
return OctaModal::create() | |
->title("Create Post") | |
->route('admin.posts.store') | |
->fieldset(PostFieldset::get()) | |
->get(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Admin\Controllers\Tags; | |
use App\Models\PostThread; | |
use App\Fieldsets\TagFieldset; | |
use App\Policies\TagsAreaPolicy; | |
use App\Support\Utils\OctaModal; | |
use App\Support\Utils\OctaResponse; | |
use Illuminate\Http\Request; | |
class PostThreadsController | |
{ | |
public function create(Request $request) | |
{ | |
if (!gateAllows(TagsAreaPolicy::EDIT)) { | |
return redirect()->back()->with('error', TagsAreaPolicy::EDIT_ERROR); | |
} | |
return OctaModal::create() | |
->title("Add thread") | |
->confirm("Add") | |
// we add this to the visit request | |
->route('admin.post-threads.store', $request->get('octa_item_id')) | |
->fieldset(TagFieldset::get('post_threads')) | |
->get(); | |
} | |
public function store(Request $request, string $id = null) | |
{ | |
if (!gateAllows(TagsAreaPolicy::EDIT)) { | |
return redirect()->back()->with('error', TagsAreaPolicy::EDIT_ERROR); | |
} | |
$validated = $request->validate([ | |
// some rules | |
]); | |
$tag = PostThread::create($validated); | |
return OctaResponse::make('Post thread added') | |
->id($id) | |
->item([ | |
'value' => $tag->id, | |
'label' => $tag->title, | |
]) | |
->get(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Illuminate\Support\Facades\Route; | |
use App\Http\Admin\Controllers\Posts\PostCreateController; | |
use App\Http\Admin\Controllers\Tags\PostThreadsController; | |
Route::get('posts/create', PostCreateController::class)->name('posts.create'); | |
Route::get('post-threads/create', [PostThreadsController::class, 'create'])->name('post-threads.create'); | |
// For the nested modals we add identification you can name it whatever | |
Route::post('post-threads/create/{id?}', [PostThreadsController::class, 'store'])->name('post-threads.store'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="absolute w-full h-screen overflow-y-auto"> | |
<transition | |
enter-active-class="transition duration-200 ease-out" | |
leave-active-class="transition duration-200 ease-in" | |
enter-class="transform translate-x-24 opacity-0" | |
enter-to-class="transform translate-x-0 opacity-100" | |
leave-class="transform translate-x-0 opacity-100" | |
leave-to-class="transform translate-x-24 opacity-0" | |
appear | |
> | |
<div | |
v-if="show" | |
class="relative flex flex-col items-center min-h-screen overflow-y-auto" | |
:class="{ | |
'transform duration-200 -translate-x-24': !isActive, | |
'transform duration-200 translate-x-0': isActive, | |
}" | |
> | |
<div class="flex-shrink-0 w-8 h-24"></div> | |
<div class="relative flex items-center flex-1"> | |
<OModalContent :size="size"> | |
<div class="flex items-start justify-between mb-10"> | |
<slot> | |
<OH class="truncate">{{ title }}</OH> | |
</slot> | |
<OButton | |
icon="close" | |
size="is-lg" | |
class="flex-shrink-0 ml-4" | |
@click="close" | |
/> | |
</div> | |
<OctoForm | |
:fieldset="octaForm.fieldset" | |
:config="octaForm.formConfig" | |
:errors="errors" | |
:loading="isLoading" | |
@cancel="close" | |
@submit="onSubmit" | |
/> | |
</OModalContent> | |
<transition | |
enter-active-class="transition-opacity duration-200 ease-out" | |
leave-active-class="transition-opacity duration-200 ease-in" | |
enter-class="opacity-0" | |
enter-to-class="opacity-100" | |
leave-class="opacity-100" | |
leave-to-class="opacity-0" | |
appear | |
> | |
<div | |
v-if="!isActive" | |
class="absolute inset-0 z-10 w-full h-full bg-black bg-opacity-50 rounded-large" | |
></div> | |
</transition> | |
</div> | |
<div class="flex-shrink-0 w-8 h-24"></div> | |
</div> | |
</transition> | |
</div> | |
</template> | |
<script> | |
import { computed, reactive, toRefs } from "@vue/composition-api"; | |
import isEmpty from "lodash/isEmpty"; | |
export default { | |
name: "StackModalForm", | |
props: { | |
show: Boolean, | |
isActive: Boolean, | |
config: Object, | |
}, | |
setup(props, { root, emit }) { | |
// NOTE WE PROVIDE THE FILE MANAGER IN THE LAYOUT FILE SINCE OF VUE-PORTAL BUG | |
const state = reactive({ | |
errors: [], | |
isLoading: false, | |
size: computed(() => props.config.size || "large"), | |
title: computed(() => props.config.title), | |
octaForm: computed(() => ({ | |
url: props.config.submit, | |
type: props.config.type, | |
formConfig: { | |
confirm: props.config.confirm, | |
}, | |
fieldset: props.config.fieldset, | |
})), | |
}); | |
const onSubmit = async (formData) => { | |
state.isLoading = true; | |
try { | |
formData.append("_method", props.config.type); | |
await root.$inertia.post(props.config.submit, formData); | |
state.isLoading = false; | |
if (!isEmpty(root.$page.errors)) { | |
state.errors = root.$page.errors; | |
} else { | |
emit("success"); | |
} | |
} catch (error) { | |
console.error(error); | |
state.isLoading = false; | |
} | |
}; | |
const close = () => { | |
emit("close"); | |
}; | |
return { | |
...toRefs(state), | |
onSubmit, | |
close, | |
}; | |
}, | |
}; | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi
This is very impressive but where is App\Support\ModalActionEnum file?