├── .flake8 ├── .gitattributes ├── .github └── workflows │ ├── build-sphinx.yml │ └── codeql-analysis.yml ├── .gitignore ├── .graphics ├── assets.png ├── caltech-round.png ├── caltech-round.svg └── status-warning.svg ├── CHANGES.md ├── CITATION.cff ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── INSTALL-Python3.md ├── INSTALL.txt ├── LICENSE ├── Makefile ├── People-Manager.md ├── README.md ├── SUPPORT.md ├── adapter.wsgi ├── admin ├── .media │ └── dropdown-menu.png ├── README.md ├── export-data ├── how-to-reset-the-folio-token-for-dibs.md ├── import-data ├── load-mock-data ├── loan-manager ├── people-manager ├── run-server ├── set-server-permissions ├── test-folio-token └── update-item-data ├── codemeta.json ├── data ├── manifests │ ├── 350470000180226-manifest.json │ └── README.md ├── processing │ └── README.md └── thumbnails │ ├── 350470000180226.jpg │ └── README.md ├── dev ├── graphics │ ├── diagrams │ │ └── architecture-diagram │ │ │ ├── README.md │ │ │ ├── dibs-architecture.graffle │ │ │ ├── dibs-architecture.jpg │ │ │ ├── dibs-architecture.png │ │ │ ├── dibs-architecture.svg │ │ │ └── omnigraffle-export-options.png │ ├── icons │ │ ├── README.md │ │ ├── dibs-icon.svg │ │ ├── missing-thumbnail.svg │ │ ├── noun_Book_2349054.svg │ │ ├── noun_Megaphone_505098.svg │ │ └── noun_book waiting_1531542.svg │ └── images │ │ └── missing-books │ │ ├── IMG_1001.JPG │ │ ├── LICENSE │ │ └── README.md ├── requirements-dev.txt └── scripts │ ├── check-json-manifests.bash │ ├── convert-permalinks.py │ ├── save-history-table.bash │ └── update-person-schema.sql ├── dibs.conf-example ├── dibs ├── __init__.py ├── data_models.py ├── date_utils.py ├── email.py ├── image_utils.py ├── lsp.py ├── people.py ├── preflight.py ├── roles.py ├── server.py ├── settings.py ├── static │ ├── dibs-icon.svg │ ├── dibs-uv.css │ ├── dibs.css │ ├── dibs.js │ ├── favicon.ico │ ├── megaphone-white.svg │ ├── megaphone.svg │ ├── missing-thumbnail.svg │ ├── missing.jpg │ └── uv-config.json └── templates │ ├── 404.tpl │ ├── README.md │ ├── about.tpl │ ├── common │ ├── banner.html │ ├── bar.tpl │ ├── footer.tpl │ ├── navbar.tpl │ └── standard-inclusions.tpl │ ├── edit.tpl │ ├── error.tpl │ ├── info.tpl │ ├── item.tpl │ ├── list.tpl │ ├── login.tpl │ ├── manage.tpl │ ├── stats.tpl │ ├── thankyou.tpl │ └── uv.tpl ├── docs ├── .nojekyll ├── Makefile ├── Notes.md ├── README.md ├── _presentations │ ├── 2021-03-08 CNI Spring meeting │ │ ├── CNI Spring 2021 Virtual Membership Meeting: Implementing Controlled Digital Lending....pdf │ │ └── Controlled Digital Lending as a core library service.pdf │ ├── 2021-05-19 CDL Implementers Forum │ │ ├── CDL Implementers - Events Calendar.pdf │ │ └── Caltech DIBS overview 2021-05-19.pdf │ ├── 2021-06-02 WOLFcon panel │ │ ├── Caltech DIBS WOLFcon.pdf │ │ └── WOLFcon 2021 CDL and resource access and sharing.pdf │ └── README.md ├── _static │ ├── css │ │ └── custom.css │ ├── media │ │ ├── add-item-page.png │ │ ├── architecture-diagram.svg │ │ ├── bottom-of-list-page.png │ │ ├── caltech-round.png │ │ ├── dibs-icon-sm.png │ │ ├── dibs-icon-white-sm.png │ │ ├── dibs-icon-white.png │ │ ├── dibs-icon-white.svg │ │ ├── dibs-icon.png │ │ ├── dibs-icon.svg │ │ ├── dropdown-menu.png │ │ ├── edit-item-page.png │ │ ├── favicon.ico │ │ ├── item-availability-checkbox.png │ │ ├── item-not-available.png │ │ ├── item-page.png │ │ ├── item-processing-hourglass.png │ │ ├── item-processing-problem.png │ │ ├── list-page.png │ │ ├── loan-ended.png │ │ ├── loan-in-viewer-thumbnails.png │ │ ├── loan-in-viewer.png │ │ ├── manage-item-list-page.png │ │ ├── manage-items-page-buttons.png │ │ ├── process-button.png │ │ ├── sso.png │ │ ├── stats-page-buttons.png │ │ ├── stats-page.png │ │ └── welcome-page.png │ └── versions.json ├── architecture.md ├── colophon.md ├── conf.py ├── faqs.md ├── general.md ├── history.md ├── index.md ├── installation.md ├── references.md └── usage.md ├── htdocs ├── README.md └── index.html ├── requirements.txt ├── settings.ini-example ├── setup.cfg ├── setup.py ├── tests ├── test_date_utils.py ├── test_init.py ├── test_lsp.py └── test_resolved_path.py └── viewer ├── README.md ├── favicon.ico ├── helpers.js ├── img └── pixel.gif ├── lib ├── AVComponent.js ├── Detector.js ├── GLTFLoader.js ├── GalleryComponent.js ├── MTLLoader.js ├── MetadataComponent.js ├── OBJLoader.js ├── PLYLoader.js ├── TreeComponent.js ├── VRControls.js ├── VREffect.js ├── WebVR.js ├── dash.all.min.js ├── hls.min.js ├── iiifgallery.proxy.js ├── index.esm.js ├── jquery-ui.min.js ├── jquery.binarytransport.js ├── jquery.ui.touch-punch.min.js ├── mediaelement-and-player.js ├── offline.js ├── openseadragon.min.js ├── p-2597ae36.system.js ├── p-30b7f65b.js ├── p-50ea2036.system.js ├── p-5b416380.system.js ├── p-a25b52a9.system.js ├── p-a614138e.system.js ├── p-d0882b30.js ├── p-d8631f0b.js ├── p-p4r1bdpj.system.entry.js ├── p-r5bfv5hp.entry.js ├── pdf.combined.js ├── pdfobject.js ├── stats.min.js ├── three.min.js ├── uv-av-extension-dependencies.js ├── uv-av-extension.cy-GB.config.json ├── uv-av-extension.en-GB.config.json ├── uv-av-extension.fr-FR.config.json ├── uv-av-extension.sv-SE.config.json ├── uv-default-extension-dependencies.js ├── uv-default-extension.cy-GB.config.json ├── uv-default-extension.en-GB.config.json ├── uv-default-extension.fr-FR.config.json ├── uv-default-extension.sv-SE.config.json ├── uv-ebook-components.css ├── uv-ebook-components.esm.js ├── uv-ebook-components.js ├── uv-ebook-extension-dependencies.js ├── uv-ebook-extension.cy-GB.config.json ├── uv-ebook-extension.en-GB.config.json ├── uv-ebook-extension.fr-FR.config.json ├── uv-ebook-extension.proxy.js ├── uv-ebook-extension.sv-SE.config.json ├── uv-mediaelement-extension-dependencies.js ├── uv-mediaelement-extension.cy-GB.config.json ├── uv-mediaelement-extension.en-GB.config.json ├── uv-mediaelement-extension.fr-FR.config.json ├── uv-mediaelement-extension.sv-SE.config.json ├── uv-pdf-extension-dependencies.js ├── uv-pdf-extension.cy-GB.config.json ├── uv-pdf-extension.en-GB.config.json ├── uv-pdf-extension.fr-FR.config.json ├── uv-pdf-extension.sv-SE.config.json ├── uv-seadragon-extension-dependencies.js ├── uv-seadragon-extension.cy-GB.config.json ├── uv-seadragon-extension.en-GB.config.json ├── uv-seadragon-extension.fr-FR.config.json ├── uv-seadragon-extension.sv-SE.config.json ├── uv-seadragon-extension.xx-XX.config.json ├── uv-virtex-extension-dependencies.js ├── uv-virtex-extension.cy-GB.config.json ├── uv-virtex-extension.en-GB.config.json ├── uv-virtex-extension.fr-FR.config.json ├── uv-virtex-extension.sv-SE.config.json ├── virtex.js └── waveform-data.js ├── themes ├── uv-cy-gb-theme │ ├── assets │ │ └── uv-mediaelementcenterpanel-module │ │ │ └── mejs-controls.svg │ └── css │ │ ├── uv-av-extension │ │ └── theme.css │ │ ├── uv-default-extension │ │ └── theme.css │ │ ├── uv-ebook-extension │ │ └── theme.css │ │ ├── uv-mediaelement-extension │ │ └── theme.css │ │ ├── uv-pdf-extension │ │ └── theme.css │ │ ├── uv-seadragon-extension │ │ └── theme.css │ │ └── uv-virtex-extension │ │ └── theme.css └── uv-en-gb-theme │ ├── assets │ ├── hamburger.png │ └── uv-mediaelementcenterpanel-module │ │ └── mejs-controls.svg │ └── css │ ├── uv-av-extension │ └── theme.css │ ├── uv-default-extension │ └── theme.css │ ├── uv-ebook-extension │ └── theme.css │ ├── uv-mediaelement-extension │ └── theme.css │ ├── uv-pdf-extension │ └── theme.css │ ├── uv-seadragon-extension │ └── theme.css │ └── uv-virtex-extension │ └── theme.css ├── uv.css ├── uv.html └── uv.js /.flake8: -------------------------------------------------------------------------------- 1 | # =========================================================== -*- conf-toml -*- 2 | # @file .flake8 3 | # @brief Project-wide Flake8 configuration 4 | # @created 2022-04-26 5 | # @license Please see the file named LICENSE in the project directory 6 | # @website https://github.com/caltechlibrary/dibs 7 | # 8 | # Note: as of version 4.0, flake8 does NOT read global configuration files 9 | # from ~/.flake8 or ~/.config/flake8. If you had such a config file of your 10 | # own, and you're looking at this config file and wondering how the two will 11 | # interaction, the answer is simple: they won't. Only this file matters. 12 | # 13 | # The following flake8 plugins are assumed to be installed: 14 | # flake8-bugbear 15 | # flake8-builtins 16 | # flake8-comprehensions 17 | # flake8-executable 18 | # flake8-implicit-str-concat 19 | # flake8-pie 20 | # flake8_simplify 21 | # ============================================================================= 22 | 23 | [flake8] 24 | ignore = 25 | # We prefer to put spaces around the = in keyword arg lists. 26 | E251, 27 | # We try to stick to 80 chars but don't want to be hung up on it. 28 | E501, 29 | # We prefer two lines between methods of a class. 30 | E303, 31 | # Sometimes we want to align keywords, and these rules run counter to it. 32 | E221, 33 | E271, 34 | # In some situations, it's more readable to omit spaces around operators 35 | # and colons. 36 | E203, 37 | E226, 38 | # According to Flake8 docs at https://www.flake8rules.com/rules/W503.html 39 | # line breaks *should* come before a binary operator, but as of version 4, 40 | # Flake8 still flags the breaks as bad. So: 41 | W503 42 | 43 | per-file-ignores = 44 | dibs/preflight.py: E241 45 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # -*- mode: sh; -*- 2 | 3 | # Set the default behavior, in case people don't have core.autocrlf set. 4 | # ............................................................................. 5 | 6 | * text=auto 7 | 8 | # Specify what's text and should be normalized. 9 | # ............................................................................. 10 | 11 | *.py text 12 | *.in text 13 | *.rst text 14 | *.cfg text 15 | *.ini text 16 | *.yml text 17 | *.json text 18 | *.bat text 19 | *.sh text 20 | LICENSE text 21 | CONTRIBUTING text 22 | 23 | # Denote all files that are truly binary and should not be modified. 24 | # ............................................................................. 25 | 26 | *.png binary 27 | *.jpg binary 28 | *.xls binary 29 | *.doc binary 30 | 31 | # This next one is because in other projects, we've had problems with git 32 | # getting confused about line endings when people using Windows and Mac edit 33 | # the same files. 34 | # ............................................................................. 35 | 36 | *.csv binary diff=csv 37 | -------------------------------------------------------------------------------- /.github/workflows/build-sphinx.yml: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # @file build-myst.yml 3 | # @brief GitHub Actions workflow to build DIBS docs using MyST 4 | # @author Michael Hucka 5 | # @license Please see the file named LICENSE in the project directory 6 | # @website https://github.com/caltechlibrary/dibs 7 | # 8 | # This workflow file was originally based on work by GitHub user "peaceiris": 9 | # https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-static-site-generators-with-python 10 | # ============================================================================= 11 | 12 | name: Update docs on GitHub 13 | 14 | on: 15 | push: 16 | branches: 17 | - develop 18 | - main 19 | 20 | jobs: 21 | deploy: 22 | runs-on: ubuntu-18.04 23 | steps: 24 | - uses: actions/checkout@v2 25 | 26 | - name: Set up Python 27 | uses: actions/setup-python@v2 28 | with: 29 | python-version: '3.8' 30 | 31 | - name: Upgrade pip 32 | run: | 33 | # install pip=>20.1 to use "pip cache dir" 34 | python3 -m pip install --upgrade pip 35 | 36 | - name: Get pip cache dir 37 | id: pip-cache 38 | run: echo "::set-output name=dir::$(pip cache dir)" 39 | 40 | - name: Cache dependencies 41 | uses: actions/cache@v2 42 | with: 43 | path: ${{ steps.pip-cache.outputs.dir }} 44 | key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} 45 | restore-keys: | 46 | ${{ runner.os }}-pip- 47 | 48 | - name: Install dependencies 49 | run: | 50 | python3 -m pip install "myst-parser[linkify]" 51 | python3 -m pip install sphinx-material 52 | python3 -m pip install sphinxcontrib-mermaid 53 | 54 | - name: Build 55 | run: | 56 | cd docs 57 | make html 58 | 59 | - name: Deploy 60 | uses: peaceiris/actions-gh-pages@v3 61 | with: 62 | github_token: ${{ secrets.GITHUB_TOKEN }} 63 | publish_dir: ./docs/_build/html 64 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main, develop ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main, develop ] 20 | schedule: 21 | - cron: '21 10 * * 2' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'python' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # =========================================================== -*- gitignore -*- 2 | # @file .gitignore 3 | # @brief Files and patterns for files and subdirs that git should ignore 4 | # @date 2022-07-15 5 | # @license Please see the file named LICENSE in the project directory 6 | # @website https://github.com/caltechlibrary/dibs 7 | # 8 | # The approach we suggest is to add ONLY project-specific rules here. Put 9 | # rules that apply to your way of doing things (and the particular tools you 10 | # happen to use) into a global git ignore file as described in the section 11 | # "Configuring ignored files for all repositories on your computer" here: 12 | # https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files 13 | # (accessed on 2022-07-14). For example, Emacs checkpoint and backup files are 14 | # things that are not specific to a given project; rather, Emacs users will 15 | # see them created everywhere, in all projects, because they're a byproduct 16 | # of using Emacs, not a consequence of working on a particular project. Thus, 17 | # they belong in a user's global ignores list, not in this project .gitignore. 18 | # 19 | # A useful starting point for global .gitignore file contents can be found at 20 | # https://github.com/github/gitignore/tree/main/Global (as of 2022-07-14). 21 | # ============================================================================= 22 | 23 | # Ignore backup files created by our Makefile 24 | # ............................................................................. 25 | 26 | *.bak 27 | 28 | # Python-specific things to ignore 29 | # ............................................................................. 30 | 31 | __pycache__/ 32 | *.py[cod] 33 | *$py.class 34 | *.egg-info/ 35 | .eggs/ 36 | .pytest_cache 37 | .coverage 38 | 39 | # Project-specific things to ignore. 40 | # ............................................................................. 41 | 42 | dibs.db 43 | docs/_build 44 | load-staff-members.bash 45 | settings.ini 46 | *.swp 47 | .tern-port 48 | dibs.conf 49 | data/manifests/*-manifest.json 50 | htpasswd 51 | .htpasswd 52 | *.tmp 53 | *.bak 54 | data/processing/*-initiated 55 | data/processing/*-processing 56 | data/processing/*-problem 57 | data/thumbnails/*.jpg 58 | -------------------------------------------------------------------------------- /.graphics/assets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/.graphics/assets.png -------------------------------------------------------------------------------- /.graphics/caltech-round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/.graphics/caltech-round.png -------------------------------------------------------------------------------- /.graphics/caltech-round.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Caltech Icon 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.graphics/status-warning.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Warning: DIBS is still in development. 6 | 7 | 8 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | # YAML 1.2 2 | --- 3 | authors: 4 | - 5 | affiliation: "Caltech Library" 6 | family-names: Hucka 7 | given-names: Michael 8 | orcid: "https://orcid.org/0000-0001-9105-5960" 9 | - 10 | affiliation: "Caltech Library" 11 | family-names: Doiel 12 | given-names: Robert 13 | orcid: "https://orcid.org/0000-0003-0900-6903" 14 | - 15 | affiliation: "Caltech Library" 16 | family-names: Keswick 17 | given-names: Tommy 18 | orcid: "https://orcid.org/0000-0001-5644-440X" 19 | cff-version: "1.1.0" 20 | date-released: 2022-10-13 21 | doi: 10.22002/D1.20029 22 | keywords: 23 | - controlled digital lending 24 | message: "If you use this software, please cite it using these metadata." 25 | repository-code: "https://github.com/caltechlibrary/dibs" 26 | title: "DIBS: An implementation of Controlled Digital Lending" 27 | version: "0.7.0" 28 | ... 29 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | Contributor Covenant Code of Conduct 2 | ==================================== 3 | 4 | ## Our Pledge 5 | 6 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 7 | 8 | ## Our Standards 9 | 10 | Examples of behavior that contributes to creating a positive environment include: 11 | 12 | * Using welcoming and inclusive language 13 | * Being respectful of differing viewpoints and experiences 14 | * Gracefully accepting constructive criticism 15 | * Focusing on what is best for the community 16 | * Showing empathy towards other community members 17 | 18 | Examples of unacceptable behavior by participants include: 19 | 20 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 21 | * Trolling, insulting/derogatory comments, and personal or political attacks 22 | * Public or private harassment 23 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 24 | * Other conduct which could reasonably be considered inappropriate in a professional setting 25 | 26 | ## Our Responsibilities 27 | 28 | Project contributors are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 29 | 30 | Project contributors have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 31 | 32 | ## Scope 33 | 34 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project contributors. 35 | 36 | ## Enforcement 37 | 38 | If a contributor engages in harassing behaviour, the project organizers may take any action they deem appropriate, including warning the offender or expelling them from online forums, online project resources, face-to-face meetings, or any other project-related activity or resource. 39 | 40 | If you are being harassed, notice that someone else is being harassed, or have any other concerns, please contact a member of the project team immediately. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 41 | 42 | ## Attribution 43 | 44 | Portions of this Code of Conduct were adapted from Electron's [Contributor Covenant Code of Conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md), which itself was adapted from the [Contributor Covenant](http://contributor-covenant.org/version/1/4), version 1.4. 45 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Guidelines for contributing to this project 2 | 3 | Any constructive contributions – bug reports, pull requests (code or documentation), suggestions for improvements, and more – are welcome. 4 | 5 | ## Conduct 6 | 7 | Everyone is asked to read and respect the [code of conduct](CODE_OF_CONDUCT.md) before participating in this project. 8 | 9 | ## Coordinating work 10 | 11 | A quick way to find out what is currently in the near-term plans for this project is to look at the [GitHub issue tracker](https://github.com/caltechlibrary/cdl/issues), but the possibilities are not limited to what you see there – if you have ideas for new features and enhancements, please feel free to write them up as a new issue or contact the developers directly! 12 | 13 | ## Submitting contributions 14 | 15 | Please feel free to contact the author directly, or even better, jump right in and use the standard GitHub approach of forking the repo and creating a pull request. When committing code changes and submitting pull requests, please write a clear log message for your commits. 16 | -------------------------------------------------------------------------------- /INSTALL-Python3.md: -------------------------------------------------------------------------------- 1 | # How to install Python version 3.x 2 | 3 | The following instructions focus on getting [Python 3](https://docs.python.org/3/) running on Debian/Ubuntu Linux-based systems as well as on macOS via [MacPorts](https://www.macports.org) or [HomeBrew](https://brew.sh). 4 | 5 | _**Tip**_: If you are running on an Intel-based computers (e.g., most Macs and Windows machines), you can use a Python distribution called [Miniconda](https://docs.conda.io/en/latest/miniconda.html). This is often the easiest approach to getting Python on your machine. If that's not suitable for you for any reason, continue reading! 6 | 7 | 8 | ## A note about Python version issues 9 | 10 | It may be possible to use the default copy of Python provided by your operating system if it happens to be a version 3 edition of Python. As of January 2021, the [oldest still-supported version of Python is 3.6](https://www.python.org/downloads/). However, for historical reasons, many operating system distributions still ship with Python version 2.7 even today. This can be confusing, because the default `python` and `pip` commands provided on these operating systems is version 2.7 of Python; attempting to run programs written for Python version 3 with version 2.7 can result in extremely confusing errors that bear no relationship to the _actual_ problem, which is that the program is not written to run in Python 2.7. 11 | 12 | 13 | ## Installing a recent version of Python and `pip` 14 | 15 | On some systems, version 3.x of the Python interpreter and `pip` are available using the commands `python3` and `pip3`, respectively. More often, they must be installed separately. The following subsections describe how Python 3 can be installed either using the standard software package managers on certain popular operating systems, or using third-party software managers. 16 | 17 | 18 | ### Debian/Ubuntu 19 | 20 | Debian-based systems still ship with older versions of Python by 21 | default. To install a modern version of Python and the associated version of `pip`, run the following command: 22 | 23 | ``` 24 | sudo apt install python3 python3-pip 25 | ``` 26 | 27 | ### macOS 28 | 29 | The version of Python that comes with macOS through at least macOS 10.15 (Catalina) is Python 2.7. The most convenient way to get Python 3.x and the associated version of `pip` is to use [MacPorts](https://www.macports.org) or [HomeBrew](https://brew.sh), depending on your preference. 30 | 31 | 32 | #### _Using MacPorts_ 33 | 34 | If you are using macOS and MacPorts, the following command will install a recent version of Python 3: 35 | 36 | ``` 37 | sudo port install python3 py38-pip 38 | ``` 39 | 40 | After running the command above, you should be able to invoke the Python interpreter using the command `python3`. You can verify the version of Python and `pip` with the following commands: 41 | 42 | ``` 43 | python3 --version 44 | python3 -m pip --version 45 | ``` 46 | 47 | #### _Using HomeBrew_ 48 | 49 | If you are using [HomeBrew](https://brew.sh), the corresponding commands are as follows: 50 | 51 | ``` 52 | brew install python3 53 | ``` 54 | 55 | HomeBrew's Python 3 package installs `pip3` by default. Unless you configured your copy of HomeBrew to install it elsewhere, programs should end up in `/usr/local/bin` on your computer. Look for `pip3` there (e.g., by running the command `ls /usr/local/bin/pip*` to see what gets listed). 56 | -------------------------------------------------------------------------------- /INSTALL.txt: -------------------------------------------------------------------------------- 1 | 2 | Installing DIBS 3 | =============== 4 | 5 | The following are instructions for installing DIBS on an Ubuntu 6 | 20.04.2 LTS host. 7 | 8 | 9 | Requirements 10 | ------------ 11 | 12 | + Python3 and pip 13 | + Apache2 + WSGI 14 | + SQLite3 15 | 16 | 17 | Preparing your machine 18 | ---------------------- 19 | 20 | We can install the general environment via Debian's package 21 | manager. 22 | 23 | sudo apt install apache2 apache2-dev apache2-ssl-dev \ 24 | libapache2-mod-wsgi-py3 python3 python3-pip sqlite3 25 | 26 | 27 | Installing DIBS 28 | --------------- 29 | 30 | 1. Take a look at https://github.com/caltechlibrary/dibs 31 | 2. mkdir a directory to host our app (e.g. /Sites) 32 | 3. Clone dibs into our host directory 33 | 4 Set the group onwership to www-data (the group Apache runs under) 34 | 5. Install Python3 modules required by DIBS 35 | 6. Load test data 36 | 8. Add users 37 | 9. Set permissions 38 | 10. Configure Apache and the dibs application 39 | 40 | All together, in a shell: 41 | 42 | sudo mkdir /Sites && sudo chown www-data.www-data /Sites 43 | cd /Sites || exit 1 44 | git clone https://github.com/caltechlbirary/dibs 45 | cd dibs 46 | sudo chgrp -R www-data . 47 | python3 -m pip install -r requirements.txt 48 | python3 load-mock-data.py # This will configure your SQLite tables 49 | sudo chown www-data.www-data dibs.db 50 | sudo chmod 664 dibs.db 51 | # NOTE: change SOMEUSER to something real 52 | python3 people-manager add uname=SOMEUSER role=library secret= 53 | 54 | 55 | Configuration 56 | ------------- 57 | 58 | 1. Setup Apache2 to support WSGI apps (see dibs.conf-example) 59 | 2. Create settings.ini and edit as needed 60 | 3. Restart apache and test3. Restart apache and test3. Restart apache and test 61 | 62 | In a shell: 63 | 64 | cp settings.ini-example settings.ini 65 | nano settings.ini 66 | cp dibs.conf-example dibs.conf 67 | nano dibs.conf 68 | # NOTE: replace MYSITE with the name of our conf file 69 | # Add an "include" link to include our dibs.conf to setup the WSGI connection. 70 | sudo nano /etd/apache2/sites-enabled/MYSITE.conf 71 | sudo apache2ctl -t && sudo systemctl restart apache2 72 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021-2022, Caltech 2 | All rights not granted herein are expressly reserved by Caltech. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /People-Manager.md: -------------------------------------------------------------------------------- 1 | 2 | # People Manager 3 | 4 | DIBS is intended to be used with a single sign-on system 5 | (SSO) but there remains a need to create and manage access 6 | to service accounts outside of SSO. This includes assigning 7 | application level roles while still using SSO for authentication. 8 | 9 | Since modifing user access is an infrequent activity managing 10 | people associated with the DIBS web application is handled through 11 | a simple command line tool. This minimized the need for either 12 | exposing user management to the web (removing an attack serface). 13 | On the backend CLI are easy to build and require minimal support 14 | as they are used by system administrative staff. 15 | 16 | ## Person Data Model 17 | 18 | DIBS supports a simple Person data model. It consists of the following 19 | attributes. 20 | 21 | uname 22 | : The username, e.g. email addresss, associated with accessing DIBS 23 | 24 | secret 25 | : If SSO is not being used this is that password used to authenticate. 26 | a empty password means the account is disabled unless SSO is used. 27 | 28 | display_name 29 | : The display name on screen, e.g. "Jane Doe" 30 | 31 | role 32 | : This is text string used to assocated a role. Initially there is 33 | one role allowing administrative access and that role is "library". 34 | If the role field is an empty string no role is assigned so patron 35 | is emplied. 36 | 37 | updated 38 | : This is a timestamp of when the Person object was last updated 39 | 40 | No additional information is stored in the Person model. This is 41 | based on all identifying information becoming toxic over time. 42 | Ideally only library staff are included in the person table holding 43 | the Person module data. If SSO is used for library staff then no 44 | password needs to be stored in the person table removing one more 45 | angle of attack and data toxicity. 46 | 47 | ## Adding People 48 | 49 | The "add" verb tells the people manager cli you want to add 50 | someone to the person table. The minimum field required is 51 | the "uname". You many also provide the remaining model fields 52 | at the same time. Here is an example of adding a user name 53 | "Jane M. Doe" with a username of "janedoe", and role of "library". 54 | 55 | ```sh 56 | ./people-manager add \ 57 | uname=janedoe \ 58 | display_name="Jane M. Doe" \ 59 | role="library" 60 | ``` 61 | 62 | NOTE: there is no space between the key, equal sign and value. 63 | 64 | If you want to include setting a password without typing it on the 65 | command line then leave the value empty. This is how to create 66 | the Jane Doe account with a password (you will be prompted to 67 | type the password before the command completes). 68 | 69 | ```sh 70 | ./people-manager add \ 71 | uname=janedoe \ 72 | display_name="Jane M. Doe" \ 73 | role="library" \ 74 | secret= 75 | ``` 76 | 77 | If you wanted to create a full Person module and be prompted 78 | for each field you could type the command as 79 | 80 | ```sh 81 | ./people-manager add \ 82 | uname= \ 83 | display_name= \ 84 | role= \ 85 | secret= 86 | ``` 87 | 88 | You would then be prompted for each value individually (sorta 89 | like the Linux `adduser` command). 90 | 91 | 92 | ## Listing People 93 | 94 | DIBS provided the command line program `people-manager` to manage 95 | the Person objects in the system. To list the people defined in 96 | DIBS use the "list" verb. 97 | 98 | ```sh 99 | ./people-manager list 100 | ``` 101 | 102 | To list an inidividual person you need to know their "uname". 103 | If I want to look up the user with a uname of "janedoe" I would 104 | do so by adding the "uname" key value pair on the command line. 105 | 106 | ```sh 107 | ./people-manager list uname=janedoe 108 | ``` 109 | 110 | NOTE: the secert field is **not** displayed. 111 | 112 | ## Updating People 113 | 114 | You can update model attributes individually. Use the "update" verb 115 | instead of "add". This will update an existing Person model. The uname 116 | value can not be changed but all other attributes can be changed. If 117 | you need to change the uname value then add a new record and remove the 118 | old one. 119 | 120 | Updating the display name for `janedoe` to "Jackie Doe". 121 | 122 | ```sh 123 | ./people-manager update uname=janedoe \ 124 | display_name="Jackie Doe" 125 | ``` 126 | 127 | Or to prompt for the display name attribute. 128 | 129 | ```sh 130 | ./people-manager update uname=janedoe \ 131 | display_name= 132 | ``` 133 | 134 | 135 | ## Removing People 136 | 137 | To remove a person from the person table you need to know their uname. 138 | The verb to remove someone is "remove". To remove janedoe from the 139 | table you would do the following. 140 | 141 | ```sh 142 | ./people-manager remove uname=jandoe 143 | ``` 144 | 145 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | Support 2 | ======= 3 | 4 | Thank you for your interest in this project. If you are experiencing problems or have questions, the following are the preferred methods of reaching someone: 5 | 6 | 1. Report a new issue using the [issue tracker](https://github.com/caltechlibrary/cdl/issues). 7 | 2. Send email to the Caltech Library: [helpdesk@library.caltech.edu](mailto:helpdesk@library.caltech.edu). 8 | 3. Send email to an individual involved in the project. People's names appear in the top-level `README.md` file in the source code repository. 9 | -------------------------------------------------------------------------------- /adapter.wsgi: -------------------------------------------------------------------------------- 1 | # ============================================================== -*- python -*- 2 | # @file adapter.wsgi 3 | # @brief WSGI adapter for DIBS 4 | # @created 2021-02-01 5 | # @license Please see the file named LICENSE in the project directory 6 | # @website https://github.com/caltechlibrary/dibs 7 | # ============================================================================= 8 | 9 | # Initial imports. More things are imported later below. 10 | 11 | import bottle 12 | from os import chdir 13 | from os.path import realpath, dirname 14 | from sidetrack import log, set_debug 15 | import sys 16 | from werkzeug.wsgi import get_host, get_script_name 17 | 18 | # The following sets the default directory to the current app's directory, so 19 | # that imports and calls to config(...) work as expected. It also prevents a 20 | # confusing error of the form "FileNotFoundError: No such file or directory: 21 | # '...../adapter.wsgi'" in the Apache or mod_wsgi logs. 22 | 23 | app_directory = realpath(dirname(__file__)) 24 | sys.path.insert(0, app_directory) 25 | chdir(app_directory) 26 | 27 | # Run a preflight check before going much further. 28 | 29 | from dibs.preflight import preflight_check 30 | preflight_check() 31 | 32 | # If we make it this far, import the core pieces. 33 | 34 | from dibs.server import dibs 35 | from dibs.settings import config 36 | 37 | # Notes: 38 | # 39 | # 1) In the function dibs_application() below, we set variable "base_url" on 40 | # "dibs" (our application object). Our application code in dibs/server.py 41 | # relies on this being set. It's set only once. 42 | # 43 | # 2) Mod_wsgi runs this .wsgi adapter with a clean environment; you cannot pass 44 | # arguments to this wrapper. Mod_wsgi expects that you use a separate config 45 | # file or alternative .wsgi scripts for different run-time configurations. 46 | # That's okay, but it makes it difficult if you want to keep things simple 47 | # and not use multiple adapter files. So, the approach taken here is to have 48 | # dibs_application(...) do a one-time operation to look for environment 49 | # variables and/or settings.ini values that change some behaviors. It sets a 50 | # flag and skips that step on subsequent invocations. This allows us to do 51 | # some configurations based on environment variables and settings.ini files 52 | # (instead of having different .wsgi files for different configurations), yet 53 | # avoid the inefficiency of doing that at every invocation. Our "run-server" 54 | # script takes advantage of that: it uses mod_wsgi-express's ability to set 55 | # environment variables, and sets debug & verbose options if requested. 56 | # 57 | # 3) Keep in mind that mod_wsgi will normally run multiple processes and/or 58 | # multiple threads (depending on the server configuration), which means this 59 | # module (adapter.wsgi) will be invoked multiple times. 60 | 61 | dibs._config_done = False 62 | 63 | def dibs_application(env, start_response): 64 | '''DIBS wrapper around Bottle WSGI application.''' 65 | if not dibs._config_done: 66 | # VERBOSE in env overrides RUN_MODE which overrides settings.ini. 67 | mode = env.get('RUN_MODE', '') or config('RUN_MODE', default = 'normal') 68 | if env.get('VERBOSE', False) or mode == 'verbose': 69 | set_debug(True, '-', show_package = True) 70 | log('VERBOSE found in env') 71 | 72 | # Determine our base url and set it once. No sense in computing this 73 | # on every call, because it won't change while running. Set a custom 74 | # property on the dibs Bottle object so our server code can read it. 75 | scheme = env.get('wsgi.url_scheme', '') or env.get('REQUEST_SCHEME', '') 76 | host = get_host(env) 77 | path = get_script_name(env) 78 | dibs.base_url = f'{scheme}://{host}{path}' 79 | log(f'dibs.base_url = {dibs.base_url}') 80 | 81 | # Mark this done. 82 | dibs._config_done = True 83 | 84 | # Now call the real DIBS Bottle server to process the request. 85 | return dibs(env, start_response) 86 | 87 | 88 | # Hook in the default WSGI interface application. Mod_wsgi looks for a 89 | # variable named 'application' unless told otherwise. 90 | 91 | application = dibs_application 92 | -------------------------------------------------------------------------------- /admin/.media/dropdown-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/admin/.media/dropdown-menu.png -------------------------------------------------------------------------------- /admin/how-to-reset-the-folio-token-for-dibs.md: -------------------------------------------------------------------------------- 1 | 2 | When folio is updated we need to regerate the token used by DIBs to access the "okapi". The steps below are what we do at Caltech Library and may reflect a similar setup in your institution. The values in angle brackes should be replaced with your organization's values. 3 | 4 | 1. There is a account that has access to Folio's dashboard. Use the URL: https://.folio.ebsco.com/dashboard 5 | 2. On the dashboard login page in very tiny print (below the fold on my monitor) is a password reset link, the account is just like any other library folio account in this regards (we always reset the password since we have access to the associated EMail account) 6 | 3. The Folio API DIBs uses os the okapi (I think that is the same as the foliage stuff generally). 7 | 4. We have some tools in a private repository that automate generating the new token. They use the Folio API to generate the token. Our `get-api-token` script requires the name and the tenant id found in the "settings.ini" of DIBs. The resulting program generates a file called "okapi-login.json". It needs to have the appropriate permissions for the app to read it. 8 | 5. Copy the generated token displayed by `get-api-token` and update the line in DIB's `settings.ini` with FOLIO_OKAPI_TOKEN 9 | 6. Restart Apache2 to make sure that DIBs is reloaded and the stale token isn't being used. 10 | -------------------------------------------------------------------------------- /admin/load-mock-data: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # ============================================================================= 3 | # @file load-mock-data 4 | # @brief Load some sample data for DIBS 5 | # @created 2021-01-07 6 | # @license Please see the file named LICENSE in the project directory 7 | # @website https://github.com/caltechlibrary/dibs 8 | # ============================================================================= 9 | 10 | from os.path import dirname, join, abspath 11 | from rich import print 12 | from rich.panel import Panel 13 | import sys 14 | 15 | sys.path.append(join(dirname(abspath(__file__)), '..')) 16 | 17 | from dibs.data_models import database, Item, Person # noqa: E402 18 | from dibs.settings import config, resolved_path # noqa: E402 19 | 20 | # Loading dibs.data_models should create a database if it doesn't exist yet. 21 | # Check that the file exists. 22 | db_file = config('DATABASE_FILE', default = 'data/dibs.db') 23 | db_path = resolved_path(db_file) 24 | if not db_path: 25 | text = f'Cannot find DIBS database {db_file or "-- not configured"}' 26 | print(Panel(text, style = 'red', width = len(text) + 4)) 27 | sys.exit(1) 28 | 29 | # Connect to the database. 30 | database.connect() 31 | 32 | # This next one is a demo item. We provide a manifest in ./manifests/ and 33 | # it references an open copy of the book at the Wellcome Collection in the UK. 34 | if not Item.get_or_none(Item.barcode == '350470000180226'): 35 | Item.create(barcode = '350470000180226', 36 | item_id = '2b2e4a55-7d82-4a97-9ed3-62e48b10699c', 37 | item_page = 'https://search.ebscohost.com/login.aspx?direct=true&site=eds-live&scope=site&authtype=ip,guest&profid=eds&custid=s8984125&groupid=main&db=cat08655a&AN=clc.2b2e4a55.7d82.4a97.9ed3.62e48b10699c', 38 | title = 'Bibliographical history of electricity & magnetism, chronologically arranged', 39 | author = 'Mottelay, Paul Fleury', 40 | year = '1922', 41 | publisher = 'C. Griffin & company limited', 42 | edition = '', 43 | num_copies = 1, 44 | duration = 3, 45 | notes = ('This is just a random book chosen because it was' 46 | ' a title we could find in both an external' 47 | ' public IIIF server and our Caltech catalog.'), 48 | ready = True) 49 | 50 | if not Person.select().exists(): 51 | text = 'Now use admin/people-manager to add library staff users' 52 | print(Panel(text, style = 'dark_orange', width = len(text) + 4)) 53 | 54 | if not database.is_closed(): 55 | database.close() 56 | -------------------------------------------------------------------------------- /codemeta.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://doi.org/10.5063/schema/codemeta-2.0", 3 | "@type": "SoftwareSourceCode", 4 | "description": "Caltech Library's Digital Borrowing System", 5 | "name": "dibs", 6 | "codeRepository": "https://github.com/caltechlibrary/dibs", 7 | "issueTracker": "https://github.com/caltechlibrary/dibs/issues", 8 | "license": "https://github.com/caltechlibrary/dibs/blob/master/LICENSE", 9 | "version": "0.7.0", 10 | "author": [ 11 | { 12 | "@type": "Person", 13 | "givenName": "Michael", 14 | "familyName": "Hucka", 15 | "affiliation": "California Institute of Technology Library", 16 | "email": "mhucka@caltech.edu", 17 | "@id": "https://orcid.org/0000-0001-9105-5960" 18 | }, 19 | { 20 | "@type": "Person", 21 | "givenName": "Robert", 22 | "familyName": "Doiel", 23 | "affiliation": "Caltech Library", 24 | "email": "rsdoiel@caltech.edu", 25 | "@id": "https://orcid.org/0000-0003-0900-6903" 26 | }, 27 | { 28 | "@type": "Person", 29 | "givenName": "Tommy", 30 | "familyName": "Keswick", 31 | "affiliation": "California Institute of Technology Library", 32 | "email": "tkeswick@caltech.edu", 33 | "@id": "https://orcid.org/0000-0001-5644-440X" 34 | } 35 | ], 36 | "developmentStatus": "active", 37 | "downloadUrl": "https://github.com/caltechlibrary/dibs/archive/master.zip", 38 | "keywords": [ 39 | "software" 40 | ], 41 | "maintainer": "https://orcid.org/0000-0001-9105-5960" 42 | } 43 | -------------------------------------------------------------------------------- /data/manifests/README.md: -------------------------------------------------------------------------------- 1 | Demo of using IIIF manifests 2 | ============================ 3 | 4 | In its current implementation, the DIBS server responds to the endpoint at `/manifests/NNNNNN` and returns a manifest for an item based on the barcode `NNNNNN`. The manifest is found by looking for a file with a name having the pattern `NNNNNN-manifest.json` in this directory. 5 | 6 | The demo manifest file found here, `350470000363458-manifest.json`, is a copy of the IIIF manifest provided by Wellcome Library for [its copy of The biocrats](https://wellcomelibrary.org/item/b18035978#?c=0&m=0&s=0&cv=0&z=-1.099%2C-0.0809%2C3.1979%2C1.6181). The metadata for this demo manifest is loaded into the demo DIBS database by the script [`../load-mock-data.py`](../load-mock-data.py). 7 | 8 | -------------------------------------------------------------------------------- /data/processing/README.md: -------------------------------------------------------------------------------- 1 | # Processing directory example 2 | 3 | DIBS embodies a simple scheme to interact with an external workflow for automated processing of scans for [IIIF](https://iiif.io). This scheme involves reading and writing files to a directory identified as the value of the variable `PROCESS_DIR` in the [`settings.ini`](../settings.ini-example) file. When a new item is added to DIBS from the `/list` page, a button named **Process** is shown next to the new item; when library staff press that button, DIBS writes a file in the `PROCESS_DIR` location and watches for the presence of other files. The end point of the workflow is assumed to be the appearance of a IIIF manifest for the item in the `MANIFEST_DIR`. 4 | -------------------------------------------------------------------------------- /data/thumbnails/350470000180226.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/data/thumbnails/350470000180226.jpg -------------------------------------------------------------------------------- /data/thumbnails/README.md: -------------------------------------------------------------------------------- 1 | # Thumbnails directory example 2 | 3 | DIBS displays cover image thumbnails on item pages. The present directory is the default location for the thumbnail images. The location of this directory is set by the variable `THUMBNAILS_DIR` in the [`settings.ini`](../settings.ini-example) file; you can use a different directory by changing the value of the variable. The DIBS LSP layer attempts to obtain cover images automatically for each new item added to DIBS, and will store the images in this directory. You can also deliberately put images here manually to override what DIBS uses. 4 | 5 | DIBS assumes that thumbnail images are in [JPEG](https://en.wikipedia.org/wiki/JPEG) format and only recognizes files named according to the pattern `N.jpg`, where `N` is the barcode used to identify the item. (The barcode is typically a long integer.) Note that the file name _must_ end in `.jpg` and _not_ `.jpeg`. 6 | -------------------------------------------------------------------------------- /dev/graphics/diagrams/architecture-diagram/README.md: -------------------------------------------------------------------------------- 1 | # DIBS architecture diagram 2 | 3 |

4 | 5 | The system overview diagram in [dibs-architecture.graffle](dibs-architecture.graffle) was created by Michael Hucka in 2021, using OmniGraffle Pro 7.18.5 on a macOS 10.4.6 computer. The SVG version in [dibs-architecture.svg](dibs-architecture.svg) was produced using the following steps: 6 | 7 | 8 | 9 | 1. Export from OmniGraffle to SVG format, using the options "transparent background" and `0`inch margin. (See screen image at the right.) 10 | 2. Run [svg-buddy](https://github.com/phauer/svg-buddy) on the SVG file produced from step #1. This will embed the fonts used in the SVG file, overcoming a limitation of OmniGraffle's SVG output. The following is the command line used: 11 | ```sh 12 | java -jar svg-buddy.jar dibs-architecture.svg 13 | ``` 14 | 15 | The architecture diagram contains, embedded within it, icons obtained from the Noun Project. All are licensed under the Creative Commons [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/) license. Here are acknowledgments for the original artwork: 16 | 17 | * [Book icon](https://thenounproject.com/search/?q=book&i=2289902) by [vigorn](https://thenounproject.com/vigorn/) 18 | * [Book scanner icon](https://thenounproject.com/search/?q=book+scanner&i=3635943) by [Oleksandr Panasovskyi](https://thenounproject.com/a.panasovsky/) 19 | * [Laptop icon](https://thenounproject.com/search/?q=laptop&i=3563257) by [Hey Rabbit](https://thenounproject.com/heyrabbit/) 20 | * [Tablet icon](https://thenounproject.com/search/?q=tablet&i=205015) by [Emel Çelik](https://thenounproject.com/iconmood/) 21 | -------------------------------------------------------------------------------- /dev/graphics/diagrams/architecture-diagram/dibs-architecture.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/dev/graphics/diagrams/architecture-diagram/dibs-architecture.graffle -------------------------------------------------------------------------------- /dev/graphics/diagrams/architecture-diagram/dibs-architecture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/dev/graphics/diagrams/architecture-diagram/dibs-architecture.jpg -------------------------------------------------------------------------------- /dev/graphics/diagrams/architecture-diagram/dibs-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/dev/graphics/diagrams/architecture-diagram/dibs-architecture.png -------------------------------------------------------------------------------- /dev/graphics/diagrams/architecture-diagram/omnigraffle-export-options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/dev/graphics/diagrams/architecture-diagram/omnigraffle-export-options.png -------------------------------------------------------------------------------- /dev/graphics/icons/README.md: -------------------------------------------------------------------------------- 1 | # Icon sources for DIBS 2 | 3 | The [vector artwork](https://thenounproject.com/term/book-waiting/1531542/) of a book with a clock on it, used as the icon for this project, was created by [Royyan Wijaya](https://thenounproject.com/roywj/) from the Noun Project. It is licensed under the Creative Commons [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/) license. I edited the logo in [Boxy SVG](https://boxy-svg.com), a native SVG editor for macOS to change the icon color to the orange used by Caltech in their logo. 4 | 5 | The [vector artwork](https://thenounproject.com/term/book/2349054/) of a closed book, used in place of missing cover thumbnails, was created by [Scott Desmond](https://thenounproject.com/thezyna/) from the Noun Project. It is licensed under the Creative Commons [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/) license. 6 | 7 | The [vector artwork](https://thenounproject.com/term/megaphone/505098/) of a megaphone was created by [SlideGenius](https://thenounproject.com/slidegenius/) from the Noun Project. It is licensed under the Creative Commons [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/) license. 8 | 9 | -------------------------------------------------------------------------------- /dev/graphics/icons/dibs-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Book waiting 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /dev/graphics/icons/missing-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | book 4 | 5 | Created by scott desmond 6 | from the Noun Project 7 | -------------------------------------------------------------------------------- /dev/graphics/icons/noun_Book_2349054.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | book 4 | 5 | Created by scott desmond 6 | from the Noun Project 7 | -------------------------------------------------------------------------------- /dev/graphics/icons/noun_Megaphone_505098.svg: -------------------------------------------------------------------------------- 1 | Created by SlideGeniusfrom the Noun Project -------------------------------------------------------------------------------- /dev/graphics/icons/noun_book waiting_1531542.svg: -------------------------------------------------------------------------------- 1 | Created by Royyan Wijayafrom the Noun Project -------------------------------------------------------------------------------- /dev/graphics/images/missing-books/IMG_1001.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/dev/graphics/images/missing-books/IMG_1001.JPG -------------------------------------------------------------------------------- /dev/graphics/images/missing-books/README.md: -------------------------------------------------------------------------------- 1 | Missing book image 2 | ================== 3 | 4 |

5 | The photo of missing books in Caltech's Sherman Fairchild Library, used on the DIBS 404 page, was taken by Rebecca Minarez, in January, 2021. IMG_1001.JPG 6 | by Rebecca R. Minjarez 7 | is licensed under 8 | CC BY-NC-SA 4.0. 9 |

10 |

11 | 12 | 13 | 14 | 15 | 16 | 17 |

18 | -------------------------------------------------------------------------------- /dev/requirements-dev.txt: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # @file requirements-dev.txt 3 | # @brief Python dependencies for DIBS for development 4 | # @created 2022-10-04 5 | # @license Please see the file named LICENSE in the project directory 6 | # @website https://github.com/caltechlibrary/dibs 7 | # ============================================================================= 8 | 9 | -r ../requirements.txt 10 | 11 | pytest >= 7.0.0 12 | pytest-cov >= 3.0.0 13 | pytest-flake8 >= 1.1.1 14 | pytest-mock >= 3.7.0 15 | pytest-pydocstyle >= 2.3.0 16 | 17 | flake8 >= 4.0.1, < 5 18 | flake8-bugbear >= 22.4.25 19 | flake8-builtins >= 1.5.3 20 | flake8-comprehensions >= 3.8.0 21 | flake8-executable >= 2.1.1 22 | flake8_implicit_str_concat >= 0.3.0 23 | flake8-pie >= 0.15.0 24 | flake8-simplify >= 0.19.2 25 | -------------------------------------------------------------------------------- /dev/scripts/check-json-manifests.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function check_manifest() { 4 | if ! jq . "$1" > /dev/null; then 5 | echo "ERROR: ${1} failed to parse."; 6 | jq . "${1}" 7 | else 8 | echo "${1}, OK" 9 | fi 10 | } 11 | 12 | ls -1 manifests/*.json | while read FNAME; do 13 | check_manifest "${FNAME}" 14 | done 15 | -------------------------------------------------------------------------------- /dev/scripts/convert-permalinks.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Created 2022-05-03 to rewrite the EDS page URLs after EDS changed the 3 | # permalinks in late April. 4 | # 5 | # This is meant to be run on the dibs-item.json file. 6 | 7 | import json 8 | import sys 9 | 10 | if len(sys.argv[1:]) != 1: 11 | sys.exit('Need 1 argument: original_file') 12 | 13 | input_file = sys.argv[1] 14 | output_file = input_file + '.converted' 15 | 16 | # Note that the AN part here includes the AN prefix. This is so that the loop 17 | # below can simply append the unique ID to this base_url string, to create the 18 | # final page url. 19 | base_url = ('https://search.ebscohost.com/login.aspx?direct=true' 20 | '&AuthType=ip,guest&db=cat09073a&site=eds-live&scope=site' 21 | '&custid=s8984125&groupid=main&profile=eds' 22 | '&AN=cit.oai.folio.org.fs00001057.') 23 | 24 | with open(sys.argv[1], 'r') as f: 25 | # Each item in the list will be a dict. 26 | record_list = json.load(f) 27 | print(f'Converting {len(record_list)} records') 28 | for record in record_list: 29 | item_id = record['item_id'] 30 | an_tail = item_id.replace('-', '.') 31 | record['item_page'] = base_url + an_tail 32 | 33 | with open(output_file, 'w') as f: 34 | f.write(json.dumps(record_list)) 35 | 36 | print('Output written to ' + output_file) 37 | -------------------------------------------------------------------------------- /dev/scripts/save-history-table.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DATE_LOG=$(date +%Y-%m-%d) 3 | echo 'History ID, Type, What, Start Time, End Time' >"history-${DATE_LOG}.csv" 4 | sqlite3 dibs.db 'SELECT historyid, type, what, start_time, end_time FROM history;' | tr '|' ',' >>"history-${DATE_LOG}.csv" 5 | -------------------------------------------------------------------------------- /dev/scripts/update-person-schema.sql: -------------------------------------------------------------------------------- 1 | BEGIN TRANSACTION; 2 | CREATE TABLE IF NOT EXISTS "person_new" ("id" INTEGER NOT NULL PRIMARY 3 | KEY, "uname" VARCHAR(255) NOT NULL, "role" VARCHAR(255) NOT NULL, "display_name" VARCHAR(255) NOT NULL, "updated" INTEGER NOT NULL); 4 | INSERT INTO person_new SELECT id, uname, role, display_name, updated FROM person; 5 | DROP TABLE person; 6 | ALTER TABLE person_new RENAME TO person; 7 | COMMIT; 8 | -------------------------------------------------------------------------------- /dibs.conf-example: -------------------------------------------------------------------------------- 1 | # 2 | # This file should be included from the Apache site configuration 3 | # (e.g. dibs.conf, dibs-ssl.conf, dibs-le-ssl.conf) for allowing 4 | # static file and WSGI application to run. 5 | # 6 | 7 | # 8 | # Web service 9 | # 10 | # NOTE: the application directory needs to be owned by www-data:www-data 11 | # 12 | # FIXME: Change /Sites/dibs to the appropriate directory and 13 | # where Apache2 expects to find your application. 14 | WSGIDaemonProcess dibs user=www-data group=www-data processes=1 threads=5 15 | WSGIScriptAlias /dibs /Sites/dibs/adapter.wsgi 16 | 17 | Require all granted 18 | 19 | -------------------------------------------------------------------------------- /dibs/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Caltech DIBS (Digital Borrowing System), an implementation of controlled 3 | digital lending by the Caltech Library. 4 | 5 | Copyright 6 | --------- 7 | 8 | Copyright (c) 2021-2022 by the California Institute of Technology. This code 9 | is open-source software released under a 3-clause BSD license. Please see the 10 | file "LICENSE" for more information. 11 | ''' 12 | 13 | # Package metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14 | # 15 | # This is set of variables is to identify the Python software package. These 16 | # values are _not_ presented in the user interface of DIBS, except for the 17 | # version number. The information presented to DIBS users, like the contact 18 | # email address, are set elsewhere, not here. 19 | # 20 | # ╭────────────────────── Notice ── Notice ── Notice ─────────────────────╮ 21 | # | The following values are automatically updated at every release | 22 | # | by the Makefile. Manual changes to these values will be lost. | 23 | # ╰────────────────────── Notice ── Notice ── Notice ─────────────────────╯ 24 | 25 | __version__ = '0.7.0' 26 | __description__ = 'DIBS (Digital Borrowing System) is an implementation of Controlled Digital Lending' 27 | __url__ = 'https://github.com/caltechlibrary/dibs' 28 | __author__ = 'Michael Hucka, Robert S. Doiel, Tommy Keswick, Stephen Davison' 29 | __email__ = 'helpdesk@library.caltech.edu' 30 | __license__ = 'BSD 3-clause' 31 | 32 | 33 | # Miscellaneous utilities. 34 | # ............................................................................. 35 | 36 | def print_version(): 37 | print(f'{__name__} version {__version__}') 38 | print(f'Authors: {__author__}') 39 | print(f'URL: {__url__}') 40 | print(f'License: {__license__}') 41 | -------------------------------------------------------------------------------- /dibs/date_utils.py: -------------------------------------------------------------------------------- 1 | ''' 2 | date_utils.py: miscellaneous date-handling utilities for DIBS 3 | 4 | Copyright 5 | --------- 6 | 7 | Copyright (c) 2021-2022 by the California Institute of Technology. This code 8 | is open-source software released under a 3-clause BSD license. Please see the 9 | file "LICENSE" for more information. 10 | ''' 11 | 12 | import arrow 13 | from datetime import datetime as dt 14 | from datetime import timedelta 15 | 16 | 17 | # Exported functions. 18 | # ............................................................................. 19 | 20 | def human_datetime(value, date_format = "%I:%M %p (%Z) on %Y-%m-%d"): 21 | '''Return a human-friendly string for the given datetime in local time.''' 22 | if not value: 23 | return '' 24 | time = arrow.get(value).to('local').strftime(date_format) 25 | # Stftime has no option to *not* zero-pad the numbers, so we have to do it: 26 | return time.lstrip('0') 27 | 28 | 29 | def round_minutes(time, direction): 30 | '''Round the given time to the minute according in the desired direction.''' 31 | new_minute = (time.minute + (1 if direction == 'up' else 0)) 32 | new_time = time + timedelta(minutes = new_minute - time.minute) 33 | return new_time.replace(second = 0, microsecond = 0) 34 | 35 | 36 | def time_now(): 37 | '''Return datetime.utcnow() but with microseconds zeroed out.''' 38 | return dt.utcnow().replace(microsecond = 0) 39 | -------------------------------------------------------------------------------- /dibs/email.py: -------------------------------------------------------------------------------- 1 | ''' 2 | email.py: email utilities for DIBS 3 | 4 | Copyright 5 | --------- 6 | 7 | Copyright (c) 2021-2022 by the California Institute of Technology. This code 8 | is open-source software released under a 3-clause BSD license. Please see the 9 | file "LICENSE" for more information. 10 | ''' 11 | 12 | from sidetrack import log 13 | import smtplib 14 | from trinomial import anon 15 | 16 | from .date_utils import human_datetime 17 | from .settings import config 18 | 19 | 20 | # Constants used throughout this file. 21 | # ............................................................................. 22 | 23 | # Body of email message sent to users 24 | _EMAIL = '''From: {sender} 25 | To: {user} 26 | Subject: {subject} 27 | 28 | You started a digital loan through DIBS at {start}. 29 | 30 | Title: {item.title} 31 | Author: {item.author} 32 | 33 | The loan period ends at {end} 34 | Link to web viewer: {viewer} 35 | 36 | Please note that DIBS only functions in web browsers that support JavaScript. DIBS is safe to use with JavaScript enabled in your browser and does not contain trackers or advertisements of any kind. 37 | 38 | Information about loan policies can be found at {info_page} 39 | 40 | We hope your experience with DIBS is a pleasant one. Don't hesitate to send us feedback, and please report any problems. You can do it directly via email to {sender} or using our anonymous feedback form at {feedback} 41 | ''' 42 | 43 | 44 | # Exported functions. 45 | # ............................................................................. 46 | 47 | def send_email(user, item, start, end, base_url): 48 | try: 49 | subject = f'DIBS loan for "{item.title}"' 50 | viewer = f'{base_url}/view/{item.barcode}' 51 | info_page = f'{base_url}/info' 52 | body = _EMAIL.format(item = item, 53 | start = human_datetime(start), 54 | end = human_datetime(end), 55 | viewer = viewer, 56 | info_page = info_page, 57 | user = user, 58 | subject = subject, 59 | sender = config('MAIL_SENDER'), 60 | feedback = config('FEEDBACK_URL', default = '')) 61 | log(f'sending mail to {anon(user)} about loan of {item.barcode}') 62 | mailer = smtplib.SMTP(config('MAIL_HOST')) 63 | mailer.sendmail(config('MAIL_SENDER'), [user], body) 64 | except Exception as ex: # noqa PIE786 65 | log(f'unable to send mail: {str(ex)}') 66 | -------------------------------------------------------------------------------- /dibs/image_utils.py: -------------------------------------------------------------------------------- 1 | ''' 2 | image_utils.py: miscellaneous image-handling utilities for DIBS 3 | 4 | Copyright 5 | --------- 6 | 7 | Copyright (c) 2021-2022 by the California Institute of Technology. This code 8 | is open-source software released under a 3-clause BSD license. Please see the 9 | file "LICENSE" for more information. 10 | ''' 11 | 12 | from io import BytesIO 13 | from PIL import Image 14 | 15 | 16 | # Exported functions 17 | # ............................................................................. 18 | 19 | def as_jpeg(byte_array): 20 | '''Convert an image, stored as an array of bytes, into JPEG format.''' 21 | img = Image.open(BytesIO(byte_array)) 22 | img = img.convert('RGB') 23 | buffer = BytesIO() 24 | img.save(buffer, 'JPEG') 25 | img.close() 26 | return buffer.getvalue() 27 | -------------------------------------------------------------------------------- /dibs/preflight.py: -------------------------------------------------------------------------------- 1 | ''' 2 | preflight.py: sanity checks to perform before starting server 3 | 4 | Copyright 5 | --------- 6 | 7 | Copyright (c) 2021-2022 by the California Institute of Technology. This code 8 | is open-source software released under a 3-clause BSD license. Please see the 9 | file "LICENSE" for more information. 10 | ''' 11 | 12 | from commonpy.file_utils import writable, readable 13 | from commonpy.string_utils import print_boxed 14 | from os.path import dirname 15 | from sidetrack import log 16 | 17 | # In order for this to work, it needs to avoid importing anything that might 18 | # in turn cause data_models to be imported. So, keep DIBS imports to a 19 | # minimum and watch the dependencies in the code. 20 | 21 | from .settings import config, resolved_path 22 | 23 | 24 | def preflight_check(database = None): 25 | '''Verify certain critical things are set up & complain if they're not.''' 26 | 27 | successes = [ 28 | verified('LSP_TYPE'), 29 | verified('IIIF_BASE_URL'), 30 | verified('DATABASE_FILE', check_parent_writable = True), 31 | verified('MANIFEST_DIR', check_readable = True), 32 | verified('PROCESS_DIR', check_readable = True, check_writable = True), 33 | verified('THUMBNAILS_DIR', check_readable = True, check_writable = True), 34 | ] 35 | 36 | if all(successes): 37 | log('preflight tests succeeded') 38 | return True 39 | else: 40 | log('preflight tests failed') 41 | return False 42 | 43 | 44 | def verified(variable, check_readable = False, check_writable = False, 45 | check_parent_writable = False): 46 | '''Verify the given configuration 'variable' in various ways.''' 47 | 48 | if not config(variable, default = None): 49 | print_boxed(f'Variable {variable} is not set.\n' 50 | ' DIBS cannot function properly.', 51 | title = 'DIBS Fatal Error') 52 | return False 53 | dir = resolved_path(config(variable)) # noqa A001 54 | success = True 55 | if check_readable and not readable(dir): 56 | print_boxed(f'Cannot read the directory indicated by the configuration\n' 57 | f'variable {variable}. The directory located at\n\n' 58 | f'{dir}\n\nis not readable. DIBS cannot function properly.', 59 | title = 'DIBS configuration error') 60 | success = False 61 | if check_writable and not writable(dir): 62 | print_boxed(f'Cannot write the directory indicated by the configuration\n' 63 | f'variable {variable}. The directory located at\n\n' 64 | f'{dir}\n\nis not writable. DIBS cannot function properly.', 65 | title = 'DIBS configuration error') 66 | success = False 67 | if check_parent_writable and not writable(dirname(dir)): 68 | parent = dirname(dir) 69 | print_boxed(f'Cannot write in the parent directory of the value indicated by\n' 70 | f'the configuraton variable {variable}. The directory located at\n\n' 71 | f'{parent}\n\nis not writable. DIBS cannot function properly.', 72 | title = 'DIBS configuration error') 73 | success = False 74 | return success 75 | -------------------------------------------------------------------------------- /dibs/roles.py: -------------------------------------------------------------------------------- 1 | ''' 2 | roles.py uses a DICT to map a role string to a redirect destination. The 3 | function role_to_redirect(...) provides a safe encapsulation, as the role 4 | application will likely evolve over time. 5 | 6 | Copyright 7 | --------- 8 | 9 | Copyright (c) 2021-2022 by the California Institute of Technology. This code 10 | is open-source software released under a 3-clause BSD license. Please see the 11 | file "LICENSE" for more information. 12 | ''' 13 | 14 | from .data_models import Person 15 | 16 | 17 | _role_table = { 18 | "library": "list", 19 | } 20 | 21 | 22 | def has_role(person, role): 23 | if person is None: 24 | return False 25 | return person.has_role(role) 26 | 27 | 28 | def role_to_redirect(role): 29 | '''Given a user role (including an empty string), return the target 30 | path for a redirect.''' 31 | if role in _role_table: 32 | return _role_table[role] 33 | else: 34 | return '' 35 | 36 | 37 | def staff_user(who): 38 | '''Return True if the person has admin priviledges in the system.''' 39 | if isinstance(who, str): 40 | # Given a user name -- look them up and try to retrieve a Person object. 41 | who = Person.get_or_none(Person.uname == who) 42 | return has_role(who, 'library') 43 | -------------------------------------------------------------------------------- /dibs/static/dibs-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Book waiting 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /dibs/static/dibs.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // @file dibs.js 3 | // @brief JavaScript code for DIBS 4 | // @created 2021-02-25 5 | // @license Please see the file named LICENSE in the project directory 6 | // @website https://github.com/caltechlibrary/dibs 7 | // ============================================================================= 8 | 9 | // General utilities. 10 | // ............................................................................ 11 | 12 | // This next function is based in part on the posting by user Alvaro Montoro 13 | // to Stack Overflow 2015-06-18, https://stackoverflow.com/a/30905277/743730 14 | function copyToClipboard(button, text) { 15 | var aux = document.createElement("input"); 16 | aux.setAttribute("value", text); 17 | document.body.appendChild(aux); 18 | aux.select(); 19 | document.execCommand("copy"); 20 | document.body.removeChild(aux); 21 | 22 | // The following code is based in part on a 2016-09-21 posting to Stack 23 | // Overflow by user Nina Scholz: https://stackoverflow.com/a/39610851/743730 24 | var last = button.innerHTML; 25 | button.innerHTML = 'Copied!'; 26 | clicked = true; 27 | setTimeout(function () { 28 | button.innerHTML = last; 29 | clicked = false; 30 | }.bind(button), 800); 31 | } 32 | 33 | 34 | // Bootstrap Table utilities. 35 | // ............................................................................ 36 | 37 | // This next function was inspired in part by the posting by user "Undry" 38 | // to Stack Overflow 2020-07-16, https://stackoverflow.com/a/62928804/743730 39 | function numberSort(a, b) { 40 | var aa = +((a + '').replace(/[^\d]/g, '')); 41 | var bb = +((b + '').replace(/[^\d]/g, '')); 42 | if (aa < bb) return -1; 43 | if (aa > bb) return 1; 44 | return 0; 45 | } 46 | 47 | function linkedNumberSort(a, b) { 48 | var aa = +(($(a).text() + '').replace(/[^\d]/g, '')); 49 | var bb = +(($(b).text() + '').replace(/[^\d]/g, '')); 50 | if (aa < bb) return -1; 51 | if (aa > bb) return 1; 52 | return 0; 53 | } 54 | 55 | function linkedTextSort(a, b) { 56 | var a = $(a).text(); 57 | var b = $(b).text(); 58 | if (a < b) return -1; 59 | if (a > b) return 1; 60 | return 0; 61 | } 62 | 63 | function dataValueSort(a, b) { 64 | var aa = +(($(a).attr('data-value') + '')); 65 | var bb = +(($(b).attr('data-value') + '')); 66 | if (aa < bb) return -1; 67 | if (aa > bb) return 1; 68 | return 0; 69 | } 70 | 71 | // Debugging utilities. 72 | // ............................................................................ 73 | 74 | // This defines a function log(...) that can be used anywhere in our code to 75 | // print message to the console if the variable "debug_mode" is true. 76 | // 77 | // Usage: execute set_debug(true) in the console to activate it. 78 | 79 | function logFunction() { 80 | var debug = (sessionStorage != null && 81 | sessionStorage.getItem('debug_mode') == 'true'); 82 | return debug ? console.log.bind(window.console, '(DIBS)') : function(){}; 83 | } 84 | 85 | function set_debug(enabled) { 86 | // This only works if DOM storage is available in the browser. 87 | if (sessionStorage == null) { 88 | console.warn("can't set debug mode: browser DOM storage unavailable"); 89 | return false; 90 | } 91 | console.info('(DIBS)', 'debug_mode =', enabled); 92 | sessionStorage.setItem('debug_mode', enabled ? 'true' : 'false'); 93 | Object.defineProperty(this, "log", {get: logFunction}); 94 | return enabled; 95 | } 96 | 97 | Object.defineProperty(this, "log", {get: logFunction}); 98 | 99 | 100 | // HTTP GET function for data polling. 101 | // ............................................................................ 102 | // This is a simple http GET function. It is based on examples at MDN 103 | // Developer site and the satirical Vanilla JS framework site. 104 | 105 | function httpGet(url, contentType, callbackFn) { 106 | let xhr = new XMLHttpRequest(); 107 | let page_url = new URL(window.location.href); 108 | 109 | xhr.onreadystatechange = function () { 110 | // Process the response. 111 | if (xhr.readyState === XMLHttpRequest.DONE) { 112 | if (xhr.status == 200) { 113 | let data = xhr.responseText; 114 | if (contentType === "application/json" && data !== "") { 115 | data = JSON.parse(xhr.responseText); 116 | } 117 | callbackFn(data, ""); 118 | } else { 119 | log('xhr status = ', xhr.status); 120 | callbackFn("", xhr.status); 121 | } 122 | } 123 | }; 124 | 125 | // We always want JSON data. 126 | xhr.open('GET', url, true); 127 | if (contentType !== "") { 128 | xhr.setRequestHeader('Content-Type', contentType); 129 | } 130 | xhr.send(); 131 | }; 132 | -------------------------------------------------------------------------------- /dibs/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/dibs/static/favicon.ico -------------------------------------------------------------------------------- /dibs/static/megaphone-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Icon by SlideGenius for the Noun Project. Originally obtained on 2021-02-09 from https://thenounproject.com/term/megaphone/505098/ 4 | Megaphone 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Created by SlideGenius 14 | from the Noun Project 15 | -------------------------------------------------------------------------------- /dibs/static/megaphone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Icon by SlideGenius for the Noun Project. Originally obtained on 2021-02-09 from https://thenounproject.com/term/megaphone/505098/ 4 | Megaphone 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Created by SlideGenius 14 | from the Noun Project 15 | -------------------------------------------------------------------------------- /dibs/static/missing-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | book 4 | 5 | Created by scott desmond 6 | from the Noun Project 7 | -------------------------------------------------------------------------------- /dibs/static/missing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/dibs/static/missing.jpg -------------------------------------------------------------------------------- /dibs/templates/404.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | %include('common/banner.html') 4 | 5 | %include('common/standard-inclusions.tpl') 6 | Error 7 | 8 | 9 | 10 |
11 | %include('common/navbar.tpl') 12 | 13 |
14 | Photo of missing books by Rebecca Minjarez, Caltech. 18 |

Very sorry, but that seems to be missing …

19 |

We hate when that happens! 20 | Maybe it's been misplaced, or maybe it's really gone. Our 21 | staff will take note of the missing item. Our apologies for the 22 | inconvenience.

23 | 24 |

(Code {{code}}: {{message}})

25 |
26 | 27 | %include('common/footer.tpl') 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /dibs/templates/README.md: -------------------------------------------------------------------------------- 1 | Conventions for DIBS templates 2 | ============================== 3 | 4 | Certain conventions are important to follow consistently in these templates, so that our server code functions properly. 5 | 6 | * When passing a barcode to or from a web page or form, always call the variable `barcode`. 7 | -------------------------------------------------------------------------------- /dibs/templates/about.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | %include('common/banner.html') 4 | 5 | %include('common/standard-inclusions.tpl') 6 | 7 | Caltech DIBS 8 | 9 | 10 | 11 |
12 | %include('common/navbar.tpl') 13 | 14 |
15 |

16 | About DIBS 17 |

18 |

19 | Version {{version}} 20 |

21 |

Caltech DIBS (Digital Borrowing System) is an implementation of Controlled Digital Lending, allowing members of Caltech to borrow materials that are not otherwise available in e-book or other electronic formats. The system was implemented in the year 2021 to help Caltech students and faculty during the global COVID-19 pandemic.

22 | 23 |
24 |

View the help documentation to learn more about DIBS and its use.

25 | 26 |

Send feedback by email to helpdesk@library.caltech.edu or the web form.

27 |
28 | 29 |

DIBS is open-source software. The source code is freely available from GitHub under the terms of a BSD 3-clause license. It was designed and implemented by Michael Hucka, Robert Doiel, Tommy Keswick and Stephen Davison of the Caltech Library's Digital Library Development team. DIBS is written primarily in Python and uses the Universal Viewer and IIIF for displaying scanned books and other items. The icons used on DIBS web pages are from Font Awesome, with additional special icons created by Royyan Wijaya, Scott Desmond and SlideGenius for the Noun Project.

30 | 31 |
32 | 33 | %include('common/footer.tpl') 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /dibs/templates/common/banner.html: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /dibs/templates/common/bar.tpl: -------------------------------------------------------------------------------- 1 | 2 | %if get('value', 0) == 0: 3 | _ 4 | %elif get('value', 0) < 75: 5 | ▁ 6 | %elif get('value', 0) < 150: 7 | ▂ 8 | %elif get('value', 0) < 300: 9 | ▄ 10 | %elif get('value', 0) < 500: 11 | ▆ 12 | %else: 13 | █ 14 | %end 15 | -------------------------------------------------------------------------------- /dibs/templates/common/footer.tpl: -------------------------------------------------------------------------------- 1 |
2 | 5 | 10 | %if feedback_url: 11 | 12 | 13 | Give feedback 14 | 15 | %else: 16 | 17 | About DIBS 18 | 19 | %end 20 |
21 | -------------------------------------------------------------------------------- /dibs/templates/common/navbar.tpl: -------------------------------------------------------------------------------- 1 | %if announcement: 2 | 3 |
4 |
5 | {{!announcement}} 6 |
7 |
8 | %end 9 | 10 | 42 | -------------------------------------------------------------------------------- /dibs/templates/common/standard-inclusions.tpl: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dibs/templates/error.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | %include('common/banner.html') 4 | 5 | %include('common/standard-inclusions.tpl') 6 | Error 7 | 8 | 9 | 10 |
11 | %include('common/navbar.tpl') 12 | 13 |
14 | 18 |
19 | 20 | %include('common/footer.tpl') 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /dibs/templates/info.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | %include('common/banner.html') 4 | 5 | %include('common/standard-inclusions.tpl') 6 | Welcome to DIBS 7 | 8 | 9 | 10 |
11 | %include('common/navbar.tpl') 12 | 13 |
14 |

15 | Welcome to Caltech DIBS 16 |

17 |

18 | The Caltech Library Digital Borrowing System 19 |

20 |

Caltech DIBS is an implementation of Controlled Digital Lending, allowing members of Caltech to borrow materials that are not otherwise available in e-book or other electronic formats. Access to materials in Caltech DIBS is limited to current Caltech faculty, students and staff.

21 |

22 | The following policies are implemented by the system: 23 |

    24 |
  1. The number of copies of each item is determined by the number of physical copies of the corresponding printed work that the Caltech Library has pulled from the shelves. (This is typically a very small number.)
  2. 25 |
  3. Each user may borrow only one item total from the system at any given time.
  4. 26 |
  5. After returning an item, a user cannot borrow that same item again for a period of {{reloan_wait_time}}. They can, however, borrow other items immediately.
  6. 27 |
28 |

29 |

30 | Users are expected to follow the Caltech Honor Code and abide by these policies, and to avoid efforts to copy the materials or circumvent restrictions imposed by DIBS. 31 |

32 |
33 | 34 | %include('common/footer.tpl') 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /dibs/templates/login.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | %include('common/banner.html') 4 | 5 | %include('common/standard-inclusions.tpl') 6 | Welcome to Caltech DIBS 7 | 8 | 9 | 10 |
11 | %include('common/navbar.tpl') 12 | 13 |
14 |
15 |
16 |

17 | Welcome to Caltech DIBS 18 |

19 |

20 | The Caltech Digital Borrowing System 21 |

22 |

Caltech DIBS is an implementation of Controlled Digital Lending, allowing members of Caltech to borrow materials that are not otherwise available in e-book or other electronic formats. The system was implemented in the year 2021 to help Caltech students and faculty during the global COVID-19 pandemic. Access to materials in Caltech DIBS is limited to current Caltech faculty, students and staff.

23 |
24 |
25 |
26 |
27 | 28 | %if get('login_failed', False): 29 |
30 | Ooops! Incorrect user or password. Try again? 31 |
32 | %end 33 | 34 |
35 | 36 | 38 |
39 | 40 |
41 | 42 | 44 |
45 | 46 | 47 |
48 |
49 |
50 | 51 | %include('common/footer.tpl') 52 |
53 | 54 | 55 | -------------------------------------------------------------------------------- /dibs/templates/manage.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | %include('common/banner.html') 4 | 5 | %include('common/standard-inclusions.tpl') 6 | 7 | 8 | List of items currently in Caltech DIBS 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | %include('common/navbar.tpl') 18 | 19 |
20 |

21 | Manage DIBS item list 22 |

23 |
24 | 25 |
26 | 28 | 29 | 30 | 32 | 33 | 35 | 36 | 38 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | %for item in items: 47 | 48 | 55 | 56 | 59 | 60 | 63 | 64 | 67 | 68 | 81 | 82 | %end 83 | 84 |
 
 
Barcode
 
 
Title
 
 
Author
 
 
Year
49 | %if item.item_page != '': 50 | {{item.barcode}} 51 | %else: 52 | {{item.barcode}} 53 | %end 54 | 57 | {{item.title}} 58 | 61 | {{item.author[:50]+"..." if len(item.author) > 50 else item.author}} 62 | 65 | {{item.year}} 66 | 69 |
76 | 77 | 79 |
80 |
85 |
86 | 87 | 98 | 99 |
100 |
101 | 102 | %include('common/footer.tpl') 103 |
104 | 105 | 106 | -------------------------------------------------------------------------------- /dibs/templates/thankyou.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | %include('common/banner.html') 4 | 5 | %include('common/standard-inclusions.tpl') 6 | Thank you 7 | 8 | 9 | 10 |
11 | %include('common/navbar.tpl') 12 | 13 |
14 |

15 | Thank you for using Caltech DIBS! 16 |

17 |

18 | If you experienced any problems or have any suggestions for 19 | this service, please let us know! 20 | %if feedback_url: 21 | You can use our simple 22 | feedback form. 23 | %end 24 |

25 |
26 | 27 | %include('common/footer.tpl') 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/.nojekyll -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # @file Makefile 3 | # @brief Makefile for building docs using Sphinx and MyST 4 | # @created 2021-01-25 5 | # @license Please see the file named LICENSE in the project directory 6 | # @website https://github.com/caltechlibrary/dibs 7 | # ============================================================================= 8 | 9 | # Before we go any further, test if certain programs are available. 10 | # The following is based on the approach posted by Jonathan Ben-Avraham to 11 | # Stack Overflow in 2014 at https://stackoverflow.com/a/25668869 12 | 13 | PROGRAMS_NEEDED = sphinx-build 14 | TEST := $(foreach p,$(PROGRAMS_NEEDED),\ 15 | $(if $(shell which $(p)),_,$(error Cannot find program "$(p)"))) 16 | 17 | 18 | # Gather values that we need ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 | 20 | # You can set the following variables from the command line, and also from 21 | # the environment for the first two. 22 | 23 | SPHINXOPTS ?= 24 | SPHINXBUILD ?= sphinx-build 25 | SPHINXAUTO = sphinx-autobuild 26 | SOURCEDIR = . 27 | BUILDDIR = _build 28 | 29 | # Actions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 30 | 31 | # Put it first so that "make" without argument is like "make help". 32 | help: 33 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 34 | 35 | auto autobuild live livehtml: 36 | @$(SPHINXAUTO) "$(SOURCEDIR)" "$(BUILDDIR)"/html $(SPHINXOPTS) $(O) 37 | 38 | # Catch-all target: route all unknown targets to Sphinx using the new 39 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 40 | %: Makefile 41 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 42 | 43 | 44 | # Cleanup and miscellaneous directives ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | 46 | .PHONY: help auto autobuild livehtml Makefile 47 | -------------------------------------------------------------------------------- /docs/Notes.md: -------------------------------------------------------------------------------- 1 | 2 | Notes 3 | ===== 4 | 5 | This are talking points based on questions that have come from presentations 6 | about DIBS: 7 | 8 | + DIBS requires a human processes in addition to the software 9 | + DIBS requires a IIIF server in addition to DIBS 10 | + DIBS requires an authentication service (e.g. Shibboleth, Apache BasicAuth) 11 | + DIBS is not about automation 12 | + DIBS is about providing access to materials via a standard viewer using IIIF 13 | + DIBS, as a CDL implementation, isn't a cost cutting tool 14 | + DIBS is not intended to reducing staffing requirements 15 | + DIBS is not used to generate E-Books 16 | + DIBS is about increasing access to materials which are not otherwise available in electronic form 17 | 18 | 19 | Other observations 20 | ------------------ 21 | 22 | Adding DRM to digital objects is complex, error prone and generally 23 | doesn't successfully prevent copying. A good example is that most 24 | cell phones have one or more high resolution of cameras. Most new monitors 25 | are high resolution and increasingly affordable. It is trivial to film a 26 | screen. You can then assemble the images into a PDF of a work or with 27 | additional effort turn that into an E-Book. DRM can't stop that. DRM at 28 | best makes it inconvenient to copy. 29 | 30 | Without a download button it is inconvenient to copy IIIF materials where 31 | the source URLs are mitigated by a login and access control. 32 | 33 | In the Caltech context the CDL approach made the most sense for resources 34 | that are not currently available for purchase in electronic form but 35 | where there was still demand to circulate the material for research or 36 | instruction without shipping physical copies to patrons. This approach 37 | solved our need for remote course reserve material that was not 38 | available in electronic form for purchase by the library. 39 | 40 | 41 | Things to track 42 | --------------- 43 | 44 | The Internet Archive is currently making the case that CDL comes under 45 | existing library sanctioned activity. If this is upheld in the courts 46 | then you may find an increased adoption CDL as well as an increase in 47 | implementations. 48 | 49 | For materials that outside of copyright concerns (e.g. material now in 50 | the public domain) the CDL technique may remain a good method of 51 | distributing materials remotely either avoiding or decreasing the need 52 | to copy and ship physical objects. This could be particularly useful in 53 | the context of historical works and archival material. 54 | 55 | In the past Tim O'Reilly of O'Reilly Media undertook a study to evaluate 56 | piracy and the effectiveness of DRM. What he found was that piracy more 57 | often occurred where there was no business relationship with the countries 58 | where the piracy took place. I.e. people pirated O'Reilly books if they 59 | could not buy them or get them from their local library. When O'Reilly 60 | material was made available through a legitimate channel the piracy 61 | decreased. This suggests that CDL may actually help publishers deal 62 | with piracy related to availability of a work. When public libraries 63 | were originally introduced in this country (the United States) publishers 64 | where extremely concerned that no one would buy their books if anyone 65 | could read them for free in a public library. In short they feared a 66 | decrease in sales revenue. What actually happened was the opposite. 67 | Public libraries spread literacy and increased the appetite of the public 68 | to purchase books. 69 | 70 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # About the DIBS docs 2 | 3 | This page describes how to (re)create the formatted DIBS documentation. 4 | 5 | ## Building the docs locally 6 | 7 | First, install [MyST](https://myst-parser.readthedocs.io/en/latest/index.html) and [Sphinx](https://www.sphinx-doc.org): 8 | 9 | ```sh 10 | python3 -m pip install "myst-parser[linkify]" 11 | python3 -m pip install sphinx-material 12 | python3 -m pip install sphinx-autobuild 13 | ``` 14 | 15 | After that, rebuilding the docs is simply a matter of running `make html` in the current directory: 16 | 17 | ```sh 18 | make html 19 | ``` 20 | 21 | The output will be put in [`_build/html`](_build/html). Instead of running `make` deliberately, you can also get auto-rebuilds and live preview using `sphinx-autobuild` by running the following command in the current directory (preferably in a new terminal window, because it will generate continuous output): 22 | 23 | ```sh 24 | make auto 25 | ``` 26 | 27 | 28 | ## Writing documentation 29 | 30 | This documentation is written in [MyST-flavored Markdown](https://myst-parser.readthedocs.io/en/latest/) and the [Napoleon](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html) extension to Sphinx. What this means is that the documentation is written in Markdown instead of reStructuredText, with essentially all the features of Sphinx and reStructuredText having MyST equivalents and some additional features beyond _that_ – things like [pandoc](https://pandoc.org)-style footnotes, LaTeX math, and more. 31 | -------------------------------------------------------------------------------- /docs/_presentations/2021-03-08 CNI Spring meeting/CNI Spring 2021 Virtual Membership Meeting: Implementing Controlled Digital Lending....pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_presentations/2021-03-08 CNI Spring meeting/CNI Spring 2021 Virtual Membership Meeting: Implementing Controlled Digital Lending....pdf -------------------------------------------------------------------------------- /docs/_presentations/2021-03-08 CNI Spring meeting/Controlled Digital Lending as a core library service.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_presentations/2021-03-08 CNI Spring meeting/Controlled Digital Lending as a core library service.pdf -------------------------------------------------------------------------------- /docs/_presentations/2021-05-19 CDL Implementers Forum/CDL Implementers - Events Calendar.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_presentations/2021-05-19 CDL Implementers Forum/CDL Implementers - Events Calendar.pdf -------------------------------------------------------------------------------- /docs/_presentations/2021-05-19 CDL Implementers Forum/Caltech DIBS overview 2021-05-19.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_presentations/2021-05-19 CDL Implementers Forum/Caltech DIBS overview 2021-05-19.pdf -------------------------------------------------------------------------------- /docs/_presentations/2021-06-02 WOLFcon panel/Caltech DIBS WOLFcon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_presentations/2021-06-02 WOLFcon panel/Caltech DIBS WOLFcon.pdf -------------------------------------------------------------------------------- /docs/_presentations/2021-06-02 WOLFcon panel/WOLFcon 2021 CDL and resource access and sharing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_presentations/2021-06-02 WOLFcon panel/WOLFcon 2021 CDL and resource access and sharing.pdf -------------------------------------------------------------------------------- /docs/_presentations/README.md: -------------------------------------------------------------------------------- 1 | # Presentations about DIBS 2 | 3 | This directory contains slides from various presentations given about DIBS. 4 | -------------------------------------------------------------------------------- /docs/_static/css/custom.css: -------------------------------------------------------------------------------- 1 | html { 2 | scroll-padding-top: 48px; 3 | } 4 | 5 | nav.md-tabs { 6 | display: none 7 | } 8 | 9 | figure { 10 | margin-top: 1.5em; 11 | text-align: center; 12 | } 13 | 14 | .button { 15 | -moz-border-radius: 2px; 16 | -webkit-border-radius: 2px; 17 | border-radius: 2px; 18 | display: inline-block; 19 | font-size: 90%; 20 | line-height: 1.2; 21 | margin: 0 .1em; 22 | padding: .15em .3em; 23 | } 24 | 25 | .color-info { 26 | background-color: #20a1b6; 27 | color: #fff; 28 | } 29 | 30 | .color-danger { 31 | background-color: #db3a4a; 32 | color: #fff; 33 | } 34 | 35 | .color-primary { 36 | background-color: #357bf6; 37 | color: #fff; 38 | } 39 | 40 | .color-secondary { 41 | background-color: #6c6c6c; 42 | color: #fff; 43 | } 44 | 45 | .color-not-available { 46 | background-color: #a6a6a6; 47 | color: #fff; 48 | } 49 | 50 | h1 { 51 | font-weight: 500 !important; 52 | color: #000 !important; 53 | } 54 | 55 | h2 { 56 | font-weight: 500 !important; 57 | color: #000; 58 | } 59 | 60 | h3 { 61 | color: #000; 62 | } 63 | 64 | h4 { 65 | font-style: italic; 66 | } 67 | -------------------------------------------------------------------------------- /docs/_static/media/add-item-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/add-item-page.png -------------------------------------------------------------------------------- /docs/_static/media/bottom-of-list-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/bottom-of-list-page.png -------------------------------------------------------------------------------- /docs/_static/media/caltech-round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/caltech-round.png -------------------------------------------------------------------------------- /docs/_static/media/dibs-icon-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/dibs-icon-sm.png -------------------------------------------------------------------------------- /docs/_static/media/dibs-icon-white-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/dibs-icon-white-sm.png -------------------------------------------------------------------------------- /docs/_static/media/dibs-icon-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/dibs-icon-white.png -------------------------------------------------------------------------------- /docs/_static/media/dibs-icon-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | This artwork was created by Royyan Vijaya for the Noun Project. The original file was downloaded on 2021-01-26 from https://thenounproject.com/term/book-waiting/1531542/ 5 | Book waiting 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/_static/media/dibs-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/dibs-icon.png -------------------------------------------------------------------------------- /docs/_static/media/dibs-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Book waiting 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/_static/media/dropdown-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/dropdown-menu.png -------------------------------------------------------------------------------- /docs/_static/media/edit-item-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/edit-item-page.png -------------------------------------------------------------------------------- /docs/_static/media/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/favicon.ico -------------------------------------------------------------------------------- /docs/_static/media/item-availability-checkbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/item-availability-checkbox.png -------------------------------------------------------------------------------- /docs/_static/media/item-not-available.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/item-not-available.png -------------------------------------------------------------------------------- /docs/_static/media/item-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/item-page.png -------------------------------------------------------------------------------- /docs/_static/media/item-processing-hourglass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/item-processing-hourglass.png -------------------------------------------------------------------------------- /docs/_static/media/item-processing-problem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/item-processing-problem.png -------------------------------------------------------------------------------- /docs/_static/media/list-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/list-page.png -------------------------------------------------------------------------------- /docs/_static/media/loan-ended.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/loan-ended.png -------------------------------------------------------------------------------- /docs/_static/media/loan-in-viewer-thumbnails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/loan-in-viewer-thumbnails.png -------------------------------------------------------------------------------- /docs/_static/media/loan-in-viewer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/loan-in-viewer.png -------------------------------------------------------------------------------- /docs/_static/media/manage-item-list-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/manage-item-list-page.png -------------------------------------------------------------------------------- /docs/_static/media/manage-items-page-buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/manage-items-page-buttons.png -------------------------------------------------------------------------------- /docs/_static/media/process-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/process-button.png -------------------------------------------------------------------------------- /docs/_static/media/sso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/sso.png -------------------------------------------------------------------------------- /docs/_static/media/stats-page-buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/stats-page-buttons.png -------------------------------------------------------------------------------- /docs/_static/media/stats-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/stats-page.png -------------------------------------------------------------------------------- /docs/_static/media/welcome-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/docs/_static/media/welcome-page.png -------------------------------------------------------------------------------- /docs/_static/versions.json: -------------------------------------------------------------------------------- 1 | {"release": "", "development": "devel"} 2 | -------------------------------------------------------------------------------- /docs/colophon.md: -------------------------------------------------------------------------------- 1 | # Colophon 2 | 3 | This documentation was written by [Michael Hucka](https://www.cds.caltech.edu/~mhucka/). 4 | 5 | The source files use [MyST-flavored Markdown](https://myst-parser.readthedocs.io/en/latest/) and the [Napoleon](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html) extension to [Sphinx](https://www.sphinx-doc.org). A [GitHub Action](https://github.com/caltechlibrary/dibs/blob/main/.github/workflows/build-sphinx.yml) takes care of creating the formatted version of the documentation and hosting it on GitHub.io at https://caltechlibrary.github.io/dibs. The formatted output can also be produced manually using commands implemented in the [Makefile](Makefile) located in the [`docs/`](https://github.com/caltechlibrary/dibs/tree/main/docs) subdirectory of the DIBS source code repository. 6 | 7 | The DIBS [architecture diagram](architecture.html#architectural-overview) was created using [OmniGraffle Pro 7.18](https://www.omnigroup.com/omnigraffle) on a macOS 10.4.6 computer. The SVG output from OmniGraffle Pro was post-processed using [svg-buddy version 1.2.3](https://github.com/phauer/svg-buddy) to embed the fonts into the SVG file. The architecture diagram contains, embedded within it, icons obtained from the Noun Project. All are licensed under the Creative Commons [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/) license. Here are acknowledgments for the original artwork contained in the architecture diagram: 8 | 9 | * [Book icon](https://thenounproject.com/search/?q=book&i=2289902) by [vigorn](https://thenounproject.com/vigorn/) 10 | * [Book scanner icon](https://thenounproject.com/search/?q=book+scanner&i=3635943) by [Oleksandr Panasovskyi](https://thenounproject.com/a.panasovsky/) 11 | * [Laptop icon](https://thenounproject.com/search/?q=laptop&i=3563257) by [Hey Rabbit](https://thenounproject.com/heyrabbit/) 12 | * [Tablet icon](https://thenounproject.com/search/?q=tablet&i=205015) by [Emel Çelik](https://thenounproject.com/iconmood/) 13 | 14 | The [vector artwork](https://thenounproject.com/term/book-waiting/1531542/) used as the icon for DIBS – a book with a clock on it – was created by [Royyan Wijaya](https://thenounproject.com/roywj/) from the Noun Project. It is licensed under the Creative Commons [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/) license. 15 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'DIBS' 21 | project_copyright = '2022, Caltech Library' 22 | author = 'Caltech Library' 23 | 24 | 25 | # -- General configuration --------------------------------------------------- 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be 28 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 29 | # ones. 30 | extensions = [ 31 | 'myst_parser', 32 | 'sphinx.ext.autodoc', 33 | 'sphinx.ext.autosectionlabel', 34 | 'sphinx.ext.napoleon', 35 | 'sphinxcontrib.mermaid' 36 | ] 37 | 38 | # Add any paths that contain templates here, relative to this directory. 39 | templates_path = ['_templates'] 40 | 41 | # List of patterns, relative to source directory, that match files and 42 | # directories to ignore when looking for source files. 43 | # This pattern also affects html_static_path and html_extra_path. 44 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'README.md', 45 | '**/README.md'] 46 | 47 | 48 | # -- Sphinx options for HTML output ------------------------------------------- 49 | 50 | html_title = 'Caltech DIBS' 51 | html_short_title = "Home" 52 | 53 | html_logo = "_static/media/dibs-icon-white-sm.png" 54 | html_favicon = "_static/media/favicon.ico" 55 | 56 | # The theme to use for HTML and HTML Help pages. 57 | html_theme = 'sphinx_material' 58 | 59 | # Add any paths that contain custom static files (such as style sheets) here, 60 | # relative to this directory. They are copied after the builtin static files, 61 | # so a file named "default.css" will overwrite the builtin "default.css". 62 | html_static_path = ['_static'] 63 | 64 | # Our additional CSS for DIBS. 65 | html_css_files = ['css/custom.css'] 66 | 67 | html_show_sourcelink = False 68 | html_sidebars = { 69 | "**": ["globaltoc.html", "searchbox.html"] 70 | } 71 | 72 | # Show the last updated date in the footer using the default format. 73 | html_last_updated_fmt = "" 74 | 75 | 76 | # -- Options for the Material theme --------------------------------------------- 77 | # C.f. https://github.com/bashtage/sphinx-material/blob/master/docs/conf.py 78 | 79 | # Material theme options (see theme.conf for more information) 80 | html_theme_options = { 81 | 82 | # Set the name of the project to appear in the navigation. 83 | 'nav_title': 'Caltech DIBS', 84 | 85 | # Set you GA account ID to enable tracking 86 | 'google_analytics_account': '', 87 | 88 | # Specify a base_url used to generate sitemap.xml. If not 89 | # specified, then no sitemap will be built. 90 | 'base_url': 'https://caltechlibrary.github.io/dibs', 91 | 92 | # Set the colors. I found a list here: 93 | # https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/ 94 | "theme_color": 'blue-grey', 95 | 'color_primary': 'deep-orange', 96 | 'color_accent': 'teal', 97 | 98 | # Set the repo location to get a badge with stats 99 | 'repo_url': 'https://github.com/caltechlibrary/dibs/', 100 | 'repo_name': 'Caltech DIBS', 101 | 102 | # Visible levels of the global TOC; -1 means unlimited 103 | 'globaltoc_depth': 2, 104 | # If False, expand all TOC entries 105 | 'globaltoc_collapse': False, 106 | # If True, show hidden TOC entries 107 | 'globaltoc_includehidden': False, 108 | 109 | "html_minify": False, 110 | "html_prettify": False, 111 | 112 | "version_dropdown": False, 113 | "version_json": "_static/versions.json", 114 | # "version_info": { 115 | # "Release": "https://bashtage.github.io/sphinx-material/", 116 | # "Development": "https://bashtage.github.io/sphinx-material/devel/", 117 | # "Release (rel)": "/sphinx-material/", 118 | # "Development (rel)": "/sphinx-material/devel/", 119 | # }, 120 | } 121 | 122 | 123 | # -- Options for the MyST parser --------------------------------------------- 124 | 125 | myst_enable_extensions = [ 126 | "colon_fence", 127 | "html_image", 128 | "linkify", 129 | "smartquotes", 130 | "substitution" 131 | ] 132 | -------------------------------------------------------------------------------- /docs/general.md: -------------------------------------------------------------------------------- 1 | # General information 2 | 3 | This section provides some general and historical information about DIBS. 4 | 5 | ```{toctree} 6 | --- 7 | maxdepth: 2 8 | --- 9 | faqs.md 10 | history.md 11 | references.md 12 | ``` 13 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | Caltech Library Digital Borrowing System 2 | ======================================== 3 | 4 | Caltech DIBS ("_**Di**gital **B**orrowing **S**ystem_") is the [Caltech Library](https://www.library.caltech.edu)'s basic implementation of a web-based [controlled digital lending](https://en.wikipedia.org/wiki/Controlled_digital_lending) system. The system was developed in the year 2021 to [help Caltech students and faculty continue their studies and work](https://www.library.caltech.edu/DIBS-overview) during the global [COVID-19 pandemic](https://www.who.int/emergencies/diseases/novel-coronavirus-2019). 5 | 6 | The concept of [controlled digital lending](https://controlleddigitallending.org) (CDL) is to allow libraries to loan items to digital patrons in a "lend like print" fashion. It is the digital equivalent of traditional library lending. Libraries digitize a physical item from their collection, then lend out a secured digital version to one user at a time while the original, printed copy is simultaneously marked as unavailable. The number of digital copies of an item allowed to be loaned at any given time is strictly controlled to match the number of physical print copies taken off the shelves, to ensure an exact "owned-to-loaned" ratio. 7 | 8 | DIBS provides three main components of a CDL system: a loan tracking system, an integrated digital content viewing interface, and a basic administrative interface. DIBS embeds the [Universal Viewer](http://universalviewer.io) to display materials that comply with the [International Image Interoperability Framework](https://iiif.io) (IIIF). DIBS also includes a basic mechanism for triggering external workflows that convert scans into IIIF format, and a software interface layer allowing DIBS to fetch book metadata automatically from (currently) [FOLIO](https://www.folio.org) or [TIND](https://tind.io). 9 | 10 | ## Sections 11 | 12 | ```{toctree} 13 | --- 14 | maxdepth: 2 15 | --- 16 | usage.md 17 | architecture.md 18 | installation.md 19 | general.md 20 | colophon.md 21 | ``` 22 | -------------------------------------------------------------------------------- /docs/references.md: -------------------------------------------------------------------------------- 1 | # References and resources 2 | 3 | The following are some additional resources about Controlled Digital Lending: 4 | 5 | * The website [Controlled Digital Lending by Libraries](https://controlleddigitallending.org) provides information and resources related to CDL, including pointers to legal frameworks, pointers to papers on the topic of CDL, and a list of [frequently asked questions (and answers)](https://controlleddigitallending.org/faq). 6 | * In September 2021, the non-profit [Library Futures Foundation](https://www.libraryfutures.net) released a policy document titled [Controlled Digital Lending: Unlocking the Library’s Full Potential](https://www.libraryfutures.net/policy-document-2021). The document _"expands beyond the legal rationale laid out in the Controlled Digital Lending (CDL) White Paper by clarifying the core principles that are the foundations of a library’s mission to provide access to materials to serve the public good. "_ 7 | * In June 2021, the [International Federation of Library Associations and Institutions](https://www.ifla.org) issued a [statement on Controlled Digital Lending](https://www.ifla.org/publications/ifla-statement-on-controlled-digital-lending/) in support of CDL as a means of enabling libraries to fulfill their missions. 8 | * The Internet Archive and Library Futures hosted a webinar on "Myth Busting Controlled Digital Lending" in Feburary, 2021. The [video is available online](http://blog.archive.org/2021/02/11/mythbusting-controlled-digital-lending-community-rallies-to-fight-misinformation-about-the-library-practice/) and touches on many myths and realities of CDL. 9 | * The [Controlled Digital Lending Implementers](https://sites.google.com/view/cdl-implementers) is a forum [organized in April 2020](https://sites.google.com/view/cdl-implementers/about-cdli?authuser=0) by a group of libraries and people interested in implementing controlled digital lending services. They host a regular forum and provide links to resources about CDL. 10 | * [Project ReShare](https://projectreshare.org/about/) is a group of libraries, consortia, information organizations, and developers, with both commercial and non-commercial interests working on implementing new and open approaches to library resource sharing. The [ReShare Community Charter](https://projectreshare.org/about/community-charter/) provides more details about the goals of the effort. 11 | * The [CDL Information & Recommendation Cooperative (CIRC)](https://www.cdlproject.org) is a group of library professionals working to discover and evaluate potential tools and solutions for CDL. 12 | 13 | Caltech's DIBS is not the only CDL implementation, nor is it the first. The following are others that the developers of DIBS are aware of: 14 | 15 | * The [Open Library](https://openlibrary.org) is an open library catalog and digital lending system implemented by the Internet Archive. The [source code is available from GitHub](https://github.com/internetarchive/openlibrary/). 16 | * Princeton University Library has implemented CDL using [Figgy](https://github.com/pulibrary/figgy), an open-source digital repository application [they developed](https://library.princeton.edu/digital-collections/digital-pul/technology). Like DIBS, it uses IIIF and the Universal Viewer. 17 | * Fordham University developed [G-CDL](https://github.com/Fordham-University-Libraries/G-CDL), an open-source CDL system that uses Google Drive as its backend. 18 | * [Alma Digital](https://developers.exlibrisgroup.com/blog/controlled-digital-lending-with-existing-tools-in-the-toolbox-alma-digital/) is a commercial repository system that's part of [ExLibris Alma](https://exlibrisgroup.com/products/alma-library-services-platform/). It supports digital lending, including control on number of concurrent users, cooling-off periods, and more. 19 | * DLSG's [Directed Lending Solution](https://www.dlsg.com) is another commercial system for digital lending. 20 | 21 | Articles about DIBS: 22 | 23 | * [How the Library’s Digital Borrowing Service (DIBS) Solved a Pandemic Problem](https://www.library.caltech.edu/DIBS-overview) (Chris Daley, June 2021, Caltech) 24 | -------------------------------------------------------------------------------- /htdocs/README.md: -------------------------------------------------------------------------------- 1 | # About this directory 2 | 3 | `htdocs` is used to redirect the browser to the subfolder containing the DIBS application in Apache, so that Shibboleth can protect the application. For example, in Caltech's case, it redirects https://ourserver.caltech.edu to https://ourserver.caltech.edu/dibs, where Shib works to protect the dibs app. 4 | -------------------------------------------------------------------------------- /htdocs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # @file requirements.txt 3 | # @brief Python dependencies for DIBS 4 | # @created 2021-01-12 5 | # @license Please see the file named LICENSE in the project directory 6 | # @website https://github.com/caltechlibrary/dibs 7 | # ============================================================================= 8 | 9 | arrow == 1.2.2 10 | boltons == 21.0.0 11 | bottle == 0.12.21 12 | bottle-fdsend == 0.1.1 13 | coif == 0.0.1 14 | commonpy == 1.9.5 15 | expiringdict == 1.2.2 16 | humanize == 4.2.3 17 | lru-dict == 1.1.8 18 | 19 | # Note: mod_wsgi is only needed by run-server. You can comment it out if you 20 | # are not using run-server and you run into problems installing it on your 21 | # system. (Tip: on Ubuntu 20, mod_wsgi won't install without the apache2-dev 22 | # library on the system. If you get an error about "apxs" missing, try doing 23 | # `sudo apt install apache2-dev` and then try pip install mod_wsgi again.) 24 | mod-wsgi == 4.9.3 25 | 26 | peewee == 3.15.1 27 | Pillow == 9.3.0 28 | plac == 1.3.5 29 | pokapi == 0.3.1 30 | python-daemon == 2.3.0 31 | python-decouple == 3.6 32 | rich == 12.5.1 33 | sidetrack == 2.0.1 34 | str2bool == 1.1 35 | trinomial == 0.0.3 36 | topi == 1.1.0 37 | yurl == 1.0.0 38 | werkzeug == 2.1.2 39 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # @file setup.cfg 3 | # @brief Package metadata and PyPI configuration 4 | # @created 2021-03-17 5 | # @license Please see the file named LICENSE in the project directory 6 | # @website https://github.com/caltechlibrary/dibs 7 | # ============================================================================= 8 | 9 | [metadata] 10 | name = dibs 11 | version = 0.7.0 12 | description = DIBS (Digital Borrowing System) is an implementation of Controlled Digital Lending 13 | author = Michael Hucka, Robert S. Doiel, Tommy Keswick, Stephen Davison 14 | author_email = helpdesk@library.caltech.edu 15 | license = BSD 3-clause 16 | license_files = LICENSE 17 | url = https://github.com/caltechlibrary/dibs 18 | # The remaining items below are used by PyPI. 19 | project_urls = 20 | Source Code = https://github.com/caltechlibrary/dibs 21 | Bug Tracker = https://github.com/caltechlibrary/dibs/issues 22 | keywords = Python, utilities 23 | classifiers = 24 | Development Status :: 4 - Beta 25 | Environment :: Web Environment 26 | Framework :: Bottle 27 | Intended Audience :: Science/Research 28 | License :: OSI Approved :: BSD License 29 | Operating System :: MacOS :: MacOS X 30 | Operating System :: POSIX 31 | Operating System :: POSIX :: Linux 32 | Operating System :: Unix 33 | Programming Language :: Python 34 | Programming Language :: Python :: 3.8 35 | long_description = file:README.md 36 | long_description_content_type = text/markdown 37 | 38 | [options] 39 | packages = find: 40 | zip_safe = False 41 | python_requires = >= 3.8 42 | 43 | [tool:pytest] 44 | addopts = --flake8 --cov=dibs --cov-report=term-missing 45 | pythonpath = . 46 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # ============================================================================= 3 | # @file setup.py 4 | # @brief Installation setup file 5 | # @created 2021-05-21 6 | # @license Please see the file named LICENSE in the project directory 7 | # @website https://github.com/caltechlibrary/dibs 8 | # 9 | # Note: configuration metadata is maintained in setup.cfg. This file exists 10 | # primarily to hook in setup.cfg and requirements.txt. 11 | # ============================================================================= 12 | 13 | from os.path import exists, join, abspath, dirname 14 | from setuptools import setup 15 | 16 | here = abspath(dirname(__file__)) 17 | 18 | requirements = [] 19 | if exists(join(here, 'requirements.txt')): 20 | with open(join(here, 'requirements.txt')) as f: 21 | requirements = f.read().rstrip().splitlines() 22 | 23 | setup( 24 | setup_requires = ['wheel'], 25 | install_requires = requirements, 26 | ) 27 | -------------------------------------------------------------------------------- /tests/test_date_utils.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | 4 | def test_round_minutes(): 5 | from dibs.date_utils import round_minutes 6 | 7 | x = datetime(2021, 4, 6, 23, 56, 3, 546899) 8 | assert round_minutes(x, 'down') == datetime(2021, 4, 6, 23, 56) 9 | assert round_minutes(x, 'up') == datetime(2021, 4, 6, 23, 57) 10 | 11 | x = datetime(2021, 4, 6, 23, 56, 30, 546899) 12 | assert round_minutes(x, 'down') == datetime(2021, 4, 6, 23, 56) 13 | assert round_minutes(x, 'up') == datetime(2021, 4, 6, 23, 57) 14 | 15 | x = datetime(2021, 4, 6, 23, 56, 0, 546899) 16 | assert round_minutes(x, 'down') == datetime(2021, 4, 6, 23, 56) 17 | assert round_minutes(x, 'up') == datetime(2021, 4, 6, 23, 57) 18 | 19 | x = datetime(2021, 4, 6, 23, 56, 55, 0) 20 | assert round_minutes(x, 'down') == datetime(2021, 4, 6, 23, 56) 21 | assert round_minutes(x, 'up') == datetime(2021, 4, 6, 23, 57) 22 | 23 | x = datetime(2021, 4, 6, 23, 0, 0, 0) 24 | assert round_minutes(x, 'down') == datetime(2021, 4, 6, 23, 0) 25 | assert round_minutes(x, 'up') == datetime(2021, 4, 6, 23, 1) 26 | 27 | 28 | def test_human_datetime(): 29 | from dibs.date_utils import human_datetime 30 | 31 | x = datetime(2021, 4, 6, 23, 0, 0, 0) 32 | hx = human_datetime(x) 33 | assert hx[0:8] == '4:00 PM ' 34 | assert hx[13:] == ' on 2021-04-06' 35 | 36 | x = datetime(2021, 4, 6, 23, 5, 6, 7) 37 | hx = human_datetime(x) 38 | assert hx[0:8] == '4:05 PM ' 39 | assert hx[13:] == ' on 2021-04-06' 40 | 41 | x = datetime(2021, 4, 6, 23, 5, 6, 7) 42 | hx = human_datetime(x, "%I:%M %p on %Y-%m-%d") 43 | assert hx == '4:05 PM on 2021-04-06' 44 | 45 | hx = human_datetime('') 46 | assert hx == '' 47 | -------------------------------------------------------------------------------- /tests/test_init.py: -------------------------------------------------------------------------------- 1 | def test_version(): 2 | """Test version import.""" 3 | from dibs import __version__ 4 | assert __version__ 5 | 6 | 7 | def test_print_version(capsys): 8 | from dibs import print_version 9 | print_version() 10 | captured = capsys.readouterr() 11 | assert 'URL' in captured.out 12 | -------------------------------------------------------------------------------- /tests/test_lsp.py: -------------------------------------------------------------------------------- 1 | def test_probable_issn(): 2 | from dibs.lsp import probable_issn 3 | 4 | assert probable_issn('1573-1332') is True 5 | assert probable_issn('15731332') is False 6 | assert probable_issn('978-0-691-20019-4') is False 7 | 8 | 9 | def test_truncated_title(): 10 | from dibs.lsp import truncated_title 11 | 12 | assert truncated_title('Foo: Bar') == 'Foo' 13 | assert truncated_title('Foo; by Bar') == 'Foo' 14 | assert truncated_title('Foo. Bar') == 'Foo' 15 | 16 | 17 | def test_names(): 18 | from dibs.lsp import TindInterface, FolioInterface 19 | 20 | interface = TindInterface() 21 | assert interface.name == 'TIND' 22 | 23 | interface = FolioInterface() 24 | assert interface.name == 'FOLIO' 25 | -------------------------------------------------------------------------------- /tests/test_resolved_path.py: -------------------------------------------------------------------------------- 1 | import os 2 | from os.path import join, dirname, abspath 3 | 4 | 5 | def test_relative_to_caller(): 6 | from dibs.settings import resolved_path 7 | 8 | me = __file__ 9 | d = resolved_path('tests/test_resolved_path.py') 10 | assert d == abspath(me) 11 | 12 | 13 | def test_relative_to_settings(): 14 | from dibs.settings import resolved_path 15 | 16 | here = dirname(__file__) 17 | other = abspath(join(here, os.pardir, 'admin/run-server')) 18 | d = resolved_path('admin/run-server') 19 | assert d == other 20 | -------------------------------------------------------------------------------- /viewer/README.md: -------------------------------------------------------------------------------- 1 | # Copy of Universal Viewer version 3.1.1 2 | 3 | This is a copy of the [Universal Viewer](http://universalviewer.io) version 3.1.1 distribution produced using the source code from the [GitHub repository](https://github.com/UniversalViewer/universalviewer/releases/tag/v3.1.1) as it existed on 2021-04-27. The specific contents of this directory were produced using the following steps: 4 | 5 | 1. Install `npm` (we used version 7; installation instructions depend on your operating system) 6 | 2. `npm install -g grunt-cli` 7 | 3. Download the UV [source code ZIP archive](https://github.com/UniversalViewer/universalviewer/archive/refs/tags/v3.1.1.zip) to a local directory (call it `uv`) 8 | 4. `cd uv` 9 | 5. `unzip v3.1.1.zip` 10 | 6. `cd universalviewer-3.1.1` 11 | 7. `npm install grunt@1.0.3 --save-dev` 12 | 8. `grunt build --dist` 13 | 14 | The outcome of this process will be a subdirectory named `dist`, and `dist` will contain the files that you see here before you (minus the `uv.zip` file that is also put in the `dist` directory by the build process, and which we removed because it simply contains all the same files and thus is redundant). 15 | 16 | The Universal Viewer is released under the MIT license. 17 | -------------------------------------------------------------------------------- /viewer/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/viewer/favicon.ico -------------------------------------------------------------------------------- /viewer/helpers.js: -------------------------------------------------------------------------------- 1 | function createUV(selector, data, dataProvider) { 2 | var uv; 3 | var isFullScreen = false; 4 | var $container = $(selector); 5 | $container.empty(); 6 | var $parent = $('
'); 7 | $container.append($parent); 8 | var $uv = $('
'); 9 | $parent.append($uv); 10 | 11 | function resize() { 12 | if (uv) { 13 | if (isFullScreen) { 14 | $parent.width(window.innerWidth); 15 | $parent.height(window.innerHeight); 16 | } else { 17 | $parent.width($container.width()); 18 | $parent.height($container.height()); 19 | } 20 | uv.resize(); 21 | } 22 | } 23 | 24 | window.addEventListener('resize', function() { 25 | resize(); 26 | }); 27 | 28 | uv = new UV({ 29 | target: $uv[0], 30 | data: data 31 | }); 32 | 33 | uv.on('create', function(obj) { 34 | resize(); 35 | }, false); 36 | 37 | uv.on('created', function(obj) { 38 | resize(); 39 | }, false); 40 | 41 | uv.on('collectionIndexChanged', function(collectionIndex) { 42 | dataProvider.set('c', collectionIndex); 43 | }, false); 44 | 45 | uv.on('manifestIndexChanged', function(manifestIndex) { 46 | dataProvider.set('m', manifestIndex); 47 | }, false); 48 | 49 | uv.on('sequenceIndexChanged', function(sequenceIndex) { 50 | dataProvider.set('s', sequenceIndex); 51 | }, false); 52 | 53 | uv.on('canvasIndexChanged', function(canvasIndex) { 54 | dataProvider.set('cv', canvasIndex); 55 | }, false); 56 | 57 | uv.on('rangeChanged', function(rangeId) { 58 | dataProvider.set('rid', rangeId); 59 | }, false); 60 | 61 | uv.on('openseadragonExtension.rotationChanged', function(rotation) { 62 | dataProvider.set('r', rotation); 63 | }, false); 64 | 65 | uv.on('openseadragonExtension.xywhChanged', function(xywh) { 66 | dataProvider.set('xywh', xywh); 67 | }, false); 68 | 69 | uv.on('openseadragonExtension.currentViewUri', function(data) { 70 | //console.log('openseadragonExtension.currentViewUri', obj); 71 | }, false); 72 | 73 | uv.on('ebookExtension.cfiFragmentChanged', function(cfi) { 74 | dataProvider.set('cfi', cfi); 75 | }, false); 76 | 77 | uv.on('reload', function(data) { 78 | data.isReload = true; 79 | uv.set(data); 80 | }, false); 81 | 82 | uv.on('toggleFullScreen', function(data) { 83 | isFullScreen = data.isFullScreen; 84 | 85 | if (data.overrideFullScreen) { 86 | return; 87 | } 88 | 89 | var elem = $parent[0]; 90 | 91 | if (isFullScreen) { 92 | var requestFullScreen = getRequestFullScreen(elem); 93 | if (requestFullScreen) { 94 | requestFullScreen.call(elem); 95 | resize(); 96 | } 97 | } else { 98 | var exitFullScreen = getExitFullScreen(); 99 | if (exitFullScreen) { 100 | exitFullScreen.call(document); 101 | resize(); 102 | } 103 | } 104 | }, false); 105 | 106 | uv.on('error', function(message) { 107 | console.error(message); 108 | }, false); 109 | 110 | uv.on('bookmark', function(data) { 111 | 112 | var absUri = parent.document.URL; 113 | var parts = Utils.Urls.getUrlParts(absUri); 114 | var relUri = parts.pathname + parts.search + parent.document.location.hash; 115 | 116 | if (!relUri.startsWith("/")) { 117 | relUri = "/" + relUri; 118 | } 119 | 120 | data.path = relUri; 121 | 122 | console.log('bookmark', data); 123 | },false); 124 | 125 | $(document).on('fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange', function(e) { 126 | if (e.type === 'webkitfullscreenchange' && !document.webkitIsFullScreen || 127 | e.type === 'fullscreenchange' && !document.fullscreenElement || 128 | e.type === 'mozfullscreenchange' && !document.mozFullScreen || 129 | e.type === 'MSFullscreenChange' && document.msFullscreenElement === null) { 130 | uv.exitFullScreen(); 131 | } 132 | }); 133 | 134 | return uv; 135 | } 136 | 137 | function getRequestFullScreen(elem) { 138 | 139 | if (elem.webkitRequestFullscreen) { 140 | return elem.webkitRequestFullscreen; 141 | } 142 | 143 | if (elem.mozRequestFullScreen) { 144 | return elem.mozRequestFullScreen; 145 | } 146 | 147 | if (elem.msRequestFullscreen) { 148 | return elem.msRequestFullscreen; 149 | } 150 | 151 | if (elem.requestFullscreen) { 152 | return elem.requestFullscreen; 153 | } 154 | 155 | return false; 156 | } 157 | 158 | function getExitFullScreen() { 159 | 160 | if (document.webkitExitFullscreen) { 161 | return document.webkitExitFullscreen; 162 | } 163 | 164 | if (document.msExitFullscreen) { 165 | return document.msExitFullscreen; 166 | } 167 | 168 | if (document.mozCancelFullScreen) { 169 | return document.mozCancelFullScreen; 170 | } 171 | 172 | if (document.exitFullscreen) { 173 | return document.exitFullscreen; 174 | } 175 | 176 | return false; 177 | } -------------------------------------------------------------------------------- /viewer/img/pixel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/viewer/img/pixel.gif -------------------------------------------------------------------------------- /viewer/lib/Detector.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * @author mr.doob / http://mrdoob.com/ 4 | */ 5 | 6 | var Detector = { 7 | 8 | canvas: !! window.CanvasRenderingContext2D, 9 | webgl: ( function () { 10 | 11 | try { 12 | 13 | var canvas = document.createElement( 'canvas' ); return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) ); 14 | 15 | } catch ( e ) { 16 | 17 | return false; 18 | 19 | } 20 | 21 | } )(), 22 | workers: !! window.Worker, 23 | fileapi: window.File && window.FileReader && window.FileList && window.Blob, 24 | 25 | getWebGLErrorMessage: function () { 26 | 27 | var element = document.createElement( 'div' ); 28 | element.id = 'webgl-error-message'; 29 | element.style.fontFamily = 'monospace'; 30 | element.style.fontSize = '13px'; 31 | element.style.fontWeight = 'normal'; 32 | element.style.textAlign = 'center'; 33 | element.style.background = '#fff'; 34 | element.style.color = '#000'; 35 | element.style.padding = '1.5em'; 36 | element.style.width = '400px'; 37 | element.style.margin = '5em auto 0'; 38 | 39 | if ( ! this.webgl ) { 40 | 41 | element.innerHTML = window.WebGLRenderingContext ? [ 42 | 'Your graphics card does not seem to support WebGL.
', 43 | 'Find out how to get it here.' 44 | ].join( '\n' ) : [ 45 | 'Your browser does not seem to support WebGL.
', 46 | 'Find out how to get it here.' 47 | ].join( '\n' ); 48 | 49 | } 50 | 51 | return element; 52 | 53 | }, 54 | 55 | addGetWebGLMessage: function ( parameters ) { 56 | 57 | var parent, id, element; 58 | 59 | parameters = parameters || {}; 60 | 61 | parent = parameters.parent !== undefined ? parameters.parent : document.body; 62 | id = parameters.id !== undefined ? parameters.id : 'oldie'; 63 | 64 | element = Detector.getWebGLErrorMessage(); 65 | element.id = id; 66 | 67 | parent.appendChild( element ); 68 | 69 | } 70 | 71 | }; 72 | 73 | // browserify support 74 | if ( typeof module === 'object' ) { 75 | 76 | module.exports = Detector; 77 | 78 | } 79 | -------------------------------------------------------------------------------- /viewer/lib/VRControls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author dmarcos / https://github.com/dmarcos 3 | * @author mrdoob / http://mrdoob.com 4 | */ 5 | 6 | THREE.VRControls = function ( object, onError ) { 7 | 8 | var scope = this; 9 | 10 | var vrDisplay, vrDisplays; 11 | 12 | var standingMatrix = new THREE.Matrix4(); 13 | 14 | var frameData = null; 15 | 16 | if ( 'VRFrameData' in window ) { 17 | 18 | frameData = new VRFrameData(); 19 | 20 | } 21 | 22 | function gotVRDisplays( displays ) { 23 | 24 | vrDisplays = displays; 25 | 26 | if ( displays.length > 0 ) { 27 | 28 | vrDisplay = displays[ 0 ]; 29 | 30 | } else { 31 | 32 | if ( onError ) onError( 'VR input not available.' ); 33 | 34 | } 35 | 36 | } 37 | 38 | if ( navigator.getVRDisplays ) { 39 | 40 | navigator.getVRDisplays().then( gotVRDisplays ).catch( function () { 41 | 42 | console.warn( 'THREE.VRControls: Unable to get VR Displays' ); 43 | 44 | } ); 45 | 46 | } 47 | 48 | // the Rift SDK returns the position in meters 49 | // this scale factor allows the user to define how meters 50 | // are converted to scene units. 51 | 52 | this.scale = 1; 53 | 54 | // If true will use "standing space" coordinate system where y=0 is the 55 | // floor and x=0, z=0 is the center of the room. 56 | this.standing = false; 57 | 58 | // Distance from the users eyes to the floor in meters. Used when 59 | // standing=true but the VRDisplay doesn't provide stageParameters. 60 | this.userHeight = 1.6; 61 | 62 | this.getVRDisplay = function () { 63 | 64 | return vrDisplay; 65 | 66 | }; 67 | 68 | this.setVRDisplay = function ( value ) { 69 | 70 | vrDisplay = value; 71 | 72 | }; 73 | 74 | this.getVRDisplays = function () { 75 | 76 | console.warn( 'THREE.VRControls: getVRDisplays() is being deprecated.' ); 77 | return vrDisplays; 78 | 79 | }; 80 | 81 | this.getStandingMatrix = function () { 82 | 83 | return standingMatrix; 84 | 85 | }; 86 | 87 | this.update = function () { 88 | 89 | if ( vrDisplay ) { 90 | 91 | var pose; 92 | 93 | if ( vrDisplay.getFrameData ) { 94 | 95 | vrDisplay.getFrameData( frameData ); 96 | pose = frameData.pose; 97 | 98 | } else if ( vrDisplay.getPose ) { 99 | 100 | pose = vrDisplay.getPose(); 101 | 102 | } 103 | 104 | if ( pose.orientation !== null ) { 105 | 106 | object.quaternion.fromArray( pose.orientation ); 107 | 108 | } 109 | 110 | if ( pose.position !== null ) { 111 | 112 | object.position.fromArray( pose.position ); 113 | 114 | } else { 115 | 116 | object.position.set( 0, 0, 0 ); 117 | 118 | } 119 | 120 | if ( this.standing ) { 121 | 122 | if ( vrDisplay.stageParameters ) { 123 | 124 | object.updateMatrix(); 125 | 126 | standingMatrix.fromArray( vrDisplay.stageParameters.sittingToStandingTransform ); 127 | object.applyMatrix( standingMatrix ); 128 | 129 | } else { 130 | 131 | object.position.setY( object.position.y + this.userHeight ); 132 | 133 | } 134 | 135 | } 136 | 137 | object.position.multiplyScalar( scope.scale ); 138 | 139 | } 140 | 141 | }; 142 | 143 | this.dispose = function () { 144 | 145 | vrDisplay = null; 146 | 147 | }; 148 | 149 | }; 150 | -------------------------------------------------------------------------------- /viewer/lib/WebVR.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mrdoob / http://mrdoob.com 3 | * @author Mugen87 / https://github.com/Mugen87 4 | * 5 | * Based on @tojiro's vr-samples-utils.js 6 | */ 7 | 8 | var WEBVR = { 9 | 10 | createButton: function ( renderer ) { 11 | 12 | function showEnterVR( display ) { 13 | 14 | button.style.display = ''; 15 | 16 | button.style.cursor = 'pointer'; 17 | button.style.left = 'calc(50% - 50px)'; 18 | button.style.width = '100px'; 19 | 20 | button.textContent = 'ENTER VR'; 21 | 22 | button.onmouseenter = function () { button.style.opacity = '1.0'; }; 23 | button.onmouseleave = function () { button.style.opacity = '0.5'; }; 24 | 25 | button.onclick = function () { 26 | 27 | display.isPresenting ? display.exitPresent() : display.requestPresent( [ { source: renderer.domElement } ] ); 28 | 29 | }; 30 | 31 | renderer.vr.setDevice( display ); 32 | 33 | } 34 | 35 | function showVRNotFound() { 36 | 37 | button.style.display = ''; 38 | 39 | button.style.cursor = 'auto'; 40 | button.style.left = 'calc(50% - 75px)'; 41 | button.style.width = '150px'; 42 | 43 | button.textContent = 'VR NOT FOUND'; 44 | 45 | button.onmouseenter = null; 46 | button.onmouseleave = null; 47 | 48 | button.onclick = null; 49 | 50 | renderer.vr.setDevice( null ); 51 | 52 | } 53 | 54 | function stylizeElement( element ) { 55 | 56 | element.style.position = 'absolute'; 57 | element.style.bottom = '20px'; 58 | element.style.padding = '12px 6px'; 59 | element.style.border = '1px solid #fff'; 60 | element.style.borderRadius = '4px'; 61 | element.style.background = 'transparent'; 62 | element.style.color = '#fff'; 63 | element.style.font = 'normal 13px sans-serif'; 64 | element.style.textAlign = 'center'; 65 | element.style.opacity = '0.5'; 66 | element.style.outline = 'none'; 67 | element.style.zIndex = '999'; 68 | 69 | } 70 | 71 | if ( 'getVRDisplays' in navigator ) { 72 | 73 | var button = document.createElement( 'button' ); 74 | button.style.display = 'none'; 75 | 76 | stylizeElement( button ); 77 | 78 | window.addEventListener( 'vrdisplayconnect', function ( event ) { 79 | 80 | showEnterVR( event.display ); 81 | 82 | }, false ); 83 | 84 | window.addEventListener( 'vrdisplaydisconnect', function ( event ) { 85 | 86 | showVRNotFound(); 87 | 88 | }, false ); 89 | 90 | window.addEventListener( 'vrdisplaypresentchange', function ( event ) { 91 | 92 | button.textContent = event.display.isPresenting ? 'EXIT VR' : 'ENTER VR'; 93 | 94 | }, false ); 95 | 96 | window.addEventListener( 'vrdisplayactivate', function ( event ) { 97 | 98 | event.display.requestPresent( [ { source: renderer.domElement } ] ); 99 | 100 | }, false ); 101 | 102 | navigator.getVRDisplays() 103 | .then( function ( displays ) { 104 | 105 | if ( displays.length > 0 ) { 106 | 107 | showEnterVR( displays[ 0 ] ); 108 | 109 | } else { 110 | 111 | showVRNotFound(); 112 | 113 | } 114 | 115 | } ); 116 | 117 | return button; 118 | 119 | } else { 120 | 121 | var message = document.createElement( 'a' ); 122 | message.href = 'https://webvr.info'; 123 | message.innerHTML = 'WEBVR NOT SUPPORTED'; 124 | 125 | message.style.left = 'calc(50% - 90px)'; 126 | message.style.width = '180px'; 127 | message.style.textDecoration = 'none'; 128 | 129 | stylizeElement( message ); 130 | 131 | return message; 132 | 133 | } 134 | 135 | }, 136 | 137 | // DEPRECATED 138 | 139 | checkAvailability: function () { 140 | console.warn( 'WEBVR.checkAvailability has been deprecated.' ); 141 | return new Promise( function () {} ); 142 | }, 143 | 144 | getMessageContainer: function () { 145 | console.warn( 'WEBVR.getMessageContainer has been deprecated.' ); 146 | return document.createElement( 'div' ); 147 | }, 148 | 149 | getButton: function () { 150 | console.warn( 'WEBVR.getButton has been deprecated.' ); 151 | return document.createElement( 'div' ); 152 | }, 153 | 154 | getVRDisplay: function () { 155 | console.warn( 'WEBVR.getVRDisplay has been deprecated.' ); 156 | } 157 | 158 | }; 159 | -------------------------------------------------------------------------------- /viewer/lib/iiifgallery.proxy.js: -------------------------------------------------------------------------------- 1 | // demonstrates how to load a stencil component via a proxy script 2 | // https://github.com/ionic-team/stencil/issues/365 3 | // *.proxy.js files are ignored when cleaning lib folders 4 | // (function() { 5 | // var t = document.createElement('script'); 6 | // t.type = 'text/javascript'; 7 | // t.src = 'uv/lib/iiifgallery.js'; 8 | // document.body.appendChild(t); 9 | // })(); -------------------------------------------------------------------------------- /viewer/lib/index.esm.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/viewer/lib/index.esm.js -------------------------------------------------------------------------------- /viewer/lib/jquery.binarytransport.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * jquery.binarytransport.js 4 | * 5 | * @description. jQuery ajax transport for making binary data type requests. 6 | * @version 1.0 7 | * @author Henry Algus 8 | * 9 | */ 10 | 11 | (function($, undefined) { 12 | "use strict"; 13 | 14 | // use this transport for "binary" data type 15 | $.ajaxTransport("+binary", function(options, originalOptions, jqXHR) { 16 | // check for conditions and support for blob / arraybuffer response type 17 | if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob))))) { 18 | return { 19 | // create new XMLHttpRequest 20 | send: function(headers, callback) { 21 | // setup all variables 22 | var xhr = new XMLHttpRequest(), 23 | url = options.url, 24 | type = options.type, 25 | async = options.async || true, 26 | // blob or arraybuffer. Default is blob 27 | dataType = options.responseType || "blob", 28 | data = options.data || null, 29 | username = options.username || null, 30 | password = options.password || null; 31 | 32 | xhr.addEventListener('load', function() { 33 | var data = {}; 34 | data[options.dataType] = xhr.response; 35 | // make callback and send data 36 | callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders()); 37 | }); 38 | 39 | xhr.open(type, url, async, username, password); 40 | 41 | // setup custom headers 42 | for (var i in headers) { 43 | xhr.setRequestHeader(i, headers[i]); 44 | } 45 | 46 | xhr.responseType = dataType; 47 | xhr.send(data); 48 | }, 49 | abort: function() {} 50 | }; 51 | } 52 | }); 53 | })(window.jQuery); 54 | -------------------------------------------------------------------------------- /viewer/lib/jquery.ui.touch-punch.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery UI Touch Punch 0.2.3 3 | * 4 | * Copyright 2011–2014, Dave Furfero 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * 7 | * Depends: 8 | * jquery.ui.widget.js 9 | * jquery.ui.mouse.js 10 | */ 11 | !function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery); -------------------------------------------------------------------------------- /viewer/lib/p-2597ae36.system.js: -------------------------------------------------------------------------------- 1 | System.register(["./p-a25b52a9.system.js"],(function(){"use strict";var e,t;return{setters:[function(i){e=i.p;t=i.b}],execute:function(){e().then((function(e){return t([["p-p4r1bdpj.system",[[0,"uv-ebook-reader",{width:[1],height:[1],mobileWidth:[2,"mobile-width"],minSpreadWidth:[2,"min-spread-width"],_bookPath:[32],_bookReady:[32],_prevEnabled:[32],_mobile:[32],_nextEnabled:[32],_showDivider:[32],load:[64],resize:[64],display:[64]},[[8,"keydown","handleKeyDown"]]],[0,"uv-ebook-toc",{toc:[16],selected:[1025],disabled:[4]}]]]],e)}))}}})); -------------------------------------------------------------------------------- /viewer/lib/p-50ea2036.system.js: -------------------------------------------------------------------------------- 1 | System.register([],(function(){"use strict";return{execute:function(){}}})); -------------------------------------------------------------------------------- /viewer/lib/stats.min.js: -------------------------------------------------------------------------------- 1 | // stats.js - http://github.com/mrdoob/stats.js 2 | var Stats=function(){function h(a){c.appendChild(a.dom);return a}function k(a){for(var d=0;de+1E3&&(r.update(1E3*a/(c-e),100),e=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){g=this.end()},domElement:c,setMode:k}}; 4 | Stats.Panel=function(h,k,l){var c=Infinity,g=0,e=Math.round,a=e(window.devicePixelRatio||1),r=80*a,f=48*a,t=3*a,u=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=f;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,f);b.fillStyle=k;b.fillText(h,t,u);b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(f, 5 | v){c=Math.min(c,f);g=Math.max(g,f);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=k;b.fillText(e(f)+" "+h+" ("+e(c)+"-"+e(g)+")",t,u);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,e((1-f/v)*p))}}};"object"===typeof module&&(module.exports=Stats); 6 | -------------------------------------------------------------------------------- /viewer/lib/uv-av-extension-dependencies.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | function isFormatAvailable(formats, format) { 3 | var isAvailable = formats.includes(format); 4 | return isAvailable; 5 | } 6 | function isHLSFormatAvailable(formats) { 7 | return isFormatAvailable(formats, 'application/vnd.apple.mpegurl') || isFormatAvailable(formats, 'vnd.apple.mpegurl'); 8 | } 9 | function isMpegDashFormatAvailable(formats) { 10 | return isFormatAvailable(formats, 'application/dash+xml'); 11 | } 12 | function canPlayHls() { 13 | var doc = typeof document === 'object' && document, videoelem = doc && doc.createElement('video'), isvideosupport = Boolean(videoelem && videoelem.canPlayType), canPlay = [ 14 | 'application/vnd.apple.mpegurl', 15 | 'audio/mpegurl', 16 | 'audio/x-mpegurl', 17 | 'application/x-mpegurl', 18 | 'video/x-mpegurl', 19 | 'video/mpegurl', 20 | 'application/mpegurl' 21 | ]; 22 | return isvideosupport && canPlay.some(function (canItPlay) { 23 | return /maybe|probably/i.test(videoelem.canPlayType(canItPlay)); 24 | }); 25 | } 26 | return function (formats) { 27 | var alwaysRequired = ['TreeComponent', 'AVComponent', 'MetadataComponent', 'jquery-ui.min', 'jquery.ui.touch-punch.min', 'jquery.binarytransport', 'waveform-data']; 28 | if (isHLSFormatAvailable(formats) && canPlayHls()) { 29 | console.log('load HLS'); 30 | return { 31 | sync: alwaysRequired.concat(['hls.min']) 32 | }; 33 | } 34 | else if (isMpegDashFormatAvailable(formats)) { 35 | console.log('load mpeg dash'); 36 | return { 37 | sync: alwaysRequired.concat(['dash.all.min']) 38 | }; 39 | } 40 | else { 41 | console.log('adaptive streaming not available'); 42 | return { 43 | sync: alwaysRequired 44 | }; 45 | } 46 | }; 47 | }); 48 | -------------------------------------------------------------------------------- /viewer/lib/uv-default-extension-dependencies.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | return function (formats) { 3 | return { 4 | async: ['MetadataComponent'] 5 | }; 6 | }; 7 | }); 8 | -------------------------------------------------------------------------------- /viewer/lib/uv-default-extension.cy-GB.config.json: -------------------------------------------------------------------------------- 1 | {"options":{"authAPIVersion":1,"bookmarkThumbHeight":150,"bookmarkThumbWidth":90,"dropEnabled":true,"footerPanelEnabled":true,"headerPanelEnabled":true,"leftPanelEnabled":true,"limitLocales":false,"openTemplate":"http://universalviewer.io?manifest={0}","pessimisticAccessControl":false,"rightPanelEnabled":true,"theme":"uv-en-GB-theme"},"modules":{"shareDialogue":{"options":{"embedTemplate":""},"content":{"customSize":"arfer","embed":"gwreiddio","embedInstructions":"Er mwyn ymgorffori'r eitem hon ar eich gwefan, cop�wch a gosodwch y cod isod.","height":"Hyd","iiif":"IIIF Manifest","share":"Rhannu","shareInstructions":"I rannu yr eitem hon, copïwch y URL isod.","size":"maint:","width":"Lled"}},"fileLinkCenterPanel":{"content":{}},"footerPanel":{"options":{"bookmarkEnabled":false,"downloadEnabled":false,"embedEnabled":false,"feedbackEnabled":false,"minimiseButtons":true,"openEnabled":false,"shareEnabled":true},"content":{"bookmark":"Ychwanegu at nodau tudalen","download":"Lawrlwytho","embed":"Ymgorffori","exitFullScreen":"Dianc o'r sgrin lawn","fullScreen":"Sgrin lawn","moreInfo":"Mwy o Wybodaeth","open":"agored"}},"genericDialogue":{"content":{"ok":"GWELD"}},"headerPanel":{"content":{"close":"Cau","help":"Cymorth"}},"helpDialogue":{"content":{"text":"testun i'w osod","title":"Cymorth"}},"moreInfoRightPanel":{"options":{"canvasDisplayOrder":"","canvasExclude":"","copyToClipboardEnabled":false,"manifestDisplayOrder":"","manifestExclude":"","panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":false,"rtlLanguageCodes":"ar, ara, dv, div, he, heb, ur, urd","showAllLanguages":false,"textLimit":4,"textLimitType":"lines"},"content":{"attribution":"Priodoledd","collapse":"Lleihau'r Wybodaeth","collapseFull":"Cuddio'r Galeri","description":"Disgrifiad","expand":"Ehangu'r Wybodaeth","expandFull":"Ehangu'r Galeri","holdingText":"Eich modiwl fan hyn!","less":"llai","license":"Trwydded","logo":"Logo","more":"mwy","noData":"Nid oes data i'w arddangos","page":"tudalen","title":"Mwy o Wybodaeth","manifestHeader":"Am yr eitem","canvasHeader":"Am y ddelwedd","copyToClipboard":"Copïo i'r clipfwrdd","copiedToClipboard":"Copïwyd i'r clipfwrdd"}},"resourcesLeftPanel":{"options":{"expandFullEnabled":false,"panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":true},"content":{"title":"Cynnwys"}},"dialogue":{"content":{"close":"Cau"}},"downloadDialogue":{"content":{"download":"Lawrlwytho","entireFileAsOriginal":"Y ffeil gyfan","noneAvailable":"Nid oes unrhyw opsiynau lawrlwytho ar gael.","preview":"Rhagolwg","title":"Lawrlwytho"}},"loginDialogue":{"content":{"login":"Mewngofnodi","cancel":"Diddymu"}},"mediaelementCenterPanel":{"content":{}},"settingsDialogue":{"content":{"locale":"Iaith","pagingEnabled":"Arddangos dwy dudalen","preserveViewport":"Cadw'r lefel o glosio","title":"Dewisiadau","website":"mwy o wybodaeth"}}},"localisation":{"label":"Cymraeg","locales":[{"name":"cy-GB","label":"Cymraeg"},{"name":"en-GB","label":"English (GB)"},{"name":"fr-FR","label":"Français (FR)"},{"name":"sv-SE","label":"Svenska"}]},"content":{"authCORSError":"Eich porwr yn peidio cefnogi CORS, os gwelwch yn dda uwchraddio i weld y cynnwys hwn.","authorisationFailedMessage":"Nid oedd yn ymddangos eich ymgais mewngofnodi i fod yn llwyddiannus . Trio eto os gwelwch yn dda.","degradedResourceMessage":"Os gwelwch yn dda mewngofnodwch i weld yn ansawdd llawn.","degradedResourceLogin":"Mewngofnodi","forbiddenResourceMessage":"Eich hawliau mynediad presennol yn annigonol i weld llun hwn"}} -------------------------------------------------------------------------------- /viewer/lib/uv-default-extension.en-GB.config.json: -------------------------------------------------------------------------------- 1 | {"options":{"authAPIVersion":1,"bookmarkThumbHeight":150,"bookmarkThumbWidth":90,"dropEnabled":true,"footerPanelEnabled":true,"headerPanelEnabled":true,"leftPanelEnabled":true,"limitLocales":false,"openTemplate":"http://universalviewer.io?manifest={0}","pessimisticAccessControl":false,"rightPanelEnabled":true,"theme":"uv-en-GB-theme"},"modules":{"shareDialogue":{"options":{"embedTemplate":""},"content":{"customSize":"custom","embed":"Embed","embedInstructions":"To embed this item in your own website, copy and paste the code below.","height":"Height","iiif":"IIIF Manifest","share":"Share","shareInstructions":"To share this item, copy the URL below.","size":"Size:","width":"Width"}},"fileLinkCenterPanel":{"content":{}},"footerPanel":{"options":{"bookmarkEnabled":false,"downloadEnabled":false,"embedEnabled":false,"feedbackEnabled":false,"minimiseButtons":true,"openEnabled":false,"shareEnabled":true},"content":{"bookmark":"Add to bookmarks","download":"Download","embed":"Share","exitFullScreen":"Exit Full Screen","fullScreen":"Full Screen","moreInfo":"More Information","open":"Open"}},"genericDialogue":{"content":{"ok":"OK"}},"headerPanel":{"content":{"close":"Close","help":"Help"}},"helpDialogue":{"content":{"text":"placeholder text","title":"Help"}},"moreInfoRightPanel":{"options":{"canvasDisplayOrder":"","canvasExclude":"","copyToClipboardEnabled":false,"manifestDisplayOrder":"","manifestExclude":"","panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":false,"rtlLanguageCodes":"ar, ara, dv, div, he, heb, ur, urd","showAllLanguages":false,"textLimit":4,"textLimitType":"lines"},"content":{"attribution":"Attribution","collapse":"Collapse Information","collapseFull":"Collapse Gallery","description":"Description","expand":"Expand Information","expandFull":"Expand Gallery","holdingText":"Your module goes here!","less":"less","license":"License","logo":"Logo","more":"more","noData":"No data to display","page":"Page","title":"More Information","manifestHeader":"About the item","canvasHeader":"About the image","copyToClipboard":"Copy to clipboard","copiedToClipboard":"Copied to clipboard"}},"resourcesLeftPanel":{"options":{"expandFullEnabled":false,"panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":true},"content":{"title":"Contents"}},"dialogue":{"content":{"close":"Close"}},"downloadDialogue":{"content":{"download":"Download","entireFileAsOriginal":"Entire file","noneAvailable":"No download options are available.","preview":"Preview","title":"Download"}},"loginDialogue":{"content":{"login":"Login","cancel":"Cancel"}},"settingsDialogue":{"content":{"locale":"Locale","pagingEnabled":"Two Page View","preserveViewport":"Preserve Zoom","title":"Settings","website":"more info"}}},"localisation":{"label":"English (GB)","locales":[{"name":"cy-GB","label":"Cymraeg"},{"name":"en-GB","label":"English (GB)"},{"name":"fr-FR","label":"Français (FR)"},{"name":"sv-SE","label":"Svenska"}]},"content":{"authCORSError":"Your browser does not support CORS, please upgrade to view this content.","authorisationFailedMessage":"Your log-in attempt did not appear to be successful. Please try again.","degradedResourceMessage":"Please log in to view at full quality.","degradedResourceLogin":"log in","forbiddenResourceMessage":"Your current access rights are insufficient to view this image"}} -------------------------------------------------------------------------------- /viewer/lib/uv-ebook-components.css: -------------------------------------------------------------------------------- 1 | :root{--toc-margin:0;--toc-padding:0;--toc-list-style-type:none;--toc-link-color:#4e4e4e;--toc-link-selected-color:#949494;--toc-link-padding:0.25rem;--reader-arrow-color:#e2e2e2;--reader-arrow-hover-color:#777;--reader-spinner-color:#bdbdbd}.disabled{pointer-events:none;opacity:.4} -------------------------------------------------------------------------------- /viewer/lib/uv-ebook-components.esm.js: -------------------------------------------------------------------------------- 1 | import{p as e,b as d}from"./p-30b7f65b.js";e().then(e=>d([["p-r5bfv5hp",[[0,"uv-ebook-reader",{width:[1],height:[1],mobileWidth:[2,"mobile-width"],minSpreadWidth:[2,"min-spread-width"],_bookPath:[32],_bookReady:[32],_prevEnabled:[32],_mobile:[32],_nextEnabled:[32],_showDivider:[32],load:[64],resize:[64],display:[64]},[[8,"keydown","handleKeyDown"]]],[0,"uv-ebook-toc",{toc:[16],selected:[1025],disabled:[4]}]]]],e)); -------------------------------------------------------------------------------- /viewer/lib/uv-ebook-extension-dependencies.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | return function (formats) { 3 | return { 4 | async: ['MetadataComponent', 'uv-ebook-extension.proxy'] 5 | }; 6 | }; 7 | }); 8 | -------------------------------------------------------------------------------- /viewer/lib/uv-ebook-extension.proxy.js: -------------------------------------------------------------------------------- 1 | // https://github.com/ionic-team/stencil/issues/365 2 | // *.proxy.js files are ignored when cleaning lib folders 3 | 4 | (function() { 5 | var t = document.createElement("script"); 6 | // if in an iframe (embedded) 7 | t.src = (window.self !== window.top)? "lib/uv-ebook-components.js" : "uv/lib/uv-ebook-components.js"; 8 | document.body.appendChild(t); 9 | })(); -------------------------------------------------------------------------------- /viewer/lib/uv-mediaelement-extension-dependencies.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | return function (formats) { 3 | return { 4 | async: ['mediaelement-and-player', 'MetadataComponent'] 5 | }; 6 | }; 7 | }); 8 | -------------------------------------------------------------------------------- /viewer/lib/uv-mediaelement-extension.cy-GB.config.json: -------------------------------------------------------------------------------- 1 | {"options":{"authAPIVersion":1,"bookmarkThumbHeight":150,"bookmarkThumbWidth":90,"dropEnabled":true,"footerPanelEnabled":true,"headerPanelEnabled":true,"leftPanelEnabled":true,"limitLocales":false,"openTemplate":"http://universalviewer.io?manifest={0}","pessimisticAccessControl":false,"rightPanelEnabled":true,"theme":"uv-en-GB-theme"},"modules":{"shareDialogue":{"options":{"embedTemplate":""},"content":{"customSize":"arfer","embed":"gwreiddio","embedInstructions":"Er mwyn ymgorffori'r eitem hon ar eich gwefan, cop�wch a gosodwch y cod isod.","height":"Hyd","iiif":"IIIF Manifest","share":"Rhannu","shareInstructions":"I rannu yr eitem hon, copïwch y URL isod.","size":"maint:","width":"Lled"}},"footerPanel":{"options":{"bookmarkEnabled":false,"embedEnabled":false,"feedbackEnabled":false,"minimiseButtons":true,"openEnabled":false,"shareEnabled":true},"content":{"bookmark":"Ychwanegu at nodau tudalen","download":"Lawrlwytho","embed":"Ymgorffori","exitFullScreen":"Dianc o'r sgrin lawn","fullScreen":"Sgrin lawn","moreInfo":"Mwy o Wybodaeth","open":"agored"}},"genericDialogue":{"content":{"ok":"GWELD"}},"headerPanel":{"content":{"close":"Cau","help":"Cymorth"}},"helpDialogue":{"content":{"text":"testun i'w osod","title":"Cymorth"}},"mediaelementCenterPanel":{"defaultHeight":420,"defaultWidth":560,"content":{}},"moreInfoRightPanel":{"options":{"canvasDisplayOrder":"","canvasExclude":"","copyToClipboardEnabled":false,"manifestDisplayOrder":"","manifestExclude":"","panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":false,"rtlLanguageCodes":"ar, ara, dv, div, he, heb, ur, urd","showAllLanguages":false,"textLimit":4,"textLimitType":"lines"},"content":{"attribution":"Priodoledd","collapse":"Lleihau'r Wybodaeth","collapseFull":"Cuddio'r Galeri","description":"Disgrifiad","expand":"Ehangu'r Wybodaeth","expandFull":"Ehangu'r Galeri","holdingText":"Eich modiwl fan hyn!","less":"llai","license":"Trwydded","logo":"Logo","more":"mwy","noData":"Nid oes data i'w arddangos","page":"tudalen","title":"Mwy o Wybodaeth","manifestHeader":"Am yr eitem","canvasHeader":"Am y ddelwedd","copyToClipboard":"Copïo i'r clipfwrdd","copiedToClipboard":"Copïwyd i'r clipfwrdd"}},"resourcesLeftPanel":{"options":{"expandFullEnabled":false,"panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":true},"content":{"title":"Cynnwys"}},"dialogue":{"content":{"close":"Cau"}},"downloadDialogue":{"content":{"download":"Lawrlwytho","entireFileAsOriginal":"Y ffeil gyfan","noneAvailable":"Nid oes unrhyw opsiynau lawrlwytho ar gael.","preview":"Rhagolwg","title":"Lawrlwytho"}},"loginDialogue":{"content":{"login":"Mewngofnodi","cancel":"Diddymu"}},"settingsDialogue":{"content":{"locale":"Iaith","pagingEnabled":"Arddangos dwy dudalen","preserveViewport":"Cadw'r lefel o glosio","title":"Dewisiadau","website":"mwy o wybodaeth"}}},"localisation":{"label":"Cymraeg","locales":[{"name":"cy-GB","label":"Cymraeg"},{"name":"en-GB","label":"English (GB)"},{"name":"fr-FR","label":"Français (FR)"},{"name":"sv-SE","label":"Svenska"}]},"content":{"authCORSError":"Eich porwr yn peidio cefnogi CORS, os gwelwch yn dda uwchraddio i weld y cynnwys hwn.","authorisationFailedMessage":"Nid oedd yn ymddangos eich ymgais mewngofnodi i fod yn llwyddiannus . Trio eto os gwelwch yn dda.","degradedResourceMessage":"Os gwelwch yn dda mewngofnodwch i weld yn ansawdd llawn.","degradedResourceLogin":"Mewngofnodi","forbiddenResourceMessage":"Eich hawliau mynediad presennol yn annigonol i weld llun hwn"}} -------------------------------------------------------------------------------- /viewer/lib/uv-mediaelement-extension.en-GB.config.json: -------------------------------------------------------------------------------- 1 | {"options":{"authAPIVersion":1,"bookmarkThumbHeight":150,"bookmarkThumbWidth":90,"dropEnabled":true,"footerPanelEnabled":true,"headerPanelEnabled":true,"leftPanelEnabled":true,"limitLocales":false,"openTemplate":"http://universalviewer.io?manifest={0}","pessimisticAccessControl":false,"rightPanelEnabled":true,"theme":"uv-en-GB-theme"},"modules":{"shareDialogue":{"options":{"embedTemplate":""},"content":{"customSize":"custom","embed":"Embed","embedInstructions":"To embed this item in your own website, copy and paste the code below.","height":"Height","iiif":"IIIF Manifest","share":"Share","shareInstructions":"To share this item, copy the URL below.","size":"Size:","width":"Width"}},"footerPanel":{"options":{"bookmarkEnabled":false,"embedEnabled":false,"feedbackEnabled":false,"minimiseButtons":true,"openEnabled":false,"shareEnabled":true},"content":{"bookmark":"Add to bookmarks","download":"Download","embed":"Share","exitFullScreen":"Exit Full Screen","fullScreen":"Full Screen","moreInfo":"More Information","open":"Open","share":"Share"}},"genericDialogue":{"content":{"ok":"OK"}},"headerPanel":{"content":{"close":"Close","help":"Help"}},"helpDialogue":{"content":{"text":"placeholder text","title":"Help"}},"mediaelementCenterPanel":{"defaultHeight":420,"defaultWidth":560,"content":{}},"moreInfoRightPanel":{"options":{"canvasDisplayOrder":"","canvasExclude":"","copyToClipboardEnabled":false,"manifestDisplayOrder":"","manifestExclude":"","panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":false,"rtlLanguageCodes":"ar, ara, dv, div, he, heb, ur, urd","showAllLanguages":false,"textLimit":4,"textLimitType":"lines"},"content":{"attribution":"Attribution","collapse":"Collapse Information","collapseFull":"Collapse Gallery","description":"Description","expand":"Expand Information","expandFull":"Expand Gallery","holdingText":"Your module goes here!","less":"less","license":"License","logo":"Logo","more":"more","noData":"No data to display","page":"Page","title":"More Information","manifestHeader":"About the item","canvasHeader":"About the image","copyToClipboard":"Copy to clipboard","copiedToClipboard":"Copied to clipboard"}},"resourcesLeftPanel":{"options":{"expandFullEnabled":false,"panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":true},"content":{"title":"Contents"}},"dialogue":{"content":{"close":"Close"}},"downloadDialogue":{"content":{"download":"Download","entireFileAsOriginal":"Entire file","noneAvailable":"No download options are available.","preview":"Preview","title":"Download"}},"loginDialogue":{"content":{"login":"Login","cancel":"Cancel"}},"settingsDialogue":{"content":{"locale":"Locale","pagingEnabled":"Two Page View","preserveViewport":"Preserve Zoom","title":"Settings","website":"more info"}}},"localisation":{"label":"English (GB)","locales":[{"name":"cy-GB","label":"Cymraeg"},{"name":"en-GB","label":"English (GB)"},{"name":"fr-FR","label":"Français (FR)"},{"name":"sv-SE","label":"Svenska"}]},"content":{"authCORSError":"Your browser does not support CORS, please upgrade to view this content.","authorisationFailedMessage":"Your log-in attempt did not appear to be successful. Please try again.","degradedResourceMessage":"Please log in to view at full quality.","degradedResourceLogin":"log in","forbiddenResourceMessage":"Your current access rights are insufficient to view this image"}} -------------------------------------------------------------------------------- /viewer/lib/uv-pdf-extension-dependencies.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | return function (formats) { 3 | return { 4 | sync: ['pdfobject'], 5 | async: ['!pdfjs-dist/build/pdf.combined', 'MetadataComponent'] 6 | }; 7 | }; 8 | }); 9 | -------------------------------------------------------------------------------- /viewer/lib/uv-pdf-extension.cy-GB.config.json: -------------------------------------------------------------------------------- 1 | {"options":{"authAPIVersion":1,"bookmarkThumbHeight":150,"bookmarkThumbWidth":90,"dropEnabled":true,"footerPanelEnabled":true,"headerPanelEnabled":true,"limitLocales":false,"openTemplate":"http://universalviewer.io?manifest={0}","pessimisticAccessControl":false,"rightPanelEnabled":true,"theme":"uv-en-GB-theme","usePdfJs":true},"modules":{"shareDialogue":{"options":{"embedTemplate":""},"content":{"customSize":"arfer","embed":"gwreiddio","embedInstructions":"Er mwyn ymgorffori'r eitem hon ar eich gwefan, cop�wch a gosodwch y cod isod.","height":"Hyd","iiif":"IIIF Manifest","share":"Rhannu","shareInstructions":"I rannu yr eitem hon, copïwch y URL isod.","size":"maint:","width":"Lled"}},"footerPanel":{"options":{"bookmarkEnabled":false,"embedEnabled":false,"feedbackEnabled":false,"minimiseButtons":true,"openEnabled":false,"shareEnabled":true},"content":{"bookmark":"Ychwanegu at nodau tudalen","download":"Lawrlwytho","embed":"Ymgorffori","exitFullScreen":"Dianc o'r sgrin lawn","feedback":"Adborth","fullScreen":"Sgrin lawn","moreInfo":"Mwy o Wybodaeth","open":"Agor","share":"Rhannu"}},"genericDialogue":{"content":{"ok":"GWELD"}},"headerPanel":{"content":{"close":"Cau","help":"Help"}},"helpDialogue":{"content":{"text":"testun i'w osod","title":"Cymorth"}},"moreInfoRightPanel":{"options":{"canvasDisplayOrder":"","canvasExclude":"","copyToClipboardEnabled":false,"manifestDisplayOrder":"","manifestExclude":"","panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":false,"rtlLanguageCodes":"ar, ara, dv, div, he, heb, ur, urd","showAllLanguages":false,"textLimit":4,"textLimitType":"lines"},"content":{"attribution":"Priodoledd","collapse":"Lleihau'r Wybodaeth","collapseFull":"Cuddio'r Galeri","description":"Disgrifiad","expand":"Ehangu'r Wybodaeth","expandFull":"Ehangu'r Galeri","holdingText":"Eich modiwl fan hyn!","less":"llai","license":"Trwydded","logo":"Logo","more":"mwy","noData":"Nid oes data i'w arddangos","page":"tudalen","title":"Mwy o Wybodaeth","manifestHeader":"Am yr eitem","canvasHeader":"Am y ddelwedd","copyToClipboard":"Copïo i'r clipfwrdd","copiedToClipboard":"Copïwyd i'r clipfwrdd"}},"pdfCenterPanel":{"options":{"titleEnabled":false}},"resourcesLeftPanel":{"options":{"elideCount":40,"galleryThumbHeight":320,"galleryThumbWidth":200,"oneColThumbHeight":320,"oneColThumbWidth":200,"pageModeEnabled":true,"panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":true,"thumbsEnabled":true,"thumbsExtraHeight":8,"thumbsImageFadeInDuration":300,"thumbsLoadRange":15,"treeEnabled":true,"twoColThumbHeight":150,"twoColThumbWidth":90}},"dialogue":{"content":{"close":"Cau"}},"downloadDialogue":{"content":{"download":"Lawrlwytho","entireFileAsOriginal":"Y ffeil gyfan","noneAvailable":"Nid oes unrhyw opsiynau lawrlwytho ar gael.","preview":"Rhagolwg","title":"Lawrlwytho"}},"pdfHeaderPanel":{"content":{"emptyValue":"Rhowch werth","first":"Gyntaf","go":"Ewch","last":"Diwethaf","next":"Nesaf","of":"o {0}","previous":"Blaenorol"}},"loginDialogue":{"content":{"login":"Mewngofnodi","cancel":"Diddymu"}},"settingsDialogue":{"content":{"locale":"Iaith","pagingEnabled":"Arddangos dwy dudalen","preserveViewport":"Cadw'r lefel o glosio","title":"Dewisiadau","website":"mwy o wybodaeth"}},"contentLeftPanel":{"content":{"collapse":"Cuddio'r Cynnwys","collapseFull":"Cuddio'r Galeri","expand":"Ehangu'r Cynnwys","expandFull":"Ehangu'r Galeri","index":"Mynegai","thumbnails":"Bodluniau","title":"Cynnwys"}}},"localisation":{"label":"Cymraeg","locales":[{"name":"cy-GB","label":"Cymraeg"},{"name":"en-GB","label":"English (GB)"},{"name":"fr-FR","label":"Français (FR)"},{"name":"sv-SE","label":"Svenska"}]},"content":{"authCORSError":"Eich porwr yn peidio cefnogi CORS, os gwelwch yn dda uwchraddio i weld y cynnwys hwn.","authorisationFailedMessage":"Nid oedd yn ymddangos eich ymgais mewngofnodi i fod yn llwyddiannus . Trio eto os gwelwch yn dda.","degradedResourceMessage":"Os gwelwch yn dda mewngofnodwch i weld yn ansawdd llawn.","degradedResourceLogin":"Mewngofnodi","forbiddenResourceMessage":"Eich hawliau mynediad presennol yn annigonol i weld llun hwn"}} -------------------------------------------------------------------------------- /viewer/lib/uv-pdf-extension.en-GB.config.json: -------------------------------------------------------------------------------- 1 | {"options":{"authAPIVersion":1,"bookmarkThumbHeight":150,"bookmarkThumbWidth":90,"dropEnabled":true,"footerPanelEnabled":true,"headerPanelEnabled":true,"limitLocales":false,"openTemplate":"http://universalviewer.io?manifest={0}","pessimisticAccessControl":false,"rightPanelEnabled":true,"theme":"uv-en-GB-theme","usePdfJs":true},"modules":{"shareDialogue":{"options":{"embedTemplate":""},"content":{"customSize":"custom","embed":"Embed","embedInstructions":"To embed this item in your own website, copy and paste the code below.","height":"Height","iiif":"IIIF Manifest","share":"Share","shareInstructions":"To share this item, copy the URL below.","size":"Size:","width":"Width"}},"footerPanel":{"options":{"bookmarkEnabled":false,"embedEnabled":false,"feedbackEnabled":false,"minimiseButtons":true,"openEnabled":false,"shareEnabled":true},"content":{"bookmark":"Add to bookmarks","download":"Download","embed":"Embed","exitFullScreen":"Exit Full Screen","feedback":"Feedback","fullScreen":"Full Screen","moreInfo":"More Information","open":"Open","share":"Share"}},"genericDialogue":{"content":{"ok":"OK"}},"headerPanel":{"content":{"close":"Close","help":"Help"}},"helpDialogue":{"content":{"text":"placeholder text","title":"Help"}},"moreInfoRightPanel":{"options":{"canvasDisplayOrder":"","canvasExclude":"","copyToClipboardEnabled":false,"manifestDisplayOrder":"","manifestExclude":"","panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":false,"rtlLanguageCodes":"ar, ara, dv, div, he, heb, ur, urd","showAllLanguages":false,"textLimit":4,"textLimitType":"lines"},"content":{"attribution":"Attribution","collapse":"Collapse Information","collapseFull":"Collapse Gallery","description":"Description","expand":"Expand Information","expandFull":"Expand Gallery","holdingText":"Your module goes here!","less":"less","license":"License","logo":"Logo","more":"more","noData":"No data to display","page":"Page","title":"More Information","manifestHeader":"About the item","canvasHeader":"About the image","copyToClipboard":"Copy to clipboard","copiedToClipboard":"Copied to clipboard"}},"pdfCenterPanel":{"options":{"titleEnabled":false},"content":{"attribution":"Attribution"}},"resourcesLeftPanel":{"options":{"elideCount":40,"galleryThumbHeight":320,"galleryThumbWidth":200,"oneColThumbHeight":320,"oneColThumbWidth":200,"pageModeEnabled":true,"panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":true,"thumbsEnabled":true,"thumbsExtraHeight":8,"thumbsImageFadeInDuration":300,"thumbsLoadRange":15,"treeEnabled":true,"twoColThumbHeight":150,"twoColThumbWidth":90}},"dialogue":{"content":{"close":"Close"}},"downloadDialogue":{"content":{"download":"Download","entireFileAsOriginal":"Entire file","noneAvailable":"No download options are available.","preview":"Preview","title":"Download"}},"pdfHeaderPanel":{"content":{"emptyValue":"Please enter a value","first":"First","go":"Go","last":"Last","next":"Next","of":"of {0}","previous":"Previous"}},"loginDialogue":{"content":{"login":"Login","cancel":"Cancel"}},"settingsDialogue":{"content":{"locale":"Locale","pagingEnabled":"Two Page View","preserveViewport":"Preserve Zoom","title":"Settings","website":"more info"}},"contentLeftPanel":{}},"localisation":{"label":"English (GB)","locales":[{"name":"cy-GB","label":"Cymraeg"},{"name":"en-GB","label":"English (GB)"},{"name":"fr-FR","label":"Français (FR)"},{"name":"sv-SE","label":"Svenska"}]},"content":{"authCORSError":"Your browser does not support CORS, please upgrade to view this content.","authorisationFailedMessage":"Your log-in attempt did not appear to be successful. Please try again.","degradedResourceMessage":"Please log in to view at full quality.","degradedResourceLogin":"log in","forbiddenResourceMessage":"Your current access rights are insufficient to view this image"}} -------------------------------------------------------------------------------- /viewer/lib/uv-seadragon-extension-dependencies.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | return function (formats) { 3 | return { 4 | async: ['TreeComponent', 'GalleryComponent', 'MetadataComponent', 'openseadragon.min'] 5 | }; 6 | }; 7 | }); 8 | -------------------------------------------------------------------------------- /viewer/lib/uv-virtex-extension-dependencies.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | return function (formats) { 3 | return { 4 | sync: ['three.min'], 5 | async: ['VRControls', 'VREffect', 'stats.min', 'OBJLoader', 'MTLLoader', 'PLYLoader', 'GLTFLoader', 'Detector', 'WebVR', 'virtex', 'MetadataComponent'] 6 | }; 7 | }; 8 | }); 9 | -------------------------------------------------------------------------------- /viewer/lib/uv-virtex-extension.cy-GB.config.json: -------------------------------------------------------------------------------- 1 | {"options":{"authAPIVersion":1,"bookmarkThumbHeight":150,"bookmarkThumbWidth":90,"dropEnabled":true,"footerPanelEnabled":true,"headerPanelEnabled":true,"leftPanelEnabled":true,"limitLocales":false,"openTemplate":"http://universalviewer.io?manifest={0}","rightPanelEnabled":true,"theme":"uv-cy-GB-theme"},"modules":{"shareDialogue":{"options":{"embedTemplate":""},"content":{"customSize":"arfer","embed":"gwreiddio","embedInstructions":"Er mwyn ymgorffori'r eitem hon ar eich gwefan, cop�wch a gosodwch y cod isod.","height":"Hyd","iiif":"IIIF Manifest","share":"Rhannu","shareInstructions":"I rannu yr eitem hon, copïwch y URL isod.","size":"maint:","width":"Lled"}},"footerPanel":{"options":{"downloadEnabled":true,"embedEnabled":false,"feedbackEnabled":false,"minimiseButtons":true,"openEnabled":false,"shareEnabled":true},"content":{"bookmark":"Ychwanegu at nodau tudalen","download":"Lawrlwytho","embed":"Ymgorffori","exitFullScreen":"Dianc o'r sgrin lawn","fullScreen":"Sgrin lawn","moreInfo":"Mwy o Wybodaeth","open":"agored","share":"Rhannu"}},"genericDialogue":{"content":{"ok":"GWELD"}},"headerPanel":{"content":{"close":"Cau","help":"Cymorth","settings":"Dewisiadau"}},"helpDialogue":{"content":{"text":"testun i'w osod","title":"Cymorth"}},"moreInfoRightPanel":{"options":{"canvasDisplayOrder":"","canvasExclude":"","copyToClipboardEnabled":false,"manifestDisplayOrder":"","manifestExclude":"","panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":false,"rtlLanguageCodes":"ar, ara, dv, div, he, heb, ur, urd","showAllLanguages":false,"textLimit":4,"textLimitType":"lines"},"content":{"attribution":"Priodoledd","collapse":"Lleihau'r Wybodaeth","collapseFull":"Cuddio'r Galeri","description":"Disgrifiad","expand":"Ehangu'r Wybodaeth","expandFull":"Ehangu'r Galeri","holdingText":"Eich modiwl fan hyn!","less":"llai","license":"Trwydded","logo":"Logo","more":"mwy","noData":"Nid oes data i'w arddangos","page":"tudalen","title":"Mwy o Wybodaeth","manifestHeader":"Am yr eitem","canvasHeader":"Am y ddelwedd","copyToClipboard":"Copïo i'r clipfwrdd","copiedToClipboard":"Copïwyd i'r clipfwrdd"}},"contentLeftPanel":{"options":{"elideCount":40,"galleryThumbHeight":320,"galleryThumbWidth":200,"oneColThumbHeight":320,"oneColThumbWidth":200,"pageModeEnabled":true,"panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":true,"thumbsEnabled":true,"thumbsExtraHeight":8,"thumbsImageFadeInDuration":300,"thumbsLoadRange":15,"treeEnabled":true,"twoColThumbHeight":150,"twoColThumbWidth":90}},"virtexCenterPanel":{"options":{"showStats":false,"trimAttributionCount":150,"vrEnabled":false},"content":{"attribution":"Priodoliad","zoomIn":"chwyddo Mewn","zoomOut":"Zoom Out","vr":"VR"}},"dialogue":{"content":{"close":"Cau"}},"downloadDialogue":{"content":{"download":"Lawrlwytho","entireFileAsOriginal":"Y ffeil gyfan","noneAvailable":"Nid oes unrhyw opsiynau lawrlwytho ar gael.","preview":"Rhagolwg","title":"Lawrlwytho"}},"loginDialogue":{"content":{"login":"Mewngofnodi","cancel":"Diddymu"}},"mediaelementCenterPanel":{"content":{}},"settingsDialogue":{"content":{"locale":"Iaith","pagingEnabled":"Arddangos dwy dudalen","preserveViewport":"Cadw'r lefel o glosio","title":"Dewisiadau","website":"mwy o wybodaeth"}}},"localisation":{"label":"Cymraeg","locales":[{"name":"cy-GB","label":"Cymraeg"},{"name":"en-GB","label":"English (GB)"},{"name":"fr-FR","label":"Français (FR)"},{"name":"sv-SE","label":"Svenska"}]},"content":{"authCORSError":"Eich porwr yn peidio cefnogi CORS, os gwelwch yn dda uwchraddio i weld y cynnwys hwn.","authorisationFailedMessage":"Nid oedd yn ymddangos eich ymgais mewngofnodi i fod yn llwyddiannus . Trio eto os gwelwch yn dda.","degradedResourceMessage":"Os gwelwch yn dda mewngofnodwch i weld yn ansawdd llawn.","degradedResourceLogin":"Mewngofnodi","forbiddenResourceMessage":"Eich hawliau mynediad presennol yn annigonol i weld llun hwn"}} -------------------------------------------------------------------------------- /viewer/lib/uv-virtex-extension.en-GB.config.json: -------------------------------------------------------------------------------- 1 | {"options":{"authAPIVersion":1,"bookmarkThumbHeight":150,"bookmarkThumbWidth":90,"dropEnabled":true,"footerPanelEnabled":true,"headerPanelEnabled":true,"leftPanelEnabled":true,"limitLocales":false,"openTemplate":"http://universalviewer.io?manifest={0}","rightPanelEnabled":true,"theme":"uv-en-GB-theme"},"modules":{"shareDialogue":{"options":{"embedTemplate":""},"content":{"customSize":"custom","embed":"Embed","embedInstructions":"To embed this item in your own website, copy and paste the code below.","height":"Height","iiif":"IIIF Manifest","share":"Share","shareInstructions":"To share this item, copy the URL below.","size":"Size:","width":"Width"}},"footerPanel":{"options":{"downloadEnabled":true,"embedEnabled":false,"feedbackEnabled":false,"minimiseButtons":true,"openEnabled":false,"shareEnabled":true},"content":{"bookmark":"Add to bookmarks","download":"Download","embed":"Embed","exitFullScreen":"Exit Full Screen","fullScreen":"Full Screen","moreInfo":"More Information","open":"Open","share":"Share"}},"genericDialogue":{"content":{"ok":"OK"}},"headerPanel":{"content":{"close":"Close","help":"Help","settings":"Settings"}},"helpDialogue":{"content":{"text":"placeholder text","title":"Help"}},"moreInfoRightPanel":{"options":{"canvasDisplayOrder":"","canvasExclude":"","copyToClipboardEnabled":false,"manifestDisplayOrder":"","manifestExclude":"","panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":false,"rtlLanguageCodes":"ar, ara, dv, div, he, heb, ur, urd","showAllLanguages":false,"textLimit":4,"textLimitType":"lines"},"content":{"attribution":"Attribution","collapse":"Collapse Information","collapseFull":"Collapse Gallery","description":"Description","expand":"Expand Information","expandFull":"Expand Gallery","holdingText":"Your module goes here!","less":"less","license":"License","logo":"Logo","more":"more","noData":"No data to display","page":"Page","title":"More Information","manifestHeader":"About the item","canvasHeader":"About the image","copyToClipboard":"Copy to clipboard","copiedToClipboard":"Copied to clipboard"}},"contentLeftPanel":{"options":{"elideCount":40,"galleryThumbHeight":320,"galleryThumbWidth":200,"oneColThumbHeight":320,"oneColThumbWidth":200,"pageModeEnabled":true,"panelAnimationDuration":250,"panelCollapsedWidth":30,"panelExpandedWidth":255,"panelOpen":true,"thumbsEnabled":true,"thumbsExtraHeight":8,"thumbsImageFadeInDuration":300,"thumbsLoadRange":15,"treeEnabled":true,"twoColThumbHeight":150,"twoColThumbWidth":90}},"virtexCenterPanel":{"options":{"showStats":false,"trimAttributionCount":150,"vrEnabled":false},"content":{"attribution":"Attribution","zoomIn":"Zoom In","zoomOut":"Zoom Out","vr":"VR"}},"dialogue":{"content":{"close":"Close"}},"downloadDialogue":{"content":{"download":"Download","entireFileAsOriginal":"Entire file","noneAvailable":"No download options are available.","preview":"Preview","title":"Download"}},"loginDialogue":{"content":{"login":"Login","cancel":"Cancel"}},"mediaelementCenterPanel":{"content":{}},"settingsDialogue":{"content":{"locale":"Locale","pagingEnabled":"Two Page View","preserveViewport":"Preserve Zoom","title":"Settings","website":"more info"}}},"localisation":{"label":"English (GB)","locales":[{"name":"cy-GB","label":"Cymraeg"},{"name":"en-GB","label":"English (GB)"},{"name":"fr-FR","label":"Français (FR)"},{"name":"sv-SE","label":"Svenska"}]},"content":{"authCORSError":"Your browser does not support CORS, please upgrade to view this content.","authorisationFailedMessage":"Your log-in attempt did not appear to be successful. Please try again.","degradedResourceMessage":"Please log in to view at full quality.","degradedResourceLogin":"log in","forbiddenResourceMessage":"Your current access rights are insufficient to view this image"}} -------------------------------------------------------------------------------- /viewer/themes/uv-en-gb-theme/assets/hamburger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caltechlibrary/dibs/7f57e5420a813e0d3fa2db7b109e65b2eda6b218/viewer/themes/uv-en-gb-theme/assets/hamburger.png -------------------------------------------------------------------------------- /viewer/uv.css: -------------------------------------------------------------------------------- 1 | 2 | .uv { 3 | background-color: #000; 4 | } 5 | 6 | .uv.loading { 7 | background-repeat: no-repeat; 8 | background-position: 50% 50%; 9 | background-image: url(data:image/gif;base64,R0lGODlhFAAUAMQSAGxsbFpaWnh4eEZGRhwcHD8/PzU1NVJSUisrKwgICH5+fkxMTGNjYyUlJXJycnt7exISEoCAgAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo1OTFjMzhjNS0xZmQyLTg5NGUtYjMyZi1kYTNkZWQ5NmQ5YjMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Qzc0OEE1NDA5OTMzMTFFNUFBRjI5MkI3NTFFODJFRTYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Qzc0OEE1M0Y5OTMzMTFFNUFBRjI5MkI3NTFFODJFRTYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NTkxYzM4YzUtMWZkMi04OTRlLWIzMmYtZGEzZGVkOTZkOWIzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjU5MWMzOGM1LTFmZDItODk0ZS1iMzJmLWRhM2RlZDk2ZDliMyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAkAABIALAAAAAAUABQAAAVAoCSOZGmeaKqmSeu+LRpEdG0Hsq1H+DnvtZ7pB+TlikYfMjlcCktE4JMU3U1HVd1VlL2hCIiweExYmc/otHoUAgAh+QQJAAASACwAAAAAFAAUAAAFWqAkjmRpnmgqEgyhnkykHNA7GlEePUXyJg6dzoFQDYTI1gnyQCIVC1PA6YySGlSkwEcCZIWGEu6bA5gSCwW5gWJlAy+EV6io/QrN3MA2ShwUW3wkBGyChocSIQAh+QQFAAASACwAAAAAFAAUAAAFXKAkjmRpnmhaJsuimoYQKcQrNkCkR8wLBbsgApUYKIJBR8LUcCCfBRPh+Aw+IKZDFXkwQR7bHc1UCO96q1yYUTMhtg6DioFUDJaq6S6AtUkWEQANfiMJcoSIiSUhADs=); 10 | } -------------------------------------------------------------------------------- /viewer/uv.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 60 | 61 | 62 | 63 |
64 | 65 | 86 | 87 | 88 | 89 | 90 | 91 | --------------------------------------------------------------------------------