Commit bb442936 authored by dindigala's avatar dindigala
Browse files

feature/#50: Making the viewer responsive

parent b5899025
......@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.2.0] - 2020-08-03
### Changed
- The logic of using splitters for mainview is removed and made use of Grid in order to make viewer responsive.
### Added
- Moved toggle buttons from the header into a dropdown menu items.
## [1.1.1] - 2020-08-03
### Fixed
......
{
"name": "viewer",
"version": "0.0.24",
"version": "1.2.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......@@ -2813,9 +2813,9 @@
}
},
"@quasar/extras": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.9.0.tgz",
"integrity": "sha512-+kWpgSMxvOuGLLQPT0PJL+SL7NPqhima4RfbJLRYbA8A3RAvFm8Ay5wE6CQKTn1sDHLBx/y/Zp+wvYlt1bfFLw=="
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.9.3.tgz",
"integrity": "sha512-9PXvmdxdO1Sa33X3FJ27T4ZBw9DEDnZcyqeGneOMSl/hzNCeEQ8BKk6ycUV9sdib0uH1sPXWEJ9m8v2QFylyqA=="
},
"@quasar/fastclick": {
"version": "1.1.4",
......@@ -4018,6 +4018,16 @@
"integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
"dev": true
},
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"dev": true,
"optional": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bl": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz",
......@@ -7286,6 +7296,13 @@
}
}
},
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"dev": true,
"optional": true
},
"filesize": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
......@@ -15178,6 +15195,7 @@
"dev": true,
"optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
},
......@@ -15814,6 +15832,7 @@
"dev": true,
"optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
},
......
{
"name": "viewer",
"version": "1.0.0",
"version": "1.2.0",
"description": "Viewer for the modular framework to present digital editions",
"productName": "EMo Viewer",
"keywords": [
......@@ -33,7 +33,7 @@
},
"private": false,
"dependencies": {
"@quasar/extras": "^1.9.0",
"@quasar/extras": "^1.9.3",
"openseadragon": "^2.4.2",
"quasar": "^1.12.13"
},
......
......@@ -12,10 +12,9 @@ module.exports = function (ctx) {
// https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css
css: [
// 'app.scss'
'../statics/support.css',
'/treeview.scss',
'/global.scss'
'/global.sass',
'/treeview.sass'
],
// https://github.com/quasarframework/quasar/tree/dev/extras
......
<template>
<q-header elevated class="bg-white text-black">
<q-header id="header" elevated class="bg-white text-black">
<div class="bar row justify-between items-center">
<Infobar v-if="config.headers.info && manifests.length"
class="col-xs-12 q-pl-md"
......@@ -64,9 +64,14 @@ export default {
</script>
<style scoped>
#header {
position: absolute;
top: 0;
left: 0;
}
.bar {
max-width: 1200px;
margin-left: auto;
margin-right: auto;
max-width: 1200px;
}
</style>
<template>
<div>
<q-btn
unelevated
class="q-mb-md"
color="black q-pr-sm"
color="black"
unelevated
:disabled="itemindex <= 0"
@click="toggleSheet(--itemindex)"
>
......@@ -16,9 +16,9 @@
</q-btn>
<q-btn
unelevated
class="q-mb-md"
color="black"
unelevated
:disabled="itemindex >= itemurls.length - 1"
@click="toggleSheet(++itemindex)"
>
......@@ -47,17 +47,13 @@ export default {
};
</script>
<style lang="scss" scoped>
button:first-of-type {
@media (min-width: 600px) {
margin-right: 8px;
}
}
.q-input {
width: 100%;
@media (min-width: 600px) {
margin-right: 8px;
width: 150px;
}
}
<style lang="sass" scoped>
button:first-of-type
@media (min-width: 600px)
margin-right: 8px
.q-input
width: 100%
@media (min-width: 600px)
margin-right: 8px
width: 150px
</style>
......@@ -22,7 +22,7 @@
<p>Copyright (c) 2020 Göttingen University - Göttingen State and University Library</p>
<p class="q-mb-none">
Version 1.1.1, licensed under GNU Affero General Public License v3.0
Version 1.2.0, licensed under GNU Affero General Public License v3.0
</p>
</q-card-section>
......
<template>
<div>
<q-btn
flat
dense
size="md"
class="q-mb-md"
v-for="(name, idx) in togglekeys"
:aria-selected="toggleAria(idx)"
:key="idx"
:title="toggleTitle(idx)"
@click="toggleIcon(idx); updateStatus(idx)"
>
<q-icon class="q-pr-xs" size="xs" :name="toggleIcon(idx)" />
{{ panelstates[name].name }}
</q-btn>
<q-btn-dropdown class="q-mb-md" color="black" label="Toggle panels ..." split>
<q-list>
<q-item v-for="(name, idx) in togglekeys" :key="idx"
clickable
:aria-selected="toggleAria(idx)"
:title="toggleTitle(idx)"
@click="toggleIcon(idx); updateStatus(idx)"
>
<q-icon class="q-pr-xs" size="xs" :name="toggleIcon(idx)" />
{{ panelstates[name].name | capitalize }}
</q-item>
</q-list>
</q-btn-dropdown>
<q-btn
flat
dense
size="md"
class="q-mb-md"
dense
flat
no-caps
title="Reset Tabs"
title="Reset panels to default view"
@click="resetPanelStatus"
>
<q-icon class="q-pr-xs" size="xs" :name="fasUndo" />
{{ 'Reset Tabs' | capitalize }}
{{ 'Reset Panels' | capitalize }}
</q-btn>
</div>
</template>
......@@ -45,8 +43,8 @@ export default {
},
data() {
return {
togglekeys: [],
states: {},
togglekeys: [],
};
},
filters: {
......@@ -61,8 +59,7 @@ export default {
},
resetPanelStatus() {
// NOTE: just loop over the initial states formerly configured to be shown (e.g. *true*)
// filtered result goes into *togglekeys*.
// leave the initial panel/s configured to be not shown (e.g. *false*) untouched!
// leave the initial panel/s configured to be hidden (e.g. *false*) untouched!
for (let idx = 0; idx < this.togglekeys.length; idx += 1) {
this.panelstates[this.togglekeys[idx]].show = true;
}
......@@ -130,13 +127,10 @@ export default {
};
</script>
<style lang="scss" scoped>
button {
@media (min-width: 600px) {
margin-right: 8px;
}
}
button:last-of-type {
margin-right: 0;
}
<style lang="sass" scoped>
button
@media (min-width: 600px)
margin-right: 8px
button:last-of-type
margin-right: 0
</style>
// global extra classes
.scroll-panel
position: relative
.sticky
background: #fff
display: flex
justify-content: flex-start
left: 0
position: sticky
top: 0
width: 100%
z-index: 99
.openseadragon-canvas
&:focus
outline: none
.content-panel
.q-tab-panel
> *
padding: 0 !important
// global extra classes
.scrollpanel {
position: relative;
.sticky {
background: #fff;
display: flex;
justify-content: flex-start;
left: 0;
position: sticky;
top: 0;
width: 100%;
z-index: 999999;
}
}
.openseadragon-canvas {
&:focus {
outline: none;
}
}
@mixin makeResponsiveHeight
$sizesSreen: ("400px": "28vh","450px": "36vh", "500px": "43vh", "550px": "50vh", "600px": "52vh", "630px": "55vh", "660px": "56vh", "700px": "60vh", "750px": "62vh", "800px": "65vh", "900px": "68vh", "980px": "71vh", "1200px": "76vh", "1300px": "78vh", "1800px": "84vh")
@each $minheight, $height in $sizesSreen
@media (min-height: #{$minheight})
height: #{$height}
@mixin makeResponsiveHeight {
$sizes: (
"400px": "15vh",
"450px": "39vh",
"500px": "55vh",
"600px": "59vh",
"660px": "63vh",
"700px": "64vh",
"750px": "67vh",
"800px": "69vh",
"900px": "72vh",
"980px": "75vh",
"1200px": "79vh",
"1300px": "80vh",
"1800px": "86vh"
);
@each $minheight, $height in $sizes {
@media (min-height: #{$minheight}) {
height: #{$height};
}
}
}
@import './responsive-heights.sass'
.view-tree
overflow-y: scroll
@include makeResponsiveHeight()
-ms-overflow-style: none
scrollbar-width: none
.q-tree__node-collapsible .q-tree__children
> .q-tree__node--parent
> .q-tree__node-header
background: white
left: 0
position: sticky
top: 0
z-index: 999
.q-tree__node-header-content.col.row.no-wrap.items-center
z-index: 99
.q-tree__children
cursor: pointer
.view-tree::-webkit-scrollbar
display: none
body
height: 100vh
overflow-y: hidden
@media(max-width: 1023px)
overflow-y: auto !important
@import './responsive-heights.scss';
.view-tree {
overflow-y: scroll;
@include makeResponsiveHeight();
-ms-overflow-style: none;
scrollbar-width: none;
.q-tree__node-collapsible .q-tree__children {
> .q-tree__node--parent {
> .q-tree__node-header {
background: white;
left: 0;
position: sticky;
top: 0;
z-index: 99999;
}
}
}
.q-tree__node-header-content.col.row.no-wrap.items-center {
z-index: 999;
}
.q-tree__children {
cursor: pointer;
}
}
.view-tree::-webkit-scrollbar {
display: none;
}
body {
height: 100vh;
overflow-y: hidden;
}
......@@ -2,7 +2,7 @@ const routes = [
{
path: '/',
name: 'MainView',
component: () => import('src/views/quasar-mainview.vue'),
component: () => import('src/views/mainview.vue'),
},
];
// Always leave this as last one
......
<template>
<q-page>
<q-splitter v-model="splitterone" :limits="[0, 100]">
<template v-show="config.panels.tabs.show && states.tabs" v-slot:before>
<div class="row panels-target">
<!-- 1st panel; defaults to Tree | Meta -->
<div class="col-12 col-sm-6 col-md-3" v-show="config.panels.tabs.show && states.tabs">
<Toolbar :heading="config.panels.tabs.name" />
<q-separator />
<q-card>
<q-tabs v-model="tab"
align="right"
active-bg-color="grey-4"
>
<q-tab name="contents" label="Contents" @click="updateTab()" />
<q-tab name="meta" label="Metadata" @click="updateTab()" />
<q-card flat>
<q-tabs v-model="tab" active-bg-color="grey-4" align="right">
<q-tab name="contents" label="Contents" />
<q-tab name="meta" label="Metadata" />
</q-tabs>
<q-separator />
<q-tab-panels v-model="tab" animated keep-alive>
<q-tab-panels v-model="tab" animated class="content-panel" keep-alive>
<q-tab-panel name="contents">
<Treeview v-if="tree.length && manifests.length"
:manifests="manifests"
:tree="tree"
>
</Treeview>
/>
</q-tab-panel>
<q-tab-panel name="meta">
<div class="scrollpanel">
<div class="scroll-panel">
<Metadata v-if="manifests.length"
:collection="collection"
:config="config"
:itemlabel="itemlabel"
:language="language"
:manifests="manifests"
:itemlabel="itemlabel"
>
</Metadata>
/>
</div>
</q-tab-panel>
</q-tab-panels>
</q-card>
</template>
<template v-slot:after>
<q-splitter v-model="splittertwo" :limits="[0, 100]">
<template v-show="config.panels.image.show && states.image && imageurl" v-slot:before>
<Toolbar :heading="config.panels.image.name" />
<q-separator />
<div class="q-pa-md q-gutter-sm overflow-hidden">
<div class="scrollpanel">
<OpenSeadragon
:key="imageurl"
:imageurl="imageurl"
>
</OpenSeadragon>
</div>
</div>
</template>
<template v-slot:after>
<q-splitter v-model="splitterthree" :limits="[0, 100]">
<template v-show="config.panels.text.show && states.text" v-slot:before>
<Toolbar :heading="config.panels.text.name" />
<q-separator />
<div class="q-pa-md q-gutter-sm">
<div class="scrollpanel">
<q-infinite-scroll>
<Content
:key="contenturl"
:contenturl="contenturl"
:fontsize="fontsize"
:manifests="manifests"
:request="request"
>
</Content>
</q-infinite-scroll>
</div>
</div>
</template>
<template v-show="config.panels.annotations.show && states.annotations" v-slot:after>
<Toolbar :heading="config.panels.annotations.name" />
<q-separator />
</template>
</q-splitter>
</template>
</q-splitter>
</template>
</q-splitter>
</div>
<!-- 2nd panel; defaults to Image -->
<div class="col-12 col-sm-6 col-md-3"
v-show="config.panels.image.show && states.image && imageurl"
>
<Toolbar :heading="config.panels.image.name" />
<div class="q-pa-md q-gutter-sm overflow-hidden">
<div class="scroll-panel">
<OpenSeadragon :key="imageurl" :imageurl="imageurl" />
</div>
</div>
</div>
<!-- 3rd panel; defaults to Text -->
<div class="col-12 col-sm-6 col-md-3" v-show="config.panels.text.show && states.text">
<Toolbar :heading="config.panels.text.name" />
<div class="q-pa-md q-gutter-sm">
<div class="scroll-panel">
<q-infinite-scroll>
<Content
:key="contenturl"
:contenturl="contenturl"
:fontsize="fontsize"
:manifests="manifests"
:request="request"
/>
</q-infinite-scroll>
</div>
</div>
</div>
<!-- 4th panel; defaults to Annotations -->
<div
class="col-12 col-sm-6 col-md-3"
v-show="config.panels.annotations.show && states.annotations"
>
<Toolbar :heading="config.panels.annotations.name" />
</div>
</div>
</q-page>
</template>
......@@ -132,64 +110,11 @@ export default {
},
data() {
return {
// status: tree, image, text, annotations
matrix: [
{ state: [1, 1, 1, 1], ratio: [25, 33, 50] },
{ state: [0, 0, 0, 0], ratio: [0, 0, 0] },
{ state: [1, 1, 1, 0], ratio: [33, 50, 100] },
{ state: [1, 1, 0, 1], ratio: [33, 50, 0] },
{ state: [1, 0, 1, 1], ratio: [33, 0, 50] },
{ state: [1, 0, 1, 0], ratio: [33, 0, 100] },
{ state: [1, 0, 0, 1], ratio: [50, 0, 0] },
{ state: [1, 1, 0, 0], ratio: [50, 100, 0] },
{ state: [1, 0, 0, 0], ratio: [100, 0, 0] },
{ state: [0, 1, 1, 1], ratio: [0, 33, 50] },
{ state: [0, 1, 1, 0], ratio: [0, 50, 100] },
{ state: [0, 1, 0, 1], ratio: [0, 50, 0] },
{ state: [0, 1, 0, 0], ratio: [0, 100, 0] },
{ state: [0, 0, 1, 1], ratio: [0, 0, 50] },
{ state: [0, 0, 1, 0], ratio: [0, 0, 100] },
{ state: [0, 0, 0, 1], ratio: [0, 0, 0] },
],
splitterone: 25,
splittertwo: 33,
splitterthree: 50,
states: {},
tab: '',
};
},