Skip to content

Commit

Permalink
tags;search
Browse files Browse the repository at this point in the history
  • Loading branch information
clarksonator committed Dec 1, 2024
1 parent ff6239c commit cea44c5
Show file tree
Hide file tree
Showing 35 changed files with 5,684 additions and 37 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ gem "markdown_checkboxes", "~> 1.0"

gem "rouge"

gem 'htmx-rails'

Check failure on line 43 in Gemfile

View workflow job for this annotation

GitHub Actions / lint

Style/StringLiterals: Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.

gem "passenger", ">= 5.3.2", require: "phusion_passenger/rack_handler"

# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ GEM
erubi (1.13.0)
globalid (1.2.1)
activesupport (>= 6.1)
htmx-rails (0.2.0)
i18n (1.14.6)
concurrent-ruby (~> 1.0)
importmap-rails (2.0.3)
Expand Down Expand Up @@ -345,6 +346,7 @@ DEPENDENCIES
debug
devise
erb
htmx-rails
importmap-rails
jbuilder
markdown_checkboxes (~> 1.0)
Expand Down
1 change: 1 addition & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//= require htmx
4 changes: 4 additions & 0 deletions app/assets/stylesheets/application.css
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ body {
color: var(--ctp-frappe-text);
}

.box {
background-color: var(--ctp-frappe-surface1);
}

*::placeholder {
/* modern browser */
color: var(--ctp-frappe-subtext0) !important;
Expand Down
24 changes: 22 additions & 2 deletions app/controllers/memos_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ def index
@memos = Memo.all
end

def search
if params[:id]
@memos = Memo.find_by_sql("SELECT * from memos INNER JOIN memos_tags on memos.id = memos_tags.memo_id where tag_id = " + params[:id])
else
@memos = Memo.all
end
end

def show
@memo = Memo.find(params[:id])
end
Expand All @@ -14,7 +22,12 @@ def new
end

def create
@memo = current_user.memos.build(memo_params)
@params = memo_params
if @params[:tagName]
@tagName = @params[:tagName]
@params.delete(:tagName)
end
@memo = current_user.memos.build(@params)

if @memo.attachment
attachmentFile = params[:memo][:attachment]
Expand All @@ -23,6 +36,13 @@ def create
end

if @memo.save
if @tagName
# @tag = Tag.new(name: @tagName)
# @tag.save
# @memo.tags << @tag
@memo.tags.create!({ name: @tagName })
end

redirect_to action: "index"
else
render :new, status: :unprocessable_entity
Expand All @@ -48,6 +68,6 @@ def update
private

def memo_params
params.require(:memo).permit(:title, :body, :attachment)
params.require(:memo).permit(:title, :body, :attachment, :tagName)
end
end
70 changes: 70 additions & 0 deletions app/controllers/tags_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
class TagsController < ApplicationController
before_action :set_tag, only: %i[ show edit update destroy ]

# GET /tags or /tags.json
def index
@tags = Tag.all
end

# GET /tags/1 or /tags/1.json
def show
end

# GET /tags/new
def new
@tag = Tag.new
end

# GET /tags/1/edit
def edit
end

# POST /tags or /tags.json
def create
@tag = Tag.new(tag_params)

respond_to do |format|
if @tag.save
format.html { redirect_to @tag, notice: "Tag was successfully created." }
format.json { render :show, status: :created, location: @tag }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @tag.errors, status: :unprocessable_entity }
end
end
end

# PATCH/PUT /tags/1 or /tags/1.json
def update
respond_to do |format|
if @tag.update(tag_params)
format.html { redirect_to @tag, notice: "Tag was successfully updated." }
format.json { render :show, status: :ok, location: @tag }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @tag.errors, status: :unprocessable_entity }
end
end
end

# DELETE /tags/1 or /tags/1.json
def destroy
@tag.destroy!

respond_to do |format|
format.html { redirect_to tags_path, status: :see_other, notice: "Tag was successfully destroyed." }
format.json { head :no_content }
end
end

private
# Use callbacks to share common setup or constraints between actions.
def set_tag
@tag = Tag.find(params.expect(:id))
end

# Only allow a list of trusted parameters through.
def tag_params
params.expect(tag: [ :name ])
end
end
2 changes: 2 additions & 0 deletions app/helpers/tags_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module TagsHelper
end
1 change: 1 addition & 0 deletions app/models/memo.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
class Memo < ApplicationRecord
belongs_to :user
has_and_belongs_to_many :tags
end
4 changes: 4 additions & 0 deletions app/models/memos_tag.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class MemosTag < ApplicationRecord
belongs_to :memo
belongs_to :tag
end
3 changes: 3 additions & 0 deletions app/models/tag.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Tag < ApplicationRecord
has_and_belongs_to_many :memos
end
17 changes: 10 additions & 7 deletions app/views/layouts/_memo.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<div id="memo">
<div class="card">
<% @guid = (0...50).map { ('a'..'z').to_a[rand(26)] }.join %>
<div id="memo" hx-include="#<%= @guid %>" hx-target="this">
<div class="card" >
<div class="card-content viewMemo">
<div class="content">
<%= raw renderMarkdown(memo.body) %>
Expand All @@ -22,11 +23,14 @@
onclick="openModal();"
/>
<% end %>
<% memo.tag_ids.each do |tagid| %>
<%= link_to "#" + (Tag.find(tagid)).name, search_memos_path + "/" + tagid.to_s %>
<% end %>
</div>
</div>
<div class="card-content updateMemo" data-url="<%= memo_path(memo.id) %>">
<div class="content">
<textarea id="editMemoTA" class="textarea"><%= memo.body %></textarea>
<textarea id='<%= @guid %>' name="memo[body]" class="textarea"><%= memo.body %></textarea>
<% if memo.attachment != nil && memo.attachment != 0 %>
<img
src="data:image/png;base64,<%= memo.attachment %>"
Expand All @@ -48,10 +52,9 @@
<i class="fa-regular fa-trash-can"></i>
<% end %>
<div>
<button
class="button saveMemo"
style="background-color:var(--ctp-frappe-blue);color:black;"
><i class="fa-regular fa-floppy-disk"></i></button>
<button class="button saveMemo" style="background-color:var(--ctp-frappe-blue);color:black;" hx-put="<%= memo_path(memo.id) %>" >
<i class="fa-regular fa-floppy-disk"></i>
</button>
<button
class="button cancelEdit"
style="background-color:var(--ctp-frappe-maroon);color:black;"
Expand Down
62 changes: 39 additions & 23 deletions app/views/layouts/_new.html.erb
Original file line number Diff line number Diff line change
@@ -1,29 +1,45 @@
<%= form_for :memo, :url => url_for(:controller => "memos", :action => "create"), html: { class: "memo_form" } do |form| %>
<div class="card" >
<div class="card-content">
<div class="content">
<div class="field">
<%= form.text_area :body, placeholder: "Memo", class: "textarea" %>
</div>
</div>
<div class="card-content">
<div class="content">
<div class="field">
<%= form.text_area :body, placeholder: "Memo", class: "textarea" %>
</div>
<footer class="card-footer">
<div class="card-footer-item">
<div class="file" style="margin-bottom: 0">
<label class="file-label">
</div>
</div>
<footer class="card-footer">
<div class="card-footer-item">
<div class="file" style="margin-bottom: 0">
<label class="file-label">
<%= form.file_field :attachment, accept: "image/png,image/jpg,image/jpeg", class: "file-input" %>
<span class="file-cta">
<span class="file-icon">
<i class="fas fa-upload"></i>
</span>
<span class="file-label"> Choose a file… </span>
</span>
</label>
</div>
<%= button_tag type: 'submit', class: "button right is-save" do %>
<i class="fa-regular fa-floppy-disk" aria-hidden="true"></i>
<% end %>
</div>
</footer>
<span class="file-cta" style="background-color: var(--ctp-frappe-green)">
<i class="fas fa-upload" style="color: black"></i>
</span>
</label>
</div>
<%= button_tag type: 'button', class: "button", style: "background-color: var(--ctp-frappe-mauve); color: black;", onclick: "addTag();" do %>
<i class="fa-regular fa-hashtag" aria-hidden="true"></i>
<% end %>
<%= button_tag type: 'submit', class: "button right is-save" do %>
<i class="fa-regular fa-floppy-disk" aria-hidden="true"></i>
<% end %>
</div>
</footer>
</div>
<div id="addTagModal" class="modal">
<div class="modal-background"></div>
<div class="modal-content">
<div class="box">
<article class="media">
<%= form.text_field :tagName, placeholder: "Tags", class: "input" %>
</article>
</div>
</div>
<button class="modal-close is-large" aria-label="close"></button>
</div>
<script>
function addTag(elem) {
$("#addTagModal").addClass("is-active");
}
</script>
<% end %>
12 changes: 10 additions & 2 deletions app/views/memos/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,15 @@
<% end %>
</div>
<script>
document.querySelectorAll('.modal-background, .modal-close,.modal-card-head .delete, .modal-card-foot .button').forEach(($el) => {const $modal = $el.closest('.modal');$el.addEventListener('click', () => {$modal.classList.remove("is-active");});});
document.body.addEventListener('htmx:configRequest', function(evt) {
event.detail.headers['X-CSRF-Token'] = $('meta[name="csrf-token"]').attr('content');
})

