mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-11-22 15:20:09 +01:00
Sharing peer is done, fixed #294
Fixed issue #294 with a Vue.js plugin instead of using the `datatime-local` input tag. Still need to work on the end-user UI for sharing.
This commit is contained in:
parent
958bc864c9
commit
7463767781
@ -346,6 +346,7 @@ class PeerShareLink:
|
|||||||
self.Configuration = Configuration
|
self.Configuration = Configuration
|
||||||
self.ShareDate = ShareDate
|
self.ShareDate = ShareDate
|
||||||
self.ExpireDate = ExpireDate
|
self.ExpireDate = ExpireDate
|
||||||
|
|
||||||
|
|
||||||
def toJson(self):
|
def toJson(self):
|
||||||
return {
|
return {
|
||||||
@ -358,10 +359,10 @@ class PeerShareLink:
|
|||||||
class PeerShareLinks:
|
class PeerShareLinks:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.Links: list[PeerShareLink] = []
|
self.Links: list[PeerShareLink] = []
|
||||||
|
self.PeerShareLinkCursor = sqldb.cursor()
|
||||||
existingTables = cursor.execute("SELECT name FROM sqlite_master WHERE type='table' and name = 'PeerShareLinks'").fetchall()
|
existingTables = self.PeerShareLinkCursor.execute("SELECT name FROM sqlite_master WHERE type='table' and name = 'PeerShareLinks'").fetchall()
|
||||||
if len(existingTables) == 0:
|
if len(existingTables) == 0:
|
||||||
cursor.execute(
|
self.PeerShareLinkCursor.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TABLE PeerShareLinks (
|
CREATE TABLE PeerShareLinks (
|
||||||
ShareID VARCHAR NOT NULL PRIMARY KEY, Configuration VARCHAR NOT NULL, Peer VARCHAR NOT NULL,
|
ShareID VARCHAR NOT NULL PRIMARY KEY, Configuration VARCHAR NOT NULL, Peer VARCHAR NOT NULL,
|
||||||
@ -375,26 +376,28 @@ class PeerShareLinks:
|
|||||||
# print(self.Links)
|
# print(self.Links)
|
||||||
def __getSharedLinks(self):
|
def __getSharedLinks(self):
|
||||||
self.Links.clear()
|
self.Links.clear()
|
||||||
allLinks = cursor.execute("SELECT * FROM PeerShareLinks WHERE ExpireDate IS NULL OR ExpireDate > datetime('now', 'localtime')").fetchall()
|
allLinks = self.PeerShareLinkCursor.execute("SELECT * FROM PeerShareLinks WHERE ExpireDate IS NULL OR ExpireDate > datetime('now', 'localtime')").fetchall()
|
||||||
for link in allLinks:
|
for link in allLinks:
|
||||||
self.Links.append(PeerShareLink(*link))
|
self.Links.append(PeerShareLink(*link))
|
||||||
|
|
||||||
def getLink(self, Configuration: str, Peer: str) -> list[PeerShareLink]:
|
def getLink(self, Configuration: str, Peer: str) -> list[PeerShareLink]:
|
||||||
|
self.__getSharedLinks()
|
||||||
return list(filter(lambda x : x.Configuration == Configuration and x.Peer == Peer, self.Links))
|
return list(filter(lambda x : x.Configuration == Configuration and x.Peer == Peer, self.Links))
|
||||||
|
|
||||||
def getLinkByID(self, ShareID: str) -> list[PeerShareLink]:
|
def getLinkByID(self, ShareID: str) -> list[PeerShareLink]:
|
||||||
|
self.__getSharedLinks()
|
||||||
return list(filter(lambda x : x.ShareID == ShareID, self.Links))
|
return list(filter(lambda x : x.ShareID == ShareID, self.Links))
|
||||||
|
|
||||||
def addLink(self, Configuration: str, Peer: str, ExpireDate: datetime = None) -> tuple[bool, str]:
|
def addLink(self, Configuration: str, Peer: str, ExpireDate: datetime = None) -> tuple[bool, str]:
|
||||||
try:
|
try:
|
||||||
newShareID = str(uuid.uuid4())
|
newShareID = str(uuid.uuid4())
|
||||||
if len(self.getLink(Configuration, Peer)) > 0:
|
if len(self.getLink(Configuration, Peer)) > 0:
|
||||||
cursor.execute("UPDATE PeerShareLinks SET ExpireDate = datetime('now', 'localtime') WHERE Configuration = ? AND Peer = ?", (Configuration, Peer, ))
|
self.PeerShareLinkCursor.execute("UPDATE PeerShareLinks SET ExpireDate = datetime('now', 'localtime') WHERE Configuration = ? AND Peer = ?", (Configuration, Peer, ))
|
||||||
|
|
||||||
if ExpireDate is not None:
|
# if ExpireDate is not None:
|
||||||
ExpireDate = datetime.strptime(ExpireDate, '%Y-%m-%d %H:%M:%S')
|
# ExpireDate = datetime.strptime(ExpireDate, '%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
cursor.execute("INSERT INTO PeerShareLinks (ShareID, Configuration, Peer, ExpireDate) VALUES (?, ?, ?, ?)", (newShareID, Configuration, Peer, ExpireDate, ))
|
self.PeerShareLinkCursor.execute("INSERT INTO PeerShareLinks (ShareID, Configuration, Peer, ExpireDate) VALUES (?, ?, ?, ?)", (newShareID, Configuration, Peer, ExpireDate, ))
|
||||||
sqldb.commit()
|
sqldb.commit()
|
||||||
self.__getSharedLinks()
|
self.__getSharedLinks()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -402,16 +405,11 @@ class PeerShareLinks:
|
|||||||
return True, newShareID
|
return True, newShareID
|
||||||
|
|
||||||
def updateLinkExpireDate(self, ShareID, ExpireDate: datetime = None) -> tuple[bool, str]:
|
def updateLinkExpireDate(self, ShareID, ExpireDate: datetime = None) -> tuple[bool, str]:
|
||||||
try:
|
|
||||||
if ExpireDate is None:
|
self.PeerShareLinkCursor.execute("UPDATE PeerShareLinks SET ExpireDate = ? WHERE ShareID = ?;", (ExpireDate, ShareID, ))
|
||||||
cursor.execute("UPDATE PeerShareLinks SET ExpireDate = datetime('now', 'localtime') WHERE ShareID = ?", (ShareID, ))
|
sqldb.commit()
|
||||||
else:
|
self.__getSharedLinks()
|
||||||
cursor.execute("UPDATE PeerShareLinks SET ExpireDate = ? WHERE ShareID = ?", (ShareID, datetime.strptime(ExpireDate, '%Y-%m-%d %H:%M:%S'), ))
|
return True, ""
|
||||||
sqldb.commit()
|
|
||||||
self.__getSharedLinks()
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
return False, str(e)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1511,7 +1509,7 @@ def API_newDashboardAPIKey():
|
|||||||
if data['neverExpire']:
|
if data['neverExpire']:
|
||||||
expiredAt = None
|
expiredAt = None
|
||||||
else:
|
else:
|
||||||
expiredAt = datetime.strptime(data['ExpiredAt'], '%Y-%m-%dT%H:%M:%S')
|
expiredAt = datetime.strptime(data['ExpiredAt'], '%Y-%m-%d %H:%M:%S')
|
||||||
DashboardConfig.createAPIKeys(expiredAt)
|
DashboardConfig.createAPIKeys(expiredAt)
|
||||||
return ResponseObject(True, data=DashboardConfig.DashboardAPIKeys)
|
return ResponseObject(True, data=DashboardConfig.DashboardAPIKeys)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -1594,6 +1592,8 @@ def API_sharePeer_update():
|
|||||||
data: dict[str, str] = request.get_json()
|
data: dict[str, str] = request.get_json()
|
||||||
ShareID: str = data.get("ShareID")
|
ShareID: str = data.get("ShareID")
|
||||||
ExpireDate: str = data.get("ExpireDate")
|
ExpireDate: str = data.get("ExpireDate")
|
||||||
|
print(ShareID)
|
||||||
|
print(ExpireDate)
|
||||||
|
|
||||||
if ShareID is None:
|
if ShareID is None:
|
||||||
return ResponseObject(False, "Please specify ShareID")
|
return ResponseObject(False, "Please specify ShareID")
|
||||||
|
@ -3,10 +3,12 @@ import ScheduleDropdown from "@/components/configurationComponents/peerScheduleJ
|
|||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import {fetchPost} from "@/utilities/fetch.js";
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
|
import VueDatePicker from "@vuepic/vue-datepicker";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "schedulePeerJob",
|
name: "schedulePeerJob",
|
||||||
components: {ScheduleDropdown},
|
components: {VueDatePicker, ScheduleDropdown},
|
||||||
props: {
|
props: {
|
||||||
dropdowns: Array[Object],
|
dropdowns: Array[Object],
|
||||||
pjob: Object,
|
pjob: Object,
|
||||||
@ -94,6 +96,11 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.$emit('delete')
|
this.$emit('delete')
|
||||||
|
},
|
||||||
|
parseTime(modelData){
|
||||||
|
if(modelData){
|
||||||
|
this.job.Value = dayjs(modelData).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -128,12 +135,26 @@ export default {
|
|||||||
:data="this.job.Operator"
|
:data="this.job.Operator"
|
||||||
@update="(value) => this.job.Operator = value"
|
@update="(value) => this.job.Operator = value"
|
||||||
></ScheduleDropdown>
|
></ScheduleDropdown>
|
||||||
<input class="form-control form-control-sm form-control-dark rounded-3 flex-grow-1"
|
|
||||||
:disabled="!edit"
|
<VueDatePicker
|
||||||
type="datetime-local"
|
:is24="true"
|
||||||
v-if="this.job.Field === 'date'"
|
:min-date="new Date()"
|
||||||
v-model="this.job.Value"
|
:model-value="this.job.Value"
|
||||||
style="width: auto">
|
@update:model-value="this.parseTime" time-picker-inline
|
||||||
|
format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
preview-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
:clearable="false"
|
||||||
|
:disabled="!edit"
|
||||||
|
v-if="this.job.Field === 'date'"
|
||||||
|
:dark="this.store.Configuration.Server.dashboard_theme === 'dark'"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- <input class="form-control form-control-sm form-control-dark rounded-3 flex-grow-1"-->
|
||||||
|
<!-- :disabled="!edit"-->
|
||||||
|
<!-- type="datetime-local"-->
|
||||||
|
<!-- v-if="this.job.Field === 'date'"-->
|
||||||
|
<!-- v-model="this.job.Value"-->
|
||||||
|
<!-- style="width: auto">-->
|
||||||
<input class="form-control form-control-sm form-control-dark rounded-3 flex-grow-1"
|
<input class="form-control form-control-sm form-control-dark rounded-3 flex-grow-1"
|
||||||
:disabled="!edit"
|
:disabled="!edit"
|
||||||
v-else
|
v-else
|
||||||
@ -188,4 +209,12 @@ input:disabled{
|
|||||||
background-color: rgba(13, 110, 253, 0.09);
|
background-color: rgba(13, 110, 253, 0.09);
|
||||||
color: #0d6efd;
|
color: #0d6efd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dp__main{
|
||||||
|
width: auto;
|
||||||
|
flex-grow: 1;
|
||||||
|
--dp-input-padding: 2.5px 30px 2.5px 12px;
|
||||||
|
--dp-border-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
@ -27,17 +27,28 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.dataCopy = JSON.parse(JSON.stringify(this.peer.ShareLink)).at(0);
|
this.dataCopy = JSON.parse(JSON.stringify(this.peer.ShareLink)).at(0);
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
'peer.ShareLink': {
|
||||||
|
deep: true,
|
||||||
|
handler(newVal, oldVal){
|
||||||
|
if (oldVal.length !== newVal.length){
|
||||||
|
this.dataCopy = JSON.parse(JSON.stringify(this.peer.ShareLink)).at(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
startSharing(){
|
startSharing(){
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
fetchPost("/api/sharePeer/create", {
|
fetchPost("/api/sharePeer/create", {
|
||||||
Configuration: this.peer.configuration.Name,
|
Configuration: this.peer.configuration.Name,
|
||||||
Peer: this.peer.id,
|
Peer: this.peer.id,
|
||||||
ExpireDate: dayjs().add(30, 'd').format("YYYY-MM-DD hh:mm:ss")
|
ExpireDate: dayjs().add(7, 'd').format("YYYY-MM-DD HH:mm:ss")
|
||||||
}, (res) => {
|
}, (res) => {
|
||||||
if (res.status){
|
if (res.status){
|
||||||
this.peer.ShareLink = res.data;
|
this.peer.ShareLink = res.data;
|
||||||
this.dataCopy = res.data;
|
this.dataCopy = res.data.at(0);
|
||||||
this.store.newMessage("Server", "Share link created successfully", "success")
|
this.store.newMessage("Server", "Share link created successfully", "success")
|
||||||
}else{
|
}else{
|
||||||
this.store.newMessage("Server",
|
this.store.newMessage("Server",
|
||||||
@ -49,8 +60,29 @@ export default {
|
|||||||
},
|
},
|
||||||
updateLinkExpireDate(){
|
updateLinkExpireDate(){
|
||||||
fetchPost("/api/sharePeer/update", this.dataCopy, (res) => {
|
fetchPost("/api/sharePeer/update", this.dataCopy, (res) => {
|
||||||
console.log(res)
|
if (res.status){
|
||||||
})
|
this.dataCopy = res.data.at(0)
|
||||||
|
this.peer.ShareLink = res.data;
|
||||||
|
this.store.newMessage("Server", "Link expire date updated", "success")
|
||||||
|
}else{
|
||||||
|
this.store.newMessage("Server",
|
||||||
|
"Link expire date failed to update. Reason: " + res.message, "danger")
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
});
|
||||||
|
},
|
||||||
|
stopSharing(){
|
||||||
|
this.loading = true;
|
||||||
|
this.dataCopy.ExpireDate = dayjs().format("YYYY-MM-DD HH:mm:ss")
|
||||||
|
this.updateLinkExpireDate()
|
||||||
|
},
|
||||||
|
parseTime(modelData){
|
||||||
|
if(modelData){
|
||||||
|
this.dataCopy.ExpireDate = dayjs(modelData).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
}else{
|
||||||
|
this.dataCopy.ExpireDate = undefined
|
||||||
|
}
|
||||||
|
this.updateLinkExpireDate()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -60,11 +92,6 @@ export default {
|
|||||||
+ this.$router.resolve(
|
+ this.$router.resolve(
|
||||||
{path: "/share", query: {"ShareID": this.dataCopy.ShareID}}).href;
|
{path: "/share", query: {"ShareID": this.dataCopy.ShareID}}).href;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'dataCopy.ExpireDate'(){
|
|
||||||
this.updateLinkExpireDate()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -101,16 +128,31 @@ export default {
|
|||||||
{{ getUrl }}
|
{{ getUrl }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-column gap-2">
|
<div class="d-flex flex-column gap-2 mb-3">
|
||||||
<small>
|
<small>
|
||||||
<i class="bi bi-calendar me-2"></i>
|
<i class="bi bi-calendar me-2"></i>
|
||||||
Expire Date
|
Expire Date
|
||||||
</small>
|
</small>
|
||||||
<VueDatePicker v-model="this.dataCopy.ExpireDate" time-picker-inline
|
<VueDatePicker
|
||||||
|
:is24="true"
|
||||||
|
:min-date="new Date()"
|
||||||
|
:model-value="this.dataCopy.ExpireDate"
|
||||||
|
@update:model-value="this.parseTime" time-picker-inline
|
||||||
format="yyyy-MM-dd HH:mm:ss"
|
format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
preview-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
|
||||||
:dark="this.store.Configuration.Server.dashboard_theme === 'dark'"
|
:dark="this.store.Configuration.Server.dashboard_theme === 'dark'"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
@click="this.stopSharing()"
|
||||||
|
:disabled="this.loading"
|
||||||
|
class="w-100 btn bg-danger-subtle text-danger-emphasis border-1 border-danger-subtle rounded-3 shadow-sm">
|
||||||
|
<span :class="{'animate__animated animate__flash animate__infinite animate__slower': this.loading}">
|
||||||
|
<i class="bi bi-send-slash-fill me-2" ></i>
|
||||||
|
</span>
|
||||||
|
{{this.loading ? "Stop Sharing...":"Stop Sharing"}}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,13 +2,15 @@
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import {fetchPost} from "@/utilities/fetch.js";
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
import VueDatePicker from "@vuepic/vue-datepicker";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "newDashboardAPIKey",
|
name: "newDashboardAPIKey",
|
||||||
|
components: {VueDatePicker},
|
||||||
data(){
|
data(){
|
||||||
return{
|
return{
|
||||||
newKeyData:{
|
newKeyData:{
|
||||||
ExpiredAt: dayjs().add(1, 'd').format("YYYY-MM-DDTHH:mm:ss"),
|
ExpiredAt: dayjs().add(7, 'd').format("YYYY-MM-DD HH:mm:ss"),
|
||||||
neverExpire: false
|
neverExpire: false
|
||||||
},
|
},
|
||||||
submitting: false
|
submitting: false
|
||||||
@ -39,6 +41,13 @@ export default {
|
|||||||
fixDate(date){
|
fixDate(date){
|
||||||
console.log(dayjs(date).format("YYYY-MM-DDTHH:mm:ss"))
|
console.log(dayjs(date).format("YYYY-MM-DDTHH:mm:ss"))
|
||||||
return dayjs(date).format("YYYY-MM-DDTHH:mm:ss")
|
return dayjs(date).format("YYYY-MM-DDTHH:mm:ss")
|
||||||
|
},
|
||||||
|
parseTime(modelData){
|
||||||
|
if(modelData){
|
||||||
|
this.newKeyData.ExpiredAt = dayjs(modelData).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
}else{
|
||||||
|
this.newKeyData.ExpiredAt = undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,16 +58,23 @@ export default {
|
|||||||
style="background-color: #00000060; backdrop-filter: blur(3px)">
|
style="background-color: #00000060; backdrop-filter: blur(3px)">
|
||||||
<div class="card m-auto rounded-3 mt-5">
|
<div class="card m-auto rounded-3 mt-5">
|
||||||
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0">
|
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0">
|
||||||
Create API Key
|
<h6 class="mb-0">Create API Key</h6>
|
||||||
<button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button>
|
<button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body d-flex gap-2 p-4 flex-column">
|
<div class="card-body d-flex gap-2 p-4 flex-column">
|
||||||
<small class="text-muted">When should this API Key expire?</small>
|
<small class="text-muted">When should this API Key expire?</small>
|
||||||
<div class="d-flex align-items-center gap-2">
|
<div class="d-flex align-items-center gap-2">
|
||||||
<input class="form-control" type="datetime-local"
|
<VueDatePicker
|
||||||
@change="this.newKeyData.ExpiredAt = this.fixDate(this.newKeyData.ExpiredAt)"
|
:is24="true"
|
||||||
:disabled="this.newKeyData.neverExpire || this.submitting"
|
:min-date="new Date()"
|
||||||
v-model="this.newKeyData.ExpiredAt">
|
:model-value="this.newKeyData.ExpiredAt"
|
||||||
|
@update:model-value="this.parseTime" time-picker-inline
|
||||||
|
format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
preview-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
:clearable="false"
|
||||||
|
:disabled="this.newKeyData.neverExpire || this.submitting"
|
||||||
|
:dark="this.store.Configuration.Server.dashboard_theme === 'dark'"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox"
|
<input class="form-check-input" type="checkbox"
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
*,
|
/**{*/
|
||||||
|
/* font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";*/
|
||||||
|
/*}*/
|
||||||
|
|
||||||
.dp__input{
|
.dp__input{
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important;
|
||||||
}
|
}
|
||||||
@ -1125,6 +1128,7 @@ pre.index-alert {
|
|||||||
background-color: #00000060;
|
background-color: #00000060;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
backdrop-filter: blur(1px);
|
backdrop-filter: blur(1px);
|
||||||
|
-webkit-backdrop-filter: blur(1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboardModal{
|
.dashboardModal{
|
||||||
|
Loading…
Reference in New Issue
Block a user