added Jalalian datepicker (shamsi) (#1460)

* added datepicker option in setting page
jalalian datepicker component was added
translate files for datepicker updated

* dark mode bug fixed
This commit is contained in:
Ali Rahimi 2024-01-02 09:32:21 +01:00 committed by GitHub
parent 31e9734414
commit c76199514a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 1389 additions and 3 deletions

View File

@ -20,6 +20,7 @@ type SubService struct {
address string
showInfo bool
remarkModel string
datepicker string
inboundService service.InboundService
settingService service.SettingService
}
@ -39,6 +40,10 @@ func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string
if err != nil {
s.remarkModel = "-ieo"
}
s.datepicker, err = s.settingService.GetDatepicker()
if err != nil {
s.datepicker = "gregorian"
}
for _, inbound := range inbounds {
clients, err := s.inboundService.GetClients(inbound)
if err != nil {

View File

@ -12,6 +12,7 @@ class AllSetting {
this.expireDiff = "";
this.trafficDiff = "";
this.remarkModel = "-ieo";
this.datepicker = "gregorian";
this.tgBotEnable = false;
this.tgBotToken = "";
this.tgBotChatId = "";

1252
web/assets/moment/moment-jalali.min.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -47,6 +47,7 @@ type AllSetting struct {
SubEncrypt bool `json:"subEncrypt" form:"subEncrypt"`
SubShowInfo bool `json:"subShowInfo" form:"subShowInfo"`
SubURI string `json:"subURI" form:"subURI"`
Datepicker string `json:"datepicker" form:"datepicker"`
}
func (s *AllSetting) CheckValid() error {

View File

@ -104,8 +104,10 @@
<a-icon type="question-circle"></a-icon>
</a-tooltip>
</template>
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
<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 :dropdown-class-name="themeSwitcher.currentTheme"
value="clientsBulkModal.expiryTime" v-model="clientsBulkModal.expiryTime"></persian-datepicker>
</a-form-item>
<a-form-item v-if="clientsBulkModal.expiryTime != 0">
<template slot="label">
@ -234,6 +236,9 @@
get delayedExpireDays() {
return this.clientsBulkModal.expiryTime < 0 ? this.clientsBulkModal.expiryTime / -86400000 : 0;
},
get datepicker() {
return app.datepicker;
},
set delayedExpireDays(days) {
this.clientsBulkModal.expiryTime = -86400000 * days;
},

View File

@ -94,6 +94,9 @@
get isEdit() {
return this.clientModal.isEdit;
},
get datepicker() {
return app.datepicker;
},
get isTrafficExhausted() {
if (!clientStats) return false
if (clientStats.total <= 0) return false

View File

@ -0,0 +1,60 @@
{{define "component/persianDatepickerTemplate"}}
<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="انتخاب تاریخ">
<template #addonAfter>
<a-icon type="calendar" style="font-size: 16px;"/>
</template>
</a-input>
</div>
</template>
{{end}}
{{define "component/persianDatepicker"}}
<link rel="stylesheet" href="{{ .base_path }}assets/persian-datepicker/persian-datepicker.min.css"/>
<script src="{{ .base_path }}assets/moment/moment-jalali.min.js"></script>
<script src="{{ .base_path }}assets/persian-datepicker/persian-datepicker.min.js"></script>
<script>
const persianDatepicker = {};
Vue.component('persian-datepicker', {
props: ['dropdown-class-name', 'format', 'value'],
template: `{{template "component/persianDatepickerTemplate"}}`,
data() {
return {
date: '',
persianDatepicker,
};
},
watch: {
value: function (date) {
this.date = this.convertToJalalian(date)
}
},
mounted() {
this.date = this.convertToJalalian(this.value)
this.listenToDatepicker()
},
methods: {
convertToGregorian(date) {
return date ? moment(moment(date, 'jYYYY/jMM/jDD HH:mm:ss').format('YYYY-MM-DD HH:mm:ss')) : null
},
convertToJalalian(date) {
return date && moment.isMoment(date) ? date.format('jYYYY/jMM/jDD HH:mm:ss') : null
},
listenToDatepicker() {
jalaliDatepicker.startWatch({
time: true,
container: '.ant-modal-wrap',
hideAfterChange: true,
useDropDownYears: false,
changeMonthRotateYear: true,
});
},
}
});
</script>
{{end}}

View File

@ -150,8 +150,10 @@
<a-icon type="question-circle"></a-icon>
</a-tooltip>
</template>
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
<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 :dropdown-class-name="themeSwitcher.currentTheme"
value="client._expiryTime" v-model="client._expiryTime"></persian-datepicker>
<a-tag color="red" v-if="isEdit && isExpiry">Expired</a-tag>
</a-form-item>
<a-form-item v-if="client.expiryTime != 0">

View File

@ -54,9 +54,11 @@
<a-icon type="question-circle"></a-icon>
</a-tooltip>
</template>
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
<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="dbInbound._expiryTime"></a-date-picker>
<persian-datepicker v-else :dropdown-class-name="themeSwitcher.currentTheme"
value="dbInbound._expiryTime" v-model="dbInbound._expiryTime"></persian-datepicker>
</a-form-item>
</a-form>

View File

@ -63,6 +63,9 @@
get client() {
return inModal.inbound.clients[0];
},
get datepicker() {
return app.datepicker;
},
get delayedExpireDays() {
return this.client && this.client.expiryTime < 0 ? this.client.expiryTime / -86400000 : 0;
},

View File

@ -446,6 +446,7 @@
<script src="{{ .base_path }}assets/js/model/xray.js?{{ .cur_ver }}"></script>
<script src="{{ .base_path }}assets/js/model/dbinbound.js?{{ .cur_ver }}"></script>
{{template "component/themeSwitcher" .}}
{{template "component/persianDatepicker" .}}
<script>
const columns = [{
title: "ID",
@ -539,6 +540,7 @@
data: {
siderDrawer,
themeSwitcher,
persianDatepicker,
spinning: false,
inbounds: [],
dbInbounds: [],
@ -560,6 +562,7 @@
subURI : ''
},
remarkModel: '-ieo',
datepicker: 'gregorian',
tgBotEnable: false,
pageSize: 0,
isMobile: window.innerWidth <= 768,
@ -605,6 +608,7 @@
};
this.pageSize = pageSize;
this.remarkModel = remarkModel;
this.datepicker = datepicker;
}
},
setInbounds(dbInbounds) {

View File

@ -138,6 +138,27 @@
<setting-list-item type="number" title='{{ i18n "pages.settings.expireTimeDiff" }}' desc='{{ i18n "pages.settings.expireTimeDiffDesc" }}' v-model="allSetting.expireDiff" :min="0"></setting-list-item>
<setting-list-item type="number" title='{{ i18n "pages.settings.trafficDiff" }}' desc='{{ i18n "pages.settings.trafficDiffDesc" }}' v-model="allSetting.trafficDiff" :min="0"></setting-list-item>
<setting-list-item type="text" title='{{ i18n "pages.settings.timeZone"}}' desc='{{ i18n "pages.settings.timeZoneDesc"}}' v-model="allSetting.timeLocation"></setting-list-item>
<a-list-item>
<a-row style="padding: 20px">
<a-col :lg="24" :xl="12">
<a-list-item-meta title='{{ i18n "pages.settings.datepicker"}}'>
<template slot="description">{{ i18n "pages.settings.datepickerDescription"}}</template>
</a-list-item-meta>
</a-col>
<a-col :lg="24" :xl="12">
<template>
<a-select style="width: 100%"
:dropdown-class-name="themeSwitcher.currentTheme"
v-model="datepicker">
<a-select-option v-for="item in datepickerList" :value="item.value">
<span v-text="item.name"></span>
</a-select-option>
</a-select>
</template>
</a-col>
</a-row>
</a-list-item>
<a-list-item>
<a-row style="padding: 20px">
<a-col :lg="24" :xl="12">
@ -311,6 +332,7 @@
showAlert: false,
remarkModels: {i:'Inbound',e:'Email',o:'Other'},
remarkSeparators: [' ','-','_','@',':','~','|',',','.','/'],
datepickerList: [{name:'Gregorian (Standard)', value: 'gregorian'}, {name:'Jalalian (شمسی)', value: 'jalalian'}],
remarkSample: '',
get remarkModel() {
rm = this.allSetting.remarkModel;
@ -328,6 +350,12 @@
this.allSetting.remarkModel = value + this.allSetting.remarkModel.substring(1);
this.changeRemarkSample();
},
get datepicker() {
return this.allSetting.datepicker ? this.allSetting.datepicker : 'gregorian';
},
set datepicker(value) {
this.allSetting.datepicker = value;
},
changeRemarkSample(){
sample = []
this.remarkModel.forEach(r => sample.push(this.remarkModels[r]));

View File

@ -56,6 +56,7 @@ var defaultValueMap = map[string]string{
"subEncrypt": "true",
"subShowInfo": "true",
"subURI": "",
"datepicker": "gregorian",
}
type SettingService struct {
@ -417,6 +418,10 @@ func (s *SettingService) GetSubURI() (string, error) {
return s.getString("subURI")
}
func (s *SettingService) GetDatepicker() (string, error) {
return s.getString("datepicker")
}
func (s *SettingService) GetPageSize() (int, error) {
return s.getInt("pageSize")
}
@ -463,6 +468,7 @@ func (s *SettingService) GetDefaultSettings(host string) (interface{}, error) {
"subEnable": func() (interface{}, error) { return s.GetSubEnable() },
"subURI": func() (interface{}, error) { return s.GetSubURI() },
"remarkModel": func() (interface{}, error) { return s.GetRemarkModel() },
"datepicker": func() (interface{}, error) { return s.GetDatepicker() },
}
result := make(map[string]interface{})

View File

@ -246,6 +246,8 @@
"pageSize" = "Pagination Size"
"pageSizeDesc" = "Define page size for inbounds table. Set 0 to disable"
"remarkModel" = "Remark Model and Seperation Charachter"
"datepicker" = "Datepicker"
"datepickerDescription" = "Selector calendar type specifies the expiration date"
"sampleRemark" = "Sample Remark"
"oldUsername" = "Current Username"
"currentPassword" = "Current Password"

View File

@ -246,6 +246,8 @@
"pageSize" = "Tamaño de paginación"
"pageSizeDesc" = "Defina el tamaño de página para la tabla de entradas. Establezca 0 para desactivar"
"remarkModel" = "Modelo de observación y carácter de separación"
"datepicker" = "selector de fechas"
"datepickerDescription" = "El tipo de calendario selector especifica la fecha de vencimiento"
"sampleRemark" = "Observación de muestra"
"oldUsername" = "Nombre de Usuario Actual"
"currentPassword" = "Contraseña Actual"

View File

@ -246,6 +246,8 @@
"pageSize" = "اندازه صفحه بندی جدول"
"pageSizeDesc" = "اندازه صفحه را برای جدول سرویس ها تعریف کنید. 0: غیرفعال"
"remarkModel" = "نام کانفیگ و جداکننده"
"datepicker" = "انتخاب کننده تاریخ"
"datepickerDescription" = "نوع تقویم انتخاب کننده تاریخ انقضا را مشخص میکند "
"sampleRemark" = "نمونه نام"
"oldUsername" = "نام کاربری فعلی"
"currentPassword" = "رمز عبور فعلی"

View File

@ -246,6 +246,8 @@
"pageSize" = "Размер нумерации страниц"
"pageSizeDesc" = "Определить размер страницы для входящей таблицы. Установите 0, чтобы отключить"
"remarkModel" = "Модель примечания и символ разделения"
"datepicker" = "выбор даты"
"datepickerDescription" = "Тип календаря выбора указывает дату истечения срока действия."
"sampleRemark" = "Пример замечания"
"oldUsername" = "Текущее имя пользователя"
"currentPassword" = "Текущий пароль"

View File

@ -246,6 +246,8 @@
"pageSize" = "Kích thước phân trang"
"pageSizeDesc" = "Xác định kích thước trang cho bảng gửi đến. Đặt 0 để tắt"
"remarkModel" = "Ghi chú mô hình và ký tự phân tách"
"datepicker" = "bảng chọn ngày"
"datepickerDescription" = "Loại lịch chọn chỉ định ngày hết hạn"
"sampleRemark" = "Nhận xét mẫu"
"oldUsername" = "Tên người dùng hiện tại"
"currentPassword" = "Mật khẩu hiện tại"

View File

@ -246,6 +246,8 @@
"pageSize" = "分页大小"
"pageSizeDesc" = "定义入站表的页面大小。设置 0 表示禁用"
"remarkModel" = "备注模型和分隔符"
"datepicker" = "日期选择器"
"datepickerDescription" = "选择器日历类型指定到期日期"
"sampleRemark" = "备注示例"
"oldUsername" = "原用户名"
"currentPassword" = "原密码"