mirror of
https://github.com/documize/community.git
synced 2025-07-22 14:49:42 +02:00
responsive doc TOC
This commit is contained in:
parent
b339df5125
commit
3329942d8a
11 changed files with 140 additions and 132 deletions
|
@ -19,18 +19,17 @@ module.exports = {
|
||||||
"_": true,
|
"_": true,
|
||||||
"tinymce": true,
|
"tinymce": true,
|
||||||
"CodeMirror": true,
|
"CodeMirror": true,
|
||||||
"Drop": true,
|
|
||||||
"Mousetrap": true,
|
"Mousetrap": true,
|
||||||
"Sortable": true,
|
"Sortable": true,
|
||||||
"moment": true,
|
"moment": true,
|
||||||
"Dropzone": true,
|
"Dropzone": true,
|
||||||
"Tooltip": true,
|
|
||||||
"server": true,
|
"server": true,
|
||||||
"authenticateUser": true,
|
"authenticateUser": true,
|
||||||
"stubAudit": true,
|
"stubAudit": true,
|
||||||
"stubUserNotification": true,
|
"stubUserNotification": true,
|
||||||
"userLogin": true,
|
"userLogin": true,
|
||||||
"Keycloak": true,
|
"Keycloak": true,
|
||||||
"slug": true
|
"slug": true,
|
||||||
|
"interact": true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
// https://documize.com
|
// https://documize.com
|
||||||
|
|
||||||
import { computed } from '@ember/object';
|
import { computed } from '@ember/object';
|
||||||
|
import { schedule } from '@ember/runloop';
|
||||||
import Component from '@ember/component';
|
import Component from '@ember/component';
|
||||||
import tocUtil from '../../utils/toc';
|
import tocUtil from '../../utils/toc';
|
||||||
import NotifierMixin from '../../mixins/notifier';
|
import NotifierMixin from '../../mixins/notifier';
|
||||||
|
@ -29,7 +30,7 @@ export default Component.extend(NotifierMixin, {
|
||||||
emptyState: computed('pages', function () {
|
emptyState: computed('pages', function () {
|
||||||
return this.get('pages.length') === 0;
|
return this.get('pages.length') === 0;
|
||||||
}),
|
}),
|
||||||
isDesktop: true,
|
isDesktop: false,
|
||||||
|
|
||||||
didReceiveAttrs() {
|
didReceiveAttrs() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
@ -48,6 +49,11 @@ export default Component.extend(NotifierMixin, {
|
||||||
|
|
||||||
this.eventBus.subscribe('documentPageAdded', this, 'onDocumentPageAdded');
|
this.eventBus.subscribe('documentPageAdded', this, 'onDocumentPageAdded');
|
||||||
this.eventBus.subscribe('resized', this, 'onResize');
|
this.eventBus.subscribe('resized', this, 'onResize');
|
||||||
|
|
||||||
|
schedule('afterRender', () => {
|
||||||
|
// let dg = $('#doc-toc').draggabilly({});
|
||||||
|
// this.set('dg', dg);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
willDestroyElement() {
|
willDestroyElement() {
|
||||||
|
@ -67,8 +73,10 @@ export default Component.extend(NotifierMixin, {
|
||||||
},
|
},
|
||||||
|
|
||||||
setSize() {
|
setSize() {
|
||||||
this.set('isDesktop', $(window).width() >= 1800);
|
let isDesktop = $(window).width() >= 1800;
|
||||||
|
this.set('isDesktop', isDesktop);
|
||||||
|
|
||||||
|
if (isDesktop) {
|
||||||
let h = $(window).height() - $("#nav-bar").height() - 140;
|
let h = $(window).height() - $("#nav-bar").height() - 140;
|
||||||
$("#doc-toc").css('max-height', h);
|
$("#doc-toc").css('max-height', h);
|
||||||
|
|
||||||
|
@ -79,6 +87,71 @@ export default Component.extend(NotifierMixin, {
|
||||||
if (l > 350) l = 350;
|
if (l > 350) l = 350;
|
||||||
$("#doc-toc").width(l);
|
$("#doc-toc").width(l);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
schedule('afterRender', () => {
|
||||||
|
interact('#doc-toc')
|
||||||
|
.draggable({
|
||||||
|
autoScroll: true,
|
||||||
|
onmove: dragMoveListener,
|
||||||
|
// inertia: true,
|
||||||
|
restrict: {
|
||||||
|
// restriction: ".body",
|
||||||
|
// endOnly: true,
|
||||||
|
// elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.resizable({
|
||||||
|
// resize from all edges and corners
|
||||||
|
edges: { left: true, right: true, bottom: true, top: true },
|
||||||
|
// keep the edges inside the parent
|
||||||
|
// restrictEdges: {
|
||||||
|
// outer: 'parent',
|
||||||
|
// endOnly: true,
|
||||||
|
// },
|
||||||
|
// minimum size
|
||||||
|
restrictSize: {
|
||||||
|
min: { width: 250, height: 65 },
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('resizemove', function (event) {
|
||||||
|
var target = event.target,
|
||||||
|
x = (parseFloat(target.getAttribute('data-x')) || 0),
|
||||||
|
y = (parseFloat(target.getAttribute('data-y')) || 0);
|
||||||
|
|
||||||
|
// update the element's style
|
||||||
|
target.style.width = event.rect.width + 'px';
|
||||||
|
target.style.height = event.rect.height + 'px';
|
||||||
|
|
||||||
|
// translate when resizing from top or left edges
|
||||||
|
x += event.deltaRect.left;
|
||||||
|
y += event.deltaRect.top;
|
||||||
|
|
||||||
|
target.style.webkitTransform = target.style.transform = 'translate(' + x + 'px,' + y + 'px)';
|
||||||
|
|
||||||
|
target.setAttribute('data-x', x);
|
||||||
|
target.setAttribute('data-y', y);
|
||||||
|
target.style.position = 'fixed';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function dragMoveListener (event) {
|
||||||
|
var target = event.target,
|
||||||
|
// keep the dragged position in the data-x/data-y attributes
|
||||||
|
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
|
||||||
|
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
|
||||||
|
|
||||||
|
// translate the element
|
||||||
|
target.style.webkitTransform = target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
|
||||||
|
|
||||||
|
// update the posiion attributes
|
||||||
|
target.setAttribute('data-x', x);
|
||||||
|
target.setAttribute('data-y', y);
|
||||||
|
target.style.position = 'fixed';
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is used later in the resizing and gesture demos
|
||||||
|
window.dragMoveListener = dragMoveListener;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Controls what user can do with the toc (left sidebar)
|
// Controls what user can do with the toc (left sidebar)
|
||||||
|
@ -181,44 +254,3 @@ export default Component.extend(NotifierMixin, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
Specs
|
|
||||||
-----
|
|
||||||
|
|
||||||
1. Must max max height to prevent off screen problems
|
|
||||||
2. Must be usable on mobile and desktop
|
|
||||||
3. Must be sticky and always visible (at least desktop)
|
|
||||||
4. Must set width or leave to grid system
|
|
||||||
|
|
||||||
Solution
|
|
||||||
--------
|
|
||||||
|
|
||||||
1. max-height calc on insert/repaint
|
|
||||||
1. overflow: scroll
|
|
||||||
|
|
||||||
2. on mobile/sm/md/lg we can put in little box to side of doc meta
|
|
||||||
and then set to fixed height based on screen size
|
|
||||||
2. on xl we can put into sidebar
|
|
||||||
|
|
||||||
3. sticky on xl desktop is fine as sidebar uses fixed position
|
|
||||||
and content has max-height with overflow
|
|
||||||
3. sticky on col/sm/md/lg is not available
|
|
||||||
|
|
||||||
Notes
|
|
||||||
-----
|
|
||||||
|
|
||||||
We could go with container-fluid and use full width of screen.
|
|
||||||
This would work on all devices and take more space on
|
|
||||||
|
|
||||||
$(window).width() needs to be 1800 or more for sticky sidebar...
|
|
||||||
$("#nav-bar").height()
|
|
||||||
$(window).height() - $("#nav-bar").height() - 100
|
|
||||||
|
|
||||||
Two choices:
|
|
||||||
|
|
||||||
if width >= 1800 then sidebar sticky outside container
|
|
||||||
if widht < 1800 then switch to container-fluid?
|
|
||||||
...but what about height?
|
|
||||||
...put next to doc--meta
|
|
||||||
*/
|
|
||||||
|
|
|
@ -1,24 +1,33 @@
|
||||||
{{toolbar/nav-bar}}
|
{{toolbar/nav-bar}}
|
||||||
|
|
||||||
<div class="d-none d-xl-block">
|
|
||||||
{{document/document-toc document=model.document folder=model.folder pages=model.pages page=model.page permissions=model.permissions
|
|
||||||
onPageSequenceChange=(action 'onPageSequenceChange') onPageLevelChange=(action 'onPageLevelChange') onGotoPage=(action 'onGotoPage')}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="doc-view" class="container">
|
<div id="doc-view" class="container">
|
||||||
<div class="row">
|
|
||||||
<div class="col-12">
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mb-5">
|
||||||
{{toolbar/for-document document=model.document spaces=model.folders space=model.folder permissions=model.permissions
|
{{toolbar/for-document document=model.document spaces=model.folders space=model.folder permissions=model.permissions
|
||||||
onDocumentDelete=(action 'onDocumentDelete') onSaveTemplate=(action 'onSaveTemplate')}}
|
onDocumentDelete=(action 'onDocumentDelete') onSaveTemplate=(action 'onSaveTemplate')}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
{{document/document-heading document=model.document permissions=model.permissions
|
{{document/document-heading document=model.document permissions=model.permissions
|
||||||
onSaveDocument=(action 'onSaveDocument')}}
|
onSaveDocument=(action 'onSaveDocument')}}
|
||||||
|
|
||||||
{{document/document-meta document=model.document folder=model.folder folders=model.folders permissions=model.permissions
|
{{document/document-meta document=model.document folder=model.folder folders=model.folders permissions=model.permissions
|
||||||
onSaveDocument=(action 'onSaveDocument')}}
|
onSaveDocument=(action 'onSaveDocument')}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
{{document/document-toc document=model.document folder=model.folder pages=model.pages page=model.page permissions=model.permissions
|
||||||
|
onPageSequenceChange=(action 'onPageSequenceChange') onPageLevelChange=(action 'onPageLevelChange') onGotoPage=(action 'onGotoPage')}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mb-5 text-center">
|
<div class="row no-gutters">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="mt-5 mb-5 text-center">
|
||||||
<ul class="tabnav-control">
|
<ul class="tabnav-control">
|
||||||
<li class="tab {{if (eq tab 'content') 'selected'}}" {{action 'onTabChange' 'content'}}>Content</li>
|
<li class="tab {{if (eq tab 'content') 'selected'}}" {{action 'onTabChange' 'content'}}>Content</li>
|
||||||
<li class="tab {{if (eq tab 'attachment') 'selected'}}" {{action 'onTabChange' 'attachment'}}>Attachments</li>
|
<li class="tab {{if (eq tab 'attachment') 'selected'}}" {{action 'onTabChange' 'attachment'}}>Attachments</li>
|
||||||
|
@ -47,9 +56,7 @@
|
||||||
{{#if (eq tab 'revision')}}
|
{{#if (eq tab 'revision')}}
|
||||||
{{document/view-revision document=model.document folder=model.folder pages=model.pages onRollback=(action 'onRollback')}}
|
{{document/view-revision document=model.document folder=model.folder pages=model.pages onRollback=(action 'onRollback')}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
// 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 Service from '@ember/service';
|
|
||||||
|
|
||||||
import Ember from 'ember';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a work around problems that tether introduces into testing.
|
|
||||||
* TODO: remove this code and refactor in favour of ember-tether
|
|
||||||
*/
|
|
||||||
export default Service.extend({
|
|
||||||
createDrop() {
|
|
||||||
if (Ember.testing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Drop(...arguments);
|
|
||||||
},
|
|
||||||
createTooltip() {
|
|
||||||
if (Ember.testing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Tooltip(...arguments);
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -32,10 +32,10 @@
|
||||||
@import "section/wysiwyg.scss";
|
@import "section/wysiwyg.scss";
|
||||||
|
|
||||||
// Bootstrap override that removes gutter space on smaller screens
|
// Bootstrap override that removes gutter space on smaller screens
|
||||||
@media (max-width: 1200px) {
|
// @media (max-width: 1200px) {
|
||||||
.container {
|
// .container {
|
||||||
width: 100%;
|
// width: 100%;
|
||||||
max-width: none;
|
// max-width: none;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
.view-document {
|
.view-document {
|
||||||
> .document-heading {
|
> .document-heading {
|
||||||
margin-top: 3rem;
|
|
||||||
|
|
||||||
.doc-title {
|
.doc-title {
|
||||||
margin: 50px 0 10px;
|
margin: 50px 0 10px;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
|
@ -16,7 +14,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
> .document-heading-edit {
|
> .document-heading-edit {
|
||||||
margin-top: 5.5rem;
|
margin-top: 3.5rem;
|
||||||
margin-bottom: 3rem;
|
margin-bottom: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
.document-toc {
|
.document-toc {
|
||||||
@include border-radius(3px);
|
@include border-radius(3px);
|
||||||
margin: 30px 0 30px 0;
|
@include ease-in();
|
||||||
|
margin: 0;
|
||||||
padding: 0 20px 20px 20px;
|
padding: 0 20px 20px 20px;
|
||||||
background-color: $color-off-white;
|
background-color: $color-off-white;
|
||||||
border: 1px solid $color-border;
|
border: 1px solid $color-border;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
|
box-sizing: border-box; // ensures width/height properties (and min/max properties) includes content, padding and border
|
||||||
|
z-index: 777;
|
||||||
|
|
||||||
> .header {
|
> .header {
|
||||||
@include sticky();
|
@include sticky();
|
||||||
|
@ -36,7 +39,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
> .index-list {
|
> .index-list {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
@ -77,12 +79,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.document-toc-desktop {
|
.document-toc-desktop {
|
||||||
|
margin: 30px 0 30px 0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
top: 100px;
|
||||||
right: 30px;
|
right: 30px;
|
||||||
z-index: 777;
|
-webkit-transform: translate(0px, 0px);
|
||||||
|
transform: translate(0px, 0px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.document-toc-small {
|
.document-toc-small {
|
||||||
display: block;
|
display: inline-block;
|
||||||
|
position: relative !important;
|
||||||
|
margin: 0;
|
||||||
|
width: 100% !important;
|
||||||
|
height: 500px;
|
||||||
|
transform: none !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
<div class="mt-5">
|
<div class="mt-5">
|
||||||
{{#if hasRevisions}}
|
{{#if hasRevisions}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-10">
|
<div class="col-12">
|
||||||
|
<div class="form-group">
|
||||||
{{ui-select tagName="span" class="revision-picker" content=revisions action=(action 'onSelectRevision') optionValuePath="id" optionLabelPath="label"}}
|
{{ui-select tagName="span" class="revision-picker" content=revisions action=(action 'onSelectRevision') optionValuePath="id" optionLabelPath="label"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2">
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="form-group">
|
||||||
<div id="restore-history-button" class="btn btn-success" data-toggle="modal" data-target="#document-rollback-modal" data-backdrop="static">Restore</div>
|
<div id="restore-history-button" class="btn btn-success" data-toggle="modal" data-target="#document-rollback-modal" data-backdrop="static">Restore</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 view-revision">
|
<div class="col-12 view-revision">
|
||||||
<div class="diff-zone">
|
<div class="diff-zone">
|
||||||
|
|
|
@ -45,6 +45,7 @@ module.exports = function (defaults) {
|
||||||
app.import('vendor/documize.js');
|
app.import('vendor/documize.js');
|
||||||
app.import('vendor/dropzone.js');
|
app.import('vendor/dropzone.js');
|
||||||
app.import('vendor/hoverIntent.min.js');
|
app.import('vendor/hoverIntent.min.js');
|
||||||
|
app.import('vendor/interact.min.js');
|
||||||
app.import('vendor/is.js');
|
app.import('vendor/is.js');
|
||||||
app.import('vendor/keycloak.js');
|
app.import('vendor/keycloak.js');
|
||||||
app.import('vendor/markdown-it.min.js');
|
app.import('vendor/markdown-it.min.js');
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
|
|
||||||
<cross-domain-policy>
|
|
||||||
<!-- Read this: www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html -->
|
|
||||||
|
|
||||||
<!-- Most restrictive policy: -->
|
|
||||||
<!--<site-control permitted-cross-domain-policies="none"/>-->
|
|
||||||
|
|
||||||
<!-- Least restrictive policy: -->
|
|
||||||
<!--<site-control permitted-cross-domain-policies="all"/>
|
|
||||||
<allow-access-from domain="*" to-ports="*" secure="false"/>
|
|
||||||
<allow-http-request-headers-from domain="*" headers="*" secure="false"/>-->
|
|
||||||
|
|
||||||
</cross-domain-policy>
|
|
4
gui/vendor/interact.min.js
vendored
Executable file
4
gui/vendor/interact.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue