parent
f6078b66e0
commit
9d4572d3d8
@ -0,0 +1,28 @@ |
|||||||
|
"""Added article ratings. |
||||||
|
|
||||||
|
Revision ID: 21ec84874208 |
||||||
|
Revises: 3d58e8ebf8c6 |
||||||
|
Create Date: 2020-03-19 01:10:12.194485 |
||||||
|
|
||||||
|
""" |
||||||
|
from alembic import op |
||||||
|
import sqlalchemy as sa |
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic. |
||||||
|
revision = '21ec84874208' |
||||||
|
down_revision = '3d58e8ebf8c6' |
||||||
|
branch_labels = None |
||||||
|
depends_on = None |
||||||
|
|
||||||
|
|
||||||
|
def upgrade(): |
||||||
|
# ### commands auto generated by Alembic - please adjust! ### |
||||||
|
op.add_column('article', sa.Column('article_rating', sa.Integer(), nullable=True)) |
||||||
|
# ### end Alembic commands ### |
||||||
|
|
||||||
|
|
||||||
|
def downgrade(): |
||||||
|
# ### commands auto generated by Alembic - please adjust! ### |
||||||
|
op.drop_column('article', 'article_rating') |
||||||
|
# ### end Alembic commands ### |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 6.0 KiB |
@ -0,0 +1,2 @@ |
|||||||
|
.rating-stars { float: right ; margin-top: -0.1em ; margin-right: 0.25em ; } |
||||||
|
.rating-stars img { height: 0.75em ; margin-right: 0.1em ; cursor: pointer ; } |
@ -0,0 +1,63 @@ |
|||||||
|
import React from "react" ; |
||||||
|
import "./RatingStars.css" ; |
||||||
|
|
||||||
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
export class RatingStars extends React.Component |
||||||
|
{ |
||||||
|
|
||||||
|
constructor( props ) { |
||||||
|
// initialize
|
||||||
|
super( props ) ; |
||||||
|
this.state = { |
||||||
|
rating: props.rating, |
||||||
|
} ; |
||||||
|
} |
||||||
|
|
||||||
|
render() { |
||||||
|
|
||||||
|
let changeRating = ( starIndex ) => { |
||||||
|
// update the rating
|
||||||
|
let newRating ; |
||||||
|
if ( starRefs[starIndex].src.indexOf( "rating-star-disabled.png" ) !== -1 ) |
||||||
|
newRating = starIndex + 1 ; |
||||||
|
else { |
||||||
|
// NOTE: We get here if the clicked-on star is enabled. If this is the highest enabled star,
|
||||||
|
// we disable it (i.e. set the rating to N-1), otherwise we make it the highest star (i.e. set
|
||||||
|
// the rating to N). This has the down-side that if the user wants to set a rating of 0,
|
||||||
|
// they have to set the rating to 1 first, then set it to 0, but this is unlikely to be an issue
|
||||||
|
// i.e. going from 1 to 0 will be far more common than 3 to 0.
|
||||||
|
if ( starIndex+1 === this.state.rating ) |
||||||
|
newRating = starIndex ; |
||||||
|
else |
||||||
|
newRating = starIndex + 1 ; |
||||||
|
} |
||||||
|
const prevRating = this.state.rating ; |
||||||
|
this.setState( { rating: newRating } ) ; |
||||||
|
// notify the parent
|
||||||
|
if ( this.props.onChange ) { |
||||||
|
this.props.onChange( newRating, () => { |
||||||
|
this.setState( { rating: prevRating } ) ; // nb: the update failed, rollback
|
||||||
|
} ) ; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// prepare the rating stars
|
||||||
|
let stars=[], starRefs={} ; |
||||||
|
for ( let i=0 ; i < 3 ; ++i ) { |
||||||
|
const fname = this.state.rating > i ? "rating-star.png" : "rating-star-disabled.png" ; |
||||||
|
stars.push( |
||||||
|
<img src={"/images/"+fname} key={i} alt="Rating star." |
||||||
|
ref = { r => starRefs[i] = r } |
||||||
|
onClick={ () => changeRating(i) } |
||||||
|
/> |
||||||
|
) ; |
||||||
|
} |
||||||
|
|
||||||
|
// render the component
|
||||||
|
return ( <span className="rating-stars" title={this.props.title} > |
||||||
|
{stars} |
||||||
|
</span> ) ; |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue