refactor: allow banner service to hold multiple banners and display the banner with the highest score (#3556)
This commit is contained in:
committed by
GitHub
parent
a3aa9b68fc
commit
24ae090916
@@ -1,38 +1,53 @@
|
||||
import { describe, expect, it } from "vitest"
|
||||
import { BannerContent, BannerService } from "../banner.service"
|
||||
import { TestContainer } from "dioc/testing"
|
||||
import { getI18n } from "~/modules/i18n"
|
||||
import {
|
||||
BannerService,
|
||||
BANNER_PRIORITY_LOW,
|
||||
BANNER_PRIORITY_HIGH,
|
||||
BannerContent,
|
||||
} from "../banner.service"
|
||||
|
||||
describe("BannerService", () => {
|
||||
const container = new TestContainer()
|
||||
const service = container.bind(BannerService)
|
||||
const banner = container.bind(BannerService)
|
||||
|
||||
it("initally there are no banners defined", () => {
|
||||
expect(service.content.value).toEqual(null)
|
||||
})
|
||||
|
||||
it("should be able to set and retrieve banner content", () => {
|
||||
const sampleBanner: BannerContent = {
|
||||
it("should be able to show and remove a banner", () => {
|
||||
const bannerContent: BannerContent = {
|
||||
type: "info",
|
||||
text: "Info Banner",
|
||||
text: (t: ReturnType<typeof getI18n>) => t("Info Banner"),
|
||||
score: BANNER_PRIORITY_LOW,
|
||||
}
|
||||
|
||||
const banner = service.content
|
||||
banner.value = sampleBanner
|
||||
const retrievedBanner = service.content.value
|
||||
const bannerId = banner.showBanner(bannerContent)
|
||||
expect(banner.content.value).toEqual({
|
||||
id: bannerId,
|
||||
content: bannerContent,
|
||||
})
|
||||
|
||||
expect(retrievedBanner).toEqual(sampleBanner)
|
||||
banner.removeBanner(bannerId)
|
||||
expect(banner.content.value).toBeNull()
|
||||
})
|
||||
|
||||
it("should be able to update the banner content", () => {
|
||||
const updatedBanner: BannerContent = {
|
||||
type: "warning",
|
||||
text: "Updated Banner Content",
|
||||
alternateText: "Updated Banner",
|
||||
it("should show the banner with the highest score", () => {
|
||||
const lowPriorityBanner: BannerContent = {
|
||||
type: "info",
|
||||
text: (t: ReturnType<typeof getI18n>) => t("Low Priority Banner"),
|
||||
score: BANNER_PRIORITY_LOW,
|
||||
}
|
||||
|
||||
service.content.value = updatedBanner
|
||||
const retrievedBanner = service.content.value
|
||||
const highPriorityBanner: BannerContent = {
|
||||
type: "warning",
|
||||
text: (t: ReturnType<typeof getI18n>) => t("High Priority Banner"),
|
||||
score: BANNER_PRIORITY_HIGH,
|
||||
}
|
||||
|
||||
expect(retrievedBanner).toEqual(updatedBanner)
|
||||
banner.showBanner(lowPriorityBanner)
|
||||
const highPriorityBannerID = banner.showBanner(highPriorityBanner)
|
||||
|
||||
expect(banner.content.value).toEqual({
|
||||
id: highPriorityBannerID,
|
||||
content: highPriorityBanner,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,16 +1,35 @@
|
||||
import { Service } from "dioc"
|
||||
import { ref } from "vue"
|
||||
import { computed, ref } from "vue"
|
||||
import { getI18n } from "~/modules/i18n"
|
||||
|
||||
export const BANNER_PRIORITY_LOW = 1
|
||||
export const BANNER_PRIORITY_MEDIUM = 3
|
||||
export const BANNER_PRIORITY_HIGH = 5
|
||||
|
||||
/**
|
||||
* The different types of banners that can be used.
|
||||
*/
|
||||
export type BannerType = "info" | "warning" | "error"
|
||||
|
||||
export type BannerContent = {
|
||||
type: BannerType
|
||||
text: string
|
||||
text: (t: ReturnType<typeof getI18n>) => string
|
||||
// Can be used to display an alternate text when display size is small
|
||||
alternateText?: string
|
||||
alternateText?: (t: ReturnType<typeof getI18n>) => string
|
||||
// Used to determine which banner should be displayed when multiple banners are present
|
||||
score: number
|
||||
}
|
||||
|
||||
export type Banner = {
|
||||
id: number
|
||||
content: BannerContent
|
||||
}
|
||||
|
||||
// Returns the banner with the highest score
|
||||
const getBannerWithHighestScore = (list: Banner[]) => {
|
||||
if (list.length === 0) return null
|
||||
else if (list.length === 1) return list[0]
|
||||
else {
|
||||
const highestScore = Math.max(...list.map((banner) => banner.content.score))
|
||||
return list.find((banner) => banner.content.score === highestScore)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -20,9 +39,22 @@ export type BannerContent = {
|
||||
export class BannerService extends Service {
|
||||
public static readonly ID = "BANNER_SERVICE"
|
||||
|
||||
/**
|
||||
* This is a reactive variable that can be used to set the contents of the banner
|
||||
* and use it to render the banner on components.
|
||||
*/
|
||||
public content = ref<BannerContent | null>(null)
|
||||
private bannerID = 0
|
||||
private bannerList = ref<Banner[]>([])
|
||||
|
||||
public content = computed(() =>
|
||||
getBannerWithHighestScore(this.bannerList.value)
|
||||
)
|
||||
|
||||
public showBanner(banner: BannerContent) {
|
||||
this.bannerID = this.bannerID + 1
|
||||
this.bannerList.value.push({ id: this.bannerID, content: banner })
|
||||
return this.bannerID
|
||||
}
|
||||
|
||||
public removeBanner(id: number) {
|
||||
this.bannerList.value = this.bannerList.value.filter(
|
||||
(banner) => id !== banner.id
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user