feat: Add export ID on Taxonomy details and import new Taxonomy (#814)

Adds a new prompt on the import new taxonomy workflow to enter the export_id, and adds the export_id on the Taxonomy page details.

Implements  modular-learning#183 '[Tagging] An "Export ID" identifies each Taxonomy'
This commit is contained in:
Chris Chávez
2024-02-08 22:57:17 -05:00
committed by GitHub
parent a318c322b2
commit 3938015aaa
8 changed files with 51 additions and 3 deletions

View File

@@ -5,6 +5,7 @@
* @property {number} id
* @property {string} name
* @property {string} description
* @property {string} exportId
* @property {boolean} enabled
* @property {boolean} allowMultiple
* @property {boolean} allowFreeText

View File

@@ -1,4 +1,5 @@
export default {
name: 'Taxonomy name',
exportId: 'taxonomy_export_id',
description: 'Taxonomy description',
};

View File

@@ -35,10 +35,11 @@ export const getTagsPlanImportApiUrl = (taxonomyId) => new URL(
* @param {File} file
* @returns {Promise<import('../../data/types.mjs').TaxonomyData>}
*/
export async function importNewTaxonomy(taxonomyName, taxonomyDescription, file) {
export async function importNewTaxonomy(taxonomyName, taxonomyExportId, taxonomyDescription, file) {
// ToDo: transform this to use react-query like useImportTags
const formData = new FormData();
formData.append('taxonomy_name', taxonomyName);
formData.append('taxonomy_export_id', taxonomyExportId);
formData.append('taxonomy_description', taxonomyDescription);
formData.append('file', file);

View File

@@ -51,7 +51,7 @@ describe('import taxonomy api calls', () => {
it('should call import new taxonomy', async () => {
axiosMock.onPost(getTaxonomyImportNewApiUrl()).reply(201, taxonomyImportMock);
const result = await importNewTaxonomy('Taxonomy name', 'Taxonomy description');
const result = await importNewTaxonomy('Taxonomy name', 'taxonomy_export_id', 'Taxonomy description');
expect(axiosMock.history.post[0].url).toEqual(getTaxonomyImportNewApiUrl());
expect(result).toEqual(taxonomyImportMock);

View File

@@ -64,6 +64,26 @@ export const importTaxonomy = async (intl) => { // eslint-disable-line import/pr
return taxonomyName;
};
const getTaxonomyExportId = () => {
let taxonomyExportId = null;
const validationRegex = /^[\p{L}\w\-.]+$/u;
while (!taxonomyExportId) {
taxonomyExportId = prompt(intl.formatMessage(messages.promptTaxonomyExportId));
if (taxonomyExportId == null) {
break;
}
if (!taxonomyExportId) {
alert(intl.formatMessage(messages.promptTaxonomyExportIdRequired));
} else if (!validationRegex.test(taxonomyExportId)) {
alert(intl.formatMessage(messages.promptTaxonomyExportIdInvalid));
taxonomyExportId = null;
}
}
return taxonomyExportId;
};
const getTaxonomyDescription = () => prompt(intl.formatMessage(messages.promptTaxonomyDescription));
const file = await selectFile();
@@ -77,12 +97,17 @@ export const importTaxonomy = async (intl) => { // eslint-disable-line import/pr
return;
}
const taxonomyExportId = getTaxonomyExportId();
if (taxonomyExportId == null) {
return;
}
const taxonomyDescription = getTaxonomyDescription();
if (taxonomyDescription == null) {
return;
}
importNewTaxonomy(taxonomyName, taxonomyDescription, file)
importNewTaxonomy(taxonomyName, taxonomyExportId, taxonomyDescription, file)
.then(() => {
alert(intl.formatMessage(messages.importTaxonomySuccess));
})

View File

@@ -92,6 +92,18 @@ const messages = defineMessages({
id: 'course-authoring.import-tags.prompt.taxonomy-name.required',
defaultMessage: 'You must enter a name for the new taxonomy',
},
promptTaxonomyExportId: {
id: 'course-authoring.import-tags.prompt.taxonomy-export-id',
defaultMessage: "Enter a Export ID for the new taxonomy. Should only contain alphanumeric characters or '_' '-' '.'",
},
promptTaxonomyExportIdRequired: {
id: 'course-authoring.import-tags.prompt.taxonomy-export-id.required',
defaultMessage: 'You must enter an Export ID for the new taxonomy.',
},
promptTaxonomyExportIdInvalid: {
id: 'course-authoring.import-tags.prompt.taxonomy-export-id.invalid',
defaultMessage: "Invalid Export ID. Should only contain alphanumeric characters or '_' '-' '.'",
},
promptTaxonomyDescription: {
id: 'course-authoring.import-tags.prompt.taxonomy-description',
defaultMessage: 'Enter a description for the new taxonomy',

View File

@@ -18,6 +18,9 @@ const TaxonomyDetailSideCard = ({ taxonomy }) => {
<Card.Section title={intl.formatMessage(messages.taxonomyDetailsDescription)}>
{taxonomy.description}
</Card.Section>
<Card.Section title={intl.formatMessage(messages.taxonomyDetailsExportID)}>
{taxonomy.exportId}
</Card.Section>
</Card>
);
};
@@ -25,6 +28,7 @@ const TaxonomyDetailSideCard = ({ taxonomy }) => {
TaxonomyDetailSideCard.propTypes = {
taxonomy: PropTypes.shape({
name: PropTypes.string.isRequired,
exportId: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
}).isRequired,
};

View File

@@ -14,6 +14,10 @@ const messages = defineMessages({
id: 'course-authoring.taxonomy-detail.side-card.description',
defaultMessage: 'Description',
},
taxonomyDetailsExportID: {
id: 'course-authoring.taxonomy-detail.side-card.exportID',
defaultMessage: 'Export ID',
},
});
export default messages;