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

[MEL]: Application banner #1142

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 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
28 changes: 28 additions & 0 deletions apps/datahub-e2e/src/e2e/header.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,32 @@ describe('header', () => {
.should('equal', 'desc,userSavedCount')
})
})
describe('Warning banner', () => {
beforeEach(() => {
cy.login()
cy.visit('/geonetwork/srv/eng/admin.console#/settings/languages')
cy.get('.input-group').find('input').first().type('application-banner')
cy.get('.input-group').find('button').click()
cy.get('input')
.first()
.type(
'This is a warning message that should be shown when the key is set'
)
cy.get('.btn-group').eq(1).find('button').first().click()
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't know if there is an enpoint api to add a new translation key, maybe it will save time to do so as a POST instead of login and navigate in geonetwork admin.
But it works fine as is too, this is a thought about improving e2e runing time.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think there is, and it would also fail a bit less. Will change that, thanks for the suggestion :)

})
it('should display a warning banner if the translation key exists and display the message', () => {
cy.visit('/search')
cy.get('gn-ui-application-banner').should(
'have.text',
'This is a warning message that should be shown when the key is set'
)
})
it('should not display the banner when the translation is deleted', () => {
cy.visit('/geonetwork/srv/eng/admin.console#/settings/languages')
cy.get('.btn-group').eq(1).find('button').eq(1).click()
cy.get('[data-ng-click="removeAllTranslations()"]').click()
cy.visit('/search')
cy.get('gn-ui-application-banner').should('not.exist')
})
})
})
2 changes: 2 additions & 0 deletions apps/datahub/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ import {
matMoreHorizOutline,
matRemoveOutline,
matStarOutline,
matWarningAmberOutline,
} from '@ng-icons/material-icons/outline'
import { NgIconsModule, provideNgIconsConfig } from '@ng-icons/core'
import { MAX_FEATURE_COUNT } from './record/record-data-preview/record-data-preview.component'
Expand Down Expand Up @@ -176,6 +177,7 @@ export const metaReducers: MetaReducer[] = !environment.production ? [] : []
matAddOutline,
matExpandMoreOutline,
matStarOutline,
matWarningAmberOutline,
}),
OrganisationsComponent,
LanguageSwitcherComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
<div
class="container-lg relative h-full mx-auto flex flex-col-reverse justify-between sm:flex-col sm:justify-end"
>
<gn-ui-application-banner
[message]="platformService.translateKey(bannerKey) | async"
class="container-sm"
type="secondary"
></gn-ui-application-banner>
Copy link
Collaborator

Choose a reason for hiding this comment

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

It is a little broken with a long text 😅
image