document.body.addEventListener('htmx:afterSettle', function(evt) {
setupClicks();
})

document.querySelectorAll('.modal-background, .modal-close,.modal-card-head .delete, .modal-card-foot .button').forEach(($el) => {const $modal = $el.closest('.modal');$el.addEventListener('click', () => {$modal.classList.remove("is-active");});});

function setupClicks() {
$(".editMemo").on("click", function() {
Expand All @@ -32,7 +40,7 @@
card.children(".updateMemo").hide();
$(this).hide();
});
$(".saveMemo").on("click", function() {
$(".saveMemo").on("clickt", function() {
var card = $(this).parents(".card");
var url = card.children(".updateMemo").data('url');
var body = card.find("#editMemoTA").val();
Expand Down
63 changes: 63 additions & 0 deletions app/views/memos/search.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<% if user_signed_in? %>
<%= csrf_meta_tag %>
<script>
function openModal() {
document.getElementById("modal1")
.classList.add("is-active");
}
</script>
<div class="memoIndex">
<%= render "layouts/new" %>
<% @memos.each do |memo| %>
<%= render partial: "layouts/memo", object: memo %>
<% end %>
</div>
<script>
document.body.addEventListener('htmx:configRequest', function(evt) {
event.detail.headers['X-CSRF-Token'] = $('meta[name="csrf-token"]').attr('content');
})

document.body.addEventListener('htmx:afterSettle', function(evt) {
setupClicks();
})

document.querySelectorAll('.modal-background, .modal-close,.modal-card-head .delete, .modal-card-foot .button').forEach(($el) => {const $modal = $el.closest('.modal');$el.addEventListener('click', () => {$modal.classList.remove("is-active");});});

function setupClicks() {
$(".editMemo").on("click", function() {
$(this).parent().find(".saveMemo").show();
$(this).parent().find(".cancelEdit").show();
var card = $(this).parents(".card");
card.children(".viewMemo").hide();
card.children(".updateMemo").show();
$(this).hide();
});
$(".cancelEdit").on("click", function() {
$(this).parent().find(".saveMemo").hide();
$(this).parents().find(".editMemo").show();
var card = $(this).parents(".card");
card.children(".viewMemo").show();
card.children(".updateMemo").hide();
$(this).hide();
});
$(".saveMemo").on("clickt", function() {
var card = $(this).parents(".card");
var url = card.children(".updateMemo").data('url');
var body = card.find("#editMemoTA").val();
$.ajax({
url: url,
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
data: "memo%5Bbody%5D="+encodeURIComponent(body),
dataType: "html",
type: 'PUT',
success: function(result) {
var memoDiv = card.parents("#memo");
memoDiv.replaceWith(result);
setupClicks();
}
});
});
}
setupClicks();
</script>
<% end %>
22 changes: 22 additions & 0 deletions app/views/tags/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<%= form_with(model: tag) do |form| %>
<% if tag.errors.any? %>
<div style="color: red">
<h2><%= pluralize(tag.errors.count, "error") %> prohibited this tag from being saved:</h2>

<ul>
<% tag.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>

<div>
<%= form.label :name, style: "display: block" %>
<%= form.text_field :name %>
</div>

<div>
<%= form.submit %>
</div>
<% end %>
Loading

0 comments on commit cea44c5

Please sign in to comment.