Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 58 additions & 2 deletions src/dashboard/Settings/Modals/editParseVersionModal.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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 () => {
Expand Down Expand Up @@ -126,6 +144,44 @@ export const EditParseVersionModal = ({ context, setParentState, currentParseVer
</div>

<div className={styles.modalBody}>
{visibleMigrations.length > 0 && (
<div className={styles.migrationCard}>
{visibleMigrations.map((m) => (
<div key={m.id || m._id || m.version} className={styles.migrationItem}>
<div className={styles.migrationHead}>
<span className={styles.migrationTitle}>
Upgrade to the latest Parse Server
</span>
<a
className={styles.migrationLink}
href={`${m.link}?appId=${context.applicationId}`}
target='_blank'
rel='noopener noreferrer'
aria-label='Schedule migration'
title='Schedule migration'
>
<svg
width='18'
height='18'
viewBox='0 0 24 24'
fill='#27AE60'
aria-hidden='true'
>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M8 1.5a1 1 0 0 1 1 1V4h6V2.5a1 1 0 1 1 2 0V4h1.5A2.5 2.5 0 0 1 21 6.5V9H3V6.5A2.5 2.5 0 0 1 5.5 4H7V2.5a1 1 0 0 1 1-1ZM3 10.5h18v8A2.5 2.5 0 0 1 18.5 21h-13A2.5 2.5 0 0 1 3 18.5v-8ZM7.25 12.5h1.5a.5.5 0 0 1 .5.5v1.5a.5.5 0 0 1-.5.5h-1.5a.5.5 0 0 1-.5-.5v-1.5a.5.5 0 0 1 .5-.5Zm4 0h1.5a.5.5 0 0 1 .5.5v1.5a.5.5 0 0 1-.5.5h-1.5a.5.5 0 0 1-.5-.5v-1.5a.5.5 0 0 1 .5-.5Zm4 0h1.5a.5.5 0 0 1 .5.5v1.5a.5.5 0 0 1-.5.5h-1.5a.5.5 0 0 1-.5-.5v-1.5a.5.5 0 0 1 .5-.5Zm-8 4h1.5a.5.5 0 0 1 .5.5v1.5a.5.5 0 0 1-.5.5h-1.5a.5.5 0 0 1-.5-.5V17a.5.5 0 0 1 .5-.5Zm4 0h1.5a.5.5 0 0 1 .5.5v1.5a.5.5 0 0 1-.5.5h-1.5a.5.5 0 0 1-.5-.5V17a.5.5 0 0 1 .5-.5Zm4 0h1.5a.5.5 0 0 1 .5.5v1.5a.5.5 0 0 1-.5.5h-1.5a.5.5 0 0 1-.5-.5V17a.5.5 0 0 1 .5-.5Z'
/>
</svg>
</a>
</div>
{m.description && (
<p className={styles.migrationDescription}>{m.description}</p>
)}
</div>
))}
</div>
)}
<div className={styles.content}>


Expand Down
56 changes: 56 additions & 0 deletions src/dashboard/Settings/Modals/editParseVersionModal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

5 changes: 5 additions & 0 deletions src/lib/ParseApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand Down
Loading