Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: move components to angular-accelerator #526

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div ocxContentContainer [layout]="layout" [breakpoint]="breakpoint" [style]="styleClass">
<ng-content></ng-content>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { OcxContentContainerHarness } from '../../../../testing/content-container.harness'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { OcxContentContainerComponent } from './content-container.component'
import { OcxContentContainerDirective } from '../../directives/content-container.directive'
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'

describe('OcxContentContainerComponent', () => {
let component: OcxContentContainerComponent
let fixture: ComponentFixture<OcxContentContainerComponent>
let ocxContentContainerHarness: OcxContentContainerHarness

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

fixture = TestBed.createComponent(OcxContentContainerComponent)
component = fixture.componentInstance
ocxContentContainerHarness = await TestbedHarnessEnvironment.harnessForFixture(fixture, OcxContentContainerHarness)
})

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

it('should render a horizontal layout container with md breakpoint by default', async () => {
const expectedClasses = ['flex', 'gap-3', 'flex-column', 'md:flex-row']
expect(await ocxContentContainerHarness.getLayoutClasses()).toEqual(expectedClasses)
expect(await ocxContentContainerHarness.getLayout()).toEqual('horizontal')
expect(await ocxContentContainerHarness.getBreakpoint()).toEqual('md')
})

it('should render a horizontal layout container while respecting a specified breakpoint', async () => {
component.breakpoint = 'lg'

const expectedClassesLG = ['flex', 'gap-3', 'flex-column', 'lg:flex-row']
expect(await ocxContentContainerHarness.getLayoutClasses()).toEqual(expectedClassesLG)
expect(await ocxContentContainerHarness.getLayout()).toEqual('horizontal')
expect(await ocxContentContainerHarness.getBreakpoint()).toEqual('lg')
})

it('should render a vertical layout container if specified', async () => {
component.layout = 'vertical'

const expectedClasses = ['flex', 'gap-3', 'flex-column']
expect(await ocxContentContainerHarness.getLayoutClasses()).toEqual(expectedClasses)
expect(await ocxContentContainerHarness.getLayout()).toEqual('vertical')
expect(await ocxContentContainerHarness.getBreakpoint()).toBeUndefined()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default {
breakpoint: {
options: ['sm', 'md', 'lg', 'xl'],
control: { type: 'select' },
}
},
},
decorators: [
moduleMetadata({
Expand All @@ -38,7 +38,7 @@ export const Basic = {
}),
args: {
layout: 'horizontal',
breakpoint: 'md'
breakpoint: 'md',
},
}

Expand All @@ -60,7 +60,7 @@ export const WithNestedOCXContent = {
}),
args: {
layout: 'horizontal',
breakpoint: 'md'
breakpoint: 'md',
},
}

Expand All @@ -84,7 +84,23 @@ export const WithNestedOCXContentContainer = {
}),
args: {
layout: 'horizontal',
breakpoint: 'md'
breakpoint: 'md',
},
}

export const WithStyleClass = {
render: (args: OcxContentComponent) => ({
props: {
...args,
},
template: `
<ocx-content-container styleClass="${args.styleClass}">
<p>Content inside of ocx-content-container with styleClass</p>
</ocx-content-container>
`,
}),
args: {
styleClass: 'color: red',
},
}

Expand All @@ -102,6 +118,6 @@ export const DirectiveOnly = {
}),
args: {
layout: 'horizontal',
breakpoint: 'md'
breakpoint: 'md',
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Component, Input } from '@angular/core'

