Add (new post)
This commit is contained in:
622
resources/css/toastify.css
Normal file
622
resources/css/toastify.css
Normal file
@@ -0,0 +1,622 @@
|
||||
:root {
|
||||
--toastify-color-light: #fff;
|
||||
--toastify-color-dark: #121212;
|
||||
--toastify-color-info: #3498db;
|
||||
--toastify-color-success: #07bc0c;
|
||||
--toastify-color-warning: #f1c40f;
|
||||
--toastify-color-error: #e74c3c;
|
||||
--toastify-color-transparent: #ffffffb3;
|
||||
--toastify-icon-color-info: var(--toastify-color-info);
|
||||
--toastify-icon-color-success: var(--toastify-color-success);
|
||||
--toastify-icon-color-warning: var(--toastify-color-warning);
|
||||
--toastify-icon-color-error: var(--toastify-color-error);
|
||||
--toastify-toast-width: 320px;
|
||||
--toastify-toast-background: #fff;
|
||||
--toastify-toast-min-height: 64px;
|
||||
--toastify-toast-max-height: 800px;
|
||||
--toastify-font-family: inherit;
|
||||
--toastify-z-index: 9999;
|
||||
--toastify-text-color-light: #757575;
|
||||
--toastify-text-color-dark: #fff;
|
||||
--toastify-text-color-info: #fff;
|
||||
--toastify-text-color-success: #fff;
|
||||
--toastify-text-color-warning: #fff;
|
||||
--toastify-text-color-error: #fff;
|
||||
--toastify-spinner-color: #616161;
|
||||
--toastify-spinner-color-empty-area: #e0e0e0;
|
||||
--toastify-color-progress-light: linear-gradient(
|
||||
90deg,
|
||||
#4cd964,
|
||||
#5ac8fa,
|
||||
#007aff,
|
||||
#34aadc,
|
||||
#5856d6,
|
||||
#ff2d55
|
||||
);
|
||||
--toastify-color-progress-dark: #bb86fc;
|
||||
--toastify-color-progress-info: var(--toastify-color-info);
|
||||
--toastify-color-progress-success: var(--toastify-color-success);
|
||||
--toastify-color-progress-warning: var(--toastify-color-warning);
|
||||
--toastify-color-progress-error: var(--toastify-color-error);
|
||||
--toastify-color-progress-colored: #ddd;
|
||||
}
|
||||
.Toastify__toast-container {
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
padding: 4px;
|
||||
position: fixed;
|
||||
transform: translate3d(0, 0, var(--toastify-z-index) px);
|
||||
width: var(--toastify-toast-width);
|
||||
z-index: var(--toastify-z-index);
|
||||
}
|
||||
.Toastify__toast-container--top-left {
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
}
|
||||
.Toastify__toast-container--top-center {
|
||||
left: 50%;
|
||||
top: 1em;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.Toastify__toast-container--top-right {
|
||||
right: 1em;
|
||||
top: 1em;
|
||||
}
|
||||
.Toastify__toast-container--bottom-left {
|
||||
bottom: 1em;
|
||||
left: 1em;
|
||||
}
|
||||
.Toastify__toast-container--bottom-center {
|
||||
bottom: 1em;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.Toastify__toast-container--bottom-right {
|
||||
bottom: 1em;
|
||||
right: 1em;
|
||||
}
|
||||
@media only screen and (max-width: 480px) {
|
||||
.Toastify__toast-container {
|
||||
left: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100vw;
|
||||
}
|
||||
.Toastify__toast-container--top-center,
|
||||
.Toastify__toast-container--top-left,
|
||||
.Toastify__toast-container--top-right {
|
||||
top: 0;
|
||||
transform: translateX(0);
|
||||
}
|
||||
.Toastify__toast-container--bottom-center,
|
||||
.Toastify__toast-container--bottom-left,
|
||||
.Toastify__toast-container--bottom-right {
|
||||
bottom: 0;
|
||||
transform: translateX(0);
|
||||
}
|
||||
.Toastify__toast-container--rtl {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
.Toastify__toast {
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 10px 0 #0000001a, 0 2px 15px 0 #0000000d;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
direction: ltr;
|
||||
display: flex;
|
||||
font-family: var(--toastify-font-family);
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1rem;
|
||||
max-height: var(--toastify-toast-max-height);
|
||||
min-height: var(--toastify-toast-min-height);
|
||||
overflow: hidden;
|
||||
padding: 8px;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
.Toastify__toast--rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
.Toastify__toast-body {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
margin: auto 0;
|
||||
padding: 6px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.Toastify__toast-body > div:last-child {
|
||||
flex: 1;
|
||||
}
|
||||
.Toastify__toast-icon {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
margin-inline-end: 10px;
|
||||
width: 20px;
|
||||
}
|
||||
.Toastify--animate {
|
||||
animation-duration: 0.7s;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
.Toastify--animate-icon {
|
||||
animation-duration: 0.3s;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
@media only screen and (max-width: 480px) {
|
||||
.Toastify__toast {
|
||||
border-radius: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
.Toastify__toast-theme--dark {
|
||||
background: var(--toastify-color-dark);
|
||||
color: var(--toastify-text-color-dark);
|
||||
}
|
||||
.Toastify__toast-theme--colored.Toastify__toast--default,
|
||||
.Toastify__toast-theme--light {
|
||||
background: var(--toastify-color-light);
|
||||
color: var(--toastify-text-color-light);
|
||||
}
|
||||
.Toastify__toast-theme--colored.Toastify__toast--info {
|
||||
background: var(--toastify-color-info);
|
||||
color: var(--toastify-text-color-info);
|
||||
}
|
||||
.Toastify__toast-theme--colored.Toastify__toast--success {
|
||||
background: var(--toastify-color-success);
|
||||
color: var(--toastify-text-color-success);
|
||||
}
|
||||
.Toastify__toast-theme--colored.Toastify__toast--warning {
|
||||
background: var(--toastify-color-warning);
|
||||
color: var(--toastify-text-color-warning);
|
||||
}
|
||||
.Toastify__toast-theme--colored.Toastify__toast--error {
|
||||
background: var(--toastify-color-error);
|
||||
color: var(--toastify-text-color-error);
|
||||
}
|
||||
.Toastify__progress-bar-theme--light {
|
||||
background: var(--toastify-color-progress-light);
|
||||
}
|
||||
.Toastify__progress-bar-theme--dark {
|
||||
background: var(--toastify-color-progress-dark);
|
||||
}
|
||||
.Toastify__progress-bar--info {
|
||||
background: var(--toastify-color-progress-info);
|
||||
}
|
||||
.Toastify__progress-bar--success {
|
||||
background: var(--toastify-color-progress-success);
|
||||
}
|
||||
.Toastify__progress-bar--warning {
|
||||
background: var(--toastify-color-progress-warning);
|
||||
}
|
||||
.Toastify__progress-bar--error {
|
||||
background: var(--toastify-color-progress-error);
|
||||
}
|
||||
.Toastify__progress-bar-theme--colored.Toastify__progress-bar--default {
|
||||
background: var(--toastify-color-progress-colored);
|
||||
}
|
||||
.Toastify__progress-bar-theme--colored.Toastify__progress-bar--error,
|
||||
.Toastify__progress-bar-theme--colored.Toastify__progress-bar--info,
|
||||
.Toastify__progress-bar-theme--colored.Toastify__progress-bar--success,
|
||||
.Toastify__progress-bar-theme--colored.Toastify__progress-bar--warning {
|
||||
background: var(--toastify-color-transparent);
|
||||
}
|
||||
.Toastify__close-button {
|
||||
align-self: flex-start;
|
||||
background: #0000;
|
||||
border: none;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
opacity: 0.7;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
transition: 0.3s ease;
|
||||
}
|
||||
.Toastify__close-button--light {
|
||||
color: #000;
|
||||
opacity: 0.3;
|
||||
}
|
||||
.Toastify__close-button > svg {
|
||||
fill: currentcolor;
|
||||
height: 16px;
|
||||
width: 14px;
|
||||
}
|
||||
.Toastify__close-button:focus,
|
||||
.Toastify__close-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
@keyframes Toastify__trackProgress {
|
||||
0% {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
to {
|
||||
transform: scaleX(0);
|
||||
}
|
||||
}
|
||||
.Toastify__progress-bar {
|
||||
bottom: 0;
|
||||
height: 5px;
|
||||
left: 0;
|
||||
opacity: 0.7;
|
||||
position: absolute;
|
||||
transform-origin: left;
|
||||
width: 100%;
|
||||
z-index: var(--toastify-z-index);
|
||||
}
|
||||
.Toastify__progress-bar--animated {
|
||||
animation: Toastify__trackProgress linear 1 forwards;
|
||||
}
|
||||
.Toastify__progress-bar--controlled {
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.Toastify__progress-bar--rtl {
|
||||
left: auto;
|
||||
right: 0;
|
||||
transform-origin: right;
|
||||
}
|
||||
.Toastify__spinner {
|
||||
animation: Toastify__spin 0.65s linear infinite;
|
||||
border: 2px solid;
|
||||
border-color: var(--toastify-spinner-color-empty-area);
|
||||
border-radius: 100%;
|
||||
border-right-color: var(--toastify-spinner-color);
|
||||
box-sizing: border-box;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
@keyframes Toastify__bounceInRight {
|
||||
0%,
|
||||
60%,
|
||||
75%,
|
||||
90%,
|
||||
to {
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate3d(3000px, 0, 0);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: translate3d(-25px, 0, 0);
|
||||
}
|
||||
75% {
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
90% {
|
||||
transform: translate3d(-5px, 0, 0);
|
||||
}
|
||||
to {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__bounceOutRight {
|
||||
20% {
|
||||
opacity: 1;
|
||||
transform: translate3d(-20px, 0, 0);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate3d(2000px, 0, 0);
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__bounceInLeft {
|
||||
0%,
|
||||
60%,
|
||||
75%,
|
||||
90%,
|
||||
to {
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate3d(-3000px, 0, 0);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: translate3d(25px, 0, 0);
|
||||
}
|
||||
75% {
|
||||
transform: translate3d(-10px, 0, 0);
|
||||
}
|
||||
90% {
|
||||
transform: translate3d(5px, 0, 0);
|
||||
}
|
||||
to {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__bounceOutLeft {
|
||||
20% {
|
||||
opacity: 1;
|
||||
transform: translate3d(20px, 0, 0);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate3d(-2000px, 0, 0);
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__bounceInUp {
|
||||
0%,
|
||||
60%,
|
||||
75%,
|
||||
90%,
|
||||
to {
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, 3000px, 0);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, -20px, 0);
|
||||
}
|
||||
75% {
|
||||
transform: translate3d(0, 10px, 0);
|
||||
}
|
||||
90% {
|
||||
transform: translate3d(0, -5px, 0);
|
||||
}
|
||||
to {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__bounceOutUp {
|
||||
20% {
|
||||
transform: translate3d(0, -10px, 0);
|
||||
}
|
||||
40%,
|
||||
45% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 20px, 0);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, -2000px, 0);
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__bounceInDown {
|
||||
0%,
|
||||
60%,
|
||||
75%,
|
||||
90%,
|
||||
to {
|
||||
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, -3000px, 0);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 25px, 0);
|
||||
}
|
||||
75% {
|
||||
transform: translate3d(0, -10px, 0);
|
||||
}
|
||||
90% {
|
||||
transform: translate3d(0, 5px, 0);
|
||||
}
|
||||
to {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__bounceOutDown {
|
||||
20% {
|
||||
transform: translate3d(0, 10px, 0);
|
||||
}
|
||||
40%,
|
||||
45% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, -20px, 0);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, 2000px, 0);
|
||||
}
|
||||
}
|
||||
.Toastify__bounce-enter--bottom-left,
|
||||
.Toastify__bounce-enter--top-left {
|
||||
animation-name: Toastify__bounceInLeft;
|
||||
}
|
||||
.Toastify__bounce-enter--bottom-right,
|
||||
.Toastify__bounce-enter--top-right {
|
||||
animation-name: Toastify__bounceInRight;
|
||||
}
|
||||
.Toastify__bounce-enter--top-center {
|
||||
animation-name: Toastify__bounceInDown;
|
||||
}
|
||||
.Toastify__bounce-enter--bottom-center {
|
||||
animation-name: Toastify__bounceInUp;
|
||||
}
|
||||
.Toastify__bounce-exit--bottom-left,
|
||||
.Toastify__bounce-exit--top-left {
|
||||
animation-name: Toastify__bounceOutLeft;
|
||||
}
|
||||
.Toastify__bounce-exit--bottom-right,
|
||||
.Toastify__bounce-exit--top-right {
|
||||
animation-name: Toastify__bounceOutRight;
|
||||
}
|
||||
.Toastify__bounce-exit--top-center {
|
||||
animation-name: Toastify__bounceOutUp;
|
||||
}
|
||||
.Toastify__bounce-exit--bottom-center {
|
||||
animation-name: Toastify__bounceOutDown;
|
||||
}
|
||||
@keyframes Toastify__zoomIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__zoomOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0;
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.Toastify__zoom-enter {
|
||||
animation-name: Toastify__zoomIn;
|
||||
}
|
||||
.Toastify__zoom-exit {
|
||||
animation-name: Toastify__zoomOut;
|
||||
}
|
||||
@keyframes Toastify__flipIn {
|
||||
0% {
|
||||
animation-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
transform: perspective(400px) rotateX(90deg);
|
||||
}
|
||||
40% {
|
||||
animation-timing-function: ease-in;
|
||||
transform: perspective(400px) rotateX(-20deg);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
transform: perspective(400px) rotateX(10deg);
|
||||
}
|
||||
80% {
|
||||
transform: perspective(400px) rotateX(-5deg);
|
||||
}
|
||||
to {
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__flipOut {
|
||||
0% {
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
opacity: 1;
|
||||
transform: perspective(400px) rotateX(-20deg);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: perspective(400px) rotateX(90deg);
|
||||
}
|
||||
}
|
||||
.Toastify__flip-enter {
|
||||
animation-name: Toastify__flipIn;
|
||||
}
|
||||
.Toastify__flip-exit {
|
||||
animation-name: Toastify__flipOut;
|
||||
}
|
||||
@keyframes Toastify__slideInRight {
|
||||
0% {
|
||||
transform: translate3d(110%, 0, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
to {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__slideInLeft {
|
||||
0% {
|
||||
transform: translate3d(-110%, 0, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
to {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__slideInUp {
|
||||
0% {
|
||||
transform: translate3d(0, 110%, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
to {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__slideInDown {
|
||||
0% {
|
||||
transform: translate3d(0, -110%, 0);
|
||||
visibility: visible;
|
||||
}
|
||||
to {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__slideOutRight {
|
||||
0% {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
to {
|
||||
transform: translate3d(110%, 0, 0);
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__slideOutLeft {
|
||||
0% {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
to {
|
||||
transform: translate3d(-110%, 0, 0);
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__slideOutDown {
|
||||
0% {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
to {
|
||||
transform: translate3d(0, 500px, 0);
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
@keyframes Toastify__slideOutUp {
|
||||
0% {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
to {
|
||||
transform: translate3d(0, -500px, 0);
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
.Toastify__slide-enter--bottom-left,
|
||||
.Toastify__slide-enter--top-left {
|
||||
animation-name: Toastify__slideInLeft;
|
||||
}
|
||||
.Toastify__slide-enter--bottom-right,
|
||||
.Toastify__slide-enter--top-right {
|
||||
animation-name: Toastify__slideInRight;
|
||||
}
|
||||
.Toastify__slide-enter--top-center {
|
||||
animation-name: Toastify__slideInDown;
|
||||
}
|
||||
.Toastify__slide-enter--bottom-center {
|
||||
animation-name: Toastify__slideInUp;
|
||||
}
|
||||
.Toastify__slide-exit--bottom-left,
|
||||
.Toastify__slide-exit--top-left {
|
||||
animation-name: Toastify__slideOutLeft;
|
||||
}
|
||||
.Toastify__slide-exit--bottom-right,
|
||||
.Toastify__slide-exit--top-right {
|
||||
animation-name: Toastify__slideOutRight;
|
||||
}
|
||||
.Toastify__slide-exit--top-center {
|
||||
animation-name: Toastify__slideOutUp;
|
||||
}
|
||||
.Toastify__slide-exit--bottom-center {
|
||||
animation-name: Toastify__slideOutDown;
|
||||
}
|
||||
@keyframes Toastify__spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,57 @@
|
||||
import "@tabler/core/src/js/tabler.js";
|
||||
|
||||
import '@tabler/core/src/js/tabler.js';
|
||||
import "./bootstrap";
|
||||
|
||||
import './bootstrap';
|
||||
import { createApp, defineAsyncComponent } from "vue";
|
||||
|
||||
import AdminApp from "@/vue/AdminApp.vue";
|
||||
|
||||
const app = createApp({ AdminApp });
|
||||
const vueComponents = import.meta.glob("@/vue/**/*.vue", {
|
||||
eager: false,
|
||||
});
|
||||
|
||||
console.log(vueComponents);
|
||||
|
||||
import.meta.glob(["../images/**", "../fonts/**"]);
|
||||
|
||||
import { createPinia } from "pinia";
|
||||
app.use(createPinia());
|
||||
|
||||
import axios from "./plugins/axios";
|
||||
import VueAxios from "vue-axios";
|
||||
app.use(VueAxios, axios);
|
||||
|
||||
import auth from "./plugins/auth";
|
||||
app.use(auth);
|
||||
|
||||
import eventBus from "./plugins/event-bus";
|
||||
app.use(eventBus);
|
||||
|
||||
import Vue3Toastify from "vue3-toastify";
|
||||
import "../css/toastify.css";
|
||||
app.use(Vue3Toastify);
|
||||
|
||||
import { Ziggy as ZiggyRoute } from "./ziggy";
|
||||
import { ZiggyVue } from "ziggy-js/dist/vue";
|
||||
app.use(ZiggyVue, ZiggyRoute);
|
||||
|
||||
window.Ziggy = ZiggyRoute;
|
||||
|
||||
Object.entries({ ...vueComponents }).forEach(([path, definition]) => {
|
||||
// Get name of component, based on filename
|
||||
// "./components/Fruits.vue" will become "Fruits"
|
||||
const componentName = path
|
||||
.split("/")
|
||||
.pop()
|
||||
.replace(/\.\w+$/, "")
|
||||
.replace(/([a-z])([A-Z])/g, "$1-$2")
|
||||
.toLowerCase();
|
||||
// console.log(componentName);
|
||||
// console.log(typeof definition);
|
||||
|
||||
// Register component on this Vue instance
|
||||
app.component(componentName, defineAsyncComponent(definition));
|
||||
});
|
||||
|
||||
app.mount("#app");
|
||||
|
||||
11
resources/js/plugins/auth.js
Normal file
11
resources/js/plugins/auth.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { useAuthStore } from "@/stores/useAuth";
|
||||
|
||||
export default {
|
||||
install: ({ config }) => {
|
||||
config.globalProperties.$auth = useAuthStore();
|
||||
|
||||
if (useAuthStore().loggedIn) {
|
||||
useAuthStore().ftechUser();
|
||||
}
|
||||
},
|
||||
};
|
||||
71
resources/js/plugins/axios.js
Normal file
71
resources/js/plugins/axios.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import { useErrorStore } from "../stores/useError";
|
||||
import axios from "axios";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
axios.defaults.headers.common["Authorization"] = localStorage.getItem("token");
|
||||
axios.defaults.withCredentials = true;
|
||||
axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
|
||||
|
||||
const setCSRFToken = () => {
|
||||
return axios.get("/sanctum/csrf-cookie"); // resolves to '/api/csrf-cookie'.
|
||||
};
|
||||
|
||||
// Add a request interceptor
|
||||
axios.interceptors.request.use(
|
||||
function (config) {
|
||||
// Do something before request is sent
|
||||
|
||||
useErrorStore().$reset();
|
||||
|
||||
if (!Cookies.get("XSRF-TOKEN")) {
|
||||
return setCSRFToken().then((response) => config);
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
function (error) {
|
||||
// Do something with request error
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// Add a response interceptor
|
||||
axios.interceptors.response.use(
|
||||
function (response) {
|
||||
// console.warn("axios.interceptors.response");
|
||||
// console.warn(response);
|
||||
|
||||
if (response?.data?.data?.csrf_token?.length > 0) {
|
||||
Cookies.set("XSRF-TOKEN", response.data.data.csrf_token);
|
||||
} else if (response?.data?.data?.token?.length > 0) {
|
||||
Cookies.set("XSRF-TOKEN", response.data.data.csrf_token);
|
||||
}
|
||||
|
||||
// Any status code that lie within the range of 2xx cause this function to trigger
|
||||
// Do something with response data
|
||||
return response;
|
||||
},
|
||||
function (error) {
|
||||
// Any status codes that falls outside the range of 2xx cause this function to trigger
|
||||
// Do something with response error
|
||||
switch (error.response.status) {
|
||||
case 401:
|
||||
localStorage.removeItem("token");
|
||||
window.location.reload();
|
||||
break;
|
||||
case 403:
|
||||
case 404:
|
||||
console.error("404");
|
||||
break;
|
||||
case 422:
|
||||
useErrorStore().$state = error.response.data;
|
||||
break;
|
||||
default:
|
||||
console.log(error.response.data);
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
export default axios;
|
||||
7
resources/js/plugins/event-bus.js
Normal file
7
resources/js/plugins/event-bus.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import mitt from "mitt";
|
||||
|
||||
export default {
|
||||
install: (app, options) => {
|
||||
app.config.globalProperties.$eventBus = mitt();
|
||||
},
|
||||
};
|
||||
53
resources/js/stores/postStore.js
Normal file
53
resources/js/stores/postStore.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
import route from "ziggy-js/src/js/index";
|
||||
|
||||
import axios from "axios";
|
||||
|
||||
export const usePostStore = defineStore("postStore", {
|
||||
state: () => ({
|
||||
data: {
|
||||
defaultLocaleSlug: "my",
|
||||
countryLocales: [],
|
||||
localeCategories: [],
|
||||
},
|
||||
}),
|
||||
getters: {
|
||||
defaultLocaleSlug(state) {
|
||||
return state.data.defaultLocaleSlug;
|
||||
},
|
||||
countryLocales(state) {
|
||||
return state.data.countryLocales;
|
||||
},
|
||||
localeCategories(state) {
|
||||
return state.data.localeCategories;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async fetchCountryLocales() {
|
||||
try {
|
||||
const response = await axios.get(route("api.admin.country-locales"));
|
||||
console.log(response);
|
||||
this.data.countryLocales = response.data.country_locales;
|
||||
this.data.defaultLocaleSlug = response.data.default_locale_slug;
|
||||
} catch (error) {
|
||||
// alert(error);
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
async fetchLocaleCategories(countryLocaleSlug) {
|
||||
try {
|
||||
const response = await axios.get(
|
||||
route("api.admin.categories", {
|
||||
country_locale_slug: countryLocaleSlug,
|
||||
})
|
||||
);
|
||||
console.log(response);
|
||||
this.data.localeCategories = response.data.categories;
|
||||
} catch (error) {
|
||||
// alert(error);
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
44
resources/js/stores/useAuth.js
Normal file
44
resources/js/stores/useAuth.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import { defineStore } from "pinia";
|
||||
import axios from "axios";
|
||||
|
||||
export const useAuthStore = defineStore("auth", {
|
||||
state: () => ({
|
||||
loggedIn: localStorage.getItem("token") ? true : false,
|
||||
user: null,
|
||||
}),
|
||||
|
||||
getters: {},
|
||||
|
||||
actions: {
|
||||
async login(credentials) {
|
||||
await axios.get("sanctum/csrf-cookie");
|
||||
|
||||
const response = (await axios.post("api/login", credentials)).data;
|
||||
|
||||
if (response) {
|
||||
const token = `Bearer ${response.token}`;
|
||||
|
||||
localStorage.setItem("token", token);
|
||||
axios.defaults.headers.common["Authorization"] = token;
|
||||
|
||||
await this.ftechUser();
|
||||
}
|
||||
},
|
||||
|
||||
async logout() {
|
||||
const response = (await axios.post("api/logout")).data;
|
||||
|
||||
if (response) {
|
||||
localStorage.removeItem("token");
|
||||
|
||||
this.$reset();
|
||||
}
|
||||
},
|
||||
|
||||
async ftechUser() {
|
||||
this.user = (await axios.get("api/me")).data;
|
||||
|
||||
this.loggedIn = true;
|
||||
},
|
||||
},
|
||||
});
|
||||
8
resources/js/stores/useError.js
Normal file
8
resources/js/stores/useError.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export const useErrorStore = defineStore("error", {
|
||||
state: () => ({
|
||||
message: null,
|
||||
errors: {},
|
||||
}),
|
||||
});
|
||||
9
resources/js/vue/AdminApp.vue
Normal file
9
resources/js/vue/AdminApp.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "App",
|
||||
};
|
||||
</script>
|
||||
<style></style>
|
||||
127
resources/js/vue/NativeImageBlock.vue
Normal file
127
resources/js/vue/NativeImageBlock.vue
Normal file
@@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="card">
|
||||
<div class="card-body ratio ratio-21x9 bg-dark overflow-hidden">
|
||||
<div
|
||||
class="d-flex justify-content-center text-center rounded-2"
|
||||
:style="bgStyle"
|
||||
></div>
|
||||
<div
|
||||
class="position-absolute w-100 h-100 d-flex justify-content-center text-center"
|
||||
>
|
||||
<div v-if="isUploading" class="align-self-center">
|
||||
<div class="spinner-border text-light" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="align-self-center">
|
||||
<input
|
||||
type="file"
|
||||
@change="handleFileChange"
|
||||
accept="image/*"
|
||||
ref="fileInput"
|
||||
style="display: none"
|
||||
/>
|
||||
<button class="btn btn-primary" @click="openFileInput">
|
||||
{{ getButtonName }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
name: "NativeImageBlock",
|
||||
props: {
|
||||
apiUrl: {
|
||||
type: String,
|
||||
default: "https://productalert.test/api/admin/image/upload",
|
||||
},
|
||||
},
|
||||
data: () => ({
|
||||
isUploading: false,
|
||||
imgSrc: null,
|
||||
placeholderSrc: "https://placekitten.com/g/2100/900",
|
||||
}),
|
||||
computed: {
|
||||
getButtonName() {
|
||||
if (this.imgSrc != null && this.imgSrc?.length > 0) {
|
||||
return "Change featured image";
|
||||
} else {
|
||||
return "Upload featured image";
|
||||
}
|
||||
},
|
||||
getBlurPx() {
|
||||
return this.imgSrc ? 0 : 12;
|
||||
},
|
||||
bgStyle() {
|
||||
return {
|
||||
backgroundImage: `url(${this.getImgSrc})`,
|
||||
backgroundPosition: "center",
|
||||
backgroundSize: "cover",
|
||||
filter: `blur(${this.getBlurPx}px)`,
|
||||
webkitFilter: `blur(${this.getBlurPx}px)`,
|
||||
};
|
||||
},
|
||||
getImgSrc() {
|
||||
if (this.imgSrc != null && this.imgSrc?.length > 0) {
|
||||
return this.imgSrc;
|
||||
}
|
||||
return this.placeholderSrc;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
openFileInput() {
|
||||
this.$refs.fileInput.click();
|
||||
},
|
||||
handleFileChange(event) {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
this.uploadImage(file);
|
||||
}
|
||||
},
|
||||
uploadImage(file) {
|
||||
this.isUploading = true;
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
axios
|
||||
.post(this.apiUrl, formData, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
if (
|
||||
response.data.success === 1 &&
|
||||
response.data.file &&
|
||||
response.data.file.url
|
||||
) {
|
||||
this.imgSrc = response.data.file.url;
|
||||
this.$emit("saved", response.data.file.url);
|
||||
} else {
|
||||
console.error("Image upload failed. Invalid response format.");
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Image upload failed:", error.response); // Log the full response
|
||||
})
|
||||
.finally(() => {
|
||||
this.isUploading = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.isUploading = false;
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Add your custom styles here */
|
||||
</style>
|
||||
311
resources/js/vue/PostEditor.vue
Normal file
311
resources/js/vue/PostEditor.vue
Normal file
@@ -0,0 +1,311 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-9" style="max-width: 700px">
|
||||
<div class="mb-3">
|
||||
<div class="form-floating">
|
||||
<input
|
||||
v-model="post.title"
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="Post title"
|
||||
/>
|
||||
<label>Write a SEO post title</label>
|
||||
</div>
|
||||
<small>
|
||||
<span class="text-secondary">{{ getPostFullUrl }}</span>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="form-floating mb-3">
|
||||
<textarea
|
||||
v-model="post.excerpt"
|
||||
class="form-control"
|
||||
style="min-height: 150px"
|
||||
placeholder="Enter a post excerpt/summary"
|
||||
></textarea>
|
||||
<label
|
||||
>Write a simple excerpt to convince & entice users to view this
|
||||
post!</label
|
||||
>
|
||||
</div>
|
||||
|
||||
<native-image-block
|
||||
class="mb-3"
|
||||
:input-image="post.featured_image"
|
||||
@saved="imageSaved"
|
||||
></native-image-block>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<vue-editor-js
|
||||
v-on:saved="editorSaved"
|
||||
:config="config"
|
||||
:initialized="onInitialized"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="d-grid mb-2">
|
||||
<select
|
||||
class="form-select mb-2"
|
||||
aria-label="Default select example"
|
||||
v-on:change="statusChanged"
|
||||
>
|
||||
<option
|
||||
v-for="item in status"
|
||||
v-bind:key="item"
|
||||
:selected="item == post.status"
|
||||
:value="item"
|
||||
>
|
||||
Post Status: {{ item }}
|
||||
</option>
|
||||
</select>
|
||||
<button @click="checkAndSave" class="btn btn-primary">
|
||||
Save as {{ post.status }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="card mb-2">
|
||||
<div class="card-header fw-bold">Country Locality</div>
|
||||
<div class="card-body">
|
||||
<select class="form-select" v-on:change="localeChanged">
|
||||
<option
|
||||
v-for="item in countryLocales"
|
||||
v-bind:key="item.id"
|
||||
:value="item.slug"
|
||||
:selected="item.slug == post.locale_slug"
|
||||
>
|
||||
{{ item.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2">
|
||||
<div class="card-header fw-bold">Categories</div>
|
||||
<div class="card-body">
|
||||
<div
|
||||
class="py-1"
|
||||
v-for="item in localeCategories"
|
||||
v-bind:key="item.id"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
:id="item.id"
|
||||
:value="item.id"
|
||||
v-model="post.categories"
|
||||
/>
|
||||
{{ item.name }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VueEditorJs from "./VueEditorJs.vue";
|
||||
|
||||
import List from "@editorjs/list";
|
||||
import Header from "@editorjs/header";
|
||||
|
||||
import { mapActions, mapState } from "pinia";
|
||||
|
||||
import { usePostStore } from "@/stores/postStore.js";
|
||||
|
||||
export default {
|
||||
components: { VueEditorJs, List, Header },
|
||||
data() {
|
||||
return {
|
||||
post: {
|
||||
title: "",
|
||||
slug: "",
|
||||
excerpt: "",
|
||||
author_id: null,
|
||||
featured: false,
|
||||
featured_image: null,
|
||||
body: {
|
||||
time: 1591362820044,
|
||||
blocks: [],
|
||||
version: "2.25.0",
|
||||
},
|
||||
locale_slug: null,
|
||||
locale_id: null,
|
||||
status: "draft",
|
||||
categories: null,
|
||||
},
|
||||
|
||||
status: ["publish", "future", "draft", "private", "trash"],
|
||||
|
||||
config: {
|
||||
placeholder: "Write something (ノ◕ヮ◕)ノ*:・゚✧",
|
||||
tools: {
|
||||
header: {
|
||||
class: Header,
|
||||
config: {
|
||||
placeholder: "Enter a header",
|
||||
levels: [2, 3, 4],
|
||||
defaultLevel: 3,
|
||||
},
|
||||
},
|
||||
list: {
|
||||
class: List,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
},
|
||||
onReady: () => {},
|
||||
onChange: (args) => {},
|
||||
data: {
|
||||
time: 1591362820044,
|
||||
blocks: [],
|
||||
version: "2.25.0",
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
"post.title": {
|
||||
deep: true,
|
||||
handler(after, before) {
|
||||
this.post.slug = this.slugify(after);
|
||||
},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState(usePostStore, [
|
||||
"countryLocales",
|
||||
"localeCategories",
|
||||
"defaultLocaleSlug",
|
||||
]),
|
||||
getPostFullUrl() {
|
||||
if (this.post.slug?.length > 0) {
|
||||
return (
|
||||
"https://productalert.co/" +
|
||||
this.post.locale_slug +
|
||||
"/posts/" +
|
||||
this.post.slug
|
||||
);
|
||||
}
|
||||
return (
|
||||
"https://productalert.co/" +
|
||||
this.post.locale_slug +
|
||||
"/posts/enter-a-post-title-to-autogen-slug"
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(usePostStore, [
|
||||
"fetchCountryLocales",
|
||||
"fetchLocaleCategories",
|
||||
]),
|
||||
checkAndSave() {
|
||||
let errors = [];
|
||||
|
||||
if (!(this.post.title?.length > 0)) {
|
||||
errors.push("post title");
|
||||
}
|
||||
|
||||
if (!(this.post.slug?.length > 0)) {
|
||||
errors.push("post slug");
|
||||
}
|
||||
|
||||
if (!(this.post.excerpt?.length > 0)) {
|
||||
errors.push("post excerpt");
|
||||
}
|
||||
|
||||
if (!(this.post.featured_image?.length > 0)) {
|
||||
errors.push("post featured image");
|
||||
}
|
||||
|
||||
if (!(this.post.body.blocks?.length > 0)) {
|
||||
errors.push("Post body");
|
||||
}
|
||||
|
||||
if (
|
||||
!(this.post.locale_slug?.length > 0) ||
|
||||
!(this.post.locale_id != null)
|
||||
) {
|
||||
errors.push("Country locality");
|
||||
}
|
||||
|
||||
if (!(this.post.categories != null)) {
|
||||
errors.push("Category");
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
alert("HAIYA many errors! pls fix " + errors.join(", "));
|
||||
} else {
|
||||
this.savePost();
|
||||
}
|
||||
},
|
||||
savePost() {},
|
||||
onInitialized(editor) {},
|
||||
imageSaved(src) {
|
||||
this.post.featured_image = src;
|
||||
},
|
||||
editorSaved(payload) {
|
||||
this.post.body = payload;
|
||||
},
|
||||
statusChanged(e) {
|
||||
this.post.status = e.target.value;
|
||||
},
|
||||
localeChanged(e) {
|
||||
this.post.locale_slug = e.target.value;
|
||||
this.post.locale_id = this.getLocaleIdBySlug(e.target.value);
|
||||
this.post.categories = [];
|
||||
|
||||
setTimeout(
|
||||
function () {
|
||||
this.fetchLocaleCategories(this.post.locale_slug);
|
||||
}.bind(this),
|
||||
100
|
||||
);
|
||||
},
|
||||
setDefaultLocale() {
|
||||
if (this.post.locale_slug == null || this.post.locale_slug == "") {
|
||||
this.post.locale_slug = this.defaultLocaleSlug;
|
||||
this.post.locale_id = this.getLocaleIdBySlug(this.defaultLocaleSlug);
|
||||
}
|
||||
},
|
||||
getLocaleIdBySlug(slug) {
|
||||
for (const [key, _item] of Object.entries(this.countryLocales)) {
|
||||
if (_item.slug == slug) {
|
||||
return _item.id;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
slugify: function (title) {
|
||||
var slug = "";
|
||||
// Change to lower case
|
||||
var titleLower = title.toLowerCase();
|
||||
// Replace characters that are not alphabets (a-z), digits (0-9), or spaces with an empty string
|
||||
slug = titleLower.replace(/[^a-z0-9\s]/g, "");
|
||||
// Replace consecutive spaces with a single space
|
||||
slug = slug.replace(/\s+/g, " ");
|
||||
// Trim any leading or trailing spaces
|
||||
slug = slug.trim();
|
||||
// Replace spaces with a single dash
|
||||
slug = slug.replace(/\s+/g, "-");
|
||||
return slug;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchCountryLocales().then(() => {
|
||||
this.setDefaultLocale();
|
||||
|
||||
setTimeout(
|
||||
function () {
|
||||
this.fetchLocaleCategories(this.post.locale_slug);
|
||||
}.bind(this),
|
||||
100
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
109
resources/js/vue/VueEditorJs.vue
Normal file
109
resources/js/vue/VueEditorJs.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<div :id="holder" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EditorJS from "@editorjs/editorjs";
|
||||
import { defineComponent, onMounted, reactive } from "vue";
|
||||
|
||||
export const PLUGINS = {
|
||||
header: import("@editorjs/header"),
|
||||
list: import("@editorjs/list"),
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: "vue-editor-js",
|
||||
props: {
|
||||
holder: {
|
||||
type: String,
|
||||
default: () => "vue-editor-js",
|
||||
require: true,
|
||||
},
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
require: true,
|
||||
},
|
||||
initialized: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
setup: (props, context) => {
|
||||
const state = reactive({ editor: null });
|
||||
|
||||
function initEditor(props) {
|
||||
destroyEditor();
|
||||
state.editor = new EditorJS({
|
||||
holder: props.holder || "vue-editor-js",
|
||||
...props.config,
|
||||
onChange: (api, event) => {
|
||||
saveEditor();
|
||||
},
|
||||
});
|
||||
props.initialized(state.editor);
|
||||
}
|
||||
|
||||
function destroyEditor() {
|
||||
if (state.editor) {
|
||||
state.editor.destroy();
|
||||
state.editor = null;
|
||||
}
|
||||
}
|
||||
|
||||
function saveEditor() {
|
||||
console.log("saveEditor");
|
||||
if (state.editor) {
|
||||
state.editor.save().then((data) => {
|
||||
// Do what you want with the data here
|
||||
console.log(data);
|
||||
context.emit("saved", data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onMounted((_) => initEditor(props));
|
||||
|
||||
return { props, state };
|
||||
},
|
||||
methods: {
|
||||
useTools(props, config) {
|
||||
const pluginKeys = Object.keys(PLUGINS);
|
||||
const tools = { ...props.customTools };
|
||||
|
||||
if (pluginKeys.every((p) => !props[p])) {
|
||||
pluginKeys.forEach((key) => (tools[key] = { class: PLUGINS[key] }));
|
||||
Object.keys(config).forEach((key) => {
|
||||
if (tools[key] !== undefined && tools[key] !== null) {
|
||||
tools[key]["config"] = config[key];
|
||||
}
|
||||
});
|
||||
return tools;
|
||||
}
|
||||
|
||||
pluginKeys.forEach((key) => {
|
||||
const prop = props[key];
|
||||
if (!prop) {
|
||||
return;
|
||||
}
|
||||
|
||||
tools[key] = { class: PLUGINS[key] };
|
||||
|
||||
if (typeof prop === "object") {
|
||||
const options = Object.assign({}, props[key]);
|
||||
delete options["class"];
|
||||
tools[key] = Object.assign(tools[key], options);
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(config).forEach((key) => {
|
||||
if (tools[key] !== undefined && tools[key] !== null) {
|
||||
tools[key]["config"] = config[key];
|
||||
}
|
||||
});
|
||||
|
||||
return tools;
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
7
resources/js/ziggy.js
Normal file
7
resources/js/ziggy.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const Ziggy = {"url":"https:\/\/productalert.test","port":null,"defaults":{},"routes":{"debugbar.openhandler":{"uri":"_debugbar\/open","methods":["GET","HEAD"]},"debugbar.clockwork":{"uri":"_debugbar\/clockwork\/{id}","methods":["GET","HEAD"]},"debugbar.assets.css":{"uri":"_debugbar\/assets\/stylesheets","methods":["GET","HEAD"]},"debugbar.assets.js":{"uri":"_debugbar\/assets\/javascript","methods":["GET","HEAD"]},"debugbar.cache.delete":{"uri":"_debugbar\/cache\/{key}\/{tags?}","methods":["DELETE"]},"sanctum.csrf-cookie":{"uri":"sanctum\/csrf-cookie","methods":["GET","HEAD"]},"ignition.healthCheck":{"uri":"_ignition\/health-check","methods":["GET","HEAD"]},"ignition.executeSolution":{"uri":"_ignition\/execute-solution","methods":["POST"]},"ignition.updateConfig":{"uri":"_ignition\/update-config","methods":["POST"]},"api.auth.login.post":{"uri":"api\/login","methods":["POST"]},"api.auth.logout.post":{"uri":"api\/logout","methods":["POST"]},"api.admin.country-locales":{"uri":"api\/admin\/country-locales","methods":["GET","HEAD"]},"api.admin.categories":{"uri":"api\/admin\/categories\/{country_locale_slug}","methods":["GET","HEAD"]},"api.admin.upload.cloud.image":{"uri":"api\/admin\/image\/upload","methods":["GET","HEAD"]},"login":{"uri":"login","methods":["GET","HEAD"]},"logout":{"uri":"logout","methods":["POST"]},"register":{"uri":"register","methods":["GET","HEAD"]},"password.request":{"uri":"password\/reset","methods":["GET","HEAD"]},"password.email":{"uri":"password\/email","methods":["POST"]},"password.reset":{"uri":"password\/reset\/{token}","methods":["GET","HEAD"]},"password.update":{"uri":"password\/reset","methods":["POST"]},"password.confirm":{"uri":"password\/confirm","methods":["GET","HEAD"]},"dashboard":{"uri":"admin","methods":["GET","HEAD"]},"about":{"uri":"admin\/about","methods":["GET","HEAD"]},"users.index":{"uri":"admin\/users","methods":["GET","HEAD"]},"posts.manage":{"uri":"admin\/posts","methods":["GET","HEAD"]},"posts.manage.edit":{"uri":"admin\/posts\/edit\/{post_id}","methods":["GET","HEAD"]},"posts.manage.new":{"uri":"admin\/posts\/new","methods":["GET","HEAD"]},"profile.show":{"uri":"admin\/profile","methods":["GET","HEAD"]},"profile.update":{"uri":"admin\/profile","methods":["PUT"]},"home":{"uri":"\/","methods":["GET","HEAD"]},"home.country":{"uri":"{country}","methods":["GET","HEAD"]},"home.country.posts":{"uri":"{country}\/posts","methods":["GET","HEAD"]},"home.country.post":{"uri":"{country}\/posts\/{post_slug}","methods":["GET","HEAD"]},"home.country.category":{"uri":"{country}\/{category}","methods":["GET","HEAD"]}}};
|
||||
|
||||
if (typeof window !== 'undefined' && typeof window.Ziggy !== 'undefined') {
|
||||
Object.assign(Ziggy.routes, window.Ziggy.routes);
|
||||
}
|
||||
|
||||
export { Ziggy };
|
||||
24
resources/views/admin/posts/upsert.blade.php
Normal file
24
resources/views/admin/posts/upsert.blade.php
Normal file
@@ -0,0 +1,24 @@
|
||||
@extends('layouts.admin.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container-xl text-center">
|
||||
<!-- Page title -->
|
||||
<div class="page-header d-print-none">
|
||||
<h2 class="page-title text-center justify-content-center">
|
||||
<div class="align-self-center">
|
||||
@if (!is_null($post))
|
||||
Edit Post
|
||||
@else
|
||||
New Post
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
<post-editor></post-editor>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -16,7 +16,7 @@
|
||||
</head>
|
||||
|
||||
<body class="theme-light">
|
||||
<div class="page">
|
||||
<div class="page" id="app">
|
||||
<div class="sticky-top">
|
||||
@include('layouts.admin.header')
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Core plugin JavaScript-->
|
||||
@vite('resources/js/admin-app.js')
|
||||
|
||||
Reference in New Issue
Block a user