Merge branch 'master' into add-groups-to-command-palette

This commit is contained in:
Jan Faracik 2025-02-17 20:59:02 +00:00 committed by GitHub
commit 7b527340a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 614 additions and 88 deletions

View File

@ -36,6 +36,7 @@ import hudson.console.ConsoleAnnotatorFactory;
import hudson.init.InitMilestone;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.Actionable;
import hudson.model.Computer;
import hudson.model.Describable;
import hudson.model.Descriptor;
@ -167,6 +168,9 @@ import jenkins.model.Jenkins;
import jenkins.model.ModelObjectWithChildren;
import jenkins.model.ModelObjectWithContextMenu;
import jenkins.model.SimplePageDecorator;
import jenkins.model.details.Detail;
import jenkins.model.details.DetailFactory;
import jenkins.model.details.DetailGroup;
import jenkins.util.SystemProperties;
import org.apache.commons.jelly.JellyContext;
import org.apache.commons.jelly.JellyTagException;
@ -2586,6 +2590,33 @@ public class Functions {
return String.valueOf(Math.floor(Math.random() * 3000));
}
/**
* Returns a grouped list of Detail objects for the given Actionable object
*/
@Restricted(NoExternalUse.class)
public static Map<DetailGroup, List<Detail>> getDetailsFor(Actionable object) {
ExtensionList<DetailGroup> groupsExtensionList = ExtensionList.lookup(DetailGroup.class);
List<ExtensionComponent<DetailGroup>> components = groupsExtensionList.getComponents();
Map<String, Double> detailGroupOrdinal = components.stream()
.collect(Collectors.toMap(
(k) -> k.getInstance().getClass().getName(),
ExtensionComponent::ordinal
));
Map<DetailGroup, List<Detail>> result = new TreeMap<>(Comparator.comparingDouble(d -> detailGroupOrdinal.get(d.getClass().getName())));
for (DetailFactory taf : DetailFactory.factoriesFor(object.getClass())) {
List<Detail> details = taf.createFor(object);
details.forEach(e -> result.computeIfAbsent(e.getGroup(), k -> new ArrayList<>()).add(e));
}
for (Map.Entry<DetailGroup, List<Detail>> entry : result.entrySet()) {
List<Detail> detailList = entry.getValue();
detailList.sort(Comparator.comparingInt(Detail::getOrder));
}
return result;
}
@Restricted(NoExternalUse.class)
public static ExtensionList<SearchFactory> getSearchFactories() {
return SearchFactory.all();

View File

@ -40,6 +40,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.AbortException;
import hudson.BulkChange;
import hudson.EnvVars;
import hudson.Extension;
import hudson.ExtensionList;
import hudson.ExtensionPoint;
import hudson.FeedAdapter;
@ -120,6 +121,10 @@ import jenkins.model.Jenkins;
import jenkins.model.JenkinsLocationConfiguration;
import jenkins.model.RunAction2;
import jenkins.model.StandardArtifactManager;
import jenkins.model.details.Detail;
import jenkins.model.details.DetailFactory;
import jenkins.model.details.DurationDetail;
import jenkins.model.details.TimestampDetail;
import jenkins.model.lazy.BuildReference;
import jenkins.model.lazy.LazyBuildMixIn;
import jenkins.security.MasterToSlaveCallable;
@ -2669,4 +2674,17 @@ public abstract class Run<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
out.flush();
}
}
@Extension
public static final class BasicRunDetailFactory extends DetailFactory<Run> {
@Override
public Class<Run> type() {
return Run.class;
}
@NonNull @Override public List<? extends Detail> createFor(@NonNull Run target) {
return List.of(new TimestampDetail(target), new DurationDetail(target));
}
}
}

View File

