Sheet

Sheet input is the component that allows you to import large amounts of excel data and add it to the database in cli mode. To save the imported data, it should be used with a sheet saving template that you have created yourself.

To see more detailed examples of the components, check out our demo application on the homepage.

Upload Screen

The following image shows the file uploading stage.

Form

Import Screen

The following image shows the next step after the file is uploaded.

Form

Template

<template>
    <va-list 
        disable-create
        :filters="filters"
        :fields="fields"
        :items-per-page="50"
    >
        <va-data-table-server
            row-edit
            row-create
            disable-edit
            disable-create
            disable-clone
            disable-show
            :disable-empty-data-row-create="true"
        >
            <template v-slot:row.actions="{ item }">
                <v-btn
                    :item="item"
                    :label="$t('va.actions.show')"
                    :color="'blue'"
                    variant="text"
                    exact
                    @click.stop="getRoute(item)"
                >
                    <v-icon size="small">mdi-eye</v-icon>
                </v-btn>
            </template>
        </va-data-table-server>
 </va-list>
 <v-card
        class="mx-auto mt-2"
        variant="flat"
    >
        <template v-slot:title>
            {{ $t("resources.jobtitles.createNewList") }}
        </template>
        <v-card-text>
            <div>
                {{ $t("resources.jobtitles.importDescription") }}
            </div>
        </v-card-text>
        <v-card-actions>
            <v-btn 
                color="primary"
                @click="downloadEmptyXls()">
                {{ $t("resources.jobtitles.downloadXls") }}
            </v-btn>
        </v-card-actions>
    </v-card>
    <v-card
        variant="flat"
        class="mt-2"
    >
        <v-card-text>
            <v-row class="mt-2">
                <v-col sm="2">
                    <va-select-input
                        v-model="yearId"
                        reference="years"
                        variant="outlined"
                        clearable
                        :disabled="loadingStatus"
                        :error-messages="yearIdErrors"
                    ></va-select-input>        
                </v-col>
                <v-col sm="2">
                    <va-text-input
                        v-model="listName"
                        variant="outlined"
                        clearable
                        :disabled="loadingStatus"
                        :error-messages="listNameErrors"
                    ></va-text-input>        
                </v-col>
                <v-col sm="8">
                    <v-btn
                        v-if="loadingStatus"
                        color="primary"
                        class="mr-2"
                        @click="cancelSaveList()"
                        variant="outlined"
                    >
                        {{ $t("va.actions.cancel") }}
                    </v-btn>
                    <v-btn 
                        :loading="loadingStatus"
                        color="primary"
                        variant="outlined" 
                        @click="saveList()">
                        {{ $t("resources.jobtitles.saveList") }}
                    </v-btn>
                </v-col>
            </v-row>
        </v-card-text>
    </v-card>
    <v-card
        variant="flat"
        class="mt-2"
        v-if="!loadingStatus"
    >
        <v-card-text>
        <h5 class="h4 mb-3">Sheet Input Component</h5>
        <va-sheet-input
            icon="mdi-file-excel"
            items-per-page="100"
            upload-url="/jobtitlelists/upload"
            preview-url="/jobtitlelists/preview"
            remove-url="/jobtitlelists/remove"
            @importedItems="onItems"
        >
        </va-sheet-input>
        </v-card-text>
    </v-card>
</template>

Script

<script>
import { useVuelidate } from "@vuelidate/core";
import { required } from "@vuelidate/validators";
import { provide } from 'vue';
import { mapActions } from "vuex"

export default {
  props: [],
  inject: ['admin'],
  setup() {
    provide('v$', useVuelidate() )
    return { v$: useVuelidate() }
  },
  provide() {
    return {
      validations: {
        form: {
          listName: {
            required
          },
        }
      },
      errors: {
        listNameErrors: (v$) => {
          const errors = [];
          if (!v$['form'].listName.$dirty) return errors;
          v$['form'].listName.required.$invalid &&
            errors.push(this.$t("v.text.required"));
          return errors;
        },
      }
    };
  },
  validations() {
    return {
      yearId: {
        required
      },   
      listName: {
        required
      }
    }
  },
  data() {
    return {
    cancel: false,
    status: false,
    loadingStatus: false,
    listId: null,
    listName: null,
    companyId: null,
    yearId: new Date().getFullYear(),
    loading: false,
    loadingList: false,
    importData: [],
    validationError: null,
      filters: [
        {
          source: "yearId",
          type: "selectfilter",
          attributes: {
            optionText: "name",
            multiple: true,
            reference: "years",
          }
        },
      ],
      fields: [
        {
          source: "yearId",
          type: "select",
          attributes: {
            reference: "years",
          },
          sortable: true,
        },
        {
          source: "listName",
          sortable: true,
        },
      ],
    }
  },
  computed: {
    yearIdErrors() {
      const errors = [];
      if (!this.v$.yearId.$dirty) return errors;
      this.v$.yearId.required.$invalid &&
        errors.push(this.$t("v.text.required"));
      return errors;
    },
    listNameErrors() {
      const errors = [];
      if (!this.v$.listName.$dirty) return errors;
      this.v$.listName.required.$invalid &&
        errors.push(this.$t("v.text.required"));
      return errors;
    }
  },
  methods: {
    ...mapActions({
      checkAuth: "auth/checkAuth",
    }),
    onItems(items, vError) {
        this.importData = items;
        if (items.length == 0) {
            this.validationError = null
        } else {
            this.validationError = vError
        }
    },
    getRoute(item) {
        let filter = null
        if (item.listId) {
            filter = '{ "yearId" : ["'+ item.yearId.id + '"] , "listId" : ["' + item.listId + '"] }';
        }
            this.$router.push({ name: "jobtitles_list", query: { filter: filter } });
    },
    async importStatus() {
        let Self = this;
      this.loadingStatus = true;
      try {
        //
        // get status with EventSource
        // 
        let user = await this.checkAuth();
        if (user) {
          const apiUrl = import.meta.env.VITE_API_URL;
          this.source = new EventSource(apiUrl + '/stream/events?userId=' + user.id + '&route=list');
          this.source.onmessage = function(e) {
            if (e.data) {
              let data = JSON.parse(e.data);
              if (data.status == 1 || data.status == true) {
                Self.source.close(); // lets close it when the process is done !
                Self.status = false;
                Self.loadingStatus = false
                Self.importData = []; // reset import data
                Self.admin.http({ method: "DELETE", url: "/jobtitlelists/reset" }); // reset all status
                Self.$store.dispatch("api/refresh", 'jobtitlelists');
              }
            }
          };
        }
      } catch (e) {
        if (e["response"]
          && e["response"]["status"]
          && e.response.status === 400) {
          this.admin.message("error", e.response.data.data.error);
        }
      }
    },
    saveList() {
      this.cancel = false;
      this.v$.yearId.$touch();
      this.v$.listName.$touch();
      if (this.v$.listName.$invalid || this.v$.yearId.$invalid) {
        return false;
      }
      if (this.validationError) {
        this.$store.commit("messages/show", { type: 'error', message: this.$t("employees.fixErrorsMessage") });
      } else {
        if (this.importData.length == 0) {
            this.$store.commit("messages/show", { type: 'error', message: this.$t("employees.importDataMessage") });
        } else {
            // save imported data
            // 
            this.admin.http({ method: "POST", url: "/jobtitlelists/import", data: { yearId: this.yearId, listName: this.listName } });
                    // check status every 1 seconds
                    // 
            this.importStatus();
        }
      }
    },
    cancelSaveList() {
      this.cancel = true;
      this.loadingStatus = false;
      this.importData = []; // reset import data
      this.admin.http({ method: "DELETE", url: "/jobtitlelists/reset" }); // reset all status
      this.$store.dispatch("api/refresh", 'jobtitlelists'); // refresh page
    },
    downloadEmptyXls() {
        window.location.href = "/src/assets/JobTitles.xlsx"
    }
  }
}
</script>

Mixins

  • InputWrapper

Properties

Property Type Description Default
itemsPerPage number, string Number of items to be displayed per page. 100
icon string Sets the excel upload icon. null
iconSize string Sets the excel upload icon width. x-large
uploadUrl string Sets the backend api upload url. null
previewUrl string Sets the backend api preview url. null
removeUrl string Sets the backend api remove url. null