Skip to content

Commit

Permalink
ui: Use element-plus instead of naive-ui
Browse files Browse the repository at this point in the history
When some components need custom rendering, slot cannot be used, only the
h function can be used in `naive-ui`. As a typical example, when using a
table component, you often need to do a custom rendering of a column of
data returned by the background. At this point in the `.vue` single file
can only use the h function to perform custom rendering.

Signed-off-by: Jianhui Zhao <[email protected]>
  • Loading branch information
zhaojh329 committed Nov 25, 2023
1 parent a2fb11c commit 0423c04
Show file tree
Hide file tree
Showing 48 changed files with 6,206 additions and 4,260 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

[Lua-eco]: https://github.com/zhaojh329/lua-eco
[Vue3]: https://github.com/vuejs/core
[Naive-ui]: https://github.com/tusen-ai/naive-ui
[Element Plus]: https://github.com/element-plus/element-plus
[Vite]: https://github.com/vitejs/vite

![](/oui.gif)
Expand All @@ -25,7 +25,7 @@ A `framework` used to develop Web interface for OpenWrt.

* Separation of front-end and backend
* Developing back-end APIs using [Lua-eco].
* Developing front-end pages using [Vue3] + [Naive-ui] + [Vite].
* Developing front-end pages using [Vue3] + [Element Plus] + [Vite].
* Support multi-user and ACL management, provides fine-grained permission management.
* Modularization as with Luci, each page is individually packaged as an IPK.

Expand Down
48 changes: 48 additions & 0 deletions applications/oui-app-acl/files/rpc/acl.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
local file = require 'eco.file'
local cjson = require 'cjson'
local rpc = require 'oui.rpc'

local M = {}

function M.load()
local res = {}

for group, acls in pairs(rpc.get_acls()) do
local acl = {}

for cls, info in pairs(acls) do
acl[#acl + 1] = {
cls = cls,
matchs = info.matchs,
reverse = not not info.reverse
}
end

res[group] = acl
end

return res
end

function M.set(params)
for name in file.dir('/usr/share/oui/acl') do
if name ~= '.' and name ~= '..' then
os.remove('/usr/share/oui/acl/' .. name)
end
end

for group, acls in pairs((params.acls)) do
local acl = {}
for _, info in ipairs(acls) do
acl[info.cls] = {
matchs = info.matchs,
reverse = info.reverse
}
end
file.writefile('/usr/share/oui/acl/' .. group .. '.json', cjson.encode(acl))
end

rpc.load_acl()
end

return M
41 changes: 41 additions & 0 deletions applications/oui-app-acl/htdoc/dynamic-tags.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<template>
<el-tag v-for="tag in modelValue" :key="tag" style="margin-right: 10px;" closable @close="handleClose(tag)">{{ tag }}</el-tag>
<el-input v-if="inputVisible" ref="InputRef" v-model="inputValue" style="width: 200px;" size="small"
@keyup.enter="handleInputConfirm" @blur="handleInputConfirm"/>
<el-button v-else class="button" size="small" @click="showInput">+</el-button>
</template>

<script>
import { nextTick } from 'vue'
export default {
props: {
modelValue: {
type: Array,
required: true
}
},
emits: ['update:modelValue'],
data() {
return {
inputVisible: false,
inputValue: ''
}
},
methods: {
handleClose(tag) {
this.$emit('update:modelValue', this.modelValue.filter(x => x !== tag))
},
showInput() {
this.inputVisible = true
nextTick(() => this.$refs.InputRef.input.focus())
},
handleInputConfirm() {
if (this.inputValue)
this.$emit('update:modelValue', [...this.modelValue, this.inputValue])
this.inputVisible = false
this.inputValue = ''
}
}
}
</script>
145 changes: 52 additions & 93 deletions applications/oui-app-acl/htdoc/index.vue
Original file line number Diff line number Diff line change
@@ -1,123 +1,82 @@
<template>
<n-space>
<n-select v-model:value="group" :options="groups" style="width: 200px"/>
<n-button type="primary" @click="addGroup">{{ $t('Add group') }}</n-button>
</n-space>
<n-divider></n-divider>
<n-data-table :row-key="r => r.cls" :columns="columns" :data="acls"/>
<n-divider></n-divider>
<n-space justify="end" style="padding-right: 100px">
<n-button type="primary" :loading="loading" @click="handleSubmit">{{ $t('Save & Apply') }}</n-button>
</n-space>
<el-space>
<el-select v-model="group">
<el-option v-for="o in groups" :key="o" :label="o" :value="o"/>
</el-select>
<el-button type="primary" @click="addGroup">{{ $t('Add group') }}</el-button>
<el-button type="danger" @click="delGroup" :disabled="group == 'admin'">{{ $t('Delete group') }}</el-button>
</el-space>
<el-divider/>
<el-table :data="acls[group]">
<el-table-column prop="cls" :label="$t('Class')" width="80"/>
<el-table-column :label="$t('Matchs')">
<template #default="{ row }">
<dynamic-tags v-model="row.matchs"/>
</template>
</el-table-column>
<el-table-column :label="$t('Reverse')" width="80">
<template #default="{ row }">
<el-switch v-model="row.reverse"/>
</template>
</el-table-column>
</el-table>
<el-divider/>
<el-button type="primary" @click="handleSubmit">{{ $t('Save & Apply') }}</el-button>
</template>

