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(about): add about page #1832

Merged
merged 6 commits into from
Dec 12, 2024
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
18 changes: 2 additions & 16 deletions .github/workflows/deploy_web.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,16 @@ jobs:
with:
node-version-file: .nvmrc

- name: use pnpm
- name: Use pnpm
uses: pnpm/action-setup@v2
with:
version: 8

- name: Cache pnpm modules
uses: actions/cache@v3
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-

- name: Set env
run: |
cd apps/web
echo "VUE_APP_PAGE_TITLE=Easy-to-Use Online MQTT Client | Try Now" > .env.local
echo "VUE_APP_PAGE_DESCRIPTION=Online MQTT 5.0 client on the web, using MQTT over WebSocket to connect to the MQTT Broker and test message publishing and receiving in the browser." >> .env.local

- name: Install dependencies
run: |
pnpm install

- name: build
- name: Build
run: |
pnpm run build:web

Expand Down
5 changes: 5 additions & 0 deletions apps/desktop/src/renderer/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
AboutFooter: typeof import('./../../../../packages/ui/src/components/about/Footer.vue')['default']
AboutInfo: typeof import('./../../../../packages/ui/src/components/about/Info.vue')['default']
AboutView: typeof import('./../../../../packages/ui/src/components/about/View.vue')['default']
CommonEmptyView: typeof import('./../../../../packages/ui/src/components/common/EmptyView.vue')['default']
CommonLeftMenu: typeof import('./../../../../packages/ui/src/components/common/LeftMenu.vue')['default']
CommonMainView: typeof import('./../../../../packages/ui/src/components/common/MainView.vue')['default']
Expand All @@ -24,12 +27,14 @@ declare module 'vue' {
ElIconDelete: typeof import('@element-plus/icons-vue')['Delete']
ElIconDownload: typeof import('@element-plus/icons-vue')['Download']
ElIconPrinter: typeof import('@element-plus/icons-vue')['Printer']
ElIconRight: typeof import('@element-plus/icons-vue')['Right']
ElIconUpload: typeof import('@element-plus/icons-vue')['Upload']
ElIconWarning: typeof import('@element-plus/icons-vue')['Warning']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElMain: typeof import('element-plus/es')['ElMain']
ElOption: typeof import('element-plus/es')['ElOption']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElRow: typeof import('element-plus/es')['ElRow']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
Expand Down
3 changes: 3 additions & 0 deletions apps/desktop/src/renderer/src/pages/about.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<AboutView />
</template>
1 change: 1 addition & 0 deletions apps/desktop/typed-router.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ declare module 'vue-router/auto-routes' {
* Route name map generated by unplugin-vue-router
*/
export interface RouteNamedMap {
'/about': RouteRecordInfo<'/about', '/about', Record<never, never>, Record<never, never>>,
'/connections/': RouteRecordInfo<'/connections/', '/connections', Record<never, never>, Record<never, never>>,
'/connections/[id]': RouteRecordInfo<'/connections/[id]', '/connections/:id', { id: ParamValue<true> }, { id: ParamValue<false> }>,
'/help': RouteRecordInfo<'/help', '/help', Record<never, never>, Record<never, never>>,
Expand Down
5 changes: 5 additions & 0 deletions apps/web/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
AboutFooter: typeof import('./../../packages/ui/src/components/about/Footer.vue')['default']
AboutInfo: typeof import('./../../packages/ui/src/components/about/Info.vue')['default']
AboutView: typeof import('./../../packages/ui/src/components/about/View.vue')['default']
CommonEmptyView: typeof import('./../../packages/ui/src/components/common/EmptyView.vue')['default']
CommonLeftMenu: typeof import('./../../packages/ui/src/components/common/LeftMenu.vue')['default']
CommonMainView: typeof import('./../../packages/ui/src/components/common/MainView.vue')['default']
Expand All @@ -24,12 +27,14 @@ declare module 'vue' {
ElIconDelete: typeof import('@element-plus/icons-vue')['Delete']
ElIconDownload: typeof import('@element-plus/icons-vue')['Download']
ElIconPrinter: typeof import('@element-plus/icons-vue')['Printer']
ElIconRight: typeof import('@element-plus/icons-vue')['Right']
ElIconUpload: typeof import('@element-plus/icons-vue')['Upload']
ElIconWarning: typeof import('@element-plus/icons-vue')['Warning']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElMain: typeof import('element-plus/es')['ElMain']
ElOption: typeof import('element-plus/es')['ElOption']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElRow: typeof import('element-plus/es')['ElRow']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
Expand Down
3 changes: 3 additions & 0 deletions apps/web/src/pages/about.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<AboutView />
</template>
1 change: 1 addition & 0 deletions apps/web/typed-router.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ declare module 'vue-router/auto-routes' {
* Route name map generated by unplugin-vue-router
*/
export interface RouteNamedMap {
'/about': RouteRecordInfo<'/about', '/about', Record<never, never>, Record<never, never>>,
'/connections/': RouteRecordInfo<'/connections/', '/connections', Record<never, never>, Record<never, never>>,
'/connections/[id]': RouteRecordInfo<'/connections/[id]', '/connections/:id', { id: ParamValue<true> }, { id: ParamValue<false> }>,
'/help': RouteRecordInfo<'/help', '/help', Record<never, never>, Record<never, never>>,
Expand Down
1 change: 1 addition & 0 deletions packages/tailwind-config/base.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const config: Config = {
extend: {
backgroundImage: () => ({
'gradient-card': 'var(--color-bg-card-gradient)',
'gradient-btn': 'var(--color-bg-btn-gradient)',
}),
},
},
Expand Down
5 changes: 5 additions & 0 deletions packages/ui/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
AboutFooter: typeof import('./src/components/about/Footer.vue')['default']
AboutInfo: typeof import('./src/components/about/Info.vue')['default']
AboutView: typeof import('./src/components/about/View.vue')['default']
CommonEmptyView: typeof import('./src/components/common/EmptyView.vue')['default']
CommonLeftMenu: typeof import('./src/components/common/LeftMenu.vue')['default']
CommonMainView: typeof import('./src/components/common/MainView.vue')['default']
Expand All @@ -22,12 +25,14 @@ declare module 'vue' {
ElIconDelete: typeof import('@element-plus/icons-vue')['Delete']
ElIconDownload: typeof import('@element-plus/icons-vue')['Download']
ElIconPrinter: typeof import('@element-plus/icons-vue')['Printer']
ElIconRight: typeof import('@element-plus/icons-vue')['Right']
ElIconUpload: typeof import('@element-plus/icons-vue')['Upload']
ElIconWarning: typeof import('@element-plus/icons-vue')['Warning']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElMain: typeof import('element-plus/es')['ElMain']
ElOption: typeof import('element-plus/es')['ElOption']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElRow: typeof import('element-plus/es')['ElRow']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 76 additions & 0 deletions packages/ui/src/components/about/Footer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<script setup lang="ts">
import IconDiscord from '~icons/custom/discord'
import IconSlack from '~icons/custom/slack'
import IconWeChat from '~icons/custom/wechat'
import IconX from '~icons/custom/x'
import logoDark from '../../assets/images/about/emq-logo-dark.png'
import logoLight from '../../assets/images/about/emq-logo-light.png'
import WeChatQRCode from '../../assets/images/about/wx_qr_code.png'
import { useSettingsStore } from '../../stores'

const { settings } = useSettingsStore()
const logo = computed(() => settings!.currentTheme === 'light' ? logoDark : logoLight)

const fullYear = new Date().getFullYear()
const { about } = useLinks()

const socialLinks = [
{
icon: IconX,
name: 'X',
link: 'https://twitter.com/EMQTech',
},
{
icon: IconDiscord,
name: 'Discord',
link: 'https://discord.gg/xYGf3fQnES',
},
{
icon: IconSlack,
name: 'Slack',
link: 'https://slack-invite.emqx.io/',
},
]
</script>

<template>
<div class="py-6 border-t border-t-border-default flex gap-6 items-center justify-between">
<div class="flex items-center gap-2">
<img :src="logo" alt="EMQ" width="40" height="12">
<span class="text-default text-sm">
&copy;{{ fullYear }}
<a class="text-main-green" :href="about.EMQ" target="_blank" rel="noopener">
EMQ
</a>
Technologies Inc.
</span>
</div>
<div class="flex gap-3">
<a
v-for="{ icon, name, link } in socialLinks"
:key="name"
:href="link"
target="_blank"
rel="noopener noreferrer"
>
<component :is="icon" class="w-5 h-5 text-light" />
</a>
<ElPopover
v-if="settings?.currentLang === 'zh'"
placement="top"
width="30"
trigger="click"
>
<img :src="WeChatQRCode" alt="WeChat QR Code" width="126" height="126">
<template #reference>
<div
role="button"
tabindex="0"
>
<component :is="IconWeChat" class="w-5 h-5 text-light" />
</div>
</template>
</ElPopover>
</div>
</div>
</template>
105 changes: 105 additions & 0 deletions packages/ui/src/components/about/Info.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<script setup lang="ts">
// TODO: Implement update function, and display data collection policy.
import type { PlatformType } from 'mqttx'
import IconFaq from '~icons/custom/faq'
import IconGithub from '~icons/custom/github'
import IconWebsite from '~icons/custom/website'

const { about } = useLinks()

const platformType = inject<PlatformType>('platformType', 'web')

const { t } = useI18n()
const btns = computed(() => [
{
icon: IconGithub,
text: 'GitHub',
link: 'https://github.com/emqx/MQTTX',
},
{
icon: IconWebsite,
text: t('about.web'),
link: 'https://mqttx.app',
},
{
icon: IconFaq,
text: 'FAQ',
link: 'https://mqttx.app/faq',
},
])
</script>

<template>
<div class="mb-16">
<div :class="$style.section">
<div
v-if="platformType === 'desktop'"
role="button"
tabindex="0"
>
{{ $t('about.update') }}
</div>
<a :href="about.releases" target="_blank" rel="noopener">
{{ $t('about.releases') }}
</a>
<a href="https://github.com/emqx/MQTTX/issues" target="_blank" rel="noopener">
{{ $t('about.support') }}
</a>
<div
v-if="platformType === 'web'"
role="button"
tabindex="0"
>
{{ $t('about.dataCollectionPolicy') }}
</div>
</div>
<p class="mb-6 max-w-xl text-sm text-default">
{{ platformType === 'desktop' ? $t('about.mqttxDesc') : $t('about.mqttxWebDesc') }}
</p>
<div class="mb-16 inline-grid grid-cols-3 gap-6">
<a
v-for="{ icon, text, link } in btns"
:key="link"
class="inline-flex gap-1.5 items-center justify-center min-w-40 rounded-lg px-6 py-3 bg-card-normal text-main-green text-sm font-medium"
:href="link"
target="_blank"
rel="noopener"
>
<component :is="icon" class="text-xl text-card-icon" />
{{ text }}
<ElIconRight width="16" height="16" />
</a>
</div>
<div :class="$style.cloud">
<h2 class="mb-4 text-title text-lg font-semibold">
{{ $t('about.cloudTitle') }}
</h2>
<p class="mb-4 text-default text-sm">
{{ $t('about.cloudSummary') }}
</p>
<a
class="inline-flex gap-1.5 items-center justify-center min-w-40 rounded-lg px-4 py-2 bg-gradient-btn text-main-white text-sm font-medium"
:href="about.EMQXCloud"
target="_blank"
rel="noopener"
>
{{ $t('about.tryCloud') }}
<ElIconRight width="16" height="16" />
</a>
</div>
</div>
</template>

<style module>
.section {
@apply mb-6 flex divide-x divide-border-default text-sm text-main-green;
> div,
> a {
@apply px-3 first:pl-0 last:pr-0;
}
}

.cloud {
@apply text-center px-10 py-5 bg-gradient-card rounded-lg;
}
</style>
33 changes: 33 additions & 0 deletions packages/ui/src/components/about/View.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script setup lang="ts">
import logoDark from '../../assets/images/about/mqttx-dark.png'
import logoLight from '../../assets/images/about/mqttx-light.png'
import { useSettingsStore } from '../../stores'

const { settings } = useSettingsStore()
const logo = computed(() => settings!.currentTheme === 'light' ? logoDark : logoLight)

const { t } = useI18n()
const version = computed(() => `${t('common.version')} v${window.__APP_VERSION__}`)
</script>

<template>
<div id="help-view" class="px-4 pt-4 pb-12 bg-primary min-h-full select-none">
<div class="mx-auto max-w-screen-lg">
<h1 class="mb-12 text-lg text-title font-semibold">
{{ $t('about.about') }}
</h1>
<div class="px-6 flex flex-col items-center justify-center min-h-[calc(100vh-140px)]">
<div class="flex gap-20 items-center">
<img :src="logo" alt="MQTTX" width="200" height="192">
<div>
<div class="mb-4 font-semibold text-2xl text-title">
{{ version }}
</div>
<AboutInfo />
<AboutFooter />
</div>
</div>
</div>
</div>
</div>
</template>
2 changes: 1 addition & 1 deletion packages/ui/src/components/common/LeftMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const menus = reactive<Menus>({

<style module>
.aside {
@apply z-[1001] py-10 flex flex-col gap-8 justify-between items-center border-r border-r-border-leftbar;
@apply z-[1001] select-none py-10 flex flex-col gap-8 justify-between items-center border-r border-r-border-leftbar;
background: linear-gradient(135deg, var(--color-bg-leftbar_top) 0%, var(--color-bg-leftbar_bottom) 100%);
}

Expand Down
Loading
Loading