Browse Source

Minor updates to UI

master
Radu Liviu Carjan 5 years ago
parent
commit
f73df24b47
  1. 4
      public/css/app.css
  2. 1634
      public/js/app.js
  3. 4
      resources/js/app.ts
  4. 51
      resources/js/components/ProcessFile/ProcessFile.scss
  5. 83
      resources/js/components/ProcessFile/ProcessFile.ts
  6. 212
      resources/js/components/ProcessFile/ProcessFile.vue
  7. 2
      resources/js/components/layout/Header.vue
  8. 6
      resources/sass/_variables.scss

4
public/css/app.css

@ -10373,7 +10373,7 @@
} }
.header { .header {
background: var(--blue-400);
background: #2196F3;
height: 4rem; height: 4rem;
padding: 0 2rem; padding: 0 2rem;
border-bottom: 1px solid #dee2e6; border-bottom: 1px solid #dee2e6;
@ -10388,7 +10388,7 @@
} }
.footer { .footer {
background: var(--blue-400);
background: #2196F3;
height: 4rem; height: 4rem;
border-top: 1px solid #dee2e6; border-top: 1px solid #dee2e6;
border-bottom: 1px solid #dee2e6; border-bottom: 1px solid #dee2e6;

1634
public/js/app.js
File diff suppressed because it is too large
View File

4
resources/js/app.ts

@ -29,6 +29,8 @@ import OverlayPanel from 'primevue/overlaypanel';
import Checkbox from 'primevue/checkbox'; import Checkbox from 'primevue/checkbox';
import ProgressSpinner from 'primevue/progressspinner'; import ProgressSpinner from 'primevue/progressspinner';
import InputText from 'primevue/inputtext'; import InputText from 'primevue/inputtext';
import Dialog from 'primevue/dialog';
import Message from 'primevue/message';
// Own components // Own components
import ApiPlugin from '@plugins/ApiPlugin'; import ApiPlugin from '@plugins/ApiPlugin';
@ -68,6 +70,8 @@ Vue.component('OverlayPanel', OverlayPanel);
Vue.component('Checkbox', Checkbox); Vue.component('Checkbox', Checkbox);
Vue.component('ProgressSpinner', ProgressSpinner); Vue.component('ProgressSpinner', ProgressSpinner);
Vue.component('InputText', InputText); Vue.component('InputText', InputText);
Vue.component('Dialog', Dialog);
Vue.component('Message', Message);
Vue.component('home', Home); Vue.component('home', Home);
Vue.component('process-file', ProcessFile); Vue.component('process-file', ProcessFile);

51
resources/js/components/ProcessFile/ProcessFile.scss

@ -1,11 +1,54 @@
.file-card { .file-card {
flex: 0 1 74%;
flex: 0 1 49%;
} }
.filters-card {
flex: 0 1 24%
}
// .filters-card {
// flex: 0 1 24%
// }
.p-overlaypanel { .p-overlaypanel {
// width: 450px; // width: 450px;
min-width: 450px; min-width: 450px;
} }
.p-toolbar-group-right {
button {
margin-left: 10px;
}
}
.p-sidebar-content {
.p-toolbar {
margin-top: 32px;
}
}
.p-card-header {
.p-toolbar {
border: unset;
border-radius: unset;
border-bottom: 1px solid #dee2e6;
padding: .5rem;
}
}
button.add-searchers {
height: 100%;
}
.p-col.sidebar-title {
display: flex;
align-content: flex-start;
justify-content: flex-start;
}
.p-grid.sidebar-title-container {
padding-top: 50px;
}
.md-viewer {
text-align: start;
h1, h2, h3, h4, h5 {
font-size: initial;
}
}

83
resources/js/components/ProcessFile/ProcessFile.ts

@ -21,25 +21,37 @@ export default class ProcessFile extends Vue {
/** /**
* Class members * Class members
*/ */
public $refs!: {
'searchers-overlay': any
}
// The id of the interval used to query the file status // The id of the interval used to query the file status
private intervalId!: any; private intervalId!: any;
// The content of the file we are processing // The content of the file we are processing
private fileContent: string = ''; private fileContent: string = '';
// The processed document content
private processedFileContent: string = '';
// Flag to determine whether the text is processing or not
private processing: boolean = false;
// Toggles the visibility of the selected searchers sidebar
private searchersSidebarVisible: boolean = false;
// Toggles the visibility of the available searchers dialog
private searchersDialogVisible: boolean = false;
// The list of filters/searchers in a format usable by the datatable // The list of filters/searchers in a format usable by the datatable
private searchersData: Array<{ id: string; name: string; }> = []; private searchersData: Array<{ id: string; name: string; }> = [];
// The list of filters applied to the selected searchers
private searchersFilters: any = [];
// The list of selected filters/searchers // The list of selected filters/searchers
private selectedSearchers: Array<{ id: string; name: string; }> = []; private selectedSearchers: Array<{ id: string; name: string; }> = [];
//The list of expanded rows in the selected filters/searchers table //The list of expanded rows in the selected filters/searchers table
private expandedRows: Array<{id: string; name: string; }> = []; private expandedRows: Array<{id: string; name: string; }> = [];
// The list of options applied to the searchers (for the moment, only replace_with)
private searchersOptions: { [key: string]: string } = {}; private searchersOptions: { [key: string]: string } = {};
/** /**
@ -59,6 +71,27 @@ export default class ProcessFile extends Vue {
this.intervalId = setInterval(this.waitForFile, 3000); this.intervalId = setInterval(this.waitForFile, 3000);
} }
/**
* Toggle the sidebar containing the searchers
*/
private toggleSearchersSidebar() {
this.searchersSidebarVisible = !this.searchersSidebarVisible;
}
/**
* Toggle the menu containing the list of available searchers
*
* @param {string} newValue The new value for the dialog visibility
*/
private toggleSearchersDialog(newValue?: boolean) {
if (typeof newValue !== 'undefined') {
this.searchersDialogVisible = newValue;
} else {
this.searchersDialogVisible = !this.searchersDialogVisible;
}
}
/** /**
* Wait for the file to be processed in ingest * Wait for the file to be processed in ingest
*/ */
@ -90,15 +123,6 @@ export default class ProcessFile extends Vue {
} }
} }
/**
* Toggle the menu containing the list of available searchers
*
* @param $event
*/
private toggleSearchersMenu($event: any) {
this.$refs['searchers-overlay'].toggle($event);
}
private onSelectedSearchersReorder($event: any) private onSelectedSearchersReorder($event: any)
{ {
@ -106,21 +130,30 @@ export default class ProcessFile extends Vue {
} }
/** /**
* Run the filters
* Run the searchers
*/ */
private async runFilters() {
let searchers: Array<{ key: string; replace_with: string; }> = [];
this.selectedSearchers.forEach( (searcher) => {
searchers.push({
'key': searcher.id,
'replace_with': this.searchersOptions[searcher.id] || ''
});
})
private async runSearchers() {
this.processing = true;
this.processedFileContent = '';
setTimeout(
async () => {
let searchers: Array<{ key: string; replace_with: string; }> = [];
this.selectedSearchers.forEach( (searcher) => {
searchers.push({
'key': searcher.id,
'replace_with': this.searchersOptions[searcher.id] || ''
});
});
const response = await this.$api.filterDocument(this.fileContent, searchers);
const response = await this.$api.filterDocument(this.fileContent, searchers);
console.log(response);
console.log(response);
this.fileContent = response.content;
this.processedFileContent = response.content;
this.processing = false;
},
2500
);
} }
} }

212
resources/js/components/ProcessFile/ProcessFile.vue

@ -8,116 +8,178 @@
<template #header> <template #header>
<Toolbar> <Toolbar>
<template #left> <template #left>
<h3>File preview</h3>
</template>
<template #right>
<Button
label="Run filters"
icon="pi pi-play"
class="p-button-success p-button-outlined p-button-sm"
:disabled="fileContent == ''"
@click="runFilters()"/>
<h3>Original document content</h3>
</template> </template>
</Toolbar> </Toolbar>
</template> </template>
<template #content> <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>
<div class="md-viewer">
<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>
</div>
</template> </template>
</Card> </Card>
<Card class="p-mr-2 p-as-stretch filters-card">
<Card
class="p-mr-2 p-as-stretch file-card"
>
<template #header> <template #header>
<Toolbar> <Toolbar>
<template #left> <template #left>
<h3>Document searchers</h3>
<h3>Processed document content</h3>
</template> </template>
<template #right> <template #right>
<Button <Button
icon="pi pi-plus"
class="p-button-success p-button-sm p-button-text"
@click="toggleSearchersMenu"
aria:haspopup="true"
aria-controls="overlay_panel" />
label="Download document"
icon="pi pi-download"
class="p-button-secondary p-button-outlined p-button-sm"/>
<Button
label="Run filters"
icon="pi pi-play"
class="p-button-success p-button-outlined p-button-sm"
:disabled="fileContent == ''"
@click="runSearchers()"/>
<Button
label="Toggle filters list"
icon="pi pi-list"
class="p-button-info p-button-outlined p-button-sm"
@click="toggleSearchersSidebar()"/>
</template> </template>
</Toolbar> </Toolbar>
</template> </template>
<template #content> <template #content>
<div class="md-viewer">
<template v-if="processing === true">
<Skeleton /><br />
<Skeleton /><br />
<Skeleton /><br />
<Skeleton /><br />
<Skeleton /><br />
<Skeleton /><br />
<Skeleton /><br />
</template>
<template v-else-if="processedFileContent !== ''">
<vue-markdown :source="processedFileContent" />
</template>
<template v-else>
<Message severity="info" :closable="false">
Not processed yet. Please select and run some filters to see the result.
</Message>
</template>
</div>
</template>
</Card>
<Sidebar
:visible.sync="searchersSidebarVisible"
:showCloseIcon="true"
class="p-sidebar-md"
position="right">
<div class="p-grid p-jc-between sidebar-title-container">
<div class="p-col sidebar-title">
<h3>Document searchers</h3>
</div>
<div class="p-col-2">
<Button
icon="pi pi-plus"
class="p-button-success p-button-sm p-button-text add-searchers"
@click="toggleSearchersDialog(true)"
aria:haspopup="true"
aria-controls="searcers_dialog" />
</div>
</div>
<Dialog
header="Available document searchers"
:visible.sync="searchersDialogVisible"
:maximizable="true"
:style="{width: '50vw'}"
:contentStyle="{overflow: 'visible'}"
id="searcers_dialog"
ref="searcers-dialog">
<DataTable <DataTable
:value.sync="selectedSearchers"
:value.sync="searchersData"
:selection.sync="selectedSearchers"
dataKey="id" dataKey="id"
selectionMode="multiple"
class="p-datatable-sm" class="p-datatable-sm"
:expandedRows.sync="expandedRows"
@row-reorder="onSelectedSearchersReorder">
:metaKeySelection="false"
:paginator="true" :rows="10"
paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords}"
:rowsPerPageOptions="[10,20,50]">
<Column :rowReorder="true" headerStyle="width: 3rem" />
<Column selectionMode="multiple" headerStyle="width: 3em"></Column>
<Column field="name" header="Name" sortable></Column> <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="`replace_with__${slotProps.data.id}`">
Replace values with:
</label>
<InputText
:id="`replace_with__${slotProps.data.id}`"
type="text"
class="p-inputtext-sm"
v-model="searchersOptions[slotProps.data.id]"/>
</div>
</div>
</div>
</template>
</DataTable> </DataTable>
</template>
</Card>
<OverlayPanel
ref="searchers-overlay"
appendTo="body"
id="overlay_panel"
style="width: 300px">
<template #footer>
<Button
label="Done"
icon="pi pi-check"
class="p-button-info p-button-outlined p-button-sm"
@click="toggleSearchersDialog(false)"/>
</template>
</Dialog>
<DataTable <DataTable
:value.sync="searchersData"
:selection.sync="selectedSearchers"
:value.sync="selectedSearchers"
dataKey="id" dataKey="id"
selectionMode="multiple"
class="p-datatable-sm" class="p-datatable-sm"
:metaKeySelection="false"
:paginator="true" :rows="10"
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
:rowsPerPageOptions="[10,20,50]">
:expandedRows.sync="expandedRows"
@row-reorder="onSelectedSearchersReorder">
<Column :rowReorder="true" headerStyle="width: 3rem" />
<Column field="name" header="Name">
</Column>
<Column :expander="true" headerStyle="width: 3rem" />
<template #expansion="slotProps">
<div class="options-subtable">
<div class="p-fluid">
<div class="p-field">
<label :for="`replace_with__${slotProps.data.id}`">
Replace values with:
</label>
<InputText
:id="`replace_with__${slotProps.data.id}`"
type="text"
class="p-inputtext-sm"
v-model="searchersOptions[slotProps.data.id]"/>
</div>
</div>
<Column selectionMode="multiple" headerStyle="width: 3em"></Column>
<Column field="name" header="Name" sortable></Column>
</div>
</template>
</DataTable> </DataTable>
</OverlayPanel>
</Sidebar>
</div> </div>
</template> </template>

2
resources/js/components/layout/Header.vue

@ -2,7 +2,7 @@
<div class="header"> <div class="header">
<!-- Left side of header --> <!-- Left side of header -->
<div class="left"> <div class="left">
<Button class="p-button-text" label="Search and Displace" />
<Button class="p-button-primary" label="Search and Displace" />
</div> </div>
<!-- Right side of header --> <!-- Right side of header -->

6
resources/sass/_variables.scss

@ -1,7 +1,9 @@
$header-height: 4rem; $header-height: 4rem;
$header-background: var(--blue-400);
// $header-background: var(--blue-400);
$header-background: #2196F3;
$footer-height: 4rem; $footer-height: 4rem;
$footer-background: var(--blue-400);
// $footer-background: var(--blue-400);
$footer-background: #2196F3;
$content-padding: 25px; $content-padding: 25px;
Loading…
Cancel
Save