Skip to content
This repository has been archived by the owner on Jan 28, 2020. It is now read-only.

Commit

Permalink
Added delete term functionality in taxonomy panel
Browse files Browse the repository at this point in the history
  • Loading branch information
amir-qayyum-khan authored and George Schneeloch committed Oct 6, 2015
1 parent 455e427 commit a9b9021
Show file tree
Hide file tree
Showing 3 changed files with 276 additions and 8 deletions.
13 changes: 13 additions & 0 deletions rest/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
)
from rest.util import CheckValidMemberParamMixin
from search.api import construct_queryset
from search.utils import index_resources
from taxonomy.models import Vocabulary
from learningresources.models import (
Repository,
Expand Down Expand Up @@ -295,6 +296,18 @@ def get_queryset(self):
slug=self.kwargs['term_slug']
)

def delete(self, request, *args, **kwargs):
"""
Override delete to also update index for deleted term.
"""
term = self.get_object()
resources = list(LearningResource.objects.filter(
terms__id=term.id
))
ret = super(TermDetail, self).delete(request, *args, **kwargs)
index_resources(resources)
return ret


class RepoMemberList(ListAPIView):
"""
Expand Down
208 changes: 206 additions & 2 deletions ui/jstests/test_manage_taxonomies.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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(
<TermComponent
term={term}
repoSlug="repo"
renderConfirmationDialog={renderConfirmationDialog}
deleteTerm={deleteTerm}
vocabulary={vocabulary}
refreshFromAPI={refreshFromAPI}
ref={afterMount}
/>
);
}
);

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(
<TermComponent
term={term}
repoSlug="repo"
renderConfirmationDialog={renderConfirmationDialog}
deleteTerm={deleteTerm}
vocabulary={vocabulary}
refreshFromAPI={refreshFromAPI}
ref={afterMount}
/>
);
}
);

QUnit.test('Assert that VocabularyComponent renders properly',
function(assert) {
assert.ok(VocabularyComponent, "class object not found");
Expand Down Expand Up @@ -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
(
<TaxonomyComponent
repoSlug="repo"
refreshFromAPI={refreshFromAPI}
renderConfirmationDialog={renderConfirmationDialog}
ref={afterMount}
/>
);
}
);

QUnit.test("Test that ManageTaxonomies.loader renders into div",
function(assert) {
var container = document.createElement("div");
Expand Down
63 changes: 57 additions & 6 deletions ui/static/ui/js/manage_taxonomies.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ define('manage_taxonomies', ['react', 'lodash', 'jquery', 'uri',
<span className="utility-features">
<a href="#" onClick={this.editTerm} className={editButtonClass}>
<i className={formatActionClassName}></i>
</a> <a href="#" className={deleteButtonClass}>
</a> <a className={deleteButtonClass} href="#"
onClick={this.deleteTerm}>
<i className="fa fa-remove"></i>
</a>
</span>{label}</li>;
Expand Down Expand Up @@ -78,11 +79,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
Expand Down Expand Up @@ -120,6 +131,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();
});
}
}
});

Expand All @@ -129,11 +160,13 @@ define('manage_taxonomies', ['react', 'lodash', 'jquery', 'uri',
var thiz = this;
var items = _.map(this.props.terms, function (term) {
return <TermComponent
deleteTerm={thiz.props.deleteTerm}
updateTerm={thiz.props.updateTerm}
vocabulary={thiz.props.vocabulary}
repoSlug={thiz.props.repoSlug}
term={term}
key={term.id}
renderConfirmationDialog={thiz.props.renderConfirmationDialog}
refreshFromAPI={thiz.props.refreshFromAPI}
/>;
});
Expand Down Expand Up @@ -270,6 +303,7 @@ define('manage_taxonomies', ['react', 'lodash', 'jquery', 'uri',
var thiz = this;
var items = _.map(this.props.vocabularies, function (obj) {
return <VocabularyComponent
deleteTerm={thiz.props.deleteTerm}
updateTerm={thiz.props.updateTerm}
vocabulary={obj.vocabulary}
deleteVocabulary={thiz.props.deleteVocabulary}
Expand Down Expand Up @@ -678,6 +712,22 @@ define('manage_taxonomies', ['react', 'lodash', 'jquery', 'uri',
});
this.setState({vocabularies: vocabularies});
},
deleteTerm: function(vocabId, term) {
var vocabularies = _.map(this.state.vocabularies, function(tuple) {
if (tuple.vocabulary.id === vocabId) {
var terms = _.filter(tuple.terms, function (tupleTerm) {
return tupleTerm.id !== term.id;
});
return {
terms: terms,
vocabulary: tuple.vocabulary
};
} else {
return tuple;
}
});
this.setState({vocabularies: vocabularies});
},
render: function() {
var editVocabulary;
var thiz = this;
Expand Down Expand Up @@ -705,6 +755,7 @@ define('manage_taxonomies', ['react', 'lodash', 'jquery', 'uri',
<div className="tab-content drawer-tab-content">
<div className="tab-pane active" id="tab-taxonomies">
<AddTermsComponent
deleteTerm={this.deleteTerm}
updateTerm={this.updateTerm}
editVocabulary={this.editVocabulary}
vocabularies={this.state.vocabularies}
Expand Down

0 comments on commit a9b9021

Please sign in to comment.