From 2bc989548023efc44c4e15cc061fe1e8354ecc6e Mon Sep 17 00:00:00 2001 From: Amir Qayyum Khan Date: Mon, 14 Sep 2015 15:01:17 +0500 Subject: [PATCH] Added delete term functionality in taxonomy panel --- ui/jstests/test_manage_taxonomies.jsx | 208 +++++++++++++++++++++++++- ui/static/ui/js/manage_taxonomies.jsx | 62 +++++++- ui/views.py | 4 +- 3 files changed, 265 insertions(+), 9 deletions(-) diff --git a/ui/jstests/test_manage_taxonomies.jsx b/ui/jstests/test_manage_taxonomies.jsx index c4bf6fcf..b073f33f 100644 --- a/ui/jstests/test_manage_taxonomies.jsx +++ b/ui/jstests/test_manage_taxonomies.jsx @@ -181,7 +181,7 @@ define(['QUnit', 'jquery', 'lodash', 'manage_taxonomies', 'react', } }); - QUnit.test('Assert that TermComponent renders properly', + QUnit.test('Assert that edit TermComponent renders properly', function(assert) { assert.ok(TermComponent, "class object not found"); var done = assert.async(); @@ -475,7 +475,9 @@ define(['QUnit', 'jquery', 'lodash', 'manage_taxonomies', 'react', ); component.forceUpdate(function() { assert.equal(component.state.label, "TestB"); - + assert.equal(component.state.formatActionState, 'edit'); + assert.equal(parentUpdateCount, 0); + // listing page was not asked to refresh assert.equal(refreshCount, 0); React.addons.TestUtils.Simulate.click(saveButton); component.forceUpdate(function() { @@ -534,6 +536,137 @@ define(['QUnit', 'jquery', 'lodash', 'manage_taxonomies', 'react', } ); + QUnit.test('Assert that delete TermComponent renders properly', + function(assert) { + assert.ok(TermComponent, "class object not found"); + var done = assert.async(); + var term = { + "id": 9, + "slug": "test", + "label": "test", + "weight": 1 + }; + var parentUpdateCount = 0; + var deleteTerm = function() { + parentUpdateCount += 1; + }; + var renderConfirmationDialog = function(options) { + options.confirmationHandler(true); + }; + + TestUtils.initMockjax({ + url: "/api/v1/repositories/repo/vocabularies/difficulty/terms/test/", + type: "DELETE" + }); + + var refreshCount = 0; + var refreshFromAPI = function() { + refreshCount++; + }; + + var afterMount = function(component) { + var deleteButton = React.addons.TestUtils. + findRenderedDOMComponentWithClass( + component, + 'revert-button' + ); + //select delete + React.addons.TestUtils.Simulate.click(deleteButton); + component.forceUpdate(function() { + assert.equal(component.state.formatActionState, 'show'); + waitForAjax(1, function() { + // term is delete in parent + assert.equal(parentUpdateCount, 1); + // listing was asked to refresh + assert.equal(refreshCount, 1); + done(); + }); + }); + }; + + React.addons.TestUtils. + renderIntoDocument( + + ); + } + ); + + QUnit.test('Assert that delete ajax call fail TermComponent' + + ' renders properly', + function(assert) { + assert.ok(TermComponent, "class object not found"); + var done = assert.async(); + var term = { + "id": 9, + "slug": "test", + "label": "test", + "weight": 1 + }; + var parentUpdateCount = 0; + var deleteTerm = function() { + parentUpdateCount += 1; + }; + var renderConfirmationDialog = function(options) { + options.confirmationHandler(true); + }; + + TestUtils.initMockjax({ + url: "/api/v1/repositories/repo/vocabularies/difficulty/terms/test/", + type: "DELETE", + status: 400 + }); + + var refreshCount = 0; + var refreshFromAPI = function() { + refreshCount++; + }; + + var afterMount = function(component) { + var deleteButton = React.addons.TestUtils. + findRenderedDOMComponentWithClass( + component, + 'revert-button' + ); + //select delete + React.addons.TestUtils.Simulate.click(deleteButton); + component.forceUpdate(function() { + assert.equal( + component.state.errorMessage, '' + ); + assert.equal(component.state.formatActionState, 'show'); + waitForAjax(1, function() { + // check state of error message + assert.equal( + component.state.errorMessage, 'Unable to delete term.' + ); + done(); + }); + }); + }; + + React.addons.TestUtils. + renderIntoDocument( + + ); + } + ); + QUnit.test('Assert that VocabularyComponent renders properly', function(assert) { assert.ok(VocabularyComponent, "class object not found"); @@ -2358,6 +2491,77 @@ define(['QUnit', 'jquery', 'lodash', 'manage_taxonomies', 'react', } ); + QUnit.test('Assert that delete term works in TaxonomyComponent', + function(assert) { + assert.ok(TaxonomyComponent, "class object not found"); + var done = assert.async(); + var refreshCount = 0; + var refreshFromAPI = function() { + refreshCount++; + }; + + var renderConfirmationDialog = function(options) { + options.confirmationHandler(true); + }; + + var afterMount = function(component) { + assert.equal( + component.state.vocabularies.length, + 0 + ); + waitForAjax(2, function() { + assert.equal( + component.state.vocabularies.length, + 1 + ); + assert.equal( + component.state.vocabularies[0].terms.length, + 2 + ); + var updateTermUrl = "/api/v1/repositories/repo/vocabularies/" + + component.state.vocabularies[0].vocabulary.slug + "/terms/" + + component.state.vocabularies[0].terms[0].slug + "/"; + TestUtils.initMockjax({ + url: updateTermUrl, + type: "DELETE" + }); + var deleteButtons = React.addons.TestUtils. + scryRenderedDOMComponentsWithClass( + component, + 'revert-button' + ); + var deleteButton = deleteButtons[0]; + //open edit mode + React.addons.TestUtils.Simulate.click(deleteButton); + component.forceUpdate(function() { + waitForAjax(1, function () { + assert.equal(refreshCount, 1); + //assert term update + assert.equal( + component.state.vocabularies.length, + 1 + ); + assert.equal( + component.state.vocabularies[0].terms.length, + 1 + ); + done(); + }); + }); + }); + }; + React.addons.TestUtils.renderIntoDocument + ( + + ); + } + ); + QUnit.test("Test that ManageTaxonomies.loader renders into div", function(assert) { var container = document.createElement("div"); diff --git a/ui/static/ui/js/manage_taxonomies.jsx b/ui/static/ui/js/manage_taxonomies.jsx index 6518945f..26fe8b14 100644 --- a/ui/static/ui/js/manage_taxonomies.jsx +++ b/ui/static/ui/js/manage_taxonomies.jsx @@ -49,7 +49,7 @@ define('manage_taxonomies', ['react', 'lodash', 'jquery', 'uri', - + {label}; @@ -78,11 +78,21 @@ define('manage_taxonomies', ['react', 'lodash', 'jquery', 'uri', * On Close button select reset term UI */ cancelAction : function() { - var formatActionState = this.state.formatActionState; - if (formatActionState === 'edit') { - // user is in edit mode. Cancel edit if user presses cross icon. - this.resetUtilityFeatures(); - } + // user is in edit mode. Cancel edit if user presses cross icon. + this.resetUtilityFeatures(); + }, + deleteTerm: function() { + var options = { + actionButtonName: "Delete", + actionButtonClass: "btn btn-danger btn-ok", + title: "Confirm Delete", + message: "Are you sure you want to delete term '" + + this.props.term.label + "'?", + description: "Deleting this term will remove it from all " + + "learning resources.", + confirmationHandler: this.confirmedDeleteResponse + }; + this.props.renderConfirmationDialog(options); }, /** * Reset term edit UI @@ -120,6 +130,26 @@ define('manage_taxonomies', ['react', 'lodash', 'jquery', 'uri', thiz.props.updateTerm(thiz.props.vocabulary.id, term); thiz.props.refreshFromAPI(); }); + }, + confirmedDeleteResponse: function(success) { + var thiz = this; + if (success) { + var API_ROOT_VOCAB_URL = '/api/v1/repositories/' + this.props.repoSlug + + '/vocabularies/' + this.props.vocabulary.slug + '/terms/' + + this.props.term.slug + "/"; + $.ajax({ + type: 'DELETE', + url: API_ROOT_VOCAB_URL, + contentType: "application/json" + }).fail(function() { + thiz.setState({ + errorMessage: 'Unable to delete term.' + }); + }).done(function() { + thiz.props.deleteTerm(thiz.props.vocabulary.id, thiz.props.term); + thiz.props.refreshFromAPI(); + }); + } } }); @@ -129,11 +159,13 @@ define('manage_taxonomies', ['react', 'lodash', 'jquery', 'uri', var thiz = this; var items = _.map(this.props.terms, function (term) { return ; }); @@ -270,6 +302,7 @@ define('manage_taxonomies', ['react', 'lodash', 'jquery', 'uri', var thiz = this; var items = _.map(this.props.vocabularies, function (obj) { return