diff options
| -rwxr-xr-x | backend/server.py | 5 | ||||
| -rw-r--r-- | src/App.vue | 20 | ||||
| -rw-r--r-- | src/components/SearchModal.vue | 26 | ||||
| -rw-r--r-- | src/components/Tile.vue | 6 | ||||
| -rw-r--r-- | src/components/TileInfoModal.vue | 22 |
5 files changed, 51 insertions, 28 deletions
diff --git a/backend/server.py b/backend/server.py index 374fb53..6d2970d 100755 --- a/backend/server.py +++ b/backend/server.py @@ -121,8 +121,11 @@ def lookupNodeInfo(name): imgInfo = None if row != None: imgInfo = {"eolId": row[0], "sourceUrl": row[1], "license": row[2], "copyrightOwner": row[3]} + # Get other info + temp = lookupNodes([name], False) + nodeObj = temp[name] if name in temp else None # - return {"desc": desc, "imgInfo": imgInfo} + return {"desc": desc, "imgInfo": imgInfo, "nodeObj": nodeObj} class DbServer(BaseHTTPRequestHandler): def do_GET(self): diff --git a/src/App.vue b/src/App.vue index 55dc271..3cabecd 100644 --- a/src/App.vue +++ b/src/App.vue @@ -100,7 +100,7 @@ export default defineComponent({ layoutMap: initLayoutMap(layoutTree), // Maps names to LayoutNode objects overflownRoot: false, // Set when displaying a root tile with many children, with overflow // Modals and settings related - infoModalNode: null as LayoutNode | null, // Node to display info for, or null + infoModalNodeName: null as string | null, // Name of node to display info for, or null helpOpen: false, searchOpen: false, settingsOpen: false, @@ -323,9 +323,11 @@ export default defineComponent({ this.overflownRoot = false; }, // For tile-info events - onInfoIconClick(node: LayoutNode){ - this.resetMode(); - this.infoModalNode = node; + onInfoIconClick(nodeName: string){ + if (!this.searchOpen){ + this.resetMode(); + } + this.infoModalNodeName = nodeName; }, // For help events onHelpIconClick(){ @@ -574,7 +576,7 @@ export default defineComponent({ }); }, resetMode(){ - this.infoModalNode = null; + this.infoModalNodeName = null; this.searchOpen = false; this.helpOpen = false; this.settingsOpen = false; @@ -634,12 +636,12 @@ export default defineComponent({ text-white/40 hover:text-white hover:cursor-pointer"/> <!-- Modals --> <transition name="fade"> - <tile-info-modal v-if="infoModalNode != null" :node="infoModalNode" :tolMap="tolMap" :uiOpts="uiOpts" - @info-modal-close="infoModalNode = null"/> + <search-modal v-if="searchOpen" :tolMap="tolMap" :uiOpts="uiOpts" ref="searchModal" + @search-close="searchOpen = false" @search-node="onSearchNode" @info-icon-click="onInfoIconClick"/> </transition> <transition name="fade"> - <search-modal v-if="searchOpen" :tolMap="tolMap" :uiOpts="uiOpts" - @search-close="searchOpen = false" @search-node="onSearchNode" ref="searchModal"/> + <tile-info-modal v-if="infoModalNodeName != null" :nodeName="infoModalNodeName" :tolMap="tolMap" :uiOpts="uiOpts" + @info-modal-close="infoModalNodeName = null"/> </transition> <transition name="fade"> <help-modal v-if="helpOpen" :uiOpts="uiOpts" @help-modal-close="helpOpen = false"/> diff --git a/src/components/SearchModal.vue b/src/components/SearchModal.vue index eccc685..bc77a39 100644 --- a/src/components/SearchModal.vue +++ b/src/components/SearchModal.vue @@ -1,6 +1,7 @@ <script lang="ts"> import {defineComponent, PropType} from 'vue'; import SearchIcon from './icon/SearchIcon.vue'; +import InfoIcon from './icon/InfoIcon.vue'; import {LayoutNode} from '../layout'; import type {TolMap} from '../tol'; @@ -23,6 +24,18 @@ export default defineComponent({ tolMap: {type: Object as PropType<TolMap>, required: true}, uiOpts: {type: Object, required: true}, }, + computed: { + infoIconStyles(): Record<string,string> { + let size = this.uiOpts.infoIconSz + 'px'; + return { + width: size, + height: size, + minWidth: size, + minHeight: size, + margin: this.uiOpts.infoIconMargin + 'px', + }; + }, + }, methods: { onCloseClick(evt: Event){ if (evt.target == this.$el || (this.$refs.searchIcon as typeof SearchIcon).$el.contains(evt.target)){ @@ -123,12 +136,15 @@ export default defineComponent({ } } }, + onInfoIconClick(nodeName: string){ + this.$emit('info-icon-click', nodeName); + }, }, mounted(){ (this.$refs.searchInput as HTMLInputElement).focus(); }, - components: {SearchIcon, }, - emits: ['search-node', 'search-close', ], + components: {SearchIcon, InfoIcon, }, + emits: ['search-node', 'search-close', 'info-icon-click'], }); </script> @@ -143,8 +159,10 @@ export default defineComponent({ <div class="absolute top-[100%] w-full"> <div v-for="(sugg, idx) of searchSuggs" :style="{backgroundColor: idx == focusedSuggIdx ? '#a3a3a3' : 'white'}" - class="bg-white border p-1 hover:underline hover:cursor-pointer" - @click="resolveSearch(sugg.name)"> + class="border p-1 hover:underline hover:cursor-pointer" @click="resolveSearch(sugg.name)"> + <info-icon :style="infoIconStyles" + class="float-right text-stone-500 hover:text-stone-900 hover:cursor-pointer" + @click.stop="onInfoIconClick(sugg.name)"/> {{sugg.name == sugg.altName ? sugg.name : `${sugg.altName} (aka ${sugg.name})`}} </div> <div v-if="searchHasMoreSuggs" class="bg-white px-1 text-center border">...</div> diff --git a/src/components/Tile.vue b/src/components/Tile.vue index ddf2fc0..86770ef 100644 --- a/src/components/Tile.vue +++ b/src/components/Tile.vue @@ -315,7 +315,7 @@ export default defineComponent({ this.$emit(this.isLeaf ? 'leaf-click-held' : 'nonleaf-click-held', this.layoutNode); }, onInfoIconClick(evt: Event){ - this.$emit('info-icon-click', this.layoutNode); + this.$emit('info-icon-click', this.layoutNode.name); }, // Mouse hover handling onMouseEnter(evt: Event){ @@ -341,8 +341,8 @@ export default defineComponent({ onInnerNonleafClickHeld(node: LayoutNode){ this.$emit('nonleaf-click-held', node); }, - onInnerInfoIconClick(node: LayoutNode){ - this.$emit('info-icon-click', node); + onInnerInfoIconClick(nodeName: string){ + this.$emit('info-icon-click', nodeName); }, // Other onTransitionEnd(evt: Event){ diff --git a/src/components/TileInfoModal.vue b/src/components/TileInfoModal.vue index 6701f1f..4b904b2 100644 --- a/src/components/TileInfoModal.vue +++ b/src/components/TileInfoModal.vue @@ -13,27 +13,25 @@ export default defineComponent({ desc: null as null | string, fromRedirect: false, imgInfo: null as null | {eolId: string, sourceUrl: string, license: string, copyrightOwner: string}, + tolNode: null as null | TolNode, }; }, props: { - node: {type: Object as PropType<LayoutNode>, required: true}, + nodeName: {type: String, required: true}, tolMap: {type: Object as PropType<TolMap>, required: true}, uiOpts: {type: Object, required: true}, }, computed: { - tolNode(): TolNode { - return this.tolMap.get(this.node.name)!; - }, displayName(): string { - if (this.tolNode.commonName == null){ - return capitalizeWords(this.node.name); + if (this.tolNode == null || this.tolNode.commonName == null){ + return capitalizeWords(this.nodeName); } else { - return `${capitalizeWords(this.tolNode.commonName)} (aka ${capitalizeWords(this.node.name)})`; + return `${capitalizeWords(this.tolNode.commonName)} (aka ${capitalizeWords(this.nodeName)})`; } }, imgStyles(): Record<string,string> { return { - backgroundImage: this.tolNode.imgName != null ? + backgroundImage: this.tolNode != null && this.tolNode.imgName != null ? 'linear-gradient(to bottom, rgba(0,0,0,0.4), #0000 40%, #0000 60%, rgba(0,0,0,0.4) 100%),' + 'url(\'/img/' + this.tolNode.imgName.replaceAll('\'', '\\\'') + '\')' : 'none', @@ -55,7 +53,7 @@ export default defineComponent({ created(){ let url = new URL(window.location.href); url.pathname = '/data/info'; - url.search = '?name=' + encodeURIComponent(this.node.name); + url.search = '?name=' + encodeURIComponent(this.nodeName); fetch(url.toString()) .then(response => response.json()) .then(obj => { @@ -63,6 +61,7 @@ export default defineComponent({ if (obj.desc != null){ this.desc = obj.desc.text; this.fromRedirect = obj.desc.fromRedirect; + this.tolNode = obj.nodeObj; } this.imgInfo = obj.imgInfo; } @@ -81,8 +80,9 @@ export default defineComponent({ 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}} - <div v-if="tolNode.children.length > 0">({{tolNode.children.length}} children)</div> - <div>({{tolNode.tips}} tips)</div> + <div v-if="tolNode != null"> + ({{tolNode.children.length}} children, {{tolNode.tips}} tips) + </div> </h1> <hr class="mb-4 border-stone-400"/> <div class="flex"> |
