## -*- coding: utf-8; -*-
<%inherit file="/master/create.mako" />

<%def name="extra_styles()">
  ${parent.extra_styles()}
  <style type="text/css">
    .label {
        white-space: nowrap;
    }
  </style>
</%def>

<%def name="render_this_page()">
  <b-steps v-model="activeStep"
           :animated="false"
           rounded
           :has-navigation="false"
           vertical
           icon-pack="fas">

    <b-step-item step="1"
                 value="enter-details"
                 label="Enter Details"
                 clickable>
      <h3 class="is-size-3 block">
        Enter Details
      </h3>

      <b-field label="Schema Branch"
               message="Leave this set to your custom app branch, unless you know what you're doing.">
        <b-select v-model="alembicBranch">
          <option v-for="branch in alembicBranchOptions"
                  :key="branch"
                  :value="branch">
            {{ branch }}
          </option>
        </b-select>
      </b-field>

      <b-field grouped>

        <b-field label="Table Name"
                 message="Should be singular in nature, i.e. 'widget' not 'widgets'">
          <b-input v-model="tableName">
          </b-input>
        </b-field>

        <b-field label="Model/Class Name"
                 message="Should be singular in nature, i.e. 'Widget' not 'Widgets'">
          <b-input v-model="tableModelName">
          </b-input>
        </b-field>

      </b-field>

      <b-field grouped>

        <b-field label="Model Title"
                 message="Human-friendly singular model title.">
          <b-input v-model="tableModelTitle">
          </b-input>
        </b-field>

        <b-field label="Model Title Plural"
                 message="Human-friendly plural model title.">
          <b-input v-model="tableModelTitlePlural">
          </b-input>
        </b-field>

      </b-field>

      <b-field label="Description"
               message="Brief description of what a record in this table represents.">
        <b-input v-model="tableDescription">
        </b-input>
      </b-field>

      <b-field>
        <b-checkbox v-model="tableVersioned">
          Record version data for this table
        </b-checkbox>
      </b-field>

      <br />

      <div class="level-left">
        <div class="level-item">
          <h4 class="block is-size-4">Columns</h4>
        </div>
        <div class="level-item">
          <b-button type="is-primary"
                    icon-pack="fas"
                    icon-left="plus"
                    @click="tableAddColumn()">
            New
          </b-button>
        </div>
      </div>

      <b-table
        :data="tableColumns">
        % if buefy_0_8:
        <template slot-scope="props">
          % endif

          <b-table-column field="name"
                          label="Name"
                          % if not buefy_0_8:
                          v-slot="props"
                          % endif
                          >
            {{ props.row.name }}
          </b-table-column>

          <b-table-column field="data_type"
                          label="Data Type"
                          % if not buefy_0_8:
                          v-slot="props"
                          % endif
                          >
            {{ props.row.data_type }}
          </b-table-column>

          <b-table-column field="nullable"
                          label="Nullable"
                          % if not buefy_0_8:
                          v-slot="props"
                          % endif
                          >
            {{ props.row.nullable ? "Yes" : "No" }}
          </b-table-column>

          <b-table-column field="versioned"
                          label="Versioned"
                          :visible="tableVersioned"
                          % if not buefy_0_8:
                          v-slot="props"
                          % endif
                          >
            {{ props.row.versioned ? "Yes" : "No" }}
          </b-table-column>

          <b-table-column field="description"
                          label="Description"
                          % if not buefy_0_8:
                          v-slot="props"
                          % endif
                          >
            {{ props.row.description }}
          </b-table-column>

          <b-table-column field="actions"
                          label="Actions"
                          % if not buefy_0_8:
                          v-slot="props"
                          % endif
                          >
            <a v-if="props.row.name != 'uuid'"
               href="#"
               @click.prevent="tableEditColumn(props.row)">
              <i class="fas fa-edit"></i>
              Edit
            </a>
            &nbsp;

            <a v-if="props.row.name != 'uuid'"
               href="#"
               class="has-text-danger"
               @click.prevent="tableDeleteColumn(props.index)">
              <i class="fas fa-trash"></i>
              Delete
            </a>
            &nbsp;
          </b-table-column>

          % if buefy_0_8:
        </template>
        % endif
      </b-table>

      <b-modal has-modal-card
               :active.sync="editingColumnShowDialog">
        <div class="modal-card">

          <header class="modal-card-head">
            <p class="modal-card-title">
              {{ (editingColumn && editingColumn.name) ? "Edit" : "New" }} Column
            </p>
          </header>

          <section class="modal-card-body">

            <b-field label="Name">
              <b-input v-model="editingColumnName"
                       ref="editingColumnName">
              </b-input>
            </b-field>

            <b-field label="Data Type">
              <b-input v-model="editingColumnDataType"></b-input>
            </b-field>

            <b-field grouped>

            <b-field label="Nullable">
              <b-checkbox v-model="editingColumnNullable"
                          native-value="true">
                {{ editingColumnNullable }}
              </b-checkbox>
            </b-field>

            <b-field label="Versioned"
                     v-if="tableVersioned">
              <b-checkbox v-model="editingColumnVersioned"
                          native-value="true">
                {{ editingColumnVersioned }}
              </b-checkbox>
            </b-field>

            </b-field>

            <b-field label="Description">
              <b-input v-model="editingColumnDescription"></b-input>
            </b-field>

          </section>

          <footer class="modal-card-foot">
            <b-button @click="editingColumnShowDialog = false">
              Cancel
            </b-button>
            <b-button type="is-primary"
                      icon-pack="fas"
                      icon-left="save"
                      @click="editingColumnSave()">
              Save
            </b-button>
          </footer>
        </div>
      </b-modal>

      <br />

      <div class="buttons">
        <b-button type="is-primary"
                  icon-pack="fas"
                  icon-left="check"
                  @click="activeStep = 'write-model'">
          Details are complete
        </b-button>
      </div>

    </b-step-item>

    <b-step-item step="2"
                 value="write-model"
                 label="Write Model">
      <h3 class="is-size-3 block">
        Write Model
      </h3>

      <b-field label="Schema Branch" horizontal>
        {{ alembicBranch }}
      </b-field>

      <b-field label="Table Name" horizontal>
        {{ tableName }}
      </b-field>

      <b-field label="Model Class" horizontal>
        {{ tableModelName }}
      </b-field>

      <b-field horizontal label="File">
        <b-input v-model="tableModelFile"></b-input>
      </b-field>

      <b-field horizontal>
        <b-checkbox v-model="tableModelFileOverwrite">
          Overwrite file if it exists
        </b-checkbox>
      </b-field>

      <div class="form">
        <div class="buttons">
          <b-button icon-pack="fas"
                    icon-left="arrow-left"
                    @click="activeStep = 'enter-details'">
            Back
          </b-button>
          <b-button type="is-primary"
                    icon-pack="fas"
                    icon-left="save"
                    @click="writeModelFile()"
                    :disabled="writingModelFile">
            {{ writingModelFile ? "Working, please wait..." : "Write model class to file" }}
          </b-button>
          <b-button icon-pack="fas"
                    icon-left="arrow-right"
                    @click="activeStep = 'review-model'">
            Skip
          </b-button>
        </div>
      </div>
    </b-step-item>

    <b-step-item step="3"
                 value="review-model"
                 label="Review Model"
                 clickable>
      <h3 class="is-size-3 block">
        Review Model
      </h3>

      <p class="block">
        Model code was generated to file:
      </p>

      <p class="block is-family-code" style="padding-left: 3rem;">
        {{ tableModelFile }}
      </p>

      <p class="block">
        First, review that code and adjust to your liking.
      </p>

      <p class="block">
        Next be sure to import the new model.  Typically this is done
        by editing the file...
      </p>

      <p class="block is-family-code" style="padding-left: 3rem;">
        ${model_dir}__init__.py
      </p>

      <p class="block">
        ...and adding a line such as:
      </p>

      <p class="block is-family-code" style="padding-left: 3rem;">
        from .{{ tableModelFileModuleName }} import {{ tableModelName }}
      </p>

      <p class="block">
        Once you&apos;ve done all that, the web app must be restarted.
        This may happen automatically depending on your setup.
        Test the model import status below.
      </p>

      <div class="card block">
        <header class="card-header">
          <p class="card-header-title">
            Model Import Status
          </p>
        </header>
        <div class="card-content">
          <div class="content">
            <div class="level">
              <div class="level-left">

                <div class="level-item">
                  <span v-if="!modelImported && !modelImportProblem">
                    import not yet attempted
                  </span>
                  <span v-if="modelImported"
                        class="has-text-success has-text-weight-bold">
                    imported okay
                  </span>
                  <span v-if="modelImportProblem"
                        class="has-text-danger">
                    import failed: {{ modelImportStatus }}
                  </span>
                </div>
              </div>
              <div class="level-right">
                <div class="level-item">
                  <b-field horizontal label="Model Class">
                    <b-input v-model="modelImportName"></b-input>
                  </b-field>
                </div>
                <div class="level-item">
                  <b-button type="is-primary"
                            icon-pack="fas"
                            icon-left="redo"
                            @click="modelImportTest()">
                    Refresh / Test Import
                  </b-button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="buttons">
        <b-button icon-pack="fas"
                  icon-left="arrow-left"
                  @click="activeStep = 'write-model'">
          Back
        </b-button>
        <b-button type="is-primary"
                  icon-pack="fas"
                  icon-left="check"
                  @click="activeStep = 'write-revision'"
                  :disabled="!modelImported">
          Model class looks good!
        </b-button>
        <b-button icon-pack="fas"
                  icon-left="arrow-right"
                  @click="activeStep = 'write-revision'">
          Skip
        </b-button>
      </div>
    </b-step-item>

    <b-step-item step="4"
                 value="write-revision"
                 label="Write Revision"
                 clickable>
      <h3 class="is-size-3 block">
        Write Revision
      </h3>
      <p class="block">
        You said the model class looked good, so next we will generate
        a revision script, used to modify DB schema.
      </p>

      <b-field label="Schema Branch"
               message="Leave this set to your custom app branch, unless you know what you're doing.">
        <b-select v-model="alembicBranch">
          <option v-for="branch in alembicBranchOptions"
                  :key="branch"
                  :value="branch">
            {{ branch }}
          </option>
        </b-select>
      </b-field>

      <b-field label="Message"
               message="Human-friendly brief description of the changes">
        <b-input v-model="revisionMessage"></b-input>
      </b-field>

      <br />

      <div class="buttons">
        <b-button icon-pack="fas"
                  icon-left="arrow-left"
                  @click="activeStep = 'review-model'">
          Back
        </b-button>
        <b-button type="is-primary"
                  icon-pack="fas"
                  icon-left="save"
                  @click="writeRevisionScript()"
                  :disabled="writingRevisionScript">
          {{ writingRevisionScript ? "Working, please wait..." : "Generate revision script" }}
        </b-button>
        <b-button icon-pack="fas"
                  icon-left="arrow-right"
                  @click="activeStep = 'review-revision'">
          Skip
        </b-button>
      </div>
    </b-step-item>

    <b-step-item step="5"
                 value="review-revision"
                 label="Review Revision">
      <h3 class="is-size-3 block">
        Review Revision
      </h3>

      <p class="block">
        Revision script was generated to file:
      </p>

      <p class="block is-family-code" style="padding-left: 3rem;">
        {{ revisionScript }}
      </p>

      <p class="block">
        Please review that code and adjust to your liking.
      </p>

      <div class="buttons">
        <b-button icon-pack="fas"
                  icon-left="arrow-left"
                  @click="activeStep = 'write-revision'">
          Back
        </b-button>
        <b-button type="is-primary"
                  icon-pack="fas"
                  icon-left="check"
                  @click="activeStep = 'upgrade-db'">
          Revision script looks good!
        </b-button>
      </div>
    </b-step-item>

    <b-step-item step="6"
                 value="upgrade-db"
                 label="Upgrade DB"
                 clickable>
      <h3 class="is-size-3 block">
        Upgrade DB
      </h3>
      <p class="block">
        You said the revision script looked good, so next we will use
        it to upgrade your actual database.
      </p>

      <div class="buttons">
        <b-button icon-pack="fas"
                  icon-left="arrow-left"
                  @click="activeStep = 'review-revision'">
          Back
        </b-button>
        <b-button type="is-primary"
                  icon-pack="fas"
                  icon-left="arrow-up"
                  @click="upgradeDB()"
                  :disabled="upgradingDB">
          {{ upgradingDB ? "Working, please wait..." : "Upgrade database" }}
        </b-button>
      </div>
    </b-step-item>

    <b-step-item step="7"
                 value="review-db"
                 label="Review DB"
                 clickable>
      <h3 class="is-size-3 block">
        Review DB
      </h3>

      <p class="block">
        At this point your new table should be present in the DB.
        Test below.
      </p>

      <div class="card block">
        <header class="card-header">
          <p class="card-header-title">
            Table Status
          </p>
        </header>
        <div class="card-content">
          <div class="content">
            <div class="level">
              <div class="level-left">

                <div class="level-item">
                  <span v-if="!tableCheckAttempted">
                    check not yet attempted
                  </span>
                  <span v-if="tableCheckAttempted && !tableCheckProblem"
                        class="has-text-success has-text-weight-bold">
                    table exists!
                  </span>
                  <span v-if="tableCheckProblem"
                        class="has-text-danger">
                    {{ tableCheckProblem }}
                  </span>
                </div>
              </div>
              <div class="level-right">
                <div class="level-item">
                  <b-field horizontal label="Table Name">
                    <b-input v-model="tableName"></b-input>
                  </b-field>
                </div>
                <div class="level-item">
                  <b-button type="is-primary"
                            icon-pack="fas"
                            icon-left="redo"
                            @click="tableCheck()">
                    Test for Table
                  </b-button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="buttons">
        <b-button icon-pack="fas"
                  icon-left="arrow-left"
                  @click="activeStep = 'upgrade-db'">
          Back
        </b-button>
        <b-button type="is-primary"
                  icon-pack="fas"
                  icon-left="check"
                  @click="activeStep = 'commit-code'"
                  :disabled="!tableCheckAttempted || tableCheckProblem">
          DB looks good!
        </b-button>
      </div>
    </b-step-item>

    <b-step-item step="8"
                 value="commit-code"
                 label="Commit Code">
      <h3 class="is-size-3 block">
        Commit Code
      </h3>

      <p class="block">
        Hope you're having a great day.
      </p>

      <p class="block">
        Don't forget to commit code changes to your source repo.
      </p>

      <div class="buttons">
        <b-button icon-pack="fas"
                  icon-left="arrow-left"
                  @click="activeStep = 'review-db'">
          Back
        </b-button>
        <once-button type="is-primary"
                     tag="a" :href="tableURL"
                     icon-left="arrow-right"
                     :text="`Show me my new table: ${'$'}{tableName}`">
        </once-button>
      </div>
    </b-step-item>
  </b-steps>
