snackbar imlementation

This commit is contained in:
Jan Prochazka
2021-06-06 12:39:05 +02:00
parent 27311afb31
commit 4d529e7e3f
6 changed files with 155 additions and 12 deletions

View File

@@ -6,6 +6,7 @@
currentThemeDefinition, currentThemeDefinition,
isFileDragActive, isFileDragActive,
leftPanelWidth, leftPanelWidth,
openedSnackbars,
selectedWidget, selectedWidget,
visibleCommandPalette, visibleCommandPalette,
visibleToolbar, visibleToolbar,
@@ -17,11 +18,13 @@
import splitterDrag from './utility/splitterDrag'; import splitterDrag from './utility/splitterDrag';
import CurrentDropDownMenu from './modals/CurrentDropDownMenu.svelte'; import CurrentDropDownMenu from './modals/CurrentDropDownMenu.svelte';
import StatusBar from './widgets/StatusBar.svelte'; import StatusBar from './widgets/StatusBar.svelte';
import Snackbar from './widgets/Snackbar.svelte';
import ModalLayer from './modals/ModalLayer.svelte'; import ModalLayer from './modals/ModalLayer.svelte';
import DragAndDropFileTarget from './DragAndDropFileTarget.svelte'; import DragAndDropFileTarget from './DragAndDropFileTarget.svelte';
import dragDropFileTarget from './utility/dragDropFileTarget'; import dragDropFileTarget from './utility/dragDropFileTarget';
$: currentThemeType = $currentThemeDefinition?.themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light'; $: currentThemeType = $currentThemeDefinition?.themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light';
</script> </script>
<div class={`${$currentTheme} ${currentThemeType} root`} use:dragDropFileTarget> <div class={`${$currentTheme} ${currentThemeType} root`} use:dragDropFileTarget>
@@ -64,6 +67,11 @@
{#if $isFileDragActive} {#if $isFileDragActive}
<DragAndDropFileTarget /> <DragAndDropFileTarget />
{/if} {/if}
<div class="snackbar-container">
{#each $openedSnackbars as snackbar}
<Snackbar {...snackbar} />
{/each}
</div>
</div> </div>
<style> <style>
@@ -139,4 +147,11 @@
bottom: var(--dim-statusbar-height); bottom: var(--dim-statusbar-height);
left: calc(var(--dim-widget-icon-size) + var(--dim-left-panel-width)); left: calc(var(--dim-widget-icon-size) + var(--dim-left-panel-width));
} }
.snackbar-container {
position: fixed;
right: 0;
bottom: var(--dim-statusbar-height);
}
</style> </style>

View File

@@ -71,11 +71,7 @@
</script> </script>
<script lang="ts"> <script lang="ts">
import { changeSetToSql, createChangeSet } from 'dbgate-datalib';
import { scriptToSql } from 'dbgate-sqltree';
import registerCommand from '../commands/registerCommand'; import registerCommand from '../commands/registerCommand';
import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte';
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
import ImportExportModal from '../modals/ImportExportModal.svelte'; import ImportExportModal from '../modals/ImportExportModal.svelte';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';

View File

@@ -20,14 +20,6 @@
</script> </script>
<script lang="ts"> <script lang="ts">
import { changeSetToSql, createChangeSet } from 'dbgate-datalib';
import { scriptToSql } from 'dbgate-sqltree';
import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte';
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
import { showModal } from '../modals/modalTools';
import axiosInstance from '../utility/axiosInstance'; import axiosInstance from '../utility/axiosInstance';
import ChangeSetFormer from './ChangeSetFormer'; import ChangeSetFormer from './ChangeSetFormer';
import FormView from './FormView.svelte'; import FormView from './FormView.svelte';

View File

@@ -55,6 +55,7 @@ export const visibleToolbar = writableWithStorage(true, 'visibleToolbar');
export const leftPanelWidth = writable(300); export const leftPanelWidth = writable(300);
export const currentDropDownMenu = writable(null); export const currentDropDownMenu = writable(null);
export const openedModals = writable([]); export const openedModals = writable([]);
export const openedSnackbars = writable([]);
export const nullStore = readable(null, () => {}); export const nullStore = readable(null, () => {});
export const currentArchive = writable('default'); export const currentArchive = writable('default');
export const isFileDragActive = writable(false); export const isFileDragActive = writable(false);

