Skip to content

Commit

Permalink
feat(timeline): added timeline component
Browse files Browse the repository at this point in the history
Co-authored-by: Stefano Zanelli <stefano.zanelli@unitn.it>
  • Loading branch information
AntoninoBonanno and stefanozanelliunitn authored Jul 12, 2024
1 parent be076df commit 147b8f5
Show file tree
Hide file tree
Showing 27 changed files with 520 additions and 1 deletion.
5 changes: 5 additions & 0 deletions projects/design-angular-kit/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@
"aria-label-toggle": "Show/Hide navigation",
"hide": "Hide navigation"
},
"timeline": {
"read-more": "Read more",
"read-more-on": "on {{title}}",
"today": "Today"
},
"utils": {
"selected": "Selected",
"language-selection": "Language selection: {{lang}}",
Expand Down
5 changes: 5 additions & 0 deletions projects/design-angular-kit/assets/i18n/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@
"aria-label-toggle": "Mostra/Nascondi la navigazione",
"hide": "Nascondi la navigazione"
},
"timeline": {
"read-more": "Leggi di più",
"read-more-on": "su {{title}}",
"today": "Oggi"
},
"utils": {
"selected": "Selezionata",
"language-selection": "Selezione lingua: {{lang}}",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<div class="timeline-element">
@if (pinType === 'now') {
<span class="it-now-label d-none d-lg-flex">{{ 'it.timeline.today' | translate }}</span>
}
<div class="it-pin-wrapper" [ngClass]="{ 'it-evidence': pinType === 'evidence', 'it-now': pinType === 'now' }">
<div class="pin-icon">
@if (pinIcon) {
<it-icon [name]="pinIcon"></it-icon>
} @else {
<it-icon name="code-circle"></it-icon>
}
</div>
<div class="pin-text">
<span>{{ pinText }}</span>
</div>
</div>
<div class="card-wrapper">
<div class="card">
<div class="card-body">
@if ((categoryTitle && categoryLink) || eventDate) {
<div class="category-top">
@if (categoryTitle) {
<a class="category" [href]="categoryLink">{{ categoryTitle }}</a>
}
@if (eventDate) {
<span class="data">{{ eventDate | date: dateFormat }}</span>
}
</div>
}
<h5 class="card-title">{{ title }}</h5>
<p class="card-text">{{ text }}</p>
@if (signature) {
<span class="card-signature">{{ signature }}</span>
}
@if (showReadMore) {
<a class="read-more" [href]="readMoreLink">
<span class="text">{{ 'it.timeline.read-more' | translate }}</span>
<span class="visually-hidden">{{ 'it.timeline.read-more-on' | translate: { title: title } }}</span>
<it-icon name="arrow-right"></it-icon>
</a>
}
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ItTimelineItemComponent } from './timeline-item.component';
import { tb_base } from '../../../../../test';

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

beforeEach(async () => {
await TestBed.configureTestingModule(tb_base).compileComponents();

// await TestBed.configureTestingModule({
// imports: [ItTimelineItemComponent],
// }).compileComponents();

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

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { ItAbstractComponent } from '../../../../abstracts/abstract.component';
import { ItIconComponent } from '../../../utils/icon/icon.component';
import { DatePipe, NgClass } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { TimelinePINType } from '../../../../interfaces/core';
import { IconName } from '../../../../interfaces/icon';
import { inputToBoolean } from '../../../../utils/coercion';

/**
* Timeline Item
* @description Represents a single event for Timeline component.
*/
@Component({
standalone: true,
selector: 'it-timeline-item',
templateUrl: './timeline-item.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ItIconComponent, DatePipe, TranslateModule, NgClass],
})
export class ItTimelineItemComponent extends ItAbstractComponent {
/**
* Timeline element title
*/
@Input({ required: true }) title!: string;

/**
* Timeline element text
*/
@Input({ required: true }) text!: string;

/**
* Timeline element signature
*/
@Input() signature: string | undefined;

/**
* Timeline element reference date
*/
@Input() eventDate: Date | undefined;

/**
* Timeline element reference date format
* @default dd/MM/yyyy
*/
@Input() dateFormat: string = 'dd/MM/yyyy';

/**
* Timeline element PIN text
*/
@Input({ required: true }) pinText: string | undefined;

/**
* Timeline element PIN type
* @default none
*/
@Input() pinType: TimelinePINType | undefined = 'default';

/**
* Timeline element PIN icon
* @default code-circle
*/
@Input() pinIcon: IconName | undefined = 'code-circle';

/**
* Timeline element category title
*/
@Input() categoryTitle: string | undefined;

/**
* Timeline element category link
*/
@Input() categoryLink: string | undefined;

/**
* Timeline element show detail link
* @default false
*/
@Input({ transform: inputToBoolean })
showReadMore: boolean = false;

/** Timeline element detail link
* @default #
*/
@Input() readMoreLink: string | undefined = '#';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div class="it-timeline-wrapper">
<div class="row">
@for (element of timelineElements; track $index) {
<div class="col-12">
<it-timeline-item
[title]="element.title"
[text]="element.text"
[signature]="element.signature"
[pinType]="element.pin?.type"
[pinIcon]="element.pin?.icon"
[pinText]="element.pin?.text"
[eventDate]="element.eventDate"
[dateFormat]="dateFormat"
[categoryTitle]="element.category?.title"
[categoryLink]="element.category?.link"
[showReadMore]="!!element.link?.length"
[readMoreLink]="element.link" />
</div>
}
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ItTimelineComponent } from './timeline.component';
import { tb_base } from '../../../../test';

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

beforeEach(async () => {
await TestBed.configureTestingModule(tb_base).compileComponents();

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

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { ItTimelineItemComponent } from './timeline-item/timeline-item.component';
import { ItIconComponent } from '../../utils/icon/icon.component';
import { TranslateModule } from '@ngx-translate/core';
import { ItAbstractComponent } from '../../../abstracts/abstract.component';
import { TimelineElement } from '../../../interfaces/core';

/**
* Timeline
* @description Build timeline for chronological representation of events.
*/
@Component({
standalone: true,
selector: 'it-timeline',
templateUrl: './timeline.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ItIconComponent, TranslateModule, ItTimelineItemComponent],
})
export class ItTimelineComponent extends ItAbstractComponent {
/**
* Timeline elements array
* @default []
*/
@Input() timelineElements: TimelineElement[] = [];

/**
* Default date format for timeline element reference date
* @default dd/MM/yyyy
*/
@Input() dateFormat: string = 'dd/MM/yyyy';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { NgModule } from '@angular/core';
import { ItTimelineComponent } from './timeline.component';
import { ItTimelineItemComponent } from './timeline-item/timeline-item.component';

const timelineComponents = [ItTimelineComponent, ItTimelineItemComponent];

@NgModule({
imports: timelineComponents,
exports: timelineComponents,
})
export class ItTimelineModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { ItLanguageSwitcherComponent } from './components/utils/language-switche
import { ItDateAgoPipe } from './pipes/date-ago.pipe';
import { ItDurationPipe } from './pipes/duration.pipe';
import { ItMarkMatchingTextPipe } from './pipes/mark-matching-text.pipe';
import { ItTimelineModule } from './components/core/timeline/timeline.module';

/**
* Core components
Expand Down Expand Up @@ -72,6 +73,7 @@ const core = [
ItTabModule,
ItTableModule,
ItTooltipDirective,
ItTimelineModule,
];

/**
Expand Down
19 changes: 19 additions & 0 deletions projects/design-angular-kit/src/lib/interfaces/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ export type DropdownDirection = 'dropup' | 'dropend' | 'dropstart';

export type CarouselType = 'default' | 'three-cols' | 'three-cols-arrow-visible';

export type TimelinePINType = 'default' | 'evidence' | 'now';

export interface TimelineElement {
pin: {
type?: TimelinePINType;
icon?: IconName;
text: string;
};
category?: {
title: string;
link: string;
};
title: string;
text: string;
signature?: string;
eventDate?: Date;
link?: string;
}

export interface Notification {
/**
* Notification type
Expand Down
1 change: 1 addition & 0 deletions projects/design-angular-kit/src/lib/interfaces/icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const IconNameArray = [
'close',
'close-big',
'close-circle',
'code-circle',
'comment',
'copy',
'delete',
Expand Down
4 changes: 4 additions & 0 deletions projects/design-angular-kit/src/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ export * from './lib/components/core/table/table.component';
export * from './lib/components/core/table/sort/sort.directive';
export * from './lib/components/core/table/sort/sort-header/sort-header.component';

export * from './lib/components/core/timeline/timeline.module';
export * from './lib/components/core/timeline/timeline.component';
export * from './lib/components/core/timeline/timeline-item/timeline-item.component';

export * from './lib/components/core/tooltip/tooltip.directive';

// Forms components
Expand Down
1 change: 1 addition & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const routes: Routes = [
{ path: 'range', loadChildren: () => import('src/app/range/range.module').then(m => m.RangeModule) },
{ path: 'autocomplete', loadChildren: () => import('src/app/autocomplete/autocomplete.module').then(m => m.AutocompleteModule) },
{ path: 'sidebar', loadChildren: () => import('src/app/sidebar/sidebar.module').then(m => m.SidebarModule) },
{ path: 'timeline', loadChildren: () => import('src/app/timeline/timeline.module').then(m => m.TimelineModule) },
],
},
{ path: 'error/not-found', component: ItErrorPageComponent, data: { errorCode: 404 } },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<h3>Esempi</h3>

<div class="bd-example">
<div class="example-section">
<it-timeline [timelineElements]="timelineElements" [dateFormat]="defaultDateFormat" />
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { TimelineDefaultExampleComponent } from './timeline-default-example.component';

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

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

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

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading

0 comments on commit 147b8f5

Please sign in to comment.