paperclip-github-plugin 0.5.3 → 0.6.1
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/README.md +51 -2
- package/dist/manifest.js +21 -2
- package/dist/ui/index.js +589 -51
- package/dist/ui/index.js.map +3 -3
- package/dist/worker.js +1187 -46
- package/package.json +3 -3
package/dist/ui/index.js
CHANGED
|
@@ -22995,6 +22995,28 @@ var EMPTY_SETTINGS = {
|
|
|
22995
22995
|
advancedSettings: DEFAULT_ADVANCED_SETTINGS,
|
|
22996
22996
|
availableAssignees: []
|
|
22997
22997
|
};
|
|
22998
|
+
var EMPTY_DASHBOARD_METRICS = {
|
|
22999
|
+
status: "company_required",
|
|
23000
|
+
historyWindowDays: 14,
|
|
23001
|
+
comparisonWindowDays: 30,
|
|
23002
|
+
backlog: {
|
|
23003
|
+
history: []
|
|
23004
|
+
},
|
|
23005
|
+
githubIssuesClosed: {
|
|
23006
|
+
currentPeriodCount: 0,
|
|
23007
|
+
previousPeriodCount: 0,
|
|
23008
|
+
history: []
|
|
23009
|
+
},
|
|
23010
|
+
paperclipPullRequestsCreated: {
|
|
23011
|
+
currentPeriodCount: 0,
|
|
23012
|
+
previousPeriodCount: 0,
|
|
23013
|
+
history: []
|
|
23014
|
+
},
|
|
23015
|
+
notes: {
|
|
23016
|
+
backlogHistoryAvailable: false,
|
|
23017
|
+
activityHistoryAvailable: false
|
|
23018
|
+
}
|
|
23019
|
+
};
|
|
22998
23020
|
function createIdleSyncState() {
|
|
22999
23021
|
return {
|
|
23000
23022
|
status: "idle"
|
|
@@ -26142,7 +26164,7 @@ var WIDGET_STYLES = `
|
|
|
26142
26164
|
.ghsync-widget__stats {
|
|
26143
26165
|
display: grid;
|
|
26144
26166
|
gap: 12px;
|
|
26145
|
-
grid-template-columns: repeat(
|
|
26167
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
26146
26168
|
border-top: 1px solid var(--ghsync-border-soft);
|
|
26147
26169
|
padding-top: 14px;
|
|
26148
26170
|
}
|
|
@@ -26155,39 +26177,117 @@ var WIDGET_STYLES = `
|
|
|
26155
26177
|
|
|
26156
26178
|
.ghsync-widget__stat {
|
|
26157
26179
|
display: grid;
|
|
26158
|
-
gap:
|
|
26159
|
-
padding:
|
|
26180
|
+
gap: 10px;
|
|
26181
|
+
padding: 14px;
|
|
26160
26182
|
border: 1px solid var(--ghsync-border-soft);
|
|
26161
26183
|
border-radius: 10px;
|
|
26162
26184
|
background: var(--ghsync-surfaceAlt);
|
|
26163
26185
|
}
|
|
26164
26186
|
|
|
26165
|
-
.ghsync-widget__stat--
|
|
26166
|
-
border-color: var(--ghsync-
|
|
26167
|
-
|
|
26187
|
+
.ghsync-widget__stat--success {
|
|
26188
|
+
border-color: var(--ghsync-success-border);
|
|
26189
|
+
}
|
|
26190
|
+
|
|
26191
|
+
.ghsync-widget__stat--warning {
|
|
26192
|
+
border-color: var(--ghsync-warning-border);
|
|
26168
26193
|
}
|
|
26169
26194
|
|
|
26170
|
-
.ghsync-widget__stat
|
|
26195
|
+
.ghsync-widget__stat--info {
|
|
26196
|
+
border-color: var(--ghsync-info-border);
|
|
26197
|
+
}
|
|
26198
|
+
|
|
26199
|
+
.ghsync-widget__stat-top {
|
|
26200
|
+
display: flex;
|
|
26201
|
+
align-items: flex-start;
|
|
26202
|
+
justify-content: space-between;
|
|
26203
|
+
gap: 12px;
|
|
26204
|
+
}
|
|
26205
|
+
|
|
26206
|
+
.ghsync-widget__stat-value {
|
|
26207
|
+
display: grid;
|
|
26208
|
+
gap: 6px;
|
|
26209
|
+
}
|
|
26210
|
+
|
|
26211
|
+
.ghsync-widget__stat-label {
|
|
26171
26212
|
display: block;
|
|
26172
26213
|
font-size: 12px;
|
|
26173
26214
|
font-weight: 600;
|
|
26174
26215
|
color: var(--ghsync-title);
|
|
26175
26216
|
}
|
|
26176
26217
|
|
|
26177
|
-
.ghsync-widget__stat strong {
|
|
26218
|
+
.ghsync-widget__stat-value strong {
|
|
26178
26219
|
display: block;
|
|
26179
26220
|
font-size: 24px;
|
|
26180
26221
|
line-height: 1;
|
|
26181
26222
|
color: var(--ghsync-title);
|
|
26182
26223
|
}
|
|
26183
26224
|
|
|
26184
|
-
.ghsync-widget__stat
|
|
26225
|
+
.ghsync-widget__stat-change {
|
|
26226
|
+
margin: 0;
|
|
26227
|
+
font-size: 11px;
|
|
26228
|
+
line-height: 1.45;
|
|
26229
|
+
color: var(--ghsync-muted);
|
|
26230
|
+
}
|
|
26231
|
+
|
|
26232
|
+
.ghsync-widget__stat-change--success {
|
|
26233
|
+
color: var(--ghsync-success-text);
|
|
26234
|
+
}
|
|
26235
|
+
|
|
26236
|
+
.ghsync-widget__stat-change--warning {
|
|
26237
|
+
color: var(--ghsync-warning-text);
|
|
26238
|
+
}
|
|
26239
|
+
|
|
26240
|
+
.ghsync-widget__stat-change--info {
|
|
26241
|
+
color: var(--ghsync-info-text);
|
|
26242
|
+
}
|
|
26243
|
+
|
|
26244
|
+
.ghsync-widget__stat-note {
|
|
26185
26245
|
margin: 0;
|
|
26186
26246
|
color: var(--ghsync-muted);
|
|
26187
26247
|
font-size: 11px;
|
|
26188
26248
|
line-height: 1.5;
|
|
26189
26249
|
}
|
|
26190
26250
|
|
|
26251
|
+
.ghsync-widget__trend {
|
|
26252
|
+
color: var(--ghsync-muted);
|
|
26253
|
+
}
|
|
26254
|
+
|
|
26255
|
+
.ghsync-widget__trend svg {
|
|
26256
|
+
display: block;
|
|
26257
|
+
width: 100%;
|
|
26258
|
+
height: 32px;
|
|
26259
|
+
}
|
|
26260
|
+
|
|
26261
|
+
.ghsync-widget__trend--success {
|
|
26262
|
+
color: var(--ghsync-success-text);
|
|
26263
|
+
}
|
|
26264
|
+
|
|
26265
|
+
.ghsync-widget__trend--warning {
|
|
26266
|
+
color: var(--ghsync-warning-text);
|
|
26267
|
+
}
|
|
26268
|
+
|
|
26269
|
+
.ghsync-widget__trend--info {
|
|
26270
|
+
color: var(--ghsync-info-text);
|
|
26271
|
+
}
|
|
26272
|
+
|
|
26273
|
+
.ghsync-widget__trend-line {
|
|
26274
|
+
fill: none;
|
|
26275
|
+
stroke: currentColor;
|
|
26276
|
+
stroke-width: 2;
|
|
26277
|
+
stroke-linecap: round;
|
|
26278
|
+
stroke-linejoin: round;
|
|
26279
|
+
}
|
|
26280
|
+
|
|
26281
|
+
.ghsync-widget__trend-area {
|
|
26282
|
+
fill: currentColor;
|
|
26283
|
+
opacity: 0.12;
|
|
26284
|
+
}
|
|
26285
|
+
|
|
26286
|
+
.ghsync-widget__trend-bar {
|
|
26287
|
+
fill: currentColor;
|
|
26288
|
+
opacity: 0.9;
|
|
26289
|
+
}
|
|
26290
|
+
|
|
26191
26291
|
.ghsync-widget__summary {
|
|
26192
26292
|
display: grid;
|
|
26193
26293
|
gap: 4px;
|
|
@@ -26430,7 +26530,6 @@ var WIDGET_STYLES = `
|
|
|
26430
26530
|
@media (max-width: 720px) {
|
|
26431
26531
|
.ghsync-widget__stats {
|
|
26432
26532
|
grid-template-columns: minmax(0, 1fr);
|
|
26433
|
-
gap: 12px;
|
|
26434
26533
|
}
|
|
26435
26534
|
|
|
26436
26535
|
.ghsync-widget__top,
|
|
@@ -26439,11 +26538,6 @@ var WIDGET_STYLES = `
|
|
|
26439
26538
|
align-items: stretch;
|
|
26440
26539
|
}
|
|
26441
26540
|
|
|
26442
|
-
.ghsync-widget__stat {
|
|
26443
|
-
padding-left: 0;
|
|
26444
|
-
border-left: 0;
|
|
26445
|
-
}
|
|
26446
|
-
|
|
26447
26541
|
.ghsync-widget__button-row {
|
|
26448
26542
|
width: 100%;
|
|
26449
26543
|
}
|
|
@@ -28681,6 +28775,68 @@ function getSyncMetricCards(params) {
|
|
|
28681
28775
|
}
|
|
28682
28776
|
];
|
|
28683
28777
|
}
|
|
28778
|
+
function getSyncMetricCardTone(card) {
|
|
28779
|
+
if (card.key === "errored") {
|
|
28780
|
+
return card.emphasized ? "warning" : "success";
|
|
28781
|
+
}
|
|
28782
|
+
return card.value > 0 ? "success" : "info";
|
|
28783
|
+
}
|
|
28784
|
+
function getKpiDashboardSummary(params) {
|
|
28785
|
+
if (!params.hasCompanyContext) {
|
|
28786
|
+
return {
|
|
28787
|
+
label: "Company required",
|
|
28788
|
+
tone: "warning",
|
|
28789
|
+
title: "Open a company dashboard",
|
|
28790
|
+
body: "Compare backlog, issue closure, and Paperclip PR creation over time."
|
|
28791
|
+
};
|
|
28792
|
+
}
|
|
28793
|
+
if (params.syncIssue === "missing_token") {
|
|
28794
|
+
return {
|
|
28795
|
+
label: "Setup required",
|
|
28796
|
+
tone: "warning",
|
|
28797
|
+
title: "Finish setup",
|
|
28798
|
+
body: "Save a GitHub token to start KPI tracking."
|
|
28799
|
+
};
|
|
28800
|
+
}
|
|
28801
|
+
if (params.syncIssue === "missing_board_access") {
|
|
28802
|
+
return {
|
|
28803
|
+
label: "Board access required",
|
|
28804
|
+
tone: "warning",
|
|
28805
|
+
title: "Connect Paperclip board access",
|
|
28806
|
+
body: "This deployment needs board access before KPI history can refresh."
|
|
28807
|
+
};
|
|
28808
|
+
}
|
|
28809
|
+
if (params.metrics.status === "no_mappings") {
|
|
28810
|
+
return {
|
|
28811
|
+
label: "Setup required",
|
|
28812
|
+
tone: "warning",
|
|
28813
|
+
title: "Map a repository",
|
|
28814
|
+
body: "Add at least one repository, then run a full sync."
|
|
28815
|
+
};
|
|
28816
|
+
}
|
|
28817
|
+
if (params.syncState.status === "running") {
|
|
28818
|
+
return {
|
|
28819
|
+
label: "Syncing",
|
|
28820
|
+
tone: "info",
|
|
28821
|
+
title: "KPI history is updating",
|
|
28822
|
+
body: "Backlog and activity history refresh during sync."
|
|
28823
|
+
};
|
|
28824
|
+
}
|
|
28825
|
+
if (!params.metrics.notes.backlogHistoryAvailable && !params.metrics.notes.activityHistoryAvailable) {
|
|
28826
|
+
return {
|
|
28827
|
+
label: "Waiting on first sync",
|
|
28828
|
+
tone: "info",
|
|
28829
|
+
title: "Run the first full sync",
|
|
28830
|
+
body: "The first sync seeds backlog and issue history."
|
|
28831
|
+
};
|
|
28832
|
+
}
|
|
28833
|
+
return {
|
|
28834
|
+
label: "Ready",
|
|
28835
|
+
tone: params.syncState.status === "success" ? "success" : "info",
|
|
28836
|
+
title: "Company delivery KPIs",
|
|
28837
|
+
body: "Track backlog, issue closure, and Paperclip PR creation against recent history."
|
|
28838
|
+
};
|
|
28839
|
+
}
|
|
28684
28840
|
function getDashboardSummary(params) {
|
|
28685
28841
|
const cadence = formatScheduleFrequency(params.scheduleFrequencyMinutes);
|
|
28686
28842
|
const activeRateLimitPause = getActiveRateLimitPause(params.syncState);
|
|
@@ -28756,6 +28912,157 @@ function getDashboardSummary(params) {
|
|
|
28756
28912
|
body: `Your repository mapping is in place. Automatic sync runs ${cadence}.`
|
|
28757
28913
|
};
|
|
28758
28914
|
}
|
|
28915
|
+
function formatWidgetMetricValue(value) {
|
|
28916
|
+
return typeof value === "number" ? String(value) : "\u2014";
|
|
28917
|
+
}
|
|
28918
|
+
function getPeriodDeltaTone(current, previous3) {
|
|
28919
|
+
if (current > previous3) {
|
|
28920
|
+
return "success";
|
|
28921
|
+
}
|
|
28922
|
+
if (current < previous3) {
|
|
28923
|
+
return "warning";
|
|
28924
|
+
}
|
|
28925
|
+
return "neutral";
|
|
28926
|
+
}
|
|
28927
|
+
function getBacklogDeltaTone(current, previous3) {
|
|
28928
|
+
if (current < previous3) {
|
|
28929
|
+
return "success";
|
|
28930
|
+
}
|
|
28931
|
+
if (current > previous3) {
|
|
28932
|
+
return "warning";
|
|
28933
|
+
}
|
|
28934
|
+
return "neutral";
|
|
28935
|
+
}
|
|
28936
|
+
function describePeriodChange(current, previous3, comparisonWindowDays) {
|
|
28937
|
+
if (current > previous3) {
|
|
28938
|
+
return `+${current - previous3} vs previous ${comparisonWindowDays} days`;
|
|
28939
|
+
}
|
|
28940
|
+
if (current < previous3) {
|
|
28941
|
+
return `-${previous3 - current} vs previous ${comparisonWindowDays} days`;
|
|
28942
|
+
}
|
|
28943
|
+
return `No change vs previous ${comparisonWindowDays} days`;
|
|
28944
|
+
}
|
|
28945
|
+
function describeBacklogChange(current, previous3, comparisonWindowDays) {
|
|
28946
|
+
if (current === void 0 || previous3 === void 0) {
|
|
28947
|
+
return "Need more sync history to compare backlog.";
|
|
28948
|
+
}
|
|
28949
|
+
if (current < previous3) {
|
|
28950
|
+
return `-${previous3 - current} open issues vs ${comparisonWindowDays} days ago`;
|
|
28951
|
+
}
|
|
28952
|
+
if (current > previous3) {
|
|
28953
|
+
return `+${current - previous3} open issues vs ${comparisonWindowDays} days ago`;
|
|
28954
|
+
}
|
|
28955
|
+
return `No change vs ${comparisonWindowDays} days ago`;
|
|
28956
|
+
}
|
|
28957
|
+
function buildDashboardKpiCards(params) {
|
|
28958
|
+
const { metrics, hasCompanyContext } = params;
|
|
28959
|
+
const genericContextNote = !hasCompanyContext ? "Open in a company dashboard." : metrics.status === "no_mappings" ? "Add a repository mapping." : null;
|
|
28960
|
+
const backlogAvailable = hasCompanyContext && metrics.status === "ready" && metrics.notes.backlogHistoryAvailable && typeof metrics.backlog.currentOpenIssueCount === "number";
|
|
28961
|
+
const backlogCurrent = metrics.backlog.currentOpenIssueCount;
|
|
28962
|
+
const backlogComparison = metrics.backlog.comparisonOpenIssueCount;
|
|
28963
|
+
const closedIssuesAvailable = hasCompanyContext && metrics.status === "ready" && metrics.notes.activityHistoryAvailable;
|
|
28964
|
+
const createdAvailable = closedIssuesAvailable;
|
|
28965
|
+
return [
|
|
28966
|
+
{
|
|
28967
|
+
key: "backlog",
|
|
28968
|
+
title: "Open GitHub backlog",
|
|
28969
|
+
valueLabel: formatWidgetMetricValue(backlogCurrent),
|
|
28970
|
+
changeLabel: describeBacklogChange(backlogCurrent, backlogComparison, metrics.comparisonWindowDays),
|
|
28971
|
+
note: genericContextNote ?? (backlogAvailable ? metrics.backlog.lastCapturedAt ? `Snapshot ${formatDate(metrics.backlog.lastCapturedAt, metrics.backlog.lastCapturedAt)}.` : "Latest sync snapshot." : "Run a full sync to seed backlog history."),
|
|
28972
|
+
tone: backlogAvailable && backlogComparison !== void 0 && backlogCurrent !== void 0 ? getBacklogDeltaTone(backlogCurrent, backlogComparison) : "neutral",
|
|
28973
|
+
chartKind: "line",
|
|
28974
|
+
history: metrics.backlog.history.map((point5) => point5.value),
|
|
28975
|
+
available: backlogAvailable
|
|
28976
|
+
},
|
|
28977
|
+
{
|
|
28978
|
+
key: "closed-issues",
|
|
28979
|
+
title: "GitHub issues closed",
|
|
28980
|
+
valueLabel: String(metrics.githubIssuesClosed.currentPeriodCount),
|
|
28981
|
+
changeLabel: describePeriodChange(
|
|
28982
|
+
metrics.githubIssuesClosed.currentPeriodCount,
|
|
28983
|
+
metrics.githubIssuesClosed.previousPeriodCount,
|
|
28984
|
+
metrics.comparisonWindowDays
|
|
28985
|
+
),
|
|
28986
|
+
note: genericContextNote ?? (closedIssuesAvailable ? metrics.githubIssuesClosed.lastRecordedAt ? `Through ${formatDate(metrics.githubIssuesClosed.lastRecordedAt, metrics.githubIssuesClosed.lastRecordedAt)}.` : "From sync-detected closures." : "Appears after sync records closures."),
|
|
28987
|
+
tone: getPeriodDeltaTone(
|
|
28988
|
+
metrics.githubIssuesClosed.currentPeriodCount,
|
|
28989
|
+
metrics.githubIssuesClosed.previousPeriodCount
|
|
28990
|
+
),
|
|
28991
|
+
chartKind: "bars",
|
|
28992
|
+
history: metrics.githubIssuesClosed.history.map((point5) => point5.value),
|
|
28993
|
+
available: closedIssuesAvailable
|
|
28994
|
+
},
|
|
28995
|
+
{
|
|
28996
|
+
key: "created-prs",
|
|
28997
|
+
title: "Paperclip PRs created",
|
|
28998
|
+
valueLabel: String(metrics.paperclipPullRequestsCreated.currentPeriodCount),
|
|
28999
|
+
changeLabel: describePeriodChange(
|
|
29000
|
+
metrics.paperclipPullRequestsCreated.currentPeriodCount,
|
|
29001
|
+
metrics.paperclipPullRequestsCreated.previousPeriodCount,
|
|
29002
|
+
metrics.comparisonWindowDays
|
|
29003
|
+
),
|
|
29004
|
+
note: genericContextNote ?? (createdAvailable ? metrics.paperclipPullRequestsCreated.lastRecordedAt ? `Through ${formatDate(metrics.paperclipPullRequestsCreated.lastRecordedAt, metrics.paperclipPullRequestsCreated.lastRecordedAt)}.` : "From Paperclip-attributed PR events." : "Appears after Paperclip records PR creation."),
|
|
29005
|
+
tone: getPeriodDeltaTone(
|
|
29006
|
+
metrics.paperclipPullRequestsCreated.currentPeriodCount,
|
|
29007
|
+
metrics.paperclipPullRequestsCreated.previousPeriodCount
|
|
29008
|
+
),
|
|
29009
|
+
chartKind: "bars",
|
|
29010
|
+
history: metrics.paperclipPullRequestsCreated.history.map((point5) => point5.value),
|
|
29011
|
+
available: createdAvailable
|
|
29012
|
+
}
|
|
29013
|
+
];
|
|
29014
|
+
}
|
|
29015
|
+
function buildLineChartPath(values, width, height) {
|
|
29016
|
+
if (values.length === 0) {
|
|
29017
|
+
return "";
|
|
29018
|
+
}
|
|
29019
|
+
const min = Math.min(...values);
|
|
29020
|
+
const max = Math.max(...values);
|
|
29021
|
+
const range = max - min || 1;
|
|
29022
|
+
return values.map((value, index2) => {
|
|
29023
|
+
const x = values.length === 1 ? width / 2 : index2 / (values.length - 1) * width;
|
|
29024
|
+
const y = height - (value - min) / range * (height - 6) - 3;
|
|
29025
|
+
return `${index2 === 0 ? "M" : "L"} ${x.toFixed(2)} ${y.toFixed(2)}`;
|
|
29026
|
+
}).join(" ");
|
|
29027
|
+
}
|
|
29028
|
+
function buildLineChartArea(values, width, height) {
|
|
29029
|
+
const linePath = buildLineChartPath(values, width, height);
|
|
29030
|
+
if (!linePath || values.length === 0) {
|
|
29031
|
+
return "";
|
|
29032
|
+
}
|
|
29033
|
+
const firstX = values.length === 1 ? width / 2 : 0;
|
|
29034
|
+
const lastX = values.length === 1 ? width / 2 : width;
|
|
29035
|
+
return `${linePath} L ${lastX.toFixed(2)} ${height} L ${firstX.toFixed(2)} ${height} Z`;
|
|
29036
|
+
}
|
|
29037
|
+
function DashboardTrendGraphic(props) {
|
|
29038
|
+
const values = props.values.length > 0 ? props.values : [0];
|
|
29039
|
+
const width = 112;
|
|
29040
|
+
const height = 32;
|
|
29041
|
+
const max = Math.max(...values, 0, 1);
|
|
29042
|
+
const linePath = props.kind === "line" ? buildLineChartPath(values, width, height) : "";
|
|
29043
|
+
const areaPath = props.kind === "line" ? buildLineChartArea(values, width, height) : "";
|
|
29044
|
+
return /* @__PURE__ */ jsx2("div", { className: `ghsync-widget__trend ghsync-widget__trend--${props.tone}`, "aria-hidden": "true", children: /* @__PURE__ */ jsx2("svg", { viewBox: `0 0 ${width} ${height}`, focusable: "false", children: props.kind === "line" ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
29045
|
+
areaPath ? /* @__PURE__ */ jsx2("path", { d: areaPath, className: "ghsync-widget__trend-area" }) : null,
|
|
29046
|
+
linePath ? /* @__PURE__ */ jsx2("path", { d: linePath, className: "ghsync-widget__trend-line" }) : null
|
|
29047
|
+
] }) : values.map((value, index2) => {
|
|
29048
|
+
const barWidth = width / values.length;
|
|
29049
|
+
const x = index2 * barWidth + 1;
|
|
29050
|
+
const barHeight = Math.max(3, value / max * (height - 4));
|
|
29051
|
+
const y = height - barHeight - 1;
|
|
29052
|
+
return /* @__PURE__ */ jsx2(
|
|
29053
|
+
"rect",
|
|
29054
|
+
{
|
|
29055
|
+
x,
|
|
29056
|
+
y,
|
|
29057
|
+
width: Math.max(2, barWidth - 3),
|
|
29058
|
+
height: barHeight,
|
|
29059
|
+
rx: 2,
|
|
29060
|
+
className: "ghsync-widget__trend-bar"
|
|
29061
|
+
},
|
|
29062
|
+
`${index2}-${value}`
|
|
29063
|
+
);
|
|
29064
|
+
}) }) });
|
|
29065
|
+
}
|
|
28759
29066
|
function buildThemeVars(theme, themeMode) {
|
|
28760
29067
|
return {
|
|
28761
29068
|
colorScheme: themeMode,
|
|
@@ -33195,15 +33502,19 @@ function GitHubSyncDashboardWidget() {
|
|
|
33195
33502
|
runningSync,
|
|
33196
33503
|
scheduleFrequencyMinutes
|
|
33197
33504
|
});
|
|
33198
|
-
const syncProgress = getRunningSyncProgressModel(displaySyncState);
|
|
33199
33505
|
const syncMetricCards = getSyncMetricCards({
|
|
33200
33506
|
totalSyncedIssuesCount: current.totalSyncedIssuesCount,
|
|
33201
33507
|
erroredIssuesCount: displaySyncState.erroredIssuesCount,
|
|
33202
33508
|
syncState: displaySyncState,
|
|
33203
33509
|
savedMappingCount
|
|
33204
33510
|
});
|
|
33511
|
+
const syncProgress = getRunningSyncProgressModel(displaySyncState);
|
|
33205
33512
|
const lastSync = formatDate(displaySyncState.checkedAt, "Never");
|
|
33206
33513
|
const armSyncCompletionToast = useSyncCompletionToast(displaySyncState, toast);
|
|
33514
|
+
const widgetStatusSummary = showInitialLoadingState ? "Fetching the latest GitHub sync state from the worker." : syncProgress ? [
|
|
33515
|
+
syncProgress.issueProgressLabel,
|
|
33516
|
+
syncProgress.currentIssueLabel ?? syncProgress.repositoryPosition
|
|
33517
|
+
].filter((value) => Boolean(value)).join(" \xB7 ") : syncSetupIssue === "missing_token" ? "Open settings to validate GitHub access." : syncSetupIssue === "missing_mapping" ? "Open settings and add a repository. The Paperclip project will be created if it does not exist." : syncSetupIssue === "missing_board_access" ? hasCompanyContext ? "Open settings and connect Paperclip board access before running sync." : "Open plugin settings inside a company to connect required Paperclip board access." : displaySyncState.message ?? (displaySyncState.checkedAt ? `Last checked ${lastSync}.` : `Automatic sync runs ${scheduleDescription}.`);
|
|
33207
33518
|
useEffect2(() => {
|
|
33208
33519
|
if (settings.data) {
|
|
33209
33520
|
setCachedSettings(settings.data);
|
|
@@ -33232,41 +33543,41 @@ function GitHubSyncDashboardWidget() {
|
|
|
33232
33543
|
if (displaySyncState.status !== "running") {
|
|
33233
33544
|
return;
|
|
33234
33545
|
}
|
|
33235
|
-
const
|
|
33546
|
+
const intervalId = globalThis.setInterval(() => {
|
|
33236
33547
|
try {
|
|
33237
33548
|
settings.refresh();
|
|
33238
33549
|
} catch {
|
|
33239
33550
|
return;
|
|
33240
33551
|
}
|
|
33241
|
-
};
|
|
33242
|
-
const intervalId = globalThis.setInterval(() => {
|
|
33243
|
-
refreshSettings();
|
|
33244
33552
|
}, SYNC_POLL_INTERVAL_MS);
|
|
33245
|
-
|
|
33553
|
+
try {
|
|
33554
|
+
settings.refresh();
|
|
33555
|
+
} catch {
|
|
33556
|
+
}
|
|
33246
33557
|
return () => {
|
|
33247
33558
|
globalThis.clearInterval(intervalId);
|
|
33248
33559
|
};
|
|
33249
33560
|
}, [displaySyncState.status, settings.refresh]);
|
|
33250
33561
|
useEffect2(() => {
|
|
33251
|
-
|
|
33562
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
33563
|
+
return;
|
|
33564
|
+
}
|
|
33565
|
+
const refreshWidgetData = () => {
|
|
33252
33566
|
try {
|
|
33253
33567
|
settings.refresh();
|
|
33254
33568
|
} catch {
|
|
33255
33569
|
return;
|
|
33256
33570
|
}
|
|
33257
33571
|
};
|
|
33258
|
-
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
33259
|
-
return;
|
|
33260
|
-
}
|
|
33261
33572
|
const handleSettingsUpdated = () => {
|
|
33262
|
-
|
|
33573
|
+
refreshWidgetData();
|
|
33263
33574
|
};
|
|
33264
33575
|
const handleWindowFocus = () => {
|
|
33265
|
-
|
|
33576
|
+
refreshWidgetData();
|
|
33266
33577
|
};
|
|
33267
33578
|
const handleVisibilityChange = () => {
|
|
33268
33579
|
if (document.visibilityState === "visible") {
|
|
33269
|
-
|
|
33580
|
+
refreshWidgetData();
|
|
33270
33581
|
}
|
|
33271
33582
|
};
|
|
33272
33583
|
window.addEventListener(GITHUB_SYNC_SETTINGS_UPDATED_EVENT, handleSettingsUpdated);
|
|
@@ -33299,7 +33610,7 @@ function GitHubSyncDashboardWidget() {
|
|
|
33299
33610
|
});
|
|
33300
33611
|
armSyncCompletionToast(nextSyncState);
|
|
33301
33612
|
notifyGitHubSyncSettingsChanged();
|
|
33302
|
-
await settings.refresh();
|
|
33613
|
+
await Promise.resolve().then(() => settings.refresh());
|
|
33303
33614
|
} catch (error) {
|
|
33304
33615
|
const message = getActionErrorMessage(error, "Unable to run GitHub sync.");
|
|
33305
33616
|
setManualSyncRequestError(message);
|
|
@@ -33309,7 +33620,7 @@ function GitHubSyncDashboardWidget() {
|
|
|
33309
33620
|
tone: "error"
|
|
33310
33621
|
});
|
|
33311
33622
|
try {
|
|
33312
|
-
await settings.refresh();
|
|
33623
|
+
await Promise.resolve().then(() => settings.refresh());
|
|
33313
33624
|
} catch {
|
|
33314
33625
|
return;
|
|
33315
33626
|
}
|
|
@@ -33333,7 +33644,7 @@ function GitHubSyncDashboardWidget() {
|
|
|
33333
33644
|
});
|
|
33334
33645
|
armSyncCompletionToast(nextSyncState);
|
|
33335
33646
|
notifyGitHubSyncSettingsChanged();
|
|
33336
|
-
await settings.refresh();
|
|
33647
|
+
await Promise.resolve().then(() => settings.refresh());
|
|
33337
33648
|
} catch (error) {
|
|
33338
33649
|
const message = getActionErrorMessage(error, "Unable to cancel GitHub sync.");
|
|
33339
33650
|
setManualSyncRequestError(message);
|
|
@@ -33378,40 +33689,42 @@ function GitHubSyncDashboardWidget() {
|
|
|
33378
33689
|
] })
|
|
33379
33690
|
] }),
|
|
33380
33691
|
settings.error ? /* @__PURE__ */ jsx2("div", { className: "ghsync-widget__message", children: settings.error.message }) : null,
|
|
33381
|
-
/* @__PURE__ */ jsx2("div", { className: "ghsync-widget__stats", children: syncMetricCards.map((
|
|
33382
|
-
|
|
33383
|
-
|
|
33384
|
-
|
|
33385
|
-
|
|
33386
|
-
|
|
33387
|
-
|
|
33388
|
-
|
|
33389
|
-
|
|
33390
|
-
|
|
33391
|
-
|
|
33392
|
-
|
|
33393
|
-
|
|
33692
|
+
/* @__PURE__ */ jsx2("div", { className: "ghsync-widget__stats", children: syncMetricCards.map((card) => {
|
|
33693
|
+
const tone = getSyncMetricCardTone(card);
|
|
33694
|
+
return /* @__PURE__ */ jsxs2(
|
|
33695
|
+
"div",
|
|
33696
|
+
{
|
|
33697
|
+
className: `ghsync-widget__stat ghsync-widget__stat--${tone}`,
|
|
33698
|
+
children: [
|
|
33699
|
+
/* @__PURE__ */ jsx2("div", { className: "ghsync-widget__stat-top", children: /* @__PURE__ */ jsxs2("div", { className: "ghsync-widget__stat-value", children: [
|
|
33700
|
+
/* @__PURE__ */ jsx2("span", { className: "ghsync-widget__stat-label", children: card.label }),
|
|
33701
|
+
/* @__PURE__ */ jsx2("strong", { children: showInitialLoadingState ? /* @__PURE__ */ jsx2(LoadingSpinner, { size: "sm", label: `Loading ${card.label.toLowerCase()}` }) : String(card.value) })
|
|
33702
|
+
] }) }),
|
|
33703
|
+
/* @__PURE__ */ jsx2("p", { className: `ghsync-widget__stat-change ghsync-widget__stat-change--${tone}`, children: showInitialLoadingState ? "Loading sync summary." : card.description })
|
|
33704
|
+
]
|
|
33705
|
+
},
|
|
33706
|
+
card.key
|
|
33707
|
+
);
|
|
33708
|
+
}) }),
|
|
33709
|
+
syncInFlight ? /* @__PURE__ */ jsx2(
|
|
33394
33710
|
SyncProgressPanel,
|
|
33395
33711
|
{
|
|
33396
33712
|
syncState: displaySyncState,
|
|
33397
33713
|
compact: true
|
|
33398
33714
|
}
|
|
33399
|
-
),
|
|
33715
|
+
) : null,
|
|
33400
33716
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync-widget__summary", children: [
|
|
33401
33717
|
/* @__PURE__ */ jsx2("strong", { children: showInitialLoadingState ? "Loading sync status\u2026" : syncInFlight ? "Live run" : syncUnlocked ? "Latest result" : "Next step" }),
|
|
33402
|
-
/* @__PURE__ */ jsx2("span", { children:
|
|
33403
|
-
syncProgress.issueProgressLabel,
|
|
33404
|
-
syncProgress.currentIssueLabel ?? syncProgress.repositoryPosition
|
|
33405
|
-
].filter((value) => Boolean(value)).join(" \xB7 ") : syncSetupIssue === "missing_token" ? "Open settings to validate GitHub access." : syncSetupIssue === "missing_mapping" ? "Open settings and add a repository. The Paperclip project will be created if it does not exist." : syncSetupIssue === "missing_board_access" ? hasCompanyContext ? "Open settings and connect Paperclip board access before running sync." : "Open plugin settings inside a company to connect required Paperclip board access." : displaySyncState.checkedAt ? `Last checked ${lastSync}.` : "Everything is configured. Run the first sync when you are ready." })
|
|
33718
|
+
/* @__PURE__ */ jsx2("span", { children: widgetStatusSummary })
|
|
33406
33719
|
] }),
|
|
33407
|
-
/* @__PURE__ */ jsx2(
|
|
33720
|
+
manualSyncRequestError || displaySyncState.status === "error" || Boolean(displaySyncState.recentFailures?.length) ? /* @__PURE__ */ jsx2(
|
|
33408
33721
|
SyncDiagnosticsPanel,
|
|
33409
33722
|
{
|
|
33410
33723
|
syncState: displaySyncState,
|
|
33411
33724
|
requestError: manualSyncRequestError,
|
|
33412
33725
|
compact: true
|
|
33413
33726
|
}
|
|
33414
|
-
),
|
|
33727
|
+
) : null,
|
|
33415
33728
|
/* @__PURE__ */ jsx2("div", { className: "ghsync-widget__actions", children: /* @__PURE__ */ jsxs2("div", { className: "ghsync-widget__button-row", children: [
|
|
33416
33729
|
/* @__PURE__ */ jsx2(
|
|
33417
33730
|
"a",
|
|
@@ -33445,6 +33758,230 @@ function GitHubSyncDashboardWidget() {
|
|
|
33445
33758
|
] })
|
|
33446
33759
|
] });
|
|
33447
33760
|
}
|
|
33761
|
+
function GitHubSyncKpiDashboardWidget() {
|
|
33762
|
+
const hostContext = useHostContext();
|
|
33763
|
+
const settings = usePluginData(
|
|
33764
|
+
"settings.registration",
|
|
33765
|
+
hostContext.companyId ? { companyId: hostContext.companyId } : {}
|
|
33766
|
+
);
|
|
33767
|
+
const dashboardMetrics = usePluginData(
|
|
33768
|
+
"dashboard.metrics",
|
|
33769
|
+
hostContext.companyId ? { companyId: hostContext.companyId } : {}
|
|
33770
|
+
);
|
|
33771
|
+
const [settingsHref, setSettingsHref] = useState2(SETTINGS_INDEX_HREF2);
|
|
33772
|
+
const [cachedSettings, setCachedSettings] = useState2(null);
|
|
33773
|
+
const [cachedDashboardMetrics, setCachedDashboardMetrics] = useState2(null);
|
|
33774
|
+
const themeMode = useResolvedThemeMode();
|
|
33775
|
+
const boardAccessRequirement = usePaperclipBoardAccessRequirement();
|
|
33776
|
+
const theme = themeMode === "light" ? LIGHT_PALETTE : DARK_PALETTE;
|
|
33777
|
+
const themeVars = buildThemeVars(theme, themeMode);
|
|
33778
|
+
const current = settings.data ?? cachedSettings ?? EMPTY_SETTINGS;
|
|
33779
|
+
const currentDashboardMetrics = dashboardMetrics.data ?? cachedDashboardMetrics ?? EMPTY_DASHBOARD_METRICS;
|
|
33780
|
+
const showInitialLoadingState = settings.loading && !settings.data && !cachedSettings;
|
|
33781
|
+
const syncState = current.syncState ?? EMPTY_SETTINGS.syncState;
|
|
33782
|
+
const tokenValid = Boolean(current.githubTokenConfigured);
|
|
33783
|
+
const hasCompanyContext = Boolean(hostContext.companyId);
|
|
33784
|
+
const showInitialKpiLoadingState = hasCompanyContext && dashboardMetrics.loading && !dashboardMetrics.data && !cachedDashboardMetrics;
|
|
33785
|
+
const boardAccessConfigured = Boolean(current.paperclipBoardAccessConfigured);
|
|
33786
|
+
const boardAccessRequired = boardAccessRequirement.required;
|
|
33787
|
+
const boardAccessReady = !boardAccessRequired || hasCompanyContext && boardAccessConfigured;
|
|
33788
|
+
const savedMappingCount = getComparableMappings(current.mappings ?? []).length;
|
|
33789
|
+
const syncSetupIssue = getSyncSetupIssue({
|
|
33790
|
+
tokenStatus: tokenValid ? "valid" : "required",
|
|
33791
|
+
savedMappingCount,
|
|
33792
|
+
boardAccessRequired,
|
|
33793
|
+
boardAccessConfigured,
|
|
33794
|
+
hasCompanyContext
|
|
33795
|
+
});
|
|
33796
|
+
const displaySyncState = getDisplaySyncState(syncState, {
|
|
33797
|
+
hasToken: tokenValid,
|
|
33798
|
+
hasMappings: savedMappingCount > 0,
|
|
33799
|
+
hasBoardAccess: boardAccessReady
|
|
33800
|
+
});
|
|
33801
|
+
const syncPersistedRunning = displaySyncState.status === "running";
|
|
33802
|
+
const scheduleDescription = formatScheduleFrequency(normalizeScheduleFrequencyMinutes(current.scheduleFrequencyMinutes));
|
|
33803
|
+
const kpiSummary = getKpiDashboardSummary({
|
|
33804
|
+
hasCompanyContext,
|
|
33805
|
+
metrics: currentDashboardMetrics,
|
|
33806
|
+
syncState: displaySyncState,
|
|
33807
|
+
syncIssue: syncSetupIssue
|
|
33808
|
+
});
|
|
33809
|
+
const kpiCards = buildDashboardKpiCards({
|
|
33810
|
+
metrics: currentDashboardMetrics,
|
|
33811
|
+
hasCompanyContext
|
|
33812
|
+
});
|
|
33813
|
+
const syncProgress = getRunningSyncProgressModel(displaySyncState);
|
|
33814
|
+
const lastSync = formatDate(displaySyncState.checkedAt, "Never");
|
|
33815
|
+
const widgetStatusSummary = showInitialLoadingState ? "Loading KPI status." : syncProgress ? [
|
|
33816
|
+
syncProgress.issueProgressLabel,
|
|
33817
|
+
syncProgress.currentIssueLabel ?? syncProgress.repositoryPosition
|
|
33818
|
+
].filter((value) => Boolean(value)).join(" \xB7 ") : syncSetupIssue === "missing_token" ? "Finish setup to refresh KPI history." : syncSetupIssue === "missing_board_access" ? "Connect board access to refresh KPI history." : !hasCompanyContext ? "Open in a company dashboard." : currentDashboardMetrics.status === "no_mappings" ? "Add a mapped repository." : !currentDashboardMetrics.notes.backlogHistoryAvailable && !currentDashboardMetrics.notes.activityHistoryAvailable ? "Run a full sync to seed KPI history." : [
|
|
33819
|
+
currentDashboardMetrics.backlog.lastCapturedAt ? `Backlog ${formatDate(currentDashboardMetrics.backlog.lastCapturedAt, currentDashboardMetrics.backlog.lastCapturedAt)}` : null,
|
|
33820
|
+
currentDashboardMetrics.githubIssuesClosed.lastRecordedAt ? `Activity ${formatDate(currentDashboardMetrics.githubIssuesClosed.lastRecordedAt, currentDashboardMetrics.githubIssuesClosed.lastRecordedAt)}` : null
|
|
33821
|
+
].filter((value) => Boolean(value)).join(" \xB7 ") || (displaySyncState.checkedAt ? `Last sync ${lastSync}` : `Auto-sync ${scheduleDescription}`);
|
|
33822
|
+
useEffect2(() => {
|
|
33823
|
+
if (settings.data) {
|
|
33824
|
+
setCachedSettings(settings.data);
|
|
33825
|
+
}
|
|
33826
|
+
}, [settings.data]);
|
|
33827
|
+
useEffect2(() => {
|
|
33828
|
+
if (dashboardMetrics.data) {
|
|
33829
|
+
setCachedDashboardMetrics(dashboardMetrics.data);
|
|
33830
|
+
}
|
|
33831
|
+
}, [dashboardMetrics.data]);
|
|
33832
|
+
useEffect2(() => {
|
|
33833
|
+
let cancelled = false;
|
|
33834
|
+
async function loadSettingsHref() {
|
|
33835
|
+
try {
|
|
33836
|
+
const plugins = await fetchJson("/api/plugins");
|
|
33837
|
+
if (!cancelled) {
|
|
33838
|
+
setSettingsHref(resolvePluginSettingsHref(plugins));
|
|
33839
|
+
}
|
|
33840
|
+
} catch {
|
|
33841
|
+
if (!cancelled) {
|
|
33842
|
+
setSettingsHref(SETTINGS_INDEX_HREF2);
|
|
33843
|
+
}
|
|
33844
|
+
}
|
|
33845
|
+
}
|
|
33846
|
+
void loadSettingsHref();
|
|
33847
|
+
return () => {
|
|
33848
|
+
cancelled = true;
|
|
33849
|
+
};
|
|
33850
|
+
}, []);
|
|
33851
|
+
useEffect2(() => {
|
|
33852
|
+
if (displaySyncState.status !== "running") {
|
|
33853
|
+
return;
|
|
33854
|
+
}
|
|
33855
|
+
const refreshWidgetData = () => {
|
|
33856
|
+
try {
|
|
33857
|
+
settings.refresh();
|
|
33858
|
+
} catch {
|
|
33859
|
+
}
|
|
33860
|
+
try {
|
|
33861
|
+
dashboardMetrics.refresh();
|
|
33862
|
+
} catch {
|
|
33863
|
+
return;
|
|
33864
|
+
}
|
|
33865
|
+
};
|
|
33866
|
+
const intervalId = globalThis.setInterval(() => {
|
|
33867
|
+
refreshWidgetData();
|
|
33868
|
+
}, SYNC_POLL_INTERVAL_MS);
|
|
33869
|
+
refreshWidgetData();
|
|
33870
|
+
return () => {
|
|
33871
|
+
globalThis.clearInterval(intervalId);
|
|
33872
|
+
};
|
|
33873
|
+
}, [dashboardMetrics.refresh, displaySyncState.status, settings.refresh]);
|
|
33874
|
+
useEffect2(() => {
|
|
33875
|
+
const refreshWidgetData = () => {
|
|
33876
|
+
try {
|
|
33877
|
+
settings.refresh();
|
|
33878
|
+
} catch {
|
|
33879
|
+
}
|
|
33880
|
+
try {
|
|
33881
|
+
dashboardMetrics.refresh();
|
|
33882
|
+
} catch {
|
|
33883
|
+
return;
|
|
33884
|
+
}
|
|
33885
|
+
};
|
|
33886
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
33887
|
+
return;
|
|
33888
|
+
}
|
|
33889
|
+
const handleSettingsUpdated = () => {
|
|
33890
|
+
refreshWidgetData();
|
|
33891
|
+
};
|
|
33892
|
+
const handleWindowFocus = () => {
|
|
33893
|
+
refreshWidgetData();
|
|
33894
|
+
};
|
|
33895
|
+
const handleVisibilityChange = () => {
|
|
33896
|
+
if (document.visibilityState === "visible") {
|
|
33897
|
+
refreshWidgetData();
|
|
33898
|
+
}
|
|
33899
|
+
};
|
|
33900
|
+
window.addEventListener(GITHUB_SYNC_SETTINGS_UPDATED_EVENT, handleSettingsUpdated);
|
|
33901
|
+
window.addEventListener("focus", handleWindowFocus);
|
|
33902
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
33903
|
+
return () => {
|
|
33904
|
+
window.removeEventListener(GITHUB_SYNC_SETTINGS_UPDATED_EVENT, handleSettingsUpdated);
|
|
33905
|
+
window.removeEventListener("focus", handleWindowFocus);
|
|
33906
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
33907
|
+
};
|
|
33908
|
+
}, [dashboardMetrics.refresh, settings.refresh]);
|
|
33909
|
+
return /* @__PURE__ */ jsxs2("section", { className: "ghsync-widget", style: themeVars, children: [
|
|
33910
|
+
/* @__PURE__ */ jsx2("style", { children: WIDGET_STYLES }),
|
|
33911
|
+
/* @__PURE__ */ jsxs2("div", { className: "ghsync-widget__card", children: [
|
|
33912
|
+
/* @__PURE__ */ jsxs2("div", { className: "ghsync-widget__top", children: [
|
|
33913
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
33914
|
+
/* @__PURE__ */ jsx2("div", { className: "ghsync-widget__eyebrow", children: "GitHub KPIs" }),
|
|
33915
|
+
/* @__PURE__ */ jsx2("h3", { children: kpiSummary.title }),
|
|
33916
|
+
/* @__PURE__ */ jsx2("p", { children: kpiSummary.body }),
|
|
33917
|
+
/* @__PURE__ */ jsxs2("div", { className: "ghsync-widget__meta", children: [
|
|
33918
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
33919
|
+
savedMappingCount,
|
|
33920
|
+
" ",
|
|
33921
|
+
savedMappingCount === 1 ? "repository" : "repositories"
|
|
33922
|
+
] }),
|
|
33923
|
+
/* @__PURE__ */ jsx2("span", { className: "ghsync-widget__meta-dot", "aria-hidden": "true" }),
|
|
33924
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
33925
|
+
"Auto-sync ",
|
|
33926
|
+
scheduleDescription
|
|
33927
|
+
] }),
|
|
33928
|
+
/* @__PURE__ */ jsx2("span", { className: "ghsync-widget__meta-dot", "aria-hidden": "true" }),
|
|
33929
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
33930
|
+
"Last sync ",
|
|
33931
|
+
lastSync
|
|
33932
|
+
] })
|
|
33933
|
+
] })
|
|
33934
|
+
] }),
|
|
33935
|
+
/* @__PURE__ */ jsxs2("span", { className: `ghsync__badge ${getToneClass(kpiSummary.tone)}`, children: [
|
|
33936
|
+
/* @__PURE__ */ jsx2("span", { className: "ghsync__badge-dot", "aria-hidden": "true" }),
|
|
33937
|
+
kpiSummary.label
|
|
33938
|
+
] })
|
|
33939
|
+
] }),
|
|
33940
|
+
settings.error ? /* @__PURE__ */ jsx2("div", { className: "ghsync-widget__message", children: settings.error.message }) : null,
|
|
33941
|
+
dashboardMetrics.error ? /* @__PURE__ */ jsx2("div", { className: "ghsync-widget__message", children: dashboardMetrics.error.message }) : null,
|
|
33942
|
+
/* @__PURE__ */ jsx2("div", { className: "ghsync-widget__stats", children: kpiCards.map((card) => /* @__PURE__ */ jsxs2(
|
|
33943
|
+
"div",
|
|
33944
|
+
{
|
|
33945
|
+
className: `ghsync-widget__stat ghsync-widget__stat--${card.tone}`,
|
|
33946
|
+
children: [
|
|
33947
|
+
/* @__PURE__ */ jsxs2("div", { className: "ghsync-widget__stat-top", children: [
|
|
33948
|
+
/* @__PURE__ */ jsxs2("div", { className: "ghsync-widget__stat-value", children: [
|
|
33949
|
+
/* @__PURE__ */ jsx2("span", { className: "ghsync-widget__stat-label", children: card.title }),
|
|
33950
|
+
/* @__PURE__ */ jsx2("strong", { children: showInitialKpiLoadingState ? /* @__PURE__ */ jsx2(LoadingSpinner, { size: "sm", label: `Loading ${card.title.toLowerCase()}` }) : card.valueLabel })
|
|
33951
|
+
] }),
|
|
33952
|
+
/* @__PURE__ */ jsx2(
|
|
33953
|
+
DashboardTrendGraphic,
|
|
33954
|
+
{
|
|
33955
|
+
values: card.history,
|
|
33956
|
+
tone: card.tone,
|
|
33957
|
+
kind: card.chartKind
|
|
33958
|
+
}
|
|
33959
|
+
)
|
|
33960
|
+
] }),
|
|
33961
|
+
/* @__PURE__ */ jsx2("p", { className: `ghsync-widget__stat-change ghsync-widget__stat-change--${card.tone}`, children: showInitialKpiLoadingState ? "Loading KPI history." : card.changeLabel }),
|
|
33962
|
+
/* @__PURE__ */ jsx2("p", { className: "ghsync-widget__stat-note", children: showInitialKpiLoadingState ? "Fetching the latest company KPI data." : card.note })
|
|
33963
|
+
]
|
|
33964
|
+
},
|
|
33965
|
+
card.key
|
|
33966
|
+
)) }),
|
|
33967
|
+
/* @__PURE__ */ jsxs2("div", { className: "ghsync-widget__summary", children: [
|
|
33968
|
+
/* @__PURE__ */ jsx2("strong", { children: showInitialLoadingState ? "Status" : syncPersistedRunning ? "Live sync" : "Latest snapshot" }),
|
|
33969
|
+
/* @__PURE__ */ jsx2("span", { children: widgetStatusSummary })
|
|
33970
|
+
] }),
|
|
33971
|
+
/* @__PURE__ */ jsx2("div", { className: "ghsync-widget__actions", children: /* @__PURE__ */ jsx2("div", { className: "ghsync-widget__button-row", children: /* @__PURE__ */ jsx2(
|
|
33972
|
+
"a",
|
|
33973
|
+
{
|
|
33974
|
+
href: settingsHref,
|
|
33975
|
+
className: getPluginActionClassName({
|
|
33976
|
+
variant: "secondary",
|
|
33977
|
+
extraClassName: "ghsync-widget__link"
|
|
33978
|
+
}),
|
|
33979
|
+
children: "Open settings"
|
|
33980
|
+
}
|
|
33981
|
+
) }) })
|
|
33982
|
+
] })
|
|
33983
|
+
] });
|
|
33984
|
+
}
|
|
33448
33985
|
function GitHubMarkIcon(props) {
|
|
33449
33986
|
return /* @__PURE__ */ jsx2(
|
|
33450
33987
|
"svg",
|
|
@@ -34217,6 +34754,7 @@ export {
|
|
|
34217
34754
|
GitHubSyncGlobalToolbarButton,
|
|
34218
34755
|
GitHubSyncIssueDetailTab,
|
|
34219
34756
|
GitHubSyncIssueTaskDetailView,
|
|
34757
|
+
GitHubSyncKpiDashboardWidget,
|
|
34220
34758
|
GitHubSyncProjectPullRequestsPage,
|
|
34221
34759
|
GitHubSyncProjectPullRequestsSidebarItem,
|
|
34222
34760
|
GitHubSyncSettingsPage,
|