Skip to content

Commit

Permalink
Merge pull request #2 from OleksandrKirovychDev/reusable-header
Browse files Browse the repository at this point in the history
Reusable header
  • Loading branch information
OleksandrKirovychDev committed Aug 2, 2024
2 parents 8a278cc + ce20365 commit 143c3e8
Show file tree
Hide file tree
Showing 17 changed files with 300 additions and 336 deletions.
Empty file modified .github/workflows/node.js.yml
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea
Empty file modified LICENSE
100644 → 100755
Empty file.
Empty file modified README.md
100644 → 100755
Empty file.
332 changes: 3 additions & 329 deletions tasktrellis/src/app/app.component.html

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions tasktrellis/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ describe('AppComponent', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain(
'Hello, tasktrellis',
);
expect(compiled.querySelector('h1')?.textContent).toContain('TASKTRELLIS');
});
});
6 changes: 4 additions & 2 deletions tasktrellis/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Component } from '@angular/core';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { HeaderComponent } from './core/header/header.component';

@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
imports: [RouterOutlet, HeaderComponent],
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
title = 'tasktrellis';
Expand Down
2 changes: 1 addition & 1 deletion tasktrellis/src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
} from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { provideStore } from '@ngrx/store';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
providers: [
Expand Down
13 changes: 12 additions & 1 deletion tasktrellis/src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
import { Routes } from '@angular/router';
import { AppComponent } from './app.component';

export const routes: Routes = [];
export const routes: Routes = [
{
path: '',
redirectTo: 'home',
pathMatch: 'full',
},
{
path: 'home',
component: AppComponent,
},
];
23 changes: 23 additions & 0 deletions tasktrellis/src/app/core/header/header.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { HeaderComponent } from './header.component';

describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HeaderComponent]
})
.compileComponents();

fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
92 changes: 92 additions & 0 deletions tasktrellis/src/app/core/header/header.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { MatToolbarModule } from '@angular/material/toolbar';
import { DropDownComponent } from '../../shared/components/drop-down/drop-down.component';
import { OverlayModule } from '@angular/cdk/overlay';
import { ProjectListDropdownComponent } from '../project-list-dropdown/project-list-dropdown.component';
import { DropDownButtonComponent } from '../../shared/components/drop-down-button/drop-down-button.component';
import { PortalModule } from '@angular/cdk/portal';