<script>
import { h, resolveComponent } from 'vue'
import DynamicTags from './dynamic-tags.vue'
export default {
components: {
DynamicTags
},
data() {
return {
columns: [
{
title: () => this.$t('Class'),
key: 'cls',
width: 100
},
{
title: () => this.$t('Matchs'),
key: 'matchs',
ellipsis: {
tooltip: true
},
render: r => h(resolveComponent('n-dynamic-tags'), {
value: r.matchs,
'on-update:value': value => {
if (value.length > r.matchs.length) {
r.matchs.push(value[value.length - 1])
return
}
r.matchs.forEach((m, i) => {
if (!value.includes(m)) {
r.matchs.splice(i, 1)
return false
}
})
}
})
},
{
title: () => this.$t('Reverse'),
key: 'reverse',
width: 100,
render: r => h(resolveComponent('n-switch'), {
value: r.reverse,
'on-update:value': value => this.allAcls[this.group][r.cls].reverse = value
})
}
],
group: '',
allAcls: {},
loading: false
acls: {}
}
},
computed: {
groups() {
return Object.keys(this.allAcls).map(group => {
return {
label: group,
value: group
}
})
},
acls() {
if (!this.allAcls || !this.group)
return []
const acls = this.allAcls[this.group]
return Object.keys(acls).map(cls => {
return {
cls: cls,
matchs: acls[cls].matchs,
reverse: acls[cls].reverse || false
}
})
return Object.keys(this.acls)
}
},
methods: {
handleSubmit() {
this.loading = true
this.$oui.call('acl', 'set', { acls: this.allAcls }).then(() => this.loading = false)
this.$oui.call('acl', 'set', { acls: this.acls })
},
addGroup() {
let group = ''
this.$dialog.create({
title: this.$t('Add group'),
content: () => h(resolveComponent('n-input'), {
'on-update:value': value => group = value
}),
positiveText: this.$t('OK'),
onPositiveClick: () => {
group = group.trim()
if (!group)
return
this.$prompt('', this.$t('Add group'), {
}).then(({ value }) => {
value = value.trim()
if (!value)
return
this.allAcls[group] = {
rpc: { matchs: [ '.+' ] },
menu: { matchs: [ '.+' ] },
ubus: { matchs: [ '.+' ] },
uci: { matchs: [ '.+' ] }
this.acls[value] = [ 'rpc', 'menu', 'ubus', 'uci' ].map(cls => {
return {
cls: cls,
matchs: [ '.+' ],
reverse: false
}
})
this.group = group
}
this.group = value
})
},
delGroup() {
this.$confirm(this.$t('delete-group-confirm', { group: this.group }), this.$t('Delete group'), {
type: 'warning'
}).then(() => {
delete this.acls[this.group]
this.group = this.groups[0]
})
}
},
created() {
this.$oui.call('acl', 'load').then(acls => {
this.allAcls = acls
this.group = this.groups[0].value
this.acls = acls
this.group = this.groups[0]
})
}
}
Expand Down
6 changes: 6 additions & 0 deletions applications/oui-app-acl/htdoc/locale.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"Reverse": "Reverse",
"Change Matchs": "Change Matchs",
"Add group": "Add group",
"Delete group": "Delete group",
"delete-group-confirm": "Are you sure you want to delete the group '{ group }'?",
"Save & Apply": "Save & Apply"
},
"zh-CN": {
Expand All @@ -14,6 +16,8 @@
"Matchs": "匹配项",
"Reverse": "反向匹配",
"Add group": "添加组",
"Delete group": "删除组",
"delete-group-confirm": "你确定要删除组 \"{ group }\" 吗?",
"Save & Apply": "保存和应用"
},
"zh-TW": {
Expand All @@ -23,6 +27,8 @@
"Reverse": "反向匹配",
"Username": "用戶名",
"Add group": "添加組",
"Delete group": "刪除組",
"delete-group-confirm": "你確定要刪除組 \"{ group }\" 嗎?",
"Save & Apply": "保存和應用"
}
}
Loading

0 comments on commit 0423c04

Please sign in to comment.