db diff: save/sync

This commit is contained in:
Jan Prochazka
2021-11-06 16:34:02 +01:00
parent 17286e0c3e
commit 6269171f5d
6 changed files with 157 additions and 17 deletions

View File

@@ -25,6 +25,9 @@
right: 0;
bottom: 0;
overflow-y: scroll;
background: white;
color: #000000;
}
/* :global(.d2h-file-diff) {
overflow-y: scroll;

View File

@@ -60,7 +60,7 @@
<svelte:fragment slot="0" let:row>
<CheckboxField
checked={row.isOutput}
onChange={e => {
on:change={e => {
if (e.target.checked) changeColumn({ ...row, isOutput: true });
else changeColumn({ ...row, isOutput: false });
}}

View File

@@ -6,6 +6,7 @@
getProps?: any;
formatter?: any;
slot?: number;
headerSlot?: number;
isHighlighted?: Function;
width?: string;
}
@@ -98,7 +99,22 @@
>
<tr>
{#each columnList as col}
<td style={col.width ? `width: ${col.width}` : undefined}>{col.header || ''}</td>
<td style={col.width ? `width: ${col.width}` : undefined}>
{#if col.headerSlot != null}
{#if col.headerSlot == -1}<slot name="-1" />
{:else if col.headerSlot == 0}<slot name="0" />
{:else if col.headerSlot == 1}<slot name="1" />
{:else if col.headerSlot == 2}<slot name="2" />
{:else if col.headerSlot == 3}<slot name="3" />
{:else if col.headerSlot == 4}<slot name="4" />
{:else if col.headerSlot == 5}<slot name="5" />
{:else if col.headerSlot == 6}<slot name="6" />
{:else if col.headerSlot == 7}<slot name="7" />
{/if}
{:else}
{col.header || ''}
{/if}
</td>
{/each}
</tr>
</thead>
@@ -107,6 +123,9 @@
<tr
class:selected={selectable && selectedIndex == index}
class:clickable
class:isAdded={row.__isAdded}
class:isDeleted={row.__isDeleted}
class:isChanged={row.__isChanged}
on:click={() => {
if (selectable) {
selectedIndex = index;
@@ -215,4 +234,15 @@
td.isHighlighted {
background-color: var(--theme-bg-1);
}
tr.isAdded {
background: var(--theme-bg-green);
}
tr.isChanged {
background: var(--theme-bg-orange);
}
tr.isDeleted {
background: var(--theme-bg-red);
}
</style>

View File

@@ -63,6 +63,7 @@
'icon markdown': 'mdi mdi-application',
'icon preview': 'mdi mdi-file-find',
'icon eye': 'mdi mdi-eye',
'icon check-all': 'mdi mdi-check-all',
'icon run': 'mdi mdi-play',
'icon chevron-down': 'mdi mdi-chevron-down',
@@ -75,6 +76,8 @@
'icon add-column': 'mdi mdi-table-column-plus-after',
'icon add-key': 'mdi mdi-key-plus',
'icon report': 'mdi mdi-file-chart',
'icon swap': 'mdi mdi-swap-horizontal-bold',
'icon save-sync': 'mdi mdi-content-save-move',
'img ok': 'mdi mdi-check-circle color-icon-green',
'img ok-inv': 'mdi mdi-check-circle color-icon-inv-green',

View File

@@ -14,6 +14,31 @@
onClick: () => getCurrentEditor().showReport(),
testEnabled: () => getCurrentEditor() != null,
});
registerCommand({
id: 'compareModels.swap',
category: 'Compare models',
toolbarName: 'Swap',
name: 'Swap source & target',
icon: 'icon swap',
toolbar: true,
isRelatedToTab: true,
onClick: () => getCurrentEditor().swap(),
testEnabled: () => getCurrentEditor() != null,
});
registerCommand({
id: 'compareModels.saveSync',
category: 'Compare models',
toolbarName: 'Save/Sync',
name: 'Save/Sync',
icon: 'icon save-sync',
group: 'save',
toolbar: true,
isRelatedToTab: true,
onClick: () => getCurrentEditor().saveSync(),
testEnabled: () => getCurrentEditor() != null,
});
</script>
<script lang="ts">
@@ -27,10 +52,11 @@
getCreateObjectScript,
} from 'dbgate-tools';
import _ from 'lodash';
import _, { startsWith } from 'lodash';
import { derived, writable } from 'svelte/store';
import registerCommand from '../commands/registerCommand';
import DiffView from '../elements/DiffView.svelte';
import InlineButton from '../elements/InlineButton.svelte';
import ScrollableTableControl from '../elements/ScrollableTableControl.svelte';
import TabControl from '../elements/TabControl.svelte';
import TableControl from '../elements/TableControl.svelte';
@@ -40,6 +66,9 @@
import FontIcon from '../icons/FontIcon.svelte';
import FormConnectionSelect from '../impexp/FormConnectionSelect.svelte';
import FormDatabaseSelect from '../impexp/FormDatabaseSelect.svelte';
import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte';
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
import { showModal } from '../modals/modalTools';
import SqlEditor from '../query/SqlEditor.svelte';
import useEditorData from '../query/useEditorData';
import { extensions } from '../stores';
@@ -47,6 +76,7 @@
import createActivator, { getActiveComponent } from '../utility/createActivator';
import { useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders';
import resolveApi from '../utility/resolveApi';
import { showSnackbarSuccess } from '../utility/snackbar';
export let tabid;
@@ -100,20 +130,69 @@
});
window.open(`${resolveApi()}/uploads/get?file=${resp.data}`, '_blank');
}
// window.open(
// `${resolveApi()}/database-connections/get-diff-html?sourceConid=` +
// `${$values?.sourceConid}&sourceDatabase=${$values?.sourceDatabase}&` +
// `targetConid=${$values?.targetConid}&targetDatabase=${$values?.targetDatabase}`,
// '_blank'
// );
export function swap() {
$values = {
...$values,
sourceConid: $values?.targetConid,
sourceDatabase: $values?.targetDatabase,
targetConid: $values?.sourceConid,
targetDatabase: $values?.sourceDatabase,
};
}
function handleCheckAll() {
const isAnyChecked = diffRows.some(row => $values[`isChecked_${row.identifier}`]);
if (isAnyChecked) {
$values = _.omitBy($values, (v, k) => k.startsWith('isChecked_'));
} else {
$values = {
...$values,
..._.fromPairs(diffRows.filter(row => row.state != 'equal').map(row => [`isChecked_${row.identifier}`, true])),
};
}
}
async function handleConfirmSql(sql) {
const conid = $values?.targetConid;
const database = $values?.targetDatabase;
const resp = await axiosInstance.request({
url: 'database-connections/run-script',
method: 'post',
params: { conid, database },
data: { sql },
});
const { errorMessage } = resp.data || {};
if (errorMessage) {
showModal(ErrorMessageModal, { title: 'Error when saving', message: errorMessage });
} else {
await axiosInstance.post('database-connections/sync-model', { conid, database });
showSnackbarSuccess('Saved to database');
}
}
function getSyncSql() {
return diffRows
.filter(row => $values[`isChecked_${row.identifier}`])
.map(row => getAlterTableScript(row?.source, row.target, dbDiffOptions, targetDb, driver).sql)
.join('\n');
}
export function saveSync() {
const sql = getSyncSql();
showModal(ConfirmSqlModal, {
sql,
onConfirm: () => {
handleConfirmSql(sql);
},
engine: driver.engine,
});
}
const { editorState, editorValue, setEditorData } = useEditorData({
tabid,
// onInitialData: value => {
// dispatchModel({ type: 'reset', value });
// },
});
const values = {
@@ -175,6 +254,7 @@
selectable
disableFocusOutline
columns={[
{ fieldName: 'isChecked', header: '', width: '50px', slot: 1, headerSlot: 2 },
{ fieldName: 'type', header: 'Type', width: '100px' },
{ fieldName: 'sourceSchemaName', header: 'Schema' },
{ fieldName: 'sourcePureName', header: 'Name' },
@@ -182,7 +262,24 @@
{ fieldName: 'targetSchemaName', header: 'Schema' },
{ fieldName: 'targetPureName', header: 'Name' },
]}
/>
>
<input
type="checkbox"
slot="1"
let:row
disabled={row.state == 'equal'}
checked={!!$values[`isChecked_${row['identifier']}`]}
on:change={e => {
// @ts-ignore
$values = { ...$values, [`isChecked_${row.identifier}`]: e.target.checked };
}}
/>
<svelte:fragment slot="2">
<InlineButton on:click={handleCheckAll}>
<FontIcon icon="icon check-all" />
</InlineButton>
</svelte:fragment>
</ScrollableTableControl>
</div>
</div>
@@ -194,7 +291,7 @@
slot: 1,
},
{
label: 'SQL script',
label: 'Synchronize script',
slot: 2,
},
{