diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/card-columns.css index bdbad0bcc..90f6859c6 100644 --- a/app/assets/stylesheets/card-columns.css +++ b/app/assets/stylesheets/card-columns.css @@ -108,6 +108,10 @@ } } } + + .card__steps { + display: flex; + } } /* Column elements @@ -197,7 +201,7 @@ .card__header { color: color-mix(in srgb, var(--card-color) 40%, var(--color-ink)); - margin-inline-start: calc(-0.5 * var(--card-padding-inline)); + margin-inline: calc(-0.5 * var(--card-padding-inline)) calc(-0.25 * var(--card-padding-inline)); } .card__people-label { diff --git a/app/assets/stylesheets/cards.css b/app/assets/stylesheets/cards.css index 9595b98ee..4462dfb6e 100644 --- a/app/assets/stylesheets/cards.css +++ b/app/assets/stylesheets/cards.css @@ -119,8 +119,8 @@ flex-wrap: nowrap; gap: var(--inline-space); margin-block-start: calc(-1 * var(--card-padding-block)); - margin-inline-start: calc(-1 * var(--card-padding-inline)); - max-inline-size: 100%; + margin-inline: calc(-1 * var(--card-padding-inline)) calc(-0.5 * var(--card-padding-inline)); + max-inline-size: unset; min-inline-size: 0; .workflow-stage { diff --git a/app/assets/stylesheets/icons.css b/app/assets/stylesheets/icons.css index fd12630d9..2870088c2 100644 --- a/app/assets/stylesheets/icons.css +++ b/app/assets/stylesheets/icons.css @@ -30,6 +30,7 @@ .icon--camera { --svg: url("camera.svg "); } .icon--caret-down { --svg: url("caret-down.svg "); } .icon--check { --svg: url("check.svg "); } + .icon--check-all { --svg: url("check-all.svg "); } .icon--clipboard { --svg: url("clipboard.svg "); } .icon--close { --svg: url("close.svg "); } .icon--collection { --svg: url("collection.svg "); } diff --git a/app/assets/stylesheets/steps.css b/app/assets/stylesheets/steps.css new file mode 100644 index 000000000..2f526662c --- /dev/null +++ b/app/assets/stylesheets/steps.css @@ -0,0 +1,98 @@ +@layer components { + .step { + display: grid; + grid-template-columns: 1em auto auto; + gap: calc(var(--inline-space) * 2/3); + inline-size: auto; + } + + .step__checkbox { + --hover-color: var(--card-color); + + appearance: none; + background-color: var(--color-canvas); + block-size: 1.1em; + border: 1px solid currentColor; + border-radius: 0.15em; + color: currentColor; + display: grid; + font: inherit; + inline-size: 1.1em; + margin: 0; + place-content: center; + transform: translateY(0.1em); + + &::before { + background-color: CanvasText; + block-size: 0.65em; + box-shadow: inset 1em 1em currentColor; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); + content: ""; + inline-size: 0.65em; + transform: scale(0); + transform-origin: center; + transition: 150ms transform ease-in-out; + } + + &:checked::before { + transform: scale(1) rotate(10deg); + } + + &:where([disabled]):not(:hover):not(:active) { + filter: none; + opacity: 0.5; + } + } + + .step__content { + --input-border-radius: 0; + --input-border-size: 0; + --input-padding: 0; + + border-bottom: 1px solid transparent; + color: currentColor; + font-weight: 500; + margin-block-end: calc(var(--block-space) * 1/3); + + &:is(a, input[type=text]) { + --hover-size: 0; + } + + .step:has(:checked) & { + opacity: 0.7; + text-decoration: line-through; + } + + &::placeholder { + color: var(--card-color); + } + } + + .step__content--edit { + border-bottom-color: currentColor; + } + + .steps { + contain: inline-size; + display: grid; + list-style: none; + margin: 0; + max-inline-size: 100%; + padding: 0; + } + + .steps__icon { + background-color: var(--card-color); + block-size: 1.3em; + border-radius: 50%; + display: grid; + inline-size: 1.3em; + place-content: center; + + .icon { + background-color: var(--color-ink-inverted); + block-size: 0.8em; + inline-size: 0.8em; + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/trays.css b/app/assets/stylesheets/trays.css index d90c56ea8..48ae50b31 100644 --- a/app/assets/stylesheets/trays.css +++ b/app/assets/stylesheets/trays.css @@ -315,6 +315,7 @@ .card__meta .btn, .card__meta-item:not(.card__meta-item--updated), .card__stages, + .card__steps, .card__closed { display: none; } diff --git a/app/controllers/cards/steps_controller.rb b/app/controllers/cards/steps_controller.rb new file mode 100644 index 000000000..8821289b7 --- /dev/null +++ b/app/controllers/cards/steps_controller.rb @@ -0,0 +1,35 @@ +class Cards::StepsController < ApplicationController + include CardScoped + + before_action :set_step, only: %i[ show edit update destroy ] + + def create + @step = @card.steps.create!(step_params) + render_card_replacement + end + + def show + end + + def edit + end + + def update + @step.update!(step_params) + render_card_replacement + end + + def destroy + @step.destroy! + render_card_replacement + end + + private + def set_step + @step = @card.steps.find(params[:id]) + end + + def step_params + params.require(:step).permit(:content, :completed) + end +end diff --git a/app/models/card.rb b/app/models/card.rb index 94ee043d2..c83c1325b 100644 --- a/app/models/card.rb +++ b/app/models/card.rb @@ -1,6 +1,6 @@ class Card < ApplicationRecord include Assignable, Colored, Engageable, Entropic, Eventable, - Golden, Mentions, Pinnable, Closeable, Readable, Searchable, + Golden, Mentions, Multistep, Pinnable, Closeable, Readable, Searchable, Staged, Stallable, Statuses, Taggable, Watchable belongs_to :collection, touch: true diff --git a/app/models/card/multistep.rb b/app/models/card/multistep.rb new file mode 100644 index 000000000..ccd3a9786 --- /dev/null +++ b/app/models/card/multistep.rb @@ -0,0 +1,11 @@ +module Card::Multistep + extend ActiveSupport::Concern + + included do + has_many :steps, dependent: :destroy + end + + def completed_steps_count + steps.where(completed: true).count + end +end diff --git a/app/models/step.rb b/app/models/step.rb new file mode 100644 index 000000000..7451832c9 --- /dev/null +++ b/app/models/step.rb @@ -0,0 +1,7 @@ +class Step < ApplicationRecord + belongs_to :card, touch: true + + def completed? + completed + end +end diff --git a/app/views/cards/_container.html.erb b/app/views/cards/_container.html.erb index f43466a2b..df7d6c917 100644 --- a/app/views/cards/_container.html.erb +++ b/app/views/cards/_container.html.erb @@ -19,6 +19,8 @@ <%= render "cards/stagings/stages", card: card if card.doing? %> + <%= render "cards/display/perma/steps", card: card %> +