Initial Spark Install

This commit is contained in:
Deon George
2017-11-03 16:26:07 +11:00
commit b1a5807eb3
766 changed files with 128896 additions and 0 deletions

View File

@@ -0,0 +1,212 @@
<spark-kiosk-announcements inline-template>
<div>
<div class="panel panel-default">
<div class="panel-heading">Create Announcement</div>
<div class="panel-body">
<div class="alert alert-info">
Announcements you create here will be sent to the "Product Announcements" section of
the notifications modal window, informing your users about new features and improvements
to your application.
</div>
<form class="form-horizontal" role="form">
<!-- Announcement -->
<div class="form-group" :class="{'has-error': createForm.errors.has('body')}">
<label class="col-md-4 control-label">Announcement</label>
<div class="col-md-6">
<textarea class="form-control" name="announcement" rows="7" v-model="createForm.body" style="font-family: monospace;">
</textarea>
<span class="help-block" v-show="createForm.errors.has('body')">
@{{ createForm.errors.get('body') }}
</span>
</div>
</div>
<!-- Action Text -->
<div class="form-group" :class="{'has-error': createForm.errors.has('action_text')}">
<label class="col-md-4 control-label">Action Button Text</label>
<div class="col-md-6">
<input type="text" class="form-control" name="action_text" v-model="createForm.action_text">
<span class="help-block" v-show="createForm.errors.has('action_text')">
@{{ createForm.errors.get('action_text') }}
</span>
</div>
</div>
<!-- Action URL -->
<div class="form-group" :class="{'has-error': createForm.errors.has('action_url')}">
<label class="col-md-4 control-label">Action Button URL</label>
<div class="col-md-6">
<input type="text" class="form-control" name="action_url" v-model="createForm.action_url">
<span class="help-block" v-show="createForm.errors.has('action_url')">
@{{ createForm.errors.get('action_url') }}
</span>
</div>
</div>
<!-- Create Button -->
<div class="form-group">
<div class="col-md-offset-4 col-md-6">
<button type="submit" class="btn btn-primary"
@click.prevent="create"
:disabled="createForm.busy">
Create
</button>
</div>
</div>
</form>
</div>
</div>
<!-- Recent Announcements List -->
<div class="panel panel-default" v-if="announcements.length > 0">
<div class="panel-heading">Recent Announcements</div>
<div class="panel-body">
<table class="table table-borderless m-b-none">
<thead>
<th></th>
<th>Date</th>
<th></th>
<th></th>
</thead>
<tbody>
<tr v-for="announcement in announcements">
<!-- Photo -->
<td>
<img :src="announcement.creator.photo_url" class="spark-profile-photo">
</td>
<!-- Date -->
<td>
<div class="btn-table-align">
@{{ announcement.created_at | datetime }}
</div>
</td>
<!-- Edit Button -->
<td>
<button class="btn btn-primary" @click="editAnnouncement(announcement)">
<i class="fa fa-pencil"></i>
</button>
</td>
<!-- Delete Button -->
<td>
<button class="btn btn-danger-outline" @click="approveAnnouncementDelete(announcement)">
<i class="fa fa-times"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Edit Announcement Modal -->
<div class="modal fade" id="modal-update-announcement" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" v-if="updatingAnnouncement">
<div class="modal-content">
<div class="modal-header">
<button type="button " class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">
Update Announcement
</h4>
</div>
<div class="modal-body">
<!-- Update Announcement -->
<form class="form-horizontal" role="form">
<!-- Announcement -->
<div class="form-group" :class="{'has-error': updateForm.errors.has('body')}">
<label class="col-md-4 control-label">Announcement</label>
<div class="col-md-6">
<textarea class="form-control" rows="7" v-model="updateForm.body" style="font-family: monospace;">
</textarea>
<span class="help-block" v-show="updateForm.errors.has('body')">
@{{ updateForm.errors.get('body') }}
</span>
</div>
</div>
<!-- Action Text -->
<div class="form-group" :class="{'has-error': updateForm.errors.has('action_text')}">
<label class="col-md-4 control-label">Action Button Text</label>
<div class="col-md-6">
<input type="text" class="form-control" name="action_text" v-model="updateForm.action_text">
<span class="help-block" v-show="updateForm.errors.has('action_text')">
@{{ updateForm.errors.get('action_text') }}
</span>
</div>
</div>
<!-- Action URL -->
<div class="form-group" :class="{'has-error': updateForm.errors.has('action_url')}">
<label class="col-md-4 control-label">Action Button URL</label>
<div class="col-md-6">
<input type="text" class="form-control" name="action_url" v-model="updateForm.action_url">
<span class="help-block" v-show="updateForm.errors.has('action_url')">
@{{ updateForm.errors.get('action_url') }}
</span>
</div>
</div>
</form>
</div>
<!-- Modal Actions -->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" @click="update" :disabled="updateForm.busy">
Update
</button>
</div>
</div>
</div>
</div>
<!-- Delete Announcement Modal -->
<div class="modal fade" id="modal-delete-announcement" tabindex="-1" role="dialog">
<div class="modal-dialog" v-if="deletingAnnouncement">
<div class="modal-content">
<div class="modal-header">
<button type="button " class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">
Delete Announcement
</h4>
</div>
<div class="modal-body">
Are you sure you want to delete this announcement?
</div>
<!-- Modal Actions -->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">No, Go Back</button>
<button type="button" class="btn btn-danger" @click="deleteAnnouncement" :disabled="deleteForm.busy">
Yes, Delete
</button>
</div>
</div>
</div>
</div>
</div>
</spark-kiosk-announcements>

