@peers-app/peers-ui 0.18.3 → 0.18.4
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.
- package/dist/screens/packages/package-info.js +1 -1
- package/dist/screens/packages/package-list.js +1 -1
- package/dist/screens/packages/package-versions.js +30 -7
- package/package.json +3 -3
- package/src/screens/packages/package-info.tsx +1 -1
- package/src/screens/packages/package-list.tsx +1 -1
- package/src/screens/packages/package-versions.tsx +30 -7
|
@@ -106,7 +106,7 @@ const PackageInfo = (props) => {
|
|
|
106
106
|
peers_sdk_1.rpcServerCalls.openPackage(localPath || peers_sdk_1.packagesRootDir);
|
|
107
107
|
}, children: "Open Local" })] })] }), (0, jsx_runtime_1.jsx)("input", { type: "text", className: "form-control mb-3 p-0 ps-2", placeholder: "~/peers/packages/my-package", value: localPath || "", onChange: (e) => setLocalPath(e.target.value) })] }), remoteRepoUrl ? ((0, jsx_runtime_1.jsxs)("div", { className: "mt-2", children: [(0, jsx_runtime_1.jsxs)("small", { children: ["Source URL:", (0, jsx_runtime_1.jsxs)("small", { children: [(0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: `The remote source of this package. Often a github repository URL or a link to the Peers page for the package.` }), (0, jsx_runtime_1.jsx)("button", { className: "btn btn-sm btn-link", onClick: () => {
|
|
108
108
|
peers_sdk_1.rpcServerCalls.openLinkInBrowser(remoteRepoUrl);
|
|
109
|
-
}, children: "Open Remote" })] })] }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: pkg.qs.remoteRepo, className: "form-control mb-3 p-0 ps-2", disabled: true })] })) : null, (0, jsx_runtime_1.jsxs)("div", { className: "mt-2", children: [(0, jsx_runtime_1.jsx)("hr", {}), (0, jsx_runtime_1.jsxs)("small", { children: ["Version:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: "The currently active version of this package. Manage versions in the Versions tab." })] }), activeVersion ? ((0, jsx_runtime_1.jsxs)("div", { className: "d-flex align-items-center mt-1 mb-3", children: [(0, jsx_runtime_1.jsxs)("strong", { className: "me-2", children: ["v", activeVersion.version] }), activeVersion.versionTag && ((0, jsx_runtime_1.jsx)("span", { className: `badge ${activeVersion.versionTag.startsWith("beta") ? "text-bg-warning" : "text-bg-
|
|
109
|
+
}, children: "Open Remote" })] })] }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: pkg.qs.remoteRepo, className: "form-control mb-3 p-0 ps-2", disabled: true })] })) : null, (0, jsx_runtime_1.jsxs)("div", { className: "mt-2", children: [(0, jsx_runtime_1.jsx)("hr", {}), (0, jsx_runtime_1.jsxs)("small", { children: ["Version:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: "The currently active version of this package. Manage versions in the Versions tab." })] }), activeVersion ? ((0, jsx_runtime_1.jsxs)("div", { className: "d-flex align-items-center mt-1 mb-3", children: [(0, jsx_runtime_1.jsxs)("strong", { className: "me-2", children: ["v", activeVersion.version] }), activeVersion.versionTag && ((0, jsx_runtime_1.jsx)("span", { className: `badge ${activeVersion.versionTag === "dev" ? "text-bg-danger" : activeVersion.versionTag.startsWith("beta") ? "text-bg-warning" : "text-bg-success"} me-2`, children: activeVersion.versionTag })), (0, jsx_runtime_1.jsx)("code", { className: "text-muted small me-2", children: activeVersion.packageVersionHash?.substring(0, 8) }), newerLevel === "uptodate" ? ((0, jsx_runtime_1.jsx)("span", { className: "badge text-bg-success", children: "Up to date" })) : newerLevel ? ((0, jsx_runtime_1.jsxs)("span", { className: `badge text-bg-${newerLevel === "major" ? "danger" : newerLevel === "minor" ? "warning" : "info"}`, children: ["Newer ", newerLevel, " version available"] })) : null] })) : ((0, jsx_runtime_1.jsx)("div", { className: "text-muted small mt-1 mb-3", children: "No active version" })), (0, jsx_runtime_1.jsxs)("div", { className: "mb-3", children: [(0, jsx_runtime_1.jsxs)("small", { children: ["Auto-Update Range:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: "Controls which new versions are auto-activated. **Pinned** = never auto-update. **Patch** = same major.minor (e.g. 1.2.x). **Minor** = same major (e.g. 1.x.x). **Latest** = always auto-update to newest." })] }), (0, jsx_runtime_1.jsxs)("select", { className: "form-select form-select-sm", value: versionFollowRange || "latest", onChange: (e) => {
|
|
110
110
|
const val = e.target.value;
|
|
111
111
|
pkg.versionFollowRange = val === "latest" ? undefined : val;
|
|
112
112
|
}, children: [(0, jsx_runtime_1.jsx)("option", { value: "latest", children: "Latest (auto-update to newest)" }), (0, jsx_runtime_1.jsx)("option", { value: "minor", children: "Minor (same major version)" }), (0, jsx_runtime_1.jsx)("option", { value: "patch", children: "Patch (same major.minor version)" }), (0, jsx_runtime_1.jsx)("option", { value: "pinned", children: "Pinned (no auto-updates)" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: `mb-3 ${isPinned ? "opacity-50" : ""}`, children: [(0, jsx_runtime_1.jsxs)("small", { children: ["Follow Version Tags:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: "Which version tags to auto-activate. Leave empty for **current** (follows the active version's tag). Use `*` for any tag, or a comma-separated list like `stable,prod`." })] }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: pkg.qs.followVersionTags, className: "form-control form-control-sm p-0 ps-2", placeholder: `Following "${activeVersion?.versionTag || "stable"}"`, disabled: isPinned })] }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-2", children: [(0, jsx_runtime_1.jsxs)("small", { children: ["Device-Specific Version Tag:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: "Override the tag policy for this device only. For example, set to `beta` to test pre-release versions on this device without affecting other devices or group members. This is not synced." })] }), (0, jsx_runtime_1.jsxs)("div", { className: "d-flex align-items-center gap-2", children: [(0, jsx_runtime_1.jsx)("input", { type: "text", className: "form-control form-control-sm p-0 ps-2", placeholder: "e.g. beta", value: deviceTagDraft, onChange: (e) => setDeviceTagDraft(e.target.value) }), deviceTagDraft && ((0, jsx_runtime_1.jsx)("button", { className: "btn btn-sm btn-outline-secondary", title: "Clear device tag override", onClick: () => setDeviceTagDraft(""), children: (0, jsx_runtime_1.jsx)("i", { className: "bi bi-x-lg" }) }))] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-2", children: [(0, jsx_runtime_1.jsx)("hr", {}), (0, jsx_runtime_1.jsxs)("small", { children: ["Description:", (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { markdownContent: `This should be edited in the package's README.md. It will automatically update when you restart Peers or reload the package.` })] }), (0, jsx_runtime_1.jsx)(markdown_with_mentions_1.MarkdownWithMentions, { content: pkg.description || "" })] })] }));
|
|
@@ -55,7 +55,7 @@ const PackageVersionBadge = ({ activePackageVersionId, packageId, followVersionT
|
|
|
55
55
|
if (!data)
|
|
56
56
|
return null;
|
|
57
57
|
const { pv, newerLevel } = data;
|
|
58
|
-
return ((0, jsx_runtime_1.jsxs)("span", { className: "ms-2", children: [(0, jsx_runtime_1.jsxs)("small", { className: "text-muted", children: ["v", pv.version] }), pv.versionTag && ((0, jsx_runtime_1.jsx)("span", { className: `badge ms-1 ${pv.versionTag.startsWith("beta") ? "text-bg-warning" : "text-bg-
|
|
58
|
+
return ((0, jsx_runtime_1.jsxs)("span", { className: "ms-2", children: [(0, jsx_runtime_1.jsxs)("small", { className: "text-muted", children: ["v", pv.version] }), pv.versionTag && ((0, jsx_runtime_1.jsx)("span", { className: `badge ms-1 ${pv.versionTag === "dev" ? "text-bg-danger" : pv.versionTag.startsWith("beta") ? "text-bg-warning" : "text-bg-success"}`, style: { fontSize: "0.65em" }, children: pv.versionTag })), newerLevel ? ((0, jsx_runtime_1.jsxs)("span", { className: `badge ms-1 text-bg-${newerLevel === "major" ? "danger" : newerLevel === "minor" ? "warning" : "info"}`, style: { fontSize: "0.65em" }, children: [newerLevel, " update"] })) : ((0, jsx_runtime_1.jsx)("span", { className: "badge ms-1 text-bg-success", style: { fontSize: "0.65em" }, children: "up to date" }))] }));
|
|
59
59
|
};
|
|
60
60
|
const PackageList = () => {
|
|
61
61
|
const [searchTextObs] = (0, react_1.useState)(() => (0, peers_sdk_1.observable)(""));
|
|
@@ -30,10 +30,12 @@ function formatDate(iso) {
|
|
|
30
30
|
function tagBadgeClass(tag) {
|
|
31
31
|
if (!tag)
|
|
32
32
|
return "text-bg-secondary";
|
|
33
|
+
if (tag === "dev")
|
|
34
|
+
return "text-bg-danger";
|
|
33
35
|
if (tag.startsWith("beta"))
|
|
34
36
|
return "text-bg-warning";
|
|
35
37
|
if (tag === "stable")
|
|
36
|
-
return "text-bg-
|
|
38
|
+
return "text-bg-success";
|
|
37
39
|
return "text-bg-secondary";
|
|
38
40
|
}
|
|
39
41
|
const PackageVersionsList = (props) => {
|
|
@@ -106,8 +108,16 @@ const PackageVersionsList = (props) => {
|
|
|
106
108
|
}
|
|
107
109
|
async function promoteVersion(pv, newTag) {
|
|
108
110
|
try {
|
|
111
|
+
const me = await (0, peers_sdk_1.getMe)();
|
|
112
|
+
const history = [...(pv.history ?? [])];
|
|
113
|
+
history.push({
|
|
114
|
+
action: `promoted:${newTag}`,
|
|
115
|
+
by: me.userId,
|
|
116
|
+
at: new Date().toISOString(),
|
|
117
|
+
signature: "",
|
|
118
|
+
});
|
|
109
119
|
const pvHash = (0, peers_sdk_1.computePackageVersionHash)(pv.version, newTag, pv.packageBundleFileHash, pv.routesBundleFileHash, pv.uiBundleFileHash);
|
|
110
|
-
const updated = { ...pv, versionTag: newTag, packageVersionHash: pvHash };
|
|
120
|
+
const updated = { ...pv, versionTag: newTag, packageVersionHash: pvHash, history };
|
|
111
121
|
await (0, peers_sdk_1.PackageVersions)().signAndSave(updated, { saveAsSnapshot: true });
|
|
112
122
|
refreshKey(refreshKey() + 1);
|
|
113
123
|
}
|
|
@@ -117,7 +127,7 @@ const PackageVersionsList = (props) => {
|
|
|
117
127
|
}
|
|
118
128
|
async function updateVersion(pv, newSemver) {
|
|
119
129
|
try {
|
|
120
|
-
const pvHash = (0, peers_sdk_1.computePackageVersionHash)(newSemver, pv.versionTag || "
|
|
130
|
+
const pvHash = (0, peers_sdk_1.computePackageVersionHash)(newSemver, pv.versionTag || "dev", pv.packageBundleFileHash, pv.routesBundleFileHash, pv.uiBundleFileHash);
|
|
121
131
|
const updated = { ...pv, version: newSemver, packageVersionHash: pvHash };
|
|
122
132
|
await (0, peers_sdk_1.PackageVersions)().signAndSave(updated, { saveAsSnapshot: true });
|
|
123
133
|
refreshKey(refreshKey() + 1);
|
|
@@ -153,7 +163,20 @@ const PackageVersionsList = (props) => {
|
|
|
153
163
|
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("small", { className: "text-muted", children: [sorted.length, " version", sorted.length !== 1 ? "s" : ""] }), (0, jsx_runtime_1.jsx)("div", { className: "list-group mt-2", children: sorted.map((pv) => ((0, jsx_runtime_1.jsx)(VersionRow, { pv: pv, isActive: pv.packageVersionId === activeVersionId, isPinned: isPinned, pinning: pinning, activating: activating, deleting: deleting, userMap: userMap, onActivate: activateVersion, onDelete: deleteVersion, onPin: pinVersion, onPromote: promoteVersion, onUpdateVersion: updateVersion }, pv.packageVersionId))) })] }));
|
|
154
164
|
};
|
|
155
165
|
exports.PackageVersionsList = PackageVersionsList;
|
|
156
|
-
|
|
166
|
+
/**
|
|
167
|
+
* Valid promotion targets for each version tag. Promotion only moves forward:
|
|
168
|
+
* dev -> beta -> stable. No demotions allowed.
|
|
169
|
+
*/
|
|
170
|
+
function getPromoteTargets(currentTag) {
|
|
171
|
+
switch (currentTag) {
|
|
172
|
+
case "dev":
|
|
173
|
+
return ["beta", "stable"];
|
|
174
|
+
case "beta":
|
|
175
|
+
return ["stable"];
|
|
176
|
+
default:
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
157
180
|
function VersionRow(props) {
|
|
158
181
|
const { pv, isActive, isPinned, pinning, activating, deleting, userMap } = props;
|
|
159
182
|
const creatorName = userMap.get(pv.createdBy);
|
|
@@ -170,12 +193,12 @@ function VersionRow(props) {
|
|
|
170
193
|
}
|
|
171
194
|
setEditingVersion(false);
|
|
172
195
|
}
|
|
173
|
-
const currentTag = pv.versionTag || "
|
|
174
|
-
const promoteTargets =
|
|
196
|
+
const currentTag = pv.versionTag || "dev";
|
|
197
|
+
const promoteTargets = getPromoteTargets(currentTag);
|
|
175
198
|
return ((0, jsx_runtime_1.jsx)("div", { className: `list-group-item ${isActive ? "list-group-item-success" : ""}`, children: (0, jsx_runtime_1.jsxs)("div", { className: "d-flex align-items-center justify-content-between", children: [(0, jsx_runtime_1.jsxs)("div", { className: "d-flex align-items-center flex-wrap", children: [editingVersion ? ((0, jsx_runtime_1.jsx)("input", { type: "text", className: "form-control form-control-sm me-2", style: { width: "7em" }, value: versionDraft, onChange: (e) => setVersionDraft(e.target.value), onBlur: commitVersion, onKeyDown: (e) => {
|
|
176
199
|
if (e.key === "Enter")
|
|
177
200
|
commitVersion();
|
|
178
201
|
if (e.key === "Escape")
|
|
179
202
|
setEditingVersion(false);
|
|
180
|
-
} })) : ((0, jsx_runtime_1.jsxs)("strong", { className: "me-2", style: { cursor: "pointer" }, onClick: startEditing, title: "Click to edit version", children: ["v", pv.version] })), pv.versionTag && ((0, jsx_runtime_1.jsx)("span", { className: `badge ${tagBadgeClass(pv.versionTag)} me-2`, children: pv.versionTag })), (0, jsx_runtime_1.jsx)("code", { className: "text-muted small me-2", children: pv.packageVersionHash?.substring(0, 8) }), (0, jsx_runtime_1.jsx)("small", { className: "text-muted me-2", children: formatDate(pv.createdAt) }), creatorName && (0, jsx_runtime_1.jsxs)("small", { className: "text-muted", children: ["by ", creatorName] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "d-flex gap-1 align-items-center", children: [promoteTargets.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "dropdown", children: [(0, jsx_runtime_1.jsx)("button", { className: "btn btn-sm btn-outline-info dropdown-toggle", "data-bs-toggle": "dropdown", title: "Change version tag", children: "Promote" }), (0, jsx_runtime_1.jsx)("ul", { className: "dropdown-menu dropdown-menu-end", children: promoteTargets.map((tag) => ((0, jsx_runtime_1.jsx)("li", { children: (0, jsx_runtime_1.jsxs)("button", { className: "dropdown-item", onClick: () => props.onPromote(pv, tag), children: [currentTag, " \u2192 ", tag] }) }, tag))) })] })), isActive ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { className: "btn btn-sm btn-outline-secondary", disabled: isPinned || pinning, onClick: () => props.onPin(), title: isPinned ? "Already pinned" : "Pin to this version (disable auto-updates)", children: [pinning ? ((0, jsx_runtime_1.jsx)("span", { className: "spinner-border spinner-border-sm" })) : ((0, jsx_runtime_1.jsx)("i", { className: "bi bi-pin-fill" })), isPinned ? " Pinned" : " Pin"] }), (0, jsx_runtime_1.jsx)("span", { className: "badge text-bg-
|
|
203
|
+
} })) : ((0, jsx_runtime_1.jsxs)("strong", { className: "me-2", style: { cursor: "pointer" }, onClick: startEditing, title: "Click to edit version", children: ["v", pv.version] })), pv.versionTag && ((0, jsx_runtime_1.jsx)("span", { className: `badge ${tagBadgeClass(pv.versionTag)} me-2`, children: pv.versionTag })), (0, jsx_runtime_1.jsx)("code", { className: "text-muted small me-2", children: pv.packageVersionHash?.substring(0, 8) }), (0, jsx_runtime_1.jsx)("small", { className: "text-muted me-2", children: formatDate(pv.createdAt) }), creatorName && (0, jsx_runtime_1.jsxs)("small", { className: "text-muted", children: ["by ", creatorName] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "d-flex gap-1 align-items-center", children: [promoteTargets.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "dropdown", children: [(0, jsx_runtime_1.jsx)("button", { className: "btn btn-sm btn-outline-info dropdown-toggle", "data-bs-toggle": "dropdown", title: "Change version tag", children: "Promote" }), (0, jsx_runtime_1.jsx)("ul", { className: "dropdown-menu dropdown-menu-end", children: promoteTargets.map((tag) => ((0, jsx_runtime_1.jsx)("li", { children: (0, jsx_runtime_1.jsxs)("button", { className: "dropdown-item", onClick: () => props.onPromote(pv, tag), children: [currentTag, " \u2192 ", tag] }) }, tag))) })] })), isActive ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { className: "btn btn-sm btn-outline-secondary", disabled: isPinned || pinning, onClick: () => props.onPin(), title: isPinned ? "Already pinned" : "Pin to this version (disable auto-updates)", children: [pinning ? ((0, jsx_runtime_1.jsx)("span", { className: "spinner-border spinner-border-sm" })) : ((0, jsx_runtime_1.jsx)("i", { className: "bi bi-pin-fill" })), isPinned ? " Pinned" : " Pin"] }), (0, jsx_runtime_1.jsx)("span", { className: "badge text-bg-info align-self-center", children: "active" })] })) : ((0, jsx_runtime_1.jsxs)("button", { className: "btn btn-sm btn-outline-primary", disabled: activating === pv.packageVersionId, onClick: () => props.onActivate(pv), children: [activating === pv.packageVersionId ? ((0, jsx_runtime_1.jsx)("span", { className: "spinner-border spinner-border-sm me-1" })) : ((0, jsx_runtime_1.jsx)("i", { className: "bi bi-check2-circle me-1" })), "Activate"] })), !isActive && ((0, jsx_runtime_1.jsx)("button", { className: "btn btn-sm btn-outline-danger", disabled: deleting === pv.packageVersionId, onClick: () => props.onDelete(pv), children: deleting === pv.packageVersionId ? ((0, jsx_runtime_1.jsx)("span", { className: "spinner-border spinner-border-sm" })) : ((0, jsx_runtime_1.jsx)("i", { className: "bi bi-trash" })) }))] })] }) }));
|
|
181
204
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peers-app/peers-ui",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.4",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/peers-app/peers-ui.git"
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"lint:fix": "biome check --write ."
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@peers-app/peers-sdk": "^0.18.
|
|
31
|
+
"@peers-app/peers-sdk": "^0.18.4",
|
|
32
32
|
"bootstrap": "^5.3.3",
|
|
33
33
|
"react": "^18.0.0",
|
|
34
34
|
"react-dom": "^18.0.0"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@babel/preset-env": "^7.24.5",
|
|
40
40
|
"@babel/preset-react": "^7.24.1",
|
|
41
41
|
"@babel/preset-typescript": "^7.27.1",
|
|
42
|
-
"@peers-app/peers-sdk": "0.18.
|
|
42
|
+
"@peers-app/peers-sdk": "0.18.4",
|
|
43
43
|
"@testing-library/dom": "^10.4.0",
|
|
44
44
|
"@testing-library/jest-dom": "^6.6.3",
|
|
45
45
|
"@testing-library/react": "^16.3.0",
|
|
@@ -189,7 +189,7 @@ export const PackageInfo = (props: {
|
|
|
189
189
|
<strong className="me-2">v{activeVersion.version}</strong>
|
|
190
190
|
{activeVersion.versionTag && (
|
|
191
191
|
<span
|
|
192
|
-
className={`badge ${activeVersion.versionTag.startsWith("beta") ? "text-bg-warning" : "text-bg-
|
|
192
|
+
className={`badge ${activeVersion.versionTag === "dev" ? "text-bg-danger" : activeVersion.versionTag.startsWith("beta") ? "text-bg-warning" : "text-bg-success"} me-2`}
|
|
193
193
|
>
|
|
194
194
|
{activeVersion.versionTag}
|
|
195
195
|
</span>
|
|
@@ -80,7 +80,7 @@ const PackageVersionBadge = ({
|
|
|
80
80
|
<small className="text-muted">v{pv.version}</small>
|
|
81
81
|
{pv.versionTag && (
|
|
82
82
|
<span
|
|
83
|
-
className={`badge ms-1 ${pv.versionTag.startsWith("beta") ? "text-bg-warning" : "text-bg-
|
|
83
|
+
className={`badge ms-1 ${pv.versionTag === "dev" ? "text-bg-danger" : pv.versionTag.startsWith("beta") ? "text-bg-warning" : "text-bg-success"}`}
|
|
84
84
|
style={{ fontSize: "0.65em" }}
|
|
85
85
|
>
|
|
86
86
|
{pv.versionTag}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computePackageVersionHash,
|
|
3
|
+
getMe,
|
|
3
4
|
type IDoc,
|
|
4
5
|
type IPackage,
|
|
5
6
|
type IPackageVersion,
|
|
@@ -30,8 +31,9 @@ function formatDate(iso: string): string {
|
|
|
30
31
|
|
|
31
32
|
function tagBadgeClass(tag?: string): string {
|
|
32
33
|
if (!tag) return "text-bg-secondary";
|
|
34
|
+
if (tag === "dev") return "text-bg-danger";
|
|
33
35
|
if (tag.startsWith("beta")) return "text-bg-warning";
|
|
34
|
-
if (tag === "stable") return "text-bg-
|
|
36
|
+
if (tag === "stable") return "text-bg-success";
|
|
35
37
|
return "text-bg-secondary";
|
|
36
38
|
}
|
|
37
39
|
|
|
@@ -106,6 +108,14 @@ export const PackageVersionsList = (props: { pkg: IDoc<IPackage> }) => {
|
|
|
106
108
|
|
|
107
109
|
async function promoteVersion(pv: IPackageVersion, newTag: string) {
|
|
108
110
|
try {
|
|
111
|
+
const me = await getMe();
|
|
112
|
+
const history = [...(pv.history ?? [])];
|
|
113
|
+
history.push({
|
|
114
|
+
action: `promoted:${newTag}`,
|
|
115
|
+
by: me.userId,
|
|
116
|
+
at: new Date().toISOString(),
|
|
117
|
+
signature: "",
|
|
118
|
+
});
|
|
109
119
|
const pvHash = computePackageVersionHash(
|
|
110
120
|
pv.version,
|
|
111
121
|
newTag,
|
|
@@ -113,7 +123,7 @@ export const PackageVersionsList = (props: { pkg: IDoc<IPackage> }) => {
|
|
|
113
123
|
pv.routesBundleFileHash,
|
|
114
124
|
pv.uiBundleFileHash,
|
|
115
125
|
);
|
|
116
|
-
const updated = { ...pv, versionTag: newTag, packageVersionHash: pvHash };
|
|
126
|
+
const updated = { ...pv, versionTag: newTag, packageVersionHash: pvHash, history };
|
|
117
127
|
await PackageVersions().signAndSave(updated, { saveAsSnapshot: true });
|
|
118
128
|
refreshKey(refreshKey() + 1);
|
|
119
129
|
} catch (err) {
|
|
@@ -125,7 +135,7 @@ export const PackageVersionsList = (props: { pkg: IDoc<IPackage> }) => {
|
|
|
125
135
|
try {
|
|
126
136
|
const pvHash = computePackageVersionHash(
|
|
127
137
|
newSemver,
|
|
128
|
-
pv.versionTag || "
|
|
138
|
+
pv.versionTag || "dev",
|
|
129
139
|
pv.packageBundleFileHash,
|
|
130
140
|
pv.routesBundleFileHash,
|
|
131
141
|
pv.uiBundleFileHash,
|
|
@@ -201,7 +211,20 @@ export const PackageVersionsList = (props: { pkg: IDoc<IPackage> }) => {
|
|
|
201
211
|
);
|
|
202
212
|
};
|
|
203
213
|
|
|
204
|
-
|
|
214
|
+
/**
|
|
215
|
+
* Valid promotion targets for each version tag. Promotion only moves forward:
|
|
216
|
+
* dev -> beta -> stable. No demotions allowed.
|
|
217
|
+
*/
|
|
218
|
+
function getPromoteTargets(currentTag?: string): string[] {
|
|
219
|
+
switch (currentTag) {
|
|
220
|
+
case "dev":
|
|
221
|
+
return ["beta", "stable"];
|
|
222
|
+
case "beta":
|
|
223
|
+
return ["stable"];
|
|
224
|
+
default:
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
205
228
|
|
|
206
229
|
function VersionRow(props: {
|
|
207
230
|
pv: IPackageVersion;
|
|
@@ -235,8 +258,8 @@ function VersionRow(props: {
|
|
|
235
258
|
setEditingVersion(false);
|
|
236
259
|
}
|
|
237
260
|
|
|
238
|
-
const currentTag = pv.versionTag || "
|
|
239
|
-
const promoteTargets =
|
|
261
|
+
const currentTag = pv.versionTag || "dev";
|
|
262
|
+
const promoteTargets = getPromoteTargets(currentTag);
|
|
240
263
|
|
|
241
264
|
return (
|
|
242
265
|
<div className={`list-group-item ${isActive ? "list-group-item-success" : ""}`}>
|
|
@@ -308,7 +331,7 @@ function VersionRow(props: {
|
|
|
308
331
|
)}
|
|
309
332
|
{isPinned ? " Pinned" : " Pin"}
|
|
310
333
|
</button>
|
|
311
|
-
<span className="badge text-bg-
|
|
334
|
+
<span className="badge text-bg-info align-self-center">active</span>
|
|
312
335
|
</>
|
|
313
336
|
) : (
|
|
314
337
|
<button
|