fix search, new, delete

This commit is contained in:
Chris Sexton 2019-11-08 00:26:02 -05:00
parent 08894f1ef4
commit b67a1cccd5
8 changed files with 90 additions and 36 deletions

View File

@ -52,13 +52,18 @@ func PrepareTable(tx *sqlx.Tx) error {
return nil return nil
} }
func New(db *db.Database) Entry { func New(db *db.Database) *Entry {
return Entry{ e := Entry{
db: db, db: db,
ID: -1, ID: -1,
Created: time.Now(), Created: time.Now(),
Updated: time.Now(), Updated: time.Now(),
Tags: []string{},
} }
e.Title = e.GenerateTitle()
e.Slug = e.UniqueSlug()
e.Content = "= " + e.Title
return &e
} }
func GetBySlug(db *db.Database, slug string) (Entry, error) { func GetBySlug(db *db.Database, slug string) (Entry, error) {
@ -85,13 +90,13 @@ func Search(db *db.Database, query string) ([]*Entry, error) {
entries := []*Entry{} entries := []*Entry{}
log.Debug().Str("query", query).Msg("searching") log.Debug().Str("query", query).Msg("searching")
if query != "" { if query != "" {
q := `select * from entries where content like ?` q := `select * from entries where content like ? order by updated desc`
err := db.Select(&entries, q, "%"+query+"%") err := db.Select(&entries, q, "%"+query+"%")
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else { } else {
q := `select * from entries` q := `select * from entries order by updated desc`
err := db.Select(&entries, q) err := db.Select(&entries, q)
if err != nil { if err != nil {
return nil, err return nil, err
@ -119,12 +124,12 @@ func RemoveBySlug(db *db.Database, slug string) error {
tx.Rollback() tx.Rollback()
return err return err
} }
q = `delete from entries where entry_id = ?` q = `delete from entries where id = ?`
if _, err := tx.Exec(q, e.ID); err != nil { if _, err := tx.Exec(q, e.ID); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
return nil return tx.Commit()
} }
func (e *Entry) populateTags() error { func (e *Entry) populateTags() error {

View File

@ -7,6 +7,11 @@
<b-nav-item to="/console">Console</b-nav-item> <b-nav-item to="/console">Console</b-nav-item>
<b-nav-item to="/about">About</b-nav-item> <b-nav-item to="/about">About</b-nav-item>
</b-navbar-nav> </b-navbar-nav>
<b-navbar-nav class="ml-auto">
<b-nav-form>
<b-button @click="newFile">+</b-button>
</b-nav-form>
</b-navbar-nav>
</b-navbar> </b-navbar>
<Error/> <Error/>
<router-view/> <router-view/>
@ -42,6 +47,16 @@
name: 'app', name: 'app',
components: { components: {
Error Error
},
methods: {
newFile: function() {
this.$store.dispatch('newFile')
.catch(err => console.log(err))
.then(file => {
this.$store.dispatch('updateSearch')
this.$router.push({ name: 'console-slug', params: { slug: file.Slug }})
})
}
} }
} }
</script> </script>

View File

@ -1,11 +1,11 @@
<template> <template>
<b-container fluid> <b-container fluid>
<b-row> <b-row>
<b-input placeholder="Search" @update="runQuery" v-model="queryText" /> <b-input placeholder="Search" @update="getResults" v-model="queryText" />
</b-row> </b-row>
<b-row v-for="item in results" v-bind:key="item.ID"> <b-row v-for="item in results" v-bind:key="item.ID">
<b-col> <b-col>
<b-link <b-button :hidden="!editMode" size="sm" class="deleteLink" @click="deleteFile(item.Slug)">X</b-button> <b-link
:to="{ name: target, params: { slug: item.Slug } }" :to="{ name: target, params: { slug: item.Slug } }"
>{{item.Title}}</b-link> >{{item.Title}}</b-link>
</b-col> </b-col>
@ -24,7 +24,8 @@
}, },
props: { props: {
target: String, target: String,
query: String query: String,
editMode: Boolean
}, },
watch: { watch: {
query: function(newValue) { query: function(newValue) {
@ -42,15 +43,21 @@
}, },
created() { created() {
this.getResults() this.getResults()
this.runQuery = _.debounce(this.runQuery, 1000) this.getResults = _.debounce(this.getResults, 1000)
}, },
methods: { methods: {
getResults: function () { getResults: function () {
this.$store.dispatch('getSearchResults', null) this.$store.dispatch('updateSearch')
}, },
runQuery: function() { deleteFile: function(slug) {
this.$store.dispatch('getSearchResults', this.query) this.$store.dispatch('deleteBySlug', slug)
} }
} }
} }
</script> </script>
<style scoped>
.deleteLink {
font-size: x-small;
}
</style>

View File

@ -23,7 +23,7 @@
}, },
watch: { watch: {
tags: function (newValue) { tags: function (newValue) {
this.internalTags = newValue this.internalTags = newValue || []
} }
}, },
computed: { computed: {

View File

@ -49,6 +49,19 @@ export default new Vuex.Store({
} }
}, },
actions: { actions: {
newFile: function({commit}) {
return new Promise((resolve, reject) => {
axios.post('/v1/entries', {})
.catch(err => {
commit('addError', err)
reject(err)
})
.then(res => {
commit('setFile', res.data)
resolve(res.data)
})
})
},
getFile: function({ commit }, slug) { getFile: function({ commit }, slug) {
if (slug) if (slug)
return axios.get('/v1/entries/'+slug) return axios.get('/v1/entries/'+slug)
@ -57,23 +70,36 @@ export default new Vuex.Store({
commit('setFile', res.data) commit('setFile', res.data)
}) })
}, },
getSearchResults: function ({dispatch}) {
dispatch('updateSearch')
},
updateSearch: function ({commit, state}) { updateSearch: function ({commit, state}) {
return new Promise((resolve, reject) => {
let query = state.query || "" let query = state.query || ""
console.log("running search for: " + query) console.log("running search for: " + query)
axios.get('/v1/entries?query='+query) axios.get('/v1/entries?query='+query)
.catch(err => state.addError(err)) .catch(err => {
state.addError(err)
reject(err)
})
.then(res =>{ .then(res =>{
console.log("getSearchResults:"+res.data)
commit('setResults', res.data) commit('setResults', res.data)
resolve(res.data)
})
}) })
}, },
saveFile: function({state}) { saveFile: function({state}) {
console.log(state.file) console.log(state.file)
if (state.file) if (state.file)
return axios.put('/v1/entries/'+state.file.Slug, state.file) return axios.put('/v1/entries/'+state.file.Slug, state.file)
},
deleteBySlug: function({dispatch,commit}, slug) {
axios.delete('/v1/entries/'+slug)
.catch(err => {
commit('addError', err)
console.log(err)
})
.then(res => {
dispatch('updateSearch')
console.log(res.status, res.statusText)
})
} }
}, },
modules: { modules: {

View File

@ -25,7 +25,7 @@
</b-col> </b-col>
<b-col md="2"> <b-col md="2">
<h2>Search Results</h2> <h2>Search Results</h2>
<SearchResults target="console-slug" /> <SearchResults :editMode="true" target="console-slug" />
</b-col> </b-col>
</b-row> </b-row>
</b-container> </b-container>

View File

@ -130,6 +130,7 @@ func (web *Web) removeEntry(w http.ResponseWriter, r *http.Request) {
err := entry.RemoveBySlug(web.db, slug) err := entry.RemoveBySlug(web.db, slug)
if err != nil { if err != nil {
log.Error().Msgf("Error deleting: %s", err)
w.WriteHeader(500) w.WriteHeader(500)
fmt.Fprint(w, err) fmt.Fprint(w, err)
return return

View File

@ -11,8 +11,8 @@ import (
"github.com/speps/go-hashids" "github.com/speps/go-hashids"
"github.com/gorilla/mux"
"github.com/gorilla/handlers" "github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/stretchr/graceful" "github.com/stretchr/graceful"
) )
@ -44,7 +44,7 @@ func (web *Web) routeSetup() http.Handler {
api := r.PathPrefix("/v1/").Subrouter() api := r.PathPrefix("/v1/").Subrouter()
api.HandleFunc("/entries", web.allEntries).Methods(http.MethodGet) api.HandleFunc("/entries", web.allEntries).Methods(http.MethodGet)
api.HandleFunc("/entries", web.newEntry).Methods(http.MethodPost) api.HandleFunc("/entries", web.newEntry).Methods(http.MethodPost)
api.HandleFunc("/entries", web.removeEntry).Methods(http.MethodDelete) api.HandleFunc("/entries/{slug}", web.removeEntry).Methods(http.MethodDelete)
api.HandleFunc("/entries/{slug}", web.editEntry).Methods(http.MethodPut) api.HandleFunc("/entries/{slug}", web.editEntry).Methods(http.MethodPut)
api.HandleFunc("/entries/{slug}", web.getEntry).Methods(http.MethodGet) api.HandleFunc("/entries/{slug}", web.getEntry).Methods(http.MethodGet)
r.PathPrefix("/").HandlerFunc(web.indexHandler("/index.html")) r.PathPrefix("/").HandlerFunc(web.indexHandler("/index.html"))