Basic set of stuff working!

This commit is contained in:
James Cole 2023-07-22 16:42:33 +02:00
parent 2c2dddc071
commit 190508fa54
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80
17 changed files with 381 additions and 282 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@

View File

@ -0,0 +1 @@
var p=Object.defineProperty;var u=(n,t,e)=>t in n?p(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var l=(n,t,e)=>(u(n,typeof t!="symbol"?t+"":t,e),e);import{a as m,m as i,n as s}from"./index-bc37dda8.js";class y{get(t,e,a){return m.get("/api/v1/summary/basic",{params:{start:t,end:e,code:a}})}}class w{constructor(){l(this,"balanceBox",{foo:"bar"});console.log("IndexApp constructor")}init(){console.log("IndexApp init"),this.loadBoxes()}loadBoxes(){console.log("IndexApp loadBoxes");let t=new y,e=window.BasicStore.get("start"),a=window.BasicStore.get("end");e!==null&&a!==null&&(e=new Date(e),a=new Date(a)),t.get(s(e,"yyyy-MM-dd"),s(a,"yyyy-MM-dd"),null).then(o=>{console.log("IndexApp done!"),console.log(o.data),document.querySelector("#balanceAmount").innerText="ok dan";for(const d in o.data)if(o.data.hasOwnProperty(d)){const c=o.data[d];d.startsWith("balance-in-")&&console.log("Balance in: ",c)}})}}let r=new w;document.addEventListener("AppReady",n=>{r.init()},!1);window.BasicStore.isReady()&&r.init();document.addEventListener("alpine:init",()=>{i.data("balanceBox",()=>({foo:"barX"}))});window.Alpine=i;i.start();

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,7 @@
{
"_index-bc37dda8.js": {
"file": "assets/index-bc37dda8.js"
},
"node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf": {
"file": "assets/fa-brands-400-20c4a58b.ttf",
"src": "node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf"
@ -24,12 +27,18 @@
"src": "node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2"
},
"resources/assets/v4/app.js": {
"file": "assets/app-afb3782a.js",
"file": "assets/app-c6b26402.js",
"imports": [
"_index-bc37dda8.js"
],
"isEntry": true,
"src": "resources/assets/v4/app.js"
},
"resources/assets/v4/index.js": {
"file": "assets/index-4ed993c7.js",
"file": "assets/index-a835f2af.js",
"imports": [
"_index-bc37dda8.js"
],
"isEntry": true,
"src": "resources/assets/v4/index.js"
},

View File

@ -25,6 +25,10 @@ export default class Preferences {
return api.get('/api/v1/preferences/' + name);
}
getByNameNow(name) {
return api.get('/api/v1/preferences/' + name);
}
postByName(name, value) {
return api.post('/api/v1/preferences', {name: name, data: value});
}

View File

@ -61,102 +61,6 @@ class MainApp {
// default range is always the current period (initialized ahead)
}
setDatesFromViewRange(today) {
console.log('MainApp: setDatesFromViewRange');
let start;
let end;
let viewRange = this.viewRange;
console.log('MainApp: viewRange: ' + viewRange);
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;
}
console.log('MainApp: setDatesFromViewRange done!');
return {start: start, end: end};
}
buildDateRange() {
console.log('MainApp: buildDateRange');

View File

@ -5,8 +5,29 @@
*/
import axios from 'axios';
//import Alpine from 'alpinejs';
import BasicStore from './store/Basic';
import store from 'store2';
import Alpine from "alpinejs";
import {getVariable} from "./store/get-variable.js";
import {getViewRange} from "./support/get-viewrange.js";
// wait for 3 promises, because we need those later on.
window.bootstrapped = false;
Promise.all([
getVariable('viewRange'),
getVariable('darkMode'),
getVariable('locale')
]).then((values) => {
if (!store.has('start') || !store.has('end')) {
// calculate new start and end, and store them.
const range = getViewRange(values[0], new Date);
store.set('start', range.start);
store.set('end', range.end);
}
const event = new Event('firefly-iii-bootstrapped');
document.dispatchEvent(event);
window.bootstrapped = true;
});
window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
@ -14,31 +35,7 @@ window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
// include popper js
import '@popperjs/core';
// include bootstrap
// include bootstrap CSS
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
* allows your team to easily build robust real-time web applications.
*/
// import Echo from 'laravel-echo';
// import Pusher from 'pusher-js';
// window.Pusher = Pusher;
// window.Echo = new Echo({
// broadcaster: 'pusher',
// key: import.meta.env.VITE_PUSHER_APP_KEY,
// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1',
// wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
// wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
// wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
// forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
// enabledTransports: ['ws', 'wss'],
// });
window.BasicStore = new BasicStore;
window.BasicStore.init();
window.Alpine = Alpine

View File

@ -19,20 +19,23 @@
*/
import './bootstrap.js';
import Alpine from "alpinejs";
import boxes from './pages/dashboard/boxes.js';
// move to bootstrap later on?
window.Alpine = Alpine
const comps = {boxes};
import dashboard from './pages/dashboard.js';
const comps = {dashboard};
//import * as comps from '/dist/demo/index.js';
function loadPage(comps) {
Object.keys(comps).forEach(comp => {
//let data = new comps[comp]();
console.log('Loaded component ' + comp);
let data = comps[comp]();
Alpine.data(comp, () => data);
});
Alpine.start();
}
// wait for load until bootstrapped event is received.
document.addEventListener('firefly-iii-bootstrapped', () => {
loadPage(comps);
});
// or is bootstrapped before event is triggered.
if (window.bootstrapped) {
loadPage(comps);
}

View File

@ -1,63 +0,0 @@
/*
* dashboard.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 Summary from "../api/summary/index.js";
import {format} from "date-fns";
export default () => ({
balanceBox: {amounts: [], subtitles: []},
constructor() {
console.log('DashboardClass constructor');
//
},
// Getter
init() {
// get boxes info.
let getter = new Summary();
let start = window.BasicStore.get('start');
let end = window.BasicStore.get('end');
// check on NULL values:
if (start !== null && end !== null) {
start = new Date(start);
end = new Date(end);
}
getter.get(format(start, 'yyyy-MM-dd'), format(end, 'yyyy-MM-dd'), null).then((response) => {
console.log('DashboardClass done!');
console.log(response.data);
for (const i in response.data) {
if (response.data.hasOwnProperty(i)) {
const current = response.data[i];
if (i.startsWith('balance-in-')) {
console.log('Balance in: ', current);
this.balanceBox.amounts.push(current.value_parsed);
this.balanceBox.subtitles.push(current.sub_title);
}
}
}
});
},
});

View File

@ -0,0 +1,82 @@
/*
* dashboard.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 Summary from "../../api/summary/index.js";
import {format} from "date-fns";
import {getVariable} from "../../store/get-variable.js";
import store from 'store2';
export default () => ({
balanceBox: {amounts: [], subtitles: []},
billBox: {paid: [], unpaid: []},
leftBox: {left: [], perDay: []},
netBox: {net: []},
constructor() {
console.log('DashboardClass constructor');
//
},
// Getter
init() {
console.log('Now in boxes');
Promise.all([
getVariable('viewRange'),
]).then((values) => {
let getter = new Summary();
let start = new Date(store.get('start'));
let end = new Date(store.get('end'));
getter.get(format(start, 'yyyy-MM-dd'), format(end, 'yyyy-MM-dd'), null).then((response) => {
for (const i in response.data) {
if (response.data.hasOwnProperty(i)) {
const current = response.data[i];
if (i.startsWith('balance-in-')) {
this.balanceBox.amounts.push(current.value_parsed);
this.balanceBox.subtitles.push(current.sub_title);
continue;
}
if (i.startsWith('bills-unpaid-in-')) {
this.billBox.unpaid.push(current.value_parsed);
continue;
}
if (i.startsWith('bills-paid-in-')) {
this.billBox.paid.push(current.value_parsed);
continue;
}
if (i.startsWith('spent-in-')) {
this.leftBox.left.push(current.value_parsed);
}
if (i.startsWith('net-worth-in-')) {
this.netBox.net.push(current.value_parsed);
}
console.log('Next up: ', current);
}
}
});
});
},
});

View File

@ -3,42 +3,37 @@
import Get from '../api/preferences/index.js';
import store from 'store2';
/**
* A basic store for Firefly III persistent UI data and preferences.
*/
class Basic {
const Basic = () => {
// currently availabel variables:
viewRange = '1M';
darkMode = 'browser';
language = 'en-US';
locale = 'en-US';
const viewRange = '1M';
const darkMode = 'browser';
const language = 'en-US';
const locale = 'en-US';
// start and end are used by most pages to allow the user to browse back and forth.
start = null;
end = null;
const start = null;
const end = null;
// others, to be used in the future.
listPageSize = 10;
currencyCode = 'AAA';
currencyId = '0';
ready = false;
const listPageSize = 10;
const currencyCode = 'AAA';
const currencyId = '0';
const ready = false;
//
// a very basic way to signal the store now contains all variables.
count = 0;
readyCount = 4;
const count = 0;
const readyCount = 4;
/**
*
*/
constructor() {
console.log('Basic constructor')
}
/**
*
*/
init() {
console.log('Basic init')
const init = () => {
console.log('Basic store init')
this.loadVariable('viewRange')
this.loadVariable('darkMode')
this.loadVariable('language')
@ -49,7 +44,7 @@ class Basic {
* Load a variable, fresh or from storage.
* @param name
*/
loadVariable(name) {
const loadVariable = (name) => {
// currently unused, window.X can be used by the blade template
// to make things available quicker than if the store has to grab it through the API.
@ -69,28 +64,29 @@ class Basic {
let getter = (new Get);
getter.getByName(name).then((response) => this.parseResponse(name, response));
}
parseResponse(name, response) {
//
const parseResponse = (name, response) => {
let value = response.data.data.attributes.data;
this[name] = value;
// TODO store.
store.set(name, value);
this.triggerReady();
}
set(name, value) {
this[name] = value;
store.set(name, value);
}
get(name) {
return store.get(name, this[name]);
}
isReady() {
//
// set(name, value) {
// this[name] = value;
// store.set(name, value);
// }
//
// get(name) {
// return store.get(name, this[name]);
// }
//
const isReady = () => {
return this.count === this.readyCount;
}
triggerReady() {
const triggerReady = () => {
this.count++;
if (this.count === this.readyCount) {
console.log('Basic store is ready!')
@ -99,6 +95,8 @@ class Basic {
document.dispatchEvent(event);
}
}
return {
init
};
}
export default Basic;
export const basic = Basic();

View File

@ -0,0 +1,51 @@
/*
* get-variable.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 store from "store2";
import Get from "../api/preferences/index.js";
export function getVariable(name) {
// currently unused, window.X can be used by the blade template
// to make things available quicker than if the store has to grab it through the API.
// then again, it's not that slow.
if (window.hasOwnProperty(name)) {
console.log('Store from window');
return Promise.resolve(window[name]);
}
// load from store2, if it's present.
if (store.has(name)) {
console.log('Store from store2');
return Promise.resolve(store.get(name));
}
let getter = (new Get);
return getter.getByName(name).then((response) => {
return Promise.resolve(parseResponse(name, response));
});
}
function parseResponse(name, response) {
let value = response.data.data.attributes.data;
store.set(name, value);
console.log('Store from API');
return value;
}

View File

@ -1,22 +0,0 @@
class DateRange {
start=null;
end = null;
constructor() {
this.start = null
this.end = null
}
setStart(start) {
this.start = start
}
setEnd(end) {
this.end = end
}
}
export default DateRange

View File

@ -0,0 +1,107 @@
import {
endOfDay, endOfMonth, endOfQuarter,
endOfWeek,
startOfDay,
startOfMonth,
startOfQuarter,
startOfWeek,
startOfYear,
subDays
} from "date-fns";
function getViewRange(viewRange, today) {
let start;
let end;
console.log('getViewRange: ' + viewRange);
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;
}
console.log('MainApp: setDatesFromViewRange done!');
return {start: start, end: end};
}
export {getViewRange};

View File

@ -1,8 +1,8 @@
<div class="row">
<div class="row" x-data="boxes">
<!--begin::Col-->
<div class="col-lg-3 col-6">
<!--begin::Small Box Widget 1-->
<div class="small-box text-bg-primary" x-data="dashboard">
<div class="small-box text-bg-primary">
<div class="inner">
<h3 id="balanceAmount">
<template x-for="(amount, index) in balanceBox.amounts" :key="index">
@ -37,7 +37,14 @@
<!--begin::Small Box Widget 2-->
<div class="small-box text-bg-success">
<div class="inner">
<h3>TODO amount</h3>
<h3>
<template x-for="(amount, index) in billBox.unpaid" :key="index">
<span>
<span x-text="amount"></span><span
:class="{ 'invisible': (billBox.unpaid.length == index+1) }">, </span>
</span>
</template>
</h3>
<p><a href="{{ route('bills.index') }}">{{ __('firefly.bills_to_pay') }}</a></p>
</div>
@ -45,7 +52,13 @@
<em class="fa-regular fa-calendar"></em>
</span>
<span class="small-box-footer">
{{ __('firefly.paid') }}: TODO amount
{{ __('firefly.paid') }}:
<template x-for="(amount, index) in billBox.paid" :key="index">
<span>
<span x-text="amount"></span><span
:class="{ 'invisible': (billBox.paid.length == index+1) }">, </span>
</span>
</template>
</span>
</div>
<!--end::Small Box Widget 2-->
@ -55,7 +68,14 @@
<!--begin::Small Box Widget 3-->
<div class="small-box text-bg-warning">
<div class="inner">
<h3>TODO amount</h3>
<h3>
<template x-for="(amount, index) in leftBox.left" :key="index">
<span>
<span x-text="amount"></span><span
:class="{ 'invisible': (leftBox.left.length == index+1) }">, </span>
</span>
</template>
</h3>
<p><a href="{{ route('budgets.index') }}">{{ __('firefly.left_to_spend') }}</a></p>
</div>
@ -73,7 +93,14 @@
<!--begin::Small Box Widget 4-->
<div class="small-box text-bg-danger">
<div class="inner">
<h3>TODO amount</h3>
<h3>
<template x-for="(amount, index) in netBox.net" :key="index">
<span>
<span x-text="amount"></span><span
:class="{ 'invisible': (netBox.net.length == index+1) }">, </span>
</span>
</template>
</h3>
<p>
<a href="{{ route('reports.report.default', ['allAssetAccounts','currentYearStart','currentYearEnd']) }}">{{ __('firefly.net_worth') }}</a>