mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-11 08:04:09 -08:00
f16ce09a7a
* If a user id is provided in the name column of an import, we should assume that it is a user id and check out to it. * Fix build of vue files. The location is public/js/build, not public/build * Ensure a status type is set before allowing submission of an import. Also expand the status text label to change color based on success/failure. Fixes #4658 * Use right key to lookup emails when importing users. Fixes 4619. * Import serial for components, and make unique matches based on the serial as well as the name. Fixes #4569 * Set the location_id when importing an item properly. This moves as well to using the Asset::checkout() method, which should consolidate the logic into a useful spot. Fixes #4563 (I think) * Production assets. * Case insensitive field map guessing and repopulate when changingin import type.
248 lines
10 KiB
Vue
248 lines
10 KiB
Vue
<style>
|
|
tr {
|
|
padding-left:30px;
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
<tr v-show="processDetail">
|
|
<td colspan="3">
|
|
<h4 class="modal-title">Import File:</h4>
|
|
<div class="dynamic-form-row">
|
|
<div class="col-md-4 col-xs-12">
|
|
<label for="import-type">Import Type:</label>
|
|
</div>
|
|
<div class="col-md-4 col-xs-12">
|
|
<select2 :options="options.importTypes" v-model="options.importType" required>
|
|
<option disabled value="0"></option>
|
|
</select2>
|
|
</div>
|
|
</div>
|
|
<div class="dynamic-form-row">
|
|
<div class="col-md-4 col-xs-12">
|
|
<label for="import-update">Update Existing Values?:</label>
|
|
</div>
|
|
<div class="col-md-4 col-xs-12">
|
|
<input type="checkbox" name="import-update" v-model="options.update">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-12" style="padding-top: 30px;">
|
|
<table class="table">
|
|
<thead>
|
|
<th>Header Field</th>
|
|
<th>Import Field</th>
|
|
<th>Sample Value</th>
|
|
</thead>
|
|
<tbody>
|
|
<template v-for="(header, index) in file.header_row">
|
|
<tr>
|
|
<td>
|
|
<label :for="header" class="controllabel">{{ header }}</label>
|
|
</td>
|
|
<td>
|
|
<div required>
|
|
<select2 :options="columns" v-model="columnMappings[header]">
|
|
<option value="0">Do Not Import</option>
|
|
</select2>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div>{{ activeFile.first_row[index] }}</div>
|
|
</td>
|
|
</tr>
|
|
</template>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</td>
|
|
|
|
<td>
|
|
<button type="button" class="btn btn-sm btn-default" @click="processDetail = false">Cancel</button>
|
|
<button type="submit" class="btn btn-sm btn-primary" @click="postSave">Import</button>
|
|
<div
|
|
class="alert col-md-5 col-md-offset-1"
|
|
:class="alertClass"
|
|
style="text-align:left"
|
|
v-if="statusText"
|
|
>
|
|
{{ this.statusText }}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
props: ['file', 'customFields'],
|
|
data() {
|
|
return {
|
|
activeFile: this.file,
|
|
processDetail: false,
|
|
statusText: null,
|
|
statusType: null,
|
|
options: {
|
|
importType: this.file.import_type,
|
|
update: false,
|
|
importTypes: [
|
|
{ id: 'asset', text: 'Assets' },
|
|
{ id: 'accessory', text: 'Accessories' },
|
|
{ id: 'consumable', text: 'Consumables' },
|
|
{ id: 'component', text: 'Components' },
|
|
{ id: 'license', text: 'Licenses' },
|
|
{ id: 'user', text: 'Users' }
|
|
],
|
|
statusText: null,
|
|
},
|
|
columnOptions: {
|
|
general: [
|
|
{id: 'category', text: 'Category' },
|
|
{id: 'company', text: 'Company' },
|
|
{id: 'checkout_to', text: 'Checked out to' },
|
|
{id: 'email', text: 'Email' },
|
|
{id: 'first_name', text: 'First Name' },
|
|
{id: 'item_name', text: 'Item Name' },
|
|
{id: 'last_name', text: 'Last Name' },
|
|
{id: 'location', text: 'Location' },
|
|
{id: 'maintained', text: 'Maintained' },
|
|
{id: 'manufacturer', text: 'Manufacturer' },
|
|
{id: 'notes', text: 'Notes' },
|
|
{id: 'order_number', text: 'Order Number' },
|
|
{id: 'purchase_cost', text: 'Purchase Cost' },
|
|
{id: 'purchase_date', text: 'Purchase Date' },
|
|
{id: 'quantity', text: 'Quantity' },
|
|
{id: 'requestable', text: 'Requestable' },
|
|
{id: 'serial', text: 'Serial Number' },
|
|
{id: 'supplier', text: 'Supplier' },
|
|
{id: 'username', text: 'Username' },
|
|
],
|
|
assets: [
|
|
{id: 'asset_tag', text: 'Asset Tag' },
|
|
{id: 'asset_model', text: 'Model Name' },
|
|
{id: 'image', text: 'Image Filename' },
|
|
{id: 'model_number', text: 'Model Number' },
|
|
{id: 'name', text: 'Full Name' },
|
|
{id: 'status', text: 'Status' },
|
|
{id: 'warranty_months', text: 'Warranty Months' },
|
|
],
|
|
licenses: [
|
|
{id: 'expiration_date', text: 'Expiration Date' },
|
|
{id: 'license_email', text: 'Licensed To Email' },
|
|
{id: 'license_name', text: 'Licensed To Name' },
|
|
{id: 'purchase_order', text: 'Purchase Order' },
|
|
{id: 'reassignable', text: 'Reassignable' },
|
|
{id: 'seats', text: 'Seats' },
|
|
],
|
|
users: [
|
|
{id: 'employee_num', text: 'Employee Number' },
|
|
{id: 'jobtitle', text: 'Job Title' },
|
|
{id: 'phone_number', text: 'Phone Number' },
|
|
],
|
|
customFields: this.customFields,
|
|
},
|
|
columnMappings: this.file.field_map || {},
|
|
activeColumn: null,
|
|
}
|
|
},
|
|
created() {
|
|
window.eventHub.$on('showDetails', this.toggleExtendedDisplay)
|
|
this.populateSelect2ActiveItems();
|
|
},
|
|
computed: {
|
|
columns() {
|
|
switch(this.options.importType) {
|
|
case 'asset':
|
|
return this.columnOptions.general.concat(this.columnOptions.assets).concat(this.columnOptions.customFields);
|
|
case 'license':
|
|
return this.columnOptions.general.concat(this.columnOptions.licenses);
|
|
case 'user':
|
|
return this.columnOptions.general.concat(this.columnOptions.users);
|
|
}
|
|
return this.columnOptions.general;
|
|
},
|
|
alertClass() {
|
|
if(this.statusType=='success') {
|
|
return 'alert-success';
|
|
}
|
|
if(this.statusType=='error') {
|
|
return 'alert-danger';
|
|
}
|
|
return 'alert-info';
|
|
},
|
|
},
|
|
watch: {
|
|
columns() {
|
|
console.log("CHANGED");
|
|
this.populateSelect2ActiveItems();
|
|
}
|
|
},
|
|
methods: {
|
|
postSave() {
|
|
console.log('saving');
|
|
console.log(this.options.importType);
|
|
if(!this.options.importType) {
|
|
this.statusType='error';
|
|
this.statusText= "An import type is required... ";
|
|
return;
|
|
}
|
|
this.statusType='pending';
|
|
this.statusText = "Processing...";
|
|
this.$http.post(route('api.imports.importFile', this.file.id), {
|
|
'import-update': this.options.update,
|
|
'import-type': this.options.importType,
|
|
'column-mappings': this.columnMappings
|
|
}).then( ({body}) => {
|
|
// Success
|
|
this.statusType="success";
|
|
this.statusText = "Success... Redirecting.";
|
|
window.location.href = body.messages.redirect_url;
|
|
}, ({body}) => {
|
|
// Failure
|
|
if(body.status == 'import-errors') {
|
|
window.eventHub.$emit('importErrors', body.messages);
|
|
this.statusType='error';
|
|
this.statusText = "Error";
|
|
} else {
|
|
this.$emit('alert', {
|
|
message: body.messages,
|
|
type: "danger",
|
|
visible: true,
|
|
})
|
|
}
|
|
this.displayImportModal=false;
|
|
});
|
|
},
|
|
populateSelect2ActiveItems() {
|
|
if(this.file.field_map == null) {
|
|
// Begin by populating the active selection in dropdowns with blank values.
|
|
for (var i=0; i < this.file.header_row.length; i++) {
|
|
this.$set(this.columnMappings, this.file.header_row[i], null);
|
|
}
|
|
// Then, for any values that have a likely match, we make that active.
|
|
for(var j=0; j < this.columns.length; j++) {
|
|
let column = this.columns[j];
|
|
let lower = this.file.header_row.map((value) => value.toLowerCase());
|
|
console.dir(lower);
|
|
let index = lower.indexOf(column.text.toLowerCase())
|
|
if(index != -1) {
|
|
this.$set(this.columnMappings, this.file.header_row[index], column.id)
|
|
}
|
|
}
|
|
}
|
|
},
|
|
toggleExtendedDisplay(fileId) {
|
|
if(fileId == this.file.id) {
|
|
this.processDetail = !this.processDetail
|
|
}
|
|
},
|
|
updateModel(header, value) {
|
|
console.log(header, value);
|
|
this.columnMappings[header] = value;
|
|
}
|
|
},
|
|
components: {
|
|
select2: require('../select2.vue')
|
|
}
|
|
}
|
|
</script>
|