1
1
mirror of https://github.com/Fabio286/antares.git synced 2025-02-18 12:40:41 +01:00

feat: filter schemas in sidebar, closes #555

This commit is contained in:
Fabio Di Stasio 2023-04-07 18:06:41 +02:00
parent d802b32597
commit 8be9f932e7
3 changed files with 69 additions and 16 deletions

View File

@ -32,13 +32,20 @@
</span> </span>
</div> </div>
<div class="workspace-explorebar-search"> <div class="workspace-explorebar-search">
<div v-if="workspace.connectionStatus === 'connected'" class="has-icon-right"> <div v-if="workspace.connectionStatus === 'connected'" class="input-group has-icon-right">
<div
class="input-group-addon px-1 py-0 p-vcentered c-hand"
:title="t('message.switchSearchMethod')"
@click="toggleSearchMethod"
>
<i class="mdi mdi-18px" :class="[searchMethod === 'elements' ? 'mdi-shape' : 'mdi-database']" />
</div>
<input <input
ref="searchInput" ref="searchInput"
v-model="searchTerm" v-model="searchTerm"
class="form-input input-sm" class="form-input input-sm"
type="text" type="text"
:placeholder="t('message.searchForElements')" :placeholder="searchMethod === 'elements' ? t('message.searchForElements') : t('message.searchForSchemas')"
> >
<i v-if="!searchTerm" class="form-icon mdi mdi-magnify mdi-18px" /> <i v-if="!searchTerm" class="form-icon mdi mdi-magnify mdi-18px" />
<i <i
@ -50,11 +57,12 @@
</div> </div>
<div class="workspace-explorebar-body" @click="explorebar.focus()"> <div class="workspace-explorebar-body" @click="explorebar.focus()">
<WorkspaceExploreBarSchema <WorkspaceExploreBarSchema
v-for="db of workspace.structure" v-for="db of filteredSchemas"
:key="db.name" :key="db.name"
ref="schema" ref="schema"
:database="db" :database="db"
:connection="connection" :connection="connection"
:search-method="searchMethod"
@show-schema-context="openSchemaContext" @show-schema-context="openSchemaContext"
@show-table-context="openTableContext" @show-table-context="openTableContext"
@show-misc-context="openMiscContext" @show-misc-context="openMiscContext"
@ -181,6 +189,7 @@ const selectedSchema = ref('');
const selectedTable = ref(null); const selectedTable = ref(null);
const selectedMisc = ref(null); const selectedMisc = ref(null);
const searchTerm = ref(''); const searchTerm = ref('');
const searchMethod: Ref<'elements' | 'schemas'> = ref('elements');
const workspace = computed(() => { const workspace = computed(() => {
return getWorkspace(props.connection.uid); return getWorkspace(props.connection.uid);
@ -194,6 +203,13 @@ const customizations = computed(() => {
return workspace.value.customizations; return workspace.value.customizations;
}); });
const filteredSchemas = computed(() => {
if (searchMethod.value === 'schemas')
return workspace.value.structure.filter(schema => schema.name.search(searchTerm.value) >= 0);
else
return workspace.value.structure;
});
watch(localWidth, (val: number) => { watch(localWidth, (val: number) => {
clearTimeout(explorebarWidthInterval.value); clearTimeout(explorebarWidthInterval.value);
@ -403,6 +419,15 @@ const duplicateTable = async (payload: { schema: string; table: { name: string }
}); });
}; };
const toggleSearchMethod = () => {
searchTerm.value = '';
setSearchTerm(searchTerm.value);
if (searchMethod.value === 'elements')
searchMethod.value = 'schemas';
else
searchMethod.value = 'elements';
};
</script> </script>
<style lang="scss"> <style lang="scss">
@ -478,6 +503,8 @@ const duplicateTable = async (payload: { schema: string; table: { name: string }
justify-content: space-between; justify-content: space-between;
font-size: 0.6rem; font-size: 0.6rem;
height: 28px; height: 28px;
margin: 5px 0;
z-index: 10;
.has-icon-right { .has-icon-right {
width: 100%; width: 100%;
@ -491,6 +518,7 @@ const duplicateTable = async (payload: { schema: string; table: { name: string }
.form-input { .form-input {
height: 1.2rem; height: 1.2rem;
padding-left: 0.2rem; padding-left: 0.2rem;
border-radius:0 $border-radius $border-radius 0;
&:focus + .form-icon { &:focus + .form-icon {
opacity: 0.9; opacity: 0.9;

View File

@ -10,7 +10,7 @@
<i v-else class="icon mdi mdi-18px mdi-chevron-right" /> <i v-else class="icon mdi mdi-18px mdi-chevron-right" />
<i class="database-icon mdi mdi-18px mdi-database mr-1" /> <i class="database-icon mdi mdi-18px mdi-database mr-1" />
<div class=""> <div class="">
<span>{{ database.name }}</span> <span v-html="highlightWord(database.name, 'schemas')" />
<div <div
v-if="database.size" v-if="database.size"
class="schema-size tooltip tooltip-left mr-1" class="schema-size tooltip tooltip-left mr-1"
@ -249,7 +249,8 @@ const { t } = useI18n();
const props = defineProps({ const props = defineProps({
database: Object as Prop<WorkspaceStructure>, database: Object as Prop<WorkspaceStructure>,
connection: Object connection: Object,
searchMethod: String as Prop<'elements' | 'schemas'>
}); });
const emit = defineEmits([ const emit = defineEmits([
@ -282,29 +283,51 @@ const searchTerm = computed(() => {
}); });
const filteredTables = computed(() => { const filteredTables = computed(() => {
if (props.searchMethod === 'elements')
return props.database.tables.filter(table => table.name.search(searchTerm.value) >= 0); return props.database.tables.filter(table => table.name.search(searchTerm.value) >= 0);
else
return props.database.tables;
}); });
const filteredTriggers = computed(() => { const filteredTriggers = computed(() => {
if (props.searchMethod === 'elements')
return props.database.triggers.filter(trigger => trigger.name.search(searchTerm.value) >= 0); return props.database.triggers.filter(trigger => trigger.name.search(searchTerm.value) >= 0);
else
return props.database.triggers;
}); });
const filteredProcedures = computed(() => { const filteredProcedures = computed(() => {
if (props.searchMethod === 'elements')
return props.database.procedures.filter(procedure => procedure.name.search(searchTerm.value) >= 0); return props.database.procedures.filter(procedure => procedure.name.search(searchTerm.value) >= 0);
else
return props.database.procedures;
}); });
const filteredFunctions = computed(() => { const filteredFunctions = computed(() => {
if (props.searchMethod === 'elements')
return props.database.functions.filter(func => func.name.search(searchTerm.value) >= 0); return props.database.functions.filter(func => func.name.search(searchTerm.value) >= 0);
else
return props.database.functions;
}); });
const filteredTriggerFunctions = computed(() => { const filteredTriggerFunctions = computed(() => {
if (props.searchMethod === 'elements') {
return props.database.triggerFunctions return props.database.triggerFunctions
? props.database.triggerFunctions.filter(func => func.name.search(searchTerm.value) >= 0) ? props.database.triggerFunctions.filter(func => func.name.search(searchTerm.value) >= 0)
: []; : [];
}
else {
return props.database.triggerFunctions
? props.database.triggerFunctions
: [];
}
}); });
const filteredSchedulers = computed(() => { const filteredSchedulers = computed(() => {
if (props.searchMethod === 'elements')
return props.database.schedulers.filter(scheduler => scheduler.name.search(searchTerm.value) >= 0); return props.database.schedulers.filter(scheduler => scheduler.name.search(searchTerm.value) >= 0);
else
return props.database.schedulers;
}); });
const workspace = computed(() => { const workspace = computed(() => {
@ -446,10 +469,10 @@ const setBreadcrumbs = (payload: Breadcrumb) => {
changeBreadcrumbs(payload); changeBreadcrumbs(payload);
}; };
const highlightWord = (string: string) => { const highlightWord = (string: string, type = 'elements') => {
string = string.replaceAll('<', '&lt;').replaceAll('>', '&gt;'); string = string.replaceAll('<', '&lt;').replaceAll('>', '&gt;');
if (searchTerm.value) { if (searchTerm.value && props.searchMethod === type) {
const regexp = new RegExp(`(${searchTerm.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'); const regexp = new RegExp(`(${searchTerm.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
return string.replace(regexp, '<span class="text-primary">$1</span>'); return string.replace(regexp, '<span class="text-primary">$1</span>');
} }

View File

@ -337,7 +337,9 @@ export const enUS = {
executeSelectedQuery: 'Execute selected query', executeSelectedQuery: 'Execute selected query',
defaultCopyType: 'Default copy type', defaultCopyType: 'Default copy type',
showTableSize: 'Show table size in sidebar', showTableSize: 'Show table size in sidebar',
showTableSizeDescription: 'MySQL/MariaDB only. Enable this option may affects performance on schema with many tables.' showTableSizeDescription: 'MySQL/MariaDB only. Enable this option may affects performance on schema with many tables.',
searchForSchemas: 'Search for schemas',
switchSearchMethod: 'Switch search method'
}, },
faker: { faker: {
address: 'Address', address: 'Address',