packer (WIP)

This commit is contained in:
bQUARKz 2026-03-20 04:57:42 +00:00
parent 83546149e4
commit 66375aaa86
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
4 changed files with 518 additions and 0 deletions

View File

@ -249,6 +249,42 @@ public enum I18n {
ASSETS_RELOCATE_WIZARD_ERROR_OUTSIDE_ASSETS("assets.relocateWizard.error.outsideAssets"),
ASSETS_RELOCATE_WIZARD_ERROR_TARGET_ALREADY_ASSET("assets.relocateWizard.error.targetAlreadyAsset"),
ASSETS_RELOCATE_WIZARD_ERROR_TARGET_SAME("assets.relocateWizard.error.targetSame"),
ASSETS_PACK_WIZARD_TITLE("assets.packWizard.title"),
ASSETS_PACK_WIZARD_STEP_SUMMARY_TITLE("assets.packWizard.step.summary.title"),
ASSETS_PACK_WIZARD_STEP_SUMMARY_DESCRIPTION("assets.packWizard.step.summary.description"),
ASSETS_PACK_WIZARD_STEP_VALIDATION_TITLE("assets.packWizard.step.validation.title"),
ASSETS_PACK_WIZARD_STEP_VALIDATION_DESCRIPTION("assets.packWizard.step.validation.description"),
ASSETS_PACK_WIZARD_STEP_PACKING_TITLE("assets.packWizard.step.packing.title"),
ASSETS_PACK_WIZARD_STEP_PACKING_DESCRIPTION("assets.packWizard.step.packing.description"),
ASSETS_PACK_WIZARD_STEP_RESULT_TITLE("assets.packWizard.step.result.title"),
ASSETS_PACK_WIZARD_STEP_RESULT_DESCRIPTION("assets.packWizard.step.result.description"),
ASSETS_PACK_WIZARD_BUTTON_VALIDATE("assets.packWizard.button.validate"),
ASSETS_PACK_WIZARD_BUTTON_PACK("assets.packWizard.button.pack"),
ASSETS_PACK_WIZARD_BUTTON_CLOSE("assets.packWizard.button.close"),
ASSETS_PACK_WIZARD_BUTTON_COPY_FAILURES("assets.packWizard.button.copyFailures"),
ASSETS_PACK_WIZARD_LOADING_SUMMARY("assets.packWizard.loading.summary"),
ASSETS_PACK_WIZARD_LOADING_VALIDATION("assets.packWizard.loading.validation"),
ASSETS_PACK_WIZARD_LOADING_PACKING("assets.packWizard.loading.packing"),
ASSETS_PACK_WIZARD_LABEL_CANONICAL_ARTIFACT("assets.packWizard.label.canonicalArtifact"),
ASSETS_PACK_WIZARD_LABEL_INCLUDED_ASSETS("assets.packWizard.label.includedAssets"),
ASSETS_PACK_WIZARD_LABEL_OUTSIDE_BUILD_SET("assets.packWizard.label.outsideBuildSet"),
ASSETS_PACK_WIZARD_LABEL_TOTAL_IN_SCOPE("assets.packWizard.label.totalInScope"),
ASSETS_PACK_WIZARD_LABEL_VALID_ASSETS("assets.packWizard.label.validAssets"),
ASSETS_PACK_WIZARD_LABEL_BLOCKED_ASSETS("assets.packWizard.label.blockedAssets"),
ASSETS_PACK_WIZARD_LABEL_STATUS("assets.packWizard.label.status"),
ASSETS_PACK_WIZARD_LABEL_PACKED_ASSETS("assets.packWizard.label.packedAssets"),
ASSETS_PACK_WIZARD_LABEL_ELAPSED("assets.packWizard.label.elapsed"),
ASSETS_PACK_WIZARD_LABEL_EMITTED_ARTIFACTS("assets.packWizard.label.emittedArtifacts"),
ASSETS_PACK_WIZARD_STATUS_READY("assets.packWizard.status.ready"),
ASSETS_PACK_WIZARD_STATUS_BLOCKED("assets.packWizard.status.blocked"),
ASSETS_PACK_WIZARD_STATUS_RUNNING("assets.packWizard.status.running"),
ASSETS_PACK_WIZARD_STATUS_FINISHED("assets.packWizard.status.finished"),
ASSETS_PACK_WIZARD_VALIDATION_EMPTY("assets.packWizard.validation.empty"),
ASSETS_PACK_WIZARD_RESULT_NO_ARTIFACTS("assets.packWizard.result.noArtifacts"),
ASSETS_PACK_WIZARD_RESULT_COPY_FAILURES_HINT("assets.packWizard.result.copyFailuresHint"),
ASSETS_PACK_WIZARD_ERROR_SUMMARY("assets.packWizard.error.summary"),
ASSETS_PACK_WIZARD_ERROR_VALIDATION("assets.packWizard.error.validation"),
ASSETS_PACK_WIZARD_ERROR_PACK("assets.packWizard.error.pack"),
WORKSPACE_DEBUG("workspace.debug"),

View File

@ -18,6 +18,7 @@ import p.studio.workspaces.assets.list.AssetListControl;
import p.studio.workspaces.assets.messages.events.StudioAssetsRefreshRequestedEvent;
import p.studio.workspaces.assets.messages.events.StudioAssetsWorkspaceSelectionRequestedEvent;
import p.studio.workspaces.assets.wizards.AddAssetWizard;
import p.studio.workspaces.assets.wizards.PackWorkspaceWizard;
import java.util.List;
@ -121,6 +122,7 @@ public final class AssetWorkspace extends Workspace {
"studio-button",
"studio-button-secondary",
"assets-workspace-action-button");
packButton.setOnAction(event -> openPackWizard());
return packButton;
}
@ -134,6 +136,13 @@ public final class AssetWorkspace extends Workspace {
});
}
private void openPackWizard() {
if (root.getScene() == null) {
return;
}
PackWorkspaceWizard.showAndWait(root.getScene().getWindow(), projectReference);
}
private SplitPane createAssetSplitPane() {
final var splitPane = new SplitPane(assetListControl, detailsControl);
splitPane.setDividerPositions(0.34);

View File

@ -0,0 +1,437 @@
package p.studio.workspaces.assets.wizards;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
import p.packer.dtos.PackerEmittedArtifactDTO;
import p.packer.dtos.PackerPackValidationAssetDTO;
import p.packer.messages.PackWorkspaceRequest;
import p.packer.messages.PackWorkspaceResult;
import p.packer.messages.PackWorkspaceSummaryRequest;
import p.packer.messages.PackWorkspaceSummaryResult;
import p.packer.messages.PackerOperationStatus;
import p.packer.messages.ValidatePackWorkspaceRequest;
import p.packer.messages.ValidatePackWorkspaceResult;
import p.studio.Container;
import p.studio.projects.ProjectReference;
import p.studio.utilities.i18n.I18n;
import p.studio.workspaces.assets.details.AssetDetailsUiSupport;
import java.util.List;
import java.util.Objects;
public final class PackWorkspaceWizard {
private enum Phase {
SUMMARY,
VALIDATION,
PACKING,
RESULT
}
private final ProjectReference projectReference;
private final Stage stage;
private final Label stepTitle = new Label();
private final Label stepDescription = new Label();
private final VBox stepBody = new VBox(12);
private final Label feedbackLabel = new Label();
private final Button backButton = new Button();
private final Button nextButton = new Button();
private final Button packButton = new Button();
private final Button closeButton = new Button();
private final Button copyFailuresButton = new Button();
private Phase phase = Phase.SUMMARY;
private boolean loadingSummary;
private boolean loadingValidation;
private boolean packing;
private PackWorkspaceSummaryResult summaryResult;
private ValidatePackWorkspaceResult validationResult;
private PackWorkspaceResult packResult;
private PackWorkspaceWizard(Window owner, ProjectReference projectReference) {
this.projectReference = Objects.requireNonNull(projectReference, "projectReference");
this.stage = new Stage();
stage.initOwner(owner);
stage.initModality(Modality.WINDOW_MODAL);
stage.setTitle(Container.i18n().text(I18n.ASSETS_PACK_WIZARD_TITLE));
stage.setScene(new Scene(buildRoot(), 760, 560));
stage.getScene().getStylesheets().add(Container.theme().getDefaultTheme());
stage.setOnCloseRequest(event -> {
if (packing) {
event.consume();
}
});
render();
loadSummary();
}
public static void showAndWait(Window owner, ProjectReference projectReference) {
new PackWorkspaceWizard(owner, projectReference).stage.showAndWait();
}
private VBox buildRoot() {
stepTitle.getStyleClass().add("studio-launcher-section-title");
stepDescription.getStyleClass().add("studio-launcher-subtitle");
feedbackLabel.getStyleClass().add("studio-launcher-feedback");
feedbackLabel.setWrapText(true);
backButton.textProperty().bind(Container.i18n().bind(I18n.WIZARD_BACK));
backButton.getStyleClass().addAll("studio-button", "studio-button-secondary");
backButton.setOnAction(ignored -> goBack());
nextButton.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_BUTTON_VALIDATE));
nextButton.getStyleClass().addAll("studio-button", "studio-button-primary");
nextButton.setOnAction(ignored -> loadValidation());
packButton.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_BUTTON_PACK));
packButton.getStyleClass().addAll("studio-button", "studio-button-primary");
packButton.setOnAction(ignored -> startPack());
copyFailuresButton.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_BUTTON_COPY_FAILURES));
copyFailuresButton.getStyleClass().addAll("studio-button", "studio-button-secondary");
copyFailuresButton.setDisable(true);
closeButton.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_BUTTON_CLOSE));
closeButton.getStyleClass().addAll("studio-button", "studio-button-cancel");
closeButton.setOnAction(ignored -> {
if (!packing) {
stage.close();
}
});
final HBox actions = new HBox(12, backButton, nextButton, packButton, copyFailuresButton, closeButton);
actions.setAlignment(Pos.CENTER_RIGHT);
final VBox root = new VBox(16, stepTitle, stepDescription, stepBody, feedbackLabel, actions);
root.setPadding(new Insets(24));
VBox.setVgrow(stepBody, Priority.ALWAYS);
return root;
}
private void render() {
final boolean busy = loadingSummary || loadingValidation || packing;
backButton.setDisable(busy || phase == Phase.SUMMARY);
nextButton.setVisible(phase == Phase.SUMMARY);
nextButton.setManaged(phase == Phase.SUMMARY);
nextButton.setDisable(busy || summaryResult == null);
packButton.setVisible(phase == Phase.VALIDATION);
packButton.setManaged(phase == Phase.VALIDATION);
packButton.setDisable(busy || validationResult == null || !validationResult.validation().canPack());
copyFailuresButton.setVisible(phase == Phase.RESULT);
copyFailuresButton.setManaged(phase == Phase.RESULT);
switch (phase) {
case SUMMARY -> renderSummaryPhase();
case VALIDATION -> renderValidationPhase();
case PACKING -> renderPackingPhase();
case RESULT -> renderResultPhase();
}
}
private void renderSummaryPhase() {
stepTitle.textProperty().unbind();
stepDescription.textProperty().unbind();
stepTitle.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_SUMMARY_TITLE));
stepDescription.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_SUMMARY_DESCRIPTION));
if (loadingSummary) {
stepBody.getChildren().setAll(createBusyBox(I18n.ASSETS_PACK_WIZARD_LOADING_SUMMARY));
return;
}
if (summaryResult == null) {
stepBody.getChildren().setAll(AssetDetailsUiSupport.createSectionMessage(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_ERROR_SUMMARY)));
return;
}
stepBody.getChildren().setAll(
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_CANONICAL_ARTIFACT),
summaryResult.packSummary().canonicalArtifactName()),
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_INCLUDED_ASSETS),
Integer.toString(summaryResult.packSummary().includedRegisteredAssetCount())),
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_OUTSIDE_BUILD_SET),
Integer.toString(summaryResult.packSummary().outsideBuildSetAssetCount())),
AssetDetailsUiSupport.createSectionMessage(summaryResult.summary()));
}
private void renderValidationPhase() {
stepTitle.textProperty().unbind();
stepDescription.textProperty().unbind();
stepTitle.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_VALIDATION_TITLE));
stepDescription.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_VALIDATION_DESCRIPTION));
if (loadingValidation) {
stepBody.getChildren().setAll(createBusyBox(I18n.ASSETS_PACK_WIZARD_LOADING_VALIDATION));
return;
}
if (validationResult == null) {
stepBody.getChildren().setAll(AssetDetailsUiSupport.createSectionMessage(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_ERROR_VALIDATION)));
return;
}
final VBox content = new VBox(12);
content.getChildren().addAll(
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_TOTAL_IN_SCOPE),
Integer.toString(validationResult.validation().totalAssetsInScope())),
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_VALID_ASSETS),
Integer.toString(validationResult.validation().validAssetCount())),
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_BLOCKED_ASSETS),
Integer.toString(validationResult.validation().blockedAssetCount())),
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_STATUS),
validationResult.validation().canPack()
? Container.i18n().text(I18n.ASSETS_PACK_WIZARD_STATUS_READY)
: Container.i18n().text(I18n.ASSETS_PACK_WIZARD_STATUS_BLOCKED)),
AssetDetailsUiSupport.createSectionMessage(validationResult.summary()));
if (validationResult.assets().isEmpty()) {
content.getChildren().add(AssetDetailsUiSupport.createSectionMessage(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_VALIDATION_EMPTY)));
} else {
final Accordion accordion = new Accordion();
for (PackerPackValidationAssetDTO asset : validationResult.assets()) {
accordion.getPanes().add(createValidationPane(asset));
}
VBox.setVgrow(accordion, Priority.ALWAYS);
content.getChildren().add(accordion);
}
stepBody.getChildren().setAll(content);
}
private TitledPane createValidationPane(PackerPackValidationAssetDTO asset) {
final VBox content = new VBox(8);
content.getChildren().addAll(
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_LABEL_NAME),
asset.asset().identity().assetName()),
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_LABEL_LOCATION),
asset.asset().identity().assetRoot().toString()),
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_STATUS),
asset.blocked()
? Container.i18n().text(I18n.ASSETS_PACK_WIZARD_STATUS_BLOCKED)
: Container.i18n().text(I18n.ASSETS_PACK_WIZARD_STATUS_READY)));
final List<p.packer.dtos.PackerDiagnosticDTO> blockingDiagnostics = asset.diagnostics().stream()
.filter(p.packer.dtos.PackerDiagnosticDTO::blocking)
.toList();
if (blockingDiagnostics.isEmpty()) {
content.getChildren().add(AssetDetailsUiSupport.createSectionMessage(
Container.i18n().text(I18n.ASSETS_DIAGNOSTICS_EMPTY)));
} else {
blockingDiagnostics.forEach(diagnostic -> content.getChildren().add(AssetDetailsUiSupport.createSectionMessage(
diagnostic.severity().name() + ": " + diagnostic.message())));
}
final String title = asset.asset().identity().assetName() + (asset.blocked() ? " (blocked)" : " (ready)");
final TitledPane pane = new TitledPane(title, content);
pane.setExpanded(false);
return pane;
}
private void renderPackingPhase() {
stepTitle.textProperty().unbind();
stepDescription.textProperty().unbind();
stepTitle.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_PACKING_TITLE));
stepDescription.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_PACKING_DESCRIPTION));
stepBody.getChildren().setAll(createBusyBox(I18n.ASSETS_PACK_WIZARD_LOADING_PACKING));
}
private void renderResultPhase() {
stepTitle.textProperty().unbind();
stepDescription.textProperty().unbind();
stepTitle.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_RESULT_TITLE));
stepDescription.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_RESULT_DESCRIPTION));
if (packResult == null) {
stepBody.getChildren().setAll(AssetDetailsUiSupport.createSectionMessage(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_ERROR_PACK)));
return;
}
final VBox content = new VBox(12);
content.getChildren().addAll(
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_STATUS),
switch (packResult.status()) {
case SUCCESS, PARTIAL -> Container.i18n().text(I18n.ASSETS_PACK_WIZARD_STATUS_FINISHED);
case FAILED -> packResult.status().name();
}),
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_CANONICAL_ARTIFACT),
packResult.result().canonicalArtifactName()),
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_PACKED_ASSETS),
Integer.toString(packResult.result().packedAssetCount())),
AssetDetailsUiSupport.createKeyValueRow(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_ELAPSED),
formatElapsed(packResult.result().elapsedMillis())),
AssetDetailsUiSupport.createSectionMessage(packResult.summary()));
if (packResult.result().emittedArtifacts().isEmpty()) {
content.getChildren().add(AssetDetailsUiSupport.createSectionMessage(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_RESULT_NO_ARTIFACTS)));
} else {
final VBox artifacts = new VBox(8);
artifacts.getChildren().add(new Label(Container.i18n().text(I18n.ASSETS_PACK_WIZARD_LABEL_EMITTED_ARTIFACTS)));
for (PackerEmittedArtifactDTO artifact : packResult.result().emittedArtifacts()) {
artifacts.getChildren().add(AssetDetailsUiSupport.createKeyValueRow(
artifact.label(),
artifact.path().toString()));
}
content.getChildren().add(artifacts);
}
content.getChildren().add(AssetDetailsUiSupport.createSectionMessage(
Container.i18n().text(I18n.ASSETS_PACK_WIZARD_RESULT_COPY_FAILURES_HINT)));
stepBody.getChildren().setAll(content);
}
private VBox createBusyBox(I18n messageKey) {
final ProgressIndicator indicator = new ProgressIndicator();
indicator.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
final VBox box = new VBox(16, indicator, AssetDetailsUiSupport.createSectionMessage(
Container.i18n().text(messageKey)));
box.setAlignment(Pos.CENTER_LEFT);
return box;
}
private void goBack() {
if (phase == Phase.VALIDATION && !loadingValidation) {
phase = Phase.SUMMARY;
feedbackLabel.setText("");
render();
}
}
private void loadSummary() {
loadingSummary = true;
feedbackLabel.setText("");
summaryResult = null;
render();
Container.backgroundTasks().submit(() -> {
try {
final PackWorkspaceSummaryResult result = Container.packer().workspaceService().getPackWorkspaceSummary(
new PackWorkspaceSummaryRequest(projectReference.toPackerProjectContext()));
Platform.runLater(() -> applySummaryResult(result));
} catch (RuntimeException exception) {
Platform.runLater(() -> applySummaryFailure(exception));
}
});
}
private void applySummaryResult(PackWorkspaceSummaryResult result) {
loadingSummary = false;
summaryResult = result;
feedbackLabel.setText(result.status() == PackerOperationStatus.FAILED ? result.summary() : "");
render();
}
private void applySummaryFailure(RuntimeException exception) {
loadingSummary = false;
feedbackLabel.setText(extractMessage(exception, I18n.ASSETS_PACK_WIZARD_ERROR_SUMMARY));
render();
}
private void loadValidation() {
if (summaryResult == null || loadingValidation) {
return;
}
phase = Phase.VALIDATION;
loadingValidation = true;
validationResult = null;
feedbackLabel.setText("");
render();
Container.backgroundTasks().submit(() -> {
try {
final ValidatePackWorkspaceResult result = Container.packer().workspaceService().validatePackWorkspace(
new ValidatePackWorkspaceRequest(projectReference.toPackerProjectContext()));
Platform.runLater(() -> applyValidationResult(result));
} catch (RuntimeException exception) {
Platform.runLater(() -> applyValidationFailure(exception));
}
});
}
private void applyValidationResult(ValidatePackWorkspaceResult result) {
loadingValidation = false;
validationResult = result;
if (!result.validation().canPack()) {
feedbackLabel.setText(result.summary());
} else {
feedbackLabel.setText("");
}
render();
}
private void applyValidationFailure(RuntimeException exception) {
loadingValidation = false;
feedbackLabel.setText(extractMessage(exception, I18n.ASSETS_PACK_WIZARD_ERROR_VALIDATION));
render();
}
private void startPack() {
if (validationResult == null || !validationResult.validation().canPack() || packing) {
return;
}
phase = Phase.PACKING;
packing = true;
packResult = null;
feedbackLabel.setText("");
render();
Container.backgroundTasks().submit(() -> {
try {
final PackWorkspaceResult result = Container.packer().workspaceService().packWorkspace(
new PackWorkspaceRequest(projectReference.toPackerProjectContext()));
Platform.runLater(() -> applyPackResult(result));
} catch (RuntimeException exception) {
Platform.runLater(() -> applyPackFailure(exception));
}
});
}
private void applyPackResult(PackWorkspaceResult result) {
packing = false;
packResult = result;
phase = Phase.RESULT;
feedbackLabel.setText(result.status() == PackerOperationStatus.FAILED ? result.summary() : "");
render();
}
private void applyPackFailure(RuntimeException exception) {
packing = false;
phase = Phase.RESULT;
feedbackLabel.setText(extractMessage(exception, I18n.ASSETS_PACK_WIZARD_ERROR_PACK));
render();
}
private String extractMessage(RuntimeException exception, I18n fallbackKey) {
final String message = exception.getMessage();
if (message == null || message.isBlank()) {
return Container.i18n().text(fallbackKey);
}
return message;
}
private String formatElapsed(long elapsedMillis) {
final long seconds = elapsedMillis / 1000L;
final long milliseconds = elapsedMillis % 1000L;
return seconds + "." + String.format("%03d", milliseconds) + "s";
}
}

View File

@ -240,4 +240,40 @@ assets.relocateWizard.error.name=Destination folder name is required.
assets.relocateWizard.error.outsideAssets=The planned target root must stay inside assets/.
assets.relocateWizard.error.targetAlreadyAsset=The planned target root already contains asset.json.
assets.relocateWizard.error.targetSame=The planned target root must differ from the current asset root.
assets.packWizard.title=Pack Workspace
assets.packWizard.step.summary.title=Pack Summary
assets.packWizard.step.summary.description=Review the current build set before validating or packing it.
assets.packWizard.step.validation.title=Validation
assets.packWizard.step.validation.description=Inspect blocking diagnostics for included assets before starting the pack.
assets.packWizard.step.packing.title=Packing
assets.packWizard.step.packing.description=Wait while the packer emits assets.pa and companion artifacts.
assets.packWizard.step.result.title=Pack Result
assets.packWizard.step.result.description=Review the final status returned by the packer.
assets.packWizard.button.validate=Validate
assets.packWizard.button.pack=Pack
assets.packWizard.button.close=Close
assets.packWizard.button.copyFailures=Copy Failure Summary
assets.packWizard.loading.summary=Loading pack summary...
assets.packWizard.loading.validation=Running pack validation...
assets.packWizard.loading.packing=Packing assets...
assets.packWizard.label.canonicalArtifact=Canonical Artifact
assets.packWizard.label.includedAssets=Included Assets
assets.packWizard.label.outsideBuildSet=Outside Build Set
assets.packWizard.label.totalInScope=Assets In Scope
assets.packWizard.label.validAssets=Valid Assets
assets.packWizard.label.blockedAssets=Blocked Assets
assets.packWizard.label.status=Status
assets.packWizard.label.packedAssets=Packed Assets
assets.packWizard.label.elapsed=Elapsed
assets.packWizard.label.emittedArtifacts=Emitted Artifacts
assets.packWizard.status.ready=Ready to pack
assets.packWizard.status.blocked=Validation blocked
assets.packWizard.status.running=Packing in progress
assets.packWizard.status.finished=Packing finished
assets.packWizard.validation.empty=No validation entries are currently available.
assets.packWizard.result.noArtifacts=No emitted artifacts were reported.
assets.packWizard.result.copyFailuresHint=Failure summary export is reserved for a future iteration.
assets.packWizard.error.summary=Unable to load pack summary.
assets.packWizard.error.validation=Unable to validate the current pack set.
assets.packWizard.error.pack=Unable to pack the current build set.
workspace.debug=Debug