View File

@@ -0,0 +1,197 @@
<spark-kiosk-metrics :user="user" inline-template>
<!-- The Landsman™ -->
<div>
<div class="row">
<!-- Monthly Recurring Revenue -->
<div class="col-md-6">
<div class="panel panel-success">
<div class="panel-heading text-center">Monthly Recurring Revenue</div>
<div class="panel-body text-center">
<div style="font-size: 24px;">
@{{ monthlyRecurringRevenue | currency }}
</div>
<!-- Compared To Last Month -->
<div v-if="monthlyChangeInMonthlyRecurringRevenue" style="font-size: 12px;">
@{{ monthlyChangeInMonthlyRecurringRevenue }}% From Last Month
</div>
<!-- Compared To Last Year -->
<div v-if="yearlyChangeInMonthlyRecurringRevenue" style="font-size: 12px;">
@{{ yearlyChangeInMonthlyRecurringRevenue }}% From Last Year
</div>
</div>
</div>
</div>
<!-- Yearly Recurring Revenue -->
<div class="col-md-6">
<div class="panel panel-success">
<div class="panel-heading text-center">Yearly Recurring Revenue</div>
<div class="panel-body text-center">
<div style="font-size: 24px;">
@{{ yearlyRecurringRevenue | currency }}
</div>
<!-- Compared To Last Month -->
<div v-if="monthlyChangeInYearlyRecurringRevenue" style="font-size: 12px;">
@{{ monthlyChangeInYearlyRecurringRevenue }}% From Last Month
</div>
<!-- Compared To Last Year -->
<div v-if="yearlyChangeInYearlyRecurringRevenue" style="font-size: 12px;">
@{{ yearlyChangeInYearlyRecurringRevenue }}% From Last Year
</div>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Total Volume -->
<div class="col-md-6">
<div class="panel panel-success">
<div class="panel-heading text-center">Total Volume</div>
<div class="panel-body text-center">
<span style="font-size: 24px;">
@{{ totalVolume | currency }}
</span>
</div>
</div>
</div>
<!-- Total Trials -->
<div class="col-md-6">
<div class="panel panel-info">
@if(Spark::teamTrialDays())
<div class="panel-heading text-center">Teams Currently Trialing</div>
@else
<div class="panel-heading text-center">Users Currently Trialing</div>
@endif
<div class="panel-body text-center">
<span style="font-size: 24px;">
@{{ totalTrialUsers }}
</span>
</div>
</div>
</div>
</div>
<!-- Monthly Recurring Revenue Chart -->
<div class="row" v-show="indicators.length > 0">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">Monthly Recurring Revenue</div>
<div class="panel-body">
<canvas id="monthlyRecurringRevenueChart" height="100"></canvas>
</div>
</div>
</div>
</div>
<!-- Yearly Recurring Revenue Chart -->
<div class="row" v-show="indicators.length > 0">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">Yearly Recurring Revenue</div>
<div class="panel-body">
<canvas id="yearlyRecurringRevenueChart" height="100"></canvas>
</div>
</div>
</div>
</div>
<div class="row" v-show="indicators.length > 0">
<!-- Daily Volume Chart -->
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">Daily Volume</div>
<div class="panel-body">
<canvas id="dailyVolumeChart" height="100"></canvas>
</div>
</div>
</div>
<!-- Daily New Users Chart -->
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">New Users</div>
<div class="panel-body">
<canvas id="newUsersChart" height="100"></canvas>
</div>
</div>
</div>
</div>
<!-- Subscribers Per Plan -->
<div class="row" v-if="plans.length > 0">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">Subscribers</div>
<div class="panel-body">
<table class="table table-borderless m-b-none">
<thead>
<th>Name</th>
<th>Subscribers</th>
<th>Trialing</th>
</thead>
<tbody>
<tr v-if="genericTrialUsers">
<td>
<div class="btn-table-align">
On Generic Trial
</div>
</td>
<td>
<div class="btn-table-align">
N/A
</div>
</td>
<td>
<div class="btn-table-align">
@{{ genericTrialUsers }}
</div>
</td>
</tr>
<tr v-for="plan in plans">
<!-- Plan Name -->
<td>
<div class="btn-table-align">
@{{ plan.name }} (@{{ plan.interval | capitalize }})
</div>
</td>
<!-- Subscriber Count -->
<td>
<div class="btn-table-align">
@{{ plan.count }}
</div>
</td>
<!-- Trialing Count -->
<td>
<div class="btn-table-align">
@{{ plan.trialing }}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</spark-kiosk-metrics>

