--- /dev/null
+<?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');
+ }
+
+}
Route::get('/', 'HomeController@index');
Route::get('/home', 'HomeController@index');
+ // Settings
+ Route::get('/settings', 'SettingController@index');
+ Route::post('/settings', 'SettingController@update');
+
});
use Illuminate\Support\ServiceProvider;
use Oxbow\Services\ActivityService;
+use Oxbow\Services\SettingService;
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'));
+ });
}
}
* 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);
}
/**
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);
}
* @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;
--- /dev/null
+<?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'; }
+}
\ No newline at end of file
--- /dev/null
+<?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();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace Oxbow;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Setting extends Model
+{
+ protected $fillable = ['setting_key', 'value'];
+
+ protected $primaryKey = 'setting_key';
+}
|
*/
- 'debug' => env('APP_DEBUG', false),
+ 'debug' => env('APP_DEBUG', false),
/*
|--------------------------------------------------------------------------
|
*/
- 'url' => 'http://localhost',
+ 'url' => 'http://localhost',
/*
|--------------------------------------------------------------------------
|
*/
- 'timezone' => 'UTC',
+ 'timezone' => 'UTC',
/*
|--------------------------------------------------------------------------
|
*/
- 'locale' => 'en',
+ 'locale' => 'en',
/*
|--------------------------------------------------------------------------
|
*/
- 'key' => env('APP_KEY', 'AbAZchsay4uBTU33RubBzLKw203yqSqr'),
+ 'key' => env('APP_KEY', 'AbAZchsay4uBTU33RubBzLKw203yqSqr'),
- 'cipher' => 'AES-256-CBC',
+ 'cipher' => 'AES-256-CBC',
/*
|--------------------------------------------------------------------------
|
*/
- 'log' => 'single',
+ 'log' => 'single',
/*
|--------------------------------------------------------------------------
|
*/
- 'providers' => [
+ 'providers' => [
/*
* Laravel Framework Service Providers...
|
*/
- 'aliases' => [
+ 'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
* Custom
*/
- 'Activity' => Oxbow\Services\Facades\Activity::class,
+ 'Activity' => Oxbow\Services\Facades\Activity::class,
+ 'Setting' => Oxbow\Services\Facades\Setting::class,
],
--- /dev/null
+<?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');
+ }
+}
color: #222;
width: 250px;
max-width: 100%;
- -webkit-appearance:none;
+ //-webkit-appearance:none;
&.neg, &.invalid {
border: 1px solid $negative;
}
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 {
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;
+ }
+ }
}
\ No newline at end of file
<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">
</div>
-
-
<script>
$(function() {
--- /dev/null
+@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
\ No newline at end of file
--- /dev/null
+<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>
\ No newline at end of file
<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">
@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>