1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-18 20:59:43 +02:00

document tab basics

This commit is contained in:
Harvey Kandola 2016-11-09 15:16:44 -08:00
parent 5c09407d2f
commit 8caa53bed7
49 changed files with 493 additions and 239 deletions

View file

@ -5,7 +5,17 @@
"indent_with_tabs": true,
"preserve_newlines": true,
"max_preserve_newlines": 2,
"newline_between_rules": true
"newline_between_rules": true,
"selector_separator_newlines": true
},
"scss": {
"indent_size": 4,
"indent_level": 0,
"indent_with_tabs": true,
"preserve_newlines": true,
"max_preserve_newlines": 2,
"newline_between_rules": true,
"selector_separator_newlines": true
},
"html": {
"indent_size": 4,
@ -49,4 +59,4 @@
"indent_level": 0,
"indent_with_tabs": true
}
}
}

View file

@ -0,0 +1,45 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import NotifierMixin from '../../mixins/notifier';
import TooltipMixin from '../../mixins/tooltip';
export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
viewMode: true,
editMode: false,
actions: {
onEdit() {
this.set('viewMode', false);
this.set('editMode', true);
},
onView() {
this.set('viewMode', true);
this.set('editMode', false);
},
onCancel() {
this.send('onView');
},
onAction(page, meta) {
this.get('onAction')(page, meta);
this.send('onView');
},
onDelete() {
this.get('onDelete')(this.get('model.document'), this.get('model.page'));
return true;
}
}
});

View file

@ -30,6 +30,12 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
this.set('saveTemplate.description', this.get('document.excerpt'));
},
didRender() {
if (this.session.isEditor) {
this.addTooltip(document.getElementById("add-document-tab"));
}
},
willDestroyElement() {
this.destroyTooltips();
},
@ -67,4 +73,4 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
return true;
}
}
});
});

View file

@ -18,26 +18,17 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
sectionService: Ember.inject.service('section'),
appMeta: Ember.inject.service(),
link: Ember.inject.service(),
/* Parameters */
document: null,
// pages: [],
attachments: [],
folder: null,
folders: [],
isEditor: false,
/* Internal */
drop: null,
deleteAttachment: {
id: "",
name: "",
},
noSections: Ember.computed('pages', function () {
return this.get('pages.length') === 0;
}),
didInsertElement() {
let self = this;
// let self = this;
// this.get('sectionService').refresh(this.get('document.id')).then(function (changes) {
// changes.forEach(function (newPage) {
@ -57,12 +48,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
willDestroyElement() {
this.destroyTooltips();
let drop = this.get('drop');
if (is.not.null(drop)) {
drop.destroy();
}
},
contentLinkHandler() {
@ -70,7 +55,7 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
let doc = this.get('document');
let self = this;
$("a[data-documize='true']").off('click').on('click', function(e) {
$("a[data-documize='true']").off('click').on('click', function (e) {
let link = links.getLinkObject(self.get('meta.outboundLinks'), this);
// local link? exists?
@ -99,55 +84,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
},
actions: {
confirmDeleteAttachment(id, name) {
this.set('deleteAttachment', {
id: id,
name: name
});
$(".delete-attachment-dialog").css("display", "block");
let drop = new Drop({
target: $(".delete-attachment-" + id)[0],
content: $(".delete-attachment-dialog")[0],
classes: 'drop-theme-basic',
position: "bottom right",
openOn: "always",
tetherOptions: {
offset: "5px 0",
targetOffset: "10px 0"
},
remove: false
});
this.set('drop', drop);
},
cancel() {
let drop = this.get('drop');
drop.close();
this.set('deleteAttachment', {
id: "",
name: ""
});
},
deleteAttachment() {
let attachment = this.get('deleteAttachment');
let drop = this.get('drop');
drop.close();
this.showNotification(`Deleted ${attachment.name}`);
this.attrs.onAttachmentDeleted(this.get('deleteAttachment').id);
this.set('deleteAttachment', {
id: "",
name: ""
});
return true;
},
onDeletePage(id, deleteChildren) {
let page = this.get('pages').findBy("id", id);
@ -164,7 +100,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
this.attrs.onDeletePage(params);
},
// onTagChange event emitted from document/tag-editor component
onTagChange(tags) {
let doc = this.get('document');
doc.set('tags', tags);

View file

@ -13,31 +13,28 @@ import Ember from 'ember';
import NotifierMixin from '../../mixins/notifier';
export default Ember.Component.extend(NotifierMixin, {
sectionService: Ember.inject.service('section'),
display: 'section', // which CSS to use
didReceiveAttrs() {
didRender() {
let self = this;
this.get('sectionService').getAll().then(function(sections) {
self.set('sections', sections);
Mousetrap.bind('esc', function () {
if (self.get('isDestroyed') || self.get('isDestroying')) {
return;
}
self.send('onCancel');
return false;
});
},
didRender() {
let self = this;
Mousetrap.bind('esc', function() {
self.send('onCancel');
return false;
});
},
actions: {
actions: {
onCancel() {
this.attrs.onCancel();
},
addSection(section) {
this.attrs.onAction(section);
}
}
addSection(section) {
this.attrs.onAction(section);
}
}
});

View file

@ -18,6 +18,7 @@ export default Model.extend({
documentId: attr('string'),
orgId: attr('string'),
contentType: attr('string'),
pageType: attr('string'),
level: attr('number', { defaultValue: 1 }),
sequence: attr('number', { defaultValue: 0 }),
revisions: attr('number', { defaultValue: 0 }),
@ -41,4 +42,4 @@ export default Model.extend({
}),
created: attr(),
revised: attr()
});
});

View file

@ -16,6 +16,7 @@ import Ember from 'ember';
export default Model.extend({
contentType: attr('string'),
pageType: attr('string'),
title: attr('string'),
description: attr('string'),
iconFont: attr('string'),
@ -24,6 +25,7 @@ export default Model.extend({
hasImage: Ember.computed('iconFont', 'iconFile', function () {
return this.get('iconFile').length > 0;
}),
created: attr(),
revised: attr()
});
});

View file

@ -172,7 +172,8 @@ export default Ember.Controller.extend(NotifierMixin, {
level: 1,
sequence: 2048,
body: "",
contentType: section.get('contentType')
contentType: section.get('contentType'),
pageType: section.get('pageType')
};
let data = this.get('store').normalize('page', page);
@ -212,4 +213,4 @@ export default Ember.Controller.extend(NotifierMixin, {
});
}
}
});
});

View file

@ -93,13 +93,6 @@ export default Ember.Controller.extend(NotifierMixin, {
}
self.set('pages', _.sortBy(self.get('pages'), "sequence"));
self.audit.record("deleted-page");
// fetch document meta
self.get('documentService').getMeta(self.model.get('id')).then(function (meta) {
self.set('meta', meta);
});
});
} else {
// page delete followed by re-leveling child pages
@ -107,17 +100,12 @@ export default Ember.Controller.extend(NotifierMixin, {
self.set('pages', _.reject(self.get('pages'), function (p) {
return p.get('id') === deleteId;
}));
self.audit.record("deleted-page");
// fetch document meta
self.get('documentService').getMeta(self.model.get('id')).then(function (meta) {
self.set('meta', meta);
});
});
self.send('onPageLevelChange', pendingChanges);
}
self.audit.record("deleted-page");
},
}
});

