Radu Liviu Carjan
3 years ago
32 changed files with 27613 additions and 7011 deletions
-
113app/Http/Controllers/FileController.php
-
21app/Http/Controllers/FilterController.php
-
10app/Http/Controllers/HomeController.php
-
24app/Http/Controllers/PagesController.php
-
183package-lock.json
-
2package.json
-
BINpublic/fonts/vendor/primevue/resources/themes/mdc-dark-indigo/roboto-v20-latin-ext_latin-500.woff
-
BINpublic/fonts/vendor/primevue/resources/themes/mdc-dark-indigo/roboto-v20-latin-ext_latin-500.woff2
-
BINpublic/fonts/vendor/primevue/resources/themes/mdc-dark-indigo/roboto-v20-latin-ext_latin-700.woff
-
BINpublic/fonts/vendor/primevue/resources/themes/mdc-dark-indigo/roboto-v20-latin-ext_latin-700.woff2
-
BINpublic/fonts/vendor/primevue/resources/themes/mdc-dark-indigo/roboto-v20-latin-ext_latin-regular.woff
-
BINpublic/fonts/vendor/primevue/resources/themes/mdc-dark-indigo/roboto-v20-latin-ext_latin-regular.woff2
-
33522public/js/app.js
-
33resources/js/app.ts
-
100resources/js/components/Home.vue
-
42resources/js/components/Home/Home.ts
-
35resources/js/components/Home/Home.vue
-
84resources/js/components/ProcessFile.vue
-
11resources/js/components/ProcessFile/ProcessFile.scss
-
121resources/js/components/ProcessFile/ProcessFile.ts
-
111resources/js/components/ProcessFile/ProcessFile.vue
-
69resources/js/components/helpers/Filter.vue
-
7resources/js/interfaces/FilterInterface.ts
-
4resources/js/interfaces/FilterOptions.ts
-
18resources/js/plugins/ApiPlugin.ts
-
7resources/js/plugins/plugins.d.ts
-
60resources/js/services/ApiService.ts
-
1resources/sass/app.scss
-
2resources/views/pages/home.blade.php
-
2routes/api.php
-
5routes/web.php
-
7webpack.mix.js
@ -1,24 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Http\Controllers; |
|
||||
|
|
||||
use Illuminate\View\View; |
|
||||
use Illuminate\Contracts\View\Factory; |
|
||||
use Illuminate\Contracts\Container\BindingResolutionException; |
|
||||
|
|
||||
class PagesController extends Controller |
|
||||
{ |
|
||||
|
|
||||
/** |
|
||||
* Return the home page view |
|
||||
* |
|
||||
* @return View|Factory |
|
||||
* |
|
||||
* @throws BindingResolutionException |
|
||||
*/ |
|
||||
public function home(): View |
|
||||
{ |
|
||||
$filters = FilterController::$filters; |
|
||||
return view('pages.home')->with('filters', $filters); |
|
||||
} |
|
||||
} |
|
33522
public/js/app.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,100 +0,0 @@ |
|||||
<template> |
|
||||
<div class="wrap" v-if="!fileUploaded && !uploading"> |
|
||||
<Toast position="top-right" /> |
|
||||
|
|
||||
<Panel header="Please upload a file"> |
|
||||
<FileUpload |
|
||||
name="demo[]" |
|
||||
:customUpload="true" |
|
||||
:auto="true" |
|
||||
@uploader="uploadFile" |
|
||||
> |
|
||||
<template #empty> |
|
||||
<p>Drag and drop files to here to upload.</p> |
|
||||
</template> |
|
||||
</FileUpload> |
|
||||
</Panel> |
|
||||
|
|
||||
<BlockUI :blocked="uiBlocked" :fullScreen="true"></BlockUI> |
|
||||
</div> |
|
||||
<div class="wrap" v-else-if="!fileUploaded && uploading"> |
|
||||
<Skeleton /> |
|
||||
<Skeleton /> |
|
||||
<Skeleton /> |
|
||||
<Skeleton /> |
|
||||
<Skeleton /> |
|
||||
<Skeleton /> |
|
||||
<Skeleton /> |
|
||||
</div> |
|
||||
<div class="wrap" v-else> |
|
||||
<process-file :file="uploadResult" :filters="filters"></process-file> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script lang="ts"> |
|
||||
import axios from 'axios'; |
|
||||
// import Vue from 'vue'; |
|
||||
// import Component from 'vue-class-component'; |
|
||||
import { Vue, Component, Prop } from 'vue-property-decorator'; |
|
||||
|
|
||||
@Component |
|
||||
export default class Home extends Vue { |
|
||||
|
|
||||
@Prop({ default: [] }) |
|
||||
public readonly filters!: Array<object> |
|
||||
|
|
||||
public uiBlocked = false; |
|
||||
public uploading = false; |
|
||||
public fileUploaded: boolean = false; |
|
||||
public uploadResult = null; |
|
||||
|
|
||||
/** |
|
||||
* |
|
||||
*/ |
|
||||
public created() |
|
||||
{ |
|
||||
console.log(this.filters); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* A method which uploads the files to the server for processing |
|
||||
* |
|
||||
* @param event The event containing the uploaded files information |
|
||||
*/ |
|
||||
public uploadFile(event: any): void { |
|
||||
this.uploading = true; |
|
||||
this.fileUploaded = false; |
|
||||
|
|
||||
|
|
||||
this['$toast'].add({severity:'success', summary: 'Success Message', detail:'Order submitted', life: 3000}); |
|
||||
let file = event.files[0]; |
|
||||
|
|
||||
let formData = new FormData(); |
|
||||
formData.append('file', file); |
|
||||
|
|
||||
setTimeout( |
|
||||
() => { |
|
||||
axios.post( |
|
||||
'http://core.sandd/api/file', |
|
||||
formData, |
|
||||
{ |
|
||||
headers: { |
|
||||
'Content-Type': 'multipart/form-data' |
|
||||
} |
|
||||
} |
|
||||
).then( |
|
||||
(response) => { |
|
||||
this.fileUploaded = true; |
|
||||
this.uploadResult = response.data; |
|
||||
// console.log('Success: ', response); |
|
||||
} |
|
||||
).catch( |
|
||||
(err) => { |
|
||||
console.log('Error: ', err); |
|
||||
} |
|
||||
); |
|
||||
}, 500 |
|
||||
) |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
@ -0,0 +1,42 @@ |
|||||
|
import axios from 'axios'; |
||||
|
import { Vue, Component, Prop } from 'vue-property-decorator'; |
||||
|
|
||||
|
@Component |
||||
|
export default class Home extends Vue { |
||||
|
|
||||
|
@Prop({ default: [] }) |
||||
|
public readonly searchers!: { [key: string]: string; } |
||||
|
|
||||
|
public uiBlocked = false; |
||||
|
public uploading = false; |
||||
|
public fileUploaded: boolean = false; |
||||
|
public uploadResult = null; |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
*/ |
||||
|
public created() |
||||
|
{} |
||||
|
|
||||
|
/** |
||||
|
* A method which uploads the files to the server for processing |
||||
|
* |
||||
|
* @param event The event containing the uploaded files information |
||||
|
*/ |
||||
|
public uploadFile(event: any): void { |
||||
|
this.uploading = true; |
||||
|
this.fileUploaded = false; |
||||
|
|
||||
|
|
||||
|
this.$toast.add({severity:'success', summary: 'Success Message', detail:'Order submitted', life: 3000}); |
||||
|
let file = event.files[0]; |
||||
|
|
||||
|
setTimeout( |
||||
|
async () => { |
||||
|
let response = await this.$api.uploadFile(file); |
||||
|
this.fileUploaded = true; |
||||
|
this.uploadResult = response; |
||||
|
}, 500 |
||||
|
) |
||||
|
} |
||||
|
} |
@ -0,0 +1,35 @@ |
|||||
|
<template> |
||||
|
<div class="wrap" v-if="!fileUploaded && !uploading"> |
||||
|
<Toast position="top-right" /> |
||||
|
|
||||
|
<Panel header="Please upload a file"> |
||||
|
<FileUpload |
||||
|
name="demo[]" |
||||
|
:customUpload="true" |
||||
|
:auto="true" |
||||
|
@uploader="uploadFile" |
||||
|
> |
||||
|
<template #empty> |
||||
|
<p>Drag and drop files to here to upload.</p> |
||||
|
</template> |
||||
|
</FileUpload> |
||||
|
</Panel> |
||||
|
|
||||
|
<BlockUI :blocked="uiBlocked" :fullScreen="true"></BlockUI> |
||||
|
</div> |
||||
|
<div class="wrap" v-else-if="!fileUploaded && uploading"> |
||||
|
<Skeleton /> |
||||
|
<Skeleton /> |
||||
|
<Skeleton /> |
||||
|
<Skeleton /> |
||||
|
<Skeleton /> |
||||
|
<Skeleton /> |
||||
|
<Skeleton /> |
||||
|
</div> |
||||
|
<div class="wrap" v-else> |
||||
|
<process-file :file="uploadResult" :searchers="searchers"></process-file> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" src="./Home.ts"> |
||||
|
</script> |
@ -1,84 +0,0 @@ |
|||||
<template> |
|
||||
|
|
||||
<div class="p-d-flex p-flex-row p-jc-between p-ai-stretch"> |
|
||||
<Panel |
|
||||
class="p-mr-2 p-as-stretch file-card" |
|
||||
> |
|
||||
<template #header> |
|
||||
File preview |
|
||||
</template> |
|
||||
|
|
||||
<Skeleton /><br /> |
|
||||
<Skeleton /><br /> |
|
||||
<Skeleton /><br /> |
|
||||
<Skeleton /><br /> |
|
||||
<Skeleton /><br /> |
|
||||
<Skeleton /><br /> |
|
||||
<Skeleton /><br /> |
|
||||
</Panel> |
|
||||
|
|
||||
<Card class="p-mr-2 p-as-stretch filters-card"> |
|
||||
<template #header> |
|
||||
<Toolbar> |
|
||||
<template #left> |
|
||||
<h3>Available filters</h3> |
|
||||
</template> |
|
||||
<template #right> |
|
||||
<Button |
|
||||
icon="pi pi-plus" |
|
||||
class="p-button-success" |
|
||||
/> |
|
||||
</template> |
|
||||
</Toolbar> |
|
||||
</template> |
|
||||
|
|
||||
<template #content> |
|
||||
<filter-view |
|
||||
v-for="(filter, id, index) in filters" |
|
||||
:key="index" |
|
||||
:id="id" |
|
||||
:display-name="filter.display_name" |
|
||||
:options="filter.options" |
|
||||
></filter-view> |
|
||||
</template> |
|
||||
</Card> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script lang="ts"> |
|
||||
import axios from 'axios'; |
|
||||
import { Vue, Component, Prop } from 'vue-property-decorator'; |
|
||||
import { FileData } from '../interfaces/FileData'; |
|
||||
import { FilterInterface } from '../interfaces/FilterInterface'; |
|
||||
|
|
||||
@Component |
|
||||
export default class ProcessFile extends Vue { |
|
||||
|
|
||||
@Prop({ default: null }) |
|
||||
public readonly file!: FileData|null; |
|
||||
|
|
||||
@Prop({ default: [] }) |
|
||||
public readonly filters!: { [keys:string]: FilterInterface } |
|
||||
|
|
||||
private selectedFile: File|null = null; |
|
||||
private selectedFilters = []; |
|
||||
|
|
||||
/** |
|
||||
* |
|
||||
*/ |
|
||||
created() { |
|
||||
console.log('FILE: ', this.file); |
|
||||
console.log('FILTERS: ', this.filters); |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss"> |
|
||||
.file-card { |
|
||||
flex: 0 1 66%; |
|
||||
} |
|
||||
|
|
||||
.filters-card { |
|
||||
flex: 0 1 32% |
|
||||
} |
|
||||
</style> |
|
@ -0,0 +1,11 @@ |
|||||
|
.file-card { |
||||
|
flex: 0 1 74%; |
||||
|
} |
||||
|
|
||||
|
.filters-card { |
||||
|
flex: 0 1 24% |
||||
|
} |
||||
|
.p-overlaypanel { |
||||
|
// width: 450px; |
||||
|
min-width: 300px; |
||||
|
} |
@ -0,0 +1,121 @@ |
|||||
|
import axios from 'axios'; |
||||
|
// import OverlayPanel from 'primevue/overlaypanel/OverlayPanel';
|
||||
|
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'; |
||||
|
import { FileData } from '@interfaces/FileData'; |
||||
|
|
||||
|
@Component |
||||
|
export default class ProcessFile extends Vue { |
||||
|
|
||||
|
/** |
||||
|
* Props |
||||
|
*/ |
||||
|
// The data for the file we are processing
|
||||
|
@Prop({ default: { id: -1, file: '', path: '' } }) |
||||
|
public readonly file!: FileData; |
||||
|
|
||||
|
// The list of available searchers
|
||||
|
@Prop({ default: [] }) |
||||
|
public readonly searchers!: { [keys: string]: string; } |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Class members |
||||
|
*/ |
||||
|
public $refs!: { |
||||
|
'searchers-overlay': any |
||||
|
} |
||||
|
|
||||
|
// The id of the interval used to query the file status
|
||||
|
private intervalId!: any; |
||||
|
|
||||
|
// The content of the file we are processing
|
||||
|
private fileContent: string = ''; |
||||
|
|
||||
|
// The list of filters/searchers in a format usable by the datatable
|
||||
|
private searchersData: Array<{ id: string; name: string; }> = []; |
||||
|
|
||||
|
// The list of selected filters/searchers
|
||||
|
private selectedSearchers: Array<{ id: string; name: string; }> = []; |
||||
|
|
||||
|
//The list of expanded rows in the selected filters/searchers table
|
||||
|
private expandedRows: Array<{id: string; name: string; }> = []; |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
*/ |
||||
|
created() { |
||||
|
for(let index in this.searchers) { |
||||
|
let searcherData = { |
||||
|
id: index, |
||||
|
name: this.searchers[index] |
||||
|
}; |
||||
|
|
||||
|
this.searchersData.push(searcherData); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
this.intervalId = setInterval(this.waitForFile, 3000); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
*/ |
||||
|
private async waitForFile() { |
||||
|
|
||||
|
const response = await this.$api.getFileData(this.file.id); |
||||
|
|
||||
|
if (response.text !== null && response.ready === true) { |
||||
|
|
||||
|
if (response.ingest_status === 'fail') { |
||||
|
this.$toast.add({ |
||||
|
severity: 'error', |
||||
|
summary: 'File error', |
||||
|
detail: 'THere was an error processing the file in ingest', |
||||
|
life: 3000 |
||||
|
}); |
||||
|
} else { |
||||
|
this.fileContent = response.documentContent; |
||||
|
|
||||
|
this.$toast.add({ |
||||
|
severity:'success', |
||||
|
summary: 'File loaded', |
||||
|
detail: 'The file has been processed by ingest.', |
||||
|
life: 3000 |
||||
|
}); |
||||
|
|
||||
|
clearInterval(this.intervalId); |
||||
|
} |
||||
|
} else { |
||||
|
console.log('FILE NOT READY YET!'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private toggleSearchersMenu($event: any) { |
||||
|
this.$refs['searchers-overlay'].toggle($event); |
||||
|
} |
||||
|
|
||||
|
private onRowSelect($event: any) { |
||||
|
console.log('SELECT: ', $event); |
||||
|
console.log(this.selectedSearchers); |
||||
|
} |
||||
|
|
||||
|
private onRowUnselect($event: any) { |
||||
|
console.log('UNSELECT: ', $event); |
||||
|
console.log(this.selectedSearchers); |
||||
|
} |
||||
|
|
||||
|
private onSelectedSearchersReorder($event: any) |
||||
|
{ |
||||
|
this.selectedSearchers = $event.value; |
||||
|
} |
||||
|
|
||||
|
private onSelectedSearcherExpand($event:any) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
private onSelectedSearcherCollapse($event:any) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,111 @@ |
|||||
|
<template> |
||||
|
|
||||
|
<div class="p-d-flex p-flex-row p-jc-between p-ai-stretch"> |
||||
|
<Toast /> |
||||
|
<Card |
||||
|
class="p-mr-2 p-as-stretch file-card" |
||||
|
> |
||||
|
<template #header> |
||||
|
<Toolbar> |
||||
|
<template #left> |
||||
|
<h3>File preview</h3> |
||||
|
</template> |
||||
|
</Toolbar> |
||||
|
</template> |
||||
|
|
||||
|
<template #content> |
||||
|
<template v-if="fileContent === ''"> |
||||
|
<Skeleton /><br /> |
||||
|
<Skeleton /><br /> |
||||
|
<Skeleton /><br /> |
||||
|
<Skeleton /><br /> |
||||
|
<Skeleton /><br /> |
||||
|
<Skeleton /><br /> |
||||
|
<Skeleton /><br /> |
||||
|
</template> |
||||
|
<template v-else> |
||||
|
<vue-markdown :source="fileContent" /> |
||||
|
</template> |
||||
|
</template> |
||||
|
|
||||
|
</Card> |
||||
|
|
||||
|
<Card class="p-mr-2 p-as-stretch filters-card"> |
||||
|
<template #header> |
||||
|
<Toolbar> |
||||
|
<template #left> |
||||
|
<h3>Document searchers</h3> |
||||
|
</template> |
||||
|
<template #right> |
||||
|
<Button |
||||
|
icon="pi pi-plus" |
||||
|
class="p-button-success p-button-sm p-button-text" |
||||
|
@click="toggleSearchersMenu" |
||||
|
aria:haspopup="true" |
||||
|
aria-controls="overlay_panel" /> |
||||
|
</template> |
||||
|
</Toolbar> |
||||
|
</template> |
||||
|
|
||||
|
<template #content> |
||||
|
<DataTable |
||||
|
:value.sync="selectedSearchers" |
||||
|
dataKey="id" |
||||
|
:expandedRows.sync="expandedRows" |
||||
|
@row-reorder="onSelectedSearchersReorder" |
||||
|
@row-expand="onSelectedSearcherExpand" |
||||
|
@row-collapse="onSelectedSearcherCollapse"> |
||||
|
|
||||
|
<Column :rowReorder="true" headerStyle="width: 3rem" /> |
||||
|
<Column field="name" header="Name" sortable></Column> |
||||
|
<Column :expander="true" headerStyle="width: 3rem" /> |
||||
|
|
||||
|
<template #expansion="slotProps"> |
||||
|
<div class="options-subtable"> |
||||
|
<!-- TODO: Add real options here --> |
||||
|
<h5>Options for {{slotProps.data.name}}</h5> |
||||
|
|
||||
|
<!-- <ProgressSpinner /> --> |
||||
|
|
||||
|
<div class="p-fluid"> |
||||
|
<div class="p-field"> |
||||
|
<label for="firstname">Option 1</label> |
||||
|
<InputText id="firstname" type="text" class="p-inputtext-sm" /> |
||||
|
</div> |
||||
|
<div class="p-field"> |
||||
|
<label for="lastname">Option 2</label> |
||||
|
<InputText id="lastname" type="text" class="p-inputtext-sm" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
</DataTable> |
||||
|
</template> |
||||
|
</Card> |
||||
|
|
||||
|
<OverlayPanel |
||||
|
ref="searchers-overlay" |
||||
|
appendTo="body" |
||||
|
id="overlay_panel" |
||||
|
style="width: 300px"> |
||||
|
|
||||
|
<DataTable |
||||
|
:value.sync="searchersData" |
||||
|
:selection.sync="selectedSearchers" |
||||
|
dataKey="id" |
||||
|
selectionMode="multiple" |
||||
|
class="p-datatable-sm" |
||||
|
:metaKeySelection="false"> |
||||
|
|
||||
|
<Column selectionMode="multiple" headerStyle="width: 3em"></Column> |
||||
|
<Column field="name" header="Name" sortable></Column> |
||||
|
|
||||
|
</DataTable> |
||||
|
</OverlayPanel> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" src="./ProcessFile.ts"></script> |
||||
|
<style lang="scss" src="./ProcessFile.scss"></style> |
@ -1,69 +0,0 @@ |
|||||
<template> |
|
||||
<Fieldset :legend="displayName" :toggleable="true" class="filter-container"> |
|
||||
|
|
||||
<div v-for="option of optionsList" :key="option.name" class="filter-option"> |
|
||||
<h5>{{ option.name }}</h5> |
|
||||
|
|
||||
<SelectButton |
|
||||
:key="option.name" |
|
||||
v-model="selectedOption" |
|
||||
:options="option.list" |
|
||||
optionLabel="name" /> |
|
||||
</div> |
|
||||
</Fieldset> |
|
||||
</template> |
|
||||
|
|
||||
<script lang="ts"> |
|
||||
|
|
||||
import { Vue, Component, Prop } from 'vue-property-decorator'; |
|
||||
import { FilterOptions } from '../../interfaces/FilterOptions'; |
|
||||
|
|
||||
@Component |
|
||||
export default class Filter extends Vue { |
|
||||
|
|
||||
@Prop(String) |
|
||||
public readonly id!: string; |
|
||||
|
|
||||
@Prop(String) |
|
||||
public readonly displayName!: string; |
|
||||
|
|
||||
@Prop({ default: [] }) |
|
||||
public readonly options!: FilterOptions; |
|
||||
|
|
||||
private optionsList = new Array; |
|
||||
|
|
||||
public selectedOption = null; |
|
||||
|
|
||||
public created() |
|
||||
{ |
|
||||
for (let index in this.options) { |
|
||||
let words = index.split('_'); |
|
||||
for (let i = 0; i < words.length; i++) { |
|
||||
words[i] = words[i].charAt(0).toUpperCase() + words[i].substr(1); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
let option = { |
|
||||
name: words.join(' '), |
|
||||
list: new Array |
|
||||
}; |
|
||||
this.options[index].forEach( opt => { |
|
||||
option.list.push({ |
|
||||
'name': opt, |
|
||||
'value': opt |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
this.optionsList.push(option); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss"> |
|
||||
.filter-container, |
|
||||
.filter-option { |
|
||||
margin-bottom: 10px; |
|
||||
} |
|
||||
</style> |
|
@ -1,7 +0,0 @@ |
|||||
import { FilterOptions } from "./FilterOptions"; |
|
||||
|
|
||||
export interface FilterInterface |
|
||||
{ |
|
||||
display_name: string; |
|
||||
options: FilterOptions; |
|
||||
} |
|
@ -1,4 +0,0 @@ |
|||||
export interface FilterOptions |
|
||||
{ |
|
||||
[keys: string]: string[] |
|
||||
} |
|
@ -0,0 +1,18 @@ |
|||||
|
import _Vue, { PluginFunction } from 'vue'; |
||||
|
import ApiService from '@services/ApiService'; |
||||
|
|
||||
|
const ApiPlugin = { |
||||
|
|
||||
|
install: (Vue: typeof _Vue, options?: any) => { |
||||
|
|
||||
|
let apiService = new ApiService(); |
||||
|
|
||||
|
Vue.mixin({ |
||||
|
created() { |
||||
|
Vue.prototype.$api = apiService; |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default ApiPlugin; |
@ -0,0 +1,7 @@ |
|||||
|
import ApiService from '@services/ApiService'; |
||||
|
|
||||
|
declare module 'vue/types/vue' { |
||||
|
interface Vue { |
||||
|
$api: ApiService; |
||||
|
} |
||||
|
} |
@ -0,0 +1,60 @@ |
|||||
|
import axios from 'axios'; |
||||
|
|
||||
|
export default class ApiService { |
||||
|
private readonly baseUrl: string = 'http://core.sandd'; |
||||
|
|
||||
|
private readonly apiRoutes = { |
||||
|
file: '/api/file', |
||||
|
searchAndDisplace: '/search-and-displace' |
||||
|
}; |
||||
|
|
||||
|
constructor() |
||||
|
{} |
||||
|
|
||||
|
/** |
||||
|
* Upload a file to the server and return its response. |
||||
|
* Throws an error if the response wasn't successful |
||||
|
* |
||||
|
* @param file |
||||
|
* @returns |
||||
|
*/ |
||||
|
public async uploadFile(file: File) |
||||
|
{ |
||||
|
let formData = new FormData(); |
||||
|
formData.append('file', file); |
||||
|
|
||||
|
try { |
||||
|
let response = await axios.post( |
||||
|
this.baseUrl + this.apiRoutes.file, |
||||
|
formData, |
||||
|
{ |
||||
|
headers: { |
||||
|
'Content-Type': 'multipart/form-data' |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
return response.data; |
||||
|
} catch (err) { |
||||
|
throw err; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get data for a file from the server. |
||||
|
* Throws an error if the response wasn't successful |
||||
|
* |
||||
|
* @param fileId |
||||
|
* @returns |
||||
|
*/ |
||||
|
public async getFileData(fileId: string) |
||||
|
{ |
||||
|
try { |
||||
|
let response = await axios.get(this.baseUrl + this.apiRoutes.searchAndDisplace + `/${fileId}`); |
||||
|
|
||||
|
return response.data; |
||||
|
} catch (err) { |
||||
|
throw err; |
||||
|
} |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue