Feat expiration date (#1296)
Closes #1287 Co-authored-by: Vadim Babadzhanyan <vadim.babadzhanyan@my.games>
This commit is contained in:
committed by
GitHub
parent
40af030266
commit
8145809e22
@@ -714,6 +714,10 @@ video {
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.mb-2 {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
@@ -1160,6 +1164,10 @@ video {
|
||||
fill: #4b5563;
|
||||
}
|
||||
|
||||
.p-0 {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.p-1 {
|
||||
padding: 0.25rem;
|
||||
}
|
||||
@@ -1465,6 +1473,10 @@ video {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.p-0 {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.last\:border-b-0:last-child {
|
||||
border-bottom-width: 0px;
|
||||
}
|
||||
|
||||
+38
-2
@@ -127,7 +127,7 @@
|
||||
</button>
|
||||
|
||||
<!-- New client -->
|
||||
<button @click="clientCreate = true; clientCreateName = '';"
|
||||
<button @click="clientCreate = true; clientCreateName = ''; clientExpiredDate = '';"
|
||||
class="hover:bg-red-800 hover:border-red-800 hover:text-white text-gray-700 dark:text-neutral-200 max-md:border-l-0 border-2 border-gray-100 dark:border-neutral-600 py-2 px-4 rounded-r-full md:rounded inline-flex items-center transition">
|
||||
<svg class="w-4 md:mr-2" inline xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
@@ -259,6 +259,32 @@
|
||||
<div v-if="uiShowLinks" :ref="'client-' + client.id + '-hash'" class="text-gray-400 text-xs">
|
||||
<a :href="'./' + client.hash + ''">{{document.location.protocol}}//{{document.location.host}}/{{client.hash}}</a>
|
||||
</div>
|
||||
<!-- Expire Date -->
|
||||
<div v-show="enableExpireTime" class=" block md:inline-block pb-1 md:pb-0 text-gray-500 dark:text-neutral-400 text-xs">
|
||||
<span class="group">
|
||||
<!-- Show -->
|
||||
<input v-show="clientEditExpireDateId === client.id" v-model="clientEditExpireDate"
|
||||
v-on:keyup.enter="updateClientExpireDate(client, clientEditExpireDate); clientEditExpireDate = null; clientEditExpireDateId = null;"
|
||||
v-on:keyup.escape="clientEditExpireDate = null; clientEditExpireDateId = null;"
|
||||
:ref="'client-' + client.id + '-expire'"
|
||||
type="text"
|
||||
class="rounded border-2 dark:bg-neutral-700 border-gray-100 dark:border-neutral-600 focus:border-gray-200 dark:focus:border-neutral-500 outline-none w-70 text-black dark:text-neutral-300 dark:placeholder:text-neutral-500 text-xs p-0" />
|
||||
<span v-show="clientEditExpireDateId !== client.id"
|
||||
class="inline-block ">{{client.expiredAt | expiredDateFormat}}</span>
|
||||
|
||||
<!-- Edit -->
|
||||
<span v-show="clientEditExpireDateId !== client.id"
|
||||
@click="clientEditExpireDate = client.expiredAt ? client.expiredAt.toISOString().slice(0, 10) : 'yyyy-mm-dd'; clientEditExpireDateId = client.id; setTimeout(() => $refs['client-' + client.id + '-expire'][0].select(), 1);"
|
||||
class="cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-4 inline align-middle opacity-25 hover:opacity-100" fill="none"
|
||||
viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info -->
|
||||
@@ -378,7 +404,7 @@
|
||||
<div v-if="clients && clients.length === 0">
|
||||
<p class="text-center m-10 text-gray-400 dark:text-neutral-400 text-sm">
|
||||
{{$t("noClients")}}<br /><br />
|
||||
<button @click="clientCreate = true; clientCreateName = '';"
|
||||
<button @click="clientCreate = true; clientCreateName = ''; clientExpiredDate = '';"
|
||||
class="bg-red-800 hover:bg-red-700 text-white border-2 border-none py-2 px-4 rounded inline-flex items-center transition">
|
||||
<svg class="w-4 mr-2" inline xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
@@ -470,6 +496,16 @@
|
||||
type="text" v-model.trim="clientCreateName" :placeholder="$t('name')" />
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-2" v-show="enableExpireTime">
|
||||
<p class="text-sm text-gray-500">
|
||||
<label class="block text-gray-900 dark:text-neutral-200 text-sm font-bold mb-2" for="expireDate">
|
||||
{{$t("ExpireDate")}}
|
||||
</label>
|
||||
<input
|
||||
class="rounded p-2 border-2 dark:bg-neutral-700 dark:text-neutral-200 border-gray-100 dark:border-neutral-600 focus:border-gray-200 focus:dark:border-neutral-500 dark:placeholder:text-neutral-400 outline-none w-full"
|
||||
type="date" v-model.trim="clientExpiredDate" :placeholder="$t('expireDate')" name="expireDate"/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+20
-2
@@ -71,6 +71,13 @@ class API {
|
||||
});
|
||||
}
|
||||
|
||||
async getWGEnableExpireTime() {
|
||||
return this.call({
|
||||
method: 'get',
|
||||
path: '/wg-enable-expire-time',
|
||||
});
|
||||
}
|
||||
|
||||
async getSession() {
|
||||
return this.call({
|
||||
method: 'get',
|
||||
@@ -101,17 +108,20 @@ class API {
|
||||
...client,
|
||||
createdAt: new Date(client.createdAt),
|
||||
updatedAt: new Date(client.updatedAt),
|
||||
expiredAt: client.expiredAt !== null
|
||||
? new Date(client.expiredAt)
|
||||
: null,
|
||||
latestHandshakeAt: client.latestHandshakeAt !== null
|
||||
? new Date(client.latestHandshakeAt)
|
||||
: null,
|
||||
})));
|
||||
}
|
||||
|
||||
async createClient({ name }) {
|
||||
async createClient({ name, expiredDate }) {
|
||||
return this.call({
|
||||
method: 'post',
|
||||
path: '/wireguard/client',
|
||||
body: { name },
|
||||
body: { name, expiredDate },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -152,6 +162,14 @@ class API {
|
||||
});
|
||||
}
|
||||
|
||||
async updateClientExpireDate({ clientId, expireDate }) {
|
||||
return this.call({
|
||||
method: 'put',
|
||||
path: `/wireguard/client/${clientId}/expireDate/`,
|
||||
body: { expireDate },
|
||||
});
|
||||
}
|
||||
|
||||
async restoreConfiguration(file) {
|
||||
return this.call({
|
||||
method: 'put',
|
||||
|
||||
+28
-1
@@ -77,10 +77,13 @@ new Vue({
|
||||
clientDelete: null,
|
||||
clientCreate: null,
|
||||
clientCreateName: '',
|
||||
clientExpiredDate: '',
|
||||
clientEditName: null,
|
||||
clientEditNameId: null,
|
||||
clientEditAddress: null,
|
||||
clientEditAddressId: null,
|
||||
clientEditExpireDate: null,
|
||||
clientEditExpireDateId: null,
|
||||
qrcode: null,
|
||||
|
||||
currentRelease: null,
|
||||
@@ -92,6 +95,7 @@ new Vue({
|
||||
uiShowLinks: false,
|
||||
enableSortClient: false,
|
||||
sortClient: true, // Sort clients by name, true = asc, false = desc
|
||||
enableExpireTime: false,
|
||||
|
||||
uiShowCharts: localStorage.getItem('uiShowCharts') === '1',
|
||||
uiTheme: localStorage.theme || 'auto',
|
||||
@@ -296,9 +300,10 @@ new Vue({
|
||||
},
|
||||
createClient() {
|
||||
const name = this.clientCreateName;
|
||||
const expiredDate = this.clientExpiredDate;
|
||||
if (!name) return;
|
||||
|
||||
this.api.createClient({ name })
|
||||
this.api.createClient({ name, expiredDate })
|
||||
.catch((err) => alert(err.message || err.toString()))
|
||||
.finally(() => this.refresh().catch(console.error));
|
||||
},
|
||||
@@ -327,6 +332,11 @@ new Vue({
|
||||
.catch((err) => alert(err.message || err.toString()))
|
||||
.finally(() => this.refresh().catch(console.error));
|
||||
},
|
||||
updateClientExpireDate(client, expireDate) {
|
||||
this.api.updateClientExpireDate({ clientId: client.id, expireDate })
|
||||
.catch((err) => alert(err.message || err.toString()))
|
||||
.finally(() => this.refresh().catch(console.error));
|
||||
},
|
||||
restoreConfig(e) {
|
||||
e.preventDefault();
|
||||
const file = e.currentTarget.files.item(0);
|
||||
@@ -370,6 +380,15 @@ new Vue({
|
||||
timeago: (value) => {
|
||||
return timeago.format(value, i18n.locale);
|
||||
},
|
||||
expiredDateFormat: (value) => {
|
||||
if (value === null) return i18n.t('Permanent');
|
||||
const dateTime = new Date(value);
|
||||
const options = { year: 'numeric', month: 'long', day: 'numeric' };
|
||||
return dateTime.toLocaleDateString(i18n.locale, options);
|
||||
},
|
||||
expiredDateEditFormat: (value) => {
|
||||
if (value === null) return 'yyyy-MM-dd';
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.prefersDarkScheme.addListener(this.handlePrefersChange);
|
||||
@@ -433,6 +452,14 @@ new Vue({
|
||||
this.enableSortClient = false;
|
||||
});
|
||||
|
||||
this.api.getWGEnableExpireTime()
|
||||
.then((res) => {
|
||||
this.enableExpireTime = res;
|
||||
})
|
||||
.catch(() => {
|
||||
this.enableExpireTime = false;
|
||||
});
|
||||
|
||||
Promise.resolve().then(async () => {
|
||||
const lang = await this.api.getLang();
|
||||
if (lang !== localStorage.getItem('lang') && i18n.availableLocales.includes(lang)) {
|
||||
|
||||
@@ -37,6 +37,8 @@ const messages = { // eslint-disable-line no-unused-vars
|
||||
rememberMe: 'Remember me',
|
||||
titleRememberMe: 'Stay logged after closing the browser',
|
||||
sort: 'Sort',
|
||||
ExpireDate: 'Expire Date',
|
||||
Permanent: 'Permanent',
|
||||
},
|
||||
ua: {
|
||||
name: 'Ім`я',
|
||||
@@ -108,6 +110,8 @@ const messages = { // eslint-disable-line no-unused-vars
|
||||
rememberMe: 'Запомнить меня',
|
||||
titleRememberMe: 'Оставаться в системе после закрытия браузера',
|
||||
sort: 'Сортировка',
|
||||
ExpireDate: 'Дата истечения срока',
|
||||
Permanent: 'Бессрочно',
|
||||
},
|
||||
tr: { // Müslüm Barış Korkmazer @babico
|
||||
name: 'İsim',
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
.p-0 {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user