mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-11-22 15:20:09 +01:00
Finished selecting peers in bulk to delete and download
This commit is contained in:
parent
56744cec7b
commit
563268558b
@ -135,17 +135,18 @@ class DashboardLogger:
|
|||||||
self.loggerdb.commit()
|
self.loggerdb.commit()
|
||||||
|
|
||||||
def log(self, URL: str = "", IP: str = "", Status: str = "true", Message: str = "") -> bool:
|
def log(self, URL: str = "", IP: str = "", Status: str = "true", Message: str = "") -> bool:
|
||||||
try:
|
pass
|
||||||
with self.loggerdb:
|
# try:
|
||||||
loggerdbCursor = self.loggerdb.cursor()
|
# with self.loggerdb:
|
||||||
loggerdbCursor.execute(
|
# loggerdbCursor = self.loggerdb.cursor()
|
||||||
"INSERT INTO DashboardLog (LogID, URL, IP, Status, Message) VALUES (?, ?, ?, ?, ?)", (str(uuid.uuid4()), URL, IP, Status, Message,))
|
# loggerdbCursor.execute(
|
||||||
if self.loggerdb.in_transaction:
|
# "INSERT INTO DashboardLog (LogID, URL, IP, Status, Message) VALUES (?, ?, ?, ?, ?)", (str(uuid.uuid4()), URL, IP, Status, Message,))
|
||||||
self.loggerdb.commit()
|
# if self.loggerdb.in_transaction:
|
||||||
return True
|
# self.loggerdb.commit()
|
||||||
except Exception as e:
|
# return True
|
||||||
print(f"[WGDashboard] Access Log Error: {str(e)}")
|
# except Exception as e:
|
||||||
return False
|
# print(f"[WGDashboard] Access Log Error: {str(e)}")
|
||||||
|
# return False
|
||||||
|
|
||||||
class PeerJobLogger:
|
class PeerJobLogger:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -1942,6 +1943,7 @@ def API_downloadPeer(configName):
|
|||||||
return ResponseObject(data=peer.downloadPeer())
|
return ResponseObject(data=peer.downloadPeer())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.get(f"{APP_PREFIX}/api/downloadAllPeers/<configName>")
|
@app.get(f"{APP_PREFIX}/api/downloadAllPeers/<configName>")
|
||||||
def API_downloadAllPeers(configName):
|
def API_downloadAllPeers(configName):
|
||||||
if configName not in WireguardConfigurations.keys():
|
if configName not in WireguardConfigurations.keys():
|
||||||
|
@ -33,7 +33,7 @@ const resetForm = () => {
|
|||||||
dataChanged.value = false;
|
dataChanged.value = false;
|
||||||
Object.assign(data, JSON.parse(JSON.stringify(props.configurationInfo)))
|
Object.assign(data, JSON.parse(JSON.stringify(props.configurationInfo)))
|
||||||
}
|
}
|
||||||
const emit = defineEmits(["changed"])
|
const emit = defineEmits(["changed", "close"])
|
||||||
const saveForm = () => {
|
const saveForm = () => {
|
||||||
saving.value = true
|
saving.value = true
|
||||||
fetchPost("/api/updateWireguardConfiguration", data, (res) => {
|
fetchPost("/api/updateWireguardConfiguration", data, (res) => {
|
@ -42,7 +42,8 @@ import PeerJobsLogsModal from "@/components/configurationComponents/peerJobsLogs
|
|||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
import PeerShareLinkModal from "@/components/configurationComponents/peerShareLinkModal.vue";
|
import PeerShareLinkModal from "@/components/configurationComponents/peerShareLinkModal.vue";
|
||||||
import LocaleText from "@/components/text/localeText.vue";
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
import EditConfiguration from "@/components/configurationComponents/peerScheduleJobsComponents/editConfiguration.vue";
|
import EditConfiguration from "@/components/configurationComponents/editConfiguration.vue";
|
||||||
|
import SelectPeers from "@/components/configurationComponents/selectPeers.vue";
|
||||||
|
|
||||||
Chart.register(
|
Chart.register(
|
||||||
ArcElement,
|
ArcElement,
|
||||||
@ -73,6 +74,7 @@ Chart.register(
|
|||||||
export default {
|
export default {
|
||||||
name: "peerList",
|
name: "peerList",
|
||||||
components: {
|
components: {
|
||||||
|
SelectPeers,
|
||||||
EditConfiguration,
|
EditConfiguration,
|
||||||
LocaleText,
|
LocaleText,
|
||||||
PeerShareLinkModal,
|
PeerShareLinkModal,
|
||||||
@ -144,6 +146,9 @@ export default {
|
|||||||
},
|
},
|
||||||
editConfiguration: {
|
editConfiguration: {
|
||||||
modalOpen: false
|
modalOpen: false
|
||||||
|
},
|
||||||
|
selectPeers: {
|
||||||
|
modalOpen: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -592,6 +597,7 @@ export default {
|
|||||||
@jobsAll="this.peerScheduleJobsAll.modalOpen = true"
|
@jobsAll="this.peerScheduleJobsAll.modalOpen = true"
|
||||||
@jobLogs="this.peerScheduleJobsLogs.modalOpen = true"
|
@jobLogs="this.peerScheduleJobsLogs.modalOpen = true"
|
||||||
@editConfiguration="this.editConfiguration.modalOpen = true"
|
@editConfiguration="this.editConfiguration.modalOpen = true"
|
||||||
|
@selectPeers="this.selectPeers.modalOpen = true"
|
||||||
:configuration="this.configurationInfo"></PeerSearch>
|
:configuration="this.configurationInfo"></PeerSearch>
|
||||||
<TransitionGroup name="list" tag="div" class="row gx-2 gy-2 z-0">
|
<TransitionGroup name="list" tag="div" class="row gx-2 gy-2 z-0">
|
||||||
<div class="col-12 col-lg-6 col-xl-4"
|
<div class="col-12 col-lg-6 col-xl-4"
|
||||||
@ -658,14 +664,21 @@ export default {
|
|||||||
:configurationInfo="this.configurationInfo"
|
:configurationInfo="this.configurationInfo"
|
||||||
v-if="this.editConfiguration.modalOpen"></EditConfiguration>
|
v-if="this.editConfiguration.modalOpen"></EditConfiguration>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
<Transition name="zoom">
|
||||||
|
<SelectPeers
|
||||||
|
@refresh="this.getPeers()"
|
||||||
|
v-if="this.selectPeers.modalOpen"
|
||||||
|
:configurationPeers="this.configurationPeers"
|
||||||
|
@close="this.selectPeers.modalOpen = false"
|
||||||
|
></SelectPeers>
|
||||||
|
</Transition>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.peerNav .nav-link{
|
.peerNav .nav-link{
|
||||||
&.active{
|
&.active{
|
||||||
//background: linear-gradient(var(--degree), var(--brandColor1) var(--distance2), var(--brandColor2) 100%);
|
|
||||||
//color: white;
|
|
||||||
background-color: #efefef;
|
background-color: #efefef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,10 +181,24 @@ export default {
|
|||||||
<div class="container-md d-flex h-100 w-100">
|
<div class="container-md d-flex h-100 w-100">
|
||||||
<div class="m-auto modal-dialog-centered dashboardModal">
|
<div class="m-auto modal-dialog-centered dashboardModal">
|
||||||
<div class="card rounded-3 shadow w-100">
|
<div class="card rounded-3 shadow w-100">
|
||||||
<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">
|
||||||
|
<h4 class="mb-0">
|
||||||
|
<LocaleText t="Other Settings"></LocaleText>
|
||||||
|
</h4>
|
||||||
<button type="button" class="btn-close ms-auto" @click="this.showMoreSettings = false"></button>
|
<button type="button" class="btn-close ms-auto" @click="this.showMoreSettings = false"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body px-4 pb-4 d-flex gap-3 flex-column pt-0">
|
<div class="card-body px-4 pb-4 d-flex gap-3 flex-column pt-0">
|
||||||
|
<div>
|
||||||
|
<p class="text-muted fw-bold mb-2"><small>
|
||||||
|
<LocaleText t="Manage Peers"></LocaleText>
|
||||||
|
</small></p>
|
||||||
|
<div class="list-group">
|
||||||
|
<a class="list-group-item list-group-item-action d-flex" role="button"
|
||||||
|
@click="this.$emit('selectPeers')">
|
||||||
|
<LocaleText t="Select Peers"></LocaleText>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p class="text-muted fw-bold mb-2"><small>
|
<p class="text-muted fw-bold mb-2"><small>
|
||||||
<LocaleText t="Peer Jobs"></LocaleText>
|
<LocaleText t="Peer Jobs"></LocaleText>
|
||||||
|
@ -0,0 +1,266 @@
|
|||||||
|
<script setup>
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
import {computed, reactive, ref, useTemplateRef, watch} from "vue";
|
||||||
|
import {fetchGet, fetchPost} from "@/utilities/fetch.js";
|
||||||
|
import {useRoute} from "vue-router";
|
||||||
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
configurationPeers: Array
|
||||||
|
})
|
||||||
|
const deleteConfirmation = ref(false)
|
||||||
|
const downloadConfirmation = ref(false)
|
||||||
|
const selectedPeers = ref([])
|
||||||
|
const selectPeersSearchInput = ref("")
|
||||||
|
|
||||||
|
const togglePeers = (id) => {
|
||||||
|
if (selectedPeers.value.find(x => x === id)){
|
||||||
|
selectedPeers.value = selectedPeers.value.filter(x => x !== id)
|
||||||
|
}else{
|
||||||
|
selectedPeers.value.push(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchPeers = computed(() => {
|
||||||
|
if (deleteConfirmation.value || downloadConfirmation.value){
|
||||||
|
return props.configurationPeers.filter(x =>
|
||||||
|
selectedPeers.value.find(y => y === x.id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (selectPeersSearchInput.value.length > 0){
|
||||||
|
return props.configurationPeers.filter(x => {
|
||||||
|
return x.id.includes(selectPeersSearchInput.value) || x.name.includes(selectPeersSearchInput.value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return props.configurationPeers
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(selectedPeers, () => {
|
||||||
|
if (selectedPeers.value.length === 0){
|
||||||
|
deleteConfirmation.value = false;
|
||||||
|
downloadConfirmation.value = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const dashboardStore = DashboardConfigurationStore()
|
||||||
|
const emit = defineEmits(["refresh", "close"])
|
||||||
|
const submitting = ref(false)
|
||||||
|
const submitDelete = () => {
|
||||||
|
submitting.value = true;
|
||||||
|
fetchPost(`/api/deletePeers/${route.params.id}`, {
|
||||||
|
peers: selectedPeers.value
|
||||||
|
}, (res) => {
|
||||||
|
dashboardStore.newMessage("Server", res.message, res.status ? "success":"danger")
|
||||||
|
if (res.status){
|
||||||
|
selectedPeers.value = []
|
||||||
|
deleteConfirmation.value = false
|
||||||
|
}
|
||||||
|
emit("refresh")
|
||||||
|
submitting.value = false;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloaded = reactive({
|
||||||
|
success: [],
|
||||||
|
failed: []
|
||||||
|
})
|
||||||
|
const cardBody = useTemplateRef('card-body');
|
||||||
|
const sleep = m => new Promise(resolve => setTimeout(resolve, m))
|
||||||
|
const el = useTemplateRef("sp")
|
||||||
|
console.log(el.value)
|
||||||
|
const submitDownload = async () => {
|
||||||
|
downloadConfirmation.value = true
|
||||||
|
// await sleep(100)
|
||||||
|
for (const x of selectedPeers.value) {
|
||||||
|
// await sleep(100)
|
||||||
|
cardBody.value.scrollTo({
|
||||||
|
top: el.value.find(y => y.dataset.id === x).offsetTop - 20,
|
||||||
|
behavior: 'smooth'
|
||||||
|
})
|
||||||
|
|
||||||
|
await fetchGet("/api/downloadPeer/"+route.params.id, {
|
||||||
|
id: x
|
||||||
|
}, (res) => {
|
||||||
|
if (res.status){
|
||||||
|
const blob = new Blob([res.data.file], { type: "text/plain" });
|
||||||
|
const jsonObjectUrl = URL.createObjectURL(blob);
|
||||||
|
const filename = `${res.data.fileName}.conf`;
|
||||||
|
const anchorEl = document.createElement("a");
|
||||||
|
anchorEl.href = jsonObjectUrl;
|
||||||
|
anchorEl.download = filename;
|
||||||
|
anchorEl.click();
|
||||||
|
downloaded.success.push(x)
|
||||||
|
}else{
|
||||||
|
downloaded.failed.push(x)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const clearDownload = () => {
|
||||||
|
downloaded.success = []
|
||||||
|
downloaded.failed = []
|
||||||
|
downloadConfirmation.value = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll" ref="selectPeersContainer">
|
||||||
|
<div class="container d-flex h-100 w-100">
|
||||||
|
<div class="m-auto modal-dialog-centered dashboardModal" style="width: 700px">
|
||||||
|
<div class="card rounded-3 shadow flex-grow-1">
|
||||||
|
<div class="card-header bg-transparent d-flex align-items-center gap-2 p-4 flex-column pb-3">
|
||||||
|
<div class="mb-2 w-100 d-flex">
|
||||||
|
<h4 class="mb-0">
|
||||||
|
<LocaleText t="Select Peers"></LocaleText>
|
||||||
|
</h4>
|
||||||
|
<button type="button" class="btn-close ms-auto"
|
||||||
|
@click="emit('close')"></button>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 align-items-center gap-2">
|
||||||
|
<div class="d-flex gap-3">
|
||||||
|
<a role="button"
|
||||||
|
v-if="!downloadConfirmation"
|
||||||
|
@click="selectedPeers = configurationPeers.map(x => x.id)"
|
||||||
|
class="text-decoration-none text-body">
|
||||||
|
<small>
|
||||||
|
<i class="bi bi-check-all me-2"></i>Select All
|
||||||
|
</small>
|
||||||
|
</a>
|
||||||
|
<a role="button" class="text-decoration-none text-body"
|
||||||
|
@click="selectedPeers = []"
|
||||||
|
v-if="selectedPeers.length > 0 && !downloadConfirmation">
|
||||||
|
<small>
|
||||||
|
<i class="bi bi-x-circle-fill me-2"></i>Clear
|
||||||
|
</small>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label class="ms-auto" for="selectPeersSearchInput">
|
||||||
|
<i class="bi bi-search"></i>
|
||||||
|
</label>
|
||||||
|
<input class="form-control form-control-sm rounded-3"
|
||||||
|
v-model="selectPeersSearchInput"
|
||||||
|
id="selectPeersSearchInput"
|
||||||
|
style="width: 200px !important;" type="text">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body px-4 flex-grow-1 d-flex gap-2 flex-column position-relative"
|
||||||
|
ref="card-body"
|
||||||
|
style="overflow-y: scroll">
|
||||||
|
<button type="button" class="btn w-100 peerBtn text-start rounded-3"
|
||||||
|
@click="togglePeers(p.id)"
|
||||||
|
:class="{active: selectedPeers.find(x => x === p.id)}"
|
||||||
|
:key="p.id"
|
||||||
|
:disabled="deleteConfirmation || downloadConfirmation"
|
||||||
|
ref="sp"
|
||||||
|
:data-id="p.id"
|
||||||
|
v-for="p in searchPeers">
|
||||||
|
<div class="d-flex align-items-center gap-3">
|
||||||
|
<span v-if="!downloadConfirmation">
|
||||||
|
<i class="bi"
|
||||||
|
:class="[ selectedPeers.find(x => x === p.id) ? 'bi-check-circle-fill':'bi-circle']"
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<small class="fw-bold">
|
||||||
|
{{p.name ? p.name : "Untitled Peer"}}
|
||||||
|
</small>
|
||||||
|
<small class="text-muted">
|
||||||
|
<samp>{{p.id}}</samp>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<span v-if="downloadConfirmation" class="ms-auto">
|
||||||
|
<div class="spinner-border spinner-border-sm" role="status"
|
||||||
|
v-if="!downloaded.success.find(x => x === p.id) && !downloaded.failed.find(x => x === p.id)">
|
||||||
|
<span class="visually-hidden">Loading...</span>
|
||||||
|
</div>
|
||||||
|
<i class="bi"
|
||||||
|
v-else
|
||||||
|
:class="[downloaded.failed.find(x => x === p.id) ? 'bi-x-circle-fill':'bi-check-circle-fill']"
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer px-4 py-3 gap-2 d-flex align-items-center">
|
||||||
|
<template v-if="!deleteConfirmation && !downloadConfirmation">
|
||||||
|
<button class="btn bg-primary-subtle text-primary-emphasis border-primary-subtle rounded-3"
|
||||||
|
:disabled="selectedPeers.length === 0 || submitting"
|
||||||
|
@click="submitDownload()"
|
||||||
|
>
|
||||||
|
<i class="bi bi-download"></i>
|
||||||
|
</button>
|
||||||
|
<span v-if="selectedPeers.length > 0" class="flex-grow-1 text-center">
|
||||||
|
<i class="bi bi-check-circle-fill me-2"></i> {{selectedPeers.length}} Peer{{selectedPeers.length > 1 ? 's':''}}
|
||||||
|
</span>
|
||||||
|
<button class="btn bg-danger-subtle text-danger-emphasis border-danger-subtle ms-auto rounded-3"
|
||||||
|
@click="deleteConfirmation = true"
|
||||||
|
:disabled="selectedPeers.length === 0 || submitting"
|
||||||
|
>
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="downloadConfirmation">
|
||||||
|
<strong v-if="downloaded.failed.length + downloaded.success.length < selectedPeers.length" class="flex-grow-1 text-center">
|
||||||
|
Downloading {{selectedPeers.length}} Peer{{selectedPeers.length > 1 ? 's':''}}...
|
||||||
|
</strong>
|
||||||
|
<template v-else>
|
||||||
|
<strong>
|
||||||
|
Download Finished
|
||||||
|
</strong>
|
||||||
|
<button
|
||||||
|
@click="clearDownload()"
|
||||||
|
class="btn bg-secondary-subtle text-secondary-emphasis border border-secondary-subtle rounded-3 ms-auto">
|
||||||
|
Done
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="deleteConfirmation">
|
||||||
|
<button class="btn btn-danger rounded-3"
|
||||||
|
:disabled="selectedPeers.length === 0 || submitting"
|
||||||
|
@click="submitDelete()"
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</button>
|
||||||
|
<strong v-if="selectedPeers.length > 0" class="flex-grow-1 text-center">
|
||||||
|
Are you sure to delete {{selectedPeers.length}} Peer{{selectedPeers.length > 1 ? 's':''}}?
|
||||||
|
</strong>
|
||||||
|
<button class="btn bg-secondary-subtle text-secondary-emphasis border border-secondary-subtle ms-auto rounded-3"
|
||||||
|
:disabled="selectedPeers.length === 0 || submitting"
|
||||||
|
@click="deleteConfirmation = false"
|
||||||
|
>
|
||||||
|
No
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.card{
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboardModal{
|
||||||
|
height: calc(100% - 1rem) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-height: 700px) {
|
||||||
|
.card{
|
||||||
|
height: 700px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.peerBtn{
|
||||||
|
border: var(--bs-border-width) solid var(--bs-border-color);
|
||||||
|
}
|
||||||
|
.peerBtn.active{
|
||||||
|
border: var(--bs-border-width) solid var(--bs-body-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
@ -45,7 +45,7 @@ export default {
|
|||||||
>
|
>
|
||||||
<nav id="sidebarMenu" class=" bg-body-tertiary sidebar border h-100 rounded-3 shadow overflow-y-scroll" >
|
<nav id="sidebarMenu" class=" bg-body-tertiary sidebar border h-100 rounded-3 shadow overflow-y-scroll" >
|
||||||
<div class="sidebar-sticky ">
|
<div class="sidebar-sticky ">
|
||||||
<h5 class="text-white text-center m-0 py-3 mb-3 btn-brand fw-light">WGDashboard</h5>
|
<h5 class="text-white text-center m-0 py-3 mb-3 btn-brand">WGDashboard</h5>
|
||||||
<ul class="nav flex-column px-2">
|
<ul class="nav flex-column px-2">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<RouterLink class="nav-link rounded-3"
|
<RouterLink class="nav-link rounded-3"
|
||||||
@ -92,7 +92,7 @@ export default {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<hr class="text-body">
|
<hr class="text-body">
|
||||||
<ul class="nav flex-column px-2">
|
<ul class="nav flex-column px-2 mb-3">
|
||||||
<li class="nav-item"><a class="nav-link text-danger rounded-3"
|
<li class="nav-item"><a class="nav-link text-danger rounded-3"
|
||||||
@click="this.dashboardConfigurationStore.signOut()"
|
@click="this.dashboardConfigurationStore.signOut()"
|
||||||
role="button" style="font-weight: bold">
|
role="button" style="font-weight: bold">
|
||||||
|
@ -142,7 +142,7 @@
|
|||||||
.sidebar .nav-link, .bottomNavContainer .nav-link{
|
.sidebar .nav-link, .bottomNavContainer .nav-link{
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #333;
|
color: #333;
|
||||||
transition: 0.2s cubic-bezier(0.82, -0.07, 0, 1.01);
|
transition: 0.2s cubic-bezier(0.82, -0.07, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme="dark"] .sidebar .nav-link{
|
[data-bs-theme="dark"] .sidebar .nav-link{
|
||||||
@ -248,7 +248,7 @@
|
|||||||
|
|
||||||
.info h6 {
|
.info h6 {
|
||||||
line-break: anywhere;
|
line-break: anywhere;
|
||||||
transition: all 0.4s cubic-bezier(0.96, -0.07, 0.34, 1.01);
|
transition: all 0.4s cubic-bezier(0.96, -0.07, 0.34, 1.0);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +301,7 @@
|
|||||||
.share_peer_btn_group .btn-control {
|
.share_peer_btn_group .btn-control {
|
||||||
margin: 0 0 0 1rem;
|
margin: 0 0 0 1rem;
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
transition: all 0.4s cubic-bezier(1, -0.43, 0, 1.37);
|
transition: all 0.4s cubic-bezier(1, -0.43, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-control:hover {
|
.btn-control:hover {
|
||||||
@ -421,7 +421,7 @@ main {
|
|||||||
display: none;
|
display: none;
|
||||||
transform: translateY(-30px);
|
transform: translateY(-30px);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: all 0.3s cubic-bezier(0.58, 0.03, 0.05, 1.28);
|
transition: all 0.3s cubic-bezier(0.58, 0.03, 0.05, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-manage-group .setting_btn_menu.show {
|
.btn-manage-group .setting_btn_menu.show {
|
||||||
@ -1051,7 +1051,7 @@ pre.index-alert {
|
|||||||
|
|
||||||
.fade2-enter-active,
|
.fade2-enter-active,
|
||||||
.fade2-leave-active {
|
.fade2-leave-active {
|
||||||
transition: all 0.3s cubic-bezier(0.82, 0.58, 0.17, 1.3);
|
transition: all 0.3s cubic-bezier(0.82, 0.58, 0.17, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade2-enter-from{
|
.fade2-enter-from{
|
||||||
@ -1163,9 +1163,7 @@ pre.index-alert {
|
|||||||
.zoom-enter-active,
|
.zoom-enter-active,
|
||||||
.zoom-leave-active, .zoomReversed-enter-active,
|
.zoom-leave-active, .zoomReversed-enter-active,
|
||||||
.zoomReversed-leave-active {
|
.zoomReversed-leave-active {
|
||||||
transition: all 0.3s cubic-bezier(0.82, 0.58, 0.17, 0.9);
|
transition: all 0.3s cubic-bezier(0.82, 0.58, 0.17, 1);
|
||||||
/*position: absolute;*/
|
|
||||||
/*padding-top: 50px*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.zoom-enter-from,
|
.zoom-enter-from,
|
||||||
@ -1190,7 +1188,7 @@ pre.index-alert {
|
|||||||
.slide-move, /* apply transition to moving elements */
|
.slide-move, /* apply transition to moving elements */
|
||||||
.slide-enter-active,
|
.slide-enter-active,
|
||||||
.slide-leave-active {
|
.slide-leave-active {
|
||||||
transition: all 0.4s cubic-bezier(0.82, 0.58, 0.17, 0.9);
|
transition: all 0.4s cubic-bezier(0.82, 0.58, 0.17, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.slide-leave-active{
|
.slide-leave-active{
|
||||||
|
Loading…
Reference in New Issue
Block a user