@Component({
selector: 'ocx-content-container',
templateUrl: './content-container.component.html',
})
export class OcxContentContainerComponent {
/**
* Allows specifying the layout direction of the container
*/
@Input() layout: 'vertical' | 'horizontal' = 'horizontal'

/**
* Allows specifying the breakpoint below which a horizontal layout switches to a vertical layout.
* Only necessary if horizontal layout is used
* Default: md
*/
@Input() breakpoint: 'sm' | 'md' | 'lg' | 'xl' = 'md'

/**
* Optionally allows specifying styles for the container
*/
@Input() styleClass = ''
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div [ocxContent]="title" [style]="styleClass">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The styleClass input should be applied as a class, not as a custom style. The same also applies to the content container component. Please also make sure that the style classes provided via input have a higher priority than the classes which are added by the directive itself. This way we don't only allow devs to specify additional classes but also allow them to overwrite existing style classes such as padding through the given input.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please verify the class merging behavior described above in a unit test.

<ng-content></ng-content>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { OcxContentHarness } from '../../../../testing/content.harness'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { OcxContentComponent } from './content.component'
import { OcxContentDirective } from '../../directives/content.directive'
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'

describe('OcxContentComponent', () => {
let component: OcxContentComponent
let fixture: ComponentFixture<OcxContentComponent>
let ocxContentHarness: OcxContentHarness
const testComponentTitle = 'My cool title'

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

fixture = TestBed.createComponent(OcxContentComponent)
component = fixture.componentInstance
ocxContentHarness = await TestbedHarnessEnvironment.harnessForFixture(fixture, OcxContentHarness)
})

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

it('should render a ocxContent card with no title by default', async () => {
const expectedClasses = ['card']
expect(await ocxContentHarness.getContentClasses()).toEqual(expectedClasses)
expect(await ocxContentHarness.hasTitle()).toEqual(false)
})

it('should render a ocxContent card with a title, when given a title via input', async () => {
const expectedClasses = ['card']
expect(await ocxContentHarness.getContentClasses()).toEqual(expectedClasses)
expect(await ocxContentHarness.hasTitle()).toEqual(false)

component.title = testComponentTitle

const expectedTitleClasses = ['font-medium', 'text-lg']
expect(await ocxContentHarness.hasTitle()).toEqual(true)
expect(await ocxContentHarness.getTitle()).toEqual(testComponentTitle)
expect(await ocxContentHarness.getTitleClasses()).toEqual(expectedTitleClasses)
})
})
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { OcxContentDirective } from '../../directives/content.directive';
import { OcxContentComponent } from './content.component';
import { OcxContentDirective } from '../../directives/content.directive'
import { OcxContentComponent } from './content.component'
import { moduleMetadata, Meta } from '@storybook/angular'

export default {
title: 'ContentComponent',
component: OcxContentComponent,
decorators: [
moduleMetadata({
declarations: [
OcxContentDirective,
]
declarations: [OcxContentDirective],
}),
],
} as Meta<OcxContentComponent>
Expand All @@ -26,7 +24,7 @@ export const WithTitle = {
`,
}),
args: {
title: 'My Title'
title: 'My Title',
},
}

Expand All @@ -43,6 +41,22 @@ export const WithoutTitle = {
}),
}

export const WithStyleClass = {
render: (args: OcxContentComponent) => ({
props: {
...args,
},
template: `
<ocx-content styleClass="${args.styleClass}">
<p>Content inside of ocx-content with styleClass</p>
</ocx-content>
`,
}),
args: {
styleClass: 'color: red',
},
}

export const DirectiveOnly = {
render: (args: OcxContentComponent) => ({
props: {
Expand All @@ -55,6 +69,6 @@ export const DirectiveOnly = {
`,
}),
args: {
title: 'My Title'
title: 'My Title',
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Component, Input } from '@angular/core'

