Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6,475 changes: 6,475 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"devDependencies": {
"@testing-library/react": "^16.3.1",
"@types/jest": "^30.0.0",
"@types/testing-library__react": "^10.0.1",
"jest": "^30.2.0",
"vitest": "^4.0.15"
}
}
23 changes: 18 additions & 5 deletions src/tools/dashboard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
-->
# Pullpiri Dashboard

Pullpiri DashboardλŠ” Podman λ“± μ»¨ν…Œμ΄λ„ˆ μž‘μ—…μ„ μ›Ήμ—μ„œ μ§κ΄€μ μœΌλ‘œ 관리할 수 μžˆλ„λ‘ λ§Œλ“  React 기반 λŒ€μ‹œλ³΄λ“œμž…λ‹ˆλ‹€.
Pullpiri DashboardλŠ” Podman λ“± μ»¨ν…Œμ΄λ„ˆ μž‘μ—…μ„ μ›Ήμ—μ„œ μ§κ΄€μ μœΌλ‘œ 관리할 수 μžˆλ„λ‘ λ§Œλ“  React 기반 λŒ€μ‹œλ³΄λ“œμž…λ‹ˆλ‹€.
이 λ””λ ‰ν† λ¦¬μ˜ μ½”λ“œλŠ” Vite 기반 ν”„λ‘ νŠΈμ—”λ“œμ΄λ©°, μ˜€ν”ˆμ†ŒμŠ€ pullpiri ν”„λ‘œμ νŠΈμ˜ μΌλΆ€λ‘œ λ°°ν¬λ©λ‹ˆλ‹€.

## μ‹œμž‘ν•˜κΈ°

### 1. μ˜μ‘΄μ„± μ„€μΉ˜

