diff options
| -rw-r--r-- | src/App.vue | 85 | ||||
| -rw-r--r-- | src/components/AncestryBar.vue | 3 | ||||
| -rw-r--r-- | src/components/SearchModal.vue | 3 | ||||
| -rw-r--r-- | src/components/SettingsModal.vue | 16 | ||||
| -rw-r--r-- | src/components/Tile.vue | 3 | ||||
| -rw-r--r-- | src/components/TileInfoModal.vue | 4 | ||||
| -rw-r--r-- | src/layout.ts | 2 | ||||
| -rw-r--r-- | src/lib.ts | 86 | ||||
| -rw-r--r-- | src/tol.ts | 26 |
9 files changed, 121 insertions, 107 deletions
diff --git a/src/App.vue b/src/App.vue index ba36a69..aa0e859 100644 --- a/src/App.vue +++ b/src/App.vue @@ -84,11 +84,12 @@ import SettingsIcon from './components/icon/SettingsIcon.vue'; import HelpIcon from './components/icon/HelpIcon.vue'; // Other // Note: Import paths lack a .ts or .js extension because .ts makes vue-tsc complain, and .js makes vite complain -import {TolNode, TolMap, getServerResponse, InfoResponse, Action, UiOptions, OptionType} from './lib'; -import {LayoutNode, LayoutOptions, LayoutTreeChg} from './layout'; -import {initLayoutTree, initLayoutMap, tryLayout} from './layout'; -import {getBreakpoint, getScrollBarWidth, isTouchDevice, - arraySum, randWeightedChoice, timeout} from './util'; +import {TolNode, TolMap} from './tol'; +import {LayoutNode, LayoutOptions, LayoutTreeChg, + initLayoutTree, initLayoutMap, tryLayout} from './layout'; +import {getServerResponse, InfoResponse, Action, + UiOptions, getDefaultLytOpts, getDefaultUiOpts, OptionType} from './lib'; +import {arraySum, randWeightedChoice, timeout} from './util'; // Type representing auto-mode actions type AutoAction = 'move across' | 'move down' | 'move up' | Action; @@ -107,66 +108,6 @@ function getReverseAction(action: AutoAction): AutoAction | null { } } // For options -function getDefaultLytOpts(): LayoutOptions { - let screenSz = getBreakpoint(); - return { - tileSpacing: screenSz == 'sm' ? 6 : 10, //px - headerSz: 22, // px - minTileSz: 50, // px - maxTileSz: 200, // px - // Layout-algorithm related - layoutType: 'sweep', // 'sqr' | 'rect' | 'sweep' - rectMode: 'auto first-row', // 'horz' | 'vert' | 'linear' | 'auto' | 'auto first-row' - rectSensitivity: 0.9, // Between 0 and 1 - sweepMode: 'left', // 'left' | 'top' | 'shorter' | 'auto' - sweptNodesPrio: 'sqrt', // 'linear' | 'sqrt' | 'pow-2/3' - sweepToParent: 'fallback', // 'none' | 'prefer' | 'fallback' - }; -} -function getDefaultUiOpts(lytOpts: LayoutOptions): UiOptions { - let screenSz = getBreakpoint(); - // Reused option values - let textColor = '#fafaf9', textColorAlt = '#1c1917'; - let bgColor = '#292524', - bgColorLight = '#44403c', bgColorDark = '#1c1917', - bgColorLight2 = '#57534e', bgColorDark2 = '#0e0c0b', - bgColorAlt = '#fafaf9', bgColorAltDark = '#a8a29e'; - let altColor = '#a3e623', altColorDark = '#65a30d'; - let accentColor = '#f59e0b'; - let scrollGap = getScrollBarWidth(); - // - return { - // Shared coloring/sizing - textColor, textColorAlt, - bgColor, bgColorLight, bgColorDark, bgColorLight2, bgColorDark2, bgColorAlt, bgColorAltDark, - altColor, altColorDark, - borderRadius: 5, // px - shadowNormal: '0 0 2px black', - shadowHovered: '0 0 1px 2px ' + altColor, - shadowFocused: '0 0 1px 2px ' + accentColor, - // Component coloring - childQtyColors: [[1, 'greenyellow'], [10, 'orange'], [100, 'red']], - nonleafBgColors: [bgColorLight, bgColorLight2], - nonleafHeaderColor: bgColorDark, - ancestryBarBgColor: bgColorLight, - // Component sizing - ancestryBarBreadth: lytOpts.maxTileSz / 2 + lytOpts.tileSpacing*2, // px - tutPaneSz: 200, // px - scrollGap, - // Timing related - clickHoldDuration: 400, // ms - transitionDuration: 300, // ms - animationDelay: 100, // ms - autoActionDelay: 500, // ms - // Other - useReducedTree: false, - searchSuggLimit: 10, - searchJumpMode: false, - tutorialSkip: false, - disabledActions: new Set() as Set<Action>, - useDblClick: isTouchDevice(), - }; -} export default defineComponent({ data(){ @@ -737,19 +678,13 @@ export default defineComponent({ this.relayoutWithCollapse(); } }, - onResetSettings(): void { + onResetSettings(reinit: boolean): void { localStorage.clear(); - // Restore default options - let defaultLytOpts = getDefaultLytOpts(); - let defaultUiOpts = getDefaultUiOpts(defaultLytOpts); - if (this.uiOpts.useReducedTree != defaultUiOpts.useReducedTree){ + if (reinit){ this.reInit(); + } else { + this.relayoutWithCollapse(); } - Object.assign(this.lytOpts, defaultLytOpts); - Object.assign(this.uiOpts, defaultUiOpts); - console.log('Settings reset'); - // - this.relayoutWithCollapse(); }, // For help events onHelpIconClick(): void { diff --git a/src/components/AncestryBar.vue b/src/components/AncestryBar.vue index 38d51c3..78972b2 100644 --- a/src/components/AncestryBar.vue +++ b/src/components/AncestryBar.vue @@ -9,8 +9,9 @@ <script lang="ts"> import {defineComponent, PropType} from 'vue'; import Tile from './Tile.vue' -import {TolMap, UiOptions} from '../lib'; +import {TolMap} from '../tol'; import {LayoutNode, LayoutOptions} from '../layout'; +import {UiOptions} from '../lib'; export default defineComponent({ props: { diff --git a/src/components/SearchModal.vue b/src/components/SearchModal.vue index cb062e3..d866c91 100644 --- a/src/components/SearchModal.vue +++ b/src/components/SearchModal.vue @@ -38,8 +38,9 @@ import {defineComponent, PropType} from 'vue'; import SearchIcon from './icon/SearchIcon.vue'; import LogInIcon from './icon/LogInIcon.vue'; import InfoIcon from './icon/InfoIcon.vue'; -import {TolNode, TolMap, getServerResponse, SearchSugg, SearchSuggResponse, UiOptions} from '../lib'; +import {TolNode, TolMap} from '../tol'; import {LayoutNode, LayoutOptions} from '../layout'; +import {getServerResponse, SearchSugg, SearchSuggResponse, UiOptions} from '../lib'; export default defineComponent({ props: { diff --git a/src/components/SettingsModal.vue b/src/components/SettingsModal.vue index b11c84c..2e4d217 100644 --- a/src/components/SettingsModal.vue +++ b/src/components/SettingsModal.vue @@ -93,7 +93,7 @@ import {defineComponent, PropType} from 'vue'; import SButton from './SButton.vue'; import CloseIcon from './icon/CloseIcon.vue'; -import {UiOptions, OptionType} from '../lib'; +import {UiOptions, OptionType, getDefaultLytOpts, getDefaultUiOpts} from '../lib'; import {LayoutOptions} from '../layout'; export default defineComponent({ @@ -141,11 +141,11 @@ export default defineComponent({ this.$emit('setting-chg', 'LYT', 'minTileSz', {save: false}); } } - // + // Notify App this.$emit('setting-chg', optionType, option, {save, relayout: optionType == 'LYT', reinit: optionType == 'UI' && option == 'useReducedTree'}); + // Possibly make saved-indicator appear/animate if (save){ - // Make saved-indicator appear/animate if (!this.saved){ this.saved = true; } else { @@ -157,7 +157,15 @@ export default defineComponent({ } }, onReset(){ - this.$emit('reset'); + // Restore default options + let defaultLytOpts = getDefaultLytOpts(); + let defaultUiOpts = getDefaultUiOpts(defaultLytOpts); + let needReinit = this.uiOpts.useReducedTree != defaultUiOpts.useReducedTree; + Object.assign(this.lytOpts, defaultLytOpts); + Object.assign(this.uiOpts, defaultUiOpts); + // Notify App + this.$emit('reset', needReinit); + // Clear saved-indicator this.saved = false; }, pxToDisplayStr(px: number): string { diff --git a/src/components/Tile.vue b/src/components/Tile.vue index 15b1b48..7b24590 100644 --- a/src/components/Tile.vue +++ b/src/components/Tile.vue @@ -51,8 +51,9 @@ <script lang="ts"> import {defineComponent, PropType} from 'vue'; import InfoIcon from './icon/InfoIcon.vue'; -import {TolNode, TolMap, getImagePath, UiOptions} from '../lib'; +import {TolNode, TolMap} from '../tol'; import {LayoutNode, LayoutOptions} from '../layout'; +import {getImagePath, UiOptions} from '../lib'; import {capitalizeWords} from '../util'; const scrimGradient = 'linear-gradient(to bottom, rgba(0,0,0,0.4), #0000 40%)'; diff --git a/src/components/TileInfoModal.vue b/src/components/TileInfoModal.vue index c7b6305..c5f46ec 100644 --- a/src/components/TileInfoModal.vue +++ b/src/components/TileInfoModal.vue @@ -68,9 +68,9 @@ import {defineComponent, PropType} from 'vue'; import CloseIcon from './icon/CloseIcon.vue'; import ExternalLinkIcon from './icon/ExternalLinkIcon.vue'; +import {TolNode, TolMap} from '../tol'; import {LayoutNode, LayoutOptions} from '../layout'; -import {TolNode, TolMap, getServerResponse, getImagePath, - DescInfo, ImgInfo, NodeInfo, InfoResponse, UiOptions} from '../lib'; +import {getServerResponse, getImagePath, DescInfo, ImgInfo, NodeInfo, InfoResponse, UiOptions} from '../lib'; import {capitalizeWords} from '../util'; export default defineComponent({ diff --git a/src/layout.ts b/src/layout.ts index 79d3b70..665c617 100644 --- a/src/layout.ts +++ b/src/layout.ts @@ -5,7 +5,7 @@ * LayoutNode tree, on which tryLayout() can run a layout algorithm. */ -import {TolNode, TolMap} from './lib'; +import {TolNode, TolMap} from './tol'; import {range, arraySum, linspace, limitVals, updateAscSeq} from './util'; // Represents a node/tree that holds layout data for a TolNode node/tree @@ -2,28 +2,9 @@ * Project-wide types/classes */ -// Represents a tree-of-life node -export class TolNode { - otolId: string | null; - children: string[]; - parent: string | null; - tips: number; - pSupport: boolean; - commonName: null | string; - imgName: null | string | - [string, string] | [null, string] | [string, null]; // Pairs represent compound-images - constructor(children: string[] = [], parent = null, tips = 0, pSupport = false){ - this.otolId = null; - this.children = children; - this.parent = parent; - this.tips = tips; - this.pSupport = pSupport; - this.commonName = null; - this.imgName = null; - } -} -// Maps TolNode names to TolNode objects -export type TolMap = Map<string, TolNode>; +import {TolNode} from './tol'; +import {LayoutOptions} from './layout'; +import {getBreakpoint, getScrollBarWidth, isTouchDevice} from './util'; // For server requests const SERVER_URL = 'http://localhost:8000/cgi-bin/data.py' @@ -129,5 +110,66 @@ export type UiOptions = { disabledActions: Set<Action>, useDblClick: boolean, }; +// Option defaults +export function getDefaultLytOpts(): LayoutOptions { + let screenSz = getBreakpoint(); + return { + tileSpacing: screenSz == 'sm' ? 6 : 10, //px + headerSz: 22, // px + minTileSz: 50, // px + maxTileSz: 200, // px + // Layout-algorithm related + layoutType: 'sweep', // 'sqr' | 'rect' | 'sweep' + rectMode: 'auto first-row', // 'horz' | 'vert' | 'linear' | 'auto' | 'auto first-row' + rectSensitivity: 0.9, // Between 0 and 1 + sweepMode: 'left', // 'left' | 'top' | 'shorter' | 'auto' + sweptNodesPrio: 'sqrt', // 'linear' | 'sqrt' | 'pow-2/3' + sweepToParent: 'fallback', // 'none' | 'prefer' | 'fallback' + }; +} +export function getDefaultUiOpts(lytOpts: LayoutOptions): UiOptions { + let screenSz = getBreakpoint(); + // Reused option values + let textColor = '#fafaf9', textColorAlt = '#1c1917'; + let bgColor = '#292524', + bgColorLight = '#44403c', bgColorDark = '#1c1917', + bgColorLight2 = '#57534e', bgColorDark2 = '#0e0c0b', + bgColorAlt = '#fafaf9', bgColorAltDark = '#a8a29e'; + let altColor = '#a3e623', altColorDark = '#65a30d'; + let accentColor = '#f59e0b'; + let scrollGap = getScrollBarWidth(); + // + return { + // Shared coloring/sizing + textColor, textColorAlt, + bgColor, bgColorLight, bgColorDark, bgColorLight2, bgColorDark2, bgColorAlt, bgColorAltDark, + altColor, altColorDark, + borderRadius: 5, // px + shadowNormal: '0 0 2px black', + shadowHovered: '0 0 1px 2px ' + altColor, + shadowFocused: '0 0 1px 2px ' + accentColor, + // Component coloring + childQtyColors: [[1, 'greenyellow'], [10, 'orange'], [100, 'red']], + nonleafBgColors: [bgColorLight, bgColorLight2], + nonleafHeaderColor: bgColorDark, + ancestryBarBgColor: bgColorLight, + // Component sizing + ancestryBarBreadth: lytOpts.maxTileSz / 2 + lytOpts.tileSpacing*2, // px + tutPaneSz: 200, // px + scrollGap, + // Timing related + clickHoldDuration: 400, // ms + transitionDuration: 300, // ms + animationDelay: 100, // ms + autoActionDelay: 500, // ms + // Other + useReducedTree: false, + searchSuggLimit: 10, + searchJumpMode: false, + tutorialSkip: false, + disabledActions: new Set() as Set<Action>, + useDblClick: isTouchDevice(), + }; +} // Used in Settings.vue, and when saving to localStorage export type OptionType = 'LYT' | 'UI'; diff --git a/src/tol.ts b/src/tol.ts new file mode 100644 index 0000000..bf7a2f5 --- /dev/null +++ b/src/tol.ts @@ -0,0 +1,26 @@ +/* + * Used to represent tree-of-life data + */ + +// Represents a tree-of-life node +export class TolNode { + otolId: string | null; + children: string[]; + parent: string | null; + tips: number; + pSupport: boolean; + commonName: null | string; + imgName: null | string | + [string, string] | [null, string] | [string, null]; // Pairs represent compound-images + constructor(children: string[] = [], parent = null, tips = 0, pSupport = false){ + this.otolId = null; + this.children = children; + this.parent = parent; + this.tips = tips; + this.pSupport = pSupport; + this.commonName = null; + this.imgName = null; + } +} +// Maps TolNode names to TolNode objects +export type TolMap = Map<string, TolNode>; |
