diff --git a/frontend/src/dialog/photo-edit/meta.vue b/frontend/src/dialog/photo-edit/meta.vue index b4d36fac4..84a609f0e 100644 --- a/frontend/src/dialog/photo-edit/meta.vue +++ b/frontend/src/dialog/photo-edit/meta.vue @@ -168,7 +168,16 @@ v-model="model.PhotoAltitude" > - + + + - - - - - - Note: This is a first draft and may contain bugs - - Cancel + Close @@ -353,12 +348,14 @@ if(!this.date) { return ""; } + return DateTime.fromISO(this.date).toLocaleString(DateTime.DATE_FULL); }, timeFormatted() { if(!this.time) { return ""; } + return DateTime.fromISO(this.time).toLocaleString(DateTime.TIME_24_WITH_SECONDS); }, countryOptions() { @@ -387,12 +384,16 @@ model.refreshFileAttr(); if(model.TakenAt) { - this.date = DateTime.fromISO(model.TakenAt).toISODate(); - - this.time = DateTime.fromISO(model.TakenAt).toFormat("HH:mm:ss"); + const date = DateTime.fromISO(model.TakenAt).toUTC(); + this.date = date.toISODate(); + this.time = date.toFormat("HH:mm:ss"); } }, save() { + if(this.time && this.date) { + this.model.TakenAt = this.date + "T" + this.time + "Z"; + } + this.model.update(); }, cancel() { diff --git a/frontend/src/dialog/photo-edit/todo.vue b/frontend/src/dialog/photo-edit/todo.vue index 5c85ce3a1..f6f1866a7 100644 --- a/frontend/src/dialog/photo-edit/todo.vue +++ b/frontend/src/dialog/photo-edit/todo.vue @@ -2,7 +2,7 @@

- This is a first draft for an edit dialog. Feedback and contributions welcome. + This is work in progress. Feedback and contributions welcome.

diff --git a/frontend/src/model/abstract.js b/frontend/src/model/abstract.js index 364700122..c33766736 100644 --- a/frontend/src/model/abstract.js +++ b/frontend/src/model/abstract.js @@ -13,10 +13,10 @@ class Abstract { } setValues(values) { - if(!values) return; + if (!values) return; - for(let key in values) { - if(values.hasOwnProperty(key) && key !== "__originalValues") { + for (let key in values) { + if (values.hasOwnProperty(key) && key !== "__originalValues") { this[key] = values[key]; this.__originalValues[key] = values[key]; } @@ -25,12 +25,32 @@ class Abstract { return this; } - getValues() { + getValues(changed) { const result = {}; + const defaults = this.getDefaults(); - for(let key in this.__originalValues) { - if(this.__originalValues.hasOwnProperty(key) && key !== "__originalValues") { - result[key] = this[key]; + for (let key in this.__originalValues) { + if (this.__originalValues.hasOwnProperty(key) && key !== "__originalValues") { + let val; + if (defaults.hasOwnProperty(key)) { + switch (typeof defaults[key]) { + case "bigint": + case "number": + val = parseFloat(this[key]); + break; + case "boolean": + val = !!this[key]; + break; + default: + val = this[key]; + } + } else { + val = this[key]; + } + + if(!changed || val !== this.__originalValues[key]) { + result[key] = val; + } } } @@ -62,7 +82,7 @@ class Abstract { } update() { - return Api.put(this.getEntityResource(), this.getValues()).then((response) => Promise.resolve(this.setValues(response.data))); + return Api.put(this.getEntityResource(), this.getValues(true)).then((response) => Promise.resolve(this.setValues(response.data))); } remove() { @@ -113,7 +133,7 @@ class Abstract { return Api.get(this.getCollectionResource(), options).then((response) => { response.models = []; - for(let i = 0; i < response.data.length; i++) { + for (let i = 0; i < response.data.length; i++) { response.models.push(new this(response.data[i])); } diff --git a/frontend/src/model/photo.js b/frontend/src/model/photo.js index fdb89b2af..11d8a10b4 100644 --- a/frontend/src/model/photo.js +++ b/frontend/src/model/photo.js @@ -25,7 +25,7 @@ class Photo extends Abstract { PhotoAltitude: 0, PhotoFocalLength: 0, PhotoIso: 0, - PhotoFNumber: 0, + PhotoFNumber: 0.0, PhotoExposure: "", PhotoViews: 0, Camera: {}, diff --git a/internal/entity/photo.go b/internal/entity/photo.go index c0ce4e37a..9aa747db4 100644 --- a/internal/entity/photo.go +++ b/internal/entity/photo.go @@ -12,49 +12,49 @@ import ( // A photo can have multiple images and sidecar files type Photo struct { ID uint `gorm:"primary_key"` - TakenAt time.Time `gorm:"type:datetime;index:idx_photos_taken_uuid;"` + TakenAt time.Time `gorm:"type:datetime;index:idx_photos_taken_uuid;" json:"TakenAt"` PhotoUUID string `gorm:"type:varbinary(36);unique_index;index:idx_photos_taken_uuid;"` PhotoPath string `gorm:"type:varbinary(512);index;"` PhotoName string `gorm:"type:varbinary(256);"` PhotoTitle string `json:"PhotoTitle"` - PhotoTitleChanged bool - PhotoDescription string `gorm:"type:text;"` - PhotoNotes string `gorm:"type:text;"` - PhotoArtist string `json:"PhotoArtist"` - PhotoCopyright string `json:"PhotoCopyright"` - PhotoFavorite bool `json:"PhotoFavorite"` - PhotoPrivate bool `json:"PhotoPrivate"` - PhotoNSFW bool `json:"PhotoNSFW"` - PhotoStory bool `json:"PhotoStory"` - PhotoLat float64 `gorm:"index;"` - PhotoLng float64 `gorm:"index;"` - PhotoAltitude int - PhotoFocalLength int - PhotoIso int - PhotoFNumber float64 - PhotoExposure string `gorm:"type:varbinary(64);"` - PhotoViews uint - Camera *Camera - CameraID uint `gorm:"index:idx_photos_camera_lens;"` - Lens *Lens - LensID uint `gorm:"index:idx_photos_camera_lens;"` - CountryChanged bool - Location *Location - LocationID string `gorm:"type:varbinary(16);index;"` - Place *Place - PlaceID string `gorm:"type:varbinary(16);index;"` - LocationChanged bool - LocationEstimated bool - PhotoCountry string `gorm:"index:idx_photos_country_year_month;"` + PhotoTitleChanged bool `json:"PhotoTitleChanged"` + PhotoDescription string `gorm:"type:text;" json:"PhotoDescription"` + PhotoNotes string `gorm:"type:text;" json:"PhotoNotes"` + PhotoArtist string `json:"PhotoArtist"` + PhotoCopyright string `json:"PhotoCopyright"` + PhotoFavorite bool `json:"PhotoFavorite"` + PhotoPrivate bool `json:"PhotoPrivate"` + PhotoNSFW bool `json:"PhotoNSFW"` + PhotoStory bool `json:"PhotoStory"` + PhotoLat float64 `gorm:"index;" json:"PhotoLat"` + PhotoLng float64 `gorm:"index;" json:"PhotoLng"` + PhotoAltitude int `json:"PhotoAltitude"` + PhotoFocalLength int `json:"PhotoFocalLength"` + PhotoIso int `json:"PhotoIso"` + PhotoFNumber float64 `json:"PhotoFNumber"` + PhotoExposure string `gorm:"type:varbinary(64);" json:"PhotoExposure"` + CameraID uint `gorm:"index:idx_photos_camera_lens;" json:"CameraID"` + LensID uint `gorm:"index:idx_photos_camera_lens;" json:"LensID"` + LocationID string `gorm:"type:varbinary(16);index;" json:"LocationID"` + PlaceID string `gorm:"type:varbinary(16);index;" json:"PlaceID"` + LocationChanged bool `json:"LocationChanged"` + LocationEstimated bool `json:"LocationEstimated"` + PhotoCountry string `gorm:"index:idx_photos_country_year_month;" json:"PhotoCountry"` PhotoYear int `gorm:"index:idx_photos_country_year_month;"` PhotoMonth int `gorm:"index:idx_photos_country_year_month;"` + TimeZone string `gorm:"type:varbinary(64);" json:"TimeZone"` TakenAtLocal time.Time `gorm:"type:datetime;"` TakenAtChanged bool - TimeZone string `gorm:"type:varbinary(64);"` + PhotoViews uint + CountryChanged bool + Camera *Camera `json:"-"` + Lens *Lens `json:"-"` + Location *Location `json:"-"` + Place *Place `json:"-"` Files []File Labels []Label - Keywords []Keyword - Albums []Album + Keywords []Keyword `json:"-"` + Albums []Album `json:"-"` CreatedAt time.Time UpdatedAt time.Time DeletedAt *time.Time `sql:"index"`