Implement wizard setup

This commit is contained in:
Joseph Cohen
2015-01-06 13:08:15 -06:00
parent 0d326de0b2
commit f8319a23d9
8 changed files with 252 additions and 74 deletions

View File

@@ -126,4 +126,50 @@ $(function() {
$('#banner-view').remove();
$('input[name=remove_banner]').val('1');
});
// Setup wizard
$('.wizard-next').on('click', function () {
var $form = $('#setup-form'),
$btn = $(this),
current = $btn.data('currentBlock'),
next = $btn.data('nextBlock');
$btn.button('loading');
// Only validate going forward. If current group is invalid, do not go further
if (next > current) {
var url = '/setup/step' + current;
$.post(url, $form.serializeObject())
.done(function(response) {
goForward(current, next);
})
.fail(function(response) {
var errors = _.toArray(response.responseJSON.errors);
_.each(errors, function(error) {
(new CachetHQ.Notifier()).notify(error);
});
})
.always(function() {
$btn.button('reset');
});
return false;
}
});
function goForward(current, next) {
// validation was ok. We can go on next step.
$('.block-' + current)
.removeClass('show')
.addClass('hidden');
$('.block-' + next)
.removeClass('hidden')
.addClass('show');
$('.steps .step')
.removeClass("active")
.filter(":lt(" + (next) + ")")
.addClass("active");
}
});

View File

@@ -22,6 +22,7 @@ html, body {
// Styles for specific page
@import "pages/login";
@import "pages/setup";
// Styles for plugins
@import "plugins/messenger";

View File

@@ -0,0 +1,66 @@
.setup-page {
padding-top: 60px;
.logo {
display: block;
margin: 0 auto 30px;
}
.steps {
@extend .row;
margin: 0 auto;
border-radius: 2px 2px 0 0;
margin-bottom: 20px;
.step {
@extend .col-xs-4;
padding: 20px 0;
text-align: center;
position: relative;
font-size: 13px;
&:not(:last-child):after {
content: '';
position: absolute;
bottom: 31px;
left: 55%;
display: block;
height: 1px;
background: #94A1B8;
width: 100%;
}
span {
width: 23px;
height: 23px;
display: block;
position: relative;
margin: 0 auto;
margin-top: 13px;
border-radius: 25px;
background: $cachet-base-medium;
border: 1px solid #94A1B8;
-webkit-transition: all 0.2s linear;
-moz-transition: all 0.2s linear;
-ms-transition: all 0.2s linear;
-o-transition: all 0.2s linear;
transition: all 0.2s linear;
}
&.active {
span {
background: $cachet-primary;
}
}
}
}
.setup-success {
text-align: center;
i {
font-size: 47px;
}
h3 {
margin-top: 25px;
font-size: 21px;
color: #556579;
}
.btn {
margin-top: 40px;
}
}
}

View File

@@ -7,5 +7,7 @@ return [
'status_page_setup' => 'Status Page Setup',
'show_support' => 'Show support for Cachet? <small>Places a link in the footer linking to Cachet.</small>',
'admin_account' => 'Administrator Account',
'complete_setup' => 'Complete Setup'
'complete_setup' => 'Complete Setup',
'completed' => 'Cachet has been configured successfully!',
'finish_setup' => 'Go to dashboard',
];

View File

@@ -7,5 +7,7 @@ return [
'status_page_setup' => 'Installation de la page de statut',
'show_support' => 'Show support for Cachet? <small>Places a link in the footer linking to Cachet.</small>',
'admin_account' => 'Compte administrateur',
'complete_setup' => 'Terminer l\'installation'
'complete_setup' => 'Terminer l\'installation',
'completed' => 'Cachet a été configuré avec succès !',
'finish_setup' => 'Aller au tableau de bord',
];

View File

@@ -1,7 +1,7 @@
@extends('layout.clean')
@section('content')
<div class='login row'>
<div class='login'>
<div class='col-xs-12 col-xs-offset-0 col-sm-6 col-sm-offset-3 col-md-4 col-md-offset-4 text-center'>
<div class="welcome-logo">
<img class="logo" height="50" src="{{ url('img/cachet-logo.svg') }}" alt="Cachet"/>

View File

@@ -1,76 +1,104 @@
@extends('layout.dashboard')
@extends('layout.clean')
@section('content')
<div class="header">
<span class="uppercase">
<i class='ion-gear-a'></i> {{ trans('setup.title') }}
</span>
</div>
<div class="content-wrapper">
<div class='row'>
<div class='col-sm-12'>
<div class='panel panel-default'>
<div class='panel-heading'>{{ trans('setup.service_details') }}</div>
<div class='panel-body'>
{{ Form::open(['name' => 'SetupForm', 'class' => 'form-vertical', 'role' => 'form']) }}
<fieldset>
<legend>{{ trans('setup.status_page_setup') }}</legend>
<div class='form-group'>
<label class='sr-only'>{{ trans('forms.site_name') }}</label>
<input type='text' name='settings[app_name]' class='form-control' placeholder='{{ trans("forms.setup.site_name") }}' value='{{ Input::old("settings.app_name", "") }}' required />
@if($errors->has('settings.app_name'))
<span class='text-danger'>{{ $errors->first('settings.app_name') }}</span>
@endif
</div>
<div class='form-group'>
<label class='sr-only'>{{ trans('forms.site_domain') }}</label>
<input type='text' name='settings[app_domain]' class='form-control' placeholder='{{ trans("forms.setup.site_domain") }}' value='{{ Input::old("settings.app_domain", "") }}' required />
@if($errors->has('settings.app_domain'))
<span class='text-danger'>{{ $errors->first('settings.app_domain') }}</span>
@endif
</div>
<div class='form-group'>
<label>
<input type='checkbox' name='settings[show_support]' value='1' checked />
{{ trans("setup.show_support") }}
</label>
</div>
</fieldset>
<fieldset>
<legend>{{ trans("setup.admin_account") }}</legend>
<div class='form-group'>
<label class='sr-only'>{{ trans("forms.username") }}</label>
<input type='text' name='user[username]' class='form-control' placeholder='{{ trans("forms.setup.username") }}' value='{{ Input::old("user.username", "") }}' required />
@if($errors->has('user.username'))
<span class='text-danger'>{{ $errors->first('user.username') }}</span>
@endif
</div>
<div class='form-group'>
<label class='sr-only'>{{ trans("forms.email") }}</label>
<input type='email' name='user[email]' class='form-control' placeholder='{{ trans("forms.setup.email") }}' value='{{ Input::old("user.email", "") }}' required />
@if($errors->has('user.email'))
<span class='text-danger'>{{ $errors->first('user.email') }}</span>
@endif
</div>
<div class='form-group'>
<label class='sr-only'>{{ trans("forms.password") }}</label>
<input type='password' name='user[password]' class='form-control' placeholder='{{ trans("forms.setup.password") }}' value='{{ Input::old("user.password", "") }}' required />
@if($errors->has('user.password'))
<span class='text-danger'>{{ $errors->first('user.password') }}</span>
@endif
</div>
</fieldset>
<hr />
<div class='form-group'>
<input type='hidden' name='settings[app_incident_days]' value='7' />
<button type='submit' class='btn btn-success'>{{ trans("setup.complete_setup") }}</button>
</div>
{{ Form::close() }}
</div>
<div class="setup-page">
<div class="text-center">
<img class="logo" height="50" src="{{ url('img/cachet-logo.svg') }}" alt="Cachet"/>
<h4>{{ trans('setup.title') }}</h4>
<br>
</div>
<div class='col-xs-12 col-xs-offset-0 col-sm-8 col-sm-offset-2'>
<div class="steps">
<div class="step active">
{{ trans('setup.status_page_setup') }}
<span></span>
</div>
<div class="step">
{{ trans("setup.admin_account") }}
<span></span>
</div>
<div class="step">
{{ trans("setup.complete_setup") }}
<span></span>
</div>
</div>
<div class="clearfix"></div>
{{ Form::open(['name' => 'SetupForm', 'class' => 'form-vertical', 'id' => 'setup-form', 'role' => 'form', 'method' => 'POST']) }}
<div class="step block-1 show">
<fieldset>
<div class='form-group'>
<label class='sr-only'>{{ trans('forms.site_name') }}</label>
<input type='text' name='settings[app_name]' class='form-control' placeholder='{{ trans("forms.setup.site_name") }}' value='{{ Input::old("settings.app_name", "") }}' required />
@if($errors->has('settings.app_name'))
<span class='text-danger'>{{ $errors->first('settings.app_name') }}</span>
@endif
</div>
<div class='form-group'>
<label class='sr-only'>{{ trans('forms.site_domain') }}</label>
<input type='text' name='settings[app_domain]' class='form-control' placeholder='{{ trans("forms.setup.site_domain") }}' value='{{ Input::old("settings.app_domain", "") }}' required />
@if($errors->has('settings.app_domain'))
<span class='text-danger'>{{ $errors->first('settings.app_domain') }}</span>
@endif
</div>
<div class='form-group'>
<label>
<input type='checkbox' name='settings[show_support]' value='1' checked />
{{ trans("setup.show_support") }}
</label>
<hr/>
<span class="wizard-next btn btn-success" data-current-block="1" data-next-block="2" data-loading-text="<i class='icon ion-load-c'></i>">
{{ trans('pagination.next') }}
</span>
</div>
</fieldset>
</div>
<div class="step block-2 hidden">
<fieldset>
<div class='form-group'>
<label class='sr-only'>{{ trans("forms.username") }}</label>
<input type='text' name='user[username]' class='form-control' placeholder='{{ trans("forms.setup.username") }}' value='{{ Input::old("user.username", "") }}' required />
@if($errors->has('user.username'))
<span class='text-danger'>{{ $errors->first('user.username') }}</span>
@endif
</div>
<div class='form-group'>
<label class='sr-only'>{{ trans("forms.email") }}</label>
<input type='text' name='user[email]' class='form-control' placeholder='{{ trans("forms.setup.email") }}' value='{{ Input::old("user.email", "") }}' required />
@if($errors->has('user.email'))
<span class='text-danger'>{{ $errors->first('user.email') }}</span>
@endif
</div>
<div class='form-group'>
<label class='sr-only'>{{ trans("forms.password") }}</label>
<input type='password' name='user[password]' class='form-control' placeholder='{{ trans("forms.setup.password") }}' value='{{ Input::old("user.password", "") }}' required />
@if($errors->has('user.password'))
<span class='text-danger'>{{ $errors->first('user.password') }}</span>
@endif
</div>
</fieldset>
<hr />
<div class='form-group'>
<input type='hidden' name='settings[app_incident_days]' value='7' />
<span class="wizard-next btn btn-info" data-current-block="2" data-next-block="1">
{{ trans('pagination.previous') }}
</span>
<span class="wizard-next btn btn-success" data-current-block="2" data-next-block="3" data-loading-text="<i class='icon ion-load-c'></i>">
{{ trans("setup.complete_setup") }}
</span>
</div>
</div>
<div class="step block-3 hidden">
<div class="setup-success">
<i class="ion-checkmark-circled"></i>
<h3>
{{ trans("setup.completed") }}
</h3>
<a href="{{ route('dashboard') }}" class="btn btn-default">
<span>{{ trans("setup.finish_setup") }}</span>
</a>
</div>
</div>
{{ Form::close() }}
</div>
</div>
@stop

View File

@@ -8,6 +8,8 @@ use GrahamCampbell\Binput\Facades\Binput;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\View;
@@ -35,12 +37,35 @@ class SetupController extends Controller
]);
}
/**
* Handles validation on step one of setup form.
*
* @return \Illuminate\Http\Response
*/
public function postStep1()
{
$postData = Binput::all();
$v = Validator::make($postData, [
'settings.app_name' => 'required',
'settings.app_domain' => 'required',
'settings.show_support' => 'boolean',
]);
if ($v->passes()) {
return Response::json(['status' => 1]);
} else {
// No good, let's try that again.
return Response::json(['errors' => $v->messages()], 400);
}
}
/**
* Handles the actual app setup.
*
* @return \Illuminate\Http\RedirectResponse
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
*/
public function postIndex()
public function postStep2()
{
$postData = Binput::all();
@@ -76,9 +101,17 @@ class SetupController extends Controller
]);
}
if (Request::ajax()) {
return Response::json(['status' => 1]);
}
return Redirect::to('dashboard');
} else {
// No good, let's try that again.
if (Request::ajax()) {
return Response::json(['errors' => $v->messages()], 400);
}
return Redirect::back()->withInput()->with('errors', $v->messages());
}
}