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 12, 2022
1 parent 96f6553 commit 10a29fe
Show file tree
Hide file tree
Showing 15 changed files with 163 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
cakedayBirthday,
cakedayBirthdayTitle,
cakedayTitle,
userAgeTitle,
} from "discourse/plugins/discourse-cakeday/discourse/lib/cakeday";

export default {
Expand All @@ -17,5 +18,10 @@ 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, this.currentUser));
}
},
};
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
9 changes: 9 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,14 @@ 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) ? I18n.t("cakeday.age", {age: userAge(user.date_of_birth)}) : 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
Expand Up @@ -9,3 +9,4 @@
{{emoji-images list=siteSettings.cakeday_emoji title=cakedayTitle}}
{{/if}}
{{/if}}
{{userAgeTitle}}
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 "user.date_of_birth.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
5 changes: 5 additions & 0 deletions assets/stylesheets/user-date-of-birth-input.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.user-custom-preferences-outlet.user-date-of-birth-input {
input.year {
width: 80px;
}
}
3 changes: 3 additions & 0 deletions config/locales/client.da.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ da:
user_title: "I dag er det din fødselsdag!"
title: "I dag er det min fødselsdag!"
label: "Fødselsdato"
yyyy: "ÅÅÅÅ"
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!"
Expand All @@ -20,6 +22,7 @@ da:
tomorrow: "I morgen"
upcoming: "Kommende"
all: "Alle"
age: "%{age} år"
birthdays:
title: "Fødselsdage"
month:
Expand Down
4 changes: 4 additions & 0 deletions config/locales/client.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ en:
user_title: "Today is your birthday!"
title: "Today is my birthday!"
label: "Date of Birth"
yyyy: "YYYY"
anniversary:
user_title: "Today is the anniversary of the day you joined our community!"
title: "Today is the anniversary of the day I joined this community!"
cakeday:
none: " "
dd: "DD"
mm: "MM"
title: Cakeday
today: "Today"
tomorrow: "Tomorrow"
upcoming: "Upcoming"
all: "All"
age: "%{age} years"
birthdays:
title: "Birthdays"
month:
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 10a29fe

Please sign in to comment.