invenio-vocabularies 3.4.2__py2.py3-none-any.whl → 4.1.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of invenio-vocabularies might be problematic. Click here for more details.

Files changed (69) hide show
  1. invenio_vocabularies/__init__.py +1 -1
  2. invenio_vocabularies/administration/__init__.py +10 -0
  3. invenio_vocabularies/administration/views/__init__.py +10 -0
  4. invenio_vocabularies/administration/views/vocabularies.py +44 -0
  5. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/CustomAwardForm.js +8 -20
  6. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FundingField.js +2 -2
  7. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FundingModal.js +5 -7
  8. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/NoAwardResults.js +3 -3
  9. invenio_vocabularies/cli.py +10 -39
  10. invenio_vocabularies/config.py +33 -3
  11. invenio_vocabularies/contrib/affiliations/config.py +2 -2
  12. invenio_vocabularies/contrib/affiliations/datastreams.py +67 -0
  13. invenio_vocabularies/contrib/affiliations/jsonschemas/affiliations/affiliation-v1.0.0.json +38 -1
  14. invenio_vocabularies/contrib/affiliations/mappings/os-v1/affiliations/affiliation-v1.0.0.json +21 -0
  15. invenio_vocabularies/contrib/affiliations/mappings/os-v2/affiliations/affiliation-v1.0.0.json +21 -0
  16. invenio_vocabularies/contrib/affiliations/mappings/v7/affiliations/affiliation-v1.0.0.json +21 -0
  17. invenio_vocabularies/contrib/affiliations/schema.py +17 -3
  18. invenio_vocabularies/contrib/awards/datastreams.py +90 -3
  19. invenio_vocabularies/contrib/awards/jsonschemas/awards/award-v1.0.0.json +3 -0
  20. invenio_vocabularies/contrib/awards/mappings/os-v1/awards/award-v1.0.0.json +3 -0
  21. invenio_vocabularies/contrib/awards/mappings/os-v2/awards/award-v1.0.0.json +3 -0
  22. invenio_vocabularies/contrib/awards/mappings/v7/awards/award-v1.0.0.json +3 -0
  23. invenio_vocabularies/contrib/common/__init__.py +9 -0
  24. invenio_vocabularies/contrib/common/ror/__init__.py +9 -0
  25. invenio_vocabularies/contrib/common/ror/datastreams.py +166 -0
  26. invenio_vocabularies/contrib/funders/config.py +2 -0
  27. invenio_vocabularies/contrib/funders/datastreams.py +10 -59
  28. invenio_vocabularies/contrib/funders/jsonschemas/funders/funder-v1.0.0.json +36 -1
  29. invenio_vocabularies/contrib/funders/mappings/os-v1/funders/funder-v1.0.0.json +21 -0
  30. invenio_vocabularies/contrib/funders/mappings/os-v2/funders/funder-v1.0.0.json +21 -0
  31. invenio_vocabularies/contrib/funders/mappings/v7/funders/funder-v1.0.0.json +21 -0
  32. invenio_vocabularies/contrib/funders/schema.py +8 -0
  33. invenio_vocabularies/contrib/funders/serializer.py +2 -1
  34. invenio_vocabularies/contrib/names/jsonschemas/names/name-v1.0.0.json +3 -0
  35. invenio_vocabularies/contrib/names/mappings/os-v1/names/name-v1.0.0.json +3 -0
  36. invenio_vocabularies/contrib/names/mappings/os-v2/names/name-v1.0.0.json +3 -0
  37. invenio_vocabularies/contrib/names/mappings/v7/names/name-v1.0.0.json +3 -0
  38. invenio_vocabularies/contrib/subjects/jsonschemas/subjects/subject-v1.0.0.json +3 -0
  39. invenio_vocabularies/contrib/subjects/mappings/os-v1/subjects/subject-v1.0.0.json +3 -0
  40. invenio_vocabularies/contrib/subjects/mappings/os-v2/subjects/subject-v1.0.0.json +3 -0
  41. invenio_vocabularies/contrib/subjects/mappings/v7/subjects/subject-v1.0.0.json +3 -0
  42. invenio_vocabularies/datastreams/factories.py +1 -2
  43. invenio_vocabularies/datastreams/readers.py +96 -3
  44. invenio_vocabularies/datastreams/writers.py +2 -2
  45. invenio_vocabularies/ext.py +22 -7
  46. invenio_vocabularies/factories.py +93 -0
  47. invenio_vocabularies/proxies.py +2 -2
  48. invenio_vocabularies/records/jsonschemas/vocabularies/definitions-v1.0.0.json +7 -0
  49. invenio_vocabularies/records/jsonschemas/vocabularies/vocabulary-v1.0.0.json +1 -4
  50. invenio_vocabularies/resources/__init__.py +8 -1
  51. invenio_vocabularies/resources/config.py +105 -0
  52. invenio_vocabularies/resources/resource.py +31 -41
  53. invenio_vocabularies/services/__init__.py +5 -2
  54. invenio_vocabularies/services/config.py +179 -0
  55. invenio_vocabularies/services/permissions.py +3 -1
  56. invenio_vocabularies/services/results.py +110 -0
  57. invenio_vocabularies/services/schema.py +1 -1
  58. invenio_vocabularies/services/service.py +41 -86
  59. invenio_vocabularies/services/tasks.py +31 -1
  60. invenio_vocabularies/templates/semantic-ui/invenio_vocabularies/vocabularies-list.html +12 -0
  61. invenio_vocabularies/templates/semantic-ui/invenio_vocabularies/vocabulary-details.html +71 -0
  62. invenio_vocabularies/views.py +7 -0
  63. {invenio_vocabularies-3.4.2.dist-info → invenio_vocabularies-4.1.1.dist-info}/METADATA +32 -7
  64. {invenio_vocabularies-3.4.2.dist-info → invenio_vocabularies-4.1.1.dist-info}/RECORD +69 -56
  65. {invenio_vocabularies-3.4.2.dist-info → invenio_vocabularies-4.1.1.dist-info}/entry_points.txt +7 -0
  66. {invenio_vocabularies-3.4.2.dist-info → invenio_vocabularies-4.1.1.dist-info}/AUTHORS.rst +0 -0
  67. {invenio_vocabularies-3.4.2.dist-info → invenio_vocabularies-4.1.1.dist-info}/LICENSE +0 -0
  68. {invenio_vocabularies-3.4.2.dist-info → invenio_vocabularies-4.1.1.dist-info}/WHEEL +0 -0
  69. {invenio_vocabularies-3.4.2.dist-info → invenio_vocabularies-4.1.1.dist-info}/top_level.txt +0 -0
