From 442cc99324a154f15aa95e6a4b332dabacc16cd5 Mon Sep 17 00:00:00 2001 From: Adam Cox Date: Fri, 29 Dec 2023 22:21:31 -0600 Subject: [PATCH 01/40] consolidate all markdown pages into simpler structure --- ohmg/frontend/context_processors.py | 3 +- .../about-sanborn-maps.md} | 14 +++--- .../src/lib/About.svelte => pages/about.md} | 12 ++--- .../lib/Contact.svelte => pages/contact.md} | 18 ++++---- .../src/lib/FAQ.svelte => pages/faq.md} | 13 ++---- ohmg/frontend/pages/getting-started.md | 34 ++++++++++++++ ohmg/frontend/svelte/rollup.config.js | 1 + ohmg/frontend/svelte/src/entry/page.js | 6 +++ ohmg/frontend/svelte/src/lib/Index.svelte | 15 ------ .../MarkdownPage.svelte => Page.svelte} | 14 +++--- ohmg/frontend/templates/about.html | 9 ---- ohmg/frontend/templates/base.html | 2 +- ohmg/frontend/templates/page.html | 9 ++++ ohmg/frontend/urls.py | 32 ++++--------- ohmg/frontend/views.py | 46 +++++++++++++++---- requirements.txt | 2 +- 16 files changed, 129 insertions(+), 101 deletions(-) rename ohmg/frontend/{svelte/src/lib/FireInsuranceMaps.svelte => pages/about-sanborn-maps.md} (95%) rename ohmg/frontend/{svelte/src/lib/About.svelte => pages/about.md} (95%) rename ohmg/frontend/{svelte/src/lib/Contact.svelte => pages/contact.md} (52%) rename ohmg/frontend/{svelte/src/lib/FAQ.svelte => pages/faq.md} (95%) create mode 100644 ohmg/frontend/pages/getting-started.md create mode 100644 ohmg/frontend/svelte/src/entry/page.js rename ohmg/frontend/svelte/src/lib/{components/MarkdownPage.svelte => Page.svelte} (83%) delete mode 100644 ohmg/frontend/templates/about.html create mode 100644 ohmg/frontend/templates/page.html diff --git a/ohmg/frontend/context_processors.py b/ohmg/frontend/context_processors.py index d5390e1b..3e6d69c7 100644 --- a/ohmg/frontend/context_processors.py +++ b/ohmg/frontend/context_processors.py @@ -21,7 +21,8 @@ def loc_info(request): return { 'navbar_params': { 'USER': user_info - } + }, + 'footer_params': {}, } def general(request): diff --git a/ohmg/frontend/svelte/src/lib/FireInsuranceMaps.svelte b/ohmg/frontend/pages/about-sanborn-maps.md similarity index 95% rename from ohmg/frontend/svelte/src/lib/FireInsuranceMaps.svelte rename to ohmg/frontend/pages/about-sanborn-maps.md index 908f8d2f..e48f36b8 100644 --- a/ohmg/frontend/svelte/src/lib/FireInsuranceMaps.svelte +++ b/ohmg/frontend/pages/about-sanborn-maps.md @@ -1,7 +1,9 @@ - - - diff --git a/ohmg/frontend/svelte/src/lib/About.svelte b/ohmg/frontend/pages/about.md similarity index 95% rename from ohmg/frontend/svelte/src/lib/About.svelte rename to ohmg/frontend/pages/about.md index 0fed88cc..775cc93d 100644 --- a/ohmg/frontend/svelte/src/lib/About.svelte +++ b/ohmg/frontend/pages/about.md @@ -1,7 +1,8 @@ - - - diff --git a/ohmg/frontend/svelte/src/lib/Contact.svelte b/ohmg/frontend/pages/contact.md similarity index 52% rename from ohmg/frontend/svelte/src/lib/Contact.svelte rename to ohmg/frontend/pages/contact.md index be694c42..fc005e61 100644 --- a/ohmg/frontend/svelte/src/lib/Contact.svelte +++ b/ohmg/frontend/pages/contact.md @@ -1,14 +1,12 @@ - +
asdf + +
- +Bugs and technical discussion: [mradamcox/ohmg](https://github.com/mradamcox/ohmg) diff --git a/ohmg/frontend/svelte/src/lib/FAQ.svelte b/ohmg/frontend/pages/faq.md similarity index 95% rename from ohmg/frontend/svelte/src/lib/FAQ.svelte rename to ohmg/frontend/pages/faq.md index 8534c654..3cf80c0d 100644 --- a/ohmg/frontend/svelte/src/lib/FAQ.svelte +++ b/ohmg/frontend/pages/faq.md @@ -1,7 +1,8 @@ - - - diff --git a/ohmg/frontend/pages/getting-started.md b/ohmg/frontend/pages/getting-started.md new file mode 100644 index 00000000..775b4f4a --- /dev/null +++ b/ohmg/frontend/pages/getting-started.md @@ -0,0 +1,34 @@ +--- +page_title: Getting Started +header: Getting Started +--- + +There are a few different ways to interact with this platform, and this page will offer a quick overview for all of them, as well as links out to more detailed information. If you need any help, do not hesitate to get in touch. Thanks! + +## Finding and Viewing Maps + +**Search by Place** - Each fire insurance map atlas is attached to a locale, generally a city or town. Find your locale of interest by [searching the map](/browse/#map), and then go to the Viewer for that locale. You can also [search by place name](browse/#places), or [explore places as a hierarchy](/united-states) (this latter option works but is still in development). + +**Search by Item** - You can also [search all items](/browse/#items) individually, which is the quickest way to access the summary page for each one, showing its georeferencing progress. + +## Contributing Work + +Hooray! You've created an account and are ready to get started! The workflow is very structured and hierarchical, based on two levels of content: items (Sanborn map editions, or "volumes") and resources (pages or "sheets" within a given volume). + +The entry point for georeferencing is an item, so start by [finding an item](/browse#items), and going to its summary page. + +### Item-level management + +Here is a recommended approach for creating a mosaic from a given edition or volume. + +1. + +### Georeferencing Individual Resources + +T + +The system is organized with two high-level entities: Items and Places. Items are Sanborn map editions, or individual volumes of multi-part atlases, with a one-to-one relationship to items in the LOC collection. Each item is attached to one or more Places, the latter being a + + +Places are heirarchical geographical boundaries, state, county, city, etc.--and each Item is a Sanborn map edition or volume attached to one or more Places. + diff --git a/ohmg/frontend/svelte/rollup.config.js b/ohmg/frontend/svelte/rollup.config.js index 36db03a2..220be847 100644 --- a/ohmg/frontend/svelte/rollup.config.js +++ b/ohmg/frontend/svelte/rollup.config.js @@ -101,6 +101,7 @@ let exportable = []; "Split", "Viewer", "Volume", + "Page", ].forEach((d) => exportable.push(componentExportDetails(d))); export default exportable; diff --git a/ohmg/frontend/svelte/src/entry/page.js b/ohmg/frontend/svelte/src/entry/page.js new file mode 100644 index 00000000..b8de80f9 --- /dev/null +++ b/ohmg/frontend/svelte/src/entry/page.js @@ -0,0 +1,6 @@ +import Page from '../lib/Page.svelte'; + +export default new Page({ + target: document.getElementById("page-target"), + props: JSON.parse(document.getElementById("page-props").textContent), +}); \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/Index.svelte b/ohmg/frontend/svelte/src/lib/Index.svelte index cad9efed..6fe130d6 100644 --- a/ohmg/frontend/svelte/src/lib/Index.svelte +++ b/ohmg/frontend/svelte/src/lib/Index.svelte @@ -3,15 +3,10 @@ import '../css/shared.css' import Browse from './Browse.svelte' import Home from './Home.svelte' - import About from './About.svelte' - import FAQ from './FAQ.svelte' - import Contact from './Contact.svelte' import Profile from './Profile.svelte' import Participants from './Participants.svelte' import Place from './Place.svelte' - import GettingStarted from './GettingStarted.svelte' import Activity from './Activity.svelte' - import FireInsuranceMaps from './FireInsuranceMaps.svelte'; export let PAGE_NAME = ''; export let PARAMS = {}; @@ -33,16 +28,6 @@ VIEWER_SHOWCASE={PARAMS.VIEWER_SHOWCASE} PLACES_CT={PARAMS.PLACES_CT} ITEMS_CT={PARAMS.ITEMS_CT} /> -{:else if PAGE_NAME == 'about'} - -{:else if PAGE_NAME == 'about-sanborn-maps'} - -{:else if PAGE_NAME == 'faq'} - -{:else if PAGE_NAME == 'contact'} - -{:else if PAGE_NAME == 'getting-started'} - {:else if PAGE_NAME == 'profile'} - import '../../css/shared.css'; + import '../css/shared.css'; import SvelteMarkdown from 'svelte-markdown' - import TitleBar from './TitleBar.svelte'; + import TitleBar from './components/TitleBar.svelte'; - export let source = '*add your markdown here*' - export let title = '*add your title here*' - export let makeToc = true + export let source = '*add your markdown here*'; + export let HEADER = '*add your h1 here*'; + export let MAKE_TOC = true function slugify(str) { return str @@ -28,12 +28,12 @@
- +
- {#if makeToc} + {#if MAKE_TOC}
    diff --git a/ohmg/frontend/templates/about.html b/ohmg/frontend/templates/about.html deleted file mode 100644 index dbb0b651..00000000 --- a/ohmg/frontend/templates/about.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'base.html' %} -{% load i18n %} - -{% block title %}About{% endblock title %} - -{% block main_content %} -{{ browse_params|json_script:'about-props'}} -{% include '_svelte_component.html' with component_name='About' %} -{% endblock %} diff --git a/ohmg/frontend/templates/base.html b/ohmg/frontend/templates/base.html index bd665e72..a8db467b 100644 --- a/ohmg/frontend/templates/base.html +++ b/ohmg/frontend/templates/base.html @@ -95,7 +95,7 @@ {% endblock %} {% block footer %} - {{ navbar_params|json_script:'footer-props'}} + {{ footer_params|json_script:'footer-props'}} {% include '_svelte_component.html' with component_name='Footer' %} {% endblock footer %} diff --git a/ohmg/frontend/templates/page.html b/ohmg/frontend/templates/page.html new file mode 100644 index 00000000..a22151e1 --- /dev/null +++ b/ohmg/frontend/templates/page.html @@ -0,0 +1,9 @@ +{% extends 'base.html' %} +{% load i18n %} + +{% block title %}{% if params.PAGE_TITLE %}{{ params.PAGE_TITLE }} | {% endif %}{{ block.super }}{% endblock title %} + +{% block main_content %} +{{ params|json_script:'page-props'}} +{% include '_svelte_component.html' with component_name='Page' %} +{% endblock %} diff --git a/ohmg/frontend/urls.py b/ohmg/frontend/urls.py index 3cc97ca0..f2f18657 100644 --- a/ohmg/frontend/urls.py +++ b/ohmg/frontend/urls.py @@ -8,35 +8,21 @@ MRMEndpointList, MRMEndpointLayer, Browse, - BasicPage, + ActivityView, NewsList, NewsArticle, + Page, ) urlpatterns = [ path('', HomePage.as_view(), name='home'), path("robots.txt", TemplateView.as_view(template_name="robots.txt", content_type="text/plain")), - path('about/', BasicPage.as_view(), name='about', kwargs={ - "slug":"about", - "title":"About", - }), - path('about-sanborn-maps/', BasicPage.as_view(), name='about-sanborn-maps', kwargs={ - "slug":"about-sanborn-maps", - "title":"About Sanborn Maps", - }), - path('faq/', BasicPage.as_view(), name='faq', kwargs={ - "slug":"faq", - "title":"FAQ", - }), - path('contact/', BasicPage.as_view(), name='contact', kwargs={ - "slug":"contact", - "title":"Contact", - }), - # path('getting-started/', BasicPage.as_view(), name='faq', kwargs={"page_name":"getting-started"}), - path('activity/', BasicPage.as_view(), name='activity', kwargs={ - "slug":"activity", - "title": "Activity", - }), + path('about-sanborn-maps/', Page.as_view(), {"slug":"about-sanborn-maps"}), + path('about/', Page.as_view(), {"slug":"about"}), + path('contact/', Page.as_view(), {"slug":"contact"}), + path('faq/', Page.as_view(), {"slug":"faq"}), + path('getting-started/', Page.as_view(), {"slug":"getting-started"}), + path('activity/', ActivityView.as_view(), name='activity'), path('search/', Browse.as_view(), name='search'), path('browse/', RedirectView.as_view(pattern_name='search'), name='browse'), path('loc/volumes/', RedirectView.as_view(pattern_name='search', permanent=True), name='volumes_list'), @@ -45,5 +31,5 @@ path('mrm/', MRMEndpointList.as_view(), name="mrm_layer_list"), path('mrm//', MRMEndpointLayer.as_view(), name="mrm_get_resource"), path('news/', NewsList.as_view(), name="news"), - path('news//', NewsArticle.as_view(), name="article") + path('news//', NewsArticle.as_view(), name="article"), ] diff --git a/ohmg/frontend/views.py b/ohmg/frontend/views.py index e9c6b8bc..a2ee0a7f 100644 --- a/ohmg/frontend/views.py +++ b/ohmg/frontend/views.py @@ -3,6 +3,9 @@ import json import logging from datetime import datetime +from pathlib import Path + +import frontmatter from django.conf import settings from django.contrib.gis.geos import GEOSGeometry @@ -125,28 +128,51 @@ def get(self, request): context=context_dict ) -class BasicPage(View): +class ActivityView(View): - def get(self, request, slug, title): + def get(self, request): context_dict = { "params": { - "PAGE_TITLE": title, - "PAGE_NAME": slug, - "PARAMS": {} + "PAGE_TITLE": "Activity", + "PAGE_NAME": 'activity', + "PARAMS": { + "SESSION_API_URL": reverse("api-beta:session_list"), + "OHMG_API_KEY": settings.OHMG_API_KEY, + } } } - if slug == "activity": - context_dict['params']['PARAMS'].update({ - "SESSION_API_URL": reverse("api-beta:session_list"), - "OHMG_API_KEY": settings.OHMG_API_KEY, - }) return render( request, "index.html", context=context_dict ) + +class Page(View): + + def get(self, request, slug): + + md_path = Path(settings.PROJECT_DIR, 'frontend', 'pages', f"{slug}.md") + if not os.path.isfile(md_path): + raise Http404 + + post = frontmatter.load(md_path) + + context_dict = { + "params": { + "PAGE_TITLE": post['page_title'], + "HEADER": post['header'], + # downstream SvelteMarkdown requires this variable to be `source` + "source": post.content, + } + } + + return render( + request, + "page.html", + context=context_dict + ) class VolumeTrim(View): diff --git a/requirements.txt b/requirements.txt index 4dd4a197..785443b8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,7 +16,7 @@ django-ninja==0.21.0 psycopg2==2.9.5 pygments==2.14.0 - +python-frontmatter==1.0.1 python-dotenv==1.0.0 kombu==5.2.4 dj_database_url==1.2.0 From e74f43db429d25211c1ea5c6083106155e626ab5 Mon Sep 17 00:00:00 2001 From: Adam Cox Date: Fri, 29 Dec 2023 22:50:44 -0600 Subject: [PATCH 02/40] replace fullscreen with fake fullscreen --- ohmg/frontend/static/css/site_base.css | 8 ++++++++ ohmg/frontend/svelte/src/js/utils.js | 18 ----------------- .../svelte/src/lib/Georeference.svelte | 20 +++++++++++-------- ohmg/frontend/svelte/src/lib/Split.svelte | 13 +++++++----- .../src/lib/components/MultiTrim.svelte | 10 +--------- .../lib/components/VolumePreviewMap.svelte | 13 ++++++++---- 6 files changed, 38 insertions(+), 44 deletions(-) diff --git a/ohmg/frontend/static/css/site_base.css b/ohmg/frontend/static/css/site_base.css index 104efae3..31fc27d7 100644 --- a/ohmg/frontend/static/css/site_base.css +++ b/ohmg/frontend/static/css/site_base.css @@ -488,4 +488,12 @@ footer a:hover { } .alert-danger .alert-link { color: #843534; + } + + .ffs { + position: fixed !important; + width: 100%; + top: 60px; + height: calc(100vh - 60px) !important; + left: 0; } \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/js/utils.js b/ohmg/frontend/svelte/src/js/utils.js index 3dbd0aca..ab184c81 100644 --- a/ohmg/frontend/svelte/src/js/utils.js +++ b/ohmg/frontend/svelte/src/js/utils.js @@ -25,24 +25,6 @@ import MapboxVector from 'ol/layer/MapboxVector'; import Crop from 'ol-ext/filter/Crop'; import { extendFlatCoordinates } from 'ol/extent'; -export function toggleFullscreen (elementId) { - // https://www.w3schools.com/howto/howto_js_fullscreen.asp - const elem = document.getElementById(elementId) - if (document.fullscreenElement == null) { - if (elem.requestFullscreen) { - elem.requestFullscreen(); - } else if (elem.webkitRequestFullscreen) { /* Safari */ - elem.webkitRequestFullscreen(); - } else if (elem.msRequestFullscreen) { /* IE11 */ - elem.msRequestFullscreen(); - } - return true - } else { - document.exitFullscreen(); - return false - } -} - export function makeTitilerXYZUrl (options) { // options must be an object with the following properties: // { diff --git a/ohmg/frontend/svelte/src/lib/Georeference.svelte b/ohmg/frontend/svelte/src/lib/Georeference.svelte index 730dd57d..e1e048b5 100644 --- a/ohmg/frontend/svelte/src/lib/Georeference.svelte +++ b/ohmg/frontend/svelte/src/lib/Georeference.svelte @@ -47,7 +47,6 @@ import Snap from 'ol/interaction/Snap'; import Styles from '../js/ol-styles'; const styles = new Styles(); import { - toggleFullscreen, makeLayerGroupFromVolume, makeTitilerXYZUrl, makeBasemaps, @@ -127,7 +126,6 @@ setTimeout(promptRefresh, (SESSION_LENGTH*1000) - 15000) let autoRedirect; function promptRefresh() { if (!leaveOkay) { - if (document.fullscreenElement != null) { document.exitFullscreen(); } getModal('modal-expiration').open() leaveOkay = true; autoRedirect = setTimeout(cancelAndRedirectToDetail, 15000); @@ -734,9 +732,6 @@ $: { } } -let inFullscreen = false; - - const previewLayer = new TileLayer({ source: new XYZ(), zIndex: 20, @@ -839,7 +834,7 @@ function handleKeydown(e) { if (document.activeElement.id == "") { switch(e.key) { case "Escape": - if (document.fullscreenElement != null) { document.exitFullscreen(); } + handleFfs('map-container') break; case "d": case "D": removeActiveGCP(); @@ -928,6 +923,15 @@ const iconLinks = [ url: VOLUME.urls.summary, } ] + +let ffs = false +function handleFfs(elementId) { + ffs = !ffs + document.getElementById(elementId).classList.toggle('ffs'); + docView.map.updateSize(); + mapView.map.updateSize(); +} + {if (!leaveOkay) {confirmLeave()}}} on:unload={cleanup}/> @@ -1000,8 +1004,8 @@ const iconLinks = [ - - {#if n != PLACE.breadcrumbs.length-1} → {/if} - {/each} -
-
-
-

Locales

- {#if PLACE.descendants.length > 0} -
    - {#each PLACE.descendants as d} + +
    +
    + {#if PLACE.parents.length > 0} +

    Super-locale

    +
      + {#each PLACE.parents as d} +
    • + +
    • + {/each} +
    + {/if} +

    Sub-locales

    + only show those with maps + {#if PLACE.descendants.length > 0 && PLACE.descendants.filter(function (i) {return i.volume_count_inclusive != 0}).length > 0} +
      + {#each localeList as d}
    • {/each} @@ -79,10 +91,10 @@ $: sideLinks = PLACE.volumes.length > 0 ? [

      ---

      {/if}
    -
    -

    Items

    +
    +

    Maps

    {#if PLACE.volumes.length > 0} -
      +
        {#each PLACE.volumes as v}
      • {v.year}{#if v.volume_no} vol. {v.volume_no}{/if}
      • {/each} @@ -110,7 +122,8 @@ button:disabled { display:flex; flex-direction:row; flex-wrap: wrap; - margin-top: 5px; + padding: 10px 0px; + font-size: .95em; } .breadcrumbs-select-row select { /* min-width: 35px; */ @@ -123,4 +136,22 @@ button:disabled { .breadcrumbs-select-row select:disabled { cursor: default; } +.sub-list { + padding: 0; + list-style: none; + max-height: calc(100vh - 435px); + overflow-y: scroll; + background: #e9e9ed; + border: 1px solid #8f8f9d; + border-radius: 4px; +} +.sub-list li { + padding: 5px; +} +.sub-list li:nth-child(2n) { + background-color: #f6f6f6; +} +.sub-list li:nth-child(2n+1) { + background-color: #ffffff; +} diff --git a/ohmg/frontend/svelte/src/lib/Volume.svelte b/ohmg/frontend/svelte/src/lib/Volume.svelte index b4b264e4..b34d7bbd 100644 --- a/ohmg/frontend/svelte/src/lib/Volume.svelte +++ b/ohmg/frontend/svelte/src/lib/Volume.svelte @@ -15,7 +15,6 @@ import Trash from "phosphor-svelte/lib/Trash"; import {getCenter} from 'ol/extent'; import TitleBar from './components/TitleBar.svelte'; -import PlaceSelect from "./components/PlaceSelect.svelte"; import VolumePreviewMap from "./components/VolumePreviewMap.svelte"; import MultiTrim from "./components/MultiTrim.svelte"; import ConditionalDoubleChevron from './components/ConditionalDoubleChevron.svelte'; @@ -30,12 +29,18 @@ import SingleLayerViewer from './components/SingleLayerViewer.svelte'; import SingleDocumentViewer from './components/SingleDocumentViewer.svelte'; export let VOLUME; -export let OTHER_VOLUMES; export let CSRFTOKEN; export let USER_TYPE; export let MAPBOX_API_KEY; export let TITILER_HOST; +console.log(VOLUME.locale) + +let current_identifier = VOLUME.identifier +function goToItem(identifier) { + window.location = "/loc/" + current_identifier +} + $: sheetsLoading = VOLUME.status == "initializing..."; // This variable is used to trigger a reinit of the VolumePreviewMap component. @@ -247,16 +252,18 @@ let modalLyrExtent = "";

        - -
        -

        - {#each OTHER_VOLUMES as link, n} - {#if n != 0} • {/if} - {#if link.url}{link.display}{:else}{link.display}{/if} +

        + {#each VOLUME.locale.breadcrumbs as bc, n} + {bc.name}{#if n != VOLUME.locale.breadcrumbs.length-1} → {/if} + {/each} +  →  +
        +
        -
        -
        +
        +
        {#if PLACE.parents.length > 0}

        Super-locale

          @@ -75,9 +81,10 @@ $: sideLinks = PLACE.volumes.length > 0 ? [ {/each}
        {/if} + {#if PLACE.descendants.length > 0}

        Sub-locales

        - only show those with maps - {#if PLACE.descendants.length > 0 && PLACE.descendants.filter(function (i) {return i.volume_count_inclusive != 0}).length > 0} + + {#if localeList.length > 0}
          {#each localeList as d}
        • @@ -90,18 +97,13 @@ $: sideLinks = PLACE.volumes.length > 0 ? [ {:else}

          ---

          {/if} + {/if}
        -
        +

        Maps

        - {#if PLACE.volumes.length > 0} - - {:else} -

        ---

        - {/if} + {#each reinitList as key (key)} + + {/each}
        diff --git a/ohmg/frontend/svelte/src/lib/components/Volumes.svelte b/ohmg/frontend/svelte/src/lib/components/Volumes.svelte index 9c8825e1..a18116d7 100644 --- a/ohmg/frontend/svelte/src/lib/components/Volumes.svelte +++ b/ohmg/frontend/svelte/src/lib/components/Volumes.svelte @@ -3,44 +3,51 @@ import {TableSort} from 'svelte-tablesort' export let ITEM_API_URL; export let OHMG_API_KEY; +export let ALL_ITEMS = []; +export let PLACE_SLUG; +export let PLACE_INCLUSIVE = false; -let all_items = []; let filtered_items = []; let loading = true -const apiHeaders = { - 'X-API-Key': OHMG_API_KEY, -} - -fetch(ITEM_API_URL, { headers: apiHeaders }) - .then(response => response.json()) - .then(result => { - all_items = flatten_response(result); - filtered_items = all_items; - }); - -function flatten_response(items_json) { - const flattened = [] - items_json.forEach( function(item) { - item.loaded_by_name = item.loaded_by.username; - item.loaded_by_profile = item.loaded_by.profile_url; - item.unprepared_ct = item.stats.unprepared_ct; - item.prepared_ct = item.stats.prepared_ct; - item.georeferenced_ct = item.stats.georeferenced_ct; - item.percent = item.stats.percent; - item.mm_ct = item.stats.mm_todo; - item.mm_display = item.stats.mm_display; - item.mm_percent = item.stats.mm_percent; - flattened.push(item) - }) - loading = false - return flattened +let loadedOnly = true; +$: url = PLACE_SLUG ? `${ITEM_API_URL}?locale=${PLACE_SLUG}&locale_inclusive=${PLACE_INCLUSIVE}&loaded=${loadedOnly}` : `${ITEM_API_URL}?loaded=${loadedOnly}` +function handleFetch(url) { + const apiHeaders = { + 'X-API-Key': OHMG_API_KEY, + } + fetch(url, { headers: apiHeaders }) + .then(response => response.json()) + .then(result => { + ALL_ITEMS = flatten_response(result); + filtered_items = ALL_ITEMS; + }); + + function flatten_response(items_json) { + const flattened = [] + items_json.forEach( function(item) { + item.load_date = item.loaded_by ? item.load_date : "---"; + item.loaded_by_name = item.loaded_by ? item.loaded_by.username : "---"; + item.loaded_by_profile = item.loaded_by ? item.loaded_by.profile_url : ""; + item.unprepared_ct = item.stats.unprepared_ct; + item.prepared_ct = item.stats.prepared_ct; + item.georeferenced_ct = item.stats.georeferenced_ct; + item.percent = item.stats.percent; + item.mm_ct = item.stats.mm_todo; + item.mm_display = item.stats.mm_display; + item.mm_percent = item.stats.mm_percent; + flattened.push(item) + }) + loading = false + return flattened + } } +$: handleFetch(url) function updateFilteredList(filterText) { if (filterText && filterText.length > 0) { filtered_items = []; - all_items.forEach( function(vol) { + ALL_ITEMS.forEach( function(vol) { const volumeName = vol.title.toUpperCase(); const filterBy = filterText.toUpperCase(); if (volumeName.indexOf(filterBy) > -1) { @@ -48,7 +55,7 @@ function updateFilteredList(filterText) { } }); } else { - filtered_items = all_items; + filtered_items = ALL_ITEMS; } } let filterInput; @@ -56,7 +63,8 @@ $: updateFilteredList(filterInput)
        - + +
        {#if loading} @@ -89,7 +97,13 @@ $: updateFilteredList(filterInput) {v.year_vol} {v.sheet_ct} - {v.loaded_by_name} + + {#if v.loaded_by_name != "---" } + {v.loaded_by_name} + {:else} + {v.loaded_by_name} + {/if} + {v.load_date} {v.unprepared_ct} {v.prepared_ct} @@ -118,11 +132,8 @@ $: updateFilteredList(filterInput) diff --git a/ohmg/frontend/svelte/src/lib/Volume.svelte b/ohmg/frontend/svelte/src/lib/Volume.svelte index b34d7bbd..8e627cbc 100644 --- a/ohmg/frontend/svelte/src/lib/Volume.svelte +++ b/ohmg/frontend/svelte/src/lib/Volume.svelte @@ -8,6 +8,7 @@ import X from "phosphor-svelte/lib/X"; import Check from "phosphor-svelte/lib/Check"; import CropIcon from "phosphor-svelte/lib/Crop"; import Wrench from "phosphor-svelte/lib/Wrench"; +import ArrowRight from "phosphor-svelte/lib/ArrowRight"; import ArrowsClockwise from "phosphor-svelte/lib/ArrowsClockwise"; import ArrowSquareOut from "phosphor-svelte/lib/ArrowSquareOut"; import Trash from "phosphor-svelte/lib/Trash"; @@ -252,11 +253,11 @@ let modalLyrExtent = "";

        -
        +
        {#if loading} @@ -78,7 +78,7 @@ $: updateFilteredList(filterInput) {:else} - Item Title + Title Year Sheets Loaded by From 42f52cc045bb9237569819dae74f3170344a6a29 Mon Sep 17 00:00:00 2001 From: Adam Cox Date: Thu, 11 Jan 2024 09:47:11 -0600 Subject: [PATCH 23/40] use avatar in navbar --- ohmg/frontend/context_processors.py | 9 ++++----- .../static/icons/noun-house-2523121-FFFFFF.png | Bin 0 -> 108878 bytes ohmg/frontend/svelte/src/lib/Navbar.svelte | 10 ++++++---- 3 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 ohmg/frontend/static/icons/noun-house-2523121-FFFFFF.png diff --git a/ohmg/frontend/context_processors.py b/ohmg/frontend/context_processors.py index 3e6d69c7..cb388938 100644 --- a/ohmg/frontend/context_processors.py +++ b/ohmg/frontend/context_processors.py @@ -2,6 +2,8 @@ from django.contrib.sites.models import Site from ohmg.utils import full_reverse +from ohmg.accounts.schemas import UserSchema + def loc_info(request): try: @@ -9,11 +11,8 @@ def loc_info(request): except AttributeError: user = None if user and user.is_authenticated: - user_info = { - 'is_authenticated': True, - 'name': user.username, - 'profile': full_reverse("profile_detail", args=(user.username, )), - } + user_info = UserSchema.from_orm(user).dict() + user_info['is_authenticated'] = True else: user_info = { 'is_authenticated': False diff --git a/ohmg/frontend/static/icons/noun-house-2523121-FFFFFF.png b/ohmg/frontend/static/icons/noun-house-2523121-FFFFFF.png new file mode 100644 index 0000000000000000000000000000000000000000..15f70540e973c93226dc273dc182959b2449a2c6 GIT binary patch literal 108878 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 P664)lY0-SRw%7jyiSacn literal 0 HcmV?d00001 diff --git a/ohmg/frontend/svelte/src/lib/Navbar.svelte b/ohmg/frontend/svelte/src/lib/Navbar.svelte index 35899689..c70992fd 100644 --- a/ohmg/frontend/svelte/src/lib/Navbar.svelte +++ b/ohmg/frontend/svelte/src/lib/Navbar.svelte @@ -68,7 +68,7 @@ let subMenus = { "links": [ { "title": "My Profile", - "href": USER.profile, + "href": USER.profile_url, "external": false, }, { @@ -110,8 +110,8 @@ function clickOutside(node, { enabled: initialEnabled, cb }) {
      - {:else} + {:else if userCanAccess} @@ -381,7 +383,7 @@ let modalLyrExtent = "";
    • georeferencing in progress...
    • {document.lock_details.user.name}
    - {:else} + {:else if userCanAccess}
    • georeference →
    • @@ -407,8 +409,8 @@ let modalLyrExtent = "";
      {#if VOLUME.items.layers.length > 0 && !settingKeyMapLayer} {/if} {#if settingKeyMapLayer} @@ -440,7 +442,7 @@ let modalLyrExtent = "";
    • session in progress...
    • {layer.lock.username}
    - {:else} + {:else if userCanAccess}
    • edit georeferencing →
    • downloads & web services →
    • @@ -481,7 +483,7 @@ let modalLyrExtent = "";
      @@ -504,11 +506,13 @@ let modalLyrExtent = ""; {nonmap.title} + {#if userCanAccess}
      + {/if}
    {/each}
    diff --git a/ohmg/frontend/svelte/src/lib/components/MultiTrim.svelte b/ohmg/frontend/svelte/src/lib/components/MultiTrim.svelte index e49dae14..86ee35f1 100644 --- a/ohmg/frontend/svelte/src/lib/components/MultiTrim.svelte +++ b/ohmg/frontend/svelte/src/lib/components/MultiTrim.svelte @@ -46,9 +46,8 @@ const styles = new Styles(); import {makeTitilerXYZUrl, makeBasemaps} from '../../js/utils'; export let VOLUME; -// export let SESSION_LENGTH; export let CSRFTOKEN; -export let USER_TYPE; +export let DISABLED; export let MAPBOX_API_KEY; export let TITILER_HOST; @@ -283,8 +282,8 @@ $: { } function submitMultiMask() { - if (USER_TYPE == "anonymous") { - window.alert("You must be signed to save"); + if (DISABLED) { + window.alert("You do not edit permissions for this multimask."); return } let multiMask = {} @@ -418,7 +417,7 @@ function handleFfs(elementId) { -{#if USER_TYPE == "anonymous"}

    Feel free to mess around; you can't save changes unless you are logged in.

    {/if} +{#if DISABLED}

    Feel free to mess around; you can't save changes unless you are logged in.

    {/if}
    @@ -476,10 +475,10 @@ function handleFfs(elementId) {
    - -
    diff --git a/ohmg/frontend/svelte/src/lib/components/buttons/NavDropdown.svelte b/ohmg/frontend/svelte/src/lib/components/buttons/NavDropdown.svelte index 4801baf1..cb0ba826 100644 --- a/ohmg/frontend/svelte/src/lib/components/buttons/NavDropdown.svelte +++ b/ohmg/frontend/svelte/src/lib/components/buttons/NavDropdown.svelte @@ -10,7 +10,11 @@ diff --git a/ohmg/frontend/svelte/src/lib/components/modals/Base.svelte b/ohmg/frontend/svelte/src/lib/components/modals/Base.svelte index 5cff7b2c..f7e79816 100644 --- a/ohmg/frontend/svelte/src/lib/components/modals/Base.svelte +++ b/ohmg/frontend/svelte/src/lib/components/modals/Base.svelte @@ -57,8 +57,6 @@ function close(retVal){ //expose the API modals[id]={open,close} - -console.log(modals) onDestroy(()=>{ delete modals[id] diff --git a/ohmg/loc_insurancemaps/management/commands/volume.py b/ohmg/loc_insurancemaps/management/commands/volume.py index b56c7975..11d02957 100644 --- a/ohmg/loc_insurancemaps/management/commands/volume.py +++ b/ohmg/loc_insurancemaps/management/commands/volume.py @@ -72,6 +72,15 @@ def add_arguments(self, parser): "--locale", help="slug for the Place to attach to this volume" ) + parser.add_argument( + "--sponsor", + help="username of sponsor for this volume" + ) + parser.add_argument( + "--access", + default="any", + help="username of sponsor for this volume" + ) parser.add_argument( "--all", help="apply to all volumes", @@ -91,6 +100,10 @@ def handle(self, *args, **options): username = "admin" user = get_user_model().objects.get(username=username) + sponsor = None + if options['sponsor']: + sponsor = get_user_model().objects.get(username=options['sponsor']) + i = options['identifier'] if options['operation'] == "refresh-lookups": if i is not None: @@ -143,6 +156,10 @@ def get_locale(locale_slug): locale=locale, dry_run=options['dry_run'] ) + if vol: + vol.access = options['access'] + vol.sponsor = sponsor + vol.save() print(vol) if options['operation'] == "remove": diff --git a/ohmg/loc_insurancemaps/migrations/0004_auto_20240116_1016.py b/ohmg/loc_insurancemaps/migrations/0004_auto_20240116_1016.py new file mode 100644 index 00000000..e4cfdc9b --- /dev/null +++ b/ohmg/loc_insurancemaps/migrations/0004_auto_20240116_1016.py @@ -0,0 +1,36 @@ +# Generated by Django 3.2.18 on 2024-01-16 10:16 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('loc_insurancemaps', '0003_volume_mosaic_preference'), + ] + + operations = [ + migrations.AddField( + model_name='volume', + name='access', + field=models.CharField(choices=[('none', 'none'), ('sponsor', 'sponsor'), ('any', 'any')], default='any', max_length=50), + ), + migrations.AddField( + model_name='volume', + name='sponsor', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='sponsor', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='volume', + name='loaded_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='loaded_by', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='volume', + name='status', + field=models.CharField(choices=[('not started', 'not started'), ('initializing...', 'initializing...'), ('ready', 'ready')], default='not started', max_length=50), + ), + ] diff --git a/ohmg/loc_insurancemaps/models.py b/ohmg/loc_insurancemaps/models.py index 3adfdda8..3053608b 100644 --- a/ohmg/loc_insurancemaps/models.py +++ b/ohmg/loc_insurancemaps/models.py @@ -194,8 +194,12 @@ class Volume(models.Model): STATUS_CHOICES = ( ("not started", "not started"), ("initializing...", "initializing..."), - ("started", "started"), - ("all georeferenced", "all georeferenced"), + ("ready", "ready"), + ) + ACCESS_CHOICES = ( + ("none", "none"), + ("sponsor", "sponsor"), + ("any", "any"), ) identifier = models.CharField(max_length=100, primary_key=True) @@ -217,7 +221,9 @@ class Volume(models.Model): settings.AUTH_USER_MODEL, blank=True, null=True, - on_delete=models.CASCADE) + on_delete=models.CASCADE, + related_name="loaded_by" + ) load_date = models.DateTimeField(null=True, blank=True) # DEPRECATE: marking this field for removal ordered_layers = models.JSONField( @@ -267,6 +273,18 @@ class Volume(models.Model): blank=True, srid=4326, ) + access = models.CharField( + max_length=50, + choices=ACCESS_CHOICES, + default="any" + ) + sponsor = models.ForeignKey( + settings.AUTH_USER_MODEL, + blank=True, + null=True, + on_delete=models.PROTECT, + related_name="sponsor", + ) def __str__(self): display_str = f"{self.city}, {STATE_ABBREV[self.state]} | {self.year}" @@ -360,7 +378,7 @@ def load_sheet_docs(self, force_reload=False): for sheet in self.sheets: if sheet.doc is None or sheet.doc.file is None or force_reload: sheet.load_doc(self.loaded_by) - self.update_status("started") + self.update_status("ready") self.refresh_lookups() def remove_sheets(self): @@ -663,6 +681,8 @@ def serialize(self, include_session_info=False): "extent": self.extent.extent if self.extent else None, "locale": self.get_locale(serialized=True), "mosaic_preference": self.mosaic_preference, + "sponsor": self.sponsor.username if self.sponsor else None, + "access": self.access, } if include_session_info: From e5e2a937d675f6cc71b8f423c227353590d0da07 Mon Sep 17 00:00:00 2001 From: Adam Cox Date: Tue, 16 Jan 2024 23:42:12 -0600 Subject: [PATCH 29/40] implement import aliases --- ohmg/frontend/svelte/package.json | 1 + ohmg/frontend/svelte/pnpm-lock.yaml | 23 +++++++++++++++++++++-- ohmg/frontend/svelte/rollup.config.js | 26 +++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/ohmg/frontend/svelte/package.json b/ohmg/frontend/svelte/package.json index 8e412410..e5aa116b 100644 --- a/ohmg/frontend/svelte/package.json +++ b/ohmg/frontend/svelte/package.json @@ -22,6 +22,7 @@ }, "dependencies": { "@petamoriken/float16": "3.4.7", + "@rollup/plugin-alias": "^5.1.0", "ol": "^6.15.1", "ol-ext": "^3.2.28", "ol-hashed": "^2.1.0", diff --git a/ohmg/frontend/svelte/pnpm-lock.yaml b/ohmg/frontend/svelte/pnpm-lock.yaml index c91dd28c..f75607c8 100644 --- a/ohmg/frontend/svelte/pnpm-lock.yaml +++ b/ohmg/frontend/svelte/pnpm-lock.yaml @@ -8,6 +8,9 @@ dependencies: '@petamoriken/float16': specifier: 3.4.7 version: 3.4.7 + '@rollup/plugin-alias': + specifier: ^5.1.0 + version: 5.1.0(rollup@2.79.1) ol: specifier: ^6.15.1 version: 6.15.1 @@ -441,6 +444,19 @@ packages: resolution: {integrity: sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==} dev: false + /@rollup/plugin-alias@5.1.0(rollup@2.79.1): + resolution: {integrity: sha512-lpA3RZ9PdIG7qqhEfv79tBffNaoDuukFDrmhLqg9ifv99u/ehn+lOg30x2zmhf8AQqQUZaMk/B9fZraQ6/acDQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + rollup: 2.79.1 + slash: 4.0.0 + dev: false + /@rollup/plugin-commonjs@16.0.0(rollup@2.79.1): resolution: {integrity: sha512-LuNyypCP3msCGVQJ7ki8PqYdpjfEkE/xtFa5DqlF+7IBD0JsfMZ87C58heSwIMint58sAUZbt3ITqOmdQv/dXw==} engines: {node: '>= 8.0.0'} @@ -985,7 +1001,6 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true - dev: true optional: true /function-bind@1.1.2: @@ -1666,7 +1681,6 @@ packages: hasBin: true optionalDependencies: fsevents: 2.3.3 - dev: true /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -1749,6 +1763,11 @@ packages: totalist: 1.1.0 dev: false + /slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: false + /sort-asc@0.1.0: resolution: {integrity: sha512-jBgdDd+rQ+HkZF2/OHCmace5dvpos/aWQpcxuyRs9QUbPRnkEJmYVo81PIGpjIdpOcsnJ4rGjStfDHsbn+UVyw==} engines: {node: '>=0.10.0'} diff --git a/ohmg/frontend/svelte/rollup.config.js b/ohmg/frontend/svelte/rollup.config.js index 220be847..201b814f 100644 --- a/ohmg/frontend/svelte/rollup.config.js +++ b/ohmg/frontend/svelte/rollup.config.js @@ -4,6 +4,8 @@ import resolve from '@rollup/plugin-node-resolve'; import livereload from 'rollup-plugin-livereload'; import { terser } from 'rollup-plugin-terser'; import css from 'rollup-plugin-css-only'; +import alias from '@rollup/plugin-alias'; +import path from "path"; const production = !process.env.ROLLUP_WATCH; @@ -30,7 +32,7 @@ function serve() { function componentExportDetails(componentName) { return { - input: `src/entry/${componentName.toLowerCase()}.js`, + input: `src/${componentName.toLowerCase()}.js`, output: { sourcemap: true, format: 'iife', @@ -39,6 +41,28 @@ function componentExportDetails(componentName) { inlineDynamicImports: true, }, plugins: [ + alias({ + /** + * For custom files extension you might want to add "customerResolver" + * https://github.com/rollup/plugins/tree/master/packages/alias#custom-resolvers + * + * By doing that this plugin can read different kind of files. + */ + entries: [{ + find: "@src", + replacement: path.resolve(__dirname, "src"), + }, + { + find: "@helpers", + replacement: path.resolve(__dirname, "src/helpers"), + }, + { + find: "@components", + replacement: path.resolve(__dirname, "src/lib/components"), + }, + ], + }), + svelte({ compilerOptions: { // enable run-time checks when not in production From 2b5b3ec8e4baa423b925f5ff1b64d433a5f32902 Mon Sep 17 00:00:00 2001 From: Adam Cox Date: Tue, 16 Jan 2024 23:43:05 -0600 Subject: [PATCH 30/40] big refactor to begin unifying components --- .../frontend/svelte/src/{entry => }/footer.js | 2 +- .../svelte/src/{entry => }/georeference.js | 6 +- .../svelte/src/{js => helpers}/ol-styles.js | 0 .../svelte/src/{js => helpers}/utils.js | 7 + ohmg/frontend/svelte/src/{entry => }/index.js | 2 +- ohmg/frontend/svelte/src/lib/Activity.svelte | 4 +- ohmg/frontend/svelte/src/lib/Browse.svelte | 10 +- .../svelte/src/lib/Georeference.svelte | 1175 +---------------- .../svelte/src/lib/GettingStarted.svelte | 60 - ohmg/frontend/svelte/src/lib/Home.svelte | 8 +- ohmg/frontend/svelte/src/lib/Index.svelte | 2 +- ohmg/frontend/svelte/src/lib/Page.svelte | 4 +- .../svelte/src/lib/Participants.svelte | 2 +- ohmg/frontend/svelte/src/lib/Place.svelte | 8 +- ohmg/frontend/svelte/src/lib/Profile.svelte | 6 +- ohmg/frontend/svelte/src/lib/Resource.svelte | 14 +- ohmg/frontend/svelte/src/lib/Split.svelte | 518 +------- ohmg/frontend/svelte/src/lib/Volume.svelte | 64 +- .../svelte/src/lib/components/Modal.svelte | 100 -- .../src/lib/components/SessionList.svelte | 2 +- .../lib/components/VolumePreviewMap.svelte | 241 ---- .../{InfoButton.svelte => LiteButton.svelte} | 9 +- .../lib/components/buttons/NavDropdown.svelte | 2 +- .../lib/components/buttons/OpenModal.svelte | 3 + .../buttons/PaginationButtons.svelte | 2 +- .../interfaces/Georeferencer.svelte | 1112 ++++++++++++++++ .../interfaces/ItemPreviewMap.svelte | 197 +++ .../MultiMask.svelte} | 38 +- .../interfaces/PlaceViewer.svelte} | 8 +- .../SingleDocumentViewer.svelte | 11 +- .../{ => interfaces}/SingleLayerViewer.svelte | 14 +- .../lib/components/interfaces/Splitter.svelte | 461 +++++++ .../buttons/BasemapToggleButton.svelte | 11 + .../interfaces/buttons/ExpandElement.svelte | 34 + .../buttons/FullExtentButton.svelte | 11 + .../interfaces/buttons/OpenModalButton.svelte | 12 + .../interfaces/modals/LegendModal.svelte | 11 + .../src/lib/components/modals/Base.svelte | 4 +- .../modals/DocumentViewerModal.svelte | 2 +- .../{Volumes.svelte => search/Items.svelte} | 0 .../components/{ => search}/MapBrowse.svelte | 2 +- .../lib/components/{ => search}/Places.svelte | 0 .../ConditionalDoubleChevron.svelte | 0 .../lib/{ => components/shared}/Footer.svelte | 2 +- .../lib/{ => components/shared}/Navbar.svelte | 5 +- .../components/{ => shared}/TitleBar.svelte | 2 +- .../frontend/svelte/src/{entry => }/navbar.js | 2 +- ohmg/frontend/svelte/src/{entry => }/page.js | 2 +- .../svelte/src/{entry => }/resource.js | 4 +- ohmg/frontend/svelte/src/{entry => }/split.js | 6 +- .../frontend/svelte/src/{entry => }/viewer.js | 4 +- .../frontend/svelte/src/{entry => }/volume.js | 8 +- 52 files changed, 2057 insertions(+), 2157 deletions(-) rename ohmg/frontend/svelte/src/{entry => }/footer.js (76%) rename ohmg/frontend/svelte/src/{entry => }/georeference.js (60%) rename ohmg/frontend/svelte/src/{js => helpers}/ol-styles.js (100%) rename ohmg/frontend/svelte/src/{js => helpers}/utils.js (97%) rename ohmg/frontend/svelte/src/{entry => }/index.js (79%) delete mode 100644 ohmg/frontend/svelte/src/lib/GettingStarted.svelte delete mode 100644 ohmg/frontend/svelte/src/lib/components/Modal.svelte delete mode 100644 ohmg/frontend/svelte/src/lib/components/VolumePreviewMap.svelte rename ohmg/frontend/svelte/src/lib/components/buttons/{InfoButton.svelte => LiteButton.svelte} (65%) create mode 100644 ohmg/frontend/svelte/src/lib/components/interfaces/Georeferencer.svelte create mode 100644 ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte rename ohmg/frontend/svelte/src/lib/components/{MultiTrim.svelte => interfaces/MultiMask.svelte} (92%) rename ohmg/frontend/svelte/src/lib/{Viewer.svelte => components/interfaces/PlaceViewer.svelte} (99%) rename ohmg/frontend/svelte/src/lib/components/{ => interfaces}/SingleDocumentViewer.svelte (95%) rename ohmg/frontend/svelte/src/lib/components/{ => interfaces}/SingleLayerViewer.svelte (93%) create mode 100644 ohmg/frontend/svelte/src/lib/components/interfaces/Splitter.svelte create mode 100644 ohmg/frontend/svelte/src/lib/components/interfaces/buttons/BasemapToggleButton.svelte create mode 100644 ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte create mode 100644 ohmg/frontend/svelte/src/lib/components/interfaces/buttons/FullExtentButton.svelte create mode 100644 ohmg/frontend/svelte/src/lib/components/interfaces/buttons/OpenModalButton.svelte create mode 100644 ohmg/frontend/svelte/src/lib/components/interfaces/modals/LegendModal.svelte rename ohmg/frontend/svelte/src/lib/components/{Volumes.svelte => search/Items.svelte} (100%) rename ohmg/frontend/svelte/src/lib/components/{ => search}/MapBrowse.svelte (99%) rename ohmg/frontend/svelte/src/lib/components/{ => search}/Places.svelte (100%) rename ohmg/frontend/svelte/src/lib/components/{ => shared}/ConditionalDoubleChevron.svelte (100%) rename ohmg/frontend/svelte/src/lib/{ => components/shared}/Footer.svelte (97%) rename ohmg/frontend/svelte/src/lib/{ => components/shared}/Navbar.svelte (96%) rename ohmg/frontend/svelte/src/lib/components/{ => shared}/TitleBar.svelte (98%) rename ohmg/frontend/svelte/src/{entry => }/navbar.js (76%) rename ohmg/frontend/svelte/src/{entry => }/page.js (78%) rename ohmg/frontend/svelte/src/{entry => }/resource.js (68%) rename ohmg/frontend/svelte/src/{entry => }/split.js (60%) rename ohmg/frontend/svelte/src/{entry => }/viewer.js (59%) rename ohmg/frontend/svelte/src/{entry => }/volume.js (55%) diff --git a/ohmg/frontend/svelte/src/entry/footer.js b/ohmg/frontend/svelte/src/footer.js similarity index 76% rename from ohmg/frontend/svelte/src/entry/footer.js rename to ohmg/frontend/svelte/src/footer.js index 78050a71..2bfcc7e6 100644 --- a/ohmg/frontend/svelte/src/entry/footer.js +++ b/ohmg/frontend/svelte/src/footer.js @@ -1,4 +1,4 @@ -import Footer from '../lib/Footer.svelte'; +import Footer from '@components/shared/Footer.svelte'; const footer = new Footer({ target: document.getElementById("footer-target"), diff --git a/ohmg/frontend/svelte/src/entry/georeference.js b/ohmg/frontend/svelte/src/georeference.js similarity index 60% rename from ohmg/frontend/svelte/src/entry/georeference.js rename to ohmg/frontend/svelte/src/georeference.js index 4cb26eb4..ac9ed0f3 100644 --- a/ohmg/frontend/svelte/src/entry/georeference.js +++ b/ohmg/frontend/svelte/src/georeference.js @@ -1,6 +1,6 @@ -import '../css/interface.css'; -import Georeference from '../lib/Georeference.svelte'; -import '../css/ol-overrides.css' +import '@src/css/interface.css'; +import Georeference from '@src/lib/Georeference.svelte'; +import '@src/css/ol-overrides.css' const app = new Georeference({ target: document.getElementById("georeference-target"), diff --git a/ohmg/frontend/svelte/src/js/ol-styles.js b/ohmg/frontend/svelte/src/helpers/ol-styles.js similarity index 100% rename from ohmg/frontend/svelte/src/js/ol-styles.js rename to ohmg/frontend/svelte/src/helpers/ol-styles.js diff --git a/ohmg/frontend/svelte/src/js/utils.js b/ohmg/frontend/svelte/src/helpers/utils.js similarity index 97% rename from ohmg/frontend/svelte/src/js/utils.js rename to ohmg/frontend/svelte/src/helpers/utils.js index ab184c81..62aa9e5b 100644 --- a/ohmg/frontend/svelte/src/js/utils.js +++ b/ohmg/frontend/svelte/src/helpers/utils.js @@ -255,4 +255,11 @@ export function removeRotateCenter (layer) { // just inherit color I think. export const iconProps = { weight: 'bold', +} + +export function setMapExtent(map, extent4326) { + if (map) { + const extent3857 = transformExtent(extent4326, "EPSG:4326", "EPSG:3857"); + map.getView().fit(extent3857); + } } \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/entry/index.js b/ohmg/frontend/svelte/src/index.js similarity index 79% rename from ohmg/frontend/svelte/src/entry/index.js rename to ohmg/frontend/svelte/src/index.js index bce7a0ef..d1723bc3 100644 --- a/ohmg/frontend/svelte/src/entry/index.js +++ b/ohmg/frontend/svelte/src/index.js @@ -1,4 +1,4 @@ -import Index from '../lib/Index.svelte'; +import Index from '@src/lib/Index.svelte'; const app = new Index({ target: document.getElementById("index-target"), diff --git a/ohmg/frontend/svelte/src/lib/Activity.svelte b/ohmg/frontend/svelte/src/lib/Activity.svelte index 97db8755..19cbde68 100644 --- a/ohmg/frontend/svelte/src/lib/Activity.svelte +++ b/ohmg/frontend/svelte/src/lib/Activity.svelte @@ -1,6 +1,6 @@ - {if (!leaveOkay) {confirmLeave()}}} on:unload={cleanup}/> - -

    Create 3 or more ground control points to georeference this document. To create a ground control point, first click on a location in the left panel, then find and click on the corresponding location in right panel. Learn more

    - - -

    This georeferencing session is expiring, and will be cancelled soon.

    - -
    - -

    Feel free to experiment with the interface, but submit your work you must - sign in or - sign up. -

    -
    - -

    Are you sure you want to cancel this session?

    - - -
    - -
    - {#if disableInterface} -
    - -
    - {/if} - -
    -
    -
    -
    -
    - {#if showLayerPanel} - - {/if} - {#if showSettingsPanel} - - {/if} - {#if showNotePanel} - - {/if} - -
    -
    - + diff --git a/ohmg/frontend/svelte/src/lib/GettingStarted.svelte b/ohmg/frontend/svelte/src/lib/GettingStarted.svelte deleted file mode 100644 index 08db9a46..00000000 --- a/ohmg/frontend/svelte/src/lib/GettingStarted.svelte +++ /dev/null @@ -1,60 +0,0 @@ - - -
    - - -

    Collaborations

    -
    - -
    - OHM is an OpenStreetMap-inspired project, where contributors can add historical features from anywhere in the world. Any georeferenced historical maps on OldInsuranceMaps.net can be easily integrated as basemaps in the OHM editor, so that features can be digitized directly from them. -
    -
    -
    - - diff --git a/ohmg/frontend/svelte/src/lib/Home.svelte b/ohmg/frontend/svelte/src/lib/Home.svelte index c3189c86..47143cb1 100644 --- a/ohmg/frontend/svelte/src/lib/Home.svelte +++ b/ohmg/frontend/svelte/src/lib/Home.svelte @@ -2,13 +2,13 @@ import SvelteMarkdown from 'svelte-markdown' import IconContext from 'phosphor-svelte/lib/IconContext'; -import { iconProps } from "../js/utils" +import { iconProps } from "@helpers/utils" import ArrowSquareOut from 'phosphor-svelte/lib/ArrowSquareOut' -import MapBrowse from './components/MapBrowse.svelte'; -import LatestAdditions from './components/LatestAdditions.svelte'; +import MapBrowse from '@components/search/MapBrowse.svelte'; +import LatestAdditions from '@components/LatestAdditions.svelte'; -import SessionList from './components/SessionList.svelte' +import SessionList from '@components/SessionList.svelte' export let ITEM_API_URL; export let SESSION_API_URL; diff --git a/ohmg/frontend/svelte/src/lib/Index.svelte b/ohmg/frontend/svelte/src/lib/Index.svelte index 0461b756..e9a12ecc 100644 --- a/ohmg/frontend/svelte/src/lib/Index.svelte +++ b/ohmg/frontend/svelte/src/lib/Index.svelte @@ -1,6 +1,6 @@ - {if (!leaveOkay) {confirmLeave()}}} on:unload={cleanup}/> - - -

    This preparation session is expiring, and will be cancelled soon.

    - -
    - - -

    Feel free to experiment with the interface, but submit your work you must - sign in or - sign up. -

    -
    - - -

    This document has already been prepared!

    -
    - -

    Are you sure you want to cancel this session?

    - - -
    -

    {currentTxt} Learn more

    -
    - {#if disableInterface} -
    - -
    - {/if} - -
    -
    -
    -
    -
    \ No newline at end of file + diff --git a/ohmg/frontend/svelte/src/lib/Volume.svelte b/ohmg/frontend/svelte/src/lib/Volume.svelte index 0d69445e..b61ba7bf 100644 --- a/ohmg/frontend/svelte/src/lib/Volume.svelte +++ b/ohmg/frontend/svelte/src/lib/Volume.svelte @@ -2,7 +2,7 @@ import { slide } from 'svelte/transition'; import IconContext from 'phosphor-svelte/lib/IconContext'; -import { iconProps } from "../js/utils" +import { iconProps, makeTitilerXYZUrl } from "@helpers/utils" import Wrench from "phosphor-svelte/lib/Wrench"; import ArrowRight from "phosphor-svelte/lib/ArrowRight"; @@ -11,29 +11,26 @@ import ArrowSquareOut from "phosphor-svelte/lib/ArrowSquareOut"; import {getCenter} from 'ol/extent'; -import TitleBar from './components/TitleBar.svelte'; -import VolumePreviewMap from "./components/VolumePreviewMap.svelte"; -import MultiTrim from "./components/MultiTrim.svelte"; -import ConditionalDoubleChevron from './components/ConditionalDoubleChevron.svelte'; +import TitleBar from '@components/shared/TitleBar.svelte'; +import MultiMask from "@components/interfaces/MultiMask.svelte"; +import ConditionalDoubleChevron from '@components/shared/ConditionalDoubleChevron.svelte'; -import ItemPreviewMapModal from './components/modals/ItemPreviewMapModal.svelte' -import GeoreferenceOverviewModal from './components/modals/GeoreferenceOverviewModal.svelte' -import UnpreparedSectionModal from './components/modals/UnpreparedSectionModal.svelte' -import PreparedSectionModal from './components/modals/PreparedSectionModal.svelte' -import GeoreferencedSectionModal from './components/modals/GeoreferencedSectionModal.svelte' -import MultiMaskModal from './components/modals/MultiMaskModal.svelte' -import NonMapContentModal from './components/modals/NonMapContentModal.svelte' -import DocumentViewerModal from './components/modals/DocumentViewerModal.svelte' -import LayerViewerModal from './components/modals/LayerViewerModal.svelte' +import ItemPreviewMapModal from '@components/modals/ItemPreviewMapModal.svelte' +import GeoreferenceOverviewModal from '@components/modals/GeoreferenceOverviewModal.svelte' +import UnpreparedSectionModal from '@components/modals/UnpreparedSectionModal.svelte' +import PreparedSectionModal from '@components/modals/PreparedSectionModal.svelte' +import GeoreferencedSectionModal from '@components/modals/GeoreferencedSectionModal.svelte' +import MultiMaskModal from '@components/modals/MultiMaskModal.svelte' +import NonMapContentModal from '@components/modals/NonMapContentModal.svelte' -import Modal, {getModal} from './components/modals/Base.svelte'; +import Modal, {getModal} from '@components/modals/Base.svelte'; -import OpenModal from './components/buttons/OpenModal.svelte'; +import OpenModal from '@components/buttons/OpenModal.svelte'; -import {makeTitilerXYZUrl} from '../js/utils'; - -import SingleLayerViewer from './components/SingleLayerViewer.svelte'; -import SingleDocumentViewer from './components/SingleDocumentViewer.svelte'; +import ItemPreviewMap from "@components/interfaces/ItemPreviewMap.svelte"; +import SingleLayerViewer from '@components/interfaces/SingleLayerViewer.svelte'; +import SingleDocumentViewer from '@components/interfaces/SingleDocumentViewer.svelte'; + import LiteButton from './components/buttons/LiteButton.svelte'; export let VOLUME; export let CSRFTOKEN; @@ -50,7 +47,7 @@ function goToItem(identifier) { $: sheetsLoading = VOLUME.status == "initializing..."; -// This variable is used to trigger a reinit of the VolumePreviewMap component. +// This variable is used to trigger a reinit of the ItemPreviewMap component. // See https://svelte.dev/repl/65c80083b515477784d8128c3655edac?version=3.24.1 let reinitMap = [{}] @@ -117,7 +114,7 @@ function postOperation(operation) { }) .then(response => response.json()) .then(result => { - // trigger a reinit of the VolumePreviewMap component + // trigger a reinit of the ItemPreviewMap component if (operation == "set-index-layers" || VOLUME.items.layers.length != result.items.layers.length) { reinitMap = [{}]; } @@ -230,7 +227,7 @@ let modalLyrExtent = ""; {/each} - +
    {/if} @@ -260,7 +257,12 @@ let modalLyrExtent = ""; {#if refreshingLookups}
    {/if} - +
    + {#if USER.is_authenticated} + {postOperation("refresh-lookups")}} title="Regenerate summary (may take a moment)"/> + {/if} + +
    @@ -280,16 +282,6 @@ let modalLyrExtent = ""; {/if}
    -
    - {#if USER.is_authenticated} - - {/if} - -
    {#if !USER.is_authenticated} {#if showMultimask}
    - - let onTop //keeping track of which open modal is on top - const modals={} //all modals get registered here for easy future access - - // returns an object for the modal specified by `id`, which contains the API functions (`open` and `close` ) - export function getModal(id=''){ - return modals[id] - } - - - - - - -
    close('')}> - - -
    - - - diff --git a/ohmg/frontend/svelte/src/lib/components/SessionList.svelte b/ohmg/frontend/svelte/src/lib/components/SessionList.svelte index f1b453d5..8584fcd8 100644 --- a/ohmg/frontend/svelte/src/lib/components/SessionList.svelte +++ b/ohmg/frontend/svelte/src/lib/components/SessionList.svelte @@ -2,7 +2,7 @@ import {TableSort} from 'svelte-tablesort'; import IconContext from 'phosphor-svelte/lib/IconContext'; -import { iconProps } from "../../js/utils" +import { iconProps } from "@helpers/utils" import CaretDoubleLeft from 'phosphor-svelte/lib/CaretDoubleLeft' import CaretDoubleRight from 'phosphor-svelte/lib/CaretDoubleRight' diff --git a/ohmg/frontend/svelte/src/lib/components/VolumePreviewMap.svelte b/ohmg/frontend/svelte/src/lib/components/VolumePreviewMap.svelte deleted file mode 100644 index 9ce190b6..00000000 --- a/ohmg/frontend/svelte/src/lib/components/VolumePreviewMap.svelte +++ /dev/null @@ -1,241 +0,0 @@ - - - {keyImgCaption} - - -
    -
    -
    -
    -
    -
    - - - -
    -
    - -
    - Basemap - -
    -
    - {currentBasemap} -
    - -
    - Key Map - -
    -
    - {#if VOLUME.sorted_layers.key_map.length == 0} - no key map set - {:else} - - {/if} -
    -
    - Main Layers - -
    -
    - {#if VOLUME.sorted_layers.main.length == 0} - no layers - {:else} - - {/if} -
    -
    -
    -
    -
    diff --git a/ohmg/frontend/svelte/src/lib/components/buttons/InfoButton.svelte b/ohmg/frontend/svelte/src/lib/components/buttons/LiteButton.svelte similarity index 65% rename from ohmg/frontend/svelte/src/lib/components/buttons/InfoButton.svelte rename to ohmg/frontend/svelte/src/lib/components/buttons/LiteButton.svelte index ef627415..017bebe0 100644 --- a/ohmg/frontend/svelte/src/lib/components/buttons/InfoButton.svelte +++ b/ohmg/frontend/svelte/src/lib/components/buttons/LiteButton.svelte @@ -1,13 +1,14 @@ - diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte new file mode 100644 index 00000000..586e5af3 --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte @@ -0,0 +1,197 @@ + + + + +
    +
    +
    +
    +
    +
    + {setMapExtent(map, VOLUME.extent)}} /> + + +
    +
    +
    + Basemap + +
    +
    + {currentBasemap} +
    + {#each layerSetList as id} + {#if layerSets[id].layerCt > 0} +
    + {layerSets[id].name} +
    +
    +
    + + +
    +
    + {/if} + {/each} +
    +
    +
    +
    diff --git a/ohmg/frontend/svelte/src/lib/components/MultiTrim.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte similarity index 92% rename from ohmg/frontend/svelte/src/lib/components/MultiTrim.svelte rename to ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte index 86ee35f1..ebafd696 100644 --- a/ohmg/frontend/svelte/src/lib/components/MultiTrim.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte @@ -5,11 +5,7 @@ import CropIcon from "phosphor-svelte/lib/Crop"; import Trash from "phosphor-svelte/lib/Trash"; import Check from "phosphor-svelte/lib/Check"; import X from "phosphor-svelte/lib/X"; -import ArrowsInSimple from "phosphor-svelte/lib/ArrowsInSimple"; -import ArrowsOutSimple from "phosphor-svelte/lib/ArrowsOutSimple"; -import CornersOut from "phosphor-svelte/lib/CornersOut"; import IconContext from 'phosphor-svelte/lib/IconContext'; -import { iconProps } from "../../js/utils" import 'ol/ol.css'; import Map from 'ol/Map'; @@ -40,10 +36,14 @@ import {Draw, Modify, Snap} from 'ol/interaction'; import Style from 'ol/style/Style'; import Stroke from 'ol/style/Stroke'; -import Styles from '../../js/ol-styles'; +import FullExtentButton from './buttons/FullExtentButton.svelte'; +import ExpandElement from './buttons/ExpandElement.svelte'; + +import { iconProps, makeTitilerXYZUrl, makeBasemaps } from "@helpers/utils" +import Styles from '@helpers/ol-styles'; + const styles = new Styles(); -import {makeTitilerXYZUrl, makeBasemaps} from '../../js/utils'; export let VOLUME; export let CSRFTOKEN; @@ -199,12 +199,13 @@ function makeModifyInteraction(hitDetection, source, targetElement) { return modify } +let map; function MapViewer (elementId) { const targetElement = document.getElementById(elementId); // create map - const map = new Map({ + map = new Map({ target: targetElement, layers: [osmBasemap.layer], view: new View({ @@ -407,13 +408,6 @@ function layerRemoveMask(layer, confirm) { } -let ffs = false -function handleFfs(elementId) { - ffs = !ffs - document.getElementById(elementId).classList.toggle('ffs'); - mapView.map.updateSize(); -} - @@ -425,16 +419,8 @@ function handleFfs(elementId) {
    - - + +
    @@ -443,7 +429,7 @@ function handleFfs(elementId) {
    {#each layerLookupUnmaskedArr as layer}
    -   @@ -461,7 +447,7 @@ function handleFfs(elementId) {
    {#each layerLookupMaskedArr as layer}
    -   diff --git a/ohmg/frontend/svelte/src/lib/Viewer.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/PlaceViewer.svelte similarity index 99% rename from ohmg/frontend/svelte/src/lib/Viewer.svelte rename to ohmg/frontend/svelte/src/lib/components/interfaces/PlaceViewer.svelte index 7d74e4ef..1a8ac4b7 100644 --- a/ohmg/frontend/svelte/src/lib/Viewer.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/PlaceViewer.svelte @@ -3,7 +3,7 @@ import {onMount} from 'svelte'; import { slide } from 'svelte/transition'; import IconContext from 'phosphor-svelte/lib/IconContext'; -import { iconProps } from "../js/utils" +import { iconProps } from "@helpers/utils" import CrosshairSimple from "phosphor-svelte/lib/CrosshairSimple"; import MapTrifold from "phosphor-svelte/lib/MapTrifold"; @@ -21,7 +21,7 @@ import {fromLonLat} from 'ol/proj'; import {createXYZ} from 'ol/tilegrid'; import 'ol/ol.css'; -import '../css/ol-overrides.css'; +import '@src/css/ol-overrides.css'; import Map from 'ol/Map'; import View from 'ol/View'; @@ -44,8 +44,8 @@ import VectorLayer from 'ol/layer/Vector'; import {MouseWheelZoom, defaults} from 'ol/interaction'; -import {makeTitilerXYZUrl, makeLayerGroupFromVolume, makeBasemaps} from '../js/utils'; -import Modal, {getModal} from './components/Modal.svelte' +import {makeTitilerXYZUrl, makeLayerGroupFromVolume, makeBasemaps} from '@helpers/utils'; +import Modal, {getModal} from '@components/modals/Base.svelte' export let PLACE; export let MAPBOX_API_KEY; diff --git a/ohmg/frontend/svelte/src/lib/components/SingleDocumentViewer.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/SingleDocumentViewer.svelte similarity index 95% rename from ohmg/frontend/svelte/src/lib/components/SingleDocumentViewer.svelte rename to ohmg/frontend/svelte/src/lib/components/interfaces/SingleDocumentViewer.svelte index 0fc07e5b..81706cda 100644 --- a/ohmg/frontend/svelte/src/lib/components/SingleDocumentViewer.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/SingleDocumentViewer.svelte @@ -2,21 +2,22 @@ import {onMount} from 'svelte'; import IconContext from 'phosphor-svelte/lib/IconContext'; - import { iconProps } from "../../js/utils" + import { iconProps } from "@helpers/utils" import CornersOut from "phosphor-svelte/lib/CornersOut"; import 'ol/ol.css'; - import '../../css/ol-overrides.css'; - + import Map from 'ol/Map'; import View from 'ol/View'; import {ZoomToExtent, defaults as defaultControls} from 'ol/control.js'; - + import {Projection} from 'ol/proj'; - + import {ImageStatic} from 'ol/source'; import {Image as ImageLayer} from 'ol/layer'; + import '@src/css/ol-overrides.css'; + export let IMAGE_SIZE; export let LAYER_URL; diff --git a/ohmg/frontend/svelte/src/lib/components/SingleLayerViewer.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/SingleLayerViewer.svelte similarity index 93% rename from ohmg/frontend/svelte/src/lib/components/SingleLayerViewer.svelte rename to ohmg/frontend/svelte/src/lib/components/interfaces/SingleLayerViewer.svelte index 15be670c..c9e15ca5 100644 --- a/ohmg/frontend/svelte/src/lib/components/SingleLayerViewer.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/SingleLayerViewer.svelte @@ -2,24 +2,24 @@ import {onMount} from 'svelte'; import IconContext from 'phosphor-svelte/lib/IconContext'; - import { iconProps } from "../../js/utils" import CornersOut from "phosphor-svelte/lib/CornersOut"; import 'ol/ol.css'; - import '../../css/ol-overrides.css'; - + import Map from 'ol/Map'; import {ZoomToExtent, defaults as defaultControls} from 'ol/control.js'; - + import {transformExtent} from 'ol/proj'; - + import {XYZ} from 'ol/source'; import {Tile as TileLayer} from 'ol/layer'; - + + import '@src/css/ol-overrides.css'; import { + iconProps, makeTitilerXYZUrl, makeBasemaps, - } from '../../js/utils'; + } from '@helpers/utils'; export let EXTENT; export let MAPBOX_API_KEY; diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/Splitter.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/Splitter.svelte new file mode 100644 index 00000000..225703f8 --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/Splitter.svelte @@ -0,0 +1,461 @@ + + {if (!leaveOkay) {confirmLeave()}}} on:unload={cleanup}/> + + +

    This preparation session is expiring, and will be cancelled soon.

    + +
    + + +

    Feel free to experiment with the interface, but submit your work you must + sign in or + sign up. +

    +
    + + +

    This document has already been prepared!

    +
    + +

    Are you sure you want to cancel this session?

    + + +
    + +

    {currentTxt} Learn more

    +
    + {#if disableInterface} +
    + +
    + {/if} + +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/BasemapToggleButton.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/BasemapToggleButton.svelte new file mode 100644 index 00000000..3ecfe4c0 --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/BasemapToggleButton.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte new file mode 100644 index 00000000..8f90c212 --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte @@ -0,0 +1,34 @@ + + + + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/FullExtentButton.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/FullExtentButton.svelte new file mode 100644 index 00000000..8e75fb0f --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/FullExtentButton.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/OpenModalButton.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/OpenModalButton.svelte new file mode 100644 index 00000000..1f227cd7 --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/OpenModalButton.svelte @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/modals/LegendModal.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/modals/LegendModal.svelte new file mode 100644 index 00000000..2344aefc --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/modals/LegendModal.svelte @@ -0,0 +1,11 @@ + + + + {legendAlt} + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/modals/Base.svelte b/ohmg/frontend/svelte/src/lib/components/modals/Base.svelte index f7e79816..6091a1e7 100644 --- a/ohmg/frontend/svelte/src/lib/components/modals/Base.svelte +++ b/ohmg/frontend/svelte/src/lib/components/modals/Base.svelte @@ -13,8 +13,8 @@ import {onDestroy} from 'svelte' import SvelteMarkdown from 'svelte-markdown'; -import '../../../css/modal.css'; -import '../../../css/ol-overrides.css'; +import '@src/css/modal.css'; +import '@src/css/ol-overrides.css'; let topDiv let visible=false diff --git a/ohmg/frontend/svelte/src/lib/components/modals/DocumentViewerModal.svelte b/ohmg/frontend/svelte/src/lib/components/modals/DocumentViewerModal.svelte index 889ce845..230bff0c 100644 --- a/ohmg/frontend/svelte/src/lib/components/modals/DocumentViewerModal.svelte +++ b/ohmg/frontend/svelte/src/lib/components/modals/DocumentViewerModal.svelte @@ -1,6 +1,6 @@ diff --git a/ohmg/frontend/svelte/src/lib/Navbar.svelte b/ohmg/frontend/svelte/src/lib/components/shared/Navbar.svelte similarity index 96% rename from ohmg/frontend/svelte/src/lib/Navbar.svelte rename to ohmg/frontend/svelte/src/lib/components/shared/Navbar.svelte index 36d2440a..f89ec14f 100644 --- a/ohmg/frontend/svelte/src/lib/Navbar.svelte +++ b/ohmg/frontend/svelte/src/lib/components/shared/Navbar.svelte @@ -1,9 +1,8 @@ -
    - - -
    - - diff --git a/ohmg/frontend/svelte/src/lib/components/base/IconButton.svelte b/ohmg/frontend/svelte/src/lib/components/base/IconButton.svelte new file mode 100644 index 00000000..7f3bc3ff --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/base/IconButton.svelte @@ -0,0 +1,104 @@ + + + + + + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/icons/GlobalIconContext.svelte b/ohmg/frontend/svelte/src/lib/components/base/IconContext.svelte similarity index 81% rename from ohmg/frontend/svelte/src/lib/components/icons/GlobalIconContext.svelte rename to ohmg/frontend/svelte/src/lib/components/base/IconContext.svelte index 38365634..bf0cd835 100644 --- a/ohmg/frontend/svelte/src/lib/components/icons/GlobalIconContext.svelte +++ b/ohmg/frontend/svelte/src/lib/components/base/IconContext.svelte @@ -1,4 +1,5 @@ + + {getModal(modalId).open()}} title={title}> + + diff --git a/ohmg/frontend/svelte/src/lib/components/buttons/LiteButton.svelte b/ohmg/frontend/svelte/src/lib/components/buttons/LiteButton.svelte deleted file mode 100644 index 017bebe0..00000000 --- a/ohmg/frontend/svelte/src/lib/components/buttons/LiteButton.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - - - - \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/buttons/OpenModal.svelte b/ohmg/frontend/svelte/src/lib/components/buttons/OpenModal.svelte deleted file mode 100644 index 8cf28d86..00000000 --- a/ohmg/frontend/svelte/src/lib/components/buttons/OpenModal.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - - - - \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/Georeferencer.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/Georeferencer.svelte index d41f29ab..e693d674 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/Georeferencer.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/Georeferencer.svelte @@ -56,7 +56,7 @@ import { removeRotateCenter, } from '@helpers/utils'; -import Modal, {getModal} from '@components/modals/Base.svelte'; +import Modal, {getModal} from '@components/base/Modal.svelte'; export let USER; export let SESSION_LENGTH; diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte index 586e5af3..1ca8f34e 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte @@ -3,10 +3,10 @@ import {onMount} from 'svelte'; import IconContext from 'phosphor-svelte/lib/IconContext'; +import OpenModalButton from "@components/base/OpenModalButton.svelte" import BasemapToggleButton from "./buttons/BasemapToggleButton.svelte" import ExpandElement from "./buttons/ExpandElement.svelte" import FullExtentButton from "./buttons/FullExtentButton.svelte" -import OpenModalButton from "./buttons/OpenModalButton.svelte" import LegendModal from "./modals/LegendModal.svelte" @@ -165,7 +165,7 @@ onMount(() => {
    {setMapExtent(map, VOLUME.extent)}} /> - +
    diff --git a/ohmg/frontend/svelte/src/lib/components/search/MapBrowse.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/MapBrowse.svelte similarity index 100% rename from ohmg/frontend/svelte/src/lib/components/search/MapBrowse.svelte rename to ohmg/frontend/svelte/src/lib/components/interfaces/MapBrowse.svelte diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte index ebafd696..da7c690b 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte @@ -36,6 +36,7 @@ import {Draw, Modify, Snap} from 'ol/interaction'; import Style from 'ol/style/Style'; import Stroke from 'ol/style/Stroke'; +import IconButton from '@components/base/IconButton.svelte'; import FullExtentButton from './buttons/FullExtentButton.svelte'; import ExpandElement from './buttons/ExpandElement.svelte'; @@ -429,9 +430,7 @@ function layerRemoveMask(layer, confirm) {
    {#each layerLookupUnmaskedArr as layer}
    - + addMask(layer)} />   + layerRemoveMask(layer)} />  
    - - + +
    diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/PlaceViewer.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/PlaceViewer.svelte index 1a8ac4b7..b6d1f43b 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/PlaceViewer.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/PlaceViewer.svelte @@ -45,7 +45,7 @@ import VectorLayer from 'ol/layer/Vector'; import {MouseWheelZoom, defaults} from 'ol/interaction'; import {makeTitilerXYZUrl, makeLayerGroupFromVolume, makeBasemaps} from '@helpers/utils'; -import Modal, {getModal} from '@components/modals/Base.svelte' +import Modal, {getModal} from '@components/base/Modal.svelte' export let PLACE; export let MAPBOX_API_KEY; diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/Splitter.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/Splitter.svelte index 225703f8..b4528b20 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/Splitter.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/Splitter.svelte @@ -38,8 +38,8 @@ import LineString from 'ol/geom/LineString'; import Styles from '@helpers/ol-styles'; -import TitleBar from '@components/shared/TitleBar.svelte'; -import Modal, {getModal} from '@components/modals/Base.svelte'; +import TitleBar from '@components/layout/TitleBar.svelte'; +import Modal, {getModal} from '@components/base/Modal.svelte'; const styles = new Styles(); diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/BasemapToggleButton.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/BasemapToggleButton.svelte index 3ecfe4c0..e9785cc2 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/BasemapToggleButton.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/BasemapToggleButton.svelte @@ -1,4 +1,5 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte index 8f90c212..6b54dbc1 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte @@ -1,5 +1,7 @@ - + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/Georeferencer.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/Georeferencer.svelte index e693d674..2192e24a 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/Georeferencer.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/Georeferencer.svelte @@ -4,9 +4,6 @@ import { iconProps } from "@helpers/utils" import X from "phosphor-svelte/lib/X"; import Check from "phosphor-svelte/lib/Check"; import ArrowsClockwise from "phosphor-svelte/lib/ArrowsClockwise"; -import ArrowsOutSimple from "phosphor-svelte/lib/ArrowsOutSimple"; -import ArrowsInSimple from "phosphor-svelte/lib/ArrowsInSimple"; -import ArrowSquareOut from "phosphor-svelte/lib/ArrowSquareOut"; import Trash from "phosphor-svelte/lib/Trash"; import Stack from "phosphor-svelte/lib/Stack"; import GearSix from "phosphor-svelte/lib/GearSix"; @@ -57,6 +54,9 @@ import { } from '@helpers/utils'; import Modal, {getModal} from '@components/base/Modal.svelte'; +import Link from '@components/base/Link.svelte'; + +import ExpandElement from "./buttons/ExpandElement.svelte"; export let USER; export let SESSION_LENGTH; @@ -77,6 +77,10 @@ let syncPanelWidth = false; let docView; let mapView; + +let mapViewMap; +let docViewMap; + let gcpList = []; let activeGCP = null; @@ -398,6 +402,8 @@ function DocumentViewer (elementId) { this.drawInteraction = draw; this.modifyInteraction = modify; + docViewMap = map; + this.resetExtent = function () { map.getView().setRotation(0); map.getView().fit(docExtent, {padding: [10, 10, 10, 10]}); @@ -474,6 +480,7 @@ function MapViewer (elementId) { // expose properties as necessary this.map = map; + mapViewMap = map; this.element = targetElement; this.drawInteraction = draw; this.modifyInteraction = modify; @@ -829,9 +836,6 @@ function handleKeydown(e) { // so shortcuts aren't activated while typing a note. if (document.activeElement.id == "") { switch(e.key) { - case "Escape": - handleFfs('map-container') - break; case "d": case "D": removeActiveGCP(); break; @@ -896,19 +900,11 @@ function cleanup () { process('cancel') } -let ffs = false -function handleFfs(elementId) { - ffs = !ffs - document.getElementById(elementId).classList.toggle('ffs'); - docView.map.updateSize(); - mapView.map.updateSize(); -} - {if (!leaveOkay) {confirmLeave()}}} on:unload={cleanup}/> -

    Create 3 or more ground control points to georeference this document. To create a ground control point, first click on a location in the left panel, then find and click on the corresponding location in right panel. Learn more

    +

    Create 3 or more ground control points to georeference this document. To create a ground control point, first click on a location in the left panel, then find and click on the corresponding location in right panel. Learn more

    This georeferencing session is expiring, and will be cancelled soon.

    @@ -919,8 +915,8 @@ function handleFfs(elementId) {

    Feel free to experiment with the interface, but submit your work you must - sign in or - sign up. + sign in or + sign up.

    @@ -940,12 +936,12 @@ function handleFfs(elementId) {
    diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte index 1ca8f34e..bd2633a0 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/ItemPreviewMap.svelte @@ -166,7 +166,7 @@ onMount(() => {
    {setMapExtent(map, VOLUME.extent)}} /> - +
    diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte index da7c690b..0b65767a 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte @@ -421,7 +421,7 @@ function layerRemoveMask(layer, confirm) {
    - +
    diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/PlaceViewer.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/PlaceViewer.svelte index b6d1f43b..9456ac5d 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/PlaceViewer.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/PlaceViewer.svelte @@ -1,6 +1,5 @@ {if (!leaveOkay) {confirmLeave()}}} on:unload={cleanup}/> @@ -374,9 +370,9 @@ function handleFfs(elementId) { -

    Feel free to experiment with the interface, but submit your work you must - sign in or - sign up. +

    Feel free to experiment with the interface, but to submit your work you must + sign in or + sign up.

    @@ -394,7 +390,7 @@ function handleFfs(elementId) { }>No - keep working -

    {currentTxt} Learn more

    +

    {currentTxt} Learn more

    {#if disableInterface}
    @@ -444,14 +440,7 @@ function handleFfs(elementId) { - - +
    diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte index 6b54dbc1..a8f6e800 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/ExpandElement.svelte @@ -7,16 +7,29 @@ import ArrowsOutSimple from "phosphor-svelte/lib/ArrowsOutSimple"; export let elementId; - export let map = null; + export let maps = []; let ffs = false; function handleFfs(elementId) { ffs = !ffs document.getElementById(elementId).classList.toggle('ffs'); - map && map.updateSize(); + maps.forEach((map) => map && map.updateSize()); + } + + function handleKeydown(e) { + // only allow these shortcuts if the maps have focus, + // so shortcuts aren't activated while typing a note. + if (document.activeElement.id == "") { + switch(e.key) { + case "Escape": + handleFfs('map-container') + break; + } + } } + {handleFfs(elementId)}}> {#if ffs} diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/MapboxLogoLink.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/MapboxLogoLink.svelte new file mode 100644 index 00000000..b1e3086d --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/buttons/MapboxLogoLink.svelte @@ -0,0 +1,21 @@ + + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/layout/Footer.svelte b/ohmg/frontend/svelte/src/lib/components/layout/Footer.svelte index ca65561d..84f03111 100644 --- a/ohmg/frontend/svelte/src/lib/components/layout/Footer.svelte +++ b/ohmg/frontend/svelte/src/lib/components/layout/Footer.svelte @@ -1,39 +1,88 @@ @@ -51,12 +100,7 @@ display: flex; flex-direction: row; justify-content: space-around; - } - footer a { - color: white; - text-decoration: none; - } - + } footer > div { margin: 0px 10px; } diff --git a/ohmg/frontend/svelte/src/lib/components/layout/MarkdownPage.svelte b/ohmg/frontend/svelte/src/lib/components/layout/MarkdownPage.svelte index 556f6b0c..d10d273a 100644 --- a/ohmg/frontend/svelte/src/lib/components/layout/MarkdownPage.svelte +++ b/ohmg/frontend/svelte/src/lib/components/layout/MarkdownPage.svelte @@ -1,6 +1,8 @@ - - diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/modals/DownloadSectionModal.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/modals/DownloadSectionModal.svelte index 8e4cbc24..dc7a360a 100644 --- a/ohmg/frontend/svelte/src/lib/components/overviews/modals/DownloadSectionModal.svelte +++ b/ohmg/frontend/svelte/src/lib/components/overviews/modals/DownloadSectionModal.svelte @@ -7,7 +7,7 @@ -

    Mosaic Downloads & Web Services

    +

    Download & Web Services

    After multiple pages have been georeferenced and a multimask has been created, a single mosaic can be generated from all of this item's layers. Once created, the mosaic can be downloaded as a GeoTIFF, or integrated as a web service into any common GIS or web GIS software via the XYZ tiles URL.

    How to use XYZ tiles in desktop software

    diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/modals/ItemPreviewMapModal.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/modals/ItemPreviewMapModal.svelte index 44a549c9..1fb5c875 100644 --- a/ohmg/frontend/svelte/src/lib/components/overviews/modals/ItemPreviewMapModal.svelte +++ b/ohmg/frontend/svelte/src/lib/components/overviews/modals/ItemPreviewMapModal.svelte @@ -1,6 +1,6 @@ + + + +

    Item Details

    +View item in LOC collection + + + + + + + + + + + + + +
    TitleSanborn Map of {ITEM.title}
    Year{ITEM.year}
    Locale{ITEM.locale.display_name}
    +

    Contributors & Attribution

    +
    +

    + {#if ITEM.sheet_ct.loaded == ITEM.sheet_ct.total} + {ITEM.sheet_ct.loaded} of {ITEM.sheet_ct.total} sheet{#if ITEM.sheet_ct.total != 1}s{/if} loaded by {ITEM.loaded_by.name} - {ITEM.loaded_by.date}
    + {/if} + {ITEM.sessions.prep_ct} sheet{#if ITEM.sessions.prep_ct != 1}s{/if} prepared{#if ITEM.sessions.prep_ct > 0} by + {#each ITEM.sessions.prep_contributors as c, n}{c.name} ({c.ct}){#if n != ITEM.sessions.prep_contributors.length-1}, {/if}{/each}{/if} +
    + {ITEM.sessions.georef_ct} georeferencing session{#if ITEM.sessions.georef_ct != 1}s{/if}{#if ITEM.sessions.georef_ct > 0} by + {#each ITEM.sessions.georef_contributors as c, n}{c.name} ({c.ct}){#if n != ITEM.sessions.georef_contributors.length-1}, {/if}{/each}{/if} +
    + Credit Line: Library of Congress, Geography and Map Division, Sanborn Maps Collection. +

    +
    +
    +

    Download & Web Services

    + +
    +

    + Only layers that have been trimmed in the MultiMask will appear in the mosaic. You can access untrimmed layers individually through the Georeferenced section. +

    + + + + + + + + + + + + + +
    XYZ Tiles URL + {#if mosaicUrl} +
    {mosaicUrl}
    + {:else} + n/a + {/if} +
    OHM + {#if ohmUrl} + Use in OpenHistoricalMap iD editor + {:else} + n/a + {/if}
    GeoTIFF + {#if ITEM.urls.mosaic_geotiff} + Download GeoTIFF (direct download) + {:else} + n/a + {/if} +
    + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/pages/Georeference.svelte b/ohmg/frontend/svelte/src/lib/pages/Georeference.svelte index d6f99593..cc45edcb 100644 --- a/ohmg/frontend/svelte/src/lib/pages/Georeference.svelte +++ b/ohmg/frontend/svelte/src/lib/pages/Georeference.svelte @@ -37,7 +37,7 @@ - + -import SvelteMarkdown from 'svelte-markdown' + import SvelteMarkdown from 'svelte-markdown' -import IconContext from 'phosphor-svelte/lib/IconContext'; -import { iconProps } from "@helpers/utils" -import ArrowSquareOut from 'phosphor-svelte/lib/ArrowSquareOut' + import IconContext from 'phosphor-svelte/lib/IconContext'; + import { iconProps } from "@helpers/utils"; -import MapBrowse from '@components/interfaces/MapBrowse.svelte'; + import Link from '@components/base/Link.svelte'; + import MapBrowse from '@components/interfaces/MapBrowse.svelte'; -import LatestAdditions from '@components/lists/LatestAdditions.svelte'; -import SessionList from '@components/lists/SessionList.svelte' + import LatestAdditions from '@components/lists/LatestAdditions.svelte'; + import SessionList from '@components/lists/SessionList.svelte' -export let ITEM_API_URL; -export let SESSION_API_URL; -export let PLACES_GEOJSON_URL; -export let IS_MOBILE; -export let CSRFTOKEN; -export let OHMG_API_KEY; -export let NEWSLETTER_SLUG; -export let USER_SUBSCRIBED; -export let USER_EMAIL; -export let PLACES_CT; -export let ITEMS_CT; + export let ITEM_API_URL; + export let SESSION_API_URL; + export let PLACES_GEOJSON_URL; + export let IS_MOBILE; + export let CSRFTOKEN; + export let OHMG_API_KEY; + export let NEWSLETTER_SLUG; + export let USER_SUBSCRIBED; + export let USER_EMAIL; + export let PLACES_CT; + export let ITEMS_CT; -let showBrowseMap = !IS_MOBILE; -$: showBrowseMapBtnLabel = showBrowseMap ? "Hide map finder" : "Show map finder"; -let showBRMap = !IS_MOBILE; + let showBrowseMap = !IS_MOBILE; + $: showBrowseMapBtnLabel = showBrowseMap ? "Hide map finder" : "Show map finder"; + let showBRMap = !IS_MOBILE; -const urlSegs = window.location.href.split('/') + const urlSegs = window.location.href.split('/') -if (urlSegs[urlSegs.length - 2] == 'about') { - page = 'about' -} + if (urlSegs[urlSegs.length - 2] == 'about') { + page = 'about' + }

    OldInsuranceMaps.net

    -

    A crowdsourcing site for creating and viewing georeferenced mosaics of historical fire insurance maps from the Library of Congress. See how it works or visit the about or FAQ pages to learn more.

    +

    A crowdsourcing site for creating and viewing georeferenced mosaics of historical fire insurance maps from the Library of Congress. See how it works or visit the about or FAQ pages to learn more.

    Explore georeferenced maps from {PLACES_CT} locations...

    -

    Click a point to access the viewer for that locale, or search by place name. +

    Click a point to access the viewer for that locale, or search by place name.

    {#if IS_MOBILE}{/if} {#if showBrowseMap} @@ -58,16 +58,16 @@ if (urlSegs[urlSegs.length - 2] == 'about') {

    Recently Added Maps

    - Want to see more? View all items and sort by Load date. + Want to see more? View all items and sort by Load date.
    {#if NEWSLETTER_SLUG} @@ -76,12 +76,12 @@ if (urlSegs[urlSegs.length - 2] == 'about') { {#if USER_SUBSCRIBED} - manage subscription + manage subscription {:else} {/if} - newsletter archive + newsletter archive
    {/if}
    @@ -93,34 +93,34 @@ if (urlSegs[urlSegs.length - 2] == 'about') {

    - Digital scans of Sanborn maps are available through the Library of Congress and are pulled into this site through the LOC JSON API, generating a "Volume Summary" page (Baton Rouge, 1885). + Digital scans of Sanborn maps are available through the Library of Congress and are pulled into this site through the LOC JSON API, generating a "Volume Summary" page (Baton Rouge, 1885).

    - Contributors prepare each sheet in the volume, sometimes splitting it into multiple documents, each to be georeferenced individually (Baton Rouge, 1885, page 1). + Contributors prepare each sheet in the volume, sometimes splitting it into multiple documents, each to be georeferenced individually (Baton Rouge, 1885, page 1).

    - Next, each document must be georeferenced by creating ground control points, linking features on the old map with latitude/longitude coordinates to create a geospatial layer (Baton Rouge, 1885, page 1, part 3). + Next, each document must be georeferenced by creating ground control points, linking features on the old map with latitude/longitude coordinates to create a geospatial layer (Baton Rouge, 1885, page 1, part 3).

    - As they are georeferenced, layers slowly build a collage of all the content from a given volume, and their overlapping margins must be trimmed to create a seamless mosaic. + As they are georeferenced, layers slowly build a collage of all the content from a given volume, and their overlapping margins must be trimmed to create a seamless mosaic.

    - Finally, all volume mosaics for a given locale are automatically aggregated into a simple web viewer so you can easily compare different years and current maps (Baton Rouge viewer). + Finally, all volume mosaics for a given locale are automatically aggregated into a simple web viewer so you can easily compare different years and current maps (Baton Rouge viewer).

    -

    Want to learn more? Visit the documentation site .

    +

    Want to learn more? Visit the documentation site.

    @@ -128,7 +128,7 @@ if (urlSegs[urlSegs.length - 2] == 'about') {

    Latest activity

    -

    all activity

    +

    all activity

    diff --git a/ohmg/frontend/svelte/src/lib/pages/Place.svelte b/ohmg/frontend/svelte/src/lib/pages/Place.svelte index cb078cc8..70c295cc 100644 --- a/ohmg/frontend/svelte/src/lib/pages/Place.svelte +++ b/ohmg/frontend/svelte/src/lib/pages/Place.svelte @@ -76,7 +76,7 @@ $: sideLinks = PLACE.volumes.length > 0 ? [ {/each}
    - +
    {#if PLACE.parents.length > 0} diff --git a/ohmg/frontend/svelte/src/lib/pages/Split.svelte b/ohmg/frontend/svelte/src/lib/pages/Split.svelte index 4e5f7c9d..db0b77f5 100644 --- a/ohmg/frontend/svelte/src/lib/pages/Split.svelte +++ b/ohmg/frontend/svelte/src/lib/pages/Split.svelte @@ -33,7 +33,7 @@ ] - + - - From 86e39efad74c62b878f9e66e8bec2811787079b2 Mon Sep 17 00:00:00 2001 From: Adam Cox Date: Mon, 5 Feb 2024 09:39:58 -0600 Subject: [PATCH 36/40] increase thumbnail size to support title page display --- ohmg/georeference/renderers.py | 4 ++-- ohmg/settings.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ohmg/georeference/renderers.py b/ohmg/georeference/renderers.py index f7668431..98c010a2 100644 --- a/ohmg/georeference/renderers.py +++ b/ohmg/georeference/renderers.py @@ -10,9 +10,9 @@ def generate_document_thumbnail_content(image_file_path): full_image = Image.open(image_file_path) width, height = full_image.size # only resize if one of the dimensions is larger than 200 - if width > 200 or height > 200: + if width > settings.DEFAULT_MAX_THUMBNAIL_DIMENSION or height > settings.DEFAULT_MAX_THUMBNAIL_DIMENSION: biggest_dim = max([width, height]) - ratio = 200/biggest_dim + ratio = settings.DEFAULT_MAX_THUMBNAIL_DIMENSION/biggest_dim new_width, new_height = int(ratio*width), int(ratio*height) new_size = (new_width, new_height) if 0 in new_size: diff --git a/ohmg/settings.py b/ohmg/settings.py index 6e909f6a..3412f594 100644 --- a/ohmg/settings.py +++ b/ohmg/settings.py @@ -305,7 +305,9 @@ # To allow other sites to read IIIF resources set CORS_ORIGIN_ALLOW_ALL to True CORS_ORIGIN_ALLOW_ALL = False -DEFAULT_THUMBNAIL_SIZE = (240, 200) +# Doubling this to 480, 400 (2/1/24) to present higher fidelity cover pages. +DEFAULT_MAX_THUMBNAIL_DIMENSION = 400 +DEFAULT_THUMBNAIL_SIZE = (480, 400) # Location of locale files LOCALE_PATHS = ( From 4bac1de5272578d5a1492c821e32a0ff6dcc5ec3 Mon Sep 17 00:00:00 2001 From: Adam Cox Date: Mon, 5 Feb 2024 17:47:47 -0600 Subject: [PATCH 37/40] refactor svg icons --- ohmg/frontend/static/css/icons.css | 180 --------------- .../static/icons/noun-camera-858458.svg | 23 ++ .../src/lib/components/base/SVGButton.svelte | 52 +++++ .../src/lib/components/base/SVGIcon.svelte | 211 ++++++++++++++++++ .../frontend/svelte/src/lib/pages/Home.svelte | 21 +- ohmg/frontend/templates/404.html | 1 - ohmg/frontend/templates/500.html | 1 - ohmg/frontend/templates/base.html | 1 - ohmg/frontend/templates/viewer.html | 1 - 9 files changed, 302 insertions(+), 189 deletions(-) delete mode 100644 ohmg/frontend/static/css/icons.css create mode 100644 ohmg/frontend/static/icons/noun-camera-858458.svg create mode 100644 ohmg/frontend/svelte/src/lib/components/base/SVGButton.svelte create mode 100644 ohmg/frontend/svelte/src/lib/components/base/SVGIcon.svelte diff --git a/ohmg/frontend/static/css/icons.css b/ohmg/frontend/static/css/icons.css deleted file mode 100644 index a3f04d38..00000000 --- a/ohmg/frontend/static/css/icons.css +++ /dev/null @@ -1,180 +0,0 @@ -:root { - --volume-svg: url(../icons/noun_UprightBook_2089467.svg); - --volume2-svg: url(../icons/noun-book-3124501-FFFFFF.svg); - --document-svg: url(../icons/noun_Scroll_2592600.svg); - --layer-svg: url(../icons/noun_Layer_2583171.svg); - --webmap-svg: url(../icons/noun_FoldedMap_2592599.svg); - --pinmap-svg: url(../icons/noun_pinmap_1832932.svg); - --user-svg: url(../icons/noun_User_1236015.svg); - --magnifier-svg: url(../icons/noun-magnifier-858462.svg); - --pin-svg: url(../icons/noun-map-pin-858464.svg); - --compass-svg: url(../icons/noun-compass-867471.svg); - --volume-size: 65px; - --document-size: 70px; - --layer-size: 75px; - --webmap-size: 70px; - --pinmap-size: 70px; - --user-size: 50px; - --magnifier-size: 55px; - --pin-size: 55px; - --compass-size: 55px; -} - -.i-magnifier { - mask-image: var(--magnifier-svg); - -webkit-mask-image: var(--magnifier-svg); - display: inline-block; - background: black; - mask-size: cover; - -webkit-mask-size: cover; -} -.i-magnifier-lg{ - width: var(--magnifier-size); - height: var(--magnifier-size); -} -.i-magnifier-sm { - width: calc(var(--pin-size)*.55); - height: calc(var(--pin-size)*.55); -} - -.i-pin { - mask-image: var(--pin-svg); - -webkit-mask-image: var(--pin-svg); - display: inline-block; - background: black; - mask-size: cover; - -webkit-mask-size: cover; -} -.i-pin-lg{ - width: var(--pin-size); - height: var(--pin-size); -} -.i-pin-sm { - width: calc(var(--pin-size)*.55); - height: calc(var(--pin-size)*.55); -} - -.i-compass { - mask-image: var(--compass-svg); - -webkit-mask-image: var(--compass-svg); - display: inline-block; - background: black; - mask-size: cover; - -webkit-mask-size: cover; -} -.i-compass-lg{ - width: var(--compass-size); - height: var(--compass-size); -} -.i-compass-sm { - width: calc(var(--compass-size)*.55); - height: calc(var(--compass-size)*.55); -} - -.i-volume { - mask-image: var(--volume2-svg); - -webkit-mask-image: var(--volume2-svg); - display: inline-block; - background: black; - mask-size: cover; - -webkit-mask-size: cover; -} -.i-volume-lg{ - width: var(--volume-size); - height: var(--volume-size); -} -.i-volume-sm { - width: calc(var(--volume-size)*.55); - height: calc(var(--volume-size)*.55); -} - -.i-document { - display: inline-block; - background: black; - mask-size: cover; - -webkit-mask-size: cover; - mask-image: var(--document-svg); - -webkit-mask-image: var(--document-svg); -} -.i-document-lg { - width: var(--document-size); - height: var(--document-size); -} -.i-document-sm { - width: calc(var(--document-size)*.55); - height: calc(var(--document-size)*.55); -} - -.i-layer { - display: inline-block; - background: black; - mask-size: cover; - -webkit-mask-size: cover; - mask-image: var(--layer-svg); - -webkit-mask-image: var(--layer-svg); -} -.i-layer-lg { - width: var(--layer-size); - height: var(--layer-size); -} -.i-layer-sm { - width: calc(var(--layer-size)*.55); - height: calc(var(--layer-size)*.55); -} - -.i-webmap { - display: inline-block; - background: black; - mask-size: cover; - -webkit-mask-size: cover; - mask-image: var(--webmap-svg); - -webkit-mask-image: var(--webmap-svg); -} -.i-webmap-lg { - width: var(--webmap-size); - height: var(--webmap-size); -} -.i-webmap-sm { - width: calc(var(--webmap-size)*.55); - height: calc(var(--webmap-size)*.55); -} - -.i-pinmap { - display: inline-block; - background: black; - mask-size: cover; - -webkit-mask-size: cover; - mask-image: var(--pinmap-svg); - -webkit-mask-image: var(--pinmap-svg); -} -.i-pinmap-lg { - width: var(--pinmap-size); - height: var(--pinmap-size); -} -.i-pinmap-sm { - width: calc(var(--pinmap-size)*.55); - height: calc(var(--pinmap-size)*.55); -} - -.i-user { - display: inline-block; - background: black; - mask-size: cover; - -webkit-mask-size: cover; - mask-image: var(--user-svg); - -webkit-mask-image: var(--user-svg); -} -.i-user-lg { - width: var(--user-size); - height: var(--user-size); -} -.i-user-sm { - width: calc(var(--user-size)*.55); - height: calc(var(--user-size)*.55); -} -.imi { - display: inline-block; - background: black; - mask-size: cover; - -webkit-mask-size: cover; -} \ No newline at end of file diff --git a/ohmg/frontend/static/icons/noun-camera-858458.svg b/ohmg/frontend/static/icons/noun-camera-858458.svg new file mode 100644 index 00000000..231cd510 --- /dev/null +++ b/ohmg/frontend/static/icons/noun-camera-858458.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ohmg/frontend/svelte/src/lib/components/base/SVGButton.svelte b/ohmg/frontend/svelte/src/lib/components/base/SVGButton.svelte new file mode 100644 index 00000000..43e09c5e --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/base/SVGButton.svelte @@ -0,0 +1,52 @@ + + + + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/base/SVGIcon.svelte b/ohmg/frontend/svelte/src/lib/components/base/SVGIcon.svelte new file mode 100644 index 00000000..fca05706 --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/base/SVGIcon.svelte @@ -0,0 +1,211 @@ + + + + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/pages/Home.svelte b/ohmg/frontend/svelte/src/lib/pages/Home.svelte index 11295a13..e23a0c61 100644 --- a/ohmg/frontend/svelte/src/lib/pages/Home.svelte +++ b/ohmg/frontend/svelte/src/lib/pages/Home.svelte @@ -5,6 +5,7 @@ import { iconProps } from "@helpers/utils"; import Link from '@components/base/Link.svelte'; + import SVGIcon from '@components/base/SVGIcon.svelte'; import MapBrowse from '@components/interfaces/MapBrowse.svelte'; import LatestAdditions from '@components/lists/LatestAdditions.svelte'; @@ -91,31 +92,41 @@

    How it Works

    -
    +
    + +

    Digital scans of Sanborn maps are available through the Library of Congress and are pulled into this site through the LOC JSON API, generating a "Volume Summary" page (Baton Rouge, 1885).

    -
    +
    + +

    Contributors prepare each sheet in the volume, sometimes splitting it into multiple documents, each to be georeferenced individually (Baton Rouge, 1885, page 1).

    -
    +
    + +

    Next, each document must be georeferenced by creating ground control points, linking features on the old map with latitude/longitude coordinates to create a geospatial layer (Baton Rouge, 1885, page 1, part 3).

    -
    +
    + +

    As they are georeferenced, layers slowly build a collage of all the content from a given volume, and their overlapping margins must be trimmed to create a seamless mosaic.

    -
    +
    + +

    Finally, all volume mosaics for a given locale are automatically aggregated into a simple web viewer so you can easily compare different years and current maps (Baton Rouge viewer).

    diff --git a/ohmg/frontend/templates/404.html b/ohmg/frontend/templates/404.html index e08b9b07..0f54fced 100644 --- a/ohmg/frontend/templates/404.html +++ b/ohmg/frontend/templates/404.html @@ -29,7 +29,6 @@ - - @@ -58,6 +72,10 @@ vertical-align: middle; } + button:disabled { + cursor: default; + } + button.lite { background: none; border: none; @@ -67,14 +85,16 @@ button.lite:hover { color:#123B4F; } - - button.lite { + button.lite:disabled { + color: grey; + } + + button.lite-sm { background: none; border: none; color:#2c689c; - font-size: 1.7em; } - button.lite:hover { + button.lite-sm:hover { color:#123B4F; } @@ -104,4 +124,30 @@ background: lightgrey; cursor: default; } + + button.link { + color: #2c689c; + background: none; + border: none; + display: inline; + vertical-align: unset; + padding: 0; + } + + button.link:hover { + text-decoration: underline; + } + + button.nav-link { + color: white; + background: none; + border: none; + display: inline; + padding: 0; + } + + button.nav-link:hover { + text-decoration: underline; + } + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/base/Link.svelte b/ohmg/frontend/svelte/src/lib/components/base/Link.svelte index d8560fcb..c63f145b 100644 --- a/ohmg/frontend/svelte/src/lib/components/base/Link.svelte +++ b/ohmg/frontend/svelte/src/lib/components/base/Link.svelte @@ -6,6 +6,7 @@ export let title = ""; export let classes = []; export let download = null; + export let filename = null; const classStr = classes.join(" ") @@ -19,7 +20,7 @@ {:else} - + {/if} diff --git a/ohmg/frontend/svelte/src/lib/components/base/Modal.svelte b/ohmg/frontend/svelte/src/lib/components/base/Modal.svelte index 2dbb54e1..24191641 100644 --- a/ohmg/frontend/svelte/src/lib/components/base/Modal.svelte +++ b/ohmg/frontend/svelte/src/lib/components/base/Modal.svelte @@ -13,7 +13,6 @@ import {onDestroy} from 'svelte' import SvelteMarkdown from 'svelte-markdown'; -import '@src/css/modal.css'; import '@src/css/ol-overrides.css'; let topDiv @@ -87,6 +86,63 @@ onDestroy(()=>{
    diff --git a/ohmg/frontend/svelte/src/lib/components/base/OpenModalButton.svelte b/ohmg/frontend/svelte/src/lib/components/base/OpenModalButton.svelte index c0078c3f..f6e87ce5 100644 --- a/ohmg/frontend/svelte/src/lib/components/base/OpenModalButton.svelte +++ b/ohmg/frontend/svelte/src/lib/components/base/OpenModalButton.svelte @@ -8,6 +8,6 @@ export let icon = "question"; - {getModal(modalId).open()}} title={title}> + {getModal(modalId).open()}} title={title}> diff --git a/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte b/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte index 0b65767a..9976563f 100644 --- a/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte +++ b/ohmg/frontend/svelte/src/lib/components/interfaces/MultiMask.svelte @@ -1,10 +1,6 @@ -{#if DISABLED}

    Feel free to mess around; you can't save changes unless you are logged in.

    {/if}
    diff --git a/ohmg/frontend/svelte/src/lib/components/layout/Navbar.svelte b/ohmg/frontend/svelte/src/lib/components/layout/Navbar.svelte index 243b1062..e52e1e1b 100644 --- a/ohmg/frontend/svelte/src/lib/components/layout/Navbar.svelte +++ b/ohmg/frontend/svelte/src/lib/components/layout/Navbar.svelte @@ -3,10 +3,13 @@ import IconContext from 'phosphor-svelte/lib/IconContext'; import CaretDown from "phosphor-svelte/lib/CaretDown"; import { iconProps } from "@helpers/utils" +import OpenModalButton from '@components/base/OpenModalButton.svelte'; import NavDropdown from './NavDropdown.svelte'; +import SigninModal from './SigninModal.svelte'; import Link from '@components/base/Link.svelte'; export let USER; +export let CSRFTOKEN; let subMenus = { "georef": { @@ -112,6 +115,7 @@ function clickOutside(node, { enabled: initialEnabled, cb }) { + diff --git a/ohmg/frontend/svelte/src/lib/components/layout/SigninModal.svelte b/ohmg/frontend/svelte/src/lib/components/layout/SigninModal.svelte new file mode 100644 index 00000000..95ec8ad1 --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/layout/SigninModal.svelte @@ -0,0 +1,48 @@ + + + + {#if showForm == "signin"} +

    Sign in

    +

    If you have not yet created an account, then please {showForm = 'signup'}} title="Sign up">sign up first.

    + + {:else if showForm == 'signup'} +

    Sign up

    +

    If you already have an account, please {showForm = 'signin'}} title="Sign in">sign in.

    + + {/if} +
    + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/layout/SigninReminder.svelte b/ohmg/frontend/svelte/src/lib/components/layout/SigninReminder.svelte new file mode 100644 index 00000000..b33921a1 --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/layout/SigninReminder.svelte @@ -0,0 +1,25 @@ + + + + + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/layout/TitleBar.svelte b/ohmg/frontend/svelte/src/lib/components/layout/TitleBar.svelte index 44383992..4d499c78 100644 --- a/ohmg/frontend/svelte/src/lib/components/layout/TitleBar.svelte +++ b/ohmg/frontend/svelte/src/lib/components/layout/TitleBar.svelte @@ -1,10 +1,11 @@
    @@ -17,19 +18,15 @@ {#if ICON_LINKS.length > 0}
    {#each ICON_LINKS as link} - {#if link.visible} - - - - {/if} + {#if link.visible} + {location.href = link.url}} disabled={!link.enabled} /> + {/if} {/each}
    {/if} - {#if SIDE_LINKS.length > 0} - @@ -52,16 +49,6 @@ margin: 0px; } - .title-bar div.link-box { - display: flex; - flex-direction: column; - align-items: end; - background: #e6e6e6; - padding: 10px; - box-shadow: gray 0px 0px 5px; - border-radius: 4px; - } - .title-bar div.icon-box { display: flex; flex-direction: row; @@ -71,11 +58,4 @@ box-shadow: gray 0px 0px 5px; border-radius: 4px; } - .title-bar div.icon-box i { - display: block; - background: #2c689c; - } - .title-bar div.icon-box i:hover { - background: #1b4060; - } \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/lists/Items.svelte b/ohmg/frontend/svelte/src/lib/components/lists/Items.svelte index 65b506e8..d56e1d20 100644 --- a/ohmg/frontend/svelte/src/lib/components/lists/Items.svelte +++ b/ohmg/frontend/svelte/src/lib/components/lists/Items.svelte @@ -11,8 +11,8 @@ export let PLACE_INCLUSIVE = false; let filtered_items = []; let loading = true -let loadedOnly = true; -$: url = PLACE_SLUG ? `${ITEM_API_URL}?locale=${PLACE_SLUG}&locale_inclusive=${PLACE_INCLUSIVE}&loaded=${loadedOnly}` : `${ITEM_API_URL}?loaded=${loadedOnly}` +let showAll = false; +$: url = PLACE_SLUG ? `${ITEM_API_URL}?locale=${PLACE_SLUG}&locale_inclusive=${PLACE_INCLUSIVE}&loaded=${!showAll}` : `${ITEM_API_URL}?loaded=${!showAll}` function handleFetch(url) { const apiHeaders = { 'X-API-Key': OHMG_API_KEY, @@ -65,7 +65,7 @@ $: updateFilteredList(filterInput)
    - +
    {#if loading} @@ -135,6 +135,7 @@ $: updateFilteredList(filterInput) .filter-container { display: flex; margin-bottom: 5px; + align-items: center; } /* Credit to this SO answer: https://stackoverflow.com/a/52205730/3873885 */ diff --git a/ohmg/frontend/svelte/src/lib/components/lists/SessionList.svelte b/ohmg/frontend/svelte/src/lib/components/lists/SessionList.svelte index cd57654f..179cdacb 100644 --- a/ohmg/frontend/svelte/src/lib/components/lists/SessionList.svelte +++ b/ohmg/frontend/svelte/src/lib/components/lists/SessionList.svelte @@ -4,6 +4,8 @@ import {TableSort} from 'svelte-tablesort'; import IconContext from 'phosphor-svelte/lib/IconContext'; import { iconProps } from "@helpers/utils" +import IconButton from '../base/IconButton.svelte'; + import CaretDoubleLeft from 'phosphor-svelte/lib/CaretDoubleLeft' import CaretDoubleRight from 'phosphor-svelte/lib/CaretDoubleRight' import ArrowsClockwise from 'phosphor-svelte/lib/ArrowsClockwise' @@ -19,7 +21,7 @@ export let limit = "10"; export let showThumbs = false; export let showUser = true; export let showResource = true; -export let allowPagination = true; +export let paginate = true; let loading = false; @@ -57,17 +59,16 @@ $: {
    - {#if allowPagination}
    + {#if paginate}
    - - {offset} - {offset + limitInt < total ? offset + limitInt : total} ({total}) - + {offset = offset - limitInt}} style="lite" icon="caret-double-left" /> + {offset} - {offset + limitInt < total ? offset + limitInt : total} ({total}) + = total || loading} action={() => {offset = offset + limitInt}} style="lite" icon="caret-double-right" />
    + {:else} +
    + {/if}
    {#if showResource}
    @@ -85,17 +86,10 @@ $: {
    {/if} -
    - -
    -
    + {offset = 1000; offset=0}} style="lite" icon="refresh" />
    -
    - {/if}
    {#if loading}
    @@ -163,10 +157,6 @@ $: {
    diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/modals/DownloadSectionModal.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/modals/DownloadSectionModal.svelte deleted file mode 100644 index dc7a360a..00000000 --- a/ohmg/frontend/svelte/src/lib/components/overviews/modals/DownloadSectionModal.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - - -

    Download & Web Services

    -

    After multiple pages have been georeferenced and a multimask has been created, a single mosaic can be generated from all of this item's layers. Once created, the mosaic can be downloaded as a GeoTIFF, or integrated as a web service into any common GIS or web GIS software via the XYZ tiles URL.

    -

    -

    How to use XYZ tiles in desktop software

    -
      -
    • QGIS
    • -
    • ArcGIS
    • -
    -

    How to use XYZ tiles on the web

    -
      -
    • Leaflet
    • -
    • OpenLayers
    • -
    • Mapbox/MapLibre GL JS
    • -
    • ArcGIS Online
    • -
    • OpenHistoricalMap (iD Editor)
    • - {#if ohmUrl} -
        -
      • Direct link to this mosaic in (iD Editor)
      • -
      - {/if} -
    -
    \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/modals/ItemDownloadSectionModal.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/modals/ItemDownloadSectionModal.svelte new file mode 100644 index 00000000..3204eef1 --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/overviews/modals/ItemDownloadSectionModal.svelte @@ -0,0 +1,13 @@ + + + +

    Download & Web Services

    +

    After multiple pages have been georeferenced and a multimask has been created, a single mosaic can be generated from all of this item's layers. Once created, the mosaic can be downloaded as a GeoTIFF, or integrated as a web service into any common GIS or web GIS software via the XYZ tiles URL.

    + +
    \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/modals/ResourceDownloadSectionModal.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/modals/ResourceDownloadSectionModal.svelte new file mode 100644 index 00000000..0eb001e6 --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/overviews/modals/ResourceDownloadSectionModal.svelte @@ -0,0 +1,11 @@ + + + +

    Download & Web Services

    + +
    \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/sections/HowToUseXYZ.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/sections/HowToUseXYZ.svelte new file mode 100644 index 00000000..145f5cdd --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/overviews/sections/HowToUseXYZ.svelte @@ -0,0 +1,17 @@ + + +

    How to use XYZ tiles in desktop software

    +
      +
    • QGIS
    • +
    • ArcGIS
    • +
    +

    How to use XYZ tiles on the web

    +
      +
    • Leaflet
    • +
    • OpenLayers
    • +
    • Mapbox/MapLibre GL JS
    • +
    • ArcGIS Online
    • +
    • OpenHistoricalMap (iD Editor)
    • +
    \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/sections/ItemDetails.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/sections/ItemDetails.svelte index 25a342fc..4ac13a67 100644 --- a/ohmg/frontend/svelte/src/lib/components/overviews/sections/ItemDetails.svelte +++ b/ohmg/frontend/svelte/src/lib/components/overviews/sections/ItemDetails.svelte @@ -1,7 +1,7 @@ - -

    Item Details

    -View item in LOC collection - - - - - - - - - - - - - -
    TitleSanborn Map of {ITEM.title}
    Year{ITEM.year}
    Locale{ITEM.locale.display_name}
    -

    Contributors & Attribution

    -
    -

    - {#if ITEM.sheet_ct.loaded == ITEM.sheet_ct.total} - {ITEM.sheet_ct.loaded} of {ITEM.sheet_ct.total} sheet{#if ITEM.sheet_ct.total != 1}s{/if} loaded by {ITEM.loaded_by.name} - {ITEM.loaded_by.date}
    - {/if} - {ITEM.sessions.prep_ct} sheet{#if ITEM.sessions.prep_ct != 1}s{/if} prepared{#if ITEM.sessions.prep_ct > 0} by - {#each ITEM.sessions.prep_contributors as c, n}{c.name} ({c.ct}){#if n != ITEM.sessions.prep_contributors.length-1}, {/if}{/each}{/if} -
    - {ITEM.sessions.georef_ct} georeferencing session{#if ITEM.sessions.georef_ct != 1}s{/if}{#if ITEM.sessions.georef_ct > 0} by - {#each ITEM.sessions.georef_contributors as c, n}{c.name} ({c.ct}){#if n != ITEM.sessions.georef_contributors.length-1}, {/if}{/each}{/if} -
    - Credit Line: Library of Congress, Geography and Map Division, Sanborn Maps Collection. -

    -
    -
    -

    Download & Web Services

    - -
    -

    - Only layers that have been trimmed in the MultiMask will appear in the mosaic. You can access untrimmed layers individually through the Georeferenced section. -

    - - - - - - - - - - - - - -
    XYZ Tiles URL - {#if mosaicUrl} -
    {mosaicUrl}
    - {:else} - n/a - {/if} -
    OHM - {#if ohmUrl} - Use in OpenHistoricalMap iD editor - {:else} - n/a - {/if}
    GeoTIFF - {#if ITEM.urls.mosaic_geotiff} - Download GeoTIFF (direct download) - {:else} - n/a - {/if} -
    +
    +

    Item Details

    + View item in LOC collection + + + + + + + + + + + + + +
    TitleSanborn Map of {ITEM.title}
    Year{ITEM.year}
    Locale{ITEM.locale.display_name}
    +

    Contributors & Attribution

    +
    +

    + {#if ITEM.sheet_ct.loaded == ITEM.sheet_ct.total} + {ITEM.sheet_ct.loaded} of {ITEM.sheet_ct.total} sheet{#if ITEM.sheet_ct.total != 1}s{/if} loaded by {ITEM.loaded_by.name} - {ITEM.loaded_by.date}
    + {/if} + {ITEM.sessions.prep_ct} sheet{#if ITEM.sessions.prep_ct != 1}s{/if} prepared{#if ITEM.sessions.prep_ct > 0} by + {#each ITEM.sessions.prep_contributors as c, n}{c.name} ({c.ct}){#if n != ITEM.sessions.prep_contributors.length-1}, {/if}{/each}{/if} +
    + {ITEM.sessions.georef_ct} georeferencing session{#if ITEM.sessions.georef_ct != 1}s{/if}{#if ITEM.sessions.georef_ct > 0} by + {#each ITEM.sessions.georef_contributors as c, n}{c.name} ({c.ct}){#if n != ITEM.sessions.georef_contributors.length-1}, {/if}{/each}{/if} +
    + Credit Line: Library of Congress, Geography and Map Division, Sanborn Maps Collection. +

    +
    +
    +

    Download & Web Services

    + +
    +

    + Only layers that have been trimmed in the MultiMask will appear in the mosaic. You can access untrimmed layers individually through the Georeferenced section. +

    + + + + + + + + + + + + + +
    XYZ Tiles URL + {#if mosaicUrl} +
    {mosaicUrl}
    + {:else} + n/a + {/if} +
    OHM + {#if ohmUrl} + Open in OpenHistoricalMap iD editor + {:else} + n/a + {/if}
    GeoTIFF + {#if ITEM.urls.mosaic_geotiff} + Download GeoTIFF (direct download) + {:else} + n/a + {/if} +
    +
    \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/sections/ResourceDetails.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/sections/ResourceDetails.svelte new file mode 100644 index 00000000..edfdb8ff --- /dev/null +++ b/ohmg/frontend/svelte/src/lib/components/overviews/sections/ResourceDetails.svelte @@ -0,0 +1,177 @@ + + + + +

    Resource Details

    + + + + + + + + + +
    TitleSanborn Map of {RESOURCE.title}
    Status{RESOURCE.status}
    +
    +

    Downloads & Web Services

    + +
    + + + + + + + + + + + + + + + + + +
    Image + {#if jpegUrl} + JPEG + {/if} + {#if cogUrl} + • + GeoTIFF + {/if} +
    Ground Control Points + {#if gcpsGeojsonUrl} + GeoJSON + + {:else} + n/a + {/if} +
    XYZ Tiles URL + {#if xyzUrl} +
    {xyzUrl}
    + {:else} + n/a + {/if} +
    OHM + {#if ohmUrl} + Open in OpenHistoricalMap iD editor + {:else} + n/a + {/if}
    + + \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/pages/Home.svelte b/ohmg/frontend/svelte/src/lib/pages/Home.svelte index e23a0c61..9850968f 100644 --- a/ohmg/frontend/svelte/src/lib/pages/Home.svelte +++ b/ohmg/frontend/svelte/src/lib/pages/Home.svelte @@ -38,7 +38,7 @@

    OldInsuranceMaps.net

    -

    A crowdsourcing site for creating and viewing georeferenced mosaics of historical fire insurance maps from the Library of Congress. See how it works or visit the about or FAQ pages to learn more.

    +

    A crowdsourcing site for creating and viewing georeferenced mosaics of historical fire insurance maps from the Library of Congress. See how it works or visit the about or FAQ pages to learn more.

    @@ -140,7 +140,7 @@

    Latest activity

    all activity

    - +
    diff --git a/ohmg/frontend/svelte/src/lib/pages/Place.svelte b/ohmg/frontend/svelte/src/lib/pages/Place.svelte index 70c295cc..1e2b9eae 100644 --- a/ohmg/frontend/svelte/src/lib/pages/Place.svelte +++ b/ohmg/frontend/svelte/src/lib/pages/Place.svelte @@ -14,10 +14,10 @@ export let OHMG_API_KEY; let reinitList = [{}] -let onlySLMaps = true; +let showAllSublocales = false; $: subLocales = PLACE.descendants $: subLocalesWithMaps = PLACE.descendants.filter(function (i) {return i.volume_count_inclusive != 0}) -$: localeList = onlySLMaps ? subLocalesWithMaps : subLocales +$: localeList = showAllSublocales ? subLocales : subLocalesWithMaps function update(place_slug) { // take a --- selection to mean clear that category, so re-fetch the parent @@ -45,6 +45,8 @@ $: sideLinks = PLACE.volumes.length > 0 ? [ }, ] : []; +$: VIEWER_LINK = PLACE.volumes.length > 0 ? `/viewer/${PLACE.slug}/` : ''; + @@ -76,7 +78,7 @@ $: sideLinks = PLACE.volumes.length > 0 ? [ {/each}
    - +
    {#if PLACE.parents.length > 0} @@ -93,7 +95,9 @@ $: sideLinks = PLACE.volumes.length > 0 ? [ {/if} {#if PLACE.descendants.length > 0}

    Sub-locales

    - +
    + +
    {#if localeList.length > 0}
      {#each localeList as d} @@ -152,6 +156,7 @@ button:disabled { } .sub-list { padding: 0; + margin: 0; list-style: none; max-height: calc(100vh - 435px); overflow-y: scroll; From ffcb2db99e1cbf7f18e750621e033400dbbb3c95 Mon Sep 17 00:00:00 2001 From: Adam Cox Date: Mon, 5 Feb 2024 20:15:13 -0600 Subject: [PATCH 39/40] cleanup, fix download file names --- .../src/lib/components/overviews/Item.svelte | 21 ------------------- .../lib/components/overviews/Profile.svelte | 4 ++-- .../lib/components/overviews/Resource.svelte | 12 +++++++---- .../overviews/sections/ItemDetails.svelte | 17 ++++++++------- .../overviews/sections/ResourceDetails.svelte | 15 +++++-------- 5 files changed, 24 insertions(+), 45 deletions(-) diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/Item.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/Item.svelte index 3d624818..87017460 100644 --- a/ohmg/frontend/svelte/src/lib/components/overviews/Item.svelte +++ b/ohmg/frontend/svelte/src/lib/components/overviews/Item.svelte @@ -558,15 +558,6 @@ a.no-link { text-decoration:unset; } -/* h2 { - font-size: 1.6em; -} - -h3 { - font-size: 1.3em; - margin-top: 15px; -} */ - section { border-bottom: 1px solid rgb(149, 149, 149); } @@ -575,18 +566,6 @@ section.subsection { border-bottom: 1px dashed rgb(149, 149, 149); } -.subsection-inline-header { - border-bottom: 1px dashed rgb(149, 149, 149); - height: 12px; - margin-bottom: 25px; -} - -.subsection-inline-header > h3 { - display: inline; - background: rgb(234, 224, 193); - padding-right: 5px; -} - button.section-toggle-btn { display: flex; justify-content: space-between; diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/Profile.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/Profile.svelte index dbd3e1f3..6bde7959 100644 --- a/ohmg/frontend/svelte/src/lib/components/overviews/Profile.svelte +++ b/ohmg/frontend/svelte/src/lib/components/overviews/Profile.svelte @@ -79,7 +79,7 @@ button.section-toggle-btn { padding: 0; } -button.section-toggle-btn, a { +button.section-toggle-btn { text-decoration: none; } @@ -87,7 +87,7 @@ button.section-toggle-btn:hover { color: #1b4060; } -button.section-toggle-btn:disabled, button.section-toggle-btn:disabled > a { +button.section-toggle-btn:disabled { color: grey; } diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/Resource.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/Resource.svelte index 9d40a4d1..a0023107 100644 --- a/ohmg/frontend/svelte/src/lib/components/overviews/Resource.svelte +++ b/ohmg/frontend/svelte/src/lib/components/overviews/Resource.svelte @@ -437,7 +437,7 @@ button.section-toggle-btn { padding: 0; } -button.section-toggle-btn, a { +button.section-toggle-btn { text-decoration: none; } @@ -445,10 +445,14 @@ button.section-toggle-btn:hover { color: #1b4060; } -button.section-toggle-btn:disabled, button.section-toggle-btn:disabled > a { +button.section-toggle-btn:disabled { color: grey; } +/* button.section-toggle-btn:disabled > a { + color: grey; +} */ + .section-body { margin: 10px 0px; } @@ -534,11 +538,11 @@ section.breadcrumbs { border-bottom: none; } -select.item-select { +/* select.item-select { margin-right: 3px; color: #2c689c; cursor: pointer; -} +} */ :global(section.breadcrumbs svg) { margin: 0px 2px; diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/sections/ItemDetails.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/sections/ItemDetails.svelte index 4ac13a67..00cc52e5 100644 --- a/ohmg/frontend/svelte/src/lib/components/overviews/sections/ItemDetails.svelte +++ b/ohmg/frontend/svelte/src/lib/components/overviews/sections/ItemDetails.svelte @@ -72,7 +72,7 @@ GeoTIFF {#if ITEM.urls.mosaic_geotiff} - Download GeoTIFF (direct download) + Download GeoTIFF (direct download) {:else} n/a {/if} @@ -103,7 +103,7 @@ padding: 4px; } - caption { + /* caption { width: 100%; font-size: .9em; } @@ -111,16 +111,17 @@ table caption { color: #333; text-align: left; - } + } */ - th, td { + td { padding: 4px; } - th { + /* th { font-variant: small-caps; font-size: .85em; - } + padding: 4px; + } */ /* tr:nth-child(even) { background-color: #f6f6f6; @@ -139,9 +140,9 @@ width: 150px; } - button.thumbnail-btn { + /* button.thumbnail-btn { border: none; background: none; cursor: zoom-in; - } + } */ \ No newline at end of file diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/sections/ResourceDetails.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/sections/ResourceDetails.svelte index edfdb8ff..dab67661 100644 --- a/ohmg/frontend/svelte/src/lib/components/overviews/sections/ResourceDetails.svelte +++ b/ohmg/frontend/svelte/src/lib/components/overviews/sections/ResourceDetails.svelte @@ -81,11 +81,11 @@ Image {#if jpegUrl} - JPEG + JPEG {/if} {#if cogUrl} • - GeoTIFF + GeoTIFF {/if} @@ -137,7 +137,7 @@ justify-content:space-between; } - .non-table-section { + /* .non-table-section { background-color: #ffffff; border: 1px solid #ddd; border-radius: 4px; @@ -147,17 +147,12 @@ table caption { color: #333; text-align: left; - } + } */ - th, td { + td { padding: 4px; } - th { - font-variant: small-caps; - font-size: .85em; - } - /* tr:nth-child(even) { background-color: #f6f6f6; } From 57ac3bcfc4c289791903b093fdb17b4f07b9f46e Mon Sep 17 00:00:00 2001 From: Adam Cox Date: Fri, 9 Feb 2024 12:05:25 -0600 Subject: [PATCH 40/40] hide load button from anonymous users --- ohmg/frontend/svelte/src/lib/components/overviews/Item.svelte | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ohmg/frontend/svelte/src/lib/components/overviews/Item.svelte b/ohmg/frontend/svelte/src/lib/components/overviews/Item.svelte index 87017460..4d5b97fc 100644 --- a/ohmg/frontend/svelte/src/lib/components/overviews/Item.svelte +++ b/ohmg/frontend/svelte/src/lib/components/overviews/Item.svelte @@ -42,7 +42,7 @@ export let TITILER_HOST; console.log(VOLUME) let userCanEdit = false; -userCanEdit = USER.is_staff || VOLUME.access == "any" || (VOLUME.access == "sponsor" && VOLUME.sponsor == USER.username) +userCanEdit = USER.is_staff || (VOLUME.access == "any" && USER.is_authenticated) || (VOLUME.access == "sponsor" && VOLUME.sponsor == USER.username) let currentIdentifier = VOLUME.identifier function goToItem() { @@ -57,7 +57,6 @@ $: sheetsLoading = VOLUME.status == "initializing..."; let hash = window.location.hash.substr(1); -console.log(!hash) const sectionVis = { "summary": (!hash && VOLUME.items.layers.length == 0) || hash == "summary", "preview": (!hash && VOLUME.items.layers.length > 0) || hash == "preview", @@ -192,7 +191,6 @@ if (VOLUME.urls.mosaic_geotiff) { const ll = getCenter(VOLUME.extent); ohmUrl = `https://www.openhistoricalmap.org/edit#map=16/${ll[1]}/${ll[0]}&background=custom:${mosaicUrlEncoded}` } -console.log(ohmUrl, mosaicUrl) let settingKeyMapLayer = false;