## -*- coding: utf-8; -*-
## ##############################################################################
## 
## Default master 'index' template.  Features a prominent data table and
## exposes a way to filter and sort the data, etc.  Some index pages also
## include a "tools" section, just above the grid on the right.
## 
## ##############################################################################
<%inherit file="/page.mako" />

<%def name="title()">${index_title}</%def>

<%def name="content_title()"></%def>

<%def name="grid_tools()">

  ## grid totals
  % if master.supports_grid_totals:
      <div style="display: flex; align-items: center;">
        <b-button v-if="gridTotalsDisplay == null"
                  :disabled="gridTotalsFetching"
                  @click="gridTotalsFetch()">
          {{ gridTotalsFetching ? "Working, please wait..." : "Show Totals" }}
        </b-button>
        <div v-if="gridTotalsDisplay != null"
             class="control">
          Totals: {{ gridTotalsDisplay }}
        </div>
      </div>
  % endif

  ## download search results
  % if master.results_downloadable and master.has_perm('download_results'):
      <div>
        <b-button type="is-primary"
                  icon-pack="fas"
                  icon-left="download"
                  @click="showDownloadResultsDialog = true"
                  :disabled="!total">
          Download Results
        </b-button>

        ${h.form(url('{}.download_results'.format(route_prefix)), ref='download_results_form')}
        ${h.csrf_token(request)}
        <input type="hidden" name="fmt" :value="downloadResultsFormat" />
        <input type="hidden" name="fields" :value="downloadResultsFieldsIncluded" />
        ${h.end_form()}

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

            <div class="card-content">
              <p>
                There are
                <span class="is-size-4 has-text-weight-bold">
                  {{ total.toLocaleString('en') }} ${model_title_plural}
                </span>
                matching your current filters.
              </p>
              <p>
                You may download this set as a single data file if you like.
              </p>
              <br />

              <b-notification type="is-warning" :closable="false"
                              v-if="downloadResultsFormat == 'xlsx' && total >= 1000">
                Excel downloads for large data sets can take a long time to
                generate, and bog down the server in the meantime.  You are
                encouraged to choose CSV for a large data set, even though
                the end result (file size) may be larger with CSV.
              </b-notification>

              <div style="display: flex; justify-content: space-between">

                <div>
                  <b-field label="Format">
                    <b-select v-model="downloadResultsFormat">
                      % for key, label in master.download_results_supported_formats().items():
                      <option value="${key}">${label}</option>
                      % endfor
                    </b-select>
                  </b-field>
                </div>

                <div>

                  <div v-show="downloadResultsFieldsMode != 'choose'"
                       class="has-text-right">
                    <p v-if="downloadResultsFieldsMode == 'default'">
                      Will use DEFAULT fields.
                    </p>
                    <p v-if="downloadResultsFieldsMode == 'all'">
                      Will use ALL fields.
                    </p>
                    <br />
                  </div>

                  <div class="buttons is-right">
                    <b-button type="is-primary"
                              v-show="downloadResultsFieldsMode != 'default'"
                              @click="downloadResultsUseDefaultFields()">
                      Use Default Fields
                    </b-button>
                    <b-button type="is-primary"
                              v-show="downloadResultsFieldsMode != 'all'"
                              @click="downloadResultsUseAllFields()">
                      Use All Fields
                    </b-button>
                    <b-button type="is-primary"
                              v-show="downloadResultsFieldsMode != 'choose'"
                              @click="downloadResultsFieldsMode = 'choose'">
                      Choose Fields
                    </b-button>
                  </div>

                  <div v-show="downloadResultsFieldsMode == 'choose'">
                    <div style="display: flex;">
                      <div>
                        <b-field label="Excluded Fields">
                          <b-select multiple native-size="8"
                                    expanded
                                    v-model="downloadResultsExcludedFieldsSelected"
                                    ref="downloadResultsExcludedFields">
                            <option v-for="field in downloadResultsFieldsExcluded"
                                    :key="field"
                                    :value="field">
                              {{ field }}
                            </option>
                          </b-select>
                        </b-field>
                      </div>
                      <div>
                        <br /><br />
                        <b-button style="margin: 0.5rem;"
                                  @click="downloadResultsExcludeFields()">
                          &lt;
                        </b-button>
                        <br />
                        <b-button style="margin: 0.5rem;"
                                  @click="downloadResultsIncludeFields()">
                          &gt;
                        </b-button>
                      </div>
                      <div>
                        <b-field label="Included Fields">
                          <b-select multiple native-size="8"
                                    expanded
                                    v-model="downloadResultsIncludedFieldsSelected"
                                    ref="downloadResultsIncludedFields">
                            <option v-for="field in downloadResultsFieldsIncluded"
                                    :key="field"
                                    :value="field">
                              {{ field }}
                            </option>
                          </b-select>
                        </b-field>
                      </div>
                    </div>
                  </div>

                </div>
              </div>
            </div> <!-- card-content -->

            <footer class="modal-card-foot">
              <b-button @click="showDownloadResultsDialog = false">
                Cancel
              </b-button>
              <once-button type="is-primary"
                           @click="downloadResultsSubmit()"
                           icon-pack="fas"
                           icon-left="download"
                           :disabled="!downloadResultsFieldsIncluded.length"
                           text="Download Results">
              </once-button>
            </footer>
          </div>
        </b-modal>
      </div>
  % endif

  ## download rows for search results
  % if master.has_rows and master.results_rows_downloadable and master.has_perm('download_results_rows'):
      <b-button type="is-primary"
                icon-pack="fas"
                icon-left="download"
                @click="downloadResultsRows()"
                :disabled="downloadResultsRowsButtonDisabled">
        {{ downloadResultsRowsButtonText }}
      </b-button>
      ${h.form(url('{}.download_results_rows'.format(route_prefix)), ref='downloadResultsRowsForm')}
      ${h.csrf_token(request)}
      ${h.end_form()}
  % endif

  ## merge 2 objects
  % if master.mergeable and request.has_perm('{}.merge'.format(permission_prefix)):

      ${h.form(url('{}.merge'.format(route_prefix)), class_='control', **{'@submit': 'submitMergeForm'})}
      ${h.csrf_token(request)}
      <input type="hidden"
             name="uuids"
             :value="checkedRowUUIDs()" />
      <b-button type="is-primary"
                native-type="submit"
                icon-pack="fas"
                icon-left="object-ungroup"
                :disabled="mergeFormSubmitting || checkedRows.length != 2">
        {{ mergeFormButtonText }}
      </b-button>
      ${h.end_form()}
  % endif

  ## enable / disable selected objects
  % if master.supports_set_enabled_toggle and master.has_perm('enable_disable_set'):

      ${h.form(url('{}.enable_set'.format(route_prefix)), class_='control', ref='enable_selected_form')}
      ${h.csrf_token(request)}
      ${h.hidden('uuids', v_model='selected_uuids')}
      <b-button :disabled="enableSelectedDisabled"
                @click="enableSelectedSubmit()">
        {{ enableSelectedText }}
      </b-button>
      ${h.end_form()}

      ${h.form(url('{}.disable_set'.format(route_prefix)), ref='disable_selected_form', class_='control')}
      ${h.csrf_token(request)}
      ${h.hidden('uuids', v_model='selected_uuids')}
      <b-button :disabled="disableSelectedDisabled"
                @click="disableSelectedSubmit()">
        {{ disableSelectedText }}
      </b-button>
      ${h.end_form()}
  % endif

  ## delete selected objects
  % if master.set_deletable and master.has_perm('delete_set'):
      ${h.form(url('{}.delete_set'.format(route_prefix)), ref='delete_selected_form', class_='control')}
      ${h.csrf_token(request)}
      ${h.hidden('uuids', v_model='selected_uuids')}
      <b-button type="is-danger"
                :disabled="deleteSelectedDisabled"
                @click="deleteSelectedSubmit()"
                icon-pack="fas"
                icon-left="trash">
        {{ deleteSelectedText }}
      </b-button>
      ${h.end_form()}
  % endif

  ## delete search results
  % if master.bulk_deletable and request.has_perm('{}.bulk_delete'.format(permission_prefix)):
      ${h.form(url('{}.bulk_delete'.format(route_prefix)), ref='delete_results_form', class_='control')}
      ${h.csrf_token(request)}
      <b-button type="is-danger"
                :disabled="deleteResultsDisabled"
                :title="total ? null : 'There are no results to delete'"
                @click="deleteResultsSubmit()"
                icon-pack="fas"
                icon-left="trash">
        {{ deleteResultsText }}
      </b-button>
      ${h.end_form()}
  % endif