@@ -10,6 +10,6 @@
10
10
 
11
11
  from .ext import InvenioVocabularies
12
12
 
13
- __version__ = "3.4.2"
13
+ __version__ = "4.1.1"
14
14
 
15
15
  __all__ = ("__version__", "InvenioVocabularies")
@@ -0,0 +1,10 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2024 CERN.
4
+ # Copyright (C) 2024 Uni Münster.
5
+ #
6
+ # Invenio-Vocabularies is free software; you can redistribute it and/or
7
+ # modify it under the terms of the MIT License; see LICENSE file for more
8
+ # details.
9
+
10
+ """Invenio administration views module for vocabularies."""
@@ -0,0 +1,10 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2020-2024 CERN.
4
+ # Copyright (C) 2024 Uni Münster.
5
+ #
6
+ # Invenio-Vocabularies is free software; you can redistribute it and/or
7
+ # modify it under the terms of the MIT License; see LICENSE file for more
8
+ # details.
9
+
10
+ """Invenio administration views module for Vocabularies."""
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2020-2024 CERN.
4
+ # Copyright (C) 2024 Uni Münster.
5
+ #
6
+ # Invenio-Vocabularies is free software; you can redistribute it and/or
7
+ # modify it under the terms of the MIT License; see LICENSE file for more
8
+ # details.
9
+
10
+ """Vocabularies admin interface."""
11
+ from invenio_administration.views.base import (
12
+ AdminResourceEditView,
13
+ AdminResourceListView,
14
+ )
15
+
16
+
17
+ class VocabulariesListView(AdminResourceListView):
18
+ """Configuration for vocabularies list view."""
19
+
20
+ api_endpoint = "/vocabularies/"
21
+ name = "vocabulary-types"
22
+ menu_label = "Vocabulary Types"
23
+ resource_config = "vocabulary_admin_resource"
24
+ search_request_headers = {"Accept": "application/json"}
25
+ title = "Vocabulary Types"
26
+ category = "Site management"
27
+
28
+ pid_path = "id"
29
+ icon = "exchange"
30
+ template = "invenio_administration/search.html"
31
+
32
+ display_search = True
33
+ display_delete = False
34
+ display_edit = False
35
+ display_create = False
36
+
37
+ item_field_list = {
38
+ "id": {"text": "Name", "order": 1},
39
+ "count": {"text": "Number of entries", "order": 2},
40
+ }
41
+
42
+ search_config_name = "VOCABULARIES_TYPES_SEARCH"
43
+ search_facets_config_name = "VOCABULARIES_TYPES_FACETS"
44
+ search_sort_config_name = "VOCABULARIES_TYPES_SORT_OPTIONS"
@@ -1,5 +1,5 @@
1
1
  // This file is part of InvenioVocabularies
2
- // Copyright (C) 2021-2023 CERN.
2
+ // Copyright (C) 2021-2024 CERN.
3
3
  // Copyright (C) 2021 Northwestern University.
4
4
  //
5
5
  // Invenio is free software; you can redistribute it and/or modify it
@@ -16,21 +16,9 @@ import Overridable from "react-overridable";
16
16
 
17
17
  function CustomAwardForm({ deserializeFunder, selectedFunding }) {
18
18
  function deserializeFunderToDropdown(funderItem) {
19
- let funderName = null;
20
- let funderPID = null;
21
- let funderCountry = null;
22
-
23
- if (funderItem.name) {
24
- funderName = funderItem.name;
25
- }
26
-
27
- if (funderItem.id) {
28
- funderPID = funderItem.id;
29
- }
30
-
31
- if (funderItem.country) {
32
- funderCountry = funderItem.country;
33
- }
19
+ const funderName = funderItem?.name;
20
+ const funderPID = funderItem?.id;
21
+ const funderCountry = funderItem?.country_name ?? funderItem?.country;
34
22
 
35
23
  if (!funderName && !funderPID) {
36
24
  return {};
@@ -100,7 +88,7 @@ function CustomAwardForm({ deserializeFunder, selectedFunding }) {
100
88
  </Overridable>
101
89
  <Overridable id="InvenioVocabularies.CustomAwardForm.AwardInformationHeader.Container">
102
90
  <Header as="h3" size="small">
103
- {i18next.t("Award information")} ({i18next.t("optional")})
91
+ {i18next.t("Additional information")} ({i18next.t("optional")})
104
92
  </Header>
105
93
  </Overridable>
106
94
  <Form.Group widths="equal">
@@ -110,7 +98,7 @@ function CustomAwardForm({ deserializeFunder, selectedFunding }) {
110
98
  >
111
99
  <TextField
112
100
  label={i18next.t("Number")}
113
- placeholder={i18next.t("Award number")}
101
+ placeholder={i18next.t("Award/Grant number")}
114
102
  fieldPath="selectedFunding.award.number"
115
103
  />
116
104
  </Overridable>
@@ -120,7 +108,7 @@ function CustomAwardForm({ deserializeFunder, selectedFunding }) {
120
108
  >
121
109
  <TextField
122
110
  label={i18next.t("Title")}
123
- placeholder={i18next.t("Award Title")}
111
+ placeholder={i18next.t("Award/Grant Title")}
124
112
  fieldPath="selectedFunding.award.title"
125
113
  />
126
114
  </Overridable>
@@ -130,7 +118,7 @@ function CustomAwardForm({ deserializeFunder, selectedFunding }) {
130
118
  >
131
119
  <TextField
132
120
  label={i18next.t("URL")}
133
- placeholder={i18next.t("Award URL")}
121
+ placeholder={i18next.t("Award/Grant URL")}
134
122
  fieldPath="selectedFunding.award.url"
135
123
  />
136
124
  </Overridable>
@@ -1,5 +1,5 @@
1
1
  // This file is part of InvenioVocabularies
2
- // Copyright (C) 2021-2023 CERN.
2
+ // Copyright (C) 2021-2024 CERN.
3
3
  // Copyright (C) 2021 Northwestern University.
4
4
  //
5
5
  // Invenio is free software; you can redistribute it and/or modify it
@@ -123,7 +123,7 @@ function FundingFieldForm(props) {
123
123
  className="mb-5"
124
124
  >
125
125
  <Icon name="add" />
126
- {i18next.t("Add award")}
126
+ {i18next.t("Add")}
127
127
  </Button>
128
128
  }
129
129
  onAwardChange={(selectedFunding) => {
@@ -1,5 +1,5 @@
1
1
  // This file is part of InvenioVocabularies
2
- // Copyright (C) 2021-2023 CERN.
2
+ // Copyright (C) 2021-2024 CERN.
3
3
  // Copyright (C) 2021 Northwestern University.
4
4
  //
5
5
  // Invenio is free software; you can redistribute it and/or modify it
@@ -157,8 +157,8 @@ function FundingModal({
157
157
  >
158
158
  <Modal.Header as="h2" className="pt-10 pb-10">
159
159
  {mode === "standard"
160
- ? i18next.t("Add standard award")
161
- : i18next.t("Add custom award")}
160
+ ? i18next.t("Add standard award/grant")
161
+ : i18next.t("Add custom funding")}
162
162
  </Modal.Header>
163
163
  <Modal.Content>
164
164
  {mode === ModalTypes.STANDARD && (
@@ -172,7 +172,7 @@ function FundingModal({
172
172
  <Grid.Row>
173
173
  <Grid.Column width={11} floated="left" verticalAlign="middle">
174
174
  <SearchBar
175
- placeholder={i18next.t("Search for awards")}
175
+ placeholder={i18next.t("Search for awards/grants")}
176
176
  autofocus
177
177
  actionProps={{
178
178
  icon: "search",
@@ -234,9 +234,7 @@ function FundingModal({
234
234
  primary
235
235
  icon="checkmark"
236
236
  content={
237
- action === ModalActions.ADD
238
- ? i18next.t("Add award")
239
- : i18next.t("Change award")
237
+ action === ModalActions.ADD ? i18next.t("Add") : i18next.t("Change")
240
238
  }
241
239
  />
242
240
  </Modal.Actions>
@@ -1,5 +1,5 @@
1
1
  // This file is part of InvenioVocabularies
2
- // Copyright (C) 2021-2023 CERN.
2
+ // Copyright (C) 2021-2024 CERN.
3
3
  // Copyright (C) 2021 Northwestern University.
4
4
  //
5
5
  // Invenio is free software; you can redistribute it and/or modify it
@@ -16,7 +16,7 @@ export function NoAwardResults({ switchToCustom }) {
16
16
  basic
17
17
  content={
18
18
  <p>
19
- {i18next.t("Did not find your award? ")}
19
+ {i18next.t("Did not find your award/grant? ")}
20
20
  <a
21
21
  href="/"
22
22
  onClick={(e) => {
@@ -24,7 +24,7 @@ export function NoAwardResults({ switchToCustom }) {
24
24
  switchToCustom();
25
25
  }}
26
26
  >
27
- {i18next.t("Add a custom award.")}
27
+ {i18next.t("Add a custom award/grant.")}
28
28
  </a>
29
29
  </p>
30
30
  }
@@ -9,46 +9,14 @@
9
9
 
10
10
  """Commands to create and manage vocabularies."""
11
11
 
12
- from copy import deepcopy
13
12
 
14
13
  import click
15
- import yaml
16
14
  from flask.cli import with_appcontext
17
15
  from invenio_access.permissions import system_identity
18
16
  from invenio_pidstore.errors import PIDDeletedError, PIDDoesNotExistError
19
- from invenio_records_resources.proxies import current_service_registry
20
17
 
21
- from .contrib.awards.datastreams import DATASTREAM_CONFIG as awards_ds_config
22
- from .contrib.funders.datastreams import DATASTREAM_CONFIG as funders_ds_config
23
- from .contrib.names.datastreams import DATASTREAM_CONFIG as names_ds_config
24
18
  from .datastreams import DataStreamFactory
25
-
26
-
27
- def get_config_for_ds(vocabulary, filepath=None, origin=None):
28
- """Calculates the configuration for a Data Stream."""
29
- config = None
30
- if vocabulary == "names": # FIXME: turn into a proper factory
31
- config = deepcopy(names_ds_config)
32
- elif vocabulary == "funders":
33
- config = deepcopy(funders_ds_config)
34
- elif vocabulary == "awards":
35
- config = deepcopy(awards_ds_config)
36
-
37
- if config:
38
- if filepath:
39
- with open(filepath) as f:
40
- config = yaml.safe_load(f).get(vocabulary)
41
- if origin:
42
- config["readers"][0].setdefault("args", {})
43
- config["readers"][0]["args"]["origin"] = origin
44
-
45
- return config
46
-
47
-
48
- def get_service_for_vocabulary(vocabulary):
49
- """Calculates the configuration for a Data Stream."""
50
- if vocabulary == "names": # FIXME: turn into a proper factory
51
- return current_service_registry.get("names")
19
+ from .factories import get_vocabulary_config
52
20
 
53
21
 
54
22
  @click.group()
@@ -111,7 +79,9 @@ def import_vocab(vocabulary, filepath=None, origin=None, num_samples=None):
111
79
  click.secho("One of --filepath or --origin must be present.", fg="red")
112
80
  exit(1)
113
81
 
114
- config = get_config_for_ds(vocabulary, filepath, origin)
82
+ vc = get_vocabulary_config(vocabulary)
83
+ config = vc.get_config(filepath, origin)
84
+
115
85
  success, errored, filtered = _process_vocab(config, num_samples)
116
86
 
117
87
  _output_process(vocabulary, "imported", success, errored, filtered)
@@ -127,8 +97,8 @@ def update(vocabulary, filepath=None, origin=None):
127
97
  if not filepath and not origin:
128
98
  click.secho("One of --filepath or --origin must be present.", fg="red")
129
99
  exit(1)
130
-
131
- config = get_config_for_ds(vocabulary, filepath, origin)
100
+ vc = get_vocabulary_config(vocabulary)
101
+ config = vc.get_config(filepath, origin)
132
102
 
133
103
  for w_conf in config["writers"]:
134
104
  w_conf["args"]["update"] = True
@@ -153,7 +123,8 @@ def convert(vocabulary, filepath=None, origin=None, target=None, num_samples=Non
153
123
  )
154
124
  exit(1)
155
125
 
156
- config = get_config_for_ds(vocabulary, filepath, origin)
126
+ vc = get_vocabulary_config(vocabulary)
127
+ config = vc.get_config(filepath, origin)
157
128
  if not filepath:
158
129
  config["writers"] = [{"type": "yaml", "args": {"filepath": target}}]
159
130
 
@@ -176,8 +147,8 @@ def delete(vocabulary, identifier, all):
176
147
  if not id and not all:
177
148
  click.secho("An identifier or the --all flag must be present.", fg="red")
178
149
  exit(1)
179
-
180
- service = get_service_for_vocabulary(vocabulary)
150
+ vc = get_vocabulary_config(vocabulary)
151
+ service = vc.get_service()
181
152
  if identifier:
182
153
  try:
183
154
  if service.delete(identifier, system_identity):
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2020 CERN.
3
+ # Copyright (C) 2020-2024 CERN.
4
4
  # Copyright (C) 2021 Northwestern University.
5
5
  #
6
6
  # Invenio-Vocabularies is free software; you can redistribute it and/or
@@ -17,6 +17,7 @@ from .datastreams.readers import (
17
17
  GzipReader,
18
18
  JsonLinesReader,
19
19
  JsonReader,
20
+ OAIPMHReader,
20
21
  TarReader,
21
22
  XMLReader,
22
23
  YamlReader,
@@ -24,8 +25,8 @@ from .datastreams.readers import (
24
25
  )
25
26
  from .datastreams.transformers import XMLTransformer
26
27
  from .datastreams.writers import ServiceWriter, YamlWriter
27
- from .resources.resource import VocabulariesResourceConfig
28
- from .services.service import VocabulariesServiceConfig
28
+ from .resources import VocabulariesResourceConfig
29
+ from .services.config import VocabulariesServiceConfig
29
30
 
30
31
  VOCABULARIES_RESOURCE_CONFIG = VocabulariesResourceConfig
31
32
  """Configure the resource."""
@@ -75,6 +76,7 @@ VOCABULARIES_AWARDS_OPENAIRE_FUNDERS = {
75
76
  "fwf_________": "013tf3c58",
76
77
  "inca________": "03m8vkq32",
77
78
  "irb_hr______": "03n51vw80",
79
+ "lcs_________": "02ar66p97",
78
80
  "mestd_______": "01znas443",
79
81
  "nhmrc_______": "011kf5r70",
80
82
  "nih_________": "01cwqze88",
@@ -102,6 +104,15 @@ VOCABULARIES_NAMES_SCHEMES = {
102
104
  }
103
105
  """Names allowed identifier schemes."""
104
106
 
107
+ # configure CUSTOM_VOCABULARY_TYPES to differentiate output. Is used in VocabulariesServiceConfig
108
+ VOCABULARIES_CUSTOM_VOCABULARY_TYPES = [
109
+ "names",
110
+ "affiliations",
111
+ "awards",
112
+ "funders",
113
+ "subjects",
114
+ ]
115
+
105
116
  VOCABULARIES_DATASTREAM_READERS = {
106
117
  "csv": CSVReader,
107
118
  "json": JsonReader,
@@ -111,6 +122,7 @@ VOCABULARIES_DATASTREAM_READERS = {
111
122
  "yaml": YamlReader,
112
123
  "zip": ZipReader,
113
124
  "xml": XMLReader,
125
+ "oai-pmh": OAIPMHReader,
114
126
  }
115
127
  """Data Streams readers."""
116
128
 
@@ -124,3 +136,21 @@ VOCABULARIES_DATASTREAM_WRITERS = {
124
136
  "yaml": YamlWriter,
125
137
  }
126
138
  """Data Streams writers."""
139
+
140
+ VOCABULARIES_TYPES_SORT_OPTIONS = {
141
+ "name": dict(
142
+ title=_("Name"),
143
+ fields=["id"],
144
+ ),
145
+ "count": dict(
146
+ title=_("Number of entries"),
147
+ fields=["count"],
148
+ ),
149
+ }
150
+ """Definitions of available Vocabulary types sort options. """
151
+
152
+ VOCABULARIES_TYPES_SEARCH = {
153
+ "facets": [],
154
+ "sort": ["name", "count"],
155
+ }
156
+ """Vocabulary type search configuration."""
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2021 CERN.
3
+ # Copyright (C) 2021-2024 CERN.
4
4
  #
5
5
  # Invenio-Vocabularies is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the MIT License; see LICENSE file for more
@@ -26,7 +26,7 @@ class AffiliationsSearchOptions(SearchOptions):
26
26
  """Search options."""
27
27
 
28
28
  suggest_parser_cls = SuggestQueryParser.factory(
29
- fields=["name^100", "acronym^20", "id^20"],
29
+ fields=["name^100", "acronym^50", "title.*^20", "id^20", "aliases^20"],
30
30
  )
31
31
 
32
32
  sort_default = "bestmatch"
@@ -0,0 +1,67 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2022-2024 CERN.
4
+ # Copyright (C) 2024 California Institute of Technology.
5
+ #
6
+ # Invenio-Vocabularies is free software; you can redistribute it and/or
7
+ # modify it under the terms of the MIT License; see LICENSE file for more
8
+ # details.
9
+
10
+ """Affiliations datastreams, transformers, writers and readers."""
11
+
12
+ from invenio_access.permissions import system_identity
13
+ from invenio_i18n import lazy_gettext as _
14
+
15
+ from ...datastreams.writers import ServiceWriter
16
+ from .config import affiliation_schemes
17
+
18
+
19
+ class AffiliationsServiceWriter(ServiceWriter):
20
+ """Affiliations service writer."""
21
+
22
+ def __init__(self, *args, **kwargs):
23
+ """Constructor."""
24
+ service_or_name = kwargs.pop("service_or_name", "affiliations")
25
+ super().__init__(service_or_name=service_or_name, *args, **kwargs)
26
+
27
+ def _entry_id(self, entry):
28
+ """Get the id from an entry."""
29
+ return entry["id"]
30
+
31
+
32
+ VOCABULARIES_DATASTREAM_WRITERS = {
33
+ "affiliations-service": AffiliationsServiceWriter,
34
+ }
35
+
36
+
37
+ DATASTREAM_CONFIG = {
38
+ "readers": [
39
+ {
40
+ "type": "zip",
41
+ "args": {
42
+ "regex": "_schema_v2\\.json$",
43
+ },
44
+ },
45
+ {"type": "json"},
46
+ ],
47
+ "transformers": [
48
+ {
49
+ "type": "ror",
50
+ "args": {
51
+ "vocab_schemes": affiliation_schemes,
52
+ },
53
+ },
54
+ ],
55
+ "writers": [
56
+ {
57
+ "type": "affiliations-service",
58
+ "args": {
59
+ "identity": system_identity,
60
+ },
61
+ }
62
+ ],
63
+ }
64
+ """Data Stream configuration.
65
+
66
+ An origin is required for the reader.
67
+ """
@@ -7,13 +7,50 @@
7
7
  "$schema": {
8
8
  "$ref": "local://definitions-v1.0.0.json#/$schema"
9
9
  },
10
+ "tags": {
11
+ "$ref": "local://vocabularies/definitions-v1.0.0.json#/tags"
12
+ },
13
+ "country": {
14
+ "type": "string",
15
+ "description": "Represents a affiliation's country as a country code."
16
+ },
17
+ "country_name": {
18
+ "type": "string",
19
+ "description": "Represents a affiliation's country as a full name."
20
+ },
21
+ "location_name": {
22
+ "type": "string",
23
+ "description": "Represents a affiliation's location name (usually a city)."
24
+ },
10
25
  "acronym": {
11
26
  "type": "string"
12
27
  },
13
28
  "identifiers": {
14
29
  "description": "Alternate identifiers for the record.",
15
30
  "type": "array",
16
- "items": {"$ref": "local://definitions-v1.0.0.json#/identifiers_with_scheme"},
31
+ "items": {
32
+ "$ref": "local://definitions-v1.0.0.json#/identifiers_with_scheme"
33
+ },
34
+ "uniqueItems": true
35
+ },
36
+ "status": {
37
+ "type": "string",
38
+ "description": "Status of the affiliation organization."
39
+ },
40
+ "aliases": {
41
+ "description": "Alternate names for the affiliation.",
42
+ "type": "array",
43
+ "items": {
44
+ "type": "string"
45
+ },
46
+ "uniqueItems": true
47
+ },
48
+ "types": {
49
+ "description": "Types of affiliation organization.",
50
+ "type": "array",
51
+ "items": {
52
+ "type": "string"
53
+ },
17
54
  "uniqueItems": true
18
55
  },
19
56
  "name": {
@@ -85,6 +85,27 @@
85
85
  "title": {
86
86
  "type": "object",
87
87
  "dynamic": "true"
88
+ },
89
+ "tags": {
90
+ "type": "keyword"
91
+ },
92
+ "country": {
93
+ "type": "text"
94
+ },
95
+ "country_name": {
96
+ "type": "text"
97
+ },
98
+ "location_name": {
99
+ "type": "text"
100
+ },
101
+ "status": {
102
+ "type": "keyword"
103
+ },
104
+ "aliases": {
105
+ "type": "text"
106
+ },
107
+ "types": {
108
+ "type": "keyword"
88
109
  }
89
110
  }
90
111
  }
@@ -85,6 +85,27 @@
85
85
  "title": {
86
86
  "type": "object",
87
87
  "dynamic": "true"
88
+ },
89
+ "tags": {
90
+ "type": "keyword"
91
+ },
92
+ "country": {
93
+ "type": "text"
94
+ },
95
+ "country_name": {
96
+ "type": "text"
97
+ },
98
+ "location_name": {
99
+ "type": "text"
100
+ },
101
+ "status": {
102
+ "type": "keyword"
103
+ },
104
+ "aliases": {
105
+ "type": "text"
106
+ },
107
+ "types": {
108
+ "type": "keyword"
88
109
  }
89
110
  }
90
111
  }
@@ -85,6 +85,27 @@
85
85
  "title": {
86
86
  "type": "object",
87
87
  "dynamic": "true"
88
+ },
89
+ "tags": {
90
+ "type": "keyword"
91
+ },
92
+ "country": {
93
+ "type": "text"
94
+ },
95
+ "country_name": {
96
+ "type": "text"
97
+ },
98
+ "location_name": {
99
+ "type": "text"
100
+ },
101
+ "status": {
102
+ "type": "keyword"
103
+ },
104
+ "aliases": {
105
+ "type": "text"
106
+ },
107
+ "types": {
108
+ "type": "keyword"
88
109
  }
89
110
  }
90
111
  }
@@ -1,6 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2020-2022 CERN.
3
+ # Copyright (C) 2020-2024 CERN.
4
+ # Copyright (C) 2024 California Institute of Technology.
4
5
  #
5
6
  # Invenio-Vocabularies is free software; you can redistribute it and/or
6
7
  # modify it under the terms of the MIT License; see LICENSE file for more
@@ -11,7 +12,7 @@
11
12
  from functools import partial
12
13
 
13
14
  from invenio_i18n import lazy_gettext as _
14
- from marshmallow import fields
15
+ from marshmallow import fields, validate
15
16
  from marshmallow_utils.fields import IdentifierSet, SanitizedUnicode
16
17
  from marshmallow_utils.schemas import IdentifierSchema
17
18
 
@@ -36,7 +37,20 @@ class AffiliationSchema(BaseVocabularySchema, ModePIDFieldVocabularyMixin):
36
37
  )
37
38
  )
38
39
  )
39
- name = SanitizedUnicode(required=True)
40
+ name = SanitizedUnicode(
41
+ required=True, validate=validate.Length(min=1, error=_("Name cannot be blank."))
42
+ )
43
+ country = SanitizedUnicode()
44
+ country_name = SanitizedUnicode()
45
+ location_name = SanitizedUnicode()
46
+ id = SanitizedUnicode(
47
+ validate=validate.Length(min=1, error=_("PID cannot be blank."))
48
+ )
49
+
50
+ acronym = SanitizedUnicode()
51
+ aliases = fields.List(SanitizedUnicode())
52
+ status = SanitizedUnicode()
53
+ types = fields.List(SanitizedUnicode())
40
54
 
41
55
 
42
56
  class AffiliationRelationSchema(ContribVocabularyRelationSchema):