Added initial settings interface, Fixes #9.

This commit is contained in:
Dan Brown 2015-08-30 15:31:16 +01:00
parent 8af012bc2a
commit 17f4aa4300
17 changed files with 275 additions and 35 deletions

View File

@ -0,0 +1,44 @@
<?php
namespace Oxbow\Http\Controllers;
use Illuminate\Http\Request;
use Oxbow\Http\Requests;
use Oxbow\Http\Controllers\Controller;
use Setting;
class SettingController extends Controller
{
/**
* Display a listing of the settings.
*
* @return Response
*/
public function index()
{
$this->checkPermission('settings-update');
return view('settings/index');
}
/**
* Update the specified settings in storage.
*
* @param Request $request
* @return Response
*/
public function update(Request $request)
{
$this->checkPermission('settings-update');
// Cycles through posted settings and update them
foreach($request->all() as $name => $value) {
if(strpos($name, 'setting-') !== 0) continue;
$key = str_replace('setting-', '', trim($name));
Setting::put($key, $value);
}
return redirect('/settings');
}
}

View File

@ -71,6 +71,10 @@ Route::group(['middleware' => 'auth'], function () {
Route::get('/', 'HomeController@index');
Route::get('/home', 'HomeController@index');
// Settings
Route::get('/settings', 'SettingController@index');
Route::post('/settings', 'SettingController@update');
});

View File

@ -4,6 +4,7 @@ namespace Oxbow\Providers;
use Illuminate\Support\ServiceProvider;
use Oxbow\Services\ActivityService;
use Oxbow\Services\SettingService;
class CustomFacadeProvider extends ServiceProvider
{
@ -27,5 +28,9 @@ class CustomFacadeProvider extends ServiceProvider
$this->app->bind('activity', function() {
return new ActivityService($this->app->make('Oxbow\Activity'));
});
$this->app->bind('setting', function() {
return new SettingService($this->app->make('Oxbow\Setting'));
});
}
}

View File

