Commit dca6b716 authored by NGPixel's avatar NGPixel

Search results + suggestions

parent 7945d024
......@@ -27,6 +27,6 @@
- [ ] Markdown Editor
- [x] Navigation
- [x] Parsing / Tree / Metadata
- [ ] Search
- [x] Search
- [x] UI
- [x] View Entry Source
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
"use strict";function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function setInputSelection(e,t,a){if(e.focus(),"undefined"!=typeof e.selectionStart)e.selectionStart=t,e.selectionEnd=a;else if(document.selection&&document.selection.createRange){e.select();var n=document.selection.createRange();n.collapse(!0),n.moveEnd("character",a),n.moveStart("character",t),n.select()}}function makeSafePath(e){var t=_.split(_.trim(e),"/");return t=_.map(t,function(e){return _.kebabCase(_.deburr(_.trim(e)))}),_.join(_.filter(t,function(e){return!_.isEmpty(e)}),"/")}var _createClass=function(){function e(e,t){for(var a=0;a<t.length;a++){var n=t[a];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,a,n){return a&&e(t.prototype,a),n&&e(t,n),t}}(),Alerts=function(){function e(){_classCallCheck(this,e);var t=this;t.mdl=new Vue({el:"#alerts",data:{children:[]},methods:{acknowledge:function(e){t.close(e)}}}),t.uidNext=1}return _createClass(e,[{key:"push",value:function(e){var t=this,a=_.defaults(e,{_uid:t.uidNext,class:"is-info",message:"---",sticky:!1,title:"---"});t.mdl.children.push(a),a.sticky||_.delay(function(){t.close(a._uid)},5e3),t.uidNext++}},{key:"pushError",value:function(e,t){this.push({class:"is-danger",message:t,sticky:!1,title:e})}},{key:"pushSuccess",value:function(e,t){this.push({class:"is-success",message:t,sticky:!1,title:e})}},{key:"close",value:function(e){var t=this,a=_.findIndex(t.mdl.children,["_uid",e]),n=_.nth(t.mdl.children,a);a>=0&&n&&(n.class+=" exit",t.mdl.children.$set(a,n),_.delay(function(){t.mdl.children.$remove(n)},500))}}]),e}();jQuery(document).ready(function(e){e("a").smoothScroll({speed:400,offset:-20});new Sticky(".stickyscroll");e(window).bind("beforeunload",function(){e("#notifload").addClass("active")}),e(document).ajaxSend(function(){e("#notifload").addClass("active")}).ajaxComplete(function(){e("#notifload").removeClass("active")});var t=new Alerts;if(alertsData&&_.forEach(alertsData,function(e){t.push(e)}),1===e("#mk-editor").length)var a=new SimpleMDE({autofocus:!0,autoDownloadFontAwesome:!1,element:e("#mk-editor").get(0),hideIcons:["heading","quote"],placeholder:"Enter Markdown formatted content here...",showIcons:["strikethrough","heading-1","heading-2","heading-3","code","table","horizontal-rule"],spellChecker:!1,status:!1});var n=io(ioHost),o=new Vue({el:"#header-container",data:{searchq:"",searchres:[]},watch:{searchq:function(e,t){e.length>=3&&n.emit("search",{terms:e},function(e){o.$set("searchres",e)})}},methods:{}});if(e("#page-type-view").length&&!function(){var t="home"!==e("#page-type-view").data("entrypath")?e("#page-type-view").data("entrypath")+"/":"",a=t+"new-page";e(".btn-create-prompt").on("click",function(n){e("#txt-create-prompt").val(a),e("#modal-create-prompt").toggleClass("is-active"),setInputSelection(e("#txt-create-prompt").get(0),t.length,a.length),e("#txt-create-prompt").removeClass("is-danger").next().addClass("is-hidden")}),e("#txt-create-prompt").on("keypress",function(t){13===t.which&&e(".btn-create-go").trigger("click")}),e(".btn-create-go").on("click",function(t){var a=makeSafePath(e("#txt-create-prompt").val());_.isEmpty(a)?e("#txt-create-prompt").addClass("is-danger").next().removeClass("is-hidden"):(e("#txt-create-prompt").parent().addClass("is-loading"),window.location.assign("/create/"+a))})}(),e("#page-type-create").length&&(e(".btn-create-discard").on("click",function(t){e("#modal-create-discard").toggleClass("is-active")}),e(".btn-create-save").on("click",function(n){e.ajax(window.location.href,{data:{markdown:a.value()},dataType:"json",method:"PUT"}).then(function(a,n,o){a.ok?window.location.assign("/"+e("#page-type-create").data("entrypath")):t.pushError("Something went wrong",a.error)},function(e,a,n){t.pushError("Something went wrong","Save operation failed.")})})),e("#page-type-edit").length){e(".editor-toolbar").attr("data-margin-top",e("#header").height());new Sticky(".editor-toolbar");e(".btn-edit-discard").on("click",function(t){e("#modal-edit-discard").toggleClass("is-active")}),e(".btn-edit-save").on("click",function(n){e.ajax(window.location.href,{data:{markdown:a.value()},dataType:"json",method:"PUT"}).then(function(a,n,o){a.ok?window.location.assign("/"+e("#page-type-edit").data("entrypath")):t.pushError("Something went wrong",a.error)},function(e,a,n){t.pushError("Something went wrong","Save operation failed.")})})}if(e("#page-type-source").length){var i=ace.edit("source-display");i.setTheme("ace/theme/tomorrow_night"),i.getSession().setMode("ace/mode/markdown"),i.setReadOnly(!0),i.renderer.updateFull()}});
\ No newline at end of file
"use strict";function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function setInputSelection(e,t,a){if(e.focus(),"undefined"!=typeof e.selectionStart)e.selectionStart=t,e.selectionEnd=a;else if(document.selection&&document.selection.createRange){e.select();var n=document.selection.createRange();n.collapse(!0),n.moveEnd("character",a),n.moveStart("character",t),n.select()}}function makeSafePath(e){var t=_.split(_.trim(e),"/");return t=_.map(t,function(e){return _.kebabCase(_.deburr(_.trim(e)))}),_.join(_.filter(t,function(e){return!_.isEmpty(e)}),"/")}var _createClass=function(){function e(e,t){for(var a=0;a<t.length;a++){var n=t[a];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,a,n){return a&&e(t.prototype,a),n&&e(t,n),t}}();jQuery(document).ready(function(e){e("a").smoothScroll({speed:400,offset:-20});new Sticky(".stickyscroll");e(window).bind("beforeunload",function(){e("#notifload").addClass("active")}),e(document).ajaxSend(function(){e("#notifload").addClass("active")}).ajaxComplete(function(){e("#notifload").removeClass("active")});var t=new Alerts;if(alertsData&&_.forEach(alertsData,function(e){t.push(e)}),1===e("#mk-editor").length)var a=new SimpleMDE({autofocus:!0,autoDownloadFontAwesome:!1,element:e("#mk-editor").get(0),hideIcons:["heading","quote"],placeholder:"Enter Markdown formatted content here...",showIcons:["strikethrough","heading-1","heading-2","heading-3","code","table","horizontal-rule"],spellChecker:!1,status:!1});var n=io(ioHost);if(jQuery(document).ready(function(e){if(e("#search-input").length){e("#search-input").focus(),Vue.transition("slide",{enterClass:"slideInDown",leaveClass:"fadeOutUp"}),e(".searchresults").css("display","block");var t=new Vue({el:"#header-container",data:{searchq:"",searchres:[],searchsuggest:[],searchload:0,searchactive:!1,searchmoveidx:0,searchmovekey:"",searchmovearr:[]},watch:{searchq:function(e,a){e.length>=3?(t.searchactive=!0,t.searchload++,n.emit("search",{terms:e},function(e){t.searchres=e.match,t.searchsuggest=e.suggest,t.searchload>0&&t.searchload--})):(t.searchactive=!1,t.searchres=[],t.searchsuggest=[],t.searchload=0)},searchmoveidx:function(e,t){}},methods:{useSuggestion:function(e){t.searchq=e},closeSearch:function(){t.searchq="",t.searchactive=!1},moveSelectSearch:function(){},moveDownSearch:function(){t.searchmoveidx<t.searchmovearr&&t.searchmoveidx++},moveUpSearch:function(){t.searchmoveidx>0&&t.searchmoveidx--}}});e("main").on("click",t.closeSearch)}}),e("#page-type-view").length&&!function(){var t="home"!==e("#page-type-view").data("entrypath")?e("#page-type-view").data("entrypath")+"/":"",a=t+"new-page";e(".btn-create-prompt").on("click",function(n){e("#txt-create-prompt").val(a),e("#modal-create-prompt").toggleClass("is-active"),setInputSelection(e("#txt-create-prompt").get(0),t.length,a.length),e("#txt-create-prompt").removeClass("is-danger").next().addClass("is-hidden")}),e("#txt-create-prompt").on("keypress",function(t){13===t.which&&e(".btn-create-go").trigger("click")}),e(".btn-create-go").on("click",function(t){var a=makeSafePath(e("#txt-create-prompt").val());_.isEmpty(a)?e("#txt-create-prompt").addClass("is-danger").next().removeClass("is-hidden"):(e("#txt-create-prompt").parent().addClass("is-loading"),window.location.assign("/create/"+a))})}(),e("#page-type-create").length&&(e(".btn-create-discard").on("click",function(t){e("#modal-create-discard").toggleClass("is-active")}),e(".btn-create-save").on("click",function(n){e.ajax(window.location.href,{data:{markdown:a.value()},dataType:"json",method:"PUT"}).then(function(a,n,o){a.ok?window.location.assign("/"+e("#page-type-create").data("entrypath")):t.pushError("Something went wrong",a.error)},function(e,a,n){t.pushError("Something went wrong","Save operation failed.")})})),e("#page-type-edit").length){e(".editor-toolbar").attr("data-margin-top",e("#header").height());new Sticky(".editor-toolbar");e(".btn-edit-discard").on("click",function(t){e("#modal-edit-discard").toggleClass("is-active")}),e(".btn-edit-save").on("click",function(n){e.ajax(window.location.href,{data:{markdown:a.value()},dataType:"json",method:"PUT"}).then(function(a,n,o){a.ok?window.location.assign("/"+e("#page-type-edit").data("entrypath")):t.pushError("Something went wrong",a.error)},function(e,a,n){t.pushError("Something went wrong","Save operation failed.")})})}if(e("#page-type-source").length){var o=ace.edit("source-display");o.setTheme("ace/theme/tomorrow_night"),o.getSession().setMode("ace/mode/markdown"),o.setReadOnly(!0),o.renderer.updateFull()}});var Alerts=function(){function e(){_classCallCheck(this,e);var t=this;t.mdl=new Vue({el:"#alerts",data:{children:[]},methods:{acknowledge:function(e){t.close(e)}}}),t.uidNext=1}return _createClass(e,[{key:"push",value:function(e){var t=this,a=_.defaults(e,{_uid:t.uidNext,class:"is-info",message:"---",sticky:!1,title:"---"});t.mdl.children.push(a),a.sticky||_.delay(function(){t.close(a._uid)},5e3),t.uidNext++}},{key:"pushError",value:function(e,t){this.push({class:"is-danger",message:t,sticky:!1,title:e})}},{key:"pushSuccess",value:function(e,t){this.push({class:"is-success",message:t,sticky:!1,title:e})}},{key:"close",value:function(e){var t=this,a=_.findIndex(t.mdl.children,["_uid",e]),n=_.nth(t.mdl.children,a);a>=0&&n&&(n.class+=" exit",t.mdl.children.$set(a,n),_.delay(function(){t.mdl.children.$remove(n)},500))}}]),e}();
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -58,25 +58,7 @@ jQuery( document ).ready(function( $ ) {
var socket = io(ioHost);
var vueHeader = new Vue({
el: '#header-container',
data: {
searchq: '',
searchres: []
},
watch: {
searchq: (val, oldVal) => {
if(val.length >= 3) {
socket.emit('search', { terms: val }, (data) => {
vueHeader.$set('searchres', data);
});
}
}
},
methods: {
}
});
//=include components/search.js
// ====================================
// Pages logic
......@@ -90,4 +72,6 @@ jQuery( document ).ready(function( $ ) {
});
//=include helpers/form.js
//=include helpers/pages.js
\ No newline at end of file
//=include helpers/pages.js
//=include components/alerts.js
\ No newline at end of file
"use strict";
jQuery( document ).ready(function( $ ) {
if($('#search-input').length) {
$('#search-input').focus();
Vue.transition('slide', {
enterClass: 'slideInDown',
leaveClass: 'fadeOutUp'
});
$('.searchresults').css('display', 'block');
var vueHeader = new Vue({
el: '#header-container',
data: {
searchq: '',
searchres: [],
searchsuggest: [],
searchload: 0,
searchactive: false,
searchmoveidx: 0,
searchmovekey: '',
searchmovearr: []
},
watch: {
searchq: (val, oldVal) => {
searchmoveidx: 0;
if(val.length >= 3) {
vueHeader.searchactive = true;
vueHeader.searchload++;
socket.emit('search', { terms: val }, (data) => {
vueHeader.searchres = data.match;
vueHeader.searchsuggest = data.suggest;
if(vueHeader.searchload > 0) { vueHeader.searchload--; }
});
} else {
vueHeader.searchactive = false;
vueHeader.searchres = [];
vueHeader.searchsuggest = [];
vueHeader.searchload = 0;
}
},
searchmoveidx: (val, oldVal) => {
}
},
methods: {
useSuggestion: (sug) => {
vueHeader.searchq = sug;
},
closeSearch: () => {
vueHeader.searchq = '';
vueHeader.searchactive = false;
},
moveSelectSearch: () => {
},
moveDownSearch: () => {
if(vueHeader.searchmoveidx < vueHeader.searchmovearr) {
vueHeader.searchmoveidx++;
}
},
moveUpSearch: () => {
if(vueHeader.searchmoveidx > 0) {
vueHeader.searchmoveidx--;
}
}
}
});
$('main').on('click', vueHeader.closeSearch);
}
});
\ No newline at end of file
......@@ -6,4 +6,8 @@ html {
}
//$family-sans-serif: "Roboto", "Helvetica", "Arial", sans-serif;
$family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
\ No newline at end of file
$family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
[v-cloak] {
display: none;
}
\ No newline at end of file
......@@ -27,6 +27,11 @@ h2.nav-item {
}
#search-input {
max-width: 300px;
width: 33vw;
}
.searchresults {
position: fixed;
top: 45px;
......@@ -35,5 +40,9 @@ h2.nav-item {
margin: 0 auto;
width: 500px;
z-index: 1;
//display: none;
&.slideInDown {
@include prefix(animation-duration, .6s);
}
}
\ No newline at end of file
......@@ -31,7 +31,6 @@ var paths = {
'./node_modules/lodash/lodash.min.js'
],
scriptapps: [
'./client/js/components/*.js',
'./client/js/app.js'
],
scriptapps_watch: [
......
......@@ -50,16 +50,43 @@ module.exports = {
.toLower()
.trim()
.replace(/[^a-z0-9 ]/g, '')
.split(' ')
.filter((f) => { return !_.isEmpty(f); })
.value();
let arrTerms = _.chain(terms)
.split(' ')
.filter((f) => { return !_.isEmpty(f); })
.value();
return self._si.searchAsync({
query: {
AND: [{ '*': terms }]
AND: [{ '*': arrTerms }]
},
pageSize: 10
}).get('hits');
}).get('hits').then((hits) => {
if(hits.length < 5) {
return self._si.matchAsync({
beginsWith: terms,
threshold: 3,
limit: 5,
type: 'simple'
}).then((matches) => {
return {
match: hits,
suggest: matches
};
});
} else {
return {
match: hits,
suggest: []
};
}
});
},
......
......@@ -32,7 +32,7 @@
"dependencies": {
"auto-load": "^2.1.0",
"bcryptjs-then": "^1.0.1",
"bluebird": "^3.4.5",
"bluebird": "^3.4.6",
"body-parser": "^1.15.2",
"bson": "^0.5.4",
"cheerio": "^0.22.0",
......@@ -48,7 +48,7 @@
"express-brute-loki": "^1.0.0",
"express-session": "^1.14.1",
"express-validator": "^2.20.8",
"farmhash": "^1.2.0",
"farmhash": "^1.2.1",
"fs-extra": "^0.30.0",
"git-wrapper2-promise": "^0.2.9",
"highlight.js": "^9.6.0",
......@@ -77,7 +77,8 @@
"serve-favicon": "^2.3.0",
"simplemde": "^1.11.2",
"socket.io": "^1.4.8",
"validator": "^5.5.0",
"sticky-js": "^1.0.7",
"validator": "^5.6.0",
"validator-as-promised": "^1.0.2",
"winston": "^2.2.0"
},
......
......@@ -9,8 +9,9 @@
h1.title Wiki
.nav-center
block rootNavCenter
p.nav-item
input.input(type='text', v-model='searchq', debounce='500' placeholder='Search...', style= { 'max-width': '300px', width: '33vw' })
.nav-item
p.control(v-bind:class="{ 'is-loading': searchload > 0 }")
input.input#search-input(type='text', v-model='searchq', @keyup.esc='closeSearch', @keyup.down='moveDownSearch', @keyup.up='moveUpSearch', debounce='400', placeholder='Search...')
span.nav-toggle
span
span
......@@ -32,14 +33,19 @@
i.fa.fa-plus
span Create
.box.searchresults
.box.searchresults.animated(v-show='searchactive', transition='slide', v-cloak, style={'display':'none'})
.menu
p.menu-label
| Search Results
ul.menu-list
li(v-if="searchres.length === 0")
a: em No results matching your query
li(v-for='sres in searchres')
a(href='#') {{ sres.document.title }}
p.menu-label
| Do you mean...?
a(href='/{{ sres.document.entryPath }}', v-bind:class="{ 'is-active': searchmovekey === 'res.' + sres.document.entryPath }") {{ sres.document.title }}
p.menu-label(v-if='searchsuggest.length > 0')
| Did you mean...?
ul.menu-list(v-if='searchsuggest.length > 0')
li(v-for='sug in searchsuggest')
a(v-on:click="useSuggestion(sug)") {{ sug }}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment