Merge a3013a2750e5ac111d3e7e06dff0310e180b2d1d into 12d08985855353681c02d9eb9448cd69dc5f69bf

This commit is contained in:
zacaj 2025-11-22 19:09:49 -08:00 committed by GitHub
commit 9993984e4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 45 additions and 4 deletions

View File

@ -0,0 +1,7 @@
-- +goose Up
-- +goose StatementBegin
ALTER TABLE annotation ADD COLUMN rated_at datetime;
-- +goose StatementEnd
-- +goose Down

View File

@ -6,6 +6,7 @@ type Annotations struct {
PlayCount int64 `structs:"play_count" json:"playCount,omitempty"`
PlayDate *time.Time `structs:"play_date" json:"playDate,omitempty" `
Rating int `structs:"rating" json:"rating,omitempty" `
RatedAt *time.Time `structs:"rated_at" json:"ratedAt,omitempty" `
Starred bool `structs:"starred" json:"starred,omitempty" `
StarredAt *time.Time `structs:"starred_at" json:"starredAt,omitempty"`
}

View File

@ -44,6 +44,7 @@ var fieldMap = map[string]*mappedField{
"loved": {field: "COALESCE(annotation.starred, false)"},
"dateloved": {field: "annotation.starred_at"},
"lastplayed": {field: "annotation.play_date"},
"daterated": {field: "annotation.rated_at"},
"playcount": {field: "COALESCE(annotation.play_count, 0)"},
"rating": {field: "COALESCE(annotation.rating, 0)"},
"mbz_album_id": {field: "media_file.mbz_album_id"},

View File

@ -388,6 +388,7 @@ func (r *playlistRepository) loadTracks(sel SelectBuilder, id string) (model.Pla
"coalesce(play_count, 0) as play_count",
"play_date",
"coalesce(rating, 0) as rating",
"rated_at",
"f.*",
"playlist_tracks.*",
"library.path as library_path",

View File

@ -97,6 +97,7 @@ func (r *playlistTrackRepository) Read(id string) (interface{}, error) {
"coalesce(rating, 0) as rating",
"starred_at",
"play_date",
"rated_at",
"f.*",
"playlist_tracks.*",
).

View File

@ -28,6 +28,7 @@ func (r sqlRepository) withAnnotation(query SelectBuilder, idField string) Selec
"coalesce(rating, 0) as rating",
"starred_at",
"play_date",
"rated_at",
)
if conf.Server.AlbumPlayCountMode == consts.AlbumPlayCountModeNormalized && r.tableName == "album" {
query = query.Columns(
@ -77,7 +78,8 @@ func (r sqlRepository) SetStar(starred bool, ids ...string) error {
}
func (r sqlRepository) SetRating(rating int, itemID string) error {
return r.annUpsert(map[string]interface{}{"rating": rating}, itemID)
ratedAt := time.Now()
return r.annUpsert(map[string]interface{}{"rating": rating, "rated_at": ratedAt}, itemID)
}
func (r sqlRepository) IncPlayCount(itemID string, ts time.Time) error {

View File

@ -1,10 +1,11 @@
import React from 'react'
import { isDateSet } from '../utils/validations'
import { DateField as RADateField } from 'react-admin'
export const DateField = (props) => {
const { record, source } = props
const value = record?.[source]
if (value === '0001-01-01T00:00:00Z' || value === null) return null
if (!isDateSet(value)) return null
return <RADateField {...props} />
}

View File

@ -7,6 +7,7 @@ import { makeStyles } from '@material-ui/core/styles'
import { useToggleLove } from './useToggleLove'
import { useRecordContext } from 'react-admin'
import config from '../config'
import { isDateSet } from '../utils/validations'
const useStyles = makeStyles({
love: {
@ -46,8 +47,13 @@ export const LoveButton = ({
<Button
onClick={handleToggleLove}
size={'small'}
disabled={disabled || loading || record?.missing}
disabled={disabled || loading || record.missing}
className={classes.love}
title={
isDateSet(record.starredAt)
? new Date(record.starredAt).toLocaleString()
: undefined
}
{...rest}
>
{record.starred ? (

View File

@ -2,6 +2,7 @@ import React, { useCallback } from 'react'
import PropTypes from 'prop-types'
import Rating from '@material-ui/lab/Rating'
import { makeStyles } from '@material-ui/core/styles'
import { isDateSet } from '../utils/validations'
import StarBorderIcon from '@material-ui/icons/StarBorder'
import clsx from 'clsx'
import { useRating } from './useRating'
@ -45,7 +46,14 @@ export const RatingField = ({
)
return (
<span onClick={(e) => stopPropagation(e)}>
<span
onClick={(e) => stopPropagation(e)}
title={
isDateSet(record.ratedAt)
? new Date(record.ratedAt).toLocaleString()
: undefined
}
>
<Rating
name={record.mediaFileId || record.id}
className={clsx(

View File

@ -10,3 +10,16 @@ export const urlValidate = (value) => {
return 'ra.validation.url'
}
}
export function isDateSet(date) {
if (!date) {
return false
}
if (typeof date === 'string') {
return date !== '0001-01-01T00:00:00Z'
}
if (date instanceof Date) {
return date.toISOString() !== '0001-01-01T00:00:00Z'
}
return !!date
}