Browse Source

Feature/upgrade bootstrap to version 5.3.8 (#8131)

* Update bootstrap to version 5.3.8

* Update changelog
pull/8162/head
Kenrick Tandrian 2 days ago
committed by GitHub
parent
commit
c169311fa3
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      CHANGELOG.md
  2. 2
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html
  3. 2
      apps/client/src/app/components/footer/footer.component.html
  4. 2
      apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html
  5. 50
      apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html
  6. 2
      apps/client/src/app/components/rule/rule.component.html
  7. 4
      apps/client/src/app/components/rule/rule.component.scss
  8. 16
      apps/client/src/app/pages/landing/landing-page.html
  9. 4
      apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.scss
  10. 6
      apps/client/src/app/pages/register/register-page.html
  11. 4
      apps/client/src/app/pages/webauthn/webauthn-page.html
  12. 181
      apps/client/src/styles/bootstrap.scss
  13. 12
      libs/ui/src/lib/activity-type/activity-type.component.scss
  14. 4
      libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.scss
  15. 42
      package-lock.json
  16. 2
      package.json

6
CHANGELOG.md

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Changed
- Upgraded `bootstrap` from version `4.6.2` to `5.3.8`
## 3.86.0 - 2026-10-13
### Added

2
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html

@ -188,7 +188,7 @@
>Symbol</gf-value
>
</div>
<div class="col-6 mb-3">
<div class="col-6 mb-3 position-relative">
<gf-value
i18n
size="medium"

2
apps/client/src/app/components/footer/footer.component.html

@ -191,7 +191,7 @@
</div>
</div>
<div class="container d-none d-md-block mt-5">
<div class="row justify-content-center">
<div class="d-flex justify-content-center">
<div class="font-weight-bold line-height-1 logotype">Ghostfolio</div>
</div>
</div>

2
apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html

@ -1,5 +1,5 @@
<div class="container p-0">
<div class="no-gutters row">
<div class="d-flex flex-wrap">
<div class="px-1 status-container text-muted text-right">
@if ((errors()?.length ?? 0) > 0 && !isLoading()) {
<ion-icon

50
apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html

@ -1,5 +1,5 @@
<div class="container p-0">
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 text-truncate" i18n>Time in Market</div>
<div class="justify-content-end">
<gf-value
@ -10,7 +10,7 @@
</div>
</div>
@if (isLoading) {
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="d-flex flex-grow-1 indent-1 text-truncate">
<ngx-skeleton-loader
animation="pulse"
@ -19,7 +19,7 @@
</div>
</div>
} @else {
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="d-flex flex-grow-1 indent-1 text-truncate">
{{ summary?.activityCount }}
<ng-container i18n>{summary?.activityCount, plural,
@ -39,7 +39,7 @@
<div class="row">
<div class="col"><hr /></div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 text-truncate" i18n>Buy</div>
<div class="justify-content-end">
<gf-value
@ -53,7 +53,7 @@
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 text-truncate" i18n>Sell</div>
<div class="justify-content-end">
<gf-value
@ -70,7 +70,7 @@
<div class="row">
<div class="col"><hr /></div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 text-truncate" i18n>Invested Capital</div>
<div class="justify-content-end">
<gf-value
@ -84,7 +84,7 @@
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 text-truncate" i18n>Absolute Gross Performance</div>
<div class="justify-content-end">
<gf-value
@ -98,7 +98,7 @@
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row text-muted">
<div class="d-flex py-1 text-muted">
<div class="flex-grow-1 indent-1 text-truncate" i18n>thereof Dividend</div>
<div class="justify-content-end">
<gf-value
@ -112,7 +112,7 @@
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 text-truncate" i18n>Fees</div>
<div class="d-flex justify-content-end">
@if (isNumber(summary?.fees)) {
@ -132,7 +132,7 @@
<div class="row">
<div class="col"><hr /></div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 text-truncate" i18n>Absolute Net Performance</div>
<div class="justify-content-end">
<gf-value
@ -146,7 +146,7 @@
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 indent-1 text-truncate">
<ng-container i18n>Net Performance</ng-container>
@if (
@ -173,7 +173,7 @@
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row text-muted">
<div class="d-flex py-1 text-muted">
<div class="flex-grow-1 indent-2 text-truncate">
<ng-container i18n>thereof Dividend Performance</ng-container>
</div>
@ -191,7 +191,7 @@
<div class="row">
<div class="col"><hr /></div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 text-truncate" i18n>Total Assets</div>
<div class="flex-column flex-wrap justify-content-end">
<gf-value
@ -206,7 +206,7 @@
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div
class="align-items-center d-flex flex-grow-1 indent-1"
[class.cursor-pointer]="hasHoldingsBreakdown"
@ -253,7 +253,7 @@
</div>
</div>
@if (hasHoldingsBreakdown && isHoldingsExpanded) {
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 indent-2 text-truncate" i18n>Investments</div>
<div class="flex-column flex-wrap justify-content-end">
<gf-value
@ -268,7 +268,7 @@
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 indent-2 text-truncate" i18n>Emergency Fund</div>
<div class="flex-column flex-wrap justify-content-end">
<gf-value
@ -284,7 +284,7 @@
</div>
</div>
}
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div
class="align-items-center d-flex flex-grow-1 indent-1"
[class.cursor-pointer]="hasCashBreakdown"
@ -331,7 +331,7 @@
</div>
</div>
@if (hasCashBreakdown && isCashExpanded) {
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 indent-2 text-truncate" i18n>Buying Power</div>
<div class="flex-column flex-wrap justify-content-end">
<gf-value
@ -346,7 +346,7 @@
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 indent-2 text-truncate" i18n>Emergency Fund</div>
<div class="flex-column flex-wrap justify-content-end">
<gf-value
@ -362,7 +362,7 @@
</div>
</div>
}
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="align-items-center d-flex flex-grow-1">
<ng-container i18n>Excluded from Analysis</ng-container>
@if (
@ -394,7 +394,7 @@
<div class="row">
<div class="col"><hr /></div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 text-truncate" i18n>Liabilities</div>
<div class="d-flex justify-content-end">
@if (isNumber(summary?.liabilitiesInBaseCurrency)) {
@ -414,7 +414,7 @@
<div class="row">
<div class="col"><hr /></div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 font-weight-bold text-truncate" i18n>Net Worth</div>
<div class="justify-content-end">
<gf-value
@ -428,7 +428,7 @@
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 indent-1 text-truncate">
<ng-container i18n>Annualized Performance</ng-container>
</div>
@ -447,7 +447,7 @@
<div class="row">
<div class="col"><hr /></div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="align-items-center d-flex flex-grow-1">
<ng-container i18n>Emergency Fund</ng-container>
@if (
@ -503,7 +503,7 @@
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row">
<div class="d-flex py-1">
<div class="flex-grow-1 text-truncate" i18n>Interest</div>
<div class="justify-content-end">
<gf-value

2
apps/client/src/app/components/rule/rule.component.html

@ -1,5 +1,5 @@
<div class="py-3">
<div class="align-items-center flex-nowrap no-gutters row">
<div class="align-items-center d-flex">
@if (isLoading) {
<div>
<ngx-skeleton-loader

4
apps/client/src/app/components/rule/rule.component.scss

@ -7,11 +7,11 @@
height: 2rem;
&.okay {
color: var(--success);
color: var(--bs-success);
}
&.warn {
color: var(--danger);
color: var(--bs-danger);
}
}

16
apps/client/src/app/pages/landing/landing-page.html

@ -360,21 +360,17 @@
</div>
<div class="container">
<div class="d-block row">
<div class="outro-inner-container mx-auto">
<div class="h-100 w-100"></div>
</div>
<div class="outro-inner-container mx-auto">
<div class="h-100 w-100"></div>
</div>
<div class="row mb-4">
<div
class="align-items-center d-flex flex-column justify-content-center w-100"
>
<div class="d-flex justify-content-center mb-4">
<div class="align-items-center d-flex flex-column justify-content-center">
<gf-logo size="medium" />
<div>Wealth Management Software</div>
</div>
</div>
<div class="row">
<div class="align-items-center d-flex flex-column w-100">
<div class="d-flex justify-content-center">
<div class="align-items-center d-flex flex-column">
<a
class="logo logo-agplv3 mask"
href="https://www.gnu.org/licenses/agpl-3.0.html"

4
apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.scss

@ -7,11 +7,11 @@
height: 2rem;
&.okay {
color: var(--success);
color: var(--bs-success);
}
&.warn {
color: var(--danger);
color: var(--bs-danger);
}
}
}

6
apps/client/src/app/pages/register/register-page.html

@ -5,10 +5,8 @@
</div>
<div class="container">
<div class="row">
<div
class="align-items-center d-flex flex-column justify-content-center w-100"
>
<div class="d-flex justify-content-center">
<div class="align-items-center d-flex flex-column justify-content-center">
<gf-logo size="large" />
<p class="lead m-0">Wealth Management Software</p>
</div>

4
apps/client/src/app/pages/webauthn/webauthn-page.html

@ -2,12 +2,12 @@
<div class="row">
<div class="col">
@if (!hasError) {
<div class="col d-flex justify-content-center">
<div class="d-flex justify-content-center">
<mat-spinner [diameter]="20" />
</div>
} @else {
<div
class="align-items-center col d-flex flex-column justify-content-center"
class="align-items-center d-flex flex-column justify-content-center"
>
<h1 class="d-flex h5 justify-content-center mb-0 text-center">
<ng-container i18n>Oops, authentication has failed.</ng-container>

181
apps/client/src/styles/bootstrap.scss

@ -1,18 +1,143 @@
/*!
* Bootstrap v4.6.2 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors
* Copyright 2011-2022 Twitter, Inc.
* Bootstrap v5.3.8 (https://getbootstrap.com/)
* Copyright 2011-2025 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
@use 'sass:map';
// Configuration
@import 'bootstrap/scss/functions';
// Restore Bootstrap 4 defaults
$badge-padding-x: 0.4em;
$badge-padding-y: 0.25em;
$blue: #007bff;
$body-secondary-color: #6c757d;
$border-radius: 0.25rem;
$code-color: inherit;
$code-color-dark: inherit;
$code-font-size: 1em;
$container-max-widths: (
sm: 540px,
md: 720px,
lg: 960px,
xl: 1140px
);
$cyan: #17a2b8;
$enable-dark-mode: false;
$enable-rfs: false;
$enable-smooth-scroll: false;
$figure-caption-font-size: 90%;
$green: #28a745;
$grid-gutter-width: 30px;
$hr-opacity: 1;
$initialism-font-size: 90%;
$link-decoration: none;
$link-hover-decoration: underline;
$table-cell-padding-y: 0.75rem;
@import 'bootstrap/scss/variables';
@import 'bootstrap/scss/variables-dark';
@import 'bootstrap/scss/maps';
@import 'bootstrap/scss/mixins';
@import 'bootstrap/scss/utilities';
// Compatibility mappings for legacy Bootstrap 4 utility classes
$utilities: map.merge(
$utilities,
(
'margin-right-compat': (
responsive: true,
property: margin-right,
class: mr,
values: map.merge(
map.merge(
$spacers,
(
auto: auto
)
),
negativify-map($spacers)
)
),
'margin-left-compat': (
responsive: true,
property: margin-left,
class: ml,
values: map.merge(
map.merge(
$spacers,
(
auto: auto
)
),
negativify-map($spacers)
)
),
'padding-right-compat': (
responsive: true,
property: padding-right,
class: pr,
values: $spacers
),
'padding-left-compat': (
responsive: true,
property: padding-left,
class: pl,
values: $spacers
),
'text-align-compat': (
responsive: true,
property: text-align,
class: text,
values: (
left: left,
right: right
)
),
'font-weight-compat': (
property: font-weight,
class: font-weight,
values: (
bold: $font-weight-bold,
normal: $font-weight-normal,
light: $font-weight-light,
bolder: $font-weight-bolder,
lighter: $font-weight-lighter
)
),
'font-style-compat': (
property: font-style,
class: font,
values: (
italic: italic
)
),
'float-compat': (
responsive: true,
property: float,
values: (
left: left,
right: right
)
),
'font-family-compat': (
property: font-family,
class: text,
values: (
monospace: var(--bs-font-monospace)
)
)
)
);
// Layout & components
@import 'bootstrap/scss/root';
@import 'bootstrap/scss/reboot';
@import 'bootstrap/scss/type';
@import 'bootstrap/scss/images';
// @import 'bootstrap/scss/code';
@import 'bootstrap/scss/containers';
@import 'bootstrap/scss/grid';
// @import 'bootstrap/scss/tables';
// @import 'bootstrap/scss/forms';
@ -20,18 +145,15 @@
// @import 'bootstrap/scss/transitions';
// @import 'bootstrap/scss/dropdown';
// @import 'bootstrap/scss/button-group';
// @import 'bootstrap/scss/input-group';
// @import 'bootstrap/scss/custom-forms';
// @import 'bootstrap/scss/nav';
// @import 'bootstrap/scss/navbar';
// @import 'bootstrap/scss/card';
// @import 'bootstrap/scss/accordion';
@import 'bootstrap/scss/breadcrumb';
// @import 'bootstrap/scss/pagination';
@import 'bootstrap/scss/badge';
// @import 'bootstrap/scss/jumbotron';
// @import 'bootstrap/scss/alert';
// @import 'bootstrap/scss/progress';
// @import 'bootstrap/scss/media';
// @import 'bootstrap/scss/list-group';
// @import 'bootstrap/scss/close';
// @import 'bootstrap/scss/toasts';
@ -40,5 +162,44 @@
// @import 'bootstrap/scss/popover';
// @import 'bootstrap/scss/carousel';
// @import 'bootstrap/scss/spinners';
@import 'bootstrap/scss/utilities';
// @import 'bootstrap/scss/print';
// @import 'bootstrap/scss/offcanvas';
// @import 'bootstrap/scss/placeholders';
// Helpers
@import 'bootstrap/scss/helpers/text-truncation';
// Utilities
@import 'bootstrap/scss/utilities/api';
// Grid & layout compatibility
.no-gutters {
--bs-gutter-x: 0;
--bs-gutter-y: 0;
}
// Badge compatibility
.badge-pill {
border-radius: var(--bs-border-radius-pill, 50rem);
padding-left: 0.6em;
padding-right: 0.6em;
}
.badge-secondary {
background-color: var(--bs-secondary);
}
.badge-light {
background-color: var(--bs-light);
color: var(--bs-dark);
}
.badge-warning {
background-color: var(--bs-warning);
color: var(--bs-dark);
}
// Typography compatibility
small,
.small {
font-weight: $font-weight-normal;
}

12
libs/ui/src/lib/activity-type/activity-type.component.scss

@ -11,27 +11,27 @@
}
&.buy {
color: var(--green);
color: var(--bs-green);
}
&.dividend {
color: var(--blue);
color: var(--bs-blue);
}
&.fee {
color: var(--gray);
color: var(--bs-gray);
}
&.interest {
color: var(--cyan);
color: var(--bs-cyan);
}
&.liability {
color: var(--red);
color: var(--bs-red);
}
&.sell {
color: var(--orange);
color: var(--bs-orange);
}
}
}

4
libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.scss

@ -17,11 +17,11 @@
}
&.valid {
background-color: var(--danger);
background-color: var(--bs-danger);
}
&.available {
background-color: var(--success);
background-color: var(--bs-success);
}
&.today {

42
package-lock.json

@ -55,7 +55,7 @@
"ai": "7.0.127",
"alphavantage": "2.2.0",
"big.js": "7.0.1",
"bootstrap": "4.6.2",
"bootstrap": "5.3.8",
"bull": "4.16.5",
"chart.js": "4.5.1",
"chartjs-adapter-date-fns": "3.0.0",
@ -12345,6 +12345,17 @@
"url": "https://opencollective.com/pkgr"
}
},
"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==",
"license": "MIT",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@prisma/adapter-pg": {
"version": "7.10.0",
"resolved": "https://registry.npmjs.org/@prisma/adapter-pg/-/adapter-pg-7.10.0.tgz",
@ -16817,10 +16828,9 @@
"license": "ISC"
},
"node_modules/bootstrap": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz",
"integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==",
"deprecated": "This version of Bootstrap is no longer supported. Please upgrade to the latest version.",
"version": "5.3.8",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz",
"integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==",
"funding": [
{
"type": "github",
@ -16833,8 +16843,7 @@
],
"license": "MIT",
"peerDependencies": {
"jquery": "1.9.1 - 3",
"popper.js": "^1.16.1"
"@popperjs/core": "^2.11.8"
}
},
"node_modules/brace-expansion": {
@ -25149,13 +25158,6 @@
"url": "https://github.com/sponsors/panva"
}
},
"node_modules/jquery": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
"license": "MIT",
"peer": true
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -29254,18 +29256,6 @@
"node": ">=4"
}
},
"node_modules/popper.js": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
"deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
"license": "MIT",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/portfinder": {
"version": "1.0.38",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.38.tgz",

2
package.json

@ -99,7 +99,7 @@
"ai": "7.0.127",
"alphavantage": "2.2.0",
"big.js": "7.0.1",
"bootstrap": "4.6.2",
"bootstrap": "5.3.8",
"bull": "4.16.5",
"chart.js": "4.5.1",
"chartjs-adapter-date-fns": "3.0.0",

Loading…
Cancel
Save