</%def>

<%def name="page_content()">

  % if download_results_path:
      <b-notification type="is-info">
        Your download should start automatically, or you can
        ${h.link_to("click here", '{}?filename={}'.format(url('{}.download_results'.format(route_prefix)), h.os.path.basename(download_results_path)))}
      </b-notification>
  % endif

  % if download_results_rows_path:
      <b-notification type="is-info">
        Your download should start automatically, or you can
        ${h.link_to("click here", '{}?filename={}'.format(url('{}.download_results_rows'.format(route_prefix)), h.os.path.basename(download_results_rows_path)))}
      </b-notification>
  % endif

  ${self.render_grid_component()}

  % if master.deletable and request.has_perm('{}.delete'.format(permission_prefix)) and master.delete_confirm == 'simple':
      ${h.form('#', ref='deleteObjectForm')}
      ${h.csrf_token(request)}
      ${h.end_form()}
  % endif
</%def>

<%def name="make_grid_component()">
  ## TODO: stop using |n filter?
  ${grid.render_complete(tools=capture(self.grid_tools).strip(), context_menu=capture(self.context_menu_items).strip())|n}
</%def>

<%def name="render_grid_component()">
  <${grid.component} ref="grid" :csrftoken="csrftoken"
     % if master.deletable and request.has_perm('{}.delete'.format(permission_prefix)) and master.delete_confirm == 'simple':
     @deleteActionClicked="deleteObject"
     % endif
     >
  </${grid.component}>