View File

@@ -0,0 +1,127 @@
<spark-kiosk-add-discount inline-template>
<div>
<div class="modal fade" id="modal-add-discount" tabindex="-1" role="dialog">
<div class="modal-dialog" v-if="discountingUser">
<div class="modal-content">
<div class="modal-header">
<button type="button " class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">
Add Discount (@{{ discountingUser.name }})
</h4>
</div>
<div class="modal-body">
<!-- Current Discount -->
<div class="alert alert-success" v-if="currentDiscount">
This user has a discount of @{{ formattedDiscount(currentDiscount) }}
for @{{ formattedDiscountDuration(currentDiscount) }}.
</div>
<!-- Add Discount Form -->
<form class="form-horizontal" role="form">
<!-- Discount Type -->
<div class="form-group" :class="{'has-error': form.errors.has('type')}">
<label class="col-sm-4 control-label">Discount Type</label>
<div class="col-sm-6">
<div class="radio">
<label>
<input type="radio" value="amount" v-model="form.type">&nbsp;&nbsp;Amount
</label>
</div>
<div class="radio">
<label>
<input type="radio" value="percent" v-model="form.type">&nbsp;&nbsp;Percentage
</label>
</div>
<span class="help-block" v-show="form.errors.has('type')">
@{{ form.errors.get('type') }}
</span>
</div>
</div>
<!-- Discount Value -->
<div class="form-group" :class="{'has-error': form.errors.has('value')}">
<label class="col-md-4 control-label">
<span v-if="form.type == 'percent'">Percentage</span>
<span v-if="form.type == 'amount'">Amount</span>
</label>
<div class="col-md-6">
<input type="text" class="form-control" v-model="form.value">
<span class="help-block" v-show="form.errors.has('value')">
@{{ form.errors.get('value') }}
</span>
</div>
</div>
<!-- Discount Duration -->
<div class="form-group" :class="{'has-error': form.errors.has('duration')}">
<label class="col-sm-4 control-label">Discount Duration</label>
<div class="col-sm-6">
<div class="radio">
<label>
<input type="radio" value="once" v-model="form.duration">&nbsp;&nbsp;Once
</label>
</div>
<div class="radio">
<label>
<input type="radio" value="forever" v-model="form.duration">&nbsp;&nbsp;Forever
</label>
</div>
<div class="radio">
<label>
<input type="radio" value="repeating" v-model="form.duration">&nbsp;&nbsp;Multiple Months
</label>
</div>
<span class="help-block" v-show="form.errors.has('duration')">
@{{ form.errors.get('duration') }}
</span>
</div>
</div>
<!-- Duration Months -->
<div class="form-group" :class="{'has-error': form.errors.has('months')}" v-if="form.duration == 'repeating'">
<label class="col-md-4 control-label">
Months
</label>
<div class="col-md-6">
<input type="text" class="form-control" v-model="form.months">
<span class="help-block" v-show="form.errors.has('months')">
@{{ form.errors.get('months') }}
</span>
</div>
</div>
</form>
</div>
<!-- Modal Actions -->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" @click="applyDiscount" :disabled="form.busy">
<span v-if="form.busy">
<i class="fa fa-btn fa-spinner fa-spin"></i>Applying
</span>
<span v-else>
Apply Discount
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</spark-kiosk-add-discount>

View File

