diff --git a/packages/hoppscotch-common/src/components.d.ts b/packages/hoppscotch-common/src/components.d.ts index b1c4080b5..09f6cd1d7 100644 --- a/packages/hoppscotch-common/src/components.d.ts +++ b/packages/hoppscotch-common/src/components.d.ts @@ -9,6 +9,7 @@ declare module "vue" { export interface GlobalComponents { AppActionHandler: typeof import('./components/app/ActionHandler.vue')['default'] AppAnnouncement: typeof import('./components/app/Announcement.vue')['default'] + AppBanner: typeof import('./components/app/Banner.vue')['default'] AppContextMenu: typeof import('./components/app/ContextMenu.vue')['default'] AppDeveloperOptions: typeof import('./components/app/DeveloperOptions.vue')['default'] AppFooter: typeof import('./components/app/Footer.vue')['default'] @@ -140,6 +141,7 @@ declare module "vue" { HttpTests: typeof import('./components/http/Tests.vue')['default'] HttpURLEncodedParams: typeof import('./components/http/URLEncodedParams.vue')['default'] IconLucideActivity: typeof import('~icons/lucide/activity')['default'] + IconLucideAlertCircle: typeof import('~icons/lucide/alert-circle')['default'] IconLucideAlertTriangle: typeof import('~icons/lucide/alert-triangle')['default'] IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default'] IconLucideArrowUpRight: typeof import('~icons/lucide/arrow-up-right')['default'] diff --git a/packages/hoppscotch-common/src/components/app/Announcement.vue b/packages/hoppscotch-common/src/components/app/Announcement.vue deleted file mode 100644 index 0f458c325..000000000 --- a/packages/hoppscotch-common/src/components/app/Announcement.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/packages/hoppscotch-common/src/components/app/Banner.vue b/packages/hoppscotch-common/src/components/app/Banner.vue new file mode 100644 index 000000000..d74994d2a --- /dev/null +++ b/packages/hoppscotch-common/src/components/app/Banner.vue @@ -0,0 +1,54 @@ + + + diff --git a/packages/hoppscotch-common/src/components/app/Header.vue b/packages/hoppscotch-common/src/components/app/Header.vue index ec769d23d..f17df26e4 100644 --- a/packages/hoppscotch-common/src/components/app/Header.vue +++ b/packages/hoppscotch-common/src/components/app/Header.vue @@ -215,7 +215,7 @@ - + { + if (network.isOnline) { + banner.value = null + return + } + banner.value = { + type: "info", + text: t("helpers.offline"), + alternateText: t("helpers.offline_short"), + } +}) + const currentUser = useReadonlyStream( platform.auth.getProbableUserStream(), platform.auth.getProbableUser() diff --git a/packages/hoppscotch-common/src/modules/dioc.ts b/packages/hoppscotch-common/src/modules/dioc.ts index c33822496..a7d24630a 100644 --- a/packages/hoppscotch-common/src/modules/dioc.ts +++ b/packages/hoppscotch-common/src/modules/dioc.ts @@ -2,6 +2,7 @@ import { HoppModule } from "." import { Container, Service } from "dioc" import { diocPlugin } from "dioc/vue" import { DebugService } from "~/services/debug.service" +import { platform } from "~/platform" const serviceContainer = new Container() @@ -34,5 +35,8 @@ export default { app.use(diocPlugin, { container: serviceContainer, }) + for (const service of platform.addedServices ?? []) { + serviceContainer.bind(service) + } }, } diff --git a/packages/hoppscotch-common/src/platform/index.ts b/packages/hoppscotch-common/src/platform/index.ts index 22cbaf112..bae7ce208 100644 --- a/packages/hoppscotch-common/src/platform/index.ts +++ b/packages/hoppscotch-common/src/platform/index.ts @@ -9,10 +9,12 @@ import { AnalyticsPlatformDef } from "./analytics" import { InterceptorsPlatformDef } from "./interceptors" import { HoppModule } from "~/modules" import { InspectorsPlatformDef } from "./inspectors" +import { Service } from "dioc" export type PlatformDef = { ui?: UIPlatformDef addedHoppModules?: HoppModule[] + addedServices?: Array & { ID: string }> auth: AuthPlatformDef analytics?: AnalyticsPlatformDef sync: { diff --git a/packages/hoppscotch-common/src/services/__tests__/banner.service.spec.ts b/packages/hoppscotch-common/src/services/__tests__/banner.service.spec.ts new file mode 100644 index 000000000..a2fcc9fed --- /dev/null +++ b/packages/hoppscotch-common/src/services/__tests__/banner.service.spec.ts @@ -0,0 +1,38 @@ +import { describe, expect, it } from "vitest" +import { BannerContent, BannerService } from "../banner.service" +import { TestContainer } from "dioc/testing" + +describe("BannerService", () => { + const container = new TestContainer() + const service = 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 = { + type: "info", + text: "Info Banner", + } + + const banner = service.content + banner.value = sampleBanner + const retrievedBanner = service.content.value + + expect(retrievedBanner).toEqual(sampleBanner) + }) + + it("should be able to update the banner content", () => { + const updatedBanner: BannerContent = { + type: "warning", + text: "Updated Banner Content", + alternateText: "Updated Banner", + } + + service.content.value = updatedBanner + const retrievedBanner = service.content.value + + expect(retrievedBanner).toEqual(updatedBanner) + }) +}) diff --git a/packages/hoppscotch-common/src/services/banner.service.ts b/packages/hoppscotch-common/src/services/banner.service.ts new file mode 100644 index 000000000..f550efd29 --- /dev/null +++ b/packages/hoppscotch-common/src/services/banner.service.ts @@ -0,0 +1,28 @@ +import { Service } from "dioc" +import { ref } from "vue" + +/** + * The different types of banners that can be used. + */ +export type BannerType = "info" | "warning" | "error" + +export type BannerContent = { + type: BannerType + text: string + // Can be used to display an alternate text when display size is small + alternateText?: string +} + +/** + * This service is used to display a banner on the app. + * It can used to display information, warnings or errors. + */ +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(null) +}