1
0
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:
Donald Zou 2024-08-06 19:15:00 -04:00
parent 958bc864c9
commit 7463767781
5 changed files with 136 additions and 45 deletions

View File

@ -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")

View File

@ -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>

View File

@ -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>

View File

@ -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"

View File

@ -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{