diff --git a/src/dashboard/Settings/Modals/editParseVersionModal.react.js b/src/dashboard/Settings/Modals/editParseVersionModal.react.js index 9e76e957ed..23a776f45b 100644 --- a/src/dashboard/Settings/Modals/editParseVersionModal.react.js +++ b/src/dashboard/Settings/Modals/editParseVersionModal.react.js @@ -16,6 +16,9 @@ export const EditParseVersionModal = ({ context, setParentState, currentParseVer const [dropdownOpen, setDropdownOpen] = useState(false); const [note, setNote] = useState(''); const [noteColor, setNoteColor] = useState('red'); + const [migrationLinks, setMigrationLinks] = useState([]); + + const isGDPR = !!(context && context.custom && context.custom.isGDPR); const parseDependencies = (deps) => { if (!deps) { @@ -66,7 +69,7 @@ export const EditParseVersionModal = ({ context, setParentState, currentParseVer useEffect(() => { setProcessing(true); - context.supportedParseServerVersionsForApp() + const versionsPromise = context.supportedParseServerVersionsForApp() .then((data) => { const versions = Array.isArray(data) ? data : (data.results || []); setParseVersions(versions); @@ -77,13 +80,28 @@ export const EditParseVersionModal = ({ context, setParentState, currentParseVer setNote(e.error || 'Failed to load versions'); console.log('e', e); setNoteColor('red'); + }); + + // Migration links are best-effort: if they fail we still show the version picker. + const linksPromise = context.parseServerMigrationLinks() + .then((data) => { + const links = Array.isArray(data) ? data : (data?.results || []); + setMigrationLinks(links); }) - .finally(() => setProcessing(false)); + .catch(() => { + setMigrationLinks([]); + }); + + Promise.all([versionsPromise, linksPromise]).finally(() => setProcessing(false)); }, []); const npmModules = parseDependencies(selectedVersion?.dependencies ?? selectedVersion?.npmModules); const hasSelectedVersion = !!selectedVersion?.version; + const visibleMigrations = isGDPR + ? [] + : (migrationLinks || []).filter((m) => m && m.link && m.version !== selectedVersion?.version); + const close = () => setParentState({ showEditParseVersionModal: false }); const save = async () => { @@ -126,6 +144,44 @@ export const EditParseVersionModal = ({ context, setParentState, currentParseVer
+ {visibleMigrations.length > 0 && ( +
+ {visibleMigrations.map((m) => ( +
+
+ + Upgrade to the latest Parse Server + + + + +
+ {m.description && ( +

{m.description}

+ )} +
+ ))} +
+ )}
diff --git a/src/dashboard/Settings/Modals/editParseVersionModal.scss b/src/dashboard/Settings/Modals/editParseVersionModal.scss index 5b30321785..a5b2d7a63f 100644 --- a/src/dashboard/Settings/Modals/editParseVersionModal.scss +++ b/src/dashboard/Settings/Modals/editParseVersionModal.scss @@ -227,3 +227,59 @@ font-size: 14px; } +/* Migration scheduling callouts */ +.migrationCard { + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 12px; +} + +.migrationItem { + background: $white; + border: 1px solid rgba($dark, 0.15); + border-radius: 8px; + padding: 12px 16px; +} + +.migrationHead { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.migrationTitle { + @include InterFont; + font-size: 14px; + font-weight: 500; + color: $dark; + line-height: 1.3; +} + +.migrationLink { + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + width: 24px; + height: 24px; + border-radius: 50%; + + &:hover { + cursor: pointer; + } + + &:focus { + outline: none; + } +} + +.migrationDescription { + @include InterFont; + font-size: 10px; + color: rgba($dark, 0.65); + margin: 6px 0 0; + line-height: 1.45; +} + diff --git a/src/lib/ParseApp.js b/src/lib/ParseApp.js index 7a64a239dd..9443288c8b 100644 --- a/src/lib/ParseApp.js +++ b/src/lib/ParseApp.js @@ -451,6 +451,11 @@ export default class ParseApp { return AJAX.get(path); } + parseServerMigrationLinks() { + const path = `/parse-version/links/${this.slug}`; + return AJAX.get(path); + } + changeParseServerVersion(parseVersion) { const path = `/parse-version/${this.slug}/`; return AJAX.post(path, { parseVersion });