</%def>

<%def name="make_this_page_component()">

  ## define grid
  ${self.make_grid_component()}

  ${parent.make_this_page_component()}

  ## finalize grid
  <script>

    ${grid.component_studly}.data = () => { return ${grid.component_studly}Data }
    Vue.component('${grid.component}', ${grid.component_studly})

  </script>
</%def>

<%def name="render_this_page()">
  ${self.page_content()}
</%def>

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

    % if master.supports_grid_totals:
        ${grid.component_studly}Data.gridTotalsDisplay = null
        ${grid.component_studly}Data.gridTotalsFetching = false

        ${grid.component_studly}.methods.gridTotalsFetch = function() {
            this.gridTotalsFetching = true

            let url = '${url(f'{route_prefix}.fetch_grid_totals')}'
            this.simpleGET(url, {}, response => {
                this.gridTotalsDisplay = response.data.totals_display
                this.gridTotalsFetching = false
            }, response => {
                this.gridTotalsFetching = false
            })
        }

        ${grid.component_studly}.methods.appliedFiltersHook = function() {
            this.gridTotalsDisplay = null
            this.gridTotalsFetching = false
        }
    % endif

    ## maybe auto-redirect to download latest results file
    % if download_results_path:
        ThisPage.methods.downloadResultsRedirect = function() {
            location.href = '${url('{}.download_results'.format(route_prefix))}?filename=${h.os.path.basename(download_results_path)}';
        }
        ThisPage.mounted = function() {
            // we give this 1 second before attempting the redirect; otherwise
            // the FontAwesome icons do not seem to load properly.  so this way
            // the page should fully render before redirecting
            window.setTimeout(this.downloadResultsRedirect, 1000)
        }
    % endif

    ## maybe auto-redirect to download latest "rows for results" file
    % if download_results_rows_path:
        ThisPage.methods.downloadResultsRowsRedirect = function() {
            location.href = '${url('{}.download_results_rows'.format(route_prefix))}?filename=${h.os.path.basename(download_results_rows_path)}';
        }
        ThisPage.mounted = function() {
            // we give this 1 second before attempting the redirect; otherwise
            // the FontAwesome icons do not seem to load properly.  so this way
            // the page should fully render before redirecting
            window.setTimeout(this.downloadResultsRowsRedirect, 1000)
        }
    % endif

    % if request.session.pop('{}.results_csv.generated'.format(route_prefix), False):
        ThisPage.mounted = function() {
            location.href = '${url('{}.results_csv_download'.format(route_prefix))}';
        }
    % endif
    % if request.session.pop('{}.results_xlsx.generated'.format(route_prefix), False):
        ThisPage.mounted = function() {
            location.href = '${url('{}.results_xlsx_download'.format(route_prefix))}';
        }
    % endif

    ## delete single object
    % if master.deletable and master.has_perm('delete') and master.delete_confirm == 'simple':
        ThisPage.methods.deleteObject = function(url) {
            if (confirm("Are you sure you wish to delete this ${model_title}?")) {
                let form = this.$refs.deleteObjectForm
                form.action = url
                form.submit()
            }
        }
    % endif

    ## download results
    % if master.results_downloadable and master.has_perm('download_results'):

        ${grid.component_studly}Data.downloadResultsFormat = '${master.download_results_default_format()}'
        ${grid.component_studly}Data.showDownloadResultsDialog = false
        ${grid.component_studly}Data.downloadResultsFieldsMode = 'default'
        ${grid.component_studly}Data.downloadResultsFieldsAvailable = ${json.dumps(download_results_fields_available)|n}
        ${grid.component_studly}Data.downloadResultsFieldsDefault = ${json.dumps(download_results_fields_default)|n}
        ${grid.component_studly}Data.downloadResultsFieldsIncluded = ${json.dumps(download_results_fields_default)|n}

        ${grid.component_studly}Data.downloadResultsExcludedFieldsSelected = []
        ${grid.component_studly}Data.downloadResultsIncludedFieldsSelected = []

        ${grid.component_studly}.computed.downloadResultsFieldsExcluded = function() {
            let excluded = []
            this.downloadResultsFieldsAvailable.forEach(field => {
                if (!this.downloadResultsFieldsIncluded.includes(field)) {
                    excluded.push(field)
                }
            }, this)
            return excluded
        }

        ${grid.component_studly}.methods.downloadResultsExcludeFields = function() {
            const selected = Array.from(this.downloadResultsIncludedFieldsSelected)
            if (!selected) {
                return
            }

            selected.forEach(field => {
                let index

                // remove field from selected
                index = this.downloadResultsIncludedFieldsSelected.indexOf(field)
                if (index >= 0) {
                    this.downloadResultsIncludedFieldsSelected.splice(index, 1)
                }

                // remove field from included
                // nb. excluded list will reflect this change too
                index = this.downloadResultsFieldsIncluded.indexOf(field)
                if (index >= 0) {
                    this.downloadResultsFieldsIncluded.splice(index, 1)
                }
            })
        }

        ${grid.component_studly}.methods.downloadResultsIncludeFields = function() {
            const selected = Array.from(this.downloadResultsExcludedFieldsSelected)
            if (!selected) {
                return
            }

            selected.forEach(field => {
                let index

                // remove field from selected
                index = this.downloadResultsExcludedFieldsSelected.indexOf(field)
                if (index >= 0) {
                    this.downloadResultsExcludedFieldsSelected.splice(index, 1)
                }

                // add field to included
                // nb. excluded list will reflect this change too
                this.downloadResultsFieldsIncluded.push(field)
            })
        }

        ${grid.component_studly}.methods.downloadResultsUseDefaultFields = function() {
            this.downloadResultsFieldsIncluded = Array.from(this.downloadResultsFieldsDefault)
            this.downloadResultsFieldsMode = 'default'
        }

        ${grid.component_studly}.methods.downloadResultsUseAllFields = function() {
            this.downloadResultsFieldsIncluded = Array.from(this.downloadResultsFieldsAvailable)
            this.downloadResultsFieldsMode = 'all'
        }

        ${grid.component_studly}.methods.downloadResultsSubmit = function() {
            this.$refs.download_results_form.submit()
        }
    % endif

    ## download rows for results
    % if master.has_rows and master.results_rows_downloadable and master.has_perm('download_results_rows'):

        ${grid.component_studly}Data.downloadResultsRowsButtonDisabled = false
        ${grid.component_studly}Data.downloadResultsRowsButtonText = "Download Rows for Results"

        ${grid.component_studly}.methods.downloadResultsRows = function() {
            if (confirm("This will generate an Excel file which contains "
                        + "not the results themselves, but the *rows* for "
                        + "each.\n\nAre you sure you want this?")) {
                this.downloadResultsRowsButtonDisabled = true
                this.downloadResultsRowsButtonText = "Working, please wait..."
                this.$refs.downloadResultsRowsForm.submit()
            }
        }
    % endif

    ## enable / disable selected objects
    % if master.supports_set_enabled_toggle and master.has_perm('enable_disable_set'):

        ${grid.component_studly}Data.enableSelectedSubmitting = false
        ${grid.component_studly}Data.enableSelectedText = "Enable Selected"

        ${grid.component_studly}.computed.enableSelectedDisabled = function() {
            if (this.enableSelectedSubmitting) {
                return true
            }
            if (!this.checkedRowUUIDs().length) {
                return true
            }
            return false
        }

        ${grid.component_studly}.methods.enableSelectedSubmit = function() {
            let uuids = this.checkedRowUUIDs()
            if (!uuids.length) {
                alert("You must first select one or more objects to disable.")
                return
            }
            if (! confirm("Are you sure you wish to ENABLE the " + uuids.length + " selected objects?")) {
                return
            }

            this.enableSelectedSubmitting = true
            this.enableSelectedText = "Working, please wait..."
            this.$refs.enable_selected_form.submit()
        }

        ${grid.component_studly}Data.disableSelectedSubmitting = false
        ${grid.component_studly}Data.disableSelectedText = "Disable Selected"

        ${grid.component_studly}.computed.disableSelectedDisabled = function() {
            if (this.disableSelectedSubmitting) {
                return true
            }
            if (!this.checkedRowUUIDs().length) {
                return true
            }
            return false
        }

        ${grid.component_studly}.methods.disableSelectedSubmit = function() {
            let uuids = this.checkedRowUUIDs()
            if (!uuids.length) {
                alert("You must first select one or more objects to disable.")
                return
            }
            if (! confirm("Are you sure you wish to DISABLE the " + uuids.length + " selected objects?")) {
                return
            }

            this.disableSelectedSubmitting = true
            this.disableSelectedText = "Working, please wait..."
            this.$refs.disable_selected_form.submit()
        }

    % endif

    ## delete selected objects
    % if master.set_deletable and master.has_perm('delete_set'):

        ${grid.component_studly}Data.deleteSelectedSubmitting = false
        ${grid.component_studly}Data.deleteSelectedText = "Delete Selected"

        ${grid.component_studly}.computed.deleteSelectedDisabled = function() {
            if (this.deleteSelectedSubmitting) {
                return true
            }
            if (!this.checkedRowUUIDs().length) {
                return true
            }
            return false
        }

        ${grid.component_studly}.methods.deleteSelectedSubmit = function() {
            let uuids = this.checkedRowUUIDs()
            if (!uuids.length) {
                alert("You must first select one or more objects to disable.")
                return
            }
            if (! confirm("Are you sure you wish to DELETE the " + uuids.length + " selected objects?")) {
                return
            }

            this.deleteSelectedSubmitting = true
            this.deleteSelectedText = "Working, please wait..."
            this.$refs.delete_selected_form.submit()
        }
    % endif

    % if master.bulk_deletable and master.has_perm('bulk_delete'):

        ${grid.component_studly}Data.deleteResultsSubmitting = false
        ${grid.component_studly}Data.deleteResultsText = "Delete Results"

        ${grid.component_studly}.computed.deleteResultsDisabled = function() {
            if (this.deleteResultsSubmitting) {
                return true
            }
            if (!this.total) {
                return true
            }
            return false
        }

        ${grid.component_studly}.methods.deleteResultsSubmit = function() {
            // TODO: show "plural model title" here?
            if (!confirm("You are about to delete " + this.total.toLocaleString('en') + " objects.\n\nAre you sure?")) {
                return
            }

            this.deleteResultsSubmitting = true
            this.deleteResultsText = "Working, please wait..."
            this.$refs.delete_results_form.submit()
        }

    % endif

    % if master.mergeable and master.has_perm('merge'):

        ${grid.component_studly}Data.mergeFormButtonText = "Merge 2 ${model_title_plural}"
        ${grid.component_studly}Data.mergeFormSubmitting = false

        ${grid.component_studly}.methods.submitMergeForm = function() {
            this.mergeFormSubmitting = true
            this.mergeFormButtonText = "Working, please wait..."
        }
    % endif
  </script>
</%def>


${parent.body()}
