Remove "save as draft"
Removes the creating status completely as well as the abandoned cards system. It will always resume drafts if they exist, for a given collection and user. https://app.box-car.com/5986089/cards/2489
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
class Cards::RecoversController < ApplicationController
|
||||
include CardScoped
|
||||
|
||||
def create
|
||||
redirect_to @card.recover_abandoned_creation
|
||||
end
|
||||
end
|
||||
@@ -9,7 +9,7 @@ class CardsController < ApplicationController
|
||||
end
|
||||
|
||||
def create
|
||||
card = @collection.cards.create!
|
||||
card = @collection.cards.find_or_create_by!(creator: Current.user, status: "drafted")
|
||||
redirect_to card
|
||||
end
|
||||
|
||||
@@ -30,7 +30,7 @@ class CardsController < ApplicationController
|
||||
|
||||
def destroy
|
||||
@card.destroy!
|
||||
redirect_to @card.collection, notice: ("Card deleted" unless @card.creating?)
|
||||
redirect_to @card.collection, notice: "Card deleted"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
class RemoveAbandonedCreationsJob < ApplicationJob
|
||||
def perform
|
||||
ApplicationRecord.with_each_tenant do |tenant|
|
||||
Card.remove_abandoned_creations
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2,38 +2,17 @@ module Card::Statuses
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
enum :status, %w[ creating drafted published ].index_by(&:itself)
|
||||
enum :status, %w[ drafted published ].index_by(&:itself)
|
||||
|
||||
after_create -> { track_event :published }, if: :published?
|
||||
|
||||
scope :published_or_drafted_by, ->(user) { where(status: :published).or(where(status: :drafted, creator: user)) }
|
||||
end
|
||||
|
||||
class_methods do
|
||||
def remove_abandoned_creations
|
||||
Card.creating.where(updated_at: ..1.day.ago).destroy_all
|
||||
end
|
||||
end
|
||||
|
||||
def can_recover_abandoned_creation?
|
||||
abandoned_creations.where(updated_at: 1.day.ago..).any?
|
||||
end
|
||||
|
||||
def recover_abandoned_creation
|
||||
abandoned_creations.last.tap do |card|
|
||||
Card.creating.where(creator: creator).excluding(card).destroy_all
|
||||
end
|
||||
end
|
||||
|
||||
def publish
|
||||
transaction do
|
||||
published!
|
||||
track_event :published
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def abandoned_creations
|
||||
Card.creating.where(creator: creator).where("created_at != updated_at").excluding(self)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
<% if card.published? %>
|
||||
<%= render "cards/container/footer/published", card: card %>
|
||||
<% elsif card.creating? %>
|
||||
<% elsif card.drafted? %>
|
||||
<%= render "cards/container/footer/draft", card: card %>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
<% if card.creating? && card.can_recover_abandoned_creation? %>
|
||||
<div class="card__banner min-width max-width" style="--card-color: <%= card.color %>;">
|
||||
<span class="overflow-ellipsis">You have an unsaved card. Would you like to continue where you left off?</span>
|
||||
<%= button_to card_recover_path(card), class: "btn txt-small", data: { turbo_action: "replace" } do %>
|
||||
<span>Restore</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if card.drafted? %>
|
||||
<div class="card__banner min-width max-width" style="--card-color: <%= card.color %>;">
|
||||
<span class="overflow-ellipsis">This is a draft, it’s only visible to you.</span>
|
||||
|
||||
@@ -3,6 +3,4 @@
|
||||
|
||||
<%= button_to "Create and add another", card_publish_path(card), method: :post, class: "btn btn--reversed", name: "creation_type", value: "add_another",
|
||||
title: "Create and add another (ctrl+shift+enter)", form: { data: { turbo: false } }, data: { controller: "hotkey", action: "keydown.ctrl+shift+enter@document->hotkey#click" } %>
|
||||
|
||||
<%= button_to "Save as a draft", card_path(card), name: "card[status]", value: "drafted", method: :put, class: "btn btn--reversed" %>
|
||||
</div>
|
||||
|
||||
@@ -15,13 +15,9 @@
|
||||
</span>
|
||||
|
||||
<span class="card__meta-text card__meta-text--updated overflow-ellipsis">
|
||||
<% if card.creating? %>
|
||||
|
||||
<% else %>
|
||||
<%= icon_tag "refresh--meta" %>
|
||||
Updated
|
||||
<%= local_datetime_tag(card.last_active_at, style: :daysago) %>
|
||||
<% end %>
|
||||
<%= icon_tag "refresh--meta" %>
|
||||
Updated
|
||||
<%= local_datetime_tag(card.last_active_at, style: :daysago) %>
|
||||
</span>
|
||||
|
||||
<span class="card__meta-text card__meta-text--assignees overflow-ellipsis">
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</dialog>
|
||||
</div>
|
||||
|
||||
<% if card.tags.any? || card.creating? %>
|
||||
<% if card.tags.any? %>
|
||||
<div class="min-width overflow-ellipsis">
|
||||
<% card.tags.each_with_index do |tag, index| %>
|
||||
<%= link_to cards_path(collection_ids: [ card.collection ], tag_ids: [ tag.id ]),
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<div data-controller="beacon lightbox" data-beacon-url-value="<%= card_reading_path(@card) %>">
|
||||
<%= render "cards/container", card: @card %>
|
||||
<%= render "cards/messages", card: @card unless @card.creating? %>
|
||||
<%= render "cards/messages", card: @card unless @card.drafted? %>
|
||||
|
||||
<%= render "layouts/lightbox" do %>
|
||||
<%= button_to_remove_card_image(@card) if @card.image.attached? %>
|
||||
|
||||
@@ -8,9 +8,6 @@ production: &production
|
||||
auto_postpone_all_due:
|
||||
class: Card::AutoPostponeAllDueJob
|
||||
schedule: every hour at minute 50
|
||||
remove_abandoned_creations:
|
||||
class: RemoveAbandonedCreationsJob
|
||||
schedule: every hour at minute 59
|
||||
delete_unused_tags:
|
||||
class: DeleteUnusedTagsJob
|
||||
schedule: every day at 04:02
|
||||
|
||||
@@ -71,7 +71,6 @@ Rails.application.routes.draw do
|
||||
resource :triage
|
||||
resource :publish
|
||||
resource :reading
|
||||
resource :recover
|
||||
resource :watch
|
||||
resource :collection
|
||||
resource :column
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
class ChangeCardsStatusDefaultToDrafted < ActiveRecord::Migration[8.2]
|
||||
def change
|
||||
change_column_default :cards, :status, from: "creating", to: "drafted"
|
||||
end
|
||||
end
|
||||
Generated
+1
-1
@@ -144,7 +144,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_02_115338) do
|
||||
t.integer "creator_id", null: false
|
||||
t.date "due_on"
|
||||
t.datetime "last_active_at", null: false
|
||||
t.text "status", default: "creating", null: false
|
||||
t.text "status", default: "drafted", null: false
|
||||
t.string "title"
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["collection_id"], name: "index_cards_on_collection_id"
|
||||
|
||||
+1
-1
@@ -496,7 +496,7 @@ columns:
|
||||
cast_type: *15
|
||||
sql_type_metadata: *16
|
||||
'null': false
|
||||
default: creating
|
||||
default: drafted
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
|
||||
@@ -21,11 +21,12 @@ class Cards::PublishesControllerTest < ActionDispatch::IntegrationTest
|
||||
card.drafted!
|
||||
|
||||
assert_changes -> { card.reload.published? }, from: false, to: true do
|
||||
assert_difference -> { Card.creating.count }, +1 do
|
||||
assert_difference -> { Card.count }, +1 do
|
||||
post card_publish_path(card, creation_type: "add_another")
|
||||
end
|
||||
end
|
||||
|
||||
assert_redirected_to Card.creating.last
|
||||
assert Card.last.drafted?
|
||||
assert_redirected_to Card.last
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,11 +15,23 @@ class CardsControllerTest < ActionDispatch::IntegrationTest
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "create" do
|
||||
test "create a new draft" do
|
||||
assert_difference -> { Card.count }, 1 do
|
||||
post collection_cards_path(collections(:writebook))
|
||||
end
|
||||
assert_redirected_to card_path(Card.last)
|
||||
|
||||
assert Card.last.drafted?
|
||||
assert_redirected_to Card.last
|
||||
end
|
||||
|
||||
test "create resumes existing draft if it exists" do
|
||||
draft = collections(:writebook).cards.create!(creator: users(:kevin), status: :drafted)
|
||||
|
||||
assert_no_difference -> { Card.count } do
|
||||
post collection_cards_path(collections(:writebook))
|
||||
end
|
||||
|
||||
assert_redirected_to draft
|
||||
end
|
||||
|
||||
test "show" do
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
require "test_helper"
|
||||
|
||||
class Cards::RecoversControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in_as :jz
|
||||
end
|
||||
|
||||
test "create" do
|
||||
abandoned_card = collections(:writebook).cards.create! creator: users(:kevin)
|
||||
abandoned_card.update!(title: "An edited title")
|
||||
unsaved_card = collections(:writebook).cards.create! creator: users(:kevin)
|
||||
|
||||
post card_recover_path(unsaved_card)
|
||||
|
||||
assert_redirected_to abandoned_card
|
||||
assert_equal [ abandoned_card ], Card.creating
|
||||
end
|
||||
end
|
||||
@@ -1,12 +1,10 @@
|
||||
require "test_helper"
|
||||
|
||||
class Card::StatusesTest < ActiveSupport::TestCase
|
||||
test "cards start out in a `creating` state" do
|
||||
test "cards start out in a `drafted` state" do
|
||||
card = collections(:writebook).cards.create! creator: users(:kevin), title: "Newly created card"
|
||||
|
||||
assert card.creating?
|
||||
assert_not_includes Card.published_or_drafted_by(users(:kevin)), card
|
||||
assert_not_includes Card.published_or_drafted_by(users(:jz)), card
|
||||
assert card.drafted?
|
||||
end
|
||||
|
||||
test "cards are only visible to the creator when drafted" do
|
||||
@@ -51,38 +49,4 @@ class Card::StatusesTest < ActiveSupport::TestCase
|
||||
assert_equal card, Event.last.eventable
|
||||
assert_equal "card_published", Event.last.action
|
||||
end
|
||||
|
||||
test "can_recover_abandoned_creation?" do
|
||||
card = collections(:writebook).cards.create! creator: users(:kevin)
|
||||
unsaved_card = collections(:writebook).cards.new creator: users(:kevin)
|
||||
|
||||
assert_not unsaved_card.can_recover_abandoned_creation?
|
||||
|
||||
card.update!(title: "Something worth keeping")
|
||||
assert unsaved_card.can_recover_abandoned_creation?
|
||||
end
|
||||
|
||||
test "recover_abandoned_creation" do
|
||||
card_edited = collections(:writebook).cards.create! creator: users(:kevin)
|
||||
card_edited.update!(title: "Something worth keeping")
|
||||
|
||||
card_not_edited = collections(:writebook).cards.create! creator: users(:kevin)
|
||||
|
||||
assert card_not_edited.can_recover_abandoned_creation?
|
||||
|
||||
assert_equal card_edited, card_not_edited.recover_abandoned_creation
|
||||
|
||||
assert_raises(ActiveRecord::RecordNotFound) { card_not_edited.reload }
|
||||
end
|
||||
|
||||
test "remove_abandoned_creations" do
|
||||
card_old = collections(:writebook).cards.create! creator: users(:kevin), updated_at: 2.days.ago
|
||||
card_recent = collections(:writebook).cards.create! creator: users(:kevin)
|
||||
|
||||
assert_equal 2, Card.creating.count
|
||||
|
||||
Card.remove_abandoned_creations
|
||||
|
||||
assert_equal [ card_recent ], Card.creating
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user