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:
@@ -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
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export default {
|
||||
name: 'Taxonomy name',
|
||||
exportId: 'taxonomy_export_id',
|
||||
description: 'Taxonomy description',
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
})
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user