/home/bdqbpbxa/api-uniferx.goodface.com.ua/vendor/laravel/nova/resources/js/app.js
import Localization from '@/mixins/Localization'
import { setupAxios } from '@/util/axios'
import { setupNumbro } from '@/util/numbro'
import { setupInertia } from '@/util/inertia'
import url from '@/util/url'
import { createInertiaApp, Head, Link } from '@inertiajs/inertia-vue3'
import { Inertia } from '@inertiajs/inertia'
import NProgress from 'nprogress'
import { registerViews } from './components'
import { registerFields } from './fields'
import Mousetrap from 'mousetrap'
import Form from 'form-backend-validation'
import { createNovaStore } from './store'
import resourceStore from './store/resources'
import FloatingVue from 'floating-vue'
import find from 'lodash/find'
import isNil from 'lodash/isNil'
import fromPairs from 'lodash/fromPairs'
import isString from 'lodash/isString'
import omit from 'lodash/omit'
import Toasted from 'toastedjs'
import Emitter from 'tiny-emitter'
import Layout from '@/layouts/AppLayout'
import CodeMirror from 'codemirror'
import { Settings } from 'luxon'
import 'codemirror/mode/markdown/markdown'
import 'codemirror/mode/javascript/javascript'
import 'codemirror/mode/php/php'
import 'codemirror/mode/ruby/ruby'
import 'codemirror/mode/shell/shell'
import 'codemirror/mode/sass/sass'
import 'codemirror/mode/yaml/yaml'
import 'codemirror/mode/yaml-frontmatter/yaml-frontmatter'
import 'codemirror/mode/nginx/nginx'
import 'codemirror/mode/xml/xml'
import 'codemirror/mode/vue/vue'
import 'codemirror/mode/dockerfile/dockerfile'
import 'codemirror/keymap/vim'
import 'codemirror/mode/sql/sql'
import 'codemirror/mode/twig/twig'
import 'codemirror/mode/htmlmixed/htmlmixed'
import { ColorTranslator } from 'colortranslator'
import 'floating-vue/dist/style.css'
const { parseColor } = require('tailwindcss/lib/util/color')
CodeMirror.defineMode('htmltwig', function (config, parserConfig) {
return CodeMirror.overlayMode(
CodeMirror.getMode(config, parserConfig.backdrop || 'text/html'),
CodeMirror.getMode(config, 'twig')
)
})
const emitter = new Emitter()
window.createNovaApp = config => new Nova(config)
window.Vue = require('vue')
const { createApp, h } = window.Vue
class Nova {
constructor(config) {
this.bootingCallbacks = []
this.appConfig = config
this.useShortcuts = true
this.pages = {
'Nova.Attach': require('@/pages/Attach').default,
'Nova.Create': require('@/pages/Create').default,
'Nova.Dashboard': require('@/pages/Dashboard').default,
'Nova.Detail': require('@/pages/Detail').default,
'Nova.Error': require('@/pages/AppError').default,
'Nova.Error403': require('@/pages/Error403').default,
'Nova.Error404': require('@/pages/Error404').default,
'Nova.ForgotPassword': require('@/pages/ForgotPassword').default,
'Nova.Index': require('@/pages/Index').default,
'Nova.Lens': require('@/pages/Lens').default,
'Nova.Login': require('@/pages/Login').default,
'Nova.Replicate': require('@/pages/Replicate').default,
'Nova.ResetPassword': require('@/pages/ResetPassword').default,
'Nova.Update': require('@/pages/Update').default,
'Nova.UpdateAttached': require('@/pages/UpdateAttached').default,
}
this.$toasted = new Toasted({
theme: 'nova',
position: config.rtlEnabled ? 'bottom-left' : 'bottom-right',
duration: 6000,
})
this.$progress = NProgress
this.$router = Inertia
if (config.debug === true) {
this.$testing = {
timezone: timezone => {
Settings.defaultZoneName = timezone
},
}
}
}
/**
* Register a callback to be called before Nova starts. This is used to bootstrap
* addons, tools, custom fields, or anything else Nova needs
*/
booting(callback) {
this.bootingCallbacks.push(callback)
}
/**
* Execute all of the booting callbacks.
*/
boot() {
this.store = createNovaStore()
this.bootingCallbacks.forEach(callback => callback(this.app, this.store))
this.bootingCallbacks = []
}
booted(callback) {
callback(this.app, this.store)
}
async countdown() {
this.log('Initiating Nova countdown...')
const appName = this.config('appName')
await createInertiaApp({
title: title => (!title ? appName : `${appName} - ${title}`),
resolve: name => {
const page = !isNil(this.pages[name])
? this.pages[name]
: require('@/pages/Error404').default
page.layout = page.layout || Layout
return page
},
setup: ({ el, App, props, plugin }) => {
this.mountTo = el
this.app = createApp({ render: () => h(App, props) })
this.app.use(plugin)
this.app.use(FloatingVue, {
preventOverflow: true,
flip: true,
themes: {
Nova: {
$extend: 'tooltip',
triggers: ['click'],
autoHide: true,
placement: 'bottom',
html: true,
},
},
})
},
})
}
/**
* Start the Nova app by calling each of the tool's callbacks and then creating
* the underlying Vue instance.
*/
liftOff() {
this.log('We have lift off!')
this.boot()
if (this.config('notificationCenterEnabled')) {
this.notificationPollingInterval = setInterval(() => {
if (document.hasFocus()) {
this.$emit('refresh-notifications')
}
}, this.config('notificationPollingInterval'))
}
this.registerStoreModules()
this.app.mixin(Localization)
setupInertia()
document.addEventListener('inertia:before', () => {
;(async () => {
this.log('Syncing Inertia props to the store...')
await this.store.dispatch('assignPropsFromInertia')
})()
})
document.addEventListener('inertia:navigate', () => {
;(async () => {
this.log('Syncing Inertia props to the store...')
await this.store.dispatch('assignPropsFromInertia')
})()
})
this.app.mixin({
methods: {
$url: (path, parameters) => this.url(path, parameters),
},
})
this.component('Link', Link)
this.component('InertiaLink', Link)
this.component('Head', Head)
registerViews(this)
registerFields(this)
this.app.mount(this.mountTo)
let mousetrapDefaultStopCallback = Mousetrap.prototype.stopCallback
Mousetrap.prototype.stopCallback = (e, element, combo) => {
if (!this.useShortcuts) {
return true
}
return mousetrapDefaultStopCallback.call(this, e, element, combo)
}
Mousetrap.init()
this.applyTheme()
this.log('All systems go...')
}
config(key) {
return this.appConfig[key]
}
/**
* Return a form object configured with Nova's preconfigured axios instance.
*
* @param {object} data
*/
form(data) {
return new Form(data, {
http: this.request(),
})
}
/**
* Return an axios instance configured to make requests to Nova's API
* and handle certain response codes.
*/
request(options) {
let axios = setupAxios()
if (options !== undefined) {
return axios(options)
}
return axios
}
/**
* Get the URL from base Nova prefix.
*/
url(path, parameters) {
if (path === '/') {
path = this.config('initialPath')
}
return url(this.config('base'), path, parameters)
}
/**
* Register a listener on Nova's built-in event bus
*/
$on(...args) {
emitter.on(...args)
}
/**
* Register a one-time listener on the event bus
*/
$once(...args) {
emitter.once(...args)
}
/**
* Unregister an listener on the event bus
*/
$off(...args) {
emitter.off(...args)
}
/**
* Emit an event on the event bus
*/
$emit(...args) {
emitter.emit(...args)
}
/**
* Determine if Nova is missing the requested resource with the given uri key
*/
missingResource(uriKey) {
return (
find(this.config('resources'), r => r.uriKey === uriKey) === undefined
)
}
/**
* Register a keyboard shortcut.
*/
addShortcut(keys, callback) {
Mousetrap.bind(keys, callback)
}
/**
* Unbind a keyboard shortcut.
*/
disableShortcut(keys) {
Mousetrap.unbind(keys)
}
/**
* Pause all keyboard shortcuts.
*/
pauseShortcuts() {
this.useShortcuts = false
}
/**
* Resume all keyboard shortcuts.
*/
resumeShortcuts() {
this.useShortcuts = true
}
/**
* Register the built-in Vuex modules for each resource
*/
registerStoreModules() {
this.app.use(this.store)
this.config('resources').forEach(resource => {
this.store.registerModule(resource.uriKey, resourceStore)
})
}
/**
* Register Inertia component.
*/
inertia(name, component) {
this.pages[name] = component
}
/**
* Register a custom Vue component.
*/
component(name, component) {
if (isNil(this.app._context.components[name])) {
this.app.component(name, component)
}
}
/**
* Show an error message to the user.
*
* @param {string} message
*/
info(message) {
this.$toasted.show(message, { type: 'info' })
}
/**
* Show an error message to the user.
*
* @param {string} message
*/
error(message) {
this.$toasted.show(message, { type: 'error' })
}
/**
* Show a success message to the user.
*
* @param {string} message
*/
success(message) {
this.$toasted.show(message, { type: 'success' })
}
/**
* Show a warning message to the user.
*
* @param {string} message
*/
warning(message) {
this.$toasted.show(message, { type: 'warning' })
}
/**
* Format a number using numbro.js for consistent number formatting.
*/
formatNumber(number, format) {
const numbro = setupNumbro(
document.querySelector('meta[name="locale"]').content
)
const num = numbro(number)
if (format !== undefined) {
return num.format(format)
}
return num.format()
}
/**
* Log a message to the console with the NOVA prefix
*
* @param message
* @param type
*/
log(message, type = 'log') {
console[type](`[NOVA]`, message)
}
/**
* Redirect to login path.
*/
redirectToLogin() {
const url =
!this.config('withAuthentication') && this.config('customLoginPath')
? this.config('customLoginPath')
: this.url('/login')
this.visit({
remote: true,
url,
})
}
/**
* Visit page using Inertia visit or window.location for remote.
*/
visit(path, options) {
options = options || {}
const openInNewTab = options?.openInNewTab || null
if (isString(path)) {
Inertia.visit(this.url(path), omit(options, ['openInNewTab']))
return
}
if (isString(path.url) && path.hasOwnProperty('remote')) {
if (path.remote === true) {
if (openInNewTab === true) {
window.open(path.url, '_blank')
} else {
window.location = path.url
}
return
}
Inertia.visit(path.url, omit(options, ['openInNewTab']))
}
}
applyTheme() {
const brandColors = this.config('brandColors')
if (Object.keys(brandColors).length > 0) {
const style = document.createElement('style')
// Handle converting any non-RGB user strings into valid RGB strings.
// This allows the user to specify any color in HSL, RGB, and RGBA
// format, and we'll convert it to the proper format for them.
let css = Object.keys(brandColors).reduce((carry, v) => {
let colorValue = brandColors[v]
let validColor = parseColor(colorValue)
if (validColor) {
let parsedColor = parseColor(
ColorTranslator.toRGBA(convertColor(validColor))
)
let rgbaString = `${parsedColor.color.join(' ')} / ${
parsedColor.alpha
}`
return carry + `\n --colors-primary-${v}: ${rgbaString};`
}
return carry + `\n --colors-primary-${v}: ${colorValue};`
}, '')
style.innerHTML = `:root {${css}\n}`
document.head.append(style)
}
}
}
function convertColor(parsedColor) {
let color = fromPairs(
Array.from(parsedColor.mode).map((v, i) => {
return [v, parsedColor.color[i]]
})
)
if (parsedColor.alpha !== undefined) {
color.a = parsedColor.alpha
}
return color
}