</%def>

<%def name="modify_this_page_vars()">
  ${parent.modify_this_page_vars()}
  <script type="text/javascript">

    ThisPageData.activeStep = null
    ThisPageData.alembicBranchOptions = ${json.dumps(branch_name_options)|n}

    ThisPageData.alembicBranch = ${json.dumps(branch_name)|n}
    ThisPageData.tableName = '${rattail_app.get_table_prefix()}_widget'
    ThisPageData.tableModelName = '${rattail_app.get_class_prefix()}Widget'
    ThisPageData.tableModelTitle = 'Widget'
    ThisPageData.tableModelTitlePlural = 'Widgets'
    ThisPageData.tableDescription = "Represents a cool widget."
    ThisPageData.tableVersioned = true

    ThisPageData.tableColumns = [{
        name: 'uuid',
        data_type: 'String(length=32)',
        nullable: false,
        description: "UUID primary key",
        versioned: true,
    }]

    ThisPageData.editingColumnShowDialog = false
    ThisPageData.editingColumn = null
    ThisPageData.editingColumnName = null
    ThisPageData.editingColumnDataType = null
    ThisPageData.editingColumnNullable = true
    ThisPageData.editingColumnDescription = null
    ThisPageData.editingColumnVersioned = true

    ThisPage.methods.tableAddColumn = function() {
        this.editingColumn = null
        this.editingColumnName = null
        this.editingColumnDataType = null
        this.editingColumnNullable = true
        this.editingColumnDescription = null
        this.editingColumnVersioned = true
        this.editingColumnShowDialog = true
        this.$nextTick(() => {
            this.$refs.editingColumnName.focus()
        })
    }

    ThisPage.methods.tableEditColumn = function(column) {
        this.editingColumn = column
        this.editingColumnName = column.name
        this.editingColumnDataType = column.data_type
        this.editingColumnNullable = column.nullable
        this.editingColumnDescription = column.description
        this.editingColumnVersioned = column.versioned
        this.editingColumnShowDialog = true
        this.$nextTick(() => {
            this.$refs.editingColumnName.focus()
        })
    }

    ThisPage.methods.editingColumnSave = function() {
        let column
        if (this.editingColumn) {
            column = this.editingColumn
        } else {
            column = {}
            this.tableColumns.push(column)
        }

        column.name = this.editingColumnName
        column.data_type = this.editingColumnDataType
        column.nullable = this.editingColumnNullable
        column.description = this.editingColumnDescription
        column.versioned = this.editingColumnVersioned

        this.editingColumnShowDialog = false
    }

    ThisPage.methods.tableDeleteColumn = function(index) {
        if (confirm("Really delete this column?")) {
            this.tableColumns.splice(index, 1)
        }
    }

    ThisPageData.tableModelFile = '${model_dir}widget.py'
    ThisPageData.tableModelFileOverwrite = false
    ThisPageData.writingModelFile = false

    ThisPage.methods.writeModelFile = function() {
        this.writingModelFile = true

        this.modelImportName = this.tableModelName
        this.modelImported = false
        this.modelImportStatus = "import not yet attempted"
        this.modelImportProblem = false

        let url = '${url('{}.write_model_file'.format(route_prefix))}'
        let params = {
            branch_name: this.alembicBranch,
            table_name: this.tableName,
            model_name: this.tableModelName,
            model_title: this.tableModelTitle,
            model_title_plural: this.tableModelTitlePlural,
            description: this.tableDescription,
            versioned: this.tableVersioned,
            columns: this.tableColumns,
            module_file: this.tableModelFile,
            overwrite: this.tableModelFileOverwrite,
        }
        this.submitForm(url, params, response => {
            this.writingModelFile = false
            this.activeStep = 'review-model'
        }, response => {
            this.writingModelFile = false
        })
    }

    ThisPageData.modelImportName = '${rattail_app.get_class_prefix()}Widget'
    ThisPageData.modelImportStatus = "import not yet attempted"
    ThisPageData.modelImported = false
    ThisPageData.modelImportProblem = false

    ThisPage.computed.tableModelFileModuleName = function() {
        let path = this.tableModelFile
        path = path.replace(/^.*\//, '')
        path = path.replace(/\.py$/, '')
        return path
    }

    ThisPage.methods.modelImportTest = function() {
        let url = '${url('{}.check_model'.format(route_prefix))}'
        let params = {model_name: this.modelImportName}
        this.submitForm(url, params, response => {
            if (response.data.problem) {
                this.modelImportProblem = true
                this.modelImported = false
                this.modelImportStatus = response.data.problem
            } else {
                this.modelImportProblem = false
                this.modelImported = true
                this.revisionMessage = `add table for ${'$'}{this.tableModelTitlePlural}`
            }
        })
    }

    ThisPageData.writingRevisionScript = false
    ThisPageData.revisionMessage = null
    ThisPageData.revisionScript = null

    ThisPage.methods.writeRevisionScript = function() {
        this.writingRevisionScript = true

        let url = '${url('{}.write_revision_script'.format(route_prefix))}'
        let params = {
            branch: this.alembicBranch,
            message: this.revisionMessage,
        }
        this.submitForm(url, params, response => {
            this.writingRevisionScript = false
            this.revisionScript = response.data.script
            this.activeStep = 'review-revision'
        }, response => {
            this.writingRevisionScript = false
        })
    }

    ThisPageData.upgradingDB = false

    ThisPage.methods.upgradeDB = function() {
        this.upgradingDB = true

        let url = '${url('{}.upgrade_db'.format(route_prefix))}'
        let params = {}
        this.submitForm(url, params, response => {
            this.upgradingDB = false
            this.activeStep = 'review-db'
        }, response => {
            this.upgradingDB = false
        })
    }

    ThisPageData.tableCheckAttempted = false
    ThisPageData.tableCheckProblem = null

    ThisPageData.tableURL = null

    ThisPage.methods.tableCheck = function() {
        let url = '${url('{}.check_table'.format(route_prefix))}'
        let params = {table_name: this.tableName}
        this.submitForm(url, params, response => {
            if (response.data.problem) {
                this.tableCheckProblem = response.data.problem
            } else {
                this.tableURL = response.data.url
            }
            this.tableCheckAttempted = true
        })
    }

  </script>
</%def>


${parent.body()}