@Component({
selector: 'app-header',
standalone: true,
imports: [
MatToolbarModule,
DropDownComponent,
ProjectListDropdownComponent,
DropDownButtonComponent,
PortalModule,
OverlayModule,
],
template: `
<mat-toolbar role="heading" class="!bg-slate-900 gap-2" [className]="">
<h1 class="text-slate-100 size-7 w-fit !mr-5">TASKTRELLIS</h1>
<app-drop-down-button
#workspacesDropDownButton
cdkOverlayOrigin
#workspacesBtnTrigger="cdkOverlayOrigin"
>
Workspaces
</app-drop-down-button>
<app-drop-down-button
#recentDropDownButton
cdkOverlayOrigin
#recentBtnTrigger="cdkOverlayOrigin"
>
Recent
</app-drop-down-button>
<app-drop-down-button
#starredDropDownButton
cdkOverlayOrigin
#starredBtnTrigger="cdkOverlayOrigin"
>
Starred
</app-drop-down-button>
<app-drop-down-button
#templatesDropDownButton
cdkOverlayOrigin
#templatesBtnTrigger="cdkOverlayOrigin"
>
Templates
</app-drop-down-button>
</mat-toolbar>
<app-drop-down
(clickOutside)="recentDropDownButton.toggleDropDown()"
[isDropDownOpen]="recentDropDownButton.isDropDownOpen"
[trigger]="recentBtnTrigger"
>
<app-project-list-dropdown></app-project-list-dropdown>
</app-drop-down>
<app-drop-down
(clickOutside)="workspacesDropDownButton.toggleDropDown()"
[isDropDownOpen]="workspacesDropDownButton.isDropDownOpen"
[trigger]="workspacesBtnTrigger"
>
<app-project-list-dropdown></app-project-list-dropdown>
</app-drop-down>
<app-drop-down
(clickOutside)="starredDropDownButton.toggleDropDown()"
[isDropDownOpen]="starredDropDownButton.isDropDownOpen"
[trigger]="starredBtnTrigger"
>
<app-project-list-dropdown></app-project-list-dropdown>
</app-drop-down>
<app-drop-down
(clickOutside)="templatesDropDownButton.toggleDropDown()"
[isDropDownOpen]="templatesDropDownButton.isDropDownOpen"
[trigger]="templatesBtnTrigger"
>
<app-project-list-dropdown></app-project-list-dropdown>
</app-drop-down>
`,
styles: [],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HeaderComponent {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ProjectListDropdownComponent } from './project-list-dropdown.component';

describe('ProjectListDropdownComponent', () => {
let component: ProjectListDropdownComponent;
let fixture: ComponentFixture<ProjectListDropdownComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ProjectListDropdownComponent]
})
.compileComponents();

fixture = TestBed.createComponent(ProjectListDropdownComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
selector: 'app-project-list-dropdown',
standalone: true,
imports: [],
template: `
<div class="w-full h-80 bg-slate-800 text-slate-300 rounded-md p-5">
project-list-dropdown works!
</div>
`,
styles: [],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProjectListDropdownComponent {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {
Component,
ChangeDetectionStrategy,
Input,
signal,
WritableSignal,
} from '@angular/core';
import { MatButton } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
@Component({
selector: 'app-drop-down-button',
standalone: true,
imports: [MatButton, MatIconModule],
template: `
<button
[class]="
'flex flex-row-reverse gap-4 justify-center items-center !rounded-md !w-full !p-2 !text-slate-100 hover:bg-slate-600 transition ml-2' +
class
"
mat-button
(click)="isDropDownOpen.set(!isDropDownOpen())"
>
<ng-content></ng-content>
<mat-icon [className]="'text-lg'">keyboard_arrow_down</mat-icon>
</button>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DropDownButtonComponent {
@Input() class!: string;

public isDropDownOpen: WritableSignal<boolean> = signal(false);

public toggleDropDown() {
this.isDropDownOpen.set(!this.isDropDownOpen());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { DropDownButtonComponent } from './drop-down-button.component';

describe('DropDownButtonComponent', () => {
let component: DropDownButtonComponent;
let fixture: ComponentFixture<DropDownButtonComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DropDownButtonComponent],
}).compileComponents();

fixture = TestBed.createComponent(DropDownButtonComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { DropDownComponent } from './drop-down.component';

describe('MenuComponent', () => {
let component: DropDownComponent;
let fixture: ComponentFixture<DropDownComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DropDownComponent],
})
.overrideTemplate(DropDownComponent, '')
.compileComponents();

fixture = TestBed.createComponent(DropDownComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {
ChangeDetectionStrategy,
Component,
EventEmitter,
Input,
Output,
WritableSignal,
} from '@angular/core';
import {
CdkOverlayOrigin,
FlexibleConnectedPositionStrategyOrigin,
OverlayModule,
} from '@angular/cdk/overlay';

@Component({
selector: 'app-drop-down',
standalone: true,
imports: [OverlayModule],
template: `
<ng-template
cdkConnectedOverlay
[cdkConnectedOverlayOrigin]="trigger"
[cdkConnectedOverlayOpen]="isDropDownOpen()"
(overlayOutsideClick)="clickOutside.emit()"
[cdkConnectedOverlayOffsetY]="offsetY"
>
<ng-content></ng-content>
</ng-template>
`,
styles: [],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DropDownComponent {
@Output() clickOutside = new EventEmitter<void>();

@Input({ required: true }) trigger!:
| CdkOverlayOrigin
| FlexibleConnectedPositionStrategyOrigin;
@Input({ required: true }) isDropDownOpen!: WritableSignal<boolean>;

@Input() offsetY = 5;
}

0 comments on commit 143c3e8

Please sign in to comment.