Skip to content

Commit 3a600be

Browse files
authored
Merge pull request #442 from 0xJacky/enhance/ota
Enhance/ota
2 parents 01644cc + d389bb0 commit 3a600be

File tree

37 files changed

+2064
-1290
lines changed

37 files changed

+2064
-1290
lines changed

api/system/router.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,8 @@ func InitPublicRouter(r *gin.RouterGroup) {
1313
func InitPrivateRouter(r *gin.RouterGroup) {
1414
r.GET("upgrade/release", GetRelease)
1515
r.GET("upgrade/current", GetCurrentVersion)
16+
}
17+
18+
func InitWebSocketRouter(r *gin.RouterGroup) {
1619
r.GET("upgrade/perform", PerformCoreUpgrade)
1720
}

api/system/upgrade.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,8 @@ func PerformCoreUpgrade(c *gin.Context) {
139139
return
140140
}
141141

142-
_ = os.Remove(u.ExPath)
143142
// bye, overseer will restart nginx-ui
144-
err = u.PerformCoreUpgrade(u.ExPath, tarName)
143+
err = u.PerformCoreUpgrade(tarName)
145144
if err != nil {
146145
_ = ws.WriteJSON(CoreUpgradeResp{
147146
Status: UpgradeStatusError,

app/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,47 @@ manual `h(...)` calls), you can enable Volar's Take Over mode by following these
2121
2. Reload the VS Code window by running `Developer: Reload Window` from the command palette.
2222

2323
You can learn more about Take Over mode [here](https://github.com/johnsoncodehk/volar/discussions/471).
24+
25+
## Project Setup
26+
27+
```sh
28+
pnpm install
29+
```
30+
31+
**Note:** The default target of the api proxy is `http://localhost:9000`,
32+
if you need to change this, create the `.env` file in root directory and set your target in it.
33+
34+
```env
35+
VITE_PROXY_TARGET=http://localhost:9001
36+
```
37+
38+
### Compile and Hot-Reload for Development
39+
40+
```sh
41+
pnpm dev
42+
```
43+
44+
**Note:** The default port of the dev server is `3002`,
45+
if you need to change this, create the `.env` file in root directory and set your port in it.
46+
47+
```env
48+
VITE_PORT=3456
49+
```
50+
51+
### Code Style Check
52+
53+
```sh
54+
pnpm lint
55+
```
56+
57+
### Type Check
58+
59+
```sh
60+
pnpm typecheck
61+
```
62+
63+
### Compile and Minify for Production
64+
65+
```sh
66+
pnpm build
67+
```

app/components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ declare module 'vue' {
5454
ASelect: typeof import('ant-design-vue/es')['Select']
5555
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
5656
ASpace: typeof import('ant-design-vue/es')['Space']
57+
ASpin: typeof import('ant-design-vue/es')['Spin']
5758
AStatistic: typeof import('ant-design-vue/es')['Statistic']
5859
AStep: typeof import('ant-design-vue/es')['Step']
5960
ASteps: typeof import('ant-design-vue/es')['Steps']

app/src/App.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { useSettingsStore } from '@/pinia'
1212
import gettext from '@/gettext'
1313
import loadTranslations from '@/api/translations'
1414
15+
const route = useRoute()
16+
1517
const media = window.matchMedia('(prefers-color-scheme: dark)')
1618
1719
const callback = () => {
@@ -51,7 +53,7 @@ const lang = computed(() => {
5153
const settings = useSettingsStore()
5254
const is_theme_dark = computed(() => settings.theme === 'dark')
5355
54-
loadTranslations()
56+
loadTranslations(route)
5557
</script>
5658

5759
<template>

app/src/api/translations.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1+
import type { RouteLocationNormalizedLoadedGeneric } from 'vue-router'
12
import gettext from '@/gettext'
23

3-
export default async function loadTranslations() {
4-
const route = useRoute()
5-
4+
export default async function loadTranslations(route: RouteLocationNormalizedLoadedGeneric) {
65
if (gettext.current !== 'en') {
76
await fetch(`${import.meta.env.VITE_API_ROOT}/translation/${gettext.current}`).then(async r => {
87
gettext.translations[gettext.current] = await r.json()
@@ -12,7 +11,7 @@ export default async function loadTranslations() {
1211
document.title = `${route.meta.name?.()} | Nginx UI`
1312
}
1413

15-
watch(route, () => {
14+
watch(() => route, () => {
1615
if (route?.meta?.name)
1716
document.title = `${route.meta.name?.()} | Nginx UI`
1817
})

app/src/components/ChatGPT/ChatGPT.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ async function send() {
143143
messages.value = []
144144
145145
if (messages.value.length === 0) {
146-
console.log(current.value)
147146
messages.value.push({
148147
role: 'user',
149148
content: `${props.content}\n\nCurrent Language Code: ${current.value}`,

app/src/components/SetLanguage/SetLanguage.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const current = computed({
2121
const languageAvailable = gettext.available
2222
2323
watch(current, v => {
24-
loadTranslations()
24+
loadTranslations(route)
2525
settings.set_language(v)
2626
gettext.current = v
2727

app/src/components/StdDesign/StdDataDisplay/StdCurd.vue

Lines changed: 47 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<script setup lang="ts">
1+
<script setup lang="ts" generic="T=any">
22
import { message } from 'ant-design-vue'
33
import type { ComputedRef } from 'vue'
44
import type { StdTableProps } from './StdTable.vue'
@@ -7,7 +7,7 @@ import StdDataEntry from '@/components/StdDesign/StdDataEntry'
77
import type { Column } from '@/components/StdDesign/types'
88
import StdCurdDetail from '@/components/StdDesign/StdDataDisplay/StdCurdDetail.vue'
99
10-
export interface StdCurdProps {
10+
export interface StdCurdProps<T> extends StdTableProps<T> {
1111
cardTitleKey?: string
1212
modalMaxWidth?: string | number
1313
modalMask?: boolean
@@ -16,28 +16,28 @@ export interface StdCurdProps {
1616
1717
disableAdd?: boolean
1818
onClickAdd?: () => void
19-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
20-
onClickEdit?: (id: number | string, record: any, index: number) => void
19+
20+
onClickEdit?: (id: number | string, record: T, index: number) => void
2121
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2222
beforeSave?: (data: any) => Promise<void>
2323
}
2424
25-
const props = defineProps<StdTableProps & StdCurdProps>()
26-
const route = useRoute()
27-
const router = useRouter()
25+
const props = defineProps<StdTableProps<T> & StdCurdProps<T>>()
2826
const visible = ref(false)
29-
const update = ref(0)
3027
// eslint-disable-next-line @typescript-eslint/no-explicit-any
3128
const data: any = reactive({ id: null })
3229
const modifyMode = ref(true)
3330
const editMode = ref<string>()
31+
const shouldRefetchList = ref(false)
3432
3533
provide('data', data)
3634
provide('editMode', editMode)
35+
provide('shouldRefetchList', shouldRefetchList)
3736
3837
// eslint-disable-next-line @typescript-eslint/no-explicit-any
3938
const error: any = reactive({})
4039
const selected = ref([])
40+
4141
// eslint-disable-next-line @typescript-eslint/no-explicit-any
4242
function onSelect(keys: any) {
4343
selected.value = keys
@@ -49,19 +49,35 @@ const editableColumns = computed(() => {
4949
})
5050
}) as ComputedRef<Column[]>
5151
52-
function add() {
52+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
53+
function add(preset: any = undefined) {
54+
if (props.onClickAdd)
55+
return
5356
Object.keys(data).forEach(v => {
5457
delete data[v]
5558
})
5659
60+
if (preset)
61+
Object.assign(data, preset)
62+
5763
clear_error()
5864
visible.value = true
5965
editMode.value = 'create'
6066
modifyMode.value = true
6167
}
68+
6269
const table = ref()
6370
64-
const selectedRowKeys = ref([])
71+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
72+
const selectedRowKeys = defineModel<any[]>('selectedRowKeys', {
73+
default: () => [],
74+
})
75+
76+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
77+
const selectedRows = defineModel<any[]>('selectedRows', {
78+
type: Array,
79+
default: () => [],
80+
})
6581
6682
const getParams = reactive({
6783
trash: false,
@@ -91,13 +107,14 @@ function clear_error() {
91107
}
92108
93109
const stdEntryRef = ref()
110+
94111
async function ok() {
95112
const { formRef } = stdEntryRef.value
96113
97114
clear_error()
98115
try {
99116
await formRef.validateFields()
100-
await props?.beforeSave?.(data)
117+
props?.beforeSave?.(data)
101118
props
102119
.api!.save(data.id, { ...data, ...props.overwriteParams }, { params: { ...props.overwriteParams } })
103120
.then(r => {
@@ -111,37 +128,26 @@ async function ok() {
111128
Object.assign(error, e.errors)
112129
})
113130
}
114-
catch { }
131+
catch {
132+
message.error($gettext('Please fill in the required fields'))
133+
}
115134
}
116135
117136
function cancel() {
118137
visible.value = false
119138
120139
clear_error()
121-
}
122140
123-
watch(visible, v => {
124-
if (!v) {
125-
router.push({
126-
query: {
127-
...route.query,
128-
[`open.${props.rowKey || 'id'}`]: undefined,
129-
},
130-
})
141+
if (shouldRefetchList.value) {
142+
get_list()
143+
shouldRefetchList.value = false
131144
}
132-
})
133-
134-
watch(modifyMode, v => {
135-
router.push({
136-
query: {
137-
...route.query,
138-
modify_mode: v.toString(),
139-
},
140-
})
141-
})
145+
}
142146
143147
function edit(id: number | string) {
144-
get(id, true).then(() => {
148+
if (props.onClickEdit)
149+
return
150+
get(id).then(() => {
145151
visible.value = true
146152
modifyMode.value = true
147153
editMode.value = 'modify'
@@ -151,15 +157,15 @@ function edit(id: number | string) {
151157
}
152158
153159
function view(id: number | string) {
154-
get(id, false).then(() => {
160+
get(id).then(() => {
155161
visible.value = true
156162
modifyMode.value = false
157163
}).catch(e => {
158164
message.error($gettext(e?.message ?? 'Server error'), 5)
159165
})
160166
}
161167
162-
async function get(id: number | string, _modifyMode: boolean) {
168+
async function get(id: number | string) {
163169
return props
164170
.api!.get(id, { ...props.overwriteParams })
165171
.then(async r => {
@@ -168,32 +174,14 @@ async function get(id: number | string, _modifyMode: boolean) {
168174
})
169175
data.id = null
170176
Object.assign(data, r)
171-
if (!props.disabledModify) {
172-
await router.push({
173-
query: {
174-
...route.query,
175-
[`open.${props.rowKey || 'id'}`]: id,
176-
modify_mode: _modifyMode.toString(),
177-
},
178-
})
179-
}
180177
})
181178
}
182179
183-
onMounted(async () => {
184-
const id = route.query[`open.${props.rowKey || 'id'}`] as string
185-
const _modifyMode = (route.query.modify_mode as string) === 'true'
186-
if (id && !props.disabledModify && _modifyMode)
187-
edit(id)
188-
189-
if (id && !props.disabledView && !_modifyMode)
190-
view(id)
191-
})
192-
193180
const modalTitle = computed(() => {
194181
return data.id ? modifyMode.value ? $gettext('Modify') : $gettext('View Details') : $gettext('Add')
195182
})
196183
184+
const localOverwriteParams = reactive(props.overwriteParams ?? {})
197185
</script>
198186

199187
<template>
@@ -209,7 +197,7 @@ const modalTitle = computed(() => {
209197
<ASpace>
210198
<slot name="beforeAdd" />
211199
<a
212-
v-if="!disableAdd"
200+
v-if="!disableAdd && !getParams.trash"
213201
@click="add"
214202
>{{ $gettext('Add') }}</a>
215203
<slot name="extra" />
@@ -224,19 +212,20 @@ const modalTitle = computed(() => {
224212
v-else
225213
@click="getParams.trash = false"
226214
>
227-
{{ $gettext('List') }}
215+
{{ $gettext('Back to list') }}
228216
</a>
229217
</template>
230218
</ASpace>
231219
</template>
232220

233221
<StdTable
234222
ref="table"
235-
:key="update"
236223
v-model:selected-row-keys="selectedRowKeys"
224+
v-model:selected-rows="selectedRows"
237225
v-bind="{
238226
...props,
239227
getParams,
228+
overwriteParams: localOverwriteParams,
240229
}"
241230
@click-edit="edit"
242231
@click-view="view"
@@ -269,7 +258,7 @@ const modalTitle = computed(() => {
269258
@ok="ok"
270259
>
271260
<div
272-
v-if="!disabledModify && !disabledView"
261+
v-if="!disableModify && !disableView && editMode === 'modify'"
273262
class="m-2 flex justify-end"
274263
>
275264
<ASwitch
@@ -294,7 +283,7 @@ const modalTitle = computed(() => {
294283
ref="stdEntryRef"
295284
:data-list="editableColumns"
296285
:data-source="data"
297-
:error="error"
286+
:errors="error"
298287
/>
299288

300289
<slot

0 commit comments

Comments
 (0)