Skip to content

Commit

Permalink
fix(ui/sidebar): show env variables in sidebar settings ui (#946) (#956)
Browse files Browse the repository at this point in the history
* fix(ui/sidebar): show env variables in sidebar settings ui (#946)

* fix unit test
  • Loading branch information
qwqcode authored Aug 19, 2024
1 parent 528847d commit 4d7e157
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 52 deletions.
7 changes: 7 additions & 0 deletions docs/swagger/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -4970,9 +4970,16 @@ const docTemplate = `{
"handler.ResponseSettingGet": {
"type": "object",
"required": [
"envs",
"yaml"
],
"properties": {
"envs": {
"type": "array",
"items": {
"type": "string"
}
},
"yaml": {
"type": "string"
}
Expand Down
7 changes: 7 additions & 0 deletions docs/swagger/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -4963,9 +4963,16 @@
"handler.ResponseSettingGet": {
"type": "object",
"required": [
"envs",
"yaml"
],
"properties": {
"envs": {
"type": "array",
"items": {
"type": "string"
}
},
"yaml": {
"type": "string"
}
Expand Down
5 changes: 5 additions & 0 deletions docs/swagger/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1012,9 +1012,14 @@ definitions:
type: object
handler.ResponseSettingGet:
properties:
envs:
items:
type: string
type: array
yaml:
type: string
required:
- envs
- yaml
type: object
handler.ResponseSettingTemplate:
Expand Down
11 changes: 10 additions & 1 deletion server/handler/setting_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ package handler

import (
"os"
"strings"

"github.com/ArtalkJS/Artalk/internal/core"
"github.com/ArtalkJS/Artalk/internal/i18n"
"github.com/ArtalkJS/Artalk/server/common"
"github.com/gofiber/fiber/v2"
"github.com/samber/lo"
)

type ResponseSettingGet struct {
Yaml string `json:"yaml"`
Yaml string `json:"yaml"`
Envs []string `json:"envs"`
}

// @Id GetSettings
Expand All @@ -30,8 +33,14 @@ func SettingGet(app *core.App, router fiber.Router) {
return common.RespError(c, 500, i18n.T("Config file read failed"))
}

// get all environment variables which start with ATK_
envs := lo.Filter(os.Environ(), func(v string, _ int) bool {
return strings.HasPrefix(v, "ATK_")
})

return common.RespData(c, ResponseSettingGet{
Yaml: string(dat),
Envs: envs,
})
}))
}
20 changes: 16 additions & 4 deletions ui/artalk-sidebar/src/components/PreferenceArr.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,22 @@ const props = defineProps<{
}>()
const customValue = ref<string[]>([])
const disabled = ref(false)
onMounted(() => {
sync()
})
function sync() {
const value = settings.get().getCustom(props.node.path)
customValue.value = value && typeof value.toJSON === 'function' ? value.toJSON() : []
disabled.value = !!settings.get().getEnvByPath(props.node.path)
if (typeof value === 'object' && 'toJSON' in value && typeof value.toJSON === 'function') {
customValue.value = value.toJSON()
} else if (typeof value === 'string') {
customValue.value = value.split(' ')
} else {
customValue.value = []
}
}
function save() {
Expand Down Expand Up @@ -43,21 +51,25 @@ function add() {
<input
type="text"
:value="String(item)"
:disabled="disabled"
@change="onChange(index, ($event.target as any).value)"
/>
<button class="act-btn" @click="remove(index)">-</button>
<button v-if="!disabled" class="act-btn" @click="remove(index)">-</button>
</div>
<div class="act-grp">
<div v-if="!disabled" class="act-grp">
<button class="act-btn" @click="add()">+</button>
</div>
</div>
</template>

<style scoped lang="scss">
.arr-grp {
width: 100%;
}
.arr-item {
position: relative;
margin-bottom: 20px;
margin-left: 10px;
padding-right: 50px;
.act-btn {
Expand Down
34 changes: 31 additions & 3 deletions ui/artalk-sidebar/src/components/PreferenceItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ const props = defineProps<{
}>()
const value = ref('')
const disabled = ref(false)
const { t } = useI18n()
onBeforeMount(() => {
// initial value
value.value = settings.get().getCustom(props.node.path)
disabled.value = !!settings.get().getEnvByPath(props.node.path)
})
function onChange() {
Expand All @@ -27,14 +31,18 @@ function onChange() {
</div>

<div class="value">
<div v-if="disabled" class="disable-note">
{{ t('envVarControlHint', { key: 'ATK_' + props.node.path.toUpperCase() }) }}
</div>

<!-- Array -->
<template v-if="node.type === 'array'">
<PreferenceArr :node="node" />
</template>

<!-- 候选框 -->
<template v-else-if="node.selector">
<select v-model="value" @change="onChange">
<select v-model="value" :disabled="disabled" @change="onChange">
<option v-for="(item, i) in node.selector" :key="i" :value="item">
{{ item }}
</option>
Expand All @@ -43,12 +51,12 @@ function onChange() {

<!-- 开关 -->
<template v-else-if="node.type === 'boolean'">
<input v-model="value" type="checkbox" @change="onChange" />
<input v-model="value" type="checkbox" :disabled="disabled" @change="onChange" />
</template>

<!-- 文本框 -->
<template v-else>
<input v-model="value" type="text" @change="onChange" />
<input v-model="value" type="text" :disabled="disabled" @change="onChange" />
</template>
</div>
</div>
Expand Down Expand Up @@ -78,12 +86,32 @@ function onChange() {
}
& > .value {
position: relative;
flex: 1;
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
min-height: 35px;
&:hover {
.disable-note {
opacity: 1;
}
}
.disable-note {
z-index: 999;
padding: 3px 8px;
background: rgba(105, 113, 130, 0.9);
color: #fff;
position: absolute;
top: -30px;
font-size: 13px;
left: 0;
opacity: 0;
transition: opacity 0.2s;
}
}
}
</style>
3 changes: 3 additions & 0 deletions ui/artalk-sidebar/src/i18n/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const en = {
commentAllowAll: 'Anyone Comment',
commentOnlyAdmin: 'Admin Comment Only',
config: 'Config',
envVarControlHint: 'Referenced by the environment variable {key}',
userAdminHint: 'Admin user',
userInConfHint: 'This user is defined in config file',
edit: 'Edit',
Expand Down Expand Up @@ -118,6 +119,7 @@ const zhCN: typeof en = {
commentAllowAll: '所有人可评',
commentOnlyAdmin: '仅管理员可评',
config: '配置文件',
envVarControlHint: '由环境变量 {key} 控制',
userAdminHint: '该用户具有管理员权限',
userInConfHint: '该用户存在于配置文件中',
edit: '编辑',
Expand Down Expand Up @@ -201,6 +203,7 @@ const zhTW: typeof en = {
commentAllowAll: '允許任何人評論',
commentOnlyAdmin: '僅允許管理員評論',
config: '配置文件',
envVarControlHint: '由環境變數 {key} 參照',
userAdminHint: '該用戶具有管理員權限',
userInConfHint: '該用戶存在於配置文件中',
edit: '編輯',
Expand Down
29 changes: 29 additions & 0 deletions ui/artalk-sidebar/src/lib/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export class Settings {
private tree: OptionNode
private flatten: { [path: string]: OptionNode }
private customs = shallowRef<YAML.Document.Parsed<YAML.ParsedNode>>()
private envs = shallowRef<{ [key: string]: string }>()

constructor(yamlObj: YAML.Document.Parsed) {
this.tree = getTree(yamlObj)
Expand All @@ -27,7 +28,35 @@ export class Settings {
this.customs.value = YAML.parseDocument(yamlStr)
}

setEnvs(envs: string[]) {
const envsObj: { [key: string]: string } = {}
envs.forEach((env) => {
const [key, value] = env.split('=')
envsObj[key] = value
})
this.envs.value = envsObj
}

getEnv(key: string) {
return this.envs.value?.[key] || null
}

getEnvByPath(path: string) {
// replace `.` to `_` and uppercase
// replace `ATK_TRUSTED_DOMAINS_0` to `ATK_TRUSTED_DOMAINS`
// replace `ATK_ADMIN_USERS_0_NAME` to `ATK_ADMIN_USERS`
return this.getEnv(
'ATK_' +
path
.replace(/\./g, '_')
.toUpperCase()
.replace(/(_\d+?_\w+|_\d+)$/, ''),
)
}

getCustom(path: string) {
const env = this.getEnvByPath(path)
if (env) return env
return this.customs.value?.getIn(path.split('.')) as any
}

Expand Down
1 change: 1 addition & 0 deletions ui/artalk-sidebar/src/pages/settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ onMounted(() => {
tree.value = settings.init(yamlObj).getTree()
// console.log(tree.value)
settings.get().setCustoms(custom.data.yaml)
settings.get().setEnvs(custom.data.envs)
})
})
Expand Down
7 changes: 4 additions & 3 deletions ui/artalk/src/api/v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ export interface HandlerResponsePageUpdate {
}

export interface HandlerResponseSettingGet {
envs: string[]
yaml: string
}

Expand Down Expand Up @@ -697,8 +698,8 @@ export class HttpClient<SecurityDataType = unknown> {
property instanceof Blob
? property
: typeof property === 'object' && property !== null
? JSON.stringify(property)
: `${property}`,
? JSON.stringify(property)
: `${property}`,
)
return formData
}, new FormData()),
Expand Down Expand Up @@ -774,7 +775,7 @@ export class HttpClient<SecurityDataType = unknown> {
body: typeof body === 'undefined' || body === null ? null : payloadFormatter(body),
},
).then(async (response) => {
const r = response as HttpResponse<T, E>
const r = response.clone() as HttpResponse<T, E>
r.data = null as unknown as T
r.error = null as unknown as E

Expand Down
Loading

0 comments on commit 4d7e157

Please sign in to comment.