From 21fda01cb3c8a4481235eea76c51ce6646c75f33 Mon Sep 17 00:00:00 2001 From: Ogefest Date: Sat, 23 Oct 2021 17:34:35 +0200 Subject: [PATCH] advanced search, search relevant improved --- .../com/ogefest/filehunter/IndexRead.java | 91 ++++++++++++++++-- .../filehunter/api/SearchController.java | 20 +++- .../META-INF/resources/asset-manifest.json | 6 +- .../resources/META-INF/resources/favicon.ico | Bin 0 -> 15406 bytes .../resources/META-INF/resources/index.html | 2 +- .../static/js/main.0998ecba.chunk.js | 2 + .../static/js/main.0998ecba.chunk.js.map | 1 + .../static/js/main.61eb00ba.chunk.js | 2 + .../static/js/main.61eb00ba.chunk.js.map | 1 + .../static/js/main.6c323a16.chunk.js | 2 - .../static/js/main.6c323a16.chunk.js.map | 1 - 11 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 src/main/resources/META-INF/resources/favicon.ico create mode 100644 src/main/resources/META-INF/resources/static/js/main.0998ecba.chunk.js create mode 100644 src/main/resources/META-INF/resources/static/js/main.0998ecba.chunk.js.map create mode 100644 src/main/resources/META-INF/resources/static/js/main.61eb00ba.chunk.js create mode 100644 src/main/resources/META-INF/resources/static/js/main.61eb00ba.chunk.js.map delete mode 100644 src/main/resources/META-INF/resources/static/js/main.6c323a16.chunk.js delete mode 100644 src/main/resources/META-INF/resources/static/js/main.6c323a16.chunk.js.map diff --git a/src/main/java/com/ogefest/filehunter/IndexRead.java b/src/main/java/com/ogefest/filehunter/IndexRead.java index 916481c..d8fdf95 100644 --- a/src/main/java/com/ogefest/filehunter/IndexRead.java +++ b/src/main/java/com/ogefest/filehunter/IndexRead.java @@ -3,20 +3,26 @@ import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; +import org.apache.lucene.document.LongPoint; +import org.apache.lucene.document.LongRange; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexNotFoundException; import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.Term; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.classic.QueryParser; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.ScoreDoc; -import org.apache.lucene.search.TopDocs; +import org.apache.lucene.queryparser.xml.builders.BooleanQueryBuilder; +import org.apache.lucene.queryparser.xml.builders.RangeQueryBuilder; +import org.apache.lucene.search.*; import org.apache.lucene.store.FSDirectory; +import org.apache.lucene.util.QueryBuilder; import java.io.IOException; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; public class IndexRead { @@ -96,7 +102,12 @@ public SearchResult getByUuid(String uuid) { return searchResults.get(0); } + public ArrayList query(String q) { + return query(q, new HashMap<>()); + } + + public ArrayList query(String q, HashMap filters) { ArrayList result = new ArrayList<>(); if (searcher == null) { @@ -107,10 +118,30 @@ public ArrayList query(String q) { QueryParser parser = new QueryParser("path", analyzer); parser.setDefaultOperator(QueryParser.Operator.AND); + Query pathQueryTmp = parser.parse(q); + BoostQuery pathQuery = new BoostQuery(pathQueryTmp, 1.2f); + + QueryParser parserContent = new QueryParser("content", analyzer); + parserContent.setDefaultOperator(QueryParser.Operator.AND); + Query contentQuery = parserContent.parse(q); + + + // path^1.2 OR content + BooleanQuery.Builder mainQuery = new BooleanQuery.Builder(); + mainQuery.add(pathQuery, BooleanClause.Occur.SHOULD); + mainQuery.add(contentQuery, BooleanClause.Occur.SHOULD); + - Query query = parser.parse(q); -// BoostQuery bq = new BoostQuery(query); - TopDocs hits = searcher.search(query, 100); + // final + filters + BooleanQuery.Builder finalQuery = new BooleanQuery.Builder(); + finalQuery.add(mainQuery.build(), BooleanClause.Occur.MUST); + addSingleFilters(finalQuery, filters); + addRangeFilters(finalQuery, filters); + + + Query searchQuery = finalQuery.build(); + + TopDocs hits = searcher.search(searchQuery, 100); for(ScoreDoc scoreDoc : hits.scoreDocs) { Document doc = searcher.doc(scoreDoc.doc); @@ -127,9 +158,51 @@ public ArrayList query(String q) { return result; } -// public ArrayList getFilesToUpdateMetadata() { + private void addSingleFilters(BooleanQuery.Builder query, HashMap queryFilters) { + + String supportedFields[] = { "index", "ext", "name", "content", "path" }; + List supportedFilters = Arrays.asList(supportedFields); + + for (String k : supportedFilters) { + if (queryFilters.containsKey(k)) { + query.add(new TermQuery(new Term(k, queryFilters.get(k))), BooleanClause.Occur.MUST); + } + } + } + + private void addRangeFilters(BooleanQuery.Builder query, HashMap queryFilters) { + HashMap> supported = new HashMap<>(); + + String sizeKeys[] = {"minsize", "maxsize"}; + supported.put("size", Arrays.asList(sizeKeys)); + + String modifiedKeys[] = {"modified_after", "modified_before"}; + supported.put("last_modified", Arrays.asList(modifiedKeys)); + + String createdKeys[] = {"created_after", "created_before"}; + supported.put("created", Arrays.asList(createdKeys)); + + for (String k : supported.keySet()) { + + String fieldMin = supported.get(k).get(0); + String fieldMax = supported.get(k).get(1); -// } + if (!queryFilters.containsKey(fieldMin) && !queryFilters.containsKey(fieldMax)) { + continue; + } + long fieldMinLong = 0; + if (queryFilters.containsKey(fieldMin)) { + fieldMinLong = Long.parseLong(queryFilters.get(fieldMin)); + } + + long fieldMaxLong = Long.MAX_VALUE; + if (queryFilters.containsKey(fieldMax) && !queryFilters.get(fieldMax).equals("0")) { + fieldMaxLong = Long.parseLong(queryFilters.get(fieldMax)); + } + + query.add(LongPoint.newRangeQuery(k, fieldMinLong, fieldMaxLong), BooleanClause.Occur.MUST); + } + } public int getNumDocs() { if (reader == null) { diff --git a/src/main/java/com/ogefest/filehunter/api/SearchController.java b/src/main/java/com/ogefest/filehunter/api/SearchController.java index 5ea5fe1..234eb07 100644 --- a/src/main/java/com/ogefest/filehunter/api/SearchController.java +++ b/src/main/java/com/ogefest/filehunter/api/SearchController.java @@ -5,10 +5,16 @@ import com.ogefest.filehunter.SearchResult; import javax.inject.Inject; +import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; @Path("/search") public class SearchController { @@ -17,10 +23,20 @@ public class SearchController { App app; @GET - public ArrayList search(@QueryParam("q") String query) { + public ArrayList search(@QueryParam("q") String query, @Context UriInfo uinfo) { + + MultivaluedMap abc = uinfo.getQueryParameters(); + HashMap filters = new HashMap<>(); + String kkey = ""; + for (String k : abc.keySet()) { + if (k.indexOf("filter[") == 0) { + kkey = k.substring(7, k.length()-1); + filters.put(kkey, abc.getFirst(k)); + } + } IndexRead ir = new IndexRead(app.getConfiguration()); - ArrayList result = ir.query(query); + ArrayList result = ir.query(query, filters); return result; } diff --git a/src/main/resources/META-INF/resources/asset-manifest.json b/src/main/resources/META-INF/resources/asset-manifest.json index 6a08d54..6f86c85 100644 --- a/src/main/resources/META-INF/resources/asset-manifest.json +++ b/src/main/resources/META-INF/resources/asset-manifest.json @@ -1,8 +1,8 @@ { "files": { "main.css": "/static/css/main.ee01ecee.chunk.css", - "main.js": "/static/js/main.6c323a16.chunk.js", - "main.js.map": "/static/js/main.6c323a16.chunk.js.map", + "main.js": "/static/js/main.61eb00ba.chunk.js", + "main.js.map": "/static/js/main.61eb00ba.chunk.js.map", "runtime-main.js": "/static/js/runtime-main.80fb9e64.js", "runtime-main.js.map": "/static/js/runtime-main.80fb9e64.js.map", "static/css/2.ee8d6a27.chunk.css": "/static/css/2.ee8d6a27.chunk.css", @@ -21,6 +21,6 @@ "static/css/2.ee8d6a27.chunk.css", "static/js/2.6733b7d9.chunk.js", "static/css/main.ee01ecee.chunk.css", - "static/js/main.6c323a16.chunk.js" + "static/js/main.61eb00ba.chunk.js" ] } \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/favicon.ico b/src/main/resources/META-INF/resources/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..aa60f74cdc31ebd3ebbc7c37f0c342994b99888a GIT binary patch literal 15406 zcmeHOYit!&5I($o07@~zAI5~5Al4rW8iOXr#9t;FgG4|QiAke|5dRte`AiJCEd|;J zT1+to3xs!pC@-VgSL4vSd`h8p$4KnH@j+nMlZ86iTMe|{<+Zmz0c?86dv^79 z;CbLkU19rI8-N{;d+ndp00$R)&q>mM{~_?fiyAl|j!ph&-UW`W*3fe-nE%=Lf%jg} z(00E^-?0>EpQGW_&S3gd=YM*)$A|ouU#sO0qrVLg0G~Auh58$SJqv)h?)3D%{ZW9p zuHI9=%R4X-R~EiM0wuk_zD^-RBmGRJz{3LcPeB)6SEEs*Udh&~Zjm_~cg|ty$U~r8 zc)kP?jl9FsCXJWPsFy{So}|YOJ0A5weT2nN8ZS-WNzcWO7j2(l)K|;xz`7a0va!Ye zF?~64n{V~UT{c?xubuAS@8{>cKZSFxy16*b)<-n%=PmxY4U=?#?-&04mVcpMtp20h z-^p#j+B*v2?fc@}-(Ow8pFb4Bit*l>x%RKQ1pmgd|6fl5znmxpKmO-V%bu{U5Ke54 zKY#oFd+Y4yr`YDM|9{c{@tyLsDYmVds&zA*^ACQTfc5tbAOEIXfH!Y5!}4o1|GII& zswn`!!@f2$O7}NT4(LyC-{8yNj_T1WQ#l zWv1-eC2E4SHB;`WW2S{KvJQyMt2qbp6AL6q6+0)F@*JvV9vx}PP%>Y!rE;>H{P|LL zfzYuXz{ks_szhRdD%4Oh> zv%qg>4DhYyk+lB5I|#hZq79{Tf z?f%&qJLK=DY#aE^#Xq2?1Kh#EzDaSTB7%4of*kNO!DTIZ?Al2{Jv|h#y?swwdga< z_Filehunter
\ No newline at end of file +Filehunter
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/static/js/main.0998ecba.chunk.js b/src/main/resources/META-INF/resources/static/js/main.0998ecba.chunk.js new file mode 100644 index 0000000..96417d0 --- /dev/null +++ b/src/main/resources/META-INF/resources/static/js/main.0998ecba.chunk.js @@ -0,0 +1,2 @@ +(this["webpackJsonpfilehunter-front"]=this["webpackJsonpfilehunter-front"]||[]).push([[0],{24:function(e,t,s){},25:function(e,t,s){},38:function(e,t,s){"use strict";s.r(t);var n=s(1),i=s.n(n),a=s(16),c=s.n(a),l=(s(24),s(25),s(26),s(19)),r=s(6),o=s(2),d=s(3),h=s(5),b=s(4),j=s(7),m=s(0),u=(i.a.Component,function(e){Object(h.a)(s,e);var t=Object(b.a)(s);function s(){return Object(o.a)(this,s),t.apply(this,arguments)}return Object(d.a)(s,[{key:"render",value:function(){return Object(m.jsx)("nav",{class:"navbar navbar-expand-lg navbar-light",children:Object(m.jsxs)("div",{class:"container-fluid",children:[Object(m.jsx)("span",{class:"badge bg-primary",children:"FH"})," ",Object(m.jsx)("a",{class:"navbar-brand",href:"/",children:"Filehunter"}),Object(m.jsx)("button",{class:"navbar-toggler",type:"button","data-bs-toggle":"collapse","data-bs-target":"#navbarSupportedContent","aria-controls":"navbarSupportedContent","aria-expanded":"false","aria-label":"Toggle navigation",children:Object(m.jsx)("span",{class:"navbar-toggler-icon"})}),Object(m.jsx)("div",{class:"collapse navbar-collapse",id:"navbarSupportedContent",children:Object(m.jsxs)("ul",{class:"navbar-nav ms-auto mb-1 mb-lg-0",children:[Object(m.jsx)("li",{class:"nav-item",children:Object(m.jsxs)("a",{class:"nav-link","aria-current":"page",href:"/",children:[Object(m.jsx)("i",{class:"bi bi-search"})," Search"]})}),Object(m.jsx)("li",{class:"nav-item",children:Object(m.jsxs)("a",{href:"/gui/index",class:"nav-link menu-item nav-active",children:[Object(m.jsx)("i",{class:"bi bi-folder2-open"})," Indexes"]})}),Object(m.jsx)("li",{class:"nav-item",children:Object(m.jsxs)("a",{rel:"noreferrer",href:"".concat("","/api-doc"),target:"_blank",class:"nav-link menu-item",children:[Object(m.jsx)("i",{class:"bi bi-code-slash"})," API Doc"]})}),Object(m.jsx)("li",{class:"nav-item",children:Object(m.jsxs)("a",{rel:"noreferrer",href:"https://github.com/Ogefest/filehunter",target:"_blank",class:"nav-link menu-item",children:[Object(m.jsx)("i",{class:"bi bi-github"})," Github"]})})]})})]})})}}]),s}(i.a.Component)),x=function(e){Object(h.a)(s,e);var t=Object(b.a)(s);function s(e){var n;return Object(o.a)(this,s),(n=t.call(this,e)).getColorByName=n.getColorByName.bind(Object(j.a)(n)),n}return Object(d.a)(s,[{key:"getColorByName",value:function(e){for(var t=0,s=0;s>8*s&255).toString(16)).substr(-2)}return n}},{key:"humanFileSize",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2,n=t?1e3:1024;if(Math.abs(e)=n&&a\n
\n FH Filehunter\n \n
\n \n
\n
\n \n\n )\n }\n}\n\nexport default Navbar;","import React from 'react';\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass SystemTaskStatus extends React.Component {\n constructor(props) {\n super(props)\n\n this.refreshInterval = 10000\n this.refreshStatus = this.refreshStatus.bind(this)\n } \n \n componentDidMount() {\n this.refreshStatus()\n }\n\n refreshStatus() {\n fetch(`${API_URL}/system/status`)\n .then(res => res.json())\n .then((result) => {\n this.result = result;\n\n setTimeout(this.refreshStatus, this.refreshInterval)\n this.setState({});\n });\n }\n\n render() {\n\n if (this.result === undefined) {\n return(\"\")\n }\n if (this.result.currentTask !== \"\") {\n this.refreshInterval = 1000\n } else {\n this.refreshInterval = 10000\n return(\"\")\n }\n\n return(\n Task {this.result.currentTask}\n )\n }\n}\n\nexport default SystemTaskStatus","import React from 'react';\nconst API_URL = process.env.REACT_APP_API_URL\n\n\nclass SearchResultRow extends React.Component {\n\n constructor(props) {\n super(props)\n\n this.getColorByName = this.getColorByName.bind(this)\n }\n\n getColorByName(str) {\n var hash = 0;\n for (var i = 0; i < str.length; i++) {\n hash = str.charCodeAt(i) + ((hash << 5) - hash);\n }\n var colour = '#';\n for (var i = 0; i < 3; i++) {\n var value = (hash >> (i * 8)) & 0xFF;\n colour += ('00' + value.toString(16)).substr(-2);\n }\n return colour;\n } \n \n humanFileSize(bytes, si=true, dp=2) {\n const thresh = si ? 1000 : 1024;\n \n if (Math.abs(bytes) < thresh) {\n return bytes + ' B';\n }\n \n const units = si \n ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] \n : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];\n let u = -1;\n const r = 10**dp;\n \n do {\n bytes /= thresh;\n ++u;\n } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);\n \n \n return bytes.toFixed(dp) + ' ' + units[u];\n } \n\n render() {\n let iconclass = \"bi-file-earmark\"\n if (this.props.params.type === 'd') {\n iconclass = \"bi-folder2\"\n }\n\n let badgeColor = this.getColorByName(this.props.params.indexname)\n let fileSize = this.humanFileSize(this.props.params.size)\n\n return (\n
\n \n {/*
{this.props.params.name}
*/}\n \n
\n
\n \n \n {/* {this.props.params.indexname} */}\n \n {this.props.params.name}\n {this.props.params.indexname}\n {/* {this.props.params.indexname} */}\n {fileSize}\n
\n
\n \n
\n \n {this.props.params.path}\n
\n \n
\n )\n }\n \n}\n\nexport default SearchResultRow","import React from \"react\";\n\nclass EmptySearchResult extends React.Component {\n\n render() {\n return (\n
\n
\n
\n\n\n
\n Empty search results\n
\n\n
\n
\n
\n )\n }\n\n}\n\nexport default EmptySearchResult","import React from 'react'\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass SearchAdvanced extends React.Component {\n\n constructor(props) {\n super(props)\n this.indexList = []\n this.indexName = \"\"\n this.extension = \"\"\n this.minmultiplier = 1024 * 1024\n this.maxmultiplier = 1024 * 1024\n\n this.filters = { minsize: 0, maxsize: 0 }\n\n this.state = {\n filters: {\n minsize: 0, maxsize: 0\n },\n }\n\n }\n\n componentDidMount() {\n fetch(`${API_URL}/index/list`)\n .then(res => res.json())\n .then((result) => {\n this.indexList = result;\n this.requestFinished = true\n this.setState({ filters: this.filters })\n });\n }\n\n handleAdvancedFilterChange(e) {\n\n let k = e.target.name;\n let v = e.target.value;\n\n if (v.trim().length == 0) {\n delete this.filters[k]\n } else {\n if (k === 'modified_after' || k === 'modified_before') {\n v = Date.parse(v)\n }\n\n this.filters[k] = v;\n }\n if (k === \"maxsize\" && v != '0') {\n this.filters[k] = parseInt(v) * this.maxmultiplier;\n }\n if (k === \"minsize\" && v != '0') {\n this.filters[k] = parseInt(v) * this.minmultiplier;\n }\n\n this.props.update(this.filters)\n this.setState({ filters: this.filters })\n }\n\n handleUiHelper(e) {\n\n if (e.target.name === \"maxmultiplier\") {\n this.maxmultiplier = parseInt(e.target.value)\n }\n if (e.target.name === \"minmultiplier\") {\n this.minmultiplier = parseInt(e.target.value)\n }\n\n if (e.target.name === 'maxsizerange') {\n this.filters['maxsize'] = parseInt(e.target.value) * this.maxmultiplier\n }\n if (e.target.name === 'minsizerange') {\n this.filters['minsize'] = parseInt(e.target.value) * this.minmultiplier\n }\n\n this.props.update(this.filters)\n this.setState({ filters: this.filters })\n }\n\n render() {\n return (\n
\n
\n\n
\n \n
\n
\n\n \n
\n\n
\n\n\n
\n\n
\n \n
\n
\n \n
\n\n
\n\n\n
\n\n
\n \n
\n
\n \n
\n\n
\n\n\n
\n\n
\n \n
\n
\n \n
\n\n
\n\n
\n\n
\n \n
\n
\n \n
\n\n
\n\n
\n\n
\n \n
\n
\n \n
\n
\n \n
\n\n
\n\n
\n\n
\n \n
\n
\n \n\n
\n
\n \n
\n
\n \n
\n\n
\n\n
\n\n
\n \n
\n
\n \n\n
\n
\n \n
\n
\n \n
\n\n
\n\n\n
\n\n )\n }\n}\n\nexport default SearchAdvanced","import React from 'react';\nimport SearchResultRow from './SearchResultRow.js'\nimport EmptySearchResult from './EmptySearchResult.js';\nimport SearchAdvanced from './SearchAdvanced.js';\nconst API_URL = process.env.REACT_APP_API_URL\n\n\nclass SearchForm extends React.Component {\n\n constructor(props) {\n super(props);\n this.state = {\n value: null,\n searchResultRows: []\n };\n this.sr = []\n this.lastQuery = \"\"\n this.currentQuery = \"\"\n // this.advancedFilterQuery = \"\"\n this.activeQuery = false\n this.searchTimeout = null\n this.advancedFilters = {}\n this.updateQueryWhenActive = null\n\n this.updateAdvancedFilterQuery = this.updateAdvancedFilterQuery.bind(this)\n\n }\n\n componentDidMount() {\n // this.intervalId = setInterval(this.handleSearch.bind(this), 500);\n }\n componentWillUnmount() {\n clearInterval(this.intervalId)\n }\n\n updateAdvancedFilterQuery(s) {\n this.advancedFilters = s\n\n // let asd = new URLSearchParams(s).toString();\n\n\n // if (this.currentQuery == \"\") {\n // this.advancedFilterQuery = this.advancedFilterQuery.trim().substring(3)\n // }\n\n this.handleSearch()\n }\n\n handleSearch() {\n\n let qs = Object.keys(this.advancedFilters)\n .map(key => `filter[${encodeURIComponent(key)}]=${encodeURIComponent(this.advancedFilters[key])}`)\n .join('&');\n\n let queryTodo = `${API_URL}/search?q=${encodeURIComponent(this.currentQuery)}&${qs}`\n\n if (queryTodo === this.lastQuery) {\n return;\n }\n if (this.activeQuery === true) {\n if (this.updateQueryWhenActive === null) {\n clearInterval(this.updateQueryWhenActive)\n }\n this.updateQueryWhenActive = setTimeout(this.handleSearch(), 500)\n return\n }\n\n this.activeQuery = true\n\n fetch(queryTodo)\n .then(res => res.json())\n .then((result) => {\n this.lastQuery = queryTodo;\n this.activeQuery = false;\n\n this.sr = []\n result.map((item) => (\n this.sr.push()\n ))\n if (this.sr.length === 0) {\n this.sr.push()\n }\n\n this.setState({ searchResultRows: this.sr })\n })\n .catch(err => {\n this.activeQuery = false\n console.log(err)\n })\n }\n\n handleInputChange(e) {\n this.currentQuery = e.target.value\n if (this.searchTimeout != null) {\n clearTimeout(this.searchTimeout)\n }\n this.searchTimeout = setTimeout(this.handleSearch.bind(this), 300);\n }\n\n render() {\n return (\n
\n
\n
\n
\n \n \n \n
\n
\n
\n\n
\n\n
\n \n
\n\n
\n {this.state.searchResultRows}\n
\n\n
\n
\n )\n }\n}\n\nexport default SearchForm","import React from 'react'\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass ReindexState extends React.Component {\n\n\n constructor(props) {\n super(props)\n console.log(props)\n\n this.state = { clicked: false }\n\n this.handleClick = this.handleClick.bind(this)\n }\n\n handleClick() {\n\n if (this.state.clicked === true) {\n return\n }\n\n fetch(`${API_URL}/index/reindex/${this.props.indextype}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n })\n .then(response => {\n this.setState({ clicked: true })\n })\n\n return false\n }\n\n render() {\n // console.log(this.state.clicked)\n\n return (\n \n )\n }\n\n}\n\nexport default ReindexState","import React from \"react\";\n\nclass EmptyIndexList extends React.Component {\n\n render() {\n return (\n
\n\n\n
\n
\n\n\n
\n You have no indexed directories. Click button below to add directory.\n
\n\n \n\n
\n
\n
\n )\n }\n\n}\n\nexport default EmptyIndexList","import React from 'react';\nimport ReindexState from './ReindexState';\nimport EmptyIndexList from './EmptyIndexList';\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass IndexInfo extends React.Component {\n\n // const history = useHistory()\n\n constructor(props) {\n super(props)\n\n this.result = []\n this.requestFinished = false\n\n this.handleRemove = this.handleRemove.bind(this)\n\n }\n\n componentDidMount() {\n this.refreshList()\n\n }\n\n refreshList() {\n fetch(`${API_URL}/index/list`)\n .then(res => res.json())\n .then((result) => {\n this.result = result;\n this.requestFinished = true\n this.setState({});\n });\n }\n\n\n handleRemove(row) {\n if (window.confirm(\"Are you sure?\")) {\n\n fetch(`${API_URL}/index/remove/${row.name}`, {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' }, \n })\n .then(res => res.json())\n .then((result) => {\n this.result = result;\n this.setState({});\n }); \n }\n return false\n }\n\n render() {\n\n if (this.requestFinished === false) {\n return(\"\")\n }\n\n if (this.result.length === 0) {\n return (\n \n )\n }\n\n return (\n \n
\n
\n
\n

List of indexes New

\n \n \n \n \n \n \n \n \n \n \n \n {this.result.map(directoryRow => (\n \n \n \n \n \n\n \n \n ))}\n \n
NamePathsIgnoreLast indexed 
{directoryRow.name}\n {directoryRow.path.map(pathRow => (\n {pathRow}\n ))}\n \n {directoryRow.ignorePath.map(pathRow => (\n {pathRow}\n ))}\n {directoryRow.ignorePhrase.map(pathRow => (\n *{pathRow}*\n ))} \n {directoryRow.ignoreExtension.map(pathRow => (\n *.{pathRow}\n ))}\n \n {new Date(directoryRow.lastStructureIndexed).toLocaleDateString()}\n  \n {new Date(directoryRow.lastStructureIndexed).toLocaleTimeString()}\n \n \n this.handleRemove(directoryRow)} href=\"#\" class=\"btn btn-danger btn-sm me-1\">\n \n
\n
\n
\n\n
\n\n )\n }\n}\n\nexport default IndexInfo","import React from 'react';\nimport { withRouter } from \"react-router\";\nconst API_URL = process.env.REACT_APP_API_URL\n\n\nclass IndexForm extends React.Component {\n constructor(props) {\n super(props)\n\n this.state = {\n formData: {\n \"extractMetadata\": true,\n \"ignoreExtension\": [],\n \"ignorePath\": [],\n \"ignorePhrase\": [],\n \"indexMode\": \"full\",\n \"intervalUpdateMetadata\": 3600,\n \"name\": \"\",\n \"path\": []\n }\n }\n\n this.handleSubmit = this.handleSubmit.bind(this)\n this.handleFormEdit = this.handleFormEdit.bind(this)\n }\n\n componentDidMount() {\n let id = this.props.match.params.name;\n if (id !== undefined) {\n fetch(`${API_URL}/index/get/${id}`)\n .then(res => res.json())\n .then((result) => {\n this.setState({ formData: result });\n });\n }\n\n }\n\n handleSubmit(event) {\n\n event.preventDefault();\n\n fetch(`${API_URL}/index/set`, {\n method: 'POST',\n body: JSON.stringify(this.state.formData),\n headers: { 'Content-Type': 'application/json' },\n })\n .then(response => {\n console.log(response)\n window.location = \"/gui/index\"\n })\n }\n\n handleFormEdit(event) {\n\n if (event.type !== \"change\") {\n return\n }\n\n let formData = this.state.formData\n\n switch (event.target.id) {\n case \"inputName\":\n formData.name = event.target.value.replace(/[^a-z0-9\\-]+/gi, \"\")\n break\n case \"inputPath\":\n formData.path = event.target.value.split(\",\")\n break\n case \"inputPathIgnore\":\n formData.ignorePath = event.target.value.split(\",\")\n break\n case \"inputPhraseIgnore\":\n formData.ignorePhrase = event.target.value.split(\",\")\n break\n case \"inputExtIgnore\":\n formData.ignoreExtension = event.target.value.split(\",\")\n break\n case \"inputUpdateStructure\":\n formData.intervalUpdateStructure = event.target.value.replace(/[^0-9]+/gi, \"\")\n break\n case \"inputExtractMetadata\":\n formData.extractMetadata = event.target.checked\n break\n }\n\n this.setState({ formData: formData })\n }\n\n render() {\n let id = this.props.match.params.name\n let formEditing = true\n if (id === undefined) {\n formEditing = false\n }\n\n return (\n
\n
\n
\n

{formEditing ? \"Edit\" : \"Create\"} index

\n
\n
\n \n
\n \n
\n
\n {/* Input desription */}\n
\n
\n\n
\n \n
\n \n
\n
\n Full path to index, you can add here multiple paths separate them with coma
eg. (/home/user/dir1,/home/user/dir2)
\n
\n
\n\n

Filter settings

\n\n
\n \n
\n \n
\n
\n Ignore paths from indexing separated by coma
eg. (/home/user/dir1/unwanted-path,/home/user/dir2/some/unwanted)
\n
\n
\n\n
\n \n
\n \n
\n
\n Ignore file/directory paths with phrase separated by coma. You can use * to match more files/directories
eg. (.git,vendor,attr*)
\n
\n
\n\n
\n \n
\n \n
\n
\n Ignore file extensions separated by coma
eg. (jpg,mp4,tmp)
\n
\n
\n\n\n

Reindex settings

\n\n
\n \n
\n \n
\n
\n Refresh directory structure interval in seconds.\n
\n
\n\n
\n \n
\n \n
\n
\n Enable this option when Filehunter should extract metadata/content from files and make it searchable\n
\n
\n\n
\n
\n Cancel\n \n
\n
\n\n\n
\n
\n
\n
\n )\n }\n}\n\nexport default withRouter(IndexForm)","import './App.css';\nimport \"bootstrap-icons/font/bootstrap-icons.css\";\nimport { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';\nimport Navbar from './Navbar.js';\nimport SearchForm from './Searchform.js';\nimport IndexInfo from './IndexInfo';\nimport IndexForm from './IndexForm';\n\nfunction App() {\n return (\n
\n
\n \n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n
\n
\n );\n}\n\nexport default App;\n\n","const reportWebVitals = onPerfEntry => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry);\n getFID(onPerfEntry);\n getFCP(onPerfEntry);\n getLCP(onPerfEntry);\n getTTFB(onPerfEntry);\n });\n }\n};\n\nexport default reportWebVitals;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport reportWebVitals from './reportWebVitals';\nimport 'bootstrap';\nimport 'bootstrap/dist/css/bootstrap.min.css';\n\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n);\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals();\n"],"sourceRoot":""} \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/static/js/main.61eb00ba.chunk.js b/src/main/resources/META-INF/resources/static/js/main.61eb00ba.chunk.js new file mode 100644 index 0000000..501a45d --- /dev/null +++ b/src/main/resources/META-INF/resources/static/js/main.61eb00ba.chunk.js @@ -0,0 +1,2 @@ +(this["webpackJsonpfilehunter-front"]=this["webpackJsonpfilehunter-front"]||[]).push([[0],{24:function(e,t,s){},25:function(e,t,s){},38:function(e,t,s){"use strict";s.r(t);var n=s(1),i=s.n(n),a=s(16),c=s.n(a),l=(s(24),s(25),s(26),s(19)),r=s(6),o=s(2),d=s(3),h=s(5),b=s(4),j=s(7),m=s(0),u=(i.a.Component,function(e){Object(h.a)(s,e);var t=Object(b.a)(s);function s(){return Object(o.a)(this,s),t.apply(this,arguments)}return Object(d.a)(s,[{key:"render",value:function(){return Object(m.jsx)("nav",{class:"navbar navbar-expand-lg navbar-light",children:Object(m.jsxs)("div",{class:"container-fluid",children:[Object(m.jsx)("span",{class:"badge bg-primary",children:"FH"})," ",Object(m.jsx)("a",{class:"navbar-brand",href:"/",children:"Filehunter"}),Object(m.jsx)("button",{class:"navbar-toggler",type:"button","data-bs-toggle":"collapse","data-bs-target":"#navbarSupportedContent","aria-controls":"navbarSupportedContent","aria-expanded":"false","aria-label":"Toggle navigation",children:Object(m.jsx)("span",{class:"navbar-toggler-icon"})}),Object(m.jsx)("div",{class:"collapse navbar-collapse",id:"navbarSupportedContent",children:Object(m.jsxs)("ul",{class:"navbar-nav ms-auto mb-1 mb-lg-0",children:[Object(m.jsx)("li",{class:"nav-item",children:Object(m.jsxs)("a",{class:"nav-link","aria-current":"page",href:"/",children:[Object(m.jsx)("i",{class:"bi bi-search"})," Search"]})}),Object(m.jsx)("li",{class:"nav-item",children:Object(m.jsxs)("a",{href:"/gui/index",class:"nav-link menu-item nav-active",children:[Object(m.jsx)("i",{class:"bi bi-folder2-open"})," Indexes"]})}),Object(m.jsx)("li",{class:"nav-item",children:Object(m.jsxs)("a",{rel:"noreferrer",href:"".concat("","/api-doc"),target:"_blank",class:"nav-link menu-item",children:[Object(m.jsx)("i",{class:"bi bi-code-slash"})," API Doc"]})}),Object(m.jsx)("li",{class:"nav-item",children:Object(m.jsxs)("a",{rel:"noreferrer",href:"https://github.com/Ogefest/filehunter",target:"_blank",class:"nav-link menu-item",children:[Object(m.jsx)("i",{class:"bi bi-github"})," Github"]})})]})})]})})}}]),s}(i.a.Component)),x=function(e){Object(h.a)(s,e);var t=Object(b.a)(s);function s(e){var n;return Object(o.a)(this,s),(n=t.call(this,e)).getColorByName=n.getColorByName.bind(Object(j.a)(n)),n}return Object(d.a)(s,[{key:"getColorByName",value:function(e){for(var t=0,s=0;s>8*s&255).toString(16)).substr(-2)}return n}},{key:"humanFileSize",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2,n=t?1e3:1024;if(Math.abs(e)=n&&a\n
\n FH Filehunter\n \n
\n \n
\n
\n \n\n )\n }\n}\n\nexport default Navbar;","import React from 'react';\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass SystemTaskStatus extends React.Component {\n constructor(props) {\n super(props)\n\n this.refreshInterval = 10000\n this.refreshStatus = this.refreshStatus.bind(this)\n } \n \n componentDidMount() {\n this.refreshStatus()\n }\n\n refreshStatus() {\n fetch(`${API_URL}/system/status`)\n .then(res => res.json())\n .then((result) => {\n this.result = result;\n\n setTimeout(this.refreshStatus, this.refreshInterval)\n this.setState({});\n });\n }\n\n render() {\n\n if (this.result === undefined) {\n return(\"\")\n }\n if (this.result.currentTask !== \"\") {\n this.refreshInterval = 1000\n } else {\n this.refreshInterval = 10000\n return(\"\")\n }\n\n return(\n Task {this.result.currentTask}\n )\n }\n}\n\nexport default SystemTaskStatus","import React from 'react';\nconst API_URL = process.env.REACT_APP_API_URL\n\n\nclass SearchResultRow extends React.Component {\n\n constructor(props) {\n super(props)\n\n this.getColorByName = this.getColorByName.bind(this)\n }\n\n getColorByName(str) {\n var hash = 0;\n for (var i = 0; i < str.length; i++) {\n hash = str.charCodeAt(i) + ((hash << 5) - hash);\n }\n var colour = '#';\n for (var i = 0; i < 3; i++) {\n var value = (hash >> (i * 8)) & 0xFF;\n colour += ('00' + value.toString(16)).substr(-2);\n }\n return colour;\n } \n \n humanFileSize(bytes, si=true, dp=2) {\n const thresh = si ? 1000 : 1024;\n \n if (Math.abs(bytes) < thresh) {\n return bytes + ' B';\n }\n \n const units = si \n ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] \n : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];\n let u = -1;\n const r = 10**dp;\n \n do {\n bytes /= thresh;\n ++u;\n } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);\n \n \n return bytes.toFixed(dp) + ' ' + units[u];\n } \n\n render() {\n let iconclass = \"bi-file-earmark\"\n if (this.props.params.type === 'd') {\n iconclass = \"bi-folder2\"\n }\n\n let badgeColor = this.getColorByName(this.props.params.indexname)\n let fileSize = this.humanFileSize(this.props.params.size)\n\n return (\n
\n \n {/*
{this.props.params.name}
*/}\n \n
\n
\n \n \n {/* {this.props.params.indexname} */}\n \n {this.props.params.name}\n {this.props.params.indexname}\n {/* {this.props.params.indexname} */}\n {fileSize}\n
\n
\n \n
\n \n {this.props.params.path}\n
\n \n
\n )\n }\n \n}\n\nexport default SearchResultRow","import React from \"react\";\n\nclass EmptySearchResult extends React.Component {\n\n render() {\n return (\n
\n
\n
\n\n\n
\n Empty search results\n
\n\n
\n
\n
\n )\n }\n\n}\n\nexport default EmptySearchResult","import React from 'react'\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass SearchAdvanced extends React.Component {\n\n constructor(props) {\n super(props)\n this.indexList = []\n this.indexName = \"\"\n this.extension = \"\"\n this.minmultiplier = 1024 * 1024\n this.maxmultiplier = 1024 * 1024\n\n this.filters = { minsize: 0, maxsize: 0 }\n\n this.state = {\n filters: {\n minsize: 0, maxsize: 0\n },\n }\n\n }\n\n componentDidMount() {\n fetch(`${API_URL}/index/list`)\n .then(res => res.json())\n .then((result) => {\n this.indexList = result;\n this.requestFinished = true\n this.setState({ filters: this.filters })\n });\n }\n\n handleAdvancedFilterChange(e) {\n\n let k = e.target.name;\n let v = e.target.value;\n\n if (v.trim().length == 0) {\n delete this.filters[k]\n } else {\n if (k === 'modified_after' || k === 'modified_before') {\n v = Date.parse(v)\n }\n\n this.filters[k] = v;\n }\n if (k === \"maxsize\" && v != '0') {\n this.filters[k] = parseInt(v) * this.maxmultiplier;\n }\n if (k === \"minsize\" && v != '0') {\n this.filters[k] = parseInt(v) * this.minmultiplier;\n }\n\n this.props.update(this.filters)\n this.setState({ filters: this.filters })\n }\n\n handleUiHelper(e) {\n\n if (e.target.name === \"maxmultiplier\") {\n this.maxmultiplier = parseInt(e.target.value)\n }\n if (e.target.name === \"minmultiplier\") {\n this.minmultiplier = parseInt(e.target.value)\n }\n\n if (e.target.name === 'maxsizerange') {\n this.filters['maxsize'] = parseInt(e.target.value) * this.maxmultiplier\n }\n if (e.target.name === 'minsizerange') {\n this.filters['minsize'] = parseInt(e.target.value) * this.minmultiplier\n }\n\n this.props.update(this.filters)\n this.setState({ filters: this.filters })\n }\n\n render() {\n return (\n
\n
\n\n
\n \n
\n
\n\n \n
\n\n
\n\n\n
\n\n
\n \n
\n
\n \n
\n\n
\n\n\n
\n\n
\n \n
\n
\n \n
\n\n
\n\n\n
\n\n
\n \n
\n
\n \n
\n\n
\n\n
\n\n
\n \n
\n
\n \n
\n\n
\n\n
\n\n
\n \n
\n
\n \n
\n
\n \n
\n\n
\n\n
\n\n
\n \n
\n
\n \n\n
\n
\n \n
\n
\n \n
\n\n
\n\n
\n\n
\n \n
\n
\n \n\n
\n
\n \n
\n
\n \n
\n\n
\n\n\n
\n\n )\n }\n}\n\nexport default SearchAdvanced","import React from 'react';\nimport SearchResultRow from './SearchResultRow.js'\nimport EmptySearchResult from './EmptySearchResult.js';\nimport SearchAdvanced from './SearchAdvanced.js';\nconst API_URL = process.env.REACT_APP_API_URL\n\n\nclass SearchForm extends React.Component {\n\n constructor(props) {\n super(props);\n this.state = {\n value: null,\n searchResultRows: []\n };\n this.sr = []\n this.lastQuery = \"\"\n this.currentQuery = \"\"\n // this.advancedFilterQuery = \"\"\n this.activeQuery = false\n this.searchTimeout = null\n this.advancedFilters = {}\n\n this.updateAdvancedFilterQuery = this.updateAdvancedFilterQuery.bind(this)\n\n }\n\n componentDidMount() {\n // this.intervalId = setInterval(this.handleSearch.bind(this), 500);\n }\n componentWillUnmount() {\n clearInterval(this.intervalId)\n }\n\n updateAdvancedFilterQuery(s) {\n this.advancedFilters = s\n\n // let asd = new URLSearchParams(s).toString();\n\n\n // if (this.currentQuery == \"\") {\n // this.advancedFilterQuery = this.advancedFilterQuery.trim().substring(3)\n // }\n\n this.handleSearch()\n }\n\n handleSearch() {\n\n let combinedQuery = this.currentQuery;\n let qs = Object.keys(this.advancedFilters)\n .map(key => `filter[${encodeURIComponent(key)}]=${encodeURIComponent(this.advancedFilters[key])}`)\n .join('&');\n\n\n if (combinedQuery === \"\" || combinedQuery === this.lastQuery) {\n return;\n }\n if (this.activeQuery === true) {\n return;\n }\n this.activeQuery = true\n\n // console.log(this.advancedFilters);\n\n // let asd = new URLSearchParams(this.advancedFilters).toString();\n\n\n\n\n fetch(`${API_URL}/search?q=${encodeURIComponent(combinedQuery)}&${qs}`)\n .then(res => res.json())\n .then((result) => {\n this.lastQuery = combinedQuery + qs;\n this.activeQuery = false;\n\n this.sr = []\n result.map((item) => (\n this.sr.push()\n ))\n if (this.sr.length === 0) {\n this.sr.push()\n }\n\n this.setState({ searchResultRows: this.sr })\n })\n }\n\n handleInputChange(e) {\n this.currentQuery = e.target.value\n if (this.searchTimeout != null) {\n clearTimeout(this.searchTimeout)\n }\n this.searchTimeout = setTimeout(this.handleSearch.bind(this), 300);\n }\n\n render() {\n return (\n
\n
\n
\n
\n \n \n \n
\n
\n
\n\n
\n\n
\n \n
\n\n
\n {this.state.searchResultRows}\n
\n\n
\n
\n )\n }\n}\n\nexport default SearchForm","import React from 'react'\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass ReindexState extends React.Component {\n\n\n constructor(props) {\n super(props)\n console.log(props)\n\n this.state = { clicked: false }\n\n this.handleClick = this.handleClick.bind(this)\n }\n\n handleClick() {\n\n if (this.state.clicked === true) {\n return\n }\n\n fetch(`${API_URL}/index/reindex/${this.props.indextype}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n })\n .then(response => {\n this.setState({ clicked: true })\n })\n\n return false\n }\n\n render() {\n // console.log(this.state.clicked)\n\n return (\n \n )\n }\n\n}\n\nexport default ReindexState","import React from \"react\";\n\nclass EmptyIndexList extends React.Component {\n\n render() {\n return (\n
\n\n\n
\n
\n\n\n
\n You have no indexed directories. Click button below to add directory.\n
\n\n \n\n
\n
\n
\n )\n }\n\n}\n\nexport default EmptyIndexList","import React from 'react';\nimport ReindexState from './ReindexState';\nimport EmptyIndexList from './EmptyIndexList';\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass IndexInfo extends React.Component {\n\n // const history = useHistory()\n\n constructor(props) {\n super(props)\n\n this.result = []\n this.requestFinished = false\n\n this.handleRemove = this.handleRemove.bind(this)\n\n }\n\n componentDidMount() {\n this.refreshList()\n\n }\n\n refreshList() {\n fetch(`${API_URL}/index/list`)\n .then(res => res.json())\n .then((result) => {\n this.result = result;\n this.requestFinished = true\n this.setState({});\n });\n }\n\n\n handleRemove(row) {\n if (window.confirm(\"Are you sure?\")) {\n\n fetch(`${API_URL}/index/remove/${row.name}`, {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' }, \n })\n .then(res => res.json())\n .then((result) => {\n this.result = result;\n this.setState({});\n }); \n }\n return false\n }\n\n render() {\n\n if (this.requestFinished === false) {\n return(\"\")\n }\n\n if (this.result.length === 0) {\n return (\n \n )\n }\n\n return (\n \n
\n
\n
\n

List of indexes New

\n \n \n \n \n \n \n \n \n \n \n \n {this.result.map(directoryRow => (\n \n \n \n \n \n\n \n \n ))}\n \n
NamePathsIgnoreLast indexed 
{directoryRow.name}\n {directoryRow.path.map(pathRow => (\n {pathRow}\n ))}\n \n {directoryRow.ignorePath.map(pathRow => (\n {pathRow}\n ))}\n {directoryRow.ignorePhrase.map(pathRow => (\n *{pathRow}*\n ))} \n {directoryRow.ignoreExtension.map(pathRow => (\n *.{pathRow}\n ))}\n \n {new Date(directoryRow.lastStructureIndexed).toLocaleDateString()}\n  \n {new Date(directoryRow.lastStructureIndexed).toLocaleTimeString()}\n \n \n this.handleRemove(directoryRow)} href=\"#\" class=\"btn btn-danger btn-sm me-1\">\n \n
\n
\n
\n\n
\n\n )\n }\n}\n\nexport default IndexInfo","import React from 'react';\nimport { withRouter } from \"react-router\";\nconst API_URL = process.env.REACT_APP_API_URL\n\n\nclass IndexForm extends React.Component {\n constructor(props) {\n super(props)\n\n this.state = {\n formData: {\n \"extractMetadata\": true,\n \"ignoreExtension\": [],\n \"ignorePath\": [],\n \"ignorePhrase\": [],\n \"indexMode\": \"full\",\n \"intervalUpdateMetadata\": 3600,\n \"name\": \"\",\n \"path\": []\n }\n }\n\n this.handleSubmit = this.handleSubmit.bind(this)\n this.handleFormEdit = this.handleFormEdit.bind(this)\n }\n\n componentDidMount() {\n let id = this.props.match.params.name;\n if (id !== undefined) {\n fetch(`${API_URL}/index/get/${id}`)\n .then(res => res.json())\n .then((result) => {\n this.setState({ formData: result });\n });\n }\n\n }\n\n handleSubmit(event) {\n\n event.preventDefault();\n\n fetch(`${API_URL}/index/set`, {\n method: 'POST',\n body: JSON.stringify(this.state.formData),\n headers: { 'Content-Type': 'application/json' },\n })\n .then(response => {\n console.log(response)\n window.location = \"/gui/index\"\n })\n }\n\n handleFormEdit(event) {\n\n if (event.type !== \"change\") {\n return\n }\n\n let formData = this.state.formData\n\n switch (event.target.id) {\n case \"inputName\":\n formData.name = event.target.value.replace(/[^a-z0-9\\-]+/gi, \"\")\n break\n case \"inputPath\":\n formData.path = event.target.value.split(\",\")\n break\n case \"inputPathIgnore\":\n formData.ignorePath = event.target.value.split(\",\")\n break\n case \"inputPhraseIgnore\":\n formData.ignorePhrase = event.target.value.split(\",\")\n break\n case \"inputExtIgnore\":\n formData.ignoreExtension = event.target.value.split(\",\")\n break\n case \"inputUpdateStructure\":\n formData.intervalUpdateStructure = event.target.value.replace(/[^0-9]+/gi, \"\")\n break\n case \"inputExtractMetadata\":\n formData.extractMetadata = event.target.checked\n break\n }\n\n this.setState({ formData: formData })\n }\n\n render() {\n let id = this.props.match.params.name\n let formEditing = true\n if (id === undefined) {\n formEditing = false\n }\n\n return (\n
\n
\n
\n

