diff --git a/dbrepo-auth-service/init/app.py b/dbrepo-auth-service/init/app.py
index 7d43f163fa3f50e326ba71933674500121d9fef2..28f88789c84607dc12418cceeb19ce0cf766b779 100644
--- a/dbrepo-auth-service/init/app.py
+++ b/dbrepo-auth-service/init/app.py
@@ -1,4 +1,5 @@
 import os
+
 import mariadb
 from keycloak import KeycloakAdmin
 
@@ -8,8 +9,10 @@ admin = KeycloakAdmin(server_url=os.getenv('AUTH_SERVICE_ENDPOINT', 'http://loca
                       username=os.getenv('AUTH_SERVICE_ADMIN', 'admin'),
                       password=os.getenv('AUTH_SERVICE_ADMIN_PASSWORD', 'admin'),
                       verify=True)
-user_id = admin.get_user_id(username=system_username)
-print(f'Successfully fetched user id: {user_id}')
+keycloak_user_id = admin.get_user_id(username=system_username)
+print(f'Successfully fetched keycloak user id: {keycloak_user_id}')
+ldap_user_id = admin.get_user(user_id=keycloak_user_id).get('attributes')['LDAP_ID'][0]
+print(f'Successfully fetched ldap user id: {ldap_user_id}')
 
 try:
     conn = mariadb.connect(user=os.getenv('METADATA_USERNAME', 'root'),
@@ -20,7 +23,7 @@ try:
     cursor = conn.cursor()
     cursor.execute(
         "INSERT IGNORE INTO `mdb_users` (`id`, `username`, `email`, `mariadb_password`) VALUES (?, ?, ?, PASSWORD(?))",
-        (user_id, system_username, 'some@admin', '1234567890'))
+        (ldap_user_id, system_username, 'some@admin', '1234567890'))
     conn.commit()
     conn.close()
 except mariadb.Error as e:
diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java
index f7e39c7302a5f18ae9dd97e01cce5bb501233887..b2805f8d77157d380cdeac412bce97a438eff392 100644
--- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java
+++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java
@@ -5,6 +5,8 @@ import at.tuwien.api.error.ApiErrorDto;
 import at.tuwien.entities.container.Container;
 import at.tuwien.entities.database.Database;
 import at.tuwien.entities.database.DatabaseAccess;
+import at.tuwien.entities.database.View;
+import at.tuwien.entities.database.table.Table;
 import at.tuwien.entities.user.User;
 import at.tuwien.exception.*;
 import at.tuwien.mapper.MetadataMapper;
@@ -519,13 +521,14 @@ public class DatabaseEndpoint extends AbstractEndpoint {
             /* reduce metadata */
             database.setTables(database.getTables()
                     .stream()
-                    .filter(t -> t.getIsPublic() || t.getIsSchemaPublic() || optional.isPresent())
+                    .filter(t -> t.getIsPublic() || optional.isPresent())
                     .toList());
             database.setViews(database.getViews()
                     .stream()
-                    .filter(v -> v.getIsPublic() || v.getIsSchemaPublic() || optional.isPresent())
+                    .filter(v -> v.getIsPublic() || optional.isPresent())
                     .toList());
             if (!database.getOwner().getId().equals(getId(principal))) {
+                log.trace("authenticated user is not owner: remove access list");
                 database.setAccesses(List.of());
             }
         } else {
@@ -536,11 +539,11 @@ public class DatabaseEndpoint extends AbstractEndpoint {
             /* reduce metadata */
             database.setTables(database.getTables()
                     .stream()
-                    .filter(t -> t.getIsPublic() || t.getIsSchemaPublic())
+                    .filter(Table::getIsPublic)
                     .toList());
             database.setViews(database.getViews()
                     .stream()
-                    .filter(v -> v.getIsPublic() || v.getIsSchemaPublic())
+                    .filter(View::getIsPublic)
                     .toList());
             database.setAccesses(List.of());
         }
diff --git a/dbrepo-ui/components/dialogs/DropTable.vue b/dbrepo-ui/components/dialogs/DropTable.vue
deleted file mode 100644
index d465c882d0529a817be21f836ea82739fc30155b..0000000000000000000000000000000000000000
--- a/dbrepo-ui/components/dialogs/DropTable.vue
+++ /dev/null
@@ -1,114 +0,0 @@
-<template>
-  <div>
-    <v-form ref="form" v-model="valid" autocomplete="off" @submit.prevent="submit">
-      <v-card
-        :title="$t('pages.table.subpages.drop.title') + ' ' + table.internal_name"
-        variant="elevated">
-        <v-card-text>
-          <v-row dense>
-            <v-col>
-              <span>
-                {{ $t('pages.table.subpages.drop.warning.prefix') }}
-              </span>
-              &nbsp;<code class="code-key">{{ table.internal_name }}</code>&nbsp;
-              <span>
-                {{ $t('pages.table.subpages.drop.warning.suffix') }}
-              </span>
-            </v-col>
-          </v-row>
-          <v-row>
-            <v-col>
-              <v-text-field
-                id="confirm"
-                v-model="confirm"
-                name="confirm"
-                persistent-hint
-                :variant="inputVariant"
-                :label="$t('pages.table.subpages.drop.name.label')"
-                :hint="$t('pages.table.subpages.drop.name.hint')"
-                autofocus
-                required />
-            </v-col>
-          </v-row>
-        </v-card-text>
-        <v-card-actions>
-          <v-spacer />
-          <v-btn
-            :variant="buttonVariant"
-            :text="$t('navigation.cancel')"
-            @click="cancel" />
-          <v-btn
-            color="error"
-            variant="flat"
-            :text="$t('navigation.delete')"
-            :loading="loadingDelete"
-            :disabled="confirm !== table.internal_name"
-            type="submit"
-            @click="dropTable" />
-        </v-card-actions>
-      </v-card>
-    </v-form>
-  </div>
-</template>
-
-<script>
-import { useCacheStore } from '@/stores/cache'
-
-export default {
-  data () {
-    return {
-      confirm: null,
-      loadingDelete: false,
-      valid: false,
-      cacheStore: useCacheStore()
-    }
-  },
-  computed: {
-    table () {
-      return this.cacheStore.getTable
-    },
-    database () {
-      return this.cacheStore.getDatabase
-    },
-    inputVariant () {
-      const runtimeConfig = useRuntimeConfig()
-      return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.input.contrast : runtimeConfig.public.variant.input.normal
-    },
-    buttonVariant () {
-      const runtimeConfig = useRuntimeConfig()
-      return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal
-    }
-  },
-  methods: {
-    submit () {
-      this.$refs.form.validate()
-    },
-    cancel () {
-      this.$emit('close', { action: 'closed' })
-    },
-    dropTable () {
-      if (!this.table.id) {
-        return
-      }
-      this.loadingDelete = true
-      const tableService = useTableService()
-      tableService.remove(this.database.id, this.table.id)
-        .then(() => {
-          console.info('Deleted table with id ', this.table.id)
-          this.cacheStore.reloadDatabase()
-          const toast = useToastInstance()
-          toast.success('Successfully deleted table with id ' + this.table.id)
-          this.$router.push(`/database/${this.$route.params.database_id}/table`)
-        })
-        .finally(() => {
-          this.loadingDelete = false
-        })
-    }
-  }
-}
-</script>
-<style scoped>
-.code-key {
-  padding: 2px 4px;
-}
-</style>
diff --git a/dbrepo-ui/components/dialogs/UpdateTable.vue b/dbrepo-ui/components/dialogs/UpdateTable.vue
deleted file mode 100644
index 8defb2669e68edd7c36af6b528cec0d252e4d12f..0000000000000000000000000000000000000000
--- a/dbrepo-ui/components/dialogs/UpdateTable.vue
+++ /dev/null
@@ -1,171 +0,0 @@
-<template>
-  <div>
-    <v-form
-      ref="form"
-      v-model="valid"
-      autocomplete="off"
-      @submit.prevent="submit">
-      <v-card
-        :title="$t('pages.view.visibility.title')">
-        <v-card-text>
-          <v-row>
-            <v-col>
-              <v-textarea
-                v-model="modify.description"
-                rows="2"
-                :rules="[
-                  v => (!!v || v.length <= 180) || ($t('validation.max-length') + 180),
-                ]"
-                clearable
-                counter="180"
-                persistent-counter
-                persistent-hint
-                :variant="inputVariant"
-                :hint="$t('pages.table.subpages.import.description.hint')"
-                :label="$t('pages.table.subpages.import.description.label')"/>
-            </v-col>
-          </v-row>
-          <v-row
-            dense>
-            <v-col
-              md="6">
-              <v-select
-                v-model="modify.is_public"
-                :items="dataOptions"
-                persistent-hint
-                :variant="inputVariant"
-                required
-                :rules="[
-                  v => v !== null || $t('validation.required')
-                ]"
-                :label="$t('pages.database.resource.data.label')"
-                :hint="$t('pages.database.resource.data.hint')" />
-            </v-col>
-            <v-col
-              md="6">
-              <v-select
-                v-model="modify.is_schema_public"
-                :items="schemaOptions"
-                persistent-hint
-                :variant="inputVariant"
-                required
-                :rules="[
-                  v => v !== null || $t('validation.required')
-                ]"
-                :label="$t('pages.database.resource.schema.label')"
-                :hint="$t('pages.database.resource.schema.hint')" />
-            </v-col>
-          </v-row>
-        </v-card-text>
-        <v-card-actions>
-          <v-spacer />
-          <v-btn
-            :variant="buttonVariant"
-            :text="$t('navigation.cancel')"
-            @click="cancel" />
-          <v-btn
-            id="database"
-            variant="flat"
-            :disabled="!valid || !isChange"
-            :color="buttonColor"
-            :loading="loading"
-            type="submit"
-            :text="$t('navigation.modify')"
-            @click="update" />
-        </v-card-actions>
-      </v-card>
-    </v-form>
-  </div>
-</template>
-
-<script>
-import { useCacheStore } from '@/stores/cache'
-
-export default {
-  props: {
-    table: {
-      type: Object,
-      default () {
-        return {
-          is_public: true,
-          is_schema_public: true,
-          description: null
-        }
-      }
-    },
-  },
-  data () {
-    return {
-      valid: false,
-      loading: false,
-      dataOptions: [
-        { title: this.$t('pages.database.resource.data.enabled'), value: true },
-        { title: this.$t('pages.database.resource.data.disabled'), value: false },
-      ],
-      schemaOptions: [
-        { title: this.$t('pages.database.resource.schema.enabled'), value: true },
-        { title: this.$t('pages.database.resource.schema.disabled'), value: false },
-      ],
-      modify: {
-        description: this.table.description,
-        is_public: this.table.is_public,
-        is_schema_public: this.table.is_schema_public
-      },
-      cacheStore: useCacheStore()
-    }
-  },
-  computed: {
-    database () {
-      return this.cacheStore.getDatabase
-    },
-    inputVariant () {
-      const runtimeConfig = useRuntimeConfig()
-      return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.input.contrast : runtimeConfig.public.variant.input.normal
-    },
-    buttonVariant () {
-      const runtimeConfig = useRuntimeConfig()
-      return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal
-    },
-    isChange () {
-      if (this.table.description !== this.modify.description) {
-        return true
-      }
-      if (this.table.is_public !== this.modify.is_public) {
-        return true
-      }
-      return this.table.is_schema_public !== this.modify.is_schema_public
-    },
-    buttonColor () {
-      return !this.isChange ? null : 'warning'
-    }
-  },
-  methods: {
-    submit () {
-      this.$refs.form.validate()
-    },
-    cancel () {
-      this.$emit('close', { success: false })
-    },
-    update () {
-      this.loading = true
-      const tableService = useTableService()
-      tableService.update(this.$route.params.database_id, this.$route.params.table_id, this.modify)
-        .then(() => {
-          this.loading = false
-          const toast = useToastInstance()
-          toast.success(this.$t('success.table.updated'))
-          this.$emit('close', { success: true })
-          this.cacheStore.reloadTable()
-        })
-        .catch(({ code }) => {
-          this.loading = false
-          const toast = useToastInstance()
-          toast.error(this.$t(code))
-        })
-        .finally(() => {
-          this.loading = false
-        })
-    }
-  }
-}
-</script>
diff --git a/dbrepo-ui/components/table/TableToolbar.vue b/dbrepo-ui/components/table/TableToolbar.vue
index 2840e2e4c43e545a98385bb42b993650940dc4a2..e2f1ad4b231c8fab498f7689d5ddfbea87298f18 100644
--- a/dbrepo-ui/components/table/TableToolbar.vue
+++ b/dbrepo-ui/components/table/TableToolbar.vue
@@ -45,22 +45,6 @@
         :text="($vuetify.display.lgAndUp ? $t('toolbars.database.create-view.xl') + ' ' : '') + $t('toolbars.database.create-view.permanent')"
         class="mr-2"
         :to="`/database/${$route.params.database_id}/view/create?tid=${$route.params.table_id}`" />
-      <v-btn
-        v-if="canUpdateTable"
-        class="mr-2"
-        variant="flat"
-        :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-table-edit' : null"
-        color="warning"
-        :text="($vuetify.display.lgAndUp ? $t('toolbars.database.update-table.xl') + ' ' : '') + $t('toolbars.database.update-table.permanent')"
-        @click="updateTableDialog = true" />
-      <v-btn
-        v-if="canDropTable"
-        :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-delete' : null"
-        color="error"
-        variant="flat"
-        :text="($vuetify.display.lgAndUp ? 'Drop ' : '') + 'Table'"
-        class="mr-2"
-        @click="dropTableDialog = true" />
       <v-btn
         v-if="canGetPid"
         :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-content-save-outline' : null"
@@ -82,37 +66,24 @@
             v-if="canViewSchema"
             :text="$t('navigation.schema')"
             :to="`/database/${$route.params.database_id}/table/${$route.params.table_id}/schema`" />
+          <v-tab
+            v-if="canUpdateTable"
+            :text="$t('navigation.settings')"
+            :to="`/database/${$route.params.database_id}/table/${$route.params.table_id}/settings`" />
         </v-tabs>
       </template>
     </v-toolbar>
-    <v-dialog
-      v-model="dropTableDialog"
-      max-width="640">
-      <DropTable
-        @close="closeDelete" />
-    </v-dialog>
-    <v-dialog
-      v-model="updateTableDialog"
-      max-width="640">
-      <UpdateTable
-        :table="table"
-        @close="closeUpdate" />
-    </v-dialog>
   </div>
 </template>
 
 <script>
 import EditTuple from '@/components/dialogs/EditTuple.vue'
