From b9d0e703a9b4f7ff69967217fd1d605b0892a33b Mon Sep 17 00:00:00 2001 From: Vincent Boutour Date: Sat, 31 Dec 2022 16:13:24 +0100 Subject: [PATCH] feat: Adding tagging for file only for now Signed-off-by: Vincent Boutour --- cmd/fibr/templates/edit-modal.html | 7 +++ cmd/fibr/templates/exif.html | 4 +- cmd/fibr/templates/file.html | 2 +- cmd/fibr/templates/files.html | 78 ++++++++++++++++------------ cmd/fibr/templates/items.html | 13 +++++ cmd/fibr/templates/layout.html | 43 ++++++++------- cmd/fibr/templates/search.html | 24 ++++----- cmd/fibr/templates/share-list.html | 10 ++-- cmd/fibr/templates/story.html | 28 +++++----- cmd/fibr/templates/svg.html | 8 +++ cmd/fibr/templates/webhook-list.html | 2 +- pkg/crud/browse.go | 8 +-- pkg/crud/crud.go | 4 +- pkg/crud/get.go | 4 +- pkg/crud/get_test.go | 2 +- pkg/crud/list.go | 25 +++++++-- pkg/crud/post.go | 2 +- pkg/crud/rename.go | 19 ++++--- pkg/crud/story.go | 4 +- pkg/fibr/renderer.go | 3 ++ pkg/metadata/metadata.go | 4 +- pkg/provider/metadata.go | 14 +---- pkg/provider/storage.go | 8 +-- pkg/provider/util.go | 10 ---- pkg/thumbnail/thumbnail.go | 2 +- 25 files changed, 188 insertions(+), 140 deletions(-) diff --git a/cmd/fibr/templates/edit-modal.html b/cmd/fibr/templates/edit-modal.html index ae12a46f..62790477 100644 --- a/cmd/fibr/templates/edit-modal.html +++ b/cmd/fibr/templates/edit-modal.html @@ -18,6 +18,13 @@

Rename

+ {{ if not .IsDir }} +

+ + +

+ {{ end }} + {{ if .HasThumbnail }}

diff --git a/cmd/fibr/templates/exif.html b/cmd/fibr/templates/exif.html index e6d9b72a..3ce51583 100644 --- a/cmd/fibr/templates/exif.html +++ b/cmd/fibr/templates/exif.html @@ -1,7 +1,7 @@ {{ define "exif-modal-btn" }} {{ if .Exif.HasData }} - - Exif + + info {{ end }} {{ end }} diff --git a/cmd/fibr/templates/file.html b/cmd/fibr/templates/file.html index 787dbd17..1efb8d8f 100644 --- a/cmd/fibr/templates/file.html +++ b/cmd/fibr/templates/file.html @@ -57,7 +57,7 @@ {{ else }} {{ if .File.IsImage }} - {{ .File.Name }} + Image {{ .File.Name }} {{ else }} {{ end }} diff --git a/cmd/fibr/templates/files.html b/cmd/fibr/templates/files.html index 949999d0..9008d781 100644 --- a/cmd/fibr/templates/files.html +++ b/cmd/fibr/templates/files.html @@ -9,7 +9,7 @@ {{ if .Request.CanEdit }} - + @@ -161,15 +161,15 @@