**μ΅œμƒμœ„ pullpiri ν”„λ‘œμ νŠΈ 루트**μ—μ„œ(즉, `package.json`이 μžˆλŠ” κ³³)
**μ΅œμƒμœ„ pullpiri ν”„λ‘œμ νŠΈ 루트**μ—μ„œ(즉, `package.json`이 μžˆλŠ” κ³³)
(처음 μ„€μΉ˜λΌλ©΄)
```sh
npm install
Expand Down Expand Up @@ -55,15 +55,28 @@ src/tools/dashboard/
## 자주 λ¬»λŠ” 질문(FAQ)

### Q. λŒ€μ‹œλ³΄λ“œμ—μ„œ Pod λ¦¬μŠ€νŠΈκ°€ μ•ˆ λ³΄μž…λ‹ˆλ‹€!
A. λ°±μ—”λ“œμ—μ„œ podman 정보λ₯Ό μ œκ³΅ν•˜λŠ” API μ„œλ²„κ°€ μ •μƒμ μœΌλ‘œ μ‹€ν–‰ 쀑이어야 ν•©λ‹ˆλ‹€.
(예: `podman ps` λͺ…령을 λž˜ν•‘ν•˜λŠ” Express μ„œλ²„ λ“±)
A. λ°±μ—”λ“œμ—μ„œ podman 정보λ₯Ό μ œκ³΅ν•˜λŠ” API μ„œλ²„κ°€ μ •μƒμ μœΌλ‘œ μ‹€ν–‰ 쀑이어야 ν•©λ‹ˆλ‹€.
(예: `podman ps` λͺ…령을 λž˜ν•‘ν•˜λŠ” Express μ„œλ²„ λ“±)

### Q. package μ„€μΉ˜ 쀑 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.
A. Node.js(ꢌμž₯ 18 이상)와 npm(ꢌμž₯ 9 이상)이 μ„€μΉ˜λ˜μ–΄ μžˆλŠ”μ§€ ν™•μΈν•˜μ„Έμš”.

### Q. 포트(5173)κ°€ 이미 μ‚¬μš© 쀑이라고 λ‚˜μ˜΅λ‹ˆλ‹€.
A. 이미 λ–  μžˆλŠ” Vite 개발 μ„œλ²„κ°€ μžˆλ‹€λ©΄ μ’…λ£Œν•˜κ±°λ‚˜,
A. 이미 λ–  μžˆλŠ” Vite 개발 μ„œλ²„κ°€ μžˆλ‹€λ©΄ μ’…λ£Œν•˜κ±°λ‚˜,
`vite.config.ts`μ—μ„œ λ‹€λ₯Έ 포트둜 λ³€κ²½ν•˜μ„Έμš”.

---

## Tests

Run unit tests with Vitest (from `src/tools/dashboard`):

```bash
npm install # ensure dev deps are installed
npm test # run vitest in watch mode
npm run test:coverage # run once and produce coverage (html in coverage/)
```

Coverage thresholds are set to 80% for lines, statements, functions and branches.


224 changes: 224 additions & 0 deletions src/tools/dashboard/coverage/base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
body, html {
margin:0; padding: 0;
height: 100%;
}
body {
font-family: Helvetica Neue, Helvetica, Arial;
font-size: 14px;
color:#333;
}
.small { font-size: 12px; }
*, *:after, *:before {
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
h1 { font-size: 20px; margin: 0;}
h2 { font-size: 14px; }
pre {
font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
margin: 0;
padding: 0;
-moz-tab-size: 2;
-o-tab-size: 2;
tab-size: 2;
}
a { color:#0074D9; text-decoration:none; }
a:hover { text-decoration:underline; }
.strong { font-weight: bold; }
.space-top1 { padding: 10px 0 0 0; }
.pad2y { padding: 20px 0; }
.pad1y { padding: 10px 0; }
.pad2x { padding: 0 20px; }
.pad2 { padding: 20px; }
.pad1 { padding: 10px; }
.space-left2 { padding-left:55px; }
.space-right2 { padding-right:20px; }
.center { text-align:center; }
.clearfix { display:block; }
.clearfix:after {
content:'';
display:block;
height:0;
clear:both;
visibility:hidden;
}
.fl { float: left; }
@media only screen and (max-width:640px) {
.col3 { width:100%; max-width:100%; }
.hide-mobile { display:none!important; }
}

.quiet {
color: #7f7f7f;
color: rgba(0,0,0,0.5);
}
.quiet a { opacity: 0.7; }

.fraction {
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
font-size: 10px;
color: #555;
background: #E8E8E8;
padding: 4px 5px;
border-radius: 3px;
vertical-align: middle;
}

div.path a:link, div.path a:visited { color: #333; }
table.coverage {
border-collapse: collapse;
margin: 10px 0 0 0;
padding: 0;
}

table.coverage td {
margin: 0;
padding: 0;
vertical-align: top;
}
table.coverage td.line-count {
text-align: right;
padding: 0 5px 0 20px;
}
table.coverage td.line-coverage {
text-align: right;
padding-right: 10px;
min-width:20px;
}

table.coverage td span.cline-any {
display: inline-block;
padding: 0 5px;
width: 100%;
}
.missing-if-branch {
display: inline-block;
margin-right: 5px;
border-radius: 3px;
position: relative;
padding: 0 4px;
background: #333;
color: yellow;
}

.skip-if-branch {
display: none;
margin-right: 10px;
position: relative;
padding: 0 4px;
background: #ccc;
color: white;
}
.missing-if-branch .typ, .skip-if-branch .typ {
color: inherit !important;
}
.coverage-summary {
border-collapse: collapse;
width: 100%;
}
.coverage-summary tr { border-bottom: 1px solid #bbb; }
.keyline-all { border: 1px solid #ddd; }
.coverage-summary td, .coverage-summary th { padding: 10px; }
.coverage-summary tbody { border: 1px solid #bbb; }
.coverage-summary td { border-right: 1px solid #bbb; }
.coverage-summary td:last-child { border-right: none; }
.coverage-summary th {
text-align: left;
font-weight: normal;
white-space: nowrap;
}
.coverage-summary th.file { border-right: none !important; }
.coverage-summary th.pct { }
.coverage-summary th.pic,
.coverage-summary th.abs,
.coverage-summary td.pct,
.coverage-summary td.abs { text-align: right; }
.coverage-summary td.file { white-space: nowrap; }
.coverage-summary td.pic { min-width: 120px !important; }
.coverage-summary tfoot td { }

.coverage-summary .sorter {
height: 10px;
width: 7px;
display: inline-block;
margin-left: 0.5em;
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
}
.coverage-summary .sorted .sorter {
background-position: 0 -20px;
}
.coverage-summary .sorted-desc .sorter {
background-position: 0 -10px;
}
.status-line { height: 10px; }
/* yellow */
.cbranch-no { background: yellow !important; color: #111; }
/* dark red */
.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
.low .chart { border:1px solid #C21F39 }
.highlighted,
.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
background: #C21F39 !important;
}
/* medium red */
.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
/* light red */
.low, .cline-no { background:#FCE1E5 }
/* light green */
.high, .cline-yes { background:rgb(230,245,208) }
/* medium green */
.cstat-yes { background:rgb(161,215,106) }
/* dark green */
.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
.high .chart { border:1px solid rgb(77,146,33) }
/* dark yellow (gold) */
.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
.medium .chart { border:1px solid #f9cd0b; }
/* light yellow */
.medium { background: #fff4c2; }

.cstat-skip { background: #ddd; color: #111; }
.fstat-skip { background: #ddd; color: #111 !important; }
.cbranch-skip { background: #ddd !important; color: #111; }

span.cline-neutral { background: #eaeaea; }

.coverage-summary td.empty {
opacity: .5;
padding-top: 4px;
padding-bottom: 4px;
line-height: 1;
color: #888;
}

.cover-fill, .cover-empty {
display:inline-block;
height: 12px;
}
.chart {
line-height: 0;
}
.cover-empty {
background: white;
}
.cover-full {
border-right: none !important;
}
pre.prettyprint {
border: none !important;
padding: 0 !important;
margin: 0 !important;
}
.com { color: #999 !important; }
.ignore-none { color: #999; font-weight: normal; }

.wrapper {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto -48px;
}
.footer, .push {
height: 48px;
}
87 changes: 87 additions & 0 deletions src/tools/dashboard/coverage/block-navigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/* eslint-disable */
var jumpToCode = (function init() {
// Classes of code we would like to highlight in the file view
var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];

// Elements to highlight in the file listing view
var fileListingElements = ['td.pct.low'];

// We don't want to select elements that are direct descendants of another match
var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `

// Selector that finds elements on the page to which we can jump
var selector =
fileListingElements.join(', ') +
', ' +
notSelector +
missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`

// The NodeList of matching elements
var missingCoverageElements = document.querySelectorAll(selector);

var currentIndex;

function toggleClass(index) {
missingCoverageElements
.item(currentIndex)
.classList.remove('highlighted');
missingCoverageElements.item(index).classList.add('highlighted');
}

function makeCurrent(index) {
toggleClass(index);
currentIndex = index;
missingCoverageElements.item(index).scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
});
}

function goToPrevious() {
var nextIndex = 0;
if (typeof currentIndex !== 'number' || currentIndex === 0) {
nextIndex = missingCoverageElements.length - 1;
} else if (missingCoverageElements.length > 1) {
nextIndex = currentIndex - 1;
}

makeCurrent(nextIndex);
}

function goToNext() {
var nextIndex = 0;

if (
typeof currentIndex === 'number' &&
currentIndex < missingCoverageElements.length - 1
) {
nextIndex = currentIndex + 1;
}

makeCurrent(nextIndex);
}

return function jump(event) {
if (
document.getElementById('fileSearch') === document.activeElement &&
document.activeElement != null
) {
// if we're currently focused on the search input, we don't want to navigate
return;
}

switch (event.which) {
case 78: // n
case 74: // j
goToNext();
break;
case 66: // b
case 75: // k
case 80: // p
goToPrevious();
break;
}
};
})();
window.addEventListener('keydown', jumpToCode);
Binary file added src/tools/dashboard/coverage/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading