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

Fix sizing/overflow issues #399

Merged
merged 4 commits into from
Apr 16, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
490 changes: 288 additions & 202 deletions client-v2/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions client-v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
"@ngrx/effects": "^14.3.2",
"@ngrx/store": "^14.3.2",
"@ngrx/store-devtools": "^14.3.2",
"@rx-angular/cdk": "^14.0.0",
"@rx-angular/template": "^14.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.5.0",
"zone.js": "^0.12.0"
Expand Down
8 changes: 8 additions & 0 deletions client-v2/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ import { LayoutModule } from '@angular/cdk/layout'
import { IntersectionDirective } from './directives/intersection.directive'
import { EntityDescriptionComponent } from './components/molecules/entity-description/entity-description.component'
import { ApplicationinsightsAngularpluginErrorService } from '@microsoft/applicationinsights-angularplugin-js'
import { LetModule } from '@rx-angular/template/let'
import { IfModule } from '@rx-angular/template/if'
import { ForModule } from '@rx-angular/template/for'
import { PushModule } from '@rx-angular/template/push'

@NgModule({
declarations: [
Expand Down Expand Up @@ -141,6 +145,10 @@ import { ApplicationinsightsAngularpluginErrorService } from '@microsoft/applica
OverlayModule,
CdkTreeModule,
LayoutModule,
LetModule,
IfModule,
ForModule,
PushModule,
],
providers: [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:host {
@apply inline-flex overflow-x-auto
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<span
class="inline-block cursor-text outline-none"
class="inline-block cursor-text overflow-x-auto outline-none"
[innerText]="text$ | async"
[class.show-placeholder]="!(textDomState$ | async)"
[class]="editorClass"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
:host-context(.no-delay) {
--reveal-delay: 0ms;
}
:host {
@apply box-border block max-w-xs rounded-lg border border-tinted-600/60 bg-tinted-700 glass py-1 px-2 text-sm text-tinted-100 shadow-xl;
@apply box-border block max-w-xs rounded-lg border border-tinted-600/60 bg-tinted-700 py-1 px-2 text-sm text-tinted-100 shadow-xl glass overflow-hidden;

animation: reveal 130ms 280ms forwards;
animation: reveal 130ms var(--reveal-delay, 280ms) forwards;
scale: 0.8;
opacity: 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
<ng-container *ngIf="asTemplate as template">
<ng-template [ngTemplateOutlet]="template"></ng-template>
</ng-container>

<ng-content></ng-content>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, Inject, TemplateRef } from '@angular/core'
import { ChangeDetectionStrategy, Component, Inject, Optional, TemplateRef } from '@angular/core'
import { InjectionToken } from '@angular/core'

export type TooltipData = TemplateRef<void> | string
Expand All @@ -14,7 +14,7 @@ export const TOOLTIP_DATA = new InjectionToken<TooltipData>('tooltip.data')
},
})
export class TooltipComponent {
constructor(@Inject(TOOLTIP_DATA) public tooltipData: TooltipData) {}
constructor(@Optional() @Inject(TOOLTIP_DATA) public tooltipData?: TooltipData) {}

get asString(): string | false {
return typeof this.tooltipData === 'string' ? this.tooltipData : false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,80 @@
<!-- @TODO: Fix the header width issue (breadcrumbs taking more than allowed) -->
<div
class="breadcrumbs | flex w-full flex-wrap py-2 px-4 text-tinted-300"
class="breadcrumbs | flex w-full overflow-x-auto py-2 px-4 text-tinted-300"
cdkMenuBar
data-test-name="breadcrumbs-container"
#breadcrumbsContainer
>
<div *ngFor="let breadcrumb of breadcrumbs; let isLast = last; trackBy: trackByFn" class="flex max-w-[80%]">
<button
class="breadcrumb | menu-item | max-w-[20ch] truncate py-0.5 px-1.5"
[class.text-tinted-100]="isLast"
cdkMenuItem
[cdkContextMenuTriggerFor]="menu"
[routerLink]="breadcrumb.route"
#trigger="cdkContextMenuTriggerFor"
data-test-name="breadcrumb"
>
<!-- appTooltip="Here will be more information" -->
<ng-template #menu>
<app-drop-down
*ngIf="breadcrumb.contextMenuItems?.length"
[items]="breadcrumb.contextMenuItems!"
[rootTrigger]="trigger"
></app-drop-down>
<div *rxFor="let breadcrumb of breadcrumbs$; let isLast = last; trackBy: trackByFn" class="flex max-w-[80%]">
<!-- @TODO: some fuckery is going on here with the cdkMenuItem, destroying the menu bar flow and not acting like a proper menu item -->
<ng-container *ngIf="isTruncationBreadcrumb(breadcrumb)">
<button
class="truncation-breadcrumb | menu-item | truncate py-0.5 px-1.5 font-bold"
cdkMenuItem
cdkOverlayOrigin
#trigger="cdkOverlayOrigin"
(click)="isOverlayOpen$.next(!isOverlayOpen$.value)"
data-test-name="truncation-breadcrumb"
>
...
</button>

<ng-template
cdkConnectedOverlay
[cdkConnectedOverlayOrigin]="trigger"
[cdkConnectedOverlayOpen]="(isOverlayOpen$ | async) ?? false"
(overlayOutsideClick)="closeOverlayDelayed()"
>
<app-tooltip class="bottom no-delay !border-tinted-800 !bg-tinted-900/70 !px-1">
<div class="flex flex-col text-base" cdkMenu data-test-name="truncated-breadcrumbs-container">
<div
*rxFor="
let truncatedBreadcrumb of breadcrumb.truncated;
let index = index;
trackBy: trackByFn
"
[style]="{ marginLeft: 0.5 * index + 'rem' }"
>
<ng-container
*ngTemplateOutlet="
breadcrumbTemplate;
context: { breadcrumb: truncatedBreadcrumb, isLast: false }
"
></ng-container>
</div>
</div>
</app-tooltip>
</ng-template>
</ng-container>

<ng-container *ngIf="!isTruncationBreadcrumb(breadcrumb)">
<ng-container *ngTemplateOutlet="breadcrumbTemplate; context: { breadcrumb, isLast }"></ng-container>
</ng-container>

<app-entity-page-label [pageTitle]="breadcrumb.title" [pageIcon]="breadcrumb.icon"></app-entity-page-label>
</button>
<span class="seperator | mx-0.5 text-tinted-500" *ngIf="!isLast">/</span>
<span class="separator | mx-0.5 text-tinted-500" *ngIf="!isLast">/</span>
</div>
</div>

<ng-template #breadcrumbTemplate let-breadcrumb="breadcrumb" let-isLast="isLast">
<button
*ngIf="!isTruncationBreadcrumb(breadcrumb)"
class="breadcrumb | menu-item | max-w-[20ch] truncate py-0.5 px-1.5"
[class.text-tinted-100]="isLast"
cdkMenuItem
[cdkContextMenuTriggerFor]="menu"
[routerLink]="breadcrumb.route"
(click)="closeOverlayDelayed()"
#trigger="cdkContextMenuTriggerFor"
data-test-name="breadcrumb"
>
<!-- appTooltip="Here will be more information" -->
<ng-template #menu>
<app-drop-down
*ngIf="breadcrumb.contextMenuItems?.length"
[items]="breadcrumb.contextMenuItems!"
[rootTrigger]="trigger"
></app-drop-down>
</ng-template>

<app-entity-page-label [pageTitle]="breadcrumb.title" [pageIcon]="breadcrumb.icon"></app-entity-page-label>
</button>
</ng-template>
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'

import { BreadcrumbsComponent } from './breadcrumbs.component'
import { menuServiceMock } from 'src/app/utils/unit-test.mocks'

describe('BreadcrumbsComponent', () => {
let component: BreadcrumbsComponent
Expand All @@ -9,6 +10,7 @@ describe('BreadcrumbsComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [BreadcrumbsComponent],
providers: [menuServiceMock],
}).compileComponents()

fixture = TestBed.createComponent(BreadcrumbsComponent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@ import { EntityPageLabelComponent } from '../../atoms/entity-page-label/entity-p
import { IconsModule } from '../../atoms/icons/icons.module'
import { DropDownComponent, MenuItem } from '../drop-down/drop-down.component'
import { Breadcrumb, BreadcrumbsComponent } from './breadcrumbs.component'
import { OverlayModule } from '@angular/cdk/overlay'
import { DeviceService } from 'src/app/services/device.service'
import { TooltipComponent } from '../../atoms/tooltip/tooltip.component'
import { ForModule } from '@rx-angular/template/for'
import { menuServiceMock } from 'src/app/utils/unit-test.mocks'

const defaultTemplate = `<app-breadcrumbs [breadcrumbs]="breadcrumbs"></app-breadcrumbs>`
const setupComponent = (breadcrumbs: Breadcrumb[], template = defaultTemplate) => {
cy.mount(template, {
componentProperties: {
breadcrumbs,
},
imports: [CdkMenuModule, IconsModule],
declarations: [BreadcrumbsComponent, EntityPageLabelComponent, DropDownComponent],
componentProperties: { breadcrumbs },
imports: [CdkMenuModule, IconsModule, OverlayModule, ForModule],
declarations: [BreadcrumbsComponent, EntityPageLabelComponent, DropDownComponent, TooltipComponent],
providers: [DeviceService, menuServiceMock],
})
}

describe('BreadcrumbsComponent', () => {
it('displays given breadcrumbs', () => {
cy.viewport('macbook-13')
const breadcrumbs: Breadcrumb[] = [
{ title: 'Root list', icon: 'workspace', route: '/' },
{ title: 'Nested list', icon: 'workspace', route: '/nested' },
Expand All @@ -32,6 +37,7 @@ describe('BreadcrumbsComponent', () => {
// @TODO: Navigation through clicking a breadcrumb must be tested in e2e

it('can open a context menu', () => {
cy.viewport('macbook-13')
const menuItems: MenuItem[] = [{ title: 'test' }]
const breadcrumbs: Breadcrumb[] = [
{ title: 'Root list', icon: 'workspace', route: '/', contextMenuItems: menuItems },
Expand All @@ -44,4 +50,59 @@ describe('BreadcrumbsComponent', () => {
cy.get(testName('breadcrumb')).first().rightclick()
cy.get(testName('drop-down-menu')).should('exist')
})

describe('Truncation', () => {
const menuItems: MenuItem[] = [{ title: 'test' }]
const breadcrumbs: Breadcrumb[] = [
{ title: 'Root list', icon: 'workspace', route: '/', contextMenuItems: menuItems },
{ title: '1. Nested list', icon: 'workspace', route: '/ne', contextMenuItems: menuItems },
{ title: '2. Nested list', icon: 'workspace', route: '/ne/ne', contextMenuItems: menuItems },
{ title: '3. Nested list', icon: 'workspace', route: '/ne/ne/ne', contextMenuItems: menuItems },
{ title: '4. Nested list', icon: 'workspace', route: '/ne/ne/ne/ne', contextMenuItems: menuItems },
{ title: '5. Nested list', icon: 'workspace', route: '/ne/ne/ne/ne/ne', contextMenuItems: menuItems },
{ title: '6. Nested list', icon: 'workspace', route: '/ne/ne/ne/ne/ne/ne', contextMenuItems: menuItems },
]

it('truncates breadcrumbs on tablets', () => {
cy.viewport('ipad-mini')
setupComponent(breadcrumbs)

cy.get(testName('breadcrumb')).should('have.length', 4)
cy.get(testName('truncation-breadcrumb')).should('exist')
})
it('truncates breadcrumbs on desktops', () => {
cy.viewport('macbook-13')
setupComponent(breadcrumbs)

cy.get(testName('breadcrumb')).should('have.length', 7)
cy.get(testName('truncation-breadcrumb')).should('not.exist')
})

it('truncates breadcrumbs on mobile', () => {
cy.viewport('iphone-6')
setupComponent(breadcrumbs)

cy.get(testName('breadcrumb')).should('have.length', 1)
cy.get(testName('truncation-breadcrumb')).should('exist')
})

it('can show the truncated breadcrumbs', () => {
setupComponent(breadcrumbs)

cy.get(testName('truncation-breadcrumb')).click()
cy.get(testName('truncated-breadcrumbs-container')).within(() => {
cy.get(testName('breadcrumb')).should('have.length', 5)
})
})

it('can access context menu', () => {
setupComponent(breadcrumbs)

cy.get(testName('truncation-breadcrumb')).click()
cy.get(testName('truncated-breadcrumbs-container')).within(() => {
cy.get(testName('breadcrumb')).first().rightclick()
})
cy.get(testName('drop-down-menu')).should('exist')
})
})
})
Loading