Merge branch 'main' into mobile/prepare-webviews-2
* main: (73 commits)
Fix that caching should be disabled in dev by default. References 3cf841d463.
Revert "Add CJK (Chinese, Japanese, Korean) search support"
Account for new button sizes on mobile
Bump filter z-index when filters are open
Use a dedicated resource for showing cards in draft mode
Refactor popup.css styles for focus state
Add Segoe UI Variable Fizzy font face configuration comments
Update @layer name to `base` in font-face definition for "Segoe UI Variable Fizzy"
Repair scope for card styles within the columns view
Add missing list to cards page
Account for simpler public views
Fix public layout
Pull board-tools outside of the list for mobile
saas: move log_level setting into an environment variable
Restore log level configurability in production environment
Remove engagements
Go back to board after clearing filters
Ensure filters sit on top of cards
Fix public boards
Fix card grid layout
...
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
--block-space-double: calc(var(--block-space) * 2);
|
||||
|
||||
/* Text */
|
||||
--font-sans: "Adwaita Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
||||
--font-sans: "Adwaita Sans", -apple-system, BlinkMacSystemFont, "Segoe UI Variable Fizzy", "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
||||
--font-serif: ui-serif, serif;
|
||||
--font-mono: ui-monospace, monospace;
|
||||
|
||||
@@ -213,7 +213,7 @@
|
||||
--color-terminal-text: var(--color-ink);
|
||||
--color-terminal-text-light: var(--color-ink-lighter);
|
||||
--color-golden: oklch(89.1% 0.178 95.7);
|
||||
--color-considering: oklch(var(--lch-blue-medium));
|
||||
--color-maybe: oklch(var(--lch-blue-medium));
|
||||
|
||||
/* Colors: Cards */
|
||||
--color-card-default: oklch(var(--lch-blue-dark));
|
||||
|
||||
@@ -102,7 +102,8 @@
|
||||
}
|
||||
|
||||
/* Turbo */
|
||||
turbo-frame {
|
||||
turbo-frame,
|
||||
turbo-cable-stream-source {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.cards--considering & {
|
||||
.cards--maybe & {
|
||||
background-color: var(--card-bg-color) !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,33 @@
|
||||
@layer components {
|
||||
/* Layout adjustments for contained scrolling
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Scroll columns individually on mobile */
|
||||
@media (max-width: 639px) {
|
||||
body.contained-scrolling {
|
||||
block-size: 100dvh;
|
||||
grid-template-rows: 1fr var(--footer-height);
|
||||
|
||||
#global-container {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#main {
|
||||
display: grid;
|
||||
grid-template-rows: auto auto 1fr;
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Adapt the grid to public views (no filters or watchers sections) */
|
||||
&.public #main {
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Column container
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
@@ -10,7 +39,7 @@
|
||||
--bubble-size: 3.5rem;
|
||||
--cards-gap: min(1.2cqi, 1.7rem);
|
||||
--column-gap: 8px;
|
||||
--column-padding-expanded: calc(var(--column-gap) * 2);
|
||||
--column-padding: calc(var(--column-gap) * 2);
|
||||
--column-transition-duration: 300ms;
|
||||
--column-width-collapsed: 40px;
|
||||
--column-width-expanded: 450px;
|
||||
@@ -21,17 +50,22 @@
|
||||
container-type: inline-size;
|
||||
display: grid;
|
||||
gap: var(--column-gap);
|
||||
grid-template-columns: 1fr var(--column-width-expanded) 1fr;
|
||||
grid-template-columns: 1fr auto 1fr;
|
||||
inline-size: 100%;
|
||||
margin-inline: auto;
|
||||
max-inline-size: var(--main-width);
|
||||
outline: none;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
padding-block-end: var(--column-width-collapsed);
|
||||
position: relative;
|
||||
|
||||
/* When it has something expanded */
|
||||
&:has(.card-columns__left .cards:not(.is-collapsed), .card-columns__right .cards:not(.is-collapsed)) {
|
||||
grid-template-columns: auto var(--column-width-expanded) auto;
|
||||
&:has(.card-columns__left .is-expanded, .card-columns__right .is-expanded) {
|
||||
grid-template-columns: auto auto auto;
|
||||
|
||||
@media (min-width: 640px) {
|
||||
grid-template-columns: auto var(--column-width-expanded) auto;
|
||||
}
|
||||
}
|
||||
|
||||
&:has(.cards) {
|
||||
@@ -39,11 +73,19 @@
|
||||
min-block-size: 20lh;
|
||||
}
|
||||
|
||||
body:not(.public) & {
|
||||
@media (max-width: 519px) {
|
||||
display: none;
|
||||
@media (max-width: 639px) {
|
||||
--column-width-expanded: calc(100vw - var(--column-gap) * 4);
|
||||
|
||||
scroll-snap-type: inline mandatory;
|
||||
|
||||
&:not(:has(.is-expanded)) {
|
||||
grid-template-columns: auto var(--column-width-collapsed) auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
padding-block-end: var(--column-width-collapsed);
|
||||
}
|
||||
}
|
||||
|
||||
.card-columns__left,
|
||||
@@ -51,16 +93,27 @@
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
gap: var(--column-gap);
|
||||
position: relative;
|
||||
|
||||
@media (max-width: 639px) {
|
||||
min-block-size: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.card-columns__left {
|
||||
justify-content: end;
|
||||
margin-inline-start: auto;
|
||||
padding-inline-start: var(--column-gap);
|
||||
|
||||
@media (max-width: 639px) {
|
||||
padding-inline-start: calc(var(--column-gap) * 2);
|
||||
}
|
||||
}
|
||||
|
||||
.card-columns__right {
|
||||
justify-content: start;
|
||||
padding-inline-end: var(--column-gap);
|
||||
margin-inline-end: auto;
|
||||
}
|
||||
|
||||
/* Column
|
||||
@@ -72,7 +125,13 @@
|
||||
inline-size: var(--column-width-expanded);
|
||||
outline: none;
|
||||
position: relative;
|
||||
scroll-snap-align: start;
|
||||
scroll-snap-align: center;
|
||||
|
||||
&.is-expanded {
|
||||
@media (max-width: 639px) {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-collapsed {
|
||||
inline-size: var(--column-width-collapsed);
|
||||
@@ -126,15 +185,17 @@
|
||||
.cards__transition-container {
|
||||
block-size: 100%;
|
||||
border-radius: calc(var(--column-width-collapsed) / 2);
|
||||
translate: 0;
|
||||
translate: 0 0.5ch; /* Allow a little room for the mini bubble */
|
||||
transition: translate var(--column-transition-duration) var(--ease-out-overshoot-subtle);
|
||||
|
||||
.is-collapsed:not(.cards--considering) & {
|
||||
translate: 0 var(--column-width-collapsed);
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.is-expanded & {
|
||||
translate: 0 0.5ch; /* Allow a little room for the mini bubble */
|
||||
}
|
||||
|
||||
.cards:not(.is-collapsed) & {
|
||||
padding-inline: var(--column-padding-expanded);
|
||||
.is-collapsed & {
|
||||
translate: 0 var(--column-width-collapsed);
|
||||
}
|
||||
}
|
||||
|
||||
.drag-and-drop__hover-container & {
|
||||
@@ -151,29 +212,33 @@
|
||||
.no-transitions & {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
/* Use flex so the __list container can take up the remaining space for scrolling */
|
||||
@media (max-width: 639px) {
|
||||
.is-expanded & {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The wrapper around the cards used to clip overflow while transitioning.
|
||||
* Also, don't resize cards while transitioning to avoid reflow. */
|
||||
.cards__list {
|
||||
align-items: flex-end; /* use flex-start to wipe from left */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--cards-gap);
|
||||
margin-block-start: -1ch;
|
||||
margin-inline: -1ch;
|
||||
overflow: hidden;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
.cards:not(.is-collapsed) & {
|
||||
padding: 1ch;
|
||||
}
|
||||
.is-expanded & {
|
||||
padding: var(--column-padding);
|
||||
|
||||
.card {
|
||||
inline-size: calc(var(--column-width-expanded) - var(--column-padding-expanded) * 2);
|
||||
}
|
||||
|
||||
.cards--grid & {
|
||||
display: contents;
|
||||
/* Use the rest of the column height for scrolling */
|
||||
@media (max-width: 639px) {
|
||||
flex: 1;
|
||||
padding-inline: calc(var(--column-padding) / 4);
|
||||
}
|
||||
}
|
||||
|
||||
[aria-selected] & .card[aria-selected] {
|
||||
@@ -193,7 +258,17 @@
|
||||
}
|
||||
|
||||
.cards__new-column {
|
||||
margin-block-start: var(--column-width-collapsed);
|
||||
position: relative;
|
||||
|
||||
@media (max-width: 639px) {
|
||||
inset-inline-end: 0;
|
||||
position: absolute;
|
||||
translate: 100%;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
margin-block-start: var(--column-width-collapsed);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cards grid; used when filtering
|
||||
@@ -204,11 +279,7 @@
|
||||
--card-grid-columns: 1;
|
||||
|
||||
container-type: inline-size;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--cards-gap);
|
||||
justify-content: center;
|
||||
inline-size: 100%;
|
||||
margin-inline: auto;
|
||||
max-inline-size: var(--main-width);
|
||||
|
||||
@@ -220,6 +291,15 @@
|
||||
--card-grid-columns: 3;
|
||||
}
|
||||
|
||||
.cards__list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--cards-gap);
|
||||
justify-content: center;
|
||||
padding: 1ch;
|
||||
}
|
||||
|
||||
.card {
|
||||
inline-size: calc((100% - var(--cards-gap) * (var(--card-grid-columns) - 1) ) / var(--card-grid-columns));
|
||||
}
|
||||
@@ -245,11 +325,11 @@
|
||||
block-size: 100%;
|
||||
}
|
||||
|
||||
.cards:not(.is-collapsed) & {
|
||||
.cards.is-expanded & {
|
||||
display: grid;
|
||||
grid-template-areas: "menu expander maximize";
|
||||
grid-template-columns: var(--column-width-collapsed) 1fr var(--column-width-collapsed);
|
||||
margin-block-end: calc(0.5 * var(--cards-gap));
|
||||
padding-inline: var(--column-padding);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,12 +372,18 @@
|
||||
font-weight: 600;
|
||||
gap: 0.5ch;
|
||||
grid-area: expander;
|
||||
justify-content: center;
|
||||
outline: none;
|
||||
outline-offset: -2px;
|
||||
position: relative;
|
||||
text-transform: uppercase;
|
||||
|
||||
&[disabled] {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@media (any-hover: hover) {
|
||||
&:hover {
|
||||
.is-collapsed:hover {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
}
|
||||
@@ -338,7 +424,7 @@
|
||||
block-size: 100%;
|
||||
content: "";
|
||||
inline-size: 1px;
|
||||
inset: 0 auto;
|
||||
inset-block: calc(var(--column-width-collapsed) + var(--card-count) * var(--progress-increment)) 0;
|
||||
position: absolute;
|
||||
z-index: -2;
|
||||
}
|
||||
@@ -351,22 +437,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
.cards:not(.is-collapsed) & {
|
||||
.cards.is-expanded & {
|
||||
inline-size: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.cards:is(.cards--considering) &:hover {
|
||||
cursor: unset;
|
||||
filter: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cards__expander-count {
|
||||
line-height: var(--column-width-collapsed);
|
||||
inline-size: var(--column-width-collapsed);
|
||||
|
||||
.cards:not(.is-collapsed) & {
|
||||
.cards.is-expanded & {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -384,7 +465,7 @@
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
|
||||
.cards:not(.is-collapsed, .cards--considering) & {
|
||||
.cards.is-expanded & {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: 0.25ch;
|
||||
@@ -394,74 +475,40 @@
|
||||
.icon--collapse {
|
||||
--icon-size: 1.15em;
|
||||
|
||||
opacity: 0;
|
||||
scale: 1.5;
|
||||
opacity: 0.66;
|
||||
transition: 150ms ease-out;
|
||||
transition-property: opacity, scale;
|
||||
|
||||
@media (min-width: 640px) {
|
||||
opacity: 0;
|
||||
scale: 1.5;
|
||||
}
|
||||
|
||||
.cards.is-collapsed & {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.cards:not(.is-collapsed) .cards__expander:hover & {
|
||||
.cards.is-expanded .cards__expander:hover & {
|
||||
opacity: 0.66;
|
||||
scale: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: I think this is legacy now? */
|
||||
.cards__heading {
|
||||
display: flex;
|
||||
font-size: var(--text-medium);
|
||||
inset-block-start: 0;
|
||||
justify-content: center;
|
||||
margin-block-start: 1px;
|
||||
margin-inline: -8px; /* enough to cover card shadows, but avoid overlapping bubbles */
|
||||
padding-block: var(--cards-gap) 0;
|
||||
position: sticky;
|
||||
z-index: 3;
|
||||
|
||||
/* Cover bubbles and cards on small viewports */
|
||||
@media (max-width: 639px) {
|
||||
margin-inline: calc(-1 * var(--cards-gap) - var(--main-padding));
|
||||
}
|
||||
|
||||
&, .cards__filter {
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.cards__filter {
|
||||
--filter-block-padding: 0.5rem;
|
||||
|
||||
background-color: var(--color-canvas);
|
||||
border-radius: 99rem;
|
||||
inline-size: auto;
|
||||
margin-block: calc(-1 * var(--filter-block-padding));
|
||||
padding-block: var(--filter-block-padding);
|
||||
}
|
||||
|
||||
dialog {
|
||||
font-weight: normal;
|
||||
text-transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Override card styles within columns
|
||||
/* Adding .board-tools here since it sits outside the cards container on mobile */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
.cards {
|
||||
.card {
|
||||
--block-space: 1em;
|
||||
--block-space-half: 0.5em;
|
||||
--card-padding-inline: 1em;
|
||||
--text-xx-large: 1.6em;
|
||||
--text-x-small: 1em;
|
||||
.cards .card,
|
||||
.board-tools {
|
||||
--block-space: 1em;
|
||||
--block-space-half: 0.5em;
|
||||
--card-padding-inline: 1em;
|
||||
--text-xx-large: 1.6em;
|
||||
--text-x-small: 1em;
|
||||
|
||||
/* Set lower limit for font size */
|
||||
font-size: clamp(0.6rem, 0.85cqi, 100px);
|
||||
}
|
||||
/* Set lower limit for font size */
|
||||
font-size: clamp(0.6rem, 0.85cqi, 100px);
|
||||
|
||||
.card__comments {
|
||||
--column-gap: 0.8ch;
|
||||
@@ -544,7 +591,7 @@
|
||||
/* Considering
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
.cards--considering {
|
||||
.cards--maybe {
|
||||
--card-color: oklch(var(--lch-blue-medium));
|
||||
|
||||
position: relative;
|
||||
@@ -598,15 +645,37 @@
|
||||
--card-padding-block: var(--block-space);
|
||||
|
||||
border: 1px solid var(--border-color);
|
||||
margin-block-end: var(--cards-gap);
|
||||
inline-size: auto;
|
||||
text-align: center;
|
||||
|
||||
@media (max-width: 639px) {
|
||||
/* On mobile, hide the tool card inside the Maybe column */
|
||||
.cards & {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#cards_container > & {
|
||||
margin: 0 3ch 1ch;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
/* On desktop, hide the tool card above the columns */
|
||||
#cards_container > & {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 800px) {
|
||||
margin: var(--column-padding) var(--column-padding) 0;
|
||||
}
|
||||
|
||||
&:has(dialog[open]) {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.separator--horizontal {
|
||||
margin-block: var(--block-space);
|
||||
.divider {
|
||||
--divider-color: oklch(var(--lch-blue-light));
|
||||
}
|
||||
|
||||
.btn--link {
|
||||
@@ -620,7 +689,7 @@
|
||||
|
||||
footer {
|
||||
font-size: var(--text-x-small);
|
||||
margin-block-end: calc(var(--block-space-half) * -1);
|
||||
margin-block: 1ch calc(var(--block-space-half) * -1);
|
||||
}
|
||||
|
||||
.overflow-count {
|
||||
@@ -671,18 +740,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Closed (Done)
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
.cards--closed {
|
||||
|
||||
}
|
||||
|
||||
/* Doing
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Surface a mini bubble if there are cards with bubbles inside */
|
||||
.cards--considering:has(.bubble:not([hidden])) .cards__expander-title,
|
||||
.cards--maybe:has(.bubble:not([hidden])) .cards__expander-title,
|
||||
.cards--maybe.is-collapsed:has(.bubble:not([hidden])) .cards__transition-container,
|
||||
.cards--doing.is-collapsed:has(.bubble:not([hidden])) .cards__transition-container {
|
||||
--bubble-color: var(--card-color, oklch(var(--lch-blue-medium)));
|
||||
--bubble-shape: 54% 46% 61% 39% / 57% 49% 51% 43%;
|
||||
@@ -703,13 +766,14 @@
|
||||
}
|
||||
|
||||
/* Maybe column: position bubble relative to the title, not the container */
|
||||
.cards--considering & {
|
||||
.cards--maybe.is-expanded & {
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
inset-block-start: 50%;
|
||||
translate: 125% -75%;
|
||||
inset-inline-start: 0;
|
||||
translate: -125% -75%;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
@@ -749,54 +813,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile columns
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
.mobile-card-columns {
|
||||
--column-gap: 8px;
|
||||
--column-padding-expanded: calc(var(--column-gap) * 2);
|
||||
--column-width-collapsed: 40px;
|
||||
--progress-increment: var(--progress-max-width) / var(--progress-max-cards);
|
||||
--progress-max-cards: 15; /* should match first geared pagination page size */
|
||||
--progress-max-width: 100%;
|
||||
|
||||
padding-inline: 3vw;
|
||||
|
||||
/* Hide on larger devices with cursors */
|
||||
@media (min-width: 520px) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.cards.is-collapsed {
|
||||
inline-size: auto;
|
||||
display: block;
|
||||
padding-block: 0.5ch;
|
||||
|
||||
.cards__expander {
|
||||
--gradient-direction: to right;
|
||||
|
||||
flex-direction: row;
|
||||
inline-size: auto;
|
||||
|
||||
&:before {
|
||||
block-size: 1px;
|
||||
inline-size: 100%;
|
||||
inset: 50% 0 auto;
|
||||
translate: 0 -50%;
|
||||
}
|
||||
|
||||
&:after {
|
||||
block-size: var(--column-width-collapsed);
|
||||
inline-size: calc(var(--column-width-collapsed) + var(--card-count) * var(--progress-increment));
|
||||
margin-inline-start: 0;
|
||||
max-inline-size: var(--progress-max-width);
|
||||
}
|
||||
}
|
||||
|
||||
.cards__expander-title {
|
||||
writing-mode: revert;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
--comment-padding-block: var(--block-space-half);
|
||||
--comment-padding-inline: var(--inline-space-double);
|
||||
--comment-max: 70ch;
|
||||
--reaction-size: 1.6875rem;
|
||||
--reaction-size: 2rem;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -15,6 +15,10 @@
|
||||
@media (min-width: 160ch) {
|
||||
padding-inline: var(--tray-size);
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
--reaction-size: 1.6875rem;
|
||||
}
|
||||
}
|
||||
|
||||
.comments__subscribers {
|
||||
|
||||
@@ -15,9 +15,5 @@
|
||||
outline-offset: -2px;
|
||||
transition: background-color 200ms;
|
||||
z-index: 1;
|
||||
|
||||
.cards__heading {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,17 +7,19 @@
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1ch;
|
||||
gap: var(--inline-space-half);
|
||||
justify-content: center;
|
||||
padding-block-start: 2px; /* prevents input focus-ring clipping on mobile */
|
||||
position: relative;
|
||||
view-transition-name: "filters";
|
||||
view-transition-name: filters;
|
||||
z-index: 1;
|
||||
|
||||
.btn {
|
||||
--btn-border-color: var(--color-ink-medium);
|
||||
--input-background: var(--color-canvas);
|
||||
}
|
||||
|
||||
&:has(dialog[open]),
|
||||
&:has([data-controller~="tooltip"]:hover) {
|
||||
z-index: calc(var(--z-nav) + 1);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
@layer base {
|
||||
/*
|
||||
Segoe UI Variable Fizzy font face configuration.
|
||||
|
||||
1. Segoe UI Variable (Weights 100-700):
|
||||
Leverages variable font features to:
|
||||
- Automatically adjust Weight (wght) dynamically within the 100-700 range.
|
||||
- Automatically manage Optical Size (opsz) based on font-size.
|
||||
|
||||
2. Segoe UI Black (Weights 800-900):
|
||||
Used as a fallback because Segoe UI Variable does not natively support 900 weight.
|
||||
This ensures a consistent bold experience across all weights.
|
||||
*/
|
||||
@font-face {
|
||||
font-family: "Segoe UI Variable Fizzy";
|
||||
src: local("Segoe UI Variable");
|
||||
font-weight: 100 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Segoe UI Variable Fizzy";
|
||||
src: local("Segoe UI Variable");
|
||||
font-weight: 100 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Segoe UI Variable Fizzy";
|
||||
src: local("Segoe UI Black");
|
||||
font-weight: 800 900;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Segoe UI Variable Fizzy";
|
||||
src: local("Segoe UI Black Italic");
|
||||
font-weight: 800 900;
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Required for the card column page on mobile, but not needed otherwise */
|
||||
:where(#global-container) {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
:where(#header) {
|
||||
position: relative;
|
||||
z-index: var(--z-nav);
|
||||
}
|
||||
|
||||
:where(#main) {
|
||||
inline-size: 100dvw;
|
||||
margin-inline: auto;
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
}
|
||||
|
||||
.notifications__status {
|
||||
--panel-border-radius: 0.5em;
|
||||
--panel-padding: var(--block-space);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -155,6 +155,10 @@
|
||||
max-inline-size: 100%;
|
||||
padding: var(--inline-space-half) var(--popup-item-padding-inline);
|
||||
text-align: start;
|
||||
|
||||
&:focus-visible {
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.popup__icon {
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
.card--new,
|
||||
.cards__decoration,
|
||||
.card-columns:before,
|
||||
.cards--considering:before {
|
||||
.cards--maybe:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
padding-inline: 0;
|
||||
}
|
||||
|
||||
.cards--considering {
|
||||
.cards--maybe {
|
||||
background: none;
|
||||
margin: 0;
|
||||
padding-inline: 1ch;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
flex-wrap: wrap;
|
||||
gap: var(--inline-space-half);
|
||||
inline-size: 100%;
|
||||
margin-block-start: calc(var(--block-space-half) / 2);
|
||||
margin-block-start: var(--block-space-half);
|
||||
margin-inline: calc(var(--column-gap) / -1);
|
||||
|
||||
&:has([open]) {
|
||||
@@ -44,6 +44,7 @@
|
||||
}
|
||||
|
||||
.reactions__trigger {
|
||||
--btn-size: var(--reaction-size);
|
||||
--btn-border-color: var(--reaction-border-color);
|
||||
|
||||
img {
|
||||
@@ -115,11 +116,13 @@
|
||||
|
||||
/* Make the avatar and delete buttons fit nicely within the reaction */
|
||||
.reaction__avatar,
|
||||
.reaction__avatar .avatar,
|
||||
.reaction__form-label,
|
||||
.reaction form {
|
||||
block-size: var(--btn-size);
|
||||
block-size: 100%;
|
||||
}
|
||||
|
||||
|
||||
.reaction__delete {
|
||||
display: none;
|
||||
|
||||
|
||||
@@ -96,12 +96,6 @@
|
||||
.overflow-clip { text-overflow: clip; white-space: nowrap; overflow: hidden; }
|
||||
.overflow-ellipsis { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
|
||||
|
||||
.overflow-hide-scrollbar::-webkit-scrollbar {
|
||||
@media (pointer: course) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.overflow-line-clamp {
|
||||
-webkit-line-clamp: var(--lines, 2);
|
||||
-webkit-box-orient: vertical;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
class Cards::DraftsController < ApplicationController
|
||||
include CardScoped
|
||||
|
||||
before_action :redirect_if_published
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
private
|
||||
def redirect_if_published
|
||||
redirect_to @card unless @card.drafted?
|
||||
end
|
||||
end
|
||||
@@ -1,18 +0,0 @@
|
||||
class Cards::EngagementsController < ApplicationController
|
||||
include CardScoped
|
||||
|
||||
def create
|
||||
case params[:engagement]
|
||||
when "doing"
|
||||
@card.engage
|
||||
when "on_deck"
|
||||
@card.move_to_on_deck
|
||||
end
|
||||
render_card_replacement
|
||||
end
|
||||
|
||||
def destroy
|
||||
@card.reconsider
|
||||
render_card_replacement
|
||||
end
|
||||
end
|
||||
@@ -5,7 +5,8 @@ class Cards::PublishesController < ApplicationController
|
||||
@card.publish
|
||||
|
||||
if add_another_param?
|
||||
redirect_to @board.cards.create!, notice: "Card added"
|
||||
card = @board.cards.create!(status: :drafted)
|
||||
redirect_to card_draft_path(card), notice: "Card added"
|
||||
else
|
||||
redirect_to @card.board
|
||||
end
|
||||
|
||||
@@ -3,6 +3,7 @@ class CardsController < ApplicationController
|
||||
|
||||
before_action :set_board, only: %i[ create ]
|
||||
before_action :set_card, only: %i[ show edit update destroy ]
|
||||
before_action :redirect_if_drafted, only: :show
|
||||
before_action :ensure_permission_to_administer_card, only: %i[ destroy ]
|
||||
|
||||
def index
|
||||
@@ -13,7 +14,7 @@ class CardsController < ApplicationController
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
card = Current.user.draft_new_card_in(@board)
|
||||
redirect_to card
|
||||
redirect_to card_draft_path(card)
|
||||
end
|
||||
|
||||
format.json do
|
||||
@@ -56,6 +57,10 @@ class CardsController < ApplicationController
|
||||
@card = Current.user.accessible_cards.find_by!(number: params[:id])
|
||||
end
|
||||
|
||||
def redirect_if_drafted
|
||||
redirect_to card_draft_path(@card) if @card.drafted?
|
||||
end
|
||||
|
||||
def ensure_permission_to_administer_card
|
||||
head :forbidden unless Current.user.can_administer_card?(@card)
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ class Users::RolesController < ApplicationController
|
||||
|
||||
def update
|
||||
@user.update!(role_params)
|
||||
redirect_to users_path
|
||||
redirect_to account_settings_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -30,7 +30,7 @@ class UsersController < ApplicationController
|
||||
@user.deactivate
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to users_path }
|
||||
format.html { redirect_to account_settings_path }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,7 +30,9 @@ module AccessesHelper
|
||||
displayed_watchers = watchers.first(8)
|
||||
overflow_count = watchers.size - 8
|
||||
|
||||
tag.strong(watchers.any? ? "Watching for new cards" : "No one is watching for new cards", class: "txt-uppercase") +
|
||||
tag.div(class: "divider divider--fade") do
|
||||
tag.strong(watchers.any? ? "Watching for new cards" : "No one is watching for new cards", class: "txt-uppercase")
|
||||
end +
|
||||
tag.div(avatar_tags(displayed_watchers), class: "board-tools__watching") do
|
||||
tag.div(data: { controller: "dialog", action: "keydown.esc->dialog#close click@document->dialog#closeOnClickOutside" }) do
|
||||
tag.button("+#{overflow_count}", class: "overflow-count btn btn--circle borderless", data: { action: "dialog#open" }, aria: { label: "Show #{overflow_count} more watchers" }) +
|
||||
|
||||
@@ -11,7 +11,7 @@ module ColumnsHelper
|
||||
end
|
||||
|
||||
def column_tag(id:, name:, drop_url:, collapsed: true, selected: nil, card_color: "var(--color-card-default)", data: {}, **properties, &block)
|
||||
classes = token_list("cards", properties.delete(:class), "is-collapsed": collapsed)
|
||||
classes = token_list("cards", properties.delete(:class), "is-collapsed": collapsed, "is-expanded": !collapsed)
|
||||
hotkeys_disabled = data[:card_hotkeys_disabled]
|
||||
|
||||
data = {
|
||||
|
||||
@@ -34,6 +34,7 @@ export default class extends Controller {
|
||||
showModalAndSubmit(event) {
|
||||
this.showModal()
|
||||
this.formTarget.requestSubmit()
|
||||
this.#restoreFocusAfterTurboFrameLoads()
|
||||
}
|
||||
|
||||
showModal() {
|
||||
@@ -51,6 +52,12 @@ export default class extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
#restoreFocusAfterTurboFrameLoads() {
|
||||
this.turboFrameTarget.addEventListener("turbo:frame-load", () => {
|
||||
this.searchInputTarget.focus()
|
||||
}, { once: true })
|
||||
}
|
||||
|
||||
#loadTurboFrame() {
|
||||
this.turboFrameTarget.src = this.searchUrlValue
|
||||
}
|
||||
|
||||
@@ -2,10 +2,11 @@ import { Controller } from "@hotwired/stimulus"
|
||||
import { nextFrame, debounce } from "helpers/timing_helpers";
|
||||
|
||||
export default class extends Controller {
|
||||
static classes = [ "collapsed", "noTransitions", "titleNotVisible" ]
|
||||
static targets = [ "column", "button", "title" ]
|
||||
static classes = [ "collapsed", "expanded", "noTransitions", "titleNotVisible" ]
|
||||
static targets = [ "column", "button", "title", "maybeColumn" ]
|
||||
static values = {
|
||||
board: String
|
||||
board: String,
|
||||
desktopBreakpoint: { type: String, default: "(min-width: 640px)" }
|
||||
}
|
||||
|
||||
initialize() {
|
||||
@@ -15,6 +16,11 @@ export default class extends Controller {
|
||||
async connect() {
|
||||
await this.#restoreColumnsDisablingTransitions()
|
||||
this.#setupIntersectionObserver()
|
||||
|
||||
this.mediaQuery = window.matchMedia(this.desktopBreakpointValue)
|
||||
this.handleDesktop = this.#handleDesktop.bind(this)
|
||||
this.mediaQuery.addEventListener("change", this.handleDesktop)
|
||||
this.handleDesktop(this.mediaQuery)
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
@@ -22,10 +28,11 @@ export default class extends Controller {
|
||||
this._intersectionObserver.disconnect()
|
||||
this._intersectionObserver = null
|
||||
}
|
||||
this.mediaQuery.removeEventListener("change", this.handleDesktop)
|
||||
}
|
||||
|
||||
toggle({ target }) {
|
||||
const column = target.closest('[data-collapsible-columns-target="column"]')
|
||||
const column = target.closest('[data-collapsible-columns-target~="column"]')
|
||||
this.#toggleColumn(column);
|
||||
}
|
||||
|
||||
@@ -41,7 +48,7 @@ export default class extends Controller {
|
||||
}
|
||||
|
||||
focusOnColumn({ target }) {
|
||||
if (this.#isCollapsed(target)) {
|
||||
if (this.#isDesktop && this.#isCollapsed(target)) {
|
||||
this.#collapseAllExcept(target)
|
||||
this.#expand(target)
|
||||
}
|
||||
@@ -74,7 +81,9 @@ export default class extends Controller {
|
||||
}
|
||||
|
||||
#collapseAllExcept(clickedColumn) {
|
||||
this.columnTargets.forEach(column => {
|
||||
const columns = this.#isDesktop ? this.columnTargets.filter(c => c !== this.maybeColumnTarget) : this.columnTargets
|
||||
|
||||
columns.forEach(column => {
|
||||
if (column !== clickedColumn) {
|
||||
this.#collapse(column)
|
||||
}
|
||||
@@ -88,17 +97,25 @@ export default class extends Controller {
|
||||
#collapse(column) {
|
||||
const key = this.#localStorageKeyFor(column)
|
||||
|
||||
this.#buttonFor(column).setAttribute("aria-expanded", "false")
|
||||
this.#buttonFor(column)?.setAttribute("aria-expanded", "false")
|
||||
column.classList.remove(this.expandedClass)
|
||||
column.classList.add(this.collapsedClass)
|
||||
localStorage.removeItem(key)
|
||||
}
|
||||
|
||||
#expand(column) {
|
||||
const key = this.#localStorageKeyFor(column)
|
||||
|
||||
this.#buttonFor(column).setAttribute("aria-expanded", "true")
|
||||
#expand(column, saveState = true) {
|
||||
this.#buttonFor(column)?.setAttribute("aria-expanded", "true")
|
||||
column.classList.remove(this.collapsedClass)
|
||||
localStorage.setItem(key, true)
|
||||
column.classList.add(this.expandedClass)
|
||||
|
||||
if (saveState) {
|
||||
const key = this.#localStorageKeyFor(column)
|
||||
localStorage.setItem(key, true)
|
||||
}
|
||||
|
||||
if (window.matchMedia('(max-width: 639px)').matches) {
|
||||
column.scrollIntoView({ behavior: "smooth", inline: "center" })
|
||||
}
|
||||
}
|
||||
|
||||
#buttonFor(column) {
|
||||
@@ -114,6 +131,7 @@ export default class extends Controller {
|
||||
#restoreColumn(column) {
|
||||
const key = this.#localStorageKeyFor(column)
|
||||
if (localStorage.getItem(key)) {
|
||||
this.#collapseAllExcept(column)
|
||||
this.#expand(column)
|
||||
}
|
||||
}
|
||||
@@ -140,4 +158,33 @@ export default class extends Controller {
|
||||
|
||||
this.titleTargets.forEach(title => this._intersectionObserver.observe(title))
|
||||
}
|
||||
|
||||
get #isDesktop() {
|
||||
return this.mediaQuery?.matches
|
||||
}
|
||||
|
||||
#handleDesktop() {
|
||||
this.#isDesktop ? this.#handleDesktopMode() : this.#handleMobileMode()
|
||||
}
|
||||
|
||||
async #handleDesktopMode() {
|
||||
this.#expand(this.maybeColumnTarget, false)
|
||||
this.#maybeButton.setAttribute("disabled", true)
|
||||
}
|
||||
|
||||
#handleMobileMode() {
|
||||
this.#maybeButton.removeAttribute("disabled")
|
||||
|
||||
const expandedColumn = this.columnTargets.find(column => column !== this.maybeColumnTarget && !this.#isCollapsed(column))
|
||||
|
||||
if (expandedColumn) {
|
||||
this.#collapseAllExcept(expandedColumn)
|
||||
} else {
|
||||
this.#collapseAllExcept(this.maybeColumnTarget)
|
||||
}
|
||||
}
|
||||
|
||||
get #maybeButton() {
|
||||
return this.maybeColumnTarget.querySelector('[data-collapsible-columns-target="button"]')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ module Card::Closeable
|
||||
def close(user: Current.user)
|
||||
unless closed?
|
||||
transaction do
|
||||
not_now&.destroy
|
||||
create_closure! user: user
|
||||
track_event :closed, creator: user
|
||||
end
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
class Card::Engagement < ApplicationRecord
|
||||
belongs_to :account, default: -> { card.account }
|
||||
belongs_to :card, class_name: "::Card", touch: true
|
||||
|
||||
validates :status, presence: true, inclusion: { in: %w[doing on_deck] }
|
||||
end
|
||||
@@ -14,7 +14,7 @@ class Event::Description
|
||||
end
|
||||
|
||||
def to_plain_text
|
||||
to_sentence(creator_name, h(card.title))
|
||||
to_sentence(creator_name, quoted(card.title))
|
||||
end
|
||||
|
||||
private
|
||||
@@ -41,6 +41,10 @@ class Event::Description
|
||||
h(event.creator.name)
|
||||
end
|
||||
|
||||
def quoted(text)
|
||||
%("#{h text}")
|
||||
end
|
||||
|
||||
def card
|
||||
@card ||= event.action.comment_created? ? event.eventable.card : event.eventable
|
||||
end
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
class Webhook::Delivery < ApplicationRecord
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
class ResponseTooLarge < StandardError; end
|
||||
|
||||
STALE_TRESHOLD = 7.days
|
||||
@@ -130,8 +132,7 @@ class Webhook::Delivery < ApplicationRecord
|
||||
elsif webhook.for_campfire?
|
||||
render_payload(formats: :html)
|
||||
elsif webhook.for_slack?
|
||||
html = render_payload(formats: :html)
|
||||
{ text: convert_html_to_mrkdwn(html) }.to_json
|
||||
slack_payload
|
||||
else
|
||||
render_payload(formats: :json)
|
||||
end
|
||||
@@ -158,4 +159,16 @@ class Webhook::Delivery < ApplicationRecord
|
||||
|
||||
document.text
|
||||
end
|
||||
|
||||
def slack_payload
|
||||
text = event.description_for(nil).to_plain_text
|
||||
url = polymorphic_url(event.eventable, base_url_options.merge(script_name: account.slug))
|
||||
|
||||
{ text: "#{text} <#{url}|Open in Fizzy>" }.to_json
|
||||
end
|
||||
|
||||
def base_url_options
|
||||
Rails.application.routes.default_url_options.presence ||
|
||||
Rails.application.config.action_mailer.default_url_options
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<div class="cards__list" data-drag-drop-item-container>
|
||||
<div class="blank-slate blank-slate--drag card card--hide-unless-empty">
|
||||
<p>Drag cards here</p>
|
||||
</div>
|
||||
<div class="blank-slate blank-slate--empty card--hide-unless-empty">No cards here</div>
|
||||
<div class="blank-slate blank-slate--drag card card--hide-unless-empty">
|
||||
<p>Drag cards here</p>
|
||||
</div>
|
||||
<div class="blank-slate blank-slate--empty card--hide-unless-empty">No cards here</div>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<div class="cards__list" data-drag-drop-item-container >
|
||||
<%= render "cards/display/previews", cards: cards, draggable: draggable %>
|
||||
</div>
|
||||
@@ -12,12 +12,14 @@
|
||||
|
||||
<section class="cards cards--grid">
|
||||
<%= turbo_frame_tag :closed_column do %>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :closed_column, @page do %>
|
||||
<%= render "boards/columns/list", cards: @page.records, draggable: true %>
|
||||
<div class="cards__list hide-scrollbar" data-drag-drop-item-container>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :closed_column, @page do %>
|
||||
<%= render "cards/display/previews", cards: @page.records, draggable: true %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render "boards/columns/empty_placeholder" %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render "boards/columns/empty_placeholder" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
@@ -12,12 +12,14 @@
|
||||
|
||||
<section class="cards cards--grid">
|
||||
<%= turbo_frame_tag :not_now_column do %>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :not_now_column, @page do %>
|
||||
<%= render "boards/columns/list", cards: @page.records, draggable: true %>
|
||||
<div class="cards__list hide-scrollbar" data-drag-drop-item-container>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :not_now_column, @page do %>
|
||||
<%= render "cards/display/previews", cards: @page.records, draggable: true %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render "boards/columns/empty_placeholder" %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render "boards/columns/empty_placeholder" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
@@ -12,12 +12,14 @@
|
||||
|
||||
<section class="cards cards--grid">
|
||||
<%= turbo_frame_tag @column, :cards do %>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination dom_id(@column, :cards), @page do %>
|
||||
<%= render "boards/columns/list", cards: @page.records, draggable: true %>
|
||||
<div class="cards__list hide-scrollbar" data-drag-drop-item-container>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination dom_id(@column, :cards), @page do %>
|
||||
<%= render "cards/display/previews", cards: @page.records, draggable: true %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render "boards/columns/empty_placeholder" %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render "boards/columns/empty_placeholder" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
@@ -12,12 +12,14 @@
|
||||
|
||||
<section class="cards cards--grid">
|
||||
<%= turbo_frame_tag :stream_column do %>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :stream_column, @page do %>
|
||||
<%= render "boards/columns/list", cards: @page.records, draggable: true %>
|
||||
<div class="cards__list hide-scrollbar" data-drag-drop-item-container>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :stream_column, @page do %>
|
||||
<%= render "cards/display/previews", cards: @page.records, draggable: true %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render "boards/columns/empty_placeholder" %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render "boards/columns/empty_placeholder" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<% @page_title = @board.name %>
|
||||
<% @body_class = "contained-scrolling" %>
|
||||
<% turbo_exempts_page_from_cache %>
|
||||
|
||||
<%= turbo_stream_from @board %>
|
||||
@@ -25,7 +26,7 @@
|
||||
<% if @filter.used?(ignore_boards: true) %>
|
||||
<%= render "boards/show/filtered_cards", page: @page %>
|
||||
<% else %>
|
||||
<%= render "columns/show/add_card_button", board: @board %>
|
||||
<%= render "boards/show/columns", page: @page, board: @board %>
|
||||
<%= render "boards/show/mobile_columns", page: @page, board: @board %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
drag_and_drop_hover_container_class: "drag-and-drop__hover-container",
|
||||
collapsible_columns_board_value: board.id,
|
||||
collapsible_columns_collapsed_class: "is-collapsed",
|
||||
collapsible_columns_expanded_class: "is-expanded",
|
||||
collapsible_columns_no_transitions_class: "no-transitions",
|
||||
collapsible_columns_title_not_visible_class: "is-off-screen",
|
||||
navigable_list_supports_vertical_navigation_value: false,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<section class="cards cards--grid">
|
||||
<%= with_automatic_pagination :filtered_cards_paginated_container, page do %>
|
||||
<%= render "cards/display/previews", cards: page.records, draggable: true %>
|
||||
<% end %>
|
||||
<div class="blank-slate blank-slate--empty blank-slate--filters">No cards match this filter</div>
|
||||
<div class="cards__list hide-scrollbar">
|
||||
<%= with_automatic_pagination :filtered_cards_paginated_container, page do %>
|
||||
<%= render "cards/display/previews", cards: page.records, draggable: true %>
|
||||
<% end %>
|
||||
<div class="blank-slate blank-slate--empty blank-slate--filters">No cards match this filter</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
<% postponed_count = board.cards.postponed.size %>
|
||||
<% awaiting_triage_count = board.cards.awaiting_triage.size %>
|
||||
<% closed_count = board.cards.closed.size %>
|
||||
|
||||
<section class="mobile-card-columns">
|
||||
<div class="cards margin-block-end-half">
|
||||
<%= render "columns/show/add_card_button", board: board %>
|
||||
</div>
|
||||
|
||||
<%= link_to board_columns_not_now_path(board), class: "cards cards--on-deck is-collapsed", style: "--card-color: var(--color-card-complete);", data: { turbo_frame: "_top" } do %>
|
||||
<div class="cards__expander btn btn--plain" style="--card-count: <%= postponed_count %>">
|
||||
<span class="cards__expander-count"><%= postponed_count %></span>
|
||||
<h2 class="cards__expander-title">
|
||||
Not Now
|
||||
</h2>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= link_to board_columns_stream_path(board), class: "cards cards--considering is-collapsed", data: { turbo_frame: "_top" } do %>
|
||||
<div class="cards__expander btn btn--plain" style="--card-count: <%= awaiting_triage_count %>">
|
||||
<span class="cards__expander-count"><%= awaiting_triage_count %></span>
|
||||
<h2 class="cards__expander-title">
|
||||
Maybe?
|
||||
</h2>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% board.columns.sorted.each do |column| %>
|
||||
<% active_count = column.cards.active.size %>
|
||||
<%= link_to board_column_path(column.board, column), class: "cards cards--doing is-collapsed", style: "--card-color: #{column.color}", data: { turbo_frame: "_top" } do %>
|
||||
<div class="cards__expander btn btn--plain" style="--card-count: <%= active_count %>">
|
||||
<span class="cards__expander-count"><%= active_count %></span>
|
||||
<h2 class="cards__expander-title">
|
||||
<%= column.name %>
|
||||
</h2>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= link_to board_columns_closed_path(board), class: "cards cards--closed is-collapsed", style: "--card-color: var(--color-card-complete);", data: { turbo_frame: "_top" } do %>
|
||||
<div class="cards__expander btn btn--plain" style="--card-count: <%= closed_count %>">
|
||||
<span class="cards__expander-count"><%= closed_count %></span>
|
||||
<h2 class="cards__expander-title">
|
||||
Done
|
||||
</h2>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
@@ -1,20 +1,18 @@
|
||||
<%= column_tag id: "the-stream", name: "Maybe?", drop_url: columns_card_drops_stream_path("__id__"), collapsed: false, selected: "true", class: "cards--considering" do %>
|
||||
<%= column_tag id: "maybe", name: "Maybe?", drop_url: columns_card_drops_stream_path("__id__"), collapsed: false, selected: "true", class: "cards--maybe", data: {
|
||||
drag_and_strum_target: "container",
|
||||
collapsible_columns_target: "column maybeColumn",
|
||||
action: "focus->collapsible-columns#focusOnColumn"
|
||||
} do %>
|
||||
<header class="cards__header">
|
||||
<div class="cards__expander">
|
||||
<h2 class="cards__expander-title" data-collapsible-columns-target="title">Maybe?</h2>
|
||||
</div>
|
||||
<%= link_to board_columns_stream_path(board), class: "cards__maximize-button btn btn--circle txt-x-small borderless", data: { turbo_frame: "_top" } do %>
|
||||
<%= icon_tag "grid", class: "translucent" %>
|
||||
<span class="for-screen-reader">Expand column</span>
|
||||
<% end %>
|
||||
<%= render "boards/show/expander", title: "Maybe?", count: board.cards.awaiting_triage.count, column_id: "maybe" %>
|
||||
<%= render "boards/show/menu/maximize", column_path: board_columns_stream_path(board) %>
|
||||
</header>
|
||||
<%= render "columns/show/add_card_button", board: board %>
|
||||
<% if page.used? %>
|
||||
<%= with_automatic_pagination "the-stream", @page do %>
|
||||
<%= render "boards/columns/list", cards: page.records, draggable: true %>
|
||||
<div class="cards__list hide-scrollbar" data-drag-drop-item-container>
|
||||
<% if page.used? %>
|
||||
<%= with_automatic_pagination "maybe", @page do %>
|
||||
<%= render "cards/display/previews", cards: page.records, draggable: true %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="cards__list" data-drag-drop-item-container>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="cards__new-column position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside" data-turbo-permanent>
|
||||
<div class="cards__new-column" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside" data-turbo-permanent>
|
||||
<button class="btn btn--circle txt-x-small borderless" data-controller="tooltip" data-action="click->dialog#open:stop">
|
||||
<%= icon_tag "add", class: "translucent" %>
|
||||
<span class="for-screen-reader">Add a column</span>
|
||||
|
||||
@@ -16,6 +16,8 @@ json.cache! card do
|
||||
json.board card.board, partial: "boards/board", as: :board
|
||||
json.column card.column, partial: "columns/column", as: :column if card.column
|
||||
json.creator card.creator, partial: "users/user", as: :user
|
||||
json.assignees card.assignees.limit(5), partial: "users/user", as: :user
|
||||
json.has_more_assignees card.assignees.size > 5
|
||||
|
||||
json.comments_url card_comments_url(card)
|
||||
end
|
||||
|
||||
@@ -37,11 +37,5 @@
|
||||
|
||||
<% if card.published? %>
|
||||
<%= render "cards/container/footer/published", card: card %>
|
||||
<% elsif card.drafted? %>
|
||||
<% if Fizzy.saas? %>
|
||||
<%= render "cards/container/footer/saas/create", card: card %>
|
||||
<% else %>
|
||||
<%= render "cards/container/footer/create", card: card %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<section id="<%= dom_id(card, :card_container) %>" class="card-perma" style="--card-color: <%= card.color %>;">
|
||||
<% cache card do %>
|
||||
<div class="card-perma__actions card-perma__actions--left">
|
||||
<%= render "cards/container/image", card: card %>
|
||||
</div>
|
||||
|
||||
<div class="card-perma__bg">
|
||||
<%= card_article_tag card, class: "card" do %>
|
||||
<header class="card__header">
|
||||
<%= render "cards/display/perma/board", card: card %>
|
||||
<%= render "cards/display/perma/tags", card: card %>
|
||||
</header>
|
||||
|
||||
<div class="card__body justify-space-between">
|
||||
<div class="card__content">
|
||||
<%= render "cards/container/content", card: card %>
|
||||
<%= render "cards/display/perma/steps", card: card %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="card__footer full-width flex align-start gap">
|
||||
<%= render "cards/display/perma/meta", card: card %>
|
||||
<%= render "cards/display/perma/background", card: card %>
|
||||
</footer>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if Fizzy.saas? %>
|
||||
<%= render "cards/container/footer/saas/create", card: card %>
|
||||
<% else %>
|
||||
<%= render "cards/container/footer/create", card: card %>
|
||||
<% end %>
|
||||
</section>
|
||||
@@ -0,0 +1,16 @@
|
||||
<% @page_title = @card.title %>
|
||||
<% @header_class = "header--card" %>
|
||||
|
||||
<% content_for :header do %>
|
||||
<div class="header__actions header__actions--start">
|
||||
<%= link_back_to_board(@card.board) %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div data-controller="beacon lightbox" data-beacon-url-value="<%= card_reading_path(@card) %>">
|
||||
<%= render "cards/drafts/container", card: @card %>
|
||||
|
||||
<%= render "layouts/lightbox" do %>
|
||||
<%= button_to_remove_card_image(@card) if @card.image.attached? %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -19,9 +19,11 @@
|
||||
|
||||
<%= turbo_frame_tag :cards_container do %>
|
||||
<section class="cards cards--grid">
|
||||
<%= with_automatic_pagination :cards_paginated_container, @page do %>
|
||||
<%= render "cards/display/previews", cards: @page.records, draggable: true %>
|
||||
<% end %>
|
||||
<div class="blank-slate blank-slate--empty blank-slate--filters">No cards match this filter</div>
|
||||
<div class="cards__list hide-scrollbar">
|
||||
<%= with_automatic_pagination :cards_paginated_container, @page do %>
|
||||
<%= render "cards/display/previews", cards: @page.records, draggable: true %>
|
||||
<% end %>
|
||||
<div class="blank-slate blank-slate--empty blank-slate--filters">No cards match this filter</div>
|
||||
</div>
|
||||
</section>
|
||||
<% end %>
|
||||
|
||||
@@ -16,7 +16,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.drafted? %>
|
||||
<%= render "cards/messages", card: @card %>
|
||||
|
||||
<%= render "layouts/lightbox" do %>
|
||||
<%= button_to_remove_card_image(@card) if @card.image.attached? %>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<%= turbo_stream.replace("the-stream", partial: "boards/show/stream", method: :morph, locals:{ board: @card.board, page: @page }) %>
|
||||
<%= turbo_stream.replace("maybe", partial: "boards/show/stream", method: :morph, locals:{ board: @card.board, page: @page }) %>
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
<kbd class="hide-on-touch">C</kbd>
|
||||
<% end %>
|
||||
|
||||
<hr class="separator--horizontal full-width" aria-hidden="true">
|
||||
|
||||
<footer>
|
||||
<%= access_involvement_advance_button(board, Current.user, show_watchers: true) %>
|
||||
</footer>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<% filter = user_filtering.filter %>
|
||||
|
||||
<div class="filters__manage gap-half">
|
||||
<%= link_to root_path, class: "btn btn--remove txt-x-small", data: { controller: "hotkey tooltip", action: "keydown.esc@document->hotkey#click"} do %>
|
||||
<%= link_to no_filtering_url, class: "btn btn--remove txt-x-small", data: { controller: "hotkey tooltip", action: "keydown.esc@document->hotkey#click"} do %>
|
||||
<%= icon_tag "close" %>
|
||||
<span class="for-screen-reader">Clear all</span>
|
||||
<% end %>
|
||||
|
||||
@@ -2,19 +2,21 @@
|
||||
<html lang="en">
|
||||
<%= render "layouts/shared/head" %>
|
||||
|
||||
<body data-controller="local-time timezone-cookie turbo-navigation theme" data-action="turbo:morph@window->local-time#refreshAll turbo:before-visit@document->turbo-navigation#rememberLocation" data-platform="<%= platform.type %>">
|
||||
<header class="header header--mobile-actions-stack <%= @header_class %>" id="header">
|
||||
<a href="#main" class="header__skip-navigation btn" data-turbo="false">Skip to main content</a>
|
||||
<%= render "my/menu" if Current.user %>
|
||||
<%= yield :header %>
|
||||
</header>
|
||||
<body class="<%= @body_class %>" data-controller="local-time timezone-cookie turbo-navigation theme" data-action="turbo:morph@window->local-time#refreshAll turbo:before-visit@document->turbo-navigation#rememberLocation" data-platform="<%= platform.type %>">
|
||||
<div id="global-container">
|
||||
<header class="header header--mobile-actions-stack <%= @header_class %>" id="header">
|
||||
<a href="#main" class="header__skip-navigation btn" data-turbo="false">Skip to main content</a>
|
||||
<%= render "my/menu" if Current.user %>
|
||||
<%= yield :header %>
|
||||
</header>
|
||||
|
||||
<%= render "layouts/shared/flash" %>
|
||||
<%= render "layouts/shared/time_zone" if Current.user %>
|
||||
<%= render "layouts/shared/flash" %>
|
||||
<%= render "layouts/shared/time_zone" if Current.user %>
|
||||
|
||||
<main id="main">
|
||||
<%= yield %>
|
||||
</main>
|
||||
<main id="main">
|
||||
<%= yield %>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer id="footer" class="hide-on-native">
|
||||
<%= yield :footer %>
|
||||
|
||||
@@ -2,24 +2,26 @@
|
||||
<html lang="en">
|
||||
<%= render "layouts/shared/head" %>
|
||||
|
||||
<body class="public" data-controller="local-time timezone-cookie" data-action="turbo:morph@window->local-time#refreshAll">
|
||||
<header class="header" id="header">
|
||||
<a href="#main" class="header__skip-navigation btn" data-turbo="false">Skip to main content</a>
|
||||
<nav>
|
||||
<%= link_to "https://fizzy.do", class: "header__logo center flex-inline align-center" do %>
|
||||
<span><%= image_tag "logo.png", alt: "" %></span>
|
||||
<svg height="30" viewBox="0 0 96 30" width="96" xmlns="http://www.w3.org/2000/svg" title="Fizzy"><path clip-rule="evenodd" d="m93.5609 8.52856c.9033.04314 1.3769.47352 1.4199 1.33398.1291 2.40966.0859 5.24976.1289 7.48726l.1289 7.3575c0 15.4902-10.2406 15.8354-16.8242 14.7168-.8606-.1722-1.2482-.7322-1.1621-1.5928l.3867-3.7002c.086-1.0327.732-1.2905 1.6787-.9463 4.3889 1.5919 9.122-.4737 9.0791-4.7334 0-1.0757-.6026-1.2052-1.2481-.3877-.9036 1.0757-2.2802 2.1943-4.3886 2.1944-3.0552 0-8.2188-1.2046-8.2188-11.962 0-2.6677-.086-5.5076-.0429-8.47652 0-.90362.5162-1.37702 1.4199-1.33399 1.2048.04302 2.3665.00006 3.5283-.04297.9036 0 1.4199.47328 1.4199 1.41992 0 3.22686-.0859 5.63626-.0859 6.45406 0 7.7023 1.7647 8.2187 3.7871 8.2618 2.1512.0427 3.5709-1.5491 3.8291-5.2061v-.9902c0-4.604.0861-6.2821-.043-8.47659-.086-.9036.3444-1.41986 1.2481-1.46289zm-43.4629-.21484c1.1186-.04303 1.5064.68823.9472 1.63476-1.8502 3.05502-5.3796 8.73462-8.3486 13.42482-.4733.7745-.1713 1.334.7754 1.334 2.1511.043 2.9261.0431 5.5937-.086.9464-.0429 1.4199.4306 1.42 1.377-.0431.8605-.0001 1.8504 0 2.7109 0 .9036-.4305 1.3769-1.334 1.377-3.9588.043-9.4238-.1721-15.6201-.043-1.1618 0-1.5487-.6881-.9463-1.6348l8.3906-13.2099c.4733-.7315.1721-1.3769-.7315-1.377-2.4096-.043-4.9915.0429-6.8418.1289-.9036.0431-1.4199-.3874-1.4199-1.291-.043-.9035 0-1.9792 0-2.92576 0-.86059.7316-1.33399 2.0225-1.33399 6.1531.04303 12.1341-.04291 16.0928-.08593zm21.1367 0c1.1186-.04294 1.5056.68817.9463 1.63476-1.8503 3.05502-5.3787 8.73462-8.3477 13.42482-.4733.7745-.1721 1.3339.7744 1.334 2.1514.043 2.9261.0431 5.5938-.086.9465-.043 1.4198.4305 1.4199 1.377-.043.8605 0 1.8504 0 2.7109 0 .9036-.4304 1.377-1.334 1.377-3.9586.043-9.4232-.1721-15.6191-.043-1.1617 0-1.5494-.6883-.9473-1.6348l8.3916-13.2099c.4733-.7315.1712-1.377-.7324-1.377-2.4096-.043-4.9916.0429-6.8418.1289-.9033.0429-1.4199-.3875-1.4199-1.291-.0431-.9035 0-1.9792 0-2.92576 0-.86051.7318-1.3339 2.0224-1.33399 6.1533.04303 12.135-.04291 16.0938-.08593zm-43.3252.25781c.9035-.04295 1.4199.38753 1.4199 1.24805.043 1.50602 0 3.65782 0 12.39262 0 5.6796-.086 5.4215 0 6.4111.1291.9036-.3444 1.4198-1.248 1.4629l-3.9161-.086c-.8604-.0431-1.3769-.4735-1.4199-1.3339-.1291-2.4097-.0859-5.2499-.1289-7.4874-.1291-5.5505-.0429-7.8742-.0859-11.23042-.043-.90357.4733-1.37695 1.4199-1.37695 1.7212.08606 2.8832.08606 3.959 0zm-21.88185-8.56250162c2.36657.04302752 4.77645.00000269 8.30465 0 1.2909 0 3.0554.04302142 4.6905 0 .7314 0 1.119.38683562 1.1191 1.16113162-.043 1.46292-.086 3.3134-.043 4.77637 0 .77451-.4305 1.11924-1.205 1.0332-1.2909-.12909-3.3564-.25866-5.5079-.34473-2.0653-.12908-2.1945.04296-4.25972.04297-.8606 0-1.42065.43055-1.59277 1.20508v.04297c-.12909.64544-.12891 1.03327-.12891 1.67871v.51567c.04303.9035.51653 1.3338 1.37696 1.3769 2.40954.043 5.46464.0002 7.70214-.1289.7315-.043 1.1621.3016 1.1621 1.0762l-.0859 4.3886c0 .7315-.4306 1.1192-1.1621 1.0762-2.2374-.043-4.7329-.0439-7.35746-.0869-.9035-.043-1.37677.4736-1.41992 1.334l-.17285 4.3467c0 2.6244.04379 4.0872.17285 5.292.12909.7315-.25872 1.1621-.99023 1.1621l-5.29297.0429c-.731221-.0001-1.075196-.3877-1.075196-1.1191-.000045-1.2478-.2149575-2.8399-.128907-5.7656.129086-5.7659.085256-13.7261-.12988242-21.81546-.04302878-.774508.34469842-1.162087 1.07617542-1.162105 1.592-.0430291 3.70034-.1719109 4.94824-.12890662zm19.90235.34374962c2.6247.00004 3.5283 1.377542 3.5283 3.055662-.0001 1.72099-.9038 3.09762-3.5283 3.09766-2.6677 0-3.5712-1.37665-3.5713-3.09766 0-1.67815.9034-3.055662 3.5713-3.055662z" fill="currentColor" fill-rule="evenodd"/></svg>
|
||||
<% end %>
|
||||
</nav>
|
||||
<body class="public <%= @body_class %>" data-controller="local-time timezone-cookie" data-action="turbo:morph@window->local-time#refreshAll">
|
||||
<div id="global-container">
|
||||
<header class="header" id="header">
|
||||
<a href="#main" class="header__skip-navigation btn" data-turbo="false">Skip to main content</a>
|
||||
<nav>
|
||||
<%= link_to "https://fizzy.do", class: "header__logo center flex-inline align-center" do %>
|
||||
<span><%= image_tag "logo.png", alt: "" %></span>
|
||||
<svg height="30" viewBox="0 0 96 30" width="96" xmlns="http://www.w3.org/2000/svg" title="Fizzy"><path clip-rule="evenodd" d="m93.5609 8.52856c.9033.04314 1.3769.47352 1.4199 1.33398.1291 2.40966.0859 5.24976.1289 7.48726l.1289 7.3575c0 15.4902-10.2406 15.8354-16.8242 14.7168-.8606-.1722-1.2482-.7322-1.1621-1.5928l.3867-3.7002c.086-1.0327.732-1.2905 1.6787-.9463 4.3889 1.5919 9.122-.4737 9.0791-4.7334 0-1.0757-.6026-1.2052-1.2481-.3877-.9036 1.0757-2.2802 2.1943-4.3886 2.1944-3.0552 0-8.2188-1.2046-8.2188-11.962 0-2.6677-.086-5.5076-.0429-8.47652 0-.90362.5162-1.37702 1.4199-1.33399 1.2048.04302 2.3665.00006 3.5283-.04297.9036 0 1.4199.47328 1.4199 1.41992 0 3.22686-.0859 5.63626-.0859 6.45406 0 7.7023 1.7647 8.2187 3.7871 8.2618 2.1512.0427 3.5709-1.5491 3.8291-5.2061v-.9902c0-4.604.0861-6.2821-.043-8.47659-.086-.9036.3444-1.41986 1.2481-1.46289zm-43.4629-.21484c1.1186-.04303 1.5064.68823.9472 1.63476-1.8502 3.05502-5.3796 8.73462-8.3486 13.42482-.4733.7745-.1713 1.334.7754 1.334 2.1511.043 2.9261.0431 5.5937-.086.9464-.0429 1.4199.4306 1.42 1.377-.0431.8605-.0001 1.8504 0 2.7109 0 .9036-.4305 1.3769-1.334 1.377-3.9588.043-9.4238-.1721-15.6201-.043-1.1618 0-1.5487-.6881-.9463-1.6348l8.3906-13.2099c.4733-.7315.1721-1.3769-.7315-1.377-2.4096-.043-4.9915.0429-6.8418.1289-.9036.0431-1.4199-.3874-1.4199-1.291-.043-.9035 0-1.9792 0-2.92576 0-.86059.7316-1.33399 2.0225-1.33399 6.1531.04303 12.1341-.04291 16.0928-.08593zm21.1367 0c1.1186-.04294 1.5056.68817.9463 1.63476-1.8503 3.05502-5.3787 8.73462-8.3477 13.42482-.4733.7745-.1721 1.3339.7744 1.334 2.1514.043 2.9261.0431 5.5938-.086.9465-.043 1.4198.4305 1.4199 1.377-.043.8605 0 1.8504 0 2.7109 0 .9036-.4304 1.377-1.334 1.377-3.9586.043-9.4232-.1721-15.6191-.043-1.1617 0-1.5494-.6883-.9473-1.6348l8.3916-13.2099c.4733-.7315.1712-1.377-.7324-1.377-2.4096-.043-4.9916.0429-6.8418.1289-.9033.0429-1.4199-.3875-1.4199-1.291-.0431-.9035 0-1.9792 0-2.92576 0-.86051.7318-1.3339 2.0224-1.33399 6.1533.04303 12.135-.04291 16.0938-.08593zm-43.3252.25781c.9035-.04295 1.4199.38753 1.4199 1.24805.043 1.50602 0 3.65782 0 12.39262 0 5.6796-.086 5.4215 0 6.4111.1291.9036-.3444 1.4198-1.248 1.4629l-3.9161-.086c-.8604-.0431-1.3769-.4735-1.4199-1.3339-.1291-2.4097-.0859-5.2499-.1289-7.4874-.1291-5.5505-.0429-7.8742-.0859-11.23042-.043-.90357.4733-1.37695 1.4199-1.37695 1.7212.08606 2.8832.08606 3.959 0zm-21.88185-8.56250162c2.36657.04302752 4.77645.00000269 8.30465 0 1.2909 0 3.0554.04302142 4.6905 0 .7314 0 1.119.38683562 1.1191 1.16113162-.043 1.46292-.086 3.3134-.043 4.77637 0 .77451-.4305 1.11924-1.205 1.0332-1.2909-.12909-3.3564-.25866-5.5079-.34473-2.0653-.12908-2.1945.04296-4.25972.04297-.8606 0-1.42065.43055-1.59277 1.20508v.04297c-.12909.64544-.12891 1.03327-.12891 1.67871v.51567c.04303.9035.51653 1.3338 1.37696 1.3769 2.40954.043 5.46464.0002 7.70214-.1289.7315-.043 1.1621.3016 1.1621 1.0762l-.0859 4.3886c0 .7315-.4306 1.1192-1.1621 1.0762-2.2374-.043-4.7329-.0439-7.35746-.0869-.9035-.043-1.37677.4736-1.41992 1.334l-.17285 4.3467c0 2.6244.04379 4.0872.17285 5.292.12909.7315-.25872 1.1621-.99023 1.1621l-5.29297.0429c-.731221-.0001-1.075196-.3877-1.075196-1.1191-.000045-1.2478-.2149575-2.8399-.128907-5.7656.129086-5.7659.085256-13.7261-.12988242-21.81546-.04302878-.774508.34469842-1.162087 1.07617542-1.162105 1.592-.0430291 3.70034-.1719109 4.94824-.12890662zm19.90235.34374962c2.6247.00004 3.5283 1.377542 3.5283 3.055662-.0001 1.72099-.9038 3.09762-3.5283 3.09766-2.6677 0-3.5712-1.37665-3.5713-3.09766 0-1.67815.9034-3.055662 3.5713-3.055662z" fill="currentColor" fill-rule="evenodd"/></svg>
|
||||
<% end %>
|
||||
</nav>
|
||||
|
||||
<%= yield :header %>
|
||||
</header>
|
||||
<%= yield :header %>
|
||||
</header>
|
||||
|
||||
<%= render "layouts/shared/flash" %>
|
||||
<%= render "layouts/shared/flash" %>
|
||||
|
||||
<main id="main">
|
||||
<%= yield %>
|
||||
</main>
|
||||
<main id="main">
|
||||
<%= yield %>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer id="footer">
|
||||
<%= yield :footer %>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<div data-navigable-list-target="item" class="full-width">
|
||||
<%= link_to notifications_settings_path,
|
||||
class: "btn borderless tray__notification-settings",
|
||||
title: "Notification settings",
|
||||
title: "Notification Settings",
|
||||
data: { action: "dialog#close" } do %>
|
||||
<%= icon_tag "settings" %>
|
||||
<span>Settings</span>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<li>Click <em aria-label="the Apple menu"></em> in the top left.</li>
|
||||
<li>Click <em>System Settings…</em>.</li>
|
||||
<li>Click <em>Notifications</em>.</li>
|
||||
<li>Click <em><%= platform.browser.capitalize %></em>.</li>
|
||||
<li>Click <em><%= platform.browser == "Chrome" ? "Google Chrome" : platform.browser.capitalize %></em>.</li>
|
||||
<li>Click <em><%= icon_tag "switch", alt: "the switch" %></em> to <em>Allow notifications</em>.</li>
|
||||
<% end %>
|
||||
</ol>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<% @page_title = "Notifications settings" %>
|
||||
<% @page_title = "Notification Settings" %>
|
||||
|
||||
<% content_for :header do %>
|
||||
<h1 class="header__title"><%= @page_title %></h1>
|
||||
<% end %>
|
||||
|
||||
<section class="settings">
|
||||
<section class="settings margin-block-start-half">
|
||||
<div class="settings__panel settings__panel--users panel shadow center">
|
||||
<h2 class="txt-medium txt-uppercase divider">Boards</h2>
|
||||
<div class="settings__user-list flex flex-column gap-half">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="panel margin-block-double center shadow">
|
||||
<h1 class="font-black txt-x-large margin-none-block-end">You’re unsubscribed</h1>
|
||||
<p class="margin-block-start-half">Thanks, <%= @user.first_name %>! Fizzy won’t send you any more email notifications. If you change your mind you can turn them back on in <%= link_to "Notifications Settings", notifications_settings_path %>.</p>
|
||||
<p class="margin-block-start-half">Thanks, <%= @user.first_name %>! Fizzy won’t send you any more email notifications. If you change your mind, you can turn them back on in <%= link_to "Notification Settings", notifications_settings_path %>.</p>
|
||||
|
||||
<%= link_to root_path, class: "btn btn--link margin-block-start" do %>
|
||||
<%= icon_tag "arrow-left" %>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<div class="cards__list">
|
||||
<%= render "cards/display/public_previews", cards: cards %>
|
||||
</div>
|
||||
@@ -12,13 +12,15 @@
|
||||
|
||||
<section class="cards cards--grid">
|
||||
<%= turbo_frame_tag :closed_column do %>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :closed_column, @page do %>
|
||||
<%= render "public/boards/columns/list", cards: @page.records %>
|
||||
<div class="cards__list hide-scrollbar">
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :closed_column, @page do %>
|
||||
<%= render "cards/display/public_previews", cards: @page.records %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="blank-slate blank-slate--empty">No cards here</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="blank-slate blank-slate--empty">No cards here</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -12,13 +12,15 @@
|
||||
|
||||
<section class="cards cards--grid">
|
||||
<%= turbo_frame_tag :not_now_column do %>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :not_now_column, @page do %>
|
||||
<%= render "public/boards/columns/list", cards: @page.records %>
|
||||
<div class="cards__list hide-scrollbar">
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :not_now_column, @page do %>
|
||||
<%= render "cards/display/public_previews", cards: @page.records %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="blank-slate blank-slate--empty">No cards here</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="blank-slate blank-slate--empty">No cards here</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -12,13 +12,15 @@
|
||||
|
||||
<section class="cards cards--grid">
|
||||
<%= turbo_frame_tag @column, :cards do %>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination dom_id(@column, :cards), @page do %>
|
||||
<%= render "public/boards/columns/list", cards: @page.records %>
|
||||
<div class="cards__list hide-scrollbar">
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination dom_id(@column, :cards), @page do %>
|
||||
<%= render "cards/display/public_previews", cards: @page.records %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="blank-slate blank-slate--empty">No cards here</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="blank-slate blank-slate--empty">No cards here</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -12,13 +12,15 @@
|
||||
|
||||
<section class="cards cards--grid">
|
||||
<%= turbo_frame_tag :stream_column do %>
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :stream_column, @page do %>
|
||||
<%= render "public/boards/columns/list", cards: @page.records %>
|
||||
<div class="cards__list hide-scrollbar">
|
||||
<% if @page.used? %>
|
||||
<%= with_automatic_pagination :stream_column, @page do %>
|
||||
<%= render "cards/display/public_previews", cards: @page.records %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="blank-slate blank-slate--empty">No cards here</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="blank-slate blank-slate--empty">No cards here</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<% @page_title = @board.name %>
|
||||
<% @body_class = "contained-scrolling" %>
|
||||
|
||||
<% content_for :head do %>
|
||||
<%= tag.meta property: "og:title", content: "#{@board.name} | #{Current.account.name}" %>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
data-controller="collapsible-columns"
|
||||
data-collapsible-columns-board-value="<%= board.id %>"
|
||||
data-collapsible-columns-collapsed-class="is-collapsed"
|
||||
data-collapsible-columns-expanded-class="is-expanded"
|
||||
data-collapsible-columns-no-transitions-class="no-transitions"
|
||||
data-collapsible-columns-title-not-visible-class="is-off-screen">
|
||||
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
<section id="the-stream" class="cards cards--considering" data-column-name="Maybe?"
|
||||
<section id="maybe"
|
||||
class="cards cards--maybe is-expanded"
|
||||
data-column-name="Maybe?"
|
||||
data-collapsible-columns-target="column maybeColumn"
|
||||
data-action="turbo:before-morph-attribute->collapsible-columns#preventToggle">
|
||||
<div class="cards__transition-container">
|
||||
<header class="cards__header">
|
||||
<div class="cards__expander">
|
||||
<div hidden class="cards__expander">
|
||||
<h2 class="cards__expander-title" data-collapsible-columns-target="title">Maybe?</h2>
|
||||
</div>
|
||||
|
||||
<%# render "boards/show/expander", title: "Maybe?", count: column.cards.active.count, column_id: dom_id(column) %>
|
||||
<%= render "boards/show/expander", title: "Maybe?", count: 2, column_id: "maybe" %>
|
||||
|
||||
<%= link_to public_board_columns_stream_url(board.publication.key), class: "cards__maximize-button btn btn--circle txt-x-small borderless", data: { turbo_frame: "_top" } do %>
|
||||
<%= icon_tag "grid", class: "translucent" %>
|
||||
<span class="for-screen-reader">Maximize column</span>
|
||||
|
||||
@@ -26,7 +26,7 @@ Rails.application.configure do
|
||||
config.cache_store = :memory_store
|
||||
config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{2.days.to_i}" }
|
||||
else
|
||||
config.action_controller.perform_caching = true
|
||||
config.action_controller.perform_caching = false
|
||||
|
||||
config.cache_store = :null_store
|
||||
end
|
||||
|
||||
@@ -90,6 +90,11 @@ Rails.application.configure do
|
||||
# Prepend all log lines with the following tags.
|
||||
config.log_tags = [ :request_id ]
|
||||
|
||||
# "info" includes generic and useful information about system operation, but avoids logging too much
|
||||
# information to avoid inadvertent exposure of personally identifiable information (PII). If you
|
||||
# want to log everything, set the level to "debug".
|
||||
config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info")
|
||||
|
||||
# Use a different cache store in production.
|
||||
config.cache_store = :solid_cache_store
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ Rails.application.routes.draw do
|
||||
|
||||
resources :cards do
|
||||
scope module: :cards do
|
||||
resource :draft, only: :show
|
||||
resource :board
|
||||
resource :closure
|
||||
resource :column
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
class DropCardEngagements < ActiveRecord::Migration[8.2]
|
||||
def up
|
||||
drop_table :card_engagements
|
||||
end
|
||||
|
||||
def down
|
||||
create_table :card_engagements, id: :uuid do |t|
|
||||
t.references :account, type: :uuid, null: false
|
||||
t.references :card, type: :uuid, null: false, index: true
|
||||
t.string :status, null: false
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :card_engagements, [ :account_id, :status ]
|
||||
end
|
||||
end
|
||||
Generated
+1
-11
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.2].define(version: 2025_12_10_054934) do
|
||||
ActiveRecord::Schema[8.2].define(version: 2025_12_19_120755) do
|
||||
create_table "accesses", id: :uuid, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||
t.datetime "accessed_at"
|
||||
t.uuid "account_id", null: false
|
||||
@@ -169,16 +169,6 @@ ActiveRecord::Schema[8.2].define(version: 2025_12_10_054934) do
|
||||
t.index ["card_id"], name: "index_card_activity_spikes_on_card_id", unique: true
|
||||
end
|
||||
|
||||
create_table "card_engagements", id: :uuid, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||
t.uuid "account_id", null: false
|
||||
t.uuid "card_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.string "status", default: "doing", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["account_id", "status"], name: "index_card_engagements_on_account_id_and_status"
|
||||
t.index ["card_id"], name: "index_card_engagements_on_card_id"
|
||||
end
|
||||
|
||||
create_table "card_goldnesses", id: :uuid, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||
t.uuid "account_id", null: false
|
||||
t.uuid "card_id", null: false
|
||||
|
||||
+1
-11
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.2].define(version: 2025_12_10_054934) do
|
||||
ActiveRecord::Schema[8.2].define(version: 2025_12_19_120755) do
|
||||
create_table "accesses", id: :uuid, force: :cascade do |t|
|
||||
t.datetime "accessed_at"
|
||||
t.uuid "account_id", null: false
|
||||
@@ -169,16 +169,6 @@ ActiveRecord::Schema[8.2].define(version: 2025_12_10_054934) do
|
||||
t.index ["card_id"], name: "index_card_activity_spikes_on_card_id", unique: true
|
||||
end
|
||||
|
||||
create_table "card_engagements", id: :uuid, force: :cascade do |t|
|
||||
t.uuid "account_id", null: false
|
||||
t.uuid "card_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.string "status", limit: 255, default: "doing", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["account_id", "status"], name: "index_card_engagements_on_account_id_and_status"
|
||||
t.index ["card_id"], name: "index_card_engagements_on_card_id"
|
||||
end
|
||||
|
||||
create_table "card_goldnesses", id: :uuid, force: :cascade do |t|
|
||||
t.uuid "account_id", null: false
|
||||
t.uuid "card_id", null: false
|
||||
|
||||
@@ -45,7 +45,7 @@ bin/rails secret
|
||||
Once you have one, set it in the `SECRET_KEY_BASE` environment variable:
|
||||
|
||||
```sh
|
||||
docker run --environment SECRET_KEY_BASE=abcdefabcdef ...
|
||||
docker run --env SECRET_KEY_BASE=abcdefabcdef ...
|
||||
```
|
||||
|
||||
#### SSL
|
||||
@@ -56,7 +56,7 @@ Note that if you're using SSL, you'll want to allow traffic on ports 80 and 443.
|
||||
So if you were running on `fizzy.example.com` you could enable SSL like this:
|
||||
|
||||
```sh
|
||||
docker run --publish 80:80 --publish 443:443 --environment TLS_DOMAIN=fizzy.example.com ...
|
||||
docker run --publish 80:80 --publish 443:443 --env TLS_DOMAIN=fizzy.example.com ...
|
||||
```
|
||||
|
||||
If you are terminating SSL in some other proxy in front of Fizzy, then you don't need to set `TLS_DOMAIN`, and can just publish port 80:
|
||||
@@ -67,7 +67,7 @@ docker run --publish 80:80 ...
|
||||
If you aren't using SSL at all (for example, if you want to run it locally on your laptop) then you should specify `DISABLE_SSL=true` instead:
|
||||
|
||||
```sh
|
||||
docker run --publish 80:80 --environment DISABLE_SSL=true ...
|
||||
docker run --publish 80:80 --env DISABLE_SSL=true ...
|
||||
```
|
||||
|
||||
#### SMTP Email
|
||||
@@ -96,7 +96,7 @@ Fizzy needs to know the public URL of your instance so it can generate correct l
|
||||
Set `BASE_URL` to the full URL where your Fizzy instance is accessible:
|
||||
|
||||
```sh
|
||||
docker run --environment BASE_URL=https://fizzy.example.com ...
|
||||
docker run --env BASE_URL=https://fizzy.example.com ...
|
||||
```
|
||||
|
||||
#### VAPID keys
|
||||
|
||||
@@ -76,6 +76,7 @@ env:
|
||||
clear:
|
||||
APP_FQDN: beta<%= @beta_number %>.fizzy-beta.com
|
||||
RAILS_ENV: beta
|
||||
RAILS_LOG_LEVEL: fatal # suppress unstructured log lines
|
||||
MYSQL_DATABASE_HOST: fizzy-mysql-primary
|
||||
MYSQL_DATABASE_REPLICA_HOST: fizzy-mysql-replica
|
||||
MYSQL_SOLID_CABLE_HOST: fizzy-mysql-primary
|
||||
|
||||
@@ -27,6 +27,7 @@ ssh:
|
||||
env:
|
||||
clear:
|
||||
RAILS_ENV: production
|
||||
RAILS_LOG_LEVEL: fatal # suppress unstructured log lines
|
||||
MYSQL_DATABASE_HOST: fizzy-mysql-primary
|
||||
MYSQL_DATABASE_REPLICA_HOST: fizzy-mysql-replica
|
||||
MYSQL_SOLID_CABLE_HOST: fizzy-mysql-primary
|
||||
|
||||
@@ -27,6 +27,7 @@ ssh:
|
||||
env:
|
||||
clear:
|
||||
RAILS_ENV: staging
|
||||
RAILS_LOG_LEVEL: fatal # suppress unstructured log lines
|
||||
MYSQL_DATABASE_HOST: fizzy-staging-mysql-primary
|
||||
MYSQL_DATABASE_REPLICA_HOST: fizzy-staging-mysql-replica
|
||||
MYSQL_SOLID_CABLE_HOST: fizzy-staging-mysql-primary
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
Rails.application.configure do
|
||||
config.active_storage.service = :purestorage
|
||||
|
||||
# Enable structured logging, suppress unstructured log lines
|
||||
# Enable structured logging
|
||||
config.structured_logging.logger = ActiveSupport::Logger.new(STDOUT)
|
||||
config.log_level = :fatal
|
||||
|
||||
config.action_controller.default_url_options = { host: "app.fizzy.do", protocol: "https" }
|
||||
config.action_mailer.default_url_options = { host: "app.fizzy.do", protocol: "https" }
|
||||
|
||||
@@ -10,7 +10,7 @@ class Account::Subscriptions::CardCreationTest < ActionDispatch::IntegrationTest
|
||||
test "admin sees nearing card limit notice" do
|
||||
accounts(:initech).update_column(:cards_count, 950)
|
||||
|
||||
get card_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug)
|
||||
get card_draft_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug)
|
||||
|
||||
assert_response :success
|
||||
assert_match /upgrade to unlimited/i, response.body
|
||||
@@ -19,7 +19,7 @@ class Account::Subscriptions::CardCreationTest < ActionDispatch::IntegrationTest
|
||||
test "admin sees nearing storage limit notice" do
|
||||
Account.any_instance.stubs(:bytes_used).returns(600.megabytes)
|
||||
|
||||
get card_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug)
|
||||
get card_draft_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug)
|
||||
|
||||
assert_response :success
|
||||
assert_match /upgrade to get more/i, response.body
|
||||
@@ -30,7 +30,7 @@ class Account::Subscriptions::CardCreationTest < ActionDispatch::IntegrationTest
|
||||
test "admin sees exceeding card limit notice" do
|
||||
accounts(:initech).update_column(:cards_count, 1001)
|
||||
|
||||
get card_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug)
|
||||
get card_draft_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug)
|
||||
|
||||
assert_response :success
|
||||
assert_match /you’ve used your.*free cards/i, response.body
|
||||
@@ -39,7 +39,7 @@ class Account::Subscriptions::CardCreationTest < ActionDispatch::IntegrationTest
|
||||
test "admin sees exceeding storage limit notice" do
|
||||
Account.any_instance.stubs(:bytes_used).returns(1.1.gigabytes)
|
||||
|
||||
get card_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug)
|
||||
get card_draft_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug)
|
||||
|
||||
assert_response :success
|
||||
assert_match /you’ve run out of.*free storage/i, response.body
|
||||
@@ -64,7 +64,7 @@ class Account::Subscriptions::CardCreationTest < ActionDispatch::IntegrationTest
|
||||
test "comped account under limits sees no notices" do
|
||||
accounts(:initech).comp
|
||||
|
||||
get card_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug)
|
||||
get card_draft_path(cards(:unfinished_thoughts), script_name: accounts(:initech).slug)
|
||||
|
||||
assert_response :success
|
||||
assert_no_match /upgrade/i, response.body
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
require "test_helper"
|
||||
|
||||
class Cards::DraftsControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in_as :kevin
|
||||
end
|
||||
|
||||
test "show" do
|
||||
card = boards(:writebook).cards.create!(creator: users(:kevin), status: :drafted)
|
||||
|
||||
get card_draft_path(card)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "show redirects to card when published" do
|
||||
card = cards(:logo)
|
||||
|
||||
get card_draft_path(card)
|
||||
assert_redirected_to card
|
||||
end
|
||||
end
|
||||
@@ -28,6 +28,6 @@ class Cards::PublishesControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
new_card = Card.last
|
||||
assert new_card.drafted?
|
||||
assert_redirected_to new_card
|
||||
assert_redirected_to card_draft_path(new_card)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class CardsControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
|
||||
card = Card.last
|
||||
assert_redirected_to card
|
||||
assert_redirected_to card_draft_path(card)
|
||||
|
||||
assert card.drafted?
|
||||
end
|
||||
@@ -31,10 +31,17 @@ class CardsControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
assert_no_difference -> { Card.count } do
|
||||
post board_cards_path(boards(:writebook))
|
||||
assert_redirected_to draft
|
||||
assert_redirected_to card_draft_path(draft)
|
||||
end
|
||||
end
|
||||
|
||||
test "show redirects to draft when card is drafted" do
|
||||
card = boards(:writebook).cards.create!(creator: users(:kevin), status: :drafted)
|
||||
|
||||
get card_path(card)
|
||||
assert_redirected_to card_draft_path(card)
|
||||
end
|
||||
|
||||
test "show" do
|
||||
get card_path(cards(:logo))
|
||||
assert_response :success
|
||||
|
||||
@@ -10,7 +10,7 @@ class Users::RolesControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
put user_role_path(users(:david)), params: { user: { role: "admin" } }
|
||||
|
||||
assert_redirected_to users_path
|
||||
assert_redirected_to account_settings_path
|
||||
assert users(:david).reload.admin?
|
||||
end
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
|
||||
delete user_path(users(:david))
|
||||
end
|
||||
|
||||
assert_redirected_to users_path
|
||||
assert_redirected_to account_settings_path
|
||||
assert_nil User.active.find_by(id: users(:david).id)
|
||||
end
|
||||
|
||||
|
||||
Vendored
-4
@@ -1,4 +0,0 @@
|
||||
logo:
|
||||
id: <%= ActiveRecord::FixtureSet.identify("logo_engagement", :uuid) %>
|
||||
account: 37s_uuid
|
||||
card: logo_uuid
|
||||
@@ -31,4 +31,32 @@ class Card::CloseableTest < ActiveSupport::TestCase
|
||||
assert cards(:shipping).reload.open?
|
||||
assert cards(:shipping).events.last.action.card_reopened?
|
||||
end
|
||||
|
||||
test "close card from triage column" do
|
||||
card = cards(:logo)
|
||||
assert_equal columns(:writebook_triage), card.column
|
||||
|
||||
card.close
|
||||
assert card.closed?
|
||||
end
|
||||
|
||||
test "close card from active column" do
|
||||
card = cards(:text)
|
||||
assert_equal columns(:writebook_in_progress), card.column
|
||||
|
||||
card.close
|
||||
assert card.closed?
|
||||
end
|
||||
|
||||
test "close card from NOT NOW" do
|
||||
card = cards(:logo)
|
||||
|
||||
card.postpone
|
||||
assert card.postponed?
|
||||
assert card.not_now.present?
|
||||
|
||||
card.close
|
||||
assert card.closed?
|
||||
assert_nil card.reload.not_now
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,15 +4,12 @@ class Filter::SearchTest < ActiveSupport::TestCase
|
||||
include SearchTestHelper
|
||||
|
||||
test "deduplicate multiple results" do
|
||||
user = users(:david)
|
||||
|
||||
board = boards(:writebook)
|
||||
card = board.cards.create!(title: "Duplicate results test", description: "Have you had any haggis today?", creator: user)
|
||||
card = @board.cards.create!(title: "Duplicate results test", description: "Have you had any haggis today?", creator: @user)
|
||||
card.published!
|
||||
card.comments.create(body: "I hate haggis.", creator: user)
|
||||
card.comments.create(body: "I love haggis.", creator: user)
|
||||
card.comments.create(body: "I hate haggis.", creator: @user)
|
||||
card.comments.create(body: "I love haggis.", creator: @user)
|
||||
|
||||
filter = user.filters.new(terms: [ "haggis" ], indexed_by: "all", sorted_by: "latest")
|
||||
filter = @user.filters.new(terms: [ "haggis" ], indexed_by: "all", sorted_by: "latest")
|
||||
|
||||
assert_equal [ card ], filter.cards.to_a
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user