Added initial settings interface, Fixes #9.
This commit is contained in:
parent
8af012bc2a
commit
17f4aa4300
17 changed files with 275 additions and 35 deletions
44
app/Http/Controllers/SettingController.php
Normal file
44
app/Http/Controllers/SettingController.php
Normal 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');
|
||||
}
|
||||
|
||||
}
|
|
@ -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');
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -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'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
14
app/Services/Facades/Setting.php
Normal file
14
app/Services/Facades/Setting.php
Normal 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'; }
|
||||
}
|
89
app/Services/SettingService.php
Normal file
89
app/Services/SettingService.php
Normal 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
12
app/Setting.php
Normal 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';
|
||||
}
|
|
@ -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,
|
||||
|
||||
],
|
||||
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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">
|
||||
|
|
|
@ -78,8 +78,6 @@
|
|||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
|
||||
|
|
23
resources/views/settings/index.blade.php
Normal file
23
resources/views/settings/index.blade.php
Normal 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
|
6
resources/views/settings/navbar.blade.php
Normal file
6
resources/views/settings/navbar.blade.php
Normal 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>
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue