1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-19 16:01:34 +02:00

Working on UI for subscriptions

This commit is contained in:
Hillel Coren 2017-11-28 09:57:02 +02:00
parent df937c72a5
commit f761ff289c
9 changed files with 391 additions and 1 deletions

View File

@ -0,0 +1,158 @@
<?php
namespace App\Http\Controllers;
use App\Models\Subscription;
use App\Services\SubscriptionService;
use Auth;
use Input;
use Redirect;
use Session;
use URL;
use Validator;
use View;
/**
* Class SubscriptionController.
*/
class SubscriptionController extends BaseController
{
/**
* @var SubscriptionService
*/
protected $subscriptionService;
/**
* SubscriptionController constructor.
*
* @param SubscriptionService $subscriptionService
*/
public function __construct(SubscriptionService $subscriptionService)
{
//parent::__construct();
$this->subscriptionService = $subscriptionService;
}
/**
* @return \Illuminate\Http\RedirectResponse
*/
public function index()
{
return Redirect::to('settings/' . ACCOUNT_API_TOKENS);
}
/**
* @return \Illuminate\Http\JsonResponse
*/
public function getDatatable()
{
return $this->subscriptionService->getDatatable(Auth::user()->id);
}
/**
* @param $publicId
*
* @return \Illuminate\Contracts\View\View
*/
public function edit($publicId)
{
$subscription = Subscription::scope($publicId)->firstOrFail();
$data = [
'subscription' => $subscription,
'method' => 'PUT',
'url' => 'subscriptions/' . $publicId,
'title' => trans('texts.edit_subscription'),
];
return View::make('accounts.subscription', $data);
}
/**
* @param $publicId
*
* @return \Illuminate\Http\RedirectResponse
*/
public function update($publicId)
{
return $this->save($publicId);
}
/**
* @return \Illuminate\Http\RedirectResponse
*/
public function store()
{
return $this->save();
}
/**
* @return \Illuminate\Contracts\View\View
*/
public function create()
{
$data = [
'subscription' => null,
'method' => 'POST',
'url' => 'subscriptions',
'title' => trans('texts.add_subscription'),
];
return View::make('accounts.subscription', $data);
}
/**
* @return \Illuminate\Http\RedirectResponse
*/
public function bulk()
{
$action = Input::get('bulk_action');
$ids = Input::get('bulk_public_id');
$count = $this->subscriptionService->bulk($ids, $action);
Session::flash('message', trans('texts.archived_subscription'));
return Redirect::to('settings/' . ACCOUNT_API_TOKENS);
}
/**
* @param bool $subscriptionPublicId
*
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function save($subscriptionPublicId = false)
{
if (Auth::user()->account->hasFeature(FEATURE_API)) {
$rules = [
'event_id' => 'required',
'target_url' => 'required|url',
];
if ($subscriptionPublicId) {
$subscription = Subscription::scope($subscriptionPublicId)->firstOrFail();
} else {
$subscription = Subscription::createNew();
}
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return Redirect::to($subscriptionPublicId ? 'subscriptions/edit' : 'subscriptions/create')->withInput()->withErrors($validator);
}
$subscription->fill(request()->all());
$subscription->save();
if ($subscriptionPublicId) {
$message = trans('texts.updated_subscription');
} else {
$message = trans('texts.created_subscription');
}
Session::flash('message', $message);
}
return Redirect::to('settings/' . ACCOUNT_API_TOKENS);
}
}

View File

@ -8,15 +8,24 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class Subscription.
*/
class Subscription extends Eloquent
class Subscription extends EntityModel
{
/**
* @var bool
*/
public $timestamps = true;
use SoftDeletes;
/**
* @var array
*/
protected $dates = ['deleted_at'];
/**
* @var array
*/
protected $fillable = [
'event_id',
'target_url',
];
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Ninja\Repositories;
use App\Models\Subscription;
use DB;
class SubscriptionRepository extends BaseRepository
{
public function getClassName()
{
return 'App\Models\Subscription';
}
public function find($userId)
{
$query = DB::table('account_subscriptions')
->where('account_subscriptions.user_id', '=', $userId)
->whereNull('account_subscriptions.deleted_at');
return $query->select('account_subscriptions.public_id', 'account_subscriptions.name', 'account_subscriptions.subscription', 'account_subscriptions.public_id', 'account_subscriptions.deleted_at');
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Services;
use App\Ninja\Datatables\SubscriptionDatatable;
use App\Ninja\Repositories\SubscriptionRepository;
/**
* Class SubscriptionService.
*/
class SubscriptionService extends BaseService
{
/**
* @var SubscriptionRepository
*/
protected $subscriptionRepo;
/**
* @var DatatableService
*/
protected $datatableService;
/**
* SubscriptionService constructor.
*
* @param SubscriptionRepository $subscriptionRepo
* @param DatatableService $datatableService
*/
public function __construct(SubscriptionRepository $subscriptionRepo, DatatableService $datatableService)
{
$this->subscriptionRepo = $subscriptionRepo;
$this->datatableService = $datatableService;
}
/**
* @return SubscriptionRepository
*/
protected function getRepo()
{
return $this->subscriptionRepo;
}
/**
* @param $userId
*
* @return \Illuminate\Http\JsonResponse
*/
public function getDatatable($userId)
{
$datatable = new SubscriptionDatatable(false);
$query = $this->subscriptionRepo->find($userId);
return $this->datatableService->createDatatable($datatable, $query);
}
}

View File

@ -3,6 +3,7 @@
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use App\Models\Subscription;
class AddSubdomainToLookups extends Migration
{
@ -64,6 +65,29 @@ class AddSubdomainToLookups extends Migration
$table->unique(['account_id', 'public_id']);
});
Schema::table('subscriptions', function ($table) {
$table->unsignedInteger('public_id')->nullable();
$table->unsignedInteger('user_id')->nullable();
});
$accountPublicIds = [];
foreach (Subscription::all() as $subscription) {
$accountId = $subscription->account_id;
if (isset($accountPublicIds[$accountId])) {
$publicId = $accountPublicIds[$accountId];
$accountPublicIds[$accountId]++;
} else {
$publicId = 1;
$accountPublicIds[$accountId] = 2;
}
$subscription->public_id = $publicId;
$subscription->save();
}
Schema::table('subscriptions', function ($table) {
$table->unique(['account_id', 'public_id']);
});
}
/**
@ -99,5 +123,15 @@ class AddSubdomainToLookups extends Migration
});
Schema::dropIfExists('scheduled_reports');
Schema::table('subscriptions', function ($table) {
$table->dropUnique('subscriptions_account_id_public_id_unique');
});
Schema::table('subscriptions', function ($table) {
$table->dropColumn('public_id');
$table->dropColumn('user_id');
});
}
}

View File

@ -2567,6 +2567,21 @@ $LANG = array(
'apple_pay_domain' => 'Use <code>:domain</code> as the domain in :link.',
'apple_pay_not_supported' => 'Sorry, Apple/Google Pay isn\'t supported',
'optional_payment_methods' => 'Optional Payment Methods',
'add_subscription' => 'Add Subscription',
'target_url' => 'Target URL',
'event' => 'Event',
'event_create_client' => 'Created Client',
'event_create_invoice' => 'Created Invoice',
'event_create_quote' => 'Created Quote',
'event_create_payment' => 'Created Payment',
'event_create_vendor' => 'Created Vendor',
'event_update_quote' => 'Updated Quote',
'event_delete_quote' => 'Deleted Quote',
'event_update_invoice' => 'Updated Invoice',
'event_delete_invoice' => 'Deleted Invoice',
'subscriptions' => 'Subscriptions',
'updated_subscription' => 'Successfully updated subscription',
'created_subscription' => 'Successfully created subscription',
);

View File

@ -29,6 +29,30 @@
->setOptions('aoColumnDefs', [['bSortable'=>false, 'aTargets'=>[2]]])
->render('datatable') !!}
<p>&nbsp;</p>
<div class="pull-right">
@if (Utils::hasFeature(FEATURE_API))
{!! Button::primary(trans('texts.add_subscription'))->asLinkTo(URL::to('/subscriptions/create'))->appendIcon(Icon::create('plus-sign')) !!}
@endif
</div>
@include('partials.bulk_form', ['entityType' => ENTITY_TOKEN])
{!! Datatable::table()
->addColumn(
trans('texts.name'),
trans('texts.token'),
trans('texts.action'))
->setUrl(url('api/tokens/'))
->setOptions('sPaginationType', 'bootstrap')
->setOptions('bFilter', false)
->setOptions('bAutoWidth', false)
->setOptions('aoColumns', [[ "sWidth"=> "40%" ], [ "sWidth"=> "40%" ], ["sWidth"=> "20%"]])
->setOptions('aoColumnDefs', [['bSortable'=>false, 'aTargets'=>[2]]])
->render('datatable') !!}
<script>
window.onDatatableReady = actionListHandler;

View File

@ -0,0 +1,69 @@
@extends('header')
@section('content')
@parent
@include('accounts.nav', ['selected' => ACCOUNT_API_TOKENS])
{!! Former::open($url)->method($method)->addClass('warn-on-exit')->rules(array(
'event_id' => 'required',
'target_url' => 'required|url',
)); !!}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans($title) !!}</h3>
</div>
<div class="panel-body form-padding-right">
@if ($subscription)
{!! Former::populate($subscription) !!}
@endif
{!! Former::select('event_id')
->options([
trans('texts.clients') => [
EVENT_CREATE_CLIENT => trans('texts.event_create_client'),
],
trans('texts.invoices') => [
EVENT_CREATE_INVOICE => trans('texts.event_create_invoice'),
EVENT_UPDATE_INVOICE => trans('texts.event_update_invoice'),
EVENT_DELETE_INVOICE => trans('texts.event_delete_invoice'),
],
trans('texts.payments') => [
EVENT_CREATE_PAYMENT => trans('texts.event_create_payment'),
],
trans('texts.quotes') => [
EVENT_CREATE_QUOTE => trans('texts.event_create_quote'),
EVENT_UPDATE_QUOTE => trans('texts.event_update_quote'),
EVENT_DELETE_QUOTE => trans('texts.event_delete_quote'),
]
])
->label('event') !!}
{!! Former::text('target_url')
->placeholder('https://example.com')!!}
</div>
</div>
@if (Auth::user()->hasFeature(FEATURE_API))
<center class="buttons">
{!! Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/settings/api_tokens'))->appendIcon(Icon::create('remove-circle'))->large() !!}
{!! Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk')) !!}
</center>
@else
<script>
$(function() {
$('form.warn-on-exit input').prop('disabled', true);
});
</script>
@endif
{!! Former::close() !!}
@stop
@section('onReady')
$('#name').focus();
@stop

View File

@ -266,6 +266,9 @@ Route::group([
Route::get('api/tokens', 'TokenController@getDatatable');
Route::resource('tokens', 'TokenController');
Route::post('tokens/bulk', 'TokenController@bulk');
Route::get('api/subscriptions', 'SubscriptionController@getDatatable');
Route::resource('subscriptions', 'SubscriptionController');
Route::post('subscriptions/bulk', 'SubscriptionController@bulk');
Route::get('api/tax_rates', 'TaxRateController@getDatatable');
Route::resource('tax_rates', 'TaxRateController');