diff --git a/.docs/DEVELOPMENT.md b/.docs/DEVELOPMENT.md index 4e5456a70a5fa12163fd9a69eb909895171f482f..db427a33f97c4b7afdd0a6448e465577f10e4e77 100644 --- a/.docs/DEVELOPMENT.md +++ b/.docs/DEVELOPMENT.md @@ -85,4 +85,8 @@ cluster. The full CI/CD pipeline Helm chart is documented in the [`fda-deployment`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-deployment/-/tree/master/charts/dbrepo-devops) -repository. \ No newline at end of file +repository. + +## Documentation + +For consistency reasons across the documentation, the resolution needs to be 1280x800 (16:10 ratio) \ No newline at end of file diff --git a/.docs/images/mark.psd b/.docs/images/mark.psd new file mode 100644 index 0000000000000000000000000000000000000000..2fd9b01604470ebbd270fc089fd5c890461f360e Binary files /dev/null and b/.docs/images/mark.psd differ diff --git a/.docs/images/screenshots/create-database-step-1.png b/.docs/images/screenshots/create-database-step-1.png new file mode 100644 index 0000000000000000000000000000000000000000..ccea22e4f22844f9da417a9a55e6f5192fd7bc1a Binary files /dev/null and b/.docs/images/screenshots/create-database-step-1.png differ diff --git a/.docs/images/screenshots/create-database-step-2.png b/.docs/images/screenshots/create-database-step-2.png new file mode 100644 index 0000000000000000000000000000000000000000..ae399a58eda6a5a7cb0a9e9381d2981ddae938f2 Binary files /dev/null and b/.docs/images/screenshots/create-database-step-2.png differ diff --git a/.docs/images/screenshots/create-database-step-3.png b/.docs/images/screenshots/create-database-step-3.png new file mode 100644 index 0000000000000000000000000000000000000000..6381712733252828a68084daf471be1449524b4b Binary files /dev/null and b/.docs/images/screenshots/create-database-step-3.png differ diff --git a/.docs/images/screenshots/import-dataset-step-1.png b/.docs/images/screenshots/import-dataset-step-1.png new file mode 100644 index 0000000000000000000000000000000000000000..0ac971983db7fd533807f821bbf13984571c0a51 Binary files /dev/null and b/.docs/images/screenshots/import-dataset-step-1.png differ diff --git a/.docs/images/screenshots/import-dataset-step-2.png b/.docs/images/screenshots/import-dataset-step-2.png new file mode 100644 index 0000000000000000000000000000000000000000..71eba84a62eb322cd80e15038bdb1ecbb73db053 Binary files /dev/null and b/.docs/images/screenshots/import-dataset-step-2.png differ diff --git a/.docs/images/screenshots/import-dataset-step-3.png b/.docs/images/screenshots/import-dataset-step-3.png new file mode 100644 index 0000000000000000000000000000000000000000..4f763332cab44a8cf629151a0def8fac577135bd Binary files /dev/null and b/.docs/images/screenshots/import-dataset-step-3.png differ diff --git a/.docs/images/screenshots/import-dataset-step-4.png b/.docs/images/screenshots/import-dataset-step-4.png new file mode 100644 index 0000000000000000000000000000000000000000..888a3557d74baebfb583a74535f5514d8378c7f6 Binary files /dev/null and b/.docs/images/screenshots/import-dataset-step-4.png differ diff --git a/.docs/images/screenshots/import-dataset-step-5.png b/.docs/images/screenshots/import-dataset-step-5.png new file mode 100644 index 0000000000000000000000000000000000000000..b5f441247633b6fe47d84c02737b30392be9a408 Binary files /dev/null and b/.docs/images/screenshots/import-dataset-step-5.png differ diff --git a/.docs/images/screenshots/import-dataset-step-6.png b/.docs/images/screenshots/import-dataset-step-6.png new file mode 100644 index 0000000000000000000000000000000000000000..734a4f0fa3d620e6d93b53b98158f0061ac7b622 Binary files /dev/null and b/.docs/images/screenshots/import-dataset-step-6.png differ diff --git a/.docs/images/screenshots/import-dataset-step-7.png b/.docs/images/screenshots/import-dataset-step-7.png new file mode 100644 index 0000000000000000000000000000000000000000..deccd46b17a9d8d2f36dc296f9e3895a662961b9 Binary files /dev/null and b/.docs/images/screenshots/import-dataset-step-7.png differ diff --git a/.docs/usage-overview.md b/.docs/usage-overview.md index d33852ff7b10850bcbfd036d00ee8ec185f580ef..4aff3f05eca2eef78380927384452b498ce7213e 100644 --- a/.docs/usage-overview.md +++ b/.docs/usage-overview.md @@ -4,49 +4,351 @@ author: Martin Weise # Overview -In the following we give usage examples of the seven most important use-cases we identified. They are allowed to occur -subsequently. +We give usage examples of the seven most important use-cases we identified. ## Create Database -!!! abstract "User wants to create a database in DBRepo" +A user wants to create a database in DBRepo. - aaaa +=== "UI" -aaa + Login and press the ":material-plus: DATABASE" button on the top right :material-numeric-1-circle-outline: as seen in Figure 1. + + <figure markdown> + { .img-border } + <figcaption>Figure 1: Open the create database dialog.</figcaption> + </figure> + + Give the database a meaningful title :material-numeric-1-circle-outline: that describes the contained data in few + words and select a pre-configured container :material-numeric-2-circle-outline: from the list for this database. To + finally create the database, press "Create" :material-numeric-3-circle-outline: as seen in Figure 2. + + <figure markdown> + { .img-border } + <figcaption>Figure 2: Create database form.</figcaption> + </figure> + + After a few seconds, you can see the created database in the "Recent Databases" list, as seen in Figure 3. + + <figure markdown> + { .img-border } + <figcaption>Figure 3: View the created database.</figcaption> + </figure> + +=== "Terminal" + + Obtain an access token: + + ```bash + curl -sSL \ + -X POST \ + -d 'username=foo&password=bar&grant_type=password&client_id=dbrepo-client&scope=openid&client_secret=MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG' \ + http://localhost/api/auth/realms/dbrepo/protocol/openid-connect/token | jq .access_token + ``` + + !!! note + + Please note that the `client_secret` is different for your DBRepo instance. This is a default client secret that + likely has been replaced. Please contact your DBRepo administrator to get the `client_secret` for your instance. + Similar you need to replace `localhost` with your actual DBRepo instance hostname, e.g. `test.dbrepo.tuwien.ac.at`. + + Then list all available containers with their database engine descriptions and obtain a container id. + + ```bash + curl -sSL \ + http://localhost/api/container | jq + ``` + + Create a public databse with the container id from the previous step. You can also create a private database in this + step, others can still see the metadata. + + ```bash + curl -sSL \ + -X POST \ + -d '{"name":"Danube Water Quality Measurements","container_id":1,"is_public":true}' \ + http://localhost/api/database | jq .id + ``` + +=== "Python" + + Obtain an access token: + + ```python + import requests + + auth = requests.post("http://localhost/api/auth/realms/dbrepo/protocol/openid-connect/token", data={ + "username": "foo", + "password": "bar", + "grant_type": "password", + "client_id": "dbrepo-client", + "scope": "openid", + "client_secret": "MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG" + }) + token = auth.json()["access_token"] + print(token) + ``` + + !!! note + + Please note that the `client_secret` is different for your DBRepo instance. This is a default client secret that + likely has been replaced. Please contact your DBRepo administrator to get the `client_secret` for your instance. + Similar you need to replace `localhost` with your actual DBRepo instance hostname, e.g. `test.dbrepo.tuwien.ac.at`. + + Then list all available containers with their database engine descriptions and obtain a container id. + + ```python + import requests + + containers = requests.get("http://localhost/api/container") + print(containers.json()) + ``` + + Create a public databse with the container id from the previous step. You can also create a private database in this + step, others can still see the metadata. + + ```python + import requests + + database = requests.post("http://localhost/api/database", headers={ + "Authentication": "Bearer " + token + }, json={ + "name": "Danube Water Quality Measurements", + "container_id": 1, + "is_public": True + }) + print(database.json()["id"]) + ``` ## Import Dataset -!!! abstract "User wants to import a static dataset stored as .csv file" +A user wants to import a static dataset (e.g. from a .csv file) into a database that they have at least `write-own` +access to. This is the default for self-created databases like above in [Create Databases](#create-database). + +=== "UI" + + Login and select a database where you have at least `write-all` access (this is the case for e.g. self-created + databases). Click the ":material-cloud-upload: IMPORT CSV" button :material-numeric-1-circle-outline: as seen in + Figure 4. + + <figure markdown> + { .img-border } + <figcaption>Figure 4: Open the import CSV form.</figcaption> + </figure> + + Provide the table name :material-numeric-1-circle-outline: and optionally a table description :material-numeric-2-circle-outline: + as seen in Figure 5. + + <figure markdown> + { .img-border } + <figcaption>Figure 5: Basic table information.</figcaption> + </figure> + + Next, provide the dataset metadata that is necessary for import into the table by providing the dataset separator + (e.g. `,` or `;` or `\t`) in :material-numeric-1-circle-outline:. If your dataset has a header line (the first line + containing the names of the columns) set the number of lines to skip to 1 in field :material-numeric-2-circle-outline:. + If your dataset contains more lines that should be ignored, set the number of lines accordingly. If your dataset + contains quoted values, indicate this by setting the field :material-numeric-3-circle-outline: accordingly + in Figure 6. + + If your dataset contains encodings for `NULL` (e.g. `NA`), provide this encoding information + in :material-numeric-4-circle-outline:. Similar, if it contains encodings for boolean `true` (e.g. `1` or `YES`), + provide this encoding information in :material-numeric-5-circle-outline:. For boolean `false` (e.g. `0` or `NO`), + provide this information in :material-numeric-6-circle-outline:. + + <figure markdown> + { .img-border } + <figcaption>Figure 6: Dataset metadata necessary for import.</figcaption> + </figure> + + Select the dataset file from your local computer by clicking :material-numeric-1-circle-outline: or dragging the + dataset file onto the field in Figure 7. + + <figure markdown> + { .img-border } + <figcaption>Figure 7: Dataset import file.</figcaption> + </figure> + + The table schema is suggested based on heuristics between the upload and the suggested schema in Figure 8. If your + dataset has no column names present, e.g. you didn't provide a *Number of lines to skip* (c.f. Figure 6), then you + need to provide a column name in :material-numeric-1-circle-outline:. Provide a data type from the list of MySQL 8 + available data types :material-numeric-2-circle-outline:. Indicate if the column is (part of) a primary key + :material-numeric-4-circle-outline: or if `NULL` values are allowed in :material-numeric-5-circle-outline: or if a + unique constraint is needed (no values in this column are then allowed to repeat) in :material-numeric-6-circle-outline:. + + Optionally, you can remove table column definitions by clicking the "REMOVE" button or add additional table column + definitions by clicking the "ADD COLUMN" button in Figure 8. + + <figure markdown> + { .img-border } + <figcaption>Figure 8: Confirm the table schema and provide missing information.</figcaption> + </figure> + + If a table column data type is of `DATE` or `TIMESTAMP` (or similar), provide a date format + :material-numeric-3-circle-outline: from the list of available formats that are most similar to the one in the + dataset as seen in Figure 9. + + <figure markdown> + { .img-border } + <figcaption>Figure 9: Confirm the table schema and provide missing information.</figcaption> + </figure> + + When you are finished with the table schema definition, the dataset is imported and a table is created. You are + being redirected automatically to the table info page upon success, navigate to the "DATA" tab + :material-numeric-1-circle-outline:. You can still delete the table :material-numeric-2-circle-outline: as long as + no identifier is associated with it :material-numeric-3-circle-outline:. + + Public databases allow anyone to download :material-numeric-4-circle-outline: the table data as dataset file. Also + it allows anyone to view the recent history of inserted data :material-numeric-5-circle-outline: dialog. + + <figure markdown> + { .img-border } + <figcaption>Figure 10: Table data.</figcaption> + </figure> - aaaa +=== "Terminal" + + Obtain an access token: + + ```bash + curl -sSL \ + -X POST \ + -d 'username=foo&password=bar&grant_type=password&client_id=dbrepo-client&scope=openid&client_secret=MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG' \ + http://localhost/api/auth/realms/dbrepo/protocol/openid-connect/token | jq .access_token + ``` + + !!! note + + Please note that the `client_secret` is different for your DBRepo instance. This is a default client secret that + likely has been replaced. Please contact your DBRepo administrator to get the `client_secret` for your instance. + Similar you need to replace `localhost` with your actual DBRepo instance hostname, e.g. `test.dbrepo.tuwien.ac.at`. + + Select a database where you have at least `write-all` access (this is the case for e.g. self-created databases). + + Upload the dataset via the [`tusc`](https://github.com/adhocore/tusc.sh) terminal application or use Python and + copy the file key. + + ```bash + tusc -H http://localhost/api/upload/files -f danube.csv -b /dbrepo-upload/ + ``` + + Analyse the dataset and get the table column names and datatype suggestion. + + ```bash + curl -sSL \ + -X POST \ + -d '{"filename":"FILEKEY","separator":","}' \ + http://localhost/api/analyse/determinedt | jq + ``` + + Provide the table name and optionally a table description along with the table columns. + + ```bash + curl -sSL \ + -X POST \ + -d '{"name":"Danube water levels","description":"Measurements of the river danube water levels","columns":[{"name":"datetime","type":"timestamp","dfid":1,"primary_key":false,"null_allowed":true},{"name":"level","type":"bigint","size":255,"primary_key":false,"null_allowed":true}]}' \ + http://localhost/api/database/1/table | jq .id + ``` + + Next, provide the dataset metadata that is necessary for import into the table by providing the dataset separator + (e.g. `,` or `;` or `\t`). If your dataset has a header line (the first line containing the names of the columns) + set the number of lines to skip to 1. If your dataset contains more lines that should be ignored, set the number of + lines accordingly. If your dataset contains quoted values, indicate this by setting the field accordingly. + + If your dataset contains encodings for `NULL` (e.g. `NA`), provide this encoding information. Similar, if it + contains encodings for boolean `true` (e.g. `1` or `YES`), provide this encoding information. For boolean `false` + (e.g. `0` or `NO`), provide this information. + + ```bash + curl -sSL \ + -X POST \ + -d '{"location":"FILEKEY","separator":",","quote":"\"","skip_lines":1,"null_element":"NA"}' \ + http://localhost/api/database/1/table/1/data/import | jq + ``` + + When you are finished with the table schema definition, the dataset is imported and a table is created. View the + table data: + + ```bash + curl -sSL \ + http://localhost/api/database/1/table/1/data?page=0&size=10 | jq + ``` + +=== "Python" + + 123 ## Import Database Dump -!!! abstract "User wants to import a static database dump stored as .sql file" +TBD + +=== "UI" + + ABC + +=== "HTTP API" - aaaa + DEF + +=== "JDBC API" + + 123 ## Import Live Data -!!! abstract "User wants to import continuous measurements from a sensor" +TBD + +=== "UI" + + ABC + +=== "HTTP API" - aaaa + DEF + +=== "JDBC API" + + 123 + +=== "AMQP API" + + 456 ## Export Subset -!!! abstract "User wants to export a subset as .csv file" +TBD + +=== "UI" - aaaa + ABC + +=== "HTTP API" + + DEF + +=== "JDBC API" + + 123 ## Assign Database PID -!!! abstract "User wants to assign a persistent identifier to a database" +TBD + +=== "UI" - aaaa + ABC + +=== "HTTP API" + + DEF ## Private Database & Access -!!! abstract "User wants to make the database private and give only certain users access" +TBD + +=== "UI" + + ABC + +=== "HTTP API" - aaaa \ No newline at end of file + DEF \ No newline at end of file diff --git a/dbrepo-ui/components/database/DatabaseToolbar.vue b/dbrepo-ui/components/database/DatabaseToolbar.vue index 18427cf7a8ded9ff3f70256cd51598d89a86a0db..f43f35f4c115468d37bb155b53deeb2381a6b5a9 100644 --- a/dbrepo-ui/components/database/DatabaseToolbar.vue +++ b/dbrepo-ui/components/database/DatabaseToolbar.vue @@ -2,7 +2,7 @@ <div v-if="database"> <v-toolbar flat> <v-toolbar-title> - <span v-if="$vuetify.breakpoint.lgAndUp">{{ database.name }}</span> + <span v-if="$vuetify.breakpoint.lgAndUp" v-text="database.name" /> <v-tooltip bottom> <template v-slot:activator="{ on, attrs }"> <v-icon @@ -29,25 +29,25 @@ <v-spacer /> <v-toolbar-title> <v-btn v-if="canImportCsv" class="mb-1" :to="`/database/${$route.params.database_id}/table/import`"> - <v-icon v-if="$vuetify.breakpoint.lgAndUp" left>mdi-cloud-upload</v-icon> Import .csv + <v-icon left>mdi-cloud-upload</v-icon> <span v-if="$vuetify.breakpoint.xlOnly">Import</span> csv </v-btn> <DownloadButton v-if="database && database.identifier" :pid="database.identifier.id" class="mr-2 mb-1"> - <v-icon left>mdi-code-tags</v-icon> Identifier .xml + <v-icon left>mdi-code-tags</v-icon> <span v-if="$vuetify.breakpoint.xlOnly">Identifier</span> xml </DownloadButton> <v-btn v-if="canCreateSubset" color="secondary" class="mb-1 white--text" :to="`/database/${$route.params.database_id}/query/create`"> - <v-icon v-if="$vuetify.breakpoint.lgAndUp" left>mdi-wrench</v-icon> Create Subset + <v-icon v-if="$vuetify.breakpoint.lgAndUp" left>mdi-wrench</v-icon> <span v-if="$vuetify.breakpoint.xlOnly">Create</span> Subset </v-btn> <v-btn v-if="canCreateView" color="secondary" class="mb-1 white--text" :to="`/database/${$route.params.database_id}/view/create`"> - <v-icon v-if="$vuetify.breakpoint.lgAndUp" left>mdi-view-carousel-outline</v-icon> Create View + <v-icon v-if="$vuetify.breakpoint.lgAndUp" left>mdi-view-carousel-outline</v-icon> <span v-if="$vuetify.breakpoint.xlOnly">Create</span> View </v-btn> <v-btn v-if="canCreateTable" color="secondary" class="mb-1" :to="`/database/${$route.params.database_id}/table/create`"> - <v-icon v-if="$vuetify.breakpoint.lgAndUp" left>mdi-table-large-plus</v-icon> Create Table + <v-icon v-if="$vuetify.breakpoint.lgAndUp" left>mdi-table-large-plus</v-icon> <span v-if="$vuetify.breakpoint.xlOnly">Create</span> Table </v-btn> <v-btn v-if="canCreateIdentifier" color="primary" class="mb-1" :to="`/database/${$route.params.database_id}/persist`"> - <v-icon v-if="$vuetify.breakpoint.lgAndUp" left>mdi-identifier</v-icon> Get PID + <v-icon v-if="$vuetify.breakpoint.lgAndUp" left>mdi-identifier</v-icon> <span v-if="$vuetify.breakpoint.xlOnly">Get</span> PID </v-btn> </v-toolbar-title> <template v-slot:extension> diff --git a/dbrepo-ui/components/table/TableToolbar.vue b/dbrepo-ui/components/table/TableToolbar.vue index e96d2752bb6cae794ce1a6ae6d690004701e872c..3c4935683718f353c0d54959fbdfbb88f6587e2b 100644 --- a/dbrepo-ui/components/table/TableToolbar.vue +++ b/dbrepo-ui/components/table/TableToolbar.vue @@ -21,19 +21,19 @@ <v-icon left>mdi-delete</v-icon> Delete <span v-if="selection.length > 1"> {{ selection.length }}</span> </v-btn> <v-btn v-if="canImportCsv" class="mb-1" :to="`/database/${$route.params.database_id}/table/${$route.params.table_id}/import`"> - <v-icon left>mdi-cloud-upload</v-icon> Import .csv + <v-icon left>mdi-cloud-upload</v-icon> <span v-if="$vuetify.breakpoint.xlOnly">Import</span> csv </v-btn> <v-btn v-if="canExecuteQuery" class="mb-1" :to="`/database/${$route.params.database_id}/query/create?tid=${$route.params.table_id}`" color="secondary"> - <v-icon left>mdi-wrench</v-icon> Create Subset + <v-icon left>mdi-wrench</v-icon> <span v-if="$vuetify.breakpoint.xlOnly">Create</span> Subset </v-btn> <v-btn v-if="canCreateView" class="mb-1" :to="`/database/${$route.params.database_id}/view/create?tid=${$route.params.table_id}`" color="secondary"> - <v-icon left>mdi-view-carousel</v-icon> Create View + <v-icon left>mdi-view-carousel</v-icon> <span v-if="$vuetify.breakpoint.xlOnly">Create</span> View </v-btn> <v-btn v-if="canDropTable" class="mb-1" color="error" @click="dropTableDialog = true"> - <v-icon left>mdi-delete</v-icon> Drop Table + <v-icon left>mdi-delete</v-icon> <span v-if="$vuetify.breakpoint.xlOnly">Drop</span> Table </v-btn> <v-btn v-if="canGetPid" class="mb-1" color="primary" :to="`/database/${$route.params.database_id}/table/${$route.params.table_id}/persist`"> - <v-icon left>mdi-content-save-outline</v-icon> Get PID + <v-icon left>mdi-content-save-outline</v-icon> <span v-if="$vuetify.breakpoint.xlOnly">Get</span> PID </v-btn> </v-toolbar-title> </v-toolbar> diff --git a/dbrepo-ui/pages/database/_database_id/info.vue b/dbrepo-ui/pages/database/_database_id/info.vue index 1d9eb4d45730af3c9277876331f2d3ff373f6f78..284395ed0e7e5aa39bdec7363ee80b16ba085c97 100644 --- a/dbrepo-ui/pages/database/_database_id/info.vue +++ b/dbrepo-ui/pages/database/_database_id/info.vue @@ -19,11 +19,15 @@ <v-list-item-title> Database Visibility </v-list-item-title> - <v-list-item-content v-if="!loading && database" v-text="`${database.is_public ? 'Public' : 'Private'}`" /> + <v-list-item-content v-if="database" v-text="`${database.is_public ? 'Public' : 'Private'}`" /> + <v-list-item-title class="mt-2"> + Database Name + </v-list-item-title> + <v-list-item-content v-if="database" v-text="database.name" /> <v-list-item-title class="mt-2"> Database Internal Name </v-list-item-title> - <v-list-item-content v-if="!loading" v-text="internal_name" /> + <v-list-item-content v-if="database" v-text="database.internal_name" /> <v-list-item-title class="mt-2"> Database Owner </v-list-item-title>