A little further ahead with the app in Alpine

This commit is contained in:
James Cole 2023-07-12 07:07:06 +02:00
parent 449058dad7
commit d943a5ae9b
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80
24 changed files with 868 additions and 453 deletions

View File

@ -47,7 +47,7 @@ return [
|
*/
'view' => 'partials/layout/breadcrumbs',
'view' => 'partials/layout/v4/breadcrumbs',
/*
|--------------------------------------------------------------------------

95
package-lock.json generated
View File

@ -6,7 +6,10 @@
"": {
"dependencies": {
"@fortawesome/fontawesome-free": "^6.4.0",
"alpinejs": "^3.12.3"
"@popperjs/core": "^2.11.8",
"alpinejs": "^3.12.3",
"bootstrap": "^5.3.0",
"date-fns": "^2.30.0"
},
"devDependencies": {
"axios": "^1.1.2",
@ -15,6 +18,17 @@
"vite": "^4.0.0"
}
},
"node_modules/@babel/runtime": {
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
"integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"dependencies": {
"regenerator-runtime": "^0.13.11"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.18.11",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz",
@ -376,6 +390,15 @@
"node": ">=6"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@vue/reactivity": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz",
@ -436,6 +459,24 @@
"node": ">=8"
}
},
"node_modules/bootstrap": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.0.tgz",
"integrity": "sha512-UnBV3E3v4STVNQdms6jSGO2CvOkjUMdDAVR2V5N4uCMdaIkaQjbcEAMqRimDHIs4uqBYzDAKCQwCB+97tJgHQw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"peerDependencies": {
"@popperjs/core": "^2.11.7"
}
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
@ -487,6 +528,21 @@
"node": ">= 0.8"
}
},
"node_modules/date-fns": {
"version": "2.30.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
"dependencies": {
"@babel/runtime": "^7.21.0"
},
"engines": {
"node": ">=0.11"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/date-fns"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@ -781,6 +837,11 @@
"node": ">=8.10.0"
}
},
"node_modules/regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"node_modules/rollup": {
"version": "3.26.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.2.tgz",
@ -905,6 +966,14 @@
}
},
"dependencies": {
"@babel/runtime": {
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
"integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"requires": {
"regenerator-runtime": "^0.13.11"
}
},
"@esbuild/android-arm": {
"version": "0.18.11",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz",
@ -1064,6 +1133,11 @@
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.0.tgz",
"integrity": "sha512-0NyytTlPJwB/BF5LtRV8rrABDbe3TdTXqNB3PdZ+UUUZAEIrdOJdmABqKjt4AXwIoJNaRVVZEXxpNrqvE1GAYQ=="
},
"@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
},
"@vue/reactivity": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz",
@ -1118,6 +1192,12 @@
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true
},
"bootstrap": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.0.tgz",
"integrity": "sha512-UnBV3E3v4STVNQdms6jSGO2CvOkjUMdDAVR2V5N4uCMdaIkaQjbcEAMqRimDHIs4uqBYzDAKCQwCB+97tJgHQw==",
"requires": {}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
@ -1152,6 +1232,14 @@
"delayed-stream": "~1.0.0"
}
},
"date-fns": {
"version": "2.30.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
"requires": {
"@babel/runtime": "^7.21.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@ -1341,6 +1429,11 @@
"picomatch": "^2.2.1"
}
},
"regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"rollup": {
"version": "3.26.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.2.tgz",

View File

@ -13,6 +13,9 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.4.0",
"alpinejs": "^3.12.3"
"@popperjs/core": "^2.11.8",
"alpinejs": "^3.12.3",
"bootstrap": "^5.3.0",
"date-fns": "^2.30.0"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@

View File

@ -24,10 +24,15 @@
"src": "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2"
},
"resources/assets/v4/app.js": {
"file": "assets/app-9ad4de64.js",
"file": "assets/app-afb3782a.js",
"isEntry": true,
"src": "resources/assets/v4/app.js"
},
"resources/assets/v4/index.js": {
"file": "assets/index-4ed993c7.js",
"isEntry": true,
"src": "resources/assets/v4/index.js"
},
"resources/assets/v4/sass/app.scss": {
"file": "assets/app-40e01f65.css",
"isEntry": true,

BIN
public/v4/i/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -18,11 +18,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {api} from "boot/axios";
import {api} from "../../boot/axios";
export default class Preferences {
getByName(name) {
return api.get('/api/v1/preferences/' + name);
async getByName(name) {
return await api.get('/api/v1/preferences/' + name);
}
postByName(name, value) {

View File

@ -1,15 +1,252 @@
import './bootstrap';
//import {onDOMContentLoaded} from "./util/index.js";
import {
addMonths,
endOfDay,
endOfMonth,
endOfQuarter,
endOfWeek,
startOfDay,
startOfMonth,
startOfQuarter,
startOfWeek,
startOfYear,
subDays, subMonths
} from "date-fns";
import format from './util/format'
class MainApp {
range = {
start: null, end: null
};
defaultRange = {
start: null, end: null
};
viewRange = '1M';
locale = 'en-US';
language = 'en-US';
constructor() {
//console.log('MainApp constructor');
// TODO load range from local storage (Apline)
}
init() {
// get values from store and use them accordingly.
this.viewRange = window.BasicStore.viewRange;
this.locale = window.BasicStore.locale;
this.language = window.BasicStore.language;
this.locale = 'equal' === this.locale ? this.language : this.locale;
window.__localeId__ = this.language;
//alert('hallo');
// the range is always null but later on we will store it in BasicStore.
if (null === this.range.start && null === this.range.end
&& null === this.defaultRange.start && null === this.defaultRange.end
) {
this.setDatesFromViewRange();
}
}
setDatesFromViewRange() {
let start;
let end;
let viewRange = this.viewRange;
// onDOMContentLoaded(() => {
// //alert('OK dan!');
// })
let today = new Date;
switch (viewRange) {
case 'last365':
start = startOfDay(subDays(today, 365));
end = endOfDay(today);
break;
case 'last90':
start = startOfDay(subDays(today, 90));
end = endOfDay(today);
break;
case 'last30':
start = startOfDay(subDays(today, 30));
end = endOfDay(today);
break;
case 'last7':
start = startOfDay(subDays(today, 7));
end = endOfDay(today);
break;
case 'YTD':
start = startOfYear(today);
end = endOfDay(today);
break;
case 'QTD':
start = startOfQuarter(today);
end = endOfDay(today);
break;
case 'MTD':
start = startOfMonth(today);
end = endOfDay(today);
break;
case '1D':
// today:
start = startOfDay(today);
end = endOfDay(today);
break;
case '1W':
// this week:
start = startOfDay(startOfWeek(today, {weekStartsOn: 1}));
end = endOfDay(endOfWeek(today, {weekStartsOn: 1}));
break;
case '1M':
// this month:
start = startOfDay(startOfMonth(today));
end = endOfDay(endOfMonth(today));
break;
case '3M':
// this quarter
start = startOfDay(startOfQuarter(today));
end = endOfDay(endOfQuarter(today));
break;
case '6M':
// this half-year
if (today.getMonth() <= 5) {
start = new Date(today);
start.setMonth(0);
start.setDate(1);
start = startOfDay(start);
end = new Date(today);
end.setMonth(5);
end.setDate(30);
end = endOfDay(start);
}
if (today.getMonth() > 5) {
start = new Date(today);
start.setMonth(6);
start.setDate(1);
start = startOfDay(start);
end = new Date(today);
end.setMonth(11);
end.setDate(31);
end = endOfDay(start);
}
break;
case '1Y':
// this year
start = new Date(today);
start.setMonth(0);
start.setDate(1);
start = startOfDay(start);
end = new Date(today);
end.setMonth(11);
end.setDate(31);
end = endOfDay(end);
break;
}
this.range = {start: start, end: end};
this.defaultRange = {start: start, end: end};
}
//alert('OK dan 2!');
buildDateRange() {
// generate ranges
let nextRange = this.getNextRange();
let prevRange = this.getPrevRange();
let last7 = this.lastDays(7);
let last30 = this.lastDays(30);
let mtd = this.mtd();
let ytd = this.ytd();
// set the title:
let element = document.getElementsByClassName('daterange-holder')[0];
element.textContent = format(this.range.start) + ' - ' + format(this.range.end);
element.setAttribute('data-start', format(this.range.start, 'yyyy-MM-dd'));
element.setAttribute('data-end', format(this.range.end, 'yyyy-MM-dd'));
// set the current one
element = document.getElementsByClassName('daterange-current')[0];
element.textContent = format(this.range.start) + ' - ' + format(this.range.end);
element.setAttribute('data-start', format(this.range.start, 'yyyy-MM-dd'));
element.setAttribute('data-end', format(this.range.end, 'yyyy-MM-dd'));
// generate next range
element = document.getElementsByClassName('daterange-next')[0];
element.textContent = format(nextRange.start) + ' - ' + format(nextRange.end);
element.setAttribute('data-start', format(nextRange.start, 'yyyy-MM-dd'));
element.setAttribute('data-end', format(nextRange.end, 'yyyy-MM-dd'));
// previous range.
element = document.getElementsByClassName('daterange-prev')[0];
element.textContent = format(prevRange.start) + ' - ' + format(prevRange.end);
element.setAttribute('data-start', format(prevRange.start, 'yyyy-MM-dd'));
element.setAttribute('data-end', format(prevRange.end, 'yyyy-MM-dd'));
// last 7
element = document.getElementsByClassName('daterange-7d')[0];
element.setAttribute('data-start', format(last7.start, 'yyyy-MM-dd'));
element.setAttribute('data-end', format(last7.end, 'yyyy-MM-dd'));
// last 30
element = document.getElementsByClassName('daterange-90d')[0];
element.setAttribute('data-start', format(last30.start, 'yyyy-MM-dd'));
element.setAttribute('data-end', format(last30.end, 'yyyy-MM-dd'));
// MTD
element = document.getElementsByClassName('daterange-mtd')[0];
element.setAttribute('data-start', format(mtd.start, 'yyyy-MM-dd'));
element.setAttribute('data-end', format(mtd.end, 'yyyy-MM-dd'));
// YTD
element = document.getElementsByClassName('daterange-ytd')[0];
element.setAttribute('data-start', format(ytd.start, 'yyyy-MM-dd'));
element.setAttribute('data-end', format(ytd.end, 'yyyy-MM-dd'));
// custom range.
}
getNextRange() {
let nextMonth = addMonths(this.range.start, 1);
let end = endOfMonth(nextMonth);
return {start: nextMonth, end: end};
}
getPrevRange() {
let prevMonth = subMonths(this.range.start, 1);
let end = endOfMonth(prevMonth);
return {start: prevMonth, end: end};
}
ytd() {
let end = this.range.start;
let start = startOfYear(this.range.start);
return {start: start, end: end};
}
mtd() {
let end = this.range.start;
let start = startOfMonth(this.range.start);
return {start: start, end: end};
}
lastDays(days) {
let end = this.range.start;
let start = subDays(end, days);
return {start: start, end: end};
}
}
let app = new MainApp();
// Listen for the basic store, we need it to continue with the
document.addEventListener(
"BasicStoreReady",
(e) => {
// e.target matches elem
app.init();
app.buildDateRange();
},
false,
);
function handleClick(e) {
console.log('here we are');
e.preventDefault();
alert('OK');
return false;
}
export {app, handleClick};

View File

@ -0,0 +1,40 @@
/*
* axios.js
* Copyright (c) 2022 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import axios from 'axios'
// Be careful when using SSR for cross-request state pollution
// due to creating a Singleton instance here;
// If any client changes this (global) instance, it might be a
// good idea to move this instance creation inside of the
// "export default () => {}" function below (which runs individually
// for each client)
// for use inside Vue files (Options API) through this.$axios and this.$api
const url = '/';
const api = axios.create({baseURL: url, withCredentials: true});
axios.defaults.withCredentials = true;
axios.defaults.baseURL = url;
export {api}

View File

@ -11,6 +11,12 @@ import BasicStore from './store/Basic';
window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
// include popper js
import '@popperjs/core';
// include bootstrap
import * as bootstrap from 'bootstrap'
/**
* Echo exposes an expressive API for subscribing to channels and listening
* for events that are broadcast by Laravel. Echo and event broadcasting
@ -34,12 +40,9 @@ window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
// });
window.Alpine = Alpine
Alpine.start()
window.BasicStore = new BasicStore;
window.BasicStore.init();

View File

@ -0,0 +1,15 @@
//import './bootstrap';
//import {onDOMContentLoaded} from "./util/index.js";
// alert('hallo');
// onDOMContentLoaded(() => {
// //alert('OK dan!');
// })
//alert('OK dan 2!');

View File

@ -1,41 +1,53 @@
// basic store for preferred date range and some other vars.
// used in layout.
import Get from '../api/preferences/index.js';
class Basic {
viewRange = '1M';
darkMode = 'browser';
listPageSize = 10;
locale = 'en-US';
range = {
start: null, end: null
};
language = 'en-US';
currencyCode = 'AAA';
currencyId = '0';
ready = false;
count = 0;
readyCount = 4;
constructor() {
}
init() {
console.log('init');
// load variables from window if present
this.loadVariable('viewRange')
this.loadVariable('darkMode')
this.loadVariable('language')
this.loadVariable('locale')
}
loadVariable(name) {
console.log('loadVariable(' + name + ')');
if(window.hasOwnProperty(name)) {
console.log('from windows');
if (window.hasOwnProperty(name)) {
this[name] = window[name];
return;
}
// load from local storage
if(window.Alpine.store(name)) {
console.log('from alpine');
if (window.Alpine.store(name)) {
this[name] = window.Alpine.store(name);
return;
}
// grab using axios
console.log('axios');
// grab
let getter = (new Get);
getter.getByName(name).then((response) => this.parseResponse(name, response));
}
parseResponse(name, response) {
this.count++;
let value = response.data.data.attributes.data;
this[name] = value;
if (this.count === this.readyCount) {
// trigger event:
const event = new Event("BasicStoreReady");
document.dispatchEvent(event);
}
}
}

View File

@ -0,0 +1,99 @@
/*
* format.js
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {format} from 'date-fns'
import {
bg,
cs,
da,
de,
el,
enGB,
enUS,
es,
ca,
fi,
fr,
hu,
id,
it,
ja,
ko,
nb,
nn,
nl,
pl,
ptBR,
pt,
ro,
ru,
sk,
sl,
sv,
tr,
uk,
vi,
zhTW,
zhCN
} from 'date-fns/locale'
const locales = {
bg,
cs,
da,
de,
el,
enGB,
enUS,
es,
ca,
fi,
fr,
hu,
id,
it,
ja,
ko,
nb,
nn,
nl,
pl,
ptBR,
pt,
ro,
ru,
sk,
sl,
sv,
tr,
uk,
vi,
zhTW,
zhCN
}
// by providing a default string of 'PP' or any of its variants for `formatStr`
// it will format dates in whichever way is appropriate to the locale
export default function (date, formatStr = 'PP') {
let locale = window.__localeId__.replace('_', '');
return format(date, formatStr, {
locale: locales[locale] ?? locales[locale.slice(0, 2)] ?? locales['enUS'] // or global.__localeId__
})
}

View File

@ -1356,6 +1356,7 @@ return [
// Financial administrations
'administration_index' => 'Financial administration',
'administrations_index_menu' => 'Financial administration(s)',
// profile:
'purge_data_title' => 'Purge data from Firefly III',
@ -2290,6 +2291,7 @@ return [
'invite_user' => 'Invite user',
'user_is_invited' => 'Email address ":address" was invited to Firefly III',
'administration' => 'Administration',
'system_settings' => 'System settings',
'code_already_used' => 'Invite code has been used',
'user_administration' => 'User administration',
'list_all_users' => 'All users',

View File

@ -1,4 +1,7 @@
@extends('layout.v4.default')
@section('vite')
@vite(['resources/assets/v4/index.js'])
@endsection
@section('content')
<div class="app-content">
@ -11,6 +14,7 @@
<button x-on:click="count++">Increment</button>
<span x-text="count"></span>
<button x-on:click="handleClick">KLIK</button>
</div>
</div>

View File

@ -16,13 +16,13 @@
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" data-lte-toggle="sidebar" href="#" role="button">
<i class="bi bi-list"></i>
<em class="fa-solid fa-bars"></em>
</a>
</li>
<!--begin::Navbar Search-->
<li class="nav-item">
<a class="nav-link" data-widget="navbar-search" href="#" role="button">
<i class="bi bi-search"></i>
<em class="fa-solid fa-magnifying-glass"></em>
</a>
</li>
<!--end::Navbar Search-->
@ -32,19 +32,40 @@
<!--begin::End Navbar Links-->
<ul class="navbar-nav ms-auto">
<!-- begin date range drop down -->
<li class="nav-item dropdown">
<a class="nav-link" data-bs-toggle="dropdown" href="#">
(date range hier)
</a>
<a class="nav-link daterange-holder" data-bs-toggle="dropdown" href="#"></a>
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-end">
<a href="#" class="dropdown-item">
time and date range hier
<a href="#" class="dropdown-item daterange-current" @click="handleClick">
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item dropdown-footer">
Eind
<a href="#" @click="handleClick" class="dropdown-item daterange-next">
next
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item daterange-prev">
prev
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item daterange-7d">
{{ __('firefly.last_seven_days') }}
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item daterange-90d">
{{ __('firefly.last_thirty_days') }}
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item daterange-mtd">
{{ __('firefly.month_to_date') }}
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item daterange-ytd">
{{ __('firefly.year_to_date') }}
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item dropdown-footer daterange-custom">
{{ __('firefly.customRange') }}
</a>
</div>
</li>
@ -54,29 +75,24 @@
<!--begin::Notifications Dropdown Menu-->
<li class="nav-item dropdown">
<a class="nav-link" data-bs-toggle="dropdown" href="#">
<i class="bi bi-bell-fill"></i>
<span class="navbar-badge badge text-bg-warning">15</span>
<i class="fa-solid fa-user"></i>
</a>
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-end">
<span class="dropdown-item dropdown-header">15 Notifications</span>
<span class="dropdown-item dropdown-header">{{ auth()->user()->email }}</span>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item">
<i class="bi bi-envelope me-2"></i> 4 new messages
<span class="float-end text-secondary fs-7">3 mins</span>
<a href="{{ route('profile.index') }}" class="dropdown-item">
<em class="fa-regular fa-user me-2"></em>
{{ __('firefly.profile') }}
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item">
<i class="bi bi-people-fill me-2"></i> 8 friend requests
<span class="float-end text-secondary fs-7">12 hours</span>
<i class="fa-solid fa-user-gear me-2"></i>
{{ __('firefly.preferences') }}
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item">
<i class="bi bi-file-earmark-fill me-2"></i> 3 new reports
<span class="float-end text-secondary fs-7">2 days</span>
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item dropdown-footer">
See All Notifications
<i class="fa-solid fa-money-bill-transfer me-2"></i>
TODO {{ __('firefly.administrations_index_menu') }}
</a>
</div>
</li>
@ -88,374 +104,7 @@
</nav>
<!--end::Header-->
<!--begin::Sidebar-->
<aside class="app-sidebar bg-body-secondary shadow" data-bs-theme="dark">
<!--begin::Sidebar Brand-->
<div class="sidebar-brand">
<!--begin::Brand Link-->
<a href="./index.html" class="brand-link">
<!--begin::Brand Image-->
<img src="../../dist/assets/img/AdminLTELogo.png" alt="AdminLTE Logo"
class="brand-image opacity-75 shadow">
<!--end::Brand Image-->
<!--begin::Brand Text-->
<span class="brand-text fw-light">AdminLTE 4</span>
<!--end::Brand Text-->
</a>
<!--end::Brand Link-->
</div>
<!--end::Sidebar Brand-->
<!--begin::Sidebar Wrapper-->
<div class="sidebar-wrapper">
<nav class="mt-2">
<!--begin::Sidebar Menu-->
<ul class="nav sidebar-menu flex-column" data-lte-toggle="treeview" role="menu"
data-accordion="false">
<li class="nav-item menu-open">
<a href="#" class="nav-link active">
<i class="nav-icon bi bi-speedometer"></i>
<p>
Dashboard
<i class="nav-arrow bi bi-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="./index.html" class="nav-link active">
<i class="nav-icon bi bi-circle"></i>
<p>Dashboard v1</p>
</a>
</li>
<li class="nav-item">
<a href="./index2.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Dashboard v2</p>
</a>
</li>
<li class="nav-item">
<a href="./index3.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Dashboard v3</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-box-seam-fill"></i>
<p>
Widgets
<i class="nav-arrow bi bi-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="./widgets/small-box.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Small Box</p>
</a>
</li>
<li class="nav-item">
<a href="./widgets/info-box.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>info Box</p>
</a>
</li>
<li class="nav-item">
<a href="./widgets/cards.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Cards</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-clipboard-fill"></i>
<p>
Layout Options
<span class="nav-badge badge text-bg-secondary me-3">6</span>
<i class="nav-arrow bi bi-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="./layout/unfixed-sidebar.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Default Sidebar</p>
</a>
</li>
<li class="nav-item">
<a href="./layout/fixed-sidebar.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Fixed Sidebar</p>
</a>
</li>
<li class="nav-item">
<a href="./layout/fixed-complete.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Fixed Complete</p>
</a>
</li>
<li class="nav-item">
<a href="./layout/sidebar-mini.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Sidebar Mini</p>
</a>
</li>
<li class="nav-item">
<a href="./layout/collapsed-sidebar.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Sidebar Mini <small>+ Collapsed</small></p>
</a>
</li>
<li class="nav-item">
<a href="./layout/logo-switch.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Sidebar Mini <small>+ Logo Switch</small></p>
</a>
</li>
<li class="nav-item">
<a href="./layout/layout-rtl.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Layout RTL</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-tree-fill"></i>
<p>
UI Elements
<i class="nav-arrow bi bi-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="./UI/timeline.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Timeline</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-pencil-square"></i>
<p>
Forms
<i class="nav-arrow bi bi-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="./forms/general.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>General Elements</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-table"></i>
<p>
Tables
<i class="nav-arrow bi bi-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="./tables/simple.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Simple Tables</p>
</a>
</li>
</ul>
</li>
<li class="nav-header">EXAMPLES</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-box-arrow-in-right"></i>
<p>
Login & Register
<i class="nav-arrow bi bi-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="./examples/login.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Login v1</p>
</a>
</li>
<li class="nav-item">
<a href="./examples/register.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Register v1</p>
</a>
</li>
</ul>
</li>
<li class="nav-header">DOCUMENTATIONS</li>
<li class="nav-item">
<a href="./docs/introduction.html" class="nav-link">
<i class="nav-icon bi bi-download"></i>
<p>Installation</p>
</a>
</li>
<li class="nav-item">
<a href="./docs/layout.html" class="nav-link">
<i class="nav-icon bi bi-grip-horizontal"></i>
<p>Layout</p>
</a>
</li>
<li class="nav-item">
<a href="./docs/color-mode.html" class="nav-link">
<i class="nav-icon bi bi-star-half"></i>
<p>Color Mode</p>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-palette2"></i>
<p>
Components
<i class="nav-arrow bi bi-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="./docs/components/main-header.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Main Header</p>
</a>
</li>
<li class="nav-item">
<a href="./docs/components/main-sidebar.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Main Sidebar</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-palette2"></i>
<p>
Javascript
<i class="nav-arrow bi bi-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="./docs/javascript/treeview.html" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Treeview</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="./docs/browser-support.html" class="nav-link">
<i class="nav-icon bi bi-browser-edge"></i>
<p>Browser Support</p>
</a>
</li>
<li class="nav-header">MULTI LEVEL EXAMPLE</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-circle-fill"></i>
<p>Level 1</p>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-circle-fill"></i>
<p>
Level 1
<i class="nav-arrow bi bi-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Level 2</p>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>
Level 2
<i class="nav-arrow bi bi-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-record-circle-fill"></i>
<p>Level 3</p>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-record-circle-fill"></i>
<p>Level 3</p>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-record-circle-fill"></i>
<p>Level 3</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>Level 2</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-circle-fill"></i>
<p>Level 1</p>
</a>
</li>
<li class="nav-header">LABELS</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-circle text-danger"></i>
<p class="text">Important</p>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-circle text-warning"></i>
<p>Warning</p>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon bi bi-circle text-info"></i>
<p>Informational</p>
</a>
</li>
</ul>
<!--end::Sidebar Menu-->
</nav>
</div>
<!--end::Sidebar Wrapper-->
</aside>
@include('partials.layout.v4.sidebar')
<!--end::Sidebar-->
<!--begin::App Main-->
<main class="app-main">
@ -466,15 +115,18 @@
<!--begin::Row-->
<div class="row">
<div class="col-sm-6">
<h3 class="mb-0">Dashboard</h3>
<h3 class="mb-0">
@if($mainTitleIcon)
<em class="fa {{ $mainTitleIcon }}"></em>
@endif
{{ $title }} @if($subTitle)
<small class="text-muted">
{{$subTitle}}</small>
@endif</h3>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-end">
<li class="breadcrumb-item"><a href="#">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">
Dashboard
</li>
</ol>
<!-- find me -->
{{ Breadcrumbs::render('home') }}
</div>
</div>
<!--end::Row-->

View File

@ -0,0 +1,11 @@
@if(count($breadcrumbs) > 0)
<ol class="breadcrumb float-sm-end">
@foreach ($breadcrumbs as $bc)
@if($bc->url and !$loop->last)
<li><a href="{{ $bc->url }}">{{ $bc->title }}</a></li>
@else
<li class="active">{{ $bc->title }}</li>
@endif
@endforeach
</ol>
@endif

View File

@ -1,12 +1,11 @@
<footer class="app-footer">
<!--begin::To the end-->
<div class="float-end d-none d-sm-inline">Anything you want</div>
<div class="float-end d-none d-sm-inline">
v<a href="{{ route('debug') }}">{{ $FF_VERSION }}</a>
</div>
<!--end::To the end-->
<!--begin::Copyright-->
<strong>
Copyright &copy; 2014-2023
<a href="https://adminlte.io">AdminLTE.io</a>.
</strong>
All rights reserved.
<a href="https://github.com/firefly-iii/firefly-iii/">Firefly III</a> &copy; James Cole,
<a href="https://github.com/firefly-iii/firefly-iii/blob/main/LICENSE">AGPL-3.0-or-later</a>
<!--end::Copyright-->
</footer>

View File

@ -23,12 +23,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--begin::Fonts-->
{{--
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,300;0,400;0,700;1,400&display=swap"
rel="stylesheet">
--}}
<link href="v4/css/fonts.css" rel="stylesheet">
<!--end::Fonts-->
@ -49,5 +43,6 @@
<!--end::Required Plugin(AdminLTE)-->
@vite(['resources/assets/v4/sass/app.scss', 'resources/assets/v4/app.js'])
@yield('vite')
</head>

View File

@ -1,12 +1,16 @@
<!--begin::Required Plugin(popperjs for Bootstrap 5)-->
{{--
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.7/dist/umd/popper.min.js"
integrity="sha384-zYPOMqeu1DAVkHiLqWBUTcbYfZ8osu1Nd6Z89ify25QV9guujx43ITvfi12/QExE"
crossorigin="anonymous"></script>
--}}
<!--end::Required Plugin(popperjs for Bootstrap 5)-->
<!--begin::Required Plugin(Bootstrap 5)-->
{{--
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.min.js"
integrity="sha384-Y4oOpwW3duJdCWv5ly8SCFYWqFDsfob/3GkgExXKV4idmbt98QcxXYs9UoXAB7BZ"
crossorigin="anonymous"></script>
--}}
<!--end::Required Plugin(Bootstrap 5)--><!--begin::Required Plugin(AdminLTE)-->
<script src="v4/js/adminlte.js"></script>
<!--end::Required Plugin(AdminLTE)-->

View File

@ -0,0 +1,232 @@
<aside class="app-sidebar bg-body-secondary shadow" data-bs-theme="dark">
<!--begin::Sidebar Brand-->
<div class="sidebar-brand">
<!--begin::Brand Link-->
<a href="{{route('index') }}" class="brand-link">
<!--begin::Brand Image-->
<img src="v4/i/logo.png" alt="Firefly III Logo"
class="brand-image opacity-75 shadow">
<!--end::Brand Image-->
<!--begin::Brand Text-->
<span class="brand-text fw-light">Firefly III</span>
<!--end::Brand Text-->
</a>
<!--end::Brand Link-->
</div>
<!--end::Sidebar Brand-->
<!--begin::Sidebar Wrapper-->
<div class="sidebar-wrapper">
<nav class="mt-2">
<!--begin::Sidebar Menu-->
<ul class="nav sidebar-menu flex-column" data-lte-toggle="treeview" role="menu"
data-accordion="false">
<li class="nav-item menu-open">
<a href="#" class="nav-link active">
<em class="nav-icon fa-solid fa-gauge-high"></em>
<p>
{{ __('firefly.dashboard') }}
</p>
</a>
</li>
<li class="nav-header">{{ strtoupper(__('firefly.financial_control')) }}</li>
<li class="nav-item">
<a href="{{ route('budgets.index') }}" class="nav-link">
<em class="nav-icon fa-solid fa-chart-pie"></em>
<p>{{ __('firefly.budgets') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('bills.index') }}" class="nav-link">
<i class="nav-icon fa-regular fa-calendar"></i>
<p>{{ __('firefly.bills') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('piggy-banks.index') }}" class="nav-link">
<em class="nav-icon fa-solid fa-bullseye"></em>
<p>{{ __('firefly.piggy_banks') }}</p>
</a>
</li>
<li class="nav-header">{{ strtoupper(__('firefly.accounting')) }}</li>
<li class="nav-item">
<a href="#" class="nav-link">
<em class="nav-icon fa-solid fa-arrow-right-arrow-left"></em>
<p>
{{ __('firefly.transactions') }}
<i class="nav-arrow fa-solid fa-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="{{ route('transactions.index',['withdrawal']) }}" class="nav-link">
<em class="nav-icon fa-solid fa-arrow-left"></em>
<p>{{ __('firefly.expenses') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('transactions.index', ['deposit']) }}" class="nav-link">
<em class="nav-icon fa-solid fa-arrow-right"></em>
<p>{{ __('firefly.income') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('transactions.index', ['transfers']) }}" class="nav-link">
<i class="nav-icon fa-solid fa-arrows-rotate"></i>
<p>{{ __('firefly.transfers') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('transactions.index', ['all']) }}" class="nav-link">
<i class="nav-icon fa-solid fa-arrows-turn-to-dots"></i>
<p>{{ __('firefly.all_transactions') }}</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon fa-solid fa-microchip"></i>
<p>
{{ __('firefly.automation') }}
<i class="nav-arrow fa-solid fa-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="{{ route('rules.index') }}" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>{{ __('firefly.rules') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('recurring.index') }}" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>{{ __('firefly.recurrences') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('webhooks.index') }}" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>{{ __('firefly.webhooks') }}</p>
</a>
</li>
</ul>
</li>
<li class="nav-header">{{ strtoupper(__('firefly.others')) }}</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon fa-regular fa-credit-card"></i>
<p>
{{ __('firefly.accounts') }}
<i class="nav-arrow fa-solid fa-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="{{ route('accounts.index', ['asset']) }}" class="nav-link">
<i class="nav-icon fa-solid fa-money-bills"></i>
<p>{{ __('firefly.asset_accounts') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('accounts.index', ['expense']) }}" class="nav-link">
<i class="nav-icon fa-solid fa-cart-shopping"></i>
<p>{{ __('firefly.expense_accounts') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('accounts.index', ['revenue']) }}" class="nav-link">
<i class="nav-icon fa-solid fa-money-bill-trend-up"></i>
<p>{{ __('firefly.revenue_accounts') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('accounts.index', ['liabilities']) }}" class="nav-link">
<i class="nav-icon fa-solid fa-landmark"></i>
<p>{{ __('firefly.liabilities') }}</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon fa-solid fa-tags"></i>
<p>
{{ __('firefly.classification') }}
<i class="nav-arrow fa-solid fa-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="{{ route('categories.index') }}" class="nav-link">
<i class="nav-icon fa-regular fa-bookmark"></i>
<p>{{ __('firefly.categories') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('tags.index') }}" class="nav-link">
<i class="nav-icon fa-solid fa-tag"></i>
<p>{{ __('firefly.tags') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('object-groups.index') }}" class="nav-link">
<i class="nav-icon fa-regular fa-envelope"></i>
<p>{{ __('firefly.object_groups') }}</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="{{ route('reports.index') }}" class="nav-link">
<i class="nav-icon fa-solid fa-chart-column"></i>
<p>{{ __('firefly.reports') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('export.index') }}" class="nav-link">
<i class="nav-icon fa-solid fa-upload"></i>
<p>{{ __('firefly.export_data_menu') }}</p>
</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon fa-solid fa-sliders"></i>
<p>
{{ __('firefly.options') }}
<i class="nav-arrow fa-solid fa-chevron-right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="{{ route('currencies.index') }}" class="nav-link">
<i class="nav-icon fa-solid fa-euro-sign"></i>
<p>{{ __('firefly.currencies') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('admin.index') }}" class="nav-link">
<i class="nav-icon bi bi-circle"></i>
<p>{{ __('firefly.system_settings') }}</p>
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="{{ route('logout') }}" class="nav-link logout-link">
<i class="nav-icon fa-solid fa-arrow-right-from-bracket"></i>
<p>TODO {{ __('firefly.logout') }}</p>
</a>
</li>
</ul>
<!--end::Sidebar Menu-->
</nav>
</div>
<!--end::Sidebar Wrapper-->
</aside>
<!-- simple script for logout thing -->

View File

@ -10,7 +10,11 @@ const host = 'firefly.sd.local';
export default defineConfig({
plugins: [
laravel({
input: ['resources/assets/v4/sass/app.scss', 'resources/assets/v4/app.js'],
input: [
'resources/assets/v4/sass/app.scss',
'resources/assets/v4/app.js',
'resources/assets/v4/index.js'
],
refresh: true,
}),