mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
feat(usernames): invite by username
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal-dialog {
|
.modal-dialog {
|
||||||
|
margin: 5.5rem auto 3rem;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
|||||||
@@ -1,152 +1,178 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
b-modal#invite-modal(:title="$t('inviteFriends')", size='lg')
|
b-modal#invite-modal(:title='$t(`inviteTo${groupType}`)', :hide-footer='true')
|
||||||
.modal-body
|
div
|
||||||
p.alert.alert-info(v-html="$t('inviteAlertInfo')")
|
strong {{ $t('inviteEmailUsername') }}
|
||||||
.form-horizontal
|
.small {{ $t('inviteEmailUsernameInfo') }}
|
||||||
table.table.table-striped
|
.input-group(v-for='(invite, index) in invites')
|
||||||
thead
|
.d-flex.align-items-center.justify-content-center(v-if='index === invites.length - 1 && invite.text.length === 0')
|
||||||
tr
|
.svg-icon.positive-icon(v-html='icons.positiveIcon')
|
||||||
th {{ $t('userId') }}
|
input.form-control(
|
||||||
tbody
|
type='text',
|
||||||
tr(v-for='user in invitees')
|
:placeholder='$t("emailOrUsernameInvite")',
|
||||||
td
|
v-model='invite.text',
|
||||||
input.form-control(type='text', v-model='user.uuid')
|
v-on:change='checkInviteList',
|
||||||
tr
|
:class='{"input-valid": invite.valid, "is-invalid input-invalid": invite.valid === false}',
|
||||||
td
|
)
|
||||||
button.btn.btn-primary.pull-right(@click='addUuid()')
|
.modal-footer.d-flex.justify-content-center
|
||||||
i.glyphicon.glyphicon-plus
|
a.mr-3(@click='close()') {{ $t('cancel') }}
|
||||||
| +
|
button.btn.btn-primary(@click='sendInvites()', :class='{disabled: cannotSubmit}', :disabled='cannotSubmit') {{ $t('sendInvitations') }}
|
||||||
tr
|
|
||||||
td
|
|
||||||
.col-6.col-offset-6
|
|
||||||
button.btn.btn-primary.btn-block(@click='inviteNewUsers("uuid")') {{sendInviteText}}
|
|
||||||
hr
|
|
||||||
p.alert.alert-info {{ $t('inviteByEmail') }}
|
|
||||||
.form-horizontal
|
|
||||||
table.table.table-striped
|
|
||||||
thead
|
|
||||||
tr
|
|
||||||
th {{ $t('name') }}
|
|
||||||
th {{ $t('email') }}
|
|
||||||
tbody
|
|
||||||
tr(v-for='email in emails')
|
|
||||||
td
|
|
||||||
input.form-control(type='text', v-model='email.name')
|
|
||||||
td
|
|
||||||
input.form-control(type='email', v-model='email.email')
|
|
||||||
tr
|
|
||||||
td(colspan=2)
|
|
||||||
button.btn.btn-primary.pull-right(@click='addEmail()')
|
|
||||||
i.glyphicon.glyphicon-plus
|
|
||||||
| +
|
|
||||||
tr
|
|
||||||
td.form-group(colspan=2)
|
|
||||||
label.col-sm-1.control-label {{ $t('byColon') }}
|
|
||||||
.col-sm-5
|
|
||||||
input.form-control(type='text', v-model='inviter')
|
|
||||||
.col-sm-6
|
|
||||||
button.btn.btn-primary.btn-block(@click='inviteNewUsers("email")') {{sendInviteText}}
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
#invite-modal___BV_modal_outer_ {
|
||||||
|
.modal-content {
|
||||||
|
padding: 0rem 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#invite-modal___BV_modal_header_.modal-header {
|
||||||
|
border-bottom: 0px;
|
||||||
|
}
|
||||||
|
#invite-modal___BV_modal_header_ {
|
||||||
|
.modal-title {
|
||||||
|
color: #4F2A93;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '~client/assets/scss/colors.scss';
|
||||||
|
|
||||||
|
a:not([href]) {
|
||||||
|
color: $blue-10;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
border: 0px;
|
||||||
|
color: $gray-50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
border-radius: 2px;
|
||||||
|
border: solid 1px $gray-400;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
::placeholder {
|
||||||
|
color: $gray-200;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group:focus-within {
|
||||||
|
border-color: $purple-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-footer {
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.positive-icon {
|
||||||
|
color: $green-10;
|
||||||
|
width: 10px;
|
||||||
|
margin: auto 0rem auto 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small {
|
||||||
|
color: $gray-200;
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 0.5rem 0rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'client/libs/store';
|
import { mapState } from 'client/libs/store';
|
||||||
|
import clone from 'lodash/clone';
|
||||||
|
import debounce from 'lodash/debounce';
|
||||||
|
import filter from 'lodash/filter';
|
||||||
|
import forEach from 'lodash/forEach';
|
||||||
|
import isEmail from 'validator/lib/isEmail';
|
||||||
|
import isUUID from 'validator/lib/isUUID';
|
||||||
|
import notifications from 'client/mixins/notifications';
|
||||||
|
import positiveIcon from 'assets/svg/positive.svg';
|
||||||
|
|
||||||
import filter from 'lodash/filter';
|
const INVITE_DEFAULTS = {text: '', valid: null};
|
||||||
import map from 'lodash/map';
|
|
||||||
import notifications from 'client/mixins/notifications';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [notifications],
|
computed: {
|
||||||
props: ['group'],
|
...mapState({user: 'user.data'}),
|
||||||
data () {
|
cannotSubmit () {
|
||||||
return {
|
const filteredInvites = filter(this.invites, (invite) => {
|
||||||
invitees: [],
|
return invite.text.length > 0 && !invite.valid;
|
||||||
emails: [],
|
});
|
||||||
};
|
if (filteredInvites.length > 0) return true;
|
||||||
},
|
},
|
||||||
computed: {
|
inviter () {
|
||||||
...mapState({user: 'user.data'}),
|
return this.user.profile.name;
|
||||||
inviter () {
|
},
|
||||||
return this.user.profile.name;
|
|
||||||
},
|
},
|
||||||
sendInviteText () {
|
data () {
|
||||||
return 'Send Invites';
|
return {
|
||||||
// if (!this.group) return 'Send Invites';
|
invites: [clone(INVITE_DEFAULTS), clone(INVITE_DEFAULTS)],
|
||||||
// return this.group.sendInviteText;
|
icons: Object.freeze({
|
||||||
|
positiveIcon,
|
||||||
|
}),
|
||||||
|
};
|
||||||
},
|
},
|
||||||
},
|
methods: {
|
||||||
methods: {
|
checkInviteList: debounce(function checkList () {
|
||||||
addUuid () {
|
this.invites = filter(this.invites, (invite) => {
|
||||||
this.invitees.push({uuid: ''});
|
return invite.text.length > 0;
|
||||||
|
});
|
||||||
|
if (this.invites[this.invites.length - 1].text.length > 0) this.invites.push(clone(INVITE_DEFAULTS));
|
||||||
|
forEach(this.invites, (value, index) => {
|
||||||
|
if (value.text.length < 1) return this.invites[index].valid = null;
|
||||||
|
if (isEmail(value.text)) return this.invites[index].valid = true;
|
||||||
|
if (isUUID(value.text)) {
|
||||||
|
this.$store.dispatch('user:userLookup', {uuid: value.text})
|
||||||
|
.then(res => {
|
||||||
|
if (res.status === 200) return this.invites[index].valid = true;
|
||||||
|
return this.invites[index].valid = false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.$store.dispatch('user:userLookup', {username: value.text})
|
||||||
|
.then(res => {
|
||||||
|
if (res.status === 200) return this.invites[index].valid = true;
|
||||||
|
return this.invites[index].valid = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 500),
|
||||||
|
close () {
|
||||||
|
this.invites = [clone(INVITE_DEFAULTS), clone(INVITE_DEFAULTS)];
|
||||||
|
this.$root.$emit('bv::hide::modal', 'invite-modal');
|
||||||
|
},
|
||||||
|
async sendInvites () {
|
||||||
|
let invitationDetails = {
|
||||||
|
inviter: this.inviter,
|
||||||
|
emails: [],
|
||||||
|
uuids: [],
|
||||||
|
usernames: [],
|
||||||
|
};
|
||||||
|
forEach(this.invites, (invite) => {
|
||||||
|
if (invite.text.length < 1) return;
|
||||||
|
if (isEmail(invite.text)) {
|
||||||
|
invitationDetails.emails.push({email: invite.text});
|
||||||
|
} else if (isUUID(invite.text)) {
|
||||||
|
invitationDetails.uuids.push(invite.text);
|
||||||
|
} else {
|
||||||
|
invitationDetails.usernames.push(invite.text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await this.$store.dispatch('guilds:invite', {
|
||||||
|
invitationDetails,
|
||||||
|
groupId: this.group._id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const invitesSent = invitationDetails.emails.length + invitationDetails.uuids.length + invitationDetails.usernames.length;
|
||||||
|
let invitationString = invitesSent > 1 ? 'invitationsSent' : 'invitationSent';
|
||||||
|
|
||||||
|
this.text(this.$t(invitationString));
|
||||||
|
this.close();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
addEmail () {
|
mixins: [notifications],
|
||||||
this.emails.push({name: '', email: ''});
|
props: ['group', 'groupType'],
|
||||||
},
|
};
|
||||||
inviteNewUsers (inviteMethod) {
|
|
||||||
if (!this.group._id) {
|
|
||||||
if (!this.group.name) this.group.name = this.$t('possessiveParty', {name: this.user.profile.name});
|
|
||||||
|
|
||||||
// @TODO: Add dispatch
|
|
||||||
// return Groups.Group.create(this.group)
|
|
||||||
// .then(function(response) {
|
|
||||||
// this.group = response.data.data;
|
|
||||||
// _inviteByMethod(inviteMethod);
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
this.inviteByMethod(inviteMethod);
|
|
||||||
},
|
|
||||||
async inviteByMethod (inviteMethod) {
|
|
||||||
let invitationDetails;
|
|
||||||
|
|
||||||
if (inviteMethod === 'email') {
|
|
||||||
let emails = this.getEmails();
|
|
||||||
invitationDetails = { inviter: this.inviter, emails };
|
|
||||||
} else if (inviteMethod === 'uuid') {
|
|
||||||
let uuids = this.getOnlyUuids();
|
|
||||||
invitationDetails = { uuids };
|
|
||||||
} else {
|
|
||||||
return alert('Invalid invite method.');
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.$store.dispatch('guilds:invite', {
|
|
||||||
invitationDetails,
|
|
||||||
groupId: this.group._id,
|
|
||||||
});
|
|
||||||
|
|
||||||
let invitesSent = invitationDetails.emails || invitationDetails.uuids;
|
|
||||||
let invitationString = invitesSent.length > 1 ? 'invitationsSent' : 'invitationSent';
|
|
||||||
|
|
||||||
this.text(this.$t(invitationString));
|
|
||||||
|
|
||||||
this.invitees = [];
|
|
||||||
this.emails = [];
|
|
||||||
|
|
||||||
// @TODO: This function didn't make it over this.resetInvitees();
|
|
||||||
|
|
||||||
// @TODO: Sync group invites?
|
|
||||||
// if (this.group.type === 'party') {
|
|
||||||
// this.$router.push('//party');
|
|
||||||
// } else {
|
|
||||||
// this.$router.push(`/groups/guilds/${this.group._id}`);
|
|
||||||
// }
|
|
||||||
this.$root.$emit('bv::hide::modal', 'invite-modal');
|
|
||||||
// @TODO: error?
|
|
||||||
// _resetInvitees();
|
|
||||||
},
|
|
||||||
getOnlyUuids () {
|
|
||||||
let uuids = map(this.invitees, 'uuid');
|
|
||||||
let filteredUuids = filter(uuids, (id) => {
|
|
||||||
return id !== '';
|
|
||||||
});
|
|
||||||
return filteredUuids;
|
|
||||||
},
|
|
||||||
getEmails () {
|
|
||||||
let emails = filter(this.emails, (obj) => {
|
|
||||||
return obj.email !== '';
|
|
||||||
});
|
|
||||||
return emails;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
152
website/client/components/groups/inviteModalOld.vue
Normal file
152
website/client/components/groups/inviteModalOld.vue
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
b-modal#invite-modal(:title="$t('inviteFriends')", size='lg')
|
||||||
|
.modal-body
|
||||||
|
p.alert.alert-info(v-html="$t('inviteAlertInfo')")
|
||||||
|
.form-horizontal
|
||||||
|
table.table.table-striped
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th {{ $t('userId') }}
|
||||||
|
tbody
|
||||||
|
tr(v-for='user in invitees')
|
||||||
|
td
|
||||||
|
input.form-control(type='text', v-model='user.uuid')
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
button.btn.btn-primary.pull-right(@click='addUuid()')
|
||||||
|
i.glyphicon.glyphicon-plus
|
||||||
|
| +
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
.col-6.col-offset-6
|
||||||
|
button.btn.btn-primary.btn-block(@click='inviteNewUsers("uuid")') {{sendInviteText}}
|
||||||
|
hr
|
||||||
|
p.alert.alert-info {{ $t('inviteByEmail') }}
|
||||||
|
.form-horizontal
|
||||||
|
table.table.table-striped
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th {{ $t('name') }}
|
||||||
|
th {{ $t('email') }}
|
||||||
|
tbody
|
||||||
|
tr(v-for='email in emails')
|
||||||
|
td
|
||||||
|
input.form-control(type='text', v-model='email.name')
|
||||||
|
td
|
||||||
|
input.form-control(type='email', v-model='email.email')
|
||||||
|
tr
|
||||||
|
td(colspan=2)
|
||||||
|
button.btn.btn-primary.pull-right(@click='addEmail()')
|
||||||
|
i.glyphicon.glyphicon-plus
|
||||||
|
| +
|
||||||
|
tr
|
||||||
|
td.form-group(colspan=2)
|
||||||
|
label.col-sm-1.control-label {{ $t('byColon') }}
|
||||||
|
.col-sm-5
|
||||||
|
input.form-control(type='text', v-model='inviter')
|
||||||
|
.col-sm-6
|
||||||
|
button.btn.btn-primary.btn-block(@click='inviteNewUsers("email")') {{sendInviteText}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapState } from 'client/libs/store';
|
||||||
|
|
||||||
|
import filter from 'lodash/filter';
|
||||||
|
import map from 'lodash/map';
|
||||||
|
import notifications from 'client/mixins/notifications';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [notifications],
|
||||||
|
props: ['group'],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
invitees: [],
|
||||||
|
emails: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({user: 'user.data'}),
|
||||||
|
inviter () {
|
||||||
|
return this.user.profile.name;
|
||||||
|
},
|
||||||
|
sendInviteText () {
|
||||||
|
return 'Send Invites';
|
||||||
|
// if (!this.group) return 'Send Invites';
|
||||||
|
// return this.group.sendInviteText;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addUuid () {
|
||||||
|
this.invitees.push({uuid: ''});
|
||||||
|
},
|
||||||
|
addEmail () {
|
||||||
|
this.emails.push({name: '', email: ''});
|
||||||
|
},
|
||||||
|
inviteNewUsers (inviteMethod) {
|
||||||
|
if (!this.group._id) {
|
||||||
|
if (!this.group.name) this.group.name = this.$t('possessiveParty', {name: this.user.profile.name});
|
||||||
|
|
||||||
|
// @TODO: Add dispatch
|
||||||
|
// return Groups.Group.create(this.group)
|
||||||
|
// .then(function(response) {
|
||||||
|
// this.group = response.data.data;
|
||||||
|
// _inviteByMethod(inviteMethod);
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.inviteByMethod(inviteMethod);
|
||||||
|
},
|
||||||
|
async inviteByMethod (inviteMethod) {
|
||||||
|
let invitationDetails;
|
||||||
|
|
||||||
|
if (inviteMethod === 'email') {
|
||||||
|
let emails = this.getEmails();
|
||||||
|
invitationDetails = { inviter: this.inviter, emails };
|
||||||
|
} else if (inviteMethod === 'uuid') {
|
||||||
|
let uuids = this.getOnlyUuids();
|
||||||
|
invitationDetails = { uuids };
|
||||||
|
} else {
|
||||||
|
return alert('Invalid invite method.');
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.$store.dispatch('guilds:invite', {
|
||||||
|
invitationDetails,
|
||||||
|
groupId: this.group._id,
|
||||||
|
});
|
||||||
|
|
||||||
|
let invitesSent = invitationDetails.emails || invitationDetails.uuids;
|
||||||
|
let invitationString = invitesSent.length > 1 ? 'invitationsSent' : 'invitationSent';
|
||||||
|
|
||||||
|
this.text(this.$t(invitationString));
|
||||||
|
|
||||||
|
this.invitees = [];
|
||||||
|
this.emails = [];
|
||||||
|
|
||||||
|
// @TODO: This function didn't make it over this.resetInvitees();
|
||||||
|
|
||||||
|
// @TODO: Sync group invites?
|
||||||
|
// if (this.group.type === 'party') {
|
||||||
|
// this.$router.push('//party');
|
||||||
|
// } else {
|
||||||
|
// this.$router.push(`/groups/guilds/${this.group._id}`);
|
||||||
|
// }
|
||||||
|
this.$root.$emit('bv::hide::modal', 'invite-modal');
|
||||||
|
// @TODO: error?
|
||||||
|
// _resetInvitees();
|
||||||
|
},
|
||||||
|
getOnlyUuids () {
|
||||||
|
let uuids = map(this.invitees, 'uuid');
|
||||||
|
let filteredUuids = filter(uuids, (id) => {
|
||||||
|
return id !== '';
|
||||||
|
});
|
||||||
|
return filteredUuids;
|
||||||
|
},
|
||||||
|
getEmails () {
|
||||||
|
let emails = filter(this.emails, (obj) => {
|
||||||
|
return obj.email !== '';
|
||||||
|
});
|
||||||
|
return emails;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
div
|
div
|
||||||
invite-modal(:group='inviteModalGroup')
|
invite-modal(:group='inviteModalGroup', :groupType='inviteModalGroupType')
|
||||||
create-party-modal
|
create-party-modal
|
||||||
#app-header.row(:class="{'hide-header': $route.name === 'groupPlan'}")
|
#app-header.row(:class="{'hide-header': $route.name === 'groupPlan'}")
|
||||||
members-modal(:hide-badge="true")
|
members-modal(:hide-badge="true")
|
||||||
@@ -115,6 +115,7 @@ export default {
|
|||||||
expandedMember: null,
|
expandedMember: null,
|
||||||
currentWidth: 0,
|
currentWidth: 0,
|
||||||
inviteModalGroup: undefined,
|
inviteModalGroup: undefined,
|
||||||
|
inviteModalGroupType: undefined,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -178,6 +179,7 @@ export default {
|
|||||||
mounted () {
|
mounted () {
|
||||||
this.$root.$on('inviteModal::inviteToGroup', (group) => {
|
this.$root.$on('inviteModal::inviteToGroup', (group) => {
|
||||||
this.inviteModalGroup = group;
|
this.inviteModalGroup = group;
|
||||||
|
this.inviteModalGroupType = group.type === 'guild' ? 'Guild' : 'Party';
|
||||||
this.$root.$emit('bv::show::modal', 'invite-modal');
|
this.$root.$emit('bv::show::modal', 'invite-modal');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -24,9 +24,6 @@
|
|||||||
padding-left: 2rem;
|
padding-left: 2rem;
|
||||||
padding-right: 2rem;
|
padding-right: 2rem;
|
||||||
}
|
}
|
||||||
.modal-dialog {
|
|
||||||
transform: translate(0, 50vh) translate(-5%, -48%);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -151,3 +151,14 @@ export async function togglePrivateMessagesOpt (store) {
|
|||||||
store.state.user.data.inbox.optOut = !store.state.user.data.inbox.optOut;
|
store.state.user.data.inbox.optOut = !store.state.user.data.inbox.optOut;
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function userLookup (store, params) {
|
||||||
|
let response;
|
||||||
|
if (params.uuid) {
|
||||||
|
response = await axios.get(`/api/v4/members/${params.uuid}`);
|
||||||
|
}
|
||||||
|
if (params.username) {
|
||||||
|
response = await axios.get(`/api/v4/members/username/${params.username}`);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|||||||
@@ -185,7 +185,7 @@
|
|||||||
"inviteExistUser": "Invite Existing Users",
|
"inviteExistUser": "Invite Existing Users",
|
||||||
"byColon": "By:",
|
"byColon": "By:",
|
||||||
"inviteNewUsers": "Invite New Users",
|
"inviteNewUsers": "Invite New Users",
|
||||||
"sendInvitations": "Send Invitations",
|
"sendInvitations": "Send Invites",
|
||||||
"invitationsSent": "Invitations sent!",
|
"invitationsSent": "Invitations sent!",
|
||||||
"invitationSent": "Invitation sent!",
|
"invitationSent": "Invitation sent!",
|
||||||
"invitedFriend": "Invited a Friend",
|
"invitedFriend": "Invited a Friend",
|
||||||
@@ -367,6 +367,10 @@
|
|||||||
"liked": "Liked",
|
"liked": "Liked",
|
||||||
"joinGuild": "Join Guild",
|
"joinGuild": "Join Guild",
|
||||||
"inviteToGuild": "Invite to Guild",
|
"inviteToGuild": "Invite to Guild",
|
||||||
|
"inviteToParty": "Invite to Party",
|
||||||
|
"inviteEmailUsername": "Invite via Email or Username",
|
||||||
|
"inviteEmailUsernameInfo": "Invite users via a valid email or username. If an email isn't registered yet, we'll invite them to join.",
|
||||||
|
"emailOrUsernameInvite": "Email address or username",
|
||||||
"messageGuildLeader": "Message Guild Leader",
|
"messageGuildLeader": "Message Guild Leader",
|
||||||
"donateGems": "Donate Gems",
|
"donateGems": "Donate Gems",
|
||||||
"updateGuild": "Update Guild",
|
"updateGuild": "Update Guild",
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ import {
|
|||||||
import { removeFromArray } from '../../libs/collectionManipulators';
|
import { removeFromArray } from '../../libs/collectionManipulators';
|
||||||
import { sendTxn as sendTxnEmail } from '../../libs/email';
|
import { sendTxn as sendTxnEmail } from '../../libs/email';
|
||||||
import {
|
import {
|
||||||
_inviteByUUID,
|
inviteByUUID,
|
||||||
_inviteByEmail,
|
inviteByEmail,
|
||||||
_inviteByUserName,
|
inviteByUserName,
|
||||||
} from '../../libs/invites';
|
} from '../../libs/invites';
|
||||||
import common from '../../../common';
|
import common from '../../../common';
|
||||||
import payments from '../../libs/payments/payments';
|
import payments from '../../libs/payments/payments';
|
||||||
@@ -1038,13 +1038,13 @@ api.inviteToGroup = {
|
|||||||
const results = [];
|
const results = [];
|
||||||
|
|
||||||
if (uuids) {
|
if (uuids) {
|
||||||
const uuidInvites = uuids.map((uuid) => _inviteByUUID(uuid, group, user, req, res));
|
const uuidInvites = uuids.map((uuid) => inviteByUUID(uuid, group, user, req, res));
|
||||||
const uuidResults = await Promise.all(uuidInvites);
|
const uuidResults = await Promise.all(uuidInvites);
|
||||||
results.push(...uuidResults);
|
results.push(...uuidResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emails) {
|
if (emails) {
|
||||||
const emailInvites = emails.map((invite) => _inviteByEmail(invite, group, user, req, res));
|
const emailInvites = emails.map((invite) => inviteByEmail(invite, group, user, req, res));
|
||||||
user.invitesSent += emails.length;
|
user.invitesSent += emails.length;
|
||||||
await user.save();
|
await user.save();
|
||||||
const emailResults = await Promise.all(emailInvites);
|
const emailResults = await Promise.all(emailInvites);
|
||||||
@@ -1052,7 +1052,7 @@ api.inviteToGroup = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (usernames) {
|
if (usernames) {
|
||||||
const usernameInvites = usernames.map((username) => _inviteByUserName(username, group, user, req, res));
|
const usernameInvites = usernames.map((username) => inviteByUserName(username, group, user, req, res));
|
||||||
const usernameResults = await Promise.all(usernameInvites);
|
const usernameResults = await Promise.all(usernameInvites);
|
||||||
results.push(...usernameResults);
|
results.push(...usernameResults);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,33 @@ api.getMember = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
api.getMemberByUsername = {
|
||||||
|
method: 'GET',
|
||||||
|
url: '/members/username/:username',
|
||||||
|
middlewares: [],
|
||||||
|
async handler (req, res) {
|
||||||
|
req.checkParams('username', res.t('invalidReqParams')).notEmpty();
|
||||||
|
|
||||||
|
let validationErrors = req.validationErrors();
|
||||||
|
if (validationErrors) throw validationErrors;
|
||||||
|
|
||||||
|
let username = req.params.username.toLowerCase();
|
||||||
|
|
||||||
|
let member = await User
|
||||||
|
.findOne({'auth.local.lowerCaseUsername': username})
|
||||||
|
.select(memberFields)
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
if (!member || !member.flags.verifiedUsername) throw new NotFound(res.t('userNotFound'));
|
||||||
|
|
||||||
|
// manually call toJSON with minimize: true so empty paths aren't returned
|
||||||
|
let memberToJSON = member.toJSON({minimize: true});
|
||||||
|
User.addComputedStatsToJSONObj(memberToJSON.stats, member);
|
||||||
|
|
||||||
|
res.respond(200, memberToJSON);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} /api/v3/members/:memberId/achievements Get member achievements object
|
* @api {get} /api/v3/members/:memberId/achievements Get member achievements object
|
||||||
* @apiName GetMemberAchievements
|
* @apiName GetMemberAchievements
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ async function inviteUserToParty (userToInvite, group, inviter, res) {
|
|||||||
userToInvite.invitations.party = partyInvite;
|
userToInvite.invitations.party = partyInvite;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addInvitiationToUser (userToInvite, group, inviter, res) {
|
async function addInvitationToUser (userToInvite, group, inviter, res) {
|
||||||
const publicGuild = group.type === 'guild' && group.privacy === 'public';
|
const publicGuild = group.type === 'guild' && group.privacy === 'public';
|
||||||
|
|
||||||
if (group.type === 'guild') {
|
if (group.type === 'guild') {
|
||||||
@@ -123,7 +123,7 @@ async function addInvitiationToUser (userToInvite, group, inviter, res) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _inviteByUUID (uuid, group, inviter, req, res) {
|
async function inviteByUUID (uuid, group, inviter, req, res) {
|
||||||
const userToInvite = await User.findById(uuid).exec();
|
const userToInvite = await User.findById(uuid).exec();
|
||||||
|
|
||||||
if (!userToInvite) {
|
if (!userToInvite) {
|
||||||
@@ -137,10 +137,10 @@ async function _inviteByUUID (uuid, group, inviter, req, res) {
|
|||||||
throw new NotAuthorized(res.t(objections[0], { userId: uuid, username: userToInvite.profile.name}));
|
throw new NotAuthorized(res.t(objections[0], { userId: uuid, username: userToInvite.profile.name}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return await addInvitiationToUser(userToInvite, group, inviter, res);
|
return await addInvitationToUser(userToInvite, group, inviter, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _inviteByEmail (invite, group, inviter, req, res) {
|
async function inviteByEmail (invite, group, inviter, req, res) {
|
||||||
let userReturnInfo;
|
let userReturnInfo;
|
||||||
|
|
||||||
if (!invite.email) throw new BadRequest(res.t('inviteMissingEmail'));
|
if (!invite.email) throw new BadRequest(res.t('inviteMissingEmail'));
|
||||||
@@ -154,7 +154,7 @@ async function _inviteByEmail (invite, group, inviter, req, res) {
|
|||||||
.exec();
|
.exec();
|
||||||
|
|
||||||
if (userToContact) {
|
if (userToContact) {
|
||||||
userReturnInfo = await _inviteByUUID(userToContact._id, group, inviter, req, res);
|
userReturnInfo = await inviteByUUID(userToContact._id, group, inviter, req, res);
|
||||||
} else {
|
} else {
|
||||||
userReturnInfo = invite.email;
|
userReturnInfo = invite.email;
|
||||||
|
|
||||||
@@ -188,7 +188,9 @@ async function _inviteByEmail (invite, group, inviter, req, res) {
|
|||||||
return userReturnInfo;
|
return userReturnInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _inviteByUserName (username, group, inviter, req, res) {
|
async function inviteByUserName (username, group, inviter, req, res) {
|
||||||
|
if (username.indexOf('@') === 0) username = username.slice(1, username.length);
|
||||||
|
username = username.toLowerCase();
|
||||||
const userToInvite = await User.findOne({'auth.local.lowerCaseUsername': username}).exec();
|
const userToInvite = await User.findOne({'auth.local.lowerCaseUsername': username}).exec();
|
||||||
|
|
||||||
if (!userToInvite) {
|
if (!userToInvite) {
|
||||||
@@ -199,11 +201,11 @@ async function _inviteByUserName (username, group, inviter, req, res) {
|
|||||||
throw new BadRequest(res.t('cannotInviteSelfToGroup'));
|
throw new BadRequest(res.t('cannotInviteSelfToGroup'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return await addInvitiationToUser(userToInvite, group, inviter, res);
|
return await addInvitationToUser(userToInvite, group, inviter, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
_inviteByUUID,
|
inviteByUUID,
|
||||||
_inviteByEmail,
|
inviteByEmail,
|
||||||
_inviteByUserName,
|
inviteByUserName,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user