mirror of https://github.com/ghostfolio/ghostfolio
7 changed files with 293 additions and 236 deletions
@ -0,0 +1,155 @@ |
|||
<footer class="justify-content-center overflow-hidden py-4 w-100"> |
|||
<div class="container"> |
|||
<div class="mb-3 row"> |
|||
<div class="col-sm"> |
|||
<a [routerLink]="['/']"><gf-logo /></a> |
|||
</div> |
|||
<div class="col-sm"> |
|||
<div class="h6 mt-2" i18n>Personal Finance</div> |
|||
<ul class="list-unstyled"> |
|||
@if (hasPermissionToAccessFearAndGreedIndex) { |
|||
<li> |
|||
<a i18n [routerLink]="routerLinkMarkets">Markets</a> |
|||
</li> |
|||
} |
|||
<li><a i18n [routerLink]="routerLinkResources">Resources</a></li> |
|||
</ul> |
|||
</div> |
|||
<div class="col-sm"> |
|||
<div class="h6 mt-2">Ghostfolio</div> |
|||
<ul class="list-unstyled"> |
|||
<li><a i18n [routerLink]="routerLinkAbout">About</a></li> |
|||
@if (hasPermissionForSubscription) { |
|||
<li> |
|||
<a i18n [routerLink]="routerLinkBlog">Blog</a> |
|||
</li> |
|||
} |
|||
<li> |
|||
<a i18n [routerLink]="routerLinkAboutChangelog">Changelog</a> |
|||
</li> |
|||
<li><a i18n [routerLink]="routerLinkFeatures">Features</a></li> |
|||
@if (hasPermissionForSubscription) { |
|||
<li> |
|||
<a i18n [routerLink]="routerLinkFaq">Frequently Asked Questions (FAQ)</a> |
|||
</li> |
|||
} |
|||
@if (!hasPermissionForSubscription) { |
|||
<li> |
|||
<a i18n [routerLink]="routerLinkAboutLicense">License</a> |
|||
</li> |
|||
} |
|||
@if (hasPermissionForStatistics) { |
|||
<li> |
|||
<a [routerLink]="routerLinkOpenStartup">Open Startup</a> |
|||
</li> |
|||
} |
|||
@if (hasPermissionForSubscription) { |
|||
<li> |
|||
<a i18n [routerLink]="routerLinkPricing">Pricing</a> |
|||
</li> |
|||
} |
|||
@if (hasPermissionForSubscription) { |
|||
<li> |
|||
<a i18n [routerLink]="routerLinkAboutPrivacyPolicy">Privacy Policy</a> |
|||
</li> |
|||
} |
|||
@if (hasPermissionForSubscription) { |
|||
<li> |
|||
<a i18n [routerLink]="routerLinkAboutTermsOfService">Terms of Service</a> |
|||
</li> |
|||
} |
|||
@if (hasPermissionForSubscription) { |
|||
<li> |
|||
<a class="align-items-baseline d-flex" href="https://status.ghostfol.io" target="_blank" |
|||
title="Ghostfolio Status">Status<ion-icon class="ml-1" name="open-outline" /></a> |
|||
</li> |
|||
} |
|||
</ul> |
|||
</div> |
|||
<div class="col-sm"> |
|||
<div class="h6 mt-2" i18n>Community</div> |
|||
<ul class="list-unstyled"> |
|||
<li> |
|||
<a class="align-items-baseline d-flex" href="https://github.com/ghostfolio/ghostfolio" |
|||
target="_blank" title="Find Ghostfolio on GitHub">GitHub<ion-icon class="ml-1" |
|||
name="open-outline" /></a> |
|||
</li> |
|||
<li> |
|||
<a class="align-items-baseline d-flex" href="https://linkedin.com/company/ghostfolio" |
|||
target="_blank" title="Follow Ghostfolio on LinkedIn">LinkedIn<ion-icon class="ml-1" |
|||
name="open-outline" /></a> |
|||
</li> |
|||
<li> |
|||
<a class="align-items-baseline d-flex" |
|||
href="https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg" |
|||
target="_blank" title="Join the Ghostfolio Slack community">Slack<ion-icon class="ml-1" |
|||
name="open-outline" /></a> |
|||
</li> |
|||
<li> |
|||
<a class="align-items-baseline d-flex" href="https://x.com/ghostfolio_" target="_blank" |
|||
title="Follow Ghostfolio on X (formerly Twitter)">X (formerly Twitter)<ion-icon class="ml-1" |
|||
name="open-outline" /></a> |
|||
</li> |
|||
<li> </li> |
|||
<!-- |
|||
<li> |
|||
<a href="../ca" title="Ghostfolio en català">Català</a> |
|||
</li> |
|||
--> |
|||
<li> |
|||
<a href="../zh" title="Ghostfolio in Chinese">Chinese</a> |
|||
</li> |
|||
<li> |
|||
<a href="../de" title="Ghostfolio in Deutsch">Deutsch</a> |
|||
</li> |
|||
<li> |
|||
<a href="../en" title="Ghostfolio in English">English</a> |
|||
</li> |
|||
<li> |
|||
<a href="../es" title="Ghostfolio in Español">Español</a> |
|||
</li> |
|||
<li> |
|||
<a href="../fr" title="Ghostfolio en Français">Français</a> |
|||
</li> |
|||
<li> |
|||
<a href="../it" title="Ghostfolio in Italiano">Italiano</a> |
|||
</li> |
|||
<li> |
|||
<a href="../nl" title="Ghostfolio in Nederlands">Nederlands</a> |
|||
</li> |
|||
<li> |
|||
<a href="../pl" title="Ghostfolio in Polski">Polski</a> |
|||
</li> |
|||
<li> |
|||
<a href="../pt" title="Ghostfolio in Português">Português</a> |
|||
</li> |
|||
<li> |
|||
<a href="../tr" title="Ghostfolio in Türkçe">Türkçe</a> |
|||
</li> |
|||
<!-- |
|||
<li> |
|||
<a href="../uk" title="Ghostfolio in Українська">Українська</a> |
|||
</li> |
|||
--> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
<div class="mb-2 row text-center"> |
|||
<div class="col"> |
|||
© 2021 - {{ currentYear }} |
|||
<a href="https://ghostfol.io">Ghostfolio</a> |
|||
</div> |
|||
</div> |
|||
<div class="row text-center text-muted"> |
|||
<div class="col"> |
|||
<small class="d-block" i18n>The risk of loss in trading can be substantial. It is not advisable |
|||
to invest money you may need in the short term.</small> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="container d-none d-md-block mt-5"> |
|||
<div class="row justify-content-center"> |
|||
<div class="font-weight-bold line-height-1 logotype">Ghostfolio</div> |
|||
</div> |
|||
</div> |
|||
</footer> |
|||
@ -0,0 +1,16 @@ |
|||
:host { |
|||
display: block; |
|||
background-color: rgba(var(--palette-foreground-text), 0.05); |
|||
font-size: 90%; |
|||
|
|||
.logotype { |
|||
font-size: 13vw; |
|||
letter-spacing: -0.03em; |
|||
margin-bottom: -5svw; |
|||
opacity: 0.05; |
|||
} |
|||
} |
|||
|
|||
:host-context(.theme-dark) { |
|||
background-color: rgba(var(--palette-foreground-text-dark), 0.05); |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
import { ComponentFixture, TestBed } from '@angular/core/testing'; |
|||
import { RouterTestingModule } from '@angular/router/testing'; |
|||
|
|||
import { GfFooterComponent } from './footer.component'; |
|||
|
|||
describe('GfFooterComponent', () => { |
|||
let component: GfFooterComponent; |
|||
let fixture: ComponentFixture<GfFooterComponent>; |
|||
|
|||
beforeEach(async () => { |
|||
await TestBed.configureTestingModule({ |
|||
imports: [GfFooterComponent, RouterTestingModule] |
|||
}).compileComponents(); |
|||
|
|||
fixture = TestBed.createComponent(GfFooterComponent); |
|||
component = fixture.componentInstance; |
|||
fixture.detectChanges(); |
|||
}); |
|||
|
|||
it('should create', () => { |
|||
expect(component).toBeTruthy(); |
|||
}); |
|||
|
|||
it('should have current year property', () => { |
|||
expect(component.currentYear).toBe(new Date().getFullYear()); |
|||
}); |
|||
|
|||
it('should have router links defined', () => { |
|||
expect(component.routerLinkAbout).toBeDefined(); |
|||
expect(component.routerLinkFeatures).toBeDefined(); |
|||
expect(component.routerLinkResources).toBeDefined(); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,66 @@ |
|||
import { InfoItem, User } from '@ghostfolio/common/interfaces'; |
|||
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; |
|||
import { publicRoutes } from '@ghostfolio/common/routes/routes'; |
|||
import { GfLogoComponent } from '@ghostfolio/ui/logo'; |
|||
|
|||
import { CommonModule } from '@angular/common'; |
|||
import { |
|||
ChangeDetectionStrategy, |
|||
Component, |
|||
CUSTOM_ELEMENTS_SCHEMA, |
|||
Input, |
|||
OnChanges |
|||
} from '@angular/core'; |
|||
import { RouterModule } from '@angular/router'; |
|||
import { IonIcon } from '@ionic/angular/standalone'; |
|||
|
|||
@Component({ |
|||
changeDetection: ChangeDetectionStrategy.OnPush, |
|||
imports: [CommonModule, GfLogoComponent, IonIcon, RouterModule], |
|||
schemas: [CUSTOM_ELEMENTS_SCHEMA], |
|||
selector: 'gf-footer', |
|||
templateUrl: './footer.component.html', |
|||
styleUrls: ['./footer.component.scss'] |
|||
}) |
|||
export class GfFooterComponent implements OnChanges { |
|||
@Input() info: InfoItem; |
|||
@Input() user: User; |
|||
|
|||
public currentYear = new Date().getFullYear(); |
|||
public hasPermissionForStatistics: boolean; |
|||
public hasPermissionForSubscription: boolean; |
|||
public hasPermissionToAccessFearAndGreedIndex: boolean; |
|||
public routerLinkAbout = publicRoutes.about.routerLink; |
|||
public routerLinkAboutChangelog = |
|||
publicRoutes.about.subRoutes.changelog.routerLink; |
|||
public routerLinkAboutLicense = |
|||
publicRoutes.about.subRoutes.license.routerLink; |
|||
public routerLinkAboutPrivacyPolicy = |
|||
publicRoutes.about.subRoutes.privacyPolicy.routerLink; |
|||
public routerLinkAboutTermsOfService = |
|||
publicRoutes.about.subRoutes.termsOfService.routerLink; |
|||
public routerLinkBlog = publicRoutes.blog.routerLink; |
|||
public routerLinkFaq = publicRoutes.faq.routerLink; |
|||
public routerLinkFeatures = publicRoutes.features.routerLink; |
|||
public routerLinkMarkets = publicRoutes.markets.routerLink; |
|||
public routerLinkOpenStartup = publicRoutes.openStartup.routerLink; |
|||
public routerLinkPricing = publicRoutes.pricing.routerLink; |
|||
public routerLinkResources = publicRoutes.resources.routerLink; |
|||
|
|||
public ngOnChanges() { |
|||
this.hasPermissionForStatistics = hasPermission( |
|||
this.info?.globalPermissions, |
|||
permissions.enableStatistics |
|||
); |
|||
|
|||
this.hasPermissionForSubscription = hasPermission( |
|||
this.info?.globalPermissions, |
|||
permissions.enableSubscription |
|||
); |
|||
|
|||
this.hasPermissionToAccessFearAndGreedIndex = hasPermission( |
|||
this.info?.globalPermissions, |
|||
permissions.enableFearAndGreedIndex |
|||
); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue