Repo for the search and displace core module including the interface to select files and search and displace operations to run on them. https://searchanddisplace.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

336 lines
14 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
  1. <template>
  2. <div class="p-d-flex p-flex-row p-jc-between p-ai-stretch">
  3. <Card class="p-mr-2 p-as-stretch file-card">
  4. <template #header>
  5. <div>
  6. <template>
  7. <Button @click="onAddNewSearcher"
  8. type="button"
  9. label="Add new searcher"
  10. class="p-button p-button-outlined p-button-secondary p-button-sm">
  11. </Button>
  12. <Button @click="onDefineSearcher"
  13. type="button"
  14. label="Define searcher"
  15. class="p-button p-button-outlined p-button-primary p-button-sm">
  16. </Button>
  17. <Button
  18. label="Try another document"
  19. icon="pi pi-upload"
  20. class="p-button-success p-button-outlined p-button-sm"
  21. @click="toggleUploadDialog()"/>
  22. </template>
  23. </div>
  24. </template>
  25. <template #title>
  26. Original document content
  27. </template>
  28. <template #content>
  29. <div class="md-viewer" style="text-align: start; font-size: 0.7em;">
  30. <template v-if="fileContent === ''">
  31. <Skeleton/>
  32. <br/>
  33. <Skeleton/>
  34. <br/>
  35. <Skeleton/>
  36. <br/>
  37. <Skeleton/>
  38. <br/>
  39. <Skeleton/>
  40. <br/>
  41. <Skeleton/>
  42. <br/>
  43. <Skeleton/>
  44. <br/>
  45. </template>
  46. <template v-else>
  47. <div v-html="compiledFileContent"></div>
  48. </template>
  49. </div>
  50. </template>
  51. </Card>
  52. <Card class="p-mr-2 p-as-stretch file-card">
  53. <template #header>
  54. <div>
  55. <template>
  56. <label for="show-diff-highlight" class="switch-label">Highlight differences:</label>
  57. <InputSwitch
  58. v-model="showDiffHighlight"
  59. name="show-diff-highlight"
  60. inputId="show-diff-highlight"
  61. :disabled="processedFileContent == ''"/>
  62. <Button
  63. label="Download document"
  64. icon="pi pi-download"
  65. class="p-button-secondary p-button-outlined p-button-sm"
  66. :disabled="processedFileContent == ''"
  67. @click="downloadOdt"/>
  68. <Button
  69. label="Download raw"
  70. :icon=" ! applyingOnOriginalDocument ? 'pi pi-download' : 'pi pi-loading'"
  71. class="p-button-secondary p-button-outlined p-button-sm"
  72. :disabled="processedFileContent == '' || applyingOnOriginalDocument"
  73. @click="downloadOriginal"/>
  74. <Button
  75. label="Run search"
  76. icon="pi pi-play"
  77. class="p-button-success p-button-outlined p-button-sm"
  78. :disabled="!canRunSearchers()"
  79. @click="runSearchersWithoutDisplacing"/>
  80. <Button
  81. label="Run S&D"
  82. icon="pi pi-play"
  83. class="p-button-success p-button-outlined p-button-sm"
  84. :disabled="!canRunSearchers()"
  85. @click="runSearchers"/>
  86. </template>
  87. </div>
  88. </template>
  89. <template #title>
  90. Processed document content
  91. </template>
  92. <template #content>
  93. <div class="md-viewer processed-content" style="text-align: start; font-size: 0.7em;">
  94. <template v-if="processing === true">
  95. <Skeleton/>
  96. <br/>
  97. <Skeleton/>
  98. <br/>
  99. <Skeleton/>
  100. <br/>
  101. <Skeleton/>
  102. <br/>
  103. <Skeleton/>
  104. <br/>
  105. <Skeleton/>
  106. <br/>
  107. <Skeleton/>
  108. <br/>
  109. </template>
  110. <template v-else-if="processedFileContentPreview !== false">
  111. <div v-html="compiledProcessedFileContent"></div>
  112. </template>
  113. <template v-else>
  114. <Message severity="info" :closable="false">
  115. Not processed yet. Please select and run some filters to see the result.
  116. </Message>
  117. </template>
  118. </div>
  119. </template>
  120. </Card>
  121. <Sidebar
  122. :visible="true"
  123. :showCloseIcon="false"
  124. :class="{'p-sidebar-md': true, 'p-sidebar-leave-to': !searchersSidebarVisible}"
  125. :dismissable="true"
  126. :modal="false"
  127. :autoZIndex="true"
  128. :baseZIndex="1000"
  129. position="right">
  130. <div class="p-grid p-jc-start">
  131. <Button
  132. icon="pi pi-list"
  133. class="p-button-info p-button-icon-only sidebar-toggle-button"
  134. @click="toggleSearchersSidebar()"
  135. :disabled="searchersDialogVisible === true"/>
  136. </div>
  137. <div class="p-grid p-jc-between sidebar-title-container">
  138. <div class="p-col sidebar-title">
  139. <h3>Document searchers</h3>
  140. </div>
  141. <div class="p-col-2">
  142. <Button
  143. icon="pi pi-plus"
  144. class="p-button-success p-button-sm p-button-text add-searchers"
  145. @click="toggleSearchersDialog(true)"
  146. aria:haspopup="true"
  147. aria-controls="searcers_dialog"/>
  148. </div>
  149. </div>
  150. <Dialog header="Available document searchers"
  151. :visible.sync="searchersDialogVisible"
  152. :maximizable="true"
  153. :style="{width: '50vw'}"
  154. :contentStyle="{overflow: 'visible'}"
  155. id="searchers_dialog"
  156. ref="searchers-dialog">
  157. <DataTable
  158. :value.sync="searchers"
  159. :selection.sync="newlySelectedSearchers"
  160. dataKey="id"
  161. selectionMode="multiple"
  162. class="p-datatable-sm"
  163. :metaKeySelection="false"
  164. :paginator="true"
  165. :rows="10"
  166. paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
  167. currentPageReportTemplate="Showing {first} to {last} of {totalRecords}"
  168. :rowsPerPageOptions="[10,20,50]"
  169. :filters="searchersFilters">
  170. <Column selectionMode="multiple" headerStyle="width: 3em"></Column>
  171. <Column
  172. field="name"
  173. header="Name"
  174. sortable>
  175. <template #body="slotProps">
  176. {{slotProps.data.name}}
  177. </template>
  178. <template #filter>
  179. <InputText type="text" v-model="searchersFilters['global']" class="p-column-filter" placeholder="Search by name por description"/>
  180. </template>
  181. </Column>
  182. <Column
  183. field="description"
  184. header="Description"
  185. sortable
  186. class="filter-description">
  187. </Column>
  188. </DataTable>
  189. <template #footer>
  190. <Button
  191. label="Done"
  192. icon="pi pi-check"
  193. class="p-button-info p-button-outlined p-button-sm"
  194. @click="toggleSearchersDialog(false)">
  195. </Button>
  196. </template>
  197. </Dialog>
  198. <DataTable
  199. :value.sync="Object.values(selectedSearchers)"
  200. dataKey="id"
  201. class="p-datatable-sm"
  202. :expandedRows.sync="expandedRows"
  203. @row-reorder="onSelectedSearchersReorder"
  204. :scrollable="true"
  205. scrollHeight="80vh">
  206. <Column :rowReorder="true" headerStyle="width: 3rem"/>
  207. <Column field="name" header="Name"></Column>
  208. <Column headerStyle="width: 3rem">
  209. <template #body="slotProps">
  210. <Button icon="pi pi-trash"
  211. class="p-button-rounded p-button-warning"
  212. @click="confirmDeleteProduct(slotProps.data)"/>
  213. </template>
  214. </Column>
  215. <Column :expander="true" headerStyle="width: 3rem"/>
  216. <template #expansion="slotProps">
  217. <div class="options-subtable">
  218. <div class="p-fluid">
  219. <div class="p-field">
  220. <div class="p-field-radiobutton">
  221. <RadioButton name="action_type"
  222. id="action_type_replace"
  223. value="replace"
  224. v-model="searchersOptions[slotProps.data.id].type">
  225. </RadioButton>
  226. <label for="action_type_replace">Replace</label>
  227. </div>
  228. <div class="p-field-radiobutton">
  229. <RadioButton name="action_type"
  230. id="action_type_displace"
  231. value="displace"
  232. v-model="searchersOptions[slotProps.data.id].type">
  233. </RadioButton>
  234. <label for="action_type_displace">Displace</label>
  235. </div>
  236. </div>
  237. </div>
  238. <div class="p-field">
  239. <label :for="`displace_with__${slotProps.data.id}`">
  240. <span>
  241. {{ searchersOptions[slotProps.data.id].type === 'replace' ? 'Replace' : 'Displace (tag)' }}
  242. </span>
  243. <span>
  244. values with:
  245. </span>
  246. </label>
  247. <InputText
  248. :id="`displace_with__${slotProps.data.id}`"
  249. type="text"
  250. class="p-inputtext-sm"
  251. v-model="searchersOptions[slotProps.data.id].value"
  252. v-tooltip.top="
  253. (slotProps.data.param === 'required') ?
  254. 'This field is required.' : null
  255. "
  256. :class="{'p-invalid': !isValidParam(slotProps.data.id, slotProps.data.param)}"/>
  257. </div>
  258. </div>
  259. </template>
  260. <template #footer>
  261. <Button
  262. label="Run filters"
  263. icon="pi pi-play"
  264. class="p-button-success p-button-sm"
  265. :disabled="!canRunSearchers()"
  266. @click="toggleSearchersSidebar(); runSearchers()"/>
  267. </template>
  268. </DataTable>
  269. </Sidebar>
  270. <!-- File upload dialog -->
  271. <Dialog header="Upload a new file"
  272. :visible.sync="uploadDialogVisible"
  273. :maximizable="true"
  274. :style="{width: '50vw'}"
  275. :contentStyle="{overflow: 'visible'}"
  276. :baseZIndex="2014"
  277. id="upload_dialog"
  278. ref="upload-dialog">
  279. <FileUpload
  280. name="upload[]"
  281. :showUploadButton="false"
  282. :showCancelButton="false"
  283. chooseLabel="Choose file"
  284. :customUpload="true"
  285. :auto="true"
  286. @uploader="uploadFile">
  287. <template #empty>
  288. <p>Drag and drop files to here to upload.</p>
  289. </template>
  290. </FileUpload>
  291. </Dialog>
  292. <define-searcher v-if="showDefineSearcher"
  293. :text="searcherToDefineText"
  294. @done="onSearcherDefined"
  295. @close="showDefineSearcher = false">
  296. </define-searcher>
  297. </div>
  298. </template>
  299. <script lang="ts" src="./ProcessFile.ts"></script>
  300. <style lang="scss" src="./ProcessFile.scss"></style>