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

Streaming #72

Merged
merged 6 commits into from
Nov 29, 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
26 changes: 26 additions & 0 deletions packages/components/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module.exports = {
root: true,
env: {
node: true,
es2022: true,
},
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/typescript/recommended',
'@vue/prettier',
'@vue/eslint-config-typescript',
],
parserOptions: {
ecmaVersion: 2022,
},
ignorePatterns: ['node_modules'],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': [1],
'@typescript-eslint/no-explicit-any': 'off',
'vue/multi-word-component-names': 'off',
},
}
3 changes: 3 additions & 0 deletions packages/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as StreamForm } from './streaming/StreamForm.vue'
export { default as StreamingACLForm } from './streaming/StreamingACLForm.vue'
export { default as StreamingAuthForm } from './streaming/StreamingAuthForm.vue'
54 changes: 54 additions & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "@emqx/shared-ui-components",
"version": "0.0.1",
"homepage": "https://emqx.io",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/emqx/shared-ui"
},
"publishConfig": {
"access": "public"
},
"type": "module",
"types": "./dist/index.d.ts",
"files": [
"dist",
"README.md"
],
"main": "./dist/index.umd.cjs",
"module": "./dist/index.js",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.umd.cjs"
}
},
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build && vue-tsc --declaration",
"preview": "vite preview",
"version:patch": "npm version patch",
"version:minor": "npm version minor",
"version:major": "npm version major",
"release": "npm publish"
},
"dependencies": {
"@emqx/shared-ui-constants": "link:../constants"
},
"devDependencies": {
"@emqx/shared-ui-utils": "link:../utils",
"@vitejs/plugin-vue": "^5.0.0",
"@vue/eslint-config-prettier": "^9.0.0",
"@vue/eslint-config-typescript": "^13.0.0",
"element-plus": "^2.3.0",
"rollup-plugin-visualizer": "^5.12.0",
"vue": "^3.2.0",
"vue-tsc": "^2.1.10"
Comment on lines +44 to +47
Copy link
Member

Choose a reason for hiding this comment

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

Why not use the latest package?

Copy link
Member Author

Choose a reason for hiding this comment

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

Since dashboard is still using version 3.2 of vue.. it's ok that the vue used by cloud satisfies this version number.

},
"peerDependencies": {
"@emqx/shared-ui-utils": "link:../utils",
"element-plus": "^2.3.0",
"vue": "^3.2.0"
}
}
97 changes: 97 additions & 0 deletions packages/components/streaming/StreamForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<template>
<el-form ref="form" :model="record" label-position="top">
<el-form-item prop="stream_name">
<template #label>
{{ t('streaming.streamName') }}
<component v-if="tipComponent" :is="tipComponent" :content="t('streaming.streamNameTip')" />
</template>
<el-input v-model="record.stream_name" />
</el-form-item>
<el-form-item prop="stream_type">
<template #label>
{{ t('streaming.streamType') }}
<component v-if="tipComponent" :is="tipComponent" :content="t('streaming.streamTypeTip')" />
</template>
<el-select v-model="record.stream_type" @change="handleStreamTypeChange">
<el-option
v-for="item in allStreamTypes"
:key="item"
:value="item"
:label="$t(`streaming.streamTypeLabel.${item}`)"
/>
</el-select>
</el-form-item>
<el-form-item v-if="record.stream_type === StreamType.Default" prop="mqtt_topic_filter">
<template #label>
{{ t('streaming.mqttTopic') }}
<component v-if="tipComponent" :is="tipComponent" :content="t('streaming.mqttTopicTip')" />
</template>
<el-input v-model="record.mqtt_topic_filter" />
</el-form-item>
<el-form-item v-else prop="partition_number" :label="t('streaming.partitionNum')">
<el-input-number
v-model="record.partition_number"
:min="1"
:max="64"
:precision="0"
controls-position="right"
/>
</el-form-item>
</el-form>
</template>

<script setup lang="ts">
import { StreamType } from '@emqx/shared-ui-constants'
import { useLocale } from '@emqx/shared-ui-utils'
import { Component, computed, defineEmits, defineProps } from 'vue'

interface StreamRecord {
stream_name: string
stream_type: StreamType
mqtt_topic_filter?: string
partition_number: number
retention_time: string
}

const props = defineProps<{
tipComponent?: Component
modelValue: StreamRecord
// TODO: try to optimize
lang: 'en' | 'zh' | 'ja'
}>()
const emit = defineEmits<{
(e: 'update:modelValue', v: StreamRecord): void
}>()

const { t } = useLocale(props.lang)

const record = computed({
get() {
return props.modelValue
},
set(val) {
emit('update:modelValue', val)
},
})

const allStreamTypes = Object.values(StreamType)

const handleStreamTypeChange = (val: StreamType) => {
const { stream_name, stream_type } = record.value
if (val === StreamType.Default) {
record.value = {
stream_name,
stream_type,
mqtt_topic_filter: '',
} as StreamRecord
} else {
record.value = {
stream_name,
stream_type,
partition_number: 16,
} as StreamRecord
}
}
</script>

