Added database search
This commit is contained in:
parent
24914cb6ff
commit
da4e026f41
5
main.go
5
main.go
@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/animenotifier/notify.moe/pages/character"
|
"github.com/animenotifier/notify.moe/pages/character"
|
||||||
"github.com/animenotifier/notify.moe/pages/charge"
|
"github.com/animenotifier/notify.moe/pages/charge"
|
||||||
"github.com/animenotifier/notify.moe/pages/dashboard"
|
"github.com/animenotifier/notify.moe/pages/dashboard"
|
||||||
|
"github.com/animenotifier/notify.moe/pages/database"
|
||||||
"github.com/animenotifier/notify.moe/pages/editanime"
|
"github.com/animenotifier/notify.moe/pages/editanime"
|
||||||
"github.com/animenotifier/notify.moe/pages/editor"
|
"github.com/animenotifier/notify.moe/pages/editor"
|
||||||
"github.com/animenotifier/notify.moe/pages/embed"
|
"github.com/animenotifier/notify.moe/pages/embed"
|
||||||
@ -153,6 +154,10 @@ func configure(app *aero.Application) *aero.Application {
|
|||||||
app.Ajax("/editor/anilist", editor.AniList)
|
app.Ajax("/editor/anilist", editor.AniList)
|
||||||
app.Ajax("/editor/shoboi", editor.Shoboi)
|
app.Ajax("/editor/shoboi", editor.Shoboi)
|
||||||
|
|
||||||
|
// Mixed
|
||||||
|
app.Ajax("/database", database.Get)
|
||||||
|
app.Get("/api/select/:data-type/where/:field/is/:field-value", database.Select)
|
||||||
|
|
||||||
// Import
|
// Import
|
||||||
app.Ajax("/import", listimport.Get)
|
app.Ajax("/import", listimport.Get)
|
||||||
app.Ajax("/import/anilist/animelist", listimportanilist.Preview)
|
app.Ajax("/import/anilist/animelist", listimportanilist.Preview)
|
||||||
|
11
pages/database/database.go
Normal file
11
pages/database/database.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/aerogo/aero"
|
||||||
|
"github.com/animenotifier/notify.moe/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Get the dashboard.
|
||||||
|
func Get(ctx *aero.Context) string {
|
||||||
|
return ctx.HTML(components.Database())
|
||||||
|
}
|
36
pages/database/database.pixy
Normal file
36
pages/database/database.pixy
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
component Database
|
||||||
|
EditorTabs
|
||||||
|
|
||||||
|
.widget-form
|
||||||
|
.widget
|
||||||
|
h1.mountable Database search
|
||||||
|
|
||||||
|
.widget-section.mountable
|
||||||
|
label(for="data-type") Search
|
||||||
|
select#data-type.widget-ui-element(value="Anime")
|
||||||
|
option(value="Analytics") Analytics
|
||||||
|
option(value="Anime") Anime
|
||||||
|
option(value="AnimeList") AnimeList
|
||||||
|
option(value="Character") Character
|
||||||
|
option(value="Group") Group
|
||||||
|
option(value="Post") Post
|
||||||
|
option(value="Settings") Settings
|
||||||
|
option(value="SoundTrack") SoundTrack
|
||||||
|
option(value="Thread") Thread
|
||||||
|
option(value="User") User
|
||||||
|
|
||||||
|
.widget-section.mountable
|
||||||
|
label(for="field") where
|
||||||
|
input#field.widget-ui-element(type="text", placeholder="Field name (e.g. Title or Title.Canonical)")
|
||||||
|
|
||||||
|
.widget-section.mountable
|
||||||
|
label(for="field-value") is
|
||||||
|
input#field-value.widget-ui-element(type="text")
|
||||||
|
|
||||||
|
.buttons.mountable
|
||||||
|
button.action(data-action="searchDB", data-trigger="click")
|
||||||
|
Icon("search")
|
||||||
|
span Search
|
||||||
|
|
||||||
|
h3.text-center Results
|
||||||
|
#records
|
25
pages/database/database.scarlet
Normal file
25
pages/database/database.scarlet
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#records
|
||||||
|
horizontal-wrap
|
||||||
|
justify-content space-around
|
||||||
|
margin-top content-padding
|
||||||
|
|
||||||
|
.record
|
||||||
|
vertical
|
||||||
|
ui-element
|
||||||
|
padding 0.5rem 1rem
|
||||||
|
margin 0.5rem
|
||||||
|
|
||||||
|
.record-id
|
||||||
|
:before
|
||||||
|
content "ID: "
|
||||||
|
|
||||||
|
.record-view
|
||||||
|
//
|
||||||
|
|
||||||
|
.record-view-api
|
||||||
|
//
|
||||||
|
|
||||||
|
.record-count
|
||||||
|
text-align right
|
||||||
|
font-size 0.8rem
|
||||||
|
opacity 0.5
|
113
pages/database/select.go
Normal file
113
pages/database/select.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/aerogo/aero"
|
||||||
|
"github.com/aerogo/mirror"
|
||||||
|
"github.com/animenotifier/arn"
|
||||||
|
)
|
||||||
|
|
||||||
|
// QueryResponse ..
|
||||||
|
type QueryResponse struct {
|
||||||
|
Results []interface{} `json:"results"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select ...
|
||||||
|
func Select(ctx *aero.Context) string {
|
||||||
|
dataTypeName := ctx.Get("data-type")
|
||||||
|
field := ctx.Get("field")
|
||||||
|
searchValue := ctx.Get("field-value")
|
||||||
|
|
||||||
|
// Empty values
|
||||||
|
if dataTypeName == "+" {
|
||||||
|
dataTypeName = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if field == "+" {
|
||||||
|
field = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if searchValue == "+" {
|
||||||
|
searchValue = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check empty parameters
|
||||||
|
if dataTypeName == "" || field == "" {
|
||||||
|
return ctx.Error(http.StatusBadRequest, "Not enough parameters", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check data type parameter
|
||||||
|
_, found := arn.DB.Types()[dataTypeName]
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return ctx.Error(http.StatusBadRequest, "Invalid type", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
response := &QueryResponse{
|
||||||
|
Results: []interface{}{},
|
||||||
|
}
|
||||||
|
|
||||||
|
stream, err := arn.DB.All(dataTypeName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return ctx.Error(http.StatusInternalServerError, "Error fetching data from the database", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
process := func(obj interface{}) {
|
||||||
|
_, _, value, _ := mirror.GetField(obj, field)
|
||||||
|
|
||||||
|
if value.String() == searchValue {
|
||||||
|
response.Results = append(response.Results, obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch dataTypeName {
|
||||||
|
case "Analytics":
|
||||||
|
for obj := range stream.(chan *arn.Analytics) {
|
||||||
|
process(obj)
|
||||||
|
}
|
||||||
|
case "Anime":
|
||||||
|
for obj := range stream.(chan *arn.Anime) {
|
||||||
|
process(obj)
|
||||||
|
}
|
||||||
|
case "AnimeList":
|
||||||
|
for obj := range stream.(chan *arn.AnimeList) {
|
||||||
|
process(obj)
|
||||||
|
}
|
||||||
|
case "Character":
|
||||||
|
for obj := range stream.(chan *arn.Character) {
|
||||||
|
process(obj)
|
||||||
|
}
|
||||||
|
case "Group":
|
||||||
|
for obj := range stream.(chan *arn.Group) {
|
||||||
|
process(obj)
|
||||||
|
}
|
||||||
|
case "Post":
|
||||||
|
for obj := range stream.(chan *arn.Post) {
|
||||||
|
process(obj)
|
||||||
|
}
|
||||||
|
case "Settings":
|
||||||
|
for obj := range stream.(chan *arn.Settings) {
|
||||||
|
process(obj)
|
||||||
|
}
|
||||||
|
case "SoundTrack":
|
||||||
|
for obj := range stream.(chan *arn.SoundTrack) {
|
||||||
|
process(obj)
|
||||||
|
}
|
||||||
|
case "Thread":
|
||||||
|
for obj := range stream.(chan *arn.Thread) {
|
||||||
|
process(obj)
|
||||||
|
}
|
||||||
|
case "User":
|
||||||
|
for obj := range stream.(chan *arn.User) {
|
||||||
|
process(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, obj := range response.Results {
|
||||||
|
mirror.GetField(obj, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.JSON(response)
|
||||||
|
}
|
@ -3,11 +3,12 @@ component Editor
|
|||||||
|
|
||||||
EditorTabs
|
EditorTabs
|
||||||
|
|
||||||
p Welcome to the Editor Panel!
|
p.text-center.mountable Welcome to the Editor Panel!
|
||||||
|
|
||||||
component EditorTabs
|
component EditorTabs
|
||||||
.tabs
|
.tabs
|
||||||
Tab("Editor", "pencil", "/editor")
|
Tab("Editor", "pencil", "/editor")
|
||||||
|
Tab("Search", "search", "/database")
|
||||||
Tab("Shoboi", "calendar", "/editor/shoboi")
|
Tab("Shoboi", "calendar", "/editor/shoboi")
|
||||||
Tab("AniList", "list", "/editor/anilist")
|
Tab("AniList", "list", "/editor/anilist")
|
||||||
|
|
||||||
|
@ -15,3 +15,81 @@ export function search(arn: AnimeNotifier, search: HTMLInputElement, e: Keyboard
|
|||||||
|
|
||||||
arn.diff("/search/" + term)
|
arn.diff("/search/" + term)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search database
|
||||||
|
export function searchDB(arn: AnimeNotifier, input: HTMLInputElement, e: KeyboardEvent) {
|
||||||
|
if(e.ctrlKey || e.altKey) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let dataType = (arn.app.find("data-type") as HTMLInputElement).value || "+"
|
||||||
|
let field = (arn.app.find("field") as HTMLInputElement).value || "+"
|
||||||
|
let fieldValue = (arn.app.find("field-value") as HTMLInputElement).value || "+"
|
||||||
|
let records = arn.app.find("records")
|
||||||
|
|
||||||
|
arn.loading(true)
|
||||||
|
|
||||||
|
fetch(`/api/select/${dataType}/where/${field}/is/${fieldValue}`)
|
||||||
|
.then(response => {
|
||||||
|
if(response.status !== 200) {
|
||||||
|
throw response
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
records.innerHTML = ""
|
||||||
|
let count = 0
|
||||||
|
|
||||||
|
if(data.results.length === 0) {
|
||||||
|
records.innerText = "No results."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let record of data.results) {
|
||||||
|
count++
|
||||||
|
|
||||||
|
let container = document.createElement("div")
|
||||||
|
container.classList.add("record")
|
||||||
|
|
||||||
|
let id = document.createElement("div")
|
||||||
|
id.innerText = record.id
|
||||||
|
id.classList.add("record-id")
|
||||||
|
container.appendChild(id)
|
||||||
|
|
||||||
|
let link = document.createElement("a")
|
||||||
|
link.classList.add("record-view")
|
||||||
|
link.innerText = "Open " + dataType.toLowerCase()
|
||||||
|
|
||||||
|
if(dataType === "User") {
|
||||||
|
link.href = "/+" + record.nick
|
||||||
|
} else {
|
||||||
|
link.href = "/" + dataType.toLowerCase() + "/" + record.id
|
||||||
|
}
|
||||||
|
|
||||||
|
link.target = "_blank"
|
||||||
|
container.appendChild(link)
|
||||||
|
|
||||||
|
let apiLink = document.createElement("a")
|
||||||
|
apiLink.classList.add("record-view-api")
|
||||||
|
apiLink.innerText = "JSON data"
|
||||||
|
apiLink.href = "/api/" + dataType.toLowerCase() + "/" + record.id
|
||||||
|
apiLink.target = "_blank"
|
||||||
|
container.appendChild(apiLink)
|
||||||
|
|
||||||
|
let recordCount = document.createElement("div")
|
||||||
|
recordCount.innerText = count + "/" + data.results.length
|
||||||
|
recordCount.classList.add("record-count")
|
||||||
|
container.appendChild(recordCount)
|
||||||
|
|
||||||
|
records.appendChild(container)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(response => {
|
||||||
|
response.text().then(text => {
|
||||||
|
arn.statusMessage.showError(text)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(() => arn.loading(false))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user