This commit is contained in:
Graham Steffaniak 2023-08-05 09:58:06 -05:00
parent 3dd3e01f4c
commit 6f83300f92
5 changed files with 135 additions and 36 deletions

View File

@ -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"
}

View File

@ -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
}
}
}

View File

@ -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>

View File

@ -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,
},
};

View File

@ -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,