Merge branch 'birthdays' into 'develop'
Birthdays See merge request pleroma/pleroma-fe!1432
This commit is contained in:
commit
22c3012e1c
|
@ -60,6 +60,8 @@ const getInstanceConfig = async ({ store }) => {
|
||||||
|
|
||||||
store.dispatch('setInstanceOption', { name: 'textlimit', value: textlimit })
|
store.dispatch('setInstanceOption', { name: 'textlimit', value: textlimit })
|
||||||
store.dispatch('setInstanceOption', { name: 'accountApprovalRequired', value: data.approval_required })
|
store.dispatch('setInstanceOption', { name: 'accountApprovalRequired', value: data.approval_required })
|
||||||
|
store.dispatch('setInstanceOption', { name: 'birthdayRequired', value: !!data.pleroma.metadata.birthday_required })
|
||||||
|
store.dispatch('setInstanceOption', { name: 'birthdayMinAge', value: data.pleroma.metadata.birthday_min_age || 0 })
|
||||||
|
|
||||||
if (vapidPublicKey) {
|
if (vapidPublicKey) {
|
||||||
store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
|
store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { required, requiredIf, sameAs } from '@vuelidate/validators'
|
||||||
import { mapActions, mapState } from 'vuex'
|
import { mapActions, mapState } from 'vuex'
|
||||||
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
|
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
|
||||||
import localeService from '../../services/locale/locale.service.js'
|
import localeService from '../../services/locale/locale.service.js'
|
||||||
|
import { DAY } from 'src/services/date_utils/date_utils.js'
|
||||||
|
|
||||||
const registration = {
|
const registration = {
|
||||||
setup () { return { v$: useVuelidate() } },
|
setup () { return { v$: useVuelidate() } },
|
||||||
|
@ -13,6 +14,7 @@ const registration = {
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
confirm: '',
|
confirm: '',
|
||||||
|
birthday: '',
|
||||||
reason: '',
|
reason: '',
|
||||||
language: ''
|
language: ''
|
||||||
},
|
},
|
||||||
|
@ -32,6 +34,12 @@ const registration = {
|
||||||
required,
|
required,
|
||||||
sameAs: sameAs(this.user.password)
|
sameAs: sameAs(this.user.password)
|
||||||
},
|
},
|
||||||
|
birthday: {
|
||||||
|
required: requiredIf(() => this.birthdayRequired),
|
||||||
|
maxValue: value => {
|
||||||
|
return !this.birthdayRequired || new Date(value).getTime() <= this.birthdayMin.getTime()
|
||||||
|
}
|
||||||
|
},
|
||||||
reason: { required: requiredIf(() => this.accountApprovalRequired) },
|
reason: { required: requiredIf(() => this.accountApprovalRequired) },
|
||||||
language: {}
|
language: {}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +60,24 @@ const registration = {
|
||||||
reasonPlaceholder () {
|
reasonPlaceholder () {
|
||||||
return this.replaceNewlines(this.$t('registration.reason_placeholder'))
|
return this.replaceNewlines(this.$t('registration.reason_placeholder'))
|
||||||
},
|
},
|
||||||
|
birthdayMin () {
|
||||||
|
const minAge = this.birthdayMinAge
|
||||||
|
const today = new Date()
|
||||||
|
today.setUTCMilliseconds(0)
|
||||||
|
today.setUTCSeconds(0)
|
||||||
|
today.setUTCMinutes(0)
|
||||||
|
today.setUTCHours(0)
|
||||||
|
const minDate = new Date()
|
||||||
|
minDate.setTime(today.getTime() - minAge * DAY)
|
||||||
|
return minDate
|
||||||
|
},
|
||||||
|
birthdayMinAttr () {
|
||||||
|
return this.birthdayMin.toJSON().replace(/T.+$/, '')
|
||||||
|
},
|
||||||
|
birthdayMinFormatted () {
|
||||||
|
const browserLocale = localeService.internalToBrowserLocale(this.$i18n.locale)
|
||||||
|
return this.user.birthday && new Date(Date.parse(this.birthdayMin)).toLocaleDateString(browserLocale, { timeZone: 'UTC', day: 'numeric', month: 'long', year: 'numeric' })
|
||||||
|
},
|
||||||
...mapState({
|
...mapState({
|
||||||
registrationOpen: (state) => state.instance.registrationOpen,
|
registrationOpen: (state) => state.instance.registrationOpen,
|
||||||
signedIn: (state) => !!state.users.currentUser,
|
signedIn: (state) => !!state.users.currentUser,
|
||||||
|
@ -59,7 +85,9 @@ const registration = {
|
||||||
serverValidationErrors: (state) => state.users.signUpErrors,
|
serverValidationErrors: (state) => state.users.signUpErrors,
|
||||||
termsOfService: (state) => state.instance.tos,
|
termsOfService: (state) => state.instance.tos,
|
||||||
accountActivationRequired: (state) => state.instance.accountActivationRequired,
|
accountActivationRequired: (state) => state.instance.accountActivationRequired,
|
||||||
accountApprovalRequired: (state) => state.instance.accountApprovalRequired
|
accountApprovalRequired: (state) => state.instance.accountApprovalRequired,
|
||||||
|
birthdayRequired: (state) => state.instance.birthdayRequired,
|
||||||
|
birthdayMinAge: (state) => state.instance.birthdayMinAge
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -167,6 +167,40 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="form-group"
|
||||||
|
:class="{ 'form-group--error': v$.user.birthday.$error }"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="form--label"
|
||||||
|
for="sign-up-birthday"
|
||||||
|
>
|
||||||
|
{{ birthdayRequired ? $t('registration.birthday') : $t('registration.birthday_optional') }}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="sign-up-birthday"
|
||||||
|
v-model="user.birthday"
|
||||||
|
:disabled="isPending"
|
||||||
|
class="form-control"
|
||||||
|
type="date"
|
||||||
|
:max="birthdayRequired ? birthdayMinAttr : undefined"
|
||||||
|
:aria-required="birthdayRequired"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="v$.user.birthday.$dirty"
|
||||||
|
class="form-error"
|
||||||
|
>
|
||||||
|
<ul>
|
||||||
|
<li v-if="v$.user.birthday.required.$invalid">
|
||||||
|
<span>{{ $t('registration.validations.birthday_required') }}</span>
|
||||||
|
</li>
|
||||||
|
<li v-if="v$.user.birthday.maxValue.$invalid">
|
||||||
|
<span>{{ $tc('registration.validations.birthday_min_age', { date: birthdayMinFormatted }) }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="form-group"
|
class="form-group"
|
||||||
:class="{ 'form-group--error': v$.user.language.$error }"
|
:class="{ 'form-group--error': v$.user.language.$error }"
|
||||||
|
|
|
@ -32,6 +32,8 @@ const ProfileTab = {
|
||||||
newName: this.$store.state.users.currentUser.name_unescaped,
|
newName: this.$store.state.users.currentUser.name_unescaped,
|
||||||
newBio: unescape(this.$store.state.users.currentUser.description),
|
newBio: unescape(this.$store.state.users.currentUser.description),
|
||||||
newLocked: this.$store.state.users.currentUser.locked,
|
newLocked: this.$store.state.users.currentUser.locked,
|
||||||
|
newBirthday: this.$store.state.users.currentUser.birthday,
|
||||||
|
showBirthday: this.$store.state.users.currentUser.show_birthday,
|
||||||
newFields: this.$store.state.users.currentUser.fields.map(field => ({ name: field.name, value: field.value })),
|
newFields: this.$store.state.users.currentUser.fields.map(field => ({ name: field.name, value: field.value })),
|
||||||
showRole: this.$store.state.users.currentUser.show_role,
|
showRole: this.$store.state.users.currentUser.show_role,
|
||||||
role: this.$store.state.users.currentUser.role,
|
role: this.$store.state.users.currentUser.role,
|
||||||
|
@ -125,7 +127,9 @@ const ProfileTab = {
|
||||||
display_name: this.newName,
|
display_name: this.newName,
|
||||||
fields_attributes: this.newFields.filter(el => el != null),
|
fields_attributes: this.newFields.filter(el => el != null),
|
||||||
bot: this.bot,
|
bot: this.bot,
|
||||||
show_role: this.showRole
|
show_role: this.showRole,
|
||||||
|
birthday: this.newBirthday || '',
|
||||||
|
show_birthday: this.showBirthday
|
||||||
/* eslint-enable camelcase */
|
/* eslint-enable camelcase */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,4 +129,9 @@
|
||||||
padding: 0 0.5em;
|
padding: 0 0.5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.birthday-input {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,18 @@
|
||||||
</template>
|
</template>
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
</p>
|
</p>
|
||||||
|
<div>
|
||||||
|
<p>{{ $t('settings.birthday.label') }}</p>
|
||||||
|
<input
|
||||||
|
id="birthday"
|
||||||
|
v-model="newBirthday"
|
||||||
|
type="date"
|
||||||
|
class="birthday-input"
|
||||||
|
>
|
||||||
|
<Checkbox v-model="showBirthday">
|
||||||
|
{{ $t('settings.birthday.show_birthday') }}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
<div v-if="maxFields > 0">
|
<div v-if="maxFields > 0">
|
||||||
<p>{{ $t('settings.profile_fields.label') }}</p>
|
<p>{{ $t('settings.profile_fields.label') }}</p>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -7,13 +7,16 @@ import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
|
||||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
import List from '../list/list.vue'
|
import List from '../list/list.vue'
|
||||||
import withLoadMore from '../../hocs/with_load_more/with_load_more'
|
import withLoadMore from '../../hocs/with_load_more/with_load_more'
|
||||||
|
import localeService from 'src/services/locale/locale.service.js'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faCircleNotch
|
faCircleNotch,
|
||||||
|
faBirthdayCake
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faCircleNotch
|
faCircleNotch,
|
||||||
|
faBirthdayCake
|
||||||
)
|
)
|
||||||
|
|
||||||
const FollowerList = withLoadMore({
|
const FollowerList = withLoadMore({
|
||||||
|
@ -76,6 +79,10 @@ const UserProfile = {
|
||||||
},
|
},
|
||||||
followersTabVisible () {
|
followersTabVisible () {
|
||||||
return this.isUs || !this.user.hide_followers
|
return this.isUs || !this.user.hide_followers
|
||||||
|
},
|
||||||
|
formattedBirthday () {
|
||||||
|
const browserLocale = localeService.internalToBrowserLocale(this.$i18n.locale)
|
||||||
|
return this.user.birthday && new Date(Date.parse(this.user.birthday)).toLocaleDateString(browserLocale, { timeZone: 'UTC', day: 'numeric', month: 'long', year: 'numeric' })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -12,6 +12,16 @@
|
||||||
rounded="top"
|
rounded="top"
|
||||||
:has-note-editor="true"
|
:has-note-editor="true"
|
||||||
/>
|
/>
|
||||||
|
<span
|
||||||
|
v-if="!!user.birthday"
|
||||||
|
class="user-birthday"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
class="fa-old-padding"
|
||||||
|
icon="birthday-cake"
|
||||||
|
/>
|
||||||
|
{{ $t('user_card.birthday', { birthday: formattedBirthday }) }}
|
||||||
|
</span>
|
||||||
<div
|
<div
|
||||||
v-if="user.fields_html && user.fields_html.length > 0"
|
v-if="user.fields_html && user.fields_html.length > 0"
|
||||||
class="user-profile-fields"
|
class="user-profile-fields"
|
||||||
|
@ -149,6 +159,10 @@
|
||||||
// No sticky header on user profile
|
// No sticky header on user profile
|
||||||
--currentPanelStack: 1;
|
--currentPanelStack: 1;
|
||||||
|
|
||||||
|
.user-birthday {
|
||||||
|
margin: 0 0.75em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.user-profile-fields {
|
.user-profile-fields {
|
||||||
margin: 0 0.5em;
|
margin: 0 0.5em;
|
||||||
|
|
||||||
|
|
|
@ -316,9 +316,13 @@
|
||||||
"email_required": "cannot be left blank",
|
"email_required": "cannot be left blank",
|
||||||
"password_required": "cannot be left blank",
|
"password_required": "cannot be left blank",
|
||||||
"password_confirmation_required": "cannot be left blank",
|
"password_confirmation_required": "cannot be left blank",
|
||||||
"password_confirmation_match": "should be the same as password"
|
"password_confirmation_match": "should be the same as password",
|
||||||
|
"birthday_required": "cannot be left blank",
|
||||||
|
"birthday_min_age": "must be on or before {date}"
|
||||||
},
|
},
|
||||||
"email_language": "In which language do you want to receive emails from the server?"
|
"email_language": "In which language do you want to receive emails from the server?",
|
||||||
|
"birthday": "Birthday:",
|
||||||
|
"birthday_optional": "Birthday (optional):"
|
||||||
},
|
},
|
||||||
"remote_user_resolver": {
|
"remote_user_resolver": {
|
||||||
"remote_user_resolver": "Remote user resolver",
|
"remote_user_resolver": "Remote user resolver",
|
||||||
|
@ -528,6 +532,10 @@
|
||||||
"name": "Label",
|
"name": "Label",
|
||||||
"value": "Content"
|
"value": "Content"
|
||||||
},
|
},
|
||||||
|
"birthday": {
|
||||||
|
"label": "Birthday",
|
||||||
|
"show_birthday": "Show my birthday"
|
||||||
|
},
|
||||||
"account_privacy": "Privacy",
|
"account_privacy": "Privacy",
|
||||||
"use_contain_fit": "Don't crop the attachment in thumbnails",
|
"use_contain_fit": "Don't crop the attachment in thumbnails",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
|
@ -986,6 +994,7 @@
|
||||||
"hide_repeats": "Hide repeats",
|
"hide_repeats": "Hide repeats",
|
||||||
"show_repeats": "Show repeats",
|
"show_repeats": "Show repeats",
|
||||||
"bot": "Bot",
|
"bot": "Bot",
|
||||||
|
"birthday": "Born {birthday}",
|
||||||
"admin_menu": {
|
"admin_menu": {
|
||||||
"moderation": "Moderation",
|
"moderation": "Moderation",
|
||||||
"grant_admin": "Grant Admin",
|
"grant_admin": "Grant Admin",
|
||||||
|
|
|
@ -116,6 +116,8 @@ const defaultState = {
|
||||||
restrictedNicknames: [],
|
restrictedNicknames: [],
|
||||||
safeDM: true,
|
safeDM: true,
|
||||||
knownDomains: [],
|
knownDomains: [],
|
||||||
|
birthdayRequired: false,
|
||||||
|
birthdayMinAge: 0,
|
||||||
|
|
||||||
// Feature-set, apparently, not everything here is reported...
|
// Feature-set, apparently, not everything here is reported...
|
||||||
shoutAvailable: false,
|
shoutAvailable: false,
|
||||||
|
|
|
@ -125,6 +125,8 @@ export const parseUser = (data) => {
|
||||||
output.role = 'member'
|
output.role = 'member'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output.birthday = data.pleroma.birthday
|
||||||
|
|
||||||
if (data.pleroma.privileges) {
|
if (data.pleroma.privileges) {
|
||||||
output.privileges = data.pleroma.privileges
|
output.privileges = data.pleroma.privileges
|
||||||
} else if (data.pleroma.is_admin) {
|
} else if (data.pleroma.is_admin) {
|
||||||
|
@ -162,6 +164,7 @@ export const parseUser = (data) => {
|
||||||
output.no_rich_text = data.source.pleroma.no_rich_text
|
output.no_rich_text = data.source.pleroma.no_rich_text
|
||||||
output.show_role = data.source.pleroma.show_role
|
output.show_role = data.source.pleroma.show_role
|
||||||
output.discoverable = data.source.pleroma.discoverable
|
output.discoverable = data.source.pleroma.discoverable
|
||||||
|
output.show_birthday = data.pleroma.show_birthday
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue