-
Notifications
You must be signed in to change notification settings - Fork 81
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
feat: import tags to existing taxonomy [FC-0036] #708
Closed
rpenido
wants to merge
21
commits into
openedx:master
from
open-craft:rpenido/fal-3536-bare-bones-update-of-existing-taxonomy-by-upload
Closed
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
0c60c37
feat: add import taxonomy feature
rpenido c273af1
test: add api.test.js
rpenido 047530d
test: add import button click test
rpenido 303e7ba
test: add action.test.js
rpenido 3955e91
test: add more tests to action.tests.js
rpenido 8176973
test: add more tests to action.tests.js 2
rpenido 4f31714
Merge branch 'openedx:master' into rpenido/fal-3532-import-taxonomy
rpenido df441fb
fix: import
rpenido a0e92f0
test: simplify import test
rpenido dc8ed9e
fix: remove undefined var
rpenido 120154e
refactor: rename actions.js -> utils.js
rpenido 318bbb7
revert: change in the jest.config
rpenido a8c2fd5
Merge branch 'master' into rpenido/fal-3532-import-taxonomy
pomegranited 70ac2a7
Merge branch 'openedx:master' into rpenido/fal-3532-import-taxonomy
rpenido adacf23
chore: trigger CD/CI
rpenido 5983953
Merge branch 'master' into rpenido/fal-3532-import-taxonomy
rpenido bb90002
Merge branch 'master' into rpenido/fal-3532-import-taxonomy
rpenido d8bc6c1
feat: import tags to existing taxonomy
rpenido 1ac94e8
feat: add re-import menu to taxonomy detail
rpenido c055d56
test: add tests
rpenido 8c2de23
fix: clean debug code
rpenido File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { default as taxonomyImportMock } from './taxonomyImportMock'; | ||
export { default as tagImportMock } from './tagImportMock'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export default { | ||
name: 'Taxonomy name', | ||
description: 'Taxonomy description', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export default { | ||
name: 'Taxonomy name', | ||
description: 'Taxonomy description', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// @ts-check | ||
import { camelCaseObject, getConfig } from '@edx/frontend-platform'; | ||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; | ||
|
||
const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL; | ||
|
||
export const getTaxonomyImportNewApiUrl = () => new URL( | ||
'api/content_tagging/v1/taxonomies/import/', | ||
getApiBaseUrl(), | ||
).href; | ||
|
||
/** | ||
* @param {number} taxonomyId | ||
* @returns {string} | ||
*/ | ||
export const getTagsImportApiUrl = (taxonomyId) => new URL( | ||
`api/content_tagging/v1/taxonomies/${taxonomyId}/tags/import/`, | ||
getApiBaseUrl(), | ||
).href; | ||
|
||
/** | ||
* Import a new taxonomy | ||
* @param {string} taxonomyName | ||
* @param {string} taxonomyDescription | ||
* @param {File} file | ||
* @returns {Promise<Object>} | ||
*/ | ||
export async function importNewTaxonomy(taxonomyName, taxonomyDescription, file) { | ||
const formData = new FormData(); | ||
formData.append('taxonomy_name', taxonomyName); | ||
formData.append('taxonomy_description', taxonomyDescription); | ||
formData.append('file', file); | ||
|
||
const { data } = await getAuthenticatedHttpClient().post( | ||
getTaxonomyImportNewApiUrl(), | ||
formData, | ||
); | ||
|
||
return camelCaseObject(data); | ||
} | ||
|
||
/** | ||
* Import tags to an existing taxonomy, overwriting existing tags | ||
* @param {number} taxonomyId | ||
* @param {File} file | ||
* @returns {Promise<Object>} | ||
*/ | ||
export async function importTags(taxonomyId, file) { | ||
const formData = new FormData(); | ||
formData.append('file', file); | ||
|
||
const { data } = await getAuthenticatedHttpClient().put( | ||
getTagsImportApiUrl(taxonomyId), | ||
formData, | ||
); | ||
|
||
return camelCaseObject(data); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import MockAdapter from 'axios-mock-adapter'; | ||
import { initializeMockApp } from '@edx/frontend-platform'; | ||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; | ||
|
||
import { tagImportMock, taxonomyImportMock } from '../__mocks__'; | ||
|
||
import { | ||
getTaxonomyImportNewApiUrl, | ||
getTagsImportApiUrl, | ||
importNewTaxonomy, | ||
importTags, | ||
} from './api'; | ||
|
||
let axiosMock; | ||
|
||
describe('import taxonomy api calls', () => { | ||
beforeEach(() => { | ||
initializeMockApp({ | ||
authenticatedUser: { | ||
userId: 3, | ||
username: 'abc123', | ||
administrator: true, | ||
roles: [], | ||
}, | ||
}); | ||
axiosMock = new MockAdapter(getAuthenticatedHttpClient()); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('should call import new taxonomy', async () => { | ||
axiosMock.onPost(getTaxonomyImportNewApiUrl()).reply(201, taxonomyImportMock); | ||
const result = await importNewTaxonomy('Taxonomy name', 'Taxonomy description'); | ||
|
||
expect(axiosMock.history.post[0].url).toEqual(getTaxonomyImportNewApiUrl()); | ||
expect(result).toEqual(taxonomyImportMock); | ||
}); | ||
|
||
it('should call import tags', async () => { | ||
axiosMock.onPut(getTagsImportApiUrl(1)).reply(200, tagImportMock); | ||
const result = await importTags(1); | ||
|
||
expect(axiosMock.history.put[0].url).toEqual(getTagsImportApiUrl(1)); | ||
expect(result).toEqual(tagImportMock); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// ts-check | ||
import messages from '../messages'; | ||
import { importNewTaxonomy, importTags } from './api'; | ||
|
||
/* | ||
* This function get a file from the user. It does this by creating a | ||
* file input element, and then clicking it. This allows us to get a file | ||
* from the user without using a form. The file input element is created | ||
* and appended to the DOM, then clicked. When the user selects a file, | ||
* the change event is fired, and the file is resolved. | ||
* The file input element is then removed from the DOM. | ||
*/ | ||
const selectFile = async () => new Promise((resolve) => { | ||
const fileInput = document.createElement('input'); | ||
fileInput.type = 'file'; | ||
fileInput.accept = '.json,.csv'; | ||
fileInput.style.display = 'none'; | ||
fileInput.addEventListener('change', (event) => { | ||
const file = event.target.files[0]; | ||
if (!file) { | ||
resolve(null); | ||
} | ||
resolve(file); | ||
document.body.removeChild(fileInput); | ||
}, false); | ||
|
||
fileInput.addEventListener('cancel', () => { | ||
resolve(null); | ||
document.body.removeChild(fileInput); | ||
}, false); | ||
|
||
document.body.appendChild(fileInput); | ||
|
||
// Calling click() directly was not working as expected, so we use setTimeout | ||
// to ensure the file input is added to the DOM before clicking it. | ||
setTimeout(() => fileInput.click(), 0); | ||
}); | ||
|
||
export const importTaxonomy = async (intl) => { | ||
/* | ||
* This function is a temporary "Barebones" implementation of the import | ||
* functionality with `prompt` and `alert`. It is intended to be replaced | ||
* with a component that shows a `ModalDialog` in the future. | ||
* See: https://github.com/openedx/modular-learning/issues/116 | ||
*/ | ||
/* eslint-disable no-alert */ | ||
/* eslint-disable no-console */ | ||
|
||
const getTaxonomyName = () => { | ||
let taxonomyName = null; | ||
while (!taxonomyName) { | ||
taxonomyName = prompt(intl.formatMessage(messages.promptTaxonomyName)); | ||
|
||
if (taxonomyName == null) { | ||
break; | ||
} | ||
|
||
if (!taxonomyName) { | ||
alert(intl.formatMessage(messages.promptTaxonomyNameRequired)); | ||
} | ||
} | ||
return taxonomyName; | ||
}; | ||
|
||
const getTaxonomyDescription = () => prompt(intl.formatMessage(messages.promptTaxonomyDescription)); | ||
|
||
const file = await selectFile(); | ||
|
||
if (!file) { | ||
return; | ||
} | ||
|
||
const taxonomyName = getTaxonomyName(); | ||
if (taxonomyName == null) { | ||
return; | ||
} | ||
|
||
const taxonomyDescription = getTaxonomyDescription(); | ||
if (taxonomyDescription == null) { | ||
return; | ||
} | ||
|
||
importNewTaxonomy(taxonomyName, taxonomyDescription, file) | ||
.then(() => { | ||
alert(intl.formatMessage(messages.importTaxonomySuccess)); | ||
}) | ||
.catch((error) => { | ||
alert(intl.formatMessage(messages.importTaxonomyError)); | ||
console.error(error.response); | ||
}); | ||
}; | ||
|
||
export const importTaxonomyTags = async (taxonomyId, intl) => { | ||
/* | ||
* This function is a temporary "Barebones" implementation of the import | ||
* functionality with `confirm` and `alert`. It is intended to be replaced | ||
* with a component that shows a `ModalDialog` in the future. | ||
* See: https://github.com/openedx/modular-learning/issues/126 | ||
*/ | ||
/* eslint-disable no-alert */ | ||
/* eslint-disable no-console */ | ||
console.log(intl); | ||
const file = await selectFile(); | ||
|
||
if (!file) { | ||
return; | ||
} | ||
|
||
if (!window.confirm(intl.formatMessage(messages.confirmImportTags))) { | ||
return; | ||
} | ||
|
||
importTags(taxonomyId, file) | ||
.then(() => { | ||
alert(intl.formatMessage(messages.importTaxonomySuccess)); | ||
}) | ||
.catch((error) => { | ||
alert(intl.formatMessage(messages.importTaxonomyError)); | ||
console.error(error.response); | ||
}); | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: remove debugging statements