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
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": { "dependencies": {
"@fortawesome/fontawesome-free": "^6.4.0", "@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": { "devDependencies": {
"axios": "^1.1.2", "axios": "^1.1.2",
@@ -15,6 +18,17 @@
"vite": "^4.0.0" "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": { "node_modules/@esbuild/android-arm": {
"version": "0.18.11", "version": "0.18.11",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz",
@@ -376,6 +390,15 @@
"node": ">=6" "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": { "node_modules/@vue/reactivity": {
"version": "3.1.5", "version": "3.1.5",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz",
@@ -436,6 +459,24 @@
"node": ">=8" "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": { "node_modules/braces": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
@@ -487,6 +528,21 @@
"node": ">= 0.8" "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": { "node_modules/delayed-stream": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -781,6 +837,11 @@
"node": ">=8.10.0" "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": { "node_modules/rollup": {
"version": "3.26.2", "version": "3.26.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.2.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.2.tgz",
@@ -905,6 +966,14 @@
} }
}, },
"dependencies": { "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": { "@esbuild/android-arm": {
"version": "0.18.11", "version": "0.18.11",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz", "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", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.0.tgz",
"integrity": "sha512-0NyytTlPJwB/BF5LtRV8rrABDbe3TdTXqNB3PdZ+UUUZAEIrdOJdmABqKjt4AXwIoJNaRVVZEXxpNrqvE1GAYQ==" "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": { "@vue/reactivity": {
"version": "3.1.5", "version": "3.1.5",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz",
@@ -1118,6 +1192,12 @@
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true "dev": true
}, },
"bootstrap": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.0.tgz",
"integrity": "sha512-UnBV3E3v4STVNQdms6jSGO2CvOkjUMdDAVR2V5N4uCMdaIkaQjbcEAMqRimDHIs4uqBYzDAKCQwCB+97tJgHQw==",
"requires": {}
},
"braces": { "braces": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
@@ -1152,6 +1232,14 @@
"delayed-stream": "~1.0.0" "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": { "delayed-stream": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -1341,6 +1429,11 @@
"picomatch": "^2.2.1" "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": { "rollup": {
"version": "3.26.2", "version": "3.26.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.2.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.2.tgz",

View File

@@ -13,6 +13,9 @@
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^6.4.0", "@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" "src": "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2"
}, },
"resources/assets/v4/app.js": { "resources/assets/v4/app.js": {
"file": "assets/app-9ad4de64.js", "file": "assets/app-afb3782a.js",
"isEntry": true, "isEntry": true,
"src": "resources/assets/v4/app.js" "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": { "resources/assets/v4/sass/app.scss": {
"file": "assets/app-40e01f65.css", "file": "assets/app-40e01f65.css",
"isEntry": true, "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/>. * 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 { export default class Preferences {
getByName(name) { async getByName(name) {
return api.get('/api/v1/preferences/' + name); return await api.get('/api/v1/preferences/' + name);
} }
postByName(name, value) { postByName(name, value) {

View File

@@ -1,15 +1,252 @@
import './bootstrap'; 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(() => { let today = new Date;
// //alert('OK dan!'); 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 = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 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 * Echo exposes an expressive API for subscribing to channels and listening
* for events that are broadcast by Laravel. Echo and event broadcasting * 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 window.Alpine = Alpine
Alpine.start() Alpine.start()
window.BasicStore = new BasicStore; window.BasicStore = new BasicStore;
window.BasicStore.init(); 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. // basic store for preferred date range and some other vars.
// used in layout. // used in layout.
import Get from '../api/preferences/index.js';
class Basic { class Basic {
viewRange = '1M'; viewRange = '1M';
darkMode = 'browser'; darkMode = 'browser';
listPageSize = 10; listPageSize = 10;
locale = 'en-US'; locale = 'en-US';
range = { language = 'en-US';
start: null, end: null
};
currencyCode = 'AAA'; currencyCode = 'AAA';
currencyId = '0'; currencyId = '0';
ready = false;
count = 0;
readyCount = 4;
constructor() { constructor() {
} }
init() { init() {
console.log('init');
// load variables from window if present
this.loadVariable('viewRange') this.loadVariable('viewRange')
this.loadVariable('darkMode')
this.loadVariable('language')
this.loadVariable('locale')
} }
loadVariable(name) { loadVariable(name) {
console.log('loadVariable(' + name + ')');
if (window.hasOwnProperty(name)) { if (window.hasOwnProperty(name)) {
console.log('from windows');
this[name] = window[name]; this[name] = window[name];
return; return;
} }
// load from local storage // load from local storage
if (window.Alpine.store(name)) { if (window.Alpine.store(name)) {
console.log('from alpine');
this[name] = window.Alpine.store(name); this[name] = window.Alpine.store(name);
return; return;
} }
// grab using axios // grab
console.log('axios'); 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 // Financial administrations
'administration_index' => 'Financial administration', 'administration_index' => 'Financial administration',
'administrations_index_menu' => 'Financial administration(s)',
// profile: // profile:
'purge_data_title' => 'Purge data from Firefly III', 'purge_data_title' => 'Purge data from Firefly III',
@@ -2290,6 +2291,7 @@ return [
'invite_user' => 'Invite user', 'invite_user' => 'Invite user',
'user_is_invited' => 'Email address ":address" was invited to Firefly III', 'user_is_invited' => 'Email address ":address" was invited to Firefly III',
'administration' => 'Administration', 'administration' => 'Administration',
'system_settings' => 'System settings',
'code_already_used' => 'Invite code has been used', 'code_already_used' => 'Invite code has been used',
'user_administration' => 'User administration', 'user_administration' => 'User administration',
'list_all_users' => 'All users', 'list_all_users' => 'All users',

View File

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

View File

@@ -16,13 +16,13 @@
<ul class="navbar-nav"> <ul class="navbar-nav">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-lte-toggle="sidebar" href="#" role="button"> <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> </a>
</li> </li>
<!--begin::Navbar Search--> <!--begin::Navbar Search-->
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-widget="navbar-search" href="#" role="button"> <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> </a>
</li> </li>
<!--end::Navbar Search--> <!--end::Navbar Search-->
@@ -32,19 +32,40 @@
<!--begin::End Navbar Links--> <!--begin::End Navbar Links-->
<ul class="navbar-nav ms-auto"> <ul class="navbar-nav ms-auto">
<!-- begin date range drop down --> <!-- begin date range drop down -->
<li class="nav-item dropdown"> <li class="nav-item dropdown">
<a class="nav-link" data-bs-toggle="dropdown" href="#"> <a class="nav-link daterange-holder" data-bs-toggle="dropdown" href="#"></a>
(date range hier)
</a>
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-end"> <div class="dropdown-menu dropdown-menu-lg dropdown-menu-end">
<a href="#" class="dropdown-item"> <a href="#" class="dropdown-item daterange-current" @click="handleClick">
time and date range hier
</a> </a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a href="#" class="dropdown-item dropdown-footer"> <a href="#" @click="handleClick" class="dropdown-item daterange-next">
Eind 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> </a>
</div> </div>
</li> </li>
@@ -54,29 +75,24 @@
<!--begin::Notifications Dropdown Menu--> <!--begin::Notifications Dropdown Menu-->
<li class="nav-item dropdown"> <li class="nav-item dropdown">
<a class="nav-link" data-bs-toggle="dropdown" href="#"> <a class="nav-link" data-bs-toggle="dropdown" href="#">
<i class="bi bi-bell-fill"></i> <i class="fa-solid fa-user"></i>
<span class="navbar-badge badge text-bg-warning">15</span>
</a> </a>
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-end"> <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> <div class="dropdown-divider"></div>
<a href="#" class="dropdown-item"> <a href="{{ route('profile.index') }}" class="dropdown-item">
<i class="bi bi-envelope me-2"></i> 4 new messages <em class="fa-regular fa-user me-2"></em>
<span class="float-end text-secondary fs-7">3 mins</span> {{ __('firefly.profile') }}
</a> </a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a href="#" class="dropdown-item"> <a href="#" class="dropdown-item">
<i class="bi bi-people-fill me-2"></i> 8 friend requests <i class="fa-solid fa-user-gear me-2"></i>
<span class="float-end text-secondary fs-7">12 hours</span> {{ __('firefly.preferences') }}
</a> </a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a href="#" class="dropdown-item"> <a href="#" class="dropdown-item">
<i class="bi bi-file-earmark-fill me-2"></i> 3 new reports <i class="fa-solid fa-money-bill-transfer me-2"></i>
<span class="float-end text-secondary fs-7">2 days</span> TODO {{ __('firefly.administrations_index_menu') }}
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item dropdown-footer">
See All Notifications
</a> </a>
</div> </div>
</li> </li>
@@ -88,374 +104,7 @@
</nav> </nav>
<!--end::Header--> <!--end::Header-->
<!--begin::Sidebar--> <!--begin::Sidebar-->
<aside class="app-sidebar bg-body-secondary shadow" data-bs-theme="dark"> @include('partials.layout.v4.sidebar')
<!--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>
<!--end::Sidebar--> <!--end::Sidebar-->
<!--begin::App Main--> <!--begin::App Main-->
<main class="app-main"> <main class="app-main">
@@ -466,15 +115,18 @@
<!--begin::Row--> <!--begin::Row-->
<div class="row"> <div class="row">
<div class="col-sm-6"> <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>
<div class="col-sm-6"> <div class="col-sm-6">
<ol class="breadcrumb float-sm-end"> <!-- find me -->
<li class="breadcrumb-item"><a href="#">Home</a></li> {{ Breadcrumbs::render('home') }}
<li class="breadcrumb-item active" aria-current="page">
Dashboard
</li>
</ol>
</div> </div>
</div> </div>
<!--end::Row--> <!--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"> <footer class="app-footer">
<!--begin::To the end--> <!--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--> <!--end::To the end-->
<!--begin::Copyright--> <!--begin::Copyright-->
<strong> <a href="https://github.com/firefly-iii/firefly-iii/">Firefly III</a> &copy; James Cole,
Copyright &copy; 2014-2023 <a href="https://github.com/firefly-iii/firefly-iii/blob/main/LICENSE">AGPL-3.0-or-later</a>
<a href="https://adminlte.io">AdminLTE.io</a>.
</strong>
All rights reserved.
<!--end::Copyright--> <!--end::Copyright-->
</footer> </footer>

View File

@@ -23,12 +23,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--begin::Fonts--> <!--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"> <link href="v4/css/fonts.css" rel="stylesheet">
<!--end::Fonts--> <!--end::Fonts-->
@@ -49,5 +43,6 @@
<!--end::Required Plugin(AdminLTE)--> <!--end::Required Plugin(AdminLTE)-->
@vite(['resources/assets/v4/sass/app.scss', 'resources/assets/v4/app.js']) @vite(['resources/assets/v4/sass/app.scss', 'resources/assets/v4/app.js'])
@yield('vite')
</head> </head>

View File

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