updated
This commit is contained in:
parent
3dd3e01f4c
commit
6f83300f92
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"server":{
|
||||
"port": 8080,
|
||||
"baseURL": "",
|
||||
"address": "",
|
||||
"log": "stdout",
|
||||
"database": "./database.db",
|
||||
"root": "/srv"
|
||||
}
|
||||
|
||||
"port": 8080,
|
||||
"baseURL": "",
|
||||
"address": "",
|
||||
"log": "stdout",
|
||||
"database": "./database.db",
|
||||
"root": "/srv"
|
||||
|
||||
}
|
|
@ -2,8 +2,8 @@ package search
|
|||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var typeRegexp = regexp.MustCompile(`type:(\S+)`)
|
||||
|
@ -26,22 +26,21 @@ var compressedFile = []string{
|
|||
}
|
||||
|
||||
type searchOptions struct {
|
||||
Conditions map[string]bool
|
||||
Size int
|
||||
Terms []string
|
||||
Conditions map[string]bool
|
||||
Size int
|
||||
Terms []string
|
||||
}
|
||||
|
||||
func ParseSearch(value string) *searchOptions {
|
||||
opts := &searchOptions{
|
||||
Conditions: map[string]bool{
|
||||
Conditions: map[string]bool{
|
||||
"exact": strings.Contains(value, "case:exact"),
|
||||
},
|
||||
Terms: []string{},
|
||||
Terms: []string{},
|
||||
}
|
||||
|
||||
// removes the options from the value
|
||||
value = strings.Replace(value, "case:exact", "", -1)
|
||||
value = strings.Replace(value, "case:exact", "", -1)
|
||||
value = strings.TrimSpace(value)
|
||||
|
||||
types := typeRegexp.FindAllStringSubmatch(value, -1)
|
||||
|
@ -51,15 +50,21 @@ func ParseSearch(value string) *searchOptions {
|
|||
}
|
||||
filter := filterType[1]
|
||||
switch filter {
|
||||
case "image" : opts.Conditions["image"] = true
|
||||
case "audio", "music" : opts.Conditions["audio"] = true
|
||||
case "video" : opts.Conditions["video"] = true
|
||||
case "doc" : opts.Conditions["doc"] = true
|
||||
case "archive" : opts.Conditions["archive"] = true
|
||||
case "folder" : opts.Conditions["dir"] = true
|
||||
case "file" : opts.Conditions["dir"] = false
|
||||
case "image":
|
||||
opts.Conditions["image"] = true
|
||||
case "audio", "music":
|
||||
opts.Conditions["audio"] = true
|
||||
case "video":
|
||||
opts.Conditions["video"] = true
|
||||
case "doc":
|
||||
opts.Conditions["doc"] = true
|
||||
case "archive":
|
||||
opts.Conditions["archive"] = true
|
||||
case "folder":
|
||||
opts.Conditions["dir"] = true
|
||||
case "file":
|
||||
opts.Conditions["dir"] = false
|
||||
}
|
||||
|
||||
if len(filter) < 8 {
|
||||
continue
|
||||
}
|
||||
|
@ -74,8 +79,8 @@ func ParseSearch(value string) *searchOptions {
|
|||
}
|
||||
|
||||
if len(types) > 0 {
|
||||
// Remove the fields from the search value.
|
||||
value = typeRegexp.ReplaceAllString(value, "")
|
||||
// Remove the fields from the search value, including added space
|
||||
value = typeRegexp.ReplaceAllString(value+" ", "")
|
||||
}
|
||||
|
||||
if value == "" {
|
||||
|
@ -91,9 +96,8 @@ func ParseSearch(value string) *searchOptions {
|
|||
opts.Terms = []string{unique}
|
||||
return opts
|
||||
}
|
||||
re := regexp.MustCompile(` +`)
|
||||
value = re.ReplaceAllString(value, " ")
|
||||
opts.Terms = strings.Split(value, " ")
|
||||
value = strings.TrimSpace(value)
|
||||
opts.Terms = strings.Split(value, "|")
|
||||
return opts
|
||||
}
|
||||
|
||||
|
@ -112,4 +116,4 @@ func updateSize(given string) int {
|
|||
} else {
|
||||
return size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,11 @@
|
|||
<p v-show="isEmpty && isRunning" id="renew">
|
||||
<i class="material-icons spin">autorenew</i>
|
||||
</p>
|
||||
<p v-show="isEmpty && !isRunning">{{ text }}</p>
|
||||
<div v-show="isEmpty && !isRunning">
|
||||
<div class="searchPrompt" v-show="isEmpty && !isRunning">
|
||||
<p>No results found in indexed search.</p>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="isEmpty">
|
||||
<template v-if="value.length === 0">
|
||||
<div class="boxes">
|
||||
|
@ -50,7 +54,7 @@
|
|||
</div>
|
||||
<div v-if="!isMobile && active" id="result-desktop" ref="result">
|
||||
<div id="result-list">
|
||||
<div class="button" style="width: 100%">
|
||||
<div class="button fluid">
|
||||
Search Context: {{ getContext(this.$route.path) }}
|
||||
</div>
|
||||
<ul v-show="results.length > 0">
|
||||
|
@ -72,9 +76,18 @@
|
|||
<p v-show="isEmpty && isRunning" id="renew">
|
||||
<i class="material-icons spin">autorenew</i>
|
||||
</p>
|
||||
<p v-show="isEmpty && !isRunning">{{ text }}</p>
|
||||
<div class="searchPrompt" v-show="isEmpty && !isRunning">
|
||||
<p>No results found in indexed search.</p>
|
||||
<div class="helpButton" @click="toggleHelp()">Toggle Search Help</div>
|
||||
</div>
|
||||
|
||||
<div class="helpText" v-if="showHelp">
|
||||
Search additional terms separated by <code>|</code>, for example <code>"test|not"</code> searches for both terms independently
|
||||
<p>Note: searching files by size may have significantly longer search times since it cannot rely on the index alone.
|
||||
The search looks for only files that match all other conditions first, then checks the filesize and returns matching results.</p>
|
||||
</div>
|
||||
<template>
|
||||
<div v-show="results.length == 0" class="boxes">
|
||||
<div class="boxes">
|
||||
<ButtonGroup :buttons="folderSelect" @button-clicked="init" @remove-button-clicked="removeInit" />
|
||||
<ButtonGroup :buttons="typeSelect" @button-clicked="init" @remove-button-clicked="removeInit" />
|
||||
<ButtonGroup :buttons="sizeSelect" @button-clicked="init" @remove-button-clicked="removeInit" />
|
||||
|
@ -86,6 +99,26 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.helpText{
|
||||
padding:1em
|
||||
}
|
||||
.helpButton {
|
||||
text-align: center;
|
||||
background: var(--background);
|
||||
background-color: lightgray;
|
||||
padding: .25em;
|
||||
border-radius: .25em;
|
||||
}
|
||||
.searchPrompt {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import ButtonGroup from "./ButtonGroup.vue";
|
||||
import { mapState, mapGetters, mapMutations } from "vuex";
|
||||
|
@ -110,6 +143,7 @@ export default {
|
|||
name: "search",
|
||||
data: function () {
|
||||
return {
|
||||
showHelp: false,
|
||||
folderSelect: [
|
||||
{ label: "Only Folders", value: "type:folder" },
|
||||
{ label: "Only Files", value: "type:file" },
|
||||
|
@ -182,7 +216,10 @@ export default {
|
|||
},
|
||||
isRunning() {
|
||||
return this.ongoing;
|
||||
}
|
||||
},
|
||||
searchHelp() {
|
||||
return this.showHelp
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener("resize", this.handleResize);
|
||||
|
@ -271,6 +308,9 @@ export default {
|
|||
}
|
||||
this.ongoing = false;
|
||||
},
|
||||
toggleHelp(){
|
||||
this.showHelp = !this.showHelp
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -16,6 +16,10 @@
|
|||
<i class="material-icons">note_add</i>
|
||||
<span>{{ $t("sidebar.newFile") }}</span>
|
||||
</button>
|
||||
<button id="upload-button" @click="upload($event)" class="action" :aria-label="$t('sidebar.upload')" >
|
||||
<i class="material-icons">file_upload</i>
|
||||
<span>Upload file</span>
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button class="action" @click="toSettings" :aria-label="$t('sidebar.settings')" :title="$t('sidebar.settings')">
|
||||
|
@ -62,6 +66,7 @@
|
|||
</template>
|
||||
<script>
|
||||
import { mapState, mapGetters } from "vuex";
|
||||
import * as upload from "@/utils/upload";
|
||||
import * as auth from "@/utils/auth";
|
||||
import {
|
||||
version,
|
||||
|
@ -132,6 +137,50 @@ export default {
|
|||
help() {
|
||||
this.$store.commit("showHover", "help");
|
||||
},
|
||||
upload: function () {
|
||||
if (
|
||||
typeof window.DataTransferItem !== "undefined" &&
|
||||
typeof DataTransferItem.prototype.webkitGetAsEntry !== "undefined"
|
||||
) {
|
||||
this.$store.commit("showHover", "upload");
|
||||
} else {
|
||||
document.getElementById("upload-input").click();
|
||||
}
|
||||
},
|
||||
uploadInput(event) {
|
||||
this.$store.commit("closeHovers");
|
||||
|
||||
let files = event.currentTarget.files;
|
||||
let folder_upload =
|
||||
files[0].webkitRelativePath !== undefined && files[0].webkitRelativePath !== "";
|
||||
|
||||
if (folder_upload) {
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
let file = files[i];
|
||||
files[i].fullPath = file.webkitRelativePath;
|
||||
}
|
||||
}
|
||||
|
||||
let path = this.$route.path.endsWith("/")
|
||||
? this.$route.path
|
||||
: this.$route.path + "/";
|
||||
let conflict = upload.checkConflict(files, this.req.items);
|
||||
|
||||
if (conflict) {
|
||||
this.$store.commit("showHover", {
|
||||
prompt: "replace",
|
||||
confirm: (event) => {
|
||||
event.preventDefault();
|
||||
this.$store.commit("closeHovers");
|
||||
upload.handleFiles(files, path, true);
|
||||
},
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
upload.handleFiles(files, path);
|
||||
},
|
||||
logout: auth.logout,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -22,6 +22,13 @@
|
|||
:label="$t('buttons.selectMultiple')"
|
||||
@action="toggleMultipleSelection"
|
||||
/>
|
||||
<action
|
||||
v-if="headerButtons.download"
|
||||
icon="file_download"
|
||||
:label="$t('buttons.download')"
|
||||
@action="download"
|
||||
:counter="selectedCount"
|
||||
/>
|
||||
<action
|
||||
v-if="headerButtons.share"
|
||||
icon="share"
|
||||
|
@ -303,8 +310,8 @@ export default {
|
|||
headerButtons() {
|
||||
return {
|
||||
select: this.selectedCount > 0,
|
||||
upload: this.user.perm.create,
|
||||
download: this.user.perm.download,
|
||||
upload: this.user.perm.create && this.selectedCount > 0,
|
||||
download: this.user.perm.download && this.selectedCount > 0,
|
||||
shell: this.user.perm.execute && enableExec,
|
||||
delete: this.selectedCount > 0 && this.user.perm.delete,
|
||||
rename: this.selectedCount === 1 && this.user.perm.rename,
|
||||
|
|
Loading…
Reference in New Issue