-import DropTable from '@/components/dialogs/DropTable.vue'
-import UpdateTable from '@/components/dialogs/UpdateTable.vue'
 import { useCacheStore } from '@/stores/cache'
 import { useUserStore } from '@/stores/user'
 
 export default {
   components: {
-    EditTuple,
-    DropTable,
-    UpdateTable
+    EditTuple
   },
   data () {
     return {
@@ -121,7 +92,6 @@ export default {
       error: false,
       edit: false,
       dropTableDialog: false,
-      updateTableDialog: false,
       cacheStore: useCacheStore(),
       userStore: useUserStore()
     }
@@ -161,16 +131,6 @@ export default {
       const userService = useUserService()
       return userService.hasReadAccess(this.access) && this.roles.includes('execute-query')
     },
-    canDropTable () {
-      if (!this.roles || !this.table || !this.user) {
-        return false
-      }
-      if (this.roles.includes('delete-foreign-table')) {
-        return true
-      }
-      const tableService = useTableService()
-      return tableService.isOwner(this.table, this.user) && this.roles.includes('delete-table') && this.table.identifiers.length === 0
-    },
     canCreateView () {
       if (!this.roles || !this.table || !this.user) {
         return false
@@ -217,27 +177,6 @@ export default {
     buttonVariant () {
       const runtimeConfig = useRuntimeConfig()
       return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal
-    },
-    isContrastTheme () {
-      return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast')
-    },
-    isDarkTheme () {
-      return this.$vuetify.theme.global.name.toLowerCase().startsWith('dark')
-    },
-    colorVariant () {
-      return this.isContrastTheme ? '' : (this.isDarkTheme ? 'tertiary' : 'secondary')
-    },
-  },
-  methods: {
-    closeDelete ({success}) {
-      this.dropTableDialog = false
-      if (success) {
-        this.cacheStore.reloadDatabase()
-        this.$router.push(`/database/${this.$route.params.database_id}/table`)
-      }
-    },
-    closeUpdate () {
-      this.updateTableDialog = false
     }
   }
 }
diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json
index 53fec12c18ffac36b71817dae7d5f404323453d1..6eb0b81974d570ecf2e5176a06785d7717be421d 100644
--- a/dbrepo-ui/locales/en-US.json
+++ b/dbrepo-ui/locales/en-US.json
@@ -291,8 +291,13 @@
           "read": "You can read all contents of this table"
         }
       },
-      "visibility": {
-        "title": "Visibility",
+      "settings": {
+        "title": "Metadata",
+        "subtitle": "Optional table description for humans and visibility settings."
+      },
+      "delete": {
+        "title": "Delete this table",
+        "subtitle": "This action deletes {table} and all data in it. There is no going back."
       },
       "description": {
         "title": "Description",
diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue
new file mode 100644
index 0000000000000000000000000000000000000000..44133802b8327d4fdee2e787b09df354a9078451
--- /dev/null
+++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue
@@ -0,0 +1,336 @@
+<template>
+  <div
+    v-if="canUpdateTable">
+    <TableToolbar />
+    <v-window
+      v-if="user"
+      v-model="tab">
+      <v-window-item>
+        <v-form
+          ref="form"
+          v-model="valid"
+          autocomplete="off"
+          @submit.prevent="submit">
+          <v-card
+            variant="flat"
+            rounded="0"
+            :title="$t('pages.table.settings.title')"
+            :subtitle="$t('pages.table.settings.subtitle')">
+            <v-card-text>
+              <v-row>
+                <v-col
+                  md="8">
+                  <v-textarea
+                    v-model="modify.description"
+                    rows="2"
+                    :rules="[
+                      v => (!!v || v.length <= 180) || ($t('validation.max-length') + 180),
+                    ]"
+                    clearable
+                    counter="180"
+                    persistent-counter
+                    persistent-hint
+                    :variant="inputVariant"
+                    :hint="$t('pages.table.subpages.import.description.hint')"
+                    :label="$t('pages.table.subpages.import.description.label')"/>
+                </v-col>
+              </v-row>
+              <v-row
+                dense>
+                <v-col
+                  md="4">
+                  <v-select
+                    v-model="modify.is_public"
+                    :items="dataOptions"
+                    persistent-hint
+                    :variant="inputVariant"
+                    required
+                    :rules="[
+                      v => v !== null || $t('validation.required')
+                    ]"
+                    :label="$t('pages.database.resource.data.label')"
+                    :hint="$t('pages.database.resource.data.hint')" />
+                </v-col>
+                <v-col
+                  md="4">
+                  <v-select
+                    v-model="modify.is_schema_public"
+                    :items="schemaOptions"
+                    persistent-hint
+                    :variant="inputVariant"
+                    required
+                    :rules="[
+                      v => v !== null || $t('validation.required')
+                    ]"
+                    :label="$t('pages.database.resource.schema.label')"
+                    :hint="$t('pages.database.resource.schema.hint')" />
+                </v-col>
+              </v-row>
+              <v-row>
+                <v-col>
+                  <v-btn
+                    id="database"
+                    variant="flat"
+                    size="small"
+                    :disabled="!valid || !isChange"
+                    :color="buttonColor"
+                    :loading="loading"
+                    type="submit"
+                    :text="$t('navigation.modify')"
+                    @click="update" />
+                </v-col>
+              </v-row>
+            </v-card-text>
+          </v-card>
+        </v-form>
+        <v-divider
+          v-if="canDropTable" />
+        <v-card
+          v-if="canDropTable"
+          variant="flat"
+          rounded="0"
+          :title="$t('pages.table.delete.title')"
+          :subtitle="$t('pages.table.delete.subtitle', { table: table.internal_name })">
+          <v-card-text>
+            <v-row>
+              <v-col
+                md="8">
+                <v-btn
+                  size="small"
+                  variant="flat"
+                  color="error"
+                  @click="askDelete">
+                  Delete
+                </v-btn>
+              </v-col>
+            </v-row>
+          </v-card-text>
+        </v-card>
+      </v-window-item>
+    </v-window>
+    <v-breadcrumbs
+      :items="items"
+      class="pa-0 mt-2" />
+  </div>
+</template>
+
+<script>
+import TableToolbar from '@/components/table/TableToolbar.vue'
+import { useUserStore } from '@/stores/user'
+import { useCacheStore } from '@/stores/cache'
+
+export default {
+  components: {
+    TableToolbar
+  },
+  data () {
+    return {
+      tab: 0,
+      valid: null,
+      loading: false,
+      modify: {
+        description: '',
+        is_public: null,
+        is_schema_public: null
+      },
+      dataOptions: [
+        { title: this.$t('pages.database.resource.data.enabled'), value: true },
+        { title: this.$t('pages.database.resource.data.disabled'), value: false },
+      ],
+      schemaOptions: [
+        { title: this.$t('pages.database.resource.schema.enabled'), value: true },
+        { title: this.$t('pages.database.resource.schema.disabled'), value: false },
+      ],
+      items: [
+        {
+          title: this.$t('navigation.databases'),
+          to: '/database'
+        },
+        {
+          title: `${this.$route.params.database_id}`,
+          to: `/database/${this.$route.params.database_id}/info`
+        },
+        {
+          title: this.$t('navigation.tables'),
+          to: `/database/${this.$route.params.database_id}/table`
+        },
+        {
+          title: `${this.$route.params.table_id}`,
+          to: `/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}`
+        },
+        {
+          title: this.$t('navigation.schema'),
+          to: `/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}/schema`,
+          disabled: true
+        }
+      ],
+      headers: [
+        { value: 'internal_name', title: this.$t('pages.table.subpages.schema.internal-name.title') },
+        { value: 'column_type', title: this.$t('pages.table.subpages.schema.column-type.title') },
+        { value: 'extra', title: this.$t('pages.table.subpages.schema.extra.title') },
+        { value: 'column_concept', title: this.$t('pages.table.subpages.schema.concept.title') },
+        { value: 'column_unit', title: this.$t('pages.table.subpages.schema.unit.title') },
+        { value: 'is_null_allowed', title: this.$t('pages.table.subpages.schema.nullable.title') },
+        { value: 'description', title: this.$t('pages.table.subpages.schema.description.title') },
+      ],
+      dateColumns: [],
+      userStore: useUserStore(),
+      cacheStore: useCacheStore()
+    }
+  },
+  computed: {
+    user () {
+      return this.userStore.getUser
+    },
+    database () {
+      return this.cacheStore.getDatabase
+    },
+    table () {
+      return this.cacheStore.getTable
+    },
+    access () {
+      return this.userStore.getAccess
+    },
+    hasReadAccess () {
+      if (!this.access) {
+        return false
+      }
+      return this.access.type === 'read' || this.access.type === 'write_all' || this.access.type === 'write_own'
+    },
+    roles () {
+      return this.userStore.getRoles
+    },
+    isChange () {
+      if (!this.table) {
+        return false
+      }
+      if (this.table.is_public !== this.modify.is_public) {
+        return true
+      }
+      return this.table.is_schema_public !== this.modify.is_schema_public
+    },
+    canUpdateTable () {
+      if (!this.roles || !this.user || !this.table) {
+        return false
+      }
+      return this.roles.includes('update-table') && this.table.owner.id === this.user.id
+    },
+    canModifyVisibility () {
+      if (!this.roles || !this.user || !this.table) {
+        return false
+      }
+      return this.roles.includes('update-table') && this.table.owner.id === this.user.id
+    },
+    canDropTable () {
+      if (!this.roles || !this.table || !this.user) {
+        return false
+      }
+      if (this.roles.includes('delete-foreign-table')) {
+        return true
+      }
+      const tableService = useTableService()
+      return tableService.isOwner(this.table, this.user) && this.roles.includes('delete-table') && this.table.identifiers.length === 0
+    },
+    inputVariant () {
+      const runtimeConfig = useRuntimeConfig()
+      return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.input.contrast : runtimeConfig.public.variant.input.normal
+    },
+    buttonVariant () {
+      const runtimeConfig = useRuntimeConfig()
+      return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal
+    },
+    buttonColor () {
+      return !this.isChange ? null : 'warning'
+    }
+  },
+  mounted() {
+    if (!this.table) {
+      return
+    }
+    this.modify.is_public = this.table.is_public
+    this.modify.is_schema_public = this.table.is_schema_public
+    this.modify.description = this.table.description
+  },
+  methods: {
+    submit () {
+      this.$refs.form.validate()
+    },
+    extra (column) {
+      if (column.column_type === 'float') {
+        return `precision=${column.size}`
+      } else if (['decimal', 'double'].includes(column.column_type)) {
+        let extra = ''
+        if (column.size !== null) {
+          extra += `size=${column.size}`
+        }
+        if (column.d !== null) {
+          if (extra.length > 0) {
+            extra += ', '
+          }
+          extra += `d=${column.d}`
+        }
+        return extra
+      } else if (column.column_type === 'enum') {
+        return `(${column.enums.join(', ')})`
+      } else if (column.column_type === 'set') {
+        return `(${column.sets.join(', ')})`
+      } else if (['int', 'char', 'varchar', 'binary', 'varbinary', 'tinyint', 'size="small"int', 'mediumint', 'bigint'].includes(column.column_type)) {
+        return column.size !== null ? `size=${column.size}` : ''
+      }
+      return null
+    },
+    closed (event) {
+      const { success } = event
+      console.debug('closed dialog', event)
+      if (success) {
+        const toast = useToastInstance()
+        toast.success(this.$t('success.table.semantics'))
+        this.cacheStore.reloadTable()
+      }
+      this.dialogSemantic = false
+    },
+    update () {
+      this.loading = true
+      const tableService = useTableService()
+      tableService.update(this.$route.params.database_id, this.$route.params.table_id, this.modify)
+        .then(() => {
+          this.loading = false
+          const toast = useToastInstance()
+          toast.success(this.$t('success.table.updated'))
+          this.$emit('close', { success: true })
+          this.cacheStore.reloadTable()
+        })
+        .catch(({ code }) => {
+          this.loading = false
+          const toast = useToastInstance()
+          toast.error(this.$t(code))
+        })
+        .finally(() => {
+          this.loading = false
+        })
+    },
+    askDelete () {
+      if (!confirm(this.$t('pages.table.delete.subtitle', { table: this.table.internal_name }))) {
+        return
+      }
+      this.loadingDelete = true
+      const tableService = useTableService()
+      tableService.remove(this.database.id, this.table.id)
+        .then(() => {
+          console.info('Deleted table with id ', this.table.id)
+          this.cacheStore.reloadDatabase()
+          const toast = useToastInstance()
+          toast.success('Successfully deleted table with id ' + this.table.id)
+          this.$router.push(`/database/${this.$route.params.database_id}/table`)
+        })
+        .catch(({code, message}) => {
+          const toast = useToastInstance()
+          toast.error(this.$t(code))
+        })
+        .finally(() => {
+          this.loadingDelete = false
+        })
+    }
+  }
+}
+</script>