import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as QQC2
import org.kde.plasma.components as PlasmaComponents3
import org.kde.kirigami as Kirigami
import "Status.js" as Status
// One run as an accordion: the header toggles the job list, each job
// toggles its steps, and each step toggles its log slice — the same
// run → job → step drill-down the Android client uses. Expansion state
// and fetched details live on `store` (the root item) so they survive
// the list refreshing underneath.
ColumnLayout {
id: runItem
required property var store
required property string fullName
required property var run
property bool showRepo: true
readonly property string runKey: fullName + "#" + run.number
readonly property bool expanded: store.expandedRuns[runKey] === true
readonly property var detail: store.runDetails[runKey] || null
readonly property string status: Status.runStatus(run)
readonly property bool active: Status.isActive(run.status)
// The detail's copy is fresher than the list row's once it's loaded.
readonly property var current: detail ? detail.run : run
spacing: 0
// ── header ──────────────────────────────────────────────────────────
PlasmaComponents3.ItemDelegate {
Layout.fillWidth: true
onClicked: runItem.store.toggleRun(runItem.fullName, runItem.run.number)
contentItem: RowLayout {
spacing: Kirigami.Units.smallSpacing
Kirigami.Icon {
source: runItem.expanded ? "arrow-down" : "arrow-right"
Layout.preferredWidth: Kirigami.Units.iconSizes.small
Layout.preferredHeight: Kirigami.Units.iconSizes.small
}
StatusCircle {
status: runItem.status
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
}
ColumnLayout {
Layout.fillWidth: true
spacing: 0
PlasmaComponents3.Label {
Layout.fillWidth: true
elide: Text.ElideRight
textFormat: Text.StyledText
text: (runItem.showRepo ? "<b>" + runItem.fullName + "</b> · " : "")
+ Status.runTitle(runItem.run) + " #" + runItem.run.number
}
PlasmaComponents3.Label {
Layout.fillWidth: true
elide: Text.ElideRight
font: Kirigami.Theme.smallFont
opacity: 0.7
text: Status.runMeta(runItem.run)
}
}
ColumnLayout {
spacing: 0
PlasmaComponents3.Label {
Layout.alignment: Qt.AlignRight
font: Kirigami.Theme.smallFont
color: Status.color(runItem.status, Kirigami.Theme)
text: Status.label(runItem.status)
}
PlasmaComponents3.Label {
Layout.alignment: Qt.AlignRight
font: Kirigami.Theme.smallFont
opacity: 0.7
// `store.now` ticks so relative times stay fresh.
text: (runItem.store.now, [Status.relativeTime(runItem.run.inserted_at),
Status.duration(runItem.run.started_at, runItem.run.completed_at)]
.filter(function(s) { return s !== "" }).join(" · "))
}
}
}
}
// ── body ────────────────────────────────────────────────────────────
ColumnLayout {
visible: runItem.expanded
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.gridUnit
Layout.bottomMargin: Kirigami.Units.smallSpacing
spacing: Kirigami.Units.smallSpacing
PlasmaComponents3.BusyIndicator {
visible: runItem.expanded && !runItem.detail
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: Kirigami.Units.iconSizes.medium
}
// A fork's run waits for someone with write access to approve
// it, and that happens on the pull request — say so, link there.
ColumnLayout {
visible: !!runItem.current.awaiting_approval
Layout.fillWidth: true
spacing: 0
PlasmaComponents3.Label {
Layout.fillWidth: true
color: Kirigami.Theme.neutralTextColor
text: i18n("Waiting for approval")
}
PlasmaComponents3.Label {
Layout.fillWidth: true
wrapMode: Text.WordWrap
font: Kirigami.Theme.smallFont
opacity: 0.7
text: Status.approvalNotice(runItem.current)
}
PlasmaComponents3.ToolButton {
visible: !!runItem.current.pull_request_number
icon.name: "internet-web-browser"
text: i18n("Open pull request #%1", runItem.current.pull_request_number)
display: QQC2.AbstractButton.TextBesideIcon
onClicked: Qt.openUrlExternally(runItem.store.api.pullUrl(runItem.fullName, runItem.current.pull_request_number))
}
}
RowLayout {
visible: !!runItem.detail
Layout.fillWidth: true
spacing: Kirigami.Units.smallSpacing
PlasmaComponents3.ToolButton {
visible: !!runItem.detail && runItem.detail.can_manage
enabled: !runItem.store.busy
icon.name: "view-refresh"
text: i18n("Re-run all")
display: QQC2.AbstractButton.TextBesideIcon
onClicked: runItem.store.rerunRun(runItem.fullName, runItem.run.number)
}
PlasmaComponents3.ToolButton {
visible: !!runItem.detail && runItem.detail.can_manage && runItem.active
enabled: !runItem.store.busy
icon.name: "dialog-cancel"
text: i18n("Cancel")
display: QQC2.AbstractButton.TextBesideIcon
onClicked: runItem.store.cancelRun(runItem.fullName, runItem.run.number)
}
Item { Layout.fillWidth: true }
PlasmaComponents3.ToolButton {
icon.name: "internet-web-browser"
text: i18n("Open")
display: QQC2.AbstractButton.TextBesideIcon
onClicked: Qt.openUrlExternally(runItem.store.api.webUrl(runItem.fullName, runItem.run.number))
}
}
Repeater {
model: runItem.detail ? runItem.detail.jobs : []
delegate: JobItem {
required property var modelData
Layout.fillWidth: true
store: runItem.store
fullName: runItem.fullName
runNumber: runItem.run.number
job: modelData
canManage: !!runItem.detail && runItem.detail.can_manage
}
}
PlasmaComponents3.Label {
visible: !!runItem.detail && runItem.detail.jobs.length === 0
text: i18n("No jobs")
opacity: 0.7
}
Repeater {
model: runItem.detail ? runItem.detail.artifacts : []
delegate: PlasmaComponents3.Label {
required property var modelData
Layout.fillWidth: true
elide: Text.ElideRight
font: Kirigami.Theme.smallFont
opacity: 0.7
text: "📦 " + (modelData.name || "artifact")
+ (modelData.size ? " · " + Math.round(modelData.size / 1024) + " KiB" : "")
}
}
}
Kirigami.Separator {
Layout.fillWidth: true
opacity: 0.5
}
}
neiam
/gitgud-plasmoid
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
8.0 KiB · text
History
010513e