@Component({
selector: 'ocx-content',
templateUrl: './content.component.html',
})
export class OcxContentComponent {
/**
* Optionally allows specifying a title for the content card
*/
@Input() title = ''

/**
* Optionally allows specifying styles for the content card
*/
@Input() styleClass = ''
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
<div class="flex align-items-center gap-2">
<p-dropdown
id="dataListGridSortingDropdown"
[(ngModel)]="selectedSortingOption"
class="sort-dropdown"
[options]="dropdownOptions"
[placeholder]="('OCX_LIST_GRID_SORT.DROPDOWN.PLACEHOLDER' | translate)"
(onChange)="selectSorting($event)"
[ariaLabel]="('OCX_LIST_GRID_SORT.DROPDOWN.ARIA_LABEL' | translate)"
>
<ng-template let-item pTemplate="item"> {{ item?.columnName ? (item.columnName | translate) : ''}} </ng-template>
<ng-template let-item pTemplate="selectedItem">
{{ item?.columnName ? (item.columnName | translate) : ''}}
</ng-template></p-dropdown
>
<p-floatLabel>
<p-dropdown
id="dataListGridSortingDropdown"
[(ngModel)]="selectedSortingOption"
class="sort-dropdown"
[options]="dropdownOptions"
[placeholder]="('OCX_LIST_GRID_SORT.DROPDOWN.PLACEHOLDER' | translate)"
(onChange)="selectSorting($event)"
[ariaLabel]="('OCX_LIST_GRID_SORT.DROPDOWN.ARIA_LABEL' | translate)"
>
<ng-template let-item pTemplate="item"> {{ item?.columnName ? (item.columnName | translate) : ''}} </ng-template>
<ng-template let-item pTemplate="selectedItem">
{{ item?.columnName ? (item.columnName | translate) : ''}}
</ng-template></p-dropdown
>
<label for="dataListGridSortingDropdown">{{ ("OCX_LIST_GRID_SORT.DROPDOWN.ARIA_LABEL" | translate) }}</label>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please create a separate translation OCX_LIST_GRID_SORT.DROPDOWN.LABEL for the floating label? This way, we can change the aria label in the future without unexpectedly modifying the displayed floating label. The new translation key can have the exact same value as the previously used aria label translation.

</p-floatLabel>
<p-button
id="dataListGridSortingButton"
type="button"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<p-timeline [value]="steps">
<ng-template pTemplate="marker" let-step>
<span
class="p-timeline-event-marker"
[ngClass]="activeStepId && activeStepId === step.id ? 'bg-primary' : ''"
></span>
</ng-template>
<ng-template pTemplate="content" let-step>
<div class="pb-4 h-full">
<div class="card h-full" [ngClass]="activeStepId && activeStepId === step.id ? 'bg-primary' : ''">
<p class="font-bold text-xl" [ngClass]="step.details ? 'mb-2' : ''">{{ step.title }}</p>
<p *ngIf="step.details" [ngClass]="activeStepId && activeStepId === step.id ? '' : 'text-color-secondary'">
{{ step.details }}
</p>
</div>
</div>
</ng-template>
</p-timeline>
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { LifecycleComponent, LifecycleStep } from './lifecycle.component'
import { TimelineModule } from 'primeng/timeline'
import { LifecycleHarness } from '../../../../testing/lifecycle.harness'
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'

const mockSteps: LifecycleStep[] = [
{
id: 'test1',
title: 'Test 1',
},
{
id: 'test2',
title: 'Test 2',
details: 'Test 2 description',
},
{
id: 'test3',
title: 'Test 3',
},
]

describe('LifecycleComponent', () => {
let component: LifecycleComponent
let fixture: ComponentFixture<LifecycleComponent>
let lifecycle: LifecycleHarness

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [LifecycleComponent],
imports: [TimelineModule, BrowserAnimationsModule],
}).compileComponents()

fixture = TestBed.createComponent(LifecycleComponent)
component = fixture.componentInstance
fixture.detectChanges()
lifecycle = await TestbedHarnessEnvironment.harnessForFixture(fixture, LifecycleHarness)
})

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

it('should not render any initial lifecycle steps', async () => {
const steps = await lifecycle.getSteps()
expect(steps.length).toBe(0)
})

it('should render given lifecycle steps', async () => {
component.steps = mockSteps
const steps = await lifecycle.getSteps()
const highlightedSteps = await lifecycle.getHighlightedSteps()
expect(steps.length).toBe(3)
expect(highlightedSteps.length).toBe(0)
mockSteps.forEach(async (step, index) => {
expect(await steps[index].text()).toEqual(step.title + (step.details ?? ''))
})
})

it('should highlight a given lifecycle step', async () => {
component.steps = mockSteps
component.activeStepId = 'test2'
const steps = await lifecycle.getSteps()
const highlightedSteps = await lifecycle.getHighlightedSteps()
mockSteps.forEach(async (step, index) => {
if (step.id == component.activeStepId) {
expect(await steps[index].hasClass('bg-primary')).toEqual(true)
}
})
expect(steps.length).toBe(3)
expect(highlightedSteps.length).toBe(1)
})
})
Loading