mirror of https://github.com/jenkinsci/jenkins.git
Rewrite the build history widget (#9148)
* Squashed commit of the following: commit 1ce4cb39c7df313ad000225f1f06c21d9d55d7d8 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Tue Apr 9 09:22:36 2024 +0100 Rename classes commit 107d7947874a974fc16df00dcdef46a4d55ed0bc Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Tue Apr 9 08:59:54 2024 +0100 Update HistoryWidget.java commit 13575bc27caaf902c6685e8dfdb8ecd2ffc6e64a Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Tue Apr 9 08:59:29 2024 +0100 Hide buttons commit e5de5465814c810f9bb09722a00727f73b1158b9 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Tue Apr 9 08:39:04 2024 +0100 Rename classes commit 47c84afcd1c4e45f1e202a1a38fc68ef9ec8c702 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Apr 8 23:21:36 2024 +0100 Add animation commit e7432b693357b800b91bf355a610fbd3ab62223e Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Apr 8 23:03:19 2024 +0100 Add navigation buttons commit 448a09419a0706bd83fb73b555ef55c54916da13 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Apr 8 22:29:32 2024 +0100 Update _dashboard.scss commit bb85734be0884e7cb244b13267970722db2f8c05 Merge: c451a7223c27433f19f3
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Apr 8 22:23:38 2024 +0100 Merge branch 'master' into new-build-history-2 commit c451a7223cfc68651d11c8f83134c0ee000db363 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Apr 8 13:17:05 2024 +0100 Update _job.scss commit 960b162dcd95715f6d1567f57d53fcf79591966d Merge: d020eb66e5af655e3fdc
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Apr 8 13:16:54 2024 +0100 Merge branch 'remove-table-usage' into new-build-history-2 commitaf655e3fdc
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Apr 8 13:13:38 2024 +0100 Init commit d020eb66e54a63c880dc3c335485aff92c86aaad Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Apr 8 13:09:57 2024 +0100 Update card.jelly commit 81bc1d45f17adb021d67c15531d51b8421f78132 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Apr 8 13:07:41 2024 +0100 Update _buttons.scss commit 4023460b9aa9243f45870e98ca2299a91263bcce Merge: 875fb8fb4bda5f593fb0
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Apr 8 13:03:18 2024 +0100 Merge branch 'master' into new-build-history-2 commit 875fb8fb4baa86c45284d71ee6f5a2a39af68aa0 Merge: 2dc9964871fe60facf91
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Apr 6 19:29:20 2024 +0100 Merge branch 'master' into new-build-history-2 commit 2dc9964871734a6e8386392d32a13366bc3752e9 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Fri Apr 5 22:17:08 2024 +0100 Reset files commit 2da1e14f046e518bc9c22050ddf9f394d65bbc31 Merge: dce466a846b9fac75ac8
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Fri Apr 5 22:14:46 2024 +0100 Merge branch 'master' into new-build-history-2 commit dce466a846b5e7bcad40625c8c5bcbd6c6477cf8 Merge: 935c16e1c10eed048866
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Wed Feb 28 13:55:35 2024 +0000 Merge branch 'master' into new-build-history-2 commit 935c16e1c1033c8e33fff49b0e47f9a47615f540 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Feb 18 17:54:32 2024 +0000 Update entry.jelly commit 2a19a045970d65e446e4ce894d769fb27bdfd921 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Feb 18 17:51:58 2024 +0000 Rename classes commit 3ef46abe52ba75573bb4e634ad3baad95c2b07ba Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Feb 18 17:29:25 2024 +0000 Update index.jelly commit da0b2126cdc5f959905ae7eba514a68f891f6620 Merge: 281fac04c09d9e2ab467
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Feb 18 17:27:12 2024 +0000 Merge branch 'revamp-dropdowns' into new-build-history-2 commit 281fac04c00e25ab05ff21c71ab30b263d0e3b9b Merge: 9c69bd02bea6423541f0
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Feb 18 17:19:14 2024 +0000 Merge branch 'master' into new-build-history-2 commit9d9e2ab467
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Feb 10 19:39:24 2024 +0000 Update templates.js commit1c19e431ce
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Feb 10 19:38:13 2024 +0000 Add clazz commit8b944e9e3f
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Feb 10 15:19:30 2024 +0000 Update utils.js commit069fefbe36
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Feb 10 13:23:16 2024 +0000 Linting commit7270712249
Merge:9865811d38
a6423541f0
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Feb 10 12:20:02 2024 +0000 Merge branch 'master' into revamp-dropdowns commit9865811d38
Merge:1e22c34016
86d39dd23b
Author: Mark Waite <mark.earl.waite@gmail.com> Date: Thu Jan 18 05:39:13 2024 -0700 Merge branch 'master' into revamp-dropdowns commit 9c69bd02bebcc13b695f112952a0ec97b297a8bb Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Jan 14 13:56:49 2024 +0000 Push commit 347e966aebbe013f171329c4fb00dee4acd27b33 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Jan 14 13:53:52 2024 +0000 Update filter-build-history.js commit 0b4a5dd5f4834824d70324b0698f9194a2ffb64b Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Jan 14 13:49:54 2024 +0000 Renam commit a8277bf932fc3ff5c99ec9f3496c05ed977e7990 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Jan 14 13:46:53 2024 +0000 Fix commit 855bf1317e8d7187cf4b2016f8571379c841ba91 Merge: 61b0a87e6c1eb29a8792
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Jan 14 13:38:51 2024 +0000 Merge branch 'master' into new-build-history-2 commit1e22c34016
Merge:44981c2a66
48661db9d1
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Jan 14 13:33:14 2024 +0000 Merge branch 'master' into revamp-dropdowns commit44981c2a66
Merge:0075375c9a
1eb29a8792
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Jan 8 21:14:51 2024 +0000 Merge branch 'master' into revamp-dropdowns commit0075375c9a
Merge:2dd9e32fab
78cdaa9f29
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Jan 4 13:26:24 2024 +0000 Merge branch 'master' into revamp-dropdowns commit2dd9e32fab
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Jan 4 13:24:53 2024 +0000 Remove translations commit6800c8886a
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Jan 4 13:16:19 2024 +0000 Update header.jelly commit1c3961bb64
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Jan 4 13:15:49 2024 +0000 Add additional docs commit163be529e7
Merge:4cc43e47f9
444f2de993
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Wed Jan 3 21:22:20 2024 +0000 Merge branch 'master' into revamp-dropdowns commit 61b0a87e6c3412496e65269e20055d6123d9adb8 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Dec 14 19:38:45 2023 +0000 More commit dcd6aaa54576bd1524d071b4cbe75d51aa4244f8 Merge: 0c40b9f3fcedce488000
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Dec 14 19:38:25 2023 +0000 Merge branch 'stop-button' into new-build-history-2 commitedce488000
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Dec 14 16:06:00 2023 +0000 Tidy up commit157ba0b5bc
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Dec 14 16:04:46 2023 +0000 Fix i18n commita112bd90c1
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Wed Dec 13 22:57:17 2023 +0000 Update _buttons.scss commit91751cf650
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Wed Dec 13 22:39:18 2023 +0000 Update executors.jelly commitcd89aeabf4
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Wed Dec 13 22:31:06 2023 +0000 Fixes commit1384091663
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Wed Dec 13 22:28:54 2023 +0000 Init commit 0c40b9f3fcb4f12fba2f0e0d45bffd94bb1e196b Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Wed Dec 13 16:50:53 2023 +0000 Update _buttons.scss commit 50fe8fc74312296ba6ae1b4a43f6a67680846970 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Wed Dec 13 13:13:10 2023 +0000 add view transitions commit d1fd7a9a93b241e93b18ed97af696bd32997d8b7 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Tue Dec 12 20:25:44 2023 +0000 Tidy up commit 512b9a1baaa8482aa597785a92e6183316f60030 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Tue Dec 12 19:29:16 2023 +0000 Push commit 4f1569079c353c0eddd5f665867d4239a35d8797 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Dec 11 23:30:09 2023 +0000 push commit ad75b0f10f5afae5b61e2ac97d44b51ede5801a4 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Dec 11 23:24:11 2023 +0000 Update _buttons.scss commit cec222e3bdd9104095abfaa82f07e953fa69d097 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Dec 11 23:23:52 2023 +0000 Update _buttons.scss commit4cc43e47f9
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Dec 10 16:04:28 2023 +0000 Add docs commita4c7f4f28c
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Dec 10 16:00:23 2023 +0000 Update taglib commitc01db44de3
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Dec 10 15:56:50 2023 +0000 Init commit 21bb3f4262cf65d30c48b76dc43b16a424d357ca Merge: d3e2920434428d0e560a
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Dec 10 13:22:00 2023 +0000 Merge branch 'restyle-cards' into new-build-history-2 commit428d0e560a
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Dec 7 20:17:10 2023 +0000 Lower weight commitac5c255530
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Dec 7 20:15:28 2023 +0000 Remove more bold weights commit2922a690bb
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Dec 7 20:11:33 2023 +0000 Update _style.scss commit9657d460ac
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Dec 7 20:06:16 2023 +0000 Init commit d3e2920434d44a45e968392c7617ad1ba140a062 Merge: a2bd9a08b2cabc8f67b9
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Thu Dec 7 19:50:43 2023 +0000 Merge branch 'master' into new-build-history-2 commit a2bd9a08b2679cc706f89cd12908197bf0244b13 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sun Nov 26 11:58:22 2023 +0000 Fixes commit 7cda5049b75bc7e7d7dcc8516ac6b3983d17b3b0 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Nov 25 12:28:04 2023 +0000 Working build commit abd994ebe9680f846e13029faa44a2119c861345 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Nov 25 11:58:42 2023 +0000 Working build commit 9b6defbf444b35127a81bb4cfd298f7648704e49 Merge: 29fcb64a74 7a0e57e35c Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Nov 25 11:51:24 2023 +0000 Merge branch 'progress-bar-new' into new-build-history-2 commit 29fcb64a74e37b445cde8b1847a6be988ad3b85c Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Nov 25 11:51:10 2023 +0000 More commit 2f946d3f6494223351fc9da3a98654b9a666f766 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Nov 25 09:17:06 2023 +0000 Update _buttons.scss commit f5474b33429ff8615c74e7be0cf622904c177a65 Merge: 00c3879a27982bc48fa0
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Nov 25 09:16:14 2023 +0000 Merge branch 'use-symbols-for-build-status-new' into new-build-history-2 commit982bc48fa0
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Nov 25 09:15:56 2023 +0000 Fix app bar build status icon being incorrect commit 00c3879a2740e40d81d65463028c82f32782fecf Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Nov 25 09:12:10 2023 +0000 Fixes commit a4960e9f2c9b9c17ec6f85fd24ef98ca7362455e Merge: d28aada2e1c6f5db0be7
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Nov 25 08:56:01 2023 +0000 Merge branch 'use-symbols-for-build-status-new' into new-build-history-2 commit d28aada2e1d5434a542d95afadc4c582a691319a Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Nov 25 08:55:18 2023 +0000 Update _buttons.scss commit 1d24a19982838f50a6aa6b4510c0fe1090eef364 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Sat Nov 25 08:52:58 2023 +0000 Init commit 7a0e57e35c71073258a5635ebba1a87d5456aeda Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Fri Nov 24 21:19:23 2023 +0000 More commit 67d4264da9a9ff8539ea74f7462b111d7da46f82 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Fri Nov 24 21:17:09 2023 +0000 Update _spinner.scss commit 9befc76209eede89b3e3fd9d124c6ac92ee75c81 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Fri Nov 24 21:07:55 2023 +0000 Update _spinner.scss commit 528b46acb3be57f43cf18f09a46cd7caa4ba2120 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Fri Nov 24 21:01:06 2023 +0000 More commit ea0c4878137141193ece81a1970007f34e603478 Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Fri Nov 24 20:36:53 2023 +0000 Init commitc6f5db0be7
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Fri Nov 24 17:52:28 2023 +0000 Fix icon position commit18a84076b5
Merge:aea4d9786e
a9c34d7393
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Fri Nov 24 09:58:54 2023 +0000 Merge branch 'master' into use-symbols-for-build-status-new commitaea4d9786e
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Fri Nov 24 09:58:29 2023 +0000 Rename ID commit5f76f3840c
Author: Jan Faracik <43062514+janfaracik@users.noreply.github.com> Date: Mon Nov 20 16:00:14 2023 +0000 Init * Update _job.scss * Lint * Update filter-build-history.js * Hide controls if not navigable * Update RunTest.java * Add basic JSDoc * Use dataset rather than attributes * Update filter-build-history.js * Rename JS * Update RunTest.java * Update jenkins-test-harness version (thanks again Tim!) * Update _job.scss * Remove unused SCSS * Update AbstractScmTagActionTest.java * Update builds-card.js * Update builds-card.js * Rewrite SCSS/Jelly to handle more complex scenarios * Lint * Tidy up * Update _side-panel-widgets.scss * Add background to card * Fix lint * Update queue-items.jelly * Fix cancel button * Update queue-items.jelly * Use debounce properly and adjust time to make it smoother * Use jenkins-hidden * Replace TODOs with comments, fix card controls showing when there are no builds * Add hidden text for previous/next buttons * Update builds-card.js * Add data-tooltip-append-to-parent="true" to tooltips * Wrap badges * Fix relative expandable link * Use chevron-down rather than menu icon --------- Co-authored-by: Daniel Beck <1831569+daniel-beck@users.noreply.github.com> Co-authored-by: Tim Jacomb <21194782+timja@users.noreply.github.com> Co-authored-by: Tim Jacomb <timjacomb1@gmail.com>
This commit is contained in:
parent
9459e1e061
commit
0419465f4d
|
@ -26,10 +26,19 @@ THE SOFTWARE.
|
|||
Render build histories.
|
||||
-->
|
||||
<?jelly escape-by-default='true'?>
|
||||
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
|
||||
<j:set target="${it}" property="nextBuildNumberToFetch" value="${it.nextBuildNumber}"/>
|
||||
<!-- build history -->
|
||||
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:i="jelly:fmt">
|
||||
<j:set target="${it}" property="nextBuildNumberToFetch" value="${it.nextBuildNumber}" />
|
||||
<j:invokeStatic className="java.time.LocalDate" method="now" var="now" />
|
||||
|
||||
<j:forEach var="pageEntry" items="${it.runs}">
|
||||
<i:formatDate value="${pageEntry.entry.timestamp.time}" var="date" type="date" dateStyle="long" />
|
||||
<i:formatDate value="${pageEntry.entry.timestamp.time}" var="simpleDate" type="date" pattern="YYYY-MM-dd" />
|
||||
|
||||
<j:if test="${pastDate != date}">
|
||||
<span class="app-builds-container__heading">${simpleDate == now ? "%Today" : date}</span>
|
||||
<j:set var="pastDate" value="${date}" />
|
||||
</j:if>
|
||||
|
||||
<st:include page="/hudson/widgets/HistoryWidget/entry.jelly" />
|
||||
</j:forEach>
|
||||
</j:jelly>
|
||||
</j:jelly>
|
||||
|
|
|
@ -34,54 +34,58 @@ THE SOFTWARE.
|
|||
<j:if test="${h.isUserTimeZoneOverride()}">
|
||||
<i:setTimeZone value="${h.getUserTimeZone()}" />
|
||||
</j:if>
|
||||
<tr class="build-row ${transitive} single-line" page-entry-id="${pageEntry.entryId}">
|
||||
<td class="build-row-cell">
|
||||
<div class="pane build-name">
|
||||
<div class="build-icon">
|
||||
<a class="build-status-link" href="${h.getConsoleUrl(build)}" tooltip="${build.iconColor.description} > ${%Console Output}">
|
||||
<l:icon src="symbol-status-${build.iconColor.iconName}" />
|
||||
</a>
|
||||
</div>
|
||||
<a class="model-link inside build-link display-name" update-parent-class=".build-row" href="${link}">${build.displayName}</a>
|
||||
</div>
|
||||
<div class="pane build-details" time="${build.timestamp.time.time}">
|
||||
<j:set var="linkTitleAttr" value=""/>
|
||||
<j:if test="${!build.building}">
|
||||
<j:set var="linkTitleAttr">${%Took} ${build.durationString}</j:set>
|
||||
</j:if>
|
||||
<a class="model-link inside build-link" href="${link}" update-parent-class=".build-row" tooltip="${linkTitleAttr}">
|
||||
<i:formatDate value="${build.timestamp.time}" type="both" dateStyle="medium" timeStyle="short" /> ${h.getUserTimeZonePostfix(build.timestamp.time)}
|
||||
</a>
|
||||
<j:if test="${build.building}">
|
||||
<j:set target="${it.widget}" property="nextBuildNumberToFetch" value="${build.number}"/>
|
||||
<t:buildProgressBar build="${build}"/>
|
||||
</j:if>
|
||||
</div>
|
||||
<div class="pane build-controls">
|
||||
<div class="middle-align build-badge">
|
||||
<j:set var="badges" value="${build.badgeActions}"/>
|
||||
<j:if test="${!empty(badges)}">
|
||||
<st:nbsp/>
|
||||
<j:forEach var="badge" items="${badges}">
|
||||
<st:include it="${badge}" page="badge.jelly" />
|
||||
</j:forEach>
|
||||
|
||||
<div class="app-builds-container__item" page-entry-id="${pageEntry.entryId}">
|
||||
<a class="app-builds-container__item__icon"
|
||||
href="${h.getConsoleUrl(build)}"
|
||||
tooltip="${build.iconColor.description}"
|
||||
data-tooltip-append-to-parent="true">
|
||||
<l:icon src="symbol-status-${build.iconColor.iconName}" />
|
||||
</a>
|
||||
|
||||
<div class="app-builds-container__item__inner">
|
||||
<a href="${link}" class="app-builds-container__item__inner__link">
|
||||
${build.displayName}
|
||||
<span class="app-builds-container__item__time" time="${build.timestamp.time.time}">
|
||||
<j:set var="linkTitleAttr" value="${null}" />
|
||||
<j:if test="${!build.building}">
|
||||
<j:set var="linkTitleAttr">${%Took} ${build.durationString}</j:set>
|
||||
</j:if>
|
||||
</div>
|
||||
<j:if test="${build.building}">
|
||||
<div class="build-stop">
|
||||
<!-- Check CANCEL permission for Project, Admin permission otherwise -->
|
||||
<j:if test="${empty(it.widget.owner.CANCEL) ? h.hasPermission(app.ADMINISTER) : it.widget.owner.hasPermission(it.widget.owner.CANCEL)}">
|
||||
<l:stopButton href="${link}stop" alt="${%Cancel}" confirm="${%confirm(build.fullDisplayName)}" />
|
||||
</j:if>
|
||||
<div tooltip="${linkTitleAttr}" data-tooltip-append-to-parent="true">
|
||||
<i:formatDate value="${build.timestamp.time}" type="time" timeStyle="short" />
|
||||
${h.getUserTimeZonePostfix()}
|
||||
</div>
|
||||
</span>
|
||||
</a>
|
||||
<div class="app-builds-container__item__inner__controls">
|
||||
<j:if test="${build.building}">
|
||||
<j:if test="${build.building}">
|
||||
<j:set target="${it.widget}" property="nextBuildNumberToFetch" value="${build.number}"/>
|
||||
<t:buildProgressBar build="${build}"/>
|
||||
</j:if>
|
||||
|
||||
<!-- Check CANCEL permission for Project, Admin permission otherwise -->
|
||||
<j:if test="${empty(it.widget.owner.CANCEL) ? h.hasPermission(app.ADMINISTER) : it.widget.owner.hasPermission(it.widget.owner.CANCEL)}">
|
||||
<l:stopButton href="${link}stop" alt="${%Cancel}" confirm="${%confirm(build.fullDisplayName)}" />
|
||||
</j:if>
|
||||
</j:if>
|
||||
|
||||
<j:set var="badges" value="${build.badgeActions}"/>
|
||||
<j:if test="${!empty(badges)}">
|
||||
<j:forEach var="badge" items="${badges}">
|
||||
<st:include it="${badge}" page="badge.jelly" />
|
||||
</j:forEach>
|
||||
</j:if>
|
||||
</div>
|
||||
<j:if test="${!empty build.truncatedDescription}">
|
||||
<div class="pane desc indent-multiline">
|
||||
<j:out value="${app.markupFormatter.translate(build.truncatedDescription)}"/>
|
||||
</div>
|
||||
</j:if>
|
||||
<div class="left-bar" />
|
||||
</td>
|
||||
</tr>
|
||||
</div>
|
||||
|
||||
<button class="jenkins-card__reveal jenkins-jumplist-link" data-href="${link}">
|
||||
<l:icon src="symbol-chevron-down" />
|
||||
</button>
|
||||
<j:if test="${!empty build.truncatedDescription}">
|
||||
<div class="app-builds-container__item__description">
|
||||
<j:out value="${app.markupFormatter.translate(build.truncatedDescription)}"/>
|
||||
</div>
|
||||
</j:if>
|
||||
</div>
|
||||
</j:jelly>
|
||||
|
|
|
@ -23,76 +23,54 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
-->
|
||||
<?jelly escape-by-default='true'?>
|
||||
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
|
||||
<j:parse var="paneTitle">
|
||||
<j:invokeStatic var="currentThread" className="java.lang.Thread" method="currentThread"/>
|
||||
<j:invoke var="jobClass" on="${currentThread.contextClassLoader}" method="loadClass">
|
||||
<j:arg value="hudson.model.Job"/>
|
||||
</j:invoke>
|
||||
|
||||
<div class="jenkins-pane__header--build-history">
|
||||
<j:if test="${jobClass.isAssignableFrom(it.owner.class)}">
|
||||
<t:buildHealth job="${it.owner}" iconSizeClass="icon-sm" link="${it.baseUrl}/lastBuild"/>
|
||||
</j:if>
|
||||
${it.displayName}
|
||||
<j:if test="${jobClass.isAssignableFrom(it.owner.class)}">
|
||||
<a href="${it.baseUrl}/buildTimeTrend">${%trend}</a>
|
||||
</j:if>
|
||||
</div>
|
||||
</j:parse>
|
||||
|
||||
<j:parse var="paneFooter">
|
||||
<!--
|
||||
RSS link
|
||||
-->
|
||||
<span class="build-rss-links">
|
||||
<a class="build-rss-all-link" href="${it.baseUrl}/rssAll">
|
||||
<span class="build-rss-all-icon">
|
||||
<l:icon src="symbol-rss" />
|
||||
</span>
|
||||
Atom feed ${%for all}
|
||||
</a>
|
||||
<a class="build-rss-failed-link" href="${it.baseUrl}/rssFailed">
|
||||
<span class="build-rss-failed-icon">
|
||||
<l:icon src="symbol-rss" />
|
||||
</span>
|
||||
Atom feed ${%for failures}
|
||||
</a>
|
||||
</span>
|
||||
</j:parse>
|
||||
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:dd="/lib/layout/dropdowns">
|
||||
<script src="${resURL}/jsbundles/pages/project/builds-card.js" type="text/javascript" defer="true" />
|
||||
|
||||
<j:set var="page" value="${it.historyPageFilter}" />
|
||||
<div id="buildHistoryPage" page-ajax="${it.baseUrl}/buildHistory/ajax" page-entry-newest="${page.newestOnPage}" page-entry-oldest="${page.oldestOnPage}" page-has-up="${page.hasUpPage}" page-has-down="${page.hasDownPage}">
|
||||
<div id="buildHistoryPageNav">
|
||||
<div class="buildHistoryPageNav__item buildHistoryPageNav__item--page-one pageOne" title="Page 1 (Newest/Latest Builds)">
|
||||
<div class="buildHistoryPageNav__item-page-one-top"></div>
|
||||
<l:svgIcon href="${resURL}/images/svgs/go-up.svg#arrow" viewBox="0 0 16 16" />
|
||||
|
||||
<j:set var="controls">
|
||||
<l:overflowButton icon="symbol-menu" clazz="jenkins-card__reveal">
|
||||
<dd:item icon="symbol-rss"
|
||||
text="Atom feed ${%for all}"
|
||||
href="${it.baseUrl}/rssAll" />
|
||||
<dd:item icon="symbol-rss"
|
||||
text="Atom feed ${%for failures}"
|
||||
href="${it.baseUrl}/rssFailed" />
|
||||
</l:overflowButton>
|
||||
</j:set>
|
||||
|
||||
<div id="buildHistoryPage" page-ajax="${it.baseUrl}/buildHistory/ajax"
|
||||
data-page-entry-newest="${page.newestOnPage}"
|
||||
data-page-entry-oldest="${page.oldestOnPage}"
|
||||
data-page-has-up="${page.hasUpPage}"
|
||||
data-page-has-down="${page.hasDownPage}">
|
||||
<l:card id="jenkins-builds" title="Builds" controls="${controls}" expandable="${it.baseUrl}/buildTimeTrend">
|
||||
<l:search-bar placeholder="${%find}"
|
||||
clazz="${page.runs.isEmpty() and page.queueItems.isEmpty() ? 'jenkins-hidden' : ''}"/>
|
||||
|
||||
<div class="app-builds-container">
|
||||
<div id="no-builds" class="app-builds-container__placeholder">
|
||||
${%No builds}
|
||||
</div>
|
||||
|
||||
<div id="jenkins-build-history" class="app-builds-container__items">
|
||||
</div>
|
||||
|
||||
<div class="app-builds-container__controls" id="controls">
|
||||
<button class="jenkins-button jenkins-button--tertiary jenkins-card__unveil" id="up">
|
||||
<l:icon src="symbol-arrow-left" />
|
||||
<span class="jenkins-visually-hidden">${%Newer builds}</span>
|
||||
</button>
|
||||
<button class="jenkins-button jenkins-button--tertiary jenkins-card__unveil" id="down">
|
||||
<l:icon src="symbol-arrow-right" />
|
||||
<span class="jenkins-visually-hidden">${%Older builds}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buildHistoryPageNav__item pageUp" title="Newer Builds">
|
||||
<l:svgIcon href="${resURL}/images/svgs/go-up.svg#arrow" viewBox="0 0 16 16" />
|
||||
</div>
|
||||
<div class="buildHistoryPageNav__item pageDown" title="Older Builds">
|
||||
<l:svgIcon href="${resURL}/images/svgs/go-down.svg#arrow" viewBox="0 0 16 16" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<l:pane width="3" title="${h.runScript(paneTitle)}" footer="${h.runScript(paneFooter)}" id="buildHistory" class="jenkins-pane stripped">
|
||||
<tr class="build-search-row">
|
||||
<td>
|
||||
<l:search-bar placeholder="${%find}" clazz="${page.runs.isEmpty() and page.queueItems.isEmpty() ? 'jenkins-hidden' : ''}"/>
|
||||
<div id="no-builds" class="jenkins-pane__information" style="${page.runs.isEmpty() and page.queueItems.isEmpty() ? '' : 'display: none;'}">
|
||||
${%No builds}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<st:include page="entries.jelly" it="${page}" />
|
||||
|
||||
</l:pane>
|
||||
|
||||
<!--The value for `page-next-build` is modified inside of `entries.jelly` on render, so set the attribute-->
|
||||
<!--after that component has been rendered to get the correct value to use in `filter-build-history.js`-->
|
||||
<div id="properties" page-next-build="${it.nextBuildNumberToFetch ?: it.owner.nextBuildNumber}"/>
|
||||
<!--The value for `page-next-build` is modified inside of `entries.jelly` on render, so set the attribute-->
|
||||
<!--after that component has been rendered to get the correct value to use in `builds-card.js`-->
|
||||
<div id="properties" page-next-build="${it.nextBuildNumberToFetch ?: it.owner.nextBuildNumber}"/>
|
||||
</l:card>
|
||||
</div>
|
||||
<script src="${resURL}/jsbundles/filter-build-history.js" type="text/javascript"/>
|
||||
</j:jelly>
|
||||
|
|
|
@ -1 +1 @@
|
|||
find=Filter...
|
||||
find=Filter
|
||||
|
|
|
@ -22,20 +22,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<!--
|
||||
-->
|
||||
<?jelly escape-by-default='true'?>
|
||||
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:l="/lib/layout">
|
||||
<l:ajax>
|
||||
<j:choose>
|
||||
<j:when test="${it.size() > 0}">
|
||||
<table class="pane hasPageData" page-entry-newest="${it.newestOnPage}" page-entry-oldest="${it.oldestOnPage}" page-has-up="${it.hasUpPage}" page-has-down="${it.hasDownPage}">
|
||||
<st:include page="entries.jelly" />
|
||||
</table>
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
<table class="pane"></table>
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
<j:if test="${it.size() > 0}">
|
||||
<div data-page-entry-newest="${it.newestOnPage}"
|
||||
data-page-entry-oldest="${it.oldestOnPage}"
|
||||
data-page-has-up="${it.hasUpPage}"
|
||||
data-page-has-down="${it.hasDownPage}">
|
||||
<st:include page="entries.jelly" />
|
||||
</div>
|
||||
</j:if>
|
||||
</l:ajax>
|
||||
</j:jelly>
|
||||
</j:jelly>
|
||||
|
|
|
@ -28,50 +28,43 @@ THE SOFTWARE.
|
|||
-->
|
||||
<?jelly escape-by-default='true'?>
|
||||
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:l="/lib/layout">
|
||||
<!-- pending build -->
|
||||
<j:set var="queuedItems" value="${it.queueItems}" />
|
||||
<j:if test="${!queuedItems.isEmpty()}">
|
||||
<j:forEach var="pageEntry" items="${queuedItems}" indexVar="i">
|
||||
<j:set var="item" value="${pageEntry.entry}"/>
|
||||
<j:set var="id" value="${h.generateId()}"/>
|
||||
<tr class="build-row build-pending transitive single-line" id="${item.id}" page-entry-id="${pageEntry.entryId}">
|
||||
<td class="build-row-cell">
|
||||
<div class="pane build-name">
|
||||
<div class="build-icon">
|
||||
<l:icon src="symbol-status-nobuilt" class="icon-sm"/>
|
||||
</div>
|
||||
<!-- Don't use math unless needed, in case nextBuildNumber is not numeric -->
|
||||
<div class="display-name" title="${%Expected build number}">
|
||||
#${queuedItems.size()==1 ? it.widget.owner.nextBuildNumber
|
||||
: it.widget.owner.nextBuildNumber+queuedItems.size()-i-1}
|
||||
</div>
|
||||
</div>
|
||||
<div class="pane build-details indent-multiline">
|
||||
<j:set var="cause" value="${item.getCauseOfBlockage()}"/>
|
||||
<j:choose>
|
||||
<j:when test="${cause!=null}">
|
||||
(${%pending}—<st:include it="${cause}" page="summary.jelly"/>)
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
(${%pending})
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
<j:if test="${!item.params.isEmpty()}">
|
||||
<div style="float:right;margin-right:10px;" tooltip="Build Parameters:${item.params}" data-tooltip-append-to-parent="true">
|
||||
<l:icon src="symbol-parameters" class="icon-sm" />
|
||||
</div>
|
||||
</j:if>
|
||||
</div>
|
||||
<div class="pane build-controls">
|
||||
<div class="build-stop">
|
||||
<j:if test="${item.hasCancelPermission()}">
|
||||
<l:stopButton href="${rootURL}/queue/cancelItem?id=${item.id}" alt="${%Cancel this build}"/>
|
||||
</j:if>
|
||||
</div>
|
||||
</div>
|
||||
<div class="left-bar"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</j:forEach>
|
||||
</j:if>
|
||||
<!-- pending build -->
|
||||
<j:set var="queuedItems" value="${it.queueItems}"/>
|
||||
<j:if test="${!queuedItems.isEmpty()}">
|
||||
<span class="app-builds-container__heading">${%Pending}</span>
|
||||
<j:forEach var="pageEntry" items="${queuedItems}">
|
||||
<j:set var="item" value="${pageEntry.entry}"/>
|
||||
<j:set var="id" value="${h.generateId()}"/>
|
||||
|
||||
<div class="app-builds-container__item app-builds-container__item--not-interactable" page-entry-id="${pageEntry.entryId}">
|
||||
<div class="app-builds-container__item__icon">
|
||||
<l:icon src="symbol-status-nobuilt" />
|
||||
</div>
|
||||
<div class="app-builds-container__item__inner">
|
||||
<div class="app-builds-container__item__inner__link">
|
||||
<!-- Don't use math unless needed, in case nextBuildNumber is not numeric -->
|
||||
#${queuedItems.size() == 1 ? it.widget.owner.nextBuildNumber : it.widget.owner.nextBuildNumber+queuedItems.size()-i-1}
|
||||
</div>
|
||||
<div class="app-builds-container__item__inner__controls">
|
||||
<j:if test="${!item.params.isEmpty()}">
|
||||
<div tooltip="Build Parameters: ${item.params}" data-tooltip-append-to-parent="true">
|
||||
<l:icon src="symbol-parameters" class="icon-sm" />
|
||||
</div>
|
||||
</j:if>
|
||||
<j:if test="${item.hasCancelPermission()}">
|
||||
<l:stopButton href="${rootURL}/queue/cancelItem?id=${item.id}" alt="${%Cancel}"/>
|
||||
</j:if>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-builds-container__item__description">
|
||||
<j:set var="cause" value="${item.getCauseOfBlockage()}"/>
|
||||
<j:choose>
|
||||
<j:when test="${cause!=null}">
|
||||
<st:include it="${cause}" page="summary.jelly"/>
|
||||
</j:when>
|
||||
</j:choose>
|
||||
</div>
|
||||
</div>
|
||||
</j:forEach>
|
||||
</j:if>
|
||||
</j:jelly>
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<!--
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2024 Jan Faracik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<?jelly escape-by-default='true'?>
|
||||
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout">
|
||||
<st:documentation>
|
||||
<st:attribute name="title" use="required">
|
||||
Title of the card
|
||||
</st:attribute>
|
||||
<st:attribute name="id">
|
||||
Optional ID for the card
|
||||
</st:attribute>
|
||||
<st:attribute name="controls">
|
||||
Shows controls in the top right of the card
|
||||
</st:attribute>
|
||||
<st:attribute name="expandable">
|
||||
Shows the expand icon if set, navigates to the value provided on click
|
||||
</st:attribute>
|
||||
</st:documentation>
|
||||
|
||||
<div class="jenkins-card" id="${attrs.id}">
|
||||
<div class="jenkins-card__title">
|
||||
${attrs.title}
|
||||
<div class="jenkins-card__controls">
|
||||
<j:out value="${controls}"/>
|
||||
<j:if test="${attrs.expandable != null}">
|
||||
<a href="${attrs.expandable}" class="jenkins-card__reveal" tooltip="${%Expand}">
|
||||
<l:icon src="symbol-expand" />
|
||||
</a>
|
||||
</j:if>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jenkins-card__content">
|
||||
<d:invokeBody />
|
||||
</div>
|
||||
</div>
|
||||
</j:jelly>
|
|
@ -157,7 +157,7 @@ public class RunTest {
|
|||
HtmlPage htmlPage = wc.goTo(upProject.getUrl());
|
||||
|
||||
// trigger the tooltip display
|
||||
htmlPage.executeJavaScript("document.querySelector('#buildHistory table .build-badge svg')._tippy.show()");
|
||||
htmlPage.executeJavaScript("document.querySelector('#jenkins-build-history .app-builds-container__item__inner__controls svg')._tippy.show()");
|
||||
wc.waitForBackgroundJavaScript(500);
|
||||
ScriptResult result = htmlPage.executeJavaScript("document.querySelector('.tippy-content').innerHTML;");
|
||||
Object jsResult = result.getJavaScriptResult();
|
||||
|
|
|
@ -66,7 +66,7 @@ public class AbstractScmTagActionTest {
|
|||
|
||||
HtmlPage page = wc.getPage(p);
|
||||
|
||||
DomElement buildHistory = page.getElementById("buildHistory");
|
||||
DomElement buildHistory = page.getElementById("buildHistoryPage");
|
||||
DomNodeList<HtmlElement> imgs = buildHistory.getElementsByTagName("img");
|
||||
HtmlImage tagImage = (HtmlImage) imgs.stream()
|
||||
.filter(i -> i.getAttribute("class").contains("icon-save"))
|
||||
|
|
|
@ -31,7 +31,7 @@ function generateJumplistAccessors() {
|
|||
*/
|
||||
function generateDropdowns() {
|
||||
behaviorShim.specify(
|
||||
"li.children, #menuSelector, .jenkins-menu-dropdown-chevron",
|
||||
"li.children, .jenkins-jumplist-link, #menuSelector, .jenkins-menu-dropdown-chevron",
|
||||
"-dropdown-",
|
||||
1000,
|
||||
(element) =>
|
||||
|
|
|
@ -1,590 +0,0 @@
|
|||
import debounce from "lodash/debounce";
|
||||
|
||||
const buildHistoryContainer = document.getElementById("buildHistory");
|
||||
const pageSearchInputContainer = buildHistoryContainer.querySelector(
|
||||
".build-search-row .jenkins-search",
|
||||
);
|
||||
const pageSearchInput = buildHistoryContainer.querySelector(
|
||||
".build-search-row input",
|
||||
);
|
||||
const buildHistoryPage = document.getElementById("buildHistoryPage");
|
||||
const properties = document.getElementById("properties");
|
||||
const ajaxUrl = buildHistoryPage.getAttribute("page-ajax");
|
||||
const nextBuild = properties.getAttribute("page-next-build");
|
||||
const noBuildsBanner = document.getElementById("no-builds");
|
||||
|
||||
const sidePanel = document.getElementById("side-panel");
|
||||
const buildHistoryPageNav = document.getElementById("buildHistoryPageNav");
|
||||
|
||||
const pageOne = buildHistoryPageNav.querySelector(".pageOne");
|
||||
const pageUp = buildHistoryPageNav.querySelector(".pageUp");
|
||||
const pageDown = buildHistoryPageNav.querySelector(".pageDown");
|
||||
|
||||
const leftRightPadding = 4;
|
||||
const updateBuildsRefreshInterval = 5000;
|
||||
|
||||
function updateBuilds(params) {
|
||||
if (isPageVisible()) {
|
||||
fetch(ajaxUrl + toQueryString(params), {
|
||||
headers: {
|
||||
n: buildHistoryContainer.headers[1],
|
||||
},
|
||||
}).then((rsp) => {
|
||||
if (rsp.ok) {
|
||||
rsp.text().then((responseText) => {
|
||||
var dataTable = getDataTable(buildHistoryContainer);
|
||||
var rows = dataTable.rows;
|
||||
|
||||
// Check there are no existing rows (except the search bar) before showing the no builds banner
|
||||
if (
|
||||
rows.length <= 1 &&
|
||||
responseText === '<table class="pane"></table>'
|
||||
) {
|
||||
noBuildsBanner.style.display = "block";
|
||||
if (
|
||||
typeof params === "object" &&
|
||||
"search" in params &&
|
||||
params.search !== ""
|
||||
) {
|
||||
pageSearchInputContainer.classList.remove("jenkins-hidden");
|
||||
} else {
|
||||
pageSearchInputContainer.classList.add("jenkins-hidden");
|
||||
}
|
||||
} else {
|
||||
noBuildsBanner.style.display = "none";
|
||||
pageSearchInputContainer.classList.remove("jenkins-hidden");
|
||||
}
|
||||
|
||||
//delete rows with transitive data
|
||||
var firstBuildRow = 0;
|
||||
if (rows[firstBuildRow].classList.contains("build-search-row")) {
|
||||
firstBuildRow++;
|
||||
}
|
||||
while (
|
||||
rows.length > 1 &&
|
||||
rows[firstBuildRow].classList.contains("transitive")
|
||||
) {
|
||||
rows[firstBuildRow].remove();
|
||||
}
|
||||
|
||||
// insert new rows
|
||||
var div = document.createElement("div");
|
||||
div.innerHTML = responseText;
|
||||
Behaviour.applySubtree(div);
|
||||
|
||||
var pivot = rows[firstBuildRow];
|
||||
var newDataTable = getDataTable(div);
|
||||
var newRows = newDataTable.rows;
|
||||
while (newRows.length > 0) {
|
||||
if (pivot !== undefined) {
|
||||
// The data table has rows. Insert before a "pivot" row (first row).
|
||||
pivot.parentNode.insertBefore(newRows[0], pivot);
|
||||
} else {
|
||||
// The data table has no rows. In this case, we just add all new rows directly to the
|
||||
// table, one after the other i.e. we don't insert before a "pivot" row (first row).
|
||||
dataTable
|
||||
.getElementsByTagName("tbody")[0]
|
||||
.appendChild(newRows[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (newDataTable.classList.contains("hasPageData")) {
|
||||
buildHistoryPage.setAttribute(
|
||||
"page-entry-newest",
|
||||
newDataTable.getAttribute("page-entry-newest"),
|
||||
);
|
||||
}
|
||||
|
||||
// next update
|
||||
buildHistoryContainer.headers = ["n", rsp.headers.get("n")];
|
||||
checkAllRowCellOverflows();
|
||||
createRefreshTimeout(params);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
createRefreshTimeout(params);
|
||||
}
|
||||
}
|
||||
|
||||
var buildRefreshTimeout;
|
||||
function createRefreshTimeout(params) {
|
||||
cancelRefreshTimeout();
|
||||
buildRefreshTimeout = window.setTimeout(
|
||||
() => updateBuilds(params),
|
||||
updateBuildsRefreshInterval,
|
||||
);
|
||||
}
|
||||
|
||||
function cancelRefreshTimeout() {
|
||||
if (buildRefreshTimeout) {
|
||||
window.clearTimeout(buildRefreshTimeout);
|
||||
buildRefreshTimeout = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function hasPageUp() {
|
||||
return buildHistoryPage.getAttribute("page-has-up") === "true";
|
||||
}
|
||||
function hasPageDown() {
|
||||
return buildHistoryPage.getAttribute("page-has-down") === "true";
|
||||
}
|
||||
function getNewestEntryId() {
|
||||
return buildHistoryPage.getAttribute("page-entry-newest");
|
||||
}
|
||||
function getOldestEntryId() {
|
||||
return buildHistoryPage.getAttribute("page-entry-oldest");
|
||||
}
|
||||
|
||||
function getDataTable(buildHistoryDiv) {
|
||||
return buildHistoryDiv.querySelector("table.pane");
|
||||
}
|
||||
|
||||
function updatePageParams(dataTable) {
|
||||
buildHistoryPage.setAttribute(
|
||||
"page-has-up",
|
||||
dataTable.getAttribute("page-has-up"),
|
||||
);
|
||||
buildHistoryPage.setAttribute(
|
||||
"page-has-down",
|
||||
dataTable.getAttribute("page-has-down"),
|
||||
);
|
||||
buildHistoryPage.setAttribute(
|
||||
"page-entry-newest",
|
||||
dataTable.getAttribute("page-entry-newest"),
|
||||
);
|
||||
buildHistoryPage.setAttribute(
|
||||
"page-entry-oldest",
|
||||
dataTable.getAttribute("page-entry-oldest"),
|
||||
);
|
||||
}
|
||||
function togglePageUpDown() {
|
||||
buildHistoryPageNav.classList.remove("hasUpPage");
|
||||
buildHistoryPageNav.classList.remove("hasDownPage");
|
||||
if (hasPageUp()) {
|
||||
buildHistoryPageNav.classList.add("hasUpPage");
|
||||
}
|
||||
if (hasPageDown()) {
|
||||
buildHistoryPageNav.classList.add("hasDownPage");
|
||||
}
|
||||
}
|
||||
|
||||
function checkRowCellOverflows(row) {
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (row.classList.contains("overflow-checked")) {
|
||||
// already done.
|
||||
return;
|
||||
}
|
||||
|
||||
function markSingleline() {
|
||||
row.classList.add("single-line");
|
||||
row.classList.remove("multi-line");
|
||||
}
|
||||
function markMultiline() {
|
||||
row.classList.remove("single-line");
|
||||
row.classList.add("multi-line");
|
||||
}
|
||||
function indentMultiline(element) {
|
||||
element.classList.add("indent-multiline");
|
||||
}
|
||||
|
||||
function blockWrap(el1, el2) {
|
||||
var div = document.createElement("div");
|
||||
|
||||
div.classList.add("block");
|
||||
div.classList.add("wrap");
|
||||
el1.classList.add("wrapped");
|
||||
el2.classList.add("wrapped");
|
||||
|
||||
el1.parentNode.insertBefore(div, el1);
|
||||
el1.parentNode.removeChild(el1);
|
||||
el2.parentNode.removeChild(el2);
|
||||
div.appendChild(el1);
|
||||
div.appendChild(el2);
|
||||
|
||||
return div;
|
||||
}
|
||||
function blockUnwrap(element) {
|
||||
element.querySelectorAll(".wrapped").forEach(function (wrappedEl) {
|
||||
wrappedEl.parentNode.removeChild(wrappedEl);
|
||||
element.parentNode.insertBefore(wrappedEl, element);
|
||||
wrappedEl.classList.remove("wrapped");
|
||||
});
|
||||
element.parentNode.removeChild(element);
|
||||
}
|
||||
|
||||
var buildName = row.querySelector(".build-name");
|
||||
var buildDetails = row.querySelector(".build-details");
|
||||
|
||||
if (!buildName || !buildDetails) {
|
||||
return;
|
||||
}
|
||||
|
||||
var buildControls = row.querySelector(".build-controls");
|
||||
var desc = row.querySelector(".desc");
|
||||
|
||||
function resetCellOverflows() {
|
||||
markSingleline();
|
||||
|
||||
// undo block wraps
|
||||
row.querySelectorAll(".block.wrap").forEach(function (blockWrap) {
|
||||
blockUnwrap(blockWrap);
|
||||
});
|
||||
|
||||
buildName.classList.remove("block");
|
||||
buildName.removeAttribute("style");
|
||||
buildDetails.classList.remove("block");
|
||||
buildDetails.removeAttribute("style");
|
||||
if (buildControls) {
|
||||
buildControls.classList.remove("block");
|
||||
buildDetails.removeAttribute("style");
|
||||
}
|
||||
}
|
||||
|
||||
// Undo everything from the previous poll.
|
||||
resetCellOverflows();
|
||||
|
||||
// Mark the text as multiline, if it has more than one line
|
||||
if (desc) {
|
||||
markMultiline();
|
||||
}
|
||||
|
||||
var rowWidth = buildHistoryContainer.clientWidth;
|
||||
var usableRowWidth = rowWidth - leftRightPadding * 2;
|
||||
var nameOverflowParams = getElementOverflowParams(buildName);
|
||||
var detailsOverflowParams = getElementOverflowParams(buildDetails);
|
||||
|
||||
var controlsOverflowParams;
|
||||
if (buildControls) {
|
||||
controlsOverflowParams = getElementOverflowParams(buildControls);
|
||||
}
|
||||
|
||||
function fitToControlsHeight(element) {
|
||||
if (buildControls) {
|
||||
if (element.clientHeight < buildControls.clientHeight) {
|
||||
element.style.height = buildControls.clientHeight.toString() + "px";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setBuildControlWidths() {
|
||||
if (buildControls) {
|
||||
var buildBadge = buildControls.querySelector(".build-badge");
|
||||
|
||||
if (buildBadge) {
|
||||
var buildControlsWidth = buildControls.clientWidth;
|
||||
var buildBadgeWidth;
|
||||
|
||||
var buildStop = buildControls.querySelector(".build-stop");
|
||||
if (buildStop) {
|
||||
buildStop.style.width = "24px";
|
||||
// Minus 24 for the buildStop width,
|
||||
// minus 4 for left+right padding in the controls container
|
||||
buildBadgeWidth = buildControlsWidth - 24 - leftRightPadding;
|
||||
if (buildControls.classList.contains("indent-multiline")) {
|
||||
buildBadgeWidth = buildBadgeWidth - 20;
|
||||
}
|
||||
buildBadge.style.width = buildBadgeWidth + "px";
|
||||
} else {
|
||||
buildBadge.style.width = "100%";
|
||||
}
|
||||
}
|
||||
controlsOverflowParams = getElementOverflowParams(buildControls);
|
||||
}
|
||||
}
|
||||
setBuildControlWidths();
|
||||
|
||||
var controlsRepositioned = false;
|
||||
|
||||
if (nameOverflowParams.isOverflowed || detailsOverflowParams.isOverflowed) {
|
||||
// At least one of the cells (name or details) needs to move to a row of its own.
|
||||
|
||||
markMultiline();
|
||||
|
||||
if (buildControls) {
|
||||
// We have build controls. Lets see can we find a combination that allows the build controls
|
||||
// to sit beside either the build name or the build details.
|
||||
|
||||
var badgesOverflowing = false;
|
||||
var nameLessThanHalf = true;
|
||||
var detailsLessThanHalf = true;
|
||||
var buildBadge = buildControls.querySelector(".build-badge");
|
||||
if (buildBadge) {
|
||||
var badgeOverflowParams = getElementOverflowParams(buildBadge);
|
||||
|
||||
if (badgeOverflowParams.isOverflowed) {
|
||||
// The badges are also overflowing. In this case, we will only attempt to
|
||||
// put the controls on the same line as the name or details (see below)
|
||||
// if the name or details is using less than half the width of the build history
|
||||
// widget.
|
||||
badgesOverflowing = true;
|
||||
nameLessThanHalf =
|
||||
nameOverflowParams.scrollWidth < usableRowWidth / 2;
|
||||
detailsLessThanHalf =
|
||||
detailsOverflowParams.scrollWidth < usableRowWidth / 2;
|
||||
}
|
||||
}
|
||||
function expandLeftWithRight(
|
||||
leftCellOverFlowParams,
|
||||
rightCellOverflowParams,
|
||||
) {
|
||||
// Float them left and right...
|
||||
leftCellOverFlowParams.element.style.float = "left";
|
||||
rightCellOverflowParams.element.style.float = "right";
|
||||
|
||||
if (
|
||||
!leftCellOverFlowParams.isOverflowed &&
|
||||
!rightCellOverflowParams.isOverflowed
|
||||
) {
|
||||
// If neither left nor right are overflowed, just leave as is and let them float left and right.
|
||||
return;
|
||||
}
|
||||
if (
|
||||
leftCellOverFlowParams.isOverflowed &&
|
||||
!rightCellOverflowParams.isOverflowed
|
||||
) {
|
||||
leftCellOverFlowParams.element.style.width =
|
||||
leftCellOverFlowParams.scrollWidth + "px";
|
||||
return;
|
||||
}
|
||||
if (
|
||||
!leftCellOverFlowParams.isOverflowed &&
|
||||
rightCellOverflowParams.isOverflowed
|
||||
) {
|
||||
rightCellOverflowParams.element.style.width =
|
||||
rightCellOverflowParams.scrollWidth + "px";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(!badgesOverflowing || nameLessThanHalf) &&
|
||||
nameOverflowParams.scrollWidth + controlsOverflowParams.scrollWidth <=
|
||||
usableRowWidth
|
||||
) {
|
||||
// Build name and controls can go on one row (first row). Need to move build details down
|
||||
// to a row of its own (second row) by making it a block element, forcing it to wrap. If there
|
||||
// are controls, we move them up to position them after the build name by inserting before the
|
||||
// build details.
|
||||
buildDetails.classList.add("block");
|
||||
buildControls.parentNode.removeChild(buildControls);
|
||||
buildDetails.parentNode.insertBefore(buildControls, buildDetails);
|
||||
var wrap = blockWrap(buildName, buildControls);
|
||||
wrap.classList.add("build-name-controls");
|
||||
indentMultiline(buildDetails);
|
||||
nameOverflowParams = getElementOverflowParams(buildName); // recalculate
|
||||
expandLeftWithRight(nameOverflowParams, controlsOverflowParams);
|
||||
setBuildControlWidths();
|
||||
fitToControlsHeight(buildName);
|
||||
} else if (
|
||||
(!badgesOverflowing || detailsLessThanHalf) &&
|
||||
detailsOverflowParams.scrollWidth +
|
||||
controlsOverflowParams.scrollWidth <=
|
||||
usableRowWidth
|
||||
) {
|
||||
// Build details and controls can go on one row. Need to make the
|
||||
// build name (first field) a block element, forcing the details and controls to wrap
|
||||
// onto the next row (creating a second row).
|
||||
buildName.classList.add("block");
|
||||
wrap = blockWrap(buildDetails, buildControls);
|
||||
indentMultiline(wrap);
|
||||
wrap.classList.add("build-details-controls");
|
||||
detailsOverflowParams = getElementOverflowParams(buildDetails); // recalculate
|
||||
expandLeftWithRight(detailsOverflowParams, controlsOverflowParams);
|
||||
setBuildControlWidths();
|
||||
fitToControlsHeight(buildDetails);
|
||||
} else {
|
||||
// No suitable combo fits on a row. All need to go on rows of their own.
|
||||
buildName.classList.add("block");
|
||||
buildDetails.classList.add("block");
|
||||
buildControls.classList.add("block");
|
||||
indentMultiline(buildDetails);
|
||||
indentMultiline(buildControls);
|
||||
nameOverflowParams = getElementOverflowParams(buildName); // recalculate
|
||||
detailsOverflowParams = getElementOverflowParams(buildDetails); // recalculate
|
||||
setBuildControlWidths();
|
||||
}
|
||||
controlsRepositioned = true;
|
||||
} else {
|
||||
buildName.classList.add("block");
|
||||
buildDetails.classList.add("block");
|
||||
indentMultiline(buildDetails);
|
||||
}
|
||||
}
|
||||
|
||||
if (buildControls && !controlsRepositioned) {
|
||||
buildBadge = buildControls.querySelector(".build-badge");
|
||||
if (buildBadge) {
|
||||
badgeOverflowParams = getElementOverflowParams(buildBadge);
|
||||
|
||||
if (badgeOverflowParams.isOverflowed) {
|
||||
markMultiline();
|
||||
indentMultiline(buildControls);
|
||||
buildControls.classList.add("block");
|
||||
controlsRepositioned = true;
|
||||
setBuildControlWidths();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!nameOverflowParams.isOverflowed &&
|
||||
!detailsOverflowParams.isOverflowed &&
|
||||
!controlsRepositioned
|
||||
) {
|
||||
fitToControlsHeight(buildName);
|
||||
fitToControlsHeight(buildDetails);
|
||||
}
|
||||
|
||||
row.classList.add("overflow-checked");
|
||||
}
|
||||
|
||||
function checkAllRowCellOverflows() {
|
||||
if (isRunAsTest) {
|
||||
return;
|
||||
}
|
||||
|
||||
var dataTable = getDataTable(buildHistoryContainer);
|
||||
var rows = dataTable.rows;
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
checkRowCellOverflows(row);
|
||||
}
|
||||
}
|
||||
|
||||
function loadPage(params, focusOnSearch) {
|
||||
var searchString = pageSearchInput.value;
|
||||
|
||||
if (searchString !== "") {
|
||||
if (params === undefined) {
|
||||
params = {};
|
||||
}
|
||||
params.search = searchString;
|
||||
}
|
||||
|
||||
fetch(ajaxUrl + toQueryString(params)).then((rsp) => {
|
||||
if (rsp.ok) {
|
||||
rsp.text().then((responseText) => {
|
||||
pageSearchInputContainer.classList.remove("jenkins-search--loading");
|
||||
buildHistoryContainer.classList.remove("jenkins-pane--loading");
|
||||
|
||||
if (responseText === '<table class="pane"></table>') {
|
||||
noBuildsBanner.style.display = "block";
|
||||
if (
|
||||
typeof params === "object" &&
|
||||
"search" in params &&
|
||||
params.search !== ""
|
||||
) {
|
||||
pageSearchInputContainer.classList.remove("jenkins-hidden");
|
||||
} else {
|
||||
pageSearchInputContainer.classList.add("jenkins-hidden");
|
||||
}
|
||||
} else {
|
||||
noBuildsBanner.style.display = "none";
|
||||
pageSearchInputContainer.classList.remove("jenkins-hidden");
|
||||
}
|
||||
|
||||
var dataTable = getDataTable(buildHistoryContainer);
|
||||
var tbody = dataTable.getElementsByTagName("tbody")[0];
|
||||
var rows = tbody.getElementsByClassName("build-row");
|
||||
|
||||
// Delete all build rows
|
||||
while (rows.length > 0) {
|
||||
rows[0].remove();
|
||||
}
|
||||
|
||||
// insert new rows
|
||||
var div = document.createElement("div");
|
||||
div.innerHTML = responseText;
|
||||
Behaviour.applySubtree(div);
|
||||
|
||||
var newDataTable = getDataTable(div);
|
||||
var newRows = newDataTable.rows;
|
||||
while (newRows.length > 0) {
|
||||
tbody.appendChild(newRows[0]);
|
||||
}
|
||||
|
||||
checkAllRowCellOverflows();
|
||||
updatePageParams(newDataTable);
|
||||
togglePageUpDown();
|
||||
if (!hasPageUp()) {
|
||||
createRefreshTimeout(params);
|
||||
}
|
||||
|
||||
if (focusOnSearch) {
|
||||
pageSearchInput.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const handleFilter = function () {
|
||||
loadPage({}, true);
|
||||
};
|
||||
|
||||
const debouncedFilter = debounce(handleFilter, 300);
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Apply correct styling upon filter bar text change, call API after wait
|
||||
if (pageSearchInput !== null) {
|
||||
pageSearchInput.addEventListener("input", function () {
|
||||
pageSearchInputContainer.classList.add("jenkins-search--loading");
|
||||
buildHistoryContainer.classList.add("jenkins-pane--loading");
|
||||
noBuildsBanner.style.display = "none";
|
||||
|
||||
debouncedFilter();
|
||||
});
|
||||
}
|
||||
|
||||
if (isRunAsTest) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the build history pane is collapsed, just return immediately and don't set up
|
||||
// the build history refresh.
|
||||
if (buildHistoryContainer.classList.contains("collapsed")) {
|
||||
return;
|
||||
}
|
||||
|
||||
buildHistoryContainer.headers = ["n", nextBuild];
|
||||
|
||||
createRefreshTimeout();
|
||||
checkAllRowCellOverflows();
|
||||
|
||||
// Show/hide the nav as the mouse moves into the sidepanel and build history.
|
||||
sidePanel.addEventListener("mouseover", function () {
|
||||
buildHistoryPageNav.classList.add("mouseOverSidePanel");
|
||||
});
|
||||
sidePanel.addEventListener("mouseout", function () {
|
||||
buildHistoryPageNav.classList.remove("mouseOverSidePanel");
|
||||
});
|
||||
buildHistoryContainer.addEventListener("mouseover", function () {
|
||||
buildHistoryPageNav.classList.add("mouseOverSidePanelBuildHistory");
|
||||
});
|
||||
buildHistoryContainer.addEventListener("mouseout", function () {
|
||||
buildHistoryPageNav.classList.remove("mouseOverSidePanelBuildHistory");
|
||||
});
|
||||
|
||||
pageOne.addEventListener("click", function () {
|
||||
loadPage();
|
||||
});
|
||||
pageUp.addEventListener("click", function () {
|
||||
loadPage({ "newer-than": getNewestEntryId() });
|
||||
});
|
||||
pageDown.addEventListener("click", function () {
|
||||
if (hasPageDown()) {
|
||||
cancelRefreshTimeout();
|
||||
loadPage({ "older-than": getOldestEntryId() });
|
||||
} else {
|
||||
// wrap back around to the top
|
||||
loadPage();
|
||||
}
|
||||
});
|
||||
|
||||
togglePageUpDown();
|
||||
});
|
|
@ -0,0 +1,142 @@
|
|||
import debounce from "lodash/debounce";
|
||||
import behaviorShim from "@/util/behavior-shim";
|
||||
|
||||
// Card/item controls
|
||||
const buildHistoryPage = document.getElementById("buildHistoryPage");
|
||||
const pageSearch = buildHistoryPage.querySelector(".jenkins-search");
|
||||
const pageSearchInput = buildHistoryPage.querySelector("input");
|
||||
const ajaxUrl = buildHistoryPage.getAttribute("page-ajax");
|
||||
const card = document.querySelector("#jenkins-builds");
|
||||
const contents = card.querySelector("#jenkins-build-history");
|
||||
const container = card.querySelector(".app-builds-container");
|
||||
const noBuilds = card.querySelector("#no-builds");
|
||||
|
||||
// Pagination controls
|
||||
const paginationControls = document.querySelector("#controls");
|
||||
const paginationPrevious = document.querySelector("#up");
|
||||
const paginationNext = document.querySelector("#down");
|
||||
|
||||
// Refresh variables
|
||||
let buildRefreshTimeout;
|
||||
const updateBuildsRefreshInterval = 5000;
|
||||
|
||||
/**
|
||||
* Refresh the 'Builds' card
|
||||
* @param {QueryParameters} options
|
||||
*/
|
||||
function load(options = {}) {
|
||||
/** @type {QueryParameters} */
|
||||
const params = Object.assign({}, options, { search: pageSearchInput.value });
|
||||
|
||||
// Avoid fetching if the page isn't active
|
||||
if (document.hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(ajaxUrl + toQueryString(params)).then((rsp) => {
|
||||
if (rsp.ok) {
|
||||
rsp.text().then((responseText) => {
|
||||
container.classList.remove("app-builds-container--loading");
|
||||
pageSearch.classList.remove("jenkins-search--loading");
|
||||
|
||||
// Show the 'No builds' text if there are no builds
|
||||
if (responseText.trim() === "") {
|
||||
contents.innerHTML = "";
|
||||
noBuilds.style.display = "block";
|
||||
updateCardControls({
|
||||
pageHasUp: false,
|
||||
pageHasDown: false,
|
||||
pageEntryNewest: false,
|
||||
pageEntryOldest: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Show the refreshed builds list
|
||||
contents.innerHTML = responseText;
|
||||
noBuilds.style.display = "none";
|
||||
behaviorShim.applySubtree(contents);
|
||||
|
||||
// Show the card controls
|
||||
const div = document.createElement("div");
|
||||
div.innerHTML = responseText;
|
||||
const innerChild = div.children[0];
|
||||
updateCardControls({
|
||||
pageHasUp: innerChild.dataset.pageHasUp === "true",
|
||||
pageHasDown: innerChild.dataset.pageHasDown === "true",
|
||||
pageEntryNewest: innerChild.dataset.pageEntryNewest,
|
||||
pageEntryOldest: innerChild.dataset.pageEntryOldest,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.error("Failed to load 'Builds' card, response from API is:", rsp);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows/hides the card's pagination controls depending on the passed parameter
|
||||
* @param {CardControlsOptions} parameters
|
||||
*/
|
||||
function updateCardControls(parameters) {
|
||||
paginationControls.classList.toggle(
|
||||
"jenkins-hidden",
|
||||
!parameters.pageHasUp && !parameters.pageHasDown,
|
||||
);
|
||||
paginationPrevious.classList.toggle(
|
||||
"app-builds-container__button--disabled",
|
||||
!parameters.pageHasUp,
|
||||
);
|
||||
paginationNext.classList.toggle(
|
||||
"app-builds-container__button--disabled",
|
||||
!parameters.pageHasDown,
|
||||
);
|
||||
|
||||
// We only want the list to refresh if the user is on the first page of results
|
||||
if (!parameters.pageHasUp) {
|
||||
createRefreshTimeout();
|
||||
} else {
|
||||
cancelRefreshTimeout();
|
||||
}
|
||||
|
||||
buildHistoryPage.dataset.pageEntryNewest = parameters.pageEntryNewest;
|
||||
buildHistoryPage.dataset.pageEntryOldest = parameters.pageEntryOldest;
|
||||
}
|
||||
|
||||
paginationPrevious.addEventListener("click", () => {
|
||||
load({ "newer-than": buildHistoryPage.dataset.pageEntryNewest });
|
||||
});
|
||||
|
||||
paginationNext.addEventListener("click", () => {
|
||||
cancelRefreshTimeout();
|
||||
load({ "older-than": buildHistoryPage.dataset.pageEntryOldest });
|
||||
});
|
||||
|
||||
function createRefreshTimeout() {
|
||||
cancelRefreshTimeout();
|
||||
buildRefreshTimeout = window.setTimeout(
|
||||
() => load(),
|
||||
updateBuildsRefreshInterval,
|
||||
);
|
||||
}
|
||||
|
||||
function cancelRefreshTimeout() {
|
||||
if (buildRefreshTimeout) {
|
||||
window.clearTimeout(buildRefreshTimeout);
|
||||
buildRefreshTimeout = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const debouncedLoad = debounce(() => {
|
||||
load();
|
||||
}, 150);
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
pageSearchInput.addEventListener("input", function () {
|
||||
container.classList.add("app-builds-container--loading");
|
||||
pageSearch.classList.add("jenkins-search--loading");
|
||||
debouncedLoad();
|
||||
});
|
||||
|
||||
load();
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* @typedef QueryParameters
|
||||
* @type {object}
|
||||
* @property {string | undefined} search
|
||||
* @property {string | undefined} older-than
|
||||
* @property {string | undefined} newer-than
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef CardControlsOptions
|
||||
* @type {object}
|
||||
* @property {boolean} pageHasUp
|
||||
* @property {boolean} pageHasDown
|
||||
* @property {string | undefined} pageEntryNewest
|
||||
* @property {string | undefined} pageEntryOldest
|
||||
*/
|
|
@ -0,0 +1 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H15C15.5523 4 16 4.44772 16 5V10M10 16H5C4.44772 16 4 15.5523 4 15V10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path></svg>
|
After Width: | Height: | Size: 258 B |
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512">
|
||||
<circle cx="256" cy="256" r="45" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/>
|
||||
<circle cx="441" cy="256" r="45" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/>
|
||||
<circle cx="71" cy="256" r="45" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/>
|
||||
</svg>
|
After Width: | Height: | Size: 427 B |
|
@ -244,7 +244,7 @@ $semantics: (
|
|||
--pane-link-color--visited: black;
|
||||
|
||||
// Cards
|
||||
--card-background: transparent;
|
||||
--card-background: var(--background);
|
||||
--card-background--hover: transparent;
|
||||
--card-background--active: transparent;
|
||||
--card-border-color: hsla(240, 25%, 75%, 0.25);
|
||||
|
|
|
@ -449,189 +449,6 @@ div.listview-jobs {
|
|||
display: block;
|
||||
}
|
||||
|
||||
/* ========================= build history ========================= */
|
||||
#buildHistory a:visited {
|
||||
color: fuchsia;
|
||||
}
|
||||
|
||||
#buildHistory tr.no-wrap td.middle-align {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#buildHistory .desc {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
margin-top: 5px;
|
||||
white-space: normal;
|
||||
color: var(--text-color-secondary);
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
#buildHistory .build-row-cell {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#buildHistory .build-rss-links {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
#buildHistory .build-rss-links a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
#buildHistory .build-rss-all-icon,
|
||||
#buildHistory .build-rss-failed-icon {
|
||||
margin-right: 0.25rem;
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
#buildHistoryPage {
|
||||
position: relative;
|
||||
|
||||
.build-search-row,
|
||||
.build-search-no-results-row {
|
||||
&:hover {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0 8px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.build-search-no-results-row {
|
||||
border: none !important;
|
||||
width: 100% !important;
|
||||
background: transparent;
|
||||
|
||||
td {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#buildHistoryPageNav {
|
||||
position: absolute;
|
||||
right: -28px;
|
||||
top: 96px;
|
||||
border-radius: 6px;
|
||||
background: var(--input-color);
|
||||
border: 2px solid var(--input-border);
|
||||
visibility: hidden;
|
||||
z-index: 0;
|
||||
opacity: 0;
|
||||
transition: 0.2s ease;
|
||||
|
||||
// Invisible pseudo element on the left so #buildHistoryPageNav
|
||||
// doesn't disappear when moving cursor over gap
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -8px;
|
||||
bottom: 0;
|
||||
width: 8px;
|
||||
background: transparent;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.buildHistoryPageNav__item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
padding: 0 8px;
|
||||
height: 30px;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
&:active {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 2px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
&-page-one-top {
|
||||
width: 12px;
|
||||
height: 2px;
|
||||
background: currentColor;
|
||||
margin: 2px 0;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: currentColor;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#buildHistoryPageNav.mouseOverSidePanel {
|
||||
visibility: visible;
|
||||
right: -32px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.build-row.model-link-active {
|
||||
background: var(--light-grey) !important;
|
||||
}
|
||||
|
||||
.build-row-cell {
|
||||
font-size: var(--font-size-xs);
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-name {
|
||||
width: 25%;
|
||||
font-weight: 500;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-details {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-controls {
|
||||
width: 25%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-details.block {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pane.build-name a,
|
||||
.pane.build-name a:visited {
|
||||
color: var(--pane-link-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.pane.build-details a,
|
||||
.pane.build-details a:visited {
|
||||
color: var(--pane-link-color--visited);
|
||||
opacity: 0.6;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.pane.build-details a:hover {
|
||||
opacity: 1;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ================ Element overflow calculation helper styles ================ */
|
||||
|
||||
.force-wrap,
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
$card-padding: 1rem;
|
||||
|
||||
.jenkins-card {
|
||||
position: relative;
|
||||
border-radius: 1rem;
|
||||
margin-bottom: calc(var(--section-padding) / 2);
|
||||
background: var(--card-background);
|
||||
|
||||
&__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 $card-padding;
|
||||
height: 50px;
|
||||
font-size: var(--font-size-sm) !important;
|
||||
font-weight: 500;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&__controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.4rem;
|
||||
margin-right: -0.2rem;
|
||||
}
|
||||
|
||||
&:not(:hover) {
|
||||
.jenkins-card__unveil {
|
||||
color: var(--text-color-secondary) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.jenkins-card__reveal {
|
||||
color: var(--text-color) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 $card-padding $card-padding;
|
||||
color: var(--text-color-secondary);
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
border: var(--card-border-width) solid var(--card-border-color);
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.jenkins-card__reveal {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-block: -0.5rem;
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border-radius: 0.33rem;
|
||||
color: var(--text-color-secondary) !important;
|
||||
transition:
|
||||
scale var(--standard-transition),
|
||||
opacity var(--standard-transition);
|
||||
|
||||
svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
transition: color var(--standard-transition);
|
||||
}
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
&:active {
|
||||
scale: 95%;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -254,3 +254,18 @@ $dropdown-padding: 0.4rem;
|
|||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.jenkins-jumplist-link {
|
||||
appearance: none;
|
||||
border: none;
|
||||
background: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
svg {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
@use "alert";
|
||||
@use "badges";
|
||||
@use "breadcrumbs";
|
||||
@use "buttons-deprecated";
|
||||
@use "buttons";
|
||||
@use "buttons-deprecated";
|
||||
@use "cards";
|
||||
@use "content-blocks";
|
||||
@use "dialogs";
|
||||
@use "dropdowns";
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
var(--text-color-secondary) 25%,
|
||||
transparent
|
||||
);
|
||||
margin-top: 2px;
|
||||
display: block;
|
||||
opacity: 1 !important;
|
||||
|
||||
|
|
|
@ -90,165 +90,3 @@
|
|||
#executors th.pane {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build history
|
||||
*/
|
||||
.build-row {
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
.build-row.model-link-active {
|
||||
background: var(--very-light-grey) !important;
|
||||
}
|
||||
|
||||
.build-row-cell {
|
||||
font-size: var(--font-size-xs);
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-name {
|
||||
width: 32%;
|
||||
font-weight: 500;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-details {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-controls {
|
||||
width: 18%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-details.block {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.build-row.multi-line .build-row-cell .pane.build-name.block {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-controls.block {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-name .build-icon,
|
||||
.build-row-cell .pane.build-name .display-name {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-name .build-icon {
|
||||
position: absolute;
|
||||
margin-top: 2px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.build-row-cell .build-stop {
|
||||
display: inline-block;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.build-row-cell .build-badge {
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
width: 70%;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.build-row-cell .build-badge > span {
|
||||
display: inline-block;
|
||||
max-width: 256px;
|
||||
padding: 0 1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.build-row-cell .build-badge > span + span {
|
||||
margin: 0 0 0 2px !important;
|
||||
}
|
||||
|
||||
@media (width >= 1170px) {
|
||||
.build-row-cell .build-badge > span {
|
||||
max-width: 296px;
|
||||
}
|
||||
}
|
||||
|
||||
.build-row .build-name-controls .pane.build-name,
|
||||
.build-row .build-details-controls .pane.build-details {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.build-row .build-row-cell .pane,
|
||||
#side-panel .build-row .build-row-cell .pane {
|
||||
padding: 0 2px; /* Sync changes with func expandControlsTo50Percent in hudson-behavior.js */
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.build-row.multi-line .build-row-cell .block {
|
||||
display: block;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.build-row.multi-line .build-row-cell .indent-multiline {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.build-row.multi-line .build-row-cell .left-bar {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
bottom: 10px;
|
||||
left: 17px;
|
||||
border-left: 1px solid var(--medium-grey);
|
||||
}
|
||||
|
||||
.build-row-cell .pane.build-name .display-name {
|
||||
margin-left: 20px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.build-row-cell .indent-multiline {
|
||||
padding-left: 20px !important; /* Sync changes with func expandControlsTo50Percent in hudson-behavior.js */
|
||||
}
|
||||
|
||||
.build-row.overflow-checked .build-row-cell {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.jenkins-pane {
|
||||
&__information {
|
||||
text-align: center;
|
||||
line-height: 80px;
|
||||
background-color: var(--panel-header-bg-color);
|
||||
margin-top: 10px;
|
||||
font-weight: 600;
|
||||
border-radius: var(--form-input-border-radius);
|
||||
}
|
||||
|
||||
.build-row {
|
||||
transition: opacity 0.2s ease;
|
||||
|
||||
&-cell {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&--loading .build-row {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.jenkins-pane__header--build-history {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
font-weight: 500 !important;
|
||||
|
||||
.build-health-link {
|
||||
margin: -9px -15px;
|
||||
}
|
||||
|
||||
.jenkins-table__cell--tight {
|
||||
width: auto;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
@use "build";
|
||||
@use "dashboard";
|
||||
@use "icon-legend";
|
||||
@use "job";
|
||||
@use "manage-jenkins";
|
||||
@use "plugin-manager";
|
||||
@use "setupWizardFirstUser";
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
@use "../abstracts/mixins";
|
||||
|
||||
#buildHistoryPage {
|
||||
margin: 10px 0 10px 10px;
|
||||
|
||||
.jenkins-search {
|
||||
margin-inline: -0.25rem;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.app-builds-container {
|
||||
transition: opacity var(--standard-transition);
|
||||
|
||||
&__items {
|
||||
margin-bottom: -0.5rem;
|
||||
}
|
||||
|
||||
&__placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
padding: 3rem;
|
||||
animation: fade-in-builds-placeholder var(--standard-transition);
|
||||
|
||||
@keyframes fade-in-builds-placeholder {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__heading {
|
||||
display: flex;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-color-secondary);
|
||||
margin-top: 10px;
|
||||
font-weight: 450;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
&__controls {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 15px;
|
||||
margin: 0 -0.35rem;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: -0.5rem;
|
||||
|
||||
.jenkins-button {
|
||||
padding: 10px;
|
||||
|
||||
svg {
|
||||
transition: translate var(--standard-transition);
|
||||
}
|
||||
|
||||
&:first-of-type {
|
||||
justify-content: start;
|
||||
|
||||
&:hover {
|
||||
translate: -2px 0;
|
||||
|
||||
svg {
|
||||
translate: -4px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
justify-content: end;
|
||||
|
||||
&:hover {
|
||||
translate: 2px 0;
|
||||
|
||||
svg {
|
||||
translate: 4px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-builds-container__button--disabled {
|
||||
color: var(--text-color-secondary) !important;
|
||||
opacity: 0.25;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
&--loading {
|
||||
opacity: 0.4;
|
||||
filter: blur(0.5px);
|
||||
}
|
||||
}
|
||||
|
||||
.app-builds-container__item {
|
||||
@include mixins.item();
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
gap: 0.5rem 0.65rem;
|
||||
padding: 0 0 0.25rem;
|
||||
margin: 0 -0.5rem;
|
||||
font-size: 0.8125rem !important;
|
||||
min-height: 2rem;
|
||||
|
||||
&__icon {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
padding: 0 0 0 0.5rem;
|
||||
margin-top: 0.385rem;
|
||||
|
||||
svg {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.app-builds-container__item__inner {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&__link {
|
||||
display: flex;
|
||||
color: var(--text-color);
|
||||
gap: 0.5rem;
|
||||
text-decoration: none;
|
||||
font-weight: 450;
|
||||
flex-grow: 1;
|
||||
padding: 0.45rem 0 0;
|
||||
|
||||
.app-builds-container__item__time {
|
||||
color: var(--text-color-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
&__controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
}
|
||||
|
||||
&--not-interactable {
|
||||
cursor: default;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.app-builds-container__item__description {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.jenkins-jumplist-link {
|
||||
margin-top: 0.2rem;
|
||||
padding-right: 0.8rem;
|
||||
}
|
||||
|
||||
&__description {
|
||||
color: var(--text-color-secondary);
|
||||
padding-left: 2.25rem;
|
||||
margin-top: -2px;
|
||||
grid-column: 1 / span 2;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 17px;
|
||||
top: 34px;
|
||||
bottom: 6px;
|
||||
width: 2px;
|
||||
background: var(--text-color-secondary);
|
||||
border-radius: 10px;
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2220,35 +2220,6 @@ function toQueryString(params) {
|
|||
return query;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function getElementOverflowParams(element) {
|
||||
// First we force it to wrap so we can get those dimension.
|
||||
// Then we force it to "nowrap", so we can get those dimension.
|
||||
// We can then compare the two sets, which will indicate if
|
||||
// wrapping is potentially happening, or not.
|
||||
|
||||
// Force it to wrap.
|
||||
element.classList.add("force-wrap");
|
||||
var wrappedClientWidth = element.clientWidth;
|
||||
var wrappedClientHeight = element.clientHeight;
|
||||
element.classList.remove("force-wrap");
|
||||
|
||||
// Force it to nowrap. Return the comparisons.
|
||||
element.classList.add("force-nowrap");
|
||||
var nowrapClientHeight = element.clientHeight;
|
||||
try {
|
||||
var overflowParams = {
|
||||
element: element,
|
||||
clientWidth: wrappedClientWidth,
|
||||
scrollWidth: element.scrollWidth,
|
||||
isOverflowed: wrappedClientHeight > nowrapClientHeight,
|
||||
};
|
||||
return overflowParams;
|
||||
} finally {
|
||||
element.classList.remove("force-nowrap");
|
||||
}
|
||||
}
|
||||
|
||||
// get the cascaded computed style value. 'a' is the style name like 'backgroundColor'
|
||||
function getStyle(e, a) {
|
||||
if (document.defaultView && document.defaultView.getComputedStyle) {
|
||||
|
|
|
@ -50,8 +50,8 @@ module.exports = (env, argv) => ({
|
|||
"components/row-selection-controller": [
|
||||
path.join(__dirname, "src/main/js/components/row-selection-controller"),
|
||||
],
|
||||
"filter-build-history": [
|
||||
path.join(__dirname, "src/main/js/filter-build-history.js"),
|
||||
"pages/project/builds-card": [
|
||||
path.join(__dirname, "src/main/js/pages/project/builds-card.js"),
|
||||
],
|
||||
"simple-page": [path.join(__dirname, "src/main/scss/simple-page.scss")],
|
||||
styles: [path.join(__dirname, "src/main/scss/styles.scss")],
|
||||
|
|
Loading…
Reference in New Issue