Add cake day display in user page & posts/comments #682

This commit is contained in:
Filip785 2020-07-08 02:28:47 +02:00
parent 8fda7d00d5
commit 68e9755e59
10 changed files with 90 additions and 1 deletions

View file

@ -106,6 +106,7 @@ select
u.actor_id as creator_actor_id, u.actor_id as creator_actor_id,
u."local" as creator_local, u."local" as creator_local,
u."name" as creator_name, u."name" as creator_name,
u.published as creator_published,
u.avatar as creator_avatar, u.avatar as creator_avatar,
u.banned as banned, u.banned as banned,
cb.id::bool as banned_from_community, cb.id::bool as banned_from_community,
@ -490,6 +491,7 @@ select
u.actor_id as creator_actor_id, u.actor_id as creator_actor_id,
u.local as creator_local, u.local as creator_local,
u.name as creator_name, u.name as creator_name,
u.published as creator_published,
u.avatar as creator_avatar, u.avatar as creator_avatar,
-- score details -- score details
coalesce(cl.total, 0) as score, coalesce(cl.total, 0) as score,

View file

@ -28,6 +28,7 @@ table! {
creator_local -> Bool, creator_local -> Bool,
creator_name -> Varchar, creator_name -> Varchar,
creator_avatar -> Nullable<Text>, creator_avatar -> Nullable<Text>,
creator_published -> Timestamp,
score -> BigInt, score -> BigInt,
upvotes -> BigInt, upvotes -> BigInt,
downvotes -> BigInt, downvotes -> BigInt,
@ -63,6 +64,7 @@ table! {
creator_local -> Bool, creator_local -> Bool,
creator_name -> Varchar, creator_name -> Varchar,
creator_avatar -> Nullable<Text>, creator_avatar -> Nullable<Text>,
creator_published -> Timestamp,
score -> BigInt, score -> BigInt,
upvotes -> BigInt, upvotes -> BigInt,
downvotes -> BigInt, downvotes -> BigInt,
@ -101,6 +103,7 @@ pub struct CommentView {
pub creator_local: bool, pub creator_local: bool,
pub creator_name: String, pub creator_name: String,
pub creator_avatar: Option<String>, pub creator_avatar: Option<String>,
pub creator_published: chrono::NaiveDateTime,
pub score: i64, pub score: i64,
pub upvotes: i64, pub upvotes: i64,
pub downvotes: i64, pub downvotes: i64,
@ -314,6 +317,7 @@ table! {
creator_local -> Bool, creator_local -> Bool,
creator_name -> Varchar, creator_name -> Varchar,
creator_avatar -> Nullable<Text>, creator_avatar -> Nullable<Text>,
creator_published -> Timestamp,
score -> BigInt, score -> BigInt,
upvotes -> BigInt, upvotes -> BigInt,
downvotes -> BigInt, downvotes -> BigInt,
@ -353,6 +357,7 @@ pub struct ReplyView {
pub creator_local: bool, pub creator_local: bool,
pub creator_name: String, pub creator_name: String,
pub creator_avatar: Option<String>, pub creator_avatar: Option<String>,
pub creator_published: chrono::NaiveDateTime,
pub score: i64, pub score: i64,
pub upvotes: i64, pub upvotes: i64,
pub downvotes: i64, pub downvotes: i64,
@ -576,6 +581,7 @@ mod tests {
published: inserted_comment.published, published: inserted_comment.published,
updated: None, updated: None,
creator_name: inserted_user.name.to_owned(), creator_name: inserted_user.name.to_owned(),
creator_published: inserted_user.published,
creator_avatar: None, creator_avatar: None,
score: 1, score: 1,
downvotes: 0, downvotes: 0,
@ -609,6 +615,7 @@ mod tests {
published: inserted_comment.published, published: inserted_comment.published,
updated: None, updated: None,
creator_name: inserted_user.name.to_owned(), creator_name: inserted_user.name.to_owned(),
creator_published: inserted_user.published,
creator_avatar: None, creator_avatar: None,
score: 1, score: 1,
downvotes: 0, downvotes: 0,

View file

@ -28,6 +28,7 @@ table! {
creator_actor_id -> Text, creator_actor_id -> Text,
creator_local -> Bool, creator_local -> Bool,
creator_name -> Varchar, creator_name -> Varchar,
creator_published -> Timestamp,
creator_avatar -> Nullable<Text>, creator_avatar -> Nullable<Text>,
banned -> Bool, banned -> Bool,
banned_from_community -> Bool, banned_from_community -> Bool,
@ -75,6 +76,7 @@ table! {
creator_actor_id -> Text, creator_actor_id -> Text,
creator_local -> Bool, creator_local -> Bool,
creator_name -> Varchar, creator_name -> Varchar,
creator_published -> Timestamp,
creator_avatar -> Nullable<Text>, creator_avatar -> Nullable<Text>,
banned -> Bool, banned -> Bool,
banned_from_community -> Bool, banned_from_community -> Bool,
@ -125,6 +127,7 @@ pub struct PostView {
pub creator_actor_id: String, pub creator_actor_id: String,
pub creator_local: bool, pub creator_local: bool,
pub creator_name: String, pub creator_name: String,
pub creator_published: chrono::NaiveDateTime,
pub creator_avatar: Option<String>, pub creator_avatar: Option<String>,
pub banned: bool, pub banned: bool,
pub banned_from_community: bool, pub banned_from_community: bool,
@ -499,6 +502,7 @@ mod tests {
body: None, body: None,
creator_id: inserted_user.id, creator_id: inserted_user.id,
creator_name: user_name.to_owned(), creator_name: user_name.to_owned(),
creator_published: inserted_user.published,
creator_avatar: None, creator_avatar: None,
banned: false, banned: false,
banned_from_community: false, banned_from_community: false,
@ -548,6 +552,7 @@ mod tests {
stickied: false, stickied: false,
creator_id: inserted_user.id, creator_id: inserted_user.id,
creator_name: user_name, creator_name: user_name,
creator_published: inserted_user.published,
creator_avatar: None, creator_avatar: None,
banned: false, banned: false,
banned_from_community: false, banned_from_community: false,

41
ui/src/components/cake-day.tsx vendored Normal file
View file

@ -0,0 +1,41 @@
import { Component } from 'inferno';
import moment from 'moment';
import { i18n } from '../i18next';
interface CakeDayProps {
creator_name: string;
creator_published: string;
}
export class CakeDay extends Component<CakeDayProps, any> {
render() {
const { creator_name, creator_published } = this.props;
return (
this.isCakeDay(creator_published) && (
<div
className="mr-lg-2 d-inline-block unselectable pointer mx-2"
data-tippy-content={this.cakeDayTippy(creator_name)}
>
<svg class="icon icon-inline">
<use xlinkHref="#icon-cake"></use>
</svg>
</div>
)
);
}
isCakeDay(input: string): boolean {
const userCreationDate = moment.utc(input).local();
const currentDate = moment(new Date());
return (
userCreationDate.date() === currentDate.date() &&
userCreationDate.month() === currentDate.month()
);
}
cakeDayTippy(creator_name: string): string {
return i18n.t('cake_day_info', { creator_name });
}
}

View file

@ -33,6 +33,7 @@ import { CommentForm } from './comment-form';
import { CommentNodes } from './comment-nodes'; import { CommentNodes } from './comment-nodes';
import { UserListing } from './user-listing'; import { UserListing } from './user-listing';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { CakeDay } from './cake-day';
interface CommentNodeState { interface CommentNodeState {
showReply: boolean; showReply: boolean;
@ -124,6 +125,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
render() { render() {
let node = this.props.node; let node = this.props.node;
const { creator_name, creator_published } = node.comment;
return ( return (
<div <div
className={`comment ${ className={`comment ${
@ -160,6 +162,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
}} }}
/> />
</span> </span>
<CakeDay
creator_name={creator_name}
creator_published={creator_published}
/>
{this.isMod && ( {this.isMod && (
<div className="badge badge-light d-none d-sm-inline mr-2"> <div className="badge badge-light d-none d-sm-inline mr-2">
{i18n.t('mod')} {i18n.t('mod')}

View file

@ -35,6 +35,7 @@ import {
previewLines, previewLines,
} from '../utils'; } from '../utils';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import { CakeDay } from './cake-day';
interface PostListingState { interface PostListingState {
showEdit: boolean; showEdit: boolean;
@ -253,6 +254,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
listing() { listing() {
let post = this.props.post; let post = this.props.post;
const { creator_name, creator_published } = post;
return ( return (
<div class="row"> <div class="row">
<div className={`vote-bar col-1 pr-0 small text-center`}> <div className={`vote-bar col-1 pr-0 small text-center`}>
@ -432,6 +435,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
actor_id: post.creator_actor_id, actor_id: post.creator_actor_id,
}} }}
/> />
<CakeDay
creator_name={creator_name}
creator_published={creator_published}
/>
{this.isMod && ( {this.isMod && (
<span className="mx-1 badge badge-light"> <span className="mx-1 badge badge-light">
{i18n.t('mod')} {i18n.t('mod')}

File diff suppressed because one or more lines are too long

View file

@ -46,6 +46,7 @@ import { ListingTypeSelect } from './listing-type-select';
import { CommentNodes } from './comment-nodes'; import { CommentNodes } from './comment-nodes';
import { MomentTime } from './moment-time'; import { MomentTime } from './moment-time';
import { i18n } from '../i18next'; import { i18n } from '../i18next';
import moment from 'moment';
enum View { enum View {
Overview, Overview,
@ -412,6 +413,15 @@ export class User extends Component<any, UserState> {
)} )}
</ul> </ul>
</h5> </h5>
<div className="d-flex align-items-center mb-2">
<svg class="icon">
<use xlinkHref="#icon-cake"></use>
</svg>
<span className="ml-2">
{i18n.t('cake_day_title')}{' '}
{moment.utc(user.published).local().format('MMM DD, YYYY')}
</span>
</div>
<div> <div>
{i18n.t('joined')} <MomentTime data={user} showAgo /> {i18n.t('joined')} <MomentTime data={user} showAgo />
</div> </div>

View file

@ -183,6 +183,7 @@ export interface Post {
creator_actor_id: string; creator_actor_id: string;
creator_local: boolean; creator_local: boolean;
creator_name: string; creator_name: string;
creator_published: string;
creator_avatar?: string; creator_avatar?: string;
community_actor_id: string; community_actor_id: string;
community_local: boolean; community_local: boolean;
@ -227,6 +228,7 @@ export interface Comment {
creator_local: boolean; creator_local: boolean;
creator_name: string; creator_name: string;
creator_avatar?: string; creator_avatar?: string;
creator_published: string;
score: number; score: number;
upvotes: number; upvotes: number;
downvotes: number; downvotes: number;

View file

@ -265,5 +265,7 @@
"action": "Action", "action": "Action",
"emoji_picker": "Emoji Picker", "emoji_picker": "Emoji Picker",
"block_leaving": "Are you sure you want to leave?", "block_leaving": "Are you sure you want to leave?",
"what_is": "What is" "what_is": "What is",
"cake_day_title": "Cake day:",
"cake_day_info": "It's {{ creator_name }}'s cake day today!"
} }