Commits (33)
......@@ -2,6 +2,59 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [1.18.0](https://gitlab.gwdg.de/subugoe/emo/tido/compare/v1.17.0...v1.18.0) (2021-08-31)
### Features
* displaying error message for images when there is no vpn ([39e7461](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/39e7461d19b973d8c7101fd91739705ab9c82c97))
* implement config option for the language switch ([91add1c](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/91add1c0fa50b9319fd277b84ee493313b19c497))
* make the theme switch toggleable ([72326cf](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/72326cf250e8823a9b0c9346c2d7c8739a9e5253))
* when changing sheet the selected tab remains open ([b263c29](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/b263c29c7e676e3c9dad03058e7af2e13e488ef2))
### Bug Fixes
* displaying tido with single manifest ([b92a445](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/b92a445a602358ba022bc47db5e053d9d3885930))
* hover over tooltip for outer spans and it's selected text ([b455cf4](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/b455cf4386a420aae69ef77d26a923ff89eb8662))
* revert the conf option in regards to the review comment ([2d14d59](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/2d14d592c50fb679a2a3a5b060fe4413d7cb0cf2)), closes [/gitlab.gwdg.de/subugoe/emo/tido/-/merge_requests/217#note_375950](https://gitlab.gwdg.de/subugoe/emo/tido/-/issues/note_375950)
### Styling
* just syntax fixes according to linter ([f727765](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/f7277652e081dec13f3e401f73972d7019441c48))
### Chore
* delete the footer component (according to review) ([c12f581](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/c12f5816ca996e0ebf9accb52dc9f34fa670b0d6)), closes [/gitlab.gwdg.de/subugoe/emo/tido/-/merge_requests/215#note_375185](https://gitlab.gwdg.de/subugoe/emo/tido/-/issues/note_375185)
* merge latest changes from develop ([8b0c87d](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/8b0c87dd0e29e279c5bf73a7182d929cc3696348))
* set default value to `true` ([56338a5](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/56338a55953721b223d7d01af78a36cebc10469e))
### Docs
* modified title according to stake holders requirement ([73edc36](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/73edc36a05ae39a9b449b45d782118ed6712b6b5))
### Refactoring
* adding a comment to function ([5c74208](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/5c74208e865ecac6ad99357b45e992c58260c555))
* delete legacy code (standalone) as agreed upon in today's refinement ([26071d5](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/26071d5c941ffe5c04e373d43737e83edbfd1889))
* switch off the color theme toggle. it's already configurable via index file ([fbcc6c8](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/fbcc6c8171a6f8d31e9749933c3ea8785eb743dd))
* updated color check method and refactored display of list item ([00d44e4](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/00d44e4573ec4c45dfa6b6decde9e8d7a0285376))
### Continuos Integration
* remove entry point ([3802c0e](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/3802c0e3abddb846705f1259b99c69af57c285a0))
* remove entry point ([5ce146f](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/5ce146fc35ca27e15bd9d7448a0d45d229de4884))
* remove entry point ([24406ae](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/24406ae1262398a09408ac52bc36de3ef109a50a))
* remove entry point ([0eb94db](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/0eb94dba0d98fb627f059c9552a2004cfbad8fce))
* remove entry point ([bb23eee](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/bb23eeea8f670f4345fafc0bb338c093af0d3b66))
* remove entry point ([8dbca9c](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/8dbca9cbf46477e2e95b91c1ab2ddc4cd5c6714c))
* remove entry point ([de6bd9a](https://gitlab.gwdg.de/subugoe/emo/tido/-/commit/de6bd9a5a126acbf68f36ed495c99a48b65a9b05))
## [1.17.0](https://gitlab.gwdg.de/subugoe/emo/tido/compare/v1.16.1...v1.17.0) (2021-08-20)
......
......@@ -200,100 +200,101 @@ As a rule of thumb, each key with a boolean value (e.g. *true* or *false*) defau
<script id="tido-config" type="application/json">
{
"entrypoint": "https://subugoe.pages.gwdg.de/emo/backend/sampledata/collection.json",
"annotations": {
"types": [
"annotations": {
"show": true,
"types": [
{
"contenttype": "Person",
"icon": "fasUser",
"label": "Names"
},
{
"contenttype": "Place",
"icon": "fasMapMarkerAlt",
"label": "Places"
},
{
"contenttype": "Editorial Comment",
"icon": "fasComment",
"label": "Comments"
},
{
"contenttype": "Motif",
"icon": "fasHighlighter",
"label": "Motifs"
}
],
"tabs":{
"Editorial": ["Person", "Place", "Editorial Comment"],
"Motif": ["Motif"]
}
},
"breadcrumbNavigation": {
"show": true,
"title_homepage_key": "title_homepage",
"title_viewer_key": "title_viewer",
"website": "https://ahikar.sub.uni-goettingen.de/website/"
},
"colors": {
"primary": "",
"secondary": "",
"accent": ""
},
"header_section": {
"show": true,
"navigation": true,
"panelheadings": true,
"titles": true,
"toggle": true
},
"labels": {
"item": "Sheet",
"manifest": "Manuscript"
},
"lang": "de-de",
"language-switch": true,
"meta": {
"collection": {
"all": true
},
"manifest": {
"all": true
},
"item": {
"all": true
}
},
"notificationColors": {
"info":"blue-9",
"warning":"red-9"
},
"panels": [
{
"contenttype": "Person",
"icon": "fasUser",
"label": "Names"
"connector": [1, 2],
"panel_label": "contentsMetadata",
"show": true,
"toggle": true
},
{
"contenttype": "Place",
"icon": "fasMapMarkerAlt",
"label": "Places"
"connector": [3],
"panel_label": "Image",
"show": true,
"toggle": true
},
{
"contenttype": "Editorial Comment",
"icon": "fasComment",
"label": "Comments"
"connector": [4],
"panel_label": "Text",
"show": true,
"toggle": true
},
{
"contenttype": "Motif",
"icon": "fasHighlighter",
"label": "Motifs"
"connector": [5],
"panel_label": "Annotations",
"show": true,
"toggle": true
}
],
"tabs": {
"Editorial": ["Person", "Place", "Editorial Comment"],
"Motif": ["Motif"]
}
},
"colors": {
"primary": "",
"secondary": "",
"accent": ""
},
"header_section": {
"show": true,
"navigation": true,
"panelheadings": true,
"titles": true,
"toggle": true
},
"labels": {
"item": "Sheet",
"manifest": "Manuscript"
},
"meta": {
"collection": {
"all": true
},
"manifest": {
"all": true
},
"item": {
"all": true
}
},
"notificationColors": {
"info":"blue-9",
"warning":"red-9"
},
"panels": [
{
"connector": [1, 2],
"panel_label": "Contents & Meta",
"show": true,
"toggle": true
},
{
"connector": [3],
"panel_label": "Image",
"show": true,
"toggle": true
},
{
"connector": [4],
"panel_label": "Text",
"show": true,
"toggle": true
},
{
"connector": [5],
"panel_label": "Annotations",
"show": true,
"toggle": true
}
],
"rtl": false,
"lang": "en-us",
"standalone": true,
"breadcrumbNavigation": {
"show": true,
"title_homepage_key": "title_homepage",
"title_viewer_key": "title_viewer",
"website": "https://ahikar.sub.uni-goettingen.de"
}
"rtl": false
} </script>
```
......@@ -347,6 +348,34 @@ As a rule of thumb, each key with a boolean value (e.g. *true* or *false*) defau
**Note**: The strings contained within the group label keys (e.g. *Person*, *Place*, ...) have to match its API-counterpart explicitely. Please refer to the note above (content-type).
- **breadcrumbNavigation**
- **show**
defines if a project header should be shown or not.
Defaults to `false`
- **title_homepage_key**
defines the string shown as first item in the breadcrumb. Shows a "Home Icon"
Note: To change this title please navigate to "tido/src/i18n/en or tido/src/i18n/de" and find "title_homepage".
Has to be set!
- **title_viewer_key**
defines the string shown as last item in the breadcrumb. Shows a "Document Icon"
Note: To change this title please navigate to "tido/src/i18n/en or tido/src/i18n/de" and find "title_viewer".
Has to be set!
- **website**
Navigates to the Home Page page on website.
- **colors**
set the colors used in the frontend.
......@@ -403,26 +432,6 @@ As a rule of thumb, each key with a boolean value (e.g. *true* or *false*) defau
Defaults to `Manuscript`
- **notificationColors**
sets the colors used in frontend to apply for icons in notification messages.
`info` and `warning` are set to `blue-9` `red-9` respectively which can be changed according to the project requirements.
There is a re-usable component called notification.vue (src/components/notification.vue) which receives the type of notification (ex: `info` or `warning`). Based on the type we send, this component searches for it and its respective icon which in turn gets displayed before the title message of Notifications.
If we do not send any type, than there is no `icon` set to the notification message.
**Note**: Can add additional types ex: `success`, `error`, `positive`, `negative`. Based on these we need to add them at the component level as well and their icons respectively.
- **rtl (right to left)**
refers to the direction the text inside the text panel will be displayed.
set the value to `true` if you want text to be displayed from right to left; e.g. Arabic.
Defaults to `false`
- **lang (language)**
refers to the default language of the application.
......@@ -431,39 +440,31 @@ As a rule of thumb, each key with a boolean value (e.g. *true* or *false*) defau
Defaults to `en-us`
- **standalone**
- **language-switch**
denotes if the Viewer will be used as a single page application or if it will be embedded into an existing page. If you want to use it in the latter case, please toggle the value to `false`. That way the language toggle in the footer section will not show up.
set this value to `false` if you don't want to switch the language. this setting hides the appropriate toggle.
Defaults to `true`
- **breadcrumbNavigation**
- **show**
defines if a project header should be shown or not.
Defaults to `false`
- **title_homepage_key**
- **notificationColors**
defines the string shown as first item in the breadcrumb. Shows a "Home Icon"
sets the colors used in frontend to apply for icons in notification messages.
Note: To change this title please navigate to "tido/src/i18n/en or tido/src/i18n/de" and find "title_homepage".
`info` and `warning` are set to `blue-9` `red-9` respectively which can be changed according to the project requirements.
Has to be set!
There is a re-usable component called notification.vue (src/components/notification.vue) which receives the type of notification (ex: `info` or `warning`). Based on the type we send, this component searches for it and its respective icon which in turn gets displayed before the title message of Notifications.
- **title_viewer_key**
If we do not send any type, than there is no `icon` set to the notification message.
defines the string shown as last item in the breadcrumb. Shows a "Document Icon"
**Note**: Can add additional types ex: `success`, `error`, `positive`, `negative`. Based on these we need to add them at the component level as well and their icons respectively.
Note: To change this title please navigate to "tido/src/i18n/en or tido/src/i18n/de" and find "title_viewer".
- **rtl (right to left)**
Has to be set!
refers to the direction the text inside the text panel will be displayed.
- **website**
set the value to `true` if you want text to be displayed from right to left; e.g. Arabic.
Navigates to the Home Page page on website.
Defaults to `false`
### Configure the Panels
......
{
"name": "@subugoe/tido",
"version": "1.17.0",
"version": "1.18.0",
"lockfileVersion": 2,
"requires": true,
"dependencies": {
......
{
"name": "@subugoe/tido",
"version": "1.17.0",
"version": "1.18.0",
"description": "Text vIever for Digital Objects",
"productName": "TIDO",
"keywords": [
......
// Configuration for your app
// https://quasar.dev/quasar-cli/quasar-conf-js
const path = require('path')
const path = require('path');
module.exports = function (ctx) {
// eslint-disable-next-line func-names
module.exports = function () {
return {
// app boot file (/src/boot)
// --> boot files are part of "main.js"
......@@ -14,7 +15,7 @@ module.exports = function (ctx) {
// https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css
css: [
'style.scss'
'style.scss',
],
// https://github.com/quasarframework/quasar/tree/dev/extras
......@@ -43,11 +44,11 @@ module.exports = function (ctx) {
brand: {
primary: '#212121',
secondary: '#eee',
accent: '#1a3771'
accent: '#1a3771',
},
notify: {
color: 'gray'
}
color: 'gray',
},
},
iconSet: 'fontawesome-v5',
......@@ -56,12 +57,12 @@ module.exports = function (ctx) {
// Quasar plugins
plugins: [
'Notify'
]
'Notify',
],
},
htmlVariables: {
title: 'TIDO'
title: 'TIDO',
},
// https://quasar.dev/quasar-cli/cli-documentation/supporting-ie
......@@ -85,34 +86,31 @@ module.exports = function (ctx) {
extractCSS: false,
// https://quasar.dev/quasar-cli/cli-documentation/handling-webpack
extendWebpack (cfg) {
extendWebpack(cfg) {
cfg.output = {
filename: '[name].js',
},
};
cfg.resolve.alias = {
...cfg.resolve.alias, // This adds the existing alias
'@': path.resolve(__dirname, './src/'),
},
cfg.module.rules.push(
{
enforce: 'pre',
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
formatter: require('eslint').CLIEngine.getFormatter('stylish')
},
test: /\.(js|vue)$/
}
)
}
};
cfg.module.rules.push({
enforce: 'pre',
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
formatter: require('eslint').CLIEngine.getFormatter('stylish'),
},
test: /\.(js|vue)$/,
});
},
},
// Full list of options: https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-devServer
devServer: {
https: false,
port: 8080,
open: false // opens browser window automatically
open: false, // opens browser window automatically
},
vendor: {
......@@ -125,7 +123,7 @@ module.exports = function (ctx) {
// https://quasar.dev/quasar-cli/developing-ssr/configuring-ssr
ssr: {
pwa: false
pwa: false,
},
// https://quasar.dev/quasar-cli/developing-pwa/configuring-pwa
......@@ -144,30 +142,30 @@ module.exports = function (ctx) {
{
src: 'icons/icon-128x128.png',
sizes: '128x128',
type: 'image/png'
type: 'image/png',
},
{
src: 'icons/icon-192x192.png',
sizes: '192x192',
type: 'image/png'
type: 'image/png',
},
{
src: 'icons/icon-256x256.png',
sizes: '256x256',
type: 'image/png'
type: 'image/png',
},
{
src: 'icons/icon-384x384.png',
sizes: '384x384',
type: 'image/png'
type: 'image/png',
},
{
src: 'icons/icon-512x512.png',
sizes: '512x512',
type: 'image/png'
}
]
}
type: 'image/png',
},
],
},
},
// Full list of options: https://quasar.dev/quasar-cli/developing-cordova-apps/configuring-cordova
......@@ -177,7 +175,7 @@ module.exports = function (ctx) {
// Full list of options: https://quasar.dev/quasar-cli/developing-capacitor-apps/configuring-capacitor
capacitor: {
hideSplashscreen: true
hideSplashscreen: true,
},
// Full list of options: https://quasar.dev/quasar-cli/developing-electron-apps/configuring-electron
......@@ -200,16 +198,16 @@ module.exports = function (ctx) {
builder: {
// https://www.electron.build/configuration/configuration
appId: 'q-app'
appId: 'q-app',
},
// More info: https://quasar.dev/quasar-cli/developing-electron-apps/node-integration
nodeIntegration: true,
extendWebpack (cfg) {
extendWebpack() {
// do something with Electron main process Webpack cfg
// chainWebpack also available besides this extendWebpack
}
}
}
}
},
},
};
};
......@@ -15,7 +15,6 @@
:manifests="manifests"
:panels="panels"
:projectcolors="config.colors"
:standalone="config.standalone"
/>
<q-page-container class="root">
......@@ -23,14 +22,17 @@
:annotations="annotations"
:collection="collection"
:config="config"
:contentindex="contentindex"
:contenttypes="contentTypes"
:contenturls="contentUrls"
:errormessage="errormessage"
:fontsize="fontsize"
:imageurl="imageurl"
:isloading="isLoading"
:item="item"
:labels="config.labels"
:manifests="manifests"
:oncontentindexchange="oncontentindexchange"
:panels="panels"
:request="request"
:tree="tree"
......@@ -61,8 +63,10 @@ export default {
collection: {},
collectiontitle: '',
config: {},
contentindex: 0,
contentTypes: [],
contentUrls: [],
errormessage: false,
fontsize: 16,
imageurl: '',
isCollection: false,
......@@ -253,12 +257,33 @@ export default {
.then((data) => {
this.item = data;
const previousManifest = (this.contentUrls[0] || '').split('/').pop().split('-')[0];
this.contentUrls = this.getContentUrls(data.content);
const currentManifest = this.contentUrls[0].split('/').pop().split('-')[0];
if (previousManifest !== currentManifest) {
this.$root.$emit('manifest-changed');
}
this.imageurl = data.image.id || '';
if (data.annotationCollection) {
this.getAnnotations(data.annotationCollection);
}
fetch(this.imageurl).then((response) => {
if (response.status === 200 || response.status === 201) {
this.errormessage = false;
} else {
// for vpn error.
this.errormessage = true;
}
}).catch(() => {
// for CORS error.
this.errormessage = true;
});
});
},
/**
......@@ -374,6 +399,11 @@ export default {
},
selectable: false,
});
if (this.manifests?.[0]?.sequence?.[0]?.id && !this.$route.query.itemurl) {
this.loaded = false;
this.$router.push({ query: { ...this.$route.query, itemurl: this.manifests?.[0]?.sequence?.[0]?.id } });
}
},
/**
* caller: *getItemUrls()*
......@@ -403,6 +433,10 @@ export default {
: this.getManifest(this.config.entrypoint);
},
oncontentindexchange(index) {
this.contentindex = index;
},
onItemUrlChange() {
if (this.loaded) {
return;
......
......@@ -11,6 +11,7 @@
<q-tab
v-for="annotationTab in annotationTabs"
:key="annotationTab.key"
:class="{'disabled-tab': annotationTab.key === currentTab}"
:label="$t(annotationTab.collectionTitle)"
:name="annotationTab.key"
@click="activeTab(annotationTab.key, annotationTab.type)"
......@@ -111,8 +112,7 @@ export default {
key,
collectionTitle: key,
type,
}))
.filter((el) => this.annotations.find((x) => el.type.includes(x.body['x-content-type'])));
}));
},
annotationTabConfig() {
return this.config?.annotations?.tabs || {};
......@@ -196,10 +196,16 @@ export default {
},
},
mounted() {
this.currentTab = this.annotationTabs?.[0].key;
this.$root.$on('update-annotations', this.onContentUpdate);
this.$root.$on('update-annotation-loading', (isProcessing) => {
this.isProcessing = !!isProcessing;
});
this.$root.$on('manifest-changed', () => {
this.currentTab = this.annotationTabs?.[0].key;
});
},
methods: {
activeTab(key) {
......@@ -356,7 +362,6 @@ export default {
onContentUpdate(ids) {
try {
this.currentTab = this.annotationTabs[0].key;
this.contentIds = ids;
this.highlightActiveContent(this.filteredAnnotations);
......@@ -381,23 +386,38 @@ export default {
},
onMouseHover(el, annotationClasses) {
const queue = [];
const innerQueue = [];
// this logic checks the child spans and classes.
queue.push(el);
// this logic checks the child spans and their classes.
innerQueue.push(el);
let matched = false;
while (queue.length) {
const popped = queue.pop();
while (innerQueue.length) {
const popped = innerQueue.pop();
if (parseInt(popped.getAttribute('data-annotation-level'), 10) > 0) {
matched = true;
} else {
[...popped.children].forEach((child) => {
queue.push(child);
innerQueue.push(child);
});
}
}
// this logic checks the outer spans and their classes.
if (!matched) {
const outerQueue = [];
outerQueue.push(el);
while (outerQueue.length) {
const popped = outerQueue.pop();
if (parseInt(popped.getAttribute('data-annotation-level'), 10) > 0) {
matched = true;
} else if (popped.parentElement.getAttribute('data-annotation')) {
outerQueue.push(popped.parentElement);
}
}
}
if (!el || !matched) {
return;
}
......@@ -576,4 +596,8 @@ export default {
flex: 1;
flex-direction: column;
}
.disabled-tab {
pointer-events: none;
}
</style>
......@@ -16,26 +16,16 @@
>
<q-list>
<q-item
v-for="theme in themes"
:key="theme.value"
v-close-popup
clickable
@click="changeColorsTo('default')"
:class="{'theme': selectedTheme === theme.value}"
@click="changeColorsTo(theme.value)"
>
<q-item-section>{{ $t('default') }}</q-item-section>
</q-item>
<q-item
v-if="projectcolors.primary && projectcolors.secondary && projectcolors.accent"
v-close-popup
clickable
@click="changeColorsTo('emo')"
>
<q-item-section>EMo</q-item-section>
</q-item>
<q-item
v-close-popup
clickable
@click="changeColorsTo('unicorn')"
>
<q-item-section>Unicorn</q-item-section>
<q-item-section>
{{ theme.label }}
</q-item-section>
</q-item>
</q-list>
</q-menu>
......@@ -50,36 +40,42 @@ import { fasPalette } from '@quasar/extras/fontawesome-v5';
export default {
name: 'Color',
props: {
config: {
type: Object,
default: () => {},
},
projectcolors: {
type: Object,
required: true,
},
},
data: () => ({
themes: [
{ label: 'Default', value: 'default' },
{ label: 'TIDO', value: 'tido' },
],
selectedTheme: '',
}),
mounted() {
if (this.config.themes) {
this.selectedTheme = 'tido';
}
},
created() {
this.fasPalette = fasPalette;
},
methods: {
changeColorsTo(color) {
this.selectedTheme = color;
if (color === 'default') {
if (this.projectcolors.primary && this.projectcolors.secondary && this.projectcolors.accent) {
colors.setBrand('primary', this.projectcolors.primary);
colors.setBrand('secondary', this.projectcolors.secondary);
colors.setBrand('accent', this.projectcolors.accent);
} else {
colors.setBrand('primary', this.$q.config.brand.primary);
colors.setBrand('secondary', this.$q.config.brand.secondary);
colors.setBrand('accent', this.$q.config.brand.accent);
}
}
if (color === 'emo') {
colors.setBrand('primary', this.$q.config.brand.primary);
colors.setBrand('secondary', this.$q.config.brand.secondary);
colors.setBrand('accent', this.$q.config.brand.accent);
}
if (color === 'unicorn') {
colors.setBrand('primary', 'purple');
colors.setBrand('secondary', 'lightgrey');
colors.setBrand('accent', 'hotpink');
} else if (color === 'tido' && this.projectcolors.primary && this.projectcolors.secondary && this.projectcolors.accent) {
colors.setBrand('primary', this.projectcolors.primary);
colors.setBrand('secondary', this.projectcolors.secondary);
colors.setBrand('accent', this.projectcolors.accent);
}
},
},
......@@ -92,4 +88,8 @@ export default {
display: none;
}
}
.theme {
background-color: $grey-5;
}
</style>
<template>
<div class="item">
<q-tabs
v-model="activeTab"
v-model="activeTabContents"
dense
class="text-grey q-mb-sm"
active-color="$q.dark.isActive ? 'white' : 'accent'"
......@@ -79,6 +79,10 @@ export default {
type: Array,
default: () => [],
},
contentindex: {
type: Number,
default: () => 0,
},
fontsize: {
type: Number,
default: () => 16,
......@@ -87,6 +91,10 @@ export default {
type: Array,
default: () => [],
},
oncontentindexchange: {
type: Function,
default: () => null,
},
request: {
type: Function,
default: null,
......@@ -101,7 +109,7 @@ export default {
},
},
data: () => ({
activeTab: null,
activeTabContents: '',
content: '',
fontSizeLimits: {
min: 14,
......@@ -115,75 +123,95 @@ export default {
return Object.keys(support).length && support.url !== '';
},
activeTab() {
return this.contenturls[this.contentindex];
},
},
watch: {
fontsize() {
this.$refs.contentsize.style.fontSize = `${this.fontsize}px`;
},
async activeTab(url) {
this.$root.$emit('update-annotation-loading', true);
activeTabContents(url) {
this.oncontentindexchange(this.contenturls.findIndex((x) => x === url));
},
activeTab: {
async handler(url) {
if (!url) {
return;
}
this.$root.$emit('update-annotation-loading', true);
const data = await this.request(url, 'text');
const data = await this.request(url, 'text');
if (this.supportType) {
await this.getSupport(this.manifests[0].support);
}
if (this.supportType) {
await this.getSupport(this.manifests[0].support);
}
const annotationPanelHidden = this.panels.find(
(x) => x.panel_label === 'Annotations' && !x.show,
);
const parser = new DOMParser();
let dom = parser.parseFromString(data, 'text/html');
if (!annotationPanelHidden) {
const spans = [
...dom.querySelectorAll('[data-target]:not([value=""])'),
];
const spanIds = [
...new Set(
spans.map((x) => x
.getAttribute('data-target')
.replace('_start', '')
.replace('_end', '')),
),
];
spanIds.forEach((selector) => {
dom = this.replaceSelectorWithSpan(selector, dom);
});
const dataTargets = [...dom.querySelectorAll('[id]')].map((x) => x.getAttribute('id'));
dataTargets.forEach((selector) => this.addHighlightToTargetIds(selector, dom));
}
this.content = dom.documentElement.innerHTML;
const displayedAnnotations = [
...dom.querySelectorAll('[data-annotation]'),
]
.map((x) => x.getAttribute('class'))
.reduce((prev, curr) => {
(curr || '').split(' ').forEach((c) => {
prev[c.replace(/\./g, '')] = true;
const annotationPanelHidden = this.panels.find(
(x) => x.panel_label === 'Annotations' && !x.show,
);
const parser = new DOMParser();
let dom = parser.parseFromString(data, 'text/html');
if (!annotationPanelHidden) {
const spans = [
...dom.querySelectorAll('[data-target]:not([value=""])'),
];
const spanIds = [
...new Set(
spans.map((x) => x
.getAttribute('data-target')
.replace('_start', '')
.replace('_end', '')),
),
];
spanIds.forEach((selector) => {
dom = this.replaceSelectorWithSpan(selector, dom);
});
return prev;
}, {});
await this.delay(200);
const dataTargets = [...dom.querySelectorAll('[id]')].map((x) => x.getAttribute('id'));
this.$root.$emit('update-annotations', displayedAnnotations);
this.$root.$emit('update-annotation-loading', false);
dataTargets.forEach((selector) => this.addHighlightToTargetIds(selector, dom));
}
this.content = dom.documentElement.innerHTML;
// to improve performance, here we are trying to get candidates of annotation that are
// possibly be the annotation and try to match them with their respective annotations.
const displayedAnnotations = [
...dom.querySelectorAll('[data-annotation]'),
]
.map((x) => x.getAttribute('class'))
.reduce((prev, curr) => {
(curr || '').split(' ').forEach((c) => {
prev[c.replace(/\./g, '')] = true;
});
return prev;
}, {});
await this.delay(200);
this.$root.$emit('update-annotations', displayedAnnotations);
this.$root.$emit('update-annotation-loading', false);
},
immediate: true,
},
},
async created() {
this.fasSearchPlus = fasSearchPlus;
this.fasSearchMinus = fasSearchMinus;
const [contentUrl] = this.contenturls;
const activeTab = this.contenturls[this.contentindex];
const [contenturls] = this.contenturls[0];
this.activeTab = contentUrl;
this.activeTabContents = activeTab;
if (!activeTab) {
this.oncontentindexchange(0);
this.activeTabContents = contenturls;
}
},
mounted() {
......@@ -194,6 +222,13 @@ export default {
this.getSupport(this.manifests[index].support);
}
});
const [contenturls] = this.contenturls[0];
this.$root.$on('manifest-changed', () => {
this.activeTabContents = contenturls;
this.oncontentindexchange(0);
});
},
methods: {
async delay(ms = 2500) {
......
<template>
<q-toolbar
:class="$q.dark.isActive ? 'bg-dark' : 'bg-secondary text-primary'"
>
<div class="footer__wrap">
<div
bordered
class="row justify-center items-center"
reveal
>
<Language v-if="standalone" />
<Color :projectcolors="projectcolors" />
<Softwareinfo />
</div>
</div>
</q-toolbar>
</template>
<script>
import Color from '@/components/color.vue';
import Language from '@/components/language.vue';
import Softwareinfo from '@/components/softwareinfo.vue';
export default {
name: 'Footer',
components: {
Color,
Language,
Softwareinfo,
},
props: {
projectcolors: {
type: Object,
default: () => {},
},
standalone: Boolean,
},
};
</script>
<style lang="scss" scoped>
.footer__wrap {
margin: 0 auto;
max-width: 1200px;
}
</style>
......@@ -23,7 +23,6 @@
<Tools
:config="config"
:projectcolors="projectcolors"
:standalone="standalone"
/>
</q-toolbar>
......@@ -50,7 +49,6 @@
<Tools
:config="config"
:projectcolors="projectcolors"
:standalone="standalone"
/>
</div>
</q-toolbar>
......@@ -112,7 +110,6 @@ export default {
type: Object,
default: () => {},
},
standalone: Boolean,
},
};
</script>
......
......@@ -16,7 +16,8 @@
<q-separator inset />
<q-card-section class="text-body2 text-center">
{{ message }}
<!-- eslint-disable -- https://eslint.vuejs.org/rules/no-v-html.html -->
<span v-html="message" />
</q-card-section>
</q-card>
</template>
......
<template>
<div
v-if="errormessage"
class="q-pa-sm"
>
<Notification
:message="$t(messages.none)"
:notification-colors="config.notificationColors"
title-key="imageErrorTitle"
type="warning"
/>
</div>
<figure
v-else
id="openseadragon"
class="item"
>
......@@ -35,9 +47,22 @@ import {
fasCompressArrowsAlt,
} from '@quasar/extras/fontawesome-v5';
import Notification from '@/components/notification.vue';
export default {
name: 'OpenSeadragon',
components: {
Notification,
},
props: {
config: {
type: Object,
default: () => {},
},
errormessage: {
type: Boolean,
default: () => false,
},
imageurl: {
type: String,
default: () => '',
......@@ -63,9 +88,16 @@ export default {
homeButton: 'default',
fullPageButton: 'fullscreen',
},
messages: {
none: 'imageErrorMessage',
},
};
},
mounted() {
if (this.errormessage) {
return;
}
const viewer = new OpenSeadragon.Viewer(this.options);
viewer.controlsFadeDelay = 1000;
......
<template>
<div class="row no-wrap justify-end col-xs-3">
<Language
v-if="standalone"
v-if="config['language-switch']"
:config="config"
/>
<Color :projectcolors="projectcolors" />
<Color
v-if="config.themes && projectColorsSet"
:projectcolors="projectcolors"
:config="config"
/>
<Softwareinfo />
</div>
......@@ -32,7 +36,11 @@ export default {
type: Object,
default: () => {},
},
standalone: Boolean,
},
computed: {
projectColorsSet() {
return !!Object.values(this.projectcolors).every((color) => color !== null && color !== '');
},
},
};
</script>
......@@ -18,6 +18,12 @@ export default {
Editors: 'Herausgeber',
hide: 'Verstecke',
Image: 'Digitalisat',
imageErrorMessage: 'Einige Bilder stehen Ihnen außerhalb des Netzwerks der'
+ ' Georg-August-Universität Göttingen nicht ohne VPN-Zugang zur Verfügung. '
+ 'Wenn Sie Zugang erhalten möchten, nutzen Sie bitte die Anleitung der GWDG zum'
+ ' <a href="https://docs.gwdg.de/doku.php?id=en:services:network_services:vpn:start"'
+ 'target="_blank"> Netzwerk-Service VPN</a>.',
imageErrorTitle: 'Keine Bild Verfügbar',
imageLicense: 'Bildlizenz',
imageNotes: 'Bildnotizen',
Increase: 'Vergrössern',
......
......@@ -18,6 +18,11 @@ export default {
Editors: 'Editors',
hide: 'Hide',
Image: 'Image',
imageErrorMessage: 'Some images are not available outside of the VPN (Virtual Private Network)'
+ ' of the Georg-August-University Goettingen. If you like to get access please refer to the'
+ 'guide at <a href="https://docs.gwdg.de/doku.php?id=en:services:network_services:vpn:start"'
+ 'target="_blank"> Network Services VPN</a>.',
imageErrorTitle: 'No Image Available',
imageLicense: 'Image License',
imageNotes: 'Image Notes',
Increase: 'Increase',
......@@ -55,7 +60,7 @@ export default {
Text: 'Text',
Textsize: 'Textsize',
Title: 'Title',
title_homepage: 'The Syriac, Arabic, and Karshuni Ahiqar Texts',
title_homepage: 'The Story of Ahiqar in its Syriac and Arabic Tradition',
title_viewer: 'Edition Viewer',
toolTip_Reference: 'Referenced Annotation',
toolTip_References: 'Referenced Annotations',
......
......@@ -61,6 +61,12 @@
"Motif": ["Motif"]
}
},
"breadcrumbNavigation": {
"show": true,
"title_homepage_key": "title_homepage",
"title_viewer_key": "title_viewer",
"website": "https://ahikar.sub.uni-goettingen.de/website/"
},
"colors": {
"primary": "",
"secondary": "",
......@@ -77,6 +83,8 @@
"item": "Sheet",
"manifest": "Manuscript"
},
"lang": "en-us",
"language-switch": true,
"meta": {
"collection": {
"all": true
......@@ -119,14 +127,7 @@
}
],
"rtl": false,
"lang": "en-us",
"standalone": true,
"breadcrumbNavigation": {
"show": true,
"title_homepage_key": "title_homepage",
"title_viewer_key": "title_viewer",
"website": "https://ahikar.sub.uni-goettingen.de/website/"
}
"themes": false
}
</script>
......
......@@ -75,6 +75,10 @@ export default {
this.panels = newPanels;
});
this.$root.$on('manifest-changed', () => {
this.panels = [...this.panels].map((tab) => ({ ...tab, tab_model: 'tab0' }));
});
this.$root.$on('add-panel', () => {
const newPanel = {
id: uuidv4(),
......
......@@ -93,6 +93,10 @@ export default {
type: Object,
default: () => {},
},
contentindex: {
type: Number,
default: () => 0,
},
contenttypes: {
type: Array,
default: () => [],
......@@ -109,6 +113,10 @@ export default {
type: String,
default: () => '',
},
errormessage: {
type: Boolean,
default: () => false,
},
isloading: {
type: Boolean,
default: false,
......@@ -125,6 +133,10 @@ export default {
type: Array,
default: () => [],
},
oncontentindexchange: {
type: Function,
default: () => null,
},
panels: {
type: Array,
default: () => [],
......