Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORE-1967 Initial Local Contexts label display #563

Merged

Conversation

psarando
Copy link
Member

@psarando psarando commented Jan 27, 2024

This PR will add the initial Local Contexts label display to Data Listings and Metadata Templates.

When the metadata for a folder contains a LocalContexts attribute, and a rightsURI sub-attribute with a valid Local Contexts project URI as its value, then the Local Contexts labels for that project will be displayed in the data listing, as well as in metadata templates (such as the DataCite 4.2 template) that have a LocalContexts attribute field.

Each label is also an icon button that opens a dialog which displays the label or notice's descriptive text, along with a larger image of the label, and a link to the Local Contexts project page.

This PR also adds a custom LocalContexts attribute field for metadata templates (such as the DataCite 4.2 template) which displays only a Local Contexts Hub project URI field for the user, and will auto-populate DataCite metadata and child AVUs using the project ID parsed from the URI and the Local Contexts Hub API response (which is also used to display the project's labels below the field).


DataCite Metadata Template


Data Listing


It's also possible for Local Contexts Hub projects to have sub-projects.

This can also be supported in the DE if the user adds the sub-project's URI to the associated data in the main project's folder:

Data Listing folder contents


Finally, this is an example Dialog displaying a project's TK Label and associated text:
TK Label Dialog


@psarando psarando added the enhancement New feature or request label Jan 27, 2024
@psarando psarando force-pushed the CORE-1967-local-contexts-label-display branch 6 times, most recently from 33c1990 to 8e06964 Compare February 28, 2024 03:19
@psarando psarando marked this pull request as ready for review February 29, 2024 03:26
@psarando psarando force-pushed the CORE-1967-local-contexts-label-display branch from 1d28dda to 2ecd808 Compare February 29, 2024 23:09
Comment on lines +94 to +168
const { data: project, isFetching } = useQuery({
queryKey: [LOCAL_CONTEXTS_QUERY_KEY, projectID],
queryFn: () =>
getLocalContextsProject({
projectID,
}),
enabled: projectHubURI && !fieldError,
onSuccess: (project) => {
let newValue = avu.value || "";

const projectLabels = [
...(project?.notice?.filter((label) => label?.name) || []),
...(project?.bc_labels?.filter((label) => label?.name) || []),
...(project?.tk_labels?.filter((label) => label?.name) || []),
];

if (projectLabels.length === 1) {
newValue =
projectLabels[0].label_text ||
projectLabels[0].default_text;
} else {
newValue = t("localContextsAttrDefaultValue", {
projectTitle: project?.title,
projectPage: project?.project_page,
});
}

const newLabels = projectLabels.map((label) => label.name);

let newAVUs = avu.avus || [];

const currentLabels = newAVUs
.filter(
(childAVU) => childAVU.attr === LocalContextsAttrs.RIGHTS_ID
)
?.map((childAVU) => childAVU.value);

const missingLabels = newLabels.filter(
(label) => !currentLabels.includes(label)
);

const extraLabels = currentLabels.filter(
(label) => !newLabels.includes(label)
);

const requiresUpdate =
avu.value !== newValue ||
missingLabels.length > 0 ||
extraLabels.length > 0;

if (requiresUpdate) {
newAVUs = newAVUs.filter(
(childAVU) =>
childAVU.attr !== LocalContextsAttrs.RIGHTS_URI &&
childAVU.attr !== LocalContextsAttrs.RIGHTS_ID_SCHEME &&
childAVU.attr !== LocalContextsAttrs.SCHEME_URI &&
(childAVU.attr !== LocalContextsAttrs.RIGHTS_ID ||
newLabels.includes(childAVU.value))
);

newAVUs = [
...newAVUs,
rightsURIAVU,
schemeURIAVU,
rightsIDSchemeURIAVU,
...missingLabels.map((label) => ({
attr: LocalContextsAttrs.RIGHTS_ID,
value: label,
unit: "",
})),
];

onUpdate({ ...avu, value: newValue, avus: newAVUs });
}
},
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic in the Local Contexts Hub project query's onSuccess function synchronizes the labels defined in the project with the DE metadata. It also ensures the other child AVUs required by DataCite v4.2 are included.

The top-level AVU's value is based on suggestions from DataCite's docs.

The required AVU and child AVUs should be like the following:

{
      "attr": "LocalContexts",
      "value": "The \"January Test\" project has Labels and/or Notices applied through the Local Contexts Hub. For more information, refer to the project page: https://sandbox.localcontextshub.org/projects/adcbca87-081a-4e2c-b6af-bff12fe3b7b0",
      "unit": "",
      "avus": [
        {
          "attr": "rightsIdentifier",
          "value": "Traditional Knowledge (TK) Notice",
          "unit": ""
        },
        {
          "attr": "rightsIdentifier",
          "value": "Biocultural (BC) Notice",
          "unit": ""
        },
        {
          "attr": "rightsIdentifier",
          "value": "Attribution Incomplete Notice",
          "unit": ""
        },
        {
          "attr": "rightsURI",
          "value": "https://sandbox.localcontextshub.org/projects/adcbca87-081a-4e2c-b6af-bff12fe3b7b0/",
          "unit": ""
        },
        {
          "attr": "schemeURI",
          "value": "https://localcontexts.org",
          "unit": ""
        },
        {
          "attr": "rightsIdentifierScheme",
          "value": "Local Contexts",
          "unit": ""
        }
      ]
    }

Comment on lines +179 to +209
const updateProjectHubURI = (uri) => {
setProjectHubURI(uri);
setProjectHubError(null);

let newAVUs = avu.avus || [];

if (rightsURIAVU.value !== uri) {
const newRightsURIAVU = {
attr: LocalContextsAttrs.RIGHTS_URI,
value: uri,
unit: "",
};
setRightsURIAVU(newRightsURIAVU);

newAVUs = newAVUs.filter(
(childAVU) =>
childAVU.attr !== LocalContextsAttrs.RIGHTS_URI &&
childAVU.attr !== LocalContextsAttrs.RIGHTS_ID_SCHEME &&
childAVU.attr !== LocalContextsAttrs.SCHEME_URI
);

newAVUs = [
...newAVUs,
newRightsURIAVU,
schemeURIAVU,
rightsIDSchemeURIAVU,
];

onUpdate({ ...avu, avus: newAVUs });
}
};
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is called whenever the user updates the Local Contexts Hub project URI in the form field, and if the URI does not match the rightsURI child AVU's value, then it is updated, and the other child AVUs required by DataCite v4.2 are also included.

Copy link
Member

@ianmcorvidae ianmcorvidae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw one small thing but as far as I understood the rest, looks fine to me. The only other thought I had, which it's possible is already in place since I don't think it'd be in this PR anyway, is that given the LocalContexts project URI acts as a required field, I don't know if the template should have a note saying something like "if LocalContexts doesn't apply, use <a different template, I guess just regular DataCite>" just to avoid confusion if someone selects the LocalContexts one in error.

src/server/api/metadata.js Outdated Show resolved Hide resolved
Copy link
Member

@slr71 slr71 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't catch anything. :shipit:

@psarando
Copy link
Member Author

psarando commented Mar 4, 2024

The only other thought I had, which it's possible is already in place since I don't think it'd be in this PR anyway, is that given the LocalContexts project URI acts as a required field, I don't know if the template should have a note saying something like "if LocalContexts doesn't apply, use <a different template, I guess just regular DataCite>" just to avoid confusion if someone selects the LocalContexts one in error.

So there is a little bit of trickery happening with this custom field in the DataCite template, because the top-level LocalContexts attribute is actually not marked as required, so it is not included by default and the user is not required to add it in their DataCite metadata:
custom LocalContexts attribute template default

If the user does add the LocalContexts attribute in the template, then it displays the field as required, but it's based on the fact that the rightsURI sub-attribute is required in DataCite metadata, so the custom field is borrowing the validations of that rightsURI sub-attribute.

Here's how it currently looks in prod without this custom component, when a user initially adds the attribute in the template:
prod LocalContexts template attribute

The template still defines this attribute with all these sub-attributes, it's just the UI is displaying the simplified custom component for the LocalContexts attribute; and this custom component will be displayed in any metadata template that has a LocalContexts attribute, not just the DataCite template.

This also means all the required sub-attributes will still be included in a CSV download of the template for bulk metadata uploads.

We can also add another metadata template that only has the LocalContexts attribute, for users that only need labels and notices to display for their data, but because the custom component will add all the sub-attributes required by the DataCite template, the user can still use that template later if they need a DOI for their data, and those required attributes will already be there.

I was also thinking the template's description for this attribute could be updated once these changes go live in prod, so it will make sense in both the custom component in the UI, but also in the CSV guide download.

psarando added 10 commits March 4, 2024 15:17
Initial Local Contexts label display in
Data Listings and Metadata Templates.
Add the LocalContexts label/notice default text to a card that also
includes the label/notice icon.
Improved the LocalContexts label/notice icon sizing.
Added a link to the LocalContextsHub project in the details dialog.
Added a custom LocalContextsField for metadata templates that only
displays a URL field for a Local Contexts Hub project URL,
and auto-populates DataCite metadata and child AVUs from the
Local Contexts Hub API response.
Chromatic is throwing errors that URL.canParse is not a function,
even though CanIUse and MDN docs indicate there's wide support for it.
Probably broken by MUI v5 Autocomplete upgrade in cyverse-de#554
@psarando psarando force-pushed the CORE-1967-local-contexts-label-display branch from 2ecd808 to d9b1b70 Compare March 4, 2024 22:17
@psarando
Copy link
Member Author

psarando commented Mar 5, 2024

Thanks for the reviews 👍

@psarando psarando merged commit 7d0ce9f into cyverse-de:master Mar 5, 2024
5 of 6 checks passed
@psarando psarando deleted the CORE-1967-local-contexts-label-display branch March 5, 2024 02:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants