Rework media management to use metadata.

This commit is contained in:
Feufochmar 2021-05-24 18:41:10 +02:00
parent a02208ed74
commit c62053d28b
3 changed files with 262 additions and 81 deletions

123
src/notepad/media.rkt Normal file
View File

@ -0,0 +1,123 @@
#lang racket/base
(require
"stored-objects.rkt"
"user.rkt"
; Formatting
(prefix-in scrib: scribble/reader)
)
(provide
; Accessors
media-name media-file media-type media-author media-date media-licence media-public?
; Operations
new-media update-media remove-media
get-media-by-name get-media-by-file get-all-medias get-public-medias
; Init repo
media-init-repository
)
; Media metadata structure
(stored-class notepadmedia
(name : string?) ; Name of the media, used as shortcut in notes (@media[]{}).
(file : string?) ; file path of the media
(type : string?) ; type of media
(author : integer?) ; author of last update, id of user
(date : integer?) ; date of last update
(licence : string?) ; Licence of the media
(public : boolean?) ; Media publicly listed ?
)
; Repo initialization
(define (media-init-repository repo)
(init-repository repo
notepadmedia))
; Accessors
(define media-name notepadmedia-name)
(define media-file notepadmedia-file)
(define media-type notepadmedia-type)
(define (media-author nt)
(define author (get-user-by-id (notepadmedia-author nt)))
(and author (user-pseudo author)))
(define (media-date nt)
(define dt (seconds->date (notepadmedia-date nt)))
(define (add-zero x)
(if (< x 10)
(string-append "0" (number->string x))
x))
(format "~a-~a-~a"
(date-year dt)
(add-zero (date-month dt))
(add-zero (date-day dt))))
(define media-licence notepadmedia-licence)
(define media-public? notepadmedia-public)
; Media Operations
; New media
(define (new-media
#:name name
#:file file
#:type type
#:author author
#:licence (licence #f)
#:public? (public? #f))
(within-transaction (class-repository notepadmedia)
(define md (instanciate notepadmedia))
(set-notepadmedia-name! md name)
(set-notepadmedia-file! md file)
(set-notepadmedia-type! md type)
(set-notepadmedia-author! md (instance-identifier author))
(set-notepadmedia-date! md (current-seconds))
(set-notepadmedia-licence! md licence)
(set-notepadmedia-public! md public?)
(save-instance md)
md))
; Update media. If md is #f, create a new media.
(define (update-media md
#:name name
#:file file
#:type type
#:author author
#:licence (licence #f)
#:public? (public? #f)
)
(within-transaction (class-repository notepadmedia)
(define new-md (or md (instanciate notepadmedia)))
(set-notepadmedia-name! new-md name)
(set-notepadmedia-file! new-md file)
(set-notepadmedia-type! new-md type)
(set-notepadmedia-author! new-md (instance-identifier author))
(set-notepadmedia-date! new-md (current-seconds))
(set-notepadmedia-licence! new-md licence)
(set-notepadmedia-public! new-md public?)
(save-instance new-md)
new-md))
; Remove a media
(define (remove-media md)
(within-transaction (class-repository notepadmedia)
; Remove media
(delete-instance md)))
; Find by name
(define (get-media-by-name name)
(define medias (find-instances notepadmedia `((name . ,name))))
(and (not (null? medias))
(car medias)))
; Find by file
(define (get-media-by-file file)
(define medias (find-instances notepadmedia `((file . ,file))))
(and (not (null? medias))
(car medias)))
; Get all medias
(define (get-all-medias)
(list-instances notepadmedia))
; Get all public medias
(define (get-public-medias)
(find-instances notepadmedia '((public . #t))))

View File

@ -4,15 +4,14 @@
(provide
make-notepad
; Media operations
notepad-list-media notepad-has-media?
notepad-media-type notepad-new-media
notepad-move-media notepad-delete-media
notepad-new-media notepad-update-media notepad-delete-media
)
(require
racket/port
racket/string
"notes.rkt"
"media.rkt"
"user.rkt"
"stored-objects.rkt"
)
@ -41,6 +40,7 @@
(define repo (open-repository 'sqlite3 repo-path))
(user-init-repository repo)
(note-init-repository repo)
(media-init-repository repo)
(notepad
dir
repo))
@ -49,42 +49,70 @@
(define (notepad-media-dir np)
(string-append (notepad-directory np) "/media"))
; List all media
(define (notepad-list-media np)
(map path->string (directory-list (notepad-media-dir np))))
; Does the notepad has a given media ?
(define (notepad-has-media? np media)
(and media (file-exists? (string-append (notepad-media-dir np) "/" media))))
; Get the type of media
; Return 'image, 'other or #f
(define (notepad-media-type np media)
(cond
( (ormap (lambda (x) (string-suffix? media x)) '(".png" ".jpg" ".gif" ".jpeg" ".svg"))
'image)
"image")
( #t
'other)))
"other")))
; Save a media
; Takes a filename and an input stream
(define (notepad-new-media np filename in)
(define filepath (string-append (notepad-media-dir np) "/" filename))
(define (notepad-new-media np
#:path path
#:input-stream in
#:name name
#:author author
#:public? public?)
(define filepath (string-append (notepad-media-dir np) "/" path))
(call-with-output-file
filepath
(lambda (out)
(copy-port in out)
(close-input-port in))
(close-input-port in)
(new-media
#:name name
#:file path
#:type (notepad-media-type np path)
#:author author
#:public? public?))
#:exists 'truncate/replace))
; Move a media
(define (notepad-move-media np media filename)
(define media-dir (notepad-media-dir np))
(rename-file-or-directory
(string-append media-dir "/" media)
(string-append media-dir "/" filename)))
; Update a media - return #t if there is no error
(define (notepad-update-media np media
#:path path
#:name name
#:author author
#:public? public?)
(cond
( (or (not path)
(and path (equal? "" path) (string-contains? path "/"))
(not name)
(and name (equal? "" name)))
; Return KO
#f)
( #t
; Move file
(when (not (equal? path (media-file media)))
(define media-dir (notepad-media-dir np))
(rename-file-or-directory
(string-append media-dir "/" (media-file media))
(string-append media-dir "/" path)))
; Update metadata
(update-media media
#:name name
#:file path
#:type (media-type media)
#:author author
#:public? public?)
; Return OK
#t)))
; Remove a media
(define (notepad-delete-media np media)
(delete-file (string-append (notepad-media-dir np) "/" media)))
; Delete file
(delete-file (string-append (notepad-media-dir np) "/" (media-file media)))
; Delete metadata
(remove-media media))

View File

@ -8,6 +8,7 @@
"../notepad/notepad.rkt"
"../notepad/user.rkt"
"../notepad/notes.rkt"
"../notepad/media.rkt"
"../../configuration.rkt"
web-server/http/redirect
web-server/http/request-structs
@ -79,6 +80,12 @@
(content . (article ,(caddr err)))
)))
; Concat a lock to the name if not public
(define (displayed-name name public?)
(string-append
(if public? "" "🔒︎ ")
name))
; Notepad pages
; Link to a note with a given name
@ -104,12 +111,11 @@
(define notes (if connected-usr (get-all-notes) (get-public-notes)))
`(article
,@(if (null? notes)
'("Pas de notes.")
'("Pas de note.")
(map
(lambda (n)
`(div (a ((href ,(note-link 'show (note-name n))))
,(if (note-public? n) "" "🔒︎ ")
,(note-title n))))
,(displayed-name (note-title n) (note-public? n)))))
notes))
,@(if connected-usr
'((hr)
@ -128,7 +134,7 @@
(cond
( (and note (or (note-public? note) connected-usr))
( (pages:template
#:title (note-title note)
#:title (displayed-name (note-title note) (note-public? note))
#:author (note-author note)
#:date (note-date note)
#:content
@ -343,13 +349,14 @@
#:content
(lambda (param)
(define connected-usr (get-user param))
(define files (notepad-list-media notepad))
(define files (if connected-usr (get-all-medias) (get-public-medias)))
`(article
,@(if (null? files)
'("Pas de fichiers.")
'("Pas de fichier.")
(map
(lambda (x)
`(div (a ((href ,(media-link 'show x))) ,x)))
(lambda (n)
`(div (a ((href ,(media-link 'show (media-file n))))
,(displayed-name (media-name n) (media-public? n)))))
files))
,@(if connected-usr
'((hr)
@ -362,25 +369,27 @@
; Show a given media of the notepad.
(define (pages:notepad:media-show param)
(define connected-usr (get-user param))
(define media (weblet-parameter-ref param 'media #f))
(define direct-link (media-link 'get media))
(define file (weblet-parameter-ref param 'media #f))
(define direct-link (media-link 'get file))
(define media (get-media-by-file file))
(cond
( (notepad-has-media? notepad media)
( media
( (pages:template
#:title (string-append "Fichier: " media)
#:author "feuforeve.fr"
#:title (displayed-name (media-name media) (media-public? media))
#:author (media-author media)
#:date (media-date media)
#:content
`(article
,@(case (notepad-media-type notepad media)
( (image)
,@(case (media-type media)
( ("image")
`((a ((href ,direct-link)) (img ((src ,direct-link)(class "image-preview"))))(br)))
( else
'()))
(a ((href ,direct-link)) "Lien vers le fichier")
,@(if connected-usr
`((hr)
(a ((href ,(media-link 'edit media))) "Éditer") ""
(a ((href ,(media-link 'delete media))) "Supprimer"))
(a ((href ,(media-link 'edit file))) "Éditer") ""
(a ((href ,(media-link 'delete file))) "Supprimer"))
'())
))
param))
@ -414,22 +423,33 @@
(form ((action "/media/new")
(method "post")
(enctype "multipart/form-data"))
(label ((for "filename")) "Fichier à ajouter") (br)
(input ((id "filename")(name "filename")(type "file"))) (br)
(label ((for "filepath")) "Fichier à ajouter") (br)
(input ((id "filepath")(name "filepath")(type "file"))) (br)
(label ((for "filename")) "Nom du fichier") (br)
(input ((id "filename")(name "filename")(type "text"))) (br)
(label ((for "filepublic")) "Public")
(input ((id "filepublic")(name "filepublic")(type "checkbox")(value "on"))) (br)
(input ((type "submit")
(value "Ajouter le fichier")))
)))
param))
( (and connected-usr (eq? method 'post))
(define filepath (weblet-parameter-ref param 'filepath #f))
(define in (and filepath (weblet-parameter-file-port-ref param 'filepath)))
(define filename (weblet-parameter-ref param 'filename #f))
(define in (and filename (weblet-parameter-file-port-ref param 'filename)))
(define filepublic (equal? "on" (weblet-parameter-ref param 'filepublic #f)))
; Save file
(cond
( (and filename in)
(notepad-new-media notepad filename in)
( (and filepath in filename)
(notepad-new-media notepad
#:path filepath
#:input-stream in
#:name filename
#:author connected-usr
#:public? filepublic)
; Redirect
(redirect-to
(media-link 'show filename)
(media-link 'show filepath)
see-other))
( #t
; Redirect: upload failed
@ -447,11 +467,11 @@
(define (pages:notepad:media-edit param)
(define connected-usr (get-user param))
(define method (weblet-parameter-method param))
(define media (weblet-parameter-ref param 'media #f))
(define has-media? (notepad-has-media? notepad media))
(define file (weblet-parameter-ref param 'media #f))
(define media (get-media-by-file file))
(define failed? (equal? "t" (weblet-parameter-ref param 'error #f)))
(cond
( (and has-media? connected-usr (eq? method 'get))
( (and media connected-usr (eq? method 'get))
; User connected, get method : edit media form
( (pages:template
#:title "Éditer un fichier"
@ -460,32 +480,42 @@
; Display the page as a form
`(article
,@(if failed?
'("Erreur lors du renommage du fichier. Le nom doit être valide." (br))
'("Erreur lors du renommage du fichier. Le chemin doit être valide." (br))
'())
(form ((action ,(media-link 'edit media))
(method "post"))
(label ((for "filename")) "Nom du fichier") " "
(input ((id "filename")(name "filename")(type "text")(value ,media))) (br)
(input ((type "submit")
(value "Renommer le fichier")))
(form
((action ,(media-link 'edit file))(method "post"))
(label ((for "filepath")) "Chemin du fichier") " "
(input ((id "filepath")(name "filepath")(type "text")(value ,file))) (br)
(label ((for "filename")) "Nom du fichier") " "
(input ((id "filename")(name "filename")(type "text")(value ,(media-name media)))) (br)
(label ((for "filepublic")) "Public")
(input ((id "filepublic")(name "filepublic")(type "checkbox")(value "on")
,@(if (media-public? media) '((checked "true")) '()))) (br)
(input ((type "submit")
(value "Mettre à jour le fichier")))
)))
param))
( (and has-media? connected-usr (eq? method 'post))
( (and media connected-usr (eq? method 'post))
(define filepath (weblet-parameter-ref param 'filepath #f))
(define filename (weblet-parameter-ref param 'filename #f))
(cond
( (and filename (not (equal? filename "")) (not (equal? filename media)))
; Move file
(notepad-move-media notepad media filename)
; Redirectuser-check-password
(redirect-to
(media-link 'show filename)
see-other))
( #t
; Redirect: operation failed
(redirect-to
(media-link 'edit media "?error=t")
see-other))))
( has-media?
(define filepublic (equal? "on" (weblet-parameter-ref param 'filepublic #f)))
; Move file
(define ok?
(notepad-update-media notepad media
#:path filepath
#:name filename
#:author connected-usr
#:public? filepublic))
(if ok?
; Redirect to show
(redirect-to
(media-link 'show filepath)
see-other)
; Redirect: operation failed
(redirect-to
(media-link 'edit file "?error=t")
see-other)))
( media
; Not allowed
(pages:notepad:error param 'unauthorized))
( #t
@ -499,33 +529,33 @@
(define (pages:notepad:media-delete param)
(define connected-usr (get-user param))
(define method (weblet-parameter-method param))
(define media (weblet-parameter-ref param 'media #f))
(define has-media? (notepad-has-media? notepad media))
(define file (weblet-parameter-ref param 'media #f))
(define media (get-media-by-file file))
(cond
( (and has-media? connected-usr (eq? method 'get))
( (and media connected-usr (eq? method 'get))
; Method get => ask for confirmation
( (pages:template
#:title (string-append "Suppression du fichier " media)
#:title (string-append "Suppression de " (media-name media))
#:author (user-name connected-usr)
#:content
`(article
(form ((action ,(media-link 'delete media))
(form ((action ,(media-link 'delete file))
(method "post"))
(h3 "Supprimer le fichier " ,media " ? ")
(h3 "Supprimer " ,(media-name media) " ? ")
"Cette action est irréversible." (br)
(input ((type "submit")
(value "Oui, supprimer le fichier")))
(input ((type "submit")(formaction ,(media-link 'show media))
(input ((type "submit")(formaction ,(media-link 'show file))
(formmethod "get")(value "Non, garder le fichier")))
)))
param))
( (and has-media? connected-usr (eq? method 'post))
( (and media connected-usr (eq? method 'post))
; Method post => remove
(notepad-delete-media notepad media)
(redirect-to
"/media/list"
see-other))
( has-media?
( media
; Unauthorized
(pages:notepad:error param 'unauthorized))
( #t