diff --git a/concordia/static/js/action-app/index.js b/concordia/static/js/action-app/index.js index 7358a0d90..88ebf9061 100644 --- a/concordia/static/js/action-app/index.js +++ b/concordia/static/js/action-app/index.js @@ -107,6 +107,11 @@ export class ActionApp { addToState(key, value) { this.persistentState.set(key, value); + if (key == 'campaign') { + this.persistentState.delete('topic'); + } else if (key == 'topic') { + this.persistentState.delete('campaign'); + } this.serializeStateToURL(); } @@ -424,6 +429,9 @@ export class ActionApp { this.campaignSelect = $('#selected-campaign'); fetchJSON(this.config.urls.campaignList) .then(data => { + let campaignOptGroup = document.createElement('optgroup'); + campaignOptGroup.label = 'Campaigns'; + this.campaignSelect.appendChild(campaignOptGroup); data.objects.forEach(campaign => { let o = document.createElement('option'); o.value = campaign.id; @@ -436,7 +444,7 @@ export class ActionApp { } ); - this.campaignSelect.appendChild(o); + campaignOptGroup.appendChild(o); }); }) .then(() => { @@ -448,12 +456,18 @@ export class ActionApp { }); this.campaignSelect.addEventListener('change', () => { - this.addToState('campaign', this.campaignSelect.value); + let campaignOrTopic = this.getSelectedOptionType(); + this.addToState(campaignOrTopic, this.campaignSelect.value); this.updateAssetList(); }); fetchJSON(this.config.urls.topicList) .then(data => { + let topicOptGroup = document.createElement('optgroup'); + topicOptGroup.label = 'Topics'; + topicOptGroup.classList.add('topic-optgroup'); + this.campaignSelect.appendChild(topicOptGroup); + data.objects.forEach(topic => { let o = document.createElement('option'); o.value = topic.id; @@ -466,7 +480,7 @@ export class ActionApp { } ); - this.campaignSelect.appendChild(o); + topicOptGroup.appendChild(o); }); }) .then(() => { @@ -792,6 +806,29 @@ export class ActionApp { return sortBy(assetList, keyFromAsset); } + getSelectedOptionType() { + let campaignOrTopic = 'campaign'; + + if ( + this.campaignSelect.options[ + this.campaignSelect.selectedIndex + ].parentElement.classList.contains('topic-optgroup') + ) { + campaignOrTopic = 'topic'; + } + + return campaignOrTopic; + } + + assetHasTopic(asset, topicId) { + for (let idx in asset.topics) { + if (asset.topics[idx].id === topicId) { + return true; + } + } + return false; + } + getVisibleAssets() { // We allow passing a list of asset IDs which should always be included // to avoid jarring UI transitions (the display code is responsible for @@ -807,10 +844,22 @@ export class ActionApp { alwaysIncludedAssetIDs.add(this.persistentState.get('asset')); } - let currentCampaignId = this.campaignSelect.value; - if (currentCampaignId) { + let currentCampaignSelectValue = this.campaignSelect.value; + let currentCampaignId; + let currentTopicId; + if (currentCampaignSelectValue) { + let campaignOrTopic = this.getSelectedOptionType(); + currentCampaignSelectValue = parseInt( + currentCampaignSelectValue, + 10 + ); + // The values specified in API responses are integers, not DOM strings: - currentCampaignId = parseInt(currentCampaignId, 10); + if (campaignOrTopic == 'campaign') { + currentCampaignId = currentCampaignSelectValue; + } else { + currentTopicId = currentCampaignSelectValue; + } } let currentStatuses; @@ -839,6 +888,13 @@ export class ActionApp { continue; } + if ( + currentTopicId && + !this.assetHasTopic(asset, currentTopicId) + ) { + continue; + } + if (!currentStatuses.includes(asset.status)) { continue; } diff --git a/concordia/views.py b/concordia/views.py index a5da34169..6e4514ef5 100644 --- a/concordia/views.py +++ b/concordia/views.py @@ -1717,6 +1717,16 @@ def serialize_object(self, obj): }, } + if project.topics: + metadata["topics"] = [] + + for topic in project.topics.all(): + new_topic = {} + new_topic["id"] = topic.pk + new_topic["title"] = topic.title + new_topic["url"] = topic.get_absolute_url() + metadata["topics"].append(new_topic) + # FIXME: we want to rework how this is done after deprecating Asset.media_url if obj.previous_sequence: metadata["previous_thumbnail"] = re.sub(