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.

252 lines
8.1 KiB

  1. <template>
  2. <div id="searchers-create" :class="{'is-defining': isDefining,}">
  3. <!-- <h1> {{ searcher.id ? 'Edit' : 'New' }} searcher </h1> -->
  4. <Card>
  5. <template #title>
  6. {{ searcher.id ? 'Edit' : 'New' }} searcher
  7. </template>
  8. <template #content>
  9. <div class="p-fluid p-formgrid p-grid">
  10. <div class="p-field p-col-12 p-md-6">
  11. <label for="searcher-">Searcher name</label>
  12. <InputText v-model="name"
  13. type="text"
  14. placeholder="Enter searcher name"
  15. class="input"
  16. id="searcher-name"
  17. name="searcher-name">
  18. </InputText>
  19. </div>
  20. <div class="p-field p-col-12 p-md-6">
  21. <label for="lastname">Default tag</label>
  22. <InputText v-model="tag"
  23. type="text"
  24. placeholder="Enter the default tag"
  25. class="input"
  26. id="searcher-default-tag"
  27. name="searcher-default-tag">
  28. </InputText>
  29. </div>
  30. <div class="p-field p-col-12">
  31. <label for="address">Description</label>
  32. <Textarea
  33. v-model="description"
  34. rows="5"
  35. placeholder="Enter searcher description"
  36. id="searcher-description"
  37. name="searcher-description"
  38. />
  39. </div>
  40. </div>
  41. <Message severity="info" v-if="standalone">
  42. <p>A searcher may contain multiple compounded searchers on multiple rows and columns.</p>
  43. <p>Each searcher in a row is extending the searching criteria on the content resulted from the
  44. previous row searchers.</p>
  45. </Message>
  46. </template>
  47. <template #footer>
  48. <Button @click="onSave" :disabled=" ! name || rows.length === 0">
  49. Save
  50. </Button>
  51. </template>
  52. </Card>
  53. <div v-for="(row, rowIndex) in rows"
  54. :key="`row-${rowIndex}`"
  55. class="searchers-row flex-row">
  56. <div v-for="(searcher, columnIndex) in row"
  57. :key="`column-${columnIndex}`"
  58. class="searcher box">
  59. <searcher-show :searcher="searcher"
  60. :editable="true"
  61. :standalone="false"
  62. @deleted="onRemoveItem(rowIndex, columnIndex)">
  63. </searcher-show>
  64. </div>
  65. <add-box :ignore-searcher-ids="searcher.id ? [searcher.id] : []"
  66. @added="(searcher) => { onSearcherAdded(searcher, rowIndex); }">
  67. </add-box>
  68. </div>
  69. <div class="searchers-row flex-row">
  70. <add-box @added="onNewRowSearcherAdded">
  71. </add-box>
  72. </div>
  73. </div>
  74. </template>
  75. <script lang="ts">
  76. import { eventBus } from "@/app";
  77. import {Component, Prop, Vue} from "vue-property-decorator";
  78. import AddBox from './AddBox.vue';
  79. import SearcherShow from './Show.vue';
  80. @Component({
  81. name: 'SearcherCreate',
  82. components: {
  83. AddBox,
  84. SearcherShow,
  85. },
  86. })
  87. export default class Create extends Vue {
  88. private id: String = '';
  89. private name: String = '';
  90. private description: String = '';
  91. private tag: String = '';
  92. private rows: Array<Array<any>> = [];
  93. @Prop({
  94. default: () => {
  95. return {
  96. id: '',
  97. name: '',
  98. description: '',
  99. tag: '',
  100. rows: [],
  101. };
  102. }
  103. })
  104. public readonly searcher!: any;
  105. @Prop({default: true})
  106. public readonly standalone!: boolean;
  107. @Prop({default: true})
  108. public readonly isDefining!: boolean;
  109. @Prop({default: ''})
  110. public readonly definedSearcher!: string;
  111. onNewRowSearcherAdded(searcher: Object) {
  112. const length = this.rows.push([]);
  113. this.onSearcherAdded(searcher, length - 1);
  114. }
  115. async onSearcherAdded(searcher: any, rowIndex: number) {
  116. try {
  117. const { data } = await (window as any).axios.get(`/searchers/${searcher.id}`);
  118. this.rows[rowIndex].push(data.searcher);
  119. } catch (e) {
  120. }
  121. }
  122. onSave() {
  123. if (this.standalone) {
  124. this.save();
  125. return;
  126. }
  127. const updatedSearcher = Object.assign(this.searcher, {
  128. name: this.name,
  129. description: this.description,
  130. tag: this.tag,
  131. rows: this.rows,
  132. });
  133. this.$emit('updated', updatedSearcher);
  134. }
  135. async save() {
  136. try {
  137. const searcher = this.id ? await this.update() : await this.create();
  138. if (this.isDefining) {
  139. this.$emit('defined', searcher);
  140. return;
  141. }
  142. window.location.href = `/searchers/${searcher.id}`;
  143. } catch (e) {
  144. console.log(e);
  145. console.log('Something went wrong.');
  146. }
  147. }
  148. async update() {
  149. const { data } = await (window as any).axios.put(`/searchers/${this.id}`, {
  150. name: this.name,
  151. description: this.description,
  152. tag: this.tag,
  153. rows: this.rows,
  154. });
  155. return data.searcher;
  156. }
  157. async create() {
  158. const { data } = await (window as any).axios.post('/searchers', {
  159. name: this.name,
  160. description: this.description,
  161. tag: this.tag,
  162. rows: this.rows,
  163. });
  164. return data.searcher;
  165. }
  166. onRemoveItem(rowIndex: number, columnIndex: number) {
  167. if (
  168. this.rows[rowIndex][columnIndex].hasOwnProperty('rows') &&
  169. this.rows[rowIndex][columnIndex].rows.length === 0
  170. ) {
  171. this.$toast.add({
  172. severity: 'info',
  173. summary: `${this.searcher.name} searcher deleted`,
  174. detail: 'The searcher has been deleted as well because it does not have any searching data..',
  175. life: 4000,
  176. });
  177. }
  178. this.rows[rowIndex].splice(columnIndex, 1);
  179. if (this.rows[rowIndex].length === 0) {
  180. this.rows.splice(rowIndex, 1);
  181. }
  182. }
  183. public async changeRoute(url: string) {
  184. if (this.rows.length > 0) {
  185. if (this.name === '' || this.name === undefined) {
  186. this.name = 'Unnamed searcher - ' + Date.now();
  187. }
  188. const searcher = this.id ? await this.update() : await this.create();
  189. }
  190. window.location.href = url;
  191. }
  192. created() {
  193. // Editing.
  194. if (this.searcher.id) {
  195. this.id = this.searcher.id;
  196. this.rows = this.searcher.rows;
  197. this.name = this.searcher.name;
  198. this.description = this.searcher.description;
  199. this.tag = this.searcher.tag;
  200. }
  201. if (this.isDefining && this.definedSearcher) {
  202. this.name = this.definedSearcher;
  203. this.description = '';
  204. this.rows.push([
  205. {
  206. expression: this.definedSearcher,
  207. },
  208. ]);
  209. }
  210. eventBus.$on('changeRoute', this.changeRoute);
  211. }
  212. };
  213. </script>