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
// A job inside an expanded run. Header toggles its steps; each step
// toggles its log slice. Logs are fetched once per job on first open
// (the endpoint returns every step's lines at once) and failed steps
// open themselves — that's the one you came to read.
ColumnLayout {
id: jobItem
required property var store
required property string fullName
required property int runNumber
required property var job
property bool canManage: false
readonly property bool expanded: store.expandedJobs[job.id] === true
readonly property var logs: store.jobLogs[job.id] || null
readonly property string status: Status.jobStatus(job)
readonly property string reason: Status.jobReason(job)
spacing: 0
function logsForStep(stepNumber) {
if (!logs) return null
for (var i = 0; i < logs.steps.length; i++) {
if (logs.steps[i].step.number === stepNumber) return logs.steps[i]
}
return null
}
PlasmaComponents3.ItemDelegate {
Layout.fillWidth: true
onClicked: jobItem.store.toggleJob(jobItem.fullName, jobItem.job)
contentItem: RowLayout {
spacing: Kirigami.Units.smallSpacing
Kirigami.Icon {
source: jobItem.expanded ? "arrow-down" : "arrow-right"
Layout.preferredWidth: Kirigami.Units.iconSizes.small
Layout.preferredHeight: Kirigami.Units.iconSizes.small
}
StatusCircle {
status: jobItem.status
Layout.preferredWidth: Kirigami.Units.iconSizes.small
Layout.preferredHeight: Kirigami.Units.iconSizes.small
}
ColumnLayout {
Layout.fillWidth: true
spacing: 0
PlasmaComponents3.Label {
Layout.fillWidth: true
elide: Text.ElideRight
text: Status.jobLabel(jobItem.job)
}
PlasmaComponents3.Label {
Layout.fillWidth: true
elide: Text.ElideRight
font: Kirigami.Theme.smallFont
opacity: 0.7
text: (jobItem.store.now, [Status.label(jobItem.status),
jobItem.job.attempt > 1 ? "attempt " + jobItem.job.attempt : "",
Status.duration(jobItem.job.started_at, jobItem.job.completed_at),
(jobItem.job.needs && jobItem.job.needs.length > 0) ? "needs " + jobItem.job.needs.join(", ") : ""]
.filter(function(s) { return s !== "" }).join(" · "))
}
// Why it's waiting, skipped or cancelled — or, for a
// matrix placeholder, when it expands.
PlasmaComponents3.Label {
visible: jobItem.reason !== ""
Layout.fillWidth: true
wrapMode: Text.WordWrap
maximumLineCount: 3
elide: Text.ElideRight
font: Kirigami.Theme.smallFont
opacity: 0.7
text: jobItem.reason
}
}
PlasmaComponents3.ToolButton {
// A placeholder isn't a job yet: its legs replace it.
visible: jobItem.canManage && !!jobItem.job.job_id && !jobItem.job.placeholder
enabled: !jobItem.store.busy
icon.name: "view-refresh"
onClicked: jobItem.store.rerunJob(jobItem.fullName, jobItem.runNumber, jobItem.job.job_id)
PlasmaComponents3.ToolTip { text: i18n("Re-run this job") }
}
}
}
ColumnLayout {
visible: jobItem.expanded
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.gridUnit
spacing: 0
PlasmaComponents3.Label {
visible: jobItem.job.steps.length === 0
text: jobItem.job.placeholder ? i18n("Matrix not expanded yet — its jobs appear here once it does")
: i18n("No steps yet")
opacity: 0.7
font: Kirigami.Theme.smallFont
}
Repeater {
model: jobItem.expanded ? jobItem.job.steps : []
delegate: ColumnLayout {
id: stepItem
required property var modelData
readonly property string stepKey: jobItem.job.id + ":" + modelData.number
readonly property string stepStatus: Status.effective(modelData.status, modelData.conclusion)
readonly property bool open: jobItem.store.stepOpen(stepKey, stepStatus)
readonly property var stepLogs: jobItem.logsForStep(modelData.number)
Layout.fillWidth: true
spacing: 0
PlasmaComponents3.ItemDelegate {
Layout.fillWidth: true
onClicked: jobItem.store.toggleStep(stepItem.stepKey, stepItem.stepStatus)
contentItem: RowLayout {
spacing: Kirigami.Units.smallSpacing
Kirigami.Icon {
source: stepItem.open ? "arrow-down" : "arrow-right"
Layout.preferredWidth: Kirigami.Units.iconSizes.small
Layout.preferredHeight: Kirigami.Units.iconSizes.small
}
StatusCircle {
status: stepItem.stepStatus
Layout.preferredWidth: Kirigami.Units.iconSizes.small * 0.75
Layout.preferredHeight: Kirigami.Units.iconSizes.small * 0.75
}
PlasmaComponents3.Label {
Layout.fillWidth: true
elide: Text.ElideRight
font: Kirigami.Theme.smallFont
text: stepItem.modelData.name || i18n("step %1", stepItem.modelData.number)
}
PlasmaComponents3.Label {
font: Kirigami.Theme.smallFont
opacity: 0.7
text: (jobItem.store.now, Status.duration(stepItem.modelData.started_at, stepItem.modelData.completed_at))
}
}
}
PlasmaComponents3.BusyIndicator {
visible: stepItem.open && !jobItem.logs
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: Kirigami.Units.iconSizes.small
}
// Build output is written for a terminal: no wrapping,
// scroll sideways instead.
PlasmaComponents3.ScrollView {
id: logScroll
visible: stepItem.open && !!jobItem.logs
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.gridUnit
Layout.preferredHeight: Math.min(logText.implicitHeight + Kirigami.Units.smallSpacing * 2,
Kirigami.Units.gridUnit * 16)
QQC2.ScrollBar.vertical.policy: QQC2.ScrollBar.AsNeeded
background: Rectangle {
color: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g,
Kirigami.Theme.textColor.b, 0.07)
radius: Kirigami.Units.cornerRadius
}
PlasmaComponents3.TextArea {
id: logText
readOnly: true
color: Kirigami.Theme.textColor
selectByMouse: true
wrapMode: TextEdit.NoWrap
textFormat: TextEdit.PlainText
font.family: Kirigami.Theme.fixedWidthFont.family
font.pointSize: Kirigami.Theme.smallFont.pointSize
background: null
text: {
var sl = stepItem.stepLogs
if (!sl || sl.lines.length === 0) {
return jobItem.logs.truncated ? i18n("(past the line limit — open the run in the browser)")
: i18n("(no output)")
}
return sl.lines.map(function(l) { return l.body }).join("\n")
}
// Land on the tail: that's where failures are.
onTextChanged: Qt.callLater(function() {
var flick = logScroll.contentItem
flick.contentY = Math.max(0, flick.contentHeight - flick.height)
})
}
}
}
}
PlasmaComponents3.Label {
visible: !!jobItem.logs && jobItem.logs.truncated
font: Kirigami.Theme.smallFont
opacity: 0.7
text: i18n("Output truncated — open the run in the browser for the full log")
}
}
}
neiam
/gitgud-plasmoid
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
9.3 KiB · text
History
010513e