app object list

This commit is contained in:
Jan Prochazka 2021-02-28 21:16:08 +01:00
parent 5dba5a6dfd
commit 565a60e638
12 changed files with 142 additions and 14 deletions

View File

@ -28,6 +28,10 @@ body {
background-color: var(--theme-bg-2);
}
.icon-invisible {
visibility: hidden;
}
/* html, body {
position: relative;
width: 100%;

View File

@ -6,7 +6,6 @@
export let title;
export let isBold = false;
export let prefix = '';
export let isBusy = false;
export let statusIcon = undefined;
export let statusTitle = undefined;
@ -15,7 +14,7 @@
</script>
<div class="main" class:isBold draggable on:click use:contextMenu={menu}>
{prefix}
<slot name="prefix" />
{#if isBusy}
<FontIcon icon="icon loading" />
{:else}

View File

@ -0,0 +1,37 @@
<script>
import AppObjectListItem from './AppObjectListItem.svelte';
export let group;
export let items;
export let module;
let isExpanded = true;
$: filtered = items.filter(x => x.isMatched);
$: countText = filtered.length < items.length ? `${filtered.length}/${items.length}` : `${items.length}`;
</script>
<div class="group" on:click={() => (isExpanded = !isExpanded)}>
{group}
{items && `(${countText})`}
</div>
{#if isExpanded}
{#each filtered as item (module.extractKey(item.data))}
<AppObjectListItem {module} data={item.data} on:objectClick />
{/each}
{/if}
<style>
.group {
user-select: none;
padding: 5px;
cursor: pointer;
white-space: nowrap;
font-weight: bold;
}
.group:hover {
background-color: var(--theme-bg-hover);
}
</style>

View File

@ -1,10 +1,14 @@
<script lang="ts">
<script>
import _ from 'lodash';
import AppObjectGroup from './AppObjectGroup.svelte';
import AppObjectListItem from './AppObjectListItem.svelte';
export let list;
export let module;
export let subItemsComponent = undefined;
export let expandOnClick = false;
export let isExpandable = undefined;
export let filter;
export let groupFunc = undefined;
@ -14,8 +18,27 @@
if (matcher && !matcher(filter)) return false;
return true;
});
$: listGrouped = groupFunc
? _.compact(
(list || []).map(data => {
const matcher = module.createMatcher && module.createMatcher(data);
const isMatched = matcher && !matcher(filter) ? false : true;
const group = groupFunc(data);
return { group, data, isMatched };
})
)
: null;
$: groups = groupFunc ? _.groupBy(listGrouped, 'group') : null;
</script>
{#each filtered as data}
<AppObjectListItem {module} {subItemsComponent} {expandOnClick} {data} on:objectClick />
{/each}
{#if groupFunc}
{#each _.keys(groups) as group (group)}
<AppObjectGroup {group} {module} items={groups[group]} />
{/each}
{:else}
{#each filtered as data (module.extractKey(data))}
<AppObjectListItem {module} {subItemsComponent} {expandOnClick} {data} {isExpandable} on:objectClick />
{/each}
{/if}

View File

@ -1,20 +1,52 @@
<script lang="ts">
import ExpandIcon from '../icons/ExpandIcon.svelte';
import { tick } from 'svelte';
export let module;
export let data;
export let subItemsComponent;
export let expandOnClick;
export let isExpandable = undefined;
let isExpanded = false;
function handleExpand() {
async function handleExpand() {
if (subItemsComponent && expandOnClick) {
await tick();
isExpanded = !isExpanded;
}
}
$: expandable = data && isExpandable && isExpandable(data);
$: if (!expandable && isExpanded) isExpanded = false;
</script>
<svelte:component this={module.default} {data} on:click={handleExpand} />
{#if subItemsComponent}
<svelte:component this={module.default} {data} on:click={handleExpand}>
<span class="expand-icon" slot="prefix">
{#if expandable}
<ExpandIcon {isExpanded} />
{:else}
<ExpandIcon isBlank />
{/if}
</span>
</svelte:component>
{:else}
<svelte:component this={module.default} {data} on:click={handleExpand} />
{/if}
{#if isExpanded && subItemsComponent}
<svelte:component this={subItemsComponent} {data} />
<div class="subitems">
<svelte:component this={subItemsComponent} {data} />
</div>
{/if}
<style>
.expand-icon {
margin-right: 3px;
}
.subitems {
margin-left: 28px;
}
</style>

View File

@ -102,6 +102,8 @@
statusTitle={statusTitle || engineStatusTitle}
{extInfo}
menu={getContextMenu(data, $openedConnections)}
on:click
on:click={() => ($openedConnections = _.uniq([...$openedConnections, data._id]))}
/>
on:click
>
<slot name="prefix" slot="prefix" />
</AppObjectCore>

View File

@ -1,3 +1,7 @@
<script lang="ts" context="module">
export const extractKey = props => props.name;
</script>
<script lang="ts">
import _ from 'lodash';

View File

@ -1,8 +1,14 @@
<script lang="ts" context="module">
export const extractKey = ({ schemaName, pureName }) => (schemaName ? `${schemaName}.${pureName}` : pureName);
export const createMatcher = ({ pureName }) => filter => filterName(filter, pureName);
</script>
<script lang="ts">
import _ from 'lodash';
import AppObjectCore from './AppObjectCore.svelte';
import { currentDatabase, openedConnections } from '../stores';
import openNewTab from '../utility/openNewTab';
import { filterName } from 'dbgate-datalib';
export let commonProps;
export let data;

View File

@ -0,0 +1,12 @@
<script>
import FontIcon from './FontIcon.svelte';
export let isBlank = false;
export let isExpanded = false;
</script>
{#if isBlank}
<FontIcon icon="icon invisible-box" {...$$props} />
{:else}
<FontIcon icon={isExpanded ? 'icon minus-box' : 'icon plus-box'} {...$$props} />
{/if}

View File

@ -102,4 +102,4 @@
};
</script>
<span class={iconNames[icon] || icon} {title} />
<span class={iconNames[icon] || icon} {title} on:click />

View File

@ -8,6 +8,7 @@
import AppObjectList from '../appobj/AppObjectList.svelte';
import * as connectionAppObject from '../appobj/ConnectionAppObject.svelte';
import SubDatabaseList from '../appobj/SubDatabaseList.svelte';
import { openedConnections } from '../stores';
const connections = useConnectionList();
const serverStatus = useServerStatus();
@ -30,6 +31,7 @@
module={connectionAppObject}
subItemsComponent={SubDatabaseList}
expandOnClick
isExpandable={data => $openedConnections.includes(data._id)}
{filter}
/>
</WidgetsInnerContainer>

View File

@ -12,6 +12,8 @@
export let conid;
export let database;
let filter = '';
$: objects = useDatabaseInfo({ conid, database });
$: status = useDatabaseStatus({ conid, database });
@ -26,9 +28,14 @@
</script>
<SearchBoxWrapper>
<SearchInput placeholder="Search connection" />
<SearchInput placeholder="Search connection" bind:value={filter} />
<InlineButton>Refresh</InlineButton>
</SearchBoxWrapper>
<WidgetsInnerContainer>
<AppObjectList list={objectList.map(x => ({ ...x, conid, database }))} module={databaseObjectAppObject} />
<AppObjectList
list={objectList.map(x => ({ ...x, conid, database }))}
module={databaseObjectAppObject}
groupFunc={data => _.startCase(data.objectTypeField)}
{filter}
/>
</WidgetsInnerContainer>