diff --git a/clients/tagshow/build.sh b/clients/tagshow/.npm_build_helper.sh similarity index 100% rename from clients/tagshow/build.sh rename to clients/tagshow/.npm_build_helper.sh diff --git a/clients/tagshow/build.py b/clients/tagshow/build.py new file mode 100755 index 0000000000..af7c4cbaa5 --- /dev/null +++ b/clients/tagshow/build.py @@ -0,0 +1,22 @@ +#!/usr/bin/python + +import os, os.path, subprocess, sys + +import noms.symlink as symlink + +def main(): + # ln -sf ../../js/.babelrc .babelrc hack, because zip files screw up symlinks. + babelrcPath = os.path.abspath('.babelrc') + symlink.Force('../../js/.babelrc', babelrcPath) + + subprocess.check_call('./link.sh', shell=False) + subprocess.check_call(['npm', 'install'], shell=False) + env = None + if 'NOMS_SERVER' not in os.environ: + env = os.environ + env['NOMS_SERVER'] = 'http://localhost:8000' + subprocess.check_call(['npm', 'run', 'build'], env=env, shell=False) + + +if __name__ == "__main__": + main() diff --git a/clients/tagshow/datasetpicker.js b/clients/tagshow/datasetpicker.js index d8761c255a..9115d15a81 100644 --- a/clients/tagshow/datasetpicker.js +++ b/clients/tagshow/datasetpicker.js @@ -1,9 +1,9 @@ // @flow -import {invariant, readValue} from 'noms'; import eq from './eq.js'; import React from 'react'; import type {ChunkStore} from 'noms'; +import {invariant, NomsMap, readValue, Ref} from 'noms'; type DefaultProps = { selected: string @@ -37,10 +37,14 @@ export default class DatasetPicker extends React.Component { let store = props.store; let rootRef = await store.getRoot(); - let datasets = await readValue(rootRef, store); - invariant(datasets instanceof Map); + let datasets: NomsMap = await readValue(rootRef, store); + invariant(datasets); + let s = new Set(); + await datasets.forEach((v, k) => { + s.add(k); + }); this.setState({ - datasets: new Set(datasets.keys()) + datasets: s }); } diff --git a/clients/tagshow/main.js b/clients/tagshow/main.js index 6fb453f6cc..ea27035f0e 100644 --- a/clients/tagshow/main.js +++ b/clients/tagshow/main.js @@ -9,6 +9,11 @@ import type {ChunkStore} from 'noms'; window.onload = window.onhashchange = render; +const nomsServer: ?string = process.env.NOMS_SERVER; +if (!nomsServer) { + throw new Error('NOMS_SERVER not set'); +} + function updateQuery(qs: {[key: string]: string}) { location.hash = queryString.stringify(qs); } @@ -16,14 +21,6 @@ function updateQuery(qs: {[key: string]: string}) { function render() { let qs = Object.freeze(queryString.parse(location.hash)); let target = document.getElementById('root'); - - let nomsServer; - if (qs.server) { - nomsServer = qs.server; - } else { - nomsServer = `${location.protocol}//${location.hostname}:8000`; - } - let store: ChunkStore = new HttpStore(nomsServer); ReactDOM.render( diff --git a/clients/tagshow/photo.js b/clients/tagshow/photo.js index a6177506dc..68b0e7be8e 100644 --- a/clients/tagshow/photo.js +++ b/clients/tagshow/photo.js @@ -1,9 +1,9 @@ // @flow -import {readValue} from 'noms'; import eq from './eq.js'; import React from 'react'; -import type {ChunkStore, Ref, Struct} from 'noms'; +import type {ChunkStore, Ref, NomsMap, Struct} from 'noms'; +import {readValue} from 'noms'; type DefaultProps = { onLoad: () => void, @@ -41,11 +41,12 @@ export default class Photo extends React.Component { return size.get('Width') * size.get('Height'); } - let photo = await readValue(props.photoRef, props.store); + let photo: Struct = await readValue(props.photoRef, props.store); // Sizes is a Map(Size, String) where the string is a URL. let sizes = []; - photo.get('Sizes').forEach((url, size) => { + let s: NomsMap = photo.get('Sizes'); + await s.forEach((url, size) => { sizes.push({size, url}); }); sizes.sort((a, b) => area(a.size) - area(b.size)); @@ -72,9 +73,10 @@ export default class Photo extends React.Component { let sizes = this.state.sizes; let w = this.props.style.width || 0; let h = this.props.style.height || 0; - return sizes.find(({size}) => { + let size = sizes.find(({size}) => { return size.get('Width') >= w && size.get('Height') >= h; - }).url; + }); + return size ? size.url : sizes[sizes.length - 1].url; } } diff --git a/clients/tagshow/root.js b/clients/tagshow/root.js index 743445fb7f..e95ffe9331 100644 --- a/clients/tagshow/root.js +++ b/clients/tagshow/root.js @@ -1,12 +1,12 @@ // @flow -import {readValue} from 'noms'; import DatasetPicker from './datasetpicker.js'; import eq from './eq.js'; import React from 'react'; import SlideShow from './slideshow.js'; import TagChooser from './tagchooser.js'; -import type {ChunkStore, Ref} from 'noms'; +import type {ChunkStore} from 'noms'; +import {invariant, NomsMap, NomsSet, readValue, Ref, Struct} from 'noms'; type QueryStringObject = {[key: string]: string}; @@ -40,28 +40,37 @@ export default class Root extends React.Component { if (props.qs.ds) { let {store} = props; let rootRef = await props.store.getRoot(); - let datasets = await readValue(rootRef, props.store); - let commitRef = datasets.get(props.qs.ds); - let commit = await readValue(commitRef, store); + let datasets: NomsMap = await readValue(rootRef, props.store); + let commitRef = await datasets.get(props.qs.ds); + invariant(commitRef); + let commit: Struct = await readValue(commitRef, store); let v = commit.get('value'); - if (v instanceof Map) { + if (v instanceof NomsMap) { let seenRefs: Set = new Set(); - for (let [tag, value] of v) { + + let sets = []; + + await v.forEach((value, tag) => { tags.push(tag); - if (selectedTags.has(tag) && value instanceof Set) { - for (let r of value) { - let rs = r.toString(); - if (!seenRefs.has(rs)) { - seenRefs.add(rs); - selectedPhotos.push(r); - } - } + if (selectedTags.has(tag) && value instanceof NomsSet) { + sets.push(value); } + }); + + for (let s of sets) { + await s.forEach(r => { + let rs = r.toString(); + if (!seenRefs.has(rs)) { + seenRefs.add(rs); + selectedPhotos.push(r); + } + }); } + // This sorts the photos deterministically, by the ref // TODO: Sort by create date if it ends up that the common image type // has a create date. - selectedPhotos.sort((a, b) => a.compare(b)); + selectedPhotos.sort((a, b) => a.equals(b) ? 0 : a.less(b) ? -1 : 1); tags.sort(); }