@ -0,0 +1,68 @@
package jenkins.model.details;
import edu.umd.cs.findbugs.annotations.Nullable;
import hudson.model.Actionable;
import hudson.model.ModelObject;
import hudson.model.Run;
import org.jenkins.ui.icon.IconSpec;
/**
* {@link Detail} represents a piece of information about a {@link Run}.
* Such information could include:
* <ul>
* <li>the date and time the run started</li>
* <li>the amount of time the run took to complete</li>
* <li>SCM information for the build</li>
* <li>who kicked the build off</li>
* </ul>
* @since TODO
*/
public abstract class Detail implements ModelObject, IconSpec {
private final Actionable object;
public Detail(Actionable object) {
this.object = object;
}
public Actionable getObject() {
return object;
}
/**
* {@inheritDoc}
*/
public @Nullable String getIconClassName() {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public @Nullable String getDisplayName() {
return null;
}
/**
* Optional URL for the {@link Detail}.
* If provided the detail element will be a link instead of plain text.
*/
public @Nullable String getLink() {
return null;
}
/**
* @return the grouping of the detail
*/
public DetailGroup getGroup() {
return GeneralDetailGroup.get();
}
/**
* @return order in the group, zero is first, MAX_VALUE is any order
*/
public int getOrder() {
return Integer.MAX_VALUE;
}
}

View File

@ -0,0 +1,57 @@
/*
* The MIT License
*
* Copyright 2025 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.
*/
package jenkins.model.details;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.ExtensionList;
import hudson.ExtensionPoint;
import hudson.model.Actionable;
import java.util.ArrayList;
import java.util.List;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
/**
* Allows you to add multiple details to an Actionable object at once.
* @param <T> the type of object to add to; typically an {@link Actionable} subtype
* @since TODO
*/
public abstract class DetailFactory<T extends Actionable> implements ExtensionPoint {
public abstract Class<T> type();
public abstract @NonNull List<? extends Detail> createFor(@NonNull T target);
@Restricted(NoExternalUse.class)
public static <T extends Actionable> List<DetailFactory<T>> factoriesFor(Class<T> type) {
List<DetailFactory<T>> result = new ArrayList<>();
for (DetailFactory<T> wf : ExtensionList.lookup(DetailFactory.class)) {
if (wf.type().isAssignableFrom(type)) {
result.add(wf);
}
}
return result;
}
}

View File

@ -0,0 +1,6 @@
package jenkins.model.details;
/**
* Represents a group for categorizing {@link Detail}
*/
public abstract class DetailGroup {}

View File

@ -0,0 +1,13 @@
package jenkins.model.details;
import hudson.model.Run;
/**
* Displays the duration of the given run, or, if the run has completed, shows the total time it took to execute
*/
public class DurationDetail extends Detail {
public DurationDetail(Run<?, ?> run) {
super(run);
}
}

View File

@ -0,0 +1,12 @@
package jenkins.model.details;
import hudson.Extension;
import hudson.ExtensionList;
@Extension
public class GeneralDetailGroup extends DetailGroup {
public static GeneralDetailGroup get() {
return ExtensionList.lookupSingleton(GeneralDetailGroup.class);
}
}

View File

@ -0,0 +1,13 @@
package jenkins.model.details;
import hudson.model.Run;
/**
* Displays the start time of the given run
*/
public class TimestampDetail extends Detail {
public TimestampDetail(Run<?, ?> run) {
super(run);
}
}

View File

@ -24,12 +24,14 @@ THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:i="jelly:fmt">
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:x="jelly:xml">
<l:layout title="${it.fullDisplayName}">
<st:include page="sidepanel.jelly" />
<!-- no need for additional breadcrumb here as we're on an index page already including breadcrumb -->
<l:main-panel>
<script src="${resURL}/jsbundles/pages/job.js" type="text/javascript" defer="true" />
<j:set var="controls">
<t:editDescriptionButton permission="${it.UPDATE}"/>
<l:hasPermission permission="${it.UPDATE}">
@ -37,32 +39,40 @@ THE SOFTWARE.
</l:hasPermission>
</j:set>
<t:buildCaption controls="${controls}">${it.displayName} (<i:formatDate value="${it.timestamp.time}" type="both" dateStyle="medium" timeStyle="medium"/>)</t:buildCaption>
<t:buildCaption controls="${controls}">${it.displayName}</t:buildCaption>
<div>
<t:editableDescription permission="${it.UPDATE}" hideButton="true"/>
</div>
<div class="app-build__grid">
<st:include page="console.jelly" from="${h.getConsoleProviderFor(it)}" optional="true" />
<div style="float:right; z-index: 1; position:relative; margin-left: 1em">
<div style="margin-top:1em">
${%startedAgo(it.timestampString)}
<l:card title="${%Details}">
<div class="jenkins-card__details">
<j:forEach var="group" items="${h.getDetailsFor(it)}" indexVar="index">
<j:if test="${index gt 0}">
<hr />
</j:if>
<j:forEach var="detail" items="${group.value}">
<st:include page="detail.jelly" it="${detail}" optional="true">
<x:element name="${detail.link != null ? 'a' : 'div'}">
<x:attribute name="class">jenkins-card__details__item</x:attribute>
<x:attribute name="href">${detail.link}</x:attribute>
<div class="jenkins-card__details__item__icon">
<l:icon src="${detail.iconClassName}" />
</div>
${detail.displayName}
</x:element>
</st:include>
</j:forEach>
</j:forEach>
</div>
</l:card>
<l:card title="Summary">
<div>
<j:if test="${it.building}">
${%beingExecuted(it.executor.timestampString)}
</j:if>
<j:if test="${!it.building}">
${%Took} <a href="${rootURL}/${it.parent.url}buildTimeTrend">${it.durationString}</a>
</j:if>
<st:include page="details.jelly" optional="true" />
</div>
</div>
<table>
<t:artifactList build="${it}" caption="${%Build Artifacts}"
permission="${it.ARTIFACTS}" />
<t:artifactList build="${it}" caption="${%Build Artifacts}" permission="${it.ARTIFACTS}" />
<!-- give actions a chance to contribute summary item -->
<j:forEach var="a" items="${it.allActions}">
@ -73,6 +83,9 @@ THE SOFTWARE.
</table>
<st:include page="main.jelly" optional="true" />
</div>
</l:card>
</div>
</l:main-panel>
</l:layout>
</j:jelly>

View File

@ -0,0 +1,47 @@
<!--
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:l="/lib/layout" xmlns:t="/lib/hudson">
<j:set var="object" value="${it.object}" />
<div class="jenkins-card__details__item">
<div class="jenkins-card__details__item__icon">
<l:icon src="symbol-timer" />
</div>
<div>
<j:choose>
<j:when test="${object.building}">
${%beingExecuted(object.executor.timestampString)}
</j:when>
<j:otherwise>
${%Took} ${object.durationString}
</j:otherwise>
</j:choose>
<j:if test="${!empty(app.nodes) or (object.builtOnStr != null and object.builtOnStr != '')}">
${%on} <t:node value="${object.builtOn}" valueStr="${object.builtOnStr}"/>
</j:if>
<st:include page="details.jelly" optional="true" />
</div>
</div>
</j:jelly>

View File

@ -0,0 +1,23 @@
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
#
# 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.
beingExecuted=Build has been executing for {0}

View File

@ -0,0 +1,46 @@
<!--
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:i="jelly:fmt">
<j:set var="object" value="${it.getObject()}" />
<i:formatDate var="tooltip" value="${object.timestamp.time}" type="both" dateStyle="long" timeStyle="medium" />
<div class="jenkins-card__details__item">
<j:set var="minutes" value="${360 * (object.timestamp.time.minutes / 60)}" />
<i:formatDate var="hours" value="${object.timestamp.time}" pattern="h" />
<j:set var="hours" value="${360 * (hours / 12) + (30 * (object.timestamp.time.minutes / 60))}" />
<div class="jenkins-card__details__item__icon">
<div class="app-build__clock" style="--hours: ${hours}deg; --minutes: ${minutes}deg">
<span class="app-build__clock__hours" />
<span class="app-build__clock__minutes" />
</div>
</div>
<span tooltip="${tooltip}" data-tooltip-delay="500">
${%startedAgo(object.timestampString)}
</span>
</div>
</j:jelly>

View File

@ -0,0 +1,23 @@
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
#
# 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.
startedAgo=Started {0} ago

View File

@ -39,16 +39,16 @@
"mini-css-extract-plugin": "2.9.2",
"postcss": "8.5.2",
"postcss-loader": "8.1.1",
"postcss-preset-env": "10.1.3",
"postcss-preset-env": "10.1.4",
"postcss-scss": "4.0.9",
"prettier": "3.5.0",
"sass": "1.84.0",
"prettier": "3.5.1",
"sass": "1.85.0",
"sass-loader": "16.0.4",
"style-loader": "4.0.0",
"stylelint": "16.14.1",
"stylelint-checkstyle-reporter": "1.0.0",
"stylelint-config-standard-scss": "14.0.0",
"webpack": "5.97.1",
"webpack": "5.98.0",
"webpack-cli": "6.0.1",
"webpack-remove-empty-scripts": "1.0.4"
},

