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