@@ -213,13 +213,13 @@
    {{ range .SavedSearches }}
  • - - Saved Search + + folder with magnifying glass {{ .Name }} {{ if $root.Request.CanEdit }} - Delete + delete {{ end }} @@ -233,37 +233,47 @@ {{ template "async-image-item" . }} {{ if .IsVideo }} - Play video + play icon {{ end }} {{ if .IsCover }} - Is cover image + waves {{ end }} {{ else }} - {{ if .IsDir }}Folder{{ else }}File{{ end }} + {{ if .IsDir }}folder{{ else }}file{{ end }} {{ .Name }} {{ end }} - - Download + + download {{ if $root.Request.CanShare }} - - Share {{ .Name }} + + share {{ end }} {{ if $root.Request.CanEdit }} - - Edit + + edit - - Delete + + delete {{ end }} + {{ if .Tags }} + {{- if eq $root.Request.Display "grid" -}} + tag + {{ else }} + + #{{ join .Tags " #" }} + + {{ end}} + {{ end }} + {{ if .IsDir }} {{ if or .Aggregate.Location (not .Aggregate.Start.IsZero) }} {{- $startDate := .Aggregate.Start.Format "Jan 2006" -}} @@ -273,7 +283,7 @@ Exif {{ end }} diff --git a/cmd/fibr/templates/layout.html b/cmd/fibr/templates/layout.html index fb2dea35..224af6a3 100644 --- a/cmd/fibr/templates/layout.html +++ b/cmd/fibr/templates/layout.html @@ -33,37 +33,40 @@

    {{ end }} - {{ if not (and .Previous.IsZero .Next.IsZero) }} - {{ else }} {{ if .Request.Share.Story }} {{ if .HasMap }} - - View on map + + map {{ end }} {{ else }} {{ if and .Request.CanEdit .Search }} - - Created saved search folder + + folder with magnifying glass {{ end }} - - Search files + + magnifying glass {{ end }} {{ end }} diff --git a/cmd/fibr/templates/search.html b/cmd/fibr/templates/search.html index a3465f00..0bf99c8b 100644 --- a/cmd/fibr/templates/search.html +++ b/cmd/fibr/templates/search.html @@ -70,11 +70,11 @@
    @@ -110,15 +110,15 @@ {{ template "async-image-item" . }} {{ if .IsVideo }} - Play video + play icon {{ end }} {{ else }} - {{ if .IsDir }}Folder{{ else }}File{{ end }} + {{ if .IsDir }}folder{{ else }}file{{ end }} {{ .URL }} {{ end }} - - Download + + download

  • diff --git a/cmd/fibr/templates/share-list.html b/cmd/fibr/templates/share-list.html index 21899518..cce6b66c 100644 --- a/cmd/fibr/templates/share-list.html +++ b/cmd/fibr/templates/share-list.html @@ -35,16 +35,16 @@

    {{ if .Edit }} - Editable + pencil {{ end }} {{ if .Story }} - Story mode + image {{ end }} {{ if .Password }} - Password protected + lock {{ end }} {{ if .Duration }} - Duration + hourglass {{ .Duration.Hours }}h {{ end }} @@ -53,7 +53,7 @@

    - diff --git a/cmd/fibr/templates/story.html b/cmd/fibr/templates/story.html index 0cf2a459..762304e6 100644 --- a/cmd/fibr/templates/story.html +++ b/cmd/fibr/templates/story.html @@ -140,21 +140,21 @@
    {{ if not .Request.Share.Story }} @@ -167,7 +167,7 @@ {{ template "async-image-item-large" .RenderItem }} {{ if .IsVideo }} - Play video + play icon {{ end }} @@ -175,7 +175,7 @@ {{ if or (.Exif.Geocode.HasAddress) (not .Exif.Date.IsZero) }}

    {{ if .Exif.Geocode.HasAddress }} - Location + location {{ if index .Exif.Geocode.Address "city_district" }} {{ index .Exif.Geocode.Address "city_district" }}, @@ -192,7 +192,7 @@ {{ if not .Exif.Date.IsZero }} - Location + calendar {{ .Exif.Date.Format "2006-01-02T15:04:05Z07:00" }} {{ end }}

    @@ -200,7 +200,7 @@ {{ if index .Exif.Data "Model" }}

    - Camera model + camera {{ index .Exif.Data "Model" }}

    {{ end }} @@ -216,11 +216,11 @@ {{ if $root.Request.CanEdit }} - Edit description + edit description {{ end }}
    diff --git a/cmd/fibr/templates/svg.html b/cmd/fibr/templates/svg.html index 4e87de47..5ef9909d 100644 --- a/cmd/fibr/templates/svg.html +++ b/cmd/fibr/templates/svg.html @@ -157,3 +157,11 @@ {{ define "svg-folder-search" }} {{ end }} + +{{ define "svg-folder-back" }} + +{{ end }} + +{{ define "svg-tag" }} + +{{ end }} diff --git a/cmd/fibr/templates/webhook-list.html b/cmd/fibr/templates/webhook-list.html index 68946163..4957c3b8 100644 --- a/cmd/fibr/templates/webhook-list.html +++ b/cmd/fibr/templates/webhook-list.html @@ -67,7 +67,7 @@

    diff --git a/pkg/crud/browse.go b/pkg/crud/browse.go index f1fdf785..82d203fe 100644 --- a/pkg/crud/browse.go +++ b/pkg/crud/browse.go @@ -23,7 +23,7 @@ func (a App) browse(ctx context.Context, request provider.Request, item absto.It previous provider.RenderItem next provider.RenderItem files []absto.Item - exif provider.Metadata + metadata provider.Metadata ) wg := concurrent.NewSimple() @@ -38,9 +38,9 @@ func (a App) browse(ctx context.Context, request provider.Request, item absto.It wg.Go(func() { var err error - exif, err = a.exifApp.GetMetadataFor(ctx, item) + metadata, err = a.metadataApp.GetMetadataFor(ctx, item) if err != nil && !absto.IsNotExist(err) { - logger.WithField("item", item.Pathname).Error("load exif: %s", err) + logger.WithField("item", item.Pathname).Error("load metadata: %s", err) } }) @@ -54,7 +54,7 @@ func (a App) browse(ctx context.Context, request provider.Request, item absto.It return renderer.NewPage("file", http.StatusOK, map[string]any{ "Paths": getPathParts(request), "File": renderItem, - "Exif": exif, + "Exif": metadata, "Cover": a.getCover(ctx, request, files), "HasStream": renderItem.IsVideo() && a.thumbnailApp.HasStream(ctx, item), diff --git a/pkg/crud/crud.go b/pkg/crud/crud.go index 41e16e7a..1e8c58a8 100644 --- a/pkg/crud/crud.go +++ b/pkg/crud/crud.go @@ -34,7 +34,7 @@ type App struct { storageApp absto.Storage shareApp provider.ShareManager webhookApp provider.WebhookManager - exifApp provider.MetadataManager + metadataApp provider.MetadataManager searchApp search.App pushEvent provider.EventProducer exclusiveApp exclusive.App @@ -77,7 +77,7 @@ func New(config Config, storageApp absto.Storage, filteredStorage absto.Storage, storageApp: filteredStorage, rendererApp: rendererApp, thumbnailApp: thumbnailApp, - exifApp: exifApp, + metadataApp: exifApp, shareApp: shareApp, webhookApp: webhookApp, searchApp: searchApp, diff --git a/pkg/crud/get.go b/pkg/crud/get.go index 717215e1..7aab1653 100644 --- a/pkg/crud/get.go +++ b/pkg/crud/get.go @@ -198,7 +198,7 @@ func (a App) serveGeoJSON(w http.ResponseWriter, r *http.Request, request provid var hash string if query.GetBool(r, "search") { hash = a.exifHash(ctx, items) - } else if exifs, err := a.exifApp.ListDir(ctx, item); err != nil { + } else if exifs, err := a.metadataApp.ListDir(ctx, item); err != nil { logger.WithField("item", item.Pathname).Error("list exifs: %s", err) } else { hash = sha.New(exifs) @@ -209,7 +209,7 @@ func (a App) serveGeoJSON(w http.ResponseWriter, r *http.Request, request provid return } - exifs, err := a.exifApp.GetAllMetadataFor(ctx, items...) + exifs, err := a.metadataApp.GetAllMetadataFor(ctx, items...) if err != nil { a.error(w, r, request, err) } diff --git a/pkg/crud/get_test.go b/pkg/crud/get_test.go index c81ec709..c5a746fd 100644 --- a/pkg/crud/get_test.go +++ b/pkg/crud/get_test.go @@ -76,7 +76,7 @@ func BenchmarkServeGeoJSON(b *testing.B) { mockExif.EXPECT().ListDir(gomock.Any(), gomock.Any()).Return(items, nil).AnyTimes() instance := App{ - exifApp: mockExif, + metadataApp: mockExif, } r := httptest.NewRequest(http.MethodGet, "/", nil) diff --git a/pkg/crud/list.go b/pkg/crud/list.go index 3c21d1fa..3ca37456 100644 --- a/pkg/crud/list.go +++ b/pkg/crud/list.go @@ -35,7 +35,7 @@ func (a App) list(ctx context.Context, request provider.Request, message rendere wg.Go(func() { var err error - directoryAggregate, err = a.exifApp.GetAggregateFor(ctx, item) + directoryAggregate, err = a.metadataApp.GetAggregateFor(ctx, item) if err != nil && !absto.IsNotExist(err) { listLogger(item.Pathname).Error("get aggregate: %s", err) } @@ -45,9 +45,19 @@ func (a App) list(ctx context.Context, request provider.Request, message rendere wg.Go(func() { var err error - aggregates, err = a.exifApp.GetAllAggregateFor(ctx, files...) + aggregates, err = a.metadataApp.GetAllAggregateFor(ctx, files...) if err != nil { - listLogger(item.Pathname).Error("list exifs: %s", err) + listLogger(item.Pathname).Error("list aggregates: %s", err) + } + }) + + var metadatas map[string]provider.Metadata + wg.Go(func() { + var err error + + metadatas, err = a.metadataApp.GetAllMetadataFor(ctx, files...) + if err != nil { + listLogger(item.Pathname).Error("list metadatas: %s", err) } }) @@ -85,8 +95,13 @@ func (a App) list(ctx context.Context, request provider.Request, message rendere for index, item := range files { renderItem := provider.StorageToRender(item, request) - renderItem.Aggregate = aggregates[item.ID] - renderItem.IsCover = item.Name == directoryAggregate.Cover + renderItem.Tags = metadatas[item.ID].Tags + + if item.IsDir { + renderItem.Aggregate = aggregates[item.ID] + } else { + renderItem.IsCover = item.Name == directoryAggregate.Cover + } items[index] = renderItem } diff --git a/pkg/crud/post.go b/pkg/crud/post.go index eaa403d1..414f6364 100644 --- a/pkg/crud/post.go +++ b/pkg/crud/post.go @@ -170,7 +170,7 @@ func (a App) handlePostDescription(w http.ResponseWriter, r *http.Request, reque description := r.FormValue("description") - if _, err = a.exifApp.Update(ctx, item, provider.ReplaceDescription(description)); err != nil { + if _, err = a.metadataApp.Update(ctx, item, provider.ReplaceDescription(description)); err != nil { a.error(w, r, request, err) return } diff --git a/pkg/crud/rename.go b/pkg/crud/rename.go index c18a118b..8a60e623 100644 --- a/pkg/crud/rename.go +++ b/pkg/crud/rename.go @@ -70,7 +70,7 @@ func (a App) Rename(w http.ResponseWriter, r *http.Request, request provider.Req var oldItem absto.Item var newItem absto.Item - if oldPath != newPath { + if !strings.EqualFold(oldPath, newPath) { if _, err := a.checkFile(ctx, newPath, false); err != nil { a.error(w, r, request, err) return @@ -93,15 +93,22 @@ func (a App) Rename(w http.ResponseWriter, r *http.Request, request provider.Req provider.SetPrefsCookie(w, request) } } else { - newItem, err = a.checkFile(ctx, newPath, true) + newItem, err = a.checkFile(ctx, oldPath, true) if err != nil { a.error(w, r, request, err) return } } - if !newItem.IsDir && cover { - if err := a.updateCover(ctx, newItem); err != nil { + if !newItem.IsDir { + if cover { + if err := a.updateCover(ctx, newItem); err != nil { + a.error(w, r, request, model.WrapInternal(err)) + return + } + } + + if _, err = a.metadataApp.Update(ctx, newItem, provider.ReplaceTags(strings.Split(r.Form.Get("tags"), " "))); err != nil { a.error(w, r, request, model.WrapInternal(err)) return } @@ -164,14 +171,14 @@ func (a App) updateCover(ctx context.Context, item absto.Item) error { return fmt.Errorf("get directory: %w", err) } - aggregate, err := a.exifApp.GetAggregateFor(ctx, directory) + aggregate, err := a.metadataApp.GetAggregateFor(ctx, directory) if err != nil && !absto.IsNotExist(err) { return fmt.Errorf("get aggregate: %w", err) } aggregate.Cover = item.Name - if err := a.exifApp.SaveAggregateFor(ctx, directory, aggregate); err != nil { + if err := a.metadataApp.SaveAggregateFor(ctx, directory, aggregate); err != nil { return fmt.Errorf("save aggregate: %w", err) } diff --git a/pkg/crud/story.go b/pkg/crud/story.go index ca6d3581..0d428d54 100644 --- a/pkg/crud/story.go +++ b/pkg/crud/story.go @@ -28,7 +28,7 @@ func (a App) story(r *http.Request, request provider.Request, item absto.Item, f wg.Go(func() { var err error - directoryAggregate, err = a.exifApp.GetAggregateFor(ctx, item) + directoryAggregate, err = a.metadataApp.GetAggregateFor(ctx, item) if err != nil && !absto.IsNotExist(err) { logger.WithField("fn", "crud.story").WithField("item", request.Path).Error("get aggregate: %s", err) } @@ -38,7 +38,7 @@ func (a App) story(r *http.Request, request provider.Request, item absto.Item, f wg.Go(func() { var err error - exifs, err = a.exifApp.GetAllMetadataFor(ctx, files...) + exifs, err = a.metadataApp.GetAllMetadataFor(ctx, files...) if err != nil { logger.WithField("fn", "crud.story").WithField("item", request.Path).Error("list exifs: %s", err) } diff --git a/pkg/fibr/renderer.go b/pkg/fibr/renderer.go index a1aa3827..ec1f14a1 100644 --- a/pkg/fibr/renderer.go +++ b/pkg/fibr/renderer.go @@ -18,6 +18,9 @@ var FuncMap = template.FuncMap{ "rebuildPaths": func(parts []string, index int) string { return fmt.Sprintf("/%s/", strings.Join(parts[:index+1], "/")) }, + "join": func(arr []string, separator string) string { + return strings.Join(arr, separator) + }, "raw": func(content string) template.URL { return template.URL(content) }, diff --git a/pkg/metadata/metadata.go b/pkg/metadata/metadata.go index 936ef271..774efc27 100644 --- a/pkg/metadata/metadata.go +++ b/pkg/metadata/metadata.go @@ -18,7 +18,7 @@ func (a App) Update(ctx context.Context, item absto.Item, opts ...provider.Metad metadata, err := a.GetMetadataFor(ctx, item) if err != nil && !absto.IsNotExist(err) { - logger.WithField("item", item.Pathname).Error("load exif: %s", err) + logger.WithField("item", item.Pathname).Error("load metadata: %s", err) } for _, opt := range opts { @@ -26,7 +26,7 @@ func (a App) Update(ctx context.Context, item absto.Item, opts ...provider.Metad } if err = a.exifCacheApp.EvictOnSuccess(ctx, item, a.saveMetadata(ctx, item, metadata)); err != nil { - return fmt.Errorf("save exif: %w", err) + return fmt.Errorf("save metadata: %w", err) } return nil diff --git a/pkg/provider/metadata.go b/pkg/provider/metadata.go index a9e0b8af..f007cc99 100644 --- a/pkg/provider/metadata.go +++ b/pkg/provider/metadata.go @@ -46,19 +46,9 @@ func ReplaceDescription(description string) MetadataAction { } } -func AddTag(tag string) MetadataAction { +func ReplaceTags(tags []string) MetadataAction { return func(instance Metadata) Metadata { - instance.Tags = append(instance.Tags, tag) - - return instance - } -} - -func RemoveTag(tag string) MetadataAction { - return func(instance Metadata) Metadata { - if index := findIndex(instance.Tags, tag); index != -1 { - instance.Tags = append(instance.Tags[:index], instance.Tags[index+1:]...) - } + instance.Tags = tags return instance } diff --git a/pkg/provider/storage.go b/pkg/provider/storage.go index b449be5a..6c84f340 100644 --- a/pkg/provider/storage.go +++ b/pkg/provider/storage.go @@ -56,9 +56,11 @@ func (a ByID) Less(i, j int) bool { } type RenderItem struct { - Aggregate - URL string - Path string + Aggregate Aggregate + Tags []string + URL string + Path string + absto.Item HasThumbnail bool IsCover bool diff --git a/pkg/provider/util.go b/pkg/provider/util.go index 49e2b125..1ac850ba 100644 --- a/pkg/provider/util.go +++ b/pkg/provider/util.go @@ -265,13 +265,3 @@ func EtagMatch(w http.ResponseWriter, r *http.Request, hash string) (etag string return } - -func findIndex(arr []string, value string) int { - for index, item := range arr { - if item == value { - return index - } - } - - return -1 -} diff --git a/pkg/thumbnail/thumbnail.go b/pkg/thumbnail/thumbnail.go index e0f9f78a..8daa9f72 100644 --- a/pkg/thumbnail/thumbnail.go +++ b/pkg/thumbnail/thumbnail.go @@ -270,7 +270,7 @@ func (a App) thumbnailHash(ctx context.Context, items []absto.Item) string { } thumbnails, err := a.cacheApp.List(ctx, onCacheError, ids...) - if err != nil { + if err != nil && !absto.IsNotExist(err) { logger.Error("list thumbnails from cache: %s", err) }