mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-01-19 08:42:48 +08:00
Added tags to page display and simplified editing flow
Tags now save with the page content data
This commit is contained in:
parent
78564ec61d
commit
7932069535
|
@ -14,14 +14,17 @@ class PageRepo extends EntityRepo
|
|||
{
|
||||
|
||||
protected $pageRevision;
|
||||
protected $tagRepo;
|
||||
|
||||
/**
|
||||
* PageRepo constructor.
|
||||
* @param PageRevision $pageRevision
|
||||
* @param TagRepo $tagRepo
|
||||
*/
|
||||
public function __construct(PageRevision $pageRevision)
|
||||
public function __construct(PageRevision $pageRevision, TagRepo $tagRepo)
|
||||
{
|
||||
$this->pageRevision = $pageRevision;
|
||||
$this->tagRepo = $tagRepo;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
@ -308,6 +311,11 @@ class PageRepo extends EntityRepo
|
|||
$page->slug = $this->findSuitableSlug($input['name'], $book_id, $page->id);
|
||||
}
|
||||
|
||||
// Save page tags if present
|
||||
if(isset($input['tags'])) {
|
||||
$this->tagRepo->saveTagsToEntity($page, $input['tags']);
|
||||
}
|
||||
|
||||
// Update with new details
|
||||
$userId = auth()->user()->id;
|
||||
$page->fill($input);
|
||||
|
|
|
@ -122,9 +122,153 @@
|
|||
}
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
&:hover a.link-hook {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
// Attribute form
|
||||
.floating-toolbox {
|
||||
background-color: #FFF;
|
||||
border: 1px solid #DDD;
|
||||
right: $-xl*2;
|
||||
z-index: 99;
|
||||
width: 48px;
|
||||
overflow: hidden;
|
||||
align-items: stretch;
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
transition: width ease-in-out 180ms;
|
||||
margin-top: -1px;
|
||||
&.open {
|
||||
width: 480px;
|
||||
}
|
||||
[toolbox-toggle] i {
|
||||
transition: transform ease-in-out 180ms;
|
||||
}
|
||||
[toolbox-toggle] {
|
||||
transition: background-color ease-in-out 180ms;
|
||||
}
|
||||
&.open [toolbox-toggle] {
|
||||
background-color: rgba(255, 0, 0, 0.29);
|
||||
}
|
||||
&.open [toolbox-toggle] i {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
> div {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
.tabs {
|
||||
display: block;
|
||||
border-right: 1px solid #DDD;
|
||||
width: 54px;
|
||||
flex: 0;
|
||||
}
|
||||
.tabs i {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.tabs > span {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
padding: $-s $-m;
|
||||
font-size: 13.5px;
|
||||
line-height: 1.6;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
&.open .tabs > span.active {
|
||||
color: #444;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
div[tab-content] {
|
||||
padding-bottom: 45px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
div[tab-content] .padded {
|
||||
flex: 1;
|
||||
padding-top: 0;
|
||||
}
|
||||
h4 {
|
||||
font-size: 24px;
|
||||
margin: $-m 0 0 0;
|
||||
padding: 0 $-l $-s $-l;
|
||||
}
|
||||
.tags input {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
min-width: 50px;
|
||||
}
|
||||
.tags td {
|
||||
padding-right: $-s;
|
||||
padding-top: $-s;
|
||||
}
|
||||
button.pos {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: $-s;
|
||||
height: 45px;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
&:hover{
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
.handle {
|
||||
user-select: none;
|
||||
cursor: move;
|
||||
color: #999;
|
||||
}
|
||||
form {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
[tab-content] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tag-display {
|
||||
margin: $-xl $-xs;
|
||||
border: 1px solid #DDD;
|
||||
min-width: 180px;
|
||||
max-width: 320px;
|
||||
opacity: 0.7;
|
||||
table {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
span {
|
||||
color: #666;
|
||||
margin-left: $-s;
|
||||
}
|
||||
.heading {
|
||||
padding: $-xs $-s;
|
||||
color: #444;
|
||||
}
|
||||
td {
|
||||
border: 0;
|
||||
border-bottom: 1px solid #DDD;
|
||||
padding: $-xs $-s;
|
||||
color: #444;
|
||||
}
|
||||
.tag-value {
|
||||
color: #888;
|
||||
}
|
||||
td i {
|
||||
color: #888;
|
||||
}
|
||||
tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
.tag {
|
||||
padding: $-s;
|
||||
|
||||
}
|
||||
}
|
|
@ -207,113 +207,3 @@ $btt-size: 40px;
|
|||
color: #EEE;
|
||||
}
|
||||
}
|
||||
|
||||
// Attribute form
|
||||
.floating-toolbox {
|
||||
background-color: #FFF;
|
||||
border: 1px solid #DDD;
|
||||
right: $-xl*2;
|
||||
z-index: 99;
|
||||
width: 48px;
|
||||
overflow: hidden;
|
||||
align-items: stretch;
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
transition: width ease-in-out 180ms;
|
||||
margin-top: -1px;
|
||||
&.open {
|
||||
width: 480px;
|
||||
}
|
||||
[toolbox-toggle] i {
|
||||
transition: transform ease-in-out 180ms;
|
||||
}
|
||||
[toolbox-toggle] {
|
||||
transition: background-color ease-in-out 180ms;
|
||||
}
|
||||
&.open [toolbox-toggle] {
|
||||
background-color: rgba(255, 0, 0, 0.29);
|
||||
}
|
||||
&.open [toolbox-toggle] i {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
> div {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
.tabs {
|
||||
display: block;
|
||||
border-right: 1px solid #DDD;
|
||||
width: 54px;
|
||||
flex: 0;
|
||||
}
|
||||
.tabs i {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.tabs > span {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
padding: $-s $-m;
|
||||
font-size: 13.5px;
|
||||
line-height: 1.6;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
&.open .tabs > span.active {
|
||||
color: #444;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
div[tab-content] {
|
||||
padding-bottom: 45px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
div[tab-content] .padded {
|
||||
flex: 1;
|
||||
padding-top: 0;
|
||||
}
|
||||
h4 {
|
||||
font-size: 24px;
|
||||
margin: $-m 0 0 0;
|
||||
padding: 0 $-l $-s $-l;
|
||||
}
|
||||
.tags input {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
min-width: 50px;
|
||||
}
|
||||
.tags td {
|
||||
padding-right: $-s;
|
||||
padding-top: $-s;
|
||||
}
|
||||
button.pos {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: $-s;
|
||||
height: 45px;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
&:hover{
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
.handle {
|
||||
user-select: none;
|
||||
cursor: move;
|
||||
color: #999;
|
||||
}
|
||||
form {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
[tab-content] {
|
||||
display: none;
|
||||
}
|
|
@ -14,9 +14,9 @@
|
|||
<input type="hidden" name="_method" value="PUT">
|
||||
@endif
|
||||
@include('pages/form', ['model' => $page])
|
||||
@include('pages/form-toolbox')
|
||||
</form>
|
||||
|
||||
@include('pages/form-toolbox')
|
||||
|
||||
</div>
|
||||
@include('partials/image-manager', ['imageType' => 'gallery', 'uploaded_to' => $page->id])
|
||||
|
|
|
@ -5,33 +5,30 @@
|
|||
<span tab-button="tags" title="Page Tags" class="active"><i class="zmdi zmdi-tag"></i></span>
|
||||
</div>
|
||||
<div tab-content="tags" ng-controller="PageTagController" page-id="{{ $page->id or 0 }}">
|
||||
<form ng-submit="saveTags()" >
|
||||
<h4>Page Tags</h4>
|
||||
<div class="padded tags">
|
||||
<p class="muted small">Add some tags to better categorise your content. <br> You can assign a value to a tag for more in-depth organisation.</p>
|
||||
<table class="no-style" style="width: 100%;">
|
||||
<tbody ui-sortable="sortOptions" ng-model="tags" >
|
||||
<tr ng-repeat="tag in tags">
|
||||
<td width="20" ><i class="handle zmdi zmdi-menu"></i></td>
|
||||
<td><input class="outline" type="text" ng-model="tag.name" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="Tag"></td>
|
||||
<td><input class="outline" type="text" ng-model="tag.value" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="Tag Value (Optional)"></td>
|
||||
<td width="10" class="text-center text-neg" style="padding: 0;" ng-click="removeTag(tag)"><i class="zmdi zmdi-close"></i></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="no-style" style="width: 100%;">
|
||||
<tbody>
|
||||
<tr class="unsortable">
|
||||
<td width="34"></td>
|
||||
<td ng-click="addEmptyTag()">
|
||||
<button type="button" class="text-button">Add another tag</button>
|
||||
</td>
|
||||
<td></td>
|
||||
<h4>Page Tags</h4>
|
||||
<div class="padded tags">
|
||||
<p class="muted small">Add some tags to better categorise your content. <br> You can assign a value to a tag for more in-depth organisation.</p>
|
||||
<table class="no-style" style="width: 100%;">
|
||||
<tbody ui-sortable="sortOptions" ng-model="tags" >
|
||||
<tr ng-repeat="tag in tags track by $index">
|
||||
<td width="20" ><i class="handle zmdi zmdi-menu"></i></td>
|
||||
<td><input class="outline" ng-attr-name="tags[@{{$index}}][name]" type="text" ng-model="tag.name" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="Tag"></td>
|
||||
<td><input class="outline" ng-attr-name="tags[@{{$index}}][value]" type="text" ng-model="tag.value" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="Tag Value (Optional)"></td>
|
||||
<td width="10" ng-show="tags.length != 1" class="text-center text-neg" style="padding: 0;" ng-click="removeTag(tag)"><i class="zmdi zmdi-close"></i></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<button class="button pos" type="submit">Save Tags</button>
|
||||
</form>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="no-style" style="width: 100%;">
|
||||
<tbody>
|
||||
<tr class="unsortable">
|
||||
<td width="34"></td>
|
||||
<td ng-click="addEmptyTag()">
|
||||
<button type="button" class="text-button">Add another tag</button>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,5 +1,22 @@
|
|||
<div ng-non-bindable>
|
||||
<h1 id="bkmrk-page-title">{{$page->name}}</h1>
|
||||
|
||||
<h1 id="bkmrk-page-title" class="float left">{{$page->name}}</h1>
|
||||
|
||||
@if(count($page->tags) > 0)
|
||||
<div class="tag-display float right">
|
||||
<div class="heading primary-background-light">Page Tags</div>
|
||||
<table>
|
||||
@foreach($page->tags as $tag)
|
||||
<tr class="tag">
|
||||
<td @if(!$tag->value) colspan="2" @endif> {{ $tag->name }}</td>
|
||||
@if($tag->value) <td class="tag-value">{{$tag->value}}</td> @endif
|
||||
</tr>
|
||||
@endforeach
|
||||
</table>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div style="clear:left;"></div>
|
||||
|
||||
{!! $page->html !!}
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user