]> BookStack Code Mirror - bookstack/blob - resources/js/vues/search.js
Add feature to send test e-mails
[bookstack] / resources / js / vues / search.js
1 import * as Dates from "../services/dates";
2
3 let data = {
4     terms: '',
5     termString : '',
6     search: {
7         type: {
8             page: true,
9             chapter: true,
10             book: true,
11             bookshelf: true,
12         },
13         exactTerms: [],
14         tagTerms: [],
15         option: {},
16         dates: {
17             updated_after: false,
18             updated_before: false,
19             created_after: false,
20             created_before: false,
21         }
22     }
23 };
24
25 let computed = {
26
27 };
28
29 let methods = {
30
31     appendTerm(term) {
32         this.termString += ' ' + term;
33         this.termString = this.termString.replace(/\s{2,}/g, ' ');
34         this.termString = this.termString.replace(/^\s+/, '');
35         this.termString = this.termString.replace(/\s+$/, '');
36     },
37
38     exactParse(searchString) {
39         this.search.exactTerms = [];
40         let exactFilter = /"(.+?)"/g;
41         let matches;
42         while ((matches = exactFilter.exec(searchString)) !== null) {
43             this.search.exactTerms.push(matches[1]);
44         }
45     },
46
47     exactChange() {
48         let exactFilter = /"(.+?)"/g;
49         this.termString = this.termString.replace(exactFilter, '');
50         let matchesTerm = this.search.exactTerms.filter(term =>  term.trim() !== '').map(term => `"${term}"`).join(' ');
51         this.appendTerm(matchesTerm);
52     },
53
54     addExact() {
55         this.search.exactTerms.push('');
56         setTimeout(() => {
57             let exactInputs = document.querySelectorAll('.exact-input');
58             exactInputs[exactInputs.length - 1].focus();
59         }, 100);
60     },
61
62     removeExact(index) {
63         this.search.exactTerms.splice(index, 1);
64         this.exactChange();
65     },
66
67     tagParse(searchString) {
68         this.search.tagTerms = [];
69         let tagFilter = /\[(.+?)\]/g;
70         let matches;
71         while ((matches = tagFilter.exec(searchString)) !== null) {
72             this.search.tagTerms.push(matches[1]);
73         }
74     },
75
76     tagChange() {
77         let tagFilter = /\[(.+?)\]/g;
78         this.termString = this.termString.replace(tagFilter, '');
79         let matchesTerm = this.search.tagTerms.filter(term => {
80             return term.trim() !== '';
81         }).map(term => {
82             return `[${term}]`
83         }).join(' ');
84         this.appendTerm(matchesTerm);
85     },
86
87     addTag() {
88         this.search.tagTerms.push('');
89         setTimeout(() => {
90             let tagInputs = document.querySelectorAll('.tag-input');
91             tagInputs[tagInputs.length - 1].focus();
92         }, 100);
93     },
94
95     removeTag(index) {
96         this.search.tagTerms.splice(index, 1);
97         this.tagChange();
98     },
99
100     typeParse(searchString) {
101         let typeFilter = /{\s?type:\s?(.*?)\s?}/;
102         let match = searchString.match(typeFilter);
103         let type = this.search.type;
104         if (!match) {
105             type.page = type.book = type.chapter = type.bookshelf = true;
106             return;
107         }
108         let splitTypes = match[1].replace(/ /g, '').split('|');
109         type.page = (splitTypes.indexOf('page') !== -1);
110         type.chapter = (splitTypes.indexOf('chapter') !== -1);
111         type.book = (splitTypes.indexOf('book') !== -1);
112         type.bookshelf = (splitTypes.indexOf('bookshelf') !== -1);
113     },
114
115     typeChange() {
116         let typeFilter = /{\s?type:\s?(.*?)\s?}/;
117         let type = this.search.type;
118         if (type.page === type.chapter === type.book === type.bookshelf) {
119             this.termString = this.termString.replace(typeFilter, '');
120             return;
121         }
122         let selectedTypes = Object.keys(type).filter(type => this.search.type[type]).join('|');
123         let typeTerm = '{type:'+selectedTypes+'}';
124         if (this.termString.match(typeFilter)) {
125             this.termString = this.termString.replace(typeFilter, typeTerm);
126             return;
127         }
128         this.appendTerm(typeTerm);
129     },
130
131     optionParse(searchString) {
132         let optionFilter = /{([a-z_\-:]+?)}/gi;
133         let matches;
134         while ((matches = optionFilter.exec(searchString)) !== null) {
135             this.search.option[matches[1].toLowerCase()] = true;
136         }
137     },
138
139     optionChange(optionName) {
140         let isChecked = this.search.option[optionName];
141         if (isChecked) {
142             this.appendTerm(`{${optionName}}`);
143         } else {
144             this.termString = this.termString.replace(`{${optionName}}`, '');
145         }
146     },
147
148     updateSearch(e) {
149         e.preventDefault();
150         window.location = window.baseUrl('/search?term=' + encodeURIComponent(this.termString));
151     },
152
153     enableDate(optionName) {
154         this.search.dates[optionName.toLowerCase()] = Dates.getCurrentDay();
155         this.dateChange(optionName);
156     },
157
158     dateParse(searchString) {
159         let dateFilter = /{([a-z_\-]+?):([a-z_\-0-9]+?)}/gi;
160         let dateTags = Object.keys(this.search.dates);
161         let matches;
162         while ((matches = dateFilter.exec(searchString)) !== null) {
163             if (dateTags.indexOf(matches[1]) === -1) continue;
164             this.search.dates[matches[1].toLowerCase()] = matches[2];
165         }
166     },
167
168     dateChange(optionName) {
169         let dateFilter = new RegExp('{\\s?'+optionName+'\\s?:([a-z_\\-0-9]+?)}', 'gi');
170         this.termString = this.termString.replace(dateFilter, '');
171         if (!this.search.dates[optionName]) return;
172         this.appendTerm(`{${optionName}:${this.search.dates[optionName]}}`);
173     },
174
175     dateRemove(optionName) {
176         this.search.dates[optionName] = false;
177         this.dateChange(optionName);
178     }
179
180 };
181
182 function created() {
183     this.termString = document.querySelector('[name=searchTerm]').value;
184     this.typeParse(this.termString);
185     this.exactParse(this.termString);
186     this.tagParse(this.termString);
187     this.optionParse(this.termString);
188     this.dateParse(this.termString);
189 }
190
191 export default {
192     data, computed, methods, created
193 };