blueweather/js/blueweather.js

473 lines
19 KiB
JavaScript
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class BlueWeather {
constructor(profileObjectParent) {
// cunstruct xmlhttp
this.xhttp = new XMLHttpRequest();
//this.host = "https://weather.itsblue.de"
this.host = window.location.href.substring(0, window.location.href.lastIndexOf("/"));
this.profileObjectParent = profileObjectParent
this.log("init done", 2)
this.session = {
loggedIn: false,
token: "",
user: {
realName: "Real Name",
username: "username"
}
}
this.restoreSession()
}
// ----------------------
// - session management -
// ----------------------
restoreSession() {
var thisObject = this
if (this.getCookie("session") !== "" && this.getCookie("session") !== undefined && this.getCookie("session") !== "undefined") {
// old session found
console.log("old session found: " + this.getCookie("session"), 3)
// check if the session is still valid
this.checkSession(this.getCookie("session"), function (sessionIsValid) {
if (sessionIsValid) {
thisObject.session.loggedIn = true
thisObject.session.token = thisObject.getCookie("session")
}
thisObject.loadProfileObject(thisObject.profileObjectParent)
})
}
else {
this.loadProfileObject(this.profileObjectParent)
}
}
login(async, username, password, processingFunction) {
var xhttp = new XMLHttpRequest();
var thisObject = this
if (async) {
xhttp.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200) {
thisObject.log("login response was: " + this.responseText, 3)
var ret = JSON.parse(this.responseText)
if (ret && ret['header'] === 200) {
thisObject.session.token = ret["body"]
document.cookie = "session=" + ret["body"] + ";"
thisObject.session.loggedIn = true
processingFunction(true)
return
}
else {
thisObject.endSession()
}
}
processingFunction(false)
}
}
}
var request = JSON.stringify({ header: 1000, body: { username: username, password: password } })
var url = this.host + "/api/json.php?command=" + request
this.log("starting login request; URL is: " + url, 3)
xhttp.open("GET", url, async)
xhttp.send()
}
logout() {
var xhttp = new XMLHttpRequest();
var thisObject = this
xhttp.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200) {
thisObject.log("logout response was: " + this.responseText, 3)
document.cookie = "session=;"
location.reload()
}
}
}
var request = JSON.stringify({ header: 1002, body: this.session.token })
var url = this.host + "/api/json.php?command=" + request
this.log("starting logout request; URL is: " + url, 3)
xhttp.open("GET", url, true)
xhttp.send()
}
checkSession(token, processingFunction) {
var xhttp = new XMLHttpRequest();
var thisObject = this
xhttp.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200) {
thisObject.log("login response was: " + this.responseText, 3)
var ret = JSON.parse(this.responseText)
if (ret && ret['header'] === 200) {
thisObject.session.user.username = ret["data"]["username"]
thisObject.session.user.realName = ret["data"]["realname"]
thisObject.session.user.email = ret["data"]["email"]
thisObject.session.user.emailHash = ret["data"]["emailHash"]
processingFunction(true)
return
}
else {
thisObject.endSession()
}
}
processingFunction(false)
}
}
var request = JSON.stringify({ header: 1001, body: token })
var url = this.host + "/api/json.php?command=" + request
this.log("starting session check request; URL is: " + url, 3)
xhttp.open("GET", url, true)
xhttp.send()
}
endSession() {
document.cookie = "session=;"
if (this.session.loggedIn) {
// if the user was logged in before
location.reload()
}
}
// --------------------
// - getter functions -
// --------------------
getLocations(async, processingFunction, errorFunction) {
this.xhttp.abort()
var thisObject = this
if (async) {
this.xhttp.onreadystatechange = function () {
if (this.readyState === 4) {
// Typical action to be performed when the document is ready:
if (this.status === 200) {
thisObject.log("getting sensors response was: " + this.responseText, 3)
var ret = JSON.parse(this.responseText)
if (ret) {
processingFunction(ret);
return
}
}
if (errorFunction !== null) {
errorFunction(this.status, this.text)
}
}
};
}
var url = this.host + "/api/json.php"
this.log("starting location request; URL is: " + url, 3)
this.xhttp.open("GET", url, async)
this.xhttp.send()
}
getLocationData(locId, range = { from: "", to: "" }, maxVals = 0, async, processingFunction, errorFunction) {
this.xhttp.abort()
var thisObject = this
if (async) {
this.xhttp.onreadystatechange = function () {
if (this.readyState === 4) {
// Typical action to be performed when the document is ready:
if (this.status === 200) {
thisObject.log("getting sensors response was: " + this.responseText, 3)
var ret = JSON.parse(this.responseText)
if (ret) {
processingFunction(ret);
return
}
}
if (errorFunction !== null) {
errorFunction(this.status, this.text)
}
}
};
}
var url = this.host + "/api/json.php?locId=" + locId + "&range[from]=" + range.from + "&range[to]=" + range.to + "&maxVals[mode]=" + maxVals.mode + "&maxVals[count]=" + maxVals.count
this.log("starting location request; URL is: " + url, 3)
this.xhttp.open("GET", url, async)
this.xhttp.send()
}
// ----------------------
// - template functions -
// ----------------------
loadProfileObject(parent) {
parent = this.profileObjectParent
if (!parent) {
this.log("error: no profile object parent", 3)
return false
}
parent = document.getElementById(parent)
var thisObject = this
var profileObject = document.createElement("li")
parent.appendChild(profileObject)
profileObject.classList.add("nav-item")
if (!this.session.loggedIn) {
this.log("not logged in", 3)
profileObject.classList.add("text-nowrap")
// create login button
var loginButton = document.createElement('button')
profileObject.appendChild(loginButton)
loginButton.type = "button"
loginButton.setAttribute("data-toggle", "modal")
loginButton.setAttribute("data-target", "#loginModal")
loginButton.classList.add("btn", "btn-outline-light")
loginButton.innerHTML = "Login"
// ------------
// create modal
var loginModal = document.createElement('div')
loginModal.id = "loginModal"
loginModal.setAttribute("tabindex", "-1")
loginModal.setAttribute("role", "dialog")
loginModal.setAttribute("aria-labelledby", "exampleModalLabel")
loginModal.setAttribute("aria-hidden", "true")
loginModal.classList.add("modal", "fade")
// create login form
var loginDiv = document.createElement("div")
loginModal.appendChild(loginDiv)
loginDiv.classList.add("modal-dialog", "modal-login")
loginDiv.setAttribute("role", "document")
// - modal content
var modalContent = document.createElement("div")
loginDiv.appendChild(modalContent)
modalContent.classList.add("modal-content")
// -- modal header
var modalHeader = document.createElement("div")
modalContent.appendChild(modalHeader)
modalHeader.classList.add("modal-header")
// --- close button
var modalCloseButton = document.createElement("button")
modalHeader.appendChild(modalCloseButton)
modalCloseButton.setAttribute("type", "button")
modalCloseButton.setAttribute("data-dismiss", "modal")
modalCloseButton.setAttribute("aria-label", "Close")
modalCloseButton.classList.add("close")
modalCloseButton.innerHTML = '<span aria-hidden="true">×</span>'
// -- modal body
var modalBody = document.createElement("div")
modalContent.appendChild(modalBody)
modalBody.classList.add("modal-body", "text-center")
// --- login form
var loginForm = document.createElement("form")
modalBody.appendChild(loginForm)
loginForm.classList.add("form-signin")
// ---- login form fieldset
var fieldset = document.createElement("fieldset")
loginForm.appendChild(fieldset)
// ----- blueweather icon
var loginFormIcon = document.createElement("img")
fieldset.appendChild(loginFormIcon)
loginFormIcon.width = "72"
loginFormIcon.height = "72"
loginFormIcon.src = "img/icon.png"
loginFormIcon.alt = ""
loginFormIcon.classList.add("mb-4")
// ----- 'Please sign in' text
var loginFormHeadline = document.createElement("h1")
fieldset.append(loginFormHeadline)
loginFormHeadline.classList.add("h3", "mb-3", "font-weight-normal")
loginFormHeadline.innerHTML = "Please sign in"
// ----- login failed alert
var alert = document.createElement("div")
fieldset.append(alert)
alert.id = "loginFormLoginFailedAlert"
alert.appear = function () {
alert.innerHTML = '<div class="alert alert-danger alert-dismissible fade show" role="alert">Invalid username or password<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button></div>'
}
// ----- username input
var usernameInputGroup = document.createElement("div")
fieldset.appendChild(usernameInputGroup)
usernameInputGroup.classList.add("form-group", "input-group")
usernameInputGroup.innerHTML = '<div class="input-group-prepend"><div class="input-group-text"><span data-feather="user"></span></div></div><input type="text" class="form-control" id="loginFormUsernameInput" placeholder="Username"> </div>'
// ----- password input
var passwordInputGroup = document.createElement("div")
fieldset.appendChild(passwordInputGroup)
passwordInputGroup.classList.add("form-group", "input-group")
passwordInputGroup.innerHTML = '<div class="input-group-prepend"><div class="input-group-text"><span data-feather="lock"></span></div></div><input type="password" class="form-control" id="loginFormPasswordInput" placeholder="Password"> </div>'
// ----- 'remember me' checkbox
var rememberCheckboxContainer = document.createElement("div")
rememberCheckboxContainer.classList.add("checkbox", "mb-3")
rememberCheckboxContainer.innerHTML = '<label> <input id="loginFormRememberMeChekbox" type="checkbox"> Remember me </label>'
// ----- 'sign in' button
var signInButton = document.createElement("button")
modalBody.appendChild(signInButton)
signInButton.id = "loginFormSignInButton"
signInButton.type = "submit"
signInButton.classList.add("btn", "btn-lg", "btn-primary", "btn-block")
signInButton.innerHTML = "Sign in"
signInButton.setLoading = function () {
signInButton.disabled = true
signInButton.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Signing in...'
}
signInButton.setNormal = function () {
signInButton.disabled = false
signInButton.innerHTML = 'Sign in'
}
signInButton.onclick = function () {
signInButton.setLoading()
var username = document.getElementById("loginFormUsernameInput").value
var password = document.getElementById("loginFormPasswordInput").value
thisObject.login(true, username, password, function (loginSuccess) {
if (!loginSuccess) {
alert.appear()
signInButton.setNormal()
}
else {
location.reload()
}
})
}
// ----------
parent.appendChild(loginModal)
}
else {
this.log("logged in", 3)
profileObject.classList.add("dropdown")
// create profile picture button
var profileButton = document.createElement("a")
profileObject.appendChild(profileButton)
profileButton.id = "userDropdown"
profileButton.style = "padding: 0;"
profileButton.href = "#"
profileButton.setAttribute("role", "button")
profileButton.classList.add("nav-link", "dropdown-toggle")
profileButton.setAttribute("data-toggle", "dropdown")
profileButton.setAttribute("aria-haspopup", "true")
profileButton.setAttribute("aria-expanded", "false")
// create profile image inside button
var profileImage = document.createElement("img")
profileButton.appendChild(profileImage)
profileImage.height = "30"
profileImage.src = "https://www.gravatar.com/avatar/"+this.session.user.emailHash+".jpg?d=identicon"
profileImage.classList.add("img-profile", "rounded-circle")
// create dropdown menu
var profileDropdown = document.createElement("div")
profileObject.appendChild(profileDropdown)
profileDropdown.classList.add("dropdown-menu", "dropdown-menu-right")
profileDropdown.setAttribute("aria-labelledby", "userDropdown")
// fill the dropdown menu
function createDropdownMenuElement(icon, text, onclick = null) {
// create element
var elem = document.createElement("a")
elem.classList.add("dropdown-item")
elem.href = "#"
elem.onclick = onclick
// create icon
var iconSpan = document.createElement("span")
elem.appendChild(iconSpan)
iconSpan.setAttribute("data-feather", icon)
// create text
var text = document.createTextNode(text)
elem.appendChild(text)
return elem
}
function createDropdownSeparator() {
var sep = document.createElement("div")
sep.classList.add("dropdown-divider")
return sep
}
var header = document.createElement("div")
header.classList.add("dropdown-item")
header.innerHTML = "<h6><b>" + this.session.user.realName + "</b></h6>@" + this.session.user.username
profileDropdown.appendChild(header)
profileDropdown.appendChild(createDropdownSeparator())
profileDropdown.appendChild(createDropdownMenuElement("settings", " Settings"))
profileDropdown.appendChild(createDropdownSeparator())
profileDropdown.appendChild(createDropdownMenuElement("log-out", " Log out", function () {
thisObject.logout()
}))
}
feather.replace()
}
// --------------------
// - helper functions -
// --------------------
getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length == 2) return parts.pop().split(";").shift();
}
findGetParameter(parameterName) {
var result = null,
tmp = [];
location.search
.substr(1)
.split("&")
.forEach(function (item) {
tmp = item.split("=");
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
});
return result;
}
log(text, level) {
// levels:
// 0: error
// 1: warning
// 2: info
// 3: debug
var preString = "[BlueWeather]"
switch (level) {
case 0:
preString += "[error] "
console.error(preString + text)
break
case 1:
preString += "[warining] "
console.warn(preString + text)
break
case 2:
preString += "[info] "
console.log(preString + text)
break
case 3:
preString += "[debug] "
console.debug(preString + text)
}
}
}