From 3f0a911c80ca2d174a7e1d23ff2726a8232c2459 Mon Sep 17 00:00:00 2001 From: "Shishkevich D." <135337715+shishkevichd@users.noreply.github.com> Date: Sat, 8 Mar 2025 14:39:25 +0000 Subject: [PATCH] refactor: switching to the use of typed props --- web/html/login.html | 2 +- web/html/xui/client_bulk_modal.html | 4 +- web/html/xui/common_sider.html | 4 +- web/html/xui/component/password.html | 50 +++++++++++++------ web/html/xui/component/persianDatepicker.html | 28 ++++++++--- web/html/xui/component/setting.html | 21 +++++++- web/html/xui/component/sortableTable.html | 38 ++++++++++---- web/html/xui/component/themeSwitch.html | 25 ++++++---- web/html/xui/form/client.html | 4 +- web/html/xui/form/inbound.html | 4 +- web/html/xui/xray.html | 2 +- 11 files changed, 126 insertions(+), 56 deletions(-) diff --git a/web/html/login.html b/web/html/login.html index 82c9afd5..0e5e5ef1 100644 --- a/web/html/login.html +++ b/web/html/login.html @@ -461,7 +461,7 @@ </a-form-item> <a-form-item> <a-row justify="center" class="centered"> - <theme-switch-login></theme-switch-login> + <a-theme-switch-login></a-theme-switch-login> </a-row> </a-form-item> </a-form> diff --git a/web/html/xui/client_bulk_modal.html b/web/html/xui/client_bulk_modal.html index 74e49225..82e68c74 100644 --- a/web/html/xui/client_bulk_modal.html +++ b/web/html/xui/client_bulk_modal.html @@ -106,9 +106,9 @@ <a-date-picker v-if="datepicker == 'gregorian'" :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss" :dropdown-class-name="themeSwitcher.currentTheme" v-model="clientsBulkModal.expiryTime"></a-date-picker> - <persian-datepicker v-else placeholder='{{ i18n "pages.settings.datepickerPlaceholder" }}' + <a-persian-datepicker v-else placeholder='{{ i18n "pages.settings.datepickerPlaceholder" }}' value="clientsBulkModal.expiryTime" v-model="clientsBulkModal.expiryTime"> - </persian-datepicker> + </a-persian-datepicker> </a-form-item> <a-form-item v-if="clientsBulkModal.expiryTime != 0"> <template slot="label"> diff --git a/web/html/xui/common_sider.html b/web/html/xui/common_sider.html index df659489..1d5fe075 100644 --- a/web/html/xui/common_sider.html +++ b/web/html/xui/common_sider.html @@ -34,7 +34,7 @@ {{define "commonSider"}} <a-layout-sider :theme="themeSwitcher.currentTheme" id="sider" collapsible breakpoint="md"> - <theme-switch></theme-switch> + <a-theme-switch></a-theme-switch> <a-menu :theme="themeSwitcher.currentTheme" mode="inline" :selected-keys="['{{ .request_uri }}']" @click="({key}) => key.startsWith('http') ? window.open(key) : location.href = key"> {{template "menuItems" .}} </a-menu> @@ -43,7 +43,7 @@ <div class="drawer-handle" @click="siderDrawer.change()" slot="handle"> <a-icon :type="siderDrawer.visible ? 'close' : 'menu-fold'"></a-icon> </div> - <theme-switch></theme-switch> + <a-theme-switch></a-theme-switch> <a-menu :theme="themeSwitcher.currentTheme" mode="inline" :selected-keys="['{{ .request_uri }}']" @click="({key}) => key.startsWith('http') ? window.open(key) : location.href = key"> {{template "menuItems" .}} </a-menu> diff --git a/web/html/xui/component/password.html b/web/html/xui/component/password.html index 37e4c793..70b218ef 100644 --- a/web/html/xui/component/password.html +++ b/web/html/xui/component/password.html @@ -1,26 +1,46 @@ {{define "component/passwordInput"}} <template> - <a-input :value="value" :type="showPassword ? 'text' : 'password'" - :placeholder="placeholder" - :autocomplete="autocomplete" - :name="name" - @input="$emit('input', $event.target.value)"> - <template v-if="icon" #prefix> - <a-icon :type="icon" style="font-size: 16px;" /> - </template> - <template #addonAfter> - <a-icon :type="showPassword ? 'eye-invisible' : 'eye'" - @click="toggleShowPassword" - style="font-size: 16px;" /> - </template> - </a-input> + <a-input :value="value" :type="showPassword ? 'text' : 'password'" :placeholder="placeholder" + :autocomplete="autocomplete" :name="name" @input="$emit('input', $event.target.value)"> + <template v-if="icon" #prefix> + <a-icon :type="icon" style="font-size: 16px;" /> + </template> + <template #addonAfter> + <a-icon :type="showPassword ? 'eye-invisible' : 'eye'" @click="toggleShowPassword" style="font-size: 16px;" /> + </template> + </a-input> </template> {{end}} {{define "component/password"}} <script> Vue.component('password-input', { - props: ["title", "value", "placeholder", "icon", "autocomplete", "name"], + props: { + 'title': { + type: String, + required: false, + }, + 'value': { + type: String, + required: false, + }, + 'placeholder': { + type: String, + required: false, + }, + 'autocomplete': { + type: String, + required: false, + }, + 'name': { + type: String, + required: false, + }, + 'icon': { + type: undefined, + required: false + } + }, template: `{{template "component/passwordInput"}}`, data() { return { diff --git a/web/html/xui/component/persianDatepicker.html b/web/html/xui/component/persianDatepicker.html index df47c4f3..2df79a06 100644 --- a/web/html/xui/component/persianDatepicker.html +++ b/web/html/xui/component/persianDatepicker.html @@ -2,10 +2,10 @@ <template> <div> <a-input :value="value" type="text" v-model="date" data-jdp class="persian-datepicker" - @input="$emit('input', convertToGregorian($event.target.value)); jalaliDatepicker.hide();" - :placeholder="placeholder"> + @input="$emit('input', convertToGregorian($event.target.value)); jalaliDatepicker.hide();" + :placeholder="placeholder"> <template #addonAfter> - <a-icon type="calendar" style="font-size: 14px; opacity: 0.5;"/> + <a-icon type="calendar" style="font-size: 14px; opacity: 0.5;" /> </template> </a-input> </div> @@ -13,15 +13,27 @@ {{end}} {{define "component/persianDatepicker"}} -<link rel="stylesheet" href="{{ .base_path }}assets/persian-datepicker/persian-datepicker.min.css?{{ .cur_ver }}"/> +<link rel="stylesheet" href="{{ .base_path }}assets/persian-datepicker/persian-datepicker.min.css?{{ .cur_ver }}" /> <script src="{{ .base_path }}assets/moment/moment-jalali.min.js?{{ .cur_ver }}"></script> <script src="{{ .base_path }}assets/persian-datepicker/persian-datepicker.min.js?{{ .cur_ver }}"></script> <script> - const persianDatepicker = {}; - Vue.component('persian-datepicker', { - props: ['placeholder', 'format', 'value'], + Vue.component('a-persian-datepicker', { + props: { + 'format': { + type: undefined, + required: false, + }, + 'value': { + type: String, + required: false, + }, + 'placeholder': { + type: String, + required: false, + }, + }, template: `{{template "component/persianDatepickerTemplate"}}`, data() { return { @@ -57,4 +69,4 @@ } }); </script> -{{end}} +{{end}} \ No newline at end of file diff --git a/web/html/xui/component/setting.html b/web/html/xui/component/setting.html index bc2c6e42..85220d25 100644 --- a/web/html/xui/component/setting.html +++ b/web/html/xui/component/setting.html @@ -21,7 +21,24 @@ {{define "component/setting"}} <script> Vue.component('a-setting-list-item', { - props: ["title", "description", "paddings"], + props: { + 'title': { + type: String, + required: true, + }, + 'description': { + type: String, + required: false, + }, + 'paddings': { + type: String, + required: false, + defaultValue: "default", + validator: function (value) { + return ['small', 'default'].includes(value) + } + } + }, template: `{{ template "component/settingListItem" }}`, computed: { padding() { @@ -29,7 +46,7 @@ case "small": return "10px 20px !important" break; - default: + case "default": return "20px !important" break; } diff --git a/web/html/xui/component/sortableTable.html b/web/html/xui/component/sortableTable.html index f62eba44..67bbcee2 100644 --- a/web/html/xui/component/sortableTable.html +++ b/web/html/xui/component/sortableTable.html @@ -1,9 +1,5 @@ {{define "component/sortableTableTrigger"}} -<a-icon type="drag" - class="sortable-icon" - style="cursor: move;" - @mouseup="mouseUpHandler" - @mousedown="mouseDownHandler" +<a-icon type="drag" class="sortable-icon" style="cursor: move;" @mouseup="mouseUpHandler" @mousedown="mouseDownHandler" @click="clickHandler" /> {{end}} @@ -28,7 +24,16 @@ newElementIndex: null, }; }, - props: ['data-source', 'customRow'], + props: { + 'data-source': { + type: undefined, + required: false, + }, + 'customRow': { + type: undefined, + required: false, + } + }, inheritAttrs: false, provide() { const sortable = {} @@ -44,7 +49,7 @@ sortable, } }, - render: function(createElement) { + render: function (createElement) { return createElement('a-table', { class: { 'ant-table-is-sorting': this.isDragging(), @@ -59,7 +64,7 @@ drop: (e) => this.dropHandler(e), }, scopedSlots: this.$scopedSlots, - }, this.$slots.default, ) + }, this.$slots.default,) }, created() { this.$memoSort = {}; @@ -163,9 +168,14 @@ } } }); - Vue.component('table-sort-trigger', { + Vue.component('a-table-sort-trigger', { template: `{{template "component/sortableTableTrigger"}}`, - props: ['item-index'], + props: { + 'item-index': { + type: undefined, + required: false + } + }, inject: ['sortable'], methods: { mouseDownHandler(e) { @@ -190,27 +200,33 @@ display: none; } } + .ant-table-is-sorting .draggable-row td { background-color: #ffffff !important; } + .dark .ant-table-is-sorting .draggable-row td { background-color: var(--dark-color-surface-100) !important; } + .ant-table-is-sorting .dragging td { background-color: rgb(232 244 242) !important; color: rgba(0, 0, 0, 0.3); } + .dark .ant-table-is-sorting .dragging td { background-color: var(--dark-color-table-hover) !important; color: rgba(255, 255, 255, 0.3); } + .ant-table-is-sorting .dragging { opacity: 1; box-shadow: 1px -2px 2px #008771; transition: all 0.2s; } + .ant-table-is-sorting .dragging .ant-table-row-index { opacity: 0.3; } </style> -{{end}} +{{end}} \ No newline at end of file diff --git a/web/html/xui/component/themeSwitch.html b/web/html/xui/component/themeSwitch.html index 0de64a84..28cb79b1 100644 --- a/web/html/xui/component/themeSwitch.html +++ b/web/html/xui/component/themeSwitch.html @@ -6,9 +6,13 @@ <a-icon type="bulb" :theme="themeSwitcher.isDarkTheme ? 'filled' : 'outlined'"></a-icon> <span>Theme</span> </span> - <a-menu-item id="change-theme" class="ant-menu-theme-switch" @mousedown="themeSwitcher.animationsOff()"> Dark <a-switch style="margin-left: 2px;" size="small" :default-checked="themeSwitcher.isDarkTheme" @change="themeSwitcher.toggleTheme()"></a-switch> + <a-menu-item id="change-theme" class="ant-menu-theme-switch" @mousedown="themeSwitcher.animationsOff()"> Dark + <a-switch style="margin-left: 2px;" size="small" :default-checked="themeSwitcher.isDarkTheme" + @change="themeSwitcher.toggleTheme()"></a-switch> </a-menu-item> - <a-menu-item id="change-theme-ultra" v-if="themeSwitcher.isDarkTheme" class="ant-menu-theme-switch" @mousedown="themeSwitcher.animationsOffUltra()"> Ultra <a-checkbox style="margin-left: 2px;" :checked="themeSwitcher.isUltra" @click="themeSwitcher.toggleUltra()"></a-checkbox> + <a-menu-item id="change-theme-ultra" v-if="themeSwitcher.isDarkTheme" class="ant-menu-theme-switch" + @mousedown="themeSwitcher.animationsOffUltra()"> Ultra <a-checkbox style="margin-left: 2px;" + :checked="themeSwitcher.isUltra" @click="themeSwitcher.toggleUltra()"></a-checkbox> </a-menu-item> </a-sub-menu> </a-menu> @@ -17,12 +21,15 @@ {{define "component/themeSwitchTemplateLogin"}} <template> - <a-menu @mousedown="themeSwitcher.animationsOff()" id="change-theme" :theme="themeSwitcher.currentTheme" mode="inline" selected-keys=""> + <a-menu @mousedown="themeSwitcher.animationsOff()" id="change-theme" :theme="themeSwitcher.currentTheme" mode="inline" + selected-keys=""> <a-menu-item mode="inline" class="ant-menu-theme-switch"> <a-icon type="bulb" :theme="themeSwitcher.isDarkTheme ? 'filled' : 'outlined'"></a-icon> - <a-switch size="small" :default-checked="themeSwitcher.isDarkTheme" @change="themeSwitcher.toggleTheme()"></a-switch> + <a-switch size="small" :default-checked="themeSwitcher.isDarkTheme" + @change="themeSwitcher.toggleTheme()"></a-switch> <template v-if="themeSwitcher.isDarkTheme"> - <a-checkbox style="margin-left: 1rem; vertical-align: middle;" :checked="themeSwitcher.isUltra" @click="themeSwitcher.toggleUltra()">Ultra</a-checkbox> + <a-checkbox style="margin-left: 1rem; vertical-align: middle;" :checked="themeSwitcher.isUltra" + @click="themeSwitcher.toggleUltra()">Ultra</a-checkbox> </template> </a-menu-item> </a-menu> @@ -83,8 +90,7 @@ }; } const themeSwitcher = createThemeSwitcher(); - Vue.component('theme-switch', { - props: [], + Vue.component('a-theme-switch', { template: `{{template "component/themeSwitchTemplate"}}`, data: () => ({ themeSwitcher @@ -96,8 +102,7 @@ document.getElementById('message').className = themeSwitcher.currentTheme; } }); - Vue.component('theme-switch-login', { - props: [], + Vue.component('a-theme-switch-login', { template: `{{template "component/themeSwitchTemplateLogin"}}`, data: () => ({ themeSwitcher @@ -110,4 +115,4 @@ } }); </script> -{{end}} +{{end}} \ No newline at end of file diff --git a/web/html/xui/form/client.html b/web/html/xui/form/client.html index c2bcace1..3aff67e0 100644 --- a/web/html/xui/form/client.html +++ b/web/html/xui/form/client.html @@ -154,8 +154,8 @@ </template> <a-date-picker v-if="datepicker == 'gregorian'" :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss" :dropdown-class-name="themeSwitcher.currentTheme" v-model="client._expiryTime"></a-date-picker> - <persian-datepicker v-else placeholder='{{ i18n "pages.settings.datepickerPlaceholder" }}' - value="client._expiryTime" v-model="client._expiryTime"></persian-datepicker> + <a-persian-datepicker v-else placeholder='{{ i18n "pages.settings.datepickerPlaceholder" }}' + value="client._expiryTime" v-model="client._expiryTime"></a-persian-datepicker> <a-tag color="red" v-if="isEdit && isExpiry">Expired</a-tag> </a-form-item> <a-form-item v-if="client.expiryTime != 0"> diff --git a/web/html/xui/form/inbound.html b/web/html/xui/form/inbound.html index 091393ff..e0521c69 100644 --- a/web/html/xui/form/inbound.html +++ b/web/html/xui/form/inbound.html @@ -57,9 +57,9 @@ <a-date-picker style="width: 100%;" v-if="datepicker == 'gregorian'" :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss" :dropdown-class-name="themeSwitcher.currentTheme" v-model="dbInbound._expiryTime"></a-date-picker> - <persian-datepicker v-else placeholder='{{ i18n "pages.settings.datepickerPlaceholder" }}' + <a-persian-datepicker v-else placeholder='{{ i18n "pages.settings.datepickerPlaceholder" }}' value="dbInbound._expiryTime" v-model="dbInbound._expiryTime"> - </persian-datepicker> + </a-persian-datepicker> </a-form-item> </a-form> diff --git a/web/html/xui/xray.html b/web/html/xui/xray.html index d101bdcd..41bbd214 100644 --- a/web/html/xui/xray.html +++ b/web/html/xui/xray.html @@ -348,7 +348,7 @@ :indent-size="0" v-on:onSort="replaceRule"> <template slot="action" slot-scope="text, rule, index"> - <table-sort-trigger :item-index="index"></table-sort-trigger> + <a-table-sort-trigger :item-index="index"></a-table-sort-trigger> <span class="ant-table-row-index"> [[ index+1 ]] </span> <a-dropdown :trigger="['click']"> <a-icon @click="e => e.preventDefault()" type="more" style="font-size: 16px; text-decoration: bold;"></a-icon>