Skip to content

Commit

Permalink
MARP-1205 add timeperiod below publisher of a feedback comment (#208)
Browse files Browse the repository at this point in the history
Co-authored-by: nntthuy-axonivy <[email protected]>
  • Loading branch information
phhung-axonivy and nntthuy-axonivy authored Oct 25, 2024
1 parent c65c39c commit d598a43
Show file tree
Hide file tree
Showing 13 changed files with 334 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@
class="rounded-circle img-avatar img-fit-cover"
[src]="feedback.userAvatarUrl ?? '/assets/images/misc/avatar-default.png'"
alt="Github user avatar" />
<div class="d-flex flex-row align-items-center p-0" style="gap: 10px">
<p class="text-primary mb-0">
{{ feedback.username ?? 'Github User' }}
<div>
<div class="d-flex flex-row align-items-center p-0 gap-3">
<p class="text-primary mb-0">
{{ feedback.username ?? 'Github User' }}
</p>
<i class="bi bi-github text-primary icon-feedback"></i>
</div>
<p class="feedback-time-text">
{{ feedback.updatedAt | timeAgo: languageService.selectedLanguage() | async}}
</p>
<i class="bi bi-github text-primary icon-feedback"></i>
</div>
</div>
<div class="star-rating-container">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,8 @@ $aspect-ratio: math.div(1, 1);
line-height: 21px;
}

.feedback-time-text {
font-size: 1.2rem;
line-height: 1.452rem;
color: var(--text-feedback-time-color);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { CommonModule } from '@angular/common';
import { StarRatingComponent } from '../../../../../../shared/components/star-rating/star-rating.component';
import { ElementRef } from '@angular/core';
import { Feedback } from '../../../../../../shared/models/feedback.model';
import { MissingTranslationHandler, TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
import { httpLoaderFactory } from '../../../../../../core/configs/translate.config';

describe('ProductFeedbackComponent', () => {
let component: ProductFeedbackComponent;
Expand All @@ -21,12 +23,30 @@ describe('ProductFeedbackComponent', () => {
await TestBed.configureTestingModule({
imports: [ProductFeedbackComponent, StarRatingComponent, CommonModule],
providers: [
{ provide: ElementRef, useValue: mockElementRef }
{ provide: ElementRef, useValue: mockElementRef },
TranslateService
]
}).compileComponents();


});

beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: httpLoaderFactory,
},
missingTranslationHandler: {
provide: MissingTranslationHandler,
useValue: { handle: () => 'Translation missing' }
}
})
]
});

