mirror of
https://github.com/documize/community.git
synced 2025-07-19 13:19:43 +02:00
refactored base-editor-inline to support section and block editing
This commit is contained in:
parent
81fcf0f5df
commit
7e7f63e6f4
15 changed files with 157 additions and 149 deletions
|
@ -31,7 +31,7 @@ export default Ember.Component.extend(TooltipMixin, {
|
||||||
{ label: 'Attachment', selected: false },
|
{ label: 'Attachment', selected: false },
|
||||||
{ label: 'Search', selected: false }
|
{ label: 'Search', selected: false }
|
||||||
],
|
],
|
||||||
buttonId: Ember.computed('page', function () {
|
contentLinkerButtonId: Ember.computed('page', function () {
|
||||||
let page = this.get('page');
|
let page = this.get('page');
|
||||||
return `content-linker-button-${page.id}`;
|
return `content-linker-button-${page.id}`;
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -33,6 +33,14 @@ export default Ember.Component.extend({
|
||||||
let page = this.get('page');
|
let page = this.get('page');
|
||||||
return `discard-edits-dialog-${page.id}`;
|
return `discard-edits-dialog-${page.id}`;
|
||||||
}),
|
}),
|
||||||
|
contentLinkerButtonId: Ember.computed('page', function () {
|
||||||
|
let page = this.get('page');
|
||||||
|
return `content-linker-button-${page.id}`;
|
||||||
|
}),
|
||||||
|
previewButtonId: Ember.computed('page', function () {
|
||||||
|
let page = this.get('page');
|
||||||
|
return `content-preview-button-${page.id}`;
|
||||||
|
}),
|
||||||
|
|
||||||
didRender() {
|
didRender() {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
@ -108,6 +116,14 @@ export default Ember.Component.extend({
|
||||||
|
|
||||||
discardEdits() {
|
discardEdits() {
|
||||||
this.attrs.onCancel();
|
this.attrs.onCancel();
|
||||||
}
|
},
|
||||||
|
|
||||||
|
onInsertLink(selection) {
|
||||||
|
return this.get('onInsertLink')(selection);
|
||||||
|
},
|
||||||
|
|
||||||
|
onPreview() {
|
||||||
|
return this.get('onPreview')();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,10 +32,6 @@ export default Ember.Component.extend(TooltipMixin, {
|
||||||
let page = this.get('page');
|
let page = this.get('page');
|
||||||
return `markdown-preview-${page.id}`;
|
return `markdown-preview-${page.id}`;
|
||||||
}),
|
}),
|
||||||
tooltipId: Ember.computed('page', function () {
|
|
||||||
let page = this.get('page');
|
|
||||||
return `markdown-tooltip-${page.id}`;
|
|
||||||
}),
|
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
@ -127,7 +123,7 @@ export default Ember.Component.extend(TooltipMixin, {
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
toggleMode() {
|
onPreview() {
|
||||||
this.set('editMode', !this.get('editMode'));
|
this.set('editMode', !this.get('editMode'));
|
||||||
|
|
||||||
Ember.run.schedule('afterRender', () => {
|
Ember.run.schedule('afterRender', () => {
|
||||||
|
|
|
@ -16,31 +16,23 @@ export default Ember.Controller.extend({
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
onCancel( /*page*/ ) {
|
onCancel( /*page*/ ) {
|
||||||
this.transitionToRoute('document', {
|
this.transitionToRoute('document');
|
||||||
queryParams: {
|
|
||||||
page: this.get('model.page.id')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onAction(page, meta) {
|
onAction(page, meta) {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
let block = this.get('model.block');
|
let b = this.get('model.block');
|
||||||
block.set('title', page.get('title'));
|
b.set('title', page.get('title'));
|
||||||
block.set('body', page.get('body'));
|
b.set('body', page.get('body'));
|
||||||
block.set('excerpt', page.get('excerpt'));
|
b.set('excerpt', page.get('excerpt'));
|
||||||
block.set('rawBody', meta.get('rawBody'));
|
b.set('rawBody', meta.get('rawBody'));
|
||||||
block.set('config', meta.get('config'));
|
b.set('config', meta.get('config'));
|
||||||
block.set('externalSource', meta.get('externalSource'));
|
b.set('externalSource', meta.get('externalSource'));
|
||||||
|
|
||||||
this.get('sectionService').updateBlock(block).then(function () {
|
this.get('sectionService').updateBlock(b).then(function () {
|
||||||
self.audit.record("edited-block");
|
self.audit.record("edited-block");
|
||||||
self.transitionToRoute('document', {
|
self.transitionToRoute('document');
|
||||||
queryParams: {
|
|
||||||
page: page.get('id')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
@import "activity.scss";
|
@import "activity.scss";
|
||||||
@import "edit-tools.scss";
|
@import "content-linker.scss";
|
||||||
@import "files.scss";
|
@import "files.scss";
|
||||||
@import "history.scss";
|
@import "history.scss";
|
||||||
@import "inline-editor.scss";
|
@import "inline-editor.scss";
|
||||||
|
|
|
@ -1,20 +1,3 @@
|
||||||
.edit-tools {
|
|
||||||
position: absolute;
|
|
||||||
top: 18px;
|
|
||||||
right: 78px;
|
|
||||||
|
|
||||||
> .toolbar {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
line-height: 0;
|
|
||||||
|
|
||||||
> li {
|
|
||||||
list-style: none;
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-counter-dialog {
|
.content-counter-dialog {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
height: 200px;
|
height: 200px;
|
|
@ -1,6 +1,6 @@
|
||||||
.document-editor {
|
.document-editor {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
> .toolbar {
|
> .toolbar {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
> input {
|
> input {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin: 17px 0 0 0;
|
margin: 16px 0 10px 0;
|
||||||
color: $color-wysiwyg;
|
color: $color-wysiwyg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,3 +29,13 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.document-editor-full {
|
||||||
|
@extend .transition-all;
|
||||||
|
@include border-radius(2px);
|
||||||
|
@include ease-in();
|
||||||
|
position: relative;
|
||||||
|
padding: 25px 50px;
|
||||||
|
box-shadow: 0 0 0 0.75pt $color-stroke,0 0 3pt 0.75pt $color-stroke;
|
||||||
|
background-color: $color-white;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
.zone-section-editor {
|
.zone-section-editor {
|
||||||
// min-height: 500px; //ensure dropdowns render in viewport
|
|
||||||
// height: 100%;
|
|
||||||
margin-left: 60px;
|
margin-left: 60px;
|
||||||
padding: 20px 60px;
|
padding: 20px 60px;
|
||||||
z-index: 777;
|
z-index: 777;
|
||||||
|
|
|
@ -344,11 +344,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-state-document {
|
|
||||||
margin-top: 150px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-page-toolbar {
|
.dropdown-page-toolbar {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{{component editorType document=document folder=folder page=page meta=meta onCancel=(action 'onCancel') onAction=(action 'onAction')}}
|
{{component editorType document=document folder=folder page=page meta=meta blockMode=true onCancel=(action 'onCancel') onAction=(action 'onAction')}}
|
||||||
|
|
|
@ -1,82 +1,72 @@
|
||||||
<div class="edit-tools">
|
{{#dropdown-dialog target=contentLinkerButtonId position="bottom right" button="Insert" color="flat-blue" onAction=(action 'onInsertLink')}}
|
||||||
<ul class="toolbar">
|
<div class="content-linker-dialog">
|
||||||
<li class="item">
|
<form>
|
||||||
<div class="round-button-mono" id={{buttonId}} data-tooltip="Reference link" data-tooltip-position="top center">
|
{{ui/ui-tab tabs=tabs onTabSelect=(action 'onTabSelect')}}
|
||||||
<i class="material-icons color-blue">link</i>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{{#dropdown-dialog target=buttonId position="bottom right" button="Insert" color="flat-blue" onAction=(action 'onInsertLink')}}
|
<div class="margin-top-40" />
|
||||||
<div class="content-linker-dialog">
|
|
||||||
<form>
|
|
||||||
{{ui/ui-tab tabs=tabs onTabSelect=(action 'onTabSelect')}}
|
|
||||||
|
|
||||||
<div class="margin-top-40" />
|
{{#if showSections}}
|
||||||
|
<ul class="link-list">
|
||||||
|
{{#each candidates.pages as |p|}}
|
||||||
|
<li class="link-item" {{ action 'setSelection' p }}>
|
||||||
|
{{#ui/ui-selection selected=p.selected}}
|
||||||
|
{{p.title}}
|
||||||
|
{{/ui/ui-selection}}
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if showSections}}
|
{{#if showAttachments}}
|
||||||
<ul class="link-list">
|
<ul class="link-list">
|
||||||
{{#each candidates.pages as |p|}}
|
{{#each candidates.attachments as |a|}}
|
||||||
<li class="link-item" {{ action 'setSelection' p }}>
|
<li class="link-item" {{ action 'setSelection' a }}>
|
||||||
{{#ui/ui-selection selected=p.selected}}
|
{{#ui/ui-selection selected=a.selected}}
|
||||||
{{p.title}}
|
<img class="icon" src="/assets/img/attachments/{{document/file-icon a.context}}" />
|
||||||
{{/ui/ui-selection}}
|
{{ a.title }}
|
||||||
</li>
|
{{/ui/ui-selection}}
|
||||||
{{/each}}
|
</li>
|
||||||
</ul>
|
{{/each}}
|
||||||
{{/if}}
|
</ul>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if showAttachments}}
|
{{#if showSearch}}
|
||||||
<ul class="link-list">
|
<div class="input-control">
|
||||||
{{#each candidates.attachments as |a|}}
|
<label>Search</label>
|
||||||
<li class="link-item" {{ action 'setSelection' a }}>
|
<div class="tip">For content or attachments</div>
|
||||||
{{#ui/ui-selection selected=a.selected}}
|
{{focus-input id="content-linker-search" type="input" value=keywords placeholder="keyword search" autocomplete="off"}}
|
||||||
<img class="icon" src="/assets/img/attachments/{{document/file-icon a.context}}" />
|
</div>
|
||||||
{{ a.title }}
|
{{#unless hasMatches}}
|
||||||
{{/ui/ui-selection}}
|
Nothing found.
|
||||||
</li>
|
{{/unless}}
|
||||||
{{/each}}
|
<ul class="link-list">
|
||||||
</ul>
|
{{#each matches.documents as |m|}}
|
||||||
{{/if}}
|
<li class="link-item" {{ action 'setSelection' m }}>
|
||||||
|
{{#ui/ui-selection selected=m.selected}}
|
||||||
|
{{m.title}}
|
||||||
|
{{/ui/ui-selection}}
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
{{#each matches.pages as |m|}}
|
||||||
|
<li class="link-item" {{ action 'setSelection' m }}>
|
||||||
|
{{#ui/ui-selection selected=m.selected}}
|
||||||
|
{{m.title}}<br/><span class="color-gray">{{m.context}}</span>
|
||||||
|
{{/ui/ui-selection}}
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
{{#each matches.attachments as |a|}}
|
||||||
|
<li class="link-item" {{ action 'setSelection' a }}>
|
||||||
|
{{#ui/ui-selection selected=a.selected}}
|
||||||
|
<img class="icon" src="/assets/img/attachments/{{document/file-icon a.context}}" />
|
||||||
|
{{ a.title }}
|
||||||
|
{{/ui/ui-selection}}
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if showSearch}}
|
<div class="hide regular-button button-blue pull-right" {{ action 'onInsertLink' }}>Insert</div>
|
||||||
<div class="input-control">
|
<div class="hide clearfix" />
|
||||||
<label>Search</label>
|
</form>
|
||||||
<div class="tip">For content or attachments</div>
|
</div>
|
||||||
{{focus-input id="content-linker-search" type="input" value=keywords placeholder="keyword search" autocomplete="off"}}
|
{{/dropdown-dialog}}
|
||||||
</div>
|
|
||||||
{{#unless hasMatches}}
|
|
||||||
Nothing found.
|
|
||||||
{{/unless}}
|
|
||||||
<ul class="link-list">
|
|
||||||
{{#each matches.documents as |m|}}
|
|
||||||
<li class="link-item" {{ action 'setSelection' m }}>
|
|
||||||
{{#ui/ui-selection selected=m.selected}}
|
|
||||||
{{m.title}}
|
|
||||||
{{/ui/ui-selection}}
|
|
||||||
</li>
|
|
||||||
{{/each}}
|
|
||||||
{{#each matches.pages as |m|}}
|
|
||||||
<li class="link-item" {{ action 'setSelection' m }}>
|
|
||||||
{{#ui/ui-selection selected=m.selected}}
|
|
||||||
{{m.title}}<br/><span class="color-gray">{{m.context}}</span>
|
|
||||||
{{/ui/ui-selection}}
|
|
||||||
</li>
|
|
||||||
{{/each}}
|
|
||||||
{{#each matches.attachments as |a|}}
|
|
||||||
<li class="link-item" {{ action 'setSelection' a }}>
|
|
||||||
{{#ui/ui-selection selected=a.selected}}
|
|
||||||
<img class="icon" src="/assets/img/attachments/{{document/file-icon a.context}}" />
|
|
||||||
{{ a.title }}
|
|
||||||
{{/ui/ui-selection}}
|
|
||||||
</li>
|
|
||||||
{{/each}}
|
|
||||||
</ul>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<div class="hide regular-button button-blue pull-right" {{ action 'onInsertLink' }}>Insert</div>
|
|
||||||
<div class="hide clearfix" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{{/dropdown-dialog}}
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
<div class="document-editor">
|
<div class="document-editor {{if blockMode 'document-editor-full'}}">
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<div class="input-inline input-transparent edit-title pull-left">
|
|
||||||
{{focus-input type="text" id=pageId value=page.title class=(if hasNameError 'error-inline') placeholder="Name" class="mousetrap"}}
|
|
||||||
</div>
|
|
||||||
<div class="buttons pull-right">
|
<div class="buttons pull-right">
|
||||||
{{#if busy}}
|
{{#if busy}}
|
||||||
<img src="/assets/img/busy-gray.gif" class="busy-indicator" />
|
<img src="/assets/img/busy-gray.gif" class="busy-indicator" />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if contentLinkerButton}}
|
||||||
|
{{document/edit-tools tagName="span" document=document folder=folder page=page onInsertLink=(action 'onInsertLink')}}
|
||||||
|
<div class="round-button-mono" id={{contentLinkerButtonId}} data-tooltip="Reference link" data-tooltip-position="top center">
|
||||||
|
<i class="material-icons color-blue">link</i>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if previewButton}}
|
||||||
|
<div class="round-button-mono" {{action 'onPreview'}} id={{previewButtonId}} data-tooltip="Toggle Preview" data-tooltip-position="top center">
|
||||||
|
<i class="material-icons color-gray">visibility</i>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<div class="round-button-mono" {{action 'onAction'}}>
|
<div class="round-button-mono" {{action 'onAction'}}>
|
||||||
<i class="material-icons color-green">check</i>
|
<i class="material-icons color-green">check</i>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,7 +25,23 @@
|
||||||
<i class="material-icons color-gray">close</i>
|
<i class="material-icons color-gray">close</i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{#if blockMode}}
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
<div class="input-control">
|
||||||
|
<label>Name</label>
|
||||||
|
{{focus-input id="page-id-{{pageId}}" value=page.title class="mousetrap"}}
|
||||||
|
</div>
|
||||||
|
<div class="input-control">
|
||||||
|
<label>Description</label>
|
||||||
|
{{textarea id="page-excerpt-{{pageId}}" value=page.excerpt class="mousetrap" rows="3"}}
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="input-inline input-transparent edit-title pull-left">
|
||||||
|
{{focus-input type="text" id=pageId value=page.title class=(if hasNameError 'error-inline') placeholder="Name" class="mousetrap"}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
|
||||||
<div class="dropdown-dialog cancel-edits-dialog" id={{dialogId}}>
|
<div class="dropdown-dialog cancel-edits-dialog" id={{dialogId}}>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<p>Do you want to cancel editing and lose unsaved changes?</p>
|
<p>Do you want to cancel editing and lose unsaved changes?</p>
|
||||||
|
|
|
@ -1,15 +1,7 @@
|
||||||
{{#section/base-editor-inline document=document folder=folder page=page tip="Concise name that describes code snippet" isDirty=(action 'isDirty') onCancel=(action 'onCancel') onAction=(action 'onAction')}}
|
{{#section/base-editor-inline document=document folder=folder page=page blockMode=blockMode
|
||||||
<style>
|
contentLinkerButton=true onInsertLink=(action 'onInsertLink')
|
||||||
.CodeMirror {
|
previewButton=true onPreview=(action 'onPreview')
|
||||||
height: auto;
|
isDirty=(action 'isDirty') onCancel=(action 'onCancel') onAction=(action 'onAction')}}
|
||||||
font-size: 17px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="section-markdown-preview-button round-button-mono" id={{tooltipId}} {{action 'toggleMode'}} data-tooltip="Toggle Preview" data-tooltip-position="top center">
|
|
||||||
<i class="material-icons color-gray">visibility</i>
|
|
||||||
</div>
|
|
||||||
{{document/edit-tools document=document folder=folder page=page onInsertLink=(action 'onInsertLink')}}
|
|
||||||
|
|
||||||
<div class="section-code-editor">
|
<div class="section-code-editor">
|
||||||
{{#if editMode}}
|
{{#if editMode}}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{{#section/base-editor-inline document=document folder=folder page=page isDirty=(action 'isDirty') onCancel=(action 'onCancel') onAction=(action 'onAction')}}
|
{{#section/base-editor-inline document=document folder=folder page=page
|
||||||
{{document/edit-tools document=document folder=folder page=page onInsertLink=(action 'onInsertLink')}}
|
blockMode=blockMode contentLinkerButton=true onInsertLink=(action 'onInsertLink')
|
||||||
|
isDirty=(action 'isDirty') onCancel=(action 'onCancel') onAction=(action 'onAction')}}
|
||||||
<div id={{editorId}} class="mousetrap wysiwyg wysiwyg-editor">
|
<div id={{editorId}} class="mousetrap wysiwyg wysiwyg-editor">
|
||||||
{{{pageBody}}}
|
{{{pageBody}}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -320,9 +320,15 @@ func UpdateBlock(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "UpdateBlock"
|
method := "UpdateBlock"
|
||||||
p := request.GetPersister(r)
|
p := request.GetPersister(r)
|
||||||
|
|
||||||
|
params := mux.Vars(r)
|
||||||
|
blockID := params["blockID"]
|
||||||
|
if len(blockID) == 0 {
|
||||||
|
writeMissingDataError(w, method, "blockID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
defer utility.Close(r.Body)
|
defer utility.Close(r.Body)
|
||||||
body, err := ioutil.ReadAll(r.Body)
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeBadRequestError(w, method, "Bad payload")
|
writeBadRequestError(w, method, "Bad payload")
|
||||||
return
|
return
|
||||||
|
@ -335,6 +341,8 @@ func UpdateBlock(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.RefID = blockID
|
||||||
|
|
||||||
if !p.CanUploadDocument(b.LabelID) {
|
if !p.CanUploadDocument(b.LabelID) {
|
||||||
writeForbiddenError(w)
|
writeForbiddenError(w)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue