mirror of
https://github.com/Kong/insomnia.git
synced 2026-10-25 16:19:20 -04:00
Add option to disable migrating workspaces (#3108)
This commit is contained in:
1 parent
3b81808e1d
commit
6f3d2666f8
5 files changed
+100
-53
No files matched your search
@@ -58,7 +58,7 @@ type DBType = { [string]: Array<BaseModel> };
|
||||
export type MigrationOptions = {
|
||||
useDesignerSettings: boolean,
|
||||
copyPlugins: boolean,
|
||||
copyResponses: boolean,
|
||||
copyWorkspaces: boolean,
|
||||
designerDataDir: string,
|
||||
coreDataDir: string,
|
||||
};
|
||||
@@ -149,13 +149,32 @@ export default async function migrateFromDesigner({
|
||||
designerDataDir,
|
||||
coreDataDir,
|
||||
copyPlugins,
|
||||
copyResponses,
|
||||
copyWorkspaces,
|
||||
}: MigrationOptions): Promise<MigrationResult> {
|
||||
const modelTypesToIgnore = [
|
||||
console.log(
|
||||
`[db-merge] starting process for migrating from ${designerDataDir} to ${coreDataDir}`,
|
||||
);
|
||||
|
||||
const nonWorkspaceModels = [
|
||||
models.stats.type, // TODO: investigate further any implications that may invalidate collected stats
|
||||
models.settings.type,
|
||||
];
|
||||
|
||||
const modelTypesToMerge = difference(models.types(), modelTypesToIgnore);
|
||||
// Every model except those to ignore and settings is a "workspace" model
|
||||
const workspaceModels = difference(models.types(), nonWorkspaceModels);
|
||||
|
||||
const modelTypesToMerge = [];
|
||||
|
||||
if (useDesignerSettings) {
|
||||
modelTypesToMerge.push(models.settings.type);
|
||||
console.log(`[db-merge] keeping settings from Insomnia Designer`);
|
||||
} else {
|
||||
console.log(`[db-merge] keeping settings from Insomnia Core`);
|
||||
}
|
||||
|
||||
if (copyWorkspaces) {
|
||||
modelTypesToMerge.push(...workspaceModels);
|
||||
}
|
||||
|
||||
let backupDir = '';
|
||||
|
||||
@@ -166,36 +185,23 @@ export default async function migrateFromDesigner({
|
||||
// Load designer database
|
||||
const designerDb: DBType = await loadDesignerDb(modelTypesToMerge, designerDataDir);
|
||||
|
||||
// Ensure user is not migrating an existing Insomnia Core repo
|
||||
const designerSettings: Settings = designerDb[models.settings.type][0];
|
||||
if (designerSettings.hasOwnProperty('hasPromptedToMigrateFromDesigner')) {
|
||||
console.log('[db-merge] cannot merge database');
|
||||
return;
|
||||
}
|
||||
|
||||
// For each model, batch upsert entries into the Core database
|
||||
for (const modelType of modelTypesToMerge) {
|
||||
const entries = designerDb[modelType];
|
||||
|
||||
// Decide how to merge settings
|
||||
// Persist some settings from core
|
||||
if (modelType === models.settings.type) {
|
||||
if (useDesignerSettings) {
|
||||
console.log(`[db-merge] keeping settings from Insomnia Designer`);
|
||||
const coreSettings = await models.settings.getOrCreate();
|
||||
const propertiesToPersist = [
|
||||
'_id',
|
||||
'hasPromptedOnboarding',
|
||||
'hasPromptedToMigrateFromDesigner',
|
||||
];
|
||||
propertiesToPersist.forEach(s => {
|
||||
if (coreSettings.hasOwnProperty(s)) {
|
||||
(entries[0]: Settings)[s] = coreSettings[s];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log(`[db-merge] keeping settings from Insomnia Core`);
|
||||
continue;
|
||||
}
|
||||
const coreSettings = await models.settings.getOrCreate();
|
||||
const propertiesToPersist = [
|
||||
'_id',
|
||||
'hasPromptedOnboarding',
|
||||
'hasPromptedToMigrateFromDesigner',
|
||||
];
|
||||
propertiesToPersist.forEach(s => {
|
||||
if (coreSettings.hasOwnProperty(s)) {
|
||||
(entries[0]: Settings)[s] = coreSettings[s];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// For each workspace coming from Designer, mark workspace.scope as 'designer'
|
||||
@@ -212,21 +218,17 @@ export default async function migrateFromDesigner({
|
||||
await db.batchModifyDocs({ upsert: entries, remove: [] });
|
||||
}
|
||||
|
||||
console.log(`[db-merge] migrating version control data from designer to core`);
|
||||
await copyDirs(['version-control'], designerDataDir, coreDataDir);
|
||||
if (copyWorkspaces) {
|
||||
console.log(`[db-merge] migrating version control data from designer to core`);
|
||||
await copyDirs(['version-control'], designerDataDir, coreDataDir);
|
||||
|
||||
if (copyResponses) {
|
||||
console.log(`[db-merge] migrating response cache from designer to core`);
|
||||
await copyDirs(['responses'], designerDataDir, coreDataDir);
|
||||
} else {
|
||||
console.log(`[db-merge] not migrating response cache`);
|
||||
}
|
||||
|
||||
if (copyPlugins) {
|
||||
console.log(`[db-merge] migrating plugins from designer to core`);
|
||||
await migratePlugins(designerDataDir, coreDataDir);
|
||||
} else {
|
||||
console.log(`[db-merge] not migrating plugins`);
|
||||
}
|
||||
|
||||
console.log('[db-merge] done!');
|
||||
|
||||
@@ -9,6 +9,7 @@ import { getDataDirectory, getDesignerDataDir } from '../../common/misc';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import OnboardingContainer from './onboarding-container';
|
||||
import { goToNextActivity } from '../redux/modules/global';
|
||||
import HelpTooltip from './help-tooltip';
|
||||
|
||||
type Step = 'options' | 'migrating' | 'results';
|
||||
|
||||
@@ -16,7 +17,9 @@ type SettingProps = {
|
||||
label: string,
|
||||
name: $Keys<MigrationOptions>,
|
||||
options: MigrationOptions,
|
||||
help?: string,
|
||||
};
|
||||
|
||||
type TextSettingProps = SettingProps & {
|
||||
handleChange: (SyntheticEvent<HTMLInputElement>) => void,
|
||||
};
|
||||
@@ -38,17 +41,27 @@ const TextSetting = ({ handleChange, label, name, options }: TextSettingProps) =
|
||||
type BooleanSettingProps = SettingProps & {
|
||||
handleChange: (boolean, Object, string) => void,
|
||||
};
|
||||
const BooleanSetting = ({ handleChange, label, name, options }: BooleanSettingProps) => {
|
||||
const BooleanSetting = ({ handleChange, label, name, options, help }: BooleanSettingProps) => {
|
||||
if (!options.hasOwnProperty(name)) {
|
||||
throw new Error(`Invalid text setting name ${name}`);
|
||||
}
|
||||
|
||||
const labelNode = React.useMemo(
|
||||
() => (
|
||||
<>
|
||||
{label}
|
||||
{help && <HelpTooltip className="space-left">{help}</HelpTooltip>}
|
||||
</>
|
||||
),
|
||||
[help, label],
|
||||
);
|
||||
|
||||
return (
|
||||
<ToggleSwitch
|
||||
labelClassName="row margin-bottom wide"
|
||||
checked={options[name]}
|
||||
id={name}
|
||||
label={label}
|
||||
label={labelNode}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
);
|
||||
@@ -58,8 +71,8 @@ type OptionsProps = { start: MigrationOptions => void, cancel: () => void };
|
||||
const Options = ({ start, cancel }: OptionsProps) => {
|
||||
const [options, setOptions] = React.useState<MigrationOptions>(() => ({
|
||||
useDesignerSettings: false,
|
||||
copyResponses: true,
|
||||
copyPlugins: true,
|
||||
copyWorkspaces: false,
|
||||
copyPlugins: false,
|
||||
designerDataDir: getDesignerDataDir(),
|
||||
coreDataDir: getDataDirectory(),
|
||||
}));
|
||||
@@ -72,6 +85,8 @@ const Options = ({ start, cancel }: OptionsProps) => {
|
||||
setOptions(prevOpts => ({ ...prevOpts, [id]: checked }));
|
||||
}, []);
|
||||
|
||||
const canStart = options.useDesignerSettings || options.copyWorkspaces || options.copyPlugins;
|
||||
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
@@ -83,22 +98,29 @@ const Options = ({ start, cancel }: OptionsProps) => {
|
||||
</p>
|
||||
<div className="text-left margin-top">
|
||||
<BooleanSetting
|
||||
label="Copy Designer Application Settings"
|
||||
name="useDesignerSettings"
|
||||
label="Copy Workspaces"
|
||||
name="copyWorkspaces"
|
||||
options={options}
|
||||
handleChange={handleSwitchChange}
|
||||
help={
|
||||
'This includes all resources linked to a workspace (eg. requests, proto files, environments, etc)'
|
||||
}
|
||||
/>
|
||||
<BooleanSetting
|
||||
label="Copy Plugins"
|
||||
name="copyPlugins"
|
||||
options={options}
|
||||
handleChange={handleSwitchChange}
|
||||
help={
|
||||
'Merge plugins between Designer and Insomnia, keeping the Designer version where a duplicate exists'
|
||||
}
|
||||
/>
|
||||
<BooleanSetting
|
||||
label="Copy Responses"
|
||||
name="copyResponses"
|
||||
label="Copy Designer Application Settings"
|
||||
name="useDesignerSettings"
|
||||
options={options}
|
||||
handleChange={handleSwitchChange}
|
||||
help={'Keep user preferences from Designer'}
|
||||
/>
|
||||
<details>
|
||||
<summary className="margin-bottom">Advanced options</summary>
|
||||
@@ -118,7 +140,11 @@ const Options = ({ start, cancel }: OptionsProps) => {
|
||||
</div>
|
||||
|
||||
<div className="margin-top">
|
||||
<button key="start" className="btn btn--clicky" onClick={() => start(options)}>
|
||||
<button
|
||||
key="start"
|
||||
className="btn btn--clicky"
|
||||
onClick={() => start(options)}
|
||||
disabled={!canStart}>
|
||||
Start Migration
|
||||
</button>
|
||||
<button key="cancel" className="btn btn--super-compact" onClick={cancel}>
|
||||
|
||||
@@ -9,7 +9,7 @@ type Props = {
|
||||
checked?: boolean,
|
||||
disabled?: boolean,
|
||||
onChange(checked: boolean, Event, string): void | Promise<void>,
|
||||
label?: string,
|
||||
label?: React.Node,
|
||||
};
|
||||
|
||||
const ThemedSwitch: React.ComponentType<{ checked: boolean }> = styled(Switch)`
|
||||
|
||||
@@ -41,7 +41,13 @@ describe('Migration', function() {
|
||||
await client.correctlyLaunched(app);
|
||||
|
||||
await migration.migrationMessageShown(app);
|
||||
await migration.ensureStartNotClickable(app);
|
||||
|
||||
await migration.toggleOption(app, 'Copy Workspaces');
|
||||
await migration.toggleOption(app, 'Copy Plugins');
|
||||
await migration.toggleOption(app, 'Copy Designer Application Settings');
|
||||
await migration.clickStart(app);
|
||||
|
||||
await migration.successMessageShown(app);
|
||||
await migration.clickRestart(app);
|
||||
|
||||
|
||||
@@ -6,21 +6,34 @@ export const migrationMessageShown = async app => {
|
||||
};
|
||||
|
||||
export const clickSkip = async app => {
|
||||
const button = await app.client
|
||||
.$('.onboarding__content__body')
|
||||
.then(e => e.$(`button=Skip for now`));
|
||||
const button = await app.client.react$('MigrationBody').then(e => e.$(`button=Skip for now`));
|
||||
await button.waitForClickable();
|
||||
await button.click();
|
||||
};
|
||||
|
||||
export const clickStart = async app => {
|
||||
const button = await app.client
|
||||
export const toggleOption = async (app, label) => {
|
||||
const toggle = await app.client
|
||||
.$('.onboarding__content__body')
|
||||
.then(e => e.$(`button=Start Migration`));
|
||||
.then(e => e.react$(`BooleanSetting`, { props: { label } }));
|
||||
await toggle.waitForClickable();
|
||||
await toggle.click();
|
||||
};
|
||||
|
||||
const _getStartButton = async app => {
|
||||
return await app.client.react$('MigrationBody').then(e => e.$(`button=Start Migration`));
|
||||
};
|
||||
|
||||
export const clickStart = async app => {
|
||||
const button = await _getStartButton(app);
|
||||
await button.waitForClickable();
|
||||
await button.click();
|
||||
};
|
||||
|
||||
export const ensureStartNotClickable = async app => {
|
||||
const button = await _getStartButton(app);
|
||||
await button.waitForClickable({ reverse: true });
|
||||
};
|
||||
|
||||
export const successMessageShown = async app => {
|
||||
await app.client.waitUntilTextExists(
|
||||
'.onboarding__content__body p strong',
|
||||
@@ -31,7 +44,7 @@ export const successMessageShown = async app => {
|
||||
|
||||
export const clickRestart = async app => {
|
||||
await app.client
|
||||
.$('.onboarding__content__body')
|
||||
.react$('MigrationBody')
|
||||
.then(e => e.$(`button=Restart Now`))
|
||||
.then(e => e.click());
|
||||
};
|
||||
Reference in new issue
Block a user