1
0
Fork 0
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:
Harvey Kandola 2017-12-14 13:25:05 +00:00
parent b339df5125
commit 3329942d8a
11 changed files with 140 additions and 132 deletions

View file

@ -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
} }
}; };

View file

@ -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
*/

View file

@ -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>

View file

@ -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);
}
});

View file

@ -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;
} // }
} // }

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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">

View file

@ -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');

View file

@ -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

File diff suppressed because one or more lines are too long