View file

@ -62,6 +62,6 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
controller.set('folders', this.get('folders').rejectBy('id', 0));
controller.set('currentPage', this.pageId);
controller.set('isEditor', this.get('folderService').get('canEditCurrentFolder'));
controller.set('pages', this.get('pages'));
controller.set('pages', this.get('pages').filterBy('pageType', 'section'));
}
});

View file

@ -13,6 +13,7 @@ import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
sectionService: Ember.inject.service('section'),
documentService: Ember.inject.service('document'),
folderService: Ember.inject.service('folder'),
userService: Ember.inject.service('user'),
@ -46,7 +47,11 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
return new Ember.RSVP.Promise(function (resolve) {
self.get('documentService').getPages(documentId).then(function (pages) {
self.set('pages', pages);
resolve();
self.get('sectionService').getAll().then(function (sections) {
self.set('sections', sections.filterBy('pageType', 'section'));
resolve();
});
});
});
},
@ -57,7 +62,9 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
controller.set('folders', this.get('folders').rejectBy('id', 0));
controller.set('currentPage', this.pageId);
controller.set('isEditor', this.get('folderService').get('canEditCurrentFolder'));
controller.set('pages', this.get('pages'));
controller.set('pages', this.get('pages').filterBy('pageType', 'section'));
controller.set('tabs', this.get('pages').filterBy('pageType', 'tab'));
controller.set('sections', this.get('sections'));
// setup document owner
let owner = this.get('users').findBy('id', model.get('userId'));

View file

@ -0,0 +1,46 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import NotifierMixin from '../../../mixins/notifier';
export default Ember.Controller.extend(NotifierMixin, {
documentService: Ember.inject.service('document'),
actions: {
onAction(page, meta) {
let self = this;
this.showNotification("Saving");
let model = {
page: page.toJSON({ includeId: true }),
meta: meta.toJSON({ includeId: true })
};
this.get('documentService').updatePage(page.get('documentId'), page.get('id'), model).then(function (page) {
self.audit.record("edited-page");
let data = self.get('store').normalize('page', page);
self.get('store').push(data);
});
},
onDelete(document, page) {
let self = this;
this.get('documentService').deletePage(document.get('id'), page.get('id')).then(function () {
page.deleteRecord();
self.audit.record("deleted-page");
self.showNotification('Deleted');
self.transitionToRoute('document');
});
}
}
});

View file

@ -0,0 +1,48 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
documentService: Ember.inject.service('document'),
folderService: Ember.inject.service('folder'),
userService: Ember.inject.service('user'),
pageId: '',
model(params) {
let self = this;
let document = this.modelFor('document');
let folders = this.get('store').peekAll('folder');
let folder = this.get('store').peekRecord('folder', this.paramsFor('document').folder_id);
let pages = this.get('store').peekAll('page').filter((page) => {
return page.get('documentId') === document.get('id') && page.get('pageType') === 'section';
});
let tabs = this.get('store').peekAll('page').filter((page) => {
return page.get('documentId') === document.get('id') && page.get('pageType') === 'tab';
});
let page = tabs.findBy('id', params.page_id);
this.audit.record("viewed-document-section-" + page.get('contentType'));
return Ember.RSVP.hash({
folders: folders,
folder: folder,
document: document,
pages: pages,
page: page,
meta: self.get('documentService').getPageMeta(document.get('id'), params.page_id)
});
},
});

View file

@ -0,0 +1 @@
{{document/document-tab model=model onAction=(action 'onAction') onDelete=(action 'onDelete')}}

View file

@ -1,15 +1,9 @@
{{layout/zone-navigation}}
{{#layout/zone-sidebar}}
{{document/document-sidebar document=model folder=folder pages=pages page=page isEditor=isEditor onAddSection=(action
'onAddSection') changePageSequence=(action 'onPageSequenceChange') changePageLevel=(action 'onPageLevelChange') gotoPage=(action
'gotoPage')}}
{{document/document-sidebar document=model folder=folder pages=pages page=page isEditor=isEditor sections=sections onAddSection=(action 'onAddSection') changePageSequence=(action 'onPageSequenceChange') changePageLevel=(action 'onPageLevelChange') gotoPage=(action 'gotoPage')}}
{{/layout/zone-sidebar}}
{{#layout/zone-content}}
{{document/document-toolbar document=model pages=pages folder=folder isEditor=isEditor onSaveTemplate=(action
'onSaveTemplate') onDocumentDelete=(action
'onDocumentDelete')}}
{{outlet}}
{{document/document-toolbar document=model pages=pages tabs=tabs folder=folder isEditor=isEditor onSaveTemplate=(action 'onSaveTemplate') onDocumentDelete=(action 'onDocumentDelete')}} {{outlet}}
{{/layout/zone-content}}

View file

@ -2,7 +2,7 @@ import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
documentService: Ember.inject.service('document'),
documentService: Ember.inject.service('document'),
folderService: Ember.inject.service('folder'),
sectionService: Ember.inject.service('section'),
@ -12,7 +12,9 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
return Ember.RSVP.hash({
folder: self.get('folderService').getFolder(self.paramsFor('document').folder_id),
document: self.get('documentService').getDocument(self.paramsFor('document').document_id),
sections: self.get('sectionService').getAll()
sections: this.get('sectionService').getAll().then(function (sections) {
return sections.filterBy('pageType', 'tab');
})
});
}
});

View file

@ -1 +1 @@
{{document/page-wizard document=model.document folder=model.folder sections=model.sections onCancel=(action 'onCancel') onAction=(action 'onAddSection')}}
{{document/page-wizard display='tab' document=model.document folder=model.folder sections=model.sections onCancel=(action 'onCancel') onAction=(action 'onAddSection')}}

View file

@ -41,6 +41,9 @@ export default Router.map(function () {
this.route('activity', {
path: 'activity'
});
this.route('section', {
path: 'section/:page_id'
});
this.route('edit', {
path: 'edit/:page_id'
});

View file

@ -20,7 +20,7 @@ $color-blue: #2667af;
$color-gray: #8b9096;
$color-goldy: #cc9933;
$color-header: #f3f5f8;
$color-sidebar: #f3f5f8;
$color-link: #0092d3;
$color-border: #f3f5f8;
@ -40,36 +40,47 @@ $color-chip-text: #1b88e3;
.color-white {
color: $color-white !important;
}
.color-off-white {
color: $color-off-white !important;
}
.color-black {
color: $color-black !important;
}
.color-off-black {
color: $color-off-black !important;
}
.color-primary {
color: $color-primary !important;
}
.color-link {
color: $color-link !important;
}
.color-blue {
color: $color-blue !important;
}
.color-red {
color: $color-red !important;
}
.color-green {
color: $color-green !important;
}
.color-gray {
color: $color-gray !important;
}
.background-color-white {
background-color: $color-white !important;
}
.background-color-primary {
background-color: $color-primary !important;
}

View file

@ -7,7 +7,7 @@
width: 100%;
padding: 10px;
white-space: nowrap;
overflow: auto
overflow: auto;
}
.github-repo-title {
@ -21,7 +21,6 @@
}
.github-list-title {
font-weight: bold;
color: #4c4c4c;
font-size: 14px;
margin: 5px;
@ -34,17 +33,16 @@
.github-issue-label {
font-size: 11px;
color: white;
padding: 0px 4px;
padding: 0 4px;
margin-right: 5px;
border-radius: 2px;
box-shadow: inset 0 -1px 0 rgba(0,0,0,0.12);
display: inline-block;
line-height: 22px;
}
}
}
.section-github-render {
a:hover {
text-decoration: underline;
}
@ -62,7 +60,7 @@
.heading {
font-size: 1.6rem;
margin: 30px 0 0 0;
margin: 30px 0 0;
}
.github-table thead tr th {
@ -73,36 +71,37 @@
text-align: left;
span {
color:#838d94;
color: #838d94;
}
}
.github-table tbody tr td {
border: none!important;
padding: 5px 20px 5px 20px !important;
padding: 5px 20px !important;
}
.github-table .right-column {
text-align: right;
color:#838d94;
color: #838d94;
}
span.data {
color:#838d94;
color: #838d94;
}
.issue-label {
color:white;
font-size: 11px;
padding: 4px 6px;
border-radius: 4px;
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.12);
margin-left: 10px;
color: white;
font-size: 11px;
padding: 4px 6px;
border-radius: 4px;
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.12);
margin-left: 10px;
}
.progress-bar {
display: inline-block; border-radius: 3px;
display: inline-block;
border-radius: 3px;
width: 40%;
background-color: #f1f1f1;
height: 8px;
@ -117,8 +116,8 @@
span.issue-state {
float: left;
margin-right: 10px;
margin-top: 3px;
margin-right: 10px;
margin-top: 3px;
}
img.github-avatar {

View file

@ -1,9 +1,7 @@
.document-editor {
> .toolbar {
@extend .z-depth-tiny;
background-color: $color-white;
width: 100%;
padding: 20px 40px;
padding: 0;
> .title {
width: 50%;
@ -12,7 +10,7 @@
margin: 0;
> input {
margin: 0 0 5px 0;
margin: 0 0 5px;
}
}
}
@ -23,7 +21,7 @@
}
> .canvas {
padding: 40px 40px;
padding: 40px 0;
}
.cancel-edits-dialog {

View file

@ -0,0 +1,9 @@
.document-section {
> .toolbar {
margin-bottom: 10px;
> .buttons {
margin: 10px 0;
}
}
}

View file

@ -3,7 +3,7 @@
margin: -30px 0 40px;
height: 60px;
padding: 5px 30px 0;
background-color: $color-off-white;
background-color: $color-sidebar;
@include border-radius-bottom-right(5px);
@include border-radius-bottom-left(5px);
@extend .no-select;
@ -33,6 +33,26 @@
> .active {
color: $color-link;
> .add-tab {
> i {
color: $color-link;
}
}
}
.add-tab {
display: inline-block;
vertical-align: text-top;
> i {
font-size: 1.5rem;
color: $color-gray;
&:hover {
color: $color-green;
}
}
}
}
}

View file

@ -1,5 +1,5 @@
.section-wizard {
margin: 20px 0 30px 0;
margin: 20px 0 30px;
> .canvas {
padding: 0;
@ -27,7 +27,7 @@
color: $color-primary;
}
}
}
}
.icon {
text-align: center;
@ -65,3 +65,73 @@
}
}
}
.tab-wizard {
margin: 20px 0 30px;
> .canvas {
padding: 0;
> .list {
margin: 0;
padding: 0;
> .item {
list-style: none;
cursor: pointer;
padding: 20px;
float: left;
@include ease-in();
&:hover {
@include ease-in();
> .details {
> .title {
color: $color-primary;
}
> .desc {
color: $color-primary;
}
}
}
.icon {
text-align: center;
display: inline-block;
width: 50px;
margin-right: 10px;
float: left;
> .img {
float: left;
text-align: center;
display: inline-block;
height: 40px;
width: 40px;
}
}
> .details {
vertical-align: top;
display: inline-block;
float: left;
> .title {
font-size: 1rem;
font-weight: bold;
color: $color-off-black;
letter-spacing: 0.5px;
}
> .desc {
color: $color-gray;
font-size: 0.9rem;
margin-top: 5px;
}
}
}
}
}
}

