Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
2d9eb8640b
|
|||
|
78bb0f72d5
|
|||
|
a14e1b20c0
|
|||
|
6241539cb3
|
|||
|
b87104c22d
|
|||
|
5b8a3b3714
|
|||
|
5f9d23e24a
|
|||
|
962f8eb6ad
|
|||
|
28a7b3a387
|
|||
|
5dbfc74c3b
|
|||
|
7f1dbd0f14
|
|||
|
76790b4ebf
|
|||
|
33d9e5ec06
|
@@ -34,6 +34,12 @@ REDIS_HOST=redis
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
SCOUT_DRIVER=meilisearch
|
||||
SCOUT_PREFIX=
|
||||
SCOUT_QUEUE=false
|
||||
MEILISEARCH_HOST=http://localhost:7700
|
||||
MEILISEARCH_KEY=
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailhog
|
||||
MAIL_PORT=1125
|
||||
@@ -58,8 +64,17 @@ MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
|
||||
INTEGRITY_HASH_HUMANS_TXT=""
|
||||
INTEGRITY_HASH_ROBOTS_TXT=""
|
||||
INTEGRITY_HASH_COPYRIGHT_HTML=""
|
||||
INTEGRITY_HASH_COPYRIGHT_MD=""
|
||||
INTEGRITY_HASH_RSS_FEED=""
|
||||
INTEGRITY_HASH_ATOM_FEED=""
|
||||
INTEGRITY_HASH_FAVICON_ICO=""
|
||||
INTEGRITY_HASH_FAVICON_PNG=""
|
||||
INTEGRITY_HASH_FAVICON_SVG=""
|
||||
INTEGRITY_HASH_NUNITO_REGULAR_WOFF2_FONT=""
|
||||
INTEGRITY_HASH_POIRETONE_REGULAR_WOFF2_FONT=""
|
||||
INTEGRITY_HASH_WEBMANIFEST_JSON=""
|
||||
INTEGRITY_HASH_MIX_MANIFEST_JSON=""
|
||||
INTEGRITY_HASH_APP_CSS=""
|
||||
INTEGRITY_HASH_APP_JS=""
|
||||
|
||||
@@ -9,10 +9,14 @@ use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Inertia\Response;
|
||||
use Jenssegers\Agent\Agent;
|
||||
use Laravel\Fortify\Features;
|
||||
use Laravel\Jetstream\Http\Controllers\Inertia\Concerns\ConfirmsTwoFactorAuthentication;
|
||||
use Laravel\Jetstream\Jetstream;
|
||||
|
||||
class UserProfileController extends Controller
|
||||
{
|
||||
use ConfirmsTwoFactorAuthentication;
|
||||
|
||||
/**
|
||||
* Show the general profile settings screen.
|
||||
*
|
||||
@@ -27,6 +31,7 @@ class UserProfileController extends Controller
|
||||
$this->validateTwoFactorAuthenticationState($request);
|
||||
|
||||
return Jetstream::inertia()->render($request, 'Profile/Show', [
|
||||
'confirmsTwoFactorAuthentication' => Features::optionEnabled(Features::twoFactorAuthentication(), 'confirm'),
|
||||
'sessions' => $this->sessions($request)->all(),
|
||||
'timezones' => timezone_identifiers_list(),
|
||||
]);
|
||||
|
||||
@@ -19,8 +19,8 @@ class CheckCustomSessionData
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if ((! session()->has('timezone_name') || empty(session('timezone_name'))) && $request->user()) {
|
||||
session()->put('timezone_name', $request->user()->timezone_name);
|
||||
if ((! session()->has('thing') || empty(session('thing'))) && $request->user()) {
|
||||
session()->put('thing', $request->user()->thing);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use Illuminate\Auth\Events\Login;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class SuccessfulLogin
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \Illuminate\Auth\Events\Login $event
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Login $event): void
|
||||
{
|
||||
Session::put('timezone_name', $event->user->timezone_name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use Illuminate\Auth\Events\Logout;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class SuccessfulLogout
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \Illuminate\Auth\Events\Logout $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Logout $event)
|
||||
{
|
||||
Session::forget('timezone_name');
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ class User extends Authenticatable
|
||||
/** @var array */
|
||||
protected $appends = [
|
||||
'full_name',
|
||||
'name_full',
|
||||
'surname_full',
|
||||
'profile_photo_url',
|
||||
];
|
||||
|
||||
@@ -142,7 +142,7 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
||||
*/
|
||||
public function fullNameReversed(): Attribute
|
||||
public function surnameFull(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn ($value, $attributes) => "{$attributes['surname']}, {$attributes['name']}",
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class CarbonServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Carbon::macro('getHumanInterval', function ($other) {
|
||||
$isNow = $other === null;
|
||||
|
||||
if ($isNow) {
|
||||
$other = static::now($this->tz);
|
||||
}
|
||||
|
||||
$diffInMinutes = $this->diffInMinutes($other);
|
||||
|
||||
$minutes = $diffInMinutes % 60;
|
||||
|
||||
$diffInHours = $diffInMinutes / 60;
|
||||
$hours = $diffInHours % 60;
|
||||
|
||||
$diffInDays = $diffInHours / 24;
|
||||
$days = $diffInDays % 24;
|
||||
|
||||
$diffInWeeks = $diffInDays / 24;
|
||||
$weeks = $diffInWeeks % 24;
|
||||
|
||||
$diffInMonths = $diffInWeeks / 7;
|
||||
$months = $diffInMonths % 7;
|
||||
|
||||
$diffInYears = $diffInMonths / 12;
|
||||
$years = $diffInYears % 12;
|
||||
|
||||
$outputArray = [];
|
||||
if ($years > 0) {
|
||||
$outputArray['years'] = "$years years";
|
||||
}
|
||||
if ($months > 0) {
|
||||
$outputArray['months'] = "$months months";
|
||||
}
|
||||
if ($weeks > 0 && $days === 0) {
|
||||
$outputArray['weeks'] = "$weeks weeks";
|
||||
}
|
||||
if ($days > 0) {
|
||||
$outputArray['days'] = "$days days";
|
||||
}
|
||||
if ($hours > 0) {
|
||||
$outputArray['hours'] = "$hours hours";
|
||||
}
|
||||
if ($minutes > 0) {
|
||||
$outputArray['minutes'] = "$minutes minutes";
|
||||
}
|
||||
|
||||
return implode(', ', $outputArray);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Listeners\SuccessfulLogin;
|
||||
//use App\Listeners\SuccessfulLogout;
|
||||
use Illuminate\Auth\Events\Login;
|
||||
//use Illuminate\Auth\Events\Logout;
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The event to listener mappings for the application.
|
||||
*
|
||||
* @var array<class-string, array<int, class-string>>
|
||||
*/
|
||||
protected $listen = [
|
||||
Registered::class => [
|
||||
SendEmailVerificationNotification::class,
|
||||
],
|
||||
Login::class => [
|
||||
SuccessfulLogin::class,
|
||||
],
|
||||
/*Logout::class => [
|
||||
SuccessfulLogout::class,
|
||||
],*/
|
||||
];
|
||||
|
||||
/**
|
||||
* Register any events for your application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if events and listeners should be automatically discovered.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function shouldDiscoverEvents()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
...
|
||||
|
||||
return [
|
||||
|
||||
...
|
||||
|
||||
'providers' => [
|
||||
|
||||
...
|
||||
|
||||
/*
|
||||
* Application Service Providers...
|
||||
*/
|
||||
...
|
||||
App\Providers\CarbonServiceProvider::class,
|
||||
],
|
||||
|
||||
...
|
||||
|
||||
];
|
||||
@@ -5,6 +5,8 @@ if (! function_exists('snake2Title')) {
|
||||
* Convert a snake case string to a title with spaces
|
||||
* and every word capitalized.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param string $stakeSlug A snake case string, commonly a slug
|
||||
*
|
||||
* @return string
|
||||
@@ -22,6 +24,8 @@ if (! function_exists('carbon')) {
|
||||
* It will attempt to find a timezone in the current
|
||||
* session but default to UTC.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param string|null $timestring
|
||||
*
|
||||
* @return \Carbon\Carbon
|
||||
@@ -40,6 +44,8 @@ if (! function_exists('jddayofweek')) {
|
||||
/**
|
||||
* Returns the day of the week. Can return a string or an integer depending on the mode.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param int|null $intDay
|
||||
* @param int $mode
|
||||
*
|
||||
@@ -59,10 +65,106 @@ if (! function_exists('jddayofweek')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('is_serialized')) {
|
||||
/**
|
||||
* Check a value to find if it was serialized.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param bool $strict
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function is_serialized($data, bool $strict = true): bool
|
||||
{
|
||||
// If it isn't a string, it isn't serialized.
|
||||
if (! is_string($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = trim($data);
|
||||
if ('N;' === $data) {
|
||||
return true;
|
||||
}
|
||||
if (strlen($data) < 4) {
|
||||
return false;
|
||||
}
|
||||
if (':' !== $data[1]) {
|
||||
return false;
|
||||
}
|
||||
if ($strict) {
|
||||
$lastc = substr($data, -1);
|
||||
if (';' !== $lastc && '}' !== $lastc) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$semicolon = strpos($data, ';');
|
||||
$brace = strpos($data, '}');
|
||||
// Either ; or } must exist.
|
||||
if (!$semicolon && !$brace) {
|
||||
return false;
|
||||
}
|
||||
// But neither must be in the first X characters.
|
||||
if ($semicolon && $semicolon < 3) {
|
||||
return false;
|
||||
}
|
||||
if ($brace && $brace < 4) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$token = $data[0];
|
||||
switch ($token) {
|
||||
case 's':
|
||||
if ($strict) {
|
||||
if ('"' !== substr($data, -2, 1)) {
|
||||
return false;
|
||||
}
|
||||
} elseif (!strpos($data, '"')) {
|
||||
return false;
|
||||
}
|
||||
// Or else fall through.
|
||||
case 'a':
|
||||
case 'O':
|
||||
return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
|
||||
case 'b':
|
||||
case 'i':
|
||||
case 'd':
|
||||
$end = $strict ? '$' : '';
|
||||
return (bool) preg_match("/^{$token}:[0-9.E+-]+;$end/", $data);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('maybe_unserialize')) {
|
||||
/**
|
||||
* Unserialize data only if it was serialized. Will return
|
||||
* an array if it was a serialized string, otherwise it
|
||||
* will return whatever was passed into the function
|
||||
* leaving it untouched.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function maybe_unserialize($data)
|
||||
{
|
||||
if (is_serialized($data)) { // Don't attempt to unserialize data that wasn't serialized going in.
|
||||
return @unserialize(trim($data));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('cel2Fah')) {
|
||||
/**
|
||||
* Convert from celsius to fahrenheit.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param float|int|string $celsius
|
||||
* @param int $precision
|
||||
*
|
||||
@@ -78,6 +180,8 @@ if (! function_exists('fah2Cel')) {
|
||||
/**
|
||||
* Convert from fahrenheit to celsius.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param float|int|string $fahrenheit
|
||||
* @param int $precision
|
||||
*
|
||||
@@ -93,6 +197,8 @@ if (! function_exists('meters2Miles')) {
|
||||
/**
|
||||
* Convert from meters to miles.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param float|int|string $meters
|
||||
* @param int $precision
|
||||
*
|
||||
@@ -108,6 +214,8 @@ if (! function_exists('kilometers2Miles')) {
|
||||
/**
|
||||
* Convert from kilometers to meters.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param float|int|string $kilometers
|
||||
* @param int $precision
|
||||
*
|
||||
@@ -123,6 +231,8 @@ if (! function_exists('m2Km')) {
|
||||
/**
|
||||
* Convert from meters to kilometers.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param float|int|string $meters
|
||||
* @param int $precision
|
||||
*
|
||||
@@ -138,6 +248,8 @@ if (! function_exists('mm2Inches')) {
|
||||
/**
|
||||
* Convert from milimeters to inches.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param float|int|string $milimeters
|
||||
* @param int $precision
|
||||
*
|
||||
@@ -153,6 +265,8 @@ if (! function_exists('pa2Mbar')) {
|
||||
/**
|
||||
* Convert from pascals to milibars.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param float|int|string $pascals
|
||||
* @param int $precision
|
||||
*
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,3 +1,11 @@
|
||||
.spin {
|
||||
animation: spin 1.5s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/** https://thinkdobecreate.com/articles/css-animating-newly-added-element/ **/
|
||||
|
||||
.anim-show {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@import 'tailwindcss/utilities';
|
||||
|
||||
@import 'animations.css';
|
||||
@import 'typography.css';
|
||||
@import 'fontfaces.css';
|
||||
|
||||
@import 'components/buttons.css';
|
||||
@import 'components/cards.css';
|
||||
|
||||
@@ -2,6 +2,58 @@
|
||||
/** | Sans fonts | **/
|
||||
/** +--------------------------------+ **/
|
||||
|
||||
@font-face {
|
||||
font-family: "OpenSans";
|
||||
src: url('/fonts/OpenSans/OpenSans-Regular.woff2') format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "OpenSans";
|
||||
src: url('/fonts/OpenSans/OpenSans-Italic.woff2') format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "OpenSans";
|
||||
src: url('/fonts/OpenSans/OpenSans-SemiBold.woff2') format("woff2");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "OpenSans";
|
||||
src: url('/fonts/OpenSans/OpenSans-SemiBoldItalic.woff2') format("woff2");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "OpenSans";
|
||||
src: url('/fonts/OpenSans/OpenSans-Bold.woff2') format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "OpenSans";
|
||||
src: url('/fonts/OpenSans/OpenSans-BoldItalic.woff2') format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/** +--------------------------------+ **/
|
||||
/** | Serif fonts | **/
|
||||
/** +--------------------------------+ **/
|
||||
|
||||
@font-face {
|
||||
font-family: "Nunito";
|
||||
src: url('/fonts/Nunito/Nunito-Regular.woff2') format("woff2");
|
||||
@@ -50,12 +102,6 @@
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/** +--------------------------------+ **/
|
||||
/** | Serif fonts | **/
|
||||
/** +--------------------------------+ **/
|
||||
|
||||
/**/
|
||||
|
||||
/** +--------------------------------+ **/
|
||||
/** | Monospace fonts | **/
|
||||
/** +--------------------------------+ **/
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
<script setup>
|
||||
import { reactive, computed, onBeforeMount, provide } from 'vue'
|
||||
|
||||
const emit = defineEmits(['themeUpdate'])
|
||||
|
||||
let settings = reactive({
|
||||
theme: 'light',
|
||||
})
|
||||
|
||||
const htmlNode = document.documentElement
|
||||
let mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
|
||||
// computed properties
|
||||
const isDarkMode = computed(() => {
|
||||
return settings.theme === 'dark'
|
||||
})
|
||||
|
||||
const isLightMode = computed(() => {
|
||||
return settings.theme === 'light'
|
||||
})
|
||||
|
||||
// lifecycle hooks
|
||||
onBeforeMount(() => {
|
||||
window.addEventListener('storage', update)
|
||||
|
||||
if (mediaQuery?.addEventListener) {
|
||||
mediaQuery.addEventListener('change', update)
|
||||
}
|
||||
|
||||
update()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
provide('darkMode', isDarkMode)
|
||||
})
|
||||
|
||||
// methods
|
||||
const update = () => {
|
||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
setModeDark()
|
||||
} else {
|
||||
setModeLight()
|
||||
}
|
||||
|
||||
emit('themeUpdate')
|
||||
}
|
||||
|
||||
const setModeDark = () => {
|
||||
settings.theme = 'dark'
|
||||
localStorage.theme = 'dark'
|
||||
htmlNode.classList.remove('light')
|
||||
htmlNode.classList.add('dark')
|
||||
}
|
||||
|
||||
const setModeLight = () => {
|
||||
settings.theme = 'light'
|
||||
localStorage.theme = 'light'
|
||||
htmlNode.classList.remove('dark')
|
||||
htmlNode.classList.add('light')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex items-center cursor-pointer">
|
||||
<svg v-show="isDarkMode" @click="setModeLight" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" preserveAspectRatio="xMidYMid meet">
|
||||
<circle cx="12" cy="12" r="5"></circle>
|
||||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||||
</svg>
|
||||
|
||||
<svg v-show="isLightMode" @click="setModeDark" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" preserveAspectRatio="xMidYMid meet">
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,5 +1,62 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { Link } from '@inertiajs/inertia-vue3'
|
||||
|
||||
const props = defineProps({
|
||||
paginationData: Object,
|
||||
})
|
||||
|
||||
// computed properties
|
||||
const onFirstPage = computed(() => {
|
||||
return props.paginationData.current_page === 1
|
||||
})
|
||||
|
||||
const hasMorePages = computed(() => {
|
||||
return props.paginationData.current_page < props.paginationData.last_page
|
||||
})
|
||||
|
||||
const nextPageUrl = computed(() => {
|
||||
return props.paginationData.next_page_url
|
||||
})
|
||||
|
||||
const previousPageUrl = computed(() => {
|
||||
return props.paginationData.prev_page_url
|
||||
})
|
||||
|
||||
const firstItem = computed(() => {
|
||||
if (props.paginationData.from == null) {
|
||||
return '-'
|
||||
}
|
||||
return props.paginationData.from
|
||||
})
|
||||
|
||||
const lastItem = computed(() => {
|
||||
if (props.paginationData.to == null) {
|
||||
return '-'
|
||||
}
|
||||
return props.paginationData.to
|
||||
})
|
||||
|
||||
const total = computed(() => {
|
||||
if (isNaN(props.paginationData.total)) {
|
||||
return '0'
|
||||
}
|
||||
return props.paginationData.total
|
||||
})
|
||||
|
||||
// watchers
|
||||
|
||||
// lifecycle hooks
|
||||
|
||||
// methods
|
||||
const isFirstOrLastOrDots = (index, linksLength, label) => {
|
||||
return index === 0 || index === linksLength - 1 || label.includes('...')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav v-if="pagi !== undefined" class="flex items-center justify-between" role="navigation">
|
||||
<nav v-if="paginationData !== undefined" class="flex items-center justify-between" role="navigation">
|
||||
<div class="flex justify-between flex-1 sm:hidden">
|
||||
<span v-if="onFirstPage" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-gray-100 border border-gray-300 cursor-default leading-5 rounded-md">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
@@ -45,8 +102,8 @@
|
||||
</svg>
|
||||
</Link>
|
||||
|
||||
<div v-for="(link, index) in pagi.links">
|
||||
<Link v-if="!isFirstOrLastOrDots(index, pagi.links.length, link.label)" :class="{ 'bg-blue-200' : link.active }" :href="link.url" class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 hover:text-gray-500 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150" v-html="link.label"></Link>
|
||||
<div v-for="(link, index) in paginationData.links">
|
||||
<Link v-if="!isFirstOrLastOrDots(index, paginationData.links.length, link.label)" :class="{ 'bg-blue-200' : link.active }" :href="link.url" class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 hover:text-gray-500 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150" v-html="link.label"></Link>
|
||||
<span v-else-if="link.label === '...'" aria-disabled="true" class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 cursor-default leading-5" v-html="link.label"></span>
|
||||
</div>
|
||||
|
||||
@@ -65,63 +122,3 @@
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue"
|
||||
import { Link } from "@inertiajs/inertia-vue3"
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
pagi: Object,
|
||||
},
|
||||
|
||||
components: {
|
||||
Link,
|
||||
},
|
||||
|
||||
computed: {
|
||||
onFirstPage() {
|
||||
return this.pagi.current_page === 1
|
||||
},
|
||||
|
||||
hasMorePages() {
|
||||
return this.pagi.current_page < this.pagi.last_page
|
||||
},
|
||||
|
||||
nextPageUrl() {
|
||||
return this.pagi.next_page_url
|
||||
},
|
||||
|
||||
previousPageUrl() {
|
||||
return this.pagi.prev_page_url
|
||||
},
|
||||
|
||||
firstItem() {
|
||||
if (this.pagi.from == null) {
|
||||
return '-'
|
||||
}
|
||||
return this.pagi.from
|
||||
},
|
||||
|
||||
lastItem() {
|
||||
if (this.pagi.to == null) {
|
||||
return '-'
|
||||
}
|
||||
return this.pagi.to
|
||||
},
|
||||
|
||||
total() {
|
||||
if (isNaN(this.pagi.total)) {
|
||||
return '0'
|
||||
}
|
||||
return this.pagi.total
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
isFirstOrLastOrDots(index, linksLength, label) {
|
||||
return index === 0 || index === linksLength - 1 || label.includes('...')
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
{{-- <link href="https://de.example.com/2010/06/title-of-my-article" rel="alternate" hreflang="de"> --}}
|
||||
|
||||
<!-- Android web manifest file -->
|
||||
{{-- <link href="{{ url('/.webmanifest') }}" rel="manifest"> --}}
|
||||
{{-- <link href="{{ url('/site.webmanifest') }}" rel="manifest" integrity="{{ env('INTEGRITY_HASH_WEBMANIFEST_JSON') }}"> --}}
|
||||
|
||||
<!-- Files listing who was involved in this site and copyrights -->
|
||||
<link href="{{ url('/humans.txt') }}" rel="author" integrity="{{ env('INTEGRITY_HASH_HUMANS_TXT') }}">
|
||||
@@ -63,9 +63,9 @@
|
||||
<link rel="alternate" type="text/xml+oembed" href="https://example.com/services/oembed?url=http%3A%2F%2Fexample.com%2Ffoo%2F&format=xml" title="oEmbed Profile: XML">
|
||||
|
||||
<!-- Favicon -->
|
||||
{{-- <link href="{{ asset('/favicon.ico') }}" rel="icon" sizes="16x16" type="image/icon"> --}}
|
||||
{{-- <link href="{{ asset('/favicon.svg') }}" rel="icon" type="image/svg+xml"> --}}
|
||||
{{-- <link href="{{ asset('/favicon.png') }}" rel="icon" sizes="192x192"> --}}
|
||||
{{-- <link href="{{ asset('/favicon.ico') }}" rel="icon" sizes="16x16" type="image/icon" integrity="{{ env('INTEGRITY_HASH_FAVICON_ICO') }}"> --}}
|
||||
{{-- <link href="{{ asset('/favicon.svg') }}" rel="icon" type="image/svg+xml" integrity="{{ env('INTEGRITY_HASH_FAVICON_SVG') }}"> --}}
|
||||
{{-- <link href="{{ asset('/favicon.png') }}" rel="icon" sizes="192x192" integrity="{{ env('INTEGRITY_HASH_FAVICON_PNG') }}"> --}}
|
||||
|
||||
<!-- Font preloads (should be done for each font file) -->
|
||||
<link href="{{ asset('/fonts/Nunito/Nunito-Regular.woff2') }}" rel="preload" as="font" type="font/woff2" integrity="{{ env('INTEGRITY_HASH_NUNITO_REGULAR_WOFF2_FONT') }}" crossorigin="anonymous">
|
||||
|
||||
@@ -3,9 +3,18 @@ const { exec } = require('child_process');
|
||||
|
||||
const resIntegrityFiles = [
|
||||
{ "envKey": "HUMANS_TXT", "path": "public/humans.txt" },
|
||||
{ "envKey": "ROBOTS_TXT", "path": "public/robots.txt" },
|
||||
{ "envKey": "COPYRIGHT_HTML", "path": "public/copyright.html" },
|
||||
{ "envKey": "COPYRIGHT_MD", "path": "public/copyright.md" },
|
||||
{ "envKey": "RSS_FEED", "path": "public/rss.xml" },
|
||||
{ "envKey": "ATOM_FEED", "path": "public/feed.atom" },
|
||||
{ "envKey": "FAVICON_ICO", "path": "public/favicon.ico" },
|
||||
{ "envKey": "FAVICON_SVG", "path": "public/favicon.svg" },
|
||||
{ "envKey": "FAVICON_PNG", "path": "public/favicon.png" },
|
||||
{ "envKey": "NUNITO_REGULAR_WOFF2_FONT", "path": "public/fonts/Nunito/Nunito-Regular.woff2" },
|
||||
{ "envKey": "POIRETONE_REGULAR_WOFF2_FONT", "path": "public/fonts/PoiretOne/PoiretOne-Regular.woff2" },
|
||||
{ "envKey": "WEBMANIFEST_JSON", "path": "public/site.webmanifest" },
|
||||
{ "envKey": "MIX_MANIFEST_JSON", "path": "public/mix-manifest.json" },
|
||||
{ "envKey": "APP_CSS", "path": "public/css/app.css" },
|
||||
{ "envKey": "APP_JS", "path": "public/js/app.js" },
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user