View File

@@ -16,6 +16,7 @@
export const matchingProps = ['conid', 'database', 'schemaName', 'pureName']; export const matchingProps = ['conid', 'database', 'schemaName', 'pureName'];
export const allowAddToFavorites = props => true; export const allowAddToFavorites = props => true;
</script> </script>
<script lang="ts"> <script lang="ts">
@@ -46,6 +47,7 @@
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
import registerCommand from '../commands/registerCommand'; import registerCommand from '../commands/registerCommand';
import { registerMenu } from '../utility/contextMenu'; import { registerMenu } from '../utility/contextMenu';
import { showSnackbarSuccess } from '../widgets/Snackbar.svelte';
export let tabid; export let tabid;
export let conid; export let conid;
@@ -78,6 +80,7 @@
} else { } else {
dispatchChangeSet({ type: 'reset', value: createChangeSet() }); dispatchChangeSet({ type: 'reset', value: createChangeSet() });
cache.update(reloadDataCacheFunc); cache.update(reloadDataCacheFunc);
showSnackbarSuccess('Saved to database');
} }
} }
@@ -102,6 +105,7 @@
} }
registerMenu({ command: 'tableData.save', tag: 'save' }); registerMenu({ command: 'tableData.save', tag: 'save' });
</script> </script>
<TableDataGrid <TableDataGrid

View File

@@ -0,0 +1,135 @@
<script lang="ts" context="module">
import { openedSnackbars } from '../stores';
export interface SnackbarButton {
label: string;
onClick: Function;
}
export interface SnackbarInfo {
message: string;
icon?: string;
autoClose?: boolean;
allowClose?: boolean;
buttons?: SnackbarButton[];
}
let lastSnackbarId = 0;
export function showSnackbar(snackbar: SnackbarInfo) {
lastSnackbarId += 1;
openedSnackbars.update(x => [
...x,
{
...snackbar,
id: lastSnackbarId,
},
]);
}
export function showSnackbarSuccess(message: string) {
showSnackbar({
message,
icon: 'img ok',
allowClose: true,
autoClose: true,
});
}
// showSnackbar({
// icon: 'img ok',
// message: 'Test snackbar',
// allowClose: true,
// });
// showSnackbar({
// icon: 'img ok',
// message: 'Auto close',
// autoClose: true,
// });
// showSnackbar({
// icon: 'img warn',
// message: 'Buttons',
// buttons: [{ label: 'OK', onClick: () => console.log('OK') }],
// });
</script>
<script lang="ts">
import FontIcon from '../icons/FontIcon.svelte';
import { onMount } from 'svelte';
import FormStyledButton from '../elements/FormStyledButton.svelte';
export let message;
export let id;
export let icon = null;
export let autoClose = false;
export let allowClose = false;
export let buttons = [];
function handleClose() {
openedSnackbars.update(x => x.filter(x => x.id != id));
}
onMount(() => {
if (autoClose) setTimeout(handleClose, 3000);
});
</script>
<div class="wrapper">
<div class="message">
<FontIcon {icon} />
{message}
</div>
{#if allowClose}
<div class="close" on:click={handleClose}>
<FontIcon icon="icon close" />
</div>
{/if}
{#if buttons?.length > 0}
<div class="buttons">
{#each buttons as button}
<div class="button">
<FormStyledButton value={button.label} on:click={button.onClick} />
</div>
{/each}
</div>
{/if}
</div>
<style>
.wrapper {
width: 400px;
border: 1px solid var(--theme-border);
background-color: var(--theme-bg-2);
margin: 10px;
position: relative;
}
.message {
margin: 10px;
}
.close {
position: absolute;
right: 5px;
top: 5px;
cursor: pointer;
}
.close:hover {
color: var(--theme-font-hover);
}
.buttons {
display: flex;
justify-content: flex-end;
}
.button {
margin: 5px;
}
</style>