tailbone/tailbone/templates/upgrades/view.mako
Lance Edgar b04c1054fc Override document title when upgrading
when using websockets, to mimic old behavior without them
2022-12-25 12:25:55 -06:00

322 lines
10 KiB
Mako

## -*- coding: utf-8; -*-
<%inherit file="/master/view.mako" />
<%def name="extra_javascript()">
${parent.extra_javascript()}
% if not use_buefy:
<script type="text/javascript">
function show_packages(type) {
if (type == 'all') {
$('.showing .diffs').css('font-weight', 'normal');
$('table.diff tbody tr').show();
$('.showing .all').css('font-weight', 'bold');
} else if (type == 'diffs') {
$('.showing .all').css('font-weight', 'normal');
$('table.diff tbody tr:not(.diff)').hide();
$('.showing .diffs').css('font-weight', 'bold');
}
}
$(function() {
show_packages('diffs');
$('.showing .all').click(function() {
show_packages('all');
return false;
});
$('.showing .diffs').click(function() {
show_packages('diffs')
return false;
});
});
</script>
% endif
</%def>
<%def name="extra_styles()">
${parent.extra_styles()}
% if master.has_perm('execute'):
<style type="text/css">
.progress-with-textout {
border: 1px solid Black;
line-height: 1.2;
overflow: auto;
padding: 1rem;
}
</style>
% endif
</%def>
<%def name="render_this_page()">
${parent.render_this_page()}
% if expose_websockets and master.has_perm('execute'):
<b-modal :active.sync="upgradeExecuting"
full-screen
:can-cancel="false">
<div class="card">
<div class="card-content">
<div class="level">
<div class="level-item has-text-centered"
style="display: flex; flex-direction: column;">
<p class="block">
Upgrading ${app_title} (please wait) ...
{{ executeUpgradeComplete ? "DONE!" : "" }}
</p>
<b-progress size="is-large"
style="width: 400px;"
## :value="80"
## show-value
## format="percent"
>
</b-progress>
</div>
<div class="level-right">
<div class="level-item">
<b-button type="is-warning"
icon-pack="fas"
icon-left="sad-tear"
@click="declareFailureClick()">
Declare Failure
</b-button>
</div>
</div>
</div>
<div class="container progress-with-textout is-family-monospace is-size-7"
ref="textout">
<span v-for="line in progressOutput"
:key="line.key"
v-html="line.text">
</span>
## nb. we auto-scroll down to "see" this element
<div ref="seeme"></div>
</div>
</div>
</div>
</b-modal>
% endif
% if master.has_perm('execute'):
${h.form(master.get_action_url('declare_failure', instance), ref='declareFailureForm')}
${h.csrf_token(request)}
${h.end_form()}
% endif
</%def>
<%def name="render_buefy_form()">
<div class="form">
<${form.component}
% if expose_websockets and master.has_perm('execute'):
% if instance_executable:
@execute-upgrade-click="executeUpgrade"
% endif
:upgrade-executing="upgradeExecuting"
@declare-failure-click="declareFailureClick"
:declare-failure-submitting="declareFailureSubmitting"
% endif
>
</${form.component}>
</div>
</%def>
<%def name="render_form_buttons()">
% if instance_executable and master.has_perm('execute'):
<div class="buttons">
% if instance.enabled and not instance.executing:
% if use_buefy and expose_websockets:
<b-button type="is-primary"
icon-pack="fas"
icon-left="arrow-circle-right"
:disabled="upgradeExecuting"
@click="$emit('execute-upgrade-click')">
{{ upgradeExecuting ? "Working, please wait..." : "Execute this upgrade" }}
</b-button>
% elif use_buefy:
${h.form(url('{}.execute'.format(route_prefix), uuid=instance.uuid), **{'@submit': 'submitForm'})}
${h.csrf_token(request)}
<b-button type="is-primary"
native-type="submit"
icon-pack="fas"
icon-left="arrow-circle-right"
:disabled="formSubmitting">
{{ formSubmitting ? "Working, please wait..." : "Execute this upgrade" }}
</b-button>
${h.end_form()}
% else:
${h.form(url('{}.execute'.format(route_prefix), uuid=instance.uuid), class_='autodisable')}
${h.csrf_token(request)}
${h.submit('execute', "Execute this upgrade", class_='button is-primary')}
${h.end_form()}
% endif
% elif instance.enabled:
<button type="button" class="button is-primary" disabled="disabled" title="This upgrade is currently executing">Execute this upgrade</button>
% else:
<button type="button" class="button is-primary" disabled="disabled" title="This upgrade is not enabled">Execute this upgrade</button>
% endif
</div>
% endif
</%def>
<%def name="modify_this_page_vars()">
${parent.modify_this_page_vars()}
<script type="text/javascript">
TailboneFormData.showingPackages = 'diffs'
% if master.has_perm('execute'):
% if expose_websockets:
ThisPageData.ws = null
//////////////////////////////
// execute upgrade
//////////////////////////////
TailboneForm.props.upgradeExecuting = {
type: Boolean,
default: false,
}
ThisPageData.upgradeExecuting = false
ThisPageData.progressOutput = []
ThisPageData.progressOutputCounter = 0
ThisPageData.executeUpgradeComplete = false
ThisPage.methods.adjustTextoutHeight = function() {
// grow the textout area to fill most of screen
let textout = this.$refs.textout
let height = window.innerHeight - textout.offsetTop - 50
textout.style.height = height + 'px'
}
ThisPage.methods.showExecuteDialog = function() {
this.upgradeExecuting = true
document.title = "Upgrading ${app_title} ..."
this.$nextTick(() => {
this.adjustTextoutHeight()
})
}
ThisPage.methods.establishWebsocket = function() {
## TODO: should be a cleaner way to get this url?
url = '${request.route_url('ws.upgrades.execution_progress', _query={'uuid': instance.uuid})}'
url = url.replace(/^https?:/, 'wss:')
this.ws = new WebSocket(url)
## TODO: add support for this here?
// this.ws.onclose = (event) => {
// // websocket closing means 1 of 2 things:
// // - user navigated away from page intentionally
// // - server connection was broken somehow
// // only one of those is "bad" and we only want to
// // display warning in 2nd case. so we simply use a
// // brief delay to "rule out" the 1st scenario
// setTimeout(() => { that.websocketBroken = true },
// 3000)
// }
this.ws.onmessage = (event) => {
let data = JSON.parse(event.data)
if (data.complete) {
// upgrade has completed; reload page to view result
this.executeUpgradeComplete = true
this.$nextTick(() => {
location.reload()
})
} else if (data.stdout) {
// add lines to textout area
this.progressOutput.push({
key: ++this.progressOutputCounter,
text: data.stdout})
// scroll down to end of textout area
this.$nextTick(() => {
this.$refs.seeme.scrollIntoView({behavior: 'smooth'})
})
}
}
}
% if instance.executing:
ThisPage.mounted = function() {
this.showExecuteDialog()
this.establishWebsocket()
}
% endif
% if instance_executable:
ThisPage.methods.executeUpgrade = function() {
this.showExecuteDialog()
let url = '${master.get_action_url('execute', instance)}'
this.submitForm(url, {ws: true}, response => {
this.establishWebsocket()
})
}
% endif
% else:
## no websockets
//////////////////////////////
// execute upgrade
//////////////////////////////
TailboneFormData.formSubmitting = false
TailboneForm.methods.submitForm = function() {
this.formSubmitting = true
}
% endif
//////////////////////////////
// declare failure
//////////////////////////////
TailboneForm.props.declareFailureSubmitting = {
type: Boolean,
default: false,
}
TailboneForm.methods.declareFailureClick = function() {
this.$emit('declare-failure-click')
}
ThisPageData.declareFailureSubmitting = false
ThisPage.methods.declareFailureClick = function() {
if (confirm("Really declare this upgrade a failure?")) {
this.declareFailureSubmitting = true
this.$refs.declareFailureForm.submit()
}
}
% endif
</script>
</%def>
${parent.body()}