@@ -0,0 +1,148 @@
<spark-kiosk-profile :user="user" :plans="plans" inline-template>
<div>
<!-- Loading Indicator -->
<div class="row" v-if="loading">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-body">
<i class="fa fa-btn fa-spinner fa-spin"></i>Loading
</div>
</div>
</div>
</div>
<!-- User Profile -->
<div v-if=" ! loading && profile">
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<!-- User Name -->
<div class="pull-left">
<div class="btn-table-align">
<i class="fa fa-btn fa-times" style="cursor: pointer;" @click="showSearch"></i>
@{{ profile.name }}
</div>
</div>
<!-- Profile Actions -->
<div class="pull-right" style="padding-top: 2px;">
<div class="btn-group" role="group">
<!-- Apply Discount -->
<button class="btn btn-default" v-if="spark.usesStripe && profile.stripe_id" @click="addDiscount(profile)">
<i class="fa fa-gift"></i>
</button>
<!-- Impersonate Button -->
<button class="btn btn-default" @click="impersonate(profile)" :disabled="user.id === profile.id">
<i class="fa fa-user-secret"></i>
</button>
</div>
</div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<div class="row">
<!-- Profile Photo -->
<div class="col-md-3 text-center">
<img :src="profile.photo_url" class="spark-profile-photo-xl">
</div>
<div class="col-md-9">
<!-- Email Address -->
<p>
<strong>Email Address:</strong> <a :href="'mailto:'+profile.email">@{{ profile.email }}</a>
</p>
<!-- Joined Date -->
<p>
<strong>Joined:</strong> @{{ profile.created_at | datetime }}
</p>
<!-- Subscription -->
<p>
<strong>Subscription:</strong>
<span v-if="activePlan(profile)">
<a :href="customerUrlOnBillingProvider(profile)" target="_blank">
@{{ activePlan(profile).name }} (@{{ activePlan(profile).interval | capitalize }})
</a>
</span>
<span v-else>
None
</span>
</p>
<!-- Total Revenue -->
<p>
<strong>Total Revenue:</strong> @{{ revenue | currency(spark.currencySymbol) }}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Teams -->
<div class="row" v-if="spark.usesTeams && profile.owned_teams.length > 0">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
{{ ucfirst(str_plural(Spark::teamString())) }}
</div>
<div class="panel-body">
<table class="table table-borderless m-b-none">
<thead>
<th></th>
<th>Name</th>
<th>Subscription</th>
</thead>
<tbody>
<tr v-for="team in profile.owned_teams">
<!-- Photo -->
<td>
<img :src="team.photo_url" class="spark-team-photo">
</td>
<!-- Team Name -->
<td>
<div class="btn-table-align">
@{{ team.name }}
</div>
</td>
<!-- Subscription -->
<td>
<div class="btn-table-align">
<span v-if="activePlan(team)">
<a :href="customerUrlOnBillingProvider(team)" target="_blank">
@{{ activePlan(team).name }} (@{{ activePlan(team).interval | capitalize }})
</a>
</span>
<span v-else>
None
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- Apply Discount Modal -->
<div>
@include('spark::kiosk.modals.add-discount')
</div>
</div>
</spark-kiosk-profile>

View File

@@ -0,0 +1,92 @@
<spark-kiosk-users :user="user" inline-template>
<div>
<div v-show=" ! showingUserProfile">
<!-- Search Field Panel -->
<div class="panel panel-default panel-flush" style="border: 0;">
<div class="panel-body">
<form class="form-horizontal p-b-none" role="form" @submit.prevent>
<!-- Search Field -->
<div class="form-group m-b-none">
<div class="col-md-12">
<input type="text" id="kiosk-users-search" class="form-control"
name="search"
placeholder="Search By Name Or E-Mail Address..."
v-model="searchForm.query"
@keyup.enter="search">
</div>
</div>
</form>
</div>
</div>
<!-- Searching -->
<div class="panel panel-default" v-if="searching">
<div class="panel-heading">Search Results</div>
<div class="panel-body">
<i class="fa fa-btn fa-spinner fa-spin"></i>Searching
</div>
</div>
<!-- No Search Results -->
<div class="panel panel-warning" v-if=" ! searching && noSearchResults">
<div class="panel-heading">Search Results</div>
<div class="panel-body">
No users matched the given criteria.
</div>
</div>
<!-- User Search Results -->
<div class="panel panel-default" v-if=" ! searching && searchResults.length > 0">
<div class="panel-heading">Search Results</div>
<div class="panel-body">
<table class="table table-borderless m-b-none">
<thead>
<th></th>
<th>Name</th>
<th>E-Mail Address</th>
<th></th>
</thead>
<tbody>
<tr v-for="searchUser in searchResults">
<!-- Profile Photo -->
<td>
<img :src="searchUser.photo_url" class="spark-profile-photo">
</td>
<!-- Name -->
<td>
<div class="btn-table-align">
@{{ searchUser.name }}
</div>
</td>
<!-- E-Mail Address -->
<td>
<div class="btn-table-align">
@{{ searchUser.email }}
</div>
</td>
<td>
<!-- View User Profile -->
<button class="btn btn-default" @click="showUserProfile(searchUser)">
<i class="fa fa-search"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- User Profile Detail -->
<div v-show="showingUserProfile">
@include('spark::kiosk.profile')
</div>
</div>
</spark-kiosk-users>