@ -81,11 +81,13 @@ class ActivityService
* Gets the latest activity.
* @param int $count
* @param int $page
* @return array
*/
public function latest($count = 20, $page = 0)
{
return $this->activity->orderBy('created_at', 'desc')
$activityList = $this->activity->orderBy('created_at', 'desc')
->skip($count * $page)->take($count)->get();
return $this->filterSimilar($activityList);
}
/**
@ -99,7 +101,7 @@ class ActivityService
function entityActivity($entity, $count = 20, $page = 0)
{
$activity = $entity->hasMany('Oxbow\Activity')->orderBy('created_at', 'desc')
->skip($count*$page)->take($count)->get();
->skip($count * $page)->take($count)->get();
return $this->filterSimilar($activity);
}
@ -109,16 +111,17 @@ class ActivityService
* @param Activity[] $activity
* @return array
*/
protected function filterSimilar($activity) {
protected function filterSimilar($activity)
{
$newActivity = [];
$previousItem = false;
foreach($activity as $activityItem) {
if($previousItem === false) {
foreach ($activity as $activityItem) {
if ($previousItem === false) {
$previousItem = $activityItem;
$newActivity[] = $activityItem;
continue;
}
if(!$activityItem->isSimilarTo($previousItem)) {
if (!$activityItem->isSimilarTo($previousItem)) {
$newActivity[] = $activityItem;
}
$previousItem = $activityItem;

View File

@ -0,0 +1,14 @@
<?php namespace Oxbow\Services\Facades;
use Illuminate\Support\Facades\Facade;
class Setting extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor() { return 'setting'; }
}

View File

@ -0,0 +1,89 @@
<?php namespace Oxbow\Services;
use Oxbow\Setting;
/**
* Class SettingService
*
* The settings are a simple key-value database store.
*
* @package Oxbow\Services
*/
class SettingService
{
protected $setting;
/**
* SettingService constructor.
* @param $setting
*/
public function __construct(Setting $setting)
{
$this->setting = $setting;
}
/**
* Gets a setting from the database,
* If not found, Returns default, Which is false by default.
* @param $key
* @param string|bool $default
* @return bool|string
*/
public function get($key, $default = false)
{
$setting = $this->getSettingObjectByKey($key);
return $setting === null ? $default : $setting->value;
}
/**
* Checks if a setting exists.
* @param $key
* @return bool
*/
public function has($key)
{
$setting = $this->getSettingObjectByKey($key);
return $setting !== null;
}
/**
* Add a setting to the database.
* @param $key
* @param $value
* @return bool
*/
public function put($key, $value)
{
$setting = $this->setting->firstOrNew([
'setting_key' => $key
]);
$setting->value = $value;
$setting->save();
return true;
}
/**
* Removes a setting from the database.
* @param $key
* @return bool
*/
public function remove($key)
{
$setting = $this->getSettingObjectByKey($key);
if($setting) {
$setting->delete();
}
return true;
}
/**
* Gets a setting model from the database for the given key.
* @param $key
* @return mixed
*/
private function getSettingObjectByKey($key) {
return $this->setting->where('setting_key', '=', $key)->first();
}
}

12
app/Setting.php Normal file
View File

@ -0,0 +1,12 @@
<?php
namespace Oxbow;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
{
protected $fillable = ['setting_key', 'value'];
protected $primaryKey = 'setting_key';
}

View File

@ -13,7 +13,7 @@ return [
|
*/
'debug' => env('APP_DEBUG', false),
'debug' => env('APP_DEBUG', false),
/*
|--------------------------------------------------------------------------
@ -26,7 +26,7 @@ return [
|
*/
'url' => 'http://localhost',
'url' => 'http://localhost',
/*
|--------------------------------------------------------------------------
@ -39,7 +39,7 @@ return [
|
*/
'timezone' => 'UTC',
'timezone' => 'UTC',
/*
|--------------------------------------------------------------------------
@ -52,7 +52,7 @@ return [
|
*/
'locale' => 'en',
'locale' => 'en',
/*
|--------------------------------------------------------------------------
@ -78,9 +78,9 @@ return [
|
*/
'key' => env('APP_KEY', 'AbAZchsay4uBTU33RubBzLKw203yqSqr'),
'key' => env('APP_KEY', 'AbAZchsay4uBTU33RubBzLKw203yqSqr'),
'cipher' => 'AES-256-CBC',
'cipher' => 'AES-256-CBC',
/*
|--------------------------------------------------------------------------
@ -95,7 +95,7 @@ return [
|
*/
'log' => 'single',
'log' => 'single',
/*
|--------------------------------------------------------------------------
@ -108,7 +108,7 @@ return [
|
*/
'providers' => [
'providers' => [
/*
* Laravel Framework Service Providers...
@ -165,7 +165,7 @@ return [
|
*/
'aliases' => [
'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
@ -210,7 +210,8 @@ return [
* Custom
*/
'Activity' => Oxbow\Services\Facades\Activity::class,
'Activity' => Oxbow\Services\Facades\Activity::class,
'Setting' => Oxbow\Services\Facades\Setting::class,
],

View File

@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSettingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->string('setting_key')->primary()->indexed();
$table->text('value');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('settings');
}
}

View File

@ -10,7 +10,7 @@
color: #222;
width: 250px;
max-width: 100%;
-webkit-appearance:none;
//-webkit-appearance:none;
&.neg, &.invalid {
border: 1px solid $negative;
}
@ -25,9 +25,10 @@
label {
display: block;
line-height: 1.4em;
font-size: 0.9em;
font-size: 0.94em;
font-weight: 500;
color: #333;
color: #666;
padding-bottom: 2px;
}
label.radio, label.checkbox {

View File

@ -485,4 +485,19 @@ body.dragging, body.dragging * {
background-color: $negative;
color: #EEE;
}
}
.setting-nav {
margin-top: $-l;
border-top: 1px solid #DDD;
border-bottom: 1px solid #DDD;
a {
padding: $-m;
display: inline-block;
//color: #666;
&.selected {
//color: $primary;
background-color: #f8f8f8;
}
}
}

View File

@ -54,7 +54,7 @@
<header>
<div class="padded row clearfix">
<div class="col-md-12 logo-container">
<a href="/" class="logo">BookStack</a>
<a href="/" class="logo">{{ Setting::get('app-name', 'BookStack') }}</a>
<div class="user-overview">
<img class="avatar" src="{{Auth::user()->getAvatar(50)}}" alt="{{ Auth::user()->name }}">
<span class="user-name">

View File

@ -78,8 +78,6 @@
</div>
<script>
$(function() {

View File

@ -0,0 +1,23 @@
@extends('base')
@section('content')
@include('settings/navbar', ['selected' => 'settings'])
<div class="page-content">
<h1>Settings</h1>
<form action="/settings" method="POST">
{!! csrf_field() !!}
<div class="form-group">
<label for="setting-app-name">Application Name</label>
<input type="text" value="{{ Setting::get('app-name') }}" name="setting-app-name" id="setting-app-name">
</div>
<div class="form-group">
<button type="submit" class="button pos">Update Settings</button>
</div>
</form>
</div>
@stop

View File

@ -0,0 +1,6 @@
<div class="row">
<div class="col-md-6 col-md-offset-3 setting-nav">
<a href="/settings" @if($selected == 'settings') class="selected" @endif><i class="zmdi zmdi-settings"></i>Settings</a>
<a href="/users" @if($selected == 'users') class="selected" @endif><i class="zmdi zmdi-accounts"></i>Users</a>
</div>
</div>

View File

@ -17,7 +17,7 @@
<div class="row">
<div class="col-md-6">
<h1>Edit User</h1>
<h1>Edit {{ $user->id === $currentUser->id ? 'Profile' : 'User' }}</h1>
<form action="/users/{{$user->id}}" method="post">
{!! csrf_field() !!}
<input type="hidden" name="_method" value="put">

View File

@ -3,21 +3,15 @@
@section('content')
<div class="row faded-small">
<div class="col-md-6"></div>
<div class="col-md-6 faded">
<div class="action-buttons">
@if($currentUser->can('user-create'))
<a href="/users/create" class="text-pos"><i class="zmdi zmdi-account-add"></i>New User</a>
@endif
</div>
</div>
</div>
@include('settings/navbar', ['selected' => 'users'])
<div class="page-content">
<h1>Users</h1>
@if($currentUser->can('user-create'))
<p>
<a href="/users/create" class="text-pos"><i class="zmdi zmdi-account-add"></i>Add New User</a>
</p>
@endif
<table class="table">
<tr>
<th></th>