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 committed Oct 1, 2015
1 parent 82a988b commit 2bc9895
Show file tree
Hide file tree
Showing 3 changed files with 265 additions and 9 deletions.
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
62 changes: 56 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,7 @@ 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} onClick={this.deleteTerm}>
<i className="fa fa-remove"></i>
</a>
</span>{label}</li>;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
});
}
}
});

Expand All @@ -129,11 +159,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 +302,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 +711,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 +754,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
4 changes: 3 additions & 1 deletion ui/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,9 @@ def get_vocabularies(facets):
vocab = (vocabulary_id, vocabs[int(vocabulary_id)])
vocabularies[vocab] = []
for t_id, count in term_data:
vocabularies[vocab].append((t_id, terms[int(t_id)], count))
t_id_int = int(t_id)
if t_id_int in terms:
vocabularies[vocab].append((t_id, terms[t_id_int], count))
# By default, sort alphabetically.
vocabularies[vocab].sort(key=lambda x: x[1])
return vocabularies
Expand Down

0 comments on commit 2bc9895

Please sign in to comment.