├── .gitignore ├── changes.md ├── composer.json ├── composer.lock ├── install-stubs ├── .env ├── app │ ├── Http │ │ ├── Controllers │ │ │ ├── HomeController.php │ │ │ └── WelcomeController.php │ │ ├── Kernel.php │ │ └── Middleware │ │ │ └── RedirectIfAuthenticated.php │ ├── Models │ │ ├── Team.php │ │ ├── TeamUser.php │ │ └── User.php │ └── Providers │ │ ├── EventServiceProvider.php │ │ ├── RouteServiceProvider.php │ │ ├── SparkServiceProvider.php │ │ └── SparkTeamBillingServiceProvider.php ├── config │ └── auth.php ├── database │ └── migrations │ │ ├── create_announcements_table.php │ │ ├── create_api_tokens_table.php │ │ ├── create_invitations_table.php │ │ ├── create_invoices_table.php │ │ ├── create_notifications_table.php │ │ ├── create_password_resets_table.php │ │ ├── create_performance_indicators_table.php │ │ ├── create_spark_subscriptions_table.php │ │ ├── create_tax_rates_table.php │ │ ├── create_team_users_table.php │ │ ├── create_teams_table.php │ │ └── create_users_table.php ├── package.json ├── public │ ├── favicon.ico │ ├── favicon.png │ └── img │ │ ├── color-48px.png │ │ ├── color-logo.png │ │ ├── create-team.svg │ │ ├── mono-48px.png │ │ ├── mono-logo.png │ │ └── spark-bg.png ├── resources │ ├── js │ │ ├── app.js │ │ ├── components │ │ │ ├── bootstrap.js │ │ │ └── home.js │ │ └── spark-components │ │ │ ├── auth │ │ │ └── register-stripe.js │ │ │ ├── bootstrap.js │ │ │ ├── kiosk │ │ │ ├── add-discount.js │ │ │ ├── announcements.js │ │ │ ├── kiosk.js │ │ │ ├── metrics.js │ │ │ ├── profile.js │ │ │ └── users.js │ │ │ ├── navbar │ │ │ └── navbar.js │ │ │ ├── notifications │ │ │ └── notifications.js │ │ │ └── settings │ │ │ ├── api.js │ │ │ ├── api │ │ │ ├── create-token.js │ │ │ └── tokens.js │ │ │ ├── invoices.js │ │ │ ├── invoices │ │ │ ├── invoice-list.js │ │ │ └── update-extra-billing-information.js │ │ │ ├── payment-method-stripe.js │ │ │ ├── payment-method │ │ │ ├── redeem-coupon.js │ │ │ ├── update-payment-method-stripe.js │ │ │ └── update-vat-id.js │ │ │ ├── profile.js │ │ │ ├── profile │ │ │ ├── update-contact-information.js │ │ │ └── update-profile-photo.js │ │ │ ├── security.js │ │ │ ├── security │ │ │ ├── disable-two-factor-auth.js │ │ │ ├── enable-two-factor-auth.js │ │ │ └── update-password.js │ │ │ ├── settings.js │ │ │ ├── subscription.js │ │ │ ├── subscription │ │ │ ├── cancel-subscription.js │ │ │ ├── resume-subscription.js │ │ │ ├── subscribe-stripe.js │ │ │ └── update-subscription.js │ │ │ ├── teams.js │ │ │ └── teams │ │ │ ├── create-team.js │ │ │ ├── current-teams.js │ │ │ ├── mailed-invitations.js │ │ │ ├── pending-invitations.js │ │ │ ├── send-invitation.js │ │ │ ├── team-members.js │ │ │ ├── team-membership.js │ │ │ ├── team-profile.js │ │ │ ├── team-settings.js │ │ │ ├── update-team-name.js │ │ │ └── update-team-photo.js │ ├── lang │ │ ├── ar.json │ │ ├── ar │ │ │ ├── teams.php │ │ │ └── validation.php │ │ ├── da.json │ │ ├── da │ │ │ ├── auth.php │ │ │ ├── pagination.php │ │ │ ├── passwords.php │ │ │ ├── teams.php │ │ │ └── validation.php │ │ ├── de.json │ │ ├── de │ │ │ ├── teams.php │ │ │ └── validation.php │ │ ├── en.json │ │ ├── en │ │ │ ├── teams.php │ │ │ └── validation.php │ │ ├── es.json │ │ ├── es │ │ │ ├── teams.php │ │ │ └── validation.php │ │ ├── fr.json │ │ └── fr │ │ │ ├── auth.php │ │ │ ├── pagination.php │ │ │ ├── passwords.php │ │ │ ├── teams.php │ │ │ └── validation.php │ ├── sass │ │ ├── app-rtl.scss │ │ └── app.scss │ └── views │ │ ├── home.blade.php │ │ └── welcome.blade.php ├── routes │ ├── api.php │ ├── console.php │ └── web.php ├── terms.md ├── webpack.mix.js └── yarn.lock ├── package-lock.json ├── package.json ├── readme.md ├── resources ├── assets │ ├── js │ │ ├── auth │ │ │ └── register-stripe.js │ │ ├── filters.js │ │ ├── forms │ │ │ ├── bootstrap.js │ │ │ ├── errors.js │ │ │ ├── form.js │ │ │ └── http.js │ │ ├── kiosk │ │ │ ├── add-discount.js │ │ │ ├── announcements.js │ │ │ ├── kiosk.js │ │ │ ├── metrics.js │ │ │ ├── profile.js │ │ │ └── users.js │ │ ├── mixin.js │ │ ├── mixins │ │ │ ├── discounts.js │ │ │ ├── plans.js │ │ │ ├── register.js │ │ │ ├── stripe.js │ │ │ ├── subscriptions.js │ │ │ ├── tab-state.js │ │ │ └── vat.js │ │ ├── navbar │ │ │ └── navbar.js │ │ ├── notifications │ │ │ └── notifications.js │ │ ├── settings │ │ │ ├── api.js │ │ │ ├── api │ │ │ │ ├── create-token.js │ │ │ │ └── tokens.js │ │ │ ├── invoices.js │ │ │ ├── invoices │ │ │ │ ├── invoice-list.js │ │ │ │ └── update-extra-billing-information.js │ │ │ ├── payment-method-stripe.js │ │ │ ├── payment-method │ │ │ │ ├── redeem-coupon.js │ │ │ │ ├── update-payment-method-stripe.js │ │ │ │ └── update-vat-id.js │ │ │ ├── profile.js │ │ │ ├── profile │ │ │ │ ├── update-contact-information.js │ │ │ │ └── update-profile-photo.js │ │ │ ├── security.js │ │ │ ├── security │ │ │ │ ├── disable-two-factor-auth.js │ │ │ │ ├── enable-two-factor-auth.js │ │ │ │ └── update-password.js │ │ │ ├── settings.js │ │ │ ├── subscription.js │ │ │ ├── subscription │ │ │ │ ├── cancel-subscription.js │ │ │ │ ├── resume-subscription.js │ │ │ │ ├── subscribe-stripe.js │ │ │ │ └── update-subscription.js │ │ │ ├── teams.js │ │ │ └── teams │ │ │ │ ├── create-team.js │ │ │ │ ├── current-teams.js │ │ │ │ ├── mailed-invitations.js │ │ │ │ ├── pending-invitations.js │ │ │ │ ├── send-invitation.js │ │ │ │ ├── team-members.js │ │ │ │ ├── team-membership.js │ │ │ │ ├── team-profile.js │ │ │ │ ├── team-settings.js │ │ │ │ ├── update-team-name.js │ │ │ │ └── update-team-photo.js │ │ ├── spark-bootstrap.js │ │ ├── spark.js │ │ └── vue-bootstrap.js │ └── sass │ │ ├── _custom.scss │ │ ├── _variables.scss │ │ ├── components │ │ ├── _buttons.scss │ │ ├── _cards.scss │ │ ├── _dropdown.scss │ │ ├── _metrics.scss │ │ ├── _modals.scss │ │ ├── _navbar.scss │ │ ├── _notifications.scss │ │ ├── _team-member-list.scss │ │ └── _uploader.scss │ │ ├── elements │ │ ├── _forms.scss │ │ ├── _icons.scss │ │ ├── _tables.scss │ │ ├── _text.scss │ │ └── _utilities.scss │ │ ├── img │ │ ├── radio-select-default.svg │ │ └── radio-select-is-selected.svg │ │ └── spark.scss └── views │ ├── auth │ ├── emails │ │ └── password.blade.php │ ├── login-via-emergency-token.blade.php │ ├── login.blade.php │ ├── passwords │ │ ├── email.blade.php │ │ └── reset.blade.php │ ├── register-address.blade.php │ ├── register-common-form.blade.php │ ├── register-common.blade.php │ ├── register.blade.php │ ├── token.blade.php │ └── verify.blade.php │ ├── kiosk.blade.php │ ├── kiosk │ ├── announcements.blade.php │ ├── metrics.blade.php │ ├── modals │ │ └── add-discount.blade.php │ ├── profile.blade.php │ └── users.blade.php │ ├── layouts │ ├── app.blade.php │ └── blade │ │ └── app.blade.php │ ├── missing-team.blade.php │ ├── modals │ ├── notifications.blade.php │ ├── plan-details.blade.php │ ├── session-expired.blade.php │ └── support.blade.php │ ├── nav │ ├── blade │ │ ├── teams.blade.php │ │ └── user.blade.php │ ├── brand.blade.php │ ├── developer.blade.php │ ├── guest.blade.php │ ├── subscriptions.blade.php │ ├── support.blade.php │ ├── teams.blade.php │ ├── user-left.blade.php │ └── user.blade.php │ ├── settings.blade.php │ ├── settings │ ├── api.blade.php │ ├── api │ │ ├── create-token.blade.php │ │ └── tokens.blade.php │ ├── invoices.blade.php │ ├── invoices │ │ ├── emails │ │ │ └── invoice.blade.php │ │ ├── invoice-list.blade.php │ │ └── update-extra-billing-information.blade.php │ ├── payment-method.blade.php │ ├── payment-method │ │ ├── redeem-coupon.blade.php │ │ ├── update-payment-method-address.blade.php │ │ ├── update-payment-method-stripe.blade.php │ │ └── update-vat-id.blade.php │ ├── profile.blade.php │ ├── profile │ │ ├── update-contact-information.blade.php │ │ └── update-profile-photo.blade.php │ ├── security.blade.php │ ├── security │ │ ├── disable-two-factor-auth.blade.php │ │ ├── enable-two-factor-auth.blade.php │ │ ├── modals │ │ │ └── two-factor-reset-code.blade.php │ │ └── update-password.blade.php │ ├── subscription.blade.php │ ├── subscription │ │ ├── cancel-subscription.blade.php │ │ ├── resume-subscription.blade.php │ │ ├── subscribe-address.blade.php │ │ ├── subscribe-common.blade.php │ │ ├── subscribe.blade.php │ │ ├── subscription-notice.blade.php │ │ └── update-subscription.blade.php │ ├── teams.blade.php │ └── teams │ │ ├── create-team.blade.php │ │ ├── current-teams.blade.php │ │ ├── emails │ │ ├── invitation-to-existing-user.blade.php │ │ └── invitation-to-new-user.blade.php │ │ ├── mailed-invitations.blade.php │ │ ├── pending-invitations.blade.php │ │ ├── send-invitation.blade.php │ │ ├── team-members.blade.php │ │ ├── team-membership.blade.php │ │ ├── team-profile.blade.php │ │ ├── team-settings.blade.php │ │ ├── update-team-name.blade.php │ │ └── update-team-photo.blade.php │ ├── shared │ └── errors.blade.php │ └── terms.blade.php ├── src ├── Announcement.php ├── Billable.php ├── CanJoinTeams.php ├── Configuration │ ├── CallsInteractions.php │ ├── ManagesApiOptions.php │ ├── ManagesAppDetails.php │ ├── ManagesAppOptions.php │ ├── ManagesAvailablePlans.php │ ├── ManagesAvailableRoles.php │ ├── ManagesBillingProviders.php │ ├── ManagesModelOptions.php │ ├── ManagesSupportOptions.php │ ├── ManagesTwoFactorOptions.php │ └── ProvidesScriptVariables.php ├── Console │ ├── Commands │ │ ├── InstallCommand.php │ │ ├── StorePerformanceIndicatorsCommand.php │ │ ├── UpdateCommand.php │ │ ├── UpdateViewsCommand.php │ │ └── VersionCommand.php │ ├── Installation │ │ ├── InstallConfiguration.php │ │ ├── InstallEnvironment.php │ │ ├── InstallHttp.php │ │ ├── InstallImages.php │ │ ├── InstallMigrations.php │ │ ├── InstallModels.php │ │ ├── InstallProviders.php │ │ └── InstallResources.php │ └── Updating │ │ ├── DownloadRelease.php │ │ ├── RemoveDownloadPath.php │ │ ├── UpdateInstallation.php │ │ └── UpdateViews.php ├── Contracts │ ├── Http │ │ └── Requests │ │ │ ├── Auth │ │ │ └── RegisterRequest.php │ │ │ └── Settings │ │ │ ├── PaymentMethod │ │ │ └── UpdatePaymentMethodRequest.php │ │ │ ├── Subscription │ │ │ └── CreateSubscriptionRequest.php │ │ │ └── Teams │ │ │ └── Subscription │ │ │ └── CreateSubscriptionRequest.php │ ├── InitialFrontendState.php │ ├── Interactions │ │ ├── Auth │ │ │ ├── CreateUser.php │ │ │ └── Register.php │ │ ├── CheckPlanEligibility.php │ │ ├── CheckTeamPlanEligibility.php │ │ ├── Settings │ │ │ ├── PaymentMethod │ │ │ │ ├── RedeemCoupon.php │ │ │ │ └── UpdatePaymentMethod.php │ │ │ ├── Profile │ │ │ │ ├── UpdateContactInformation.php │ │ │ │ └── UpdateProfilePhoto.php │ │ │ ├── Security │ │ │ │ ├── DisableTwoFactorAuth.php │ │ │ │ ├── EnableTwoFactorAuth.php │ │ │ │ └── VerifyTwoFactorAuthToken.php │ │ │ └── Teams │ │ │ │ ├── AddTeamMember.php │ │ │ │ ├── CreateTeam.php │ │ │ │ ├── SendInvitation.php │ │ │ │ ├── UpdateTeamMember.php │ │ │ │ └── UpdateTeamPhoto.php │ │ ├── Subscribe.php │ │ ├── SubscribeTeam.php │ │ └── Support │ │ │ └── SendSupportEmail.php │ └── Repositories │ │ ├── AnnouncementRepository.php │ │ ├── CouponRepository.php │ │ ├── Geography │ │ ├── CountryRepository.php │ │ └── StateRepository.php │ │ ├── LocalInvoiceRepository.php │ │ ├── NotificationRepository.php │ │ ├── PerformanceIndicatorsRepository.php │ │ ├── TeamRepository.php │ │ ├── TokenRepository.php │ │ └── UserRepository.php ├── Coupon.php ├── Events │ ├── AnnouncementCreated.php │ ├── Auth │ │ └── UserRegistered.php │ ├── Kiosk │ │ └── AnnouncementCreated.php │ ├── NotificationCreated.php │ ├── PaymentMethod │ │ ├── BillingAddressUpdated.php │ │ └── VatIdUpdated.php │ ├── Profile │ │ └── ContactInformationUpdated.php │ ├── Subscription │ │ ├── SubscriptionCancelled.php │ │ ├── SubscriptionUpdated.php │ │ └── UserSubscribed.php │ └── Teams │ │ ├── DeletingTeam.php │ │ ├── GuestInvitedToTeam.php │ │ ├── Subscription │ │ ├── SubscriptionCancelled.php │ │ ├── SubscriptionUpdated.php │ │ └── TeamSubscribed.php │ │ ├── TeamCreated.php │ │ ├── TeamDeleted.php │ │ ├── TeamMemberAdded.php │ │ ├── TeamMemberRemoved.php │ │ ├── TeamOwnerAdded.php │ │ └── UserInvitedToTeam.php ├── Exceptions │ └── IneligibleForPlan.php ├── HasApiTokens.php ├── Http │ ├── Controllers │ │ ├── Auth │ │ │ ├── EmergencyLoginController.php │ │ │ ├── LoginController.php │ │ │ ├── PasswordController.php │ │ │ ├── RegisterController.php │ │ │ └── VerificationController.php │ │ ├── Controller.php │ │ ├── CouponController.php │ │ ├── GeocodingController.php │ │ ├── InvitationController.php │ │ ├── Kiosk │ │ │ ├── AnnouncementController.php │ │ │ ├── DashboardController.php │ │ │ ├── DiscountController.php │ │ │ ├── ImpersonationController.php │ │ │ ├── PerformanceIndicatorsController.php │ │ │ ├── ProfileController.php │ │ │ └── SearchController.php │ │ ├── MissingTeamController.php │ │ ├── NotificationController.php │ │ ├── PlanController.php │ │ ├── Settings │ │ │ ├── API │ │ │ │ ├── TokenAbilitiesController.php │ │ │ │ └── TokenController.php │ │ │ ├── Billing │ │ │ │ ├── BillingInformationController.php │ │ │ │ ├── InvoiceController.php │ │ │ │ ├── SendsInvoiceNotifications.php │ │ │ │ └── StripeWebhookController.php │ │ │ ├── DashboardController.php │ │ │ ├── PaymentMethod │ │ │ │ ├── PaymentMethodController.php │ │ │ │ ├── RedeemCouponController.php │ │ │ │ └── VatIdController.php │ │ │ ├── Profile │ │ │ │ ├── ContactInformationController.php │ │ │ │ └── PhotoController.php │ │ │ ├── Security │ │ │ │ ├── PasswordController.php │ │ │ │ └── TwoFactorAuthController.php │ │ │ ├── Subscription │ │ │ │ └── PlanController.php │ │ │ └── Teams │ │ │ │ ├── Billing │ │ │ │ ├── BillingInformationController.php │ │ │ │ └── InvoiceController.php │ │ │ │ ├── DashboardController.php │ │ │ │ ├── MailedInvitationController.php │ │ │ │ ├── PaymentMethod │ │ │ │ ├── PaymentMethodController.php │ │ │ │ ├── RedeemCouponController.php │ │ │ │ └── VatIdController.php │ │ │ │ ├── PendingInvitationController.php │ │ │ │ ├── Subscription │ │ │ │ └── PlanController.php │ │ │ │ ├── TeamController.php │ │ │ │ ├── TeamMemberController.php │ │ │ │ ├── TeamMemberRoleController.php │ │ │ │ ├── TeamNameController.php │ │ │ │ └── TeamPhotoController.php │ │ ├── StripeTokenController.php │ │ ├── SupportController.php │ │ ├── TaxRateController.php │ │ ├── TeamController.php │ │ ├── TeamCouponController.php │ │ ├── TermsController.php │ │ ├── TokenController.php │ │ └── UserController.php │ ├── Middleware │ │ ├── CreateFreshApiToken.php │ │ ├── VerifyTeamIsSubscribed.php │ │ ├── VerifyUserHasTeam.php │ │ ├── VerifyUserIsDeveloper.php │ │ └── VerifyUserIsSubscribed.php │ ├── Requests │ │ ├── Auth │ │ │ ├── RegisterRequest.php │ │ │ └── StripeRegisterRequest.php │ │ ├── Settings │ │ │ ├── API │ │ │ │ ├── CreateTokenRequest.php │ │ │ │ ├── TokenRequest.php │ │ │ │ └── UpdateTokenRequest.php │ │ │ ├── PaymentMethod │ │ │ │ └── UpdateStripePaymentMethodRequest.php │ │ │ ├── Security │ │ │ │ └── EnableTwoFactorAuthRequest.php │ │ │ ├── Subscription │ │ │ │ ├── CreateStripeSubscriptionRequest.php │ │ │ │ ├── CreateSubscriptionRequest.php │ │ │ │ ├── DeterminesPlanEligibility.php │ │ │ │ └── UpdateSubscriptionRequest.php │ │ │ └── Teams │ │ │ │ ├── CreateInvitationRequest.php │ │ │ │ ├── RemoveTeamMemberRequest.php │ │ │ │ ├── Subscription │ │ │ │ ├── CreateStripeSubscriptionRequest.php │ │ │ │ ├── CreateSubscriptionRequest.php │ │ │ │ ├── DeterminesTeamPlanEligibility.php │ │ │ │ └── UpdateSubscriptionRequest.php │ │ │ │ └── UpdateTeamPhotoRequest.php │ │ └── ValidatesBillingAddresses.php │ └── routes.php ├── InitialFrontendState.php ├── Interactions │ ├── Auth │ │ ├── CreateUser.php │ │ └── Register.php │ ├── CheckPlanEligibility.php │ ├── CheckTeamPlanEligibility.php │ ├── Settings │ │ ├── PaymentMethod │ │ │ ├── RedeemStripeCoupon.php │ │ │ └── UpdateStripePaymentMethod.php │ │ ├── Profile │ │ │ ├── UpdateContactInformation.php │ │ │ └── UpdateProfilePhoto.php │ │ ├── Security │ │ │ ├── DisableTwoFactorAuthUsingAuthy.php │ │ │ ├── EnableTwoFactorAuthUsingAuthy.php │ │ │ └── VerifyTwoFactorAuthTokenUsingAuthy.php │ │ └── Teams │ │ │ ├── AddTeamMember.php │ │ │ ├── CreateTeam.php │ │ │ ├── SendInvitation.php │ │ │ ├── UpdateTeamMember.php │ │ │ └── UpdateTeamPhoto.php │ ├── SubscribeTeamUsingStripe.php │ ├── SubscribeUsingStripe.php │ └── Support │ │ └── SendSupportEmail.php ├── InteractsWithSparkApi.php ├── InteractsWithSparkConfiguration.php ├── Invitation.php ├── JWT.php ├── Listeners │ ├── Profile │ │ └── UpdateContactInformationOnStripe.php │ ├── Subscription │ │ ├── UpdateActiveSubscription.php │ │ ├── UpdateTaxPercentageOnStripe.php │ │ └── UpdateTrialEndingDate.php │ └── Teams │ │ ├── CreateInvitationNotification.php │ │ └── Subscription │ │ ├── UpdateActiveSubscription.php │ │ └── UpdateTrialEndingDate.php ├── LocalInvoice.php ├── Notification.php ├── Notifications │ ├── SparkChannel.php │ └── SparkNotification.php ├── Plan.php ├── Providers │ ├── AppServiceProvider.php │ └── SparkServiceProvider.php ├── Repositories │ ├── AnnouncementRepository.php │ ├── Geography │ │ ├── CountryRepository.php │ │ └── StateRepository.php │ ├── NotificationRepository.php │ ├── PassportTokenRepository.php │ ├── PerformanceIndicatorsRepository.php │ ├── StripeCouponRepository.php │ ├── StripeLocalInvoiceRepository.php │ ├── TeamRepository.php │ ├── TokenRepository.php │ └── UserRepository.php ├── Services │ ├── Security │ │ └── Authy.php │ └── Stripe.php ├── Spark.php ├── Subscription.php ├── TaxRate.php ├── Team.php ├── TeamPlan.php ├── TeamSubscription.php ├── TeamSubscriptionItem.php ├── Token.php ├── TokenGuard.php ├── User.php └── Validation │ ├── CountryValidator.php │ ├── StateValidator.php │ └── VatIdValidator.php └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /vendor 3 | .DS_Store 4 | Thumbs.db 5 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel/spark-aurelius", 3 | "description": "Laravel Spark provides scaffolding for Laravel SaaS applications.", 4 | "keywords": ["laravel", "stripe", "billing", "scaffolding", "saas"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Taylor Otwell", 9 | "email": "taylor@laravel.com" 10 | } 11 | ], 12 | "require": { 13 | "php": "^7.3|^8.0", 14 | "ext-json": "*", 15 | "ext-zip": "*", 16 | "erusev/parsedown": "~1.0", 17 | "firebase/php-jwt": "~4.0|~5.0", 18 | "intervention/image": "^2.3", 19 | "laravel/cashier": "^13.0" 20 | }, 21 | "require-dev": { 22 | "mpociot/vat-calculator": "^1.6" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "Laravel\\Spark\\": "src/" 27 | } 28 | }, 29 | "extra": { 30 | "branch-alias": { 31 | "dev-master": "12.x-dev" 32 | } 33 | }, 34 | "minimum-stability": "dev" 35 | } 36 | -------------------------------------------------------------------------------- /install-stubs/.env: -------------------------------------------------------------------------------- 1 | 2 | AUTHY_SECRET= 3 | 4 | CASHIER_CURRENCY=usd 5 | CASHIER_CURRENCY_LOCALE=en 6 | STRIPE_KEY= 7 | STRIPE_SECRET= -------------------------------------------------------------------------------- /install-stubs/app/Http/Controllers/HomeController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 17 | 18 | // $this->middleware('subscribed'); 19 | 20 | // $this->middleware('verified'); 21 | } 22 | 23 | /** 24 | * Show the application dashboard. 25 | * 26 | * @return Response 27 | */ 28 | public function show() 29 | { 30 | return view('home'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /install-stubs/app/Http/Controllers/WelcomeController.php: -------------------------------------------------------------------------------- 1 | check()) { 22 | return redirect(Spark::afterLoginRedirect()); 23 | } 24 | 25 | return $next($request); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /install-stubs/app/Models/Team.php: -------------------------------------------------------------------------------- 1 | 'datetime', 51 | 'uses_two_factor_auth' => 'boolean', 52 | ]; 53 | } 54 | -------------------------------------------------------------------------------- /install-stubs/app/Models/User.php: -------------------------------------------------------------------------------- 1 | 'datetime', 49 | 'uses_two_factor_auth' => 'boolean', 50 | ]; 51 | } 52 | -------------------------------------------------------------------------------- /install-stubs/database/migrations/create_announcements_table.php: -------------------------------------------------------------------------------- 1 | string('id')->primary(); 17 | $table->unsignedBigInteger('user_id'); 18 | $table->text('body'); 19 | $table->string('action_text')->nullable(); 20 | $table->text('action_url')->nullable(); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::drop('announcements'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /install-stubs/database/migrations/create_api_tokens_table.php: -------------------------------------------------------------------------------- 1 | string('id')->primary(); 17 | $table->unsignedBigInteger('user_id'); 18 | $table->string('name'); 19 | $table->string('token', 100)->unique(); 20 | $table->text('metadata'); 21 | $table->tinyInteger('transient')->default(0); 22 | $table->timestamp('last_used_at')->nullable(); 23 | $table->timestamp('expires_at')->nullable(); 24 | $table->timestamps(); 25 | 26 | $table->index(['user_id', 'expires_at']); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::drop('api_tokens'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /install-stubs/database/migrations/create_invitations_table.php: -------------------------------------------------------------------------------- 1 | string('id')->primary(); 17 | $table->unsignedBigInteger('team_id')->index(); 18 | $table->unsignedBigInteger('user_id')->nullable()->index(); 19 | $table->string('role')->nullable(); 20 | $table->string('email'); 21 | $table->string('token', 40)->unique(); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::drop('invitations'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /install-stubs/database/migrations/create_notifications_table.php: -------------------------------------------------------------------------------- 1 | string('id')->primary(); 17 | $table->unsignedBigInteger('user_id'); 18 | $table->unsignedBigInteger('created_by')->nullable(); 19 | $table->string('icon', 50)->nullable(); 20 | $table->text('body'); 21 | $table->string('action_text')->nullable(); 22 | $table->text('action_url')->nullable(); 23 | $table->tinyInteger('read')->default(0); 24 | $table->timestamps(); 25 | 26 | $table->index(['user_id', 'created_at']); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::drop('notifications'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /install-stubs/database/migrations/create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 17 | $table->string('token')->index(); 18 | $table->timestamp('created_at')->nullable(); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::drop('password_resets'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /install-stubs/database/migrations/create_performance_indicators_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 17 | $table->decimal('monthly_recurring_revenue'); 18 | $table->decimal('yearly_recurring_revenue'); 19 | $table->decimal('daily_volume'); 20 | $table->integer('new_users'); 21 | $table->timestamps(); 22 | 23 | $table->index('created_at'); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::drop('performance_indicators'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /install-stubs/database/migrations/create_tax_rates_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('stripe_id')->index(); 19 | $table->double('percentage')->index(); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('tax_rates'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /install-stubs/database/migrations/create_team_users_table.php: -------------------------------------------------------------------------------- 1 | unsignedBigInteger('team_id'); 17 | $table->unsignedBigInteger('user_id'); 18 | $table->string('role', 20); 19 | 20 | $table->unique(['team_id', 'user_id']); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('team_users'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /install-stubs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 5 | "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 7 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 8 | }, 9 | "dependencies": { 10 | "axios": "^0.18", 11 | "bootstrap": "^4.1.1", 12 | "cross-env": "^5.1", 13 | "dinero.js": "^1.6.0", 14 | "jquery": "^3.2", 15 | "laravel-mix": "^4.0.7", 16 | "lodash": "^4.17.4", 17 | "moment": "^2.10.6", 18 | "popper.js": "^1.12", 19 | "promise": "^7.1.1", 20 | "resolve-url-loader": "3.1.0", 21 | "rtlcss": "^2.2", 22 | "sass": "^1.22.5", 23 | "sass-loader": "7.*", 24 | "sweetalert2": "^8.13.6", 25 | "urijs": "^1.17.0", 26 | "vue": "2.*", 27 | "vue-template-compiler": "^2.6.10" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /install-stubs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel/spark-aurelius/9db0edc5fe1d067305797a46e9e45f116890d476/install-stubs/public/favicon.ico -------------------------------------------------------------------------------- /install-stubs/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel/spark-aurelius/9db0edc5fe1d067305797a46e9e45f116890d476/install-stubs/public/favicon.png -------------------------------------------------------------------------------- /install-stubs/public/img/color-48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel/spark-aurelius/9db0edc5fe1d067305797a46e9e45f116890d476/install-stubs/public/img/color-48px.png -------------------------------------------------------------------------------- /install-stubs/public/img/color-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel/spark-aurelius/9db0edc5fe1d067305797a46e9e45f116890d476/install-stubs/public/img/color-logo.png -------------------------------------------------------------------------------- /install-stubs/public/img/mono-48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel/spark-aurelius/9db0edc5fe1d067305797a46e9e45f116890d476/install-stubs/public/img/mono-48px.png -------------------------------------------------------------------------------- /install-stubs/public/img/mono-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel/spark-aurelius/9db0edc5fe1d067305797a46e9e45f116890d476/install-stubs/public/img/mono-logo.png -------------------------------------------------------------------------------- /install-stubs/public/img/spark-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel/spark-aurelius/9db0edc5fe1d067305797a46e9e45f116890d476/install-stubs/public/img/spark-bg.png -------------------------------------------------------------------------------- /install-stubs/resources/js/app.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | |-------------------------------------------------------------------------- 4 | | Laravel Spark Bootstrap 5 | |-------------------------------------------------------------------------- 6 | | 7 | | First, we will load all of the "core" dependencies for Spark which are 8 | | libraries such as Vue and jQuery. This also loads the Spark helpers 9 | | for things such as HTTP calls, forms, and form validation errors. 10 | | 11 | | Next, we'll create the root Vue application for Spark. This will start 12 | | the entire application and attach it to the DOM. Of course, you may 13 | | customize this script as you desire and load your own components. 14 | | 15 | */ 16 | 17 | require('spark-bootstrap'); 18 | 19 | require('./components/bootstrap'); 20 | 21 | var app = new Vue({ 22 | mixins: [require('spark')] 23 | }); 24 | -------------------------------------------------------------------------------- /install-stubs/resources/js/components/bootstrap.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | |-------------------------------------------------------------------------- 4 | | Laravel Spark Components 5 | |-------------------------------------------------------------------------- 6 | | 7 | | Here we will load the Spark components which makes up the core client 8 | | application. This is also a convenient spot for you to load all of 9 | | your components that you write while building your applications. 10 | */ 11 | 12 | require('./../spark-components/bootstrap'); 13 | 14 | require('./home'); 15 | -------------------------------------------------------------------------------- /install-stubs/resources/js/components/home.js: -------------------------------------------------------------------------------- 1 | Vue.component('home', { 2 | props: ['user'], 3 | 4 | mounted() { 5 | // 6 | } 7 | }); 8 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/auth/register-stripe.js: -------------------------------------------------------------------------------- 1 | var base = require('auth/register-stripe'); 2 | 3 | Vue.component('spark-register-stripe', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/kiosk/add-discount.js: -------------------------------------------------------------------------------- 1 | var base = require('kiosk/add-discount'); 2 | 3 | Vue.component('spark-kiosk-add-discount', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/kiosk/announcements.js: -------------------------------------------------------------------------------- 1 | var base = require('kiosk/announcements'); 2 | 3 | Vue.component('spark-kiosk-announcements', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/kiosk/kiosk.js: -------------------------------------------------------------------------------- 1 | var base = require('kiosk/kiosk'); 2 | 3 | Vue.component('spark-kiosk', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/kiosk/metrics.js: -------------------------------------------------------------------------------- 1 | var base = require('kiosk/metrics'); 2 | 3 | Vue.component('spark-kiosk-metrics', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/kiosk/profile.js: -------------------------------------------------------------------------------- 1 | var base = require('kiosk/profile'); 2 | 3 | Vue.component('spark-kiosk-profile', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/kiosk/users.js: -------------------------------------------------------------------------------- 1 | var base = require('kiosk/users'); 2 | 3 | Vue.component('spark-kiosk-users', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/navbar/navbar.js: -------------------------------------------------------------------------------- 1 | var base = require('navbar/navbar'); 2 | 3 | Vue.component('spark-navbar', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/notifications/notifications.js: -------------------------------------------------------------------------------- 1 | var base = require('notifications/notifications'); 2 | 3 | Vue.component('spark-notifications', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/api.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/api'); 2 | 3 | Vue.component('spark-api', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/api/create-token.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/api/create-token'); 2 | 3 | Vue.component('spark-create-token', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/api/tokens.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/api/tokens'); 2 | 3 | Vue.component('spark-tokens', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/invoices.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/invoices'); 2 | 3 | Vue.component('spark-invoices', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/invoices/invoice-list.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/invoices/invoice-list'); 2 | 3 | Vue.component('spark-invoice-list', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/invoices/update-extra-billing-information.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/invoices/update-extra-billing-information'); 2 | 3 | Vue.component('spark-update-extra-billing-information', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/payment-method-stripe.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/payment-method-stripe'); 2 | 3 | Vue.component('spark-payment-method-stripe', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/payment-method/redeem-coupon.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/payment-method/redeem-coupon'); 2 | 3 | Vue.component('spark-redeem-coupon', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/payment-method/update-payment-method-stripe.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/payment-method/update-payment-method-stripe'); 2 | 3 | Vue.component('spark-update-payment-method-stripe', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/payment-method/update-vat-id.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/payment-method/update-vat-id'); 2 | 3 | Vue.component('spark-update-vat-id', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/profile.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/profile'); 2 | 3 | Vue.component('spark-profile', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/profile/update-contact-information.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/profile/update-contact-information'); 2 | 3 | Vue.component('spark-update-contact-information', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/profile/update-profile-photo.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/profile/update-profile-photo'); 2 | 3 | Vue.component('spark-update-profile-photo', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/security.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/security'); 2 | 3 | Vue.component('spark-security', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/security/disable-two-factor-auth.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/security/disable-two-factor-auth'); 2 | 3 | Vue.component('spark-disable-two-factor-auth', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/security/enable-two-factor-auth.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/security/enable-two-factor-auth'); 2 | 3 | Vue.component('spark-enable-two-factor-auth', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/security/update-password.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/security/update-password'); 2 | 3 | Vue.component('spark-update-password', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/settings.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/settings'); 2 | 3 | Vue.component('spark-settings', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/subscription.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/subscription'); 2 | 3 | Vue.component('spark-subscription', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/subscription/cancel-subscription.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/subscription/cancel-subscription'); 2 | 3 | Vue.component('spark-cancel-subscription', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/subscription/resume-subscription.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/subscription/resume-subscription'); 2 | 3 | Vue.component('spark-resume-subscription', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/subscription/subscribe-stripe.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/subscription/subscribe-stripe'); 2 | 3 | Vue.component('spark-subscribe-stripe', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/subscription/update-subscription.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/subscription/update-subscription'); 2 | 3 | Vue.component('spark-update-subscription', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams'); 2 | 3 | Vue.component('spark-teams', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams/create-team.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams/create-team'); 2 | 3 | Vue.component('spark-create-team', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams/current-teams.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams/current-teams'); 2 | 3 | Vue.component('spark-current-teams', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams/mailed-invitations.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams/mailed-invitations'); 2 | 3 | Vue.component('spark-mailed-invitations', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams/pending-invitations.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams/pending-invitations'); 2 | 3 | Vue.component('spark-pending-invitations', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams/send-invitation.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams/send-invitation'); 2 | 3 | Vue.component('spark-send-invitation', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams/team-members.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams/team-members'); 2 | 3 | Vue.component('spark-team-members', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams/team-membership.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams/team-membership'); 2 | 3 | Vue.component('spark-team-membership', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams/team-profile.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams/team-profile'); 2 | 3 | Vue.component('spark-team-profile', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams/team-settings.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams/team-settings'); 2 | 3 | Vue.component('spark-team-settings', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams/update-team-name.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams/update-team-name'); 2 | 3 | Vue.component('spark-update-team-name', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/js/spark-components/settings/teams/update-team-photo.js: -------------------------------------------------------------------------------- 1 | var base = require('settings/teams/update-team-photo'); 2 | 3 | Vue.component('spark-update-team-photo', { 4 | mixins: [base] 5 | }); 6 | -------------------------------------------------------------------------------- /install-stubs/resources/lang/da/auth.php: -------------------------------------------------------------------------------- 1 | 'De angivne oplysninger er ugyldige.', 17 | 'throttle' => 'For mange loginforsøg. Prøv igen om :seconds sekunder.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /install-stubs/resources/lang/da/pagination.php: -------------------------------------------------------------------------------- 1 | '« Forrige', 17 | 'next' => 'Næste »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /install-stubs/resources/lang/da/passwords.php: -------------------------------------------------------------------------------- 1 | 'Adgangskode skal minimum være 6 tegn og skal være tastet ens i begge felter.', 17 | 'reset' => 'Adgangskoden er blevet nulstillet!', 18 | 'sent' => 'Vi har sendt dig en e-mail til at nulstille din adgangskode!', 19 | 'token' => 'Koden til nulstilling af adgangskoden er ugyldig.', 20 | 'user' => 'Vi kan ikke finde en bruger med den e-mailadresse.', 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /install-stubs/resources/lang/fr/auth.php: -------------------------------------------------------------------------------- 1 | 'Ces identifiants ne correspondent pas à nos enregistrements.', 17 | 'throttle' => 'Trop de tentatives de connexion. Veuillez réessayer dans :seconds secondes.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /install-stubs/resources/lang/fr/pagination.php: -------------------------------------------------------------------------------- 1 | '« Précédent', 17 | 'next' => 'Suivant »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /install-stubs/resources/lang/fr/passwords.php: -------------------------------------------------------------------------------- 1 | 'Votre mot de passe doit contenir au moins six caractères et correspondre à la confirmation.', 18 | 'reset' => 'Votre mot de passe a été réinitialisé!', 19 | 'sent' => 'Nous vous avons envoyé un e-mail contenant un lien de réinitialisation de votre mot de passe!', 20 | 'token' => 'Ce jeton de réinitialisation de mot de passe est invalide.', 21 | 'user' => "Nous n'avons aucun utilisateur correspondant à cet adresse e-mail.", 22 | 23 | ]; 24 | -------------------------------------------------------------------------------- /install-stubs/resources/sass/app-rtl.scss: -------------------------------------------------------------------------------- 1 | @import "app"; 2 | -------------------------------------------------------------------------------- /install-stubs/resources/sass/app.scss: -------------------------------------------------------------------------------- 1 | // @import "./spark/spark"; 2 | @import "./../../vendor/laravel/spark-aurelius/resources/assets/sass/spark"; 3 | -------------------------------------------------------------------------------- /install-stubs/resources/views/home.blade.php: -------------------------------------------------------------------------------- 1 | @extends('spark::layouts.app') 2 | 3 | @section('content') 4 | 5 |
6 | 7 |
8 |
9 |
10 |
{{__('Dashboard')}}
11 | 12 |
13 | {{__('Your application\'s dashboard.')}} 14 |
15 |
16 |
17 |
18 |
19 |
20 | @endsection 21 | -------------------------------------------------------------------------------- /install-stubs/routes/api.php: -------------------------------------------------------------------------------- 1 | 'auth:api' 16 | ], function () { 17 | // 18 | }); 19 | -------------------------------------------------------------------------------- /install-stubs/routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 18 | })->describe('Display an inspiring quote'); 19 | -------------------------------------------------------------------------------- /install-stubs/routes/web.php: -------------------------------------------------------------------------------- 1 | { 5 | return moment.utc(value).local().format('MMMM Do, YYYY') 6 | }); 7 | 8 | 9 | /** 10 | * Format the given date as a timestamp. 11 | */ 12 | Vue.filter('datetime', value => { 13 | return moment.utc(value).local().format('MMMM Do, YYYY h:mm A'); 14 | }); 15 | 16 | 17 | /** 18 | * Format the given date into a relative time. 19 | */ 20 | Vue.filter('relative', value => { 21 | return moment.utc(value).local().locale('en-short').fromNow(); 22 | }); 23 | 24 | 25 | /** 26 | * Convert the first character to upper case. 27 | * 28 | * Source: https://github.com/vuejs/vue/blob/1.0/src/filters/index.js#L37 29 | */ 30 | Vue.filter('capitalize', value => { 31 | if (! value && value !== 0) { 32 | return ''; 33 | } 34 | 35 | return value.toString().charAt(0).toUpperCase() 36 | + value.slice(1); 37 | }); 38 | 39 | 40 | /** 41 | * Format the given money value. 42 | */ 43 | Vue.filter('currency', value => { 44 | const Dinero = require('dinero.js').default 45 | 46 | return Dinero({ 47 | amount: Math.round(value * 100), 48 | currency: window.Spark.currency 49 | }).setLocale(window.Spark.currencyLocale).toFormat('$0,0.00'); 50 | }); -------------------------------------------------------------------------------- /resources/assets/js/forms/bootstrap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Initialize the Spark form extension points. 3 | */ 4 | Spark.forms = { 5 | register: {}, 6 | updateContactInformation: {}, 7 | updateTeamMember: {} 8 | }; 9 | 10 | /** 11 | * Load the SparkForm helper class. 12 | */ 13 | require('./form'); 14 | 15 | /** 16 | * Define the SparkFormError collection class. 17 | */ 18 | require('./errors'); 19 | 20 | /** 21 | * Add additional HTTP / form helpers to the Spark object. 22 | */ 23 | $.extend(Spark, require('./http')); 24 | -------------------------------------------------------------------------------- /resources/assets/js/kiosk/kiosk.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user'], 3 | 4 | 5 | /** 6 | * Load mixins for the component. 7 | */ 8 | mixins: [require('./../mixins/tab-state')], 9 | 10 | 11 | /** 12 | * Prepare the component. 13 | */ 14 | mounted() { 15 | this.usePushStateForTabs('.spark-settings-tabs'); 16 | }, 17 | 18 | 19 | /** 20 | * The component has been created by Vue. 21 | */ 22 | created() { 23 | Bus.$on('sparkHashChanged', function (hash, parameters) { 24 | if (hash === 'users') { 25 | setTimeout(() => { 26 | $('#kiosk-users-search').focus(); 27 | }, 150); 28 | } 29 | 30 | return true; 31 | }); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /resources/assets/js/mixin.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | computed: { 3 | /** 4 | * Get the billable entity. 5 | */ 6 | billable() { 7 | if (this.billableType) { 8 | return this.billableType === 'user' ? this.user : this.team; 9 | } else { 10 | return this.user; 11 | } 12 | }, 13 | 14 | 15 | /** 16 | * Determine if the current billable entity is a user. 17 | */ 18 | billingUser() { 19 | return this.billableType && this.billableType === 'user'; 20 | }, 21 | 22 | 23 | /** 24 | * Access the global Spark object. 25 | */ 26 | spark() { 27 | return window.Spark; 28 | } 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /resources/assets/js/navbar/navbar.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: [ 3 | 'user', 'teams', 'currentTeam', 4 | 'unreadAnnouncementsCount', 'unreadNotificationsCount' 5 | ], 6 | 7 | 8 | computed:{ 9 | notificationsCount(){ 10 | return this.unreadAnnouncementsCount + this.unreadNotificationsCount; 11 | } 12 | }, 13 | 14 | 15 | methods: { 16 | /** 17 | * Show the user's notifications. 18 | */ 19 | showNotifications() { 20 | Bus.$emit('showNotifications'); 21 | }, 22 | 23 | 24 | /** 25 | * Show the customer support e-mail form. 26 | */ 27 | showSupportForm() { 28 | Bus.$emit('showSupportForm'); 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /resources/assets/js/settings/api.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /** 3 | * The component's data. 4 | */ 5 | data() { 6 | return { 7 | tokens: [], 8 | availableAbilities: [] 9 | }; 10 | }, 11 | 12 | 13 | /** 14 | * Prepare the component. 15 | */ 16 | mounted() { 17 | this.getTokens(); 18 | this.getAvailableAbilities(); 19 | }, 20 | 21 | 22 | /** 23 | * The component has been created by Vue. 24 | */ 25 | created() { 26 | var self = this; 27 | 28 | this.$on('updateTokens', function(){ 29 | self.getTokens(); 30 | }); 31 | }, 32 | 33 | 34 | methods: { 35 | /** 36 | * Get the current API tokens for the user. 37 | */ 38 | getTokens() { 39 | axios.get('/settings/api/tokens') 40 | .then(response => this.tokens = response.data); 41 | }, 42 | 43 | 44 | /** 45 | * Get all of the available token abilities. 46 | */ 47 | getAvailableAbilities() { 48 | axios.get('/settings/api/token/abilities') 49 | .then(response => this.availableAbilities = response.data); 50 | } 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /resources/assets/js/settings/invoices.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team', 'billableType'], 3 | 4 | /** 5 | * The component's data. 6 | */ 7 | data() { 8 | return { 9 | invoices: [] 10 | }; 11 | }, 12 | 13 | 14 | /** 15 | * Prepare the component. 16 | */ 17 | mounted() { 18 | this.getInvoices(); 19 | }, 20 | 21 | 22 | methods: { 23 | /** 24 | * Get the user's billing invoices 25 | */ 26 | getInvoices() { 27 | axios.get(this.urlForInvoices) 28 | .then(response => { 29 | this.invoices = _.filter(response.data, invoice => { 30 | return invoice.total != '$0.00'; 31 | }); 32 | }); 33 | } 34 | }, 35 | 36 | 37 | computed: { 38 | /** 39 | * Get the URL for retrieving the invoices. 40 | */ 41 | urlForInvoices() { 42 | return this.billingUser 43 | ? '/settings/invoices' 44 | : `/settings/${Spark.teamsPrefix}/${this.team.id}/invoices`; 45 | } 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /resources/assets/js/settings/invoices/invoice-list.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team', 'invoices', 'billableType'], 3 | 4 | 5 | methods: { 6 | /** 7 | * Get the URL for downloading a given invoice. 8 | */ 9 | downloadUrlFor(invoice) { 10 | return this.billingUser 11 | ? `/settings/invoice/${invoice.id}` 12 | : `/settings/${Spark.teamsPrefix}/${this.team.id}/invoice/${invoice.id}`; 13 | } 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /resources/assets/js/settings/invoices/update-extra-billing-information.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team', 'billableType'], 3 | 4 | /** 5 | * The component's data. 6 | */ 7 | data() { 8 | return { 9 | form: new SparkForm({ 10 | information: '' 11 | }) 12 | }; 13 | }, 14 | 15 | 16 | /** 17 | * Prepare the component. 18 | */ 19 | mounted() { 20 | this.form.information = this.billable.extra_billing_information; 21 | }, 22 | 23 | 24 | 25 | methods: { 26 | /** 27 | * Update the extra billing information. 28 | */ 29 | update() { 30 | Spark.put(this.urlForUpdate, this.form); 31 | } 32 | }, 33 | 34 | 35 | computed: { 36 | /** 37 | * Get the URL for the extra billing information method update. 38 | */ 39 | urlForUpdate() { 40 | return this.billingUser 41 | ? '/settings/extra-billing-information' 42 | : `/settings/${Spark.teamsPrefix}/${this.team.id}/extra-billing-information`; 43 | } 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /resources/assets/js/settings/payment-method-stripe.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team', 'billableType'], 3 | 4 | 5 | /** 6 | * Load mixins for the component. 7 | */ 8 | mixins: [ 9 | require('./../mixins/discounts') 10 | ], 11 | 12 | 13 | /** 14 | * The component's data. 15 | */ 16 | data() { 17 | return { 18 | currentDiscount: null, 19 | loadingCurrentDiscount: false 20 | }; 21 | }, 22 | 23 | 24 | /** 25 | * The component has been created by Vue. 26 | */ 27 | created() { 28 | var self = this; 29 | 30 | this.$on('updateDiscount', function(){ 31 | self.getCurrentDiscountForBillable(self.billableType, self.billable); 32 | 33 | return true; 34 | }) 35 | }, 36 | 37 | /** 38 | * Prepare the component. 39 | */ 40 | mounted() { 41 | this.getCurrentDiscountForBillable(this.billableType, this.billable); 42 | }, 43 | }; 44 | -------------------------------------------------------------------------------- /resources/assets/js/settings/payment-method/redeem-coupon.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team', 'billableType'], 3 | 4 | /** 5 | * The component's data. 6 | */ 7 | data() { 8 | return { 9 | form: new SparkForm({ 10 | coupon: '' 11 | }) 12 | }; 13 | }, 14 | 15 | 16 | methods: { 17 | /** 18 | * Redeem the given coupon code. 19 | */ 20 | redeem() { 21 | Spark.post(this.urlForRedemption, this.form) 22 | .then(() => { 23 | this.form.coupon = ''; 24 | 25 | this.$parent.$emit('updateDiscount'); 26 | }); 27 | } 28 | }, 29 | 30 | 31 | computed: { 32 | /** 33 | * Get the URL for redeeming a coupon. 34 | */ 35 | urlForRedemption() { 36 | return this.billingUser 37 | ? '/settings/payment-method/coupon' 38 | : `/settings/${Spark.teamsPrefix}/${this.team.id}/payment-method/coupon`; 39 | } 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /resources/assets/js/settings/payment-method/update-vat-id.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team', 'billableType'], 3 | 4 | /** 5 | * The component's data. 6 | */ 7 | data() { 8 | return { 9 | form: new SparkForm({ vat_id: '' }) 10 | }; 11 | }, 12 | 13 | 14 | /** 15 | * Bootstrap the component. 16 | */ 17 | mounted() { 18 | this.form.vat_id = this.billable.vat_id; 19 | }, 20 | 21 | 22 | methods: { 23 | /** 24 | * Update the customer's VAT ID. 25 | */ 26 | update() { 27 | Spark.put(this.urlForUpdate, this.form); 28 | } 29 | }, 30 | 31 | 32 | computed: { 33 | /** 34 | * Get the URL for the VAT ID update. 35 | */ 36 | urlForUpdate() { 37 | return this.billingUser 38 | ? '/settings/payment-method/vat-id' 39 | : `/settings/${Spark.teamsPrefix}/${this.team.id}/payment-method/vat-id`; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /resources/assets/js/settings/profile.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user'] 3 | }; 4 | -------------------------------------------------------------------------------- /resources/assets/js/settings/profile/update-contact-information.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user'], 3 | 4 | /** 5 | * The component's data. 6 | */ 7 | data() { 8 | return { 9 | form: $.extend(true, new SparkForm({ 10 | name: '', 11 | email: '' 12 | }), Spark.forms.updateContactInformation) 13 | }; 14 | }, 15 | 16 | 17 | /** 18 | * Bootstrap the component. 19 | */ 20 | mounted() { 21 | this.form.name = this.user.name; 22 | this.form.email = this.user.email; 23 | }, 24 | 25 | 26 | methods: { 27 | /** 28 | * Update the user's contact information. 29 | */ 30 | update() { 31 | Spark.put('/settings/contact', this.form) 32 | .then(() => { 33 | Bus.$emit('updateUser'); 34 | }); 35 | } 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /resources/assets/js/settings/security.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user'], 3 | 4 | 5 | /** 6 | * The component's data. 7 | */ 8 | data() { 9 | return { 10 | twoFactorResetCode: null 11 | }; 12 | }, 13 | 14 | 15 | /** 16 | * The component has been created by Vue. 17 | */ 18 | created() { 19 | var self = this; 20 | 21 | this.$on('receivedTwoFactorResetCode', function (code) { 22 | self.twoFactorResetCode = code; 23 | 24 | $('#modal-show-two-factor-reset-code').modal('show'); 25 | }); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /resources/assets/js/settings/security/disable-two-factor-auth.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user'], 3 | 4 | /** 5 | * The component's data. 6 | */ 7 | data() { 8 | return { 9 | form: new SparkForm({}) 10 | } 11 | }, 12 | 13 | 14 | methods: { 15 | /** 16 | * Disable two-factor authentication for the user. 17 | */ 18 | disable() { 19 | Spark.delete('/settings/two-factor-auth', this.form) 20 | .then(() => { 21 | Bus.$emit('updateUser'); 22 | }); 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /resources/assets/js/settings/security/enable-two-factor-auth.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user'], 3 | 4 | /** 5 | * The component's data. 6 | */ 7 | data() { 8 | return { 9 | form: new SparkForm({ 10 | country_code: '', 11 | phone: '' 12 | }) 13 | } 14 | }, 15 | 16 | 17 | /** 18 | * Prepare the component. 19 | */ 20 | mounted() { 21 | this.form.country_code = this.user.country_code; 22 | this.form.phone = this.user.phone; 23 | }, 24 | 25 | 26 | methods: { 27 | /** 28 | * Enable two-factor authentication for the user. 29 | */ 30 | enable() { 31 | Spark.post('/settings/two-factor-auth', this.form) 32 | .then(code => { 33 | this.$parent.$emit('receivedTwoFactorResetCode', code); 34 | 35 | Bus.$emit('updateUser'); 36 | }); 37 | } 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /resources/assets/js/settings/security/update-password.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /** 3 | * The component's data. 4 | */ 5 | data() { 6 | return { 7 | form: new SparkForm({ 8 | current_password: '', 9 | password: '', 10 | password_confirmation: '' 11 | }) 12 | }; 13 | }, 14 | 15 | 16 | methods: { 17 | /** 18 | * Update the user's password. 19 | */ 20 | update() { 21 | Spark.put('/settings/password', this.form); 22 | } 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /resources/assets/js/settings/settings.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'teams'], 3 | 4 | 5 | /** 6 | * Load mixins for the component. 7 | */ 8 | mixins: [require('./../mixins/tab-state')], 9 | 10 | 11 | /** 12 | * The component's data. 13 | */ 14 | data() { 15 | return { 16 | billableType: 'user', 17 | team: null 18 | }; 19 | }, 20 | 21 | 22 | /** 23 | * Prepare the component. 24 | */ 25 | mounted() { 26 | this.usePushStateForTabs('.spark-settings-tabs'); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /resources/assets/js/settings/subscription.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team', 'billableType'], 3 | 4 | /** 5 | * Load mixins for the component. 6 | */ 7 | mixins: [ 8 | require('./../mixins/plans'), 9 | require('./../mixins/subscriptions') 10 | ], 11 | 12 | 13 | /** 14 | * The component's data. 15 | */ 16 | data() { 17 | return { 18 | plans: [] 19 | }; 20 | }, 21 | 22 | 23 | /** 24 | * Prepare the component. 25 | */ 26 | mounted() { 27 | var self = this; 28 | 29 | this.getPlans(); 30 | 31 | this.$on('showPlanDetails', function (plan) { 32 | self.showPlanDetails(plan); 33 | }); 34 | }, 35 | 36 | 37 | methods: { 38 | /** 39 | * Get the active plans for the application. 40 | */ 41 | getPlans() { 42 | axios.get('/spark/plans') 43 | .then(response => { 44 | this.plans = this.billingUser 45 | ? _.filter(response.data, {type: "user"}) 46 | : _.filter(response.data, {type: "team"}); 47 | }); 48 | } 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /resources/assets/js/settings/subscription/cancel-subscription.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team', 'billableType'], 3 | 4 | /** 5 | * The component's data. 6 | */ 7 | data() { 8 | return { 9 | form: new SparkForm({}) 10 | }; 11 | }, 12 | 13 | 14 | methods: { 15 | /** 16 | * Confirm the cancellation operation. 17 | */ 18 | confirmCancellation() { 19 | $('#modal-confirm-cancellation').modal('show'); 20 | }, 21 | 22 | 23 | /** 24 | * Cancel the current subscription. 25 | */ 26 | cancel() { 27 | Spark.delete(this.urlForCancellation, this.form) 28 | .then(() => { 29 | Bus.$emit('updateUser'); 30 | Bus.$emit('updateTeam'); 31 | 32 | $('#modal-confirm-cancellation').modal('hide'); 33 | }); 34 | } 35 | }, 36 | 37 | 38 | computed: { 39 | /** 40 | * Get the URL for the subscription cancellation. 41 | */ 42 | urlForCancellation() { 43 | return this.billingUser 44 | ? '/settings/subscription' 45 | : `/settings/${Spark.teamsPrefix}/${this.team.id}/subscription`; 46 | } 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /resources/assets/js/settings/subscription/resume-subscription.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team', 'plans', 'billableType'], 3 | 4 | /** 5 | * Load mixins for the component. 6 | */ 7 | mixins: [ 8 | require('./../../mixins/plans'), 9 | require('./../../mixins/subscriptions') 10 | ], 11 | 12 | 13 | /** 14 | * Prepare the component. 15 | */ 16 | mounted() { 17 | if (this.onlyHasYearlyPlans) { 18 | this.showYearlyPlans(); 19 | } 20 | }, 21 | 22 | 23 | methods: { 24 | /** 25 | * Show the plan details for the given plan. 26 | * 27 | * We'll ask the parent subscription component to display it. 28 | */ 29 | showPlanDetails(plan) { 30 | this.$parent.$emit('showPlanDetails', plan); 31 | }, 32 | 33 | 34 | /** 35 | * Get the plan price with the applicable VAT. 36 | */ 37 | priceWithTax(plan) { 38 | return plan.price + (plan.price * (this.billable.tax_rate / 100)); 39 | } 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /resources/assets/js/settings/teams.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'teams'], 3 | }; 4 | -------------------------------------------------------------------------------- /resources/assets/js/settings/teams/mailed-invitations.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['team', 'invitations'], 3 | 4 | 5 | methods: { 6 | /** 7 | * Cancel the sent invitation. 8 | */ 9 | cancel(invitation) { 10 | axios.delete(`/settings/invitations/${invitation.id}`) 11 | .then(() => { 12 | this.$parent.$emit('updateInvitations'); 13 | }); 14 | } 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /resources/assets/js/settings/teams/team-membership.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team', 'billableType'], 3 | 4 | /** 5 | * The component's data. 6 | */ 7 | data() { 8 | return { 9 | invitations: [] 10 | }; 11 | }, 12 | 13 | 14 | /** 15 | * The component has been created by Vue. 16 | */ 17 | created() { 18 | var self = this; 19 | 20 | this.getInvitations(); 21 | 22 | this.$on('updateInvitations', function () { 23 | self.getInvitations(); 24 | }); 25 | }, 26 | 27 | 28 | methods: { 29 | /** 30 | * Get all of the invitations for the team. 31 | */ 32 | getInvitations() { 33 | axios.get(`/settings/${Spark.teamsPrefix}/${this.team.id}/invitations`) 34 | .then(response => { 35 | this.invitations = response.data; 36 | }); 37 | } 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /resources/assets/js/settings/teams/team-profile.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team'] 3 | }; 4 | -------------------------------------------------------------------------------- /resources/assets/js/settings/teams/team-settings.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'teamId'], 3 | 4 | 5 | /** 6 | * Load mixins for the component. 7 | */ 8 | mixins: [require('./../../mixins/tab-state')], 9 | 10 | 11 | /** 12 | * The component's data. 13 | */ 14 | data() { 15 | return { 16 | billableType: 'team', 17 | team: null 18 | }; 19 | }, 20 | 21 | 22 | /** 23 | * The component has been created by Vue. 24 | */ 25 | created() { 26 | var self = this; 27 | 28 | this.getTeam(); 29 | 30 | Bus.$on('updateTeam', function () { 31 | self.getTeam(); 32 | }); 33 | }, 34 | 35 | 36 | /** 37 | * Prepare the component. 38 | */ 39 | mounted() { 40 | this.usePushStateForTabs('.spark-settings-tabs'); 41 | }, 42 | 43 | 44 | methods: { 45 | /** 46 | * Get the team being managed. 47 | */ 48 | getTeam() { 49 | axios.get(`/settings/${Spark.teamsPrefix}/json/${this.teamId}`) 50 | .then(response => { 51 | this.team = response.data; 52 | }); 53 | } 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /resources/assets/js/settings/teams/update-team-name.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | props: ['user', 'team'], 3 | 4 | /** 5 | * The component's data. 6 | */ 7 | data() { 8 | return { 9 | form: new SparkForm({ 10 | name: '' 11 | }) 12 | }; 13 | }, 14 | 15 | 16 | /** 17 | * Prepare the component. 18 | */ 19 | mounted() { 20 | this.form.name = this.team.name; 21 | }, 22 | 23 | 24 | methods: { 25 | /** 26 | * Update the team name. 27 | */ 28 | update() { 29 | Spark.put(`/settings/${Spark.teamsPrefix}/${this.team.id}/name`, this.form) 30 | .then(() => { 31 | Bus.$emit('updateTeam'); 32 | Bus.$emit('updateTeams'); 33 | }); 34 | } 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /resources/assets/js/vue-bootstrap.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Load Vue, the JavaScript framework used by Spark. 3 | */ 4 | if (window.Vue === undefined) { 5 | window.Vue = require('vue'); 6 | 7 | window.Bus = new Vue(); 8 | } 9 | 10 | /** 11 | * Load Vue Global Mixin. 12 | */ 13 | Vue.mixin(require('./mixin')); 14 | 15 | /** 16 | * Define the Vue filters. 17 | */ 18 | require('./filters'); 19 | 20 | /** 21 | * Load the Spark form utilities. 22 | */ 23 | require('./forms/bootstrap'); 24 | -------------------------------------------------------------------------------- /resources/assets/sass/_custom.scss: -------------------------------------------------------------------------------- 1 | // Elements 2 | // -------------------------------------------------------------------------- */ 3 | @import 'elements/forms'; 4 | @import 'elements/icons'; 5 | @import 'elements/tables'; 6 | @import 'elements/text'; 7 | 8 | // Components 9 | // -------------------------------------------------------------------------- */ 10 | @import 'components/buttons'; 11 | @import 'components/cards'; 12 | @import 'components/dropdown'; 13 | @import 'components/metrics'; 14 | @import 'components/modals'; 15 | @import 'components/navbar'; 16 | @import 'components/team-member-list'; 17 | @import 'components/uploader'; 18 | @import 'components/notifications'; 19 | 20 | // Utilities 21 | // -------------------------------------------------------------------------- */ 22 | @import 'elements/utilities'; 23 | -------------------------------------------------------------------------------- /resources/assets/sass/components/_buttons.scss: -------------------------------------------------------------------------------- 1 | // Buttons 2 | // -------------------------------------------------------------------------- */ 3 | .btn { 4 | box-shadow: 0 1px 2px $gray-200; 5 | font-size: 0.9375rem; 6 | } 7 | 8 | .btn-sm { 9 | font-weight: 500; 10 | font-size: 0.8125rem; 11 | } 12 | 13 | .btn-link { 14 | box-shadow: none; 15 | } 16 | 17 | .btn-reset { 18 | background: none; 19 | padding: 0; 20 | margin: 0; 21 | appearance: none; 22 | border: none; 23 | cursor: pointer; 24 | } 25 | 26 | .btn-default { 27 | background-color: $white; 28 | border-color: $gray-300; 29 | color: $gray-800; 30 | font-weight: 300; 31 | font-size: 1rem; 32 | 33 | &:hover { 34 | border-color: $gray-400; 35 | } 36 | } 37 | 38 | .btn-outline-dark { 39 | border-color: $gray-300; 40 | color: $gray-700; 41 | font-weight: 300; 42 | box-shadow: none; 43 | } 44 | -------------------------------------------------------------------------------- /resources/assets/sass/components/_cards.scss: -------------------------------------------------------------------------------- 1 | // Cards 2 | // -------------------------------------------------------------------------- */ 3 | .card { 4 | margin-bottom: 2rem; 5 | 6 | box-shadow: 0 2px 3px rgba($black, 0.16); 7 | .card-header { 8 | padding: 1rem 1.25rem; 9 | // font-weight: 500; 10 | // color: $gray-700; 11 | } 12 | .card-footer { 13 | border-top: 1px solid $gray-300; 14 | background-color: transparent; 15 | } 16 | } 17 | 18 | .card-header:first-child { 19 | border-radius: $card-border-radius; 20 | } 21 | 22 | .card-title { 23 | font-size: 1.25rem; 24 | font-weight: 300; 25 | } 26 | 27 | .card-flush { 28 | padding: 0.875rem 1.25rem; 29 | } 30 | 31 | .card-full { 32 | width: 80%; 33 | } 34 | 35 | // Intro Cards 36 | // -------------------------------------------------------------------------- */ 37 | .intro { 38 | text-align: center; 39 | // display: flex; 40 | // align-items: center; 41 | // align-content: center; 42 | // justify-content: center; 43 | } 44 | 45 | .intro-img { 46 | margin-bottom: 1.5rem; 47 | } 48 | 49 | .intro-headline { 50 | font-size: 1.25rem; 51 | font-weight: 300; 52 | } 53 | 54 | .intro-copy { 55 | } 56 | 57 | .intro-btn { 58 | margin-top: 1.5rem; 59 | } 60 | -------------------------------------------------------------------------------- /resources/assets/sass/components/_dropdown.scss: -------------------------------------------------------------------------------- 1 | // Dropdown 2 | // -------------------------------------------------------------------------- */ 3 | .dropdown-toggle::after { 4 | @include media-breakpoint-up(md) { 5 | margin-left: 0.625rem; 6 | } 7 | } 8 | 9 | .dropdown-toggle-image { 10 | height: 35px; 11 | width: 35px; 12 | border-radius: 100%; 13 | margin-right: 0; 14 | 15 | @include media-breakpoint-up(md) { 16 | margin-right: 0.625rem; 17 | } 18 | } 19 | 20 | .spark-dropdown-label { 21 | font-size: 0.9375rem; 22 | font-weight: 600; 23 | color: $black; 24 | } 25 | 26 | .notification-pill { 27 | cursor: pointer; 28 | display: flex; 29 | align-items: center; 30 | justify-content: center; 31 | border-radius: 99px; 32 | width: 4.4375rem; 33 | height: 2.125rem; 34 | background-color: $gray-100; 35 | color: $gray-900; 36 | font-weight: 600; 37 | font-size: 0.9375rem; 38 | } 39 | -------------------------------------------------------------------------------- /resources/assets/sass/components/_metrics.scss: -------------------------------------------------------------------------------- 1 | .metrics { 2 | @include media-breakpoint-up(md) { 3 | display: flex; 4 | } 5 | } 6 | 7 | .metric { 8 | display: flex; 9 | padding-top: 1.25rem; 10 | padding-bottom: 1.25rem; 11 | 12 | border-bottom: 1px solid $gray-300; 13 | 14 | &:last-child { 15 | border-bottom: none; 16 | padding-bottom: 0; 17 | } 18 | 19 | @include media-breakpoint-up(md) { 20 | flex: 1; 21 | padding-top: 0; 22 | padding-bottom: 0; 23 | border-bottom: none; 24 | } 25 | } 26 | 27 | .metric-title { 28 | font-size: 0.9375rem; 29 | color: $gray-500; 30 | } 31 | 32 | .metric-stat { 33 | font-weight: 100; 34 | font-size: 1.875rem; 35 | color: $black; 36 | } 37 | 38 | .metric-unit { 39 | font-weight: 600; 40 | font-size: 1rem; 41 | } 42 | 43 | .metric-stat-sm { 44 | font-size: 0.9375rem; 45 | color: $black; 46 | } 47 | 48 | .metric-icon { 49 | width: 1.25rem; 50 | height: 1.25rem; 51 | } 52 | -------------------------------------------------------------------------------- /resources/assets/sass/components/_modals.scss: -------------------------------------------------------------------------------- 1 | .modal-content { 2 | } 3 | 4 | .modal-title { 5 | font-weight: 300; 6 | } 7 | 8 | .modal-header { 9 | background-color: $modal-header-bg; 10 | } 11 | 12 | .modal-footer { 13 | } 14 | -------------------------------------------------------------------------------- /resources/assets/sass/components/_team-member-list.scss: -------------------------------------------------------------------------------- 1 | .team-member { 2 | padding-top: 1rem; 3 | padding-right: 1.25rem; 4 | padding-left: 1.25rem; 5 | padding-bottom: 1rem; 6 | height: 3.8125rem; 7 | border: 1px solid transparent; 8 | border-top: 1px solid $gray-400; 9 | border-bottom: 1px solid $gray-400; 10 | display: flex; 11 | justify-content: space-between; 12 | align-items: center; 13 | margin-top: -1px; 14 | } 15 | 16 | .team-member:hover { 17 | background-color: $white; 18 | border-radius: 6px; 19 | border: transparent; 20 | border: 1px solid $gray-400; 21 | box-shadow: 0 1px 2px $gray-400; 22 | } 23 | 24 | .team-member-title { 25 | font-size: 1rem; 26 | color: $black; 27 | } 28 | 29 | .team-member-subtitle { 30 | font-size: 0.875rem; 31 | color: $gray-700; 32 | } 33 | -------------------------------------------------------------------------------- /resources/assets/sass/components/_uploader.scss: -------------------------------------------------------------------------------- 1 | .spark-uploader { 2 | position: relative; 3 | border-radius: $btn-border-radius; 4 | cursor: pointer !important; 5 | 6 | &:active { 7 | box-shadow: $input-focus-box-shadow; 8 | } 9 | } 10 | 11 | .spark-uploader-control { 12 | position: absolute; 13 | top: 0; 14 | // right: 0; 15 | bottom: 0; 16 | // left: 0; 17 | max-width: 100%; 18 | opacity: 0; 19 | z-index: 99; 20 | } 21 | 22 | .image-placeholder { 23 | background: $gray-300; 24 | width: 3.75rem; 25 | height: 3.75rem; 26 | border-radius: 99px; 27 | } 28 | -------------------------------------------------------------------------------- /resources/assets/sass/elements/_forms.scss: -------------------------------------------------------------------------------- 1 | // Form Controls 2 | // -------------------------------------------------------------------------- */ 3 | .form-control { 4 | box-shadow: 0 1px 2px $gray-200; 5 | 6 | &::placeholder { 7 | color: $gray-300; 8 | } 9 | } 10 | 11 | .col-form-label { 12 | font-weight: 500; 13 | } 14 | 15 | .form-check-label { 16 | font-size: 0.9375rem; 17 | color: $gray-800; 18 | } 19 | 20 | .form-check-input { 21 | margin-top: 0.35rem; 22 | } 23 | 24 | .StripeElement { 25 | @extend .form-control; 26 | 27 | padding: 9px 12px; 28 | 29 | &--focus { 30 | border-color: $input-focus-border-color; 31 | box-shadow: $input-focus-box-shadow; 32 | } 33 | 34 | &--invalid { 35 | border-color: $red; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /resources/assets/sass/elements/_icons.scss: -------------------------------------------------------------------------------- 1 | // Icons 2 | // -------------------------------------------------------------------------- */ 3 | .icon-20 { 4 | width: 20px; 5 | height: 20px; 6 | } 7 | 8 | .fill-gray { 9 | fill: $gray-500; 10 | } 11 | 12 | .radio-select { 13 | display: inline-block; 14 | background-image: url('../img/radio-select-default.svg'); 15 | height: 28px; 16 | width: 28px; 17 | cursor: pointer; 18 | } 19 | 20 | .radio-select-selected { 21 | background-image: url('../img/radio-select-is-selected.svg'); 22 | } 23 | -------------------------------------------------------------------------------- /resources/assets/sass/elements/_tables.scss: -------------------------------------------------------------------------------- 1 | // Tables 2 | // -------------------------------------------------------------------------- */ 3 | .table { 4 | thead { 5 | th { 6 | background-color: hsl($brand-hue, 25%, 92%); 7 | font-size: 15px; 8 | font-weight: 600; 9 | } 10 | } 11 | tbody { 12 | td { 13 | } 14 | } 15 | } 16 | 17 | .table-valign-middle { 18 | td { 19 | vertical-align: middle; 20 | } 21 | } 22 | 23 | .th-fit, 24 | .td-fit { 25 | width: 1%; 26 | white-space: nowrap; 27 | } 28 | 29 | .table-plan-price { 30 | font-weight: 600; 31 | color: $gray-800; 32 | } 33 | 34 | .table-plan-text { 35 | color: $gray-600; 36 | } 37 | 38 | .card { 39 | .table th, .table td{ 40 | padding: 0.75rem 1.25rem; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /resources/assets/sass/elements/_text.scss: -------------------------------------------------------------------------------- 1 | .ft-15 { 2 | font-size: 0.9375rem; 3 | } 4 | -------------------------------------------------------------------------------- /resources/assets/sass/elements/_utilities.scss: -------------------------------------------------------------------------------- 1 | .valign-middle { 2 | vertical-align: middle !important; 3 | } 4 | 5 | .nowrap { 6 | white-space: nowrap !important; 7 | } 8 | 9 | // Width Utilities 10 | // -------------------------------------------------------------------------- */ 11 | .h-37 { 12 | height: 37px; 13 | } 14 | 15 | .h-90 { 16 | height: 90px; 17 | } 18 | 19 | .w-90 { 20 | width: 5.625rem; 21 | } 22 | 23 | .w-80\% { 24 | @include media-breakpoint-up(md) { 25 | width: 80%; 26 | } 27 | } 28 | 29 | .w-84\% { 30 | @include media-breakpoint-up(md) { 31 | width: 84%; 32 | } 33 | } 34 | 35 | .w-auto { 36 | width: auto; 37 | } 38 | 39 | .max-w-49\% { 40 | max-width: 49%; 41 | } 42 | 43 | // Misc Utilities 44 | // -------------------------------------------------------------------------- */ 45 | .reveal .reveal-target { 46 | opacity: 0; 47 | } 48 | 49 | .reveal:hover .reveal-target { 50 | opacity: 1; 51 | } 52 | 53 | // Cursor 54 | // -------------------------------------------------------------------------- */ 55 | .pointer { 56 | cursor: pointer; 57 | } 58 | .no-pointer { 59 | cursor: default; 60 | } 61 | 62 | // Flex 63 | // -------------------------------------------------------------------------- */ 64 | .flex-1 { 65 | flex: 1; 66 | } 67 | 68 | .no-shrink { 69 | flex-shrink: 0; 70 | } 71 | -------------------------------------------------------------------------------- /resources/assets/sass/spark.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | @import "~bootstrap/scss/bootstrap"; 3 | @import "~sweetalert2/src/sweetalert2"; 4 | @import 'custom'; 5 | 6 | // Vue Cloak 7 | [v-cloak] { 8 | display: none; 9 | } 10 | 11 | body { 12 | direction: ltr; 13 | } 14 | 15 | .profile-photo-preview { 16 | display: inline-block; 17 | background-position: center; 18 | background-size: cover; 19 | vertical-align: middle; 20 | height: 60px; 21 | width: 60px; 22 | border-radius: 50%; 23 | } 24 | 25 | pre { 26 | display: block; 27 | padding: 10.5px; 28 | margin: 0 0 11px; 29 | font-size: 13px; 30 | line-height: 1.6; 31 | word-break: break-all; 32 | word-wrap: break-word; 33 | color: #333333; 34 | background-color: #f5f5f5; 35 | border: 1px solid #ccc; 36 | border-radius: 4px; 37 | } 38 | 39 | .plan-feature-list{ 40 | list-style: none; 41 | } 42 | 43 | .plan-feature-list li { 44 | line-height: 25px; 45 | margin-bottom: 20px; 46 | 47 | &:last-child{ 48 | margin-bottom: 0; 49 | } 50 | } 51 | 52 | .spark-profile-photo-xs { 53 | border-radius: 50%; 54 | height: 20px; 55 | width: 20px; 56 | } 57 | 58 | .spark-profile-photo { 59 | height: 35px; 60 | width: 35px; 61 | border-radius: 50%; 62 | } 63 | 64 | .spark-profile-photo-xl { 65 | height: 125px; 66 | width: 125px; 67 | border-radius: 50%; 68 | } 69 | -------------------------------------------------------------------------------- /resources/views/auth/emails/password.blade.php: -------------------------------------------------------------------------------- 1 | {{__('Click here to reset your password:')}} {{ $link }} 2 | -------------------------------------------------------------------------------- /resources/views/auth/verify.blade.php: -------------------------------------------------------------------------------- 1 | @extends('spark::layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Verify Your Email Address') }}
9 | 10 |
11 | 12 | @if (session('resent')) 13 | 16 | @endif 17 | 18 | {{ __('Before proceeding, please check your email for a verification link.') }} 19 | {{ __('If you did not receive the email') }}, 20 |
21 | @csrf 22 | . 23 |
24 |
25 |
26 |
27 |
28 |
29 | @endsection 30 | -------------------------------------------------------------------------------- /resources/views/missing-team.blade.php: -------------------------------------------------------------------------------- 1 | @extends('spark::layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
9 | {{__('Create Team')}} 10 |
11 |

12 | {{__('teams.wheres_your_team')}} 13 |

14 |

15 | {{__('teams.looks_like_you_are_not_part_of_team')}} 16 |

17 | 22 |
23 |
24 |
25 |
26 | @endsection 27 | -------------------------------------------------------------------------------- /resources/views/modals/plan-details.blade.php: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /resources/views/modals/session-expired.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 26 | -------------------------------------------------------------------------------- /resources/views/nav/blade/teams.blade.php: -------------------------------------------------------------------------------- 1 |
  • 2 | 3 | 4 | 5 | 6 | 7 | @if (Spark::createsAdditionalTeams()) 8 |
  • 9 | 10 | {{__('teams.create_team')}} 11 | 12 |
  • 13 | @endif 14 | 15 | 16 | @if (Spark::showsTeamSwitcher()) 17 | @foreach (Auth::user()->teams as $team) 18 |
  • 19 | 20 | @if (Auth::user()->current_team_id === $team->id) 21 | {{ $team->name }} 22 | @else 23 | {{__('Team Photo')}} {{ $team->name }} 24 | @endif 25 | 26 |
  • 27 | @endforeach 28 | @endif 29 | -------------------------------------------------------------------------------- /resources/views/nav/developer.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{__('Kiosk')}} 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /resources/views/nav/subscriptions.blade.php: -------------------------------------------------------------------------------- 1 | @if (Auth::user()->onTrial()) 2 | 3 | 4 | 5 | 6 | {{__('Subscribe')}} 7 | 8 | 9 | 10 | @endif 11 | 12 | @if (Spark::usesTeams() && Auth::user()->ownsCurrentTeam() && Auth::user()->currentTeamOnTrial()) 13 | 14 | 15 | 16 | 17 | {{__('Subscribe')}} 18 | 19 | 20 | 21 | @endif 22 | -------------------------------------------------------------------------------- /resources/views/nav/support.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{__('Email Us')}} 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /resources/views/nav/teams.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | @if (Spark::createsAdditionalTeams()) 6 | 7 | {{__('teams.create_team')}} 8 | 9 | @endif 10 | 11 | 12 | @if (Spark::showsTeamSwitcher()) 13 | 14 | 15 | @{{ team.name }} 16 | 17 | 18 | 19 | {{__('Team Photo')}} @{{ team.name }} 20 | 21 | 22 | @endif 23 | 24 | 25 | -------------------------------------------------------------------------------- /resources/views/nav/user-left.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resources/views/settings/api.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 | 4 |
    5 | @include('spark::settings.api.create-token') 6 |
    7 | 8 | 9 |
    10 | @include('spark::settings.api.tokens') 11 |
    12 |
    13 |
    14 | -------------------------------------------------------------------------------- /resources/views/settings/invoices.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 | 4 |
    5 | @include('spark::settings.invoices.update-extra-billing-information') 6 |
    7 | 8 | 9 |
    10 | @include('spark::settings.invoices.invoice-list') 11 |
    12 |
    13 |
    14 | -------------------------------------------------------------------------------- /resources/views/settings/invoices/emails/invoice.blade.php: -------------------------------------------------------------------------------- 1 | @if ($billable instanceof Laravel\Spark\Team) 2 | {{__('Hi :name', ['name' => $billable->name])}} 3 | @else 4 | {{__('Hi :name', ['name' => explode(' ', $billable->name)[0]])}} 5 | @endif 6 | 7 |

    8 | 9 | {{__('Thanks for your continued support. We\'ve attached a copy of your invoice for your records. Please let us know if you have any questions or concerns!')}} 10 | 11 |

    12 | 13 | {{__('Thanks!')}} 14 | 15 |
    16 | 17 | {{ $invoiceData['product'] }} 18 | 19 | -------------------------------------------------------------------------------- /resources/views/settings/profile.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 | 4 | @include('spark::settings.profile.update-profile-photo') 5 | 6 | 7 | @include('spark::settings.profile.update-contact-information') 8 |
    9 |
    10 | -------------------------------------------------------------------------------- /resources/views/settings/profile/update-profile-photo.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    {{__('Profile Photo')}}
    4 | 5 |
    6 |
    7 | @{{ form.errors.get('photo') }} 8 |
    9 | 10 |
    11 |
    12 |
    13 |
    14 | 15 |
    16 |
    17 | 18 |
    {{__('Update Photo')}}
    19 |
    20 |
    21 |
    22 |
    23 |
    24 |
    25 |
    26 | -------------------------------------------------------------------------------- /resources/views/settings/security.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 | 4 | @include('spark::settings.security.update-password') 5 | 6 | 7 | @if (Spark::usesTwoFactorAuth()) 8 |
    9 | @include('spark::settings.security.enable-two-factor-auth') 10 |
    11 | 12 |
    13 | @include('spark::settings.security.disable-two-factor-auth') 14 |
    15 | 16 | 17 | @include('spark::settings.security.modals.two-factor-reset-code') 18 | @endif 19 |
    20 |
    21 | -------------------------------------------------------------------------------- /resources/views/settings/security/disable-two-factor-auth.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 | 13 |
    14 |
    15 |
    16 | -------------------------------------------------------------------------------- /resources/views/settings/security/modals/two-factor-reset-code.blade.php: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /resources/views/settings/subscription.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 | 5 | @include('spark::settings.subscription.subscription-notice') 6 | 7 | 8 |
    9 | @include('spark::settings.subscription.subscribe') 10 |
    11 | 12 | 13 |
    14 | @include('spark::settings.subscription.update-subscription') 15 |
    16 | 17 | 18 |
    19 | @include('spark::settings.subscription.resume-subscription') 20 |
    21 | 22 | 23 |
    24 | @include('spark::settings.subscription.cancel-subscription') 25 |
    26 |
    27 | 28 | 29 | @include('spark::modals.plan-details') 30 |
    31 |
    32 | -------------------------------------------------------------------------------- /resources/views/settings/subscription/subscription-notice.blade.php: -------------------------------------------------------------------------------- 1 | @if(auth()->user()->subscription() && in_array(auth()->user()->subscription()->stripe_status, ['incomplete' , 'past_due'])) 2 |
    3 | {!! __('Please :linkOpen confirm your payment :linkClose to activate your subscription!', ['linkOpen' => '', 'linkClose' => '']) !!} 4 |
    5 | @elseif(method_exists(auth()->user(), 'currentTeam') && auth()->user()->currentTeam() && auth()->user()->currentTeam()->subscription() && in_array(auth()->user()->currentTeam()->subscription()->stripe_status, ['incomplete' , 'past_due'])) 6 |
    7 | {!! __('Please :linkOpen confirm your payment :linkClose to activate your subscription!', ['linkOpen' => '', 'linkClose' => '']) !!} 8 |
    9 | @else 10 |
    11 | '{{ trialEndsAt }}']); ?> 12 |
    13 | @endif -------------------------------------------------------------------------------- /resources/views/settings/teams.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 | 4 | @if (Spark::createsAdditionalTeams()) 5 | @include('spark::settings.teams.create-team') 6 | @endif 7 | 8 | 9 | @include('spark::settings.teams.pending-invitations') 10 | 11 | 12 |
    13 | @include('spark::settings.teams.current-teams') 14 |
    15 |
    16 |
    17 | -------------------------------------------------------------------------------- /resources/views/settings/teams/emails/invitation-to-existing-user.blade.php: -------------------------------------------------------------------------------- 1 | {{__('Hi!')}} 2 | 3 |

    4 | 5 | {{__('teams.user_invited_to_join_team', ['userName' => $invitation->team->owner->name])}} 6 | 7 |

    8 | 9 | {{__('Since you already have an account, you may accept the invitation from your account settings screen.')}} 10 | 11 |

    12 | 13 | {{__('See you soon!')}} 14 | -------------------------------------------------------------------------------- /resources/views/settings/teams/emails/invitation-to-new-user.blade.php: -------------------------------------------------------------------------------- 1 | {{__('Hi!')}} 2 | 3 |

    4 | 5 | {{__('teams.user_invited_to_join_team', ['userName' => $invitation->team->owner->name])}} 6 | {{__('If you do not already have an account, you may click the following link to get started:')}} 7 | 8 |

    9 | 10 | {{ url('register?invitation='.$invitation->token) }} 11 | 12 |

    13 | 14 | {{__('See you soon!')}} 15 | -------------------------------------------------------------------------------- /resources/views/settings/teams/team-membership.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 | @if (Auth::user()->ownsTeam($team)) 4 | 5 |
    6 | @include('spark::settings.teams.send-invitation') 7 |
    8 | 9 | 10 |
    11 | @include('spark::settings.teams.mailed-invitations') 12 |
    13 | @endif 14 | 15 | 16 |
    17 | @include('spark::settings.teams.team-members') 18 |
    19 |
    20 |
    21 | -------------------------------------------------------------------------------- /resources/views/settings/teams/team-profile.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 | 5 | @include('spark::settings.teams.update-team-photo') 6 | 7 | 8 | @include('spark::settings.teams.update-team-name') 9 |
    10 |
    11 |
    12 | -------------------------------------------------------------------------------- /resources/views/settings/teams/update-team-photo.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 | {{__('teams.team_photo')}} 5 |
    6 | 7 |
    8 |
    9 | @{{ form.errors.get('photo') }} 10 |
    11 | 12 |
    13 |
    14 |
    15 |
    16 | 17 |
    18 |
    19 | 20 |
    {{__('Update Photo')}}
    21 |
    22 |
    23 |
    24 |
    25 |
    26 |
    27 |
    28 | -------------------------------------------------------------------------------- /resources/views/shared/errors.blade.php: -------------------------------------------------------------------------------- 1 | @if (count($errors) > 0) 2 |
    3 | {{__('Whoops!')}} {{__('Something went wrong!')}} 4 |

    5 | 10 |
    11 | @endif 12 | -------------------------------------------------------------------------------- /resources/views/terms.blade.php: -------------------------------------------------------------------------------- 1 | @extends('spark::layouts.app') 2 | 3 | @section('content') 4 |
    5 | 6 |
    7 |
    8 |
    9 |
    {{__('Terms Of Service')}}
    10 | 11 |
    12 | {!! $terms !!} 13 |
    14 |
    15 |
    16 |
    17 |
    18 | @endsection 19 | -------------------------------------------------------------------------------- /src/Configuration/ManagesSupportOptions.php: -------------------------------------------------------------------------------- 1 | each(function ($updater) { 36 | (new $updater($this, SPARK_PATH))->update(); 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Console/Commands/VersionCommand.php: -------------------------------------------------------------------------------- 1 | line('Laravel Spark version '.Spark::$version.''); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Console/Installation/InstallConfiguration.php: -------------------------------------------------------------------------------- 1 | command = $command; 23 | 24 | $this->command->line('Updating Configuration Values: '); 25 | } 26 | 27 | /** 28 | * Install the components. 29 | * 30 | * @return void 31 | */ 32 | public function install() 33 | { 34 | copy(SPARK_STUB_PATH.'/config/auth.php', config_path('auth.php')); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Console/Installation/InstallEnvironment.php: -------------------------------------------------------------------------------- 1 | command = $command; 26 | 27 | $this->command->line('Updating Environment File: '); 28 | } 29 | 30 | /** 31 | * Install the components. 32 | * 33 | * @return void 34 | */ 35 | public function install() 36 | { 37 | if (Str::contains(file_get_contents(base_path('.env')), 'AUTHY_SECRET')) { 38 | return; 39 | } 40 | 41 | (new Filesystem)->append( 42 | base_path('.env'), file_get_contents(SPARK_STUB_PATH.'/.env') 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Console/Installation/InstallHttp.php: -------------------------------------------------------------------------------- 1 | command = $command; 25 | 26 | $this->command->line('Updating Routes File: '); 27 | $this->command->line('Updating Controllers: '); 28 | $this->command->line('Updating Middleware: '); 29 | $this->command->line('Updating HTTP Kernel: '); 30 | } 31 | 32 | /** 33 | * Install the components. 34 | * 35 | * @return void 36 | */ 37 | public function install() 38 | { 39 | (new Filesystem)->copyDirectory(SPARK_STUB_PATH.'/app/Http', app_path('Http')); 40 | 41 | (new Filesystem)->copyDirectory(SPARK_STUB_PATH.'/routes', base_path('routes')); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Console/Installation/InstallModels.php: -------------------------------------------------------------------------------- 1 | command = $command; 23 | 24 | $this->command->line('Installing Eloquent Models: '); 25 | } 26 | 27 | /** 28 | * Install the components. 29 | * 30 | * @return void 31 | */ 32 | public function install() 33 | { 34 | copy($this->getUserModel(), app_path('Models/User.php')); 35 | 36 | copy(SPARK_STUB_PATH.'/app/Models/Team.php', app_path('Models/Team.php')); 37 | } 38 | 39 | /** 40 | * Get the path to the proper User model stub. 41 | * 42 | * @return string 43 | */ 44 | protected function getUserModel() 45 | { 46 | return $this->command->option('team-billing') 47 | ? SPARK_STUB_PATH.'/app/Models/TeamUser.php' 48 | : SPARK_STUB_PATH.'/app/Models/User.php'; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Console/Updating/RemoveDownloadPath.php: -------------------------------------------------------------------------------- 1 | line('Removing Temporary Download Directory: '); 18 | } 19 | 20 | /** 21 | * Update the components. 22 | * 23 | * @return void 24 | */ 25 | public function update() 26 | { 27 | (new Filesystem)->deleteDirectory(base_path('spark-new')); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Console/Updating/UpdateInstallation.php: -------------------------------------------------------------------------------- 1 | downloadPath = $downloadPath; 26 | 27 | $command->line('Updating Spark Directory: '); 28 | } 29 | 30 | /** 31 | * Update the components. 32 | * 33 | * @return void 34 | */ 35 | public function update() 36 | { 37 | (new Filesystem)->deleteDirectory(SPARK_PATH); 38 | 39 | rename($this->downloadPath, SPARK_PATH); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Contracts/Http/Requests/Auth/RegisterRequest.php: -------------------------------------------------------------------------------- 1 | announcement = $announcement; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/Auth/UserRegistered.php: -------------------------------------------------------------------------------- 1 | user = $user; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/Kiosk/AnnouncementCreated.php: -------------------------------------------------------------------------------- 1 | announcement = $announcement; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Events/NotificationCreated.php: -------------------------------------------------------------------------------- 1 | notification = $notification; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/PaymentMethod/BillingAddressUpdated.php: -------------------------------------------------------------------------------- 1 | billable = $billable; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/PaymentMethod/VatIdUpdated.php: -------------------------------------------------------------------------------- 1 | billable = $billable; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/Profile/ContactInformationUpdated.php: -------------------------------------------------------------------------------- 1 | user = $user; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/Subscription/SubscriptionCancelled.php: -------------------------------------------------------------------------------- 1 | user = $user; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/Subscription/SubscriptionUpdated.php: -------------------------------------------------------------------------------- 1 | user = $user; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/Subscription/UserSubscribed.php: -------------------------------------------------------------------------------- 1 | user = $user; 39 | $this->plan = $plan; 40 | $this->fromRegistration = $fromRegistration; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Events/Teams/DeletingTeam.php: -------------------------------------------------------------------------------- 1 | team = $team; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/Teams/GuestInvitedToTeam.php: -------------------------------------------------------------------------------- 1 | team = $team; 31 | $this->invitation = $invitation; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Events/Teams/Subscription/SubscriptionCancelled.php: -------------------------------------------------------------------------------- 1 | team = $team; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/Teams/Subscription/SubscriptionUpdated.php: -------------------------------------------------------------------------------- 1 | team = $team; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/Teams/Subscription/TeamSubscribed.php: -------------------------------------------------------------------------------- 1 | team = $team; 31 | $this->plan = $plan; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Events/Teams/TeamCreated.php: -------------------------------------------------------------------------------- 1 | team = $team; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/Teams/TeamDeleted.php: -------------------------------------------------------------------------------- 1 | team = $team; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/Teams/TeamMemberAdded.php: -------------------------------------------------------------------------------- 1 | team = $team; 31 | $this->member = $member; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Events/Teams/TeamMemberRemoved.php: -------------------------------------------------------------------------------- 1 | team = $team; 31 | $this->member = $member; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Events/Teams/TeamOwnerAdded.php: -------------------------------------------------------------------------------- 1 | team = $team; 31 | $this->owner = $owner; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Events/Teams/UserInvitedToTeam.php: -------------------------------------------------------------------------------- 1 | team = $team; 31 | $this->user = $user; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Exceptions/IneligibleForPlan.php: -------------------------------------------------------------------------------- 1 | hasMany(Token::class); 20 | } 21 | 22 | /** 23 | * Determine if the current API token is granted a given ability. 24 | * 25 | * @param string $ability 26 | * @return bool 27 | */ 28 | public function tokenCan($ability) 29 | { 30 | return $this->currentToken ? $this->currentToken->can($ability) : false; 31 | } 32 | 33 | /** 34 | * Get the currently used API token for the user. 35 | * 36 | * @return \Laravel\Spark\Token 37 | */ 38 | public function token() 39 | { 40 | return $this->currentToken; 41 | } 42 | 43 | /** 44 | * Set the current API token for the user. 45 | * 46 | * @param \Laravel\Spark\Token $token 47 | * @return $this 48 | */ 49 | public function setToken(Token $token) 50 | { 51 | $this->currentToken = $token; 52 | 53 | return $this; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | validate(); 27 | 28 | return Spark::interact($interaction, $parameters); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Http/Controllers/GeocodingController.php: -------------------------------------------------------------------------------- 1 | get('http://ip2c.org/?ip='.$request->ip()); 22 | 23 | $body = (string) $response->getBody(); 24 | 25 | if ($body[0] === '1') { 26 | return explode(';', $body)[1]; 27 | } 28 | } catch (Exception $e) { 29 | return response('', 404); 30 | } 31 | } 32 | 33 | /** 34 | * Get the states / provinces for a given country code. 35 | * 36 | * @param string $country 37 | * @return \Illuminate\Http\Response 38 | */ 39 | public function states($country) 40 | { 41 | return response()->json(app(StateRepository::class)->forCountry($country)->all()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Http/Controllers/InvitationController.php: -------------------------------------------------------------------------------- 1 | where('token', $token)->firstOrFail(); 20 | 21 | if ($invitation->isExpired()) { 22 | $invitation->delete(); 23 | 24 | abort(404); 25 | } 26 | 27 | return $invitation; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Http/Controllers/Kiosk/DashboardController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 17 | $this->middleware('dev'); 18 | } 19 | 20 | /** 21 | * Show the kiosk dashboard. 22 | * 23 | * @return \Illuminate\Http\Response 24 | */ 25 | public function show() 26 | { 27 | return view('spark::kiosk'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Http/Controllers/Kiosk/SearchController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 20 | $this->middleware('dev'); 21 | } 22 | 23 | /** 24 | * Get the users based on the incoming search query. 25 | * 26 | * @param \Illuminate\Http\Request $request 27 | * @return \Illuminate\Http\Response 28 | */ 29 | public function performBasicSearch(Request $request) 30 | { 31 | $query = str_replace('*', '%', $request->input('query')); 32 | 33 | return Spark::interact(UserRepository::class.'@search', [ 34 | $query, $request->user() 35 | ]); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Http/Controllers/MissingTeamController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 15 | } 16 | 17 | /** 18 | * Show the missing team notice. 19 | * 20 | * @return \Illuminate\Http\Response 21 | */ 22 | public function show() 23 | { 24 | return view('spark::missing-team'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Http/Controllers/PlanController.php: -------------------------------------------------------------------------------- 1 | json(Spark::allPlans()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/API/TokenAbilitiesController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 18 | } 19 | 20 | /** 21 | * Get all of the available token abilities. 22 | * 23 | * @return \Illuminate\Http\Response 24 | */ 25 | public function all() 26 | { 27 | return response()->json(collect(Spark::tokensCan())->map(function ($value, $key) { 28 | return [ 29 | 'name' => $value, 30 | 'value' => $key, 31 | 'default' => in_array($key, Spark::tokenDefaults()) 32 | ]; 33 | })->values()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/Billing/BillingInformationController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 18 | } 19 | 20 | /** 21 | * Update the user's extra billing information. 22 | * 23 | * @param \Illuminate\Http\Request $request 24 | * @return \Illuminate\Http\Response 25 | */ 26 | public function update(Request $request) 27 | { 28 | $this->validate($request, [ 29 | 'information' => 'max:2048', 30 | ]); 31 | 32 | $request->user()->forceFill([ 33 | 'extra_billing_information' => $request->information, 34 | ])->save(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/DashboardController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 18 | } 19 | 20 | /** 21 | * Show the settings dashboard. 22 | * 23 | * @param \Illuminate\Http\Request $request 24 | * @return \Illuminate\Http\Response 25 | */ 26 | public function show(Request $request) 27 | { 28 | return view('spark::settings'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/PaymentMethod/PaymentMethodController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 20 | } 21 | 22 | /** 23 | * Update the payment method for the user. 24 | * 25 | * @param \Laravel\Spark\Contracts\Http\Requests\Settings\PaymentMethod\UpdatePaymentMethodRequest $request 26 | * @return \Illuminate\Http\Response 27 | */ 28 | public function update(UpdatePaymentMethodRequest $request) 29 | { 30 | Spark::interact(UpdatePaymentMethod::class, [ 31 | $request->user(), $request->all(), 32 | ]); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/PaymentMethod/VatIdController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 20 | } 21 | 22 | /** 23 | * Update the VAT ID for the user. 24 | * 25 | * @param \Illuminate\Http\Request $request 26 | * @return \Illuminate\Http\Response 27 | */ 28 | public function update(Request $request) 29 | { 30 | $this->validate($request, [ 31 | 'vat_id' => 'max:50|vat_id', 32 | ]); 33 | 34 | Spark::call(UserRepository::class.'@updateVatId', [ 35 | $request->user(), $request->vat_id 36 | ]); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/Profile/ContactInformationController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 19 | } 20 | 21 | /** 22 | * Update the user's contact information settings. 23 | * 24 | * @param \Illuminate\Http\Request $request 25 | * @return \Illuminate\Http\Response 26 | */ 27 | public function update(Request $request) 28 | { 29 | $this->interaction( 30 | $request, UpdateContactInformation::class, 31 | [$request->user(), $request->all()] 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/Profile/PhotoController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 19 | } 20 | 21 | /** 22 | * Store the user's profile photo. 23 | * 24 | * @param \Illuminate\Http\Request $request 25 | * @return \Illuminate\Http\Response 26 | */ 27 | public function store(Request $request) 28 | { 29 | $this->interaction( 30 | $request, UpdateProfilePhoto::class, 31 | [$request->user(), $request->all()] 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/Teams/Billing/BillingInformationController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 19 | } 20 | 21 | /** 22 | * Update the team's extra billing information. 23 | * 24 | * @param \Illuminate\Http\Request $request 25 | * @param \Laravel\Spark\Team $team 26 | * @return \Illuminate\Http\Response 27 | */ 28 | public function update(Request $request, Team $team) 29 | { 30 | abort_unless($request->user()->ownsTeam($team), 403); 31 | 32 | $this->validate($request, [ 33 | 'information' => 'max:2048', 34 | ]); 35 | 36 | $team->forceFill([ 37 | 'extra_billing_information' => $request->information, 38 | ])->save(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/Teams/DashboardController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 18 | } 19 | 20 | /** 21 | * Show the team settings dashboard. 22 | * 23 | * @param \Illuminate\Http\Request $request 24 | * @param \Laravel\Spark\Team $team 25 | * @return \Illuminate\Http\Response 26 | */ 27 | public function show(Request $request, $team) 28 | { 29 | abort_unless($request->user()->onTeam($team), 404); 30 | 31 | return view('spark::settings.teams.team-settings', [ 32 | 'team' => $team 33 | ]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/Teams/PaymentMethod/PaymentMethodController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 21 | } 22 | 23 | /** 24 | * Update the payment method for the user. 25 | * 26 | * @param \Laravel\Spark\Contracts\Http\Requests\Settings\PaymentMethod\UpdatePaymentMethodRequest $request 27 | * @param \Laravel\Spark\Team $team 28 | * @return \Illuminate\Http\Response 29 | */ 30 | public function update(UpdatePaymentMethodRequest $request, Team $team) 31 | { 32 | abort_unless($request->user()->ownsTeam($team), 403); 33 | 34 | Spark::interact(UpdatePaymentMethod::class, [ 35 | $team, $request->all(), 36 | ]); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/Teams/PaymentMethod/VatIdController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 21 | } 22 | 23 | /** 24 | * Update the VAT ID for the team. 25 | * 26 | * @param \Illuminate\Http\Request $request 27 | * @param \Laravel\Spark\Team $team 28 | * @return \Illuminate\Http\Response 29 | */ 30 | public function update(Request $request, Team $team) 31 | { 32 | $this->validate($request, [ 33 | 'vat_id' => 'max:50|vat_id', 34 | ]); 35 | 36 | Spark::call(TeamRepository::class.'@updateVatId', [ 37 | $team, $request->vat_id 38 | ]); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/Teams/TeamMemberRoleController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 18 | } 19 | 20 | /** 21 | * Get the available team member roles. 22 | * 23 | * @return \Illuminate\Http\Response 24 | */ 25 | public function all() 26 | { 27 | $roles = []; 28 | 29 | foreach (Spark::roles() as $key => $value) { 30 | $roles[] = ['value' => $key, 'text' => $value]; 31 | } 32 | 33 | return response()->json($roles); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/Teams/TeamNameController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 18 | } 19 | 20 | /** 21 | * Update the given team's name. 22 | * 23 | * @param \Illuminate\Http\Request $request 24 | * @param \Laravel\Spark\Team $team 25 | * @return \Illuminate\Http\Response 26 | */ 27 | public function update(Request $request, $team) 28 | { 29 | abort_unless($request->user()->ownsTeam($team), 404); 30 | 31 | $this->validate($request, [ 32 | 'name' => 'required|max:255', 33 | ]); 34 | 35 | $team->forceFill([ 36 | 'name' => $request->name, 37 | ])->save(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Http/Controllers/Settings/Teams/TeamPhotoController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 19 | } 20 | 21 | /** 22 | * Update the given team's photo. 23 | * 24 | * @param \Laravel\Spark\Http\Requests\Settings\Teams\UpdateTeamPhotoRequest $request 25 | * @param \Laravel\Spark\Team $team 26 | * @return \Illuminate\Http\Response 27 | */ 28 | public function update(UpdateTeamPhotoRequest $request, $team) 29 | { 30 | $this->interaction( 31 | $request, UpdateTeamPhoto::class, 32 | [$team, $request->all()] 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Http/Controllers/StripeTokenController.php: -------------------------------------------------------------------------------- 1 | setupIntents->create(); 21 | 22 | return [ 23 | 'clientSecret' => $setupIntent->client_secret 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Http/Controllers/SupportController.php: -------------------------------------------------------------------------------- 1 | interaction($request, SendSupportEmail::class, [ 19 | $request->all(), 20 | ]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Http/Controllers/TaxRateController.php: -------------------------------------------------------------------------------- 1 | filled('city', 'zip', 'country')) { 19 | return response()->json(['rate' => 0]); 20 | } 21 | 22 | $user = Spark::user(); 23 | 24 | $user->forceFill([ 25 | 'vat_id' => $request->vat_id, 26 | 'billing_city' => $request->city, 27 | 'billing_state' => $request->state, 28 | 'billing_zip' => $request->zip, 29 | 'billing_country' => $request->country, 30 | 'card_country' => $request->country, 31 | ]); 32 | 33 | return response()->json([ 34 | 'rate' => $user->taxPercentage() 35 | ]); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Http/Controllers/TermsController.php: -------------------------------------------------------------------------------- 1 | getLocale().'.md')) 17 | ? base_path('terms.'.app()->getLocale().'.md') 18 | : base_path('terms.md'); 19 | 20 | return view('spark::terms', [ 21 | 'terms' => (new Parsedown)->text(file_get_contents($termsFile)) 22 | ]); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Http/Controllers/TokenController.php: -------------------------------------------------------------------------------- 1 | tokens = $tokens; 26 | 27 | $this->middleware('auth'); 28 | } 29 | 30 | /** 31 | * Exchange the current transient API token for a new one. 32 | * 33 | * @param \Illuminate\Http\Request $request 34 | * @return \Illuminate\Http\Response 35 | */ 36 | public function refresh(Request $request) 37 | { 38 | $this->tokens->deleteExpiredTokens($request->user()); 39 | 40 | return response('Refreshed.')->withCookie( 41 | $this->tokens->createTokenCookie($request->user()) 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Http/Controllers/UserController.php: -------------------------------------------------------------------------------- 1 | middleware('auth')->only( 20 | 'updateLastReadAnnouncementsTimestamp' 21 | ); 22 | } 23 | 24 | /** 25 | * Get the current user of the application. 26 | * 27 | * @return \Illuminate\Http\Response 28 | */ 29 | public function current() 30 | { 31 | return Spark::interact(UserRepository::class.'@current'); 32 | } 33 | 34 | /** 35 | * Update the last read announcements timestamp. 36 | * 37 | * @param \Illuminate\Http\Request $request 38 | * @return \Illuminate\Http\Response 39 | */ 40 | public function updateLastReadAnnouncementsTimestamp(Request $request) 41 | { 42 | $request->user()->forceFill([ 43 | 'last_read_announcements_at' => Carbon::now(), 44 | ])->save(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Http/Middleware/VerifyUserHasTeam.php: -------------------------------------------------------------------------------- 1 | user() && ! $request->user()->hasTeams()) { 19 | return redirect(Spark::teamsPrefix().'/missing'); 20 | } 21 | 22 | return $next($request); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Http/Middleware/VerifyUserIsDeveloper.php: -------------------------------------------------------------------------------- 1 | user() && Spark::developer($request->user()->email)) { 19 | return $next($request); 20 | } 21 | 22 | return $request->ajax() || $request->wantsJson() 23 | ? response('Unauthorized.', 401) 24 | : redirect()->guest('login'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Http/Requests/Auth/StripeRegisterRequest.php: -------------------------------------------------------------------------------- 1 | registerValidator(['stripe_payment_method']); 21 | 22 | if (Spark::collectsBillingAddress() && $this->hasPaidPlan()) { 23 | $this->validateBillingAddress($validator); 24 | } 25 | 26 | return $validator; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Http/Requests/Settings/API/CreateTokenRequest.php: -------------------------------------------------------------------------------- 1 | all(), [ 33 | 'stripe_payment_method' => 'required', 34 | ]); 35 | 36 | if (Spark::collectsBillingAddress()) { 37 | $this->validateBillingAddress($validator); 38 | } 39 | 40 | return $validator; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Http/Requests/Settings/Security/EnableTwoFactorAuthRequest.php: -------------------------------------------------------------------------------- 1 | 'required|numeric', 28 | 'phone' => 'required|numeric', 29 | ]; 30 | } 31 | 32 | /** 33 | * Get data to be validated from the request. 34 | * 35 | * @return array 36 | */ 37 | public function validationData() 38 | { 39 | if ($this->phone) { 40 | $this->merge(['phone' => preg_replace('/[^0-9]/', '', $this->phone)]); 41 | } 42 | 43 | return $this->all(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Http/Requests/Settings/Subscription/CreateSubscriptionRequest.php: -------------------------------------------------------------------------------- 1 | valid($this->coupon)) { 31 | $validator->errors()->add('coupon', __('This coupon code is invalid.')); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Http/Requests/Settings/Subscription/UpdateSubscriptionRequest.php: -------------------------------------------------------------------------------- 1 | all(), [ 31 | 'plan' => 'required|in:'.Spark::activePlanIdList() 32 | ]); 33 | 34 | return $validator->after(function ($validator) { 35 | $this->validatePlanEligibility($validator); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Http/Requests/Settings/Teams/RemoveTeamMemberRequest.php: -------------------------------------------------------------------------------- 1 | route('team'); 17 | 18 | $member = $this->route('team_member'); 19 | 20 | return ($this->user()->ownsTeam($team) && $this->user()->id !== $member->id) || 21 | (! $this->user()->ownsTeam($team) && $this->user()->id === $member->id); 22 | } 23 | 24 | /** 25 | * Get the validation rules for the request. 26 | * 27 | * @return array 28 | */ 29 | public function rules() 30 | { 31 | return []; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Http/Requests/Settings/Teams/Subscription/CreateStripeSubscriptionRequest.php: -------------------------------------------------------------------------------- 1 | baseValidator([ 21 | 'stripe_payment_method' => 'required_if:existing_card,0', 22 | 'vat_id' => 'nullable|max:50|vat_id', 23 | ]); 24 | 25 | if (Spark::collectsBillingAddress()) { 26 | $this->validateBillingAddress($validator); 27 | } 28 | 29 | return $validator; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Http/Requests/Settings/Teams/UpdateTeamPhotoRequest.php: -------------------------------------------------------------------------------- 1 | user()->ownsTeam($this->route('team')); 17 | } 18 | 19 | /** 20 | * Get the validation rules for the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'photo' => 'required|image|max:4000' 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Http/Requests/ValidatesBillingAddresses.php: -------------------------------------------------------------------------------- 1 | mergeCardCountryIntoRequest(); 18 | 19 | $validator->addRules([ 20 | 'address' => 'required|max:255', 21 | 'address_line_2' => 'max:255', 22 | 'city' => 'required|max:255', 23 | 'state' => 'required|max:255|state:'.$this->country, 24 | 'zip' => 'required|max:25', 25 | 'country' => 'required|max:2|country', 26 | ]); 27 | } 28 | 29 | /** 30 | * Merge the billing card country into the request. 31 | * 32 | * @return void 33 | */ 34 | protected function mergeCardCountryIntoRequest() 35 | { 36 | if (! $this->stripe_payment_method) { 37 | return; 38 | } 39 | 40 | $this->merge(['card_country' => app(StripeService::class)->countryForToken( 41 | $this->stripe_payment_method 42 | )]); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Interactions/CheckPlanEligibility.php: -------------------------------------------------------------------------------- 1 | applyCoupon($coupon); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Interactions/Settings/Security/DisableTwoFactorAuthUsingAuthy.php: -------------------------------------------------------------------------------- 1 | authy = $authy; 26 | } 27 | 28 | /** 29 | * {@inheritdoc} 30 | */ 31 | public function handle($user) 32 | { 33 | $this->authy->disable($user->authy_id); 34 | 35 | $user->forceFill([ 36 | 'authy_id' => null, 37 | ])->save(); 38 | 39 | return $user; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Interactions/Settings/Security/EnableTwoFactorAuthUsingAuthy.php: -------------------------------------------------------------------------------- 1 | authy = $authy; 26 | } 27 | 28 | /** 29 | * {@inheritdoc} 30 | */ 31 | public function handle($user, $countryCode, $phoneNumber) 32 | { 33 | $user->forceFill([ 34 | 'authy_id' => $this->authy->enable( 35 | $user->email, $phoneNumber, $countryCode 36 | ), 37 | ])->save(); 38 | 39 | return $user; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Interactions/Settings/Security/VerifyTwoFactorAuthTokenUsingAuthy.php: -------------------------------------------------------------------------------- 1 | authy = $authy; 26 | } 27 | 28 | /** 29 | * {@inheritdoc} 30 | */ 31 | public function handle($user, $token) 32 | { 33 | return $this->authy->verify($user->authy_id, $token); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Interactions/Settings/Teams/AddTeamMember.php: -------------------------------------------------------------------------------- 1 | users()->attach($user, ['role' => $role ?: Spark::defaultRole()]); 18 | 19 | event(new TeamMemberAdded($team, $user)); 20 | 21 | try { 22 | if (Spark::chargesTeamsPerMember() && $team->subscription() && 23 | $team->users()->count() > 1 24 | ) { 25 | $team->addSeat(); 26 | } 27 | } catch (IncompletePayment $e) { 28 | // We'll do nothing since members are added by accepting an invitation so 29 | // there's no immediate action the invited user can take. We'll leave it 30 | // to the team owner to notice the subscription has a pending payment. 31 | } 32 | 33 | return $team; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Interactions/Settings/Teams/UpdateTeamMember.php: -------------------------------------------------------------------------------- 1 | 'required|in:'.implode(',', array_keys(Spark::roles())), 18 | ]); 19 | } 20 | 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function handle($team, $member, array $data) 25 | { 26 | $team->users()->updateExistingPivot($member->id, [ 27 | 'role' => $data['role'] 28 | ]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Interactions/Support/SendSupportEmail.php: -------------------------------------------------------------------------------- 1 | 'required', 23 | 'subject' => 'required|max:2048', 24 | 'message' => 'required', 25 | ]); 26 | } 27 | 28 | /** 29 | * {@inheritdoc} 30 | */ 31 | public function handle(array $data) 32 | { 33 | if (! Spark::hasSupportAddress()) { 34 | throw new RuntimeException(__("No customer support request recipient is defined.")); 35 | } 36 | 37 | Mail::raw($data['message'], function ($m) use ($data) { 38 | $m->to(Spark::supportAddress())->subject(__('Support Request: ').$data['subject']); 39 | 40 | $m->replyTo($data['from']); 41 | }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/InteractsWithSparkApi.php: -------------------------------------------------------------------------------- 1 | get( 19 | $this->sparkUrl.'/api/releases/all-versions' 20 | )->getBody()); 21 | 22 | return collect($response)->filter(function ($version) use ($major) { 23 | return ! $major || Str::startsWith($version, $major); 24 | })->sort('version_compare')->last(); 25 | } 26 | 27 | /** 28 | * The Spark base URL. 29 | * 30 | * @var string 31 | */ 32 | protected $sparkUrl = 'https://spark.laravel.com'; 33 | } 34 | -------------------------------------------------------------------------------- /src/JWT.php: -------------------------------------------------------------------------------- 1 | user->hasBillingProvider()) { 15 | $customer = $event->user->asStripeCustomer(); 16 | 17 | $customer->email = $event->user->email; 18 | 19 | $customer->save(); 20 | } 21 | 22 | if (isset($event->user->ownedTeams)) { 23 | $this->updateForTeams($event->user); 24 | } 25 | } 26 | 27 | /** 28 | * Update contact information for owned teams. 29 | * 30 | * @param \Illuminate\Contracts\Auth\Authenticatable $user 31 | * @return void 32 | */ 33 | private function updateForTeams($user) 34 | { 35 | foreach ($user->ownedTeams as $team) { 36 | if ($team->hasBillingProvider()) { 37 | $customer = $team->asStripeCustomer(); 38 | 39 | $customer->email = $user->email; 40 | 41 | $customer->save(); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Listeners/Subscription/UpdateActiveSubscription.php: -------------------------------------------------------------------------------- 1 | user->subscription()->provider_plan; 19 | 20 | $event->user->forceFill([ 21 | 'current_billing_plan' => $currentPlan, 22 | ])->save(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Listeners/Subscription/UpdateTaxPercentageOnStripe.php: -------------------------------------------------------------------------------- 1 | billable->subscription(); 16 | 17 | if (! $subscription || ! $subscription->valid()) { 18 | return; 19 | } 20 | 21 | $stripeSubscription = $subscription->asStripeSubscription(); 22 | 23 | $stripeSubscription->tax_percent = $event->billable->taxPercentage(); 24 | 25 | $stripeSubscription->save(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Listeners/Subscription/UpdateTrialEndingDate.php: -------------------------------------------------------------------------------- 1 | user->forceFill([ 16 | 'trial_ends_at' => $event->user->subscription()->trial_ends_at, 17 | ])->save(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Listeners/Teams/Subscription/UpdateActiveSubscription.php: -------------------------------------------------------------------------------- 1 | team->subscription()->provider_plan; 19 | 20 | $event->team->forceFill([ 21 | 'current_billing_plan' => $currentPlan, 22 | ])->save(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Listeners/Teams/Subscription/UpdateTrialEndingDate.php: -------------------------------------------------------------------------------- 1 | team->forceFill([ 16 | 'trial_ends_at' => $event->team->subscription()->trial_ends_at, 17 | ])->save(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/LocalInvoice.php: -------------------------------------------------------------------------------- 1 | belongsTo(Spark::userModel(), 'user_id'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Services/Stripe.php: -------------------------------------------------------------------------------- 1 | paymentMethods->retrieve($token)->card->country; 19 | } 20 | 21 | /** 22 | * Verify that the given token origin country matches the given country. 23 | * 24 | * @param string $token 25 | * @param string $country 26 | * @return bool 27 | */ 28 | public function tokenIsForCountry($token, $country) 29 | { 30 | return $this->countryForToken($token) === $country; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Spark.php: -------------------------------------------------------------------------------- 1 | stripe_price; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/TaxRate.php: -------------------------------------------------------------------------------- 1 | countries = $countries; 25 | } 26 | 27 | /** 28 | * Validate the given data. 29 | * 30 | * @param string $attribute 31 | * @param mixed $value 32 | * @param array $parameters 33 | * @return bool 34 | */ 35 | public function validate($attribute, $value, $parameters) 36 | { 37 | return in_array($value, array_keys($this->countries->all())); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Validation/StateValidator.php: -------------------------------------------------------------------------------- 1 | states = $states; 25 | } 26 | 27 | /** 28 | * Validate the given data. 29 | * 30 | * @param string $attribute 31 | * @param mixed $value 32 | * @param array $parameters 33 | * @return bool 34 | */ 35 | public function validate($attribute, $value, $parameters) 36 | { 37 | if (empty($parameters)) { 38 | return true; 39 | } 40 | 41 | $states = $this->states->forCountry($parameters[0])->flatten()->map(function ($item, $key) { 42 | return strtoupper($item); 43 | })->all(); 44 | 45 | return empty($states) || in_array(strtoupper($value), $states); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Validation/VatIdValidator.php: -------------------------------------------------------------------------------- 1 | isValidVATNumber($value); 22 | } catch (Exception $e) { 23 | return false; 24 | } 25 | } 26 | } 27 | --------------------------------------------------------------------------------