fixture = TestBed.createComponent(ProductFeedbackComponent);
component = fixture.componentInstance;
component.feedback = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Component, ElementRef, HostListener, Input, signal, ViewChild } from '@angular/core';
import { Component, ElementRef, HostListener, inject, Input, signal, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { StarRatingComponent } from '../../../../../../shared/components/star-rating/star-rating.component';
import { Feedback } from '../../../../../../shared/models/feedback.model';
import { TimeAgoPipe } from '../../../../../../shared/pipes/time-ago.pipe';
import { LanguageService } from '../../../../../../core/services/language/language.service';

@Component({
selector: 'app-product-feedback',
standalone: true,
imports: [CommonModule, StarRatingComponent],
imports: [CommonModule, StarRatingComponent, TimeAgoPipe],
templateUrl: './product-feedback.component.html',
styleUrl: './product-feedback.component.scss'
})
Expand All @@ -16,6 +18,7 @@ export class ProductFeedbackComponent {

showToggle = signal(false);
isExpanded = signal(false);
languageService = inject(LanguageService);

ngAfterViewInit() {
this.setShowToggle();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { MOCK_EXTERNAL_DOCUMENT } from '../../../../shared/mocks/mock-data';

const TEST_ID = 'portal';
const TEST_VERSION = 'v10.0.0';
const TEST_ACTUAL_VERSION = '10.0.0';
const TEST_ARTIFACT_ID = 'portal-guide';
const TEST_VERSION = '10.0.0';
const TEST_ARTIFACT_NAME = 'Portal Guide';
const TEST_DOC_URL = '/market-cache/portal/portal-guide/10.0.0/doc/index.html';

Expand Down Expand Up @@ -52,7 +50,7 @@ describe('ProductDetailInformationTabComponent', () => {
const changes: SimpleChanges = {
selectedVersion: {
currentValue: TEST_VERSION,
previousValue: 'v8.0.0',
previousValue: '8.0.0',
firstChange: false,
isFirstChange: () => false
},
Expand All @@ -66,7 +64,7 @@ describe('ProductDetailInformationTabComponent', () => {

component.ngOnChanges(changes);

expect(productDetailService.getExteralDocumentForProductByVersion).toHaveBeenCalledWith(TEST_ID, TEST_ACTUAL_VERSION);
expect(productDetailService.getExteralDocumentForProductByVersion).toHaveBeenCalledWith(TEST_ID, TEST_VERSION);
expect(component.externalDocumentLink).toBe(TEST_DOC_URL);
expect(component.displayExternalDocName).toBe(TEST_ARTIFACT_NAME);
});
Expand All @@ -77,7 +75,7 @@ describe('ProductDetailInformationTabComponent', () => {
const changes: SimpleChanges = {
selectedVersion: {
currentValue: '',
previousValue: 'v8.0.0',
previousValue: '8.0.0',
firstChange: false,
isFirstChange: () => false
},
Expand All @@ -97,8 +95,8 @@ describe('ProductDetailInformationTabComponent', () => {
});

it('should extract version value correctly', () => {
const versionDisplayName = TEST_VERSION;
const versionDisplayName = "Version 10.0.0";
const extractedValue = component.extractVersionValue(versionDisplayName);
expect(extractedValue).toBe(TEST_ACTUAL_VERSION);
expect(extractedValue).toBe(TEST_VERSION);
});
});
});
8 changes: 8 additions & 0 deletions marketplace-ui/src/app/shared/constants/common.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,11 @@ export const SEARCH_URL = 'https://developer.axonivy.com/search';
export const SHOW_DEV_VERSION = "showDevVersions";
export const DEFAULT_VENDOR_IMAGE = '/assets/images/misc/axonivy-logo.svg';
export const DEFAULT_VENDOR_IMAGE_BLACK = '/assets/images/misc/axonivy-logo-black.svg';

export const SECONDS_IN_A_MINUTE = 60;
export const MINUTES_IN_A_HOUR = 60;
export const HOURS_IN_A_DAY = 24;
export const DAYS_IN_A_WEEK = 7;
export const DAYS_IN_A_MONTH = 30;
export const DAYS_IN_A_YEAR = 365;

16 changes: 16 additions & 0 deletions marketplace-ui/src/app/shared/enums/time-ago.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export enum TimeAgo {
YEAR_AGO = 'common.timeAgo.yearAgo',
YEARS_AGO = 'common.timeAgo.yearsAgo',
MONTH_AGO = 'common.timeAgo.monthAgo',
MONTHS_AGO = 'common.timeAgo.monthsAgo',
WEEK_AGO = 'common.timeAgo.weekAgo',
WEEKS_AGO = 'common.timeAgo.weeksAgo',
DAY_AGO = 'common.timeAgo.dayAgo',
DAYS_AGO = 'common.timeAgo.daysAgo',
HOUR_AGO = 'common.timeAgo.hourAgo',
HOURS_AGO = 'common.timeAgo.hoursAgo',
MINUTE_AGO = 'common.timeAgo.minuteAgo',
MINUTES_AGO = 'common.timeAgo.minutesAgo',
SECOND_AGO = 'common.timeAgo.secondAgo',
SECONDS_AGO = 'common.timeAgo.secondsAgo',
}
4 changes: 2 additions & 2 deletions marketplace-ui/src/app/shared/models/feedback.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ export interface Feedback {
username?: string;
userAvatarUrl?: string;
userProvider?: string;
createdDate?: Date;
updatedDate?: Date;
createdAt?: Date;
updatedAt?: Date;
content: string;
rating: number;
productId: string;
Expand Down
156 changes: 156 additions & 0 deletions marketplace-ui/src/app/shared/pipes/time-ago.pipe.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import { TestBed } from '@angular/core/testing';
import {
MissingTranslationHandler,
TranslateLoader,
TranslateModule,
TranslateService
} from '@ngx-translate/core';
import { Language } from '../enums/language.enum';
import { TimeAgo } from '../enums/time-ago.enum';
import { TimeAgoPipe } from './time-ago.pipe';
import { httpLoaderFactory } from '../../core/configs/translate.config';

describe('TimeAgoPipe', () => {
let pipe: TimeAgoPipe;
let translateService: TranslateService;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: httpLoaderFactory
},
missingTranslationHandler: {
provide: MissingTranslationHandler,
useValue: { handle: () => 'Translation missing' }
}
})
],
providers: [TimeAgoPipe]
});

translateService = TestBed.inject(TranslateService);
pipe = TestBed.inject(TimeAgoPipe);
});

it('should render the text 1 year ago', () => {
const oneYearAgo = new Date();
oneYearAgo.setFullYear(new Date().getFullYear() - 1);
expect(pipe.getTimeAgoValue(oneYearAgo)).toBe(
translateService.instant(TimeAgo.YEAR_AGO)
);
});

it('should render the text 2 years ago', () => {
const twoYearsAgo = new Date();
twoYearsAgo.setFullYear(new Date().getFullYear() - 2);
expect(pipe.getTimeAgoValue(twoYearsAgo)).toBe(
translateService.instant(TimeAgo.YEARS_AGO, { number: 2 })
);
});

it('should render the text 1 month ago', () => {
const oneMonthAgo = new Date();
oneMonthAgo.setMonth(new Date().getMonth() - 1);
expect(pipe.getTimeAgoValue(oneMonthAgo)).toBe(
translateService.instant(TimeAgo.MONTH_AGO)
);
});

it('should render the text 2 months ago', () => {
const twoMonthsAgo = new Date();
twoMonthsAgo.setMonth(new Date().getMonth() - 2);
expect(pipe.getTimeAgoValue(twoMonthsAgo)).toBe(
translateService.instant(TimeAgo.MONTHS_AGO, { number: 2 })
);
});

it('should render the text 1 week ago', () => {
const oneWeekAgo = new Date();
oneWeekAgo.setDate(new Date().getDate() - 7);
expect(pipe.getTimeAgoValue(oneWeekAgo)).toBe(
translateService.instant(TimeAgo.WEEK_AGO)
);
});

it('should render the text 2 weeks ago', () => {
const twoWeeksAgo = new Date();
twoWeeksAgo.setDate(new Date().getDate() - 14);
expect(pipe.getTimeAgoValue(twoWeeksAgo)).toBe(
translateService.instant(TimeAgo.WEEKS_AGO, { number: 2 })
);
});

it('should render the text 1 day ago', () => {
const oneDayAgo = new Date();
oneDayAgo.setDate(new Date().getDate() - 1);
expect(pipe.getTimeAgoValue(oneDayAgo)).toBe(
translateService.instant(TimeAgo.DAY_AGO)
);
});

it('should render the text 2 days ago', () => {
const twoDaysAgo = new Date();
twoDaysAgo.setDate(new Date().getDate() - 2);
expect(pipe.getTimeAgoValue(twoDaysAgo)).toBe(
translateService.instant(TimeAgo.DAYS_AGO, { number: 2 })
);
});

it('should render the text 1 hour ago', () => {
const oneHourAgo = new Date();
oneHourAgo.setHours(new Date().getHours() - 1);
expect(pipe.getTimeAgoValue(oneHourAgo)).toBe(
translateService.instant(TimeAgo.HOUR_AGO)
);
});

it('should render the text 2 hours ago', () => {
const twoHoursAgo = new Date();
twoHoursAgo.setHours(new Date().getHours() - 2);
expect(pipe.getTimeAgoValue(twoHoursAgo)).toBe(
translateService.instant(TimeAgo.HOURS_AGO, { number: 2 })
);
});

it('should render the text 1 minute ago', () => {
const oneMinuteAgo = new Date();
oneMinuteAgo.setMinutes(new Date().getMinutes() - 1);
expect(pipe.getTimeAgoValue(oneMinuteAgo)).toBe(
translateService.instant(TimeAgo.MINUTE_AGO)
);
});

it('should render the text 2 minutes ago', () => {
const twoMinutesAgo = new Date();
twoMinutesAgo.setMinutes(new Date().getMinutes() - 2);
expect(pipe.getTimeAgoValue(twoMinutesAgo)).toBe(
translateService.instant(TimeAgo.MINUTES_AGO, { number: 2 })
);
});

it('should render the text 1 second ago', () => {
expect(pipe.getTimeAgoValue(new Date())).toBe(
translateService.instant(TimeAgo.SECOND_AGO)
);
pipe.transform(new Date(), Language.EN).then(result => {
expect(result).toBe(translateService.instant(TimeAgo.SECOND_AGO));
});

const oneSecondAgo = new Date();
oneSecondAgo.setSeconds(new Date().getSeconds() - 1);
expect(pipe.getTimeAgoValue(oneSecondAgo)).toBe(
translateService.instant(TimeAgo.SECOND_AGO)
);
});

it('should render the text 2 seconds ago', () => {
const twoSecondsAgo = new Date();
twoSecondsAgo.setSeconds(new Date().getSeconds() - 2);
expect(pipe.getTimeAgoValue(twoSecondsAgo)).toBe(
translateService.instant(TimeAgo.SECONDS_AGO, { number: 2 })
);
});
});
Loading

0 comments on commit d598a43

Please sign in to comment.