View file

@ -9,8 +9,8 @@
z-index: 999;
overflow-x: hidden;
> .top-zone,
> .bottom-zone {
> .bottom-zone,
> .top-zone {
position: absolute;
padding: 0;
width: 100%;
@ -101,7 +101,7 @@
}
.zone-sidebar {
background-color: $color-header;
background-color: $color-sidebar;
height: 100%;
min-height: 100%;
padding: 30px 40px 0;
@ -116,8 +116,8 @@
font-weight: bold;
margin-bottom: 10px;
> a > .material-icons,
> .material-icons {
> .material-icons,
> a > .material-icons {
font-size: 1rem;
vertical-align: middle;
}

View file

@ -1,55 +1,55 @@
.page-search {
.input-control {
> input {
background-color: $color-header;
background-color: $color-sidebar;
}
}
.search-results {
.heading {
font-size: 1.2rem;
color: $color-off-black;
}
.heading {
font-size: 1.2rem;
color: $color-off-black;
}
> .list {
margin-top: 20px;
> .list {
margin-top: 20px;
list-style: none;
> .item {
cursor: pointer;
> .item {
cursor: pointer;
margin: 0 30px 30px 0;
padding-bottom: 40px;
border-bottom: 1px solid #e1e1e1;
border-bottom: 1px solid #e1e1e1;
> .link {
text-decoration: none;
color: $color-off-black;
> .link {
text-decoration: none;
color: $color-off-black;
&:hover {
color: $color-link;
}
> .title {
display: inline-block;
> .title {
display: inline-block;
font-size: 1.2rem;
}
}
> .folder {
display: inline-block;
font-size: 0.8rem;
color: $color-gray;
display: inline-block;
font-size: 0.8rem;
color: $color-gray;
margin-left: 15px;
}
}
> .excerpt {
> .excerpt {
margin-top: 1rem;
font-size: 0.9rem;
}
font-size: 0.9rem;
}
> .chips {
margin-top: 1rem;
}
}
}
> .references {
margin-top: 1rem;
@ -69,7 +69,7 @@
}
}
}
}
}
}
}
}
}
}

View file

@ -51,8 +51,8 @@
overflow-y: hidden;
}
> div select,
> select {
> select,
> div select {
background-color: $color-white;
padding: 5px;
border: 1px solid $color-input;
@ -167,25 +167,25 @@
padding: 30px 40px;
border: 10px solid $color-border;
@include border-radius(15px);
}
> .form-header {
> .title {
font-size: 1.4rem;
font-weight: normal;
font-family: $font-semibold;
pointer-events: none;
font-weight: bold;
color: $color-off-black;
}
.form-header {
> .title {
font-size: 1.4rem;
font-weight: normal;
font-family: $font-semibold;
pointer-events: none;
font-weight: bold;
color: $color-off-black;
}
> .tip {
color: $color-input;
font-size: 1.2rem;
margin: 5px 0 30px;
padding: 0;
font-family: $font-light;
text-align: left;
}
> .tip {
color: $color-input;
font-size: 1.2rem;
margin: 5px 0 30px;
padding: 0;
font-family: $font-light;
text-align: left;
}
}

View file

@ -25,6 +25,6 @@
gotoPage=(action 'gotoPage')}}
{{/if}}
{{#if showSections}}
{{document/page-wizard document=document folder=folder onCancel=(action 'onCancel') onAction=(action 'onAddSection')}}
{{document/page-wizard display='section' document=document folder=folder sections=sections onCancel=(action 'onCancel') onAction=(action 'onAddSection')}}
{{/if}}
</div>

View file

@ -0,0 +1,31 @@
<div class="document-section">
{{#if viewMode}}
<div class="toolbar pull-right">
<div class="buttons">
<div class="round-button-mono" {{action 'onEdit'}}>
<i class="material-icons color-gray">edit</i>
</div>
<div class="button-gap"></div>
<div class="round-button-mono" id="delete-section-button">
<i class="material-icons color-gray">delete</i>
</div>
</div>
</div>
<div class="clearfix"/>
{{#dropdown-dialog target="delete-section-button" position="bottom right" button="Delete" color="flat-red" onAction=(action 'onDelete')}}
<p>Are you sure you want to delete this section?</p>
<p>There is no undo!</p>
{{/dropdown-dialog}}
<div class="wysiwyg">
<h1>{{model.page.title}}</h1>
{{section/base-renderer page=model.page}}
</div>
{{/if}}
{{#if editMode}}
{{document/document-editor document=model.document folder=model.folder page=model.page meta=model.meta onCancel=(action 'onCancel') onAction=(action 'onAction')}}
{{/if}}
</div>

View file

@ -17,6 +17,20 @@
{{#link-to 'document.activity'}}Activity{{/link-to}}
</li>
{{/if}}
{{#each tabs as |tab|}}
<li class="tab">
{{#link-to 'document.section' tab.id}}{{tab.title}}{{/link-to}}
</li>
{{/each}}
{{#if isEditor}}
<li class="tab">
{{#link-to 'document.wizard'}}
<div id="add-document-tab" class="add-tab" data-tooltip="Tab" data-tooltip-position="bottom center">
<i class="material-icons">add</i>
</div>
{{/link-to}}
</li>
{{/if}}
</ul>
<ul class="options">
@ -39,7 +53,7 @@
<p>Are you sure you want to delete this document?</p>
<p>There is no undo!</p>
{{/dropdown-dialog}}
{{#dropdown-dialog target="save-template-button" position="bottom right" button="Save as Template" color="flat-green" onAction=(action 'saveTemplate') focusOn="new-template-name"}}
{{#dropdown-dialog target="save-template-button" position="bottom right" button="Save as Template" color="flat-green" onAction=(action 'saveTemplate') focusOn="new-template-name" }}
<div>
<div class="input-control">
<label>Name</label>
@ -57,4 +71,4 @@
</div>
<div class="clearfix"/>
<div class="clearfix" />

View file

@ -1,5 +1,4 @@
<div class="document-view">
<div class="wysiwyg">
<h1 class="doc-name">{{document.name}}</h1>
</div>
@ -18,7 +17,8 @@
{{#each pages key="id" as |page index|}}
<div class="wysiwyg">
<div id="page-{{ page.id }}" class="is-a-page" data-id="{{ page.id }}" data-type="{{ page.contentType }}">
{{document/page-heading tagName=page.tagName document=document folder=folder page=page isEditor=isEditor onDeletePage=(action 'onDeletePage')}} {{section/base-renderer page=page}}
{{document/page-heading tagName=page.tagName document=document folder=folder page=page isEditor=isEditor onDeletePage=(action 'onDeletePage')}}
{{section/base-renderer page=page}}
</div>
</div>
{{/each}}

View file

@ -1,4 +1,4 @@
<div class="section-wizard">
<div class="{{display}}-wizard">
<div class="canvas">
<ul class="list">
{{#each sections as |section|}}

View file

@ -1,4 +1,4 @@
<div class="document-editor">
<div class="document-editor form-bordered">
<div class="toolbar">
<div class="title pull-left">
<div class="input-control">
@ -34,4 +34,5 @@
<div class="canvas">
{{yield}}
</div>
<div class="clearfix"></div>
</div>

View file

@ -5,31 +5,26 @@
{{#if authenticated}}
<div class="pull-left width-45">
<div class="input-form">
<div class="heading">
<div class="title">Select Repository</div>
<div class="tip">Choose source of code information to be displayed</div>
</div>
<div class="input-control">
<label>Organization or User</label>
<div class="tip">Select organization or username whose repository you want to show</div>
{{ui-select id="owners-dropdown" content=owners action=(action 'onOwnerChange') optionValuePath="id" optionLabelPath="name" selection=config.owner}}
</div>
<div class="input-control">
<label>Show items since (default 7 days ago)</label>
{{input id="branch-since" value=config.branchSince type="text" }}<br>
</div>
<div class="input-control">
<label>GitHub Views</label>
<div class="tip">Select the views you want to show</div>
<div class="github-view">
{{input id="show-milestone" checked=config.showMilestones type="checkbox"}}
<label>Show Milestones</label>
{{input id="show-issues" checked=config.showIssues type="checkbox"}}
<label>Show Issues</label>
{{input id="show-commits" checked=config.showCommits type="checkbox" }}
<label>Show Commits</label>
</div>
<div class="input-control">
<label>Select repository</label>
<div class="tip">Select organization or user whose repository you want to show</div>
{{ui-select id="owners-dropdown" content=owners action=(action 'onOwnerChange') optionValuePath="id" optionLabelPath="name" selection=config.owner}}
</div>
<div class="input-control">
<label>Show items since</label>
<div class="tip">default is 7 days ago</div>
{{input id="branch-since" value=config.branchSince type="text" }}<br>
</div>
<div class="input-control">
<label>GitHub Views</label>
<div class="tip">Select the views you want to show</div>
<div class="github-view">
{{input id="show-milestone" checked=config.showMilestones type="checkbox"}}
<label>Show Milestones</label>
{{input id="show-issues" checked=config.showIssues type="checkbox"}}
<label>Show Issues</label>
{{input id="show-commits" checked=config.showCommits type="checkbox" }}
<label>Show Commits</label>
</div>
</div>
</div>

View file

@ -182,6 +182,7 @@ type Page struct {
DocumentID string `json:"documentId"`
UserID string `json:"userId"`
ContentType string `json:"contentType"`
PageType string `json:"pageType"`
Level uint64 `json:"level"`
Sequence float64 `json:"sequence"`
Title string `json:"title"`
@ -193,6 +194,7 @@ type Page struct {
func (p *Page) SetDefaults() {
if len(p.ContentType) == 0 {
p.ContentType = "wysiwyg"
p.PageType = "section"
}
p.Title = strings.TrimSpace(p.Title)

View file

@ -50,7 +50,7 @@ func (p *Persister) AddPage(model models.PageModel) (err error) {
model.Page.Sequence = maxSeq * 2
}
stmt, err := p.Context.Transaction.Preparex("INSERT INTO page (refid, orgid, documentid, userid, contenttype, level, title, body, revisions, sequence, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
stmt, err := p.Context.Transaction.Preparex("INSERT INTO page (refid, orgid, documentid, userid, contenttype, pagetype, level, title, body, revisions, sequence, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
defer utility.Close(stmt)
if err != nil {
@ -58,7 +58,7 @@ func (p *Persister) AddPage(model models.PageModel) (err error) {
return
}
_, err = stmt.Exec(model.Page.RefID, model.Page.OrgID, model.Page.DocumentID, model.Page.UserID, model.Page.ContentType, model.Page.Level, model.Page.Title, model.Page.Body, model.Page.Revisions, model.Page.Sequence, model.Page.Created, model.Page.Revised)
_, err = stmt.Exec(model.Page.RefID, model.Page.OrgID, model.Page.DocumentID, model.Page.UserID, model.Page.ContentType, model.Page.PageType, model.Page.Level, model.Page.Title, model.Page.Body, model.Page.Revisions, model.Page.Sequence, model.Page.Created, model.Page.Revised)
if err != nil {
log.Error("Unable to execute insert for page", err)
@ -91,7 +91,7 @@ func (p *Persister) AddPage(model models.PageModel) (err error) {
func (p *Persister) GetPage(pageID string) (page entity.Page, err error) {
err = nil
stmt, err := Db.Preparex("SELECT a.id, a.refid, a.orgid, a.documentid, a.userid, a.contenttype, a.level, a.sequence, a.title, a.body, a.revisions, a.created, a.revised FROM page a WHERE a.orgid=? AND a.refid=?")
stmt, err := Db.Preparex("SELECT a.id, a.refid, a.orgid, a.documentid, a.userid, a.contenttype, a.pagetype, a.level, a.sequence, a.title, a.body, a.revisions, a.created, a.revised FROM page a WHERE a.orgid=? AND a.refid=?")
defer utility.Close(stmt)
if err != nil {
@ -113,7 +113,7 @@ func (p *Persister) GetPage(pageID string) (page entity.Page, err error) {
func (p *Persister) GetPages(documentID string) (pages []entity.Page, err error) {
err = nil
err = Db.Select(&pages, "SELECT a.id, a.refid, a.orgid, a.documentid, a.userid, a.contenttype, a.level, a.sequence, a.title, a.body, a.revisions, a.created, a.revised FROM page a WHERE a.orgid=? AND a.documentid=? ORDER BY a.sequence", p.Context.OrgID, documentID)
err = Db.Select(&pages, "SELECT a.id, a.refid, a.orgid, a.documentid, a.userid, a.contenttype, a.pagetype, a.level, a.sequence, a.title, a.body, a.revisions, a.created, a.revised FROM page a WHERE a.orgid=? AND a.documentid=? ORDER BY a.sequence", p.Context.OrgID, documentID)
if err != nil {
log.Error(fmt.Sprintf("Unable to execute select pages for org %s and document %s", p.Context.OrgID, documentID), err)
@ -130,7 +130,7 @@ func (p *Persister) GetPagesWhereIn(documentID, inPages string) (pages []entity.
args := []interface{}{p.Context.OrgID, documentID}
tempValues := strings.Split(inPages, ",")
sql := "SELECT a.id, a.refid, a.orgid, a.documentid, a.userid, a.contenttype, a.level, a.sequence, a.title, a.body, a.revisions, a.created, a.revised FROM page a WHERE a.orgid=? AND a.documentid=? AND a.refid IN (?" + strings.Repeat(",?", len(tempValues)-1) + ") ORDER BY sequence"
sql := "SELECT a.id, a.refid, a.orgid, a.documentid, a.userid, a.contenttype, a.pagetype, a.level, a.sequence, a.title, a.body, a.revisions, a.created, a.revised FROM page a WHERE a.orgid=? AND a.documentid=? AND a.refid IN (?" + strings.Repeat(",?", len(tempValues)-1) + ") ORDER BY sequence"
inValues := make([]interface{}, len(tempValues))
@ -180,7 +180,7 @@ func (p *Persister) GetPagesWhereIn(documentID, inPages string) (pages []entity.
// GetPagesWithoutContent returns a slice containing all the page records for a given documentID, in presentation sequence,
// but without the body field (which holds the HTML content).
func (p *Persister) GetPagesWithoutContent(documentID string) (pages []entity.Page, err error) {
err = Db.Select(&pages, "SELECT id, refid, orgid, documentid, userid, contenttype, sequence, level, title, revisions, created, revised FROM page WHERE orgid=? AND documentid=? ORDER BY sequence", p.Context.OrgID, documentID)
err = Db.Select(&pages, "SELECT id, refid, orgid, documentid, userid, contenttype, pagetype, sequence, level, title, revisions, created, revised FROM page WHERE orgid=? AND documentid=? ORDER BY sequence", p.Context.OrgID, documentID)
if err != nil {
log.Error(fmt.Sprintf("Unable to execute select pages for org %s and document %s", p.Context.OrgID, documentID), err)
@ -199,7 +199,7 @@ func (p *Persister) UpdatePage(page entity.Page, refID, userID string, skipRevis
// Store revision history
if !skipRevision {
var stmt *sqlx.Stmt
stmt, err = p.Context.Transaction.Preparex("INSERT INTO revision (refid, orgid, documentid, ownerid, pageid, userid, contenttype, title, body, rawbody, config, created, revised) SELECT ? as refid, a.orgid, a.documentid, a.userid as ownerid, a.refid as pageid, ? as userid, a.contenttype, a.title, a.body, b.rawbody, b.config, ? as created, ? as revised FROM page a, pagemeta b WHERE a.refid=? AND a.refid=b.pageid")
stmt, err = p.Context.Transaction.Preparex("INSERT INTO revision (refid, orgid, documentid, ownerid, pageid, userid, contenttype, pagetype, title, body, rawbody, config, created, revised) SELECT ? as refid, a.orgid, a.documentid, a.userid as ownerid, a.refid as pageid, ? as userid, a.contenttype, a.pagetype, a.title, a.body, b.rawbody, b.config, ? as created, ? as revised FROM page a, pagemeta b WHERE a.refid=? AND a.refid=b.pageid")
defer utility.Close(stmt)

View file

@ -149,6 +149,7 @@ CREATE TABLE IF NOT EXISTS `page` (
`documentid` CHAR(16) NOT NULL COLLATE utf8_bin,
`userid` CHAR(16) DEFAULT '' COLLATE utf8_bin,
`contenttype` CHAR(20) NOT NULL DEFAULT 'wysiwyg',
`pagetype` CHAR(10) NOT NULL DEFAULT 'section',
`level` INT UNSIGNED NOT NULL,
`sequence` DOUBLE NOT NULL,
`title` NVARCHAR(2000) NOT NULL,
@ -239,6 +240,7 @@ CREATE TABLE IF NOT EXISTS `revision` (
`pageid` CHAR(16) NOT NULL COLLATE utf8_bin,
`userid` CHAR(16) NOT NULL COLLATE utf8_bin,
`contenttype` CHAR(20) NOT NULL DEFAULT 'wysiwyg',
`pagetype` CHAR(10) NOT NULL DEFAULT 'section',
`title` NVARCHAR(2000) NOT NULL,
`body` LONGTEXT,
`rawbody` LONGBLOB,

View file

@ -0,0 +1,6 @@
/* community edition */
ALTER TABLE page ADD COLUMN `pagetype` CHAR(10) NOT NULL DEFAULT 'section' AFTER `contenttype`;
UPDATE page SET pagetype='tab' WHERE refid IN (SELECT pageid FROM pagemeta WHERE externalsource=1);
ALTER TABLE revision ADD COLUMN `pagetype` CHAR(10) NOT NULL DEFAULT 'section' AFTER `contenttype`;
UPDATE revision SET pagetype='tab' WHERE pageid IN (SELECT pageid FROM pagemeta WHERE externalsource=1);

View file

@ -29,6 +29,7 @@ func (*Provider) Meta() provider.TypeMeta {
section.Title = "Airtable"
section.Description = "Databases, tables, views"
section.ContentType = "airtable"
section.PageType = "tab"
return section
}

View file

@ -29,6 +29,7 @@ func (*Provider) Meta() provider.TypeMeta {
section.Title = "Code"
section.Description = "Formatted code snippets"
section.ContentType = "code"
section.PageType = "section"
section.Order = 9997
return section

View file

@ -35,6 +35,7 @@ func (*Provider) Meta() provider.TypeMeta {
section.Title = "Gemini"
section.Description = "Work items and tickets"
section.ContentType = "gemini"
section.PageType = "tab"
return section
}

View file

@ -39,6 +39,7 @@ func init() {
meta.Title = "GitHub"
meta.Description = "Link code commits and issues"
meta.ContentType = "github"
meta.PageType = "tab"
meta.Callback = Callback
}

View file

@ -30,6 +30,7 @@ func (*Provider) Meta() provider.TypeMeta {
section.Title = "Markdown"
section.Description = "CommonMark based content"
section.ContentType = "markdown"
section.PageType = "section"
section.Order = 9998
return section

View file

@ -38,6 +38,7 @@ func (*Provider) Meta() provider.TypeMeta {
section.Title = "Papertrail"
section.Description = "Display log entries"
section.ContentType = "papertrail"
section.PageType = "tab"
return section
}

View file

@ -35,6 +35,7 @@ type TypeMeta struct {
ID string `json:"id"`
Order int `json:"order"`
ContentType string `json:"contentType"`
PageType string `json:"pageType"`
Title string `json:"title"`
Description string `json:"description"`
Preview bool `json:"preview"` // coming soon!

View file

@ -39,5 +39,5 @@ func Register() {
provider.Register("wysiwyg", &wysiwyg.Provider{})
provider.Register("airtable", &airtable.Provider{})
p := provider.List()
log.Info(fmt.Sprintf("Documize registered %d smart sections", len(p)))
log.Info(fmt.Sprintf("Documize registered %d sections and tabs", len(p)))
}

View file

@ -29,6 +29,7 @@ func (*Provider) Meta() provider.TypeMeta {
section.Title = "Tabular"
section.Description = "Rows, columns for tabular data"
section.ContentType = "table"
section.PageType = "section"
section.Order = 9996
return section

View file

@ -36,6 +36,7 @@ func init() {
meta.Title = "Trello"
meta.Description = "Embed cards from boards and lists"
meta.ContentType = "trello"
meta.PageType = "tab"
}
// Provider represents Trello

View file

@ -29,6 +29,7 @@ func (*Provider) Meta() provider.TypeMeta {
section.Title = "Rich Text"
section.Description = "Rich text WYSIWYG"
section.ContentType = "wysiwyg"
section.PageType = "section"
section.Order = 9999
return section