Skip to content

Commit 654ff61

Browse files
authored
Stop separatings tags by language (#438)
2 parents 4f861f9 + 6ff2d71 commit 654ff61

File tree

26 files changed

+97
-345
lines changed

26 files changed

+97
-345
lines changed

app/controllers/api/v1/tags_controller.rb

Lines changed: 0 additions & 32 deletions
This file was deleted.

app/controllers/topics/tags_controller.rb

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 13 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,29 @@
1-
import { Controller } from "@hotwired/stimulus"
2-
import { get } from "@rails/request.js"
3-
import Tags from "bootstrap5-tags"
1+
import { Controller } from "@hotwired/stimulus";
2+
import { get } from "@rails/request.js";
3+
import Tags from "bootstrap5-tags";
44

55
export default class extends Controller {
6-
static targets = ["language", "tagList"]
6+
static targets = ["tagList"];
77

88
connect() {
9-
this.initializeTags()
10-
this.changeLanguage();
9+
this.initializeTags();
1110
}
1211

1312
notify() {
14-
this.dispatch("notify", { detail: { content: Array.from(this.tagListTarget.selectedOptions).map(option => option.value) } })
15-
}
16-
17-
/**
18-
* Handle language change event and update tags accordingly
19-
* @param {Event} event - Change event
20-
*/
21-
async changeLanguage(_event) {
22-
try {
23-
const { resourceId, languageId } = this.getIds()
24-
25-
const tags = await this.fetchTags(languageId)
26-
const selectedTags = await this.fetchAssignedTags(languageId, resourceId)
27-
28-
this.presentTags(tags, selectedTags)
29-
} catch (error) {
30-
console.error("Error changing language:", error)
31-
}
32-
}
33-
34-
/**
35-
* Extract resource and language IDs from the form
36-
* @returns {Object} Object containing resourceId and languageId
37-
*/
38-
getIds() {
39-
return {
40-
resourceId: this.languageTarget.dataset.resourceId,
41-
languageId: this.languageTarget.value
42-
}
43-
}
44-
45-
/**
46-
* Fetch available tags for a given language
47-
* @param {string} languageId - ID of the selected language
48-
* @returns {Object} Dictionary of tag names
49-
*/
50-
async fetchTags(languageId) {
51-
try {
52-
const response = await get(`/api/v1/tags?language_id=${languageId}`, {
53-
responseKind: "json"
54-
})
55-
56-
if (!response.ok) return []
57-
58-
const json = await response.json
59-
return Object.fromEntries(json.map(({name}) => [name, name]))
60-
} catch (error) {
61-
console.error("Error fetching tags:", error)
62-
return []
63-
}
64-
}
65-
66-
/**
67-
* Fetch tags already assigned to the resource
68-
* @param {string} languageId - ID of the selected language
69-
* @param {string} resourceId - ID of the current resource
70-
* @returns {string} Comma-separated list of tag names
71-
*/
72-
async fetchAssignedTags(languageId, resourceId) {
73-
if (resourceId === undefined) return ""
74-
75-
try {
76-
const response = await get(`/topics/${resourceId}/tags?language_id=${languageId}`, {
77-
responseKind: "json"
78-
})
79-
80-
if (!response.ok) return ""
81-
82-
const json = await response.json
83-
return json.map(x => x.name).join()
84-
} catch (error) {
85-
console.error("Error fetching assigned tags:", error)
86-
return ""
87-
}
88-
}
89-
90-
/**
91-
* Update the tags input with new tags and selections
92-
* @param {Object} tags - Available tags
93-
* @param {string} selectedTags - Previously selected tags
94-
*/
95-
presentTags(tags, selectedTags) {
96-
this.initializeTags({
97-
items: tags,
98-
selected: selectedTags
99-
}, true)
13+
this.dispatch("notify", {
14+
detail: {
15+
content: Array.from(this.tagListTarget.selectedOptions).map(
16+
(option) => option.value
17+
),
18+
},
19+
});
10020
}
10121

10222
/**
10323
* Initialize the tags input with given options
10424
* @param {Object} options - Configuration options for bootstrap5-tags
10525
*/
10626
initializeTags(options = {}, reset = false) {
107-
Tags.init(`select#${this.tagListTarget.id}`, options, reset)
27+
Tags.init(`select#${this.tagListTarget.id}`, options, reset);
10828
}
10929
}

app/jobs/synchronize_cognates_on_topics_job.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
class SynchronizeCognatesOnTopicsJob < ApplicationJob
22
def perform(tag)
33
Topic.where(id: tag.taggings.select(:taggable_id)).each do |topic|
4-
tags = topic.current_tags_list << tag.cognates_tags.for_context(topic.language_code).uniq.pluck(:name)
5-
topic.set_tag_list_on(topic.language_code, tags)
4+
tags = topic.tag_list << tag.cognates_tags.uniq.pluck(:name)
5+
topic.tag_list.add(tags)
66
topic.save
77
end
88
end

app/models/concerns/taggable.rb

Lines changed: 13 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -13,61 +13,6 @@ class LanguageContextError < StandardError; end
1313
end
1414
end
1515

16-
# Returns the language-specific tag context based on code
17-
#
18-
# @return [Symbol] the language context for tagging
19-
# @raise [LanguageContextError] if language or code is not present
20-
def language_tag_context
21-
return nil if new_record?
22-
23-
raise LanguageContextError, "Language must be present" if language.nil?
24-
raise LanguageContextError, "Language code must be present" if language.code.blank?
25-
26-
language_code
27-
end
28-
29-
# Retrieves all available tags for the current language context
30-
#
31-
# @return [ActiveRecord::Relation] collection of ActsAsTaggableOn::Tag
32-
def available_tags
33-
return [] if language_tag_context.nil?
34-
35-
ActsAsTaggableOn::Tag.for_context(language_tag_context)&.order(name: :asc)
36-
end
37-
38-
# Retrieves associated tags for the current language context
39-
#
40-
# @return [Array<Tag>] list of tags
41-
def current_tags
42-
return [] if language_tag_context.nil?
43-
44-
tags_on(language_tag_context)
45-
end
46-
47-
# Retrieves associated tags for the current language context
48-
#
49-
# @return [Array<String>] list of tag names
50-
def current_tags_list
51-
return [] if language_tag_context.nil?
52-
53-
tag_list_on(language_tag_context)
54-
end
55-
56-
# Retrieves associated tags for a specific language
57-
# @param language_id [Integer] the ID of the language
58-
# @return [ActiveRecord::Relation] collection of ActsAsTaggableOn::Tag
59-
def current_tags_for_language(language_id)
60-
return [] if language_id.nil?
61-
62-
language = Language.find(language_id)
63-
64-
tags_on(language.code.to_sym)
65-
end
66-
67-
def language_code
68-
language.code.to_sym
69-
end
70-
7116
# Updates the list of tags for a specific record
7217
# @param attrs [Array<String>] the list of tags
7318
# @return [Boolean] true if tags are processed successfully, false otherwise
@@ -86,22 +31,25 @@ def save_with_tags(attrs)
8631

8732
private
8833

89-
def process_tags(tag_list)
90-
return unless tag_list.present?
34+
def process_tags(tag_names)
35+
return unless tag_names.present?
36+
37+
Rails.logger.info "Processing tags: #{tag_names} for record: #{id}"
38+
removed_tags = tag_list - tag_names
39+
@full_list_of_tags = tag_names + removed_tags
40+
removed_tags_with_cognates = tags_with_cognates(removed_tags)
41+
tag_names_without_redundant_cognates = tag_names - removed_tags_with_cognates
42+
tag_names_with_cognates_to_add = tag_names_without_redundant_cognates + tags_with_cognates(tag_names_without_redundant_cognates)
43+
final_tag_names = tag_names_with_cognates_to_add.uniq.compact_blank
9144

92-
Rails.logger.info "Processing tags: #{tag_list} for record: #{id}"
93-
removed_tags = current_tags_list - tag_list
94-
@full_list_of_tags = tag_list + removed_tags
95-
tag_list_without_redundant_cognates = tag_list - tags_with_cognates(removed_tags)
96-
tag_list_with_cognates_to_add = tag_list_without_redundant_cognates + tags_with_cognates(tag_list_without_redundant_cognates)
97-
final_tag_list = tag_list_with_cognates_to_add.uniq.compact_blank.join(",")
98-
set_tag_list_on(language_code, final_tag_list)
45+
self.tag_list = final_tag_names
9946
save!
47+
taggings.where(tag_id: Tag.where(name: removed_tags_with_cognates)).destroy_all
10048
end
10149

10250
def cognates_names_for(tags_to_keep_add_or_remove)
10351
Tag.where(name: tags_to_keep_add_or_remove).each_with_object({}) do |tag, hash|
104-
hash[tag.name] = tag.cognates_tags.for_context(language_code).uniq.pluck(:name).push(tag.name)
52+
hash[tag.name] = tag.cognates_tags.uniq.pluck(:name).push(tag.name)
10553
end
10654
end
10755

app/services/text_generator/tags.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def initialize(language, **args)
1010

1111
def text_content
1212
scope
13-
.flat_map { |topic| topic.current_tags_list }
13+
.flat_map { |topic| topic.tag_list }
1414
.uniq
1515
.sort
1616
.join("\n")

app/services/text_generator/title_and_tags.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def initialize(language, **args)
1111
def text_content
1212
scope
1313
.flat_map do |topic|
14-
[ topic.title ] + topic.current_tags_list
14+
[ topic.title ] + topic.tag_list
1515
end
1616
.join("\n")
1717
end

app/views/topics/_form.html.erb

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,15 @@
1717
<%= f.collection_select :provider_id, Provider.all, :id, :name, { prompt: "Select Provider" }, class: "form-select" %>
1818
</div>
1919
<% end %>
20-
<div data-controller="select-tags">
20+
<div>
2121
<div class="form-group">
2222
<%= f.label :language %>
2323
<%= f.collection_select :language_id,
2424
Language.all,
2525
:id,
2626
:name,
2727
{ prompt: "Select language", selected: topic.language&.id || Language.first.id },
28-
class: "form-select",
29-
data: { "resource-type": "topics", "resource-id": f.object.id, "select-tags-target": "language", "action": "change->select-tags#changeLanguage" }
28+
class: "form-select"
3029
%>
3130
</div>
3231
<div class="form-group">
@@ -37,23 +36,23 @@
3736
<%= f.label :publishing_month %>
3837
<%= f.select :published_at_month, options_for_select((1..12).to_a, topic.published_at_month || Date.today.month), { prompt: "Select month of publishing" }, class: "form-select" %>
3938
</div>
40-
<div class="form-group">
39+
<div class="form-group" data-controller="select-tags">
4140
<div class="d-flex">
4241
<%= f.label :tag_list, class: "flex-fill" %>
4342
<small class="flex-fill text-end fw-light text-muted text-uppercase">Press enter to add a new tag</small>
4443
</div>
4544
<p>Please note: For any tag you add or remove, its cognates are also added or removed.</p>
4645
<%= f.select :tag_list,
4746
options_from_collection_for_select(
48-
topic.available_tags,
47+
ActsAsTaggableOn::Tag.all&.order(name: :asc),
4948
:name,
5049
:name,
51-
topic.current_tags_list
50+
topic.tag_list
5251
),
5352
{ prompt: "Select tags", include_blank: true },
5453
multiple: true,
5554
class: "form-select",
56-
data: { "allow-new": "true", "allow-clear": "true", "select-tags-target": "tagList" }
55+
data: { "allow-new": "true", "allow-clear": "true", "select-tags-target": "tagList", "resource-type": "topics", "resource-id": f.object.id }
5756
%>
5857
</div>
5958
</div>

app/views/topics/_topic.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
</div>
3232
<div class="card-footer">
3333
<strong>Tags:</strong>
34-
<% topic.current_tags.each do |tag| %>
34+
<% topic.tags.each do |tag| %>
3535
<%= link_to tag.name, tag_path(tag), class: "badge bg-success text-decoration-none me-1", target: "_blank" %>
3636
<% end %>
3737
</div>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class ChangeContextForTags < ActiveRecord::Migration[8.0]
2+
def up
3+
execute "UPDATE taggings SET context = 'tags'"
4+
end
5+
6+
def down
7+
end
8+
end

0 commit comments

Comments
 (0)