<style lang="scss"></style>
146 changes: 146 additions & 0 deletions packages/components/streaming/StreamingACLForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<template>
<el-form :model="record" label-position="top">
<el-form-item prop="principal_name" :label="t('common.username')">
<el-input v-model="record.principal_name" />
</el-form-item>
<el-form-item prop="host" :label="tl('host')">
<el-input v-model="record.host" :disabled="record.host_type === StreamPatternType.All">
<template #prepend>
<el-select class="prepend-select" v-model="record.host_type" @change="changeHostType">
<el-option :label="tl('matchAll')" :value="StreamPatternType.All" />
<el-option :label="tl('literal')" :value="StreamPatternType.Literal" />
</el-select>
</template>
</el-input>
</el-form-item>
<el-form-item prop="resource_type" :label="tl('aclResourceType')">
<el-radio-group v-model="record.resource_type" @change="changeResourceType">
<el-radio
v-for="item in resourceTypeOptions"
:key="item.value"
:value="item.value"
:label="item.value"
>
{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="resource_name" :label="tl('aclResourceName')">
<el-input v-model="record.resource_name" :disabled="matchAllResource || selectedCluster">
<template #prepend>
<el-select
class="prepend-select"
v-model="record.pattern_type"
:disabled="selectedCluster"
@change="changeResourcePattern"
>
<el-option :label="tl('matchAll')" :value="StreamPatternType.All" />
<el-option :label="tl('literal')" :value="StreamPatternType.Literal" />
<el-option :label="tl('prefixed')" :value="StreamPatternType.Prefixed" />
</el-select>
</template>
</el-input>
</el-form-item>
<el-form-item prop="operation" :label="tl('aclOperation')">
<el-select v-model="record.operation">
<el-option
v-for="item in getValidOperations(record.resource_type)"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item prop="permission" :label="t('common.access')">
<el-radio-group v-model="record.permission">
<el-radio
v-for="item in permissionOptions"
:key="item.value"
:value="item.value"
:label="item.value"
>
{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</template>

<script setup lang="ts">
import {
STREAMING_CLUSTER_NAME,
STREAMING_MATCH_ALL,
StreamOperation,
StreamPatternType,
StreamPermission,
StreamResourceType,
} from '@emqx/shared-ui-constants'
import { useLocale, useStreamingAuth } from '@emqx/shared-ui-utils'
import { computed } from 'vue'

interface StreamACL {
principal_type: string
principal_name: string
host_type: StreamPatternType
host: string
resource_type: StreamResourceType
pattern_type: StreamPatternType
resource_name: string
operation: StreamOperation
permission: StreamPermission
}

const props = defineProps<{
modelValue: StreamACL
isEdit: boolean
// TODO: try to optimize
lang: 'en' | 'zh' | 'ja'
}>()
const emit = defineEmits<{
(e: 'update:modelValue', v: StreamACL): void
}>()

const { t } = useLocale(props.lang)
const tl = (key: string) => t(`streaming.${key}`)

const record = computed({
get() {
return props.modelValue
},
set(val) {
emit('update:modelValue', val)
},
})

const { permissionOptions, resourceTypeOptions, getValidOperations } = useStreamingAuth(props.lang)

const selectedCluster = computed(() => record.value.resource_type === StreamResourceType.Cluster)
const matchAllResource = computed(() => record.value.pattern_type === StreamPatternType.All)

const changeHostType = () => {
if (record.value.host_type === StreamPatternType.All) {
record.value.host = STREAMING_MATCH_ALL
} else if (record.value.host === STREAMING_MATCH_ALL) {
record.value.host = ''
}
}
const changeResourcePattern = () => {
if (matchAllResource.value) {
record.value.resource_name = STREAMING_MATCH_ALL
} else if (record.value.resource_name === STREAMING_MATCH_ALL) {
record.value.resource_name = ''
}
}
const changeResourceType = () => {
if (selectedCluster.value) {
record.value.pattern_type = StreamPatternType.Literal
record.value.resource_name = STREAMING_CLUSTER_NAME
} else {
record.value.pattern_type = StreamPatternType.All
record.value.resource_name = STREAMING_MATCH_ALL
}
record.value.operation = StreamOperation.All
}
</script>

<style lang="scss" />
58 changes: 58 additions & 0 deletions packages/components/streaming/StreamingAuthForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<template>
<el-form :model="record" label-position="top">
<el-form-item prop="mechanism" :label="t('streaming.authType')">
<el-select v-model="record.mechanism" :disabled="isEdit">
<el-option v-for="item in authTypeList" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item prop="user_name" :label="t('common.username')">
<el-input v-model="record.user_name" clearable :disabled="isEdit" />
</el-form-item>
<el-form-item prop="password" :label="t('common.password')">
<el-input
type="password"
v-model="record.password"
show-password
autocomplete="new-password"
clearable
/>
</el-form-item>
</el-form>
</template>

<script setup lang="ts">
import { StreamAuthType } from '@emqx/shared-ui-constants'
import { useLocale } from '@emqx/shared-ui-utils'
import { computed } from 'vue'

interface StreamRecord {
user_name: string
mechanism: StreamAuthType
password?: string
}

const props = defineProps<{
modelValue: StreamRecord
isEdit: boolean
// TODO: try to optimize
lang: 'en' | 'zh' | 'ja'
}>()
const emit = defineEmits<{
(e: 'update:modelValue', v: StreamRecord): void
}>()

const { t } = useLocale(props.lang)

const record = computed({
get() {
return props.modelValue
},
set(val) {
emit('update:modelValue', val)
},
})

const authTypeList = [StreamAuthType.Plain, StreamAuthType.SHA256]
</script>

<style lang="scss" />
Loading