View File

@ -20,6 +20,7 @@ function registerTooltip(element) {
const tooltip = element.getAttribute("tooltip");
const htmlTooltip = element.getAttribute("data-html-tooltip");
const delay = element.getAttribute("data-tooltip-delay") || 0;
let appendTo = document.body;
if (element.hasAttribute("data-tooltip-append-to-parent")) {
appendTo = "parent";
@ -44,6 +45,7 @@ function registerTooltip(element) {
instance.reference.setAttribute("title", instance.props.content);
},
appendTo: appendTo,
delay: [delay, null],
},
TOOLTIP_BASE,
),
@ -63,6 +65,7 @@ function registerTooltip(element) {
"true";
},
appendTo: appendTo,
delay: [delay, null],
},
TOOLTIP_BASE,
),

View File

@ -1,4 +1,5 @@
$card-padding: 1rem;
$icon-size: 1.375rem;
.jenkins-card {
position: relative;
@ -100,4 +101,41 @@ $card-padding: 1rem;
opacity: 0.5;
}
}
hr {
align-self: stretch;
border: none;
border-top: var(--card-border-width) solid var(--text-color-secondary);
opacity: 0.1;
margin: 0;
}
}
.jenkins-card__details {
display: flex;
flex-direction: column;
align-items: start;
gap: 0.75rem;
}
.jenkins-card__details__item {
display: grid;
grid-template-columns: auto 1fr;
gap: 0.75rem;
font-weight: normal;
&__icon {
display: flex;
align-items: center;
justify-content: center;
align-self: start;
width: $icon-size;
height: 1lh;
svg {
width: $icon-size;
height: $icon-size;
color: var(--text-color);
}
}
}

