diff --git a/config/routes.rb b/config/routes.rb
index 8d16a16..eae9be4 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -66,6 +66,10 @@ module Adamantium
post "/tags/auto_tagging", to: "auto_tagging.create"
delete "/tags/auto_taggings/:id", to: "auto_tagging.delete"
+ get "/tags/merge", to: "merge_tags.index"
+ get "/tags/merge/:id", to: "merge_tags.new"
+ post "/tags/merge", to: "merge_tags.merge"
+
get "/bookmarks", to: "bookmarks.index"
delete "/bookmarks/:id", to: "bookmarks.delete"
post "/bookmarks/cache/:id", to: "bookmarks.cache"
diff --git a/slices/admin/actions/merge_tags/index.rb b/slices/admin/actions/merge_tags/index.rb
new file mode 100644
index 0000000..7f0b014
--- /dev/null
+++ b/slices/admin/actions/merge_tags/index.rb
@@ -0,0 +1,14 @@
+module Admin
+ module Actions
+ module MergeTags
+ class Index < Action
+
+ include Deps["views.merge_tags.index"]
+
+ def handle(req, res)
+ res.render index
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/slices/admin/actions/merge_tags/merge.rb b/slices/admin/actions/merge_tags/merge.rb
new file mode 100644
index 0000000..3549724
--- /dev/null
+++ b/slices/admin/actions/merge_tags/merge.rb
@@ -0,0 +1,24 @@
+module Admin
+ module Actions
+ module MergeTags
+ class Merge < Action
+
+ include Deps["commands.merge_tags.merge"]
+
+ def handle(req, res)
+ target_id = req.params[:target_id]
+ source_id = req.params[:source_id]
+
+ result = merge.(target_id: target_id, source_id: source_id)
+
+ if result.success?
+ res.redirect_to "/admin/tags/merge"
+ res.status 200
+ else
+ res.status 500
+ end
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/slices/admin/actions/merge_tags/new.rb b/slices/admin/actions/merge_tags/new.rb
new file mode 100644
index 0000000..5e0bcdc
--- /dev/null
+++ b/slices/admin/actions/merge_tags/new.rb
@@ -0,0 +1,14 @@
+module Admin
+ module Actions
+ module MergeTags
+ class New < Action
+
+ include Deps[new_view: "views.merge_tags.new"]
+
+ def handle(req, res)
+ res.render new_view, id: req.params[:id]
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/slices/admin/commands/merge_tags/merge.rb b/slices/admin/commands/merge_tags/merge.rb
new file mode 100644
index 0000000..b3afcb5
--- /dev/null
+++ b/slices/admin/commands/merge_tags/merge.rb
@@ -0,0 +1,17 @@
+module Admin
+ module Commands
+ module MergeTags
+ class Merge
+ include Dry::Monads[:result]
+ include Deps["repos.post_tag_repo", "repos.tag_repo"]
+
+ def call(target_id:, source_id:)
+ post_tag_repo.merge_tags(target_id: target_id, source_id: source_id)
+ tag_repo.delete(tag_id: source_id)
+
+ Success()
+ end
+ end
+ end
+ end
+end
diff --git a/slices/admin/repos/post_tag_repo.rb b/slices/admin/repos/post_tag_repo.rb
index 39f687d..1432a56 100644
--- a/slices/admin/repos/post_tag_repo.rb
+++ b/slices/admin/repos/post_tag_repo.rb
@@ -1,7 +1,13 @@
+require 'pry'
+
module Admin
module Repos
class PostTagRepo < Adamantium::Repo[:post_tags]
+ def merge_tags(target_id:, source_id:)
+ post_tags.where(tag_id: source_id).update(tag_id: target_id)
+ end
+
def delete(tag_id:)
post_tags.where(tag_id: tag_id).delete
end
diff --git a/slices/admin/repos/tag_repo.rb b/slices/admin/repos/tag_repo.rb
index 86d6c0f..56b39a0 100644
--- a/slices/admin/repos/tag_repo.rb
+++ b/slices/admin/repos/tag_repo.rb
@@ -16,6 +16,10 @@ module Admin
def delete(tag_id:)
tags.by_pk(tag_id).delete
end
+
+ def fetch(id)
+ tags.by_pk(id).one
+ end
end
end
end
diff --git a/slices/admin/templates/auto_tagging/index.html.slim b/slices/admin/templates/auto_tagging/index.html.slim
index 0e3c5a2..6d2443b 100644
--- a/slices/admin/templates/auto_tagging/index.html.slim
+++ b/slices/admin/templates/auto_tagging/index.html.slim
@@ -6,6 +6,6 @@ div class="prose dark:prose-invert max-w-prose mx-auto mb-12"
div id="auto-tag-#{auto_tagging.id}" class="mb-2"
== "Tag post with #{auto_tagging.tag.label} when #{auto_tagging.title_only? ? "title" : "content"} contains #{auto_tagging.term}"
= " — "
- button hx-delete="/admin/tags/auto_taggings/#{auto_tagging.id}" hx-target="#auto-tag-#{auto_tagging.id}" delete
+ button class="text-red-600 hover:text-red-400" hx-delete="/admin/tags/auto_taggings/#{auto_tagging.id}" hx-target="#auto-tag-#{auto_tagging.id}" delete
a class="bg-blue-100 text-blue-600 p-1 rounded no-underline" href="/admin/tags/auto_tagging/new" New
div class="max-w-screen-md mx-auto border-t-4 border-solid border-gray-400 dark:border-gray-600"
diff --git a/slices/admin/templates/auto_tagging/new.html.slim b/slices/admin/templates/auto_tagging/new.html.slim
index 3b3b0a9..71e2df5 100644
--- a/slices/admin/templates/auto_tagging/new.html.slim
+++ b/slices/admin/templates/auto_tagging/new.html.slim
@@ -10,19 +10,22 @@ div class="max-w-prose mx-auto"
form method="POST" action="/admin/tags/auto_tagging"
div class="mb-4"
- label class="text-gray-800 dark:text-gray-200" for="title_contains" Title contains:
+ label class="text-gray-800 dark:text-gray-200 mr-2" for="title_contains" Title contains:
input class="text-gray-800 p-1 border border-gray-400" type="text" id="title_contains" name="title_contains"
div class="mb-4"
- label class="text-gray-800 dark:text-gray-200" for="body_contains" ... or body contains:
+ label class="text-gray-800 dark:text-gray-200 mr-2" for="body_contains" ... or body contains:
input class="text-gray-800 p-1 border border-gray-400" type="text" id="body_contains" name="body_contains"
div class="mb-4"
- label class="text-gray-800 dark:text-gray-200" for="tags" Tag with:
+ label class="text-gray-800 dark:text-gray-200 mr-2" for="tags" Tag with:
select class="text-gray-800" id="tags" name="tag_id"
- tags.each do |tag|
option value=tag.id
= tag.label
+ div class="mb-4"
+ label class="text-gray-800 dark:text-gray-200 mr-2" for="tag_now" Tag all now?
+ input type="checkbox" name="tag_now" id="tag_now"
div class="mb-4"
button class="rounded bg-blue-100 hover:bg-blue-200 text-blue-600 px-2 hover:cursor-pointer" type="submit"
= "Create"
diff --git a/slices/admin/templates/index.html.slim b/slices/admin/templates/index.html.slim
index 4c6ca81..0b70e55 100644
--- a/slices/admin/templates/index.html.slim
+++ b/slices/admin/templates/index.html.slim
@@ -11,6 +11,8 @@ div class="max-w-prose mx-auto prose dark:prose-invert"
a href="/admin/tags" Tags
li
a href="/admin/tags/auto_tagging" Auto tagging
+ li
+ a href="/admin/tags/merge" Merge tags
li
a href="/admin/bookmarks" Bookmarks
diff --git a/slices/admin/templates/merge_tags/index.html.slim b/slices/admin/templates/merge_tags/index.html.slim
new file mode 100644
index 0000000..ac75905
--- /dev/null
+++ b/slices/admin/templates/merge_tags/index.html.slim
@@ -0,0 +1,11 @@
+div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
+ h1 Admin // Merge Tags
+
+div class="max-w-prose mx-auto"
+ ul
+ - tags.each do |tag|
+ li id="tag-#{tag.id}" class="text-gray-800 dark:text-gray-200"
+ a href="/admin/tags/merge/#{tag.id}"
+ = "#{tag.label} (#{tag.posts.count})"
+
+div class="max-w-screen-md mx-auto border-t-4 border-solid border-gray-400 dark:border-gray-600"
diff --git a/slices/admin/templates/merge_tags/new.html.slim b/slices/admin/templates/merge_tags/new.html.slim
new file mode 100644
index 0000000..4b1484e
--- /dev/null
+++ b/slices/admin/templates/merge_tags/new.html.slim
@@ -0,0 +1,19 @@
+div class="mb-12 prose dark:prose-invert max-w-prose mx-auto text-gray-800 dark:text-gray-200"
+ h1 Admin // Merge Tags
+
+div class="max-w-prose mx-auto prose dark:prose-invert"
+ h3 Pick a tag to merge in to #{tag.label}
+
+ form action="/admin/tags/merge" method="POST"
+ input type="hidden" name="target_id" value=tag.id
+
+ div class="mb-4"
+ select class="text-gray-800" name="source_id"
+ - tags.each do |source_tag|
+ option value=source_tag.id
+ = source_tag.label
+ div class="mb-4"
+ button class="rounded bg-blue-100 hover:bg-blue-200 text-blue-600 px-2 hover:cursor-pointer"
+ = "Merge"
+
+div class="max-w-screen-md mx-auto border-t-4 border-solid border-gray-400 dark:border-gray-600"
diff --git a/slices/admin/views/merge_tags/index.rb b/slices/admin/views/merge_tags/index.rb
new file mode 100644
index 0000000..0537824
--- /dev/null
+++ b/slices/admin/views/merge_tags/index.rb
@@ -0,0 +1,14 @@
+module Admin
+ module Views
+ module MergeTags
+ class Index < Admin::View
+
+ include Deps["repos.tag_repo"]
+
+ expose :tags do
+ tag_repo.list_with_posts
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/slices/admin/views/merge_tags/new.rb b/slices/admin/views/merge_tags/new.rb
new file mode 100644
index 0000000..b09c03b
--- /dev/null
+++ b/slices/admin/views/merge_tags/new.rb
@@ -0,0 +1,18 @@
+module Admin
+ module Views
+ module MergeTags
+ class New < Admin::View
+
+ include Deps["repos.tag_repo"]
+
+ expose :tag do |id:|
+ tag_repo.fetch(id)
+ end
+
+ expose :tags do |id:|
+ tag_repo.list.reject { |t| t.id.to_s == id.to_s }
+ end
+ end
+ end
+ end
+end
\ No newline at end of file