Skip to content

Bookkeeper Dashboard #75

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 55 commits into
base: Release-0.0.7
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
8189f07
Fetch and Process Balance Sheet data
evansmj Apr 23, 2024
fd75581
skip balance sheet tests for now
evansmj Jun 2, 2024
9ee2b5b
Hide 'external' accounts
evansmj Jun 2, 2024
d79a36b
Format table sats with 3 decimal places.
evansmj Jun 3, 2024
9193922
Remove comma from y-axis
evansmj Jun 10, 2024
8dc1fc3
Add sats label to y-axis
evansmj Jun 10, 2024
7fcab6c
add 5 percent top margin so max y-axis value displays
evansmj Jun 10, 2024
ee38b41
Add tooltip on hover of bars
evansmj Jun 11, 2024
e76ca88
Highlight entire row when a cell is hovered
evansmj Jun 11, 2024
3ca0666
Highlight bar color on hover
evansmj Jun 11, 2024
17d2309
Support zooming and panning
evansmj Jun 22, 2024
f7403e6
Add clip so elements dont render behind y axis after zooming or panning
evansmj Jun 22, 2024
9f85d27
Add minutely and yearly time granularity
evansmj Jun 24, 2024
a6cf936
Fix zooming
evansmj Jun 24, 2024
a247b9b
Center x-axis ticks under each bar when zooming
evansmj Jun 24, 2024
7dc32d1
Memoize fetchBalanceSheetData and suppress exhaustive deps since we d…
evansmj Jun 25, 2024
2423fcb
Pass BalanceSheetRoot container width to graph
evansmj Jun 29, 2024
3902d73
constraint table to container width and make scrollable
evansmj Jul 1, 2024
717147d
Make table scrollable vertically
evansmj Jul 2, 2024
497d6fd
Refactor balance sheet types to convert raw sql to workable object.
evansmj Jul 13, 2024
83ff561
Clarify balance sheet data processing
evansmj Jul 17, 2024
37c1e92
Add sats-flow chart
evansmj Aug 6, 2024
7734f79
Add checkbox to hide zero activity
evansmj Aug 7, 2024
d6a45dd
Refactor bar drawing
evansmj Aug 8, 2024
35b1b45
Update zoom behavior
evansmj Aug 20, 2024
cc32b93
Display Invoice Rune (#56)
evansmj Jun 6, 2024
b655e26
Move @types/d3 to devDependencies
evansmj Aug 21, 2024
27e5f73
Set default TimeGranularity to Monthly
evansmj Aug 22, 2024
7b6ea21
Add VolumeGraph
evansmj Sep 12, 2024
48532b3
Add sql terminal
evansmj Oct 1, 2024
12a9eb1
Fix header not rendering in bookkeeper routes
evansmj Oct 1, 2024
a7b044a
Add date range to balance sheet
evansmj Oct 3, 2024
6ab8c91
Update TimeGranularity button style and support dark mode
evansmj Oct 21, 2024
0e43d77
Style balance sheet according to figma
evansmj Oct 31, 2024
d5f075e
Update styles
evansmj Nov 11, 2024
547f42b
format volume sats
evansmj Nov 11, 2024
cec1b1b
format net inflow
evansmj Nov 11, 2024
3f577b6
Fix lint issues on VolumeGraph
evansmj Nov 22, 2024
a4a01d9
Hide dropdown icon when value is selected in DatepickerInput
evansmj Nov 22, 2024
81ada6e
Hide zero activity periods on balance sheet.
evansmj Nov 22, 2024
cb22c10
Add total period balance to balance sheet graph tool tip
evansmj Nov 23, 2024
80e763a
Move balance format to constants.ts
evansmj Nov 23, 2024
d1e4b7e
Refactor timestamp range calculation out of sql into transform function
evansmj Nov 23, 2024
c823078
Add date range options to sats flow
evansmj Nov 28, 2024
ea28aad
Bookkeeper landing layout
evansmj Dec 20, 2024
f0f21ad
Fix dark/light mode colors
evansmj Dec 20, 2024
b69dc8e
Fetch data for bookkeeper landing
evansmj Dec 23, 2024
0ab2fef
Fix volume summation
evansmj Dec 26, 2024
bb1649c
Display routes for volume chart instead of channels
evansmj Dec 26, 2024
71d3676
Add terminal button
evansmj Dec 26, 2024
1009fb2
fix lints
evansmj Dec 26, 2024
90ee75d
Update bar color scheme
evansmj Dec 26, 2024
bdacc25
Fix inbound display
evansmj Dec 26, 2024
625bf7a
Add tests for bookkeeper components
evansmj Dec 28, 2024
2c975d4
Compiled code after all bookkeeper updatescommits
ShahanaFarooqui Feb 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions apps/frontend/build/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"files": {
"main.css": "/static/css/main.7f1e45cf.css",
"main.js": "/static/js/main.c5e37ea7.js",
"main.css": "/static/css/main.79f288c9.css",
"main.js": "/static/js/main.69a32e2c.js",
"static/media/Inter-Bold.ttf": "/static/media/Inter-Bold.88fa7ae373b07b41ecce.ttf",
"static/media/Inter-SemiBold.ttf": "/static/media/Inter-SemiBold.4d56bb21f2399db8ad48.ttf",
"static/media/Inter-Medium.ttf": "/static/media/Inter-Medium.6dcbc9bed1ec438907ee.ttf",
"static/media/Inter-Thin.ttf": "/static/media/Inter-Thin.f341ca512063c66296d1.ttf",
"index.html": "/index.html",
"main.7f1e45cf.css.map": "/static/css/main.7f1e45cf.css.map",
"main.c5e37ea7.js.map": "/static/js/main.c5e37ea7.js.map"
"main.79f288c9.css.map": "/static/css/main.79f288c9.css.map",
"main.69a32e2c.js.map": "/static/js/main.69a32e2c.js.map"
},
"entrypoints": [
"static/css/main.7f1e45cf.css",
"static/js/main.c5e37ea7.js"
"static/css/main.79f288c9.css",
"static/js/main.69a32e2c.js"
]
}
2 changes: 1 addition & 1 deletion apps/frontend/build/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./images/cln-favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="color-scheme" content="light dark"><meta name="description" content="Core lightning application"/><link rel="apple-touch-icon" href="./images/cln-logo-dark.png"/><title>Core Lightning</title><script defer="defer" src="/static/js/main.c5e37ea7.js"></script><link href="/static/css/main.7f1e45cf.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./images/cln-favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="color-scheme" content="light dark"><meta name="description" content="Core lightning application"/><link rel="apple-touch-icon" href="./images/cln-logo-dark.png"/><title>Core Lightning</title><script defer="defer" src="/static/js/main.69a32e2c.js"></script><link href="/static/css/main.79f288c9.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions apps/frontend/build/static/css/main.79f288c9.css.map

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion apps/frontend/build/static/css/main.7f1e45cf.css.map

