github-issue-tower-defence-management 1.151.6 → 1.151.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/bin/adapter/entry-points/console/ui-dist/assets/index-BjFRJoM1.js +83 -0
- package/bin/adapter/entry-points/console/ui-dist/assets/index-CGqYXHZV.css +2 -0
- package/bin/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/package.json +1 -1
- package/src/adapter/entry-points/console/ui/e2e/consoleScenario.spec.ts +23 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommentComposer.stories.tsx +0 -1
- package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommentComposer.test.tsx +6 -15
- package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommentComposer.tsx +1 -33
- package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.tsx +4 -1
- package/src/adapter/entry-points/console/ui/src/features/console/logic/postedComments.test.ts +44 -0
- package/src/adapter/entry-points/console/ui/src/features/console/logic/postedComments.ts +17 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.test.tsx +77 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.tsx +14 -3
- package/src/adapter/entry-points/console/ui-dist/assets/index-BjFRJoM1.js +83 -0
- package/src/adapter/entry-points/console/ui-dist/assets/index-CGqYXHZV.css +2 -0
- package/src/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/bin/adapter/entry-points/console/ui-dist/assets/index-ChJztBsb.js +0 -83
- package/bin/adapter/entry-points/console/ui-dist/assets/index-wDluFyBz.css +0 -2
- package/src/adapter/entry-points/console/ui-dist/assets/index-ChJztBsb.js +0 -83
- package/src/adapter/entry-points/console/ui-dist/assets/index-wDluFyBz.css +0 -2
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--radius-md:.375rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-input:#e5e5e5;--color-ring:#0a0a0a;--color-background:#fff;--color-foreground:#0a0a0a;--color-primary:#171717;--color-primary-foreground:#fafafa;--color-secondary:#f5f5f5;--color-secondary-foreground:#171717;--color-accent:#f5f5f5;--color-accent-foreground:#171717}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.block{display:block}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.grow{flex-grow:1}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-input{border-color:var(--color-input)}.border-transparent{border-color:#0000}.bg-background{background-color:var(--color-background)}.bg-primary{background-color:var(--color-primary)}.bg-secondary{background-color:var(--color-secondary)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-2{padding-block:calc(var(--spacing) * 2)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-foreground{color:var(--color-foreground)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.lowercase{text-transform:lowercase}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.hover\:bg-accent:hover{background-color:var(--color-accent)}.hover\:bg-primary\/90:hover{background-color:#171717e6}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--color-primary) 90%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:#f5f5f5cc}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--color-secondary) 80%, transparent)}}.hover\:text-accent-foreground:hover{color:var(--color-accent-foreground)}}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--color-ring)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}}html{font-size:clamp(15px,2.1vw,26px)}body{color:#e6edf3;background-color:#0d1117;margin:0;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif}.console-app{flex-direction:column;width:100%;min-height:100dvh;display:flex}.console-tabbar{-webkit-overflow-scrolling:touch;background:#161b22;border-bottom:2px solid #30363d;flex-wrap:nowrap;align-items:stretch;gap:0;min-height:42px;padding:0 8px;display:flex;overflow-x:auto}.console-tab{color:#8b949e;white-space:nowrap;cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;align-items:center;gap:6px;margin-bottom:-2px;padding:10px 14px;font-size:.8125rem;font-weight:500;line-height:1.2;text-decoration:none;display:inline-flex}.console-tab:hover{color:#e6edf3}.console-tab[data-active=true]{color:#e6edf3;border-bottom-color:#2f81f7;font-weight:700}.console-tab-badge{text-align:center;color:#e6edf3;background:#484f58;border-radius:20px;min-width:20px;padding:1px 7px;font-size:.6875rem;font-weight:700;line-height:1.5}.console-tab-badge[data-zero=true]{color:#8b949e;background:#30363d}.console-tab-pjname{color:#8b949e;align-self:center;margin-left:auto;padding:0 8px;font-size:.7188rem}.console-tab-geninfo{color:#8b949e;align-self:center;padding:0 4px;font-size:.6875rem}.console-list{margin:0;padding:12px 18px 18px;list-style:none}.console-list-group{list-style:none}.console-item-row .console-item-icon{flex:none;margin-top:3px}.console-group-header{background:#0b0f14;border-bottom:1px solid #21262d;justify-content:space-between;align-items:center;padding:6px 12px;display:flex}.console-storytag{align-items:center;gap:8px;font-size:.8125rem;font-weight:700;display:inline-flex}.console-story-dot{border-radius:999px;width:10px;height:10px;display:inline-block}.console-group-count{color:#8b949e;font-size:.75rem}.console-item-row{color:#e6edf3;text-align:left;cursor:pointer;background:#161b22;border:1px solid #30363d;border-radius:8px;align-items:flex-start;gap:14px;width:100%;margin-bottom:10px;padding:12px 16px;display:flex}.console-item-row:hover{background:#1a2029;border-color:#484f58}.console-item-row[data-active=true]{background:#1a2029;border-color:#4493f8}.console-item-meta{flex:1;min-width:0}.console-item-title{font-size:.9063rem;font-weight:600;display:block}.console-item-sub{color:#8b949e;margin-top:3px;font-size:.7813rem;display:block}.console-item-pill{color:#8b949e;border:1px solid #30363d;border-radius:20px;margin-right:6px;padding:1px 8px;font-size:.6875rem;display:inline-block}.console-item-createdat{color:#8b949e;cursor:help}.console-item-fields{color:#adbac7;flex-wrap:wrap;gap:4px 10px;margin-top:4px;font-size:.7188rem;display:flex}.console-item-field{word-break:break-all;align-items:baseline;gap:4px;min-width:0;display:inline-flex}.console-item-field-label{color:#6e7681;text-transform:uppercase;letter-spacing:.03em;font-size:.625rem}.console-list-message{color:#8b949e;padding:16px;font-size:.875rem}.console-list-empty{text-align:center;color:#8b949e;padding:40px;font-size:.875rem}.console-list-error,.console-comment-error,.console-files-error,.console-commits-error,.console-detail-fetch-error,.console-detail-body-error{color:#f85149}.console-detail{flex-direction:column;flex:1 0 auto;gap:12px;padding:16px 16px 0;display:flex}.console-detail-topline{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.console-detail-title{align-items:center;gap:8px;margin:0;font-size:1.25rem;display:flex}.console-detail-title-text{flex:1}.console-detail-number{color:#8b949e;font-weight:400}.console-detail-closed-label{color:#a371f7;font-size:.8125rem}.console-detail-subbar{align-items:center;gap:12px;font-size:.8125rem;display:flex}.console-detail-link{color:#4493f8}.console-detail-repo{color:#8b949e;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-copy-url-button{color:#c9d1d9;border:1px solid #30363d;border-radius:6px;height:24px;padding:0 8px;font-size:.75rem}.console-copy-url-button:hover{color:#e6edf3;background-color:#21262d}.console-detail-pill,.console-label-chip,.console-detail-status-chip{border:1px solid #30363d;border-radius:999px;padding:2px 8px;font-size:.75rem;display:inline-block}.console-detail-pr-status{flex-wrap:wrap;align-items:center;gap:6px;display:inline-flex}.console-detail-ci-missing{opacity:.85;font-weight:400}.console-detail-mergeable-chip{font-weight:600}.console-detail-mergeable-chip-unknown{opacity:.7;font-weight:400}.console-detail-labels{flex-wrap:wrap;gap:6px;display:flex}.console-detail-createdat{color:#8b949e;font-size:.75rem}.console-panel{border:1px solid #30363d;border-radius:8px;overflow:hidden}.console-panel-header{background:#161b22;justify-content:space-between;align-items:center;display:flex}.console-panel-toggle{color:#e6edf3;text-align:left;cursor:pointer;background:0 0;border:none;flex:1;align-items:center;gap:8px;padding:6px 12px;font-size:.875rem;font-weight:600;display:flex}.console-panel-toggle:hover{background:#1a2029}.console-panel-action{padding:6px 12px}.console-panel-body{padding:12px}.console-markdown{word-break:break-word;font-size:.875rem;line-height:1.5}.console-markdown ul{margin:.5em 0;padding-left:1.5em;list-style:outside}.console-markdown ol{margin:.5em 0;padding-left:1.5em;list-style:decimal}.console-markdown li{margin:.25em 0}.console-markdown table{border-collapse:collapse;margin:.5em 0}.console-markdown th,.console-markdown td{border:1px solid #30363d;padding:4px 8px}.console-markdown th{background:#161b22}.console-markdown h1,.console-markdown h2,.console-markdown h3,.console-markdown h4,.console-markdown h5,.console-markdown h6{margin:1em 0 .5em;font-weight:700;line-height:1.25}.console-markdown h1{font-size:1.6em}.console-markdown h2{font-size:1.4em}.console-markdown h3{font-size:1.2em}.console-markdown h4{font-size:1.05em}.console-markdown h5{font-size:.95em}.console-markdown h6{color:#8b949e;font-size:.9em}.console-markdown pre{background:#161b22;border:1px solid #30363d;border-radius:6px;margin:.5em 0;padding:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.8125rem;line-height:1.45;overflow-x:auto}.console-markdown code{background:#6e768166;border-radius:4px;padding:.15em .4em;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9em}.console-markdown pre code{font-size:inherit;background:0 0;border-radius:0;padding:0}.console-markdown-code-block{flex-direction:column;margin:.5em 0;display:flex}.console-markdown-code-block pre{margin:0}.console-markdown-code-copy-host{justify-content:flex-end;margin-bottom:4px;display:flex}.console-copy-code-button{color:#c9d1d9;background-color:#161b22;border:1px solid #30363d;border-radius:6px;height:24px;padding:0 8px;font-size:.75rem}.console-copy-code-button:hover{color:#e6edf3;background-color:#21262d}.console-markdown blockquote{color:#8b949e;border-left:3px solid #30363d;margin:.5em 0;padding:0 1em}.console-markdown a{color:#4493f8;text-decoration:none}.console-markdown a:hover{text-decoration:underline}.console-markdown-reference-host{display:inline}.console-markdown-reference{vertical-align:baseline;align-items:center;gap:.25em;display:inline-flex}.console-markdown-reference .console-item-icon{flex-shrink:0}.console-markdown-reference-title{text-decoration:none}.console-markdown-reference:hover .console-markdown-reference-title{text-decoration:underline}.console-markdown hr{border:none;border-top:1px solid #30363d;margin:1em 0}.console-mermaid-error{color:#f85149;font-size:.8125rem}.console-comment{background:#161b22;border:1px solid #30363d;border-radius:8px;margin-bottom:10px;padding:12px 16px}.console-comment-header{color:#8b949e;gap:8px;font-size:.75rem;display:flex}.console-comment-show-all{color:#e6edf3;cursor:pointer;background:#21262d;border:1px solid #30363d;border-radius:6px;margin-bottom:10px;padding:6px 12px;font-size:.75rem;font-weight:600}.console-comment-show-all:hover{background-color:#262c34;border-color:#484f58}.console-comment-author{color:#e6edf3;font-weight:600}.console-files,.console-commits{margin:0;padding:0;list-style:none}.console-commit{align-items:center;gap:8px;padding:4px 0;font-size:.8125rem;display:flex}.console-file{flex-direction:column;font-size:.8125rem;display:flex}.console-file-tree,.console-file-tree-children{margin:0;padding:0;list-style:none}.console-file-tree-dir{flex-direction:column;display:flex}.console-file-tree-dir-name{color:#8b949e;align-items:center;gap:6px;padding:4px 0;font-weight:600;display:flex}.console-file-tree-dir-icon{flex:none}.console-file-badge{text-align:center;border:1px solid;border-radius:4px;width:18px;font-size:.6875rem}.console-file-path,.console-commit-message{flex:1;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-file-add,.console-pr-add{color:#3fb950}.console-file-del,.console-pr-del{color:#f85149}.console-commit-sha{color:#8b949e;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-detail-dock{z-index:100;background:#161b22;border-top:2px solid #30363d;margin-top:auto;position:sticky;bottom:0}.console-detail-dock-composer{max-height:50vh;padding:8px 16px 0;overflow-y:auto}.console-actionbar{padding:10px 16px;padding-bottom:calc(10px + env(safe-area-inset-bottom));background:#161b22}.console-operation-bar{flex-direction:column;gap:8px;width:100%;display:flex}.console-op-group{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;display:flex}.console-op-group-review{gap:10px}.console-op-group-stories{max-height:33vh;overflow-y:auto}.console-op-button{color:#e6edf3;white-space:nowrap;cursor:pointer;background:#21262d;border:1px solid #30363d;border-radius:6px;padding:9px 16px;font-size:.8125rem;font-weight:600}.console-op-button:hover{border-color:#484f58}.console-op-button:disabled{opacity:.4;cursor:not-allowed}.console-op-requirement{text-align:right;color:#8b949e;width:100%;margin:0;font-size:.75rem}.console-op-button-approve{color:#fff;background:#238636;border-color:#2ea043}.console-op-button-reject{color:#ffd166;background:#7d5000;border-color:#a06800}.console-op-button-wrong{color:#f85149;background:#3a1518;border-color:#f85149}.console-op-button-unneeded{color:#aab0b8;background:#2a2d31;border-color:#6e7681}.console-op-button-snooze{color:#79c0ff;background:#1c2b4a;border-color:#4493f8}.console-pr-section{border:1px solid #30363d;border-radius:8px;flex-direction:column;gap:10px;padding:12px;display:flex}.console-pr-statbar{color:#8b949e;gap:12px;font-size:.75rem;display:flex}.console-detail-screen{flex-direction:column;flex:1 0 auto;display:flex}.console-panel-open-link{color:#4493f8;font-size:.8125rem;font-weight:400}.console-composer{margin-top:4px}.console-composer-toggle{color:#8b949e;cursor:pointer;background:0 0;border:none;margin-left:auto;padding:2px 0;font-size:.7813rem;display:block}.console-composer-toggle:hover{color:#e6edf3}.console-composer-posted{flex-direction:column;gap:8px;margin-top:8px;display:flex}.console-composer-form{margin-top:8px}.console-composer-input{box-sizing:border-box;color:#e6edf3;width:100%;font:inherit;resize:vertical;background:#21262d;border:1px solid #30363d;border-radius:6px;padding:8px;font-size:.875rem}.console-composer-attach{align-items:center;gap:8px;padding:0 10px;display:flex}.console-composer-file-input{display:none}.console-composer-attach-button{color:#c9d1d9;cursor:pointer;background:#21262d;border:1px solid #30363d;border-radius:4px;padding:4px 8px;font-size:.75rem}.console-composer-attach-button:disabled{opacity:.6;cursor:default}.console-composer-row{justify-content:flex-end;align-items:center;gap:8px;margin-top:6px;display:flex}.console-composer-submit{color:#fff;cursor:pointer;background:#238636;border:1px solid #2ea043;border-radius:6px;padding:7px 16px;font-size:.8125rem;font-weight:600}.console-composer-submit:disabled{opacity:.6;cursor:default}.console-composer-status{color:#8b949e;font-size:.75rem}.console-composer-error{color:#f85149}.console-undo-toast{z-index:9998;white-space:nowrap;border-radius:10px;align-items:center;gap:12px;max-width:92vw;padding:12px 18px;font-size:.8438rem;display:flex;position:fixed;top:12px;left:50%;transform:translate(-50%);box-shadow:0 4px 20px #0009}.console-undo-toast-green{color:#3fb950;background:#0d3320;border:1px solid #2ea043}.console-undo-toast-amber{color:#ffd166;background:#3a2800;border:1px solid #a06800}.console-undo-toast-red{color:#f85149;background:#3a1518;border:1px solid #da3633}.console-undo-toast-gray{color:#aab0b8;background:#2a2d31;border:1px solid #6e7681}.console-undo-toast-blue{color:#79c0ff;background:#0d1f40;border:1px solid #4493f8}.console-undo-toast-error{color:#f85149;background:#3a1518;border:1px solid #f85149}.console-undo-toast-message{text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.console-undo-toast-undo{cursor:pointer;color:inherit;background:#ffffff1f;border:none;border-radius:6px;flex:none;padding:4px 12px;font-size:.8125rem;font-weight:700}.console-undo-toast-undo:hover{background:#ffffff38}.console-undo-toast-countdown{opacity:.7;flex:none;font-size:.6875rem}.console-undo-toast-bar{opacity:.5;background:currentColor;border-radius:0 0 10px 10px;height:3px;transition:width .1s linear;position:absolute;bottom:0;left:0}.console-file-row{width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:4px 0;font-size:.8125rem;display:flex}.console-file-row:hover{background:#1a2029}.console-file-caret{color:#8b949e;flex:none;width:1em}.console-file-diff{border-collapse:collapse;width:100%;margin:4px 0 8px;font:.8125rem/1.6 ui-monospace,SFMono-Regular,Menlo,monospace}.console-file-diff td{white-space:pre-wrap;word-break:break-word;vertical-align:top;padding:0 10px}.console-diff-ln{text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;white-space:nowrap;border-right:1px solid #30363d;width:1%;padding:0 8px}.console-file-diff td.console-diff-ln{white-space:nowrap;word-break:normal;overflow-wrap:normal}.console-diff-add td{background:#2ea04326}.console-diff-add .console-diff-code{color:#aff5b4}.console-diff-del td{background:#f8514926}.console-diff-del .console-diff-code{color:#ffdcd7}.console-diff-hunk td{color:#79c0ff;background:#161b22}.console-diff-ctx .console-diff-code{color:#c9d1d9}.console-file-diff-empty{color:#8b949e;padding:8px 14px;font-size:.75rem}.console-file-diff-image{padding:8px 14px}.console-file-diff-image-content{object-fit:contain;object-position:left top;border:1px solid #30363d;border-radius:4px;max-width:100%;max-height:420px}.console-diff-comment-cell{text-align:center;-webkit-user-select:none;user-select:none;width:1%;padding:0 2px}.console-diff-comment-button{color:#6e7681;cursor:pointer;opacity:.6;background:0 0;border:1px solid #30363d;border-radius:4px;width:18px;height:18px;padding:0;font-size:.875rem;line-height:16px}.console-diff-row:hover .console-diff-comment-button,.console-diff-comment-button:focus-visible,.console-diff-comment-button[aria-expanded=true]{opacity:1;color:#fff;background:#1f6feb;border-color:#2f81f7}.console-diff-composer-row td{background:#0d1117;padding:6px 10px}.console-diff-composer{background:#161b22;border:1px solid #30363d;border-radius:6px;flex-direction:column;gap:6px;padding:8px;display:flex}.console-diff-composer-anchor{color:#8b949e;font-size:.6875rem}.console-diff-composer-input{resize:vertical;color:#c9d1d9;width:100%;font:inherit;background:#0d1117;border:1px solid #30363d;border-radius:6px;padding:6px 8px}.console-diff-composer-controls{align-items:center;gap:8px;display:flex}.console-diff-composer-submit{color:#fff;cursor:pointer;background:#238636;border:1px solid #238636;border-radius:6px;padding:4px 12px}.console-diff-composer-submit:disabled{opacity:.6;cursor:default}.console-diff-composer-cancel{color:#c9d1d9;cursor:pointer;background:0 0;border:1px solid #30363d;border-radius:6px;padding:4px 12px}.console-diff-composer-status{color:#8b949e;font-size:.75rem}.console-diff-composer-error{color:#ff7b72}.console-diff-composer-posted{color:#3fb950;margin:0;font-size:.75rem}.console-pr-header{flex-wrap:wrap;align-items:center;gap:10px;padding-top:4px;display:flex}.console-pr-section-title{color:#e6edf3;font-size:.9375rem;font-weight:600}.console-pr-section-state{color:#8b949e;border:1px solid #6e7681;border-radius:999px;padding:1px 8px;font-size:.6875rem}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>TDPM Console</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-BjFRJoM1.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CGqYXHZV.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -312,4 +312,27 @@ test('opens the comment input with the item detail, keeps it on screen while the
|
|
|
312
312
|
|
|
313
313
|
await composerToggle.click();
|
|
314
314
|
await expect(page.locator('.console-composer-input')).toBeInViewport();
|
|
315
|
+
|
|
316
|
+
const dockHeightBeforePosting = (
|
|
317
|
+
await page.locator('.console-detail-dock').boundingBox()
|
|
318
|
+
)?.height;
|
|
319
|
+
await page
|
|
320
|
+
.locator('.console-composer-input')
|
|
321
|
+
.fill('The dock must not grow with every comment.');
|
|
322
|
+
await page.locator('.console-composer-submit').click();
|
|
323
|
+
|
|
324
|
+
const postedComment = page.locator('.console-comment', {
|
|
325
|
+
hasText: 'The dock must not grow with every comment.',
|
|
326
|
+
});
|
|
327
|
+
await expect(postedComment).toHaveCount(1);
|
|
328
|
+
await expect(
|
|
329
|
+
page.locator('.console-detail-dock .console-comment'),
|
|
330
|
+
).toHaveCount(0);
|
|
331
|
+
await expect(page.locator('.console-comment-list')).toContainText(
|
|
332
|
+
'The dock must not grow with every comment.',
|
|
333
|
+
);
|
|
334
|
+
const dockHeightAfterPosting = (
|
|
335
|
+
await page.locator('.console-detail-dock').boundingBox()
|
|
336
|
+
)?.height;
|
|
337
|
+
expect(dockHeightAfterPosting).toBe(dockHeightBeforePosting);
|
|
315
338
|
});
|
|
@@ -9,14 +9,11 @@ jest.mock('../../lib/mermaidLoader', () => ({
|
|
|
9
9
|
renderMermaidToSvg: jest.fn(async () => '<svg></svg>'),
|
|
10
10
|
}));
|
|
11
11
|
|
|
12
|
-
const now = Date.parse('2026-06-19T12:00:00.000Z');
|
|
13
|
-
|
|
14
12
|
describe('ConsoleCommentComposer', () => {
|
|
15
13
|
it('shows the form when it starts open', () => {
|
|
16
14
|
const { getByPlaceholderText } = render(
|
|
17
15
|
<ConsoleCommentComposer
|
|
18
16
|
initiallyOpen
|
|
19
|
-
now={now}
|
|
20
17
|
onSubmit={async (body) => ({
|
|
21
18
|
author: 'HiromiShikata',
|
|
22
19
|
body,
|
|
@@ -31,7 +28,6 @@ describe('ConsoleCommentComposer', () => {
|
|
|
31
28
|
const { queryByPlaceholderText, getByText } = render(
|
|
32
29
|
<ConsoleCommentComposer
|
|
33
30
|
initiallyOpen={false}
|
|
34
|
-
now={now}
|
|
35
31
|
onSubmit={async (body) => ({
|
|
36
32
|
author: 'HiromiShikata',
|
|
37
33
|
body,
|
|
@@ -47,7 +43,6 @@ describe('ConsoleCommentComposer', () => {
|
|
|
47
43
|
const { getByText, getByPlaceholderText, queryByPlaceholderText } = render(
|
|
48
44
|
<ConsoleCommentComposer
|
|
49
45
|
initiallyOpen={false}
|
|
50
|
-
now={now}
|
|
51
46
|
onSubmit={async (body) => ({
|
|
52
47
|
author: 'HiromiShikata',
|
|
53
48
|
body,
|
|
@@ -61,7 +56,7 @@ describe('ConsoleCommentComposer', () => {
|
|
|
61
56
|
expect(queryByPlaceholderText('Leave a comment…')).toBeNull();
|
|
62
57
|
});
|
|
63
58
|
|
|
64
|
-
it('submits the comment and
|
|
59
|
+
it('submits the comment, empties the draft and renders no comment of its own', async () => {
|
|
65
60
|
const onSubmit = jest.fn(
|
|
66
61
|
async (body: string): Promise<ConsoleComment> => ({
|
|
67
62
|
author: 'HiromiShikata',
|
|
@@ -69,24 +64,25 @@ describe('ConsoleCommentComposer', () => {
|
|
|
69
64
|
createdAt: '2026-06-19T11:58:00.000Z',
|
|
70
65
|
}),
|
|
71
66
|
);
|
|
72
|
-
const { getByPlaceholderText, getByText } = render(
|
|
73
|
-
<ConsoleCommentComposer initiallyOpen
|
|
67
|
+
const { container, getByPlaceholderText, getByText, queryByText } = render(
|
|
68
|
+
<ConsoleCommentComposer initiallyOpen onSubmit={onSubmit} />,
|
|
74
69
|
);
|
|
75
70
|
fireEvent.change(getByPlaceholderText('Leave a comment…'), {
|
|
76
71
|
target: { value: 'Looks good after the rebase.' },
|
|
77
72
|
});
|
|
78
73
|
fireEvent.click(getByText('Comment'));
|
|
79
74
|
await waitFor(() => {
|
|
80
|
-
expect(
|
|
75
|
+
expect(getByPlaceholderText('Leave a comment…')).toHaveValue('');
|
|
81
76
|
});
|
|
82
77
|
expect(onSubmit).toHaveBeenCalledWith('Looks good after the rebase.');
|
|
78
|
+
expect(queryByText('Looks good after the rebase.')).toBeNull();
|
|
79
|
+
expect(container.querySelectorAll('.console-comment').length).toBe(0);
|
|
83
80
|
});
|
|
84
81
|
|
|
85
82
|
it('shows a failure message when the submission rejects', async () => {
|
|
86
83
|
const { getByPlaceholderText, getByText, findByRole } = render(
|
|
87
84
|
<ConsoleCommentComposer
|
|
88
85
|
initiallyOpen
|
|
89
|
-
now={now}
|
|
90
86
|
onSubmit={async () => {
|
|
91
87
|
throw new Error('HTTP 500');
|
|
92
88
|
}}
|
|
@@ -104,7 +100,6 @@ describe('ConsoleCommentComposer', () => {
|
|
|
104
100
|
const { queryByText } = render(
|
|
105
101
|
<ConsoleCommentComposer
|
|
106
102
|
initiallyOpen
|
|
107
|
-
now={now}
|
|
108
103
|
onSubmit={async (body) => ({
|
|
109
104
|
author: 'HiromiShikata',
|
|
110
105
|
body,
|
|
@@ -122,7 +117,6 @@ describe('ConsoleCommentComposer', () => {
|
|
|
122
117
|
const { getByPlaceholderText, getByLabelText } = render(
|
|
123
118
|
<ConsoleCommentComposer
|
|
124
119
|
initiallyOpen
|
|
125
|
-
now={now}
|
|
126
120
|
onSubmit={async (body) => ({
|
|
127
121
|
author: 'HiromiShikata',
|
|
128
122
|
body,
|
|
@@ -154,7 +148,6 @@ describe('ConsoleCommentComposer', () => {
|
|
|
154
148
|
const { getByPlaceholderText } = render(
|
|
155
149
|
<ConsoleCommentComposer
|
|
156
150
|
initiallyOpen
|
|
157
|
-
now={now}
|
|
158
151
|
onSubmit={async (body) => ({
|
|
159
152
|
author: 'HiromiShikata',
|
|
160
153
|
body,
|
|
@@ -183,7 +176,6 @@ describe('ConsoleCommentComposer', () => {
|
|
|
183
176
|
const { getByPlaceholderText } = render(
|
|
184
177
|
<ConsoleCommentComposer
|
|
185
178
|
initiallyOpen
|
|
186
|
-
now={now}
|
|
187
179
|
onSubmit={async (body) => ({
|
|
188
180
|
author: 'HiromiShikata',
|
|
189
181
|
body,
|
|
@@ -209,7 +201,6 @@ describe('ConsoleCommentComposer', () => {
|
|
|
209
201
|
const { getByLabelText, findByRole } = render(
|
|
210
202
|
<ConsoleCommentComposer
|
|
211
203
|
initiallyOpen
|
|
212
|
-
now={now}
|
|
213
204
|
onSubmit={async (body) => ({
|
|
214
205
|
author: 'HiromiShikata',
|
|
215
206
|
body,
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import { useRef, useState } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
formatFullTimestamp,
|
|
4
|
-
formatRelativeTime,
|
|
5
|
-
} from '../../logic/relativeTime';
|
|
6
2
|
import type { ConsoleComment } from '../../logic/types';
|
|
7
|
-
import { ConsoleMarkdownContent } from '../content/ConsoleMarkdownContent';
|
|
8
3
|
|
|
9
4
|
export type ConsoleCommentComposerProps = {
|
|
10
5
|
initiallyOpen: boolean;
|
|
11
|
-
now: number;
|
|
12
6
|
onSubmit: (body: string) => Promise<ConsoleComment>;
|
|
13
7
|
onUploadFile?: (file: File) => Promise<string>;
|
|
14
8
|
};
|
|
@@ -38,7 +32,6 @@ export const appendAttachmentMarkdown = (
|
|
|
38
32
|
|
|
39
33
|
export const ConsoleCommentComposer = ({
|
|
40
34
|
initiallyOpen,
|
|
41
|
-
now,
|
|
42
35
|
onSubmit,
|
|
43
36
|
onUploadFile,
|
|
44
37
|
}: ConsoleCommentComposerProps) => {
|
|
@@ -48,7 +41,6 @@ export const ConsoleCommentComposer = ({
|
|
|
48
41
|
const [uploadStatus, setUploadStatus] = useState<UploadStatus>({
|
|
49
42
|
kind: 'idle',
|
|
50
43
|
});
|
|
51
|
-
const [posted, setPosted] = useState<ConsoleComment[]>([]);
|
|
52
44
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
|
53
45
|
|
|
54
46
|
const submit = async (): Promise<void> => {
|
|
@@ -58,8 +50,7 @@ export const ConsoleCommentComposer = ({
|
|
|
58
50
|
}
|
|
59
51
|
setStatus({ kind: 'posting' });
|
|
60
52
|
try {
|
|
61
|
-
|
|
62
|
-
setPosted((previous) => [...previous, comment]);
|
|
53
|
+
await onSubmit(body);
|
|
63
54
|
setDraft('');
|
|
64
55
|
setStatus({ kind: 'idle' });
|
|
65
56
|
} catch (error) {
|
|
@@ -101,29 +92,6 @@ export const ConsoleCommentComposer = ({
|
|
|
101
92
|
>
|
|
102
93
|
{open ? '✕ Close' : '💬 Add a comment'}
|
|
103
94
|
</button>
|
|
104
|
-
{posted.length > 0 && (
|
|
105
|
-
<div className="console-composer-posted">
|
|
106
|
-
{posted.map((comment) => (
|
|
107
|
-
<article
|
|
108
|
-
key={`${comment.author}:${comment.createdAt}:${comment.body}`}
|
|
109
|
-
className="console-comment"
|
|
110
|
-
>
|
|
111
|
-
<header
|
|
112
|
-
className="console-comment-header"
|
|
113
|
-
title={formatFullTimestamp(comment.createdAt)}
|
|
114
|
-
>
|
|
115
|
-
<span className="console-comment-author">
|
|
116
|
-
{comment.author === '' ? 'you' : comment.author}
|
|
117
|
-
</span>
|
|
118
|
-
<span className="console-comment-time">
|
|
119
|
-
{formatRelativeTime(comment.createdAt, now)}
|
|
120
|
-
</span>
|
|
121
|
-
</header>
|
|
122
|
-
<ConsoleMarkdownContent body={comment.body} />
|
|
123
|
-
</article>
|
|
124
|
-
))}
|
|
125
|
-
</div>
|
|
126
|
-
)}
|
|
127
95
|
{open && (
|
|
128
96
|
<div className="console-composer-form">
|
|
129
97
|
<textarea
|
|
@@ -51,6 +51,7 @@ export type ConsoleItemDetailProps = {
|
|
|
51
51
|
bodyIsLoading: boolean;
|
|
52
52
|
bodyError: string | null;
|
|
53
53
|
comments: ConsoleComment[];
|
|
54
|
+
hasPostedComment?: boolean;
|
|
54
55
|
commentsAreLoading: boolean;
|
|
55
56
|
commentsError: string | null;
|
|
56
57
|
files: ConsoleChangedFile[];
|
|
@@ -82,6 +83,7 @@ export const ConsoleItemDetail = ({
|
|
|
82
83
|
bodyIsLoading,
|
|
83
84
|
bodyError,
|
|
84
85
|
comments,
|
|
86
|
+
hasPostedComment = false,
|
|
85
87
|
commentsAreLoading,
|
|
86
88
|
commentsError,
|
|
87
89
|
files,
|
|
@@ -275,9 +277,10 @@ export const ConsoleItemDetail = ({
|
|
|
275
277
|
)}
|
|
276
278
|
|
|
277
279
|
<ConsolePanel
|
|
280
|
+
key={hasPostedComment ? 'comments-with-posted' : 'comments'}
|
|
278
281
|
title="Comments"
|
|
279
282
|
count={commentsCount}
|
|
280
|
-
defaultCollapsed={item.isPr}
|
|
283
|
+
defaultCollapsed={item.isPr && !hasPostedComment}
|
|
281
284
|
>
|
|
282
285
|
<ConsoleCommentList
|
|
283
286
|
comments={comments}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { mergePostedComments } from './postedComments';
|
|
2
|
+
import type { ConsoleComment } from './types';
|
|
3
|
+
|
|
4
|
+
const loadedComment: ConsoleComment = {
|
|
5
|
+
author: 'HiromiShikata',
|
|
6
|
+
body: 'Loaded from GitHub.',
|
|
7
|
+
createdAt: '2026-06-19T10:00:00.000Z',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const postedComment: ConsoleComment = {
|
|
11
|
+
author: 'HiromiShikata',
|
|
12
|
+
body: 'Posted from the console.',
|
|
13
|
+
createdAt: '2026-06-19T11:58:00.000Z',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
describe('mergePostedComments', () => {
|
|
17
|
+
it('appends a posted comment after the loaded comments', () => {
|
|
18
|
+
expect(mergePostedComments([loadedComment], [postedComment])).toEqual([
|
|
19
|
+
loadedComment,
|
|
20
|
+
postedComment,
|
|
21
|
+
]);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('drops a posted comment that the reloaded comments already carry', () => {
|
|
25
|
+
expect(
|
|
26
|
+
mergePostedComments([loadedComment, postedComment], [postedComment]),
|
|
27
|
+
).toEqual([loadedComment, postedComment]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('keeps a posted comment whose body differs from an otherwise identical loaded comment', () => {
|
|
31
|
+
const editedComment: ConsoleComment = {
|
|
32
|
+
...postedComment,
|
|
33
|
+
body: 'Posted from the console, then edited.',
|
|
34
|
+
};
|
|
35
|
+
expect(mergePostedComments([postedComment], [editedComment])).toEqual([
|
|
36
|
+
postedComment,
|
|
37
|
+
editedComment,
|
|
38
|
+
]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('returns the loaded comments unchanged when nothing was posted', () => {
|
|
42
|
+
expect(mergePostedComments([loadedComment], [])).toEqual([loadedComment]);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ConsoleComment } from './types';
|
|
2
|
+
|
|
3
|
+
const commentIdentity = (comment: ConsoleComment): string =>
|
|
4
|
+
JSON.stringify([comment.author, comment.createdAt, comment.body]);
|
|
5
|
+
|
|
6
|
+
export const mergePostedComments = (
|
|
7
|
+
loadedComments: ConsoleComment[],
|
|
8
|
+
postedComments: ConsoleComment[],
|
|
9
|
+
): ConsoleComment[] => {
|
|
10
|
+
const loadedIdentities = new Set(loadedComments.map(commentIdentity));
|
|
11
|
+
return [
|
|
12
|
+
...loadedComments,
|
|
13
|
+
...postedComments.filter(
|
|
14
|
+
(comment) => !loadedIdentities.has(commentIdentity(comment)),
|
|
15
|
+
),
|
|
16
|
+
];
|
|
17
|
+
};
|
|
@@ -140,6 +140,83 @@ describe('ConsoleItemDetailContainer', () => {
|
|
|
140
140
|
expect(getByPlaceholderText('Leave a comment…')).toBeInTheDocument();
|
|
141
141
|
});
|
|
142
142
|
|
|
143
|
+
it('puts a posted comment in the scrolling comment list and leaves the sticky dock holding only the input', async () => {
|
|
144
|
+
const operations = buildOperations();
|
|
145
|
+
operations.addComment = jest.fn(async (_item, body) => ({
|
|
146
|
+
author: 'HiromiShikata',
|
|
147
|
+
body,
|
|
148
|
+
createdAt: '2026-06-19T11:58:00.000Z',
|
|
149
|
+
}));
|
|
150
|
+
const { container, getByPlaceholderText, getByText } = render(
|
|
151
|
+
<ConsoleItemDetailContainer
|
|
152
|
+
tab="unread"
|
|
153
|
+
item={issueItem}
|
|
154
|
+
caches={buildCaches()}
|
|
155
|
+
operations={operations}
|
|
156
|
+
statusOptions={consoleStatusOptionsFixture}
|
|
157
|
+
storyOptions={consoleStoryOptionsFixture}
|
|
158
|
+
storyColors={consoleStoryColorsFixture}
|
|
159
|
+
storyName="TDPM Console port"
|
|
160
|
+
overlayStatus={null}
|
|
161
|
+
now={Date.parse('2026-06-19T12:00:00.000Z')}
|
|
162
|
+
onQueueAction={jest.fn()}
|
|
163
|
+
/>,
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
fireEvent.change(getByPlaceholderText('Leave a comment…'), {
|
|
167
|
+
target: { value: 'The dock must not grow with every comment.' },
|
|
168
|
+
});
|
|
169
|
+
fireEvent.click(getByText('Comment'));
|
|
170
|
+
|
|
171
|
+
await waitFor(() => {
|
|
172
|
+
expect(
|
|
173
|
+
container.querySelector('.console-comment-list')?.textContent,
|
|
174
|
+
).toContain('The dock must not grow with every comment.');
|
|
175
|
+
});
|
|
176
|
+
expect(
|
|
177
|
+
container.querySelector('.console-detail-dock')?.textContent,
|
|
178
|
+
).not.toContain('The dock must not grow with every comment.');
|
|
179
|
+
expect(
|
|
180
|
+
container.querySelectorAll('.console-detail-dock .console-comment')
|
|
181
|
+
.length,
|
|
182
|
+
).toBe(0);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('opens the comments panel of a pull request item so the posted comment is on screen', async () => {
|
|
186
|
+
const operations = buildOperations();
|
|
187
|
+
operations.addComment = jest.fn(async (_item, body) => ({
|
|
188
|
+
author: 'HiromiShikata',
|
|
189
|
+
body,
|
|
190
|
+
createdAt: '2026-06-19T11:58:00.000Z',
|
|
191
|
+
}));
|
|
192
|
+
const { container, getByPlaceholderText, getByText } = render(
|
|
193
|
+
<ConsoleItemDetailContainer
|
|
194
|
+
tab="prs"
|
|
195
|
+
item={prItem}
|
|
196
|
+
caches={buildCaches()}
|
|
197
|
+
operations={operations}
|
|
198
|
+
statusOptions={consoleStatusOptionsFixture}
|
|
199
|
+
storyOptions={consoleStoryOptionsFixture}
|
|
200
|
+
storyColors={consoleStoryColorsFixture}
|
|
201
|
+
storyName="TDPM Console port"
|
|
202
|
+
overlayStatus={null}
|
|
203
|
+
now={Date.parse('2026-06-19T12:00:00.000Z')}
|
|
204
|
+
onQueueAction={jest.fn()}
|
|
205
|
+
/>,
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
fireEvent.change(getByPlaceholderText('Leave a comment…'), {
|
|
209
|
+
target: { value: 'Posted from the pull request item.' },
|
|
210
|
+
});
|
|
211
|
+
fireEvent.click(getByText('Comment'));
|
|
212
|
+
|
|
213
|
+
await waitFor(() => {
|
|
214
|
+
expect(
|
|
215
|
+
container.querySelector('.console-comment-list')?.textContent,
|
|
216
|
+
).toContain('Posted from the pull request item.');
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
143
220
|
it('shows Approve for an issue item from the generated related open pull request urls before the related pull requests are fetched', () => {
|
|
144
221
|
const operations = buildOperations();
|
|
145
222
|
const onQueueAction = jest.fn();
|
|
@@ -13,8 +13,10 @@ import type {
|
|
|
13
13
|
ConsoleOperationHandlers,
|
|
14
14
|
ConsolePendingReviewComment,
|
|
15
15
|
} from '../logic/operations';
|
|
16
|
+
import { mergePostedComments } from '../logic/postedComments';
|
|
16
17
|
import type {
|
|
17
18
|
ConsoleColor,
|
|
19
|
+
ConsoleComment,
|
|
18
20
|
ConsoleFieldOption,
|
|
19
21
|
ConsoleListItem,
|
|
20
22
|
ConsoleOverlayStatus,
|
|
@@ -87,6 +89,15 @@ export const ConsoleItemDetailContainer = ({
|
|
|
87
89
|
},
|
|
88
90
|
[],
|
|
89
91
|
);
|
|
92
|
+
const [postedComments, setPostedComments] = useState<ConsoleComment[]>([]);
|
|
93
|
+
const addComment = useCallback(
|
|
94
|
+
async (body: string): Promise<ConsoleComment> => {
|
|
95
|
+
const comment = await operations.addComment(item, body);
|
|
96
|
+
setPostedComments((previous) => [...previous, comment]);
|
|
97
|
+
return comment;
|
|
98
|
+
},
|
|
99
|
+
[item, operations],
|
|
100
|
+
);
|
|
90
101
|
|
|
91
102
|
const handlers: ConsoleOperationHandlers = {
|
|
92
103
|
onReview: (action) => {
|
|
@@ -159,7 +170,8 @@ export const ConsoleItemDetailContainer = ({
|
|
|
159
170
|
body={detail.body}
|
|
160
171
|
bodyIsLoading={detail.bodyIsLoading}
|
|
161
172
|
bodyError={detail.bodyError}
|
|
162
|
-
comments={detail.comments}
|
|
173
|
+
comments={mergePostedComments(detail.comments, postedComments)}
|
|
174
|
+
hasPostedComment={postedComments.length > 0}
|
|
163
175
|
commentsAreLoading={detail.commentsAreLoading}
|
|
164
176
|
commentsError={detail.commentsError}
|
|
165
177
|
files={detail.files}
|
|
@@ -179,8 +191,7 @@ export const ConsoleItemDetailContainer = ({
|
|
|
179
191
|
commentComposer={
|
|
180
192
|
<ConsoleCommentComposer
|
|
181
193
|
initiallyOpen
|
|
182
|
-
|
|
183
|
-
onSubmit={(body) => operations.addComment(item, body)}
|
|
194
|
+
onSubmit={addComment}
|
|
184
195
|
onUploadFile={(file) => operations.uploadAttachment(item, file)}
|
|
185
196
|
/>
|
|
186
197
|
}
|