Skip to content

Commit

Permalink
DEV: Adds age support to discourse-cakeday plugin
Browse files Browse the repository at this point in the history
Enables staff/admins to see the age of a given user, directly from the user card. Hides the year in json files for non staff/admin users Added an input element to user preferences, for year input. Added sitesettings to enable new feature, and select order of input fields MM-DD-YYYY vs. DD-MM-YYYY

TODO: Enable user to choose age visibility for non staff/admins
  • Loading branch information
DaVania committed Apr 15, 2022
1 parent 96f6553 commit 1539776
Show file tree
Hide file tree
Showing 17 changed files with 186 additions and 29 deletions.
12 changes: 12 additions & 0 deletions assets/javascripts/discourse/components/user-age-title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Component from "@ember/component";
import computed from "discourse-common/utils/decorators";
import I18n from "I18n";

export default Component.extend({
classNames: ["user-age-title"],

@computed("title")
titleText(title) {
return I18n.t('js.user.date_of_birth.label') + ': ' + title;
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
cakedayBirthday,
cakedayBirthdayTitle,
cakedayTitle,
userAgeTitle,
userBirthdateTitle,
} from "discourse/plugins/discourse-cakeday/discourse/lib/cakeday";

export default {
Expand All @@ -17,5 +19,11 @@ export default {
"cakedayBirthdayTitle",
cakedayBirthdayTitle(args.user, this.currentUser)
);
const isStaff = this.currentUser && this.currentUser.staff;
const isAdmin = this.currentUser && this.currentUser.admin;
if (isAdmin || isStaff) {
component.set("userAgeTitle", userAgeTitle(args.user));
component.set("userBirthdateTitle", userBirthdateTitle(args.user));
}
},
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
export default {
setupComponent(args, component) {
const year = 1904;
const months = moment.months().map((month, index) => {
return { name: month, value: index + 1 };
});

const days = Array.from(Array(31).keys()).map((x) => (x + 1).toString());

const dateOfBirth = args.model.get("date_of_birth");
const userBirthdayYear = dateOfBirth
? (moment(dateOfBirth, "YYYY-MM-DD").year() !== year ? moment(dateOfBirth, "YYYY-MM-DD").year() : null)
: null;
const userBirthdayMonth = dateOfBirth
? moment(dateOfBirth, "YYYY-MM-DD").month() + 1
: null;
Expand All @@ -15,22 +19,28 @@ export default {
: null;

component.setProperties({
year,
months,
days,
userBirthdayYear,
userBirthdayMonth,
userBirthdayDay,
});

const updateBirthday = function () {
let date = "";

if (component.userBirthdayMonth && component.userBirthdayDay) {
if (component.userBirthdayYear && component.userBirthdayMonth && component.userBirthdayDay) {
date = `${component.userBirthdayYear}-${component.userBirthdayMonth}-${component.userBirthdayDay}`;
}
else if (component.userBirthdayMonth && component.userBirthdayDay) {
date = `1904-${component.userBirthdayMonth}-${component.userBirthdayDay}`;
}

args.model.set("date_of_birth", date);
};

component.addObserver("userBirthdayYear", updateBirthday);
component.addObserver("userBirthdayMonth", updateBirthday);
component.addObserver("userBirthdayDay", updateBirthday);
},
Expand Down
15 changes: 13 additions & 2 deletions assets/javascripts/discourse/initializers/cakeday.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,20 @@ function initializeCakeday(api) {
});
},

@observes("userBirthdayMonth", "userBirthdayDay")
@observes("userBirthdayYear", "userBirthdayMonth", "userBirthdayDay")
_setUserDateOfBirth() {
const userBirthdayYear = this.get("userBirthdayYear");
const userBirthdayMonth = this.get("userBirthdayMonth");
const userBirthdayDay = this.get("userBirthdayDay");
const user = this.get("model");
let date = "";

if (userBirthdayMonth !== "" && userBirthdayDay !== "") {
if (userBirthdayYear !== "" && userBirthdayMonth !== "" && userBirthdayDay !== "") {
date = `${this.get("userBirthdayYear")}-${this.get("userBirthdayMonth")}-${this.get(
"userBirthdayDay"
)}`;
}
else if (userBirthdayMonth !== "" && userBirthdayDay !== "") {
date = `1904-${this.get("userBirthdayMonth")}-${this.get(
"userBirthdayDay"
)}`;
Expand All @@ -46,6 +52,11 @@ function initializeCakeday(api) {
user.set("date_of_birth", date);
},

@discourseComputed("model.date_of_birth")
userBirthdayYear(dateOfBirth) {
return moment(dateOfBirth, "YYYY-MM-DD").year() + 1;
},

@discourseComputed("model.date_of_birth")
userBirthdayMonth(dateOfBirth) {
return moment(dateOfBirth, "YYYY-MM-DD").month() + 1;
Expand Down
13 changes: 13 additions & 0 deletions assets/javascripts/discourse/lib/cakeday.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { isEmpty } from "@ember/utils";
import I18n from "I18n";

export function isSameDay(date, opts) {
let formatString = "YYYY";
Expand Down Expand Up @@ -30,6 +31,18 @@ export function cakedayBirthday(dateOfBirth) {
return isSameDay(dateOfBirth);
}

export function userAge(dateOfBirth) {
return dateOfBirth ? (moment(dateOfBirth, "YYYY-MM-DD").year() !== 1904 ? moment().diff(dateOfBirth, 'years') : null) : null;
}

export function userAgeTitle(user) {
return (user.date_of_birth && moment(user.date_of_birth, "YYYY-MM-DD").year() !== 1904) ? userAge(user.date_of_birth) + ' ' + I18n.default.t("relative_time_picker.years", {count: userAge(user.date_of_birth)}) : null;
}

export function userBirthdateTitle(user) {
return (user.date_of_birth && moment(user.date_of_birth, "YYYY-MM-DD").year() !== 1904) ? moment(user.date_of_birth).format(I18n.t("dates.long_with_year_no_time")) : null;
}

export function cakedayTitle(user, currentUser) {
if (isSameUser(user, currentUser)) {
return "user.anniversary.user_title";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div title={{titleText}}>
{{userage}}
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
{{emoji-images list=siteSettings.cakeday_emoji title=cakedayTitle}}
{{/if}}
{{/if}}
{{user-age-title userage=userAgeTitle title=userBirthdateTitle}}
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,76 @@
<div class="control-group">
<label class="control-label">{{i18n "user.date_of_birth.label"}}</label>
<div class="controls">
{{combo-box
content=months
value=userBirthdayMonth
valueAttribute="value"
valueProperty="value"
none="cakeday.none"
options=(hash
clearable=true
autoInsertNoneItem=false
)
onChange=(action (mut userBirthdayMonth))
}}

{{combo-box
content=days
value=userBirthdayDay
valueProperty=null
nameProperty=null
none="cakeday.none"
options=(hash
clearable=true
autoInsertNoneItem=false
)
onChange=(action (mut userBirthdayDay))
}}
{{#if siteSettings.cakeday_birthday_formatdmy}}
{{combo-box
content=days
value=userBirthdayDay
valueProperty=null
nameProperty=null
none="cakeday.dd"
options=(hash
clearable=true
autoInsertNoneItem=false
)
onChange=(action (mut userBirthdayDay))
}}
{{#if siteSettings.cakeday_birthday_show_year}}
-
{{/if}}
{{combo-box
content=months
value=userBirthdayMonth
valueAttribute="value"
valueProperty="value"
none="cakeday.mm"
options=(hash
clearable=true
autoInsertNoneItem=false
)
onChange=(action (mut userBirthdayMonth))
}}
{{else}}
{{combo-box
content=months
value=userBirthdayMonth
valueAttribute="value"
valueProperty="value"
none="cakeday.mm"
options=(hash
clearable=true
autoInsertNoneItem=false
)
onChange=(action (mut userBirthdayMonth))
}}
{{#if siteSettings.cakeday_birthday_show_year}}
-
{{/if}}
{{combo-box
content=days
value=userBirthdayDay
valueProperty=null
nameProperty=null
none="cakeday.dd"
options=(hash
clearable=true
autoInsertNoneItem=false
)
onChange=(action (mut userBirthdayDay))
}}
{{/if}}
{{#if siteSettings.cakeday_birthday_show_year}}
-
{{input
type="number"
class="year"
content=year
value=userBirthdayYear
min=1905
max=2904
placeholder=(i18n "cakeday.yyyy")
onChange=(action (mut userBirthdayYear))
}}
{{/if}}
</div>
</div>
{{/if}}
5 changes: 5 additions & 0 deletions assets/stylesheets/mobile/user-date-of-birth-input.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.mobile-view .user-custom-preferences-outlet.user-date-of-birth-input {
input.year {
width: 62px;
}
}
.user-custom-preferences-outlet.user-date-of-birth-input {
select {
width: 49%;
Expand Down
7 changes: 7 additions & 0 deletions assets/stylesheets/user-date-of-birth-input.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.user-custom-preferences-outlet.user-date-of-birth-input {
input.year {
width: 80px;
vertical-align: middle;
height: 41.5px;
}
}
4 changes: 4 additions & 0 deletions config/locales/client.da.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ da:
user_title: "I dag er det din fødselsdag!"
title: "I dag er det min fødselsdag!"
label: "Fødselsdato"
show_age: "Vis alder til brugere"
anniversary:
user_title: "I dag er årsdagen hvor du blev en del af vores fælleskab!"
title: "I dag er årsdagen for at jeg blev en del af dette fælleskab!"
cakeday:
dd: "DD"
mm: "MM"
yyyy: "ÅÅÅÅ"
title: Kagedag
today: "I dag"
tomorrow: "I morgen"
Expand Down
3 changes: 3 additions & 0 deletions config/locales/client.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ en:
title: "Today is the anniversary of the day I joined this community!"
cakeday:
none: " "
dd: "DD"
mm: "MM"
yyyy: "YYYY"
title: Cakeday
today: "Today"
tomorrow: "Tomorrow"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/server.da.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
da:
site_settings:
cakeday_enabled: "Vis cakeday humørikon[er] ved siden af navnet på brugeren, på den dato, hvor de blev medlem af Discourse."
cakeday_birthday_show_year: "Vis Kagedag års vælger, for at tillade brugere at indtaste deres alder."
cakeday_birthday_formatdmy: "Vis Kagedag vælgere som DD-MM-ÅÅÅÅ, i stedet for MM-DD-ÅÅÅÅ"
cakeday_emoji: "De humørikon[er], der vises ved siden af navnet på brugeren, på den dato, hvor de blev medlem af Discourse. Flere humørikoner kan specificeres ved: smile|cake|smile"
cakeday_birthday_enabled: "Vis fødselsdags humørikon[er] ved siden af navnet på brugeren, på deres fødselsdag."
cakeday_birthday_emoji: "De humørikon[er], der vises ved siden af navnet på brugeren, på deres fødselsdag. Flere humørikoner kan specificeres ved: smile|cake|smile"
2 changes: 2 additions & 0 deletions config/locales/server.en.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
en:
site_settings:
cakeday_enabled: "Show cakeday emoji[s] beside the user's name on the date they joined Discourse."
cakeday_birthday_show_year: "Show cakeday year selector, to allow users to input their age."
cakeday_birthday_formatdmy: "Show cakeday selectors as DD-MM-YYYY, instead of MM-DD-YYYY"
cakeday_emoji: "The emoji[s] that will be shown beside the user's name on the date that they joined Discourse. Multiple emojis can be specified by: smile|cake|smile"
cakeday_birthday_enabled: "Show birthday emoji[s] beside the user's name on their birthday."
cakeday_birthday_emoji: "The emoji[s] that will be shown beside the user's name on their birthday. Multiple emojis can be specified by: smile|cake|smile"
6 changes: 6 additions & 0 deletions config/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@ plugins:
cakeday_birthday_emoji:
default: 'birthday'
client: true
cakeday_birthday_show_year:
default: false
client: true
cakeday_birthday_formatdmy:
default: false
client: true
11 changes: 10 additions & 1 deletion plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

register_asset 'stylesheets/cakeday.scss'
register_asset 'stylesheets/emoji-images.scss'
register_asset 'stylesheets/user-date-of-birth-input.scss'
register_asset 'stylesheets/mobile/user-date-of-birth-input.scss'

register_svg_icon "birthday-cake" if respond_to?(:register_svg_icon)
Expand Down Expand Up @@ -60,7 +61,15 @@ class ::User
end

add_to_serializer(:user_card, :date_of_birth, false) do
object.date_of_birth
if object.date_of_birth != nil
if (scope.is_staff? || scope.is_admin?)
object.date_of_birth
else
Date.new(1904, object.date_of_birth.month, object.date_of_birth.day)
end
else
nil
end
end

add_to_serializer(:user_card, :include_date_of_birth?) do
Expand Down
16 changes: 16 additions & 0 deletions spec/serializers/user_serializer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,26 @@

RSpec.describe UserSerializer do
let(:user) { Fabricate(:user, date_of_birth: '2017-04-05') }
let!(:admin) { Fabricate(:admin) }
let(:agesafe_date_of_birth) { '1904-04-05' }

context 'when user is logged in' do
let(:serializer) { described_class.new(user, scope: Guardian.new(user), root: false) }

it "should include the user's date of birth" do
expect(serializer.as_json[:date_of_birth]).to eq(agesafe_date_of_birth)
end

it "should not include the user's date of birth when cakeday_birthday_enabled is false" do
SiteSetting.cakeday_birthday_enabled = false

expect(serializer.as_json[:date_of_birth]).to eq(nil)
end
end

context 'when admin is logged in' do
let(:serializer) { described_class.new(user, scope: Guardian.new(admin), root: false) }

it "should include the user's date of birth" do
expect(serializer.as_json[:date_of_birth]).to eq(user.date_of_birth)
end
Expand Down

0 comments on commit 1539776

Please sign in to comment.