Files
hasaddon/hassio-google-drive-backup/backup/static/index.jinja2
T
admins 702d080a1e New Addon
Google BK
2023-04-23 18:17:03 +07:00

391 lines
16 KiB
Django/Jinja

{% extends "layouts/base.jinja2" %}
{% block head %}
{{ super() }}
{% endblock %}
{% block content %}
<main>
<div class="section no-pad-bot" id="index-banner">
<div class="container">
<br><br>
<h1 class="header center">Get Started</h1>
<div class="row center">
<h5 class="header col s12 light">To begin, this add-on will need access to your Google Drive&trade;.
<span id="flavor_auto_folder">On your first backup it will create a new folder at the root of your <a
href="https://drive.google.com/drive/my-drive" target="_blank" rel="noreferrer">My Drive</a> where future backups will be stored. Once
its created, you can move the folder wherever you want.</span>
<span id="flavor_specific_folder">After connecting with Google Drive, you'll be prompted to select your
backup folder.</span>
</h5>
</div>
<div>
</div>
<div class="row center">
<div id="option1" class="col m12 l6 offset-l3 center center-align">
<div id="option1-step1">
<div class="row center">
<div class="col s12">
<h6 id="what_do_next_now_please" style="display: none;" class="header light">
<span id="what_do_next_now_please_text"></span>
Change your <a href="#!" onclick="loadSettings()"><i class="material-icons"
style="display: inline; margin-right: 2px; vertical-align: middle; font-size: 15px">settings</i>settings</a>
to alter the add-on's behavior if that isn't what you want.
</h6>
</div>
</div>
<a target="_blank" id="authenticate-button" style="margin: 10px"
class="btn-large btn-flat btn-high-vis">
Authenticate with Google Drive
</a>
<div class="row center">
<div class="col s12">
<ul class="browser-default" style="text-align: left;">
<li>
Clicking this link authenticates you with an external domain maintained by the developer of this add-on (<a
href="https://habackup.io">habackup.io</a>).
</li>
<li>You can <a href="https://github.com/sabeechen/hassio-google-drive-backup/blob/master/hassio-google-drive-backup/AUTHENTICATION.md" target="_blank" rel="noreferrer">read this</a> to understand what this means and why it's necessary.
</li>
<li>
By doing this you must agree to the <a href="pp">Privacy Policy</a> and <a href="tos">Terms of Service</a></h6>
</li>
<li>
The addon will only have access to the files and folders it creates. It can't see any of the other files you've added to Google Drive.</h6>
</li>
</ul>
</div>
</div>
<div class="row center">
<div class="col s12">
After you get the authorization code from the link above, paste the result here:
<br/>
<textarea id="google_credentials_box" style="height: 5rem;"></textarea>
<br>
<div class="left" style="display: none;" id="save_cred_message">
<div class="cls-spinner left" id="save_cred_working">
<div class="cls-signal"></div>
</div>
<div class="left center" style="display: flex;align-items: center;height: 52px;" id="save_cred_message"></div>
</div>
<a target="_blank" class="right btn-large btn-flat btn-high-vis disabled"
id="send_creds_button" onclick="send_creds($('#google_credentials_box').val())">Save</a>
</div>
</div>
<div class="row center">
To generate your own private credentials with Google instead that doesn't use a third-party domain, <a href="#" onclick="doOption2();">click here</a>. Fair warning: that way is much more complicated.
</div>
</div>
</div>
<div id="option2" class="col s12 m6 offset-m3 default-hidden">
<div id="option2-step1">
Follow the <a target="_blank" rel="noreferrer"
href="https://github.com/sabeechen/hassio-google-drive-backup/blob/master/LOCAL_AUTH.md">instructions
here</a> to get your own client ID and client secret from Google's Cloud Console. This is a much more complicated and time
consuming approach but doesn't require you to authenticate yourself with an external domain.
<div class="row">
<form class="col s10" action="manualauth" method="get">
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">vpn_key</i>
<input id="client_id" name="client_id" type="text" class="validate" />
<label for="client_id">Client ID</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">vpn_key</i>
<input id="client_secret" name="client_secret" type="text" class="validate" />
<label for="client_secret">Client Secret</label>
</div>
</div>
<div class=row>
<div class="input-field col s12">
<a target="_blank" class="right btn-large btn-flat btn-high-vis disabled right-align" style="position: absolute; right: 0px;"
id="secret_button" onclick="getAuthUrl()">Next</a>
<a target="_blank" class="right btn-large btn-flat btn-high-vis left-align" style="position: absolute; left: 30px;"
id="secret_button" onclick="backOption2Step1()"><i class="material-icons">arrow_back</i>back</a>
</div>
</div>
</form>
</div>
</div>
<div class="row" style="display: none" id="option2-step2">
<div class="col s12">
<div class="row">
<div class="col s12">
Please navigate to <a id="custom-auth-link" target="_blank" rel="noreferrer"></a> and enter the code shown below to authorize the addon using your Google account. This page will automatically update once you do so.
</div>
</div>
<div class="row">
<div class="col s12">
<span id="code-box" class="device-code-box"></span>
</div>
</div>
<div class="row">
<div class="col s12">
<div>
Expires: <span id="device-code-valid-time-left"></span>
</div>
<div id="device-code-loading" class="progress">
<div class="indeterminate"></div>
</div>
<div id="device-code-status-text">
Loading...
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<a target="_blank" class="right btn-large btn-flat btn-high-vis left-align"
id="secret_button" onclick="backOption2Step2()">Back</a>
</div>
</div>
</div>
</div>
</div>
</div>
<br><br>
</div>
</div>
</main>
{% endblock %}
{% block scripts %}
<script type="text/javascript">
function doOption2() {
$('#option2').show();
$('#option1').hide();
}
function backOption2Step1() {
$('#option2').hide();
$('#option1').show();
}
function backOption2Step2() {
$("#option2-step1").show();
$("#option2-step2").hide();
}
function submitCode() {
var code = $("#code").val();
if (!code || code.length == 0) {
M.toast({ html: "Please enter the code you got form Google by clicking \"connect\" above" })
}
var url = "manualauth?code=" + code;
$.get(url,
function (data) {
M.toast({ html: "Submitting authorization code..." })
if (data.hasOwnProperty("auth_url")) {
console.log("Redirecting to " + data.auth_url)
window.location = data.auth_url
} else if (data.hasOwnProperty("error")) {
M.toast({ html: data.error })
}
}, "json")
}
function updateHref() {
var client_id = $("#client_id").val();
var client_secret = $("#client_secret").val();
if (client_id && client_id.length > 0 && client_secret && client_secret.length > 0) {
$("#secret_button").removeClass('disabled');
$("#help_text").fadeIn(400)
$("#code_form").fadeIn(400)
} else {
$("#secret_button").addClass('disabled');
}
}
function updateCredsButton() {
var text = $('#google_credentials_box').val()
if (text.length > 0){
$("#send_creds_button").removeClass('disabled');
} else {
$("#send_creds_button").addClass('disabled');
}
}
function send_creds(value) {
path = URI("{{save_drive_creds_path}}").query({
'creds': value,
'host': getOutterHomeUri()
});
postJson(path.toString(), {}, function(data){
window.location.assign(getInnerHomeUri());
},
function(data){
M.toast({ html: "Couldn't save these credentials, did you copy the whole string?" })
}, "Saving credentials")
}
last_cred_version = -1;
function reloadForNewCreds() {
var jqxhr = $.get("getstatus", function (data) {
last_data = data;
if (data.is_custom_creds) {
$(".hide-for-custom-creds").hide();
$(".hide-for-default-creds").show();
} else {
$(".hide-for-custom-creds").show();
$(".hide-for-default-creds").hide();
}
if (data.is_specify_folder) {
$("#flavor_auto_folder").hide();
$("#flavor_specific_folder").show();
} else {
$("#flavor_auto_folder").show();
$("#flavor_specific_folder").hide();
}
if (data.hasOwnProperty("cred_version")) {
if (last_cred_version == -1) {
last_cred_version = data.cred_version;
} else if (last_cred_version != data.cred_version) {
//reload
window.location.assign(getInnerHomeUri())
} else {
last_cred_version = data.cred_version;
}
}
token_url = URI(getInnerHomeUri() + "{{ save_drive_creds_path }}");
return_url = getOutterHomeUri()
auth_url = URI(data.authenticate_url).query({
'redirectbacktoken': encodeURIComponent(token_url.toString()),
'version': encodeURIComponent("{{ version }}"),
'return': encodeURIComponent(return_url),
'bg': themeStyleContainer.dataset.backgroundColor,
"ac": themeStyleContainer.dataset.accentColor,
});
document.getElementById("authenticate-button").href = auth_url.toString();
if (!data.firstSync) {
backups = data.sources.HomeAssistant.backups;
hasBackups = backups > 0;
maxConfigured = data.sources.HomeAssistant.max;
toDelete = Math.max(0, hasBackups - data.sources.HomeAssistant.max);
if (data.sources.HomeAssistant.max == 0) {
toDelete = 0;
}
willBackup = data.next_backup_text != "Disabled";
willUpload = data.sources.GoogleDrive.max > 0;
toUpload = Math.min(data.sources.GoogleDrive.max, backups - toDelete);
text = "";
if (!hasBackups && !willBackup) {
text = "You have no backups in Home Assistant and you've configured this add-on not to create any."
} else if (hasBackups && toDelete > 0) {
text = "You have <b>" + backups + " backup(s)</b> in Home Assistant already. Once you authenticate with Google Drive the <b>" + toDelete + " oldest backup(s) will be deleted</b>";
if (toUpload > 0) {
text += " and the <b>" + toUpload + " newest backup(s) will get uploaded</b>."
} else {
text += "."
}
} else if (hasBackups && toUpload > 0) {
text = "You have <b>" + backups + " backup(s)</b> in Home Assistant already. Once you authenticate with Google Drive the <b>" + toUpload + " newest backup(s) will get uploaded</b>."
} else if (!hasBackups) {
text = "You have <b>no backups in Home Assistant</b>";
if (willUpload) {
text += ", authenticate with Google Drive to start automatically creating and backing them up."
} else {
text += ", authenticate with Google Drive to start automatically creating them."
}
} else if (willBackup) {
text = "You have <b>" + backups + " backup(s)</b> in Home Assistant already, authenticate with Google Drive to start creating new ones on a schedule."
} else {
text = "You have <b>" + backups + " backup(s)</b> in Home Assistant already but you haven't configured this add-on to do anything with them or create new ones."
}
$("#what_do_next_now_please_text").html(text);
$("#what_do_next_now_please").show();
}
})
}
$(document).ready(function () {
// Needed to make modal dialogs work.
$('.modal').modal();
$("#client_id").change(updateHref);
$("#client_secret").change(updateHref);
$("#client_secret").keyup(updateHref);
$("#client_id").keyup(updateHref);
$("#client_secret").mouseup(updateHref);
$("#client_id").mouseup(updateHref);
$("#google_credentials_box").change(updateCredsButton)
$("#google_credentials_box").keyup(updateCredsButton);
window.setInterval(reloadForNewCreds, 5000);
reloadForNewCreds();
const params = new URLSearchParams(window.location.search);
if (params.get("private")) {
doOption2();
}
});
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getAuthUrl() {
var client_id = $("#client_id").val();
var client_secret = $("#client_secret").val();
if (!(client_id && client_id.length > 0 && client_secret && client_secret.length > 0)) {
M.toast({ html: "Please enter a Client ID and Client Secret first" })
}
let toast = M.toast({ html: "Talking with Google..."})
url = URI("manualauth").query({
'client_id': client_id,
'client_secret': client_secret});
try {
const resp = await fetch(url.toString());
const data = await resp.json();
if (resp.ok) {
$("#custom-auth-link").attr("href", data.auth_url);
$("#custom-auth-link").html(data.auth_url);
$("#code-box").html(data.code);
$("#code-hidden").val(data.code);
$("#option2-step2").show();
$("#option2-step1").hide();
} else {
toast.dismiss();
M.toast({ html: data.message })
return;
}
} catch (e) {
toast.dismiss();
M.toast({ html: "Encountered and unexpected error. Please make sure the add-on is still running."})
return;
}
toast.dismiss();
// Continually check for status
let status = $("#device-code-status-text");
let progress = $("#device-code-loading");
progress.show();
while(true) {
try {
const resp = await fetch(URI("checkManualAuth").toString());
const data = await resp.json();
status.html(data.message);
if(resp.ok) {
$("#device-code-valid-time-left").html(data.expires)
await sleep(1000);
} else {
progress.hide();
break;
}
} catch (e) {
progress.hode();
status.html("Unexpected error: " + e);
break;
}
}
}
</script>
{% endblock %}