<div
class="py-8 relative z-40 mb-[184px] sm:mb-0"
[ngClass]="{ 'pointer-events-none': expandRatio < 0.2 }"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class searchServiceMock {
class PlatformServiceMock {
isAnonymous = jest.fn(() => this._isAnonymous$)
_isAnonymous$ = new BehaviorSubject(true)
translateKey = jest.fn()
}

class FieldsServiceMock {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,13 @@ export class HomeHeaderComponent {
searchConfig: SearchConfig = getOptionalSearchConfig()
showLanguageSwitcher = getGlobalConfig().LANGUAGES?.length > 0
foregroundColor = getThemeConfig().HEADER_FOREGROUND_COLOR || '#ffffff'
bannerKey = 'application-banner'

constructor(
public routerFacade: RouterFacade,
public searchFacade: SearchFacade,
private searchService: SearchService,
private platformService: PlatformServiceInterface,
protected platformService: PlatformServiceInterface,
private fieldsService: FieldsService
) {}

Expand Down
1 change: 1 addition & 0 deletions libs/ui/elements/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ export * from './lib/thumbnail/thumbnail.component'
export * from './lib/ui-elements.module'
export * from './lib/user-feedback-item/user-feedback-item.component'
export * from './lib/user-preview/user-preview.component'
export * from './lib/application-banner/application-banner.component'
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div *ngIf="message" style="top: 0" class="absolute text-wrap bg-white mt-4">
<div
class="flex flex-row py-2.5 px-5 gap-5 justify-start items-center border"
[ngClass]="classList"
>
<ng-icon [name]="icon"></ng-icon>
<div class="flex flex-col justify-start gap-2.5">
<span *ngIf="title" class="font-bold">{{ title }}</span>
<span class="font-medium" [innerHTML]="message"></span>
</div>
<button
*ngIf="closeEnabled"
class="self-start"
type="button"
(click)="closeMessage()"
>
<ng-icon name="matCloseOutline"> </ng-icon>
</button>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { ApplicationBannerComponent } from './application-banner.component'

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

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

fixture = TestBed.createComponent(ApplicationBannerComponent)
component = fixture.componentInstance
fixture.detectChanges()
})

it('should create', () => {
expect(component).toBeTruthy()
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {
applicationConfig,
componentWrapperDecorator,
Meta,
moduleMetadata,
StoryObj,
} from '@storybook/angular'
import { ApplicationBannerComponent } from './application-banner.component'
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
import { importProvidersFrom } from '@angular/core'

export default {
title: 'Elements/ApplicationBannerComponent',
component: ApplicationBannerComponent,
decorators: [
moduleMetadata({
imports: [ApplicationBannerComponent],
}),
applicationConfig({
providers: [importProvidersFrom(BrowserAnimationsModule)],
}),
componentWrapperDecorator(
(story) => `<div style="max-width: 800px">${story}</div>`
),
],
} as Meta<ApplicationBannerComponent>

export const Default: StoryObj<ApplicationBannerComponent> = {
args: {
message: 'This is a warning message',
closeEnabled: false,
type: 'primary',
},
}

export const PrimaryFull: StoryObj<ApplicationBannerComponent> = {
args: {
message: 'This is a warning message',
title: 'Warning',
closeEnabled: true,
type: 'primary',
},
}

export const SecondaryFull: StoryObj<ApplicationBannerComponent> = {
args: {
message: 'This is a warning message',
title: 'Warning',
closeEnabled: true,
type: 'secondary',
},
}

export const LightFull: StoryObj<ApplicationBannerComponent> = {
args: {
message: 'This is a warning message',
title: 'Warning',
closeEnabled: true,
type: 'light',
},
Copy link
Collaborator

@AlitaBernachot AlitaBernachot Mar 4, 2025

Choose a reason for hiding this comment

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

image

I don't see colored background on the story book for Secondary and Light, i don't know if this was made on purpose?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It wasn't, I don't know why it's happening like that in the storybook, maybe it's a matter of colors imports? Because in the datahub the right colors are shown when switching to secondary or light :/
Since it works in the app & it's only on storybook, I will look into it if there is time left

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { CommonModule } from '@angular/common'
import {
NgIconComponent,
provideIcons,
provideNgIconsConfig,
} from '@ng-icons/core'
import {
matCloseOutline,
matWarningAmberOutline,
} from '@ng-icons/material-icons/outline'

@Component({
selector: 'gn-ui-application-banner',
standalone: true,
imports: [CommonModule, NgIconComponent],
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './application-banner.component.html',
styleUrl: './application-banner.component.css',
providers: [
provideIcons({
matWarningAmberOutline,
matCloseOutline,
}),
provideNgIconsConfig({ size: '1.5em' }),
],
})
export class ApplicationBannerComponent {
@Input() message: string
@Input() title: string
@Input() closeEnabled = false
@Input() extraClass = ''
@Input() icon = 'matWarningAmberOutline'
msgClass = ''

@Input() set type(value: 'primary' | 'secondary' | 'light') {
switch (value) {
case 'primary':
this.msgClass = 'bg-primary-darkest border-primary text-white'
break
case 'secondary':
this.msgClass = 'bg-primary-opacity-50 border-primary-darker text-black'
break
case 'light':
this.msgClass =
'bg-primary-opacity-10 border-primary-lightest text-black'
break
default:
this.msgClass = 'bg-primary-opacity-50 border-primary-darker text-black'
break
}
}

get classList() {
return `${this.msgClass} ${this.extraClass}`
}

closeMessage() {
this.message = ''
}
}
3 changes: 3 additions & 0 deletions libs/ui/elements/src/lib/ui-elements.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { MarkdownParserComponent } from './markdown-parser/markdown-parser.compo
import { ThumbnailComponent } from './thumbnail/thumbnail.component'
import { TimeSincePipe } from './user-feedback-item/time-since.pipe'
import { UserPreviewComponent } from './user-preview/user-preview.component'
import { ApplicationBannerComponent } from './application-banner/application-banner.component'

@NgModule({
imports: [
Expand All @@ -40,6 +41,7 @@ import { UserPreviewComponent } from './user-preview/user-preview.component'
MaxLinesComponent,
TextInputComponent,
ImageInputComponent,
ApplicationBannerComponent,
],
providers: [
provideNgIconsConfig({
Expand All @@ -53,6 +55,7 @@ import { UserPreviewComponent } from './user-preview/user-preview.component'
UserPreviewComponent,
MarkdownParserComponent,
ImageInputComponent,
ApplicationBannerComponent,
],
})
export class UiElementsModule {}
Loading