{formEditing ? \"Edit\" : \"Create\"} index

\n
\n
\n \n
\n \n
\n
\n {/* Input desription */}\n
\n
\n\n
\n \n
\n \n
\n
\n Full path to index, you can add here multiple paths separate them with coma
eg. (/home/user/dir1,/home/user/dir2)
\n
\n
\n\n

Filter settings

\n\n
\n \n
\n \n
\n
\n Ignore paths from indexing separated by coma
eg. (/home/user/dir1/unwanted-path,/home/user/dir2/some/unwanted)
\n
\n
\n\n
\n \n
\n \n
\n
\n Ignore file/directory paths with phrase separated by coma. You can use * to match more files/directories
eg. (.git,vendor,attr*)
\n
\n
\n\n
\n \n
\n \n
\n
\n Ignore file extensions separated by coma
eg. (jpg,mp4,tmp)
\n
\n
\n\n\n

Reindex settings

\n\n
\n \n
\n \n
\n
\n Refresh directory structure interval in seconds.\n
\n
\n\n
\n \n
\n \n
\n
\n Enable this option when Filehunter should extract metadata/content from files and make it searchable\n
\n
\n\n
\n
\n Cancel\n \n
\n
\n\n\n
\n
\n
\n
\n )\n }\n}\n\nexport default withRouter(IndexForm)","import './App.css';\nimport \"bootstrap-icons/font/bootstrap-icons.css\";\nimport { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';\nimport Navbar from './Navbar.js';\nimport SearchForm from './Searchform.js';\nimport IndexInfo from './IndexInfo';\nimport IndexForm from './IndexForm';\n\nfunction App() {\n return (\n
\n
\n \n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n
\n
\n );\n}\n\nexport default App;\n\n","const reportWebVitals = onPerfEntry => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry);\n getFID(onPerfEntry);\n getFCP(onPerfEntry);\n getLCP(onPerfEntry);\n getTTFB(onPerfEntry);\n });\n }\n};\n\nexport default reportWebVitals;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport reportWebVitals from './reportWebVitals';\nimport 'bootstrap';\nimport 'bootstrap/dist/css/bootstrap.min.css';\n\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n);\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals();\n"],"sourceRoot":""} \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/static/js/main.6c323a16.chunk.js b/src/main/resources/META-INF/resources/static/js/main.6c323a16.chunk.js deleted file mode 100644 index 67c702b..0000000 --- a/src/main/resources/META-INF/resources/static/js/main.6c323a16.chunk.js +++ /dev/null @@ -1,2 +0,0 @@ -(this["webpackJsonpfilehunter-front"]=this["webpackJsonpfilehunter-front"]||[]).push([[0],{24:function(e,t,n){},25:function(e,t,n){},38:function(e,t,n){"use strict";n.r(t);var s=n(1),a=n.n(s),c=n(16),i=n.n(c),r=(n(24),n(25),n(26),n(19)),l=n(6),o=n(2),d=n(3),h=n(5),j=n(4),b=n(7),u=n(0),x=function(e){Object(h.a)(n,e);var t=Object(j.a)(n);function n(e){var s;return Object(o.a)(this,n),(s=t.call(this,e)).refreshInterval=1e4,s.refreshStatus=s.refreshStatus.bind(Object(b.a)(s)),s}return Object(d.a)(n,[{key:"componentDidMount",value:function(){this.refreshStatus()}},{key:"refreshStatus",value:function(){var e=this;fetch("".concat("","/system/status")).then((function(e){return e.json()})).then((function(t){e.result=t,setTimeout(e.refreshStatus,e.refreshInterval),e.setState({})}))}},{key:"render",value:function(){return void 0===this.result?"":""===this.result.currentTask?(this.refreshInterval=1e4,""):(this.refreshInterval=1e3,Object(u.jsxs)("span",{class:"badge bg-success",children:["Task ",this.result.currentTask]}))}}]),n}(a.a.Component),m=function(e){Object(h.a)(n,e);var t=Object(j.a)(n);function n(){return Object(o.a)(this,n),t.apply(this,arguments)}return Object(d.a)(n,[{key:"render",value:function(){return Object(u.jsx)("nav",{class:"navbar navbar-expand-lg navbar-light",children:Object(u.jsxs)("div",{class:"container-fluid",children:[Object(u.jsx)("span",{class:"badge bg-primary",children:"FH"})," ",Object(u.jsx)("a",{class:"navbar-brand",href:"/",children:"Filehunter"}),Object(u.jsx)("button",{class:"navbar-toggler",type:"button","data-bs-toggle":"collapse","data-bs-target":"#navbarSupportedContent","aria-controls":"navbarSupportedContent","aria-expanded":"false","aria-label":"Toggle navigation",children:Object(u.jsx)("span",{class:"navbar-toggler-icon"})}),Object(u.jsxs)("div",{class:"collapse navbar-collapse",id:"navbarSupportedContent",children:[Object(u.jsxs)("ul",{class:"navbar-nav ms-auto mb-1 mb-lg-0",children:[Object(u.jsx)("li",{class:"nav-item",children:Object(u.jsxs)("a",{class:"nav-link","aria-current":"page",href:"/",children:[Object(u.jsx)("i",{class:"bi bi-search"})," Search"]})}),Object(u.jsx)("li",{class:"nav-item",children:Object(u.jsxs)("a",{href:"/gui/index",class:"nav-link menu-item nav-active",children:[Object(u.jsx)("i",{class:"bi bi-folder2-open"})," Indexes"]})}),Object(u.jsx)("li",{class:"nav-item",children:Object(u.jsxs)("a",{rel:"noreferrer",href:"".concat("","/api-doc"),target:"_blank",class:"nav-link menu-item",children:[Object(u.jsx)("i",{class:"bi bi-code-slash"})," API Doc"]})}),Object(u.jsx)("li",{class:"nav-item",children:Object(u.jsxs)("a",{rel:"noreferrer",href:"https://github.com/Ogefest/filehunter",target:"_blank",class:"nav-link menu-item",children:[Object(u.jsx)("i",{class:"bi bi-github"})," Github"]})})]}),Object(u.jsx)(x,{})]})]})})}}]),n}(a.a.Component),p=function(e){Object(h.a)(n,e);var t=Object(j.a)(n);function n(e){var s;return Object(o.a)(this,n),(s=t.call(this,e)).getColorByName=s.getColorByName.bind(Object(b.a)(s)),s}return Object(d.a)(n,[{key:"getColorByName",value:function(e){for(var t=0,n=0;n>8*n&255).toString(16)).substr(-2)}return s}},{key:"render",value:function(){var e="bi-file-earmark";"d"===this.props.params.type&&(e="bi-folder2");this.getColorByName(this.props.params.indexname);return Object(u.jsxs)("div",{class:"row mb-3",children:[Object(u.jsxs)("h5",{children:[Object(u.jsx)("i",{class:"bi ".concat(e)})," ",Object(u.jsx)("a",{rel:"noreferrer",target:"_blank",href:"".concat("","/download/").concat(this.props.params.uuid),children:this.props.params.name})]}),Object(u.jsx)("small",{class:"text-success",children:this.props.params.path})]},this.props.params.uuid)}}]),n}(a.a.Component),O=function(e){Object(h.a)(n,e);var t=Object(j.a)(n);function n(){return Object(o.a)(this,n),t.apply(this,arguments)}return Object(d.a)(n,[{key:"render",value:function(){return Object(u.jsx)("div",{class:"container",children:Object(u.jsx)("div",{class:"row",children:Object(u.jsx)("div",{class:"col-8 offset-4",children:Object(u.jsx)("div",{class:"alert alert-info col-md-12 col-md-offset-12",align:"center",children:"Empty search results"})})},"empty-results")})}}]),n}(a.a.Component),f=function(e){Object(h.a)(n,e);var t=Object(j.a)(n);function n(e){var s;return Object(o.a)(this,n),(s=t.call(this,e)).indexList=[],s.indexName="",s.extension="",s}return Object(d.a)(n,[{key:"componentDidMount",value:function(){var e=this;fetch("".concat("","/index/list")).then((function(e){return e.json()})).then((function(t){e.indexList=t,e.requestFinished=!0,e.setState({})}))}},{key:"handleIndexNameChange",value:function(e){this.indexName=e.target.value,this.handleAddFilters()}},{key:"handleExtensionChange",value:function(e){this.extension=e.target.value,this.handleAddFilters()}},{key:"handleAddFilters",value:function(){var e="";""!==this.indexName&&(e+=" AND indexname:"+this.indexName+" "),""!==this.extension&&(e+=" AND ext:"+this.extension+" "),this.props.update(e)}},{key:"render",value:function(){return Object(u.jsx)("div",{children:Object(u.jsxs)("div",{class:"row",id:"",children:[Object(u.jsx)("div",{class:"col-3",children:Object(u.jsxs)("div",{class:"input-group input-group-sm mb-3",children:[Object(u.jsx)("label",{class:"input-group-text",for:"selectIndexname",children:"Index"}),Object(u.jsxs)("select",{onChange:this.handleIndexNameChange.bind(this),id:"selectIndexname",class:"form-select form-select-sm","aria-label":"Index name",children:[Object(u.jsx)("option",{}),this.indexList.map((function(e){return Object(u.jsx)("option",{value:e.name,children:e.name})}))]})]})}),Object(u.jsx)("div",{class:"col-3",children:Object(u.jsxs)("div",{class:"input-group input-group-sm mb-3",children:[Object(u.jsx)("label",{class:"input-group-text",for:"inputExtension",children:"Extension"}),Object(u.jsx)("input",{onChange:this.handleExtensionChange.bind(this),type:"text",class:"form-control","aria-label":"extension","aria-describedby":"extension"})]})})]})})}}]),n}(a.a.Component),v=function(e){Object(h.a)(n,e);var t=Object(j.a)(n);function n(e){var s;return Object(o.a)(this,n),(s=t.call(this,e)).state={value:null,searchResultRows:[]},s.sr=[],s.lastQuery="",s.currentQuery="",s.advancedFilterQuery="",s.activeQuery=!1,s.searchTimeout=null,s.updateAdvancedFilterQuery=s.updateAdvancedFilterQuery.bind(Object(b.a)(s)),s}return Object(d.a)(n,[{key:"componentDidMount",value:function(){}},{key:"componentWillUnmount",value:function(){clearInterval(this.intervalId)}},{key:"updateAdvancedFilterQuery",value:function(e){this.advancedFilterQuery=e,""==this.currentQuery&&(this.advancedFilterQuery=this.advancedFilterQuery.trim().substring(3)),this.handleSearch()}},{key:"handleSearch",value:function(){var e=this,t=this.currentQuery+" "+this.advancedFilterQuery;""!==t&&t!==this.lastQuery&&!0!==this.activeQuery&&(this.activeQuery=!0,fetch("".concat("","/search?q=").concat(encodeURIComponent(t))).then((function(e){return e.json()})).then((function(n){e.lastQuery=t,e.activeQuery=!1,e.sr=[],n.map((function(t){return e.sr.push(Object(u.jsx)(p,{params:t}))})),0===e.sr.length&&e.sr.push(Object(u.jsx)(O,{})),e.setState({searchResultRows:e.sr})})))}},{key:"handleInputChange",value:function(e){this.currentQuery=e.target.value,null!=this.searchTimeout&&clearTimeout(this.searchTimeout),this.searchTimeout=setTimeout(this.handleSearch.bind(this),300)}},{key:"render",value:function(){return Object(u.jsxs)("div",{class:"container mt-5",children:[Object(u.jsx)("div",{class:"row",children:Object(u.jsx)("div",{class:"col-8 offset-2",children:Object(u.jsxs)("div",{class:"input-group mb-3",children:[Object(u.jsx)("input",{autoFocus:!0,type:"text",class:"form-control",placeholder:"Search for files","aria-label":"Search for files","aria-describedby":"button-addon2",onChange:this.handleInputChange.bind(this)}),Object(u.jsx)("button",{class:"btn btn-primary",type:"button",onClick:this.handleSearch.bind(this),children:Object(u.jsx)("i",{class:"bi bi-search"})}),Object(u.jsx)("button",{class:"btn btn-outline-secondary",type:"button","data-bs-toggle":"collapse","data-bs-target":"#filtersForm",children:Object(u.jsx)("i",{class:"bi bi-filter"})})]})})}),Object(u.jsx)("div",{class:"row collapse mb-3",id:"filtersForm",children:Object(u.jsx)("div",{class:"col-8 offset-2",children:Object(u.jsx)(f,{update:this.updateAdvancedFilterQuery})})}),Object(u.jsx)("div",{class:"row",children:Object(u.jsx)("div",{class:"col-6 offset-2",children:this.state.searchResultRows})})]})}}]),n}(a.a.Component),g=function(e){Object(h.a)(n,e);var t=Object(j.a)(n);function n(e){var s;return Object(o.a)(this,n),s=t.call(this,e),console.log(e),s.state={clicked:!1},s.handleClick=s.handleClick.bind(Object(b.a)(s)),s}return Object(d.a)(n,[{key:"handleClick",value:function(){var e=this;if(!0!==this.state.clicked)return fetch("".concat("","/index/reindex/").concat(this.props.indextype),{method:"POST",headers:{"Content-Type":"application/json"}}).then((function(t){e.setState({clicked:!0})})),!1}},{key:"render",value:function(){return Object(u.jsx)("button",{"data-placement":"top",title:"Reindex",class:"btn btn-sm btn-success",href:"#",onClick:this.handleClick,children:Object(u.jsx)("i",{class:"bi bi-arrow-repeat"})})}}]),n}(a.a.Component),y=function(e){Object(h.a)(n,e);var t=Object(j.a)(n);function n(){return Object(o.a)(this,n),t.apply(this,arguments)}return Object(d.a)(n,[{key:"render",value:function(){return Object(u.jsx)("div",{class:"container mt-5",children:Object(u.jsx)("div",{class:"row",children:Object(u.jsxs)("div",{class:"col-6 offset-3",children:[Object(u.jsx)("div",{class:"alert alert-info col-md-12 col-md-offset-12",align:"center",children:"You have no indexed directories. Click button below to add directory."}),Object(u.jsx)("div",{align:"center",children:Object(u.jsxs)("a",{href:"/gui/index/create",class:"btn btn-lg btn-success",children:[Object(u.jsx)("i",{class:"bi bi-plus"})," Create new index"]})})]})},"empty-results")})}}]),n}(a.a.Component),k=function(e){Object(h.a)(n,e);var t=Object(j.a)(n);function n(e){var s;return Object(o.a)(this,n),(s=t.call(this,e)).result=[],s.requestFinished=!1,s.handleRemove=s.handleRemove.bind(Object(b.a)(s)),s}return Object(d.a)(n,[{key:"componentDidMount",value:function(){this.refreshList()}},{key:"refreshList",value:function(){var e=this;fetch("".concat("","/index/list")).then((function(e){return e.json()})).then((function(t){e.result=t,e.requestFinished=!0,e.setState({})}))}},{key:"handleRemove",value:function(e){var t=this;return window.confirm("Are you sure?")&&fetch("".concat("","/index/remove/").concat(e.name),{method:"DELETE",headers:{"Content-Type":"application/json"}}).then((function(e){return e.json()})).then((function(e){t.result=e,t.setState({})})),!1}},{key:"render",value:function(){var e=this;return!1===this.requestFinished?"":0===this.result.length?Object(u.jsx)(y,{}):Object(u.jsx)("div",{class:"container mt-5",children:Object(u.jsx)("div",{class:"row",children:Object(u.jsxs)("div",{class:"col-10 offset-1",children:[Object(u.jsxs)("h3",{children:["List of indexes ",Object(u.jsxs)("a",{href:"/gui/index/create",class:"btn btn-success btn-sm",children:[Object(u.jsx)("i",{class:"bi bi-plus"})," New"]})]}),Object(u.jsxs)("table",{class:"table",children:[Object(u.jsx)("thead",{children:Object(u.jsxs)("tr",{children:[Object(u.jsx)("th",{children:"Name"}),Object(u.jsx)("th",{children:"Paths"}),Object(u.jsx)("th",{children:"Ignore"}),Object(u.jsx)("th",{children:"Last indexed"}),Object(u.jsx)("th",{children:"\xa0"})]})}),Object(u.jsx)("tbody",{children:this.result.map((function(t){return Object(u.jsxs)("tr",{children:[Object(u.jsxs)("td",{children:[Object(u.jsx)("i",{class:"bi bi-folder2-open"})," ",t.name]}),Object(u.jsx)("td",{children:t.path.map((function(e){return Object(u.jsx)("small",{class:"badge bg-primary ms-1",children:e})}))}),Object(u.jsxs)("td",{children:[t.ignorePath.map((function(e){return Object(u.jsx)("small",{class:"badge bg-secondary ms-1",children:e})})),t.ignorePhrase.map((function(e){return Object(u.jsxs)("small",{class:"badge bg-secondary ms-1",children:["*",e,"*"]})})),t.ignoreExtension.map((function(e){return Object(u.jsxs)("small",{class:"badge bg-secondary ms-1",children:["*.",e]})}))]}),Object(u.jsxs)("td",{children:[new Date(t.lastStructureIndexed).toLocaleDateString(),"\xa0",new Date(t.lastStructureIndexed).toLocaleTimeString()]}),Object(u.jsxs)("td",{children:[Object(u.jsx)("a",{"data-placement":"top",title:"Edit",href:"/gui/index/edit/".concat(t.name),class:"btn btn-light btn-sm me-1",children:Object(u.jsx)("i",{class:"bi bi-pencil"})}),Object(u.jsx)("a",{"data-placement":"top",title:"Remove",onClick:function(){return e.handleRemove(t)},href:"#",class:"btn btn-danger btn-sm me-1",children:Object(u.jsx)("i",{class:"bi bi-trash"})}),Object(u.jsx)(g,{indextype:t.name})]})]})}))})]})]})})})}}]),n}(a.a.Component),C=function(e){Object(h.a)(n,e);var t=Object(j.a)(n);function n(e){var s;return Object(o.a)(this,n),(s=t.call(this,e)).state={formData:{extractMetadata:!0,ignoreExtension:[],ignorePath:[],ignorePhrase:[],indexMode:"full",intervalUpdateMetadata:3600,name:"",path:[]}},s.handleSubmit=s.handleSubmit.bind(Object(b.a)(s)),s.handleFormEdit=s.handleFormEdit.bind(Object(b.a)(s)),s}return Object(d.a)(n,[{key:"componentDidMount",value:function(){var e=this,t=this.props.match.params.name;void 0!==t&&fetch("".concat("","/index/get/").concat(t)).then((function(e){return e.json()})).then((function(t){e.setState({formData:t})}))}},{key:"handleSubmit",value:function(e){e.preventDefault(),fetch("".concat("","/index/set"),{method:"POST",body:JSON.stringify(this.state.formData),headers:{"Content-Type":"application/json"}}).then((function(e){console.log(e),window.location="/gui/index"}))}},{key:"handleFormEdit",value:function(e){if("change"===e.type){var t=this.state.formData;switch(e.target.id){case"inputName":t.name=e.target.value.replace(/[^a-z0-9\-]+/gi,"");break;case"inputPath":t.path=e.target.value.split(",");break;case"inputPathIgnore":t.ignorePath=e.target.value.split(",");break;case"inputPhraseIgnore":t.ignorePhrase=e.target.value.split(",");break;case"inputExtIgnore":t.ignoreExtension=e.target.value.split(",");break;case"inputUpdateStructure":t.intervalUpdateStructure=e.target.value.replace(/[^0-9]+/gi,"");break;case"inputExtractMetadata":t.extractMetadata=e.target.checked}this.setState({formData:t})}}},{key:"render",value:function(){var e=!0;return void 0===this.props.match.params.name&&(e=!1),Object(u.jsx)("div",{class:"container mt-5",children:Object(u.jsx)("div",{class:"row",children:Object(u.jsxs)("div",{class:"col-10 offset-1",children:[Object(u.jsxs)("h1",{children:[e?"Edit":"Create"," index"]}),Object(u.jsxs)("form",{onSubmit:this.handleSubmit,children:[Object(u.jsxs)("div",{class:"row mb-3",children:[Object(u.jsx)("label",{for:"inputName",class:"col-sm-3 col-form-label",children:"Index name"}),Object(u.jsx)("div",{class:"col-sm-5",children:Object(u.jsx)("input",{value:this.state.formData.name,onChange:this.handleFormEdit,type:"text",class:"form-control",id:"inputName"})}),Object(u.jsx)("div",{class:"col-sm-4"})]}),Object(u.jsxs)("div",{class:"row mb-3",children:[Object(u.jsx)("label",{for:"inputPath",class:"col-sm-3 col-form-label",children:"Path to index"}),Object(u.jsx)("div",{class:"col-sm-5",children:Object(u.jsx)("input",{value:this.state.formData.path.join(","),onChange:this.handleFormEdit,type:"text",class:"form-control",id:"inputPath"})}),Object(u.jsx)("div",{class:"col-sm-4",children:Object(u.jsxs)("small",{class:"text-muted",children:["Full path to index, you can add here multiple paths separate them with coma ",Object(u.jsx)("br",{}),"eg. (/home/user/dir1,/home/user/dir2)"]})})]}),Object(u.jsx)("h4",{children:"Filter settings"}),Object(u.jsxs)("div",{class:"row mb-3",children:[Object(u.jsx)("label",{for:"inputPathIgnore",class:"col-sm-3 col-form-label",children:"Ignore path"}),Object(u.jsx)("div",{class:"col-sm-5",children:Object(u.jsx)("input",{value:this.state.formData.ignorePath.join(","),onChange:this.handleFormEdit,type:"text",class:"form-control",id:"inputPathIgnore"})}),Object(u.jsx)("div",{class:"col-sm-4",children:Object(u.jsxs)("small",{class:"text-muted",children:["Ignore paths from indexing separated by coma ",Object(u.jsx)("br",{}),"eg. (/home/user/dir1/unwanted-path,/home/user/dir2/some/unwanted)"]})})]}),Object(u.jsxs)("div",{class:"row mb-3",children:[Object(u.jsx)("label",{for:"inputPhraseIgnore",class:"col-sm-3 col-form-label",children:"Ignore phrase"}),Object(u.jsx)("div",{class:"col-sm-5",children:Object(u.jsx)("input",{value:this.state.formData.ignorePhrase.join(","),onChange:this.handleFormEdit,type:"text",class:"form-control",id:"inputPhraseIgnore"})}),Object(u.jsx)("div",{class:"col-sm-4",children:Object(u.jsxs)("small",{class:"text-muted",children:["Ignore file/directory paths with phrase separated by coma. You can use * to match more files/directories ",Object(u.jsx)("br",{}),"eg. (.git,vendor,attr*)"]})})]}),Object(u.jsxs)("div",{class:"row mb-3",children:[Object(u.jsx)("label",{for:"inputExtIgnore",class:"col-sm-3 col-form-label",children:"Ignore extensions"}),Object(u.jsx)("div",{class:"col-sm-5",children:Object(u.jsx)("input",{value:this.state.formData.ignoreExtension.join(","),onChange:this.handleFormEdit,type:"text",class:"form-control",id:"inputExtIgnore"})}),Object(u.jsx)("div",{class:"col-sm-4",children:Object(u.jsxs)("small",{class:"text-muted",children:["Ignore file extensions separated by coma ",Object(u.jsx)("br",{}),"eg. (jpg,mp4,tmp)"]})})]}),Object(u.jsx)("h4",{children:"Reindex settings"}),Object(u.jsxs)("div",{class:"row mb-3",children:[Object(u.jsx)("label",{for:"inputUpdateStructure",class:"col-sm-3 col-form-label",children:"File structure interval"}),Object(u.jsx)("div",{class:"col-sm-5",children:Object(u.jsx)("input",{value:this.state.formData.intervalUpdateStructure,onChange:this.handleFormEdit,type:"text",class:"form-control",id:"inputUpdateStructure"})}),Object(u.jsx)("div",{class:"col-sm-4",children:Object(u.jsx)("small",{class:"text-muted",children:"Refresh directory structure interval in seconds."})})]}),Object(u.jsxs)("div",{class:"row mb-3",children:[Object(u.jsx)("label",{for:"inputExtractMetadata",class:"col-sm-3 col-form-label",children:"Extract metadata from files"}),Object(u.jsx)("div",{class:"col-sm-5",children:Object(u.jsx)("input",{onChange:this.handleFormEdit,checked:this.state.formData.extractMetadata,type:"checkbox",class:"form-check-input",id:"inputExtractMetadata"})}),Object(u.jsx)("div",{class:"col-sm-4",children:Object(u.jsx)("small",{class:"text-muted",children:"Enable this option when Filehunter should extract metadata/content from files and make it searchable"})})]}),Object(u.jsx)("div",{class:"row",children:Object(u.jsxs)("div",{class:"col-3 offset-6",children:[Object(u.jsx)("a",{href:"/gui/index",class:"btn btn-link",children:"Cancel"}),Object(u.jsx)("button",{type:"submit",class:"btn btn-primary float-right",children:"Save"})]})})]})]})})})}}]),n}(a.a.Component),S=Object(l.g)(C);var w=function(){return Object(u.jsxs)("div",{children:[Object(u.jsx)("header",{children:Object(u.jsx)(m,{})}),Object(u.jsx)("main",{class:"flex-shrink-2",children:Object(u.jsx)(r.a,{children:Object(u.jsxs)(l.d,{children:[Object(u.jsx)(l.b,{exact:!0,path:"/",children:Object(u.jsx)(l.a,{to:"/gui/"})}),Object(u.jsx)(l.b,{exact:!0,path:"/gui/",children:Object(u.jsx)(v,{})}),Object(u.jsx)(l.b,{exact:!0,path:"/gui/index",children:Object(u.jsx)(k,{})}),Object(u.jsx)(l.b,{path:"/gui/index/edit/:name",children:Object(u.jsx)(S,{})}),Object(u.jsx)(l.b,{path:"/gui/index/create",children:Object(u.jsx)(S,{})})]})})})]})},F=function(e){e&&e instanceof Function&&n.e(3).then(n.bind(null,41)).then((function(t){var n=t.getCLS,s=t.getFID,a=t.getFCP,c=t.getLCP,i=t.getTTFB;n(e),s(e),a(e),c(e),i(e)}))};n(37),n(36);i.a.render(Object(u.jsx)(a.a.StrictMode,{children:Object(u.jsx)(w,{})}),document.getElementById("root")),F()}},[[38,1,2]]]); -//# sourceMappingURL=main.6c323a16.chunk.js.map \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/static/js/main.6c323a16.chunk.js.map b/src/main/resources/META-INF/resources/static/js/main.6c323a16.chunk.js.map deleted file mode 100644 index 94a6291..0000000 --- a/src/main/resources/META-INF/resources/static/js/main.6c323a16.chunk.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["SystemTaskStatus.js","Navbar.js","SearchResultRow.js","EmptySearchResult.js","SearchAdvanced.js","Searchform.js","ReindexState.js","EmptyIndexList.js","IndexInfo.js","IndexForm.js","App.js","reportWebVitals.js","index.js"],"names":["SystemTaskStatus","props","refreshInterval","refreshStatus","bind","this","fetch","process","then","res","json","result","setTimeout","setState","undefined","currentTask","class","React","Component","Navbar","href","type","id","rel","target","SearchResultRow","getColorByName","str","hash","i","length","charCodeAt","colour","toString","substr","iconclass","params","indexname","uuid","name","path","EmptySearchResult","align","SearchAdvanced","indexList","indexName","extension","requestFinished","e","value","handleAddFilters","advQ","update","for","onChange","handleIndexNameChange","map","item","handleExtensionChange","SearchForm","state","searchResultRows","sr","lastQuery","currentQuery","advancedFilterQuery","activeQuery","searchTimeout","updateAdvancedFilterQuery","clearInterval","intervalId","s","trim","substring","handleSearch","combinedQuery","encodeURIComponent","push","clearTimeout","autoFocus","placeholder","handleInputChange","onClick","ReindexState","console","log","clicked","handleClick","indextype","method","headers","response","title","EmptyIndexList","IndexInfo","handleRemove","refreshList","row","window","confirm","directoryRow","pathRow","ignorePath","ignorePhrase","ignoreExtension","Date","lastStructureIndexed","toLocaleDateString","toLocaleTimeString","IndexForm","formData","handleSubmit","handleFormEdit","match","event","preventDefault","body","JSON","stringify","location","replace","split","intervalUpdateStructure","extractMetadata","checked","formEditing","onSubmit","join","withRouter","App","exact","to","reportWebVitals","onPerfEntry","Function","getCLS","getFID","getFCP","getLCP","getTTFB","ReactDOM","render","StrictMode","document","getElementById"],"mappings":"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","file":"static/js/main.6c323a16.chunk.js","sourcesContent":["import React from 'react';\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass SystemTaskStatus extends React.Component {\n constructor(props) {\n super(props)\n\n this.refreshInterval = 10000\n this.refreshStatus = this.refreshStatus.bind(this)\n } \n \n componentDidMount() {\n this.refreshStatus()\n }\n\n refreshStatus() {\n fetch(`${API_URL}/system/status`)\n .then(res => res.json())\n .then((result) => {\n this.result = result;\n\n setTimeout(this.refreshStatus, this.refreshInterval)\n this.setState({});\n });\n }\n\n render() {\n\n if (this.result === undefined) {\n return(\"\")\n }\n if (this.result.currentTask !== \"\") {\n this.refreshInterval = 1000\n } else {\n this.refreshInterval = 10000\n return(\"\")\n }\n\n return(\n Task {this.result.currentTask}\n )\n }\n}\n\nexport default SystemTaskStatus","import React from 'react';\nimport SystemTaskStatus from './SystemTaskStatus';\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass Navbar extends React.Component {\n render() {\n return (\n \n\n )\n }\n}\n\nexport default Navbar;","import React from 'react';\nconst API_URL = process.env.REACT_APP_API_URL\n\n\nclass SearchResultRow extends React.Component {\n\n constructor(props) {\n super(props)\n\n this.getColorByName = this.getColorByName.bind(this)\n }\n\n getColorByName(str) {\n var hash = 0;\n for (var i = 0; i < str.length; i++) {\n hash = str.charCodeAt(i) + ((hash << 5) - hash);\n }\n var colour = '#';\n for (var i = 0; i < 3; i++) {\n var value = (hash >> (i * 8)) & 0xFF;\n colour += ('00' + value.toString(16)).substr(-2);\n }\n return colour;\n } \n\n render() {\n let iconclass = \"bi-file-earmark\"\n if (this.props.params.type === 'd') {\n iconclass = \"bi-folder2\"\n }\n\n let badgeColor = this.getColorByName(this.props.params.indexname)\n\n return (\n
\n \n {/*
{this.props.params.name}
*/}\n \n
\n {this.props.params.name}\n {/* {this.props.params.indexname} */}\n
\n \n {this.props.params.path}\n \n
\n )\n }\n \n}\n\nexport default SearchResultRow","import React from \"react\";\n\nclass EmptySearchResult extends React.Component {\n\n render() {\n return (\n
\n
\n
\n\n\n
\n Empty search results\n
\n\n
\n
\n
\n )\n }\n\n}\n\nexport default EmptySearchResult","import React from 'react'\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass SearchAdvanced extends React.Component {\n\n constructor(props) {\n super(props)\n this.indexList = []\n this.indexName = \"\"\n this.extension = \"\"\n\n\n }\n\n componentDidMount() {\n fetch(`${API_URL}/index/list`)\n .then(res => res.json())\n .then((result) => {\n this.indexList = result;\n this.requestFinished = true\n this.setState({});\n });\n }\n\n handleIndexNameChange(e) {\n this.indexName = e.target.value\n this.handleAddFilters()\n }\n\n handleExtensionChange(e) {\n this.extension = e.target.value\n this.handleAddFilters()\n }\n\n handleAddFilters() {\n\n let advQ = \"\"\n if (this.indexName !== \"\") {\n advQ += \" AND indexname:\" + this.indexName + \" \"\n }\n if (this.extension !== \"\") {\n advQ += \" AND ext:\" + this.extension + \" \"\n }\n\n this.props.update(advQ)\n }\n\n\n render() {\n return (\n
\n
\n\n
\n
\n \n \n
\n
\n\n
\n
\n \n \n
\n
\n\n\n
\n
\n\n )\n }\n}\n\nexport default SearchAdvanced","import React from 'react';\nimport SearchResultRow from './SearchResultRow.js'\nimport EmptySearchResult from './EmptySearchResult.js';\nimport SearchAdvanced from './SearchAdvanced.js';\nconst API_URL = process.env.REACT_APP_API_URL\n\n\nclass SearchForm extends React.Component {\n\n constructor(props) {\n super(props);\n this.state = {\n value: null,\n searchResultRows: []\n };\n this.sr = []\n this.lastQuery = \"\"\n this.currentQuery = \"\"\n this.advancedFilterQuery = \"\"\n this.activeQuery = false\n this.searchTimeout = null\n\n this.updateAdvancedFilterQuery = this.updateAdvancedFilterQuery.bind(this)\n\n }\n\n componentDidMount() {\n // this.intervalId = setInterval(this.handleSearch.bind(this), 500);\n }\n componentWillUnmount() {\n clearInterval(this.intervalId)\n }\n\n updateAdvancedFilterQuery(s) {\n this.advancedFilterQuery = s\n\n if (this.currentQuery == \"\") {\n this.advancedFilterQuery = this.advancedFilterQuery.trim().substring(3)\n }\n\n this.handleSearch()\n }\n\n handleSearch() {\n\n let combinedQuery = this.currentQuery + \" \" + this.advancedFilterQuery;\n\n\n if (combinedQuery === \"\" || combinedQuery === this.lastQuery) {\n return;\n }\n if (this.activeQuery === true) {\n return;\n }\n this.activeQuery = true\n\n fetch(`${API_URL}/search?q=${encodeURIComponent(combinedQuery)}`)\n .then(res => res.json())\n .then((result) => {\n this.lastQuery = combinedQuery\n this.activeQuery = false;\n\n this.sr = []\n result.map((item) => (\n this.sr.push()\n ))\n if (this.sr.length === 0) {\n this.sr.push()\n }\n\n this.setState({ searchResultRows: this.sr })\n })\n }\n\n handleInputChange(e) {\n this.currentQuery = e.target.value\n if (this.searchTimeout != null) {\n clearTimeout(this.searchTimeout)\n }\n this.searchTimeout = setTimeout(this.handleSearch.bind(this), 300);\n }\n\n render() {\n return (\n
\n
\n
\n
\n \n \n \n
\n
\n
\n\n
\n
\n \n
\n
\n\n
\n
\n {this.state.searchResultRows}\n
\n\n\n
\n
\n )\n }\n}\n\nexport default SearchForm","import React from 'react'\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass ReindexState extends React.Component {\n\n\n constructor(props) {\n super(props)\n console.log(props)\n\n this.state = { clicked: false }\n\n this.handleClick = this.handleClick.bind(this)\n }\n\n handleClick() {\n\n if (this.state.clicked === true) {\n return\n }\n\n fetch(`${API_URL}/index/reindex/${this.props.indextype}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n })\n .then(response => {\n this.setState({ clicked: true })\n })\n\n return false\n }\n\n render() {\n // console.log(this.state.clicked)\n\n return (\n \n )\n }\n\n}\n\nexport default ReindexState","import React from \"react\";\n\nclass EmptyIndexList extends React.Component {\n\n render() {\n return (\n
\n\n\n
\n
\n\n\n
\n You have no indexed directories. Click button below to add directory.\n
\n\n \n\n
\n
\n
\n )\n }\n\n}\n\nexport default EmptyIndexList","import React from 'react';\nimport ReindexState from './ReindexState';\nimport EmptyIndexList from './EmptyIndexList';\nconst API_URL = process.env.REACT_APP_API_URL\n\nclass IndexInfo extends React.Component {\n\n // const history = useHistory()\n\n constructor(props) {\n super(props)\n\n this.result = []\n this.requestFinished = false\n\n this.handleRemove = this.handleRemove.bind(this)\n\n }\n\n componentDidMount() {\n this.refreshList()\n\n }\n\n refreshList() {\n fetch(`${API_URL}/index/list`)\n .then(res => res.json())\n .then((result) => {\n this.result = result;\n this.requestFinished = true\n this.setState({});\n });\n }\n\n\n handleRemove(row) {\n if (window.confirm(\"Are you sure?\")) {\n\n fetch(`${API_URL}/index/remove/${row.name}`, {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' }, \n })\n .then(res => res.json())\n .then((result) => {\n this.result = result;\n this.setState({});\n }); \n }\n return false\n }\n\n render() {\n\n if (this.requestFinished === false) {\n return(\"\")\n }\n\n if (this.result.length === 0) {\n return (\n \n )\n }\n\n return (\n \n
\n
\n
\n

List of indexes New

\n \n \n \n \n \n \n \n \n \n \n \n {this.result.map(directoryRow => (\n \n \n \n \n \n\n \n \n ))}\n \n
NamePathsIgnoreLast indexed 
{directoryRow.name}\n {directoryRow.path.map(pathRow => (\n {pathRow}\n ))}\n \n {directoryRow.ignorePath.map(pathRow => (\n {pathRow}\n ))}\n {directoryRow.ignorePhrase.map(pathRow => (\n *{pathRow}*\n ))} \n {directoryRow.ignoreExtension.map(pathRow => (\n *.{pathRow}\n ))}\n \n {new Date(directoryRow.lastStructureIndexed).toLocaleDateString()}\n  \n {new Date(directoryRow.lastStructureIndexed).toLocaleTimeString()}\n \n \n this.handleRemove(directoryRow)} href=\"#\" class=\"btn btn-danger btn-sm me-1\">\n \n
\n
\n
\n\n
\n\n )\n }\n}\n\nexport default IndexInfo","import React from 'react';\nimport { withRouter } from \"react-router\";\nconst API_URL = process.env.REACT_APP_API_URL\n\n\nclass IndexForm extends React.Component {\n constructor(props) {\n super(props)\n\n this.state = {\n formData: {\n \"extractMetadata\": true,\n \"ignoreExtension\": [],\n \"ignorePath\": [],\n \"ignorePhrase\": [],\n \"indexMode\": \"full\",\n \"intervalUpdateMetadata\": 3600,\n \"name\": \"\",\n \"path\": []\n }\n }\n\n this.handleSubmit = this.handleSubmit.bind(this)\n this.handleFormEdit = this.handleFormEdit.bind(this)\n }\n\n componentDidMount() {\n let id = this.props.match.params.name;\n if (id !== undefined) {\n fetch(`${API_URL}/index/get/${id}`)\n .then(res => res.json())\n .then((result) => {\n this.setState({ formData: result });\n });\n }\n\n }\n\n handleSubmit(event) {\n\n event.preventDefault();\n\n fetch(`${API_URL}/index/set`, {\n method: 'POST',\n body: JSON.stringify(this.state.formData),\n headers: { 'Content-Type': 'application/json' },\n })\n .then(response => {\n console.log(response)\n window.location = \"/gui/index\"\n })\n }\n\n handleFormEdit(event) {\n\n if (event.type !== \"change\") {\n return\n }\n\n let formData = this.state.formData\n\n switch (event.target.id) {\n case \"inputName\":\n formData.name = event.target.value.replace(/[^a-z0-9\\-]+/gi, \"\")\n break\n case \"inputPath\":\n formData.path = event.target.value.split(\",\")\n break\n case \"inputPathIgnore\":\n formData.ignorePath = event.target.value.split(\",\")\n break\n case \"inputPhraseIgnore\":\n formData.ignorePhrase = event.target.value.split(\",\")\n break\n case \"inputExtIgnore\":\n formData.ignoreExtension = event.target.value.split(\",\")\n break\n case \"inputUpdateStructure\":\n formData.intervalUpdateStructure = event.target.value.replace(/[^0-9]+/gi, \"\")\n break\n case \"inputExtractMetadata\":\n formData.extractMetadata = event.target.checked\n break\n }\n\n this.setState({ formData: formData })\n }\n\n render() {\n let id = this.props.match.params.name\n let formEditing = true\n if (id === undefined) {\n formEditing = false\n }\n\n return (\n
\n
\n
\n

{formEditing ? \"Edit\" : \"Create\"} index

\n
\n
\n \n
\n \n
\n
\n {/* Input desription */}\n
\n
\n\n
\n \n
\n \n
\n
\n Full path to index, you can add here multiple paths separate them with coma
eg. (/home/user/dir1,/home/user/dir2)
\n
\n
\n\n

Filter settings

\n\n
\n \n
\n \n
\n
\n Ignore paths from indexing separated by coma
eg. (/home/user/dir1/unwanted-path,/home/user/dir2/some/unwanted)
\n
\n
\n\n
\n \n
\n \n
\n
\n Ignore file/directory paths with phrase separated by coma. You can use * to match more files/directories
eg. (.git,vendor,attr*)
\n
\n
\n\n
\n \n
\n \n
\n
\n Ignore file extensions separated by coma
eg. (jpg,mp4,tmp)
\n
\n
\n\n\n

Reindex settings

\n\n
\n \n
\n \n
\n
\n Refresh directory structure interval in seconds.\n
\n
\n\n
\n \n
\n \n
\n
\n Enable this option when Filehunter should extract metadata/content from files and make it searchable\n
\n
\n\n
\n
\n Cancel\n \n
\n
\n\n\n
\n
\n
\n
\n )\n }\n}\n\nexport default withRouter(IndexForm)","import './App.css';\nimport \"bootstrap-icons/font/bootstrap-icons.css\";\nimport { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';\nimport Navbar from './Navbar.js';\nimport SearchForm from './Searchform.js';\nimport IndexInfo from './IndexInfo';\nimport IndexForm from './IndexForm';\n\nfunction App() {\n return (\n
\n
\n \n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n
\n
\n );\n}\n\nexport default App;\n\n","const reportWebVitals = onPerfEntry => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry);\n getFID(onPerfEntry);\n getFCP(onPerfEntry);\n getLCP(onPerfEntry);\n getTTFB(onPerfEntry);\n });\n }\n};\n\nexport default reportWebVitals;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport reportWebVitals from './reportWebVitals';\nimport 'bootstrap';\nimport 'bootstrap/dist/css/bootstrap.min.css';\n\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n);\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals();\n"],"sourceRoot":""} \ No newline at end of file