Browse Source

enhance: optimize the experience on small devices

Jacky 3 tháng trước cách đây
mục cha
commit
9e66c355bf

+ 19 - 6
app/src/layouts/BaseLayout.vue

@@ -8,12 +8,24 @@ import FooterLayout from './FooterLayout.vue'
 import HeaderLayout from './HeaderLayout.vue'
 import SideBar from './SideBar.vue'
 
-const drawer_visible = ref(false)
+const drawerVisible = ref(false)
 const collapsed = ref(collapse())
+const hideLayoutSidebar = ref(false)
 
-addEventListener('resize', _.throttle(() => {
+function _init() {
   collapsed.value = collapse()
-}, 50))
+  hideLayoutSidebar.value = getClientWidth() < 600
+}
+
+const init = _.throttle(_init, 50)
+
+onMounted(init)
+
+addEventListener('resize', init)
+
+onUnmounted(() => {
+  removeEventListener('resize', init)
+})
 
 function getClientWidth() {
   return document.body.clientWidth
@@ -38,17 +50,18 @@ provide('breadList', breadList)
   <ALayout class="full-screen-wrapper min-h-screen">
     <div class="drawer-sidebar">
       <ADrawer
-        v-model:open="drawer_visible"
+        v-model:open="drawerVisible"
         :closable="false"
         placement="left"
         width="256"
-        @close="drawer_visible = false"
+        @close="drawerVisible = false"
       >
         <SideBar />
       </ADrawer>
     </div>
 
     <ALayoutSider
+      v-if="!hideLayoutSidebar"
       v-model:collapsed="collapsed"
       collapsible
       :style="{ zIndex: 11 }"
@@ -60,7 +73,7 @@ provide('breadList', breadList)
 
     <ALayout class="main-container">
       <ALayoutHeader :style="{ position: 'sticky', top: '0', zIndex: 10, width: '100%' }">
-        <HeaderLayout @click-un-fold="drawer_visible = true" />
+        <HeaderLayout @click-un-fold="drawerVisible = true" />
       </ALayoutHeader>
 
       <ALayoutContent>

+ 3 - 3
app/src/routes/index.ts

@@ -227,11 +227,11 @@ export const routes: RouteRecordRaw[] = [
         }],
       },
       {
-        path: 'environment',
-        name: 'Environment',
+        path: 'environments',
+        name: 'Environments',
         component: () => import('@/views/environment/Environment.vue'),
         meta: {
-          name: () => $gettext('Environment'),
+          name: () => $gettext('Environments'),
           icon: DatabaseOutlined,
           hiddenInSidebar: (): boolean => {
             const settings = useSettingsStore()

+ 1 - 0
app/src/views/certificate/ACMEUser.vue

@@ -94,6 +94,7 @@ const columns: Column[] = [
   {
     title: () => $gettext('Action'),
     dataIndex: 'action',
+    fixed: 'right',
   },
 ]
 

+ 1 - 0
app/src/views/certificate/CertificateList/Certificate.vue

@@ -33,6 +33,7 @@ const refTable = ref()
       :api="cert"
       :columns="certColumns"
       disable-view
+      :scroll-x="1000"
       @click-edit="id => $router.push(`/certificates/${id}`)"
     />
     <WildcardCertificate

+ 1 - 0
app/src/views/certificate/CertificateList/certColumns.tsx

@@ -96,6 +96,7 @@ const columns: Column[] = [{
 }, {
   title: () => $gettext('Action'),
   dataIndex: 'action',
+  fixed: 'right',
 }]
 
 export default columns

+ 1 - 0
app/src/views/config/ConfigList.vue

@@ -135,6 +135,7 @@ const refRename = useTemplateRef('refRename')
       :get-params="getParams"
       disable-query-params
       disable-modify
+      :scroll-x="880"
     >
       <template #actions="{ record }">
         <AButton

+ 20 - 14
app/src/views/config/configColumns.ts → app/src/views/config/configColumns.tsx

@@ -1,8 +1,7 @@
 import type { CustomRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
-import type { JSXElements } from '@/components/StdDesign/types'
 import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
 import { input } from '@/components/StdDesign/StdDataEntry'
-import { h } from 'vue'
+import { FileFilled, FolderFilled } from '@ant-design/icons-vue'
 
 const configColumns = [{
   title: () => $gettext('Name'),
@@ -12,21 +11,25 @@ const configColumns = [{
   search: {
     type: input,
   },
-}, {
-  title: () => $gettext('Type'),
-  dataIndex: 'is_dir',
   customRender: (args: CustomRender) => {
-    const template: JSXElements = []
-    const { text } = args
-    if (text === true || text > 0)
-      template.push($gettext('Directory'))
-    else
-      template.push($gettext('File'))
+    function renderIcon(isDir: boolean) {
+      return (
+        <div class="mr-2 text-truegray-5">
+          {isDir
+            ? <FolderFilled />
+            : <FileFilled />}
+        </div>
+      )
+    }
 
-    return h('div', template)
+    return (
+      <div class="flex">
+        {renderIcon(args.record.is_dir)}
+        {args.text}
+      </div>
+    )
   },
-  sorter: true,
-  pithy: true,
+  width: 500,
 }, {
   title: () => $gettext('Updated at'),
   dataIndex: 'modified_at',
@@ -34,9 +37,12 @@ const configColumns = [{
   datetime: true,
   sorter: true,
   pithy: true,
+  width: 200,
 }, {
   title: () => $gettext('Action'),
   dataIndex: 'action',
+  fixed: 'right',
+  width: 180,
 }]
 
 export default configColumns

+ 5 - 2
app/src/views/environment/Environment.vue

@@ -28,13 +28,16 @@ function batchUpgrade() {
       ref="curd"
       v-model:selected-row-keys="selectedNodeIds"
       v-model:selected-rows="selectedNodes"
+      :scroll-x="1000"
       selection-type="checkbox"
-      :title="$gettext('Environment')"
+      :title="$gettext('Environments')"
       :api="environment"
       :columns="envColumns"
     >
       <template #beforeAdd>
-        <a @click="loadFromSettings">{{ $gettext('Load from settings') }}</a>
+        <AButton size="small" type="link" @click="loadFromSettings">
+          {{ $gettext('Load from settings') }}
+        </AButton>
       </template>
     </StdCurd>
 

+ 9 - 35
app/src/views/environment/envColumns.tsx

@@ -14,6 +14,7 @@ const columns: Column[] = [{
     type: input,
   },
   search: true,
+  width: 200,
 }, {
   title: () => $gettext('URL'),
   dataIndex: 'url',
@@ -25,10 +26,12 @@ const columns: Column[] = [{
       placeholder: () => 'https://10.0.0.1:9000',
     },
   },
+  width: 300,
 }, {
   title: () => $gettext('Version'),
   dataIndex: 'version',
   pithy: true,
+  width: 150,
 }, {
   title: () => 'NodeSecret',
   dataIndex: 'token',
@@ -37,41 +40,7 @@ const columns: Column[] = [{
   edit: {
     type: input,
   },
-},
-
-//     {
-//     title: () => $gettext('OperationSync'),
-//     dataIndex: 'operation_sync',
-//     sorter: true,
-//     pithy: true,
-//     edit: {
-//         type: antSwitch
-//     },
-//     extra: $gettext('Whether config api regex that will redo on this environment'),
-//     customRender: (args: customRender) => {
-//         const {operation_sync} = args.record
-//         if (operation_sync) {
-//             return h(Tag, {color: 'success'}, {default: ()=> h('span', $gettext('Yes'))})
-//         } else {
-//             return h(Tag, {color: 'default'}, {default: ()=> h('span', $gettext('No'))})
-//         }
-//     },
-// }, {
-//     title: () => $gettext('SyncApiRegex'),
-//     dataIndex: 'sync_api_regex',
-//     sorter: true,
-//     pithy: true,
-//     display: false,
-//     edit: {
-//       type: textarea,
-//       show: (data) => {
-//         const {operation_sync} = data
-//         return operation_sync
-//       }
-//     },
-//     extra: $gettext('Such as Reload and Configs, regex can configure as `/api/nginx/reload|/api/nginx/test|/api/config/.+`, please see system api'),
-// },
-{
+}, {
   title: () => $gettext('Status'),
   dataIndex: 'status',
   customRender: (args: CustomRender) => {
@@ -96,6 +65,7 @@ const columns: Column[] = [{
   },
   sorter: true,
   pithy: true,
+  width: 200,
 }, {
   title: () => $gettext('Enabled'),
   dataIndex: 'enabled',
@@ -115,15 +85,19 @@ const columns: Column[] = [{
   },
   sorter: true,
   pithy: true,
+  width: 150,
 }, {
   title: () => $gettext('Updated at'),
   dataIndex: 'updated_at',
   customRender: datetime,
   sorter: true,
   pithy: true,
+  width: 150,
 }, {
   title: () => $gettext('Action'),
   dataIndex: 'action',
+  fixed: 'right',
+  width: 200,
 }]
 
 export default columns

+ 1 - 0
app/src/views/notification/Notification.vue

@@ -24,6 +24,7 @@ watch(unreadCount, () => {
 <template>
   <StdCurd
     ref="curd"
+    :scroll-x="1000"
     :title="$gettext('Notification')"
     :columns="notificationColumns"
     :api="notification"

+ 4 - 0
app/src/views/notification/notificationColumns.tsx

@@ -47,20 +47,24 @@ const columns: Column[] = [{
     return h('span', $gettext(args.text))
   },
   pithy: true,
+  width: 250,
 }, {
   title: () => $gettext('Details'),
   dataIndex: 'details',
   customRender: detailRender,
   pithy: true,
+  width: 300,
 }, {
   title: () => $gettext('Created at'),
   dataIndex: 'created_at',
   sorter: true,
   customRender: datetime,
   pithy: true,
+  width: 180,
 }, {
   title: () => $gettext('Action'),
   dataIndex: 'action',
+  fixed: 'right',
 }]
 
 export default columns

+ 1 - 0
app/src/views/site/site_category/SiteCategory.vue

@@ -10,6 +10,7 @@ import columns from '@/views/site/site_category/columns'
     :title="$gettext('Site Categories')"
     :api="site_category"
     :columns="columns"
+    :scroll-x="600"
   >
     <template #edit="{ data }">
       <div class="mb-2">

+ 5 - 0
app/src/views/site/site_category/columns.ts

@@ -10,21 +10,26 @@ const columns: Column[] = [{
     type: input,
   },
   pithy: true,
+  width: 120,
 }, {
   title: () => $gettext('Created at'),
   dataIndex: 'created_at',
   customRender: datetime,
   sorter: true,
   pithy: true,
+  width: 150,
 }, {
   title: () => $gettext('Updated at'),
   dataIndex: 'updated_at',
   customRender: datetime,
   sorter: true,
   pithy: true,
+  width: 150,
 }, {
   title: () => $gettext('Action'),
   dataIndex: 'action',
+  fixed: 'right',
+  width: 150,
 }]
 
 export default columns

+ 1 - 0
app/src/views/site/site_list/SiteList.vue

@@ -109,6 +109,7 @@ function handleBatchUpdated() {
       :get-params="{
         site_category_id: siteCategoryId,
       }"
+      :scroll-x="1200"
       @click-edit="(r: string) => router.push({
         path: `/sites/${r}`,
       })"

+ 6 - 5
app/src/views/site/site_list/columns.tsx

@@ -20,7 +20,7 @@ const columns: Column[] = [{
     type: input,
   },
   search: true,
-  minWidth: 400,
+  width: 120,
 }, {
   title: () => $gettext('Category'),
   dataIndex: 'site_category_id',
@@ -37,7 +37,7 @@ const columns: Column[] = [{
   sorter: true,
   pithy: true,
   batch: true,
-  minWidth: 200,
+  width: 100,
 }, {
   title: () => $gettext('Status'),
   dataIndex: 'enabled',
@@ -64,18 +64,19 @@ const columns: Column[] = [{
   },
   sorter: true,
   pithy: true,
-  minWidth: 100,
+  width: 80,
 }, {
   title: () => $gettext('Updated at'),
   dataIndex: 'modified_at',
   customRender: datetime,
   sorter: true,
   pithy: true,
-  minWidth: 200,
+  width: 150,
 }, {
   title: () => $gettext('Action'),
   dataIndex: 'action',
-  minWidth: 300,
+  width: 80,
+  fixed: 'right',
 }]
 
 export default columns

+ 5 - 0
app/src/views/stream/StreamList.vue

@@ -18,6 +18,7 @@ const columns: Column[] = [{
     type: input,
   },
   search: true,
+  width: 200,
 }, {
   title: () => $gettext('Status'),
   dataIndex: 'enabled',
@@ -37,6 +38,7 @@ const columns: Column[] = [{
   },
   sorter: true,
   pithy: true,
+  width: 100,
 }, {
   title: () => $gettext('Updated at'),
   dataIndex: 'modified_at',
@@ -46,6 +48,8 @@ const columns: Column[] = [{
 }, {
   title: () => $gettext('Action'),
   dataIndex: 'action',
+  width: 120,
+  fixed: 'right',
 }]
 
 const table = ref()
@@ -126,6 +130,7 @@ function handleAddStream() {
       row-key="name"
       disable-delete
       disable-view
+      :scroll-x="800"
       @click-edit="r => $router.push({
         path: `/stream/${r}`,
       })"

+ 1 - 0
app/src/views/user/User.vue

@@ -6,6 +6,7 @@ import userColumns from '@/views/user/userColumns'
 
 <template>
   <StdCurd
+    :scroll-x="1000"
     :title="$gettext('Manage Users')"
     :columns="userColumns"
     :api="user"

+ 1 - 0
app/src/views/user/userColumns.tsx

@@ -59,6 +59,7 @@ const columns: Column[] = [{
 }, {
   title: () => $gettext('Action'),
   dataIndex: 'action',
+  fixed: 'right',
 }]
 
 export default columns

+ 23 - 0
internal/cert/config/myaddr.toml

@@ -0,0 +1,23 @@
+Name = "myaddr.{tools,dev,io}"
+Description = ''''''
+URL = "https://myaddr.tools/"
+Code = "myaddr"
+Since = "v4.22.0"
+
+Example = '''
+MYADDR_PRIVATE_KEYS_MAPPING="example:123,test:456" \
+lego --email you@example.com --dns myaddr -d '*.example.com' -d example.com run
+'''
+
+[Configuration]
+  [Configuration.Credentials]
+    MYADDR_PRIVATE_KEYS_MAPPING = "Mapping between subdomains and private keys. The format is: `<subdomain1>:<private_key1>,<subdomain2>:<private_key2>,<subdomain3>:<private_key3>`"
+  [Configuration.Additional]
+    MYADDR_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)"
+    MYADDR_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)"
+    MYADDR_SEQUENCE_INTERVAL = "Time between sequential requests in seconds (Default: 2)"
+    MYADDR_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)"
+    MYADDR_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)"
+
+[Links]
+  API = "https://myaddr.tools/"