pandorga 1.4.4 → 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -3
- data/functions/api/studio/_lib/github.js +115 -20
- data/lib/pandorga/version.rb +1 -1
- data/scripts/test/test-studio-api-contract.rb +8 -2
- data/studio/assets/{index-Cf9OPjQU.js → index-OAmrbW7i.js} +60 -60
- data/studio/index.html +1 -1
- data/studio-app/src/api/client.js +6 -4
- data/studio-app/src/main.js +72 -61
- metadata +2 -2
data/studio/index.html
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
rel="stylesheet"
|
|
19
19
|
href="https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.2.3/css/flag-icons.min.css"
|
|
20
20
|
/>
|
|
21
|
-
<script type="module" crossorigin src="/studio/assets/index-
|
|
21
|
+
<script type="module" crossorigin src="/studio/assets/index-OAmrbW7i.js"></script>
|
|
22
22
|
<link rel="stylesheet" crossorigin href="/studio/assets/index-Cd1mlY_H.css">
|
|
23
23
|
</head>
|
|
24
24
|
<body>
|
|
@@ -73,10 +73,12 @@ export const studioApi = {
|
|
|
73
73
|
method: "POST",
|
|
74
74
|
body: JSON.stringify(payload),
|
|
75
75
|
}),
|
|
76
|
-
/** Content-pipeline run for a commit SHA
|
|
77
|
-
pipelineStatus: (sha, workflow = null) => {
|
|
78
|
-
const params = new URLSearchParams(
|
|
76
|
+
/** Content-pipeline run for a commit SHA, or latest on the branch when omitted. */
|
|
77
|
+
pipelineStatus: (sha = null, workflow = null) => {
|
|
78
|
+
const params = new URLSearchParams();
|
|
79
|
+
if (sha) params.set("sha", String(sha));
|
|
79
80
|
if (workflow) params.set("workflow", String(workflow));
|
|
80
|
-
|
|
81
|
+
const q = params.toString();
|
|
82
|
+
return api(q ? `pipeline-status?${q}` : "pipeline-status");
|
|
81
83
|
},
|
|
82
84
|
};
|
data/studio-app/src/main.js
CHANGED
|
@@ -892,7 +892,9 @@ function pipelineChipMeta(pipelineState) {
|
|
|
892
892
|
icon: "cloud_off",
|
|
893
893
|
className: "pipeline-chip pipeline-idle",
|
|
894
894
|
spinning: false,
|
|
895
|
-
title:
|
|
895
|
+
title:
|
|
896
|
+
state.pipeline.message ||
|
|
897
|
+
"Set pandorga.content.workflow in _config.yml (e.g. content-pipeline.yml)",
|
|
896
898
|
};
|
|
897
899
|
default:
|
|
898
900
|
return {
|
|
@@ -940,6 +942,39 @@ function renderPipelineChip() {
|
|
|
940
942
|
);
|
|
941
943
|
}
|
|
942
944
|
|
|
945
|
+
function applyPipelinePayload(data) {
|
|
946
|
+
state.pipeline.runUrl = data.run?.html_url || state.pipeline.runUrl || "";
|
|
947
|
+
if (data.sha) state.pipeline.sha = String(data.sha).toLowerCase();
|
|
948
|
+
state.pipeline.message = "";
|
|
949
|
+
if (data.state === "unconfigured") {
|
|
950
|
+
state.pipeline.state = "unconfigured";
|
|
951
|
+
state.pipeline.message =
|
|
952
|
+
"Set pandorga.content.workflow in _config.yml (e.g. content-pipeline.yml)";
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
state.pipeline.state = data.state || "idle";
|
|
956
|
+
if (data.state === "error") {
|
|
957
|
+
state.pipeline.message = "Content pipeline failed for this commit.";
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
/** Hydrate the always-visible chip from the latest workflow run (or a SHA). */
|
|
962
|
+
async function refreshPipelineStatus(sha = null) {
|
|
963
|
+
if (isLocalDevHost()) return;
|
|
964
|
+
try {
|
|
965
|
+
const data = await studioApi.pipelineStatus(sha || null);
|
|
966
|
+
applyPipelinePayload(data);
|
|
967
|
+
renderShell();
|
|
968
|
+
} catch (err) {
|
|
969
|
+
const code = err?.code || "";
|
|
970
|
+
if (code === "actions_forbidden" || code === "github_unconfigured") {
|
|
971
|
+
state.pipeline.state = "error";
|
|
972
|
+
state.pipeline.message = String(err.message || err);
|
|
973
|
+
renderShell();
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
943
978
|
/**
|
|
944
979
|
* After a production Save, poll Actions for the content-pipeline run on this SHA.
|
|
945
980
|
*/
|
|
@@ -976,32 +1011,17 @@ async function pollPipelineStatus(gen, sha) {
|
|
|
976
1011
|
const data = await studioApi.pipelineStatus(sha);
|
|
977
1012
|
if (gen !== state.pipeline.pollGen) return;
|
|
978
1013
|
softFails = 0;
|
|
979
|
-
|
|
980
|
-
state.pipeline.message = "";
|
|
1014
|
+
applyPipelinePayload(data);
|
|
981
1015
|
|
|
982
|
-
if (data.state === "unconfigured") {
|
|
983
|
-
state.pipeline.state = "unconfigured";
|
|
1016
|
+
if (data.state === "unconfigured" || data.state === "ok" || data.state === "error") {
|
|
984
1017
|
renderShell();
|
|
985
1018
|
return;
|
|
986
1019
|
}
|
|
987
|
-
if (data.state === "
|
|
988
|
-
state.pipeline.state =
|
|
989
|
-
if (data.state === "error") {
|
|
990
|
-
state.pipeline.message = "Content pipeline failed for this commit.";
|
|
991
|
-
}
|
|
1020
|
+
if (data.state === "awaiting_run" && elapsed > STALL_MS) {
|
|
1021
|
+
state.pipeline.state = "stalled";
|
|
992
1022
|
renderShell();
|
|
993
1023
|
return;
|
|
994
1024
|
}
|
|
995
|
-
if (data.state === "running") {
|
|
996
|
-
state.pipeline.state = "running";
|
|
997
|
-
} else if (data.state === "awaiting_run") {
|
|
998
|
-
if (elapsed > STALL_MS) {
|
|
999
|
-
state.pipeline.state = "stalled";
|
|
1000
|
-
renderShell();
|
|
1001
|
-
return;
|
|
1002
|
-
}
|
|
1003
|
-
state.pipeline.state = "awaiting_run";
|
|
1004
|
-
}
|
|
1005
1025
|
renderShell();
|
|
1006
1026
|
} catch (err) {
|
|
1007
1027
|
if (gen !== state.pipeline.pollGen) return;
|
|
@@ -1114,8 +1134,35 @@ function renderStudioToolbar({ brand = null, menuToggle = null } = {}) {
|
|
|
1114
1134
|
: null,
|
|
1115
1135
|
]);
|
|
1116
1136
|
|
|
1117
|
-
const actions = [
|
|
1118
|
-
|
|
1137
|
+
const actions = [renderThemeMenu()];
|
|
1138
|
+
|
|
1139
|
+
// Theme → pipeline/Export → Revert → Save. Pipeline chip is always present.
|
|
1140
|
+
if (isLocalDevHost()) {
|
|
1141
|
+
const exportBusy = state.reexporting || state.pipeline.state === "syncing";
|
|
1142
|
+
actions.push(
|
|
1143
|
+
toolbarActionButton({
|
|
1144
|
+
className:
|
|
1145
|
+
"btn btn-tool btn-reexport" +
|
|
1146
|
+
(exportBusy ? " pipeline-running" : "") +
|
|
1147
|
+
(state.pipeline.state === "ok" && !exportBusy ? " pipeline-ok" : "") +
|
|
1148
|
+
(state.pipeline.state === "error" && !exportBusy ? " pipeline-error" : ""),
|
|
1149
|
+
title: exportBusy
|
|
1150
|
+
? "Exporting content JSON locally"
|
|
1151
|
+
: "Export content JSON locally and reload",
|
|
1152
|
+
ariaLabel: exportBusy ? "Exporting locally" : "Export locally",
|
|
1153
|
+
action: "reexport",
|
|
1154
|
+
disabled: exportBusy,
|
|
1155
|
+
onClick: () => reexportLocalContent(),
|
|
1156
|
+
icon: exportBusy ? "progress_activity" : "sync",
|
|
1157
|
+
label: exportBusy ? "Exporting…" : "Export",
|
|
1158
|
+
spinning: exportBusy,
|
|
1159
|
+
})
|
|
1160
|
+
);
|
|
1161
|
+
} else {
|
|
1162
|
+
actions.push(renderPipelineChip());
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
actions.push(
|
|
1119
1166
|
toolbarActionButton({
|
|
1120
1167
|
className: "btn btn-tool",
|
|
1121
1168
|
title: "Revert all edits to the last loaded or saved version",
|
|
@@ -1140,45 +1187,8 @@ function renderStudioToolbar({ brand = null, menuToggle = null } = {}) {
|
|
|
1140
1187
|
icon: saveIcon,
|
|
1141
1188
|
label: saveLabel,
|
|
1142
1189
|
spinning: state.saving,
|
|
1143
|
-
})
|
|
1144
|
-
|
|
1145
|
-
if (state.file && collectionAllowsDelete()) {
|
|
1146
|
-
actions.push(
|
|
1147
|
-
toolbarActionButton({
|
|
1148
|
-
className: "btn btn-tool btn-danger",
|
|
1149
|
-
title: "Delete this entry from the repository",
|
|
1150
|
-
ariaLabel: "Delete entry",
|
|
1151
|
-
action: "delete",
|
|
1152
|
-
onClick: () => deleteCurrentEntry(),
|
|
1153
|
-
icon: "delete",
|
|
1154
|
-
label: "Delete",
|
|
1155
|
-
})
|
|
1156
|
-
);
|
|
1157
|
-
}
|
|
1158
|
-
if (isLocalDevHost()) {
|
|
1159
|
-
const exportBusy = state.reexporting || state.pipeline.state === "syncing";
|
|
1160
|
-
actions.push(
|
|
1161
|
-
toolbarActionButton({
|
|
1162
|
-
className:
|
|
1163
|
-
"btn btn-tool btn-reexport" +
|
|
1164
|
-
(exportBusy ? " pipeline-running" : "") +
|
|
1165
|
-
(state.pipeline.state === "ok" && !exportBusy ? " pipeline-ok" : "") +
|
|
1166
|
-
(state.pipeline.state === "error" && !exportBusy ? " pipeline-error" : ""),
|
|
1167
|
-
title: exportBusy
|
|
1168
|
-
? "Exporting content JSON locally"
|
|
1169
|
-
: "Export content JSON locally and reload",
|
|
1170
|
-
ariaLabel: exportBusy ? "Exporting locally" : "Export locally",
|
|
1171
|
-
action: "reexport",
|
|
1172
|
-
disabled: exportBusy,
|
|
1173
|
-
onClick: () => reexportLocalContent(),
|
|
1174
|
-
icon: exportBusy ? "progress_activity" : "sync",
|
|
1175
|
-
label: exportBusy ? "Exporting…" : "Export",
|
|
1176
|
-
spinning: exportBusy,
|
|
1177
|
-
})
|
|
1178
|
-
);
|
|
1179
|
-
} else if (state.pipeline.state !== "idle") {
|
|
1180
|
-
actions.push(renderPipelineChip());
|
|
1181
|
-
}
|
|
1190
|
+
})
|
|
1191
|
+
);
|
|
1182
1192
|
|
|
1183
1193
|
const kids = [
|
|
1184
1194
|
brandCluster,
|
|
@@ -4257,6 +4267,7 @@ async function bootApp(clerk) {
|
|
|
4257
4267
|
}
|
|
4258
4268
|
|
|
4259
4269
|
renderShell();
|
|
4270
|
+
void refreshPipelineStatus();
|
|
4260
4271
|
|
|
4261
4272
|
scheduleTreePrefetch();
|
|
4262
4273
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pandorga
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.4.
|
|
4
|
+
version: 1.4.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The Pandorga contributors
|
|
@@ -450,7 +450,7 @@ files:
|
|
|
450
450
|
- studio-app/src/styles/studio.css
|
|
451
451
|
- studio-app/vite.config.js
|
|
452
452
|
- studio/assets/index-Cd1mlY_H.css
|
|
453
|
-
- studio/assets/index-
|
|
453
|
+
- studio/assets/index-OAmrbW7i.js
|
|
454
454
|
- studio/index.html
|
|
455
455
|
- studio/schema.yml
|
|
456
456
|
- templates/articles/README.md
|