Warn user if DB not up to date, in new table wizard
also start adding 'dirty' page behavior, to warn user if navigating away that changes will be lost also improve steps in wizard, so page header is scrolled into view when prev/next buttons are clicked. unfortunately it still does not work right if user clicks the step number on left of screen..
This commit is contained in:
parent
f5f973dc3a
commit
29817653ed
|
@ -11,8 +11,25 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_this_page()">
|
<%def name="render_this_page()">
|
||||||
|
|
||||||
|
## scroll target used when navigating prev/next
|
||||||
|
<div ref="showme"></div>
|
||||||
|
|
||||||
|
% if not alembic_current_head:
|
||||||
|
<b-notification type="is-warning"
|
||||||
|
:closable="false">
|
||||||
|
<p class="block">
|
||||||
|
DB is not up to date! There are
|
||||||
|
${h.link_to("pending migrations", url('{}.migrations'.format(route_prefix)))}.
|
||||||
|
</p>
|
||||||
|
<p class="block">
|
||||||
|
(This will be a problem if you wish to auto-generate a migration for a new table.)
|
||||||
|
</p>
|
||||||
|
</b-notification>
|
||||||
|
% endif
|
||||||
|
|
||||||
<b-steps v-model="activeStep"
|
<b-steps v-model="activeStep"
|
||||||
:animated="false"
|
animated
|
||||||
rounded
|
rounded
|
||||||
:has-navigation="false"
|
:has-navigation="false"
|
||||||
vertical
|
vertical
|
||||||
|
@ -28,7 +45,8 @@
|
||||||
|
|
||||||
<b-field label="Schema Branch"
|
<b-field label="Schema Branch"
|
||||||
message="Leave this set to your custom app branch, unless you know what you're doing.">
|
message="Leave this set to your custom app branch, unless you know what you're doing.">
|
||||||
<b-select v-model="alembicBranch">
|
<b-select v-model="alembicBranch"
|
||||||
|
@input="dirty = true">
|
||||||
<option v-for="branch in alembicBranchOptions"
|
<option v-for="branch in alembicBranchOptions"
|
||||||
:key="branch"
|
:key="branch"
|
||||||
:value="branch">
|
:value="branch">
|
||||||
|
@ -41,13 +59,15 @@
|
||||||
|
|
||||||
<b-field label="Table Name"
|
<b-field label="Table Name"
|
||||||
message="Should be singular in nature, i.e. 'widget' not 'widgets'">
|
message="Should be singular in nature, i.e. 'widget' not 'widgets'">
|
||||||
<b-input v-model="tableName">
|
<b-input v-model="tableName"
|
||||||
|
@input="dirty = true">
|
||||||
</b-input>
|
</b-input>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<b-field label="Model/Class Name"
|
<b-field label="Model/Class Name"
|
||||||
message="Should be singular in nature, i.e. 'Widget' not 'Widgets'">
|
message="Should be singular in nature, i.e. 'Widget' not 'Widgets'">
|
||||||
<b-input v-model="tableModelName">
|
<b-input v-model="tableModelName"
|
||||||
|
@input="dirty = true">
|
||||||
</b-input>
|
</b-input>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
|
@ -57,13 +77,15 @@
|
||||||
|
|
||||||
<b-field label="Model Title"
|
<b-field label="Model Title"
|
||||||
message="Human-friendly singular model title.">
|
message="Human-friendly singular model title.">
|
||||||
<b-input v-model="tableModelTitle">
|
<b-input v-model="tableModelTitle"
|
||||||
|
@input="dirty = true">
|
||||||
</b-input>
|
</b-input>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<b-field label="Model Title Plural"
|
<b-field label="Model Title Plural"
|
||||||
message="Human-friendly plural model title.">
|
message="Human-friendly plural model title.">
|
||||||
<b-input v-model="tableModelTitlePlural">
|
<b-input v-model="tableModelTitlePlural"
|
||||||
|
@input="dirty = true">
|
||||||
</b-input>
|
</b-input>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
|
@ -71,12 +93,14 @@
|
||||||
|
|
||||||
<b-field label="Description"
|
<b-field label="Description"
|
||||||
message="Brief description of what a record in this table represents.">
|
message="Brief description of what a record in this table represents.">
|
||||||
<b-input v-model="tableDescription">
|
<b-input v-model="tableDescription"
|
||||||
|
@input="dirty = true">
|
||||||
</b-input>
|
</b-input>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<b-field>
|
<b-field>
|
||||||
<b-checkbox v-model="tableVersioned">
|
<b-checkbox v-model="tableVersioned"
|
||||||
|
@input="dirty = true">
|
||||||
Record version data for this table
|
Record version data for this table
|
||||||
</b-checkbox>
|
</b-checkbox>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
@ -285,7 +309,7 @@
|
||||||
<b-button type="is-primary"
|
<b-button type="is-primary"
|
||||||
icon-pack="fas"
|
icon-pack="fas"
|
||||||
icon-left="check"
|
icon-left="check"
|
||||||
@click="activeStep = 'write-model'">
|
@click="showStep('write-model')">
|
||||||
Details are complete
|
Details are complete
|
||||||
</b-button>
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -325,7 +349,7 @@
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<b-button icon-pack="fas"
|
<b-button icon-pack="fas"
|
||||||
icon-left="arrow-left"
|
icon-left="arrow-left"
|
||||||
@click="activeStep = 'enter-details'">
|
@click="showStep('enter-details')">
|
||||||
Back
|
Back
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button type="is-primary"
|
<b-button type="is-primary"
|
||||||
|
@ -337,7 +361,7 @@
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button icon-pack="fas"
|
<b-button icon-pack="fas"
|
||||||
icon-left="arrow-right"
|
icon-left="arrow-right"
|
||||||
@click="activeStep = 'review-model'">
|
@click="showStep('review-model')">
|
||||||
Skip
|
Skip
|
||||||
</b-button>
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -435,19 +459,19 @@
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<b-button icon-pack="fas"
|
<b-button icon-pack="fas"
|
||||||
icon-left="arrow-left"
|
icon-left="arrow-left"
|
||||||
@click="activeStep = 'write-model'">
|
@click="showStep('write-model')">
|
||||||
Back
|
Back
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button type="is-primary"
|
<b-button type="is-primary"
|
||||||
icon-pack="fas"
|
icon-pack="fas"
|
||||||
icon-left="check"
|
icon-left="check"
|
||||||
@click="activeStep = 'write-revision'"
|
@click="showStep('write-revision')"
|
||||||
:disabled="!modelImported">
|
:disabled="!modelImported">
|
||||||
Model class looks good!
|
Model class looks good!
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button icon-pack="fas"
|
<b-button icon-pack="fas"
|
||||||
icon-left="arrow-right"
|
icon-left="arrow-right"
|
||||||
@click="activeStep = 'write-revision'">
|
@click="showStep('write-revision')">
|
||||||
Skip
|
Skip
|
||||||
</b-button>
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -486,7 +510,7 @@
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<b-button icon-pack="fas"
|
<b-button icon-pack="fas"
|
||||||
icon-left="arrow-left"
|
icon-left="arrow-left"
|
||||||
@click="activeStep = 'review-model'">
|
@click="showStep('review-model')">
|
||||||
Back
|
Back
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button type="is-primary"
|
<b-button type="is-primary"
|
||||||
|
@ -498,7 +522,7 @@
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button icon-pack="fas"
|
<b-button icon-pack="fas"
|
||||||
icon-left="arrow-right"
|
icon-left="arrow-right"
|
||||||
@click="activeStep = 'review-revision'">
|
@click="showStep('review-revision')">
|
||||||
Skip
|
Skip
|
||||||
</b-button>
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -526,13 +550,13 @@
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<b-button icon-pack="fas"
|
<b-button icon-pack="fas"
|
||||||
icon-left="arrow-left"
|
icon-left="arrow-left"
|
||||||
@click="activeStep = 'write-revision'">
|
@click="showStep('write-revision')">
|
||||||
Back
|
Back
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button type="is-primary"
|
<b-button type="is-primary"
|
||||||
icon-pack="fas"
|
icon-pack="fas"
|
||||||
icon-left="check"
|
icon-left="check"
|
||||||
@click="activeStep = 'upgrade-db'">
|
@click="showStep('upgrade-db')">
|
||||||
Revision script looks good!
|
Revision script looks good!
|
||||||
</b-button>
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -553,7 +577,7 @@
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<b-button icon-pack="fas"
|
<b-button icon-pack="fas"
|
||||||
icon-left="arrow-left"
|
icon-left="arrow-left"
|
||||||
@click="activeStep = 'review-revision'">
|
@click="showStep('review-revision')">
|
||||||
Back
|
Back
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button type="is-primary"
|
<b-button type="is-primary"
|
||||||
|
@ -627,13 +651,13 @@
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<b-button icon-pack="fas"
|
<b-button icon-pack="fas"
|
||||||
icon-left="arrow-left"
|
icon-left="arrow-left"
|
||||||
@click="activeStep = 'upgrade-db'">
|
@click="showStep('upgrade-db')">
|
||||||
Back
|
Back
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button type="is-primary"
|
<b-button type="is-primary"
|
||||||
icon-pack="fas"
|
icon-pack="fas"
|
||||||
icon-left="check"
|
icon-left="check"
|
||||||
@click="activeStep = 'commit-code'"
|
@click="showStep('commit-code')"
|
||||||
:disabled="!tableCheckAttempted || tableCheckProblem">
|
:disabled="!tableCheckAttempted || tableCheckProblem">
|
||||||
DB looks good!
|
DB looks good!
|
||||||
</b-button>
|
</b-button>
|
||||||
|
@ -658,7 +682,7 @@
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<b-button icon-pack="fas"
|
<b-button icon-pack="fas"
|
||||||
icon-left="arrow-left"
|
icon-left="arrow-left"
|
||||||
@click="activeStep = 'review-db'">
|
@click="showStep('review-db')">
|
||||||
Back
|
Back
|
||||||
</b-button>
|
</b-button>
|
||||||
<once-button type="is-primary"
|
<once-button type="is-primary"
|
||||||
|
@ -675,6 +699,9 @@
|
||||||
${parent.modify_this_page_vars()}
|
${parent.modify_this_page_vars()}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
// nb. for warning user they may lose changes if leaving page
|
||||||
|
ThisPageData.dirty = false
|
||||||
|
|
||||||
ThisPageData.activeStep = null
|
ThisPageData.activeStep = null
|
||||||
ThisPageData.alembicBranchOptions = ${json.dumps(branch_name_options)|n}
|
ThisPageData.alembicBranchOptions = ${json.dumps(branch_name_options)|n}
|
||||||
|
|
||||||
|
@ -713,6 +740,15 @@
|
||||||
ThisPageData.editingColumnVersioned = true
|
ThisPageData.editingColumnVersioned = true
|
||||||
ThisPageData.editingColumnRelationship = null
|
ThisPageData.editingColumnRelationship = null
|
||||||
|
|
||||||
|
ThisPage.methods.showStep = function(step) {
|
||||||
|
this.activeStep = step
|
||||||
|
|
||||||
|
// scroll so top of page is shown
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs['showme'].scrollIntoView(true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
ThisPage.methods.tableAddColumn = function() {
|
ThisPage.methods.tableAddColumn = function() {
|
||||||
this.editingColumn = null
|
this.editingColumn = null
|
||||||
this.editingColumnName = null
|
this.editingColumnName = null
|
||||||
|
@ -801,12 +837,14 @@
|
||||||
column.versioned = this.editingColumnVersioned
|
column.versioned = this.editingColumnVersioned
|
||||||
column.relationship = this.editingColumnRelationship
|
column.relationship = this.editingColumnRelationship
|
||||||
|
|
||||||
|
this.dirty = true
|
||||||
this.editingColumnShowDialog = false
|
this.editingColumnShowDialog = false
|
||||||
}
|
}
|
||||||
|
|
||||||
ThisPage.methods.tableDeleteColumn = function(index) {
|
ThisPage.methods.tableDeleteColumn = function(index) {
|
||||||
if (confirm("Really delete this column?")) {
|
if (confirm("Really delete this column?")) {
|
||||||
this.tableColumns.splice(index, 1)
|
this.tableColumns.splice(index, 1)
|
||||||
|
this.dirty = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -929,6 +967,20 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cf. https://stackoverflow.com/a/56551646
|
||||||
|
ThisPage.methods.beforeWindowUnload = function(e) {
|
||||||
|
|
||||||
|
// warn user if navigating away would lose changes
|
||||||
|
if (this.dirty) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.returnValue = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThisPage.created = function() {
|
||||||
|
window.addEventListener('beforeunload', this.beforeWindowUnload)
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
12
tailbone/templates/tables/index.mako
Normal file
12
tailbone/templates/tables/index.mako
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
## -*- coding: utf-8; -*-
|
||||||
|
<%inherit file="/master/index.mako" />
|
||||||
|
|
||||||
|
<%def name="context_menu_items()">
|
||||||
|
${parent.context_menu_items()}
|
||||||
|
% if master.has_perm('migrations'):
|
||||||
|
<li>${h.link_to("View / Apply Migrations", url('{}.migrations'.format(route_prefix)))}</li>
|
||||||
|
% endif
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
|
${parent.body()}
|
11
tailbone/templates/tables/migrations.mako
Normal file
11
tailbone/templates/tables/migrations.mako
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
## -*- coding: utf-8; -*-
|
||||||
|
<%inherit file="/page.mako" />
|
||||||
|
|
||||||
|
<%def name="title()">Schema Migrations</%def>
|
||||||
|
|
||||||
|
<%def name="render_this_page()">
|
||||||
|
<h3 class="is-size-3">TODO: show current revisions and allow DB upgrades</h3>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
|
${parent.body()}
|
|
@ -194,6 +194,8 @@ class TableView(MasterView):
|
||||||
app = self.get_rattail_app()
|
app = self.get_rattail_app()
|
||||||
model = self.model
|
model = self.model
|
||||||
|
|
||||||
|
kwargs['alembic_current_head'] = self.db_handler.check_alembic_current_head()
|
||||||
|
|
||||||
kwargs['branch_name_options'] = self.db_handler.get_alembic_branch_names()
|
kwargs['branch_name_options'] = self.db_handler.get_alembic_branch_names()
|
||||||
|
|
||||||
branch_name = app.get_table_prefix()
|
branch_name = app.get_table_prefix()
|
||||||
|
@ -331,6 +333,11 @@ class TableView(MasterView):
|
||||||
|
|
||||||
return HTML.tag('span', title=text, c="{} ...".format(text[:max_length]))
|
return HTML.tag('span', title=text, c="{} ...".format(text[:max_length]))
|
||||||
|
|
||||||
|
def migrations(self):
|
||||||
|
# TODO: allow alembic upgrade on POST
|
||||||
|
# TODO: pass current revisions to page context
|
||||||
|
return self.render_to_response('migrations', {})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def defaults(cls, config):
|
def defaults(cls, config):
|
||||||
rattail_config = config.registry.settings.get('rattail_config')
|
rattail_config = config.registry.settings.get('rattail_config')
|
||||||
|
@ -348,6 +355,17 @@ class TableView(MasterView):
|
||||||
url_prefix = cls.get_url_prefix()
|
url_prefix = cls.get_url_prefix()
|
||||||
permission_prefix = cls.get_permission_prefix()
|
permission_prefix = cls.get_permission_prefix()
|
||||||
|
|
||||||
|
# migrations
|
||||||
|
config.add_tailbone_permission(permission_prefix,
|
||||||
|
'{}.migrations'.format(permission_prefix),
|
||||||
|
"View / apply Alembic migrations")
|
||||||
|
config.add_route('{}.migrations'.format(route_prefix),
|
||||||
|
'{}/migrations'.format(url_prefix))
|
||||||
|
config.add_view(cls, attr='migrations',
|
||||||
|
route_name='{}.migrations'.format(route_prefix),
|
||||||
|
renderer='json',
|
||||||
|
permission='{}.migrations'.format(permission_prefix))
|
||||||
|
|
||||||
if cls.creatable:
|
if cls.creatable:
|
||||||
|
|
||||||
# write model class to file
|
# write model class to file
|
||||||
|
|
Loading…
Reference in a new issue