diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index f93b6dc87..98f6e8197 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -121,10 +121,6 @@ jobs:
--health-retries 5
ports:
- 5434:5432
- goaws:
- image: nulib/goaws
- ports:
- - 4102:4100
ldap:
image: nulib/ldap-alpine
ports:
@@ -136,25 +132,30 @@ jobs:
ELASTICSEARCH_HEAP_SIZE: "256m"
ports:
- 9202:9200
- minio:
- image: bitnami/minio
+ localstack:
+ image: localstack/localstack
env:
- MINIO_ROOT_USER: minio
- MINIO_ROOT_PASSWORD: minio123
- MINIO_ACCESS_KEY: minio
- MINIO_SECRET_KEY: minio123
- MINIO_NOTIFY_WEBHOOK_ENABLE_checksum: on
- MINIO_NOTIFY_WEBHOOK_ENDPOINT_checksum: http://minio-checksum:8000/fixity
+ DNS_ADDRESS: 127.0.0.1
+ EDGE_PORT: 4568
+ EDGE_PORT_HTTP: 4568
+ LAMBDA_EXECUTOR: local
+ LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }}
ports:
- - 9002:9000
- minio-checksum:
- image: nulib/minio-checksum
- env:
- AWS_ACCESS_KEY_ID: minio
- AWS_SECRET_ACCESS_KEY: minio123
- AWS_S3_ENDPOINT: http://minio:9000/
+ - 4568:4568
steps:
- uses: actions/checkout@v2
+ - uses: actions/checkout@v2
+ with:
+ repository: 'nulib/devstack'
+ ref: main
+ path: '.devstack'
+ - uses: hashicorp/setup-terraform@v1
+ - name: Provision Localstack resources
+ run: .devstack/bin/devstack -t provision meadow
+ env:
+ AWS_DEFAULT_REGION: us-east-1
+ AWS_ACCESS_KEY_ID: fake
+ AWS_SECRET_ACCESS_KEY: fake
- uses: actions/setup-node@v2
with:
node-version: "14"
diff --git a/.gitignore b/.gitignore
index 95bc62c2d..1b1fd7523 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,4 +69,6 @@ yarn.lock
/assets/yarn-error.log
.DS_Store
-**/*/.DS_Store
\ No newline at end of file
+**/*/.DS_Store
+localstack/.terraform
+localstack/terraform.tfstate.d
diff --git a/Localstack S3.duck b/Localstack S3.duck
new file mode 100644
index 000000000..6182ca5f1
--- /dev/null
+++ b/Localstack S3.duck
@@ -0,0 +1,25 @@
+
+
+
+
+ Protocol
+ s3
+ Provider
+ s3-https
+ Nickname
+ Localstack S3
+ UUID
+ f7fedad5-d8cd-4165-a617-b1c3bc3edf8d
+ Hostname
+ localhost.localstack.cloud
+ Port
+ 4566
+ Username
+ fake
+ Access Timestamp
+ 1643041454095
+ Labels
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index a0adddfeb..adcf68785 100644
--- a/README.md
+++ b/README.md
@@ -78,15 +78,12 @@ The task `mix meadow.ldap.setup [seed_file ...]` will seed the LDAP database usi
- Start test devstack: `devstack -t up meadow`
- run `mix test`
-### Amazon s3/Minio
+### Accessing S3 Buckets in Development
-See your local "s3" buckets.
+[Localstack](https://localstack.cloud), which we use to emulate Amazon S3 (and other services) in the development environment, does not have a full-featured S3 web UI, so it's necessary to use a utility like the [LocalStack AWS Command Line Interface](https://github.com/localstack/awscli-local) or [Cyberduck](https://cyberduck.io). There is a [Cyberduck Shortcut](Localstack%20S3.duck) in the root of this repository that will configure the app the connect to the S3 dev instance.
-- Dev: `https://devbox.library.northwestern.edu:9001/`
-- Test: `https://devbox.library.northwestern.edu:9002/`
+*Note*: You may receive “incomplete transfer” warnings when uploading files through Cyberduck. This appears to be a bug in Cyberduck, and can be safely ignored. If you click the refresh icon in the main window after upload, you should see the uploaded files.
-**Login**: minio
-**Password**: minio123
### GraphQL API
diff --git a/assets/js/components/Work/work.gql.js b/assets/js/components/Work/work.gql.js
index c4f2fe9e9..50d36c77e 100644
--- a/assets/js/components/Work/work.gql.js
+++ b/assets/js/components/Work/work.gql.js
@@ -461,7 +461,7 @@ export const UPDATE_WORK = gql`
export const INGEST_FILE_SET = gql`
mutation IngestFileSet(
$accession_number: String!
- $role: FileSetRole!
+ $role: CodedTermInput!
$coreMetadata: FileSetCoreMetadataInput!
$workId: ID!
) {
diff --git a/assets/js/components/Work/work.gql.mock.js b/assets/js/components/Work/work.gql.mock.js
index 173bb801c..d4b5c009b 100644
--- a/assets/js/components/Work/work.gql.mock.js
+++ b/assets/js/components/Work/work.gql.mock.js
@@ -30,7 +30,7 @@ export const mockWork = {
visibility: mockVisibility,
},
collection: {
- id: "1287312378238293126321308",
+ id: "7a6c7b35-41a6-465a-9be2-0587c6b39ae0",
title: "Collection 1232432 Name",
},
descriptiveMetadata: {
diff --git a/assets/package-lock.json b/assets/package-lock.json
index 759b50855..4e0457987 100644
--- a/assets/package-lock.json
+++ b/assets/package-lock.json
@@ -7,7 +7,7 @@
"license": "MIT",
"dependencies": {
"@absinthe/socket-apollo-link": "^0.2.1",
- "@apollo/client": "latest",
+ "@apollo/client": "*",
"@apollo/react-hooks": "^4.0.0",
"@apollo/react-testing": "^4.0.0",
"@appbaseio/reactivesearch": "3.23.1",
@@ -15,7 +15,7 @@
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-brands-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
- "@fortawesome/react-fontawesome": "^0.1.16",
+ "@fortawesome/react-fontawesome": "^0.1.17",
"@honeybadger-io/js": "^3.2.7",
"@honeybadger-io/react": "^1.0.1",
"@nulib/design-system": "^1.3.5",
@@ -23,7 +23,7 @@
"@radix-ui/react-dialog": "^0.1.1",
"@samvera/image-downloader": "^1.1.1",
"bulma": "^0.9.3",
- "bulma-checkradio": "^2.1.2",
+ "bulma-checkradio": "^2.1.3",
"bulma-pageloader": "^0.3.0",
"bulma-switch": "^2.0.0",
"bulma-toast": "^2.4.1",
@@ -33,10 +33,10 @@
"elasticsearch": "^16.7.2",
"faker": "^5.5.3",
"file-saver": "^2.0.5",
- "graphql": "^16.2.0",
+ "graphql": "^16.3.0",
"graphql-tag": "^2.12.6",
"hls.js": "^1.1.3",
- "inflection": "^1.13.1",
+ "inflection": "^1.13.2",
"js-cookie": "^3.0.1",
"moment": "^2.29.1",
"node-webvtt": "^1.9.3",
@@ -47,8 +47,8 @@
"prop-types": "^15.8.1",
"rc-progress": "^3.2.4",
"react-beautiful-dnd": "^13.1.0",
- "react-csv": "^2.2.1",
- "react-dropzone": "^11.5.1",
+ "react-csv": "^2.2.2",
+ "react-dropzone": "^11.5.3",
"react-error-boundary": "^3.1.4",
"react-helmet": "^6.1.0",
"react-hook-form": "7.6.2",
@@ -58,12 +58,12 @@
"use-clipboard-copy": "^0.2.0"
},
"devDependencies": {
- "@babel/core": "^7.16.7",
+ "@babel/core": "^7.17.0",
"@babel/plugin-proposal-class-properties": "^7.16.0",
"@babel/plugin-proposal-object-rest-spread": "^7.16.7",
"@babel/plugin-proposal-optional-chaining": "^7.16.7",
"@babel/plugin-transform-async-to-generator": "^7.16.0",
- "@babel/preset-env": "^7.16.8",
+ "@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"@creativebulma/bulma-divider": "^1.1.0",
"@creativebulma/bulma-tooltip": "^1.2.0",
@@ -71,8 +71,8 @@
"@honeybadger-io/webpack": "^1.5.1",
"@nulib/prettier-config": "^1.2.0",
"@svgr/webpack": "^5.5.0",
- "@testing-library/dom": "^8.11.1",
- "@testing-library/jest-dom": "^5.16.1",
+ "@testing-library/dom": "^8.11.3",
+ "@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"babel-loader": "^8.2.3",
@@ -95,7 +95,7 @@
"react-router-dom": "^5.3.0",
"react-router-prop-types": "^1.0.5",
"react-svg-loader": "^3.0.3",
- "sass": "^1.47.0",
+ "sass": "^1.49.7",
"sass-loader": "^10.1.1",
"style-loader": "^2.0.0",
"terser-webpack-plugin": "^4.2.3",
@@ -106,11 +106,11 @@
}
},
"../deps/phoenix": {
- "version": "1.5.12",
+ "version": "1.6.6",
"license": "MIT"
},
"../deps/phoenix_html": {
- "version": "2.14.3"
+ "version": "3.2.0"
},
"node_modules/@absinthe/socket": {
"version": "0.2.1",
@@ -209,10 +209,23 @@
"zen-observable": "^0.8.0"
}
},
+ "node_modules/@ampproject/remapping": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.0.2.tgz",
+ "integrity": "sha512-sE8Gx+qSDMLoJvb3QarJJlDQK7SSY4rK3hxp4XsiANeFOmjU46ZI7Y9adAQRJrmbz8zbtZkp3mJTT+rGxtF0XA==",
+ "devOptional": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.2.2",
+ "sourcemap-codec": "1.4.8"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/@apollo/client": {
- "version": "3.5.7",
- "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.5.7.tgz",
- "integrity": "sha512-HSLqTGp3sp/PVIWYLLr5v3fjQSr6Fxg6Z5RQj5Q9ALyseIVudD8GZk1jHplaUblTFMBueXGw3Z6DXObuVAr3tw==",
+ "version": "3.5.8",
+ "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.5.8.tgz",
+ "integrity": "sha512-MAm05+I1ullr64VLpZwon/ISnkMuNLf6vDqgo9wiMhHYBGT4yOAbAIseRdjCHZwfSx/7AUuBgaTNOssZPIr6FQ==",
"dependencies": {
"@graphql-typed-document-node/core": "^3.0.0",
"@wry/context": "^0.6.0",
@@ -374,26 +387,26 @@
}
},
"node_modules/@babel/core": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.7.tgz",
- "integrity": "sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.0.tgz",
+ "integrity": "sha512-x/5Ea+RO5MvF9ize5DeVICJoVrNv0Mi2RnIABrZEKYvPEpldXwauPkgvYA17cKa6WpU3LoYvYbuEMFtSNFsarA==",
"devOptional": true,
"dependencies": {
+ "@ampproject/remapping": "^2.0.0",
"@babel/code-frame": "^7.16.7",
- "@babel/generator": "^7.16.7",
+ "@babel/generator": "^7.17.0",
"@babel/helper-compilation-targets": "^7.16.7",
"@babel/helper-module-transforms": "^7.16.7",
- "@babel/helpers": "^7.16.7",
- "@babel/parser": "^7.16.7",
+ "@babel/helpers": "^7.17.0",
+ "@babel/parser": "^7.17.0",
"@babel/template": "^7.16.7",
- "@babel/traverse": "^7.16.7",
- "@babel/types": "^7.16.7",
+ "@babel/traverse": "^7.17.0",
+ "@babel/types": "^7.17.0",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.1.2",
- "semver": "^6.3.0",
- "source-map": "^0.5.0"
+ "semver": "^6.3.0"
},
"engines": {
"node": ">=6.9.0"
@@ -404,12 +417,12 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz",
- "integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.0.tgz",
+ "integrity": "sha512-I3Omiv6FGOC29dtlZhkfXO6pgkmukJSlT26QjVvS1DGZe/NzSVCPG41X0tS21oZkJYlovfj9qDWgKP+Cn4bXxw==",
"devOptional": true,
"dependencies": {
- "@babel/types": "^7.16.8",
+ "@babel/types": "^7.17.0",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
},
@@ -461,9 +474,9 @@
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.7.tgz",
- "integrity": "sha512-kIFozAvVfK05DM4EVQYKK+zteWvY85BFdGBRQBytRyY3y+6PX0DkDOn/CZ3lEuczCfrCxEzwt0YtP/87YPTWSw==",
+ "version": "7.16.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.10.tgz",
+ "integrity": "sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.16.7",
@@ -740,14 +753,14 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz",
- "integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.0.tgz",
+ "integrity": "sha512-Xe/9NFxjPwELUvW2dsukcMZIp6XwPSbI4ojFBJuX5ramHuVE22SVcZIwqzdWo5uCgeTXW8qV97lMvSOjq+1+nQ==",
"devOptional": true,
"dependencies": {
"@babel/template": "^7.16.7",
- "@babel/traverse": "^7.16.7",
- "@babel/types": "^7.16.7"
+ "@babel/traverse": "^7.17.0",
+ "@babel/types": "^7.17.0"
},
"engines": {
"node": ">=6.9.0"
@@ -767,9 +780,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.8.tgz",
- "integrity": "sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.0.tgz",
+ "integrity": "sha512-VKXSCQx5D8S04ej+Dqsr1CzYvvWgf20jIw2D+YhQCrIlr2UZGaDds23Y0xg75/skOxpLCRpUZvk/1EAVkGoDOw==",
"devOptional": true,
"bin": {
"parser": "bin/babel-parser.js"
@@ -1009,12 +1022,12 @@
}
},
"node_modules/@babel/plugin-proposal-private-methods": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.7.tgz",
- "integrity": "sha512-7twV3pzhrRxSwHeIvFE6coPgvo+exNDOiGUMg39o2LiLo1Y+4aKpfkcLGcg1UHonzorCt7SNXnoMyCnnIOA8Sw==",
+ "version": "7.16.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz",
+ "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==",
"dev": true,
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.16.7",
+ "@babel/helper-create-class-features-plugin": "^7.16.10",
"@babel/helper-plugin-utils": "^7.16.7"
},
"engines": {
@@ -1876,9 +1889,9 @@
}
},
"node_modules/@babel/preset-env": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.8.tgz",
- "integrity": "sha512-9rNKgVCdwHb3z1IlbMyft6yIXIeP3xz6vWvGaLHrJThuEIqWfHb0DNBH9VuTgnDfdbUDhkmkvMZS/YMCtP7Elg==",
+ "version": "7.16.11",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz",
+ "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.16.8",
@@ -1899,7 +1912,7 @@
"@babel/plugin-proposal-object-rest-spread": "^7.16.7",
"@babel/plugin-proposal-optional-catch-binding": "^7.16.7",
"@babel/plugin-proposal-optional-chaining": "^7.16.7",
- "@babel/plugin-proposal-private-methods": "^7.16.7",
+ "@babel/plugin-proposal-private-methods": "^7.16.11",
"@babel/plugin-proposal-private-property-in-object": "^7.16.7",
"@babel/plugin-proposal-unicode-property-regex": "^7.16.7",
"@babel/plugin-syntax-async-generators": "^7.8.4",
@@ -2022,19 +2035,19 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.8.tgz",
- "integrity": "sha512-xe+H7JlvKsDQwXRsBhSnq1/+9c+LlQcCK3Tn/l5sbx02HYns/cn7ibp9+RV1sIUqu7hKg91NWsgHurO9dowITQ==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.0.tgz",
+ "integrity": "sha512-fpFIXvqD6kC7c7PUNnZ0Z8cQXlarCLtCUpt2S1Dx7PjoRtCFffvOkHHSom+m5HIxMZn5bIBVb71lhabcmjEsqg==",
"devOptional": true,
"dependencies": {
"@babel/code-frame": "^7.16.7",
- "@babel/generator": "^7.16.8",
+ "@babel/generator": "^7.17.0",
"@babel/helper-environment-visitor": "^7.16.7",
"@babel/helper-function-name": "^7.16.7",
"@babel/helper-hoist-variables": "^7.16.7",
"@babel/helper-split-export-declaration": "^7.16.7",
- "@babel/parser": "^7.16.8",
- "@babel/types": "^7.16.8",
+ "@babel/parser": "^7.17.0",
+ "@babel/types": "^7.17.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -2043,9 +2056,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz",
- "integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
+ "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
"dependencies": {
"@babel/helper-validator-identifier": "^7.16.7",
"to-fast-properties": "^2.0.0"
@@ -2362,11 +2375,11 @@
}
},
"node_modules/@fortawesome/react-fontawesome": {
- "version": "0.1.16",
- "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.16.tgz",
- "integrity": "sha512-aLmzDwC9rEOAJv2UJdMns89VZR5Ry4IHu5dQQh24Z/lWKEm44lfQr1UNalZlkUaQN8d155tNh+CS7ntntj1VMA==",
+ "version": "0.1.17",
+ "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.17.tgz",
+ "integrity": "sha512-dX43Z5IvMaW7fwzU8farosYjKNGfRb2HB/DgjVBHeJZ/NSnuuaujPPx0YOdcAq+n3mqn70tyCde2HM1mqbhiuw==",
"dependencies": {
- "prop-types": "^15.7.2"
+ "prop-types": "^15.8.1"
},
"peerDependencies": {
"@fortawesome/fontawesome-svg-core": "~1 || >=1.3.0-beta1",
@@ -3181,6 +3194,25 @@
"node": ">=8"
}
},
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.4.tgz",
+ "integrity": "sha512-cz8HFjOFfUBtvN+NXYSFMHYRdxZMaEl0XypVrhzxBgadKIXhIkRd8aMeHhmF56Sl7SuS8OnUpQ73/k9LE4VnLg==",
+ "devOptional": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.2.5.tgz",
+ "integrity": "sha512-K+Eths78fXDFOvQ2hgJhCiI5s+g81r2yXmACBpbn+f2+Qt94PNoTgUcAXPT8DZkhXCsZRsHVWVtY5KIBMcpDqQ==",
+ "devOptional": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "sourcemap-codec": "1.4.8"
+ }
+ },
"node_modules/@jumpn/utils-array": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@jumpn/utils-array/-/utils-array-0.3.4.tgz",
@@ -4571,9 +4603,9 @@
}
},
"node_modules/@testing-library/dom": {
- "version": "8.11.2",
- "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.11.2.tgz",
- "integrity": "sha512-idsS/cqbYudXcVWngc1PuWNmXs416oBy2g/7Q8QAUREt5Z3MUkAL2XJD7xazLJ6esDfqRDi/ZBxk+OPPXitHRw==",
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.11.3.tgz",
+ "integrity": "sha512-9LId28I+lx70wUiZjLvi1DB/WT2zGOxUh46glrSNMaWVx849kKAluezVzZrXJfTKKoQTmEOutLes/bHg4Bj3aA==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
@@ -4678,9 +4710,9 @@
}
},
"node_modules/@testing-library/jest-dom": {
- "version": "5.16.1",
- "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.1.tgz",
- "integrity": "sha512-ajUJdfDIuTCadB79ukO+0l8O+QwN0LiSxDaYUTI4LndbbUsGi6rWU1SCexXzBA2NSjlVB9/vbkasQIL3tmPBjw==",
+ "version": "5.16.2",
+ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz",
+ "integrity": "sha512-6ewxs1MXWwsBFZXIk4nKKskWANelkdUehchEOokHsN8X7c2eKXGw+77aRV63UU8f/DTSVUPLaGxdrj4lN7D/ug==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.9.2",
@@ -9550,9 +9582,9 @@
"dev": true
},
"node_modules/graphql": {
- "version": "16.2.0",
- "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.2.0.tgz",
- "integrity": "sha512-MuQd7XXrdOcmfwuLwC2jNvx0n3rxIuNYOxUtiee5XOmfrWo613ar2U8pE7aHAKh8VwfpifubpD9IP+EdEAEOsA==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.3.0.tgz",
+ "integrity": "sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==",
"engines": {
"node": "^12.22.0 || ^14.16.0 || >=16.0.0"
}
@@ -10066,9 +10098,9 @@
"dev": true
},
"node_modules/inflection": {
- "version": "1.13.1",
- "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.1.tgz",
- "integrity": "sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz",
+ "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw==",
"engines": [
"node >= 0.4.0"
]
@@ -15077,9 +15109,9 @@
}
},
"node_modules/react-dropzone": {
- "version": "11.5.1",
- "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-11.5.1.tgz",
- "integrity": "sha512-eNhttdq4ZDe3eKbXAe54Opt+sbtqmNK5NWTHf/l5d+1TdZqShJ8gMjBrya00qx5zkI//TYxRhu1d9pemTgaWwg==",
+ "version": "11.5.3",
+ "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-11.5.3.tgz",
+ "integrity": "sha512-68+T6sWW5L89qJnn3SD1aRazhuRBhTT9JOI1W8vI5YWsfegM4C7tlGbPH1AgEbmZY5s8E8L0QhX0e3VdAa0KWA==",
"dependencies": {
"attr-accept": "^2.2.1",
"file-selector": "^0.2.2",
@@ -16205,9 +16237,9 @@
"dev": true
},
"node_modules/sass": {
- "version": "1.49.0",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.0.tgz",
- "integrity": "sha512-TVwVdNDj6p6b4QymJtNtRS2YtLJ/CqZriGg0eIAbAKMlN8Xy6kbv33FsEZSF7FufFFM705SQviHjjThfaQ4VNw==",
+ "version": "1.49.7",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.7.tgz",
+ "integrity": "sha512-13dml55EMIR2rS4d/RDHHP0sXMY3+30e1TKsyXaSz3iLWVoDWEoboY8WzJd5JMnxrRHffKO3wq2mpJ0jxRJiEQ==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
@@ -16218,7 +16250,7 @@
"sass": "sass.js"
},
"engines": {
- "node": ">=8.9.0"
+ "node": ">=12.0.0"
}
},
"node_modules/sass-loader": {
@@ -16774,6 +16806,12 @@
"deprecated": "See https://github.com/lydell/source-map-url#deprecated",
"dev": true
},
+ "node_modules/sourcemap-codec": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+ "devOptional": true
+ },
"node_modules/split-string": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
@@ -19744,10 +19782,20 @@
}
}
},
+ "@ampproject/remapping": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.0.2.tgz",
+ "integrity": "sha512-sE8Gx+qSDMLoJvb3QarJJlDQK7SSY4rK3hxp4XsiANeFOmjU46ZI7Y9adAQRJrmbz8zbtZkp3mJTT+rGxtF0XA==",
+ "devOptional": true,
+ "requires": {
+ "@jridgewell/trace-mapping": "^0.2.2",
+ "sourcemap-codec": "1.4.8"
+ }
+ },
"@apollo/client": {
- "version": "3.5.7",
- "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.5.7.tgz",
- "integrity": "sha512-HSLqTGp3sp/PVIWYLLr5v3fjQSr6Fxg6Z5RQj5Q9ALyseIVudD8GZk1jHplaUblTFMBueXGw3Z6DXObuVAr3tw==",
+ "version": "3.5.8",
+ "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.5.8.tgz",
+ "integrity": "sha512-MAm05+I1ullr64VLpZwon/ISnkMuNLf6vDqgo9wiMhHYBGT4yOAbAIseRdjCHZwfSx/7AUuBgaTNOssZPIr6FQ==",
"requires": {
"@graphql-typed-document-node/core": "^3.0.0",
"@wry/context": "^0.6.0",
@@ -19875,35 +19923,35 @@
"devOptional": true
},
"@babel/core": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.7.tgz",
- "integrity": "sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.0.tgz",
+ "integrity": "sha512-x/5Ea+RO5MvF9ize5DeVICJoVrNv0Mi2RnIABrZEKYvPEpldXwauPkgvYA17cKa6WpU3LoYvYbuEMFtSNFsarA==",
"devOptional": true,
"requires": {
+ "@ampproject/remapping": "^2.0.0",
"@babel/code-frame": "^7.16.7",
- "@babel/generator": "^7.16.7",
+ "@babel/generator": "^7.17.0",
"@babel/helper-compilation-targets": "^7.16.7",
"@babel/helper-module-transforms": "^7.16.7",
- "@babel/helpers": "^7.16.7",
- "@babel/parser": "^7.16.7",
+ "@babel/helpers": "^7.17.0",
+ "@babel/parser": "^7.17.0",
"@babel/template": "^7.16.7",
- "@babel/traverse": "^7.16.7",
- "@babel/types": "^7.16.7",
+ "@babel/traverse": "^7.17.0",
+ "@babel/types": "^7.17.0",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.1.2",
- "semver": "^6.3.0",
- "source-map": "^0.5.0"
+ "semver": "^6.3.0"
}
},
"@babel/generator": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz",
- "integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.0.tgz",
+ "integrity": "sha512-I3Omiv6FGOC29dtlZhkfXO6pgkmukJSlT26QjVvS1DGZe/NzSVCPG41X0tS21oZkJYlovfj9qDWgKP+Cn4bXxw==",
"devOptional": true,
"requires": {
- "@babel/types": "^7.16.8",
+ "@babel/types": "^7.17.0",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
}
@@ -19940,9 +19988,9 @@
}
},
"@babel/helper-create-class-features-plugin": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.7.tgz",
- "integrity": "sha512-kIFozAvVfK05DM4EVQYKK+zteWvY85BFdGBRQBytRyY3y+6PX0DkDOn/CZ3lEuczCfrCxEzwt0YtP/87YPTWSw==",
+ "version": "7.16.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.10.tgz",
+ "integrity": "sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.16.7",
@@ -20150,14 +20198,14 @@
}
},
"@babel/helpers": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz",
- "integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.0.tgz",
+ "integrity": "sha512-Xe/9NFxjPwELUvW2dsukcMZIp6XwPSbI4ojFBJuX5ramHuVE22SVcZIwqzdWo5uCgeTXW8qV97lMvSOjq+1+nQ==",
"devOptional": true,
"requires": {
"@babel/template": "^7.16.7",
- "@babel/traverse": "^7.16.7",
- "@babel/types": "^7.16.7"
+ "@babel/traverse": "^7.17.0",
+ "@babel/types": "^7.17.0"
}
},
"@babel/highlight": {
@@ -20171,9 +20219,9 @@
}
},
"@babel/parser": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.8.tgz",
- "integrity": "sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.0.tgz",
+ "integrity": "sha512-VKXSCQx5D8S04ej+Dqsr1CzYvvWgf20jIw2D+YhQCrIlr2UZGaDds23Y0xg75/skOxpLCRpUZvk/1EAVkGoDOw==",
"devOptional": true
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
@@ -20323,12 +20371,12 @@
}
},
"@babel/plugin-proposal-private-methods": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.7.tgz",
- "integrity": "sha512-7twV3pzhrRxSwHeIvFE6coPgvo+exNDOiGUMg39o2LiLo1Y+4aKpfkcLGcg1UHonzorCt7SNXnoMyCnnIOA8Sw==",
+ "version": "7.16.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz",
+ "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==",
"dev": true,
"requires": {
- "@babel/helper-create-class-features-plugin": "^7.16.7",
+ "@babel/helper-create-class-features-plugin": "^7.16.10",
"@babel/helper-plugin-utils": "^7.16.7"
}
},
@@ -20881,9 +20929,9 @@
}
},
"@babel/preset-env": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.8.tgz",
- "integrity": "sha512-9rNKgVCdwHb3z1IlbMyft6yIXIeP3xz6vWvGaLHrJThuEIqWfHb0DNBH9VuTgnDfdbUDhkmkvMZS/YMCtP7Elg==",
+ "version": "7.16.11",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz",
+ "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.16.8",
@@ -20904,7 +20952,7 @@
"@babel/plugin-proposal-object-rest-spread": "^7.16.7",
"@babel/plugin-proposal-optional-catch-binding": "^7.16.7",
"@babel/plugin-proposal-optional-chaining": "^7.16.7",
- "@babel/plugin-proposal-private-methods": "^7.16.7",
+ "@babel/plugin-proposal-private-methods": "^7.16.11",
"@babel/plugin-proposal-private-property-in-object": "^7.16.7",
"@babel/plugin-proposal-unicode-property-regex": "^7.16.7",
"@babel/plugin-syntax-async-generators": "^7.8.4",
@@ -21009,27 +21057,27 @@
}
},
"@babel/traverse": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.8.tgz",
- "integrity": "sha512-xe+H7JlvKsDQwXRsBhSnq1/+9c+LlQcCK3Tn/l5sbx02HYns/cn7ibp9+RV1sIUqu7hKg91NWsgHurO9dowITQ==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.0.tgz",
+ "integrity": "sha512-fpFIXvqD6kC7c7PUNnZ0Z8cQXlarCLtCUpt2S1Dx7PjoRtCFffvOkHHSom+m5HIxMZn5bIBVb71lhabcmjEsqg==",
"devOptional": true,
"requires": {
"@babel/code-frame": "^7.16.7",
- "@babel/generator": "^7.16.8",
+ "@babel/generator": "^7.17.0",
"@babel/helper-environment-visitor": "^7.16.7",
"@babel/helper-function-name": "^7.16.7",
"@babel/helper-hoist-variables": "^7.16.7",
"@babel/helper-split-export-declaration": "^7.16.7",
- "@babel/parser": "^7.16.8",
- "@babel/types": "^7.16.8",
+ "@babel/parser": "^7.17.0",
+ "@babel/types": "^7.17.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
- "version": "7.16.8",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz",
- "integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==",
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
+ "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
"requires": {
"@babel/helper-validator-identifier": "^7.16.7",
"to-fast-properties": "^2.0.0"
@@ -21301,11 +21349,11 @@
}
},
"@fortawesome/react-fontawesome": {
- "version": "0.1.16",
- "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.16.tgz",
- "integrity": "sha512-aLmzDwC9rEOAJv2UJdMns89VZR5Ry4IHu5dQQh24Z/lWKEm44lfQr1UNalZlkUaQN8d155tNh+CS7ntntj1VMA==",
+ "version": "0.1.17",
+ "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.17.tgz",
+ "integrity": "sha512-dX43Z5IvMaW7fwzU8farosYjKNGfRb2HB/DgjVBHeJZ/NSnuuaujPPx0YOdcAq+n3mqn70tyCde2HM1mqbhiuw==",
"requires": {
- "prop-types": "^15.7.2"
+ "prop-types": "^15.8.1"
}
},
"@gar/promisify": {
@@ -21940,6 +21988,22 @@
}
}
},
+ "@jridgewell/resolve-uri": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.4.tgz",
+ "integrity": "sha512-cz8HFjOFfUBtvN+NXYSFMHYRdxZMaEl0XypVrhzxBgadKIXhIkRd8aMeHhmF56Sl7SuS8OnUpQ73/k9LE4VnLg==",
+ "devOptional": true
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.2.5.tgz",
+ "integrity": "sha512-K+Eths78fXDFOvQ2hgJhCiI5s+g81r2yXmACBpbn+f2+Qt94PNoTgUcAXPT8DZkhXCsZRsHVWVtY5KIBMcpDqQ==",
+ "devOptional": true,
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "sourcemap-codec": "1.4.8"
+ }
+ },
"@jumpn/utils-array": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@jumpn/utils-array/-/utils-array-0.3.4.tgz",
@@ -23087,9 +23151,9 @@
}
},
"@testing-library/dom": {
- "version": "8.11.2",
- "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.11.2.tgz",
- "integrity": "sha512-idsS/cqbYudXcVWngc1PuWNmXs416oBy2g/7Q8QAUREt5Z3MUkAL2XJD7xazLJ6esDfqRDi/ZBxk+OPPXitHRw==",
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.11.3.tgz",
+ "integrity": "sha512-9LId28I+lx70wUiZjLvi1DB/WT2zGOxUh46glrSNMaWVx849kKAluezVzZrXJfTKKoQTmEOutLes/bHg4Bj3aA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",
@@ -23169,9 +23233,9 @@
}
},
"@testing-library/jest-dom": {
- "version": "5.16.1",
- "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.1.tgz",
- "integrity": "sha512-ajUJdfDIuTCadB79ukO+0l8O+QwN0LiSxDaYUTI4LndbbUsGi6rWU1SCexXzBA2NSjlVB9/vbkasQIL3tmPBjw==",
+ "version": "5.16.2",
+ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz",
+ "integrity": "sha512-6ewxs1MXWwsBFZXIk4nKKskWANelkdUehchEOokHsN8X7c2eKXGw+77aRV63UU8f/DTSVUPLaGxdrj4lN7D/ug==",
"dev": true,
"requires": {
"@babel/runtime": "^7.9.2",
@@ -27198,9 +27262,9 @@
"dev": true
},
"graphql": {
- "version": "16.2.0",
- "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.2.0.tgz",
- "integrity": "sha512-MuQd7XXrdOcmfwuLwC2jNvx0n3rxIuNYOxUtiee5XOmfrWo613ar2U8pE7aHAKh8VwfpifubpD9IP+EdEAEOsA=="
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.3.0.tgz",
+ "integrity": "sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A=="
},
"graphql-tag": {
"version": "2.12.6",
@@ -27579,9 +27643,9 @@
"dev": true
},
"inflection": {
- "version": "1.13.1",
- "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.1.tgz",
- "integrity": "sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA=="
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz",
+ "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw=="
},
"inflight": {
"version": "1.0.6",
@@ -31354,9 +31418,9 @@
}
},
"react-dropzone": {
- "version": "11.5.1",
- "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-11.5.1.tgz",
- "integrity": "sha512-eNhttdq4ZDe3eKbXAe54Opt+sbtqmNK5NWTHf/l5d+1TdZqShJ8gMjBrya00qx5zkI//TYxRhu1d9pemTgaWwg==",
+ "version": "11.5.3",
+ "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-11.5.3.tgz",
+ "integrity": "sha512-68+T6sWW5L89qJnn3SD1aRazhuRBhTT9JOI1W8vI5YWsfegM4C7tlGbPH1AgEbmZY5s8E8L0QhX0e3VdAa0KWA==",
"requires": {
"attr-accept": "^2.2.1",
"file-selector": "^0.2.2",
@@ -32265,9 +32329,9 @@
"dev": true
},
"sass": {
- "version": "1.49.0",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.0.tgz",
- "integrity": "sha512-TVwVdNDj6p6b4QymJtNtRS2YtLJ/CqZriGg0eIAbAKMlN8Xy6kbv33FsEZSF7FufFFM705SQviHjjThfaQ4VNw==",
+ "version": "1.49.7",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.7.tgz",
+ "integrity": "sha512-13dml55EMIR2rS4d/RDHHP0sXMY3+30e1TKsyXaSz3iLWVoDWEoboY8WzJd5JMnxrRHffKO3wq2mpJ0jxRJiEQ==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0",
@@ -32710,6 +32774,12 @@
"integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
"dev": true
},
+ "sourcemap-codec": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+ "devOptional": true
+ },
"split-string": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
diff --git a/assets/package.json b/assets/package.json
index aa7b38b79..467f57a2d 100644
--- a/assets/package.json
+++ b/assets/package.json
@@ -23,7 +23,7 @@
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-brands-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
- "@fortawesome/react-fontawesome": "^0.1.16",
+ "@fortawesome/react-fontawesome": "^0.1.17",
"@honeybadger-io/js": "^3.2.7",
"@honeybadger-io/react": "^1.0.1",
"@nulib/design-system": "^1.3.5",
@@ -31,7 +31,7 @@
"@radix-ui/react-dialog": "^0.1.1",
"@samvera/image-downloader": "^1.1.1",
"bulma": "^0.9.3",
- "bulma-checkradio": "^2.1.2",
+ "bulma-checkradio": "^2.1.3",
"bulma-pageloader": "^0.3.0",
"bulma-switch": "^2.0.0",
"bulma-toast": "^2.4.1",
@@ -41,10 +41,10 @@
"elasticsearch": "^16.7.2",
"faker": "^5.5.3",
"file-saver": "^2.0.5",
- "graphql": "^16.2.0",
+ "graphql": "^16.3.0",
"graphql-tag": "^2.12.6",
"hls.js": "^1.1.3",
- "inflection": "^1.13.1",
+ "inflection": "^1.13.2",
"js-cookie": "^3.0.1",
"moment": "^2.29.1",
"node-webvtt": "^1.9.3",
@@ -55,8 +55,8 @@
"prop-types": "^15.8.1",
"rc-progress": "^3.2.4",
"react-beautiful-dnd": "^13.1.0",
- "react-csv": "^2.2.1",
- "react-dropzone": "^11.5.1",
+ "react-csv": "^2.2.2",
+ "react-dropzone": "^11.5.3",
"react-error-boundary": "^3.1.4",
"react-helmet": "^6.1.0",
"react-hook-form": "7.6.2",
@@ -66,12 +66,12 @@
"use-clipboard-copy": "^0.2.0"
},
"devDependencies": {
- "@babel/core": "^7.16.7",
+ "@babel/core": "^7.17.0",
"@babel/plugin-proposal-class-properties": "^7.16.0",
"@babel/plugin-proposal-object-rest-spread": "^7.16.7",
"@babel/plugin-proposal-optional-chaining": "^7.16.7",
"@babel/plugin-transform-async-to-generator": "^7.16.0",
- "@babel/preset-env": "^7.16.8",
+ "@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"@creativebulma/bulma-divider": "^1.1.0",
"@creativebulma/bulma-tooltip": "^1.2.0",
@@ -79,8 +79,8 @@
"@honeybadger-io/webpack": "^1.5.1",
"@nulib/prettier-config": "^1.2.0",
"@svgr/webpack": "^5.5.0",
- "@testing-library/dom": "^8.11.1",
- "@testing-library/jest-dom": "^5.16.1",
+ "@testing-library/dom": "^8.11.3",
+ "@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"babel-loader": "^8.2.3",
@@ -103,7 +103,7 @@
"react-router-dom": "^5.3.0",
"react-router-prop-types": "^1.0.5",
"react-svg-loader": "^3.0.3",
- "sass": "^1.47.0",
+ "sass": "^1.49.7",
"sass-loader": "^10.1.1",
"style-loader": "^2.0.0",
"terser-webpack-plugin": "^4.2.3",
diff --git a/config/dev.exs b/config/dev.exs
index 932198bd4..d7d8f7d65 100644
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -89,7 +89,7 @@ config :meadow,
preservation_check_bucket: "dev-preservation-checks",
pyramid_bucket: "dev-pyramids",
streaming_bucket: "dev-streaming",
- streaming_url: "https://devbox.library.northwestern.edu:9001/dev-streaming/",
+ streaming_url: "https://dev-streaming.s3.localhost.localstack.cloud:4566/",
mediaconvert_client: MediaConvert.Mock,
multipart_upload_concurrency: System.get_env("MULTIPART_UPLOAD_CONCURRENCY", "10"),
iiif_server_url:
@@ -97,7 +97,7 @@ config :meadow,
iiif_manifest_url:
System.get_env(
"IIIF_MANIFEST_URL",
- "https://devbox.library.northwestern.edu:9001/dev-pyramids/public/"
+ "https://dev-pyramids.s3.localhost.localstack.cloud:4566/public/"
),
digital_collections_url:
System.get_env("DIGITAL_COLLECTIONS_URL", "https://fen.rdc-staging.library.northwestern.edu/"),
@@ -107,7 +107,7 @@ config :meadow,
config :meadow,
checksum_notification: %{
- arn: "arn:minio:sqs::checksum:webhook",
+ arn: "arn:aws:lambda:us-east-1:000000000000:function:digest-tag",
buckets: ["dev-ingest", "dev-uploads"]
}
@@ -115,29 +115,16 @@ config :elastix,
custom_headers: {Meadow.Utils.AWS, :add_aws_signature, ["us-east-1", "fake", "fake"]}
unless System.get_env("REAL_AWS_CONFIG", "false") == "true" do
- config :ex_aws,
- access_key_id: "fake",
- secret_access_key: "fake"
-
- config :ex_aws, :s3,
- access_key_id: "minio",
- secret_access_key: "minio123",
- host: "devbox.library.northwestern.edu",
- port: 9001,
- scheme: "https://",
- region: "us-east-1"
-
- config :ex_aws, :sqs,
- host: "localhost",
- port: 4101,
- scheme: "http://",
- region: "us-east-1"
-
- config :ex_aws, :sns,
- host: "localhost",
- port: 4101,
- scheme: "http://",
- region: "us-east-1"
+ [:s3, :sns, :sqs]
+ |> Enum.each(fn service ->
+ config :ex_aws, service,
+ access_key_id: "fake",
+ secret_access_key: "fake",
+ host: "localhost.localstack.cloud",
+ port: 4566,
+ scheme: "https://",
+ region: "us-east-1"
+ end)
end
config :meadow, Meadow.Scheduler,
diff --git a/config/test.exs b/config/test.exs
index 893e2fce6..bd2bbe482 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -45,13 +45,13 @@ config :meadow,
mediaconvert_client: MediaConvert.Mock,
multipart_upload_concurrency: System.get_env("MULTIPART_UPLOAD_CONCURRENCY", "10"),
iiif_server_url: "http://localhost:8184/iiif/2/",
- iiif_manifest_url: "http://localhost:9002/minio/test-pyramids/public/",
+ iiif_manifest_url: "http://test-pyramids.s3.localhost.localstack.cloud:4568/public/",
digital_collections_url: "https://fen.rdc-staging.library.northwestern.edu/",
work_archiver_endpoint: ""
config :meadow,
checksum_notification: %{
- arn: "arn:minio:sqs::checksum:webhook",
+ arn: "arn:aws:lambda:us-east-1:000000000000:function:digest-tag",
buckets: ["test-ingest", "test-uploads"]
},
required_checksum_tags: ["computed-md5"],
@@ -84,31 +84,17 @@ config :ueberauth, Ueberauth,
]}
]
-config :ex_aws,
- access_key_id: "minio",
- secret_access_key: "minio123"
-
-config :ex_aws, :s3,
- host: "localhost",
- port: 9002,
- scheme: "http://",
- region: "us-east-1",
- access_key_id: "minio",
- secret_access_key: "minio123"
-
-config :ex_aws, :sqs,
- host: "localhost",
- port: 4102,
- scheme: "http://",
- region: "us-east-1"
-
-config :ex_aws, :sns,
- access_key_id: "",
- secret_access_key: "",
- host: "localhost",
- port: 4102,
- scheme: "http://",
- region: "us-east-1"
+with aws_config <- [
+ access_key_id: "fake",
+ secret_access_key: "fake",
+ host: "localhost.localstack.cloud",
+ port: 4568,
+ scheme: "http://",
+ region: "us-east-1"
+ ] do
+ config :ex_aws, aws_config
+ [:s3, :sqs, :sns, :lambda] |> Enum.each(&config(:ex_aws, &1, aws_config))
+end
config :exldap, :settings,
server: "localhost",
diff --git a/lib/meadow/batches.ex b/lib/meadow/batches.ex
index 9b4420006..4180d0ede 100644
--- a/lib/meadow/batches.ex
+++ b/lib/meadow/batches.ex
@@ -428,16 +428,26 @@ defmodule Meadow.Batches do
work_ids
end
+ defp validate_work_ids(work_ids) do
+ from(w in Work, where: w.id in ^work_ids, select: w.id) |> Repo.all()
+ end
+
# Iterate over the Elasticsearch scroll and apply changes to each page of work IDs.
defp process_updates(
- {:ok, %{"hits" => %{"hits" => [], "total" => total}}},
+ {:ok, %{"hits" => %{"hits" => []}}},
_delete,
_add,
_replace,
batch_id
) do
- update_batch(batch_id, %{works_updated: total})
+ with {:ok, batch_uuid} <- Ecto.UUID.dump(batch_id),
+ total <-
+ from(wb in "works_batches", where: wb.batch_id == ^batch_uuid)
+ |> Repo.aggregate(:count) do
+ update_batch(batch_id, %{works_updated: total})
+ end
+
{:ok, :noop}
end
@@ -452,6 +462,7 @@ defmodule Meadow.Batches do
current_hits
|> Enum.map(&Map.get(&1, "_id"))
+ |> validate_work_ids()
|> apply_controlled_field_changes(delete, add)
|> apply_uncontrolled_field_changes(add, replace)
|> apply_batch_association(batch_id)
diff --git a/lib/meadow/csv_metadata_update_driver.ex b/lib/meadow/csv_metadata_update_driver.ex
index 8fd73cd64..399a22d77 100644
--- a/lib/meadow/csv_metadata_update_driver.ex
+++ b/lib/meadow/csv_metadata_update_driver.ex
@@ -20,7 +20,7 @@ defmodule Meadow.CSVMetadataUpdateDriver do
"""
def drive_update_job(state) do
MetadataUpdateJobs.reset_stalled(@timeout)
- |> log_reset()
+ |> log_reset_stalled()
case MetadataUpdateJobs.next_job() do
nil ->
@@ -37,8 +37,22 @@ defmodule Meadow.CSVMetadataUpdateDriver do
{:noreply, state}
end
- defp log_reset({:ok, 0}), do: :noop
+ defp log_reset_stalled({:ok, cancel_count, reset_count}) do
+ log_cancel(cancel_count)
+ log_reset(reset_count)
+ end
+
+ defp log_cancel(0), do: :noop
+
+ defp log_cancel(count) do
+ "Canceling #{count} #{Inflex.inflect("update job", count)} jobs for exceeding max retries"
+ |> Logger.info()
+ end
+
+ defp log_reset(0), do: :noop
- defp log_reset({:ok, count}),
- do: Logger.info("Resetting #{count} stalled #{Inflex.inflect("update job", count)}")
+ defp log_reset(count) do
+ "Resetting #{count} stalled #{Inflex.inflect("update job", count)}"
+ |> Logger.info()
+ end
end
diff --git a/lib/meadow/data/csv/import.ex b/lib/meadow/data/csv/import.ex
index 745df994f..244ef2a53 100644
--- a/lib/meadow/data/csv/import.ex
+++ b/lib/meadow/data/csv/import.ex
@@ -15,7 +15,7 @@ defmodule Meadow.Data.CSV.Import do
@empty_work_map %{administrative_metadata: %{}, descriptive_metadata: %{}}
@coded_fields ~w(library_unit license preservation_level rights_statement status visibility work_type)a
- defstruct query: nil, headers: nil, stream: nil
+ defstruct headers: nil, stream: nil
@doc """
Reads a stream of CSV data and returns an importable struct
@@ -35,15 +35,19 @@ defmodule Meadow.Data.CSV.Import do
def read_csv(source) do
with csv_stream <-
source |> StreamUtil.by_line() |> CSV.parse_stream(skip_headers: false),
- [[query | _] | [headers | []]] <- Enum.take(csv_stream, 2) do
+ [headers | stream] <- Enum.drop_while(csv_stream, &(not header_row?(&1))) do
%__MODULE__{
- query: query,
headers: Enum.map(headers, &String.to_atom/1),
- stream: Stream.drop(csv_stream, 2)
+ stream: stream
}
end
end
+ defp header_row?(headers),
+ do:
+ length(headers) == length(fields()) and
+ Enum.all?(headers, &Regex.match?(~r/[a-z_]+/, &1))
+
@doc """
Streams rows from a struct and returns a stream of structured work metadata maps
Example:
diff --git a/lib/meadow/data/csv/metadata_update_jobs.ex b/lib/meadow/data/csv/metadata_update_jobs.ex
index 1c48b3e48..b5ca17a8c 100644
--- a/lib/meadow/data/csv/metadata_update_jobs.ex
+++ b/lib/meadow/data/csv/metadata_update_jobs.ex
@@ -197,38 +197,61 @@ defmodule Meadow.Data.CSV.MetadataUpdateJobs do
"""
def reset_stalled(seconds) do
with timeout <- DateTime.utc_now() |> DateTime.add(-seconds, :second) do
- {pending_count, _} = reset_stalled("validating", "pending", timeout)
- {valid_count, _} = reset_stalled("processing", "valid", timeout)
-
- {:ok, pending_count + valid_count}
+ {:ok, {pending_canceled, pending_count}} = reset_stalled("validating", "pending", timeout)
+ {:ok, {valid_canceled, valid_count}} = reset_stalled("processing", "valid", timeout)
+ {:ok, pending_canceled + valid_canceled, pending_count + valid_count}
end
end
defp reset_stalled(stuck_status, reset_status, timeout) do
{:ok, result} =
Repo.transaction(fn ->
- ids_to_reset =
- from(job in MetadataUpdateJob,
- where: job.status == ^stuck_status and job.updated_at <= ^timeout,
- lock: "FOR UPDATE SKIP LOCKED",
- select: [:id]
- )
- |> Repo.all()
- |> Enum.map(fn %{id: id} -> id end)
-
- from(job in MetadataUpdateJob, where: job.id in ^ids_to_reset)
- |> Repo.update_all(
- set: [
- active: false,
- status: reset_status,
- updated_at: DateTime.utc_now()
- ]
- )
+ with {cancel_count, _} <- cancel_after_retries(stuck_status, timeout),
+ {reset_count, _} <- change_stalled_status(stuck_status, reset_status, timeout) do
+ {:ok, {cancel_count, reset_count}}
+ end
end)
result
end
+ defp change_stalled_status(stuck_status, reset_status, timeout) do
+ ids_to_reset =
+ from(job in MetadataUpdateJob,
+ where: job.status == ^stuck_status and job.updated_at <= ^timeout,
+ lock: "FOR UPDATE SKIP LOCKED",
+ select: job.id
+ )
+ |> Repo.all()
+
+ from(job in MetadataUpdateJob, where: job.id in ^ids_to_reset)
+ |> Repo.update_all(
+ set: [
+ active: false,
+ status: reset_status,
+ updated_at: DateTime.utc_now()
+ ],
+ inc: [retries: 1]
+ )
+ end
+
+ defp cancel_after_retries(status, timeout, retries \\ 3) do
+ error = %{row: 0, errors: %{status: ["Stuck in #{status} after #{retries} retries"]}}
+
+ from(
+ job in MetadataUpdateJob,
+ where: job.status == ^status and job.updated_at <= ^timeout and job.retries >= ^retries
+ )
+ |> Repo.update_all(
+ set: [
+ active: false,
+ status: "error",
+ updated_at: DateTime.utc_now()
+ ],
+ push: [errors: error]
+ )
+ end
+
defp errors_with_row(errors, row) do
if Enum.empty?(errors), do: [], else: [%{row: row, errors: errors}]
end
@@ -252,6 +275,10 @@ defmodule Meadow.Data.CSV.MetadataUpdateJobs do
end
end
+ defp validate_headers([] = import_stream) do
+ {import_stream, errors_with_row(%{headers: ["could not identify header row"]}, 1)}
+ end
+
defp validate_terms({import_stream, errors}) when errors == [] do
errors =
import_stream
diff --git a/lib/meadow/data/schemas/controlled_metadata_entry.ex b/lib/meadow/data/schemas/controlled_metadata_entry.ex
index 4e57cc583..083334bbd 100644
--- a/lib/meadow/data/schemas/controlled_metadata_entry.ex
+++ b/lib/meadow/data/schemas/controlled_metadata_entry.ex
@@ -25,19 +25,23 @@ defmodule Meadow.Data.Schemas.ControlledMetadataEntry do
|> validate_required([:term, :role])
end
- def from_string(value) do
- case value do
- "GEOGRAPHICAL:" <> uri ->
- %{role: %{id: "GEOGRAPHICAL", scheme: "subject_role"}, term: %{id: uri}}
+ def from_string(value) when is_binary(value) do
+ String.split(value, ":", parts: 2)
+ |> from_string_result()
+ end
- "TOPICAL:" <> uri ->
- %{role: %{id: "TOPICAL", scheme: "subject_role"}, term: %{id: uri}}
+ # An unqualified string is just a bare term
+ defp from_string_result([term | []]), do: %{term: %{id: term}}
- <> ->
- %{role: %{id: prefix, scheme: "marc_relator"}, term: %{id: uri}}
+ # A 3-character qualifier indicates a MARC Relator code
+ defp from_string_result([<> | [term]]),
+ do: %{role: %{id: qualifier, scheme: "marc_relator"}, term: %{id: term}}
- uri ->
- %{term: %{id: uri}}
+ # If the term can't be parsed as a URI, assume the qualifier was actually part of the term
+ defp from_string_result([qualifier | [term | []]] = value) do
+ case URI.parse(term) do
+ %{scheme: nil} -> %{term: %{id: Enum.join(value, ":")}}
+ _ -> %{role: %{id: qualifier, scheme: "subject_role"}, term: %{id: term}}
end
end
end
diff --git a/lib/meadow/data/schemas/csv/metadata_update_job.ex b/lib/meadow/data/schemas/csv/metadata_update_job.ex
index cbe234ca3..edcc33263 100644
--- a/lib/meadow/data/schemas/csv/metadata_update_job.ex
+++ b/lib/meadow/data/schemas/csv/metadata_update_job.ex
@@ -20,6 +20,7 @@ defmodule Meadow.Data.Schemas.CSV.MetadataUpdateJob do
field(:status, :string)
field(:started_at, :utc_datetime_usec)
field(:user, :string)
+ field(:retries, :integer, default: 0)
timestamps()
end
diff --git a/lib/meadow/data/schemas/note_entry.ex b/lib/meadow/data/schemas/note_entry.ex
index 065b6804c..3bd3d1ead 100644
--- a/lib/meadow/data/schemas/note_entry.ex
+++ b/lib/meadow/data/schemas/note_entry.ex
@@ -22,7 +22,12 @@ defmodule Meadow.Data.Schemas.NoteEntry do
def from_string(""), do: nil
def from_string(value) do
- [note_type_id | [note | []]] = value |> String.split(~r/:/, parts: 2)
- %{type: %{id: note_type_id, scheme: "note_type"}, note: note}
+ case value |> String.split(~r/:/, parts: 2) do
+ [note_type_id | [note | []]] ->
+ %{type: %{id: note_type_id, scheme: "note_type"}, note: note}
+
+ [note] ->
+ %{type: %{id: "", scheme: "note_type"}, note: note}
+ end
end
end
diff --git a/lib/meadow/data/schemas/related_url_entry.ex b/lib/meadow/data/schemas/related_url_entry.ex
index 3ba7c1fd0..e180f152e 100644
--- a/lib/meadow/data/schemas/related_url_entry.ex
+++ b/lib/meadow/data/schemas/related_url_entry.ex
@@ -21,8 +21,17 @@ defmodule Meadow.Data.Schemas.RelatedURLEntry do
def from_string(""), do: nil
- def from_string(value) do
- [role_id | [url | []]] = value |> String.split(~r/:/, parts: 2)
- %{label: %{id: role_id, scheme: "related_url"}, url: url}
+ def from_string(value) when is_binary(value) do
+ String.split(value, ":", parts: 2)
+ |> from_string_result()
end
+
+ defp from_string_result([role_id | [url | []]] = value) do
+ case URI.parse(url) do
+ %{scheme: nil} -> %{url: Enum.join(value, ":")}
+ _ -> %{label: %{id: role_id, scheme: "related_url"}, url: url}
+ end
+ end
+
+ defp from_string_result(value), do: %{url: Enum.join(value, ":")}
end
diff --git a/lib/meadow/data/schemas/work.ex b/lib/meadow/data/schemas/work.ex
index f6ce3d242..e331b8ff3 100644
--- a/lib/meadow/data/schemas/work.ex
+++ b/lib/meadow/data/schemas/work.ex
@@ -76,6 +76,7 @@ defmodule Meadow.Data.Schemas.Work do
[
:collection_id,
:ingest_sheet_id,
+ :published,
:reading_room,
:representative_file_set_id,
:visibility,
diff --git a/lib/meadow/iiif/v2/iiif.ex b/lib/meadow/iiif/v2/iiif.ex
index 62fd90838..be8503fc4 100644
--- a/lib/meadow/iiif/v2/iiif.ex
+++ b/lib/meadow/iiif/v2/iiif.ex
@@ -20,7 +20,7 @@ defmodule Meadow.IIIF.V2 do
Examples:
iex> manifest_id("37ad25ec-7eff-45d0-b759-eca65c9d560f")
- "http://localhost:9002/minio/test-pyramids/public/37/ad/25/ec/-7/ef/f-/45/d0/-b/75/9-/ec/a6/5c/9d/56/0f-manifest.json"
+ "http://test-pyramids.s3.localhost.localstack.cloud:4568/public/37/ad/25/ec/-7/ef/f-/45/d0/-b/75/9-/ec/a6/5c/9d/56/0f-manifest.json"
"""
def manifest_id(work_id) do
Config.iiif_manifest_url() <> Pairtree.manifest_path(work_id)
diff --git a/lib/meadow/iiif/v3/iiif.ex b/lib/meadow/iiif/v3/iiif.ex
index 2da207740..d6dee2059 100644
--- a/lib/meadow/iiif/v3/iiif.ex
+++ b/lib/meadow/iiif/v3/iiif.ex
@@ -20,7 +20,7 @@ defmodule Meadow.IIIF.V3 do
Examples:
iex> manifest_id("37ad25ec-7eff-45d0-b759-eca65c9d560f")
- "http://localhost:9002/minio/test-pyramids/public/iiif3/37/ad/25/ec/-7/ef/f-/45/d0/-b/75/9-/ec/a6/5c/9d/56/0f-manifest.json"
+ "http://test-pyramids.s3.localhost.localstack.cloud:4568/public/iiif3/37/ad/25/ec/-7/ef/f-/45/d0/-b/75/9-/ec/a6/5c/9d/56/0f-manifest.json"
"""
def manifest_id(work_id) do
Config.iiif_manifest_url() <> "iiif3/" <> Pairtree.manifest_path(work_id)
@@ -69,7 +69,7 @@ defmodule Meadow.IIIF.V3 do
Examples:
iex> annotation_id("37ad25ec-7eff-45d0-b759-eca65c9d560f", "030ac101-58cc-4e1e-8a13-ad6d95a6adbe",1,2)
- "http://localhost:9002/minio/test-pyramids/public/iiif3/37/ad/25/ec/-7/ef/f-/45/d0/-b/75/9-/ec/a6/5c/9d/56/0f-manifest.json/canvas/030ac101-58cc-4e1e-8a13-ad6d95a6adbe/annotation_page/1/annotation/2"
+ "http://test-pyramids.s3.localhost.localstack.cloud:4568/public/iiif3/37/ad/25/ec/-7/ef/f-/45/d0/-b/75/9-/ec/a6/5c/9d/56/0f-manifest.json/canvas/030ac101-58cc-4e1e-8a13-ad6d95a6adbe/annotation_page/1/annotation/2"
"""
def annotation_id(work_id, file_set_id, page_number, annotation_number) do
"#{manifest_id(work_id)}/canvas/#{file_set_id}/annotation_page/#{page_number}/annotation/#{annotation_number}"
@@ -80,7 +80,7 @@ defmodule Meadow.IIIF.V3 do
Examples:
iex> annotation_page_id("37ad25ec-7eff-45d0-b759-eca65c9d560f", "030ac101-58cc-4e1e-8a13-ad6d95a6adbe",1)
- "http://localhost:9002/minio/test-pyramids/public/iiif3/37/ad/25/ec/-7/ef/f-/45/d0/-b/75/9-/ec/a6/5c/9d/56/0f-manifest.json/canvas/030ac101-58cc-4e1e-8a13-ad6d95a6adbe/annotation_page/1"
+ "http://test-pyramids.s3.localhost.localstack.cloud:4568/public/iiif3/37/ad/25/ec/-7/ef/f-/45/d0/-b/75/9-/ec/a6/5c/9d/56/0f-manifest.json/canvas/030ac101-58cc-4e1e-8a13-ad6d95a6adbe/annotation_page/1"
"""
def annotation_page_id(work_id, file_set_id, page_number) do
"#{manifest_id(work_id)}/canvas/#{file_set_id}/annotation_page/#{page_number}"
@@ -91,7 +91,7 @@ defmodule Meadow.IIIF.V3 do
Examples:
iex> canvas_id("37ad25ec-7eff-45d0-b759-eca65c9d560f", "030ac101-58cc-4e1e-8a13-ad6d95a6adbe")
- "http://localhost:9002/minio/test-pyramids/public/iiif3/37/ad/25/ec/-7/ef/f-/45/d0/-b/75/9-/ec/a6/5c/9d/56/0f-manifest.json/canvas/030ac101-58cc-4e1e-8a13-ad6d95a6adbe"
+ "http://test-pyramids.s3.localhost.localstack.cloud:4568/public/iiif3/37/ad/25/ec/-7/ef/f-/45/d0/-b/75/9-/ec/a6/5c/9d/56/0f-manifest.json/canvas/030ac101-58cc-4e1e-8a13-ad6d95a6adbe"
"""
def canvas_id(work_id, file_set_id) do
"#{manifest_id(work_id)}/canvas/#{file_set_id}"
diff --git a/lib/meadow/ingest/sheets.ex b/lib/meadow/ingest/sheets.ex
index e8379e6de..c6e75b8ab 100644
--- a/lib/meadow/ingest/sheets.ex
+++ b/lib/meadow/ingest/sheets.ex
@@ -3,9 +3,7 @@ defmodule Meadow.Ingest.Sheets do
API for Ingest Sheets
"""
import Ecto.Query, warn: false
- alias Meadow.Data.Schemas.ActionState
- alias Meadow.Data.Schemas.FileSet
- alias Meadow.Data.Schemas.Work
+ alias Meadow.Data.Schemas.{ActionState, FileSet, Work}
alias Meadow.Data.Works
alias Meadow.Ingest.Schemas.{Progress, Project, Row, Sheet}
alias Meadow.Repo
@@ -370,11 +368,11 @@ defmodule Meadow.Ingest.Sheets do
def file_set_count(%Sheet{} = ingest_sheet), do: file_set_count(ingest_sheet.id)
def file_set_count(sheet_id) do
- from(r in Row,
- where: r.sheet_id == ^sheet_id,
- select: count(r.sheet_id)
+ from(w in Work,
+ left_join: f in assoc(w, :file_sets),
+ where: w.ingest_sheet_id == ^sheet_id
)
- |> Repo.one()
+ |> Repo.aggregate(:count)
end
def ingest_errors(%Sheet{} = ingest_sheet), do: ingest_errors(ingest_sheet.id)
diff --git a/lib/meadow/pipeline/actions/common.ex b/lib/meadow/pipeline/actions/common.ex
index 178a93bf5..aea80f7db 100644
--- a/lib/meadow/pipeline/actions/common.ex
+++ b/lib/meadow/pipeline/actions/common.ex
@@ -44,7 +44,7 @@ defmodule Meadow.Pipeline.Actions.Common do
defp precheck(file_set, %{overwrite: "false"} = attrs) do
if already_complete?(file_set, attrs) do
- "Marking #{__MODULE__} for #{file_set.id} as already complete without overwriting"
+ "Marking #{__MODULE__} for #{file_set.id} as already complete without overwriting"
|> Logger.warn()
ActionStates.set_state!(file_set, __MODULE__, "ok")
@@ -54,7 +54,7 @@ defmodule Meadow.Pipeline.Actions.Common do
defp precheck(_, _), do: :noop
defp process(%{id: file_set_id}, _, true) do
- Logger.warn("Skipping #{__MODULE__} for #{file_set_id} – already complete")
+ Logger.warn("Skipping #{__MODULE__} for #{file_set_id} - already complete")
:ok
end
diff --git a/lib/meadow/pipeline/actions/copy_file_to_preservation.ex b/lib/meadow/pipeline/actions/copy_file_to_preservation.ex
index 2628e54ae..be301168e 100644
--- a/lib/meadow/pipeline/actions/copy_file_to_preservation.ex
+++ b/lib/meadow/pipeline/actions/copy_file_to_preservation.ex
@@ -17,7 +17,7 @@ defmodule Meadow.Pipeline.Actions.CopyFileToPreservation do
@actiondoc "Copy File to Preservation"
- defp already_complete?(file_set, _) do
+ defp already_complete?(file_set, %{overwrite: "false"}) do
with dest_location <- FileSets.preservation_location(file_set) do
if file_set.core_metadata.location == dest_location,
do: Meadow.Utils.Stream.exists?(dest_location),
@@ -25,6 +25,12 @@ defmodule Meadow.Pipeline.Actions.CopyFileToPreservation do
end
end
+ defp already_complete?(file_set, _) do
+ file_set
+ |> FileSets.preservation_location()
+ |> Meadow.Utils.Stream.exists?()
+ end
+
defp process(file_set, attributes, _) do
ActionStates.set_state!(file_set, __MODULE__, "started")
diff --git a/lib/meadow_web/endpoint.ex b/lib/meadow_web/endpoint.ex
index d06260efc..086bc6ad7 100644
--- a/lib/meadow_web/endpoint.ex
+++ b/lib/meadow_web/endpoint.ex
@@ -31,7 +31,6 @@ defmodule MeadowWeb.Endpoint do
cookie_key: "request_logger"
plug Plug.RequestId
- plug Plug.Logger
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
diff --git a/lib/meadow_web/router.ex b/lib/meadow_web/router.ex
index c00217607..162aeef92 100644
--- a/lib/meadow_web/router.ex
+++ b/lib/meadow_web/router.ex
@@ -4,6 +4,7 @@ defmodule MeadowWeb.Router do
import Phoenix.LiveDashboard.Router
pipeline :browser do
+ plug Plug.Logger
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
@@ -12,6 +13,7 @@ defmodule MeadowWeb.Router do
end
pipeline :secure_browser do
+ plug Plug.Logger
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
diff --git a/lib/meadow_web/schema/types/data/work_types.ex b/lib/meadow_web/schema/types/data/work_types.ex
index 30aca9211..83fde4f62 100644
--- a/lib/meadow_web/schema/types/data/work_types.ex
+++ b/lib/meadow_web/schema/types/data/work_types.ex
@@ -187,9 +187,7 @@ defmodule MeadowWeb.Schema.Data.WorkTypes do
field :citation, list_of(:string)
field :date_created, list_of(:edtf_date_entry)
field :license, :coded_term
- field :notes, list_of(:note_entry)
field :rights_statement, :coded_term
- field :related_url, list_of(:related_url_entry)
import_fields(:uncontrolled_descriptive_fields)
import_fields(:controlled_fields)
end
diff --git a/lib/meadow_web/templates/layout/app.html.eex b/lib/meadow_web/templates/layout/app.html.heex
similarity index 84%
rename from lib/meadow_web/templates/layout/app.html.eex
rename to lib/meadow_web/templates/layout/app.html.heex
index ae270d1a4..d92115db9 100644
--- a/lib/meadow_web/templates/layout/app.html.eex
+++ b/lib/meadow_web/templates/layout/app.html.heex
@@ -23,7 +23,7 @@
height="0" width="0" style="display:none;visibility:hidden">
<%= @inner_content %>
-
-
+
+