Initial Spark Install
This commit is contained in:
52
spark/resources/assets/js/settings/api.js
vendored
Normal file
52
spark/resources/assets/js/settings/api.js
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
tokens: [],
|
||||
availableAbilities: []
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.getTokens();
|
||||
this.getAvailableAbilities();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The component has been created by Vue.
|
||||
*/
|
||||
created() {
|
||||
var self = this;
|
||||
|
||||
this.$on('updateTokens', function(){
|
||||
self.getTokens();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Get the current API tokens for the user.
|
||||
*/
|
||||
getTokens() {
|
||||
axios.get('/settings/api/tokens')
|
||||
.then(response => this.tokens = response.data);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the available token abilities.
|
||||
*/
|
||||
getAvailableAbilities() {
|
||||
axios.get('/settings/api/token/abilities')
|
||||
.then(response => this.availableAbilities = response.data);
|
||||
}
|
||||
}
|
||||
};
|
139
spark/resources/assets/js/settings/api/create-token.js
vendored
Normal file
139
spark/resources/assets/js/settings/api/create-token.js
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
module.exports = {
|
||||
props: ['availableAbilities'],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
showingToken: null,
|
||||
allAbilitiesAssigned: false,
|
||||
|
||||
form: new SparkForm({
|
||||
name: '',
|
||||
abilities: []
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
copyCommandSupported() {
|
||||
return document.queryCommandSupported('copy');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
watch: {
|
||||
/**
|
||||
* Watch the available abilities for changes.
|
||||
*/
|
||||
availableAbilities() {
|
||||
if (this.availableAbilities.length > 0) {
|
||||
this.assignDefaultAbilities();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Assign all of the default abilities.
|
||||
*/
|
||||
assignDefaultAbilities() {
|
||||
var defaults = _.filter(this.availableAbilities, a => a.default);
|
||||
|
||||
this.form.abilities = _.pluck(defaults, 'value');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Enable all the available abilities for the given token.
|
||||
*/
|
||||
assignAllAbilities() {
|
||||
this.allAbilitiesAssigned = true;
|
||||
|
||||
this.form.abilities = _.pluck(this.availableAbilities, 'value');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Remove all of the abilities from the token.
|
||||
*/
|
||||
removeAllAbilities() {
|
||||
this.allAbilitiesAssigned = false;
|
||||
|
||||
this.form.abilities = [];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Toggle the given ability in the list of assigned abilities.
|
||||
*/
|
||||
toggleAbility(ability) {
|
||||
if (this.abilityIsAssigned(ability)) {
|
||||
this.form.abilities = _.reject(this.form.abilities, a => a == ability);
|
||||
} else {
|
||||
this.form.abilities.push(ability);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the given ability has been assigned to the token.
|
||||
*/
|
||||
abilityIsAssigned(ability) {
|
||||
return _.contains(this.form.abilities, ability);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Create a new API token.
|
||||
*/
|
||||
create() {
|
||||
Spark.post('/settings/api/token', this.form)
|
||||
.then(response => {
|
||||
this.showToken(response.token);
|
||||
|
||||
this.resetForm();
|
||||
|
||||
this.$parent.$emit('updateTokens');
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Display the token to the user.
|
||||
*/
|
||||
showToken(token) {
|
||||
this.showingToken = token;
|
||||
|
||||
$('#modal-show-token').modal('show');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Select the token and copy to Clipboard.
|
||||
*/
|
||||
selectToken() {
|
||||
$('#api-token').select();
|
||||
|
||||
if (this.copyCommandSupported) {
|
||||
document.execCommand("copy");
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Reset the token form back to its default state.
|
||||
*/
|
||||
resetForm() {
|
||||
this.form.name = '';
|
||||
|
||||
this.assignDefaultAbilities();
|
||||
|
||||
this.allAbilitiesAssigned = false;
|
||||
}
|
||||
}
|
||||
};
|
103
spark/resources/assets/js/settings/api/tokens.js
vendored
Normal file
103
spark/resources/assets/js/settings/api/tokens.js
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
module.exports = {
|
||||
props: ['tokens', 'availableAbilities'],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
updatingToken: null,
|
||||
deletingToken: null,
|
||||
|
||||
updateTokenForm: new SparkForm({
|
||||
name: '',
|
||||
abilities: []
|
||||
}),
|
||||
|
||||
deleteTokenForm: new SparkForm({})
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Show the edit token modal.
|
||||
*/
|
||||
editToken(token) {
|
||||
this.updatingToken = token;
|
||||
|
||||
this.initializeUpdateFormWith(token);
|
||||
|
||||
$('#modal-update-token').modal('show');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the edit form with the given token.
|
||||
*/
|
||||
initializeUpdateFormWith(token) {
|
||||
this.updateTokenForm.name = token.name;
|
||||
|
||||
this.updateTokenForm.abilities = token.metadata.abilities;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Update the token being edited.
|
||||
*/
|
||||
updateToken() {
|
||||
Spark.put(`/settings/api/token/${this.updatingToken.id}`, this.updateTokenForm)
|
||||
.then(response => {
|
||||
this.$parent.$emit('updateTokens');
|
||||
|
||||
$('#modal-update-token').modal('hide');
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Toggle the ability on the current token being edited.
|
||||
*/
|
||||
toggleAbility(ability) {
|
||||
if (this.abilityIsAssigned(ability)) {
|
||||
this.updateTokenForm.abilities = _.reject(
|
||||
this.updateTokenForm.abilities, a => a == ability
|
||||
);
|
||||
} else {
|
||||
this.updateTokenForm.abilities.push(ability);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the ability has been assigned to the token being edited.
|
||||
*/
|
||||
abilityIsAssigned(ability) {
|
||||
return _.contains(this.updateTokenForm.abilities, ability);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get user confirmation that the token should be deleted.
|
||||
*/
|
||||
approveTokenDelete(token) {
|
||||
this.deletingToken = token;
|
||||
|
||||
$('#modal-delete-token').modal('show');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Delete the specified token.
|
||||
*/
|
||||
deleteToken() {
|
||||
Spark.delete(`/settings/api/token/${this.deletingToken.id}`, this.deleteTokenForm)
|
||||
.then(() => {
|
||||
this.$parent.$emit('updateTokens');
|
||||
|
||||
$('#modal-delete-token').modal('hide');
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
47
spark/resources/assets/js/settings/invoices.js
vendored
Normal file
47
spark/resources/assets/js/settings/invoices.js
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
invoices: []
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.getInvoices();
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Get the user's billing invoices
|
||||
*/
|
||||
getInvoices() {
|
||||
axios.get(this.urlForInvoices)
|
||||
.then(response => {
|
||||
this.invoices = _.filter(response.data, invoice => {
|
||||
return invoice.total != '$0.00';
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the URL for retrieving the invoices.
|
||||
*/
|
||||
urlForInvoices() {
|
||||
return this.billingUser
|
||||
? '/settings/invoices'
|
||||
: `/settings/${Spark.pluralTeamString}/${this.team.id}/invoices`;
|
||||
}
|
||||
}
|
||||
};
|
15
spark/resources/assets/js/settings/invoices/invoice-list.js
vendored
Normal file
15
spark/resources/assets/js/settings/invoices/invoice-list.js
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'invoices', 'billableType'],
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Get the URL for downloading a given invoice.
|
||||
*/
|
||||
downloadUrlFor(invoice) {
|
||||
return this.billingUser
|
||||
? `/settings/invoice/${invoice.id}`
|
||||
: `/settings/${Spark.pluralTeamString}/${this.team.id}/invoice/${invoice.id}`;
|
||||
}
|
||||
}
|
||||
};
|
45
spark/resources/assets/js/settings/invoices/update-extra-billing-information.js
vendored
Normal file
45
spark/resources/assets/js/settings/invoices/update-extra-billing-information.js
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({
|
||||
information: ''
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.form.information = this.billable.extra_billing_information;
|
||||
},
|
||||
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Update the extra billing information.
|
||||
*/
|
||||
update() {
|
||||
Spark.put(this.urlForUpdate, this.form);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the URL for the extra billing information method update.
|
||||
*/
|
||||
urlForUpdate() {
|
||||
return this.billingUser
|
||||
? '/settings/extra-billing-information'
|
||||
: `/settings/${Spark.pluralTeamString}/${this.team.id}/extra-billing-information`;
|
||||
}
|
||||
}
|
||||
};
|
77
spark/resources/assets/js/settings/payment-method-braintree.js
vendored
Normal file
77
spark/resources/assets/js/settings/payment-method-braintree.js
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
|
||||
/**
|
||||
* Load mixins for the component.
|
||||
*/
|
||||
mixins: [
|
||||
require('./../mixins/discounts')
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* The componetn's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
currentDiscount: null,
|
||||
loadingCurrentDiscount: false
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The component has been created by Vue.
|
||||
*/
|
||||
created() {
|
||||
var self = this;
|
||||
|
||||
this.$on('updateDiscount', function(){
|
||||
self.getCurrentDiscountForBillable(self.billableType, self.billable);
|
||||
|
||||
return true;
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.getCurrentDiscountForBillable(this.billableType, this.billable);
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Calculate the amount off for the given discount amount.
|
||||
*/
|
||||
calculateAmountOff(amount) {
|
||||
return amount;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the formatted discount duration for the given discount.
|
||||
*/
|
||||
formattedDiscountDuration(discount) {
|
||||
if ( ! discount) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (discount.duration) {
|
||||
case 'forever':
|
||||
return 'for all future invoices';
|
||||
case 'once':
|
||||
return 'a single invoice';
|
||||
case 'repeating':
|
||||
if (discount.duration_in_months === 1) {
|
||||
return 'all invoices during the next billing cycle';
|
||||
} else {
|
||||
return `all invoices during the next ${discount.duration_in_months} billing cycles`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
43
spark/resources/assets/js/settings/payment-method-stripe.js
vendored
Normal file
43
spark/resources/assets/js/settings/payment-method-stripe.js
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
|
||||
/**
|
||||
* Load mixins for the component.
|
||||
*/
|
||||
mixins: [
|
||||
require('./../mixins/discounts')
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* The componetn's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
currentDiscount: null,
|
||||
loadingCurrentDiscount: false
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The component has been created by Vue.
|
||||
*/
|
||||
created() {
|
||||
var self = this;
|
||||
|
||||
this.$on('updateDiscount', function(){
|
||||
self.getCurrentDiscountForBillable(self.billableType, self.billable);
|
||||
|
||||
return true;
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.getCurrentDiscountForBillable(this.billableType, this.billable);
|
||||
},
|
||||
};
|
41
spark/resources/assets/js/settings/payment-method/redeem-coupon.js
vendored
Normal file
41
spark/resources/assets/js/settings/payment-method/redeem-coupon.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({
|
||||
coupon: ''
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Redeem the given coupon code.
|
||||
*/
|
||||
redeem() {
|
||||
Spark.post(this.urlForRedemption, this.form)
|
||||
.then(() => {
|
||||
this.form.coupon = '';
|
||||
|
||||
this.$parent.$emit('updateDiscount');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the URL for redeeming a coupon.
|
||||
*/
|
||||
urlForRedemption() {
|
||||
return this.billingUser
|
||||
? '/settings/payment-method/coupon'
|
||||
: `/settings/${Spark.pluralTeamString}/${this.team.id}/payment-method/coupon`;
|
||||
}
|
||||
}
|
||||
};
|
104
spark/resources/assets/js/settings/payment-method/update-payment-method-braintree.js
vendored
Normal file
104
spark/resources/assets/js/settings/payment-method/update-payment-method-braintree.js
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
|
||||
/**
|
||||
* Load mixins for the component.
|
||||
*/
|
||||
mixins: [
|
||||
require('./../../mixins/braintree')
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({
|
||||
braintree_type: '',
|
||||
braintree_token: '',
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.braintree(
|
||||
'braintree-payment-method-container',
|
||||
this.braintreeCallback
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Update the entity's card information.
|
||||
*/
|
||||
update() {
|
||||
Spark.put(this.urlForUpdate, this.form)
|
||||
.then(() => {
|
||||
Bus.$emit('updateUser');
|
||||
Bus.$emit('updateTeam');
|
||||
|
||||
this.resetBraintree(
|
||||
'braintree-payment-method-container',
|
||||
this.braintreeCallback
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The Braintree payment method received callback.
|
||||
*/
|
||||
braintreeCallback(response) {
|
||||
this.form.braintree_type = response.type;
|
||||
this.form.braintree_token = response.nonce;
|
||||
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the URL for the payment method update.
|
||||
*/
|
||||
urlForUpdate() {
|
||||
return this.billingUser
|
||||
? '/settings/payment-method'
|
||||
: `/settings/${Spark.pluralTeamString}/${this.team.id}/payment-method`;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the proper brand icon for the customer's credit card.
|
||||
*/
|
||||
cardIcon() {
|
||||
if (! this.billable.card_brand) {
|
||||
return 'fa-credit-card';
|
||||
}
|
||||
|
||||
switch (this.billable.card_brand) {
|
||||
case 'American Express':
|
||||
return 'fa-cc-amex';
|
||||
case 'Diners Club':
|
||||
return 'fa-cc-diners-club';
|
||||
case 'Discover':
|
||||
return 'fa-cc-discover';
|
||||
case 'JCB':
|
||||
return 'fa-cc-jcb';
|
||||
case 'MasterCard':
|
||||
return 'fa-cc-mastercard';
|
||||
case 'Visa':
|
||||
return 'fa-cc-visa';
|
||||
default:
|
||||
return 'fa-credit-card';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
183
spark/resources/assets/js/settings/payment-method/update-payment-method-stripe.js
vendored
Normal file
183
spark/resources/assets/js/settings/payment-method/update-payment-method-stripe.js
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({
|
||||
stripe_token: '',
|
||||
address: '',
|
||||
address_line_2: '',
|
||||
city: '',
|
||||
state: '',
|
||||
zip: '',
|
||||
country: 'US'
|
||||
}),
|
||||
|
||||
cardForm: new SparkForm({
|
||||
name: '',
|
||||
number: '',
|
||||
cvc: '',
|
||||
month: '',
|
||||
year: ''
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
Stripe.setPublishableKey(Spark.stripeKey);
|
||||
|
||||
this.initializeBillingAddress();
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Initialize the billing address form for the billable entity.
|
||||
*/
|
||||
initializeBillingAddress() {
|
||||
if (! Spark.collectsBillingAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.form.address = this.billable.billing_address;
|
||||
this.form.address_line_2 = this.billable.billing_address_line_2;
|
||||
this.form.city = this.billable.billing_city;
|
||||
this.form.state = this.billable.billing_state;
|
||||
this.form.zip = this.billable.billing_zip;
|
||||
this.form.country = this.billable.billing_country || 'US';
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Update the billable's card information.
|
||||
*/
|
||||
update() {
|
||||
this.form.busy = true;
|
||||
this.form.errors.forget();
|
||||
this.form.successful = false;
|
||||
this.cardForm.errors.forget();
|
||||
|
||||
// Here we will build out the payload to send to Stripe to obtain a card token so
|
||||
// we can create the actual subscription. We will build out this data that has
|
||||
// this credit card number, CVC, etc. and exchange it for a secure token ID.
|
||||
const payload = {
|
||||
name: this.cardForm.name,
|
||||
number: this.cardForm.number,
|
||||
cvc: this.cardForm.cvc,
|
||||
exp_month: this.cardForm.month,
|
||||
exp_year: this.cardForm.year,
|
||||
address_line1: this.form.address,
|
||||
address_line2: this.form.address_line_2,
|
||||
address_city: this.form.city,
|
||||
address_state: this.form.state,
|
||||
address_zip: this.form.zip,
|
||||
address_country: this.form.country,
|
||||
};
|
||||
|
||||
// Once we have the Stripe payload we'll send it off to Stripe and obtain a token
|
||||
// which we will send to the server to update this payment method. If there is
|
||||
// an error we will display that back out to the user for their information.
|
||||
Stripe.card.createToken(payload, (status, response) => {
|
||||
if (response.error) {
|
||||
this.cardForm.errors.set({number: [
|
||||
response.error.message
|
||||
]});
|
||||
|
||||
this.form.busy = false;
|
||||
} else {
|
||||
this.sendUpdateToServer(response.id);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Send the credit card update information to the server.
|
||||
*/
|
||||
sendUpdateToServer(token) {
|
||||
this.form.stripe_token = token;
|
||||
|
||||
Spark.put(this.urlForUpdate, this.form)
|
||||
.then(() => {
|
||||
Bus.$emit('updateUser');
|
||||
Bus.$emit('updateTeam');
|
||||
|
||||
this.cardForm.name = '';
|
||||
this.cardForm.number = '';
|
||||
this.cardForm.cvc = '';
|
||||
this.cardForm.month = '';
|
||||
this.cardForm.year = '';
|
||||
|
||||
if ( ! Spark.collectsBillingAddress) {
|
||||
this.form.zip = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the billable entity's "billable" name.
|
||||
*/
|
||||
billableName() {
|
||||
return this.billingUser ? this.user.name : this.team.owner.name;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the URL for the payment method update.
|
||||
*/
|
||||
urlForUpdate() {
|
||||
return this.billingUser
|
||||
? '/settings/payment-method'
|
||||
: `/settings/${Spark.pluralTeamString}/${this.team.id}/payment-method`;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the proper brand icon for the customer's credit card.
|
||||
*/
|
||||
cardIcon() {
|
||||
if (! this.billable.card_brand) {
|
||||
return 'fa-cc-stripe';
|
||||
}
|
||||
|
||||
switch (this.billable.card_brand) {
|
||||
case 'American Express':
|
||||
return 'fa-cc-amex';
|
||||
case 'Diners Club':
|
||||
return 'fa-cc-diners-club';
|
||||
case 'Discover':
|
||||
return 'fa-cc-discover';
|
||||
case 'JCB':
|
||||
return 'fa-cc-jcb';
|
||||
case 'MasterCard':
|
||||
return 'fa-cc-mastercard';
|
||||
case 'Visa':
|
||||
return 'fa-cc-visa';
|
||||
default:
|
||||
return 'fa-cc-stripe';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the placeholder for the billable entity's credit card.
|
||||
*/
|
||||
placeholder() {
|
||||
if (this.billable.card_last_four) {
|
||||
return `************${this.billable.card_last_four}`;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
};
|
42
spark/resources/assets/js/settings/payment-method/update-vat-id.js
vendored
Normal file
42
spark/resources/assets/js/settings/payment-method/update-vat-id.js
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({ vat_id: '' })
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Bootstrap the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.form.vat_id = this.billable.vat_id;
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Update the customer's VAT ID.
|
||||
*/
|
||||
update() {
|
||||
Spark.put(this.urlForUpdate, this.form);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the URL for the VAT ID update.
|
||||
*/
|
||||
urlForUpdate() {
|
||||
return this.billingUser
|
||||
? '/settings/payment-method/vat-id'
|
||||
: `/settings/${Spark.pluralTeamString}/${this.team.id}/payment-method/vat-id`;
|
||||
}
|
||||
}
|
||||
}
|
3
spark/resources/assets/js/settings/profile.js
vendored
Normal file
3
spark/resources/assets/js/settings/profile.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
props: ['user']
|
||||
};
|
37
spark/resources/assets/js/settings/profile/update-contact-information.js
vendored
Normal file
37
spark/resources/assets/js/settings/profile/update-contact-information.js
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
module.exports = {
|
||||
props: ['user'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: $.extend(true, new SparkForm({
|
||||
name: '',
|
||||
email: ''
|
||||
}), Spark.forms.updateContactInformation)
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Bootstrap the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.form.name = this.user.name;
|
||||
this.form.email = this.user.email;
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Update the user's contact information.
|
||||
*/
|
||||
update() {
|
||||
Spark.put('/settings/contact', this.form)
|
||||
.then(() => {
|
||||
Bus.$emit('updateUser');
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
67
spark/resources/assets/js/settings/profile/update-profile-photo.js
vendored
Normal file
67
spark/resources/assets/js/settings/profile/update-profile-photo.js
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
module.exports = {
|
||||
props: ['user'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Update the user's profile photo.
|
||||
*/
|
||||
update(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if ( ! this.$refs.photo.files.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
this.form.startProcessing();
|
||||
|
||||
// We need to gather a fresh FormData instance with the profile photo appended to
|
||||
// the data so we can POST it up to the server. This will allow us to do async
|
||||
// uploads of the profile photos. We will update the user after this action.
|
||||
axios.post('/settings/photo', this.gatherFormData())
|
||||
.then(
|
||||
() => {
|
||||
Bus.$emit('updateUser');
|
||||
|
||||
self.form.finishProcessing();
|
||||
},
|
||||
(error) => {
|
||||
self.form.setErrors(error.response.data.errors);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Gather the form data for the photo upload.
|
||||
*/
|
||||
gatherFormData() {
|
||||
const data = new FormData();
|
||||
|
||||
data.append('photo', this.$refs.photo.files[0]);
|
||||
|
||||
return data;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Calculate the style attribute for the photo preview.
|
||||
*/
|
||||
previewStyle() {
|
||||
return `background-image: url(${this.user.photo_url})`;
|
||||
}
|
||||
}
|
||||
};
|
27
spark/resources/assets/js/settings/security.js
vendored
Normal file
27
spark/resources/assets/js/settings/security.js
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
module.exports = {
|
||||
props: ['user'],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
twoFactorResetCode: null
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The component has been created by Vue.
|
||||
*/
|
||||
created() {
|
||||
var self = this;
|
||||
|
||||
this.$on('receivedTwoFactorResetCode', function (code) {
|
||||
self.twoFactorResetCode = code;
|
||||
|
||||
$('#modal-show-two-factor-reset-code').modal('show');
|
||||
});
|
||||
}
|
||||
};
|
25
spark/resources/assets/js/settings/security/disable-two-factor-auth.js
vendored
Normal file
25
spark/resources/assets/js/settings/security/disable-two-factor-auth.js
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
module.exports = {
|
||||
props: ['user'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({})
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Disable two-factor authentication for the user.
|
||||
*/
|
||||
disable() {
|
||||
Spark.delete('/settings/two-factor-auth', this.form)
|
||||
.then(() => {
|
||||
Bus.$emit('updateUser');
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
39
spark/resources/assets/js/settings/security/enable-two-factor-auth.js
vendored
Normal file
39
spark/resources/assets/js/settings/security/enable-two-factor-auth.js
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
module.exports = {
|
||||
props: ['user'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({
|
||||
country_code: '',
|
||||
phone: ''
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.form.country_code = this.user.country_code;
|
||||
this.form.phone = this.user.phone;
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Enable two-factor authentication for the user.
|
||||
*/
|
||||
enable() {
|
||||
Spark.post('/settings/two-factor-auth', this.form)
|
||||
.then(code => {
|
||||
this.$parent.$emit('receivedTwoFactorResetCode', code);
|
||||
|
||||
Bus.$emit('updateUser');
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
24
spark/resources/assets/js/settings/security/update-password.js
vendored
Normal file
24
spark/resources/assets/js/settings/security/update-password.js
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({
|
||||
current_password: '',
|
||||
password: '',
|
||||
password_confirmation: ''
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Update the user's password.
|
||||
*/
|
||||
update() {
|
||||
Spark.put('/settings/password', this.form);
|
||||
}
|
||||
}
|
||||
};
|
28
spark/resources/assets/js/settings/settings.js
vendored
Normal file
28
spark/resources/assets/js/settings/settings.js
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
module.exports = {
|
||||
props: ['user', 'teams'],
|
||||
|
||||
|
||||
/**
|
||||
* Load mixins for the component.
|
||||
*/
|
||||
mixins: [require('./../mixins/tab-state')],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
billableType: 'user',
|
||||
team: null
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.usePushStateForTabs('.spark-settings-tabs');
|
||||
}
|
||||
};
|
50
spark/resources/assets/js/settings/subscription.js
vendored
Normal file
50
spark/resources/assets/js/settings/subscription.js
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
/**
|
||||
* Load mixins for the component.
|
||||
*/
|
||||
mixins: [
|
||||
require('./../mixins/plans'),
|
||||
require('./../mixins/subscriptions')
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
plans: []
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
var self = this;
|
||||
|
||||
this.getPlans();
|
||||
|
||||
this.$on('showPlanDetails', function (plan) {
|
||||
self.showPlanDetails(plan);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Get the active plans for the application.
|
||||
*/
|
||||
getPlans() {
|
||||
axios.get('/spark/plans')
|
||||
.then(response => {
|
||||
this.plans = this.billingUser
|
||||
? _.where(response.data, {type: "user"})
|
||||
: _.where(response.data, {type: "team"});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
48
spark/resources/assets/js/settings/subscription/cancel-subscription.js
vendored
Normal file
48
spark/resources/assets/js/settings/subscription/cancel-subscription.js
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Confirm the cancellation operation.
|
||||
*/
|
||||
confirmCancellation() {
|
||||
$('#modal-confirm-cancellation').modal('show');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Cancel the current subscription.
|
||||
*/
|
||||
cancel() {
|
||||
Spark.delete(this.urlForCancellation, this.form)
|
||||
.then(() => {
|
||||
Bus.$emit('updateUser');
|
||||
Bus.$emit('updateTeam');
|
||||
|
||||
$('#modal-confirm-cancellation').modal('hide');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the URL for the subscription cancellation.
|
||||
*/
|
||||
urlForCancellation() {
|
||||
return this.billingUser
|
||||
? '/settings/subscription'
|
||||
: `/settings/${Spark.pluralTeamString}/${this.team.id}/subscription`;
|
||||
}
|
||||
}
|
||||
};
|
41
spark/resources/assets/js/settings/subscription/resume-subscription.js
vendored
Normal file
41
spark/resources/assets/js/settings/subscription/resume-subscription.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'plans', 'billableType'],
|
||||
|
||||
/**
|
||||
* Load mixins for the component.
|
||||
*/
|
||||
mixins: [
|
||||
require('./../../mixins/plans'),
|
||||
require('./../../mixins/subscriptions')
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
if (this.onlyHasYearlyPlans) {
|
||||
this.showYearlyPlans();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Show the plan details for the given plan.
|
||||
*
|
||||
* We'll ask the parent subscription component to display it.
|
||||
*/
|
||||
showPlanDetails(plan) {
|
||||
this.$parent.$emit('showPlanDetails', plan);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the plan price with the applicable VAT.
|
||||
*/
|
||||
priceWithTax(plan) {
|
||||
return plan.price + (plan.price * (this.billable.tax_rate / 100));
|
||||
}
|
||||
}
|
||||
};
|
96
spark/resources/assets/js/settings/subscription/subscribe-braintree.js
vendored
Normal file
96
spark/resources/assets/js/settings/subscription/subscribe-braintree.js
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'plans', 'billableType'],
|
||||
|
||||
/**
|
||||
* Load mixins for the component.
|
||||
*/
|
||||
mixins: [
|
||||
require('./../../mixins/braintree'),
|
||||
require('./../../mixins/plans'),
|
||||
require('./../../mixins/subscriptions')
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({
|
||||
braintree_type: '',
|
||||
braintree_token: '',
|
||||
plan: '',
|
||||
coupon: null
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
// If only yearly subscription plans are available, we will select that interval so that we
|
||||
// can show the plans. Then we'll select the first available paid plan from the list and
|
||||
// start the form in a good default spot. The user may then select another plan later.
|
||||
if (this.onlyHasYearlyPaidPlans) {
|
||||
this.showYearlyPlans();
|
||||
}
|
||||
|
||||
// Next, we will configure the braintree container element on the page and handle the nonce
|
||||
// received callback. We'll then set the nonce and fire off the subscribe method so this
|
||||
// nonce can be used to create the subscription for the billable entity being managed.
|
||||
this.braintree('braintree-subscribe-container', response => {
|
||||
this.form.braintree_type = response.type;
|
||||
this.form.braintree_token = response.nonce;
|
||||
|
||||
this.subscribe();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Mark the given plan as selected.
|
||||
*/
|
||||
selectPlan(plan) {
|
||||
this.selectedPlan = plan;
|
||||
|
||||
this.form.plan = this.selectedPlan.id;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Subscribe to the specified plan.
|
||||
*/
|
||||
subscribe() {
|
||||
Spark.post(this.urlForNewSubscription, this.form)
|
||||
.then(response => {
|
||||
Bus.$emit('updateUser');
|
||||
Bus.$emit('updateTeam');
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Show the plan details for the given plan.
|
||||
*
|
||||
* We'll ask the parent subscription component to display it.
|
||||
*/
|
||||
showPlanDetails(plan) {
|
||||
this.$parent.$emit('showPlanDetails', plan);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the URL for subscribing to a plan.
|
||||
*/
|
||||
urlForNewSubscription() {
|
||||
return this.billingUser
|
||||
? '/settings/subscription'
|
||||
: `/settings/${Spark.pluralTeamString}/${this.team.id}/subscription`;
|
||||
}
|
||||
}
|
||||
};
|
216
spark/resources/assets/js/settings/subscription/subscribe-stripe.js
vendored
Normal file
216
spark/resources/assets/js/settings/subscription/subscribe-stripe.js
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'plans', 'billableType'],
|
||||
|
||||
/**
|
||||
* Load mixins for the component.
|
||||
*/
|
||||
mixins: [
|
||||
require('./../../mixins/plans'),
|
||||
require('./../../mixins/subscriptions'),
|
||||
require('./../../mixins/vat')
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
taxRate: 0,
|
||||
|
||||
form: new SparkForm({
|
||||
stripe_token: '',
|
||||
plan: '',
|
||||
coupon: null,
|
||||
address: '',
|
||||
address_line_2: '',
|
||||
city: '',
|
||||
state: '',
|
||||
zip: '',
|
||||
country: 'US',
|
||||
vat_id: ''
|
||||
}),
|
||||
|
||||
cardForm: new SparkForm({
|
||||
name: '',
|
||||
number: '',
|
||||
cvc: '',
|
||||
month: '',
|
||||
year: '',
|
||||
zip: ''
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
watch: {
|
||||
/**
|
||||
* Watch for changes on the entire billing address.
|
||||
*/
|
||||
'currentBillingAddress': function (value) {
|
||||
if ( ! Spark.collectsEuropeanVat) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.refreshTaxRate(this.form);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
Stripe.setPublishableKey(Spark.stripeKey);
|
||||
|
||||
this.initializeBillingAddress();
|
||||
|
||||
if (this.onlyHasYearlyPaidPlans) {
|
||||
this.showYearlyPlans();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Initialize the billing address form for the billable entity.
|
||||
*/
|
||||
initializeBillingAddress() {
|
||||
this.form.address = this.billable.billing_address;
|
||||
this.form.address_line_2 = this.billable.billing_address_line_2;
|
||||
this.form.city = this.billable.billing_city;
|
||||
this.form.state = this.billable.billing_state;
|
||||
this.form.zip = this.billable.billing_zip;
|
||||
this.form.country = this.billable.billing_country || 'US';
|
||||
this.form.vat_id = this.billable.vat_id;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Mark the given plan as selected.
|
||||
*/
|
||||
selectPlan(plan) {
|
||||
this.selectedPlan = plan;
|
||||
|
||||
this.form.plan = this.selectedPlan.id;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Subscribe to the specified plan.
|
||||
*/
|
||||
subscribe() {
|
||||
this.cardForm.errors.forget();
|
||||
|
||||
this.form.startProcessing();
|
||||
|
||||
// Here we will build out the payload to send to Stripe to obtain a card token so
|
||||
// we can create the actual subscription. We will build out this data that has
|
||||
// this credit card number, CVC, etc. and exchange it for a secure token ID.
|
||||
const payload = {
|
||||
name: this.cardForm.name,
|
||||
number: this.cardForm.number,
|
||||
cvc: this.cardForm.cvc,
|
||||
exp_month: this.cardForm.month,
|
||||
exp_year: this.cardForm.year,
|
||||
address_line1: this.form.address,
|
||||
address_line2: this.form.address_line_2,
|
||||
address_city: this.form.city,
|
||||
address_state: this.form.state,
|
||||
address_zip: this.form.zip,
|
||||
address_country: this.form.country
|
||||
};
|
||||
|
||||
// Next, we will send the payload to Stripe and handle the response. If we have a
|
||||
// valid token we can send that to the server and use the token to create this
|
||||
// subscription on the back-end. Otherwise, we will show the error messages.
|
||||
Stripe.card.createToken(payload, (status, response) => {
|
||||
if (response.error) {
|
||||
this.cardForm.errors.set({number: [
|
||||
response.error.message
|
||||
]})
|
||||
|
||||
this.form.busy = false;
|
||||
} else {
|
||||
this.createSubscription(response.id);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* After obtaining the Stripe token, create subscription on the Spark server.
|
||||
*/
|
||||
createSubscription(token) {
|
||||
this.form.stripe_token = token;
|
||||
|
||||
Spark.post(this.urlForNewSubscription, this.form)
|
||||
.then(response => {
|
||||
Bus.$emit('updateUser');
|
||||
Bus.$emit('updateTeam');
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the user has subscribed to the given plan before.
|
||||
*/
|
||||
hasSubscribed(plan) {
|
||||
return !!_.where(this.billable.subscriptions, {provider_plan: plan.id}).length
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Show the plan details for the given plan.
|
||||
*
|
||||
* We'll ask the parent subscription component to display it.
|
||||
*/
|
||||
showPlanDetails(plan) {
|
||||
this.$parent.$emit('showPlanDetails', plan);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the billable entity's "billable" name.
|
||||
*/
|
||||
billableName() {
|
||||
return this.billingUser ? this.user.name : this.team.owner.name;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the selected country collects European VAT.
|
||||
*/
|
||||
countryCollectsVat() {
|
||||
return this.collectsVat(this.form.country);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the URL for subscribing to a plan.
|
||||
*/
|
||||
urlForNewSubscription() {
|
||||
return this.billingUser
|
||||
? '/settings/subscription'
|
||||
: `/settings/${Spark.pluralTeamString}/${this.team.id}/subscription`;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the current billing address from the subscribe form.
|
||||
*
|
||||
* This used primarily for wathcing.
|
||||
*/
|
||||
currentBillingAddress() {
|
||||
return this.form.address +
|
||||
this.form.address_line_2 +
|
||||
this.form.city +
|
||||
this.form.state +
|
||||
this.form.zip +
|
||||
this.form.country +
|
||||
this.form.vat_id;
|
||||
}
|
||||
}
|
||||
};
|
92
spark/resources/assets/js/settings/subscription/update-subscription.js
vendored
Normal file
92
spark/resources/assets/js/settings/subscription/update-subscription.js
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'plans', 'billableType'],
|
||||
|
||||
/**
|
||||
* Load mixins for the component.
|
||||
*/
|
||||
mixins: [
|
||||
require('./../../mixins/plans'),
|
||||
require('./../../mixins/subscriptions')
|
||||
],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
confirmingPlan: null
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.selectActivePlanInterval();
|
||||
|
||||
// We need to watch the activePlan computed property for changes so we can select
|
||||
// the proper active plan on the plan interval button group. So, we will watch
|
||||
// this property and fire off a method anytime it changes so it can sync up.
|
||||
this.$watch('activePlan', value => {
|
||||
this.selectActivePlanInterval();
|
||||
});
|
||||
|
||||
if (this.onlyHasYearlyPlans) {
|
||||
this.showYearlyPlans();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Confirm the plan update with the user.
|
||||
*/
|
||||
confirmPlanUpdate(plan) {
|
||||
this.confirmingPlan = plan;
|
||||
|
||||
$('#modal-confirm-plan-update').modal('show');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Approve the plan update.
|
||||
*/
|
||||
approvePlanUpdate() {
|
||||
$('#modal-confirm-plan-update').modal('hide');
|
||||
|
||||
this.updateSubscription(this.confirmingPlan);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Select the active plan interval.
|
||||
*/
|
||||
selectActivePlanInterval() {
|
||||
if (this.activePlanIsMonthly || this.yearlyPlans.length == 0) {
|
||||
this.showMonthlyPlans();
|
||||
} else {
|
||||
this.showYearlyPlans();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Show the plan details for the given plan.
|
||||
*
|
||||
* We'll ask the parent subscription component to display it.
|
||||
*/
|
||||
showPlanDetails(plan) {
|
||||
this.$parent.$emit('showPlanDetails', plan);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the plan price with the applicable VAT.
|
||||
*/
|
||||
priceWithTax(plan) {
|
||||
return plan.price + (plan.price * (this.billable.tax_rate / 100));
|
||||
}
|
||||
}
|
||||
};
|
3
spark/resources/assets/js/settings/teams.js
vendored
Normal file
3
spark/resources/assets/js/settings/teams.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
props: ['user', 'teams'],
|
||||
};
|
151
spark/resources/assets/js/settings/teams/create-team.js
vendored
Normal file
151
spark/resources/assets/js/settings/teams/create-team.js
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
plans: [],
|
||||
|
||||
form: new SparkForm({
|
||||
name: '',
|
||||
slug: ''
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the active subscription instance.
|
||||
*/
|
||||
activeSubscription() {
|
||||
if ( ! this.$parent.billable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const subscription = _.find(
|
||||
this.$parent.billable.subscriptions,
|
||||
subscription => subscription.name == 'default'
|
||||
);
|
||||
|
||||
if (typeof subscription !== 'undefined') {
|
||||
return subscription;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the active plan instance.
|
||||
*/
|
||||
activePlan() {
|
||||
if (this.activeSubscription) {
|
||||
return _.find(this.plans, (plan) => {
|
||||
return plan.id == this.activeSubscription.provider_plan;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Check if there's a limit for the number of teams.
|
||||
*/
|
||||
hasTeamLimit() {
|
||||
if (! this.activePlan) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !! this.activePlan.attributes.teams;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Get the remaining teams in the active plan.
|
||||
*/
|
||||
remainingTeams() {
|
||||
var ownedTeams = _.filter(this.$parent.teams, {owner_id: this.$parent.billable.id});
|
||||
|
||||
return this.activePlan
|
||||
? this.activePlan.attributes.teams - ownedTeams.length
|
||||
: 0;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Check if the user can create more teams.
|
||||
*/
|
||||
canCreateMoreTeams() {
|
||||
if (! this.hasTeamLimit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.remainingTeams > 0;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The component has been created by Vue.
|
||||
*/
|
||||
created() {
|
||||
this.getPlans();
|
||||
},
|
||||
|
||||
|
||||
events: {
|
||||
/**
|
||||
* Handle the "activatedTab" event.
|
||||
*/
|
||||
activatedTab(tab) {
|
||||
if (tab === Spark.pluralTeamString) {
|
||||
Vue.nextTick(() => {
|
||||
$('#create-team-name').focus();
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
watch: {
|
||||
/**
|
||||
* Watch the team name for changes.
|
||||
*/
|
||||
'form.name': function (val, oldVal) {
|
||||
if (this.form.slug == '' ||
|
||||
this.form.slug == oldVal.toLowerCase().replace(/[\s\W-]+/g, '-')
|
||||
) {
|
||||
this.form.slug = val.toLowerCase().replace(/[\s\W-]+/g, '-');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Create a new team.
|
||||
*/
|
||||
create() {
|
||||
Spark.post('/settings/'+Spark.pluralTeamString, this.form)
|
||||
.then(() => {
|
||||
this.form.name = '';
|
||||
this.form.slug = '';
|
||||
|
||||
Bus.$emit('updateUser');
|
||||
Bus.$emit('updateTeams');
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get all the plans defined in the application.
|
||||
*/
|
||||
getPlans() {
|
||||
axios.get('/spark/plans')
|
||||
.then(response => {
|
||||
this.plans = response.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
85
spark/resources/assets/js/settings/teams/current-teams.js
vendored
Normal file
85
spark/resources/assets/js/settings/teams/current-teams.js
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
module.exports = {
|
||||
props: ['user', 'teams'],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
leavingTeam: null,
|
||||
deletingTeam: null,
|
||||
|
||||
leaveTeamForm: new SparkForm({}),
|
||||
deleteTeamForm: new SparkForm({})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Approve leaving the given team.
|
||||
*/
|
||||
approveLeavingTeam(team) {
|
||||
this.leavingTeam = team;
|
||||
|
||||
$('#modal-leave-team').modal('show');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Leave the given team.
|
||||
*/
|
||||
leaveTeam() {
|
||||
Spark.delete(this.urlForLeaving, this.leaveTeamForm)
|
||||
.then(() => {
|
||||
Bus.$emit('updateUser');
|
||||
Bus.$emit('updateTeams');
|
||||
|
||||
$('#modal-leave-team').modal('hide');
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Approve the deletion of the given team.
|
||||
*/
|
||||
approveTeamDelete(team) {
|
||||
this.deletingTeam = team;
|
||||
|
||||
$('#modal-delete-team').modal('show');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Delete the given team.
|
||||
*/
|
||||
deleteTeam() {
|
||||
Spark.delete(`/settings/${Spark.pluralTeamString}/${this.deletingTeam.id}`, this.deleteTeamForm)
|
||||
.then(() => {
|
||||
Bus.$emit('updateUser');
|
||||
Bus.$emit('updateTeams');
|
||||
|
||||
$('#modal-delete-team').modal('hide');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the URL for leaving a team.
|
||||
*/
|
||||
urlForLeaving() {
|
||||
return `/settings/${Spark.pluralTeamString}/${this.leavingTeam.id}/members/${this.user.id}`;
|
||||
}
|
||||
}
|
||||
};
|
16
spark/resources/assets/js/settings/teams/mailed-invitations.js
vendored
Normal file
16
spark/resources/assets/js/settings/teams/mailed-invitations.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
module.exports = {
|
||||
props: ['team', 'invitations'],
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Cancel the sent invitation.
|
||||
*/
|
||||
cancel(invitation) {
|
||||
axios.delete(`/settings/invitations/${invitation.id}`)
|
||||
.then(() => {
|
||||
this.$parent.$emit('updateInvitations');
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
67
spark/resources/assets/js/settings/teams/pending-invitations.js
vendored
Normal file
67
spark/resources/assets/js/settings/teams/pending-invitations.js
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
invitations: []
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The component has been created by Vue.
|
||||
*/
|
||||
created() {
|
||||
this.getPendingInvitations();
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Get the pending invitations for the user.
|
||||
*/
|
||||
getPendingInvitations() {
|
||||
axios.get('/settings/invitations/pending')
|
||||
.then(response => {
|
||||
this.invitations = response.data;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Accept the given invitation.
|
||||
*/
|
||||
accept(invitation) {
|
||||
axios.post(`/settings/invitations/${invitation.id}/accept`)
|
||||
.then(() => {
|
||||
Bus.$emit('updateTeams');
|
||||
|
||||
this.getPendingInvitations();
|
||||
});
|
||||
|
||||
this.removeInvitation(invitation);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Reject the given invitation.
|
||||
*/
|
||||
reject(invitation) {
|
||||
axios.post(`/settings/invitations/${invitation.id}/reject`)
|
||||
.then(() => {
|
||||
this.getPendingInvitations();
|
||||
});
|
||||
|
||||
this.removeInvitation(invitation);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Remove the given invitation from the list.
|
||||
*/
|
||||
removeInvitation(invitation) {
|
||||
this.invitations = _.reject(this.invitations, i => i.id === invitation.id);
|
||||
}
|
||||
}
|
||||
};
|
116
spark/resources/assets/js/settings/teams/send-invitation.js
vendored
Normal file
116
spark/resources/assets/js/settings/teams/send-invitation.js
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
plans: [],
|
||||
|
||||
form: new SparkForm({
|
||||
email: ''
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the active subscription instance.
|
||||
*/
|
||||
activeSubscription() {
|
||||
if ( ! this.billable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const subscription = _.find(
|
||||
this.billable.subscriptions,
|
||||
subscription => subscription.name == 'default'
|
||||
);
|
||||
|
||||
if (typeof subscription !== 'undefined') {
|
||||
return subscription;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the active plan instance.
|
||||
*/
|
||||
activePlan() {
|
||||
if (this.activeSubscription) {
|
||||
return _.find(this.plans, (plan) => {
|
||||
return plan.id == this.activeSubscription.provider_plan;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Check if there's a limit for the number of team members.
|
||||
*/
|
||||
hasTeamMembersLimit() {
|
||||
if (! this.activePlan) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !! this.activePlan.attributes.teamMembers;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Get the remaining team members in the active plan.
|
||||
*/
|
||||
remainingTeamMembers() {
|
||||
return this.activePlan
|
||||
? this.activePlan.attributes.teamMembers - this.$parent.team.users.length
|
||||
: 0;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Check if the user can invite more team members.
|
||||
*/
|
||||
canInviteMoreTeamMembers() {
|
||||
if (! this.hasTeamMembersLimit) {
|
||||
return true;
|
||||
}
|
||||
return this.remainingTeamMembers > 0;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The component has been created by Vue.
|
||||
*/
|
||||
created() {
|
||||
this.getPlans();
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Send a team invitation.
|
||||
*/
|
||||
send() {
|
||||
Spark.post(`/settings/${Spark.pluralTeamString}/${this.team.id}/invitations`, this.form)
|
||||
.then(() => {
|
||||
this.form.email = '';
|
||||
|
||||
this.$parent.$emit('updateInvitations');
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all the plans defined in the application.
|
||||
*/
|
||||
getPlans() {
|
||||
axios.get('/spark/plans')
|
||||
.then(response => {
|
||||
this.plans = response.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
144
spark/resources/assets/js/settings/teams/team-members.js
vendored
Normal file
144
spark/resources/assets/js/settings/teams/team-members.js
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team'],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
roles: [],
|
||||
|
||||
updatingTeamMember: null,
|
||||
deletingTeamMember: null,
|
||||
|
||||
updateTeamMemberForm: $.extend(true, new SparkForm({
|
||||
role: ''
|
||||
}), Spark.forms.updateTeamMember),
|
||||
|
||||
deleteTeamMemberForm: new SparkForm({})
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The component has been created by Vue.
|
||||
*/
|
||||
created() {
|
||||
this.getRoles();
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Get the available team member roles.
|
||||
*/
|
||||
getRoles() {
|
||||
axios.get(`/settings/${Spark.pluralTeamString}/roles`)
|
||||
.then(response => {
|
||||
this.roles = response.data;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Edit the given team member.
|
||||
*/
|
||||
editTeamMember(member) {
|
||||
this.updatingTeamMember = member;
|
||||
this.updateTeamMemberForm.role = member.pivot.role;
|
||||
|
||||
$('#modal-update-team-member').modal('show');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Update the team member.
|
||||
*/
|
||||
update() {
|
||||
Spark.put(this.urlForUpdating, this.updateTeamMemberForm)
|
||||
.then(() => {
|
||||
Bus.$emit('updateTeam');
|
||||
|
||||
$('#modal-update-team-member').modal('hide');
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Display the approval modal for the deletion of a team member.
|
||||
*/
|
||||
approveTeamMemberDelete(member) {
|
||||
this.deletingTeamMember = member;
|
||||
|
||||
$('#modal-delete-member').modal('show');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Delete the given team member.
|
||||
*/
|
||||
deleteMember() {
|
||||
Spark.delete(this.urlForDeleting, this.deleteTeamMemberForm)
|
||||
.then(() => {
|
||||
Bus.$emit('updateTeam');
|
||||
|
||||
$('#modal-delete-member').modal('hide');
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the current user can edit a team member.
|
||||
*/
|
||||
canEditTeamMember(member) {
|
||||
return this.user.id === this.team.owner_id && this.user.id !== member.id
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the current user can delete a team member.
|
||||
*/
|
||||
canDeleteTeamMember(member) {
|
||||
return this.user.id === this.team.owner_id && this.user.id !== member.id
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the displayable role for the given team member.
|
||||
*/
|
||||
teamMemberRole(member) {
|
||||
if (this.roles.length == 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (member.pivot.role == 'owner') {
|
||||
return 'Owner';
|
||||
}
|
||||
|
||||
const role = _.find(this.roles, role => role.value == member.pivot.role);
|
||||
|
||||
if (typeof role !== 'undefined') {
|
||||
return role.text;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the URL for updating a team member.
|
||||
*/
|
||||
urlForUpdating: function () {
|
||||
return `/settings/${Spark.pluralTeamString}/${this.team.id}/members/${this.updatingTeamMember.id}`;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Get the URL for deleting a team member.
|
||||
*/
|
||||
urlForDeleting() {
|
||||
return `/settings/${Spark.pluralTeamString}/${this.team.id}/members/${this.deletingTeamMember.id}`;
|
||||
}
|
||||
}
|
||||
};
|
39
spark/resources/assets/js/settings/teams/team-membership.js
vendored
Normal file
39
spark/resources/assets/js/settings/teams/team-membership.js
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team', 'billableType'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
invitations: []
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The component has been created by Vue.
|
||||
*/
|
||||
created() {
|
||||
var self = this;
|
||||
|
||||
this.getInvitations();
|
||||
|
||||
this.$on('updateInvitations', function () {
|
||||
self.getInvitations();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Get all of the invitations for the team.
|
||||
*/
|
||||
getInvitations() {
|
||||
axios.get(`/settings/${Spark.pluralTeamString}/${this.team.id}/invitations`)
|
||||
.then(response => {
|
||||
this.invitations = response.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
3
spark/resources/assets/js/settings/teams/team-profile.js
vendored
Normal file
3
spark/resources/assets/js/settings/teams/team-profile.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team']
|
||||
};
|
55
spark/resources/assets/js/settings/teams/team-settings.js
vendored
Normal file
55
spark/resources/assets/js/settings/teams/team-settings.js
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
module.exports = {
|
||||
props: ['user', 'teamId'],
|
||||
|
||||
|
||||
/**
|
||||
* Load mixins for the component.
|
||||
*/
|
||||
mixins: [require('./../../mixins/tab-state')],
|
||||
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
billableType: 'team',
|
||||
team: null
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The component has been created by Vue.
|
||||
*/
|
||||
created() {
|
||||
var self = this;
|
||||
|
||||
this.getTeam();
|
||||
|
||||
Bus.$on('updateTeam', function () {
|
||||
self.getTeam();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.usePushStateForTabs('.spark-settings-tabs');
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Get the team being managed.
|
||||
*/
|
||||
getTeam() {
|
||||
axios.get(`/${Spark.pluralTeamString}/${this.teamId}`)
|
||||
.then(response => {
|
||||
this.team = response.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
36
spark/resources/assets/js/settings/teams/update-team-name.js
vendored
Normal file
36
spark/resources/assets/js/settings/teams/update-team-name.js
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({
|
||||
name: ''
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Prepare the component.
|
||||
*/
|
||||
mounted() {
|
||||
this.form.name = this.team.name;
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Update the team name.
|
||||
*/
|
||||
update() {
|
||||
Spark.put(`/settings/${Spark.pluralTeamString}/${this.team.id}/name`, this.form)
|
||||
.then(() => {
|
||||
Bus.$emit('updateTeam');
|
||||
Bus.$emit('updateTeams');
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
76
spark/resources/assets/js/settings/teams/update-team-photo.js
vendored
Normal file
76
spark/resources/assets/js/settings/teams/update-team-photo.js
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
module.exports = {
|
||||
props: ['user', 'team'],
|
||||
|
||||
/**
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
form: new SparkForm({})
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Update the team's photo.
|
||||
*/
|
||||
update(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if ( ! this.$refs.photo.files.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
this.form.startProcessing();
|
||||
|
||||
// We need to gather a fresh FormData instance with the profile photo appended to
|
||||
// the data so we can POST it up to the server. This will allow us to do async
|
||||
// uploads of the profile photos. We will update the user after this action.
|
||||
axios.post(this.urlForUpdate, this.gatherFormData())
|
||||
.then(
|
||||
() => {
|
||||
Bus.$emit('updateTeam');
|
||||
Bus.$emit('updateTeams');
|
||||
|
||||
self.form.finishProcessing();
|
||||
},
|
||||
(error) => {
|
||||
self.form.setErrors(error.response.data.errors);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Gather the form data for the photo upload.
|
||||
*/
|
||||
gatherFormData() {
|
||||
const data = new FormData();
|
||||
|
||||
data.append('photo', this.$refs.photo.files[0]);
|
||||
|
||||
return data;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Get the URL for updating the team photo.
|
||||
*/
|
||||
urlForUpdate() {
|
||||
return `/settings/${Spark.pluralTeamString}/${this.team.id}/photo`;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the style attribute for the photo preview.
|
||||
*/
|
||||
previewStyle() {
|
||||
return `background-image: url(${this.team.photo_url})`;
|
||||
}
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user