add simple ISync authentication
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<style>
|
||||
body, html {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
iframe {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
Please authorise the Application in your browser!
|
||||
<script>
|
||||
const { invoke } = window.__TAURI__.tauri;
|
||||
async function start() {
|
||||
let code = await invoke("open_authorize");
|
||||
let token= await (await fetch("https://ipass.ipost.rocks/get_token?code="+code)).text()
|
||||
invoke("store_token",{
|
||||
token: token
|
||||
})
|
||||
location.href="/settings.html"
|
||||
}
|
||||
start()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+41
-41
@@ -1,41 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title id="pageTitle">IPass - x.x.x</title>
|
||||
<script type="module" src="/main.js"></script>
|
||||
<script type="module" src="/pwprompt.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 id="title">IPass</h1>
|
||||
<div class="select">
|
||||
<img src="/images/menu.png" width="50" height="50">
|
||||
<div>
|
||||
<div><a href="/settings"><img id="cogWImg" src="/images/settings.png" width="50" height="50" alt="Locked" title="Locked"></a></div>
|
||||
<div><img alt="Lock" id="lockImg" src="/images/security_lock_locked.png" height=50 width=50></img></div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div id="table_div">
|
||||
<div id="table_entries">
|
||||
<div>Entry name</div>
|
||||
<div class="entry_name" id="createEntry_name"><input type="text" placeholder="New Entry Name" tabindex="1"></div>
|
||||
</div>
|
||||
<div id="table_users">
|
||||
<div>Username</div>
|
||||
<div class="entry_user" id="createEntry_user"><input type="text" placeholder="New Username" tabindex="1"></div>
|
||||
</div>
|
||||
<div id="table_pwds">
|
||||
<div>Password</div>
|
||||
<div class="entry_pass" id="createEntry_pass"><input type="password" placeholder="New Password" tabindex="1"></div>
|
||||
</div>
|
||||
<div id="table_actions">
|
||||
<div>Action</div>
|
||||
<div class="button" id="createEntry_actions"><button tabindex="1">Create</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title id="pageTitle">IPass - x.x.x</title>
|
||||
<script type="module" src="/main.js"></script>
|
||||
<script type="module" src="/pwprompt.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 id="title">IPass</h1>
|
||||
<div class="select">
|
||||
<img src="/images/menu.png" width="50" height="50">
|
||||
<div>
|
||||
<div><a href="/settings"><img id="cogWImg" src="/images/settings.png" width="50" height="50" alt="Locked" title="Locked"></a></div>
|
||||
<div><img alt="Lock" id="lockImg" src="/images/security_lock_locked.png" height=50 width=50></img></div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div id="table_div">
|
||||
<div id="table_entries">
|
||||
<div>Entry name</div>
|
||||
<div class="entry_name" id="createEntry_name"><input type="text" placeholder="New Entry Name" tabindex="1"></div>
|
||||
</div>
|
||||
<div id="table_users">
|
||||
<div>Username</div>
|
||||
<div class="entry_user" id="createEntry_user"><input type="text" placeholder="New Username" tabindex="1"></div>
|
||||
</div>
|
||||
<div id="table_pwds">
|
||||
<div>Password</div>
|
||||
<div class="entry_pass" id="createEntry_pass"><input type="password" placeholder="New Password" tabindex="1"></div>
|
||||
</div>
|
||||
<div id="table_actions">
|
||||
<div>Action</div>
|
||||
<div class="button" id="createEntry_actions"><button tabindex="1">Create</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+329
-329
@@ -1,330 +1,330 @@
|
||||
const { invoke } = window.__TAURI__.tauri;
|
||||
|
||||
let master_pw;
|
||||
let lock_status = true;
|
||||
|
||||
// async function greet() {
|
||||
// // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
// greetMsgEl.textContent = await invoke("greet", { name: greetInputEl.value });
|
||||
// }
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
document.getElementById("lockImg").addEventListener("click",toggleLock);
|
||||
startup();
|
||||
});
|
||||
|
||||
async function startup() {
|
||||
|
||||
let select = document.querySelector(".select");
|
||||
select.addEventListener("click", function(){
|
||||
this.enabled = !this.enabled
|
||||
if(this.enabled) {
|
||||
this.classList.add("open")
|
||||
} else {
|
||||
this.classList.remove("open")
|
||||
}
|
||||
|
||||
for(let cont of document.querySelectorAll(".select > div")) {
|
||||
cont.style.display=(this.enabled && "block") || "none"
|
||||
}
|
||||
document.querySelector('#table_div').style.marginTop=(this.enabled && "8em") || "0px";
|
||||
});
|
||||
|
||||
|
||||
document.querySelector("#createEntry_actions > button").addEventListener("click",createEntry);
|
||||
|
||||
let entries = await invoke("get_entries");
|
||||
|
||||
for(let i = 0; i < entries.length; i++) {
|
||||
buildEntry(entries[i]);
|
||||
}
|
||||
|
||||
for (let input of document.querySelectorAll('input[readonly]')) {
|
||||
input.addEventListener('click', async function() {
|
||||
if(!input.hasAttribute("readonly"))return
|
||||
if(input.getAttribute("type")!="text" && lock_status)return
|
||||
|
||||
let to_copy = input.value
|
||||
|
||||
if(!lock_status) {
|
||||
let isUsername = input.parentElement.classList.contains("entry_user")
|
||||
let entry_name = input.parentElement.id.slice(0,input.parentElement.id.length-5)
|
||||
console.log(entry_name,input.parentElement.id)
|
||||
|
||||
let info = await invoke("get_entry",{
|
||||
name: entry_name,
|
||||
mpw: await get_pw()
|
||||
})
|
||||
|
||||
if(isUsername) {
|
||||
to_copy = info[0]
|
||||
} else {
|
||||
if(input.parentElement.classList.contains("entry_name")) {
|
||||
to_copy = entry_name
|
||||
} else {
|
||||
to_copy = info[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
navigator.clipboard.writeText(to_copy).then(function() {
|
||||
let originalColor = input.style.borderColor;
|
||||
input.style.borderColor = "lightgreen";
|
||||
setTimeout(function(){
|
||||
input.style.borderColor = originalColor;
|
||||
},250)
|
||||
|
||||
console.log('Text copied to clipboard');
|
||||
}, function(err) {
|
||||
|
||||
let originalColor = input.style.borderColor;
|
||||
input.style.borderColor = "red";
|
||||
setTimeout(function(){
|
||||
input.style.borderColor = originalColor;
|
||||
},500)
|
||||
|
||||
console.error('Failed to copy text: ', err);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
let entry_priority = 1
|
||||
|
||||
function buildEntry(entry) {
|
||||
|
||||
entry_priority++;
|
||||
|
||||
let nameDiv = document.createElement("div");
|
||||
nameDiv.setAttribute("class", "entry_name");
|
||||
nameDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_name`)
|
||||
|
||||
let nameInput = document.createElement("input");
|
||||
nameInput.setAttribute("type", "text");
|
||||
nameInput.setAttribute("placeholder", "New Entry Name");
|
||||
nameInput.setAttribute("value", entry);
|
||||
nameInput.setAttribute("readonly", true);
|
||||
nameInput.setAttribute("unselectable", "on")
|
||||
nameInput.setAttribute("tabindex",entry_priority)
|
||||
nameDiv.appendChild(nameInput);
|
||||
|
||||
let userDiv = document.createElement("div");
|
||||
userDiv.setAttribute("class", "entry_user");
|
||||
userDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_user`)
|
||||
|
||||
let userInput = document.createElement("input");
|
||||
userInput.setAttribute("type", "password");
|
||||
userInput.setAttribute("placeholder", "New Username");
|
||||
userInput.setAttribute("value", "PLACEHOLDER");
|
||||
userInput.setAttribute("readonly", true);
|
||||
userInput.setAttribute("unselectable", "on")
|
||||
userInput.setAttribute("tabindex",entry_priority)
|
||||
userDiv.appendChild(userInput);
|
||||
|
||||
let passDiv = document.createElement("div");
|
||||
passDiv.setAttribute("class", "entry_pass");
|
||||
passDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_pass`)
|
||||
|
||||
let passInput = document.createElement("input");
|
||||
passInput.setAttribute("type", "password");
|
||||
passInput.setAttribute("placeholder", "New Password");
|
||||
passInput.setAttribute("value", "PLACEHOLDER!");
|
||||
passInput.setAttribute("readonly", true);
|
||||
passInput.setAttribute("unselectable", "on")
|
||||
userInput.setAttribute("tabindex",entry_priority)
|
||||
passDiv.appendChild(passInput);
|
||||
|
||||
let showButton = document.createElement("button");
|
||||
showButton.innerText = "Show";
|
||||
showButton.addEventListener("click",showEntry.bind(showButton, entry),false);
|
||||
showButton.setAttribute("class", "showbutton");
|
||||
showButton.setAttribute("tabindex",entry_priority)
|
||||
|
||||
let editButton = document.createElement("button");
|
||||
editButton.innerText = "Edit";
|
||||
editButton.addEventListener("click", editEntry.bind(editButton, entry), false);
|
||||
editButton.setAttribute("class", "editbutton");
|
||||
editButton.setAttribute("tabindex",entry_priority)
|
||||
|
||||
let deleteButton = document.createElement("button");
|
||||
deleteButton.innerText = "Delete";
|
||||
deleteButton.addEventListener("click", deleteEntry.bind(deleteButton, entry), false);
|
||||
deleteButton.setAttribute("class", "deletebutton");
|
||||
deleteButton.setAttribute("tabindex",entry_priority)
|
||||
|
||||
let actionDiv = document.createElement("div")
|
||||
actionDiv.appendChild(showButton)
|
||||
actionDiv.appendChild(editButton)
|
||||
actionDiv.appendChild(deleteButton)
|
||||
|
||||
actionDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_actions`)
|
||||
|
||||
document.getElementById("table_entries").appendChild(nameDiv)
|
||||
document.getElementById("table_users").appendChild(userDiv)
|
||||
document.getElementById("table_pwds").appendChild(passDiv)
|
||||
document.getElementById("table_actions").appendChild(actionDiv)
|
||||
|
||||
}
|
||||
|
||||
function deleteEntry(entry) {
|
||||
let entry_user = document.querySelector(`#${entry.replaceAll(" ","-")}_user`);
|
||||
let entry_pass = document.querySelector(`#${entry.replaceAll(" ","-")}_pass`);
|
||||
let entry_name = document.querySelector(`#${entry.replaceAll(" ","-")}_name`);
|
||||
let actions = document.querySelector(`#${entry.replaceAll(" ","-")}_actions`);
|
||||
|
||||
entry_user.remove()
|
||||
entry_pass.remove()
|
||||
entry_name.remove()
|
||||
actions.remove()
|
||||
invoke("remove_entry",{name: entry})
|
||||
}
|
||||
|
||||
async function editEntry(entry) {
|
||||
let entry_user = document.querySelector(`#${entry.replaceAll(" ","-")}_user > input`);
|
||||
let entry_pass = document.querySelector(`#${entry.replaceAll(" ","-")}_pass > input`);
|
||||
let entry_name = document.querySelector(`#${entry.replaceAll(" ","-")}_name > input`);
|
||||
let show_button = document.querySelector(`#${entry.replaceAll(" ","-")}_actions > .showbutton`);
|
||||
if(this.innerText == "Edit") {
|
||||
|
||||
let info = await invoke("get_entry",{
|
||||
name: entry_name.value,
|
||||
mpw: await get_pw()
|
||||
})
|
||||
|
||||
entry_user.value = info[0];
|
||||
entry_pass.value = info[1];
|
||||
|
||||
entry_user.removeAttribute("readonly");
|
||||
entry_user.setAttribute("unselectable", "off")
|
||||
entry_user.type = "text";
|
||||
entry_pass.removeAttribute("readonly");
|
||||
entry_pass.setAttribute("unselectable", "off")
|
||||
entry_pass.type = "text";
|
||||
entry_name.removeAttribute("readonly");
|
||||
entry_name.setAttribute("unselectable", "off")
|
||||
show_button.disabled = true;
|
||||
this.innerText = "Save";
|
||||
|
||||
this.Name = entry_name.value
|
||||
} else {
|
||||
|
||||
//To Delete: this.Name
|
||||
|
||||
let isDeleted = await invoke("remove_entry", {name: this.Name})
|
||||
if(!isDeleted) {
|
||||
alert("Could not edit entry!")
|
||||
return;
|
||||
}
|
||||
|
||||
let success = await invoke("create_entry", {name: entry_name.value, username: entry_user.value, pw: entry_pass.value, mpw: await get_pw()});
|
||||
if(!success) {
|
||||
alert("Could not edit entry!")
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
entry_user.setAttribute("readonly", true);
|
||||
entry_user.setAttribute("unselectable", "off")
|
||||
entry_user.type = "password"
|
||||
entry_user.value = "PLACEHOLDER"
|
||||
entry_pass.setAttribute("readonly", true);
|
||||
entry_pass.setAttribute("unselectable", "off")
|
||||
entry_pass.type = "password"
|
||||
entry_pass.value = "PLACEHOLDER!"
|
||||
entry_name.setAttribute("readonly", true);
|
||||
entry_name.setAttribute("unselectable", "off")
|
||||
show_button.disabled = false;
|
||||
this.innerText = "Edit";
|
||||
}
|
||||
}
|
||||
|
||||
async function ask_pw() {
|
||||
return await password_prompt("Enter your master password to proceed")
|
||||
}
|
||||
|
||||
async function get_pw() {
|
||||
let mpw = master_pw;
|
||||
|
||||
if(lock_status){
|
||||
mpw = await ask_pw();
|
||||
}
|
||||
|
||||
return mpw;
|
||||
}
|
||||
|
||||
async function showEntry(entry_name) {
|
||||
let entry_user = document.querySelector(`#${entry_name.replaceAll(" ","-")}_user > input`);
|
||||
let entry_pass = document.querySelector(`#${entry_name.replaceAll(" ","-")}_pass > input`);
|
||||
|
||||
if(this.innerText == "Show"){
|
||||
let info = await invoke("get_entry",{
|
||||
name: entry_name,
|
||||
mpw: await get_pw()
|
||||
})
|
||||
entry_user.value = info[0];
|
||||
entry_pass.value = info[1];
|
||||
entry_user.type = "text";
|
||||
entry_pass.type = "text";
|
||||
this.innerText = "Hide";
|
||||
} else {
|
||||
entry_user.value = "PLACEHOLDER";
|
||||
entry_pass.value = "PLACEHOLDER!";
|
||||
entry_user.type = "password";
|
||||
entry_pass.type = "password";
|
||||
this.innerText = "Show";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function createEntry() {
|
||||
let entryNameField = document.querySelector("#createEntry_name > input");
|
||||
let entryUserField = document.querySelector("#createEntry_user > input");
|
||||
let entryPassField = document.querySelector("#createEntry_pass > input");
|
||||
|
||||
if(entryNameField.value == "" || entryUserField.value == "") {
|
||||
alert("Not all needed fields filled out!");
|
||||
return;
|
||||
}
|
||||
|
||||
if(entryPassField.value == "") {
|
||||
if(!(confirm("No password provided, do you want to generate a secure password?"))) {
|
||||
alert("Cant create entry without password!");
|
||||
return;
|
||||
}
|
||||
entryPassField.value = await invoke("random_password");
|
||||
}
|
||||
|
||||
let mpw = await get_pw()
|
||||
|
||||
let success = await invoke("create_entry", {name: entryNameField.value, username: entryUserField.value, pw: entryPassField.value, mpw: mpw});
|
||||
|
||||
if(success) {
|
||||
alert("Successfully created entry!");
|
||||
buildEntry(entryNameField.value)
|
||||
entryNameField.value = ""
|
||||
entryUserField.value = ""
|
||||
entryPassField.value = ""
|
||||
} else {
|
||||
alert("A critical error occured during entry creation");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function toggleLock() {
|
||||
let txt = (lock_status && "Unlocked") || "Locked";
|
||||
let src = (lock_status && "/images/security_lock_unlocked.png") || "/images/security_lock_locked.png";
|
||||
|
||||
if(lock_status){
|
||||
master_pw = await ask_pw();
|
||||
console.log(master_pw)
|
||||
if(master_pw == "" || master_pw == null)return;
|
||||
}
|
||||
|
||||
document.getElementById("lockImg").title = txt;
|
||||
document.getElementById("lockImg").alt = txt;
|
||||
document.getElementById("lockImg").src = src;
|
||||
|
||||
lock_status = !lock_status;
|
||||
const { invoke } = window.__TAURI__.tauri;
|
||||
|
||||
let master_pw;
|
||||
let lock_status = true;
|
||||
|
||||
// async function greet() {
|
||||
// // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
// greetMsgEl.textContent = await invoke("greet", { name: greetInputEl.value });
|
||||
// }
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
document.getElementById("lockImg").addEventListener("click",toggleLock);
|
||||
startup();
|
||||
});
|
||||
|
||||
async function startup() {
|
||||
|
||||
let select = document.querySelector(".select");
|
||||
select.addEventListener("click", function(){
|
||||
this.enabled = !this.enabled
|
||||
if(this.enabled) {
|
||||
this.classList.add("open")
|
||||
} else {
|
||||
this.classList.remove("open")
|
||||
}
|
||||
|
||||
for(let cont of document.querySelectorAll(".select > div")) {
|
||||
cont.style.display=(this.enabled && "block") || "none"
|
||||
}
|
||||
document.querySelector('#table_div').style.marginTop=(this.enabled && "8em") || "0px";
|
||||
});
|
||||
|
||||
|
||||
document.querySelector("#createEntry_actions > button").addEventListener("click",createEntry);
|
||||
|
||||
let entries = await invoke("get_entries");
|
||||
|
||||
for(let i = 0; i < entries.length; i++) {
|
||||
buildEntry(entries[i]);
|
||||
}
|
||||
|
||||
for (let input of document.querySelectorAll('input[readonly]')) {
|
||||
input.addEventListener('click', async function() {
|
||||
if(!input.hasAttribute("readonly"))return
|
||||
if(input.getAttribute("type")!="text" && lock_status)return
|
||||
|
||||
let to_copy = input.value
|
||||
|
||||
if(!lock_status) {
|
||||
let isUsername = input.parentElement.classList.contains("entry_user")
|
||||
let entry_name = input.parentElement.id.slice(0,input.parentElement.id.length-5)
|
||||
console.log(entry_name,input.parentElement.id)
|
||||
|
||||
let info = await invoke("get_entry",{
|
||||
name: entry_name,
|
||||
mpw: await get_pw()
|
||||
})
|
||||
|
||||
if(isUsername) {
|
||||
to_copy = info[0]
|
||||
} else {
|
||||
if(input.parentElement.classList.contains("entry_name")) {
|
||||
to_copy = entry_name
|
||||
} else {
|
||||
to_copy = info[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
navigator.clipboard.writeText(to_copy).then(function() {
|
||||
let originalColor = input.style.borderColor;
|
||||
input.style.borderColor = "lightgreen";
|
||||
setTimeout(function(){
|
||||
input.style.borderColor = originalColor;
|
||||
},250)
|
||||
|
||||
console.log('Text copied to clipboard');
|
||||
}, function(err) {
|
||||
|
||||
let originalColor = input.style.borderColor;
|
||||
input.style.borderColor = "red";
|
||||
setTimeout(function(){
|
||||
input.style.borderColor = originalColor;
|
||||
},500)
|
||||
|
||||
console.error('Failed to copy text: ', err);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
let entry_priority = 1
|
||||
|
||||
function buildEntry(entry) {
|
||||
|
||||
entry_priority++;
|
||||
|
||||
let nameDiv = document.createElement("div");
|
||||
nameDiv.setAttribute("class", "entry_name");
|
||||
nameDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_name`)
|
||||
|
||||
let nameInput = document.createElement("input");
|
||||
nameInput.setAttribute("type", "text");
|
||||
nameInput.setAttribute("placeholder", "New Entry Name");
|
||||
nameInput.setAttribute("value", entry);
|
||||
nameInput.setAttribute("readonly", true);
|
||||
nameInput.setAttribute("unselectable", "on")
|
||||
nameInput.setAttribute("tabindex",entry_priority)
|
||||
nameDiv.appendChild(nameInput);
|
||||
|
||||
let userDiv = document.createElement("div");
|
||||
userDiv.setAttribute("class", "entry_user");
|
||||
userDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_user`)
|
||||
|
||||
let userInput = document.createElement("input");
|
||||
userInput.setAttribute("type", "password");
|
||||
userInput.setAttribute("placeholder", "New Username");
|
||||
userInput.setAttribute("value", "PLACEHOLDER");
|
||||
userInput.setAttribute("readonly", true);
|
||||
userInput.setAttribute("unselectable", "on")
|
||||
userInput.setAttribute("tabindex",entry_priority)
|
||||
userDiv.appendChild(userInput);
|
||||
|
||||
let passDiv = document.createElement("div");
|
||||
passDiv.setAttribute("class", "entry_pass");
|
||||
passDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_pass`)
|
||||
|
||||
let passInput = document.createElement("input");
|
||||
passInput.setAttribute("type", "password");
|
||||
passInput.setAttribute("placeholder", "New Password");
|
||||
passInput.setAttribute("value", "PLACEHOLDER!");
|
||||
passInput.setAttribute("readonly", true);
|
||||
passInput.setAttribute("unselectable", "on")
|
||||
userInput.setAttribute("tabindex",entry_priority)
|
||||
passDiv.appendChild(passInput);
|
||||
|
||||
let showButton = document.createElement("button");
|
||||
showButton.innerText = "Show";
|
||||
showButton.addEventListener("click",showEntry.bind(showButton, entry),false);
|
||||
showButton.setAttribute("class", "showbutton");
|
||||
showButton.setAttribute("tabindex",entry_priority)
|
||||
|
||||
let editButton = document.createElement("button");
|
||||
editButton.innerText = "Edit";
|
||||
editButton.addEventListener("click", editEntry.bind(editButton, entry), false);
|
||||
editButton.setAttribute("class", "editbutton");
|
||||
editButton.setAttribute("tabindex",entry_priority)
|
||||
|
||||
let deleteButton = document.createElement("button");
|
||||
deleteButton.innerText = "Delete";
|
||||
deleteButton.addEventListener("click", deleteEntry.bind(deleteButton, entry), false);
|
||||
deleteButton.setAttribute("class", "deletebutton");
|
||||
deleteButton.setAttribute("tabindex",entry_priority)
|
||||
|
||||
let actionDiv = document.createElement("div")
|
||||
actionDiv.appendChild(showButton)
|
||||
actionDiv.appendChild(editButton)
|
||||
actionDiv.appendChild(deleteButton)
|
||||
|
||||
actionDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_actions`)
|
||||
|
||||
document.getElementById("table_entries").appendChild(nameDiv)
|
||||
document.getElementById("table_users").appendChild(userDiv)
|
||||
document.getElementById("table_pwds").appendChild(passDiv)
|
||||
document.getElementById("table_actions").appendChild(actionDiv)
|
||||
|
||||
}
|
||||
|
||||
function deleteEntry(entry) {
|
||||
let entry_user = document.querySelector(`#${entry.replaceAll(" ","-")}_user`);
|
||||
let entry_pass = document.querySelector(`#${entry.replaceAll(" ","-")}_pass`);
|
||||
let entry_name = document.querySelector(`#${entry.replaceAll(" ","-")}_name`);
|
||||
let actions = document.querySelector(`#${entry.replaceAll(" ","-")}_actions`);
|
||||
|
||||
entry_user.remove()
|
||||
entry_pass.remove()
|
||||
entry_name.remove()
|
||||
actions.remove()
|
||||
invoke("remove_entry",{name: entry})
|
||||
}
|
||||
|
||||
async function editEntry(entry) {
|
||||
let entry_user = document.querySelector(`#${entry.replaceAll(" ","-")}_user > input`);
|
||||
let entry_pass = document.querySelector(`#${entry.replaceAll(" ","-")}_pass > input`);
|
||||
let entry_name = document.querySelector(`#${entry.replaceAll(" ","-")}_name > input`);
|
||||
let show_button = document.querySelector(`#${entry.replaceAll(" ","-")}_actions > .showbutton`);
|
||||
if(this.innerText == "Edit") {
|
||||
|
||||
let info = await invoke("get_entry",{
|
||||
name: entry_name.value,
|
||||
mpw: await get_pw()
|
||||
})
|
||||
|
||||
entry_user.value = info[0];
|
||||
entry_pass.value = info[1];
|
||||
|
||||
entry_user.removeAttribute("readonly");
|
||||
entry_user.setAttribute("unselectable", "off")
|
||||
entry_user.type = "text";
|
||||
entry_pass.removeAttribute("readonly");
|
||||
entry_pass.setAttribute("unselectable", "off")
|
||||
entry_pass.type = "text";
|
||||
entry_name.removeAttribute("readonly");
|
||||
entry_name.setAttribute("unselectable", "off")
|
||||
show_button.disabled = true;
|
||||
this.innerText = "Save";
|
||||
|
||||
this.Name = entry_name.value
|
||||
} else {
|
||||
|
||||
//To Delete: this.Name
|
||||
|
||||
let isDeleted = await invoke("remove_entry", {name: this.Name})
|
||||
if(!isDeleted) {
|
||||
alert("Could not edit entry!")
|
||||
return;
|
||||
}
|
||||
|
||||
let success = await invoke("create_entry", {name: entry_name.value, username: entry_user.value, pw: entry_pass.value, mpw: await get_pw()});
|
||||
if(!success) {
|
||||
alert("Could not edit entry!")
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
entry_user.setAttribute("readonly", true);
|
||||
entry_user.setAttribute("unselectable", "off")
|
||||
entry_user.type = "password"
|
||||
entry_user.value = "PLACEHOLDER"
|
||||
entry_pass.setAttribute("readonly", true);
|
||||
entry_pass.setAttribute("unselectable", "off")
|
||||
entry_pass.type = "password"
|
||||
entry_pass.value = "PLACEHOLDER!"
|
||||
entry_name.setAttribute("readonly", true);
|
||||
entry_name.setAttribute("unselectable", "off")
|
||||
show_button.disabled = false;
|
||||
this.innerText = "Edit";
|
||||
}
|
||||
}
|
||||
|
||||
async function ask_pw() {
|
||||
return await password_prompt("Enter your master password to proceed")
|
||||
}
|
||||
|
||||
async function get_pw() {
|
||||
let mpw = master_pw;
|
||||
|
||||
if(lock_status){
|
||||
mpw = await ask_pw();
|
||||
}
|
||||
|
||||
return mpw;
|
||||
}
|
||||
|
||||
async function showEntry(entry_name) {
|
||||
let entry_user = document.querySelector(`#${entry_name.replaceAll(" ","-")}_user > input`);
|
||||
let entry_pass = document.querySelector(`#${entry_name.replaceAll(" ","-")}_pass > input`);
|
||||
|
||||
if(this.innerText == "Show"){
|
||||
let info = await invoke("get_entry",{
|
||||
name: entry_name,
|
||||
mpw: await get_pw()
|
||||
})
|
||||
entry_user.value = info[0];
|
||||
entry_pass.value = info[1];
|
||||
entry_user.type = "text";
|
||||
entry_pass.type = "text";
|
||||
this.innerText = "Hide";
|
||||
} else {
|
||||
entry_user.value = "PLACEHOLDER";
|
||||
entry_pass.value = "PLACEHOLDER!";
|
||||
entry_user.type = "password";
|
||||
entry_pass.type = "password";
|
||||
this.innerText = "Show";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function createEntry() {
|
||||
let entryNameField = document.querySelector("#createEntry_name > input");
|
||||
let entryUserField = document.querySelector("#createEntry_user > input");
|
||||
let entryPassField = document.querySelector("#createEntry_pass > input");
|
||||
|
||||
if(entryNameField.value == "" || entryUserField.value == "") {
|
||||
alert("Not all needed fields filled out!");
|
||||
return;
|
||||
}
|
||||
|
||||
if(entryPassField.value == "") {
|
||||
if(!(confirm("No password provided, do you want to generate a secure password?"))) {
|
||||
alert("Cant create entry without password!");
|
||||
return;
|
||||
}
|
||||
entryPassField.value = await invoke("random_password");
|
||||
}
|
||||
|
||||
let mpw = await get_pw()
|
||||
|
||||
let success = await invoke("create_entry", {name: entryNameField.value, username: entryUserField.value, pw: entryPassField.value, mpw: mpw});
|
||||
|
||||
if(success) {
|
||||
alert("Successfully created entry!");
|
||||
buildEntry(entryNameField.value)
|
||||
entryNameField.value = ""
|
||||
entryUserField.value = ""
|
||||
entryPassField.value = ""
|
||||
} else {
|
||||
alert("A critical error occured during entry creation");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function toggleLock() {
|
||||
let txt = (lock_status && "Unlocked") || "Locked";
|
||||
let src = (lock_status && "/images/security_lock_unlocked.png") || "/images/security_lock_locked.png";
|
||||
|
||||
if(lock_status){
|
||||
master_pw = await ask_pw();
|
||||
console.log(master_pw)
|
||||
if(master_pw == "" || master_pw == null)return;
|
||||
}
|
||||
|
||||
document.getElementById("lockImg").title = txt;
|
||||
document.getElementById("lockImg").alt = txt;
|
||||
document.getElementById("lockImg").src = src;
|
||||
|
||||
lock_status = !lock_status;
|
||||
}
|
||||
+63
-63
@@ -1,64 +1,64 @@
|
||||
window.password_prompt = async function(label_message, submitbutton_message, cancelbutton_message) {
|
||||
return new Promise((res,rej) => {
|
||||
let width = 200,height = 100;
|
||||
if (typeof label_message !== "string") label_message = "Password:";
|
||||
if (typeof submitbutton_message !== "string") submitbutton_message = "Submit";
|
||||
if (typeof cancelbutton_message !== "string") cancelbutton_message = "Cancel";
|
||||
|
||||
let submit = function() {
|
||||
document.body.removeChild(div);
|
||||
window.removeEventListener("resize", resize, false);
|
||||
res(input.value)
|
||||
};
|
||||
let cancel = function() {
|
||||
document.body.removeChild(div)
|
||||
window.removeEventListener("resize", resize, false)
|
||||
rej()
|
||||
}
|
||||
let resize = function() {
|
||||
div.style.left = ((window.innerWidth / 2) - (width / 2)) + "px";
|
||||
div.style.top = ((window.innerHeight / 2) - (height / 2)) + "px";
|
||||
};
|
||||
|
||||
let div = document.createElement("div");
|
||||
div.id = "password_prompt";
|
||||
|
||||
|
||||
let label = document.createElement("label");
|
||||
label.id = "password_prompt_label";
|
||||
label.innerHTML = label_message;
|
||||
label.for = "password_prompt_input";
|
||||
div.appendChild(label);
|
||||
|
||||
div.appendChild(document.createElement("br"));
|
||||
|
||||
let input = document.createElement("input");
|
||||
input.id = "password_prompt_input";
|
||||
input.type = "password";
|
||||
input.addEventListener("keyup", function(event) {
|
||||
if (event.key == "Enter") submit();
|
||||
}, false);
|
||||
div.appendChild(input);
|
||||
|
||||
div.appendChild(document.createElement("br"));
|
||||
|
||||
let actionDiv = document.createElement("div")
|
||||
|
||||
let submitbutton = document.createElement("button");
|
||||
submitbutton.innerHTML = submitbutton_message;
|
||||
submitbutton.style.display = "inline-block"
|
||||
submitbutton.addEventListener("click", submit, false);
|
||||
actionDiv.appendChild(submitbutton);
|
||||
|
||||
let cancelbutton = document.createElement("button");
|
||||
cancelbutton.innerHTML = cancelbutton_message;
|
||||
cancelbutton.style.display = "inline-block"
|
||||
cancelbutton.addEventListener("click", cancel, false);
|
||||
actionDiv.appendChild(cancelbutton);
|
||||
|
||||
div.appendChild(actionDiv)
|
||||
|
||||
document.body.appendChild(div);
|
||||
window.addEventListener("resize", resize, false);
|
||||
})
|
||||
window.password_prompt = async function(label_message, submitbutton_message, cancelbutton_message) {
|
||||
return new Promise((res,rej) => {
|
||||
let width = 200,height = 100;
|
||||
if (typeof label_message !== "string") label_message = "Password:";
|
||||
if (typeof submitbutton_message !== "string") submitbutton_message = "Submit";
|
||||
if (typeof cancelbutton_message !== "string") cancelbutton_message = "Cancel";
|
||||
|
||||
let submit = function() {
|
||||
document.body.removeChild(div);
|
||||
window.removeEventListener("resize", resize, false);
|
||||
res(input.value)
|
||||
};
|
||||
let cancel = function() {
|
||||
document.body.removeChild(div)
|
||||
window.removeEventListener("resize", resize, false)
|
||||
rej()
|
||||
}
|
||||
let resize = function() {
|
||||
div.style.left = ((window.innerWidth / 2) - (width / 2)) + "px";
|
||||
div.style.top = ((window.innerHeight / 2) - (height / 2)) + "px";
|
||||
};
|
||||
|
||||
let div = document.createElement("div");
|
||||
div.id = "password_prompt";
|
||||
|
||||
|
||||
let label = document.createElement("label");
|
||||
label.id = "password_prompt_label";
|
||||
label.innerHTML = label_message;
|
||||
label.for = "password_prompt_input";
|
||||
div.appendChild(label);
|
||||
|
||||
div.appendChild(document.createElement("br"));
|
||||
|
||||
let input = document.createElement("input");
|
||||
input.id = "password_prompt_input";
|
||||
input.type = "password";
|
||||
input.addEventListener("keyup", function(event) {
|
||||
if (event.key == "Enter") submit();
|
||||
}, false);
|
||||
div.appendChild(input);
|
||||
|
||||
div.appendChild(document.createElement("br"));
|
||||
|
||||
let actionDiv = document.createElement("div")
|
||||
|
||||
let submitbutton = document.createElement("button");
|
||||
submitbutton.innerHTML = submitbutton_message;
|
||||
submitbutton.style.display = "inline-block"
|
||||
submitbutton.addEventListener("click", submit, false);
|
||||
actionDiv.appendChild(submitbutton);
|
||||
|
||||
let cancelbutton = document.createElement("button");
|
||||
cancelbutton.innerHTML = cancelbutton_message;
|
||||
cancelbutton.style.display = "inline-block"
|
||||
cancelbutton.addEventListener("click", cancel, false);
|
||||
actionDiv.appendChild(cancelbutton);
|
||||
|
||||
div.appendChild(actionDiv)
|
||||
|
||||
document.body.appendChild(div);
|
||||
window.addEventListener("resize", resize, false);
|
||||
})
|
||||
};
|
||||
+29
-13
@@ -1,14 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Settings</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="title"><a href="/" class="nostyle">IPass</a></h1>
|
||||
|
||||
</body>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Settings</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="title"><a href="/" class="nostyle">IPass</a></h1>
|
||||
<div>
|
||||
<h2>ISync</h2>
|
||||
<h4>Keep your passwords up-to-date on multiple devices</h4>
|
||||
<span>Current status: <b id="ISyncStatus">Checking</b></span>
|
||||
<a href="/enableISync.html" class="nostyle" id="enableISync">Enable ISync</a>
|
||||
</div>
|
||||
<script>
|
||||
const { invoke } = window.__TAURI__.tauri;
|
||||
async function start() {
|
||||
let status = await invoke("get_isync_status")
|
||||
document.getElementById("ISyncStatus").innerText=status?"Enabled":"Disabled"
|
||||
if(status){
|
||||
document.getElementById("enableISync").remove()
|
||||
}
|
||||
}
|
||||
start()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+210
-210
@@ -1,211 +1,211 @@
|
||||
:root {
|
||||
font-family: MonoLisa, Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
:root {
|
||||
--green: #C2F9BB; /* links etc */
|
||||
--fg-color: #303034; /* post background */
|
||||
--bg-color: #1B1B1E; /* page background etc */
|
||||
--text-color: #ECEAF1; /* text */
|
||||
|
||||
color: var(--text-color);
|
||||
background-color: var(--bg-color);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #24c8db;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
color: var(--text-color);
|
||||
background-color: var(--fg-color);
|
||||
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
transition: border-color 0.25s;
|
||||
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
input,
|
||||
button {
|
||||
padding: 4px 8px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 600px) and (max-width: 900px) {
|
||||
input,
|
||||
button {
|
||||
padding: 5px 10px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 900px) {
|
||||
input,
|
||||
button {
|
||||
padding: 6.4px 12.8px;
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
tr {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
|
||||
input:not([readonly]){
|
||||
color: var(--fg-color);
|
||||
background-color: var(--text-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
border-color: #396cd8;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#table_div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.entry_name,.entry_user,.entry_pass {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.entry_name > input,.entry_user > input,.entry_pass > input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.table_actions>div>button {
|
||||
height: 40%;
|
||||
}
|
||||
|
||||
input[type="password"] {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#password_prompt {
|
||||
background: white;
|
||||
color: black;
|
||||
border: 1px solid black;
|
||||
width: 50%;
|
||||
height: 25%;
|
||||
position: fixed;
|
||||
left: 25%;
|
||||
top: 25%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
border: 3px double var(--fg-color);
|
||||
border-radius: 5%;
|
||||
}
|
||||
|
||||
#table_actions > div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#table_actions > div > button {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
#table_div > div > div {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#createEntry_actions > button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#title {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.select {
|
||||
padding: 5px 10px;
|
||||
border: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1em;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
|
||||
/* hide the default dropdown arrow */
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
|
||||
.select > div{
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 4em;
|
||||
}
|
||||
.select > div > div{
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
a.nostyle:link {
|
||||
text-decoration: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
a.nostyle:visited {
|
||||
text-decoration: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.select > img {
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.25s linear;
|
||||
}
|
||||
|
||||
.select.open > img {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.25s linear;
|
||||
}
|
||||
|
||||
/* .select.open > div {
|
||||
transition: 1s ease-in;
|
||||
height: 8em;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.select > div {
|
||||
transform: none;
|
||||
height: 0;
|
||||
transition: 1s ease-out;
|
||||
:root {
|
||||
font-family: MonoLisa, Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
:root {
|
||||
--green: #C2F9BB; /* links etc */
|
||||
--fg-color: #303034; /* post background */
|
||||
--bg-color: #1B1B1E; /* page background etc */
|
||||
--text-color: #ECEAF1; /* text */
|
||||
|
||||
color: var(--text-color);
|
||||
background-color: var(--bg-color);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #24c8db;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
color: var(--text-color);
|
||||
background-color: var(--fg-color);
|
||||
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
transition: border-color 0.25s;
|
||||
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
input,
|
||||
button {
|
||||
padding: 4px 8px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 600px) and (max-width: 900px) {
|
||||
input,
|
||||
button {
|
||||
padding: 5px 10px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 900px) {
|
||||
input,
|
||||
button {
|
||||
padding: 6.4px 12.8px;
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
tr {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
|
||||
input:not([readonly]){
|
||||
color: var(--fg-color);
|
||||
background-color: var(--text-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
border-color: #396cd8;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#table_div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.entry_name,.entry_user,.entry_pass {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.entry_name > input,.entry_user > input,.entry_pass > input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.table_actions>div>button {
|
||||
height: 40%;
|
||||
}
|
||||
|
||||
input[type="password"] {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#password_prompt {
|
||||
background: white;
|
||||
color: black;
|
||||
border: 1px solid black;
|
||||
width: 50%;
|
||||
height: 25%;
|
||||
position: fixed;
|
||||
left: 25%;
|
||||
top: 25%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
border: 3px double var(--fg-color);
|
||||
border-radius: 5%;
|
||||
}
|
||||
|
||||
#table_actions > div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#table_actions > div > button {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
#table_div > div > div {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#createEntry_actions > button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#title {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.select {
|
||||
padding: 5px 10px;
|
||||
border: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1em;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
|
||||
/* hide the default dropdown arrow */
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
|
||||
.select > div{
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 4em;
|
||||
}
|
||||
.select > div > div{
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
a.nostyle:link {
|
||||
text-decoration: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
a.nostyle:visited {
|
||||
text-decoration: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.select > img {
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.25s linear;
|
||||
}
|
||||
|
||||
.select.open > img {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.25s linear;
|
||||
}
|
||||
|
||||
/* .select.open > div {
|
||||
transition: 1s ease-in;
|
||||
height: 8em;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.select > div {
|
||||
transform: none;
|
||||
height: 0;
|
||||
transition: 1s ease-out;
|
||||
} */
|
||||
Reference in New Issue
Block a user