diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/TileInfoModal.vue | 240 |
1 files changed, 111 insertions, 129 deletions
diff --git a/src/components/TileInfoModal.vue b/src/components/TileInfoModal.vue index 90ad9a7..c8f8047 100644 --- a/src/components/TileInfoModal.vue +++ b/src/components/TileInfoModal.vue @@ -1,76 +1,66 @@ <script lang="ts"> + import {defineComponent, PropType} from 'vue'; import CloseIcon from './icon/CloseIcon.vue'; -import Tile from './Tile.vue' import {LayoutNode, LayoutOptions} from '../layout'; -import {TolNode, TolMap, UiOptions, DescInfo, ImgInfo, TileInfoResponse} from '../lib'; +import {TolNode, TolMap, UiOptions, DescInfo, ImgInfo, NodeInfo, InfoResponse} from '../lib'; import {capitalizeWords} from '../util'; -// Displays information about a tree-of-life node export default defineComponent({ - data(){ - return { - tolNode: null as null | TolNode, - descInfo: null as null | DescInfo, - descInfo1: null as null | DescInfo, - descInfo2: null as null | DescInfo, - imgInfo: null as null | ImgInfo, - imgInfo1: null as null | ImgInfo, - imgInfo2: null as null | ImgInfo, - }; - }, props: { nodeName: {type: String, required: true}, tolMap: {type: Object as PropType<TolMap>, required: true}, + // Options lytOpts: {type: Object as PropType<LayoutOptions>, required: true}, uiOpts: {type: Object as PropType<UiOptions>, required: true}, }, + data(){ + return { + // These are set using a server response + tolNode: null as null | TolNode, + nodes: [] as TolNode[], // The nodes to display info for + imgInfos: [] as (ImgInfo | null)[], + descInfos: [] as (DescInfo | null)[], + }; + }, computed: { - displayName(): string { - if (this.tolNode == null || this.tolNode.commonName == null){ - return capitalizeWords(this.nodeName); - } else { - return `${capitalizeWords(this.tolNode.commonName)} (aka ${capitalizeWords(this.nodeName)})`; - } - }, - subName1(): string { - return this.displayName.substring(1, this.displayName.indexOf(' + ')); - }, - subName2(): string { - return this.displayName.substring(this.displayName.indexOf(' + ') + 3, this.displayName.length - 1); - }, - imgStyles(): Record<string,string> { - return this.getImgStyles(this.tolNode == null ? null : this.tolNode.imgName as string); - }, - firstImgStyles(): Record<string,string> { - return this.getImgStyles(this.tolNode!.imgName![0]); - }, - secondImgStyles(): Record<string,string> { - return this.getImgStyles(this.tolNode!.imgName![1]); + subNames(): [string, string] | null { + const regex = /\[(.+) \+ (.+)\]/; + let results = regex.exec(this.nodeName); + return results == null ? null : [results[1], results[2]]; }, - dummyNode(): LayoutNode { - let newNode = new LayoutNode(this.nodeName, []); - newNode.dims = [this.lytOpts.maxTileSz, this.lytOpts.maxTileSz]; - return newNode; + styles(): Record<string,string> { + return { + backgroundColor: this.uiOpts.bgColorAlt, + borderRadius: this.uiOpts.borderRadius + 'px', + boxShadow: this.uiOpts.shadowNormal, + overflow: 'visible auto', + }; }, }, methods: { - onCloseClick(evt: Event){ - if (evt.target == this.$el || (this.$refs.closeIcon as typeof CloseIcon).$el.contains(evt.target)){ - this.$emit('close'); + getDisplayName(name: string, tolNode: TolNode | null): string { + if (tolNode == null || tolNode.commonName == null){ + return capitalizeWords(name); + } else { + return `${capitalizeWords(tolNode.commonName)} (aka ${capitalizeWords(name)})`; } }, - getImgStyles(imgName: string | null){ + getImgStyles(tolNode: TolNode): Record<string,string> { + let imgName = null; + if (typeof(tolNode.imgName) === 'string'){ // Exclude string-array case + imgName = tolNode.imgName; + } return { - boxShadow: this.uiOpts.shadowNormal, - borderRadius: this.uiOpts.borderRadius + 'px', + width: this.lytOpts.maxTileSz + 'px', + height: this.lytOpts.maxTileSz + 'px', backgroundImage: imgName != null ? 'url(\'/img/' + imgName.replaceAll('\'', '\\\'') + '\')' : 'none', - backgroundColor: '#1c1917', + backgroundColor: this.uiOpts.bgColorDark, backgroundSize: 'cover', - width: this.lytOpts.maxTileSz + 'px', - height: this.lytOpts.maxTileSz + 'px', + borderRadius: this.uiOpts.borderRadius + 'px', + boxShadow: this.uiOpts.shadowNormal, }; }, licenseToUrl(license: string){ @@ -103,41 +93,54 @@ export default defineComponent({ return "[INVALID LICENSE]"; } }, + onClose(evt: Event){ + if (evt.target == this.$el || (this.$refs.closeIcon as typeof CloseIcon).$el.contains(evt.target)){ + this.$emit('close'); + } + }, }, - created(){ + async created(){ + // Query server for tol-node info let url = new URL(window.location.href); url.pathname = '/data/info'; url.search = '?name=' + encodeURIComponent(this.nodeName); - url.search += this.uiOpts.useReducedTree ? '&tree=reduced' : ''; - fetch(url.toString()) - .then(response => response.json()) - .then(obj => { - this.tolNode = obj.tolNode; - if (!Array.isArray(obj.descData)){ - this.descInfo = obj.descData; - } else { - [this.descInfo1, this.descInfo2] = obj.descData; - } - if (!Array.isArray(obj.imgData)){ - this.imgInfo = obj.imgData; - } else { - [this.imgInfo1, this.imgInfo2] = obj.imgData; - } - }); + if (this.uiOpts.useReducedTree){ + url.search += '&tree=reduced'; + } + let responseObj: InfoResponse; + try { + let response = await fetch(url.toString()); + responseObj = await response.json(); + } catch (error){ + console.log("ERROR: Unable to retrieve data from server") + return; + } + // Set fields from response + this.tolNode = responseObj.nodeInfo.tolNode; + if (responseObj.subNodesInfo.length == 0){ + this.nodes = [this.tolNode] + this.imgInfos = [responseObj.nodeInfo.imgInfo]; + this.descInfos = [responseObj.nodeInfo.descInfo]; + } else { + for (let nodeInfo of responseObj.subNodesInfo){ + this.nodes.push(nodeInfo.tolNode); + this.imgInfos.push(nodeInfo.imgInfo); + this.descInfos.push(nodeInfo.descInfo); + } + } }, - components: {CloseIcon, Tile, }, + components: {CloseIcon, }, emits: ['close', ], }); </script> <template> -<div class="fixed left-0 top-0 w-full h-full bg-black/40" @click="onCloseClick"> - <div class="absolute left-1/2 -translate-x-1/2 w-4/5 max-h-[80%] overflow-y-auto top-1/2 -translate-y-1/2 p-4 - bg-stone-50 rounded-md shadow shadow-black"> - <close-icon @click.stop="onCloseClick" ref="closeIcon" +<div class="fixed left-0 top-0 w-full h-full bg-black/40" @click="onClose"> + <div class="absolute left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2 w-4/5 max-h-[80%] p-4" :style="styles"> + <close-icon @click.stop="onClose" ref="closeIcon" class="block absolute top-2 right-2 w-6 h-6 hover:cursor-pointer"/> <h1 class="text-center text-xl font-bold mb-2"> - {{displayName}} + {{getDisplayName(nodeName, tolNode)}} <div v-if="tolNode != null"> ({{tolNode.children.length}} children, {{tolNode.tips}} tips, <a :href="'https://tree.opentreeoflife.org/opentree/argus/opentree13.4@' + tolNode.otolId"> @@ -145,66 +148,45 @@ export default defineComponent({ </div> </h1> <hr class="mb-4 border-stone-400"/> - <div class="flex"> - <div class="mr-4"> - <div v-if="tolNode == null"/> - <div v-else-if="!Array.isArray(tolNode.imgName)"> - <div :style="imgStyles"/> - <ul v-if="imgInfo != null"> - <li>Obtained via: {{imgInfo.src}}</li> - <li>License: <a :href="licenseToUrl(imgInfo.license)">{{imgInfo.license}}</a></li> - <li><a :href="imgInfo.url" class="underline">Source URL</a></li> - <li>Artist: {{imgInfo.artist}}</li> - <li v-if="imgInfo.credit != ''">Credit: {{imgInfo.credit}}</li> - </ul> - </div> - <div v-else> - <div v-if="tolNode.imgName[0] != null" :style="firstImgStyles"/> - <ul v-if="imgInfo1 != null"> - <li>Obtained via: {{imgInfo1.src}}</li> - <li>License: <a :href="licenseToUrl(imgInfo1.license)">{{imgInfo1.license}}</a></li> - <li><a :href="imgInfo1.url" class="underline">Source URL</a></li> - <li>Artist: {{imgInfo1.artist}}</li> - <li v-if="imgInfo1.credit != ''">Credit: {{imgInfo1.credit}}</li> - </ul> - <div v-if="tolNode.imgName[1] != null" :style="secondImgStyles"/> - <ul v-if="imgInfo2 != null"> - <li>Obtained via: {{imgInfo2.src}}</li> - <li>License: <a :href="licenseToUrl(imgInfo2.license)">{{imgInfo2.license}}</a></li> - <li><a :href="imgInfo2.url" class="underline">Source URL</a></li> - <li>Artist: {{imgInfo2.artist}}</li> - <li v-if="imgInfo2.credit != ''">Credit: {{imgInfo2.credit}}</li> - </ul> - </div> - </div> - <div v-if="descInfo == null && descInfo1 == null && descInfo2 == null"> - (No description found) - </div> - <div v-else-if="descInfo != null"> - <div> - Redirected: {{descInfo.fromRedirect}} <br/> - Short-description from {{descInfo.fromDbp ? 'DBpedia' : 'Wikipedia'}} <br/> - <a :href="'https://en.wikipedia.org/?curid=' + descInfo.wikiId" class="underline"> - Wikipedia Link - </a> - </div> - <hr/> - <div>{{descInfo.text}}</div> - </div> - <div v-else> - <div> - <h2 class="font-bold">{{subName1}}</h2> - <div v-if="descInfo1 != null">{{descInfo1.text}}</div> - <div v-else>(No description found)</div> - </div> - <div> - <h2 class="font-bold">{{subName2}}</h2> - <div v-if="descInfo2 != null">{{descInfo2.text}}</div> - <div v-else>(No description found)</div> + <div v-if="tolNode == null">Querying server</div> + <template v-else> + <div v-if="nodes.length > 1">This is a compound node</div> + <div v-for="idx in (nodes.length == 1 ? [0] : [0, 1])"> + <h1 v-if="nodes.length > 1" class="text-center font-bold"> + {{getDisplayName(subNames![idx], nodes[idx])}} + </h1> + <div class="flex gap-1"> + <div class="w-1/2"> + <div :style="getImgStyles(nodes[idx])"/> + <ul v-if="imgInfos[idx]! != null"> + <li>Obtained via: {{imgInfos[idx]!.src}}</li> + <li>License: + <a :href="licenseToUrl(imgInfos[idx]!.license)">{{imgInfos[idx]!.license}}</a> + </li> + <li><a :href="imgInfos[idx]!.url" class="underline">Source URL</a></li> + <li>Artist: {{imgInfos[idx]!.artist}}</li> + <li v-if="imgInfos[idx]!.credit != ''" class="overflow-auto"> + Credit: {{imgInfos[idx]!.credit}} + </li> + </ul> + </div> + <div v-if="descInfos[idx]! != null"> + <div> + Redirected: {{descInfos[idx]!.fromRedirect}} <br/> + Short-description from {{descInfos[idx]!.fromDbp ? 'DBpedia' : 'Wikipedia'}} <br/> + <a :href="'https://en.wikipedia.org/?curid=' + descInfos[idx]!.wikiId" class="underline"> + Wikipedia Link + </a> + </div> + <hr/> + <div>{{descInfos[idx]!.text}}</div> + </div> + <div v-else> + (No description found) + </div> </div> </div> - </div> - + </template> </div> </div> </template> |