View File

@ -1,3 +1,5 @@
@use "../base/breakpoints";
.build-caption-progress-container {
display: flex;
align-items: center;
@ -6,9 +8,141 @@
gap: 10px;
}
.app-build__grid {
gap: calc(var(--section-padding) / 2);
margin-bottom: var(--section-padding);
.jenkins-card {
margin-bottom: 0; // Remove when .jenkins-card no longer has a default margin
}
@media (width < 1000px) {
display: flex;
flex-direction: column;
grid-template-columns: 1fr 1fr;
.jenkins-card__content {
max-height: 300px;
}
}
@media (width >= 1000px) {
display: grid;
justify-content: stretch;
grid-template-columns: 1fr 1fr;
margin-top: calc(var(--section-padding) * -0.25);
.jenkins-card {
overflow: clip;
margin-bottom: 0; // Remove when .jenkins-card no longer has a default margin
&:first-of-type {
grid-column: span 2;
}
&:last-of-type {
grid-column: span 2;
}
}
.jenkins-card__content {
height: 300px;
}
}
@media (width >= 1300px) {
grid-template-columns: 1fr 1fr 1fr;
.jenkins-card {
&:first-of-type {
grid-column: span 2;
}
&:last-of-type {
grid-column: span 3;
}
}
}
@media (width >= 1600px) {
grid-template-columns: 1fr 1fr 1fr 1fr;
.jenkins-card {
&:first-of-type {
grid-column: span 3;
}
&:last-of-type {
grid-column: span 4;
}
}
}
@media (width >= 1900px) {
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
.jenkins-card {
&:first-of-type {
grid-column: span 3;
}
&:last-of-type {
grid-column: span 5;
}
}
}
}
.app-build__clock {
position: relative;
width: 1.5rem;
height: 1.5rem;
flex-shrink: 0;
scale: 0.75;
&__hours,
&__minutes {
position: absolute;
inset: 0;
border-radius: 100%;
&::after {
content: "";
position: absolute;
bottom: 11px;
left: 11px;
width: 2px;
background: currentColor;
border-radius: 2px;
}
}
&__hours {
rotate: var(--hours);
&::after {
height: 6px;
}
}
&__minutes {
rotate: var(--minutes);
&::after {
height: 8px;
}
}
&::after {
position: absolute;
content: "";
inset: 0;
border-radius: 100%;
border: 2px solid currentColor;
}
}
.app-console-output-widget {
min-height: 340px;
max-height: 340px;
overflow-y: auto;
margin: 0 -1rem -1rem;
padding: 0 1rem 1rem;

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><path d="M112.91 128A191.85 191.85 0 0064 254c-1.18 106.35 85.65 193.8 192 194 106.2.2 192-85.83 192-192 0-104.54-83.55-189.61-187.5-192a4.36 4.36 0 00-4.5 4.37V152" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path d="M233.38 278.63l-79-113a8.13 8.13 0 0111.32-11.32l113 79a32.5 32.5 0 01-37.25 53.26 33.21 33.21 0 01-8.07-7.94z" fill="currentColor" /></svg>

After

Width:  |  Height:  |  Size: 493 B

View File

@ -1331,12 +1331,12 @@ __metadata:
languageName: node
linkType: hard
"@csstools/postcss-initial@npm:^2.0.0":
version: 2.0.0
resolution: "@csstools/postcss-initial@npm:2.0.0"
"@csstools/postcss-initial@npm:^2.0.1":
version: 2.0.1
resolution: "@csstools/postcss-initial@npm:2.0.1"
peerDependencies:
postcss: ^8.4
checksum: 10c0/44c443cba84cc66367f2082bf20db06c8437338c02c244c38798c5bf5342932d89fed0dd13e4409f084ecf7fce47ae6394e9a7a006fd98a973decfa24ab1eb04
checksum: 10c0/dbff7084ef4f1c4647efe2b147001daf172003c15b5e22689f0540d03c8d362f2a332cd9cf136e6c8dcda7564ee30492a4267ea188f72cb9c1000fb9bcfbfef8
languageName: node
linkType: hard
@ -2199,7 +2199,7 @@ __metadata:
languageName: node
linkType: hard
"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9":
"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.9":
version: 7.0.15
resolution: "@types/json-schema@npm:7.0.15"
checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db
@ -2482,15 +2482,6 @@ __metadata:
languageName: node
linkType: hard
"ajv-keywords@npm:^3.5.2":
version: 3.5.2
resolution: "ajv-keywords@npm:3.5.2"
peerDependencies:
ajv: ^6.9.1
checksum: 10c0/0c57a47cbd656e8cdfd99d7c2264de5868918ffa207c8d7a72a7f63379d4333254b2ba03d69e3c035e996a3fd3eb6d5725d7a1597cca10694296e32510546360
languageName: node
linkType: hard
"ajv-keywords@npm:^5.1.0":
version: 5.1.0
resolution: "ajv-keywords@npm:5.1.0"
@ -2502,7 +2493,7 @@ __metadata:
languageName: node
linkType: hard
"ajv@npm:^6.12.4, ajv@npm:^6.12.5":
"ajv@npm:^6.12.4":
version: 6.12.6
resolution: "ajv@npm:6.12.6"
dependencies:
@ -2763,7 +2754,7 @@ __metadata:
languageName: node
linkType: hard
"browserslist@npm:^4.0.0, browserslist@npm:^4.23.1, browserslist@npm:^4.23.3, browserslist@npm:^4.24.0, browserslist@npm:^4.24.3":
"browserslist@npm:^4.0.0, browserslist@npm:^4.23.3, browserslist@npm:^4.24.0, browserslist@npm:^4.24.3, browserslist@npm:^4.24.4":
version: 4.24.4
resolution: "browserslist@npm:4.24.4"
dependencies:
@ -4415,10 +4406,10 @@ __metadata:
mini-css-extract-plugin: "npm:2.9.2"
postcss: "npm:8.5.2"
postcss-loader: "npm:8.1.1"
postcss-preset-env: "npm:10.1.3"
postcss-preset-env: "npm:10.1.4"
postcss-scss: "npm:4.0.9"
prettier: "npm:3.5.0"
sass: "npm:1.84.0"
prettier: "npm:3.5.1"
sass: "npm:1.85.0"
sass-loader: "npm:16.0.4"
sortablejs: "npm:1.15.6"
style-loader: "npm:4.0.0"
@ -4426,7 +4417,7 @@ __metadata:
stylelint-checkstyle-reporter: "npm:1.0.0"
stylelint-config-standard-scss: "npm:14.0.0"
tippy.js: "npm:6.3.7"
webpack: "npm:5.97.1"
webpack: "npm:5.98.0"
webpack-cli: "npm:6.0.1"
webpack-remove-empty-scripts: "npm:1.0.4"
window-handle: "npm:1.0.1"
@ -5941,9 +5932,9 @@ __metadata:
languageName: node
linkType: hard
"postcss-preset-env@npm:10.1.3":
version: 10.1.3
resolution: "postcss-preset-env@npm:10.1.3"
"postcss-preset-env@npm:10.1.4":
version: 10.1.4
resolution: "postcss-preset-env@npm:10.1.4"
dependencies:
"@csstools/postcss-cascade-layers": "npm:^5.0.1"
"@csstools/postcss-color-function": "npm:^4.0.7"
@ -5955,7 +5946,7 @@ __metadata:
"@csstools/postcss-gradients-interpolation-method": "npm:^5.0.7"
"@csstools/postcss-hwb-function": "npm:^4.0.7"
"@csstools/postcss-ic-unit": "npm:^4.0.0"
"@csstools/postcss-initial": "npm:^2.0.0"
"@csstools/postcss-initial": "npm:^2.0.1"
"@csstools/postcss-is-pseudo-class": "npm:^5.0.1"
"@csstools/postcss-light-dark-function": "npm:^2.0.7"
"@csstools/postcss-logical-float-and-clear": "npm:^3.0.0"
@ -5978,7 +5969,7 @@ __metadata:
"@csstools/postcss-trigonometric-functions": "npm:^4.0.6"
"@csstools/postcss-unset-value": "npm:^4.0.0"
autoprefixer: "npm:^10.4.19"
browserslist: "npm:^4.23.1"
browserslist: "npm:^4.24.4"
css-blank-pseudo: "npm:^7.0.1"
css-has-pseudo: "npm:^7.0.2"
css-prefers-color-scheme: "npm:^10.0.0"
@ -6010,7 +6001,7 @@ __metadata:
postcss-selector-not: "npm:^8.0.1"
peerDependencies:
postcss: ^8.4
checksum: 10c0/0ae02015ad3ac69e8ef26afc1a06cb9fbb400104eca5c69a4baa20925e06364712f05b5d87ec9cf9445256e62344e6c2bad8d261a09b35a0e982e055564e3ba8
checksum: 10c0/bd3ad0a32fa30e53f4fdfb980b77d4e86a53ad40681dd8f7d2d9fb00728730b426cd7d039b57f0849261014e4c9e5a55f72edfda1c70165c96a52f246d273ebb
languageName: node
linkType: hard
@ -6161,12 +6152,12 @@ __metadata:
languageName: node
linkType: hard
"prettier@npm:3.5.0":
version: 3.5.0
resolution: "prettier@npm:3.5.0"
"prettier@npm:3.5.1":
version: 3.5.1
resolution: "prettier@npm:3.5.1"
bin:
prettier: bin/prettier.cjs
checksum: 10c0/6c355d74c377f5622953229d92477e8b9779162e848db90fd7e06c431deb73585d31fafc4516cf5868917825b97b9ec7c87c8d8b8e03ccd9fc9c0b7699d1a650
checksum: 10c0/9f6f810eae455d6e4213845151a484a2338f2e0d6a8b84ee8e13a83af8a2421ef6c1e31e61e4b135671fb57b9541f6624648880cc2061ac803e243ac898c0123
languageName: node
linkType: hard
@ -6440,9 +6431,9 @@ __metadata:
languageName: node
linkType: hard
"sass@npm:1.84.0":
version: 1.84.0
resolution: "sass@npm:1.84.0"
"sass@npm:1.85.0":
version: 1.85.0
resolution: "sass@npm:1.85.0"
dependencies:
"@parcel/watcher": "npm:^2.4.1"
chokidar: "npm:^4.0.0"
@ -6453,18 +6444,7 @@ __metadata:
optional: true
bin:
sass: sass.js
checksum: 10c0/4af28c12416b6f1fec2423677cfa8c48af7fb7652a50bd076e0cdd1ea260f0330948ddd6075368a734b8d6cfa16c9af5518292181334f47a9471cb542599bc7b
languageName: node
linkType: hard
"schema-utils@npm:^3.2.0":
version: 3.3.0
resolution: "schema-utils@npm:3.3.0"
dependencies:
"@types/json-schema": "npm:^7.0.8"
ajv: "npm:^6.12.5"
ajv-keywords: "npm:^3.5.2"
checksum: 10c0/fafdbde91ad8aa1316bc543d4b61e65ea86970aebbfb750bfb6d8a6c287a23e415e0e926c2498696b242f63af1aab8e585252637fabe811fd37b604351da6500
checksum: 10c0/a1af0c0596ae1904f66337d0c70a684db6e12210f97be4326cc3dcf18b0f956d7bc45ab2bcc7a8422d433d3eb3c9cb2cc8e60b2dafbdd01fb1ae5a23f5424690
languageName: node
linkType: hard
@ -6947,7 +6927,7 @@ __metadata:
languageName: node
linkType: hard
"terser-webpack-plugin@npm:^5.3.10":
"terser-webpack-plugin@npm:^5.3.11":
version: 5.3.11
resolution: "terser-webpack-plugin@npm:5.3.11"
dependencies:
@ -7174,9 +7154,9 @@ __metadata:
languageName: node
linkType: hard
"webpack@npm:5.97.1":
version: 5.97.1
resolution: "webpack@npm:5.97.1"
"webpack@npm:5.98.0":
version: 5.98.0
resolution: "webpack@npm:5.98.0"
dependencies:
"@types/eslint-scope": "npm:^3.7.7"
"@types/estree": "npm:^1.0.6"
@ -7196,9 +7176,9 @@ __metadata:
loader-runner: "npm:^4.2.0"
mime-types: "npm:^2.1.27"
neo-async: "npm:^2.6.2"
schema-utils: "npm:^3.2.0"
schema-utils: "npm:^4.3.0"
tapable: "npm:^2.1.1"
terser-webpack-plugin: "npm:^5.3.10"
terser-webpack-plugin: "npm:^5.3.11"
watchpack: "npm:^2.4.1"
webpack-sources: "npm:^3.2.3"
peerDependenciesMeta:
@ -7206,7 +7186,7 @@ __metadata:
optional: true
bin:
webpack: bin/webpack.js
checksum: 10c0/a12d3dc882ca582075f2c4bd88840be8307427245c90a8a0e0b372d73560df13fcf25a61625c9e7edc964981d16b5a8323640562eb48347cf9dd2f8bd1b39d35
checksum: 10c0/bee4fa77f444802f0beafb2ff30eb5454a606163ad7d3cc9a5dcc9d24033c62407bed04601b25dea49ea3969b352c1b530a86c753246f42560a4a084eefb094e
languageName: node
linkType: hard