Commit 975e1e0b authored by schneider210's avatar schneider210
Browse files

Feature/#29 viewer release

parent 8b8f2dcd
......@@ -5,6 +5,23 @@ 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).
## [0.1.0] - 2020-07-24
### Fixed
- bug in navigation: itemindex was updated too late; lacking the corresponding sequenceindex. passed the latter to listener
## [0.0.24] - 2020-07-22
### Added
- license AGPL v3.0
- NOTICE
- license info in softwareinfo
### Changed
- README.md completed (added diagram of Viewer's components, changes config description, updated toc with doctoc)
- extended package.json
## [0.0.23] - 2020-07-20
### Added
......
This diff is collapsed.
Copyright (c) 2020 Göttingen University - Göttingen State and University Library
Licensed under GNU Affero General Public License v3.0
......@@ -16,24 +16,66 @@ Also the commit short hash can be used to see a demo.
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Viewer components](#viewer-components)
- [Latest version](#latest-version)
- [Integration](#integration)
- [Getting Started](#getting-started)
- [Prerequisites](#prerequisites)
- [Installing](#installing)
- [Get the Dependencies](#get-the-dependencies)
- [Start the App in Development Mode (Hot-Code Reloading, Error Reporting, etc.)](#start-the-app-in-development-mode-hot-code-reloading-error-reporting-etc)
- [Lint the files](#lint-the-files)
- [Build the App for Production](#build-the-app-for-production)
- [Customize the Configuration](#customize-the-configuration)
- [Installation](#installation)
- [Set up `nvm` and the recent stable version of `node.js`](#set-up-nvm-and-the-recent-stable-version-of-nodejs)
- [Set up `global` project requirements via `npm`](#set-up-global-project-requirements-via-npm)
- [Clone the repository](#clone-the-repository)
- [Get the dependencies](#get-the-dependencies)
- [Usage](#usage)
- [Start the Viewer in `development` mode (hot reloading, error reporting, etc.)](#start-the-viewer-in-development-mode-hot-reloading-error-reporting-etc)
- [`Lint` the files](#lint-the-files)
- [`Build` the app for production](#build-the-app-for-production)
- [Customize the Configuration](#customize-the-configuration)
- [Configure the Viewer](#configure-the-viewer)
- [The keys in detail](#the-keys-in-detail)
- [Dockerfile](#dockerfile)
- [Connecting the Viewer to a Backend](#connecting-the-viewer-to-a-backend)
- [Architecture](#architecture)
- [Contributing](#contributing)
- [Versioning](#versioning)
- [Authors](#authors)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Viewer components
![Viewer components](img/Viewer.png)
## Latest version
To embed the viewer for production, the latest compiled and minified version is
available at: https://gitlab.gwdg.de/subugoe/emo/Qviewer/-/jobs/artifacts/develop/download?job=build
## Integration
To include the viewer on a website add the following to your `index.html` file:
```html
<noscript>
<strong>We're sorry but TextViewer doesn't work properly without JavaScript enabled.
Please enable it to continue.
</strong>
</noscript>
<script id="emo-config" type="application/json">
{
...
}
</script>
<div id=q-app></div>
<script src=js/app.[CHECKSUM].js></script>
<script src=js/runtime.[CHECKSUM].js></script>
<script src=js/vendor.[CHECKSUM].js></script>
```
and replace `[CHECKSUM]` with the values from the release you are going to use.
## Getting Started
### Prerequisites
......@@ -44,16 +86,17 @@ To get the EMo Viewer up and running you should have the following software inst
- **npm**
- **nvm**
**Note**:
We recommend to make use of *nvm*, since there might be issues with npm regarding permissions.
We recommend to make use of `nvm`, since there might be issues with npm regarding permissions.
The main purpose of `nvm` is to have multiple node versions installed in regards to different projects which might demand some sort of backwards compatibility.
It enables you to just switch to the appropriate node version.
Besides it also keeps track of resolving permission issues,
since all your global installations go to your home directory (~/.nvm/) instead of being applied systemwide.
#### Set up *nvm* and the recent stable version of *node.js*
### Installation
#### Set up `nvm` and the recent stable version of `node.js`
```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
......@@ -63,7 +106,7 @@ since all your global installations go to your home directory (~/.nvm/) instead
After the nvm installation is done, please `restart` your shell session once. That's due to changes to your profile environment.
#### Set up *global* project requirements via npm
#### Set up `global` project requirements via `npm`
```bash
npm install -g @vue/cli @vue/cli-service-global @quasar/cli
......@@ -75,8 +118,6 @@ After the nvm installation is done, please `restart` your shell session once. Th
git clone git@gitlab.gwdg.de:subugoe/emo/viewer.git
```
### Installation
#### Get the dependencies
Head over to your project directory, where you just cloned the repository to as described above and get all the dependencies needed by simply typing:
......@@ -86,37 +127,39 @@ Head over to your project directory, where you just cloned the repository to as
npm install
```
That's it. You now should be able to run the Viewer.
That's it. You should now be able to run the Viewer.
## Usage
### Start the App in Development Mode (Hot-Code Reloading, Error Reporting, etc.)
#### Start a local instance of a dev server
### Start the Viewer in `development` mode (hot reloading, error reporting, etc.)
```bash
npm run dev
```
(usually located at: `localhost:8080`)
#### Lint the files
#### `Lint` the files
```bash
npm run lint
```
#### Build the App for Production
#### `Build` the app for production
```bash
npm run build
```
### Customize the Configuration
**Note**: The complete build is located at /dist/spa/.
## Customize the Configuration
See [Configuring quasar.conf.js](https://quasar.dev/quasar-cli/quasar-conf-js).
## Configure the Viewer
As a rule of thumb, every key with a boolean value (e.g. *true* or *false*) defaults to `true` and denotes to show the appropriate component. If you intend to hide a component, just toggle it's corresponding key-value to `false`.
Locate the `index.template.html` file inside the root of your project dir and find the script section:
**Note**:
......@@ -124,12 +167,12 @@ Locate the `index.template.html` file inside the root of your project dir and fi
It's a json object. So if you are going to make any changes and you have to quote these, use double quotes but single ones.
```html
<script id="emo-config" type="application/json">
<script id="emo-config" type="application/json">
{
"entrypoint": "https://{server}{/prefix}/{collection}/collection.json",
"headers": {
"all": true,
"info": false,
"info": true,
"navigation": true,
"toggle": true
},
......@@ -138,10 +181,22 @@ It's a json object. So if you are going to make any changes and you have to quot
"manifest": "Manuscript"
},
"panels": {
"image": true,
"text": false,
"metadata": true,
"treeview": true
"tree": {
"name": "Contents",
"show": true
},
"text": {
"name": "Text",
"show": true
},
"image": {
"name": "Image",
"show": true
},
"metadata": {
"name": "Metadata",
"show": true
}
},
"standalone": true
}
......@@ -152,44 +207,65 @@ It's a json object. So if you are going to make any changes and you have to quot
- **entrypoint**
to link the viewer to a backend, the entrypoint should point to the collection you want to be displayed. (Further details below: [Connecting the Viewer to a Backend](#connecting-the-viewer-to-a-backend))
- **headers**
- **all**
to link the viewer to a backend, the entrypoint should point to the collection you want to be displayed.<br />
(Further details below: [Connecting the Viewer to a Backend](#connecting-the-viewer-to-a-backend))
set this value to `false` if you want to completely switch off all the headerbars at once. This value takes precedence. If it's set to *false*, the other settings for the individual bars are not taken into account.
*(A use case might be to embed the Viewer into an existing website and you simply need more screen space)*
- **info**
**Note**: You have to provide at least a valid entrypoint (see above). Otherwise the Viewer won't show anything at all!
set this value to `false` if you want to switch off the Infobar (breadcrumbs)
- **navigation**
- **headers**
set this value to `false` if you want to switch off the NavBar
- **toggle**
- **all**<br />
set this value to `false` if you want to completely switch off all the headerbars at once.<br />
This value takes precedence over the other *header-keys*.<br />
If it's set to *false*, the other settings for the individual bars are not taken into account.<br />
*(A use case might be to embed the Viewer into an existing website and you simply need more screen space)*
set this value to `false` if you want to switch off the ToggleBar.
- **info**<br />
set this value to `false` if you want to switch off the Infobar (a.k.a. breadcrumbs)
- **navigation**<br />
set this value to `false` if you want to switch off the NavBar
- **toggle**<br />
set this value to `false` if you want to switch off the ToggleBar.
**Note**: if you turn this one off, you won't be able to toggle the panels anymore.
**Note**: if you turn this one off, you won't be able to toggle the panels anymore.
All header values default to **true**
All header values default to `true`
- **labels**
- **item**: the label of the item respectively
Assuming your collection consists of letters, you'd maybe want to name it "letter" or just "sheet" for instance.
This change affects the captions of the navbuttons located in the headerbar and the metadata section.
- **item**:<br />
the label of the item respectively
Assuming your collection consists of letters, you'd maybe want to name it "letter" or just "sheet" for instance.<br />
This change affects the captions of the navbuttons located in the headerbar and the metadata section.<br />
Defaults to **Sheet**
Defaults to `Sheet`
- **manifest**: same as for `item` but related to the manifest title
- **manifest**:<br />
same as for `item` but related to the manifest title<br />
Defaults to **Manuscript**
Defaults to `Manuscript`
- **panels**
It's keys correspond to the panelnames, e.g. "treeview", "text", "image", "metadata".
Set either value to **false** if you don't want the Viewer to show the appropriate panel/s.
It's keys correspond to the panelnames, e.g. "contents", "text", "image", "metadata".
Each key consists of further sub-keys: `name` and `show`.
Change either name-key according to your liking and set either show-key to **false** if you don't want the Viewer to show the appropriate panel/s.
Example given:
```json
{
"panels": {
"tree": {
"name": "ToC",
"show": false
}
}
}
```
Defaults to **true** for every panel
Defaults to **true** for every `show`-key
- **standalone**
......
{
"name": "viewer",
"version": "0.0.22",
"version": "0.0.24",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......@@ -2813,9 +2813,9 @@
}
},
"@quasar/extras": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.8.2.tgz",
"integrity": "sha512-y3A4OO4DGDxuFyh/X4k5fS17TTxhpPauZv8Qr/0bso+RTk5f+3X4lLAcP7aaiqcBLOV8HsUKpGzNArMleClYgg=="
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.9.0.tgz",
"integrity": "sha512-+kWpgSMxvOuGLLQPT0PJL+SL7NPqhima4RfbJLRYbA8A3RAvFm8Ay5wE6CQKTn1sDHLBx/y/Zp+wvYlt1bfFLw=="
},
"@quasar/fastclick": {
"version": "1.1.4",
......@@ -12121,9 +12121,9 @@
"dev": true
},
"quasar": {
"version": "1.12.11",
"resolved": "https://registry.npmjs.org/quasar/-/quasar-1.12.11.tgz",
"integrity": "sha512-FeB/9Y1r3Uq0yVu8puOZ+8PrzOAKAvOpZInbJ8S6Qy3JnmUvZass/doDj0wtnLZ8uRjTRjwSw4uopSZMtVk+hQ=="
"version": "1.12.13",
"resolved": "https://registry.npmjs.org/quasar/-/quasar-1.12.13.tgz",
"integrity": "sha512-e5cU3cxwZEc+MIJ6/a5IyV5HJ4B1WJscpEqDi+1BpIfVu4/9/WS9a0dnki5jVEvcsbuV4G133XCHQ09fdXoL1A=="
},
"query-string": {
"version": "4.3.4",
......
{
"name": "viewer",
"version": "0.0.22",
"version": "0.0.24",
"description": "Viewer for the modular framework to present digital editions",
"productName": "EMo Viewer",
"keywords": [
"viewer",
"emo",
"digital editions",
"vue",
"quasar",
"openseadragon",
"sub"
],
"cordovaId": "de.uni-goettingen.sub.emo",
"capacitorId": "",
"author": [
"Mathias Göbel <goebel@sub.uni-goettingen.de>",
"Frank Schneider <frank.schneider@sub.uni-goettingen.de>"
],
"bugs": {
"email": "gitlab+subugoe-emo-qviewer-10921-issue-@gwdg.de"
},
"license": {
"license": "AGPL-3.0-or-later"
},
"author": "Frank Schneider <frank.schneider@sub.uni-goettingen.de>",
"contributors": [
"Nils Windisch",
"Manikanth Dindigala"
"Manikanth Dindigala <dindigala@sub.uni-goettingen.de>",
"Mathias Göbel <goebel@sub.uni-goettingen.de>",
"Michelle Weidling <weidling@sub.uni-goettingen.de>",
"Nils Windisch <windisch@sub.uni-goettingen.de>"
],
"private": true,
"scripts": {
"build": "quasar build",
"dev": "quasar dev --modern",
"lint": "eslint --ext .js,.vue src"
"repository": {
"type": "git",
"url": "https://gitlab.gwdg.de/subugoe/emo/Qviewer.git"
},
"private": true,
"dependencies": {
"@quasar/extras": "^1.8.2",
"@quasar/extras": "^1.9.0",
"openseadragon": "^2.4.2",
"quasar": "^1.12.11"
"quasar": "^1.12.13"
},
"devDependencies": {
"@quasar/app": "^1.9.6",
......@@ -37,14 +50,19 @@
"sass": "^1.26.10",
"sass-loader": "8.0.2"
},
"browserslist": [
"last 1 version, not dead, ie >= 11"
],
"engines": {
"node": ">= 10.18.1",
"npm": ">= 6.13.4"
},
"browserslist": [
"last 1 version, not dead, ie >= 11"
],
"resolutions": {
"@babel/parser": "7.7.5"
},
"scripts": {
"build": "quasar build --modern",
"dev": "quasar dev --modern",
"lint": "eslint --ext .js,.vue src"
}
}
......@@ -14,8 +14,8 @@ module.exports = function (ctx) {
css: [
// 'app.scss'
'../statics/support.css',
'/quasar.treeview.scss',
'/quasar.global.scss'
'/treeview.scss',
'/global.scss'
],
// https://github.com/quasarframework/quasar/tree/dev/extras
......
......@@ -31,8 +31,8 @@
</template>
<script>
import Header from '@/components/quasar-header.vue';
import Footer from '@/components/quasar-footer.vue';
import Header from '@/components/header.vue';
import Footer from '@/components/footer.vue';
export default {
name: 'Viewer',
......@@ -59,12 +59,30 @@ export default {
};
},
methods: {
/**
* get resources using JavaScript's native fetch api
* caller: *getCollection()*, *getItemData()*, *getManifest()*
* *@/components/content.vue::getSupport()*, *@/components/content.vue::created-hook*
*
* @param string url
* @param string responsetype
*
* @return promise data
*/
async request(url, responsetype = 'json') {
const response = await fetch(url);
const data = await (responsetype === 'text' ? response.text() : response.json());
return data;
},
/**
* get collection data according to 'entrypoint'
* (number of requests equal the number of manifests contained within a collection)
* initialize the tree's root node
* caller: *init()*
*
* @param string url
*/
getCollection(url) {
this.isCollection = true;
......@@ -90,9 +108,19 @@ export default {
}
});
},
/**
* get config object (JSON) from index.html
* caller: *created-hook*
*/
getConfig() {
this.config = JSON.parse(document.getElementById('emo-config').text);
},
/**
* fetch all data provided on 'item level'
* caller: *mounted-hook*, *getManifest()*
*
* @param string url
*/
getItemData(url) {
this.request(url)
.then((data) => {
......@@ -105,6 +133,13 @@ export default {
this.itemlanguage = data['x-langString'].split(',')[0];
});
},
/**
* caller: *getItemUrls()*
*
* @param string nodelabel
*
* @return number idx
*/
getItemIndex(nodelabel) {
let idx = 0;
this.itemurls.forEach((item, index) => {
......@@ -114,6 +149,15 @@ export default {
});
return idx;
},
/**
* get all itemurls hosted by each manifest's sequence to populate the aprropriate tree node
* caller: *getManifest()*
*
* @param array sequence
* @param string label
*
* @return array urls
*/
getItemUrls(sequence, label) {
const urls = [];
......@@ -128,7 +172,9 @@ export default {
if (this.itemurl === node.label) {
return;
}
this.$root.$emit('update-item', node.label);
// node.label === itemurl
// @param label === manifest label; passed by getManifest()
this.$root.$emit('update-item', node.label, this.getSequenceIndex(label));
this.$root.$emit('update-item-index', this.getItemIndex(node.label));
this.$root.$emit('update-sequence-index', this.getSequenceIndex(label));
},
......@@ -137,12 +183,26 @@ export default {
});
return urls;
},
/**
* get the collection label, if provided; otherwise get the manifest label
* caller: *getCollection()*, *getManifest()*
*
* @param object data
*
* @return string 'label'
*/
getLabel(data) {
if (Object.keys(this.collection).length) {
return data.title && data.title[0].title ? data.title[0].title : data.label;
}
return data.label ? data.label : 'Manifest <small>(No label available)</small>';
},
/**
* get all the data provided on 'manifest level'
* caller: *init()*, *getCollection()*
*
* @param string url
*/
getManifest(url) {
this.request(url)
.then((data) => {
......@@ -182,9 +242,24 @@ export default {
}
});
},
/**
* extract the 'label part' of the itemurl
* caller: *getItemUrls()*
*
* @param string itemurl
*
* @return string 'label part'
*/
getPageLabel(itemurl) {
return itemurl.replace(/.*-(.*)\/latest.*$/, '$1');
},
/**
* caller: *getItemUrls()*
*
* @param string label
*
* @return number index
*/
getSequenceIndex(label) {
let index = 0;
this.manifests.forEach((manifest, idx) => {
......@@ -194,6 +269,12 @@ export default {
});
return index;
},
/**
* decide whether to start with a collection or a single manifest
* caller: *created-hook*
*
* @return function getCollection() | getManifest()
*/
init() {
return this.config.entrypoint.match(/collection.json\s?$/)
? this.getCollection(this.config.entrypoint)
......@@ -207,10 +288,22 @@ export default {
this.itemurls.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
},
mounted() {
/**
* listen to fontsize change (user interaction). emitted in @/components/content.vue
* in- or rather decrease fontsize of the text by 1px
* default fontsize: 14px
*
* @param number fontsize
*/
this.$root.$on('update-fontsize', (fontsize) => {
this.fontsize = fontsize;
});
/**
* listen to item change (user interaction).
* emitted in: *getItemurls*; handler for tree nodes. fired on user interaction
*
* @param string url
*/
this.$root.$on('update-item', (url) => {
this.itemurl = url;
this.$router.push({ query: { itemurl: url } });
......
......@@ -8,12 +8,12 @@
flat
round
size="md"
title="Increase Textsize"
@click="increase()"
>
<q-icon
size="sm"
:name="fasSearchPlus"