This file was deleted.

3 changes: 0 additions & 3 deletions apps/frontend/build/static/js/main.12dcd792.js

This file was deleted.

1 change: 0 additions & 1 deletion apps/frontend/build/static/js/main.12dcd792.js.map

This file was deleted.

3 changes: 3 additions & 0 deletions apps/frontend/build/static/js/main.69a32e2c.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,20 @@
*/

/*!
* perfect-scrollbar v1.5.3
* Copyright 2021 Hyunje Jun, MDBootstrap and Contributors
react-datepicker v7.6.0
https://github.com/Hacker0x01/react-datepicker
Released under the MIT License.
*/

/*!
* Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2024 Fonticons, Inc.
*/

/*!
* perfect-scrollbar v1.5.6
* Copyright 2024 Hyunje Jun, MDBootstrap and Contributors
* Licensed under MIT
*/

Expand Down Expand Up @@ -57,7 +69,7 @@
*/

/**
* @remix-run/router v1.15.2
* @remix-run/router v1.22.0
*
* Copyright (c) Remix Software Inc.
*
Expand All @@ -68,7 +80,7 @@
*/

/**
* React Router DOM v6.22.2
* React Router DOM v6.29.0
*
* Copyright (c) Remix Software Inc.
*
Expand All @@ -79,7 +91,7 @@
*/

/**
* React Router v6.22.2
* React Router v6.29.0
*
* Copyright (c) Remix Software Inc.
*
Expand All @@ -88,3 +100,5 @@
*
* @license MIT
*/

//! moment.js
1 change: 1 addition & 0 deletions apps/frontend/build/static/js/main.69a32e2c.js.map

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions apps/frontend/build/static/js/main.c5e37ea7.js

This file was deleted.

1 change: 0 additions & 1 deletion apps/frontend/build/static/js/main.c5e37ea7.js.map

This file was deleted.

4 changes: 4 additions & 0 deletions apps/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@
"bootstrap": "^5.3.2",
"copy-to-clipboard": "^3.3.3",
"crypto-js": "^4.2.0",
"d3": "^7.9.0",
"framer-motion": "^10.16.5",
"moment": "^2.30.1",
"node-sass": "^7.0.3",
"qrcode.react": "^3.1.0",
"react": "^18.2.0",
"react-bootstrap": "^2.10.1",
"react-datepicker": "^7.3.0",
"react-dom": "^18.2.0",
"react-perfect-scrollbar": "^1.5.8",
"react-router-dom": "^6.22.1",
Expand All @@ -31,6 +34,7 @@
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.1",
"@testing-library/user-event": "^14.5.1",
"@types/d3": "^7.4.3",
"@types/jest": "^29.5.12",
"@types/node": "^20.9.4",
"@types/react": "^18.2.61",
Expand Down
10 changes: 8 additions & 2 deletions apps/frontend/src/components/App/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React from 'react';

import './App.scss';
import { useContext, useEffect } from 'react';
import { Navigate, Outlet, RouterProvider, createBrowserRouter } from 'react-router-dom';
Expand All @@ -20,6 +18,10 @@ import logger from '../../services/logger.service';
import { AuthResponse } from '../../types/app-config.type';
import Bookkeeper from '../bookkeeper/BkprRoot/BkprRoot';
import CLNHome from '../cln/CLNHome/CLNHome';
import BalanceSheetRoot from '../bookkeeper/BalanceSheet/BalanceSheetRoot';
import SatsFlowRoot from '../bookkeeper/SatsFlow/SatsFlowRoot';
import VolumeRoot from '../bookkeeper/Volume/VolumeRoot';
import Terminal from '../bookkeeper/Terminal/TerminalRoot';

export const rootRouteConfig = [
{
Expand All @@ -28,6 +30,10 @@ export const rootRouteConfig = [
{ path: "/", Component: () => <Navigate to="/home" replace /> },
{ path: "home", Component: CLNHome },
{ path: "bookkeeper", Component: Bookkeeper },
{ path: "bookkeeper/balancesheet", Component: BalanceSheetRoot },
{ path: "bookkeeper/satsflow", Component: SatsFlowRoot },
{ path: "bookkeeper/volume", Component: VolumeRoot },
{ path: "bookkeeper/terminal", Component: Terminal }
]
},
];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
@import '../../../styles/constants.scss';

.react-datepicker-popper {
.react-datepicker {
border-color: $border-color;

&__header {
background-color: transparent;
border-bottom-color: $border-color;
}

&__navigation {
&-icon::before {
border-color: currentColor;
}

&:hover *::before {
border-color: $primary;
}
}

&__day {
&:hover {
background-color: rgba($primary, 0.1);
color: $primary;
}

&--selected {
background-color: $primary;
color: white;

&:hover {
background-color: darken($primary, 5%);
}
}

&--keyboard-selected {
background-color: rgba($primary, 0.1);
color: $primary;
}
}

&__current-month,
&__day-name {
color: inherit;
}
}
}

@include color-mode(dark) {
.react-datepicker-popper {
.react-datepicker {
background-color: $picker-background-color-dark;
border-color: $picker-border-color-dark;

&__header {
background-color: $picker-background-color-dark;
border-bottom-color: $picker-border-color-dark;
}

&__current-month,
&__day-name,
&__day {
color: $light-dark;
}

&__day {
&:hover {
background-color: rgba($primary, 0.1);
color: $primary;
}

&--selected {
background-color: $primary;
color: $white;

&:hover {
background-color: darken($primary, 5%);
}
}

&--keyboard-selected {
background-color: rgba($primary, 0.1);
color: $primary;
}
}

&__navigation-icon::before {
border-color: $light-dark;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { render, screen } from '@testing-library/react';
import BalanceSheetRoot from './BalanceSheetRoot';

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: jest.fn(),
}));

describe('Balance Sheet component ', () => {
beforeEach(() => render(<BalanceSheetRoot />));

it('should be in the document', () => {
expect(screen.getByTestId('balancesheet-container')).not.toBeEmptyDOMElement()
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { useCallback, useContext, useEffect, useRef, useState } from 'react';

import './BalanceSheetRoot.scss';
import 'react-datepicker/dist/react-datepicker.css';
import Card from 'react-bootstrap/Card';
import Row from 'react-bootstrap/Row';
import BalanceSheetGraph from './Graph/BalanceSheetGraph';
import { AppContext } from '../../../store/AppContext';
import BalanceSheetTable from './Table/BalanceSheetTable';
import useHttp from '../../../hooks/use-http';
import { TimeGranularity } from '../../../utilities/constants';
import { BalanceSheet } from '../../../types/lightning-balancesheet.type';
import TimeGranularitySelection from '../TimeGranularitySelection/TimeGranularitySelection';
import { Container } from 'react-bootstrap';
import DatePicker from 'react-datepicker';
import DatepickerInput from '../DatepickerInput/DatepickerInput';

const BalanceSheetRoot = () => {
const appCtx = useContext(AppContext);
const [containerWidth, setContainerWidth] = useState(0);
const containerRef = useRef<HTMLDivElement>(null);
const [balanceSheetData, setBalanceSheetData] = useState<BalanceSheet>({ periods: [] });
const [timeGranularity, setTimeGranularity] = useState<TimeGranularity>(TimeGranularity.MONTHLY);
const [rangeStart, setRangeStart] = useState<Date | undefined>(undefined);
const [rangeEnd, setRangeEnd] = useState<Date | undefined>(undefined);
const [hideZeroActivityPeriods, setHideZeroActivityPeriods] = useState<boolean>(true);
const { getBalanceSheet } = useHttp();

const updateWidth = () => {
if (containerRef.current) {
setContainerWidth(containerRef.current.getBoundingClientRect().width);
}
};

const fetchBalanceSheetData = useCallback(
async (timeGranularity: TimeGranularity, hideZeroActivityPeriods: Boolean, startDate?: Date, endDate?: Date) => {
getBalanceSheet(timeGranularity, hideZeroActivityPeriods, startDate, endDate)
.then((response: BalanceSheet) => {
setBalanceSheetData(response);
})
.catch(err => {
console.error('fetchBalanceSheet error ' + JSON.stringify(err));
});
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[],
);

const timeGranularityChangeHandler = timeGranularity => {
setTimeGranularity(timeGranularity);
};

const hideZeroActivityPeriodsChangeHandler = (event) => {
setHideZeroActivityPeriods(event.target.checked);
};

useEffect(() => {
updateWidth();
window.addEventListener('resize', updateWidth);
return () => window.removeEventListener('resize', updateWidth);
}, []);

useEffect(() => {
if (appCtx.authStatus.isAuthenticated) {
fetchBalanceSheetData(timeGranularity, hideZeroActivityPeriods, rangeStart, rangeEnd);
}
}, [
appCtx.authStatus.isAuthenticated,
timeGranularity,
rangeStart,
rangeEnd,
fetchBalanceSheetData,
hideZeroActivityPeriods,
]);

return (
<div data-testid="balancesheet-container" ref={containerRef}>
<Card className="d-flex align-items-stretch inner-box-shadow">
<Card.Header className="p-2">
<Container fluid>
<Row>
<div className="fs-4 mt-2 fw-bold">Balance Sheet</div>
</Row>
<div className="d-flex align-items-center mt-2 gap-4">
<div className="fw-bold">Time Granularity</div>
<TimeGranularitySelection
className="time-granularity-dropdown"
timeGranularity={timeGranularity}
onTimeGranularityChanged={timeGranularityChangeHandler}
/>
<DatePicker
customInput={<DatepickerInput />}
selected={rangeStart}
onChange={date => setRangeStart(date ?? undefined)}
placeholderText="Starts"
/>
<DatePicker
customInput={<DatepickerInput />}
selected={rangeEnd}
onChange={date => setRangeEnd(date ?? undefined)}
placeholderText="Ends"
/>
<div className="ms-3 me-3 mt-2 d-flex align-items-center">
<input
type="checkbox"
id="hideZeroActivityCheckbox"
name="hideZeroActivity"
checked={hideZeroActivityPeriods}
onChange={hideZeroActivityPeriodsChangeHandler}
/>
<label htmlFor="hideZeroActivityCheckbox" className="ms-2">
Hide Zero Activity
</label>
</div>
</div>
</Container>
</Card.Header>
<Card.Body className="pb-4 d-flex flex-column align-items-center">
<Row>
<BalanceSheetGraph balanceSheetData={balanceSheetData} width={containerWidth} />
</Row>
<Row className="w-100 overflow-x-auto">
<BalanceSheetTable balanceSheetData={balanceSheetData} />
</Row>
</Card.Body>
</Card>
</div>
);
};

export default BalanceSheetRoot;
Loading