From b0ab693c3805009aa5fe1065af71826cb9bec7d2 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Thu, 27 Jul 2023 03:43:05 +0000 Subject: [PATCH 001/111] load en translations in parallel --- config/context_processors.py | 9 +++++++- mathesar/templates/mathesar/index.html | 32 ++++++++++++++++++++++---- mathesar/utils/frontend.py | 15 +++++++++++- mathesar_ui/src/App.svelte | 29 ++++++++++++++--------- mathesar_ui/src/i18n/i18n-load.ts | 8 +++++++ 5 files changed, 75 insertions(+), 18 deletions(-) diff --git a/config/context_processors.py b/config/context_processors.py index da5e98a752..800fbcc31d 100644 --- a/config/context_processors.py +++ b/config/context_processors.py @@ -4,9 +4,16 @@ def frontend_settings(request): + """ + Hard coding this for now + but will be taken from users model + and cookies later on + """ + preferred_language = 'en' frontend_settings = { 'development_mode': settings.MATHESAR_MODE == 'DEVELOPMENT', - 'manifest_data': get_manifest_data(), + 'manifest_data': get_manifest_data(preferred_language), + 'preferred_language': preferred_language, 'live_demo_mode': getattr(settings, 'MATHESAR_LIVE_DEMO', False), 'live_demo_username': getattr(settings, 'MATHESAR_LIVE_DEMO_USERNAME', None), 'live_demo_password': getattr(settings, 'MATHESAR_LIVE_DEMO_PASSWORD', None), diff --git a/mathesar/templates/mathesar/index.html b/mathesar/templates/mathesar/index.html index e26130095d..2d4e616ef6 100644 --- a/mathesar/templates/mathesar/index.html +++ b/mathesar/templates/mathesar/index.html @@ -4,9 +4,11 @@ {% block title %}Home{% endblock %} {% block styles %} - {% if not development_mode %} {% for css_file in manifest_data.module_css %} - - {% endfor %} {% endif %} + {% if not development_mode %} + {% for css_file in manifest_data.module_css %} + + {% endfor %} + {% endif %} {% endblock %} {% block scripts %} @@ -17,6 +19,17 @@ {% endfor %} {% endif %} + + {% if development_mode %} @@ -52,11 +65,20 @@ > + {% endif %} diff --git a/mathesar/utils/frontend.py b/mathesar/utils/frontend.py index 428017f7f0..78d7f4433c 100644 --- a/mathesar/utils/frontend.py +++ b/mathesar/utils/frontend.py @@ -4,7 +4,7 @@ from django.core.cache import cache -def get_manifest_data(): +def get_manifest_data(preferred_language): # We don't need the manifest data for local development. if settings.MATHESAR_MODE == 'DEVELOPMENT': return {} @@ -18,14 +18,27 @@ def get_manifest_data(): with open(settings.MATHESAR_MANIFEST_LOCATION, 'r') as manifest_file: raw_data = json.loads(manifest_file.read()) + translations_file_path = get_translations_file_path(preferred_language) + module_data = raw_data['src/main.ts'] manifest_data['module_css'] = [filename for filename in module_data['css']] manifest_data['module_js'] = module_data['file'] + # Purposefully letting it fail if the translations file for that lang is not in the bundle + manifest_data['module_translations_file'] = raw_data[translations_file_path["module"]]["file"] + legacy_data = raw_data['src/main-legacy.ts'] manifest_data['legacy_polyfill_js'] = raw_data['vite/legacy-polyfills-legacy']['file'] manifest_data['legacy_js'] = legacy_data['file'] + manifest_data['legacy_translations_file'] = raw_data[translations_file_path["legacy"]]["file"] # Cache data for 1 hour cache.set('manifest_data', manifest_data, 60 * 60) return manifest_data + + +def get_translations_file_path(preferred_language): + return { + "module": f'src/i18n/{preferred_language}/index.ts', + "legacy": f'src/i18n/{preferred_language}/index-legacy.ts' + } diff --git a/mathesar_ui/src/App.svelte b/mathesar_ui/src/App.svelte index 398725674e..1c7fb53f6e 100644 --- a/mathesar_ui/src/App.svelte +++ b/mathesar_ui/src/App.svelte @@ -19,21 +19,28 @@ import { modal } from './stores/modal'; import { setReleasesStoreInContext } from './stores/releases'; import ModalRecordSelector from './systems/record-selector/ModalRecordSelector.svelte'; - import { loadLocaleAsync } from './i18n/i18n-load'; import { setLocale } from './i18n/i18n-svelte'; + import type { Locales } from './i18n/i18n-types'; + import { loadTranslationsIntoMemory } from './i18n/i18n-load'; - /** - * Later the translations file will be loaded - * in parallel to the FE's first chunk - */ let isTranslationsLoaded = false; - (() => { - void loadLocaleAsync('en').then(() => { - setLocale('en'); + const checkTranslationsInterval = setInterval(() => { + // eslint-disable-next-line prefer-destructuring + const translations: + | { lang: Locales; translationStrings: string } + | undefined = + // @ts-expect-error added by index.html + window.translations; + if (translations) { + loadTranslationsIntoMemory( + translations.lang, + JSON.parse(translations.translationStrings), + ); + setLocale(translations.lang); isTranslationsLoaded = true; - return true; - }); - })(); + clearInterval(checkTranslationsInterval); + } + }, 100); const commonData = preloadCommonData(); if (commonData?.user) { diff --git a/mathesar_ui/src/i18n/i18n-load.ts b/mathesar_ui/src/i18n/i18n-load.ts index 02f828295e..6e0aabee3b 100644 --- a/mathesar_ui/src/i18n/i18n-load.ts +++ b/mathesar_ui/src/i18n/i18n-load.ts @@ -30,3 +30,11 @@ export async function loadLocaleAsync(locale: Locales): Promise { updateTranslationsDictionary(locale, await importLocaleAsync(locale)); loadFormatters(locale); } + +export function loadTranslationsIntoMemory( + locale: Locales, + translations: Translations, +) { + updateTranslationsDictionary(locale, translations); + loadFormatters(locale); +} From b1ceaa9ea4c07584e373e4bf394b1888ad9a0cc9 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Thu, 27 Jul 2023 09:17:21 +0000 Subject: [PATCH 002/111] BE - save users lang in the db --- config/context_processors.py | 18 ++++++++++++------ mathesar/api/ui/serializers/users.py | 1 + .../migrations/0004_user_preferred_language.py | 18 ++++++++++++++++++ mathesar/models/users.py | 1 + mathesar/views.py | 1 + 5 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 mathesar/migrations/0004_user_preferred_language.py diff --git a/config/context_processors.py b/config/context_processors.py index 800fbcc31d..1828e543bb 100644 --- a/config/context_processors.py +++ b/config/context_processors.py @@ -4,12 +4,7 @@ def frontend_settings(request): - """ - Hard coding this for now - but will be taken from users model - and cookies later on - """ - preferred_language = 'en' + preferred_language = get_user_preferred_language_from_request(request) frontend_settings = { 'development_mode': settings.MATHESAR_MODE == 'DEVELOPMENT', 'manifest_data': get_manifest_data(preferred_language), @@ -22,3 +17,14 @@ def frontend_settings(request): if frontend_settings['development_mode'] is True: frontend_settings['client_dev_url'] = settings.MATHESAR_CLIENT_DEV_URL return frontend_settings + + +def get_user_preferred_language_from_request(request): + # https://docs.djangoproject.com/en/4.2/topics/i18n/translation/#how-django-discovers-language-preference + # This automatically fallbacks to en because of https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-LANGUAGE_CODE + lang_from_locale_middleware = request.LANGUAGE_CODE + + if request.user.is_authenticated: + return request.user.preferred_language or lang_from_locale_middleware + else: + return lang_from_locale_middleware diff --git a/mathesar/api/ui/serializers/users.py b/mathesar/api/ui/serializers/users.py index 26fafd0cde..78b657cb97 100644 --- a/mathesar/api/ui/serializers/users.py +++ b/mathesar/api/ui/serializers/users.py @@ -40,6 +40,7 @@ class Meta: 'is_superuser', 'database_roles', 'schema_roles', + 'preferred_language' ] extra_kwargs = { 'password': {'write_only': True}, diff --git a/mathesar/migrations/0004_user_preferred_language.py b/mathesar/migrations/0004_user_preferred_language.py new file mode 100644 index 0000000000..be05706c91 --- /dev/null +++ b/mathesar/migrations/0004_user_preferred_language.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.14 on 2023-07-27 09:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mathesar', '0003_datafile_max_level'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='preferred_language', + field=models.CharField(blank=True, default='en', max_length=30), + ), + ] diff --git a/mathesar/models/users.py b/mathesar/models/users.py index 5bcae308bc..025d462b8d 100644 --- a/mathesar/models/users.py +++ b/mathesar/models/users.py @@ -15,6 +15,7 @@ class User(AbstractUser): full_name = models.CharField(max_length=255, blank=True, null=True) short_name = models.CharField(max_length=255, blank=True, null=True) password_change_needed = models.BooleanField(default=False) + preferred_language = models.CharField(max_length=30, blank=True, default='en') class Role(models.TextChoices): diff --git a/mathesar/views.py b/mathesar/views.py index acf58998d2..b1cd276d76 100644 --- a/mathesar/views.py +++ b/mathesar/views.py @@ -111,6 +111,7 @@ def get_common_data(request, database=None, schema=None): 'user': get_user_data(request), 'live_demo_mode': getattr(settings, 'MATHESAR_LIVE_DEMO', False), 'current_release_tag_name': __version__, + 'supported_languages': dict(getattr(settings, 'LANGUAGES', [])), } From 8e9f5bb821332fe5a89d469f7ce1700e7f3635fc Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Thu, 27 Jul 2023 09:44:03 +0000 Subject: [PATCH 003/111] added locale middleware --- config/settings/common_settings.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/config/settings/common_settings.py b/config/settings/common_settings.py index 3becf9b3a6..2e52043a01 100644 --- a/config/settings/common_settings.py +++ b/config/settings/common_settings.py @@ -15,6 +15,7 @@ from decouple import Csv, config as decouple_config from dj_database_url import parse as db_url +from django.utils.translation import gettext_lazy # We use a 'tuple' with pipes as delimiters as decople naively splits the global @@ -50,6 +51,7 @@ def pipe_delim(pipe_string): "django.middleware.security.SecurityMiddleware", "whitenoise.middleware.WhiteNoiseMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.locale.LocaleMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", @@ -247,3 +249,10 @@ def pipe_delim(pipe_string): } # List of Template names that contains additional script tags to be added to the base template BASE_TEMPLATE_ADDITIONAL_SCRIPT_TEMPLATES = [] + +# i18n +LANGUAGES = [ + ('en', gettext_lazy('English')), + ('ja', gettext_lazy('Japanese')), +] +LANGUAGE_COOKIE_NAME = 'user_preferred_language' From 0917c8c8bc4e32a38c33328eaaa284f51001dfb0 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Thu, 27 Jul 2023 15:16:24 +0530 Subject: [PATCH 004/111] preferred lang dropdown in profile page --- mathesar_ui/src/api/users.ts | 1 + mathesar_ui/src/stores/users.ts | 4 ++++ .../SelectPreferredLanguage.svelte | 20 +++++++++++++++++ .../UserDetailsForm.svelte | 22 ++++++++++++++++++- mathesar_ui/src/utils/preloadData.ts | 1 + 5 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 mathesar_ui/src/systems/users-and-permissions/SelectPreferredLanguage.svelte diff --git a/mathesar_ui/src/api/users.ts b/mathesar_ui/src/api/users.ts index f90a168396..50c8ccf9a2 100644 --- a/mathesar_ui/src/api/users.ts +++ b/mathesar_ui/src/api/users.ts @@ -12,6 +12,7 @@ export interface UnsavedUser { email: string | null; username: string; password: string; + preferred_language: string; } export type UserRole = 'viewer' | 'editor' | 'manager'; diff --git a/mathesar_ui/src/stores/users.ts b/mathesar_ui/src/stores/users.ts index 2ee528618c..aac2107f01 100644 --- a/mathesar_ui/src/stores/users.ts +++ b/mathesar_ui/src/stores/users.ts @@ -29,6 +29,8 @@ export class UserModel { readonly username: User['username']; + readonly preferredLanguage: User['preferred_language']; + private databaseRoles: Map; private schemaRoles: Map; @@ -45,6 +47,7 @@ export class UserModel { this.fullName = userDetails.full_name; this.email = userDetails.email; this.username = userDetails.username; + this.preferredLanguage = userDetails.preferred_language; } hasPermission( @@ -119,6 +122,7 @@ export class UserModel { schema_roles: [...this.schemaRoles.values()], full_name: this.fullName, email: this.email, + preferred_language: this.preferredLanguage, }; } diff --git a/mathesar_ui/src/systems/users-and-permissions/SelectPreferredLanguage.svelte b/mathesar_ui/src/systems/users-and-permissions/SelectPreferredLanguage.svelte new file mode 100644 index 0000000000..418d3e30dd --- /dev/null +++ b/mathesar_ui/src/systems/users-and-permissions/SelectPreferredLanguage.svelte @@ -0,0 +1,20 @@ + + + + + {% endblock %} diff --git a/mathesar/urls.py b/mathesar/urls.py index 931556ab67..0bafa8e3a2 100644 --- a/mathesar/urls.py +++ b/mathesar/urls.py @@ -48,6 +48,7 @@ path('administration/update/', views.admin_home, name='admin_update'), path('db/', views.home, name='db_home'), path('db//', views.schemas, name='schemas'), + path('i18n/', include('django.conf.urls.i18n')), re_path( r'^db/(?P\w+)/(?P\w+)/', views.schema_home, diff --git a/mathesar_ui/src/i18n/i18n-types.ts b/mathesar_ui/src/i18n/i18n-types.ts index 9b8ff873e2..27f341c5f9 100644 --- a/mathesar_ui/src/i18n/i18n-types.ts +++ b/mathesar_ui/src/i18n/i18n-types.ts @@ -3,196 +3,195 @@ /* eslint-disable eslint-comments/no-unlimited-disable */ /* eslint eslint-comments/disable-enable-pair: [error, {allowWholeFile: true}] */ /* eslint-disable */ -import type { - BaseTranslation as BaseTranslationType, - LocalizedString, -} from 'typesafe-i18n'; +import type { BaseTranslation as BaseTranslationType, LocalizedString } from 'typesafe-i18n' -export type BaseTranslation = BaseTranslationType; -export type BaseLocale = 'en'; +export type BaseTranslation = BaseTranslationType +export type BaseLocale = 'en' -export type Locales = 'en' | 'ja'; +export type Locales = + | 'en' + | 'ja' -export type Translation = RootTranslation; +export type Translation = RootTranslation -export type Translations = RootTranslation; +export type Translations = RootTranslation type RootTranslation = { - general: { - /** - * I​m​p​o​r​t - */ - import: string; - /** - * O​n​e​ ​t​o​ ​M​a​n​y - */ - oneToMany: string; - /** - * M​a​n​y​ ​t​o​ ​O​n​e - */ - manyToOne: string; - /** - * M​a​n​y​ ​t​o​ ​M​a​n​y - */ - manyToMany: string; - /** - * L​i​n​k​i​n​g​ ​T​a​b​l​e - */ - linkingTable: string; - }; - importUploadPage: { - /** - * U​p​l​o​a​d​ ​a​ ​f​i​l​e - */ - uploadAFile: string; - /** - * P​r​o​v​i​d​e​ ​a​ ​U​R​L​ ​t​o​ ​t​h​e​ ​f​i​l​e - */ - provideUrlToFile: string; - /** - * C​o​p​y​ ​a​n​d​ ​P​a​s​t​e​ ​T​e​x​t - */ - copyAndPasteText: string; - /** - * U​n​a​b​l​e​ ​t​o​ ​c​r​e​a​t​e​ ​a​ ​t​a​b​l​e​ ​f​r​o​m​ ​t​h​e​ ​u​p​l​o​a​d​e​d​ ​d​a​t​a - */ - unableToCreateTableFromUpload: string; - /** - * C​r​e​a​t​e​ ​a​ ​t​a​b​l​e​ ​b​y​ ​i​m​p​o​r​t​i​n​g​ ​y​o​u​r​ ​d​a​t​a - */ - createATableByImporting: string; - /** - * U​p​l​o​a​d​i​n​g​ ​D​a​t​a - */ - uploadingData: string; - /** - * L​a​r​g​e​ ​d​a​t​a​ ​s​e​t​s​ ​c​a​n​ ​s​o​m​e​t​i​m​e​s​ ​t​a​k​e​ ​s​e​v​e​r​a​l​ ​m​i​n​u​t​e​s​ ​t​o​ ​p​r​o​c​e​s​s​.​ ​P​l​e​a​s​e​ ​d​o​ ​n​o​t​ ​l​e​a​v​e​ ​t​h​i​s​ ​p​a​g​e​ ​o​r​ ​c​l​o​s​e​ ​t​h​e​ ​b​r​o​w​s​e​r​ ​t​a​b​ ​w​h​i​l​e​ ​i​m​p​o​r​t​ ​i​s​ ​i​n​ ​p​r​o​g​r​e​s​s​. - */ - largeDataTakesTimeWarning: string; - /** - * H​o​w​ ​w​o​u​l​d​ ​y​o​u​ ​l​i​k​e​ ​t​o​ ​i​m​p​o​r​t​ ​y​o​u​r​ ​d​a​t​a​? - */ - howWouldYouLikeToImport: string; - /** - * U​p​l​o​a​d​ ​f​a​i​l​e​d - */ - uploadFailed: string; - /** - * P​r​e​p​a​r​i​n​g​ ​P​r​e​v​i​e​w - */ - preparingPreview: string; - /** - * F​a​i​l​e​d​ ​t​o​ ​i​m​p​o​r​t​ ​d​a​t​a - */ - failedToImport: string; - }; - linkTypeOptions: { - /** - * O​n​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​ ​c​a​n​ ​b​e​ ​l​i​n​k​e​d​ ​f​r​o​m​ ​m​u​l​t​i​p​l​e​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​. - */ - oneToManyDescription: string; - /** - * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​t​h​e​ ​s​a​m​e​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​. - */ - manyToOneDescription: string; - /** - * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​a​n​d​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​e​a​c​h​ ​o​t​h​e​r​ ​t​h​r​o​u​g​h​ ​a​ ​n​e​w​ ​<​>​m​a​p​p​i​n​g​T​a​b​l​e​<​> - */ - manyToManyDescription: string; - /** - * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​e​a​c​h​ ​o​t​h​e​r​ ​t​h​r​o​u​g​h​ ​a​ ​n​e​w​ ​<​>​m​a​p​p​i​n​g​<​> - */ - manyToManySelfReferential: string; - }; -}; + general: { + /** + * I​m​p​o​r​t + */ + 'import': string + /** + * O​n​e​ ​t​o​ ​M​a​n​y + */ + oneToMany: string + /** + * M​a​n​y​ ​t​o​ ​O​n​e + */ + manyToOne: string + /** + * M​a​n​y​ ​t​o​ ​M​a​n​y + */ + manyToMany: string + /** + * L​i​n​k​i​n​g​ ​T​a​b​l​e + */ + linkingTable: string + } + importUploadPage: { + /** + * U​p​l​o​a​d​ ​a​ ​f​i​l​e + */ + uploadAFile: string + /** + * P​r​o​v​i​d​e​ ​a​ ​U​R​L​ ​t​o​ ​t​h​e​ ​f​i​l​e + */ + provideUrlToFile: string + /** + * C​o​p​y​ ​a​n​d​ ​P​a​s​t​e​ ​T​e​x​t + */ + copyAndPasteText: string + /** + * U​n​a​b​l​e​ ​t​o​ ​c​r​e​a​t​e​ ​a​ ​t​a​b​l​e​ ​f​r​o​m​ ​t​h​e​ ​u​p​l​o​a​d​e​d​ ​d​a​t​a + */ + unableToCreateTableFromUpload: string + /** + * C​r​e​a​t​e​ ​a​ ​t​a​b​l​e​ ​b​y​ ​i​m​p​o​r​t​i​n​g​ ​y​o​u​r​ ​d​a​t​a + */ + createATableByImporting: string + /** + * U​p​l​o​a​d​i​n​g​ ​D​a​t​a + */ + uploadingData: string + /** + * L​a​r​g​e​ ​d​a​t​a​ ​s​e​t​s​ ​c​a​n​ ​s​o​m​e​t​i​m​e​s​ ​t​a​k​e​ ​s​e​v​e​r​a​l​ ​m​i​n​u​t​e​s​ ​t​o​ ​p​r​o​c​e​s​s​.​ ​P​l​e​a​s​e​ ​d​o​ ​n​o​t​ ​l​e​a​v​e​ ​t​h​i​s​ ​p​a​g​e​ ​o​r​ ​c​l​o​s​e​ ​t​h​e​ ​b​r​o​w​s​e​r​ ​t​a​b​ ​w​h​i​l​e​ ​i​m​p​o​r​t​ ​i​s​ ​i​n​ ​p​r​o​g​r​e​s​s​. + */ + largeDataTakesTimeWarning: string + /** + * H​o​w​ ​w​o​u​l​d​ ​y​o​u​ ​l​i​k​e​ ​t​o​ ​i​m​p​o​r​t​ ​y​o​u​r​ ​d​a​t​a​? + */ + howWouldYouLikeToImport: string + /** + * U​p​l​o​a​d​ ​f​a​i​l​e​d + */ + uploadFailed: string + /** + * P​r​e​p​a​r​i​n​g​ ​P​r​e​v​i​e​w + */ + preparingPreview: string + /** + * F​a​i​l​e​d​ ​t​o​ ​i​m​p​o​r​t​ ​d​a​t​a + */ + failedToImport: string + } + linkTypeOptions: { + /** + * O​n​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​ ​c​a​n​ ​b​e​ ​l​i​n​k​e​d​ ​f​r​o​m​ ​m​u​l​t​i​p​l​e​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​. + */ + oneToManyDescription: string + /** + * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​t​h​e​ ​s​a​m​e​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​. + */ + manyToOneDescription: string + /** + * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​a​n​d​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​e​a​c​h​ ​o​t​h​e​r​ ​t​h​r​o​u​g​h​ ​a​ ​n​e​w​ ​<​>​m​a​p​p​i​n​g​T​a​b​l​e​<​> + */ + manyToManyDescription: string + /** + * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​e​a​c​h​ ​o​t​h​e​r​ ​t​h​r​o​u​g​h​ ​a​ ​n​e​w​ ​<​>​m​a​p​p​i​n​g​<​> + */ + manyToManySelfReferential: string + } +} export type TranslationFunctions = { - general: { - /** - * Import - */ - import: () => LocalizedString; - /** - * One to Many - */ - oneToMany: () => LocalizedString; - /** - * Many to One - */ - manyToOne: () => LocalizedString; - /** - * Many to Many - */ - manyToMany: () => LocalizedString; - /** - * Linking Table - */ - linkingTable: () => LocalizedString; - }; - importUploadPage: { - /** - * Upload a file - */ - uploadAFile: () => LocalizedString; - /** - * Provide a URL to the file - */ - provideUrlToFile: () => LocalizedString; - /** - * Copy and Paste Text - */ - copyAndPasteText: () => LocalizedString; - /** - * Unable to create a table from the uploaded data - */ - unableToCreateTableFromUpload: () => LocalizedString; - /** - * Create a table by importing your data - */ - createATableByImporting: () => LocalizedString; - /** - * Uploading Data - */ - uploadingData: () => LocalizedString; - /** - * Large data sets can sometimes take several minutes to process. Please do not leave this page or close the browser tab while import is in progress. - */ - largeDataTakesTimeWarning: () => LocalizedString; - /** - * How would you like to import your data? - */ - howWouldYouLikeToImport: () => LocalizedString; - /** - * Upload failed - */ - uploadFailed: () => LocalizedString; - /** - * Preparing Preview - */ - preparingPreview: () => LocalizedString; - /** - * Failed to import data - */ - failedToImport: () => LocalizedString; - }; - linkTypeOptions: { - /** - * One <>baseTable<> record can be linked from multiple <>targetTable<> records. - */ - oneToManyDescription: () => LocalizedString; - /** - * Multiple <>baseTable<> records can link to the same <>targetTable<> record. - */ - manyToOneDescription: () => LocalizedString; - /** - * Multiple <>baseTable<> and <>targetTable<> records can link to each other through a new <>mappingTable<> - */ - manyToManyDescription: () => LocalizedString; - /** - * Multiple <>baseTable<> records can link to each other through a new <>mapping<> - */ - manyToManySelfReferential: () => LocalizedString; - }; -}; + general: { + /** + * Import + */ + 'import': () => LocalizedString + /** + * One to Many + */ + oneToMany: () => LocalizedString + /** + * Many to One + */ + manyToOne: () => LocalizedString + /** + * Many to Many + */ + manyToMany: () => LocalizedString + /** + * Linking Table + */ + linkingTable: () => LocalizedString + } + importUploadPage: { + /** + * Upload a file + */ + uploadAFile: () => LocalizedString + /** + * Provide a URL to the file + */ + provideUrlToFile: () => LocalizedString + /** + * Copy and Paste Text + */ + copyAndPasteText: () => LocalizedString + /** + * Unable to create a table from the uploaded data + */ + unableToCreateTableFromUpload: () => LocalizedString + /** + * Create a table by importing your data + */ + createATableByImporting: () => LocalizedString + /** + * Uploading Data + */ + uploadingData: () => LocalizedString + /** + * Large data sets can sometimes take several minutes to process. Please do not leave this page or close the browser tab while import is in progress. + */ + largeDataTakesTimeWarning: () => LocalizedString + /** + * How would you like to import your data? + */ + howWouldYouLikeToImport: () => LocalizedString + /** + * Upload failed + */ + uploadFailed: () => LocalizedString + /** + * Preparing Preview + */ + preparingPreview: () => LocalizedString + /** + * Failed to import data + */ + failedToImport: () => LocalizedString + } + linkTypeOptions: { + /** + * One <>baseTable<> record can be linked from multiple <>targetTable<> records. + */ + oneToManyDescription: () => LocalizedString + /** + * Multiple <>baseTable<> records can link to the same <>targetTable<> record. + */ + manyToOneDescription: () => LocalizedString + /** + * Multiple <>baseTable<> and <>targetTable<> records can link to each other through a new <>mappingTable<> + */ + manyToManyDescription: () => LocalizedString + /** + * Multiple <>baseTable<> records can link to each other through a new <>mapping<> + */ + manyToManySelfReferential: () => LocalizedString + } +} -export type Formatters = {}; +export type Formatters = {} From 1e418f1e8943024e969a7a1ce925ada1e13bfb5e Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Thu, 27 Jul 2023 16:12:54 +0530 Subject: [PATCH 006/111] lint fixes --- mathesar_ui/src/i18n/i18n-types.ts | 367 +++++++++++++++-------------- 1 file changed, 184 insertions(+), 183 deletions(-) diff --git a/mathesar_ui/src/i18n/i18n-types.ts b/mathesar_ui/src/i18n/i18n-types.ts index 27f341c5f9..9b8ff873e2 100644 --- a/mathesar_ui/src/i18n/i18n-types.ts +++ b/mathesar_ui/src/i18n/i18n-types.ts @@ -3,195 +3,196 @@ /* eslint-disable eslint-comments/no-unlimited-disable */ /* eslint eslint-comments/disable-enable-pair: [error, {allowWholeFile: true}] */ /* eslint-disable */ -import type { BaseTranslation as BaseTranslationType, LocalizedString } from 'typesafe-i18n' +import type { + BaseTranslation as BaseTranslationType, + LocalizedString, +} from 'typesafe-i18n'; -export type BaseTranslation = BaseTranslationType -export type BaseLocale = 'en' +export type BaseTranslation = BaseTranslationType; +export type BaseLocale = 'en'; -export type Locales = - | 'en' - | 'ja' +export type Locales = 'en' | 'ja'; -export type Translation = RootTranslation +export type Translation = RootTranslation; -export type Translations = RootTranslation +export type Translations = RootTranslation; type RootTranslation = { - general: { - /** - * I​m​p​o​r​t - */ - 'import': string - /** - * O​n​e​ ​t​o​ ​M​a​n​y - */ - oneToMany: string - /** - * M​a​n​y​ ​t​o​ ​O​n​e - */ - manyToOne: string - /** - * M​a​n​y​ ​t​o​ ​M​a​n​y - */ - manyToMany: string - /** - * L​i​n​k​i​n​g​ ​T​a​b​l​e - */ - linkingTable: string - } - importUploadPage: { - /** - * U​p​l​o​a​d​ ​a​ ​f​i​l​e - */ - uploadAFile: string - /** - * P​r​o​v​i​d​e​ ​a​ ​U​R​L​ ​t​o​ ​t​h​e​ ​f​i​l​e - */ - provideUrlToFile: string - /** - * C​o​p​y​ ​a​n​d​ ​P​a​s​t​e​ ​T​e​x​t - */ - copyAndPasteText: string - /** - * U​n​a​b​l​e​ ​t​o​ ​c​r​e​a​t​e​ ​a​ ​t​a​b​l​e​ ​f​r​o​m​ ​t​h​e​ ​u​p​l​o​a​d​e​d​ ​d​a​t​a - */ - unableToCreateTableFromUpload: string - /** - * C​r​e​a​t​e​ ​a​ ​t​a​b​l​e​ ​b​y​ ​i​m​p​o​r​t​i​n​g​ ​y​o​u​r​ ​d​a​t​a - */ - createATableByImporting: string - /** - * U​p​l​o​a​d​i​n​g​ ​D​a​t​a - */ - uploadingData: string - /** - * L​a​r​g​e​ ​d​a​t​a​ ​s​e​t​s​ ​c​a​n​ ​s​o​m​e​t​i​m​e​s​ ​t​a​k​e​ ​s​e​v​e​r​a​l​ ​m​i​n​u​t​e​s​ ​t​o​ ​p​r​o​c​e​s​s​.​ ​P​l​e​a​s​e​ ​d​o​ ​n​o​t​ ​l​e​a​v​e​ ​t​h​i​s​ ​p​a​g​e​ ​o​r​ ​c​l​o​s​e​ ​t​h​e​ ​b​r​o​w​s​e​r​ ​t​a​b​ ​w​h​i​l​e​ ​i​m​p​o​r​t​ ​i​s​ ​i​n​ ​p​r​o​g​r​e​s​s​. - */ - largeDataTakesTimeWarning: string - /** - * H​o​w​ ​w​o​u​l​d​ ​y​o​u​ ​l​i​k​e​ ​t​o​ ​i​m​p​o​r​t​ ​y​o​u​r​ ​d​a​t​a​? - */ - howWouldYouLikeToImport: string - /** - * U​p​l​o​a​d​ ​f​a​i​l​e​d - */ - uploadFailed: string - /** - * P​r​e​p​a​r​i​n​g​ ​P​r​e​v​i​e​w - */ - preparingPreview: string - /** - * F​a​i​l​e​d​ ​t​o​ ​i​m​p​o​r​t​ ​d​a​t​a - */ - failedToImport: string - } - linkTypeOptions: { - /** - * O​n​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​ ​c​a​n​ ​b​e​ ​l​i​n​k​e​d​ ​f​r​o​m​ ​m​u​l​t​i​p​l​e​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​. - */ - oneToManyDescription: string - /** - * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​t​h​e​ ​s​a​m​e​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​. - */ - manyToOneDescription: string - /** - * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​a​n​d​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​e​a​c​h​ ​o​t​h​e​r​ ​t​h​r​o​u​g​h​ ​a​ ​n​e​w​ ​<​>​m​a​p​p​i​n​g​T​a​b​l​e​<​> - */ - manyToManyDescription: string - /** - * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​e​a​c​h​ ​o​t​h​e​r​ ​t​h​r​o​u​g​h​ ​a​ ​n​e​w​ ​<​>​m​a​p​p​i​n​g​<​> - */ - manyToManySelfReferential: string - } -} + general: { + /** + * I​m​p​o​r​t + */ + import: string; + /** + * O​n​e​ ​t​o​ ​M​a​n​y + */ + oneToMany: string; + /** + * M​a​n​y​ ​t​o​ ​O​n​e + */ + manyToOne: string; + /** + * M​a​n​y​ ​t​o​ ​M​a​n​y + */ + manyToMany: string; + /** + * L​i​n​k​i​n​g​ ​T​a​b​l​e + */ + linkingTable: string; + }; + importUploadPage: { + /** + * U​p​l​o​a​d​ ​a​ ​f​i​l​e + */ + uploadAFile: string; + /** + * P​r​o​v​i​d​e​ ​a​ ​U​R​L​ ​t​o​ ​t​h​e​ ​f​i​l​e + */ + provideUrlToFile: string; + /** + * C​o​p​y​ ​a​n​d​ ​P​a​s​t​e​ ​T​e​x​t + */ + copyAndPasteText: string; + /** + * U​n​a​b​l​e​ ​t​o​ ​c​r​e​a​t​e​ ​a​ ​t​a​b​l​e​ ​f​r​o​m​ ​t​h​e​ ​u​p​l​o​a​d​e​d​ ​d​a​t​a + */ + unableToCreateTableFromUpload: string; + /** + * C​r​e​a​t​e​ ​a​ ​t​a​b​l​e​ ​b​y​ ​i​m​p​o​r​t​i​n​g​ ​y​o​u​r​ ​d​a​t​a + */ + createATableByImporting: string; + /** + * U​p​l​o​a​d​i​n​g​ ​D​a​t​a + */ + uploadingData: string; + /** + * L​a​r​g​e​ ​d​a​t​a​ ​s​e​t​s​ ​c​a​n​ ​s​o​m​e​t​i​m​e​s​ ​t​a​k​e​ ​s​e​v​e​r​a​l​ ​m​i​n​u​t​e​s​ ​t​o​ ​p​r​o​c​e​s​s​.​ ​P​l​e​a​s​e​ ​d​o​ ​n​o​t​ ​l​e​a​v​e​ ​t​h​i​s​ ​p​a​g​e​ ​o​r​ ​c​l​o​s​e​ ​t​h​e​ ​b​r​o​w​s​e​r​ ​t​a​b​ ​w​h​i​l​e​ ​i​m​p​o​r​t​ ​i​s​ ​i​n​ ​p​r​o​g​r​e​s​s​. + */ + largeDataTakesTimeWarning: string; + /** + * H​o​w​ ​w​o​u​l​d​ ​y​o​u​ ​l​i​k​e​ ​t​o​ ​i​m​p​o​r​t​ ​y​o​u​r​ ​d​a​t​a​? + */ + howWouldYouLikeToImport: string; + /** + * U​p​l​o​a​d​ ​f​a​i​l​e​d + */ + uploadFailed: string; + /** + * P​r​e​p​a​r​i​n​g​ ​P​r​e​v​i​e​w + */ + preparingPreview: string; + /** + * F​a​i​l​e​d​ ​t​o​ ​i​m​p​o​r​t​ ​d​a​t​a + */ + failedToImport: string; + }; + linkTypeOptions: { + /** + * O​n​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​ ​c​a​n​ ​b​e​ ​l​i​n​k​e​d​ ​f​r​o​m​ ​m​u​l​t​i​p​l​e​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​. + */ + oneToManyDescription: string; + /** + * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​t​h​e​ ​s​a​m​e​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​. + */ + manyToOneDescription: string; + /** + * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​a​n​d​ ​<​>​t​a​r​g​e​t​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​e​a​c​h​ ​o​t​h​e​r​ ​t​h​r​o​u​g​h​ ​a​ ​n​e​w​ ​<​>​m​a​p​p​i​n​g​T​a​b​l​e​<​> + */ + manyToManyDescription: string; + /** + * M​u​l​t​i​p​l​e​ ​<​>​b​a​s​e​T​a​b​l​e​<​>​ ​r​e​c​o​r​d​s​ ​c​a​n​ ​l​i​n​k​ ​t​o​ ​e​a​c​h​ ​o​t​h​e​r​ ​t​h​r​o​u​g​h​ ​a​ ​n​e​w​ ​<​>​m​a​p​p​i​n​g​<​> + */ + manyToManySelfReferential: string; + }; +}; export type TranslationFunctions = { - general: { - /** - * Import - */ - 'import': () => LocalizedString - /** - * One to Many - */ - oneToMany: () => LocalizedString - /** - * Many to One - */ - manyToOne: () => LocalizedString - /** - * Many to Many - */ - manyToMany: () => LocalizedString - /** - * Linking Table - */ - linkingTable: () => LocalizedString - } - importUploadPage: { - /** - * Upload a file - */ - uploadAFile: () => LocalizedString - /** - * Provide a URL to the file - */ - provideUrlToFile: () => LocalizedString - /** - * Copy and Paste Text - */ - copyAndPasteText: () => LocalizedString - /** - * Unable to create a table from the uploaded data - */ - unableToCreateTableFromUpload: () => LocalizedString - /** - * Create a table by importing your data - */ - createATableByImporting: () => LocalizedString - /** - * Uploading Data - */ - uploadingData: () => LocalizedString - /** - * Large data sets can sometimes take several minutes to process. Please do not leave this page or close the browser tab while import is in progress. - */ - largeDataTakesTimeWarning: () => LocalizedString - /** - * How would you like to import your data? - */ - howWouldYouLikeToImport: () => LocalizedString - /** - * Upload failed - */ - uploadFailed: () => LocalizedString - /** - * Preparing Preview - */ - preparingPreview: () => LocalizedString - /** - * Failed to import data - */ - failedToImport: () => LocalizedString - } - linkTypeOptions: { - /** - * One <>baseTable<> record can be linked from multiple <>targetTable<> records. - */ - oneToManyDescription: () => LocalizedString - /** - * Multiple <>baseTable<> records can link to the same <>targetTable<> record. - */ - manyToOneDescription: () => LocalizedString - /** - * Multiple <>baseTable<> and <>targetTable<> records can link to each other through a new <>mappingTable<> - */ - manyToManyDescription: () => LocalizedString - /** - * Multiple <>baseTable<> records can link to each other through a new <>mapping<> - */ - manyToManySelfReferential: () => LocalizedString - } -} + general: { + /** + * Import + */ + import: () => LocalizedString; + /** + * One to Many + */ + oneToMany: () => LocalizedString; + /** + * Many to One + */ + manyToOne: () => LocalizedString; + /** + * Many to Many + */ + manyToMany: () => LocalizedString; + /** + * Linking Table + */ + linkingTable: () => LocalizedString; + }; + importUploadPage: { + /** + * Upload a file + */ + uploadAFile: () => LocalizedString; + /** + * Provide a URL to the file + */ + provideUrlToFile: () => LocalizedString; + /** + * Copy and Paste Text + */ + copyAndPasteText: () => LocalizedString; + /** + * Unable to create a table from the uploaded data + */ + unableToCreateTableFromUpload: () => LocalizedString; + /** + * Create a table by importing your data + */ + createATableByImporting: () => LocalizedString; + /** + * Uploading Data + */ + uploadingData: () => LocalizedString; + /** + * Large data sets can sometimes take several minutes to process. Please do not leave this page or close the browser tab while import is in progress. + */ + largeDataTakesTimeWarning: () => LocalizedString; + /** + * How would you like to import your data? + */ + howWouldYouLikeToImport: () => LocalizedString; + /** + * Upload failed + */ + uploadFailed: () => LocalizedString; + /** + * Preparing Preview + */ + preparingPreview: () => LocalizedString; + /** + * Failed to import data + */ + failedToImport: () => LocalizedString; + }; + linkTypeOptions: { + /** + * One <>baseTable<> record can be linked from multiple <>targetTable<> records. + */ + oneToManyDescription: () => LocalizedString; + /** + * Multiple <>baseTable<> records can link to the same <>targetTable<> record. + */ + manyToOneDescription: () => LocalizedString; + /** + * Multiple <>baseTable<> and <>targetTable<> records can link to each other through a new <>mappingTable<> + */ + manyToManyDescription: () => LocalizedString; + /** + * Multiple <>baseTable<> records can link to each other through a new <>mapping<> + */ + manyToManySelfReferential: () => LocalizedString; + }; +}; -export type Formatters = {} +export type Formatters = {}; From 1738aca591db359496eca1185bffb369b08cb7e4 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Wed, 6 Sep 2023 15:16:17 +0530 Subject: [PATCH 007/111] renamed loadTranslationsIntoMemory to loadTranslations --- mathesar_ui/src/App.svelte | 4 ++-- mathesar_ui/src/i18n/i18n-load.ts | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/mathesar_ui/src/App.svelte b/mathesar_ui/src/App.svelte index 391414ef5b..ed1e4d2517 100644 --- a/mathesar_ui/src/App.svelte +++ b/mathesar_ui/src/App.svelte @@ -5,13 +5,13 @@ import RootRoute from './routes/RootRoute.svelte'; import { setLocale } from './i18n/i18n-svelte'; import ErrorBox from './components/message-boxes/ErrorBox.svelte'; - import { loadTranslationsIntoMemory } from './i18n/i18n-load'; + import { loadTranslations } from './i18n/i18n-load'; let isTranslationsLoaded = false; const checkTranslationsAvailableInterval = setInterval(() => { const { translations } = window; if (translations) { - loadTranslationsIntoMemory( + loadTranslations( translations.lang, JSON.parse(translations.translationStrings), ); diff --git a/mathesar_ui/src/i18n/i18n-load.ts b/mathesar_ui/src/i18n/i18n-load.ts index 6e0aabee3b..975abf24f7 100644 --- a/mathesar_ui/src/i18n/i18n-load.ts +++ b/mathesar_ui/src/i18n/i18n-load.ts @@ -31,10 +31,7 @@ export async function loadLocaleAsync(locale: Locales): Promise { loadFormatters(locale); } -export function loadTranslationsIntoMemory( - locale: Locales, - translations: Translations, -) { +export function loadTranslations(locale: Locales, translations: Translations) { updateTranslationsDictionary(locale, translations); loadFormatters(locale); } From b5c5bde9ab57d42a5b0f1ec9be271558013d5477 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Wed, 6 Sep 2023 16:13:47 +0530 Subject: [PATCH 008/111] made translations script async --- mathesar/templates/mathesar/index.html | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/mathesar/templates/mathesar/index.html b/mathesar/templates/mathesar/index.html index 2d4e616ef6..fd95be1b96 100644 --- a/mathesar/templates/mathesar/index.html +++ b/mathesar/templates/mathesar/index.html @@ -19,8 +19,9 @@ {% endfor %} {% endif %} - + {% endif %} {% endblock %} From 0e8e6748b874d2aaf75079832d3d4b2a673617e8 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Wed, 6 Sep 2023 17:06:42 +0530 Subject: [PATCH 009/111] renamed preferred_language to display_language --- config/context_processors.py | 10 +++++----- config/settings/common_settings.py | 2 +- mathesar/api/ui/serializers/users.py | 2 +- ...language.py => 0005_user_display_language.py} | 6 +++--- mathesar/models/users.py | 2 +- mathesar/templates/mathesar/index.html | 4 ++-- mathesar/utils/frontend.py | 10 +++++----- mathesar_ui/src/api/users.ts | 2 +- mathesar_ui/src/stores/users.ts | 7 ++++--- ...guage.svelte => SelectDisplayLanguage.svelte} | 0 .../users-and-permissions/UserDetailsForm.svelte | 16 ++++++++-------- 11 files changed, 31 insertions(+), 30 deletions(-) rename mathesar/migrations/{0004_user_preferred_language.py => 0005_user_display_language.py} (67%) rename mathesar_ui/src/systems/users-and-permissions/{SelectPreferredLanguage.svelte => SelectDisplayLanguage.svelte} (100%) diff --git a/config/context_processors.py b/config/context_processors.py index 1828e543bb..902505045d 100644 --- a/config/context_processors.py +++ b/config/context_processors.py @@ -4,11 +4,11 @@ def frontend_settings(request): - preferred_language = get_user_preferred_language_from_request(request) + display_language = get_display_language_from_request(request) frontend_settings = { 'development_mode': settings.MATHESAR_MODE == 'DEVELOPMENT', - 'manifest_data': get_manifest_data(preferred_language), - 'preferred_language': preferred_language, + 'manifest_data': get_manifest_data(display_language), + 'display_language': display_language, 'live_demo_mode': getattr(settings, 'MATHESAR_LIVE_DEMO', False), 'live_demo_username': getattr(settings, 'MATHESAR_LIVE_DEMO_USERNAME', None), 'live_demo_password': getattr(settings, 'MATHESAR_LIVE_DEMO_PASSWORD', None), @@ -19,12 +19,12 @@ def frontend_settings(request): return frontend_settings -def get_user_preferred_language_from_request(request): +def get_display_language_from_request(request): # https://docs.djangoproject.com/en/4.2/topics/i18n/translation/#how-django-discovers-language-preference # This automatically fallbacks to en because of https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-LANGUAGE_CODE lang_from_locale_middleware = request.LANGUAGE_CODE if request.user.is_authenticated: - return request.user.preferred_language or lang_from_locale_middleware + return request.user.display_language or lang_from_locale_middleware else: return lang_from_locale_middleware diff --git a/config/settings/common_settings.py b/config/settings/common_settings.py index 8659cf3b9f..a2dc749b57 100644 --- a/config/settings/common_settings.py +++ b/config/settings/common_settings.py @@ -256,4 +256,4 @@ def pipe_delim(pipe_string): ('en', gettext_lazy('English')), ('ja', gettext_lazy('Japanese')), ] -LANGUAGE_COOKIE_NAME = 'user_preferred_language' +LANGUAGE_COOKIE_NAME = 'display_language' diff --git a/mathesar/api/ui/serializers/users.py b/mathesar/api/ui/serializers/users.py index 78b657cb97..199c439ac4 100644 --- a/mathesar/api/ui/serializers/users.py +++ b/mathesar/api/ui/serializers/users.py @@ -40,7 +40,7 @@ class Meta: 'is_superuser', 'database_roles', 'schema_roles', - 'preferred_language' + 'display_language' ] extra_kwargs = { 'password': {'write_only': True}, diff --git a/mathesar/migrations/0004_user_preferred_language.py b/mathesar/migrations/0005_user_display_language.py similarity index 67% rename from mathesar/migrations/0004_user_preferred_language.py rename to mathesar/migrations/0005_user_display_language.py index be05706c91..c2eb798493 100644 --- a/mathesar/migrations/0004_user_preferred_language.py +++ b/mathesar/migrations/0005_user_display_language.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.14 on 2023-07-27 09:15 +# Generated by Django 3.1.14 on 2023-09-06 11:25 from django.db import migrations, models @@ -6,13 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('mathesar', '0003_datafile_max_level'), + ('mathesar', '0004_shares'), ] operations = [ migrations.AddField( model_name='user', - name='preferred_language', + name='display_language', field=models.CharField(blank=True, default='en', max_length=30), ), ] diff --git a/mathesar/models/users.py b/mathesar/models/users.py index 025d462b8d..9e3fcbe86a 100644 --- a/mathesar/models/users.py +++ b/mathesar/models/users.py @@ -15,7 +15,7 @@ class User(AbstractUser): full_name = models.CharField(max_length=255, blank=True, null=True) short_name = models.CharField(max_length=255, blank=True, null=True) password_change_needed = models.BooleanField(default=False) - preferred_language = models.CharField(max_length=30, blank=True, default='en') + display_language = models.CharField(max_length=30, blank=True, default='en') class Role(models.TextChoices): diff --git a/mathesar/templates/mathesar/index.html b/mathesar/templates/mathesar/index.html index fd95be1b96..cc6cea11aa 100644 --- a/mathesar/templates/mathesar/index.html +++ b/mathesar/templates/mathesar/index.html @@ -22,10 +22,10 @@ {% comment %} Making it async to start the execution as soon as its downloaded without making it wait for the HTML to be parsed {% endcomment %} @@ -62,16 +62,6 @@ nomodule src="{% static manifest_data.legacy_polyfill_js %}" > - diff --git a/mathesar_ui/src/global.d.ts b/mathesar_ui/src/global.d.ts index 41aa976973..dfbdbd61e5 100644 --- a/mathesar_ui/src/global.d.ts +++ b/mathesar_ui/src/global.d.ts @@ -7,5 +7,9 @@ declare module '*.mdx' { } interface Window { - translations: { lang: Locales; translationStrings: string } | undefined; + mathesar: + | { + translations: { lang: Locales; translationStrings: string } | undefined; + } + | undefined; } From c5ed4bcd87dca4c1efe9b235923c933a3884da4f Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Tue, 19 Sep 2023 15:48:39 +0530 Subject: [PATCH 016/111] lint fixes --- mathesar_ui/src/App.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mathesar_ui/src/App.svelte b/mathesar_ui/src/App.svelte index 5eac49922f..42108129c6 100644 --- a/mathesar_ui/src/App.svelte +++ b/mathesar_ui/src/App.svelte @@ -36,7 +36,7 @@ * it as a default exported module. Otherwise vite converts the * default export to named exports internally for the sake of optimization. */ - loadLocaleAsync('en'); + void loadLocaleAsync('en'); } const commonData = preloadCommonData(); From 25c89ce4a16ea2af74322def5f540ca8e8325cd1 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Tue, 19 Sep 2023 15:50:02 +0530 Subject: [PATCH 017/111] do not read legacy builds for translations files --- mathesar/utils/frontend.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mathesar/utils/frontend.py b/mathesar/utils/frontend.py index 8c0ad8fff4..ca4f3e084d 100644 --- a/mathesar/utils/frontend.py +++ b/mathesar/utils/frontend.py @@ -27,7 +27,6 @@ def get_manifest_data(): for locale, _ in settings.LANGUAGES or []: manifest_data[locale] = raw_data[f'src/i18n/{locale}/index.ts'] - manifest_data[f"{locale}-legacy"] = raw_data[f'src/i18n/{locale}/index-legacy.ts'] # Cache data for 1 hour cache.set('manifest_data', manifest_data, 60 * 60) From 737effa9e60660e58e39c28b60c1bcdbe94de56e Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Tue, 19 Sep 2023 16:34:35 +0530 Subject: [PATCH 018/111] render page when loading default lang translations --- mathesar_ui/src/App.svelte | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/mathesar_ui/src/App.svelte b/mathesar_ui/src/App.svelte index 42108129c6..d0e4ceb352 100644 --- a/mathesar_ui/src/App.svelte +++ b/mathesar_ui/src/App.svelte @@ -15,9 +15,9 @@ * 2. And then make it available for the entry(App.svelte) * file to load them into memory. * the index.html loads it as using a script tag and attach it - * to the window's global object which is being read here + * to the window object which is being read here */ - try { + void (async () => { const { translations } = window.mathesar || {}; if (translations) { loadTranslations( @@ -26,18 +26,19 @@ ); setLocale(translations.lang); isTranslationsLoaded = true; + } else { + /** + * !!! CAUTION: DO NOT REMOVE THIS !!! + * Reason: Apart from loading the `en` translations as default + * when there are translations on the window object, + * this also tells the vite bundler to bundle + * it as a default exported module. Otherwise vite converts the + * default export to named exports internally for the sake of optimization. + */ + await loadLocaleAsync('en'); + isTranslationsLoaded = true; } - } catch { - /** - * !!! CAUTION: DO NOT REMOVE THIS !!! - * Reason: Apart from loading the `en` translations as default - * when something fails while reading the window's global - * object, this also tells the vite bundler to bundle - * it as a default exported module. Otherwise vite converts the - * default export to named exports internally for the sake of optimization. - */ - void loadLocaleAsync('en'); - } + })(); const commonData = preloadCommonData(); From 0bb7d3888e9eeb35378eaa7799d97366dca41b7c Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Fri, 22 Sep 2023 12:42:31 +0530 Subject: [PATCH 019/111] add database connection page --- mathesar/urls.py | 2 + mathesar/views.py | 15 ++ mathesar_ui/src/AppTypes.ts | 5 + mathesar_ui/src/api/databaseConnection.ts | 19 ++ .../pages/admin-users/AdminNavigation.svelte | 17 +- .../AddDatabaseConnection.svelte | 35 ++++ .../DatabaseConnectionForm.svelte | 178 ++++++++++++++++++ .../EditDatabaseConnection.svelte | 15 ++ mathesar_ui/src/routes/AdminRoute.svelte | 11 +- .../src/routes/AuthenticatedRoutes.svelte | 2 +- .../src/routes/DatabaseConnectionRoute.svelte | 13 ++ mathesar_ui/src/routes/urls.ts | 7 + .../UserFormInput.svelte | 7 + 13 files changed, 323 insertions(+), 3 deletions(-) create mode 100644 mathesar_ui/src/api/databaseConnection.ts create mode 100644 mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte create mode 100644 mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte create mode 100644 mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte create mode 100644 mathesar_ui/src/routes/DatabaseConnectionRoute.svelte diff --git a/mathesar/urls.py b/mathesar/urls.py index 62a91e0fe2..60ea9234ec 100644 --- a/mathesar/urls.py +++ b/mathesar/urls.py @@ -53,6 +53,8 @@ path('administration/users/', views.admin_home, name='admin_users_home'), path('administration/users//', views.admin_home, name='admin_users_edit'), path('administration/update/', views.admin_home, name='admin_update'), + path('administration/db-connection/add/', views.add_database_connection, name='add_database_connection'), + path('administration/db-connection/edit/', views.edit_database_connection, name='edit_database_connection'), path('shares/tables//', views.shared_table, name='shared_table'), path('shares/explorations//', views.shared_query, name='shared_query'), path('db/', views.home, name='db_home'), diff --git a/mathesar/views.py b/mathesar/views.py index c015fda19b..aaa4689e21 100644 --- a/mathesar/views.py +++ b/mathesar/views.py @@ -288,6 +288,21 @@ def schemas(request, db_name): }) +@login_required +def add_database_connection(request): + return render(request, 'mathesar/index.html', { + 'common_data': get_common_data(request) + }) + + +@login_required +def edit_database_connection(request, db_name): + database = get_current_database(request, db_name) + return render(request, 'mathesar/index.html', { + 'common_data': get_common_data(request, database, None) + }) + + def shared_table(request, slug): shared_table_link = SharedTable.get_by_slug(slug) if is_valid_uuid_v4(slug) else None table = shared_table_link.table if shared_table_link else None diff --git a/mathesar_ui/src/AppTypes.ts b/mathesar_ui/src/AppTypes.ts index d6d46b1fe3..c244eb9d0d 100644 --- a/mathesar_ui/src/AppTypes.ts +++ b/mathesar_ui/src/AppTypes.ts @@ -5,6 +5,11 @@ export interface Database { name: string; deleted: boolean; supported_types: string[]; + db_name: string; + editable: boolean; + username: string; + host: string; + port: string; } export interface DBObjectEntry { diff --git a/mathesar_ui/src/api/databaseConnection.ts b/mathesar_ui/src/api/databaseConnection.ts new file mode 100644 index 0000000000..cdf65d7461 --- /dev/null +++ b/mathesar_ui/src/api/databaseConnection.ts @@ -0,0 +1,19 @@ +import type { Database } from '@mathesar/AppTypes'; +import { getAPI, patchAPI, postAPI } from './utils/requestUtils'; + +export interface NewDatabaseConnection { + name: string; + db_name: string; + username: string; + host: string; + port: string; + password: string; +} + +function add(connectionDetails: NewDatabaseConnection) { + return postAPI('/api/db/v0/databases/', connectionDetails); +} + +export default { + add, +}; diff --git a/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte b/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte index 1b419287e7..af9ae8f165 100644 --- a/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte +++ b/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte @@ -1,8 +1,13 @@ + + + +

Add Database Connection

+ + + + diff --git a/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte b/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte new file mode 100644 index 0000000000..b378802cf2 --- /dev/null +++ b/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte @@ -0,0 +1,178 @@ + + +
+ + + + + + + + + + + + +
+ + + diff --git a/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte new file mode 100644 index 0000000000..447c1cf6a6 --- /dev/null +++ b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte @@ -0,0 +1,15 @@ + + + +
Edit DB Connection for {databaseName}
diff --git a/mathesar_ui/src/routes/AdminRoute.svelte b/mathesar_ui/src/routes/AdminRoute.svelte index 39fe9713fd..d6603458b3 100644 --- a/mathesar_ui/src/routes/AdminRoute.svelte +++ b/mathesar_ui/src/routes/AdminRoute.svelte @@ -8,8 +8,13 @@ import SoftwareUpdate from '@mathesar/pages/admin-update/SoftwareUpdatePage.svelte'; import AdminNavigation from '@mathesar/pages/admin-users/AdminNavigation.svelte'; import PageLayoutWithSidebar from '@mathesar/layouts/PageLayoutWithSidebar.svelte'; - import { ADMIN_UPDATE_PAGE_URL, ADMIN_URL } from './urls'; + import { + ADMIN_UPDATE_PAGE_URL, + ADMIN_URL, + DATABASE_CONNECTION_SLUG, + } from './urls'; import UsersRoute from './UsersRoute.svelte'; + import DatabaseConnectionRoute from './DatabaseConnectionRoute.svelte'; + + + + diff --git a/mathesar_ui/src/routes/AuthenticatedRoutes.svelte b/mathesar_ui/src/routes/AuthenticatedRoutes.svelte index a792229898..2cda4b8970 100644 --- a/mathesar_ui/src/routes/AuthenticatedRoutes.svelte +++ b/mathesar_ui/src/routes/AuthenticatedRoutes.svelte @@ -33,5 +33,5 @@ {/if} - + diff --git a/mathesar_ui/src/routes/DatabaseConnectionRoute.svelte b/mathesar_ui/src/routes/DatabaseConnectionRoute.svelte new file mode 100644 index 0000000000..aea981c2e2 --- /dev/null +++ b/mathesar_ui/src/routes/DatabaseConnectionRoute.svelte @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/mathesar_ui/src/routes/urls.ts b/mathesar_ui/src/routes/urls.ts index 2cd56707eb..b3f8999260 100644 --- a/mathesar_ui/src/routes/urls.ts +++ b/mathesar_ui/src/routes/urls.ts @@ -115,6 +115,13 @@ export const ADMIN_USERS_PAGE_URL = `${ADMIN_URL}users/`; export const ADMIN_USERS_PAGE_ADD_NEW_URL = `${ADMIN_URL}users/new/`; export const LOGOUT_URL = '/auth/logout/'; +export const DATABASE_CONNECTION_SLUG = 'db-connection'; +export const ADD_DATABASE_CONNECTION_URL = `${ADMIN_URL}${DATABASE_CONNECTION_SLUG}/add/`; + +export function getDatabaseConnectionEditUrl(databaseName: string) { + return `${ADMIN_URL}${DATABASE_CONNECTION_SLUG}/edit/${databaseName}/`; +} + export function getEditUsersPageUrl(userId: number) { return `${ADMIN_USERS_PAGE_URL}${userId}/`; } diff --git a/mathesar_ui/src/systems/users-and-permissions/UserFormInput.svelte b/mathesar_ui/src/systems/users-and-permissions/UserFormInput.svelte index 19154ed14e..8e81a7eec3 100644 --- a/mathesar_ui/src/systems/users-and-permissions/UserFormInput.svelte +++ b/mathesar_ui/src/systems/users-and-permissions/UserFormInput.svelte @@ -48,5 +48,12 @@ justify-content: end; margin-right: var(--size-large); padding-top: var(--size-ultra-small); + margin-left: var(--size-large); + } + + .help { + color: var(--slate-500); + margin-top: var(--size-extreme-small); + font-size: var(--size-small); } From e401e9f49ef26df0b9a1f7de38ccb766f2e85788 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Sat, 23 Sep 2023 01:18:52 +0530 Subject: [PATCH 020/111] edit database connection --- mathesar/urls.py | 2 +- mathesar_ui/src/api/databaseConnection.ts | 13 ++- .../pages/admin-users/AdminNavigation.svelte | 2 +- .../AddDatabaseConnection.svelte | 6 +- .../DatabaseConnectionForm.svelte | 41 +++++++-- .../EditDatabaseConnection.svelte | 23 ++++- .../src/pages/database/ConnectionError.svelte | 38 +++++++++ .../src/pages/database/DatabaseDetails.svelte | 85 +++++++++++-------- .../src/routes/DatabaseConnectionRoute.svelte | 9 +- 9 files changed, 167 insertions(+), 52 deletions(-) create mode 100644 mathesar_ui/src/pages/database/ConnectionError.svelte diff --git a/mathesar/urls.py b/mathesar/urls.py index 60ea9234ec..734d097b7b 100644 --- a/mathesar/urls.py +++ b/mathesar/urls.py @@ -54,7 +54,7 @@ path('administration/users//', views.admin_home, name='admin_users_edit'), path('administration/update/', views.admin_home, name='admin_update'), path('administration/db-connection/add/', views.add_database_connection, name='add_database_connection'), - path('administration/db-connection/edit/', views.edit_database_connection, name='edit_database_connection'), + path('administration/db-connection/edit//', views.edit_database_connection, name='edit_database_connection'), path('shares/tables//', views.shared_table, name='shared_table'), path('shares/explorations//', views.shared_query, name='shared_query'), path('db/', views.home, name='db_home'), diff --git a/mathesar_ui/src/api/databaseConnection.ts b/mathesar_ui/src/api/databaseConnection.ts index cdf65d7461..b36e2f61cf 100644 --- a/mathesar_ui/src/api/databaseConnection.ts +++ b/mathesar_ui/src/api/databaseConnection.ts @@ -1,7 +1,7 @@ import type { Database } from '@mathesar/AppTypes'; -import { getAPI, patchAPI, postAPI } from './utils/requestUtils'; +import { patchAPI, postAPI } from './utils/requestUtils'; -export interface NewDatabaseConnection { +export interface NewConnection { name: string; db_name: string; username: string; @@ -10,10 +10,17 @@ export interface NewDatabaseConnection { password: string; } -function add(connectionDetails: NewDatabaseConnection) { +export type ConnectionUpdates = Partial>; + +function add(connectionDetails: NewConnection) { return postAPI('/api/db/v0/databases/', connectionDetails); } +function update(databaseId: number, updates: ConnectionUpdates) { + return patchAPI(`/api/db/v0/databases/${databaseId}/`, updates); +} + export default { add, + update, }; diff --git a/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte b/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte index af9ae8f165..42ac87f3b0 100644 --- a/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte +++ b/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte @@ -48,7 +48,7 @@ use:active > - Add Database Connection + Database Connection diff --git a/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte b/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte index c29f524f0e..7257587c31 100644 --- a/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte +++ b/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte @@ -11,10 +11,14 @@ import { toast } from '@mathesar/stores/toast'; import type { Database } from '@mathesar/AppTypes'; import { router } from 'tinro'; + import { reloadDatabases } from '@mathesar/stores/databases'; + import { reflectApi } from '@mathesar/api/reflect'; - function handleSuccess(event: CustomEvent) { + async function handleSuccess(event: CustomEvent) { const database = event.detail; toast.success(`${database.name} connected successfully!`); + await reflectApi.reflect(); + await reloadDatabases(); router.goto(getDatabasePageUrl(database.name)); } diff --git a/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte b/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte index b378802cf2..5e463995bf 100644 --- a/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte +++ b/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte @@ -4,6 +4,7 @@ import { FormSubmit, makeForm, + optionalField, requiredField, } from '@mathesar/components/form'; import { databases } from '@mathesar/stores/databases'; @@ -26,7 +27,7 @@ $: connectionName = requiredField(database?.name ?? ''); $: databaseName = requiredField(database?.db_name ?? ''); - $: username = requiredField(''); + $: username = requiredField(database?.username ?? ''); $: host = requiredField(database?.host ?? ''); $: port = requiredField(database?.port ?? '5432', [ (value) => @@ -34,7 +35,11 @@ ? { type: 'valid' } : { type: 'invalid', errorMsg: 'Port should be a valid number' }, ]); - $: password = requiredField(''); + + // There will be no prefill value even in the case of editing + $: password = isNewConnection ? requiredField('') : optionalField(''); + $: hasPasswordChangedStore = password.hasChanges; + $: hasPasswordChanged = $hasPasswordChangedStore; $: formFields = { connectionName, @@ -45,9 +50,9 @@ password, }; $: form = makeForm(formFields); + $: ({ isSubmitting } = form); async function addNewDatabaseConnection() { - console.log('addNewDatabaseConnection'); const formValues = $form.values; return await databaseConnectionApi.add({ name: formValues.connectionName, @@ -59,11 +64,30 @@ }); } + async function updateDatabaseConnection() { + const formValues = $form.values; + if (database) { + return await databaseConnectionApi.update(database?.id, { + db_name: formValues.databaseName, + username: formValues.username, + host: formValues.host, + port: formValues.port, + ...(hasPasswordChanged ? { password: formValues.password } : undefined), + }); + } + throw new Error( + '[updateDatabaseConnection] called but no database found to edit.', + ); + } + async function saveConnectionDetails() { - console.log('saveConnectionDetails', isNewConnection); if (isNewConnection) { const database = await addNewDatabaseConnection(); dispatch('create', database); + } else { + await updateDatabaseConnection(); + form.reset(); + dispatch('update'); } } @@ -95,7 +119,10 @@ @@ -128,11 +155,11 @@ /> diff --git a/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte index 447c1cf6a6..b83b33a13d 100644 --- a/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte +++ b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte @@ -1,8 +1,21 @@ -
Edit DB Connection for {databaseName}
+ +

Edit Database Connection

+ + + + diff --git a/mathesar_ui/src/pages/database/ConnectionError.svelte b/mathesar_ui/src/pages/database/ConnectionError.svelte new file mode 100644 index 0000000000..ff4a59372b --- /dev/null +++ b/mathesar_ui/src/pages/database/ConnectionError.svelte @@ -0,0 +1,38 @@ + + + +

Error connecting to the database

+
+ + + Edit Connection + + +
+
diff --git a/mathesar_ui/src/pages/database/DatabaseDetails.svelte b/mathesar_ui/src/pages/database/DatabaseDetails.svelte index aad6f8c443..abdee66013 100644 --- a/mathesar_ui/src/pages/database/DatabaseDetails.svelte +++ b/mathesar_ui/src/pages/database/DatabaseDetails.svelte @@ -15,6 +15,7 @@ iconManageAccess, iconRefresh, iconMoreActions, + iconEdit, } from '@mathesar/icons'; import { confirmDelete } from '@mathesar/stores/confirmation'; import { modal } from '@mathesar/stores/modal'; @@ -32,6 +33,9 @@ import DbAccessControlModal from './DbAccessControlModal.svelte'; import SchemaRow from './SchemaRow.svelte'; import { deleteSchemaConfirmationBody } from './__help__/databaseHelp'; + import LinkMenuItem from '@mathesar/component-library/menu/LinkMenuItem.svelte'; + import { getDatabaseConnectionEditUrl } from '@mathesar/routes/urls'; + import ConnectionError from './ConnectionError.svelte'; const addEditModal = modal.spawnModalController(); const accessControlModal = modal.spawnModalController(); @@ -159,6 +163,12 @@ + + Edit Database Connection + {/if} @@ -169,41 +179,46 @@

Schemas ({schemasMap.size})

- - - {#if canExecuteDDL} - - {/if} - -

- {labeledCount(displayList, 'results')} - for all schemas matching - {filterQuery} -

-
    - {#each displayList as schema (schema.id)} -
  • - editSchema(schema)} - on:delete={() => deleteSchema(schema)} - /> -
  • - {/each} -
-
+ + {#if schemasMap.size === 0} + + {:else} + + + {#if canExecuteDDL} + + {/if} + +

+ {labeledCount(displayList, 'results')} + for all schemas matching + {filterQuery} +

+
    + {#each displayList as schema (schema.id)} +
  • + editSchema(schema)} + on:delete={() => deleteSchema(schema)} + /> +
  • + {/each} +
+
+ {/if} + + - - + + From 5110a402e35e1a18327984f0c2e3f7276776a3d9 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Sat, 23 Sep 2023 01:19:06 +0530 Subject: [PATCH 021/111] delete database connection --- mathesar_ui/src/api/databaseConnection.ts | 8 +- .../src/pages/database/DatabaseDetails.svelte | 36 +++++++-- ...DatabaseConnectionConfirmationModal.svelte | 75 +++++++++++++++++++ 3 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 mathesar_ui/src/pages/database/DeleteDatabaseConnectionConfirmationModal.svelte diff --git a/mathesar_ui/src/api/databaseConnection.ts b/mathesar_ui/src/api/databaseConnection.ts index b36e2f61cf..7fb041e038 100644 --- a/mathesar_ui/src/api/databaseConnection.ts +++ b/mathesar_ui/src/api/databaseConnection.ts @@ -1,5 +1,5 @@ import type { Database } from '@mathesar/AppTypes'; -import { patchAPI, postAPI } from './utils/requestUtils'; +import { deleteAPI, patchAPI, postAPI } from './utils/requestUtils'; export interface NewConnection { name: string; @@ -20,7 +20,13 @@ function update(databaseId: number, updates: ConnectionUpdates) { return patchAPI(`/api/db/v0/databases/${databaseId}/`, updates); } +function deleteConnection(databaseId: number, removeMathesarSchemas = false) { + const param = removeMathesarSchemas ? '?del_msar_schemas=True' : ''; + return deleteAPI(`/api/db/v0/databases/${databaseId}/${param}`); +} + export default { add, update, + delete: deleteConnection, }; diff --git a/mathesar_ui/src/pages/database/DatabaseDetails.svelte b/mathesar_ui/src/pages/database/DatabaseDetails.svelte index abdee66013..f79e1e89ee 100644 --- a/mathesar_ui/src/pages/database/DatabaseDetails.svelte +++ b/mathesar_ui/src/pages/database/DatabaseDetails.svelte @@ -16,6 +16,7 @@ iconRefresh, iconMoreActions, iconEdit, + iconDeleteMajor, } from '@mathesar/icons'; import { confirmDelete } from '@mathesar/stores/confirmation'; import { modal } from '@mathesar/stores/modal'; @@ -36,9 +37,13 @@ import LinkMenuItem from '@mathesar/component-library/menu/LinkMenuItem.svelte'; import { getDatabaseConnectionEditUrl } from '@mathesar/routes/urls'; import ConnectionError from './ConnectionError.svelte'; + import DeleteDatabaseConnectionConfirmationModal from './DeleteDatabaseConnectionConfirmationModal.svelte'; + import { reloadDatabases } from '@mathesar/stores/databases'; + import { router } from 'tinro'; const addEditModal = modal.spawnModalController(); const accessControlModal = modal.spawnModalController(); + const deleteConnectionModal = modal.spawnModalController(); const userProfileStore = getUserProfileStoreFromContext(); $: userProfile = $userProfileStore; @@ -114,6 +119,11 @@ isReflectionRunning = false; } } + + async function handleSuccessfulDeleteConnection() { + await reloadDatabases(); + router.goto('/'); + } - - Edit Database Connection - + {#if database.editable && userProfile?.isSuperUser} + + Edit Database Connection + + + deleteConnectionModal.open()} + > + Delete Connection + + {/if} {/if} @@ -228,6 +247,11 @@ /> + From ad09ba380418dfcab52ec6a4b6f2defb1d133b4c Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Sat, 23 Sep 2023 01:30:22 +0530 Subject: [PATCH 022/111] lint fixes --- .../AddDatabaseConnection.svelte | 4 ++-- .../DatabaseConnectionForm.svelte | 16 ++++++++-------- .../EditDatabaseConnection.svelte | 4 ++-- .../src/pages/database/DatabaseDetails.svelte | 8 ++++---- ...eteDatabaseConnectionConfirmationModal.svelte | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte b/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte index 7257587c31..ee3d147b72 100644 --- a/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte +++ b/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte @@ -1,9 +1,7 @@ +
+ diff --git a/mathesar_ui/src/routes/AdminRoute.svelte b/mathesar_ui/src/routes/AdminRoute.svelte index d6603458b3..024260e9da 100644 --- a/mathesar_ui/src/routes/AdminRoute.svelte +++ b/mathesar_ui/src/routes/AdminRoute.svelte @@ -31,6 +31,7 @@ From e7a9d1c0cff6f98f20818eec441587c5c1cfd9ff Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Tue, 26 Sep 2023 17:48:00 +0530 Subject: [PATCH 024/111] database connection list page & rounting --- mathesar/urls.py | 1 + mathesar/views.py | 7 ++ .../pages/admin-users/AdminNavigation.svelte | 76 +++++------- .../AddDatabaseConnection.svelte | 11 +- .../DatabaseConnectionItem.svelte | 77 ++++++++++++ .../DatabaseConnectionSkeleton.svelte | 16 +++ .../DatabaseConnectionsList.svelte | 116 ++++++++++++++++++ .../EditDatabaseConnection.svelte | 5 +- .../src/pages/database/NoDatabaseFound.svelte | 0 .../src/routes/DatabaseConnectionRoute.svelte | 6 +- mathesar_ui/src/routes/urls.ts | 3 +- 11 files changed, 264 insertions(+), 54 deletions(-) create mode 100644 mathesar_ui/src/pages/database-connection/DatabaseConnectionItem.svelte create mode 100644 mathesar_ui/src/pages/database-connection/DatabaseConnectionSkeleton.svelte create mode 100644 mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte create mode 100644 mathesar_ui/src/pages/database/NoDatabaseFound.svelte diff --git a/mathesar/urls.py b/mathesar/urls.py index 734d097b7b..6b51b68d11 100644 --- a/mathesar/urls.py +++ b/mathesar/urls.py @@ -53,6 +53,7 @@ path('administration/users/', views.admin_home, name='admin_users_home'), path('administration/users//', views.admin_home, name='admin_users_edit'), path('administration/update/', views.admin_home, name='admin_update'), + path('administration/db-connection/', views.list_database_connection, name='list_database_connection'), path('administration/db-connection/add/', views.add_database_connection, name='add_database_connection'), path('administration/db-connection/edit//', views.edit_database_connection, name='edit_database_connection'), path('shares/tables//', views.shared_table, name='shared_table'), diff --git a/mathesar/views.py b/mathesar/views.py index aaa4689e21..1f56ac467e 100644 --- a/mathesar/views.py +++ b/mathesar/views.py @@ -288,6 +288,13 @@ def schemas(request, db_name): }) +@login_required +def list_database_connection(request): + return render(request, 'mathesar/index.html', { + 'common_data': get_common_data(request) + }) + + @login_required def add_database_connection(request): return render(request, 'mathesar/index.html', { diff --git a/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte b/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte index f81e5df608..55e485f215 100644 --- a/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte +++ b/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte @@ -1,20 +1,15 @@
- -
- + +
diff --git a/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte b/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte index ee3d147b72..a60bf7ea97 100644 --- a/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte +++ b/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte @@ -1,9 +1,8 @@ + + + {#if !database.editable} + + + + {:else} + + + + {/if} +

{database.name}

+

{database.db_name}

+
+ + diff --git a/mathesar_ui/src/pages/database-connection/DatabaseConnectionSkeleton.svelte b/mathesar_ui/src/pages/database-connection/DatabaseConnectionSkeleton.svelte new file mode 100644 index 0000000000..ce0d043ff1 --- /dev/null +++ b/mathesar_ui/src/pages/database-connection/DatabaseConnectionSkeleton.svelte @@ -0,0 +1,16 @@ + + +
+ +
+ + diff --git a/mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte b/mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte new file mode 100644 index 0000000000..8a0de1a6f9 --- /dev/null +++ b/mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte @@ -0,0 +1,116 @@ + + + + {makeSimplePageTitle('Database Connections')} + + + + +

Database Connections {filteredConnectionsCountText}

+ +
+ {#if connectionsStatus === States.Loading && !isPreloaded} + + {:else if connectionsStatus === States.Done || isPreloaded} + + + + + Add Database Connection + + + +

+ {labeledCount(filteredConnections, 'results')} + for all database connections matching {filterQuery} +

+
+ + {#if filteredConnections.length} +
+ {#each filteredConnections as connection (connection.id)} + + {/each} +
+ {:else if connections.length === 0} +

No database connection found

+ {/if} +
+
+ {:else if connectionsStatus === States.Error} + +

Error: {connectionsError}

+
+ {/if} +
+ + diff --git a/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte index 5cb32c7a66..7f9e274f0a 100644 --- a/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte +++ b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte @@ -1,7 +1,6 @@ - + + + diff --git a/mathesar_ui/src/routes/urls.ts b/mathesar_ui/src/routes/urls.ts index b3f8999260..e4fb4e285c 100644 --- a/mathesar_ui/src/routes/urls.ts +++ b/mathesar_ui/src/routes/urls.ts @@ -116,7 +116,8 @@ export const ADMIN_USERS_PAGE_ADD_NEW_URL = `${ADMIN_URL}users/new/`; export const LOGOUT_URL = '/auth/logout/'; export const DATABASE_CONNECTION_SLUG = 'db-connection'; -export const ADD_DATABASE_CONNECTION_URL = `${ADMIN_URL}${DATABASE_CONNECTION_SLUG}/add/`; +export const DATABASE_CONNECTION_LIST_URL = `${ADMIN_URL}${DATABASE_CONNECTION_SLUG}/`; +export const DATABASE_CONNECTION_ADD_URL = `${ADMIN_URL}${DATABASE_CONNECTION_SLUG}/add/`; export function getDatabaseConnectionEditUrl(databaseName: string) { return `${ADMIN_URL}${DATABASE_CONNECTION_SLUG}/edit/${databaseName}/`; From cce8e0c5ad78ae5bb65407713fbe12fd4c1d721d Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Wed, 27 Sep 2023 18:33:06 +0530 Subject: [PATCH 025/111] renamed user form component --- .../form/GridFormInput.svelte} | 7 +++--- .../form/GridFormInputRow.svelte} | 0 .../DatabaseConnectionForm.svelte | 14 +++++------ .../PasswordChangeForm.svelte | 24 +++++++++---------- .../UserDetailsForm.svelte | 12 +++++----- 5 files changed, 29 insertions(+), 28 deletions(-) rename mathesar_ui/src/{systems/users-and-permissions/UserFormInput.svelte => components/form/GridFormInput.svelte} (92%) rename mathesar_ui/src/{systems/users-and-permissions/UserFormInputRow.svelte => components/form/GridFormInputRow.svelte} (100%) diff --git a/mathesar_ui/src/systems/users-and-permissions/UserFormInput.svelte b/mathesar_ui/src/components/form/GridFormInput.svelte similarity index 92% rename from mathesar_ui/src/systems/users-and-permissions/UserFormInput.svelte rename to mathesar_ui/src/components/form/GridFormInput.svelte index 8e81a7eec3..c703cbb6ef 100644 --- a/mathesar_ui/src/systems/users-and-permissions/UserFormInput.svelte +++ b/mathesar_ui/src/components/form/GridFormInput.svelte @@ -1,4 +1,6 @@ - +
{/if} -
+ diff --git a/mathesar_ui/src/pages/database/NoDatabaseFound.svelte b/mathesar_ui/src/pages/database/NoDatabaseFound.svelte index e69de29bb2..2be30e167a 100644 --- a/mathesar_ui/src/pages/database/NoDatabaseFound.svelte +++ b/mathesar_ui/src/pages/database/NoDatabaseFound.svelte @@ -0,0 +1,35 @@ + + + + + + + No Databases Found + + Looks like you don't have any databases set up. You'll need to connect + to a database to start using Mathesar. + + + Add Database Connection + + + + diff --git a/mathesar_ui/src/routes/AuthenticatedRoutes.svelte b/mathesar_ui/src/routes/AuthenticatedRoutes.svelte index 2cda4b8970..e71ceec904 100644 --- a/mathesar_ui/src/routes/AuthenticatedRoutes.svelte +++ b/mathesar_ui/src/routes/AuthenticatedRoutes.svelte @@ -1,8 +1,8 @@ - import type { Database, SchemaEntry } from '@mathesar/AppTypes'; + import type { + SuccessfullyConnectedDatabase, + SchemaEntry, + } from '@mathesar/AppTypes'; import { iconSchema } from '@mathesar/icons'; import { getSchemaPageUrl } from '@mathesar/routes/urls'; import { @@ -9,7 +12,7 @@ import BreadcrumbSelector from './BreadcrumbSelector.svelte'; import type { BreadcrumbSelectorEntry } from './breadcrumbTypes'; - export let database: Database; + export let database: SuccessfullyConnectedDatabase; function makeBreadcrumbSelectorItem( schemaEntry: SchemaEntry, diff --git a/mathesar_ui/src/components/breadcrumb/breadcrumbTypes.ts b/mathesar_ui/src/components/breadcrumb/breadcrumbTypes.ts index b18a6ea385..5af30bdbbf 100644 --- a/mathesar_ui/src/components/breadcrumb/breadcrumbTypes.ts +++ b/mathesar_ui/src/components/breadcrumb/breadcrumbTypes.ts @@ -1,6 +1,10 @@ import type { QueryInstance } from '@mathesar/api/types/queries'; import type { TableEntry } from '@mathesar/api/types/tables'; -import type { Database, SchemaEntry } from '@mathesar/AppTypes'; +import type { + SuccessfullyConnectedDatabase, + Database, + SchemaEntry, +} from '@mathesar/AppTypes'; import type { ComponentAndProps, IconProps, @@ -13,13 +17,13 @@ export interface BreadcrumbItemDatabase { export interface BreadcrumbItemSchema { type: 'schema'; - database: Database; + database: SuccessfullyConnectedDatabase; schema: SchemaEntry; } export interface BreadcrumbItemTable { type: 'table'; - database: Database; + database: SuccessfullyConnectedDatabase; schema: SchemaEntry; table: TableEntry; } @@ -33,7 +37,7 @@ export interface BreadcrumbItemSimple { export interface BreadcrumbItemRecord { type: 'record'; - database: Database; + database: SuccessfullyConnectedDatabase; schema: SchemaEntry; table: TableEntry; record: { @@ -44,7 +48,7 @@ export interface BreadcrumbItemRecord { export interface BreadcrumbItemExploration { type: 'exploration'; - database: Database; + database: SuccessfullyConnectedDatabase; schema: SchemaEntry; query: Pick; } diff --git a/mathesar_ui/src/components/form/GridFormInput.svelte b/mathesar_ui/src/components/form/GridFormInput.svelte index c703cbb6ef..da1ad30793 100644 --- a/mathesar_ui/src/components/form/GridFormInput.svelte +++ b/mathesar_ui/src/components/form/GridFormInput.svelte @@ -1,6 +1,5 @@ diff --git a/mathesar_ui/src/pages/database/AddEditSchemaModal.svelte b/mathesar_ui/src/pages/database/AddEditSchemaModal.svelte index 1f7dee9b77..4ef4dd0fb2 100644 --- a/mathesar_ui/src/pages/database/AddEditSchemaModal.svelte +++ b/mathesar_ui/src/pages/database/AddEditSchemaModal.svelte @@ -1,7 +1,10 @@ diff --git a/mathesar_ui/src/pages/schema/CreateNewTableButton.svelte b/mathesar_ui/src/pages/schema/CreateNewTableButton.svelte index 9d9918bccd..fc7321eda3 100644 --- a/mathesar_ui/src/pages/schema/CreateNewTableButton.svelte +++ b/mathesar_ui/src/pages/schema/CreateNewTableButton.svelte @@ -2,7 +2,10 @@ import { router } from 'tinro'; import { createTable } from '@mathesar/stores/tables'; import { getImportPageUrl, getTablePageUrl } from '@mathesar/routes/urls'; - import type { Database, SchemaEntry } from '@mathesar/AppTypes'; + import type { + SuccessfullyConnectedDatabase, + SchemaEntry, + } from '@mathesar/AppTypes'; import { DropdownMenu, Spinner, @@ -12,7 +15,7 @@ import Icon from '@mathesar/component-library/icon/Icon.svelte'; import LinkMenuItem from '@mathesar/component-library/menu/LinkMenuItem.svelte'; - export let database: Database; + export let database: SuccessfullyConnectedDatabase; export let schema: SchemaEntry; let isCreatingNewTable = false; diff --git a/mathesar_ui/src/pages/schema/CreateNewTableTutorial.svelte b/mathesar_ui/src/pages/schema/CreateNewTableTutorial.svelte index 2e1548783c..bbec045111 100644 --- a/mathesar_ui/src/pages/schema/CreateNewTableTutorial.svelte +++ b/mathesar_ui/src/pages/schema/CreateNewTableTutorial.svelte @@ -1,10 +1,13 @@ diff --git a/mathesar_ui/src/pages/schema/ExplorationItem.svelte b/mathesar_ui/src/pages/schema/ExplorationItem.svelte index 96080462e1..5cf8aa7a2e 100644 --- a/mathesar_ui/src/pages/schema/ExplorationItem.svelte +++ b/mathesar_ui/src/pages/schema/ExplorationItem.svelte @@ -5,10 +5,13 @@ import { iconExploration } from '@mathesar/icons'; import { getExplorationPageUrl } from '@mathesar/routes/urls'; import { tables as tablesStore } from '@mathesar/stores/tables'; - import type { Database, SchemaEntry } from '@mathesar/AppTypes'; + import type { + SuccessfullyConnectedDatabase, + SchemaEntry, + } from '@mathesar/AppTypes'; export let exploration: QueryInstance; - export let database: Database; + export let database: SuccessfullyConnectedDatabase; export let schema: SchemaEntry; $: baseTable = $tablesStore.data.get(exploration.base_table); diff --git a/mathesar_ui/src/pages/schema/ExplorationsList.svelte b/mathesar_ui/src/pages/schema/ExplorationsList.svelte index e900014e42..6980414a10 100644 --- a/mathesar_ui/src/pages/schema/ExplorationsList.svelte +++ b/mathesar_ui/src/pages/schema/ExplorationsList.svelte @@ -1,12 +1,15 @@ diff --git a/mathesar_ui/src/pages/schema/SchemaAccessControlModal.svelte b/mathesar_ui/src/pages/schema/SchemaAccessControlModal.svelte index d4224c7d9d..7fb5e31a81 100644 --- a/mathesar_ui/src/pages/schema/SchemaAccessControlModal.svelte +++ b/mathesar_ui/src/pages/schema/SchemaAccessControlModal.svelte @@ -3,7 +3,10 @@ ControlledModal, type ModalController, } from '@mathesar-component-library'; - import type { Database, SchemaEntry } from '@mathesar/AppTypes'; + import type { + SuccessfullyConnectedDatabase, + SchemaEntry, + } from '@mathesar/AppTypes'; import Identifier from '@mathesar/components/Identifier.svelte'; import { setUsersStoreInContext, @@ -15,7 +18,7 @@ import type { ObjectRoleMap } from '@mathesar/utils/permissions'; export let controller: ModalController; - export let database: Database; + export let database: SuccessfullyConnectedDatabase; export let schema: SchemaEntry; const usersStore = setUsersStoreInContext(); diff --git a/mathesar_ui/src/pages/schema/SchemaExplorations.svelte b/mathesar_ui/src/pages/schema/SchemaExplorations.svelte index 263e4a7692..9016768f9a 100644 --- a/mathesar_ui/src/pages/schema/SchemaExplorations.svelte +++ b/mathesar_ui/src/pages/schema/SchemaExplorations.svelte @@ -1,6 +1,9 @@ diff --git a/mathesar_ui/src/routes/AuthenticatedRoutes.svelte b/mathesar_ui/src/routes/AuthenticatedRoutes.svelte index e71ceec904..c9da932132 100644 --- a/mathesar_ui/src/routes/AuthenticatedRoutes.svelte +++ b/mathesar_ui/src/routes/AuthenticatedRoutes.svelte @@ -11,7 +11,7 @@ const userProfileStore = getUserProfileStoreFromContext(); $: userProfile = $userProfileStore; - $: firstDatabase = $databases.data?.[0]; + $: firstDatabase = $databases.successfulConnections?.[0]; {#if firstDatabase} diff --git a/mathesar_ui/src/routes/DataExplorerRoute.svelte b/mathesar_ui/src/routes/DataExplorerRoute.svelte index be960e6bce..75d2d69c60 100644 --- a/mathesar_ui/src/routes/DataExplorerRoute.svelte +++ b/mathesar_ui/src/routes/DataExplorerRoute.svelte @@ -1,6 +1,9 @@ diff --git a/mathesar_ui/src/routes/RecordPageRoute.svelte b/mathesar_ui/src/routes/RecordPageRoute.svelte index eecccf3d51..2c653e5a5b 100644 --- a/mathesar_ui/src/routes/RecordPageRoute.svelte +++ b/mathesar_ui/src/routes/RecordPageRoute.svelte @@ -2,10 +2,13 @@ import AppendBreadcrumb from '@mathesar/components/breadcrumb/AppendBreadcrumb.svelte'; import RecordPage from '@mathesar/pages/record/RecordPage.svelte'; import type { TableEntry } from '@mathesar/api/types/tables'; - import type { Database, SchemaEntry } from '@mathesar/AppTypes'; + import type { + SuccessfullyConnectedDatabase, + SchemaEntry, + } from '@mathesar/AppTypes'; import RecordStore from '@mathesar/pages/record/RecordStore'; - export let database: Database; + export let database: SuccessfullyConnectedDatabase; export let schema: SchemaEntry; export let table: TableEntry; export let recordPk: string; diff --git a/mathesar_ui/src/routes/SchemaRoute.svelte b/mathesar_ui/src/routes/SchemaRoute.svelte index 164449b2d7..a863a3be45 100644 --- a/mathesar_ui/src/routes/SchemaRoute.svelte +++ b/mathesar_ui/src/routes/SchemaRoute.svelte @@ -2,7 +2,7 @@ import { onMount } from 'svelte'; import { Route } from 'tinro'; - import type { Database } from '@mathesar/AppTypes'; + import type { SuccessfullyConnectedDatabase } from '@mathesar/AppTypes'; import ErrorPage from '@mathesar/pages/ErrorPage.svelte'; import SchemaPage from '@mathesar/pages/schema/SchemaPage.svelte'; import { currentSchemaId, schemas } from '@mathesar/stores/schemas'; @@ -16,7 +16,7 @@ const userProfile = getUserProfileStoreFromContext(); - export let database: Database; + export let database: SuccessfullyConnectedDatabase; export let schemaId: number; $: $currentSchemaId = schemaId; diff --git a/mathesar_ui/src/routes/TableRoute.svelte b/mathesar_ui/src/routes/TableRoute.svelte index 2d68876158..e13a1de0cd 100644 --- a/mathesar_ui/src/routes/TableRoute.svelte +++ b/mathesar_ui/src/routes/TableRoute.svelte @@ -2,14 +2,17 @@ import { onMount } from 'svelte'; import { Route } from 'tinro'; - import type { Database, SchemaEntry } from '@mathesar/AppTypes'; + import type { + SuccessfullyConnectedDatabase, + SchemaEntry, + } from '@mathesar/AppTypes'; import ErrorPage from '@mathesar/pages/ErrorPage.svelte'; import TablePage from '@mathesar/pages/table/TablePage.svelte'; import { currentTableId, tables } from '@mathesar/stores/tables'; import AppendBreadcrumb from '@mathesar/components/breadcrumb/AppendBreadcrumb.svelte'; import RecordPageRoute from './RecordPageRoute.svelte'; - export let database: Database; + export let database: SuccessfullyConnectedDatabase; export let schema: SchemaEntry; export let tableId: number; diff --git a/mathesar_ui/src/stores/abstract-types/store.ts b/mathesar_ui/src/stores/abstract-types/store.ts index ee9a8cf9bc..84f05fe7bd 100644 --- a/mathesar_ui/src/stores/abstract-types/store.ts +++ b/mathesar_ui/src/stores/abstract-types/store.ts @@ -4,7 +4,7 @@ import { currentDatabase } from '@mathesar/stores/databases'; import { preloadCommonData } from '@mathesar/utils/preloadData'; import type { Readable, Writable, Unsubscriber } from 'svelte/store'; -import type { Database } from '@mathesar/AppTypes'; +import type { SuccessfullyConnectedDatabase } from '@mathesar/AppTypes'; import type { CancellablePromise } from '@mathesar-component-library'; import type { AbstractTypesMap, @@ -17,16 +17,16 @@ import { constructAbstractTypeMapFromResponse } from './abstractTypeCategories'; const commonData = preloadCommonData(); const databasesToAbstractTypesStoreMap: Map< - Database['id'], + SuccessfullyConnectedDatabase['id'], Writable > = new Map(); const abstractTypesRequestMap: Map< - Database['id'], + SuccessfullyConnectedDatabase['id'], CancellablePromise > = new Map(); export async function refetchTypesForDb( - databaseId: Database['id'], + databaseId: SuccessfullyConnectedDatabase['id'], ): Promise { const store = databasesToAbstractTypesStoreMap.get(databaseId); if (!store) { @@ -75,7 +75,7 @@ export async function refetchTypesForDb( let preload = true; function getTypesForDatabase( - database: Database, + database: SuccessfullyConnectedDatabase, ): Writable { let store = databasesToAbstractTypesStoreMap.get(database.id); if (!store) { diff --git a/mathesar_ui/src/stores/databases.ts b/mathesar_ui/src/stores/databases.ts index 649733d8ca..377d320a45 100644 --- a/mathesar_ui/src/stores/databases.ts +++ b/mathesar_ui/src/stores/databases.ts @@ -1,37 +1,48 @@ import { writable, derived } from 'svelte/store'; -import { preloadCommonData } from '@mathesar/utils/preloadData'; +import { + isSuccessfullyConnectedDatabase, + preloadCommonData, +} from '@mathesar/utils/preloadData'; import databaseApi from '@mathesar/api/databases'; import { States } from '@mathesar/api/utils/requestUtils'; import type { Writable } from 'svelte/store'; -import type { Database } from '@mathesar/AppTypes'; +import type { + SuccessfullyConnectedDatabase, + Database, +} from '@mathesar/AppTypes'; import type { PaginatedResponse } from '@mathesar/api/utils/requestUtils'; import type { CancellablePromise } from '@mathesar-component-library'; const commonData = preloadCommonData(); -export const currentDBName: Writable = writable( - commonData?.current_db ?? undefined, -); +export const currentDBName: Writable< + SuccessfullyConnectedDatabase['name'] | undefined +> = writable(commonData?.current_db ?? undefined); export interface DatabaseStoreData { preload?: boolean; state: States; data: Database[]; error?: string; + successfulConnections: SuccessfullyConnectedDatabase[]; } export const databases = writable({ preload: true, state: States.Loading, data: commonData?.databases ?? [], + successfulConnections: (commonData?.databases ?? []).filter( + (database): database is SuccessfullyConnectedDatabase => + !('error' in database), + ), }); export const currentDatabase = derived( [currentDBName, databases], ([_currentDBName, databasesStore]) => { // eslint-disable-next-line @typescript-eslint/naming-convention - const _databases = databasesStore.data; + const _databases = databasesStore.successfulConnections; if (!_databases?.length) { return undefined; } @@ -54,14 +65,17 @@ export async function reloadDatabases(): Promise< databaseRequest = databaseApi.list(); const response = await databaseRequest; const data = response.results || []; + const successDatabases = data.filter(isSuccessfullyConnectedDatabase); databases.set({ state: States.Done, data, + successfulConnections: successDatabases, }); return response; } catch (err) { databases.set({ data: [], + successfulConnections: [], state: States.Error, error: err instanceof Error ? err.message : undefined, }); diff --git a/mathesar_ui/src/stores/schemas.ts b/mathesar_ui/src/stores/schemas.ts index f860c27cb7..01639be86c 100644 --- a/mathesar_ui/src/stores/schemas.ts +++ b/mathesar_ui/src/stores/schemas.ts @@ -11,7 +11,11 @@ import { } from '@mathesar/api/utils/requestUtils'; import type { PaginatedResponse } from '@mathesar/api/utils/requestUtils'; -import type { Database, SchemaEntry, SchemaResponse } from '@mathesar/AppTypes'; +import type { + SuccessfullyConnectedDatabase, + SchemaEntry, + SchemaResponse, +} from '@mathesar/AppTypes'; import type { CancellablePromise } from '@mathesar-component-library'; import { currentDBName } from './databases'; @@ -28,11 +32,11 @@ export interface DBSchemaStoreData { } const dbSchemaStoreMap: Map< - Database['name'], + SuccessfullyConnectedDatabase['name'], Writable > = new Map(); const dbSchemasRequestMap: Map< - Database['name'], + SuccessfullyConnectedDatabase['name'], CancellablePromise | undefined> > = new Map(); @@ -43,7 +47,7 @@ function findStoreBySchemaId(id: SchemaEntry['id']) { } function setDBSchemaStore( - database: Database['name'], + database: SuccessfullyConnectedDatabase['name'], schemas: SchemaResponse[], ): Writable { const schemaMap: DBSchemaStoreData['data'] = new Map(); @@ -67,7 +71,7 @@ function setDBSchemaStore( } function updateSchemaInDBSchemaStore( - database: Database['name'], + database: SuccessfullyConnectedDatabase['name'], schema: SchemaResponse, ) { const store = dbSchemaStoreMap.get(database); @@ -83,7 +87,7 @@ function updateSchemaInDBSchemaStore( } function removeSchemaInDBSchemaStore( - database: Database['name'], + database: SuccessfullyConnectedDatabase['name'], schemaId: SchemaEntry['id'], ) { const store = dbSchemaStoreMap.get(database); @@ -99,7 +103,7 @@ function removeSchemaInDBSchemaStore( } export function addCountToSchemaNumTables( - database: Database, + database: SuccessfullyConnectedDatabase, schema: SchemaEntry, count: number, ) { @@ -140,7 +144,7 @@ export function addCountToSchemaNumExplorations( } export async function refetchSchemasForDB( - database: Database['name'], + database: SuccessfullyConnectedDatabase['name'], ): Promise { const store = dbSchemaStoreMap.get(database); if (!store) { @@ -177,7 +181,7 @@ export async function refetchSchemasForDB( } export async function refetchSchema( - database: Database['name'], + database: SuccessfullyConnectedDatabase['name'], schemaId: SchemaEntry['id'], ): Promise { const store = dbSchemaStoreMap.get(database); @@ -203,7 +207,7 @@ export async function refetchSchema( let preload = true; export function getSchemasStoreForDB( - database: Database['name'], + database: SuccessfullyConnectedDatabase['name'], ): Writable { let store = dbSchemaStoreMap.get(database); if (!store) { @@ -225,7 +229,7 @@ export function getSchemasStoreForDB( } export function getSchemaInfo( - database: Database['name'], + database: SuccessfullyConnectedDatabase['name'], schemaId: SchemaEntry['id'], ): SchemaEntry | undefined { const store = dbSchemaStoreMap.get(database); @@ -236,7 +240,7 @@ export function getSchemaInfo( } export async function createSchema( - database: Database['name'], + database: SuccessfullyConnectedDatabase['name'], schemaName: SchemaEntry['name'], schemaDescription: SchemaEntry['description'], ): Promise { @@ -250,7 +254,7 @@ export async function createSchema( } export async function updateSchema( - database: Database['name'], + database: SuccessfullyConnectedDatabase['name'], schema: SchemaEntry, ): Promise { const url = `/api/db/v0/schemas/${schema.id}/`; @@ -263,7 +267,7 @@ export async function updateSchema( } export async function deleteSchema( - database: Database['name'], + database: SuccessfullyConnectedDatabase['name'], schemaId: SchemaEntry['id'], ): Promise { await deleteAPI(`/api/db/v0/schemas/${schemaId}/`); diff --git a/mathesar_ui/src/stores/tables.ts b/mathesar_ui/src/stores/tables.ts index a8a21d8bf9..6f39bc45c5 100644 --- a/mathesar_ui/src/stores/tables.ts +++ b/mathesar_ui/src/stores/tables.ts @@ -28,7 +28,11 @@ import type { SplitTableRequest, SplitTableResponse, } from '@mathesar/api/types/tables/split_table'; -import type { DBObjectEntry, Database, SchemaEntry } from '@mathesar/AppTypes'; +import type { + DBObjectEntry, + SuccessfullyConnectedDatabase, + SchemaEntry, +} from '@mathesar/AppTypes'; import { invalidIf } from '@mathesar/components/form'; import type { PaginatedResponse } from '@mathesar/api/utils/requestUtils'; import { @@ -189,7 +193,7 @@ function findAndUpdateTableStore(id: TableEntry['id'], tableEntry: TableEntry) { } export function deleteTable( - database: Database, + database: SuccessfullyConnectedDatabase, schema: SchemaEntry, tableId: TableEntry['id'], ): CancellablePromise { @@ -236,7 +240,7 @@ export function updateTableMetaData( } export function createTable( - database: Database, + database: SuccessfullyConnectedDatabase, schema: SchemaEntry, tableArgs: { name?: string; diff --git a/mathesar_ui/src/stores/users.ts b/mathesar_ui/src/stores/users.ts index 73eca377c5..8af77df9e0 100644 --- a/mathesar_ui/src/stores/users.ts +++ b/mathesar_ui/src/stores/users.ts @@ -12,7 +12,10 @@ import userApi, { import type { RequestStatus } from '@mathesar/api/utils/requestUtils'; import { getErrorMessage } from '@mathesar/utils/errors'; import type { MakeWritablePropertiesReadable } from '@mathesar/utils/typeUtils'; -import type { Database, SchemaEntry } from '@mathesar/AppTypes'; +import type { + SuccessfullyConnectedDatabase, + SchemaEntry, +} from '@mathesar/AppTypes'; import { rolesAllowOperation, type AccessOperation, @@ -49,7 +52,7 @@ export class UserModel { hasPermission( dbObject: { - database?: Pick; + database?: Pick; schema?: Pick; }, operation: AccessOperation, @@ -79,7 +82,7 @@ export class UserModel { return rolesAllowOperation(operation, roles); } - getRoleForDb(database: Pick) { + getRoleForDb(database: Pick) { return this.databaseRoles.get(database.id); } @@ -87,11 +90,11 @@ export class UserModel { return this.schemaRoles.get(schema.id); } - hasDirectDbAccess(database: Pick) { + hasDirectDbAccess(database: Pick) { return this.databaseRoles.has(database.id); } - hasDbAccess(database: Pick) { + hasDbAccess(database: Pick) { return this.hasDirectDbAccess(database) || this.isSuperUser; } @@ -100,7 +103,7 @@ export class UserModel { } hasSchemaAccess( - database: Pick, + database: Pick, schema: Pick, ) { return this.hasDbAccess(database) || this.hasDirectSchemaAccess(schema); @@ -255,7 +258,7 @@ class WritableUsersStore { async addDatabaseRoleForUser( userId: number, - database: Pick, + database: Pick, role: UserRole, ) { const dbRole = await userApi.addDatabaseRole(userId, database.id, role); @@ -272,7 +275,7 @@ class WritableUsersStore { async removeDatabaseAccessForUser( userId: number, - database: Pick, + database: Pick, ) { const user = get(this.users).find((entry) => entry.id === userId); const dbRole = user?.getRoleForDb(database); @@ -327,13 +330,15 @@ class WritableUsersStore { } } - getUsersWithAccessToDb(database: Pick) { + getUsersWithAccessToDb(database: Pick) { return derived(this.users, ($users) => $users.filter((user) => user.hasDbAccess(database)), ); } - getUsersWithoutAccessToDb(database: Pick) { + getUsersWithoutAccessToDb( + database: Pick, + ) { return derived(this.users, ($users) => $users.filter((user) => !user.hasDbAccess(database)), ); @@ -356,7 +361,7 @@ class WritableUsersStore { } getUsersWithAccessToSchema( - database: Pick, + database: Pick, schema: Pick, ) { return derived(this.users, ($users) => diff --git a/mathesar_ui/src/systems/users-and-permissions/UserDetailsForm.svelte b/mathesar_ui/src/systems/users-and-permissions/UserDetailsForm.svelte index f22197cef5..9789658696 100644 --- a/mathesar_ui/src/systems/users-and-permissions/UserDetailsForm.svelte +++ b/mathesar_ui/src/systems/users-and-permissions/UserDetailsForm.svelte @@ -21,8 +21,8 @@ } from '@mathesar/components/form'; import { iconSave, iconUndo } from '@mathesar/icons'; import { getUserProfileStoreFromContext } from '@mathesar/stores/userProfile'; - import SelectUserType from './SelectUserType.svelte'; import GridFormInput from '@mathesar/components/form/GridFormInput.svelte'; + import SelectUserType from './SelectUserType.svelte'; const dispatch = createEventDispatcher<{ create: User; update: undefined }>(); const userProfileStore = getUserProfileStoreFromContext(); diff --git a/mathesar_ui/src/utils/preloadData.ts b/mathesar_ui/src/utils/preloadData.ts index 1fbe7e567e..8ee0a2b8ef 100644 --- a/mathesar_ui/src/utils/preloadData.ts +++ b/mathesar_ui/src/utils/preloadData.ts @@ -1,7 +1,8 @@ import type { - Database, + SuccessfullyConnectedDatabase, SchemaResponse, AbstractTypeResponse, + Database, } from '@mathesar/AppTypes'; import type { TableEntry } from '@mathesar/api/types/tables'; import type { QueryInstance } from '@mathesar/api/types/queries'; @@ -43,3 +44,7 @@ export function preloadRouteData(routeName: string): T | undefined { export function preloadCommonData(): CommonData | undefined { return getData('#common-data'); } + +export const isSuccessfullyConnectedDatabase = ( + database: Database, +): database is SuccessfullyConnectedDatabase => !('error' in database); From 7c12f77b013750c205d88c206538a1a0b6c36a76 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Mon, 2 Oct 2023 23:16:12 +0530 Subject: [PATCH 028/111] renamed connections list vars --- .../DatabaseConnectionsList.svelte | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte b/mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte index b21eb86a3b..699eaaa89c 100644 --- a/mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte +++ b/mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte @@ -20,24 +20,24 @@ let filterQuery = ''; $: isPreloaded = $databases.preload; - $: connections = $databases.data; - $: connectionsStatus = $databases.state; - $: connectionsError = $databases.error; + $: allDatabases = $databases.data; + $: databasesLoadStatus = $databases.state; + $: databasesLoadError = $databases.error; - function filterConnections(_connections: Database[], query: string) { - function isMatch(connection: Database, q: string) { - if (!isSuccessfullyConnectedDatabase(connection)) { - return connection.name.toLowerCase().includes(q); + function filterDatabase(_databases: Database[], query: string) { + function isMatch(database: Database, q: string) { + if (!isSuccessfullyConnectedDatabase(database)) { + return database.name.toLowerCase().includes(q); } return ( - connection.name.toLowerCase().includes(q) || - connection.db_name.toLowerCase().includes(q) + database.name.toLowerCase().includes(q) || + database.db_name.toLowerCase().includes(q) ); } - return _connections.filter((connection) => { + return _databases.filter((database) => { if (query) { const sanitizedQuery = query.trim().toLowerCase(); - return isMatch(connection, sanitizedQuery); + return isMatch(database, sanitizedQuery); } return true; }); @@ -47,9 +47,9 @@ filterQuery = ''; } - $: filteredConnections = filterConnections(connections ?? [], filterQuery); - $: filteredConnectionsCountText = filteredConnections.length - ? `(${filteredConnections.length})` + $: filteredDatabases = filterDatabase(allDatabases ?? [], filterQuery); + $: filteredDatabasesCountText = filteredDatabases.length + ? `(${filteredDatabases.length})` : ''; @@ -66,12 +66,12 @@ }} /> -

Database Connections {filteredConnectionsCountText}

+

Database Connections {filteredDatabasesCountText}

- {#if connectionsStatus === States.Loading && !isPreloaded} + {#if databasesLoadStatus === States.Loading && !isPreloaded} - {:else if connectionsStatus === States.Done || isPreloaded} + {:else if databasesLoadStatus === States.Done || isPreloaded}

- {labeledCount(filteredConnections, 'results')} + {labeledCount(filteredDatabases, 'results')} for all database connections matching {filterQuery}

- {#if filteredConnections.length} + {#if filteredDatabases.length}
- {#each filteredConnections as connection (connection.id)} + {#each filteredDatabases as connection (connection.id)} {/each}
- {:else if connections.length === 0} + {:else if allDatabases.length === 0}

No database connection found

{/if}
- {:else if connectionsStatus === States.Error} + {:else if databasesLoadStatus === States.Error} -

Error: {connectionsError}

+

Error: {databasesLoadError}

{/if}
From fea9634406fbd2b762bfd8e8abc8f0933d82e8b2 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Mon, 2 Oct 2023 23:43:12 +0530 Subject: [PATCH 029/111] lint fixes --- .../src/pages/database/DatabaseNavigationList.svelte | 2 +- mathesar_ui/src/stores/databases.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mathesar_ui/src/pages/database/DatabaseNavigationList.svelte b/mathesar_ui/src/pages/database/DatabaseNavigationList.svelte index 8ab1a84d10..a469373a75 100644 --- a/mathesar_ui/src/pages/database/DatabaseNavigationList.svelte +++ b/mathesar_ui/src/pages/database/DatabaseNavigationList.svelte @@ -25,7 +25,7 @@ To add or remove databases, visit the - Add Database Configuration + Add Database Connection section of mathesar. diff --git a/mathesar_ui/src/stores/databases.ts b/mathesar_ui/src/stores/databases.ts index 377d320a45..abbf40592c 100644 --- a/mathesar_ui/src/stores/databases.ts +++ b/mathesar_ui/src/stores/databases.ts @@ -16,9 +16,9 @@ import type { CancellablePromise } from '@mathesar-component-library'; const commonData = preloadCommonData(); -export const currentDBName: Writable< - SuccessfullyConnectedDatabase['name'] | undefined -> = writable(commonData?.current_db ?? undefined); +export const currentDBName: Writable = writable( + commonData?.current_db ?? undefined, +); export interface DatabaseStoreData { preload?: boolean; From 8c194d4104cc1e7b1828f147b25af67d78c1a639 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Tue, 3 Oct 2023 00:26:28 +0530 Subject: [PATCH 030/111] user flow bug fixes --- mathesar/views.py | 4 +++ mathesar_ui/src/AppTypes.ts | 18 ++++++------ .../src/components/form/GridFormInput.svelte | 1 - .../AddDatabaseConnection.svelte | 2 ++ .../DatabaseConnectionForm.svelte | 29 ++++--------------- .../EditDatabaseConnection.svelte | 9 +++++- 6 files changed, 28 insertions(+), 35 deletions(-) diff --git a/mathesar/views.py b/mathesar/views.py index 30e8ae96de..0b9e548f92 100644 --- a/mathesar/views.py +++ b/mathesar/views.py @@ -81,7 +81,11 @@ def get_database_list(request): for db in permission_restricted_failed_db_qs: failed_db_data.append({ 'id': db.id, + 'username': db.username, + 'port': db.port, + 'host': db.host, 'name': db.name, + 'db_name': db.db_name, 'editable': db.editable, 'error': 'Error connecting to the database' }) diff --git a/mathesar_ui/src/AppTypes.ts b/mathesar_ui/src/AppTypes.ts index 0fec35df67..b636863b66 100644 --- a/mathesar_ui/src/AppTypes.ts +++ b/mathesar_ui/src/AppTypes.ts @@ -1,22 +1,22 @@ import type { TreeItem } from '@mathesar-component-library/types'; -export interface DatabaseWithConnectionError { +interface BaseDatabase { id: number; name: string; editable: boolean; + username: string; + host: string; + port: string; + db_name: string; +} + +export interface DatabaseWithConnectionError extends BaseDatabase { error: string; } -export interface SuccessfullyConnectedDatabase { - id: number; - name: string; +export interface SuccessfullyConnectedDatabase extends BaseDatabase { deleted: boolean; supported_types: string[]; - db_name: string; - editable: boolean; - username: string; - host: string; - port: string; } export type Database = diff --git a/mathesar_ui/src/components/form/GridFormInput.svelte b/mathesar_ui/src/components/form/GridFormInput.svelte index da1ad30793..a32c604bcf 100644 --- a/mathesar_ui/src/components/form/GridFormInput.svelte +++ b/mathesar_ui/src/components/form/GridFormInput.svelte @@ -1,5 +1,4 @@ From 070bd90ee883a2e3fd8ed29bbb597dcebbe52aff Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Tue, 3 Oct 2023 00:44:03 +0530 Subject: [PATCH 031/111] lint fixes --- .../pages/database-connection/AddDatabaseConnection.svelte | 2 +- .../pages/database-connection/DatabaseConnectionForm.svelte | 1 - .../pages/database-connection/EditDatabaseConnection.svelte | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte b/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte index ddb6972081..807033078d 100644 --- a/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte +++ b/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte @@ -9,9 +9,9 @@ import type { SuccessfullyConnectedDatabase } from '@mathesar/AppTypes'; import { router } from 'tinro'; import { reloadDatabases } from '@mathesar/stores/databases'; + import { reflectApi } from '@mathesar/api/reflect'; import FormBox from '../admin-users/FormBox.svelte'; import DatabaseConnectionForm from './DatabaseConnectionForm.svelte'; - import { reflectApi } from '@mathesar/api/reflect'; async function handleSuccess( event: CustomEvent, diff --git a/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte b/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte index 647e565f1f..9da879acab 100644 --- a/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte +++ b/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte @@ -13,7 +13,6 @@ import { createEventDispatcher } from 'svelte'; import { extractDetailedFieldBasedErrors } from '@mathesar/api/utils/errors'; import WarningBox from '@mathesar/components/message-boxes/WarningBox.svelte'; - import { isSuccessfullyConnectedDatabase } from '@mathesar/utils/preloadData'; const dispatch = createEventDispatcher<{ create: SuccessfullyConnectedDatabase; diff --git a/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte index 9f2329f641..09791aebd3 100644 --- a/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte +++ b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte @@ -7,10 +7,10 @@ getDatabasePageUrl, } from '@mathesar/routes/urls'; import { reloadDatabases } from '@mathesar/stores/databases'; - import FormBox from '../admin-users/FormBox.svelte'; - import DatabaseConnectionForm from './DatabaseConnectionForm.svelte'; import { reflectApi } from '@mathesar/api/reflect'; import { router } from 'tinro'; + import FormBox from '../admin-users/FormBox.svelte'; + import DatabaseConnectionForm from './DatabaseConnectionForm.svelte'; export let databaseName: string; From 668f922def5c0e534b5b0ea70f61c2b2b270d37c Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Tue, 3 Oct 2023 00:46:29 +0530 Subject: [PATCH 032/111] removed todos --- mathesar_ui/src/pages/database/AddEditSchemaModal.svelte | 1 - mathesar_ui/src/pages/database/DatabaseDetails.svelte | 1 - 2 files changed, 2 deletions(-) diff --git a/mathesar_ui/src/pages/database/AddEditSchemaModal.svelte b/mathesar_ui/src/pages/database/AddEditSchemaModal.svelte index 4ef4dd0fb2..604ed63711 100644 --- a/mathesar_ui/src/pages/database/AddEditSchemaModal.svelte +++ b/mathesar_ui/src/pages/database/AddEditSchemaModal.svelte @@ -1,4 +1,3 @@ - - import type { - SuccessfullyConnectedDatabase, - SchemaEntry, - } from '@mathesar/AppTypes'; + import type { Database, SchemaEntry } from '@mathesar/AppTypes'; import { iconSchema } from '@mathesar/icons'; import { getSchemaPageUrl } from '@mathesar/routes/urls'; import { @@ -12,7 +9,7 @@ import BreadcrumbSelector from './BreadcrumbSelector.svelte'; import type { BreadcrumbSelectorEntry } from './breadcrumbTypes'; - export let database: SuccessfullyConnectedDatabase; + export let database: Database; function makeBreadcrumbSelectorItem( schemaEntry: SchemaEntry, diff --git a/mathesar_ui/src/components/breadcrumb/breadcrumbTypes.ts b/mathesar_ui/src/components/breadcrumb/breadcrumbTypes.ts index 5af30bdbbf..b18a6ea385 100644 --- a/mathesar_ui/src/components/breadcrumb/breadcrumbTypes.ts +++ b/mathesar_ui/src/components/breadcrumb/breadcrumbTypes.ts @@ -1,10 +1,6 @@ import type { QueryInstance } from '@mathesar/api/types/queries'; import type { TableEntry } from '@mathesar/api/types/tables'; -import type { - SuccessfullyConnectedDatabase, - Database, - SchemaEntry, -} from '@mathesar/AppTypes'; +import type { Database, SchemaEntry } from '@mathesar/AppTypes'; import type { ComponentAndProps, IconProps, @@ -17,13 +13,13 @@ export interface BreadcrumbItemDatabase { export interface BreadcrumbItemSchema { type: 'schema'; - database: SuccessfullyConnectedDatabase; + database: Database; schema: SchemaEntry; } export interface BreadcrumbItemTable { type: 'table'; - database: SuccessfullyConnectedDatabase; + database: Database; schema: SchemaEntry; table: TableEntry; } @@ -37,7 +33,7 @@ export interface BreadcrumbItemSimple { export interface BreadcrumbItemRecord { type: 'record'; - database: SuccessfullyConnectedDatabase; + database: Database; schema: SchemaEntry; table: TableEntry; record: { @@ -48,7 +44,7 @@ export interface BreadcrumbItemRecord { export interface BreadcrumbItemExploration { type: 'exploration'; - database: SuccessfullyConnectedDatabase; + database: Database; schema: SchemaEntry; query: Pick; } diff --git a/mathesar_ui/src/pages/data-explorer/DataExplorerPage.svelte b/mathesar_ui/src/pages/data-explorer/DataExplorerPage.svelte index 9da414a031..6897eb592c 100644 --- a/mathesar_ui/src/pages/data-explorer/DataExplorerPage.svelte +++ b/mathesar_ui/src/pages/data-explorer/DataExplorerPage.svelte @@ -1,9 +1,6 @@ diff --git a/mathesar_ui/src/pages/schema/CreateNewTableButton.svelte b/mathesar_ui/src/pages/schema/CreateNewTableButton.svelte index fc7321eda3..9d9918bccd 100644 --- a/mathesar_ui/src/pages/schema/CreateNewTableButton.svelte +++ b/mathesar_ui/src/pages/schema/CreateNewTableButton.svelte @@ -2,10 +2,7 @@ import { router } from 'tinro'; import { createTable } from '@mathesar/stores/tables'; import { getImportPageUrl, getTablePageUrl } from '@mathesar/routes/urls'; - import type { - SuccessfullyConnectedDatabase, - SchemaEntry, - } from '@mathesar/AppTypes'; + import type { Database, SchemaEntry } from '@mathesar/AppTypes'; import { DropdownMenu, Spinner, @@ -15,7 +12,7 @@ import Icon from '@mathesar/component-library/icon/Icon.svelte'; import LinkMenuItem from '@mathesar/component-library/menu/LinkMenuItem.svelte'; - export let database: SuccessfullyConnectedDatabase; + export let database: Database; export let schema: SchemaEntry; let isCreatingNewTable = false; diff --git a/mathesar_ui/src/pages/schema/CreateNewTableTutorial.svelte b/mathesar_ui/src/pages/schema/CreateNewTableTutorial.svelte index bbec045111..2e1548783c 100644 --- a/mathesar_ui/src/pages/schema/CreateNewTableTutorial.svelte +++ b/mathesar_ui/src/pages/schema/CreateNewTableTutorial.svelte @@ -1,13 +1,10 @@ diff --git a/mathesar_ui/src/pages/schema/ExplorationItem.svelte b/mathesar_ui/src/pages/schema/ExplorationItem.svelte index 5cf8aa7a2e..96080462e1 100644 --- a/mathesar_ui/src/pages/schema/ExplorationItem.svelte +++ b/mathesar_ui/src/pages/schema/ExplorationItem.svelte @@ -5,13 +5,10 @@ import { iconExploration } from '@mathesar/icons'; import { getExplorationPageUrl } from '@mathesar/routes/urls'; import { tables as tablesStore } from '@mathesar/stores/tables'; - import type { - SuccessfullyConnectedDatabase, - SchemaEntry, - } from '@mathesar/AppTypes'; + import type { Database, SchemaEntry } from '@mathesar/AppTypes'; export let exploration: QueryInstance; - export let database: SuccessfullyConnectedDatabase; + export let database: Database; export let schema: SchemaEntry; $: baseTable = $tablesStore.data.get(exploration.base_table); diff --git a/mathesar_ui/src/pages/schema/ExplorationsList.svelte b/mathesar_ui/src/pages/schema/ExplorationsList.svelte index 6980414a10..e900014e42 100644 --- a/mathesar_ui/src/pages/schema/ExplorationsList.svelte +++ b/mathesar_ui/src/pages/schema/ExplorationsList.svelte @@ -1,15 +1,12 @@ diff --git a/mathesar_ui/src/pages/schema/SchemaAccessControlModal.svelte b/mathesar_ui/src/pages/schema/SchemaAccessControlModal.svelte index 7fb5e31a81..d4224c7d9d 100644 --- a/mathesar_ui/src/pages/schema/SchemaAccessControlModal.svelte +++ b/mathesar_ui/src/pages/schema/SchemaAccessControlModal.svelte @@ -3,10 +3,7 @@ ControlledModal, type ModalController, } from '@mathesar-component-library'; - import type { - SuccessfullyConnectedDatabase, - SchemaEntry, - } from '@mathesar/AppTypes'; + import type { Database, SchemaEntry } from '@mathesar/AppTypes'; import Identifier from '@mathesar/components/Identifier.svelte'; import { setUsersStoreInContext, @@ -18,7 +15,7 @@ import type { ObjectRoleMap } from '@mathesar/utils/permissions'; export let controller: ModalController; - export let database: SuccessfullyConnectedDatabase; + export let database: Database; export let schema: SchemaEntry; const usersStore = setUsersStoreInContext(); diff --git a/mathesar_ui/src/pages/schema/SchemaExplorations.svelte b/mathesar_ui/src/pages/schema/SchemaExplorations.svelte index 9016768f9a..263e4a7692 100644 --- a/mathesar_ui/src/pages/schema/SchemaExplorations.svelte +++ b/mathesar_ui/src/pages/schema/SchemaExplorations.svelte @@ -1,9 +1,6 @@ diff --git a/mathesar_ui/src/routes/AuthenticatedRoutes.svelte b/mathesar_ui/src/routes/AuthenticatedRoutes.svelte index c9da932132..e71ceec904 100644 --- a/mathesar_ui/src/routes/AuthenticatedRoutes.svelte +++ b/mathesar_ui/src/routes/AuthenticatedRoutes.svelte @@ -11,7 +11,7 @@ const userProfileStore = getUserProfileStoreFromContext(); $: userProfile = $userProfileStore; - $: firstDatabase = $databases.successfulConnections?.[0]; + $: firstDatabase = $databases.data?.[0]; {#if firstDatabase} diff --git a/mathesar_ui/src/routes/DataExplorerRoute.svelte b/mathesar_ui/src/routes/DataExplorerRoute.svelte index 75d2d69c60..be960e6bce 100644 --- a/mathesar_ui/src/routes/DataExplorerRoute.svelte +++ b/mathesar_ui/src/routes/DataExplorerRoute.svelte @@ -1,9 +1,6 @@ diff --git a/mathesar_ui/src/routes/RecordPageRoute.svelte b/mathesar_ui/src/routes/RecordPageRoute.svelte index 2c653e5a5b..eecccf3d51 100644 --- a/mathesar_ui/src/routes/RecordPageRoute.svelte +++ b/mathesar_ui/src/routes/RecordPageRoute.svelte @@ -2,13 +2,10 @@ import AppendBreadcrumb from '@mathesar/components/breadcrumb/AppendBreadcrumb.svelte'; import RecordPage from '@mathesar/pages/record/RecordPage.svelte'; import type { TableEntry } from '@mathesar/api/types/tables'; - import type { - SuccessfullyConnectedDatabase, - SchemaEntry, - } from '@mathesar/AppTypes'; + import type { Database, SchemaEntry } from '@mathesar/AppTypes'; import RecordStore from '@mathesar/pages/record/RecordStore'; - export let database: SuccessfullyConnectedDatabase; + export let database: Database; export let schema: SchemaEntry; export let table: TableEntry; export let recordPk: string; diff --git a/mathesar_ui/src/routes/SchemaRoute.svelte b/mathesar_ui/src/routes/SchemaRoute.svelte index a863a3be45..164449b2d7 100644 --- a/mathesar_ui/src/routes/SchemaRoute.svelte +++ b/mathesar_ui/src/routes/SchemaRoute.svelte @@ -2,7 +2,7 @@ import { onMount } from 'svelte'; import { Route } from 'tinro'; - import type { SuccessfullyConnectedDatabase } from '@mathesar/AppTypes'; + import type { Database } from '@mathesar/AppTypes'; import ErrorPage from '@mathesar/pages/ErrorPage.svelte'; import SchemaPage from '@mathesar/pages/schema/SchemaPage.svelte'; import { currentSchemaId, schemas } from '@mathesar/stores/schemas'; @@ -16,7 +16,7 @@ const userProfile = getUserProfileStoreFromContext(); - export let database: SuccessfullyConnectedDatabase; + export let database: Database; export let schemaId: number; $: $currentSchemaId = schemaId; diff --git a/mathesar_ui/src/routes/TableRoute.svelte b/mathesar_ui/src/routes/TableRoute.svelte index e13a1de0cd..2d68876158 100644 --- a/mathesar_ui/src/routes/TableRoute.svelte +++ b/mathesar_ui/src/routes/TableRoute.svelte @@ -2,17 +2,14 @@ import { onMount } from 'svelte'; import { Route } from 'tinro'; - import type { - SuccessfullyConnectedDatabase, - SchemaEntry, - } from '@mathesar/AppTypes'; + import type { Database, SchemaEntry } from '@mathesar/AppTypes'; import ErrorPage from '@mathesar/pages/ErrorPage.svelte'; import TablePage from '@mathesar/pages/table/TablePage.svelte'; import { currentTableId, tables } from '@mathesar/stores/tables'; import AppendBreadcrumb from '@mathesar/components/breadcrumb/AppendBreadcrumb.svelte'; import RecordPageRoute from './RecordPageRoute.svelte'; - export let database: SuccessfullyConnectedDatabase; + export let database: Database; export let schema: SchemaEntry; export let tableId: number; diff --git a/mathesar_ui/src/stores/abstract-types/store.ts b/mathesar_ui/src/stores/abstract-types/store.ts index 84f05fe7bd..ee9a8cf9bc 100644 --- a/mathesar_ui/src/stores/abstract-types/store.ts +++ b/mathesar_ui/src/stores/abstract-types/store.ts @@ -4,7 +4,7 @@ import { currentDatabase } from '@mathesar/stores/databases'; import { preloadCommonData } from '@mathesar/utils/preloadData'; import type { Readable, Writable, Unsubscriber } from 'svelte/store'; -import type { SuccessfullyConnectedDatabase } from '@mathesar/AppTypes'; +import type { Database } from '@mathesar/AppTypes'; import type { CancellablePromise } from '@mathesar-component-library'; import type { AbstractTypesMap, @@ -17,16 +17,16 @@ import { constructAbstractTypeMapFromResponse } from './abstractTypeCategories'; const commonData = preloadCommonData(); const databasesToAbstractTypesStoreMap: Map< - SuccessfullyConnectedDatabase['id'], + Database['id'], Writable > = new Map(); const abstractTypesRequestMap: Map< - SuccessfullyConnectedDatabase['id'], + Database['id'], CancellablePromise > = new Map(); export async function refetchTypesForDb( - databaseId: SuccessfullyConnectedDatabase['id'], + databaseId: Database['id'], ): Promise { const store = databasesToAbstractTypesStoreMap.get(databaseId); if (!store) { @@ -75,7 +75,7 @@ export async function refetchTypesForDb( let preload = true; function getTypesForDatabase( - database: SuccessfullyConnectedDatabase, + database: Database, ): Writable { let store = databasesToAbstractTypesStoreMap.get(database.id); if (!store) { diff --git a/mathesar_ui/src/stores/databases.ts b/mathesar_ui/src/stores/databases.ts index abbf40592c..649733d8ca 100644 --- a/mathesar_ui/src/stores/databases.ts +++ b/mathesar_ui/src/stores/databases.ts @@ -1,16 +1,10 @@ import { writable, derived } from 'svelte/store'; -import { - isSuccessfullyConnectedDatabase, - preloadCommonData, -} from '@mathesar/utils/preloadData'; +import { preloadCommonData } from '@mathesar/utils/preloadData'; import databaseApi from '@mathesar/api/databases'; import { States } from '@mathesar/api/utils/requestUtils'; import type { Writable } from 'svelte/store'; -import type { - SuccessfullyConnectedDatabase, - Database, -} from '@mathesar/AppTypes'; +import type { Database } from '@mathesar/AppTypes'; import type { PaginatedResponse } from '@mathesar/api/utils/requestUtils'; import type { CancellablePromise } from '@mathesar-component-library'; @@ -25,24 +19,19 @@ export interface DatabaseStoreData { state: States; data: Database[]; error?: string; - successfulConnections: SuccessfullyConnectedDatabase[]; } export const databases = writable({ preload: true, state: States.Loading, data: commonData?.databases ?? [], - successfulConnections: (commonData?.databases ?? []).filter( - (database): database is SuccessfullyConnectedDatabase => - !('error' in database), - ), }); export const currentDatabase = derived( [currentDBName, databases], ([_currentDBName, databasesStore]) => { // eslint-disable-next-line @typescript-eslint/naming-convention - const _databases = databasesStore.successfulConnections; + const _databases = databasesStore.data; if (!_databases?.length) { return undefined; } @@ -65,17 +54,14 @@ export async function reloadDatabases(): Promise< databaseRequest = databaseApi.list(); const response = await databaseRequest; const data = response.results || []; - const successDatabases = data.filter(isSuccessfullyConnectedDatabase); databases.set({ state: States.Done, data, - successfulConnections: successDatabases, }); return response; } catch (err) { databases.set({ data: [], - successfulConnections: [], state: States.Error, error: err instanceof Error ? err.message : undefined, }); diff --git a/mathesar_ui/src/stores/schemas.ts b/mathesar_ui/src/stores/schemas.ts index 01639be86c..f860c27cb7 100644 --- a/mathesar_ui/src/stores/schemas.ts +++ b/mathesar_ui/src/stores/schemas.ts @@ -11,11 +11,7 @@ import { } from '@mathesar/api/utils/requestUtils'; import type { PaginatedResponse } from '@mathesar/api/utils/requestUtils'; -import type { - SuccessfullyConnectedDatabase, - SchemaEntry, - SchemaResponse, -} from '@mathesar/AppTypes'; +import type { Database, SchemaEntry, SchemaResponse } from '@mathesar/AppTypes'; import type { CancellablePromise } from '@mathesar-component-library'; import { currentDBName } from './databases'; @@ -32,11 +28,11 @@ export interface DBSchemaStoreData { } const dbSchemaStoreMap: Map< - SuccessfullyConnectedDatabase['name'], + Database['name'], Writable > = new Map(); const dbSchemasRequestMap: Map< - SuccessfullyConnectedDatabase['name'], + Database['name'], CancellablePromise | undefined> > = new Map(); @@ -47,7 +43,7 @@ function findStoreBySchemaId(id: SchemaEntry['id']) { } function setDBSchemaStore( - database: SuccessfullyConnectedDatabase['name'], + database: Database['name'], schemas: SchemaResponse[], ): Writable { const schemaMap: DBSchemaStoreData['data'] = new Map(); @@ -71,7 +67,7 @@ function setDBSchemaStore( } function updateSchemaInDBSchemaStore( - database: SuccessfullyConnectedDatabase['name'], + database: Database['name'], schema: SchemaResponse, ) { const store = dbSchemaStoreMap.get(database); @@ -87,7 +83,7 @@ function updateSchemaInDBSchemaStore( } function removeSchemaInDBSchemaStore( - database: SuccessfullyConnectedDatabase['name'], + database: Database['name'], schemaId: SchemaEntry['id'], ) { const store = dbSchemaStoreMap.get(database); @@ -103,7 +99,7 @@ function removeSchemaInDBSchemaStore( } export function addCountToSchemaNumTables( - database: SuccessfullyConnectedDatabase, + database: Database, schema: SchemaEntry, count: number, ) { @@ -144,7 +140,7 @@ export function addCountToSchemaNumExplorations( } export async function refetchSchemasForDB( - database: SuccessfullyConnectedDatabase['name'], + database: Database['name'], ): Promise { const store = dbSchemaStoreMap.get(database); if (!store) { @@ -181,7 +177,7 @@ export async function refetchSchemasForDB( } export async function refetchSchema( - database: SuccessfullyConnectedDatabase['name'], + database: Database['name'], schemaId: SchemaEntry['id'], ): Promise { const store = dbSchemaStoreMap.get(database); @@ -207,7 +203,7 @@ export async function refetchSchema( let preload = true; export function getSchemasStoreForDB( - database: SuccessfullyConnectedDatabase['name'], + database: Database['name'], ): Writable { let store = dbSchemaStoreMap.get(database); if (!store) { @@ -229,7 +225,7 @@ export function getSchemasStoreForDB( } export function getSchemaInfo( - database: SuccessfullyConnectedDatabase['name'], + database: Database['name'], schemaId: SchemaEntry['id'], ): SchemaEntry | undefined { const store = dbSchemaStoreMap.get(database); @@ -240,7 +236,7 @@ export function getSchemaInfo( } export async function createSchema( - database: SuccessfullyConnectedDatabase['name'], + database: Database['name'], schemaName: SchemaEntry['name'], schemaDescription: SchemaEntry['description'], ): Promise { @@ -254,7 +250,7 @@ export async function createSchema( } export async function updateSchema( - database: SuccessfullyConnectedDatabase['name'], + database: Database['name'], schema: SchemaEntry, ): Promise { const url = `/api/db/v0/schemas/${schema.id}/`; @@ -267,7 +263,7 @@ export async function updateSchema( } export async function deleteSchema( - database: SuccessfullyConnectedDatabase['name'], + database: Database['name'], schemaId: SchemaEntry['id'], ): Promise { await deleteAPI(`/api/db/v0/schemas/${schemaId}/`); diff --git a/mathesar_ui/src/stores/tables.ts b/mathesar_ui/src/stores/tables.ts index 6f39bc45c5..a8a21d8bf9 100644 --- a/mathesar_ui/src/stores/tables.ts +++ b/mathesar_ui/src/stores/tables.ts @@ -28,11 +28,7 @@ import type { SplitTableRequest, SplitTableResponse, } from '@mathesar/api/types/tables/split_table'; -import type { - DBObjectEntry, - SuccessfullyConnectedDatabase, - SchemaEntry, -} from '@mathesar/AppTypes'; +import type { DBObjectEntry, Database, SchemaEntry } from '@mathesar/AppTypes'; import { invalidIf } from '@mathesar/components/form'; import type { PaginatedResponse } from '@mathesar/api/utils/requestUtils'; import { @@ -193,7 +189,7 @@ function findAndUpdateTableStore(id: TableEntry['id'], tableEntry: TableEntry) { } export function deleteTable( - database: SuccessfullyConnectedDatabase, + database: Database, schema: SchemaEntry, tableId: TableEntry['id'], ): CancellablePromise { @@ -240,7 +236,7 @@ export function updateTableMetaData( } export function createTable( - database: SuccessfullyConnectedDatabase, + database: Database, schema: SchemaEntry, tableArgs: { name?: string; diff --git a/mathesar_ui/src/stores/users.ts b/mathesar_ui/src/stores/users.ts index 8af77df9e0..73eca377c5 100644 --- a/mathesar_ui/src/stores/users.ts +++ b/mathesar_ui/src/stores/users.ts @@ -12,10 +12,7 @@ import userApi, { import type { RequestStatus } from '@mathesar/api/utils/requestUtils'; import { getErrorMessage } from '@mathesar/utils/errors'; import type { MakeWritablePropertiesReadable } from '@mathesar/utils/typeUtils'; -import type { - SuccessfullyConnectedDatabase, - SchemaEntry, -} from '@mathesar/AppTypes'; +import type { Database, SchemaEntry } from '@mathesar/AppTypes'; import { rolesAllowOperation, type AccessOperation, @@ -52,7 +49,7 @@ export class UserModel { hasPermission( dbObject: { - database?: Pick; + database?: Pick; schema?: Pick; }, operation: AccessOperation, @@ -82,7 +79,7 @@ export class UserModel { return rolesAllowOperation(operation, roles); } - getRoleForDb(database: Pick) { + getRoleForDb(database: Pick) { return this.databaseRoles.get(database.id); } @@ -90,11 +87,11 @@ export class UserModel { return this.schemaRoles.get(schema.id); } - hasDirectDbAccess(database: Pick) { + hasDirectDbAccess(database: Pick) { return this.databaseRoles.has(database.id); } - hasDbAccess(database: Pick) { + hasDbAccess(database: Pick) { return this.hasDirectDbAccess(database) || this.isSuperUser; } @@ -103,7 +100,7 @@ export class UserModel { } hasSchemaAccess( - database: Pick, + database: Pick, schema: Pick, ) { return this.hasDbAccess(database) || this.hasDirectSchemaAccess(schema); @@ -258,7 +255,7 @@ class WritableUsersStore { async addDatabaseRoleForUser( userId: number, - database: Pick, + database: Pick, role: UserRole, ) { const dbRole = await userApi.addDatabaseRole(userId, database.id, role); @@ -275,7 +272,7 @@ class WritableUsersStore { async removeDatabaseAccessForUser( userId: number, - database: Pick, + database: Pick, ) { const user = get(this.users).find((entry) => entry.id === userId); const dbRole = user?.getRoleForDb(database); @@ -330,15 +327,13 @@ class WritableUsersStore { } } - getUsersWithAccessToDb(database: Pick) { + getUsersWithAccessToDb(database: Pick) { return derived(this.users, ($users) => $users.filter((user) => user.hasDbAccess(database)), ); } - getUsersWithoutAccessToDb( - database: Pick, - ) { + getUsersWithoutAccessToDb(database: Pick) { return derived(this.users, ($users) => $users.filter((user) => !user.hasDbAccess(database)), ); @@ -361,7 +356,7 @@ class WritableUsersStore { } getUsersWithAccessToSchema( - database: Pick, + database: Pick, schema: Pick, ) { return derived(this.users, ($users) => diff --git a/mathesar_ui/src/utils/preloadData.ts b/mathesar_ui/src/utils/preloadData.ts index 8ee0a2b8ef..77dce99970 100644 --- a/mathesar_ui/src/utils/preloadData.ts +++ b/mathesar_ui/src/utils/preloadData.ts @@ -1,8 +1,8 @@ import type { - SuccessfullyConnectedDatabase, SchemaResponse, AbstractTypeResponse, Database, + SuccessfullyConnectedDatabase, } from '@mathesar/AppTypes'; import type { TableEntry } from '@mathesar/api/types/tables'; import type { QueryInstance } from '@mathesar/api/types/queries'; From a94015deaaf9ca30ec8b09c5f1caad394bd5da0c Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Thu, 5 Oct 2023 16:41:54 +0530 Subject: [PATCH 035/111] fixed formatting --- mathesar_ui/src/pages/admin-users/AdminNavigation.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte b/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte index 55e485f215..40218f101d 100644 --- a/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte +++ b/mathesar_ui/src/pages/admin-users/AdminNavigation.svelte @@ -47,9 +47,9 @@ class="menu-item menu-item-link" use:active > - Database Connection + + Database Connection + From 5eb453f385edc87db06afb780b6ce71fcb453f02 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Thu, 5 Oct 2023 22:55:55 +0530 Subject: [PATCH 036/111] loader while reloading the db --- .../AddDatabaseConnection.svelte | 17 ++++++++----- .../DatabaseConnectionForm.svelte | 21 ++++++++-------- .../EditDatabaseConnection.svelte | 24 +++++++++++++++---- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte b/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte index a60bf7ea97..0b59eea703 100644 --- a/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte +++ b/mathesar_ui/src/pages/database-connection/AddDatabaseConnection.svelte @@ -13,12 +13,17 @@ import FormBox from '../admin-users/FormBox.svelte'; import DatabaseConnectionForm from './DatabaseConnectionForm.svelte'; - async function handleSuccess(event: CustomEvent) { - const database = event.detail; + async function handleSuccess(database: Database) { toast.success(`${database.name} connected successfully!`); - await reflectApi.reflect(); - await reloadDatabases(); - router.goto(getDatabasePageUrl(database.name)); + + try { + await reflectApi.reflect(); + await reloadDatabases(); + } catch (e) { + toast.fromError(e); + } finally { + router.goto(getDatabasePageUrl(database.name)); + } } @@ -34,5 +39,5 @@

Add Database Connection

- + diff --git a/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte b/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte index 98ffefdb41..05cf4d230a 100644 --- a/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte +++ b/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte @@ -13,14 +13,13 @@ import { createEventDispatcher } from 'svelte'; import { extractDetailedFieldBasedErrors } from '@mathesar/api/utils/errors'; import WarningBox from '@mathesar/components/message-boxes/WarningBox.svelte'; - - const dispatch = createEventDispatcher<{ - create: Database; - update: undefined; - }>(); + import DocsLink from '@mathesar/components/DocsLink.svelte'; let databaseNameProp: string | undefined = undefined; export { databaseNameProp as databaseName }; + export let onCreate: ((database: Database) => Promise) | undefined = + undefined; + export let onUpdate: (() => Promise) | undefined = undefined; $: database = $databases.data?.find((db) => db.name === databaseNameProp); $: isNewConnection = !database; @@ -29,7 +28,7 @@ $: databaseName = requiredField(database?.db_name ?? ''); $: username = requiredField(database?.username ?? ''); $: host = requiredField(database?.host ?? ''); - $: port = requiredField(database?.port ?? '', [ + $: port = requiredField(database?.port ?? '5432', [ (value) => !Number.isNaN(+value) ? { type: 'valid' } @@ -83,11 +82,11 @@ async function saveConnectionDetails() { if (isNewConnection) { const newDatabase = await addNewDatabaseConnection(); - dispatch('create', newDatabase); + await onCreate?.(newDatabase); } else { await updateDatabaseConnection(); form.reset(); - dispatch('update'); + await onUpdate?.(); } } @@ -167,9 +166,9 @@ {#if isNewConnection} - Every PostgreSQL database includes the "public" schema. This protected - schema can be read by anybody who accesses the database. They will all be - namespaced into Mathesar-specific schemas for safety and organization. + For Mathesar to function properly, we will add a number of functions and + types to this database. They will all be namespaced into + Mathesar-specific schemas for safety and organization. {/if} @@ -34,5 +46,9 @@

Edit Database Connection

- + From ddb942b2fddb2fb9573ab4fcc3b81c8bffaf4b2a Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Thu, 5 Oct 2023 23:09:28 +0530 Subject: [PATCH 037/111] placeholder for links --- mathesar_ui/src/components/form/GridFormInput.svelte | 9 +++++++-- .../DatabaseConnectionForm.svelte | 8 ++++++-- .../DeleteDatabaseConnectionConfirmationModal.svelte | 12 ++++++++++-- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/mathesar_ui/src/components/form/GridFormInput.svelte b/mathesar_ui/src/components/form/GridFormInput.svelte index a32c604bcf..a6e6442be7 100644 --- a/mathesar_ui/src/components/form/GridFormInput.svelte +++ b/mathesar_ui/src/components/form/GridFormInput.svelte @@ -33,9 +33,14 @@
- {#if help} + {#if $$slots.help || help}
- {help} + {#if $$slots.help} + + {/if} + {#if help} + {help} + {/if}
{/if} diff --git a/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte b/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte index 05cf4d230a..1fc7828c40 100644 --- a/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte +++ b/mathesar_ui/src/pages/database-connection/DatabaseConnectionForm.svelte @@ -150,8 +150,12 @@ label="Username *" field={username} input={{ component: TextInput }} - help="The user will need to have SUPERUSER or DB OWNER privileges on the database. Why is this needed?." - /> + > + + The user will need to have SUPERUSER or DB OWNER privileges on the + database. Why is this needed?. + + (); @@ -54,10 +55,17 @@ Mathesar's custom data types.

-

Learn more about the implications of deleting the Mathesar schema.

+

+ + Learn more about the implications of deleting the + Mathesar schema. +

- From fe6c7b622b9f6dd4722a5427b96bdca95c42ceff Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Fri, 6 Oct 2023 01:29:01 +0530 Subject: [PATCH 046/111] no condition on schema page on connection error --- mathesar_ui/src/routes/DatabaseRoute.svelte | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/mathesar_ui/src/routes/DatabaseRoute.svelte b/mathesar_ui/src/routes/DatabaseRoute.svelte index 773f9fefec..4ba7e544e5 100644 --- a/mathesar_ui/src/routes/DatabaseRoute.svelte +++ b/mathesar_ui/src/routes/DatabaseRoute.svelte @@ -7,7 +7,6 @@ import ErrorPage from '@mathesar/pages/ErrorPage.svelte'; import { currentDBName, databases } from '@mathesar/stores/databases'; import AppendBreadcrumb from '@mathesar/components/breadcrumb/AppendBreadcrumb.svelte'; - import { isSuccessfullyConnectedDatabase } from '@mathesar/utils/database'; import SchemaRoute from './SchemaRoute.svelte'; export let databaseName: string; @@ -29,11 +28,9 @@
- {#if isSuccessfullyConnectedDatabase(database)} - - - - {/if} + + + {:else} Database with name {databaseName} is not found. From e59072581ebc59b1c3578aa1779e784e95fb69ff Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Fri, 6 Oct 2023 01:37:26 +0530 Subject: [PATCH 047/111] disconnect database flow ux fixes --- .../DatabaseConnectionsList.svelte | 4 --- .../EditDatabaseConnection.svelte | 35 +++++++++++++++++-- .../src/pages/database/ConnectionError.svelte | 9 ++--- .../src/pages/database/DatabaseDetails.svelte | 4 +-- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte b/mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte index 468979efca..ea4e810d49 100644 --- a/mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte +++ b/mathesar_ui/src/pages/database-connection/DatabaseConnectionsList.svelte @@ -12,7 +12,6 @@ import EntityContainerWithFilterBar from '@mathesar/components/EntityContainerWithFilterBar.svelte'; import { AnchorButton, Icon } from '@mathesar/component-library'; import { labeledCount } from '@mathesar/utils/languageUtils'; - import { isSuccessfullyConnectedDatabase } from '@mathesar/utils/database'; import DatabaseConnectionSkeleton from './DatabaseConnectionSkeleton.svelte'; import { makeSimplePageTitle } from '../pageTitleUtils'; import DatabaseConnectionItem from './DatabaseConnectionItem.svelte'; @@ -24,9 +23,6 @@ $: databasesLoadError = $databases.error; function isMatch(database: Database, q: string) { - if (!isSuccessfullyConnectedDatabase(database)) { - return database.name.toLowerCase().includes(q); - } return ( database.name.toLowerCase().includes(q) || database.db_name.toLowerCase().includes(q) diff --git a/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte index d6f90bb731..7421bb87c5 100644 --- a/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte +++ b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte @@ -1,19 +1,27 @@ + +{#if database} + + + + +{/if} diff --git a/mathesar_ui/src/pages/database/ConnectionError.svelte b/mathesar_ui/src/pages/database/ConnectionError.svelte index ff4a59372b..9f3c307a30 100644 --- a/mathesar_ui/src/pages/database/ConnectionError.svelte +++ b/mathesar_ui/src/pages/database/ConnectionError.svelte @@ -1,4 +1,5 @@ -

Error connecting to the database

+

{database.error}

diff --git a/mathesar_ui/src/pages/database/DatabaseDetails.svelte b/mathesar_ui/src/pages/database/DatabaseDetails.svelte index e395b6fb88..96d652dc6e 100644 --- a/mathesar_ui/src/pages/database/DatabaseDetails.svelte +++ b/mathesar_ui/src/pages/database/DatabaseDetails.svelte @@ -185,7 +185,7 @@ icon={iconDeleteMajor} on:click={() => deleteConnectionModal.open()} > - Delete Connection + Disconnect Database {/if} @@ -199,7 +199,7 @@

Schemas ({schemasMap.size})

{#if !isSuccessfullyConnectedDatabase(database)} - + {:else} Date: Fri, 6 Oct 2023 01:44:45 +0530 Subject: [PATCH 048/111] lint fixes --- .../pages/database-connection/EditDatabaseConnection.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte index 7421bb87c5..66a2e53894 100644 --- a/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte +++ b/mathesar_ui/src/pages/database-connection/EditDatabaseConnection.svelte @@ -9,12 +9,12 @@ import { databases, reloadDatabases } from '@mathesar/stores/databases'; import { reflectApi } from '@mathesar/api/reflect'; import { router } from 'tinro'; - import FormBox from '../admin-users/FormBox.svelte'; - import DatabaseConnectionForm from './DatabaseConnectionForm.svelte'; - import DeleteDatabaseConnectionConfirmationModal from '../database/DeleteDatabaseConnectionConfirmationModal.svelte'; import { modal } from '@mathesar/stores/modal'; import Button from '@mathesar/component-library/button/Button.svelte'; import { Icon } from '@mathesar/component-library'; + import FormBox from '../admin-users/FormBox.svelte'; + import DatabaseConnectionForm from './DatabaseConnectionForm.svelte'; + import DeleteDatabaseConnectionConfirmationModal from '../database/DeleteDatabaseConnectionConfirmationModal.svelte'; export let databaseName: string; From b11f2b04a8f161183181b852c20805dfd04f3c46 Mon Sep 17 00:00:00 2001 From: Rajat Vijay Date: Mon, 9 Oct 2023 16:58:39 +0530 Subject: [PATCH 049/111] move window.Mathesar.translations init in translations file --- config/context_processors.py | 4 ++++ mathesar/templates/mathesar/index.html | 19 ++++++++++--------- mathesar/utils/frontend.py | 1 + mathesar_ui/src/global.d.ts | 4 ++-- mathesar_ui/src/i18n/en/index.ts | 5 ++++- mathesar_ui/src/i18n/i18n-util.ts | 14 ++++++++++++++ mathesar_ui/src/i18n/ja/index.ts | 7 ++++++- 7 files changed, 41 insertions(+), 13 deletions(-) diff --git a/config/context_processors.py b/config/context_processors.py index 1c8e00ceae..4906bbf3e4 100644 --- a/config/context_processors.py +++ b/config/context_processors.py @@ -38,13 +38,17 @@ def get_i18n_settings(manifest_data, development_mode): if development_mode is True: module_translations_file_path = f'{client_dev_url}/src/i18n/{preferred_language}/index.ts' + legacy_translations_file_path = f'{client_dev_url}/src/i18n/{preferred_language}/index.ts' else: try: module_translations_file_path = static(manifest_data[preferred_language]["file"]) + legacy_translations_file_path = static(manifest_data[f"{preferred_language}-legacy"]["file"]) except KeyError: module_translations_file_path = static(manifest_data[default_language]["file"]) + legacy_translations_file_path = static(manifest_data[f"{default_language}-legacy"]["file"]) return { 'module_translations_file_path': module_translations_file_path, + 'legacy_translations_file_path': legacy_translations_file_path, 'preferred_language': preferred_language } diff --git a/mathesar/templates/mathesar/index.html b/mathesar/templates/mathesar/index.html index 0b979b348f..30e8593603 100644 --- a/mathesar/templates/mathesar/index.html +++ b/mathesar/templates/mathesar/index.html @@ -19,15 +19,7 @@ {% endfor %} {% endif %} - + {% if development_mode %} @@ -62,6 +54,15 @@ nomodule src="{% static manifest_data.legacy_polyfill_js %}" > + From 277592dde80e30a6c25905a60f406202aef3f520 Mon Sep 17 00:00:00 2001 From: Anish Date: Tue, 10 Oct 2023 20:25:59 +0530 Subject: [PATCH 054/111] use value of the fkey cell instead of the record id --- mathesar_ui/src/components/cell-fabric/CellFabric.svelte | 1 + .../components/linked-record/LinkedRecordCell.svelte | 5 ++++- .../cell-fabric/data-types/components/typeDefinitions.ts | 4 +++- .../src/systems/record-selector/RecordSelectorContent.svelte | 2 +- .../src/systems/record-selector/RecordSelectorController.ts | 2 ++ .../src/systems/record-selector/RecordSelectorTable.svelte | 2 +- 6 files changed, 12 insertions(+), 4 deletions(-) diff --git a/mathesar_ui/src/components/cell-fabric/CellFabric.svelte b/mathesar_ui/src/components/cell-fabric/CellFabric.svelte index 8a405123da..d77a167437 100644 --- a/mathesar_ui/src/components/cell-fabric/CellFabric.svelte +++ b/mathesar_ui/src/components/cell-fabric/CellFabric.svelte @@ -55,6 +55,7 @@ , LinkedRecordCellExternalProps { + columnFabric?: ProcessedColumn; recordSummary?: string; setRecordSummary?: (recordId: string, recordSummary: string) => void; } diff --git a/mathesar_ui/src/systems/record-selector/RecordSelectorContent.svelte b/mathesar_ui/src/systems/record-selector/RecordSelectorContent.svelte index ed17a9aba8..ecdf011fa7 100644 --- a/mathesar_ui/src/systems/record-selector/RecordSelectorContent.svelte +++ b/mathesar_ui/src/systems/record-selector/RecordSelectorContent.svelte @@ -96,7 +96,7 @@ template, transitiveData: buildRecordSummariesForSheet(previewData), }); - submitResult({ recordId, recordSummary }); + submitResult({ recordId, recordSummary, record }); } catch (err) { toast.error(getErrorMessage(err)); // TODO set errors in tabularData to appear within cells diff --git a/mathesar_ui/src/systems/record-selector/RecordSelectorController.ts b/mathesar_ui/src/systems/record-selector/RecordSelectorController.ts index 81768f91c1..5ae080d971 100644 --- a/mathesar_ui/src/systems/record-selector/RecordSelectorController.ts +++ b/mathesar_ui/src/systems/record-selector/RecordSelectorController.ts @@ -4,6 +4,7 @@ import { writable } from 'svelte/store'; import type { Column } from '@mathesar/api/types/tables/columns'; import type { DBObjectEntry } from '@mathesar/AppTypes'; import type { RecordSelectorPurpose } from './recordSelectorUtils'; +import type { Result as ApiRecord } from '@mathesar/api/types/tables/records'; interface RecordSelectorControllerProps { onOpen?: () => void; @@ -16,6 +17,7 @@ type FkCellValue = string | number; export interface RecordSelectorResult { recordId: FkCellValue; recordSummary: string; + record: ApiRecord; } export class RecordSelectorController { diff --git a/mathesar_ui/src/systems/record-selector/RecordSelectorTable.svelte b/mathesar_ui/src/systems/record-selector/RecordSelectorTable.svelte index b9bc990dbd..567a354d0f 100644 --- a/mathesar_ui/src/systems/record-selector/RecordSelectorTable.svelte +++ b/mathesar_ui/src/systems/record-selector/RecordSelectorTable.svelte @@ -143,7 +143,7 @@ inputData: buildInputData(record), transitiveData: $recordSummaries, }); - submitResult({ recordId, recordSummary }); + submitResult({ recordId, recordSummary, record }); } function submitSelection() { From 3ec0709240707b6757576d51598d8d4c129ad95b Mon Sep 17 00:00:00 2001 From: Anish Date: Wed, 11 Oct 2023 00:06:53 +0530 Subject: [PATCH 055/111] make linter happy --- .../components/linked-record/LinkedRecordCell.svelte | 5 ++--- .../cell-fabric/data-types/components/typeDefinitions.ts | 2 +- .../src/systems/record-selector/RecordSelectorController.ts | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte index dd2ee3defa..09eff7789a 100644 --- a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte +++ b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte @@ -42,10 +42,9 @@ } event?.stopPropagation(); const result = await recordSelector.acquireUserInput({ tableId }); - const linkFk = columnFabric!.linkFk; - const LinkedFkid = linkFk!.referent_columns[0]; + const LinkedFkid = columnFabric.linkFk?.referent_columns[0]; if (result) { - value = result.record[LinkedFkid]; + value = result.record[LinkedFkid!]; setRecordSummary(String(result.recordId), result.recordSummary); dispatch('update', { value }); } diff --git a/mathesar_ui/src/components/cell-fabric/data-types/components/typeDefinitions.ts b/mathesar_ui/src/components/cell-fabric/data-types/components/typeDefinitions.ts index 2020965a29..b510849dcd 100644 --- a/mathesar_ui/src/components/cell-fabric/data-types/components/typeDefinitions.ts +++ b/mathesar_ui/src/components/cell-fabric/data-types/components/typeDefinitions.ts @@ -46,7 +46,7 @@ export interface LinkedRecordCellExternalProps { export interface LinkedRecordCellProps extends CellTypeProps, LinkedRecordCellExternalProps { - columnFabric?: ProcessedColumn; + columnFabric: ProcessedColumn; recordSummary?: string; setRecordSummary?: (recordId: string, recordSummary: string) => void; } diff --git a/mathesar_ui/src/systems/record-selector/RecordSelectorController.ts b/mathesar_ui/src/systems/record-selector/RecordSelectorController.ts index 5ae080d971..22f503f8c2 100644 --- a/mathesar_ui/src/systems/record-selector/RecordSelectorController.ts +++ b/mathesar_ui/src/systems/record-selector/RecordSelectorController.ts @@ -3,8 +3,8 @@ import { writable } from 'svelte/store'; import type { Column } from '@mathesar/api/types/tables/columns'; import type { DBObjectEntry } from '@mathesar/AppTypes'; -import type { RecordSelectorPurpose } from './recordSelectorUtils'; import type { Result as ApiRecord } from '@mathesar/api/types/tables/records'; +import type { RecordSelectorPurpose } from './recordSelectorUtils'; interface RecordSelectorControllerProps { onOpen?: () => void; From d3a13629c9c4bb29ba3b5467d6cadfa1c61a7d01 Mon Sep 17 00:00:00 2001 From: Anish Date: Wed, 11 Oct 2023 00:22:13 +0530 Subject: [PATCH 056/111] handle warnings --- .../components/linked-record/LinkedRecordCell.svelte | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte index 09eff7789a..5f06c67b1f 100644 --- a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte +++ b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte @@ -44,7 +44,12 @@ const result = await recordSelector.acquireUserInput({ tableId }); const LinkedFkid = columnFabric.linkFk?.referent_columns[0]; if (result) { - value = result.record[LinkedFkid!]; + if (LinkedFkid !== undefined && LinkedFkid !== null){ + value = result.record[LinkedFkid]; + } + else { + value = result.recordId; + } setRecordSummary(String(result.recordId), result.recordSummary); dispatch('update', { value }); } From 6990b5ad4ec31a377562ae37b37d8a8e9a67864a Mon Sep 17 00:00:00 2001 From: Anish Date: Wed, 11 Oct 2023 00:47:35 +0530 Subject: [PATCH 057/111] add a whitespace --- .../data-types/components/linked-record/LinkedRecordCell.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte index 5f06c67b1f..6c0666f586 100644 --- a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte +++ b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte @@ -44,7 +44,7 @@ const result = await recordSelector.acquireUserInput({ tableId }); const LinkedFkid = columnFabric.linkFk?.referent_columns[0]; if (result) { - if (LinkedFkid !== undefined && LinkedFkid !== null){ + if (LinkedFkid !== undefined && LinkedFkid !== null) { value = result.record[LinkedFkid]; } else { From 5a1ec7f7e1ef6a0822ba5f4e579a650b9e4c8c1e Mon Sep 17 00:00:00 2001 From: Anish Date: Wed, 11 Oct 2023 00:53:06 +0530 Subject: [PATCH 058/111] ran prettier --- .../components/linked-record/LinkedRecordCell.svelte | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte index 6c0666f586..dc2a231e9f 100644 --- a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte +++ b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte @@ -46,8 +46,7 @@ if (result) { if (LinkedFkid !== undefined && LinkedFkid !== null) { value = result.record[LinkedFkid]; - } - else { + } else { value = result.recordId; } setRecordSummary(String(result.recordId), result.recordSummary); From 387f51e6de1222eabd1c578e90dfc5422b7aafc1 Mon Sep 17 00:00:00 2001 From: Anish Date: Thu, 12 Oct 2023 23:40:15 +0530 Subject: [PATCH 059/111] add check & exclude cons in the cons mapping dict --- mathesar/api/serializers/constraints.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mathesar/api/serializers/constraints.py b/mathesar/api/serializers/constraints.py index 761f211099..825ba47cff 100644 --- a/mathesar/api/serializers/constraints.py +++ b/mathesar/api/serializers/constraints.py @@ -139,6 +139,10 @@ class Meta: 'foreignkey': ForeignKeyConstraintSerializer, 'primary': BaseConstraintSerializer, 'unique': BaseConstraintSerializer, + # Even though 'check' & 'exclude' constraints are currently unsupported it's added here + # so that the app doesn't break in case these constraints are already present. + 'check': BaseConstraintSerializer, + 'exclude': BaseConstraintSerializer } def get_mapping_field(self, data): From 9c0253811cf0d64583aebca8d016d4ac2eda0f29 Mon Sep 17 00:00:00 2001 From: Anish Umale Date: Mon, 16 Oct 2023 18:44:04 +0530 Subject: [PATCH 060/111] rename LinkedFkid to LinkedFkCellValue --- .../components/linked-record/LinkedRecordCell.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte index dc2a231e9f..78948cf0ea 100644 --- a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte +++ b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte @@ -42,10 +42,10 @@ } event?.stopPropagation(); const result = await recordSelector.acquireUserInput({ tableId }); - const LinkedFkid = columnFabric.linkFk?.referent_columns[0]; + const LinkedFkCellValue = columnFabric.linkFk?.referent_columns[0]; if (result) { - if (LinkedFkid !== undefined && LinkedFkid !== null) { - value = result.record[LinkedFkid]; + if (LinkedFkCellValue !== undefined && LinkedFkCellValue !== null) { + value = result.record[LinkedFkCellValue]; } else { value = result.recordId; } From bc145a14e6bfcf892a73af7fd1f1c386c876551c Mon Sep 17 00:00:00 2001 From: Anish Date: Tue, 17 Oct 2023 13:35:27 +0530 Subject: [PATCH 061/111] fix validator to allow creating only 'f' 'p' & 'u' constraints --- mathesar/api/serializers/constraints.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mathesar/api/serializers/constraints.py b/mathesar/api/serializers/constraints.py index 825ba47cff..5a5955e04e 100644 --- a/mathesar/api/serializers/constraints.py +++ b/mathesar/api/serializers/constraints.py @@ -154,10 +154,12 @@ def get_mapping_field(self, data): return constraint_type def create(self, validated_data): + print('yo') serializer = self.get_serializer_class(self.get_mapping_field(validated_data)) return serializer.create(validated_data) def run_validation(self, data): + print('rv') if referent_table := data.get('referent_table', None): referent_table_name = Table.current_objects.get(id=referent_table).name if any( @@ -169,7 +171,7 @@ def run_validation(self, data): field='referent_table' ) constraint_type = data.get('type', None) - if constraint_type not in self.serializers_mapping.keys(): + if constraint_type not in ('foreignkey', 'primary', 'unique'): raise UnsupportedConstraintAPIException(constraint_type=constraint_type) columns = data.get('columns', None) if columns == []: From 727ddfbeac51fd0e66bb0ee927be375c986a6d55 Mon Sep 17 00:00:00 2001 From: Anish Date: Tue, 17 Oct 2023 13:36:24 +0530 Subject: [PATCH 062/111] rm print statements --- mathesar/api/serializers/constraints.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/mathesar/api/serializers/constraints.py b/mathesar/api/serializers/constraints.py index 5a5955e04e..0dc9b8cde8 100644 --- a/mathesar/api/serializers/constraints.py +++ b/mathesar/api/serializers/constraints.py @@ -154,12 +154,10 @@ def get_mapping_field(self, data): return constraint_type def create(self, validated_data): - print('yo') serializer = self.get_serializer_class(self.get_mapping_field(validated_data)) return serializer.create(validated_data) def run_validation(self, data): - print('rv') if referent_table := data.get('referent_table', None): referent_table_name = Table.current_objects.get(id=referent_table).name if any( From de023eabc422db98d5839656048d5a1afe4ac010 Mon Sep 17 00:00:00 2001 From: Anish Date: Thu, 19 Oct 2023 19:18:00 +0530 Subject: [PATCH 063/111] see if tests pass --- mathesar/tests/conftest.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/mathesar/tests/conftest.py b/mathesar/tests/conftest.py index f3c8f867c9..4b3dae0f01 100644 --- a/mathesar/tests/conftest.py +++ b/mathesar/tests/conftest.py @@ -99,13 +99,14 @@ def create_dj_db(request): def _create_and_add(db_name): create_db(db_name) add_db_to_dj_settings(db_name) + credentials = settings.DATABASES.get(db_name) database_model = Database.current_objects.create( name=db_name, db_name=db_name, - username='mathesar', - password='mathesar', - host='mathesar_dev_db', - port=5432 + username=credentials['USER'], + password=credentials['PASSWORD'], + host=credentials['HOST'], + port=credentials['PORT'] ) return database_model yield _create_and_add @@ -128,13 +129,14 @@ def test_db_model(request, test_db_name, django_db_blocker): add_db_to_dj_settings(test_db_name) with django_db_blocker.unblock(): + credentials = settings.DATABASES.get(test_db_name) database_model = Database.current_objects.create( name=test_db_name, db_name=test_db_name, - username='mathesar', - password='mathesar', - host='mathesar_dev_db', - port=5432 + username=credentials['USER'], + password=credentials['PASSWORD'], + host=credentials['HOST'], + port=credentials['PORT'] ) yield database_model database_model.delete() From f3fc9872fbddc1784b4c91feb338987b50017859 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 01:12:35 +0800 Subject: [PATCH 064/111] add jobs for testing strategy branches --- .github/workflows/handle-required-checks.yml | 22 ++++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/handle-required-checks.yml b/.github/workflows/handle-required-checks.yml index 40677fd4bc..13d7f42068 100644 --- a/.github/workflows/handle-required-checks.yml +++ b/.github/workflows/handle-required-checks.yml @@ -2,15 +2,7 @@ ## This handles the cases where they don't run because no Python or JS file has been changed. ## See https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks name: handle-required-checks -on: - push: - paths-ignore: - - 'mathesar_ui/**' - - '**.py' - pull_request: - paths-ignore: - - 'mathesar_ui/**' - - '**.py' +on: [push, pull_request] jobs: lint: runs-on: ubuntu-latest @@ -20,3 +12,15 @@ jobs: runs-on: ubuntu-latest steps: - run: 'echo "No tests required"' + tests (13): + runs-on: ubuntu-latest + steps: + - run: 'echo "No tests required"' + tests (14): + runs-on: ubuntu-latest + steps: + - run: 'echo "No tests required"' + tests (15): + runs-on: ubuntu-latest + steps: + - run: 'echo "No tests required"' From 7cfa9343159ac00cb3d2d4929754f00647ad186d Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 16:42:54 +0800 Subject: [PATCH 065/111] revert matrix job name specification --- .github/workflows/handle-required-checks.yml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/.github/workflows/handle-required-checks.yml b/.github/workflows/handle-required-checks.yml index 13d7f42068..277e6d596b 100644 --- a/.github/workflows/handle-required-checks.yml +++ b/.github/workflows/handle-required-checks.yml @@ -2,7 +2,7 @@ ## This handles the cases where they don't run because no Python or JS file has been changed. ## See https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks name: handle-required-checks -on: [push, pull_request] +on: [push, pull_request, merge_group] jobs: lint: runs-on: ubuntu-latest @@ -12,15 +12,3 @@ jobs: runs-on: ubuntu-latest steps: - run: 'echo "No tests required"' - tests (13): - runs-on: ubuntu-latest - steps: - - run: 'echo "No tests required"' - tests (14): - runs-on: ubuntu-latest - steps: - - run: 'echo "No tests required"' - tests (15): - runs-on: ubuntu-latest - steps: - - run: 'echo "No tests required"' From e5b10b90118beec5addb3cf3f485eeaaf2c2ab5b Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 16:48:31 +0800 Subject: [PATCH 066/111] change push out for merge_group trigger for pytest --- .github/workflows/run-pytest.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index d20f5a1d31..bf1fbb567e 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -1,23 +1,24 @@ +# Since we're using both the "require pull request" and "require merge queue" +# requirements for develop and master branches, there's no reason to run tests +# on every push. Instead, we're using the recommended "merge_group" formulation +# that runs status checks and reports them whenever a PR is added to the merge +# queue. + name: Run Python tests on: - push: + pull_request: paths: - '*.py' - 'mathesar/**' - 'db/**' - pull_request: + merge_group: paths: - '*.py' - 'mathesar/**' - 'db/**' - - jobs: tests: runs-on: ubuntu-latest - # We only want to run on external PRs, since internal PRs are covered by "push" - # This prevents this from running twice on internal PRs - if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository strategy: matrix: pg-version: [13, 14, 15] From 2ec27c89a23eab7f5ac5de263d6619b092db7df0 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 17:01:34 +0800 Subject: [PATCH 067/111] remove push trigger from fallback --- .github/workflows/handle-required-checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/handle-required-checks.yml b/.github/workflows/handle-required-checks.yml index 277e6d596b..1a3ee9f937 100644 --- a/.github/workflows/handle-required-checks.yml +++ b/.github/workflows/handle-required-checks.yml @@ -2,7 +2,7 @@ ## This handles the cases where they don't run because no Python or JS file has been changed. ## See https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks name: handle-required-checks -on: [push, pull_request, merge_group] +on: [pull_request, merge_group] jobs: lint: runs-on: ubuntu-latest From 2a8d1b70e99a5d3237247830699898304765cc09 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 17:02:14 +0800 Subject: [PATCH 068/111] remove path spec from pytest workflow (temp) --- .github/workflows/run-pytest.yml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index bf1fbb567e..2e20862920 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -5,17 +5,7 @@ # queue. name: Run Python tests -on: - pull_request: - paths: - - '*.py' - - 'mathesar/**' - - 'db/**' - merge_group: - paths: - - '*.py' - - 'mathesar/**' - - 'db/**' +on: [pull_request, merge_group] jobs: tests: runs-on: ubuntu-latest From 3cfd696632dee684e1d8f06be562fd33c4f58aa7 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 17:13:26 +0800 Subject: [PATCH 069/111] Use branching that will skip with a success output --- .github/workflows/run-pytest.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 2e20862920..4dbae133e0 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -7,8 +7,11 @@ name: Run Python tests on: [pull_request, merge_group] jobs: - tests: + python_tests: runs-on: ubuntu-latest + # Using this construct means we'll skip to "success". This avoids the + # unrecommended path filtering in this required job. + if: ${{ -n hashFiles('*.py', 'mathesar/**', 'db/**') }} strategy: matrix: pg-version: [13, 14, 15] From 1892f7736d4eb348f2b8aed5b5d01cd6802fa6e3 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 17:15:37 +0800 Subject: [PATCH 070/111] add run prompting dependent job --- .github/workflows/run-pytest.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 4dbae133e0..ec40982b9a 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -35,3 +35,5 @@ jobs: # Override setup.cfg docker-compose db service credentials with in built docker postgres server - name: Run tests with pytest run: docker exec -e DJANGO_DATABASE_URL="postgres://postgres:mathesar@localhost:5432/mathesar_django" -e MATHESAR_DATABASES="(mathesar_db_test|postgres://postgres:mathesar@localhost:5432/mathesar_db_test)" mathesar_service_test ./run_pytest.sh + tests: + needs: python_tests From 9f47674d3096a0c78cac154fa5cf42d94e15fad1 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 17:18:08 +0800 Subject: [PATCH 071/111] turn off 'tests' fallback in CI --- .github/workflows/handle-required-checks.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/handle-required-checks.yml b/.github/workflows/handle-required-checks.yml index 1a3ee9f937..13b60efadc 100644 --- a/.github/workflows/handle-required-checks.yml +++ b/.github/workflows/handle-required-checks.yml @@ -8,7 +8,3 @@ jobs: runs-on: ubuntu-latest steps: - run: 'echo "No lint required"' - tests: - runs-on: ubuntu-latest - steps: - - run: 'echo "No tests required"' From 9c2d078c2716b1d2cb0fa87b1bfca54ff77f0d78 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 17:25:29 +0800 Subject: [PATCH 072/111] experiment with extra conditional nudge --- .github/workflows/run-pytest.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index ec40982b9a..13d45f0be9 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -37,3 +37,4 @@ jobs: run: docker exec -e DJANGO_DATABASE_URL="postgres://postgres:mathesar@localhost:5432/mathesar_django" -e MATHESAR_DATABASES="(mathesar_db_test|postgres://postgres:mathesar@localhost:5432/mathesar_db_test)" mathesar_service_test ./run_pytest.sh tests: needs: python_tests + if: ${{ success() }} From 1c63067b5f1807392f95fcf6d655f4ff2e34b387 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 17:27:06 +0800 Subject: [PATCH 073/111] experiment with stronger nudge to run 'tests' --- .github/workflows/run-pytest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 13d45f0be9..e93aaaa5ea 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -37,4 +37,4 @@ jobs: run: docker exec -e DJANGO_DATABASE_URL="postgres://postgres:mathesar@localhost:5432/mathesar_django" -e MATHESAR_DATABASES="(mathesar_db_test|postgres://postgres:mathesar@localhost:5432/mathesar_db_test)" mathesar_service_test ./run_pytest.sh tests: needs: python_tests - if: ${{ success() }} + if: ${{ !failure() }} From 17e45a6e2603cef8a01261ed099258f28316ae62 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 17:47:14 +0800 Subject: [PATCH 074/111] add steps to collector job --- .github/workflows/run-pytest.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index e93aaaa5ea..36dc1c805b 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -36,5 +36,8 @@ jobs: - name: Run tests with pytest run: docker exec -e DJANGO_DATABASE_URL="postgres://postgres:mathesar@localhost:5432/mathesar_django" -e MATHESAR_DATABASES="(mathesar_db_test|postgres://postgres:mathesar@localhost:5432/mathesar_db_test)" mathesar_service_test ./run_pytest.sh tests: + runs-on: ubuntu-latest needs: python_tests - if: ${{ !failure() }} + steps: + - name: Report success + run: echo "Python tests succeeded or skipped!" From e406b49f04c6700afc30fed2975aaa8ef8008f17 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 17:48:45 +0800 Subject: [PATCH 075/111] fix syntax error (no bash conditionals?) --- .github/workflows/run-pytest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 36dc1c805b..28b0158833 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest # Using this construct means we'll skip to "success". This avoids the # unrecommended path filtering in this required job. - if: ${{ -n hashFiles('*.py', 'mathesar/**', 'db/**') }} + if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} strategy: matrix: pg-version: [13, 14, 15] From a2843deffe72206d51ad478c3949ba3381f2415a Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 21:55:34 +0800 Subject: [PATCH 076/111] try moving check into steps --- .github/workflows/run-pytest.yml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 28b0158833..f65225ba01 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -7,11 +7,10 @@ name: Run Python tests on: [pull_request, merge_group] jobs: - python_tests: + tests: runs-on: ubuntu-latest # Using this construct means we'll skip to "success". This avoids the # unrecommended path filtering in this required job. - if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} strategy: matrix: pg-version: [13, 14, 15] @@ -19,25 +18,30 @@ jobs: - uses: actions/checkout@v2 - name: Copy env file + if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} run: cp .env.example .env # The code is checked out under uid 1001 - reset this to 1000 for the # container to run tests successfully - name: Fix permissions + if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} run: sudo chown -R 1000:1000 . - name: Build the stack + if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} run: docker build -t mathesar_service_test --build-arg BUILD_PG_MAJOR=${{ matrix.pg-version }} --build-arg PYTHON_REQUIREMENTS=requirements-dev.txt . env: PG_MAJOR: ${{ matrix.pg-version }} - name: Run docker container + if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} run: docker run -d --name mathesar_service_test mathesar_service_test # Override setup.cfg docker-compose db service credentials with in built docker postgres server - name: Run tests with pytest + if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} run: docker exec -e DJANGO_DATABASE_URL="postgres://postgres:mathesar@localhost:5432/mathesar_django" -e MATHESAR_DATABASES="(mathesar_db_test|postgres://postgres:mathesar@localhost:5432/mathesar_db_test)" mathesar_service_test ./run_pytest.sh - tests: - runs-on: ubuntu-latest - needs: python_tests - steps: - - name: Report success - run: echo "Python tests succeeded or skipped!" +# tests: +# runs-on: ubuntu-latest +# needs: python_tests +# steps: +# - name: Report success +# run: echo "Python tests succeeded or skipped!" From f260d00fcb34bda8119170405153ad352c4dcaa4 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 22:42:48 +0800 Subject: [PATCH 077/111] try using 3rd party action --- .github/workflows/run-pytest.yml | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index f65225ba01..8588e5fc32 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -7,7 +7,7 @@ name: Run Python tests on: [pull_request, merge_group] jobs: - tests: + python_tests: runs-on: ubuntu-latest # Using this construct means we'll skip to "success". This avoids the # unrecommended path filtering in this required job. @@ -16,32 +16,40 @@ jobs: pg-version: [13, 14, 15] steps: - uses: actions/checkout@v2 + - name: Get changed files + id: changed_files + uses: tj-actions/changed-files@v39 + with: + files: | + *.py + mathesar/** + db/** - name: Copy env file - if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} + if: steps.changed_files.outputs.any_changed == 'true' run: cp .env.example .env # The code is checked out under uid 1001 - reset this to 1000 for the # container to run tests successfully - name: Fix permissions - if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} + if: steps.changed_files.outputs.any_changed == 'true' run: sudo chown -R 1000:1000 . - name: Build the stack - if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} + if: steps.changed_files.outputs.any_changed == 'true' run: docker build -t mathesar_service_test --build-arg BUILD_PG_MAJOR=${{ matrix.pg-version }} --build-arg PYTHON_REQUIREMENTS=requirements-dev.txt . env: PG_MAJOR: ${{ matrix.pg-version }} - name: Run docker container - if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} + if: steps.changed_files.outputs.any_changed == 'true' run: docker run -d --name mathesar_service_test mathesar_service_test # Override setup.cfg docker-compose db service credentials with in built docker postgres server - name: Run tests with pytest - if: ${{ hashFiles('*.py', 'mathesar/**', 'db/**') }} + if: steps.changed_files.outputs.any_changed == 'true' run: docker exec -e DJANGO_DATABASE_URL="postgres://postgres:mathesar@localhost:5432/mathesar_django" -e MATHESAR_DATABASES="(mathesar_db_test|postgres://postgres:mathesar@localhost:5432/mathesar_db_test)" mathesar_service_test ./run_pytest.sh -# tests: -# runs-on: ubuntu-latest -# needs: python_tests -# steps: -# - name: Report success -# run: echo "Python tests succeeded or skipped!" + tests: + runs-on: ubuntu-latest + needs: python_tests + steps: + - name: Report success + run: echo "Python tests succeeded or skipped!" From 707518eaf201748850ad61e21a86af20b5a50992 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 22:48:40 +0800 Subject: [PATCH 078/111] test tests failure --- .github/workflows/handle-required-checks.yml | 4 ++++ mathesar/tests/api/test_table_api.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/handle-required-checks.yml b/.github/workflows/handle-required-checks.yml index 13b60efadc..fae9a9075a 100644 --- a/.github/workflows/handle-required-checks.yml +++ b/.github/workflows/handle-required-checks.yml @@ -4,6 +4,10 @@ name: handle-required-checks on: [pull_request, merge_group] jobs: + tests: + runs-on: ubuntu-latest + steps: + - run: 'echo "No tests required"' lint: runs-on: ubuntu-latest steps: diff --git a/mathesar/tests/api/test_table_api.py b/mathesar/tests/api/test_table_api.py index 18df6ca1e0..1a620e6a2f 100644 --- a/mathesar/tests/api/test_table_api.py +++ b/mathesar/tests/api/test_table_api.py @@ -1679,7 +1679,7 @@ def test_table_extract_columns_retain_original_table(create_patents_table, clien response_data = current_table_response.json() extracted_table_id = response_data['extracted_table'] extracted_table = Table.objects.get(id=extracted_table_id) - assert extract_table_name == extracted_table.name + assert extract_table_name == extracted_table.name + 'a' remainder_table_id = response_data['remainder_table'] remainder_table = Table.objects.get(id=remainder_table_id) assert Table.objects.filter(id=table.id).count() == 1 From ece69407421acfdffc0cea3f48f1b28de72a2ecc Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 23:15:44 +0800 Subject: [PATCH 079/111] change back to docker compose setup --- .github/workflows/run-pytest.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 8588e5fc32..99a4bac806 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -37,16 +37,14 @@ jobs: - name: Build the stack if: steps.changed_files.outputs.any_changed == 'true' - run: docker build -t mathesar_service_test --build-arg BUILD_PG_MAJOR=${{ matrix.pg-version }} --build-arg PYTHON_REQUIREMENTS=requirements-dev.txt . + run: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d test-service env: PG_MAJOR: ${{ matrix.pg-version }} - - name: Run docker container - if: steps.changed_files.outputs.any_changed == 'true' - run: docker run -d --name mathesar_service_test mathesar_service_test - # Override setup.cfg docker-compose db service credentials with in built docker postgres server + - name: Run tests with pytest if: steps.changed_files.outputs.any_changed == 'true' - run: docker exec -e DJANGO_DATABASE_URL="postgres://postgres:mathesar@localhost:5432/mathesar_django" -e MATHESAR_DATABASES="(mathesar_db_test|postgres://postgres:mathesar@localhost:5432/mathesar_db_test)" mathesar_service_test ./run_pytest.sh + run: docker exec mathesar_service_test ./run_pytest.sh + tests: runs-on: ubuntu-latest needs: python_tests From b64ada99552630f96a0fea59318e942e9ed5d4b5 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 24 Oct 2023 23:57:33 +0800 Subject: [PATCH 080/111] test passing tests --- mathesar/tests/api/test_table_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mathesar/tests/api/test_table_api.py b/mathesar/tests/api/test_table_api.py index 1a620e6a2f..18df6ca1e0 100644 --- a/mathesar/tests/api/test_table_api.py +++ b/mathesar/tests/api/test_table_api.py @@ -1679,7 +1679,7 @@ def test_table_extract_columns_retain_original_table(create_patents_table, clien response_data = current_table_response.json() extracted_table_id = response_data['extracted_table'] extracted_table = Table.objects.get(id=extracted_table_id) - assert extract_table_name == extracted_table.name + 'a' + assert extract_table_name == extracted_table.name remainder_table_id = response_data['remainder_table'] remainder_table = Table.objects.get(id=remainder_table_id) assert Table.objects.filter(id=table.id).count() == 1 From 61ff5bb5edfc45963fdd757385859bfc3b7632f0 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 00:14:39 +0800 Subject: [PATCH 081/111] extract pytest run trigger to separate job --- .github/workflows/handle-required-checks.yml | 4 --- .github/workflows/run-pytest.yml | 31 ++++++++++---------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/.github/workflows/handle-required-checks.yml b/.github/workflows/handle-required-checks.yml index fae9a9075a..13b60efadc 100644 --- a/.github/workflows/handle-required-checks.yml +++ b/.github/workflows/handle-required-checks.yml @@ -4,10 +4,6 @@ name: handle-required-checks on: [pull_request, merge_group] jobs: - tests: - runs-on: ubuntu-latest - steps: - - run: 'echo "No tests required"' lint: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 99a4bac806..af08c9ae8c 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -7,13 +7,12 @@ name: Run Python tests on: [pull_request, merge_group] jobs: - python_tests: + python_filechanges: runs-on: ubuntu-latest - # Using this construct means we'll skip to "success". This avoids the - # unrecommended path filtering in this required job. - strategy: - matrix: - pg-version: [13, 14, 15] + # Here, we capture whether any files have changed to indicate we need to run + # python tests + outputs: + any_changed: ${{ steps.changed_files.outputs.any_changed }} steps: - uses: actions/checkout@v2 - name: Get changed files @@ -24,27 +23,29 @@ jobs: *.py mathesar/** db/** - + python_tests: + runs-on: ubuntu-latest + needs: python_filechanges + strategy: + matrix: + pg-version: [13, 14, 15] + steps: - name: Copy env file - if: steps.changed_files.outputs.any_changed == 'true' + if: needs.python_filechanges.outputs.any_changed == 'true' run: cp .env.example .env - # The code is checked out under uid 1001 - reset this to 1000 for the # container to run tests successfully - name: Fix permissions - if: steps.changed_files.outputs.any_changed == 'true' + if: needs.python_filechanges.outputs.any_changed == 'true' run: sudo chown -R 1000:1000 . - - name: Build the stack - if: steps.changed_files.outputs.any_changed == 'true' + if: needs.python_filechanges.outputs.any_changed == 'true' run: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d test-service env: PG_MAJOR: ${{ matrix.pg-version }} - - name: Run tests with pytest - if: steps.changed_files.outputs.any_changed == 'true' + if: needs.python_filechanges.outputs.any_changed == 'true' run: docker exec mathesar_service_test ./run_pytest.sh - tests: runs-on: ubuntu-latest needs: python_tests From 0071bbaa83e450c4d5118d5fbf99e81844e1e11b Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 00:18:05 +0800 Subject: [PATCH 082/111] Check that tests passing works --- mathesar/tests/api/test_table_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mathesar/tests/api/test_table_api.py b/mathesar/tests/api/test_table_api.py index 18df6ca1e0..9ff7aafddc 100644 --- a/mathesar/tests/api/test_table_api.py +++ b/mathesar/tests/api/test_table_api.py @@ -2083,6 +2083,7 @@ def test_create_table_using_duplicate_id_excel_data_file(client, duplicate_id_ex def test_create_table_using_null_id_excel_data_file(client, null_id_excel_data_file, schema): + # silly comment table_name = 'null_id' expt_name = get_expected_name(table_name, data_file=null_id_excel_data_file) first_row = (1, '1.0', 'John', '25') From 04b843f59f2412fb7710c1106fb92702b8f032ad Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 00:41:23 +0800 Subject: [PATCH 083/111] restore the checkout for testing --- .github/workflows/run-pytest.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index af08c9ae8c..bce88de1dc 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -30,6 +30,7 @@ jobs: matrix: pg-version: [13, 14, 15] steps: + - uses: actions/checkout@v2 - name: Copy env file if: needs.python_filechanges.outputs.any_changed == 'true' run: cp .env.example .env From f1c65b5a6a7f5ecdbc060ab0a51d45bab8c04ed5 Mon Sep 17 00:00:00 2001 From: pavish Date: Tue, 24 Oct 2023 22:17:36 +0530 Subject: [PATCH 084/111] Fix types --- .../linked-record/LinkedRecordCell.svelte | 6 ++--- .../data-types/components/typeDefinitions.ts | 23 +++++++++++++++++-- .../cell-fabric/data-types/typeDefinitions.ts | 13 +++++------ .../src/components/cell-fabric/types.ts | 14 ++++------- .../src/stores/table-data/processedColumns.ts | 11 +-------- 5 files changed, 35 insertions(+), 32 deletions(-) diff --git a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte index 78948cf0ea..4f115834f3 100644 --- a/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte +++ b/mathesar_ui/src/components/cell-fabric/data-types/components/linked-record/LinkedRecordCell.svelte @@ -42,10 +42,10 @@ } event?.stopPropagation(); const result = await recordSelector.acquireUserInput({ tableId }); - const LinkedFkCellValue = columnFabric.linkFk?.referent_columns[0]; + const linkedFkColumnId = columnFabric.linkFk?.referent_columns[0]; if (result) { - if (LinkedFkCellValue !== undefined && LinkedFkCellValue !== null) { - value = result.record[LinkedFkCellValue]; + if (linkedFkColumnId) { + value = result.record[linkedFkColumnId]; } else { value = result.recordId; } diff --git a/mathesar_ui/src/components/cell-fabric/data-types/components/typeDefinitions.ts b/mathesar_ui/src/components/cell-fabric/data-types/components/typeDefinitions.ts index b510849dcd..5e3269c103 100644 --- a/mathesar_ui/src/components/cell-fabric/data-types/components/typeDefinitions.ts +++ b/mathesar_ui/src/components/cell-fabric/data-types/components/typeDefinitions.ts @@ -2,10 +2,29 @@ import type { FormattedInputProps, NumberFormatterOptions, SelectProps, + ComponentAndProps, } from '@mathesar-component-library/types'; -import type { ProcessedColumn } from '@mathesar/stores/table-data/processedColumns'; import type { DBObjectEntry } from '@mathesar/AppTypes'; import type { DateTimeFormatter } from '@mathesar/utils/date-time/types'; +import type { Column } from '@mathesar/api/types/tables/columns'; +import type { FkConstraint } from '@mathesar/api/types/tables/constraints'; + +export type CellColumnLike = Pick< + Column, + 'type' | 'type_options' | 'display_options' +>; + +export interface CellColumnFabric { + id: string | number; + column: CellColumnLike; + /** + * Present when the column has one single-column FK constraint. In the + * unlikely (but theoretically possible) scenario that this column has more + * than one FK constraint, the first FK constraint is referenced. + */ + linkFk?: FkConstraint; + cellComponentAndProps: ComponentAndProps; +} export type CellValueFormatter = ( value: T | null | undefined, @@ -46,7 +65,7 @@ export interface LinkedRecordCellExternalProps { export interface LinkedRecordCellProps extends CellTypeProps, LinkedRecordCellExternalProps { - columnFabric: ProcessedColumn; + columnFabric: CellColumnFabric; recordSummary?: string; setRecordSummary?: (recordId: string, recordSummary: string) => void; } diff --git a/mathesar_ui/src/components/cell-fabric/data-types/typeDefinitions.ts b/mathesar_ui/src/components/cell-fabric/data-types/typeDefinitions.ts index b3b07b7b54..b066f67896 100644 --- a/mathesar_ui/src/components/cell-fabric/data-types/typeDefinitions.ts +++ b/mathesar_ui/src/components/cell-fabric/data-types/typeDefinitions.ts @@ -1,6 +1,10 @@ -import type { Column } from '@mathesar/api/types/tables/columns'; import type { ComponentAndProps } from '@mathesar-component-library/types'; -import type { CellValueFormatter } from './components/typeDefinitions'; +import type { + CellValueFormatter, + CellColumnLike as CellColumnLikeInner, +} from './components/typeDefinitions'; + +export type CellColumnLike = CellColumnLikeInner; // The types here are frontend types and are // different from db types. @@ -20,11 +24,6 @@ export type CompoundCellDataTypes = 'array'; export type CellDataType = SimpleCellDataTypes | CompoundCellDataTypes; -export type CellColumnLike = Pick< - Column, - 'type' | 'type_options' | 'display_options' ->; - export interface CellComponentFactory { initialInputValue?: unknown; get( diff --git a/mathesar_ui/src/components/cell-fabric/types.ts b/mathesar_ui/src/components/cell-fabric/types.ts index f824c31ed1..c1c3c7fb9b 100644 --- a/mathesar_ui/src/components/cell-fabric/types.ts +++ b/mathesar_ui/src/components/cell-fabric/types.ts @@ -1,10 +1,4 @@ -import type { ComponentAndProps } from '@mathesar-component-library/types'; -import type { CellColumnLike } from './data-types/typeDefinitions'; - -export interface CellColumnFabric { - id: string | number; - column: CellColumnLike; - cellComponentAndProps: ComponentAndProps; -} - -export type { CellValueFormatter } from './data-types/components/typeDefinitions'; +export type { + CellColumnFabric, + CellValueFormatter, +} from './data-types/components/typeDefinitions'; diff --git a/mathesar_ui/src/stores/table-data/processedColumns.ts b/mathesar_ui/src/stores/table-data/processedColumns.ts index 7fc3a907fb..a863bd58cb 100644 --- a/mathesar_ui/src/stores/table-data/processedColumns.ts +++ b/mathesar_ui/src/stores/table-data/processedColumns.ts @@ -1,10 +1,7 @@ import type { ComponentAndProps } from '@mathesar-component-library/types'; import type { TableEntry } from '@mathesar/api/types/tables'; import type { Column } from '@mathesar/api/types/tables/columns'; -import type { - Constraint, - FkConstraint, -} from '@mathesar/api/types/tables/constraints'; +import type { Constraint } from '@mathesar/api/types/tables/constraints'; import type { CellColumnFabric } from '@mathesar/components/cell-fabric/types'; import { getCellCap, @@ -39,12 +36,6 @@ export interface ProcessedColumn extends CellColumnFabric { exclusiveConstraints: Constraint[]; /** Constraints whose columns include this column and other columns too */ sharedConstraints: Constraint[]; - /** - * Present when this column has one single-column FK constraint. In the - * unlikely (but theoretically possible) scenario that this column has more - * than one FK constraint, the first FK constraint is used. - */ - linkFk: FkConstraint | undefined; abstractType: AbstractType; initialInputValue: unknown; inputComponentAndProps: ComponentAndProps; From 37ec26dd5a88d72d852c8bd56db293e934fc3e66 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 16:00:53 +0800 Subject: [PATCH 085/111] attempt to avoid stepwise if checks --- .github/workflows/run-pytest.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index bce88de1dc..6503a6c58d 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -26,26 +26,23 @@ jobs: python_tests: runs-on: ubuntu-latest needs: python_filechanges + if: needs.python_filechanges.outputs.any_changed == 'true' strategy: matrix: pg-version: [13, 14, 15] steps: - uses: actions/checkout@v2 - name: Copy env file - if: needs.python_filechanges.outputs.any_changed == 'true' run: cp .env.example .env # The code is checked out under uid 1001 - reset this to 1000 for the # container to run tests successfully - name: Fix permissions - if: needs.python_filechanges.outputs.any_changed == 'true' run: sudo chown -R 1000:1000 . - name: Build the stack - if: needs.python_filechanges.outputs.any_changed == 'true' run: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d test-service env: PG_MAJOR: ${{ matrix.pg-version }} - name: Run tests with pytest - if: needs.python_filechanges.outputs.any_changed == 'true' run: docker exec mathesar_service_test ./run_pytest.sh tests: runs-on: ubuntu-latest From d1ef2851ef056da0c895eb283e2942b4306fcabe Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 16:04:29 +0800 Subject: [PATCH 086/111] test behavior when no py changes --- mathesar/tests/api/test_table_api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mathesar/tests/api/test_table_api.py b/mathesar/tests/api/test_table_api.py index 9ff7aafddc..18df6ca1e0 100644 --- a/mathesar/tests/api/test_table_api.py +++ b/mathesar/tests/api/test_table_api.py @@ -2083,7 +2083,6 @@ def test_create_table_using_duplicate_id_excel_data_file(client, duplicate_id_ex def test_create_table_using_null_id_excel_data_file(client, null_id_excel_data_file, schema): - # silly comment table_name = 'null_id' expt_name = get_expected_name(table_name, data_file=null_id_excel_data_file) first_row = (1, '1.0', 'John', '25') From db420fd41fbd72f64c8bb44af2291fd885d3a0e2 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 16:09:04 +0800 Subject: [PATCH 087/111] See whether matrix strategy still counts as a pass --- .github/workflows/run-pytest.yml | 14 +++++++------- mathesar/tests/api/test_table_api.py | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 6503a6c58d..7af81c665b 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -23,7 +23,7 @@ jobs: *.py mathesar/** db/** - python_tests: + tests: runs-on: ubuntu-latest needs: python_filechanges if: needs.python_filechanges.outputs.any_changed == 'true' @@ -44,9 +44,9 @@ jobs: PG_MAJOR: ${{ matrix.pg-version }} - name: Run tests with pytest run: docker exec mathesar_service_test ./run_pytest.sh - tests: - runs-on: ubuntu-latest - needs: python_tests - steps: - - name: Report success - run: echo "Python tests succeeded or skipped!" +# tests: +# runs-on: ubuntu-latest +# needs: python_tests +# steps: +# - name: Report success +# run: echo "Python tests succeeded or skipped!" diff --git a/mathesar/tests/api/test_table_api.py b/mathesar/tests/api/test_table_api.py index 18df6ca1e0..9ff7aafddc 100644 --- a/mathesar/tests/api/test_table_api.py +++ b/mathesar/tests/api/test_table_api.py @@ -2083,6 +2083,7 @@ def test_create_table_using_duplicate_id_excel_data_file(client, duplicate_id_ex def test_create_table_using_null_id_excel_data_file(client, null_id_excel_data_file, schema): + # silly comment table_name = 'null_id' expt_name = get_expected_name(table_name, data_file=null_id_excel_data_file) first_row = (1, '1.0', 'John', '25') From e7615b7cb8bba4569471be64a46379e4cbd3d640 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 16:36:15 +0800 Subject: [PATCH 088/111] revert experiment, update action version --- .github/workflows/run-pytest.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 7af81c665b..3f10b38fcd 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -14,7 +14,7 @@ jobs: outputs: any_changed: ${{ steps.changed_files.outputs.any_changed }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Get changed files id: changed_files uses: tj-actions/changed-files@v39 @@ -23,7 +23,7 @@ jobs: *.py mathesar/** db/** - tests: + python_tests: runs-on: ubuntu-latest needs: python_filechanges if: needs.python_filechanges.outputs.any_changed == 'true' @@ -44,9 +44,9 @@ jobs: PG_MAJOR: ${{ matrix.pg-version }} - name: Run tests with pytest run: docker exec mathesar_service_test ./run_pytest.sh -# tests: -# runs-on: ubuntu-latest -# needs: python_tests -# steps: -# - name: Report success -# run: echo "Python tests succeeded or skipped!" + tests: + runs-on: ubuntu-latest + needs: python_tests + steps: + - name: Report success + run: echo "Python tests succeeded or skipped!" From 0e3de338a33cbd7a3003a75b8e75fabc5ec276d4 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 17:01:30 +0800 Subject: [PATCH 089/111] use new setup for python linting --- .github/workflows/handle-required-checks.yml | 7 ---- .github/workflows/run-flake8.yml | 27 ------------- .github/workflows/run-pytest.yml | 40 ++++++++++++++++++-- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/.github/workflows/handle-required-checks.yml b/.github/workflows/handle-required-checks.yml index 13b60efadc..d5962e1a77 100644 --- a/.github/workflows/handle-required-checks.yml +++ b/.github/workflows/handle-required-checks.yml @@ -1,10 +1,3 @@ ## "lint" and "tests" are required checks, but they run conditionally. ## This handles the cases where they don't run because no Python or JS file has been changed. ## See https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks -name: handle-required-checks -on: [pull_request, merge_group] -jobs: - lint: - runs-on: ubuntu-latest - steps: - - run: 'echo "No lint required"' diff --git a/.github/workflows/run-flake8.yml b/.github/workflows/run-flake8.yml index 98eba2706c..e69de29bb2 100644 --- a/.github/workflows/run-flake8.yml +++ b/.github/workflows/run-flake8.yml @@ -1,27 +0,0 @@ -name: Lint Python code - -on: - push: - paths: - - '**.py' - pull_request: - paths: - - '**.py' - -jobs: - lint: - runs-on: ubuntu-latest - # We only want to run on external PRs, since internal PRs are covered by "push" - # This prevents this from running twice on internal PRs - if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - - name: Run flake8 - uses: julianwachholz/flake8-action@main - with: - checkName: "flake8" - path: "." - plugins: flake8-no-types - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 3f10b38fcd..108035a1b3 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -7,7 +7,7 @@ name: Run Python tests on: [pull_request, merge_group] jobs: - python_filechanges: + pytest_required_check: runs-on: ubuntu-latest # Here, we capture whether any files have changed to indicate we need to run # python tests @@ -23,10 +23,26 @@ jobs: *.py mathesar/** db/** + + flake8_required_check: + runs-on: ubuntu-latest + # Here, we capture whether any files have changed to indicate we need to run + # python tests + outputs: + any_changed: ${{ steps.changed_files.outputs.any_changed }} + steps: + - uses: actions/checkout@v4 + - name: Get changed files + id: changed_files + uses: tj-actions/changed-files@v39 + with: + files: '**.py' + python_tests: + name: Run Python tests runs-on: ubuntu-latest - needs: python_filechanges - if: needs.python_filechanges.outputs.any_changed == 'true' + needs: pytest_required_check + if: needs.pytest_required_check.outputs.any_changed == 'true' strategy: matrix: pg-version: [13, 14, 15] @@ -44,6 +60,24 @@ jobs: PG_MAJOR: ${{ matrix.pg-version }} - name: Run tests with pytest run: docker exec mathesar_service_test ./run_pytest.sh + + lint: + name: Lint Python code + runs-on: ubuntu-latest + needs: flake8_required_check + if: needs.flake8_required_check.outputs.any_changed == 'true' + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + - name: Run flake8 + uses: julianwachholz/flake8-action@main + with: + checkName: "flake8" + path: "." + plugins: flake8-no-types + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + tests: runs-on: ubuntu-latest needs: python_tests From 371a8c4060ae473d037d9aceb591bca7a73e2362 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 17:10:33 +0800 Subject: [PATCH 090/111] check if there's a problem due to custom name --- .github/workflows/run-pytest.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 108035a1b3..e94d460335 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -62,7 +62,6 @@ jobs: run: docker exec mathesar_service_test ./run_pytest.sh lint: - name: Lint Python code runs-on: ubuntu-latest needs: flake8_required_check if: needs.flake8_required_check.outputs.any_changed == 'true' From 937f8f92ace409f2fcc0cb4429cf49b8807921e3 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 17:22:55 +0800 Subject: [PATCH 091/111] double-check that giving the job a name breaks the status check --- .github/workflows/run-pytest.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index e94d460335..6ce9974335 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -20,9 +20,10 @@ jobs: uses: tj-actions/changed-files@v39 with: files: | - *.py - mathesar/** - db/** + *.abcde +# *.py +# mathesar/** +# db/** flake8_required_check: runs-on: ubuntu-latest @@ -47,7 +48,7 @@ jobs: matrix: pg-version: [13, 14, 15] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Copy env file run: cp .env.example .env # The code is checked out under uid 1001 - reset this to 1000 for the @@ -62,6 +63,7 @@ jobs: run: docker exec mathesar_service_test ./run_pytest.sh lint: + name: Run Python linter runs-on: ubuntu-latest needs: flake8_required_check if: needs.flake8_required_check.outputs.any_changed == 'true' From 981b4027274645187e3fba92f71d6ed8806cf97e Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 17:40:49 +0800 Subject: [PATCH 092/111] clean up, remove cruft, rename file --- .github/workflows/handle-required-checks.yml | 3 --- .github/workflows/run-flake8.yml | 0 .../workflows/{run-pytest.yml => run-lint-tests-py.yml} | 9 ++++++++- 3 files changed, 8 insertions(+), 4 deletions(-) delete mode 100644 .github/workflows/handle-required-checks.yml delete mode 100644 .github/workflows/run-flake8.yml rename .github/workflows/{run-pytest.yml => run-lint-tests-py.yml} (94%) diff --git a/.github/workflows/handle-required-checks.yml b/.github/workflows/handle-required-checks.yml deleted file mode 100644 index d5962e1a77..0000000000 --- a/.github/workflows/handle-required-checks.yml +++ /dev/null @@ -1,3 +0,0 @@ -## "lint" and "tests" are required checks, but they run conditionally. -## This handles the cases where they don't run because no Python or JS file has been changed. -## See https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks diff --git a/.github/workflows/run-flake8.yml b/.github/workflows/run-flake8.yml deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-lint-tests-py.yml similarity index 94% rename from .github/workflows/run-pytest.yml rename to .github/workflows/run-lint-tests-py.yml index 6ce9974335..f0661f51e4 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-lint-tests-py.yml @@ -62,7 +62,7 @@ jobs: - name: Run tests with pytest run: docker exec mathesar_service_test ./run_pytest.sh - lint: + python_lint: name: Run Python linter runs-on: ubuntu-latest needs: flake8_required_check @@ -85,3 +85,10 @@ jobs: steps: - name: Report success run: echo "Python tests succeeded or skipped!" + + lint: + runs-on: ubuntu-latest + needs: python_lint + steps: + - name: Report success + run: echo "Python linter succeeded or skipped!" From 83aee3daa2f047ad87b9fd2381a4e26bd3d96ea7 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 17:54:56 +0800 Subject: [PATCH 093/111] add SQL tests to backend test yml --- .github/workflows/run-lint-tests-py.yml | 48 ++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/.github/workflows/run-lint-tests-py.yml b/.github/workflows/run-lint-tests-py.yml index f0661f51e4..40ba69269e 100644 --- a/.github/workflows/run-lint-tests-py.yml +++ b/.github/workflows/run-lint-tests-py.yml @@ -4,7 +4,7 @@ # that runs status checks and reports them whenever a PR is added to the merge # queue. -name: Run Python tests +name: Backend tests and linting on: [pull_request, merge_group] jobs: pytest_required_check: @@ -20,10 +20,9 @@ jobs: uses: tj-actions/changed-files@v39 with: files: | - *.abcde -# *.py -# mathesar/** -# db/** + *.py + mathesar/** + db/** flake8_required_check: runs-on: ubuntu-latest @@ -39,6 +38,20 @@ jobs: with: files: '**.py' + sql_tests_required_check: + runs-on: ubuntu-latest + # Here, we capture whether any files have changed to indicate we need to run + # python tests + outputs: + any_changed: ${{ steps.changed_files.outputs.any_changed }} + steps: + - uses: actions/checkout@v4 + - name: Get changed files + id: changed_files + uses: tj-actions/changed-files@v39 + with: + files: '**.sql' + python_tests: name: Run Python tests runs-on: ubuntu-latest @@ -58,10 +71,29 @@ jobs: - name: Build the stack run: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d test-service env: - PG_MAJOR: ${{ matrix.pg-version }} + PG_VERSION: ${{ matrix.pg-version }} - name: Run tests with pytest run: docker exec mathesar_service_test ./run_pytest.sh + sql_tests: + runs-on: ubuntu-latest + if: needs.sql_tests_required_check.outputs.any_changed == 'true' + strategy: + matrix: + pg-version: [13, 14, 15] + steps: + - uses: actions/checkout@v4 + - name: Copy env file + run: cp .env.example .env + - name: Fix permissions + run: sudo chown -R 1000:1000 . + - name: Build the test DB + run: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d dev-db + env: + PG_VERSION: ${{ matrix.pg-version }} + - name: Run tests with pg_prove + run: docker exec mathesar_dev_db /bin/bash /sql/run_tests.sh + python_lint: name: Run Python linter runs-on: ubuntu-latest @@ -81,10 +113,10 @@ jobs: tests: runs-on: ubuntu-latest - needs: python_tests + needs: python_tests, sql_tests steps: - name: Report success - run: echo "Python tests succeeded or skipped!" + run: echo "Backend tests succeeded or skipped!" lint: runs-on: ubuntu-latest From 0a75055e95e056a20a6e9f7eaaa88742b58daed5 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 18:00:56 +0800 Subject: [PATCH 094/111] fix syntax error in workflow file --- .github/workflows/run-lint-tests-py.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-lint-tests-py.yml b/.github/workflows/run-lint-tests-py.yml index 40ba69269e..6e7673261e 100644 --- a/.github/workflows/run-lint-tests-py.yml +++ b/.github/workflows/run-lint-tests-py.yml @@ -27,7 +27,7 @@ jobs: flake8_required_check: runs-on: ubuntu-latest # Here, we capture whether any files have changed to indicate we need to run - # python tests + # python linter outputs: any_changed: ${{ steps.changed_files.outputs.any_changed }} steps: @@ -41,7 +41,7 @@ jobs: sql_tests_required_check: runs-on: ubuntu-latest # Here, we capture whether any files have changed to indicate we need to run - # python tests + # SQL tests outputs: any_changed: ${{ steps.changed_files.outputs.any_changed }} steps: @@ -76,6 +76,7 @@ jobs: run: docker exec mathesar_service_test ./run_pytest.sh sql_tests: + name: Run SQL tests runs-on: ubuntu-latest if: needs.sql_tests_required_check.outputs.any_changed == 'true' strategy: @@ -113,7 +114,7 @@ jobs: tests: runs-on: ubuntu-latest - needs: python_tests, sql_tests + needs: [python_tests, sql_tests] steps: - name: Report success run: echo "Backend tests succeeded or skipped!" From fbd7711683c0766619948b601ad8b4eab1edfc37 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 18:06:12 +0800 Subject: [PATCH 095/111] Test pipeline fails when SQL tests fail --- .github/workflows/run-sql-tests.yml | 37 ----------------------------- db/sql/test_0_msar.sql | 2 +- 2 files changed, 1 insertion(+), 38 deletions(-) delete mode 100644 .github/workflows/run-sql-tests.yml diff --git a/.github/workflows/run-sql-tests.yml b/.github/workflows/run-sql-tests.yml deleted file mode 100644 index d5761bc3ab..0000000000 --- a/.github/workflows/run-sql-tests.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Run SQL tests -on: - push: - paths: - - '**.sql' - pull_request: - paths: - - '**.sql' - - -jobs: - tests: - runs-on: ubuntu-latest - # We only want to run on external PRs, since internal PRs are covered by "push" - # This prevents this from running twice on internal PRs - if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository - strategy: - matrix: - pg-version: [13, 14, 15] - steps: - - uses: actions/checkout@v2 - - - name: Copy env file - run: cp .env.example .env - - # The code is checked out under uid 1001 - reset this to 1000 for the - # container to run tests successfully - - name: Fix permissions - run: sudo chown -R 1000:1000 . - - - name: Build the test DB - run: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d dev-db - env: - PG_VERSION: ${{ matrix.pg-version }} - - - name: Run tests with pg_prove - run: docker exec mathesar_dev_db /bin/bash /sql/run_tests.sh diff --git a/db/sql/test_0_msar.sql b/db/sql/test_0_msar.sql index 659070202b..ce7fddb121 100644 --- a/db/sql/test_0_msar.sql +++ b/db/sql/test_0_msar.sql @@ -463,7 +463,7 @@ BEGIN PERFORM msar.copy_column( 'copy_coltest'::regclass::oid, 2::smallint, 'col1 supercopy', true, true ); - RETURN NEXT col_type_is('copy_coltest', 'col1 supercopy', 'character varying'); + RETURN NEXT col_type_is('copy_coltest', 'col1 supercopy', 'character vrying'); RETURN NEXT col_is_null('copy_coltest', 'col1 supercopy'); RETURN NEXT col_is_unique('copy_coltest', ARRAY['col1', 'col2']); RETURN NEXT col_is_unique('copy_coltest', ARRAY['col1 supercopy', 'col2']); From ee2748155477396ea56a4b834a11eecadf193c5f Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 18:14:00 +0800 Subject: [PATCH 096/111] set python tests to skip, fix SQL job bug --- .github/workflows/run-lint-tests-py.yml | 1 + mathesar/tests/api/test_table_api.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-lint-tests-py.yml b/.github/workflows/run-lint-tests-py.yml index 6e7673261e..a54c51ff54 100644 --- a/.github/workflows/run-lint-tests-py.yml +++ b/.github/workflows/run-lint-tests-py.yml @@ -78,6 +78,7 @@ jobs: sql_tests: name: Run SQL tests runs-on: ubuntu-latest + needs: sql_tests_required_check if: needs.sql_tests_required_check.outputs.any_changed == 'true' strategy: matrix: diff --git a/mathesar/tests/api/test_table_api.py b/mathesar/tests/api/test_table_api.py index 9ff7aafddc..18df6ca1e0 100644 --- a/mathesar/tests/api/test_table_api.py +++ b/mathesar/tests/api/test_table_api.py @@ -2083,7 +2083,6 @@ def test_create_table_using_duplicate_id_excel_data_file(client, duplicate_id_ex def test_create_table_using_null_id_excel_data_file(client, null_id_excel_data_file, schema): - # silly comment table_name = 'null_id' expt_name = get_expected_name(table_name, data_file=null_id_excel_data_file) first_row = (1, '1.0', 'John', '25') From 16c3c3256c5aeb15c6d59417777e1f30c7ccda4f Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 21:37:10 +0800 Subject: [PATCH 097/111] check behavior when all tests are skipped --- db/sql/test_0_msar.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/sql/test_0_msar.sql b/db/sql/test_0_msar.sql index ce7fddb121..659070202b 100644 --- a/db/sql/test_0_msar.sql +++ b/db/sql/test_0_msar.sql @@ -463,7 +463,7 @@ BEGIN PERFORM msar.copy_column( 'copy_coltest'::regclass::oid, 2::smallint, 'col1 supercopy', true, true ); - RETURN NEXT col_type_is('copy_coltest', 'col1 supercopy', 'character vrying'); + RETURN NEXT col_type_is('copy_coltest', 'col1 supercopy', 'character varying'); RETURN NEXT col_is_null('copy_coltest', 'col1 supercopy'); RETURN NEXT col_is_unique('copy_coltest', ARRAY['col1', 'col2']); RETURN NEXT col_is_unique('copy_coltest', ARRAY['col1 supercopy', 'col2']); From cfcaf2f64c45fd6e6c333d2321317309d8a1c425 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 21:48:43 +0800 Subject: [PATCH 098/111] Move vulture job into main backend file also add .py change for testing --- ...nt-tests-py.yml => backend-validation.yml} | 16 +++++++++++-- .github/workflows/run-vulture.yml | 23 ------------------- mathesar/tests/api/test_table_api.py | 1 + 3 files changed, 15 insertions(+), 25 deletions(-) rename .github/workflows/{run-lint-tests-py.yml => backend-validation.yml} (90%) delete mode 100644 .github/workflows/run-vulture.yml diff --git a/.github/workflows/run-lint-tests-py.yml b/.github/workflows/backend-validation.yml similarity index 90% rename from .github/workflows/run-lint-tests-py.yml rename to .github/workflows/backend-validation.yml index a54c51ff54..2a4fb35cb7 100644 --- a/.github/workflows/run-lint-tests-py.yml +++ b/.github/workflows/backend-validation.yml @@ -24,7 +24,7 @@ jobs: mathesar/** db/** - flake8_required_check: + python_lint_required_check: runs-on: ubuntu-latest # Here, we capture whether any files have changed to indicate we need to run # python linter @@ -52,6 +52,18 @@ jobs: with: files: '**.sql' + vulture: + runs-on: ubuntu-latest + name: Find unused code + if: needs.python_lint_required_check.outputs.any_changed == 'true' + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + - name: Install Vulture + run: pip3 install vulture + - name: Run Vulture + run: vulture . + python_tests: name: Run Python tests runs-on: ubuntu-latest @@ -100,7 +112,7 @@ jobs: name: Run Python linter runs-on: ubuntu-latest needs: flake8_required_check - if: needs.flake8_required_check.outputs.any_changed == 'true' + if: needs.python_lint_required_check.outputs.any_changed == 'true' steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v4 diff --git a/.github/workflows/run-vulture.yml b/.github/workflows/run-vulture.yml deleted file mode 100644 index b4533aedb0..0000000000 --- a/.github/workflows/run-vulture.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Find unused code - -on: - push: - paths: - - '**.py' - pull_request: - paths: - - '**.py' - -jobs: - build: - runs-on: ubuntu-latest - # We only want to run on external PRs, since internal PRs are covered by "push" - # This prevents this from running twice on internal PRs - if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - - name: Install Vulture - run: pip3 install vulture - - name: Run Vulture - run: vulture . diff --git a/mathesar/tests/api/test_table_api.py b/mathesar/tests/api/test_table_api.py index 18df6ca1e0..9ff7aafddc 100644 --- a/mathesar/tests/api/test_table_api.py +++ b/mathesar/tests/api/test_table_api.py @@ -2083,6 +2083,7 @@ def test_create_table_using_duplicate_id_excel_data_file(client, duplicate_id_ex def test_create_table_using_null_id_excel_data_file(client, null_id_excel_data_file, schema): + # silly comment table_name = 'null_id' expt_name = get_expected_name(table_name, data_file=null_id_excel_data_file) first_row = (1, '1.0', 'John', '25') From b5806d432519d559dca18d993ac5c2e8b9da2b5e Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 25 Oct 2023 22:32:54 +0800 Subject: [PATCH 099/111] fix misnamed dependency, reorganize --- .github/workflows/backend-validation.yml | 27 ++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/workflows/backend-validation.yml b/.github/workflows/backend-validation.yml index 2a4fb35cb7..bb9b8174ae 100644 --- a/.github/workflows/backend-validation.yml +++ b/.github/workflows/backend-validation.yml @@ -52,18 +52,6 @@ jobs: with: files: '**.sql' - vulture: - runs-on: ubuntu-latest - name: Find unused code - if: needs.python_lint_required_check.outputs.any_changed == 'true' - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 - - name: Install Vulture - run: pip3 install vulture - - name: Run Vulture - run: vulture . - python_tests: name: Run Python tests runs-on: ubuntu-latest @@ -111,7 +99,7 @@ jobs: python_lint: name: Run Python linter runs-on: ubuntu-latest - needs: flake8_required_check + needs: python_lint_required_check if: needs.python_lint_required_check.outputs.any_changed == 'true' steps: - uses: actions/checkout@v4 @@ -125,6 +113,19 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + vulture: + name: Find unused code + runs-on: ubuntu-latest + needs: python_lint_required_check + if: needs.python_lint_required_check.outputs.any_changed == 'true' + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + - name: Install Vulture + run: pip3 install vulture + - name: Run Vulture + run: vulture . + tests: runs-on: ubuntu-latest needs: [python_tests, sql_tests] From 825a36f7f15be5650c550b9bd395a9441421b953 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Wed, 25 Oct 2023 13:35:18 -0400 Subject: [PATCH 100/111] Resolve conflicting migrations --- mathesar/migrations/0009_merge_20231025_1733.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 mathesar/migrations/0009_merge_20231025_1733.py diff --git a/mathesar/migrations/0009_merge_20231025_1733.py b/mathesar/migrations/0009_merge_20231025_1733.py new file mode 100644 index 0000000000..83e79e46ad --- /dev/null +++ b/mathesar/migrations/0009_merge_20231025_1733.py @@ -0,0 +1,14 @@ +# Generated by Django 3.1.14 on 2023-10-25 17:33 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mathesar', '0008_auto_20230921_1834'), + ('mathesar', '0005_user_display_language'), + ] + + operations = [ + ] From 069bdd62732f3126c7a1f84c4791e2995e879a34 Mon Sep 17 00:00:00 2001 From: Evyn Date: Thu, 26 Oct 2023 08:24:39 +1000 Subject: [PATCH 101/111] Display more accurate infoAlertText on foreign key columns Update the displayed text to be more accurate, not mentioning primary keys specifically. --- .../systems/table-view/table-inspector/column/ColumnType.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mathesar_ui/src/systems/table-view/table-inspector/column/ColumnType.svelte b/mathesar_ui/src/systems/table-view/table-inspector/column/ColumnType.svelte index 3b29cb72e8..562d354b60 100644 --- a/mathesar_ui/src/systems/table-view/table-inspector/column/ColumnType.svelte +++ b/mathesar_ui/src/systems/table-view/table-inspector/column/ColumnType.svelte @@ -35,7 +35,7 @@ return 'The data type of the primary key column is restricted and cannot be changed.'; } if (column.linkFk) { - return 'The data type of the foreign key column is restricted to the data type of the primary key column and cannot be changed.'; + return 'The data type of this column must match the referenced column and cannot be changed.'; } return ''; })(); From 6c3439bf1e18fdde14da92983586938a1814dac5 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Thu, 26 Oct 2023 15:02:21 +0800 Subject: [PATCH 102/111] Clean up workflow file, add documenting comments --- .github/workflows/backend-validation.yml | 61 ++++++++++++++++-------- mathesar/tests/api/test_table_api.py | 1 - 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/.github/workflows/backend-validation.yml b/.github/workflows/backend-validation.yml index bb9b8174ae..97f1823e69 100644 --- a/.github/workflows/backend-validation.yml +++ b/.github/workflows/backend-validation.yml @@ -7,12 +7,22 @@ name: Backend tests and linting on: [pull_request, merge_group] jobs: - pytest_required_check: + +################################################################################ +## FILE CHANGE CHECKERS ## +## ## +## These jobs check which files have changed so that we can call appropriate ## +## testing, auditing, and linting jobs. Jobs in this section should check for ## +## file changes that would indicate whether we need to run some particular ## +## test suite, then they should output 'true' if such file changes are found. ## +## ## +################################################################################ + + python_tests_required: + name: Check for file changes requiring python tests runs-on: ubuntu-latest - # Here, we capture whether any files have changed to indicate we need to run - # python tests outputs: - any_changed: ${{ steps.changed_files.outputs.any_changed }} + tests_should_run: ${{ steps.changed_files.outputs.any_changed }} steps: - uses: actions/checkout@v4 - name: Get changed files @@ -24,12 +34,11 @@ jobs: mathesar/** db/** - python_lint_required_check: + python_lint_required: + name: Check for file changes requiring python linter runs-on: ubuntu-latest - # Here, we capture whether any files have changed to indicate we need to run - # python linter outputs: - any_changed: ${{ steps.changed_files.outputs.any_changed }} + lint_should_run: ${{ steps.changed_files.outputs.any_changed }} steps: - uses: actions/checkout@v4 - name: Get changed files @@ -38,12 +47,11 @@ jobs: with: files: '**.py' - sql_tests_required_check: + sql_tests_required: + name: Check for file changes requiring SQL tests runs-on: ubuntu-latest - # Here, we capture whether any files have changed to indicate we need to run - # SQL tests outputs: - any_changed: ${{ steps.changed_files.outputs.any_changed }} + tests_should_run: ${{ steps.changed_files.outputs.any_changed }} steps: - uses: actions/checkout@v4 - name: Get changed files @@ -52,11 +60,24 @@ jobs: with: files: '**.sql' +################################################################################ +## TEST/LINT RUNNERS ## +## ## +## These jobs run tests and linters. Each job in this section should be ## +## dependent on one of the FILE CHANGE CHECKERS above, and should only run if ## +## appropriate files have changed. You can see this by using a `needs:` block ## +## to make the job dependent on the relevant file checker, and an `if:` block ## +## to ensure that the file checker returned 'true' before running the actual ## +## job. Job IDs in this section must be namespaced (so `python_tests` ## +## instead of just `tests`). ## +## ## +################################################################################ + python_tests: name: Run Python tests runs-on: ubuntu-latest - needs: pytest_required_check - if: needs.pytest_required_check.outputs.any_changed == 'true' + needs: python_tests_required + if: needs.python_tests_required.outputs.tests_should_run == 'true' strategy: matrix: pg-version: [13, 14, 15] @@ -79,7 +100,7 @@ jobs: name: Run SQL tests runs-on: ubuntu-latest needs: sql_tests_required_check - if: needs.sql_tests_required_check.outputs.any_changed == 'true' + if: needs.sql_tests_required.outputs.tests_should_run == 'true' strategy: matrix: pg-version: [13, 14, 15] @@ -87,6 +108,8 @@ jobs: - uses: actions/checkout@v4 - name: Copy env file run: cp .env.example .env + # The code is checked out under uid 1001 - reset this to 1000 for the + # container to run tests successfully - name: Fix permissions run: sudo chown -R 1000:1000 . - name: Build the test DB @@ -99,8 +122,8 @@ jobs: python_lint: name: Run Python linter runs-on: ubuntu-latest - needs: python_lint_required_check - if: needs.python_lint_required_check.outputs.any_changed == 'true' + needs: python_lint_required + if: needs.python_lint_required.outputs.lint_should_run == 'true' steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v4 @@ -116,8 +139,8 @@ jobs: vulture: name: Find unused code runs-on: ubuntu-latest - needs: python_lint_required_check - if: needs.python_lint_required_check.outputs.any_changed == 'true' + needs: python_lint_required + if: needs.python_lint_required.outputs.lint_should_run == 'true' steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v4 diff --git a/mathesar/tests/api/test_table_api.py b/mathesar/tests/api/test_table_api.py index 9ff7aafddc..18df6ca1e0 100644 --- a/mathesar/tests/api/test_table_api.py +++ b/mathesar/tests/api/test_table_api.py @@ -2083,7 +2083,6 @@ def test_create_table_using_duplicate_id_excel_data_file(client, duplicate_id_ex def test_create_table_using_null_id_excel_data_file(client, null_id_excel_data_file, schema): - # silly comment table_name = 'null_id' expt_name = get_expected_name(table_name, data_file=null_id_excel_data_file) first_row = (1, '1.0', 'John', '25') From 7f4dffa89e556e14658cb898c0feec1065b11169 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Thu, 26 Oct 2023 15:05:07 +0800 Subject: [PATCH 103/111] fix workflow syntax error --- .github/workflows/backend-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backend-validation.yml b/.github/workflows/backend-validation.yml index 97f1823e69..0062615a94 100644 --- a/.github/workflows/backend-validation.yml +++ b/.github/workflows/backend-validation.yml @@ -99,7 +99,7 @@ jobs: sql_tests: name: Run SQL tests runs-on: ubuntu-latest - needs: sql_tests_required_check + needs: sql_tests_required if: needs.sql_tests_required.outputs.tests_should_run == 'true' strategy: matrix: From 414654a152a5ea1d660cadd002579cfb7ddfd551 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Thu, 26 Oct 2023 15:37:30 +0800 Subject: [PATCH 104/111] Move front end checks to main validation file --- .github/workflows/backend-validation.yml | 164 --------- .github/workflows/run-lint-audit-tests-ui.yml | 129 ------- .github/workflows/test-and-lint-code.yml | 332 ++++++++++++++++++ 3 files changed, 332 insertions(+), 293 deletions(-) delete mode 100644 .github/workflows/backend-validation.yml delete mode 100644 .github/workflows/run-lint-audit-tests-ui.yml create mode 100644 .github/workflows/test-and-lint-code.yml diff --git a/.github/workflows/backend-validation.yml b/.github/workflows/backend-validation.yml deleted file mode 100644 index 0062615a94..0000000000 --- a/.github/workflows/backend-validation.yml +++ /dev/null @@ -1,164 +0,0 @@ -# Since we're using both the "require pull request" and "require merge queue" -# requirements for develop and master branches, there's no reason to run tests -# on every push. Instead, we're using the recommended "merge_group" formulation -# that runs status checks and reports them whenever a PR is added to the merge -# queue. - -name: Backend tests and linting -on: [pull_request, merge_group] -jobs: - -################################################################################ -## FILE CHANGE CHECKERS ## -## ## -## These jobs check which files have changed so that we can call appropriate ## -## testing, auditing, and linting jobs. Jobs in this section should check for ## -## file changes that would indicate whether we need to run some particular ## -## test suite, then they should output 'true' if such file changes are found. ## -## ## -################################################################################ - - python_tests_required: - name: Check for file changes requiring python tests - runs-on: ubuntu-latest - outputs: - tests_should_run: ${{ steps.changed_files.outputs.any_changed }} - steps: - - uses: actions/checkout@v4 - - name: Get changed files - id: changed_files - uses: tj-actions/changed-files@v39 - with: - files: | - *.py - mathesar/** - db/** - - python_lint_required: - name: Check for file changes requiring python linter - runs-on: ubuntu-latest - outputs: - lint_should_run: ${{ steps.changed_files.outputs.any_changed }} - steps: - - uses: actions/checkout@v4 - - name: Get changed files - id: changed_files - uses: tj-actions/changed-files@v39 - with: - files: '**.py' - - sql_tests_required: - name: Check for file changes requiring SQL tests - runs-on: ubuntu-latest - outputs: - tests_should_run: ${{ steps.changed_files.outputs.any_changed }} - steps: - - uses: actions/checkout@v4 - - name: Get changed files - id: changed_files - uses: tj-actions/changed-files@v39 - with: - files: '**.sql' - -################################################################################ -## TEST/LINT RUNNERS ## -## ## -## These jobs run tests and linters. Each job in this section should be ## -## dependent on one of the FILE CHANGE CHECKERS above, and should only run if ## -## appropriate files have changed. You can see this by using a `needs:` block ## -## to make the job dependent on the relevant file checker, and an `if:` block ## -## to ensure that the file checker returned 'true' before running the actual ## -## job. Job IDs in this section must be namespaced (so `python_tests` ## -## instead of just `tests`). ## -## ## -################################################################################ - - python_tests: - name: Run Python tests - runs-on: ubuntu-latest - needs: python_tests_required - if: needs.python_tests_required.outputs.tests_should_run == 'true' - strategy: - matrix: - pg-version: [13, 14, 15] - steps: - - uses: actions/checkout@v4 - - name: Copy env file - run: cp .env.example .env - # The code is checked out under uid 1001 - reset this to 1000 for the - # container to run tests successfully - - name: Fix permissions - run: sudo chown -R 1000:1000 . - - name: Build the stack - run: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d test-service - env: - PG_VERSION: ${{ matrix.pg-version }} - - name: Run tests with pytest - run: docker exec mathesar_service_test ./run_pytest.sh - - sql_tests: - name: Run SQL tests - runs-on: ubuntu-latest - needs: sql_tests_required - if: needs.sql_tests_required.outputs.tests_should_run == 'true' - strategy: - matrix: - pg-version: [13, 14, 15] - steps: - - uses: actions/checkout@v4 - - name: Copy env file - run: cp .env.example .env - # The code is checked out under uid 1001 - reset this to 1000 for the - # container to run tests successfully - - name: Fix permissions - run: sudo chown -R 1000:1000 . - - name: Build the test DB - run: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d dev-db - env: - PG_VERSION: ${{ matrix.pg-version }} - - name: Run tests with pg_prove - run: docker exec mathesar_dev_db /bin/bash /sql/run_tests.sh - - python_lint: - name: Run Python linter - runs-on: ubuntu-latest - needs: python_lint_required - if: needs.python_lint_required.outputs.lint_should_run == 'true' - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 - - name: Run flake8 - uses: julianwachholz/flake8-action@main - with: - checkName: "flake8" - path: "." - plugins: flake8-no-types - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - vulture: - name: Find unused code - runs-on: ubuntu-latest - needs: python_lint_required - if: needs.python_lint_required.outputs.lint_should_run == 'true' - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 - - name: Install Vulture - run: pip3 install vulture - - name: Run Vulture - run: vulture . - - tests: - runs-on: ubuntu-latest - needs: [python_tests, sql_tests] - steps: - - name: Report success - run: echo "Backend tests succeeded or skipped!" - - lint: - runs-on: ubuntu-latest - needs: python_lint - steps: - - name: Report success - run: echo "Python linter succeeded or skipped!" diff --git a/.github/workflows/run-lint-audit-tests-ui.yml b/.github/workflows/run-lint-audit-tests-ui.yml deleted file mode 100644 index 3e9aa41f06..0000000000 --- a/.github/workflows/run-lint-audit-tests-ui.yml +++ /dev/null @@ -1,129 +0,0 @@ -name: UI - Lint, Audit and Tests - -on: - push: - paths: - - 'mathesar_ui/**' - pull_request: - paths: - - 'mathesar_ui/**' - -jobs: - format: - runs-on: ubuntu-latest - defaults: - run: - working-directory: ./mathesar_ui - timeout-minutes: 5 - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: 18 - - id: npm-cache-dir - run: echo "::set-output name=dir::$(npm config get cache)" - - uses: actions/cache@v2 - id: npm-cache - with: - path: ${{ steps.npm-cache-dir.outputs.dir }} - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: ${{ runner.os }}-node- - - run: npm ci --no-audit --prefer-offline - - run: npm run check-format - - lint: - runs-on: ubuntu-latest - defaults: - run: - working-directory: ./mathesar_ui - timeout-minutes: 5 - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: 18 - - id: npm-cache-dir - run: echo "::set-output name=dir::$(npm config get cache)" - - uses: actions/cache@v2 - id: npm-cache - with: - path: ${{ steps.npm-cache-dir.outputs.dir }} - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: ${{ runner.os }}-node- - - run: npm ci --no-audit --prefer-offline - - run: npm run lint - - typecheck: - runs-on: ubuntu-latest - defaults: - run: - working-directory: ./mathesar_ui - timeout-minutes: 5 - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: 18 - - id: npm-cache-dir - run: echo "::set-output name=dir::$(npm config get cache)" - - uses: actions/cache@v2 - id: npm-cache - with: - path: ${{ steps.npm-cache-dir.outputs.dir }} - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: ${{ runner.os }}-node- - - run: npm ci --no-audit --prefer-offline - - run: npm run typecheck - - audit: - runs-on: ubuntu-latest - defaults: - run: - working-directory: ./mathesar_ui - timeout-minutes: 5 - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: 18 - - id: npm-cache-dir - run: echo "::set-output name=dir::$(npm config get cache)" - - uses: actions/cache@v2 - id: npm-cache - with: - path: ${{ steps.npm-cache-dir.outputs.dir }} - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: ${{ runner.os }}-node- - - run: npm ci - - uses: oke-py/npm-audit-action@v1.8.2 - with: - audit_level: moderate - github_token: ${{ secrets.GITHUB_TOKEN }} - create_pr_comments: false - dedupe_issues: true - working_directory: './mathesar_ui' - issue_labels: 'restricted: maintainers,type: bug,work: frontend,status: triage' - production_flag: true - continue-on-error: true - - tests: - runs-on: ubuntu-latest - defaults: - run: - working-directory: ./mathesar_ui - timeout-minutes: 15 - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: 18 - - id: npm-cache-dir - run: echo "::set-output name=dir::$(npm config get cache)" - - uses: actions/cache@v2 - id: npm-cache - with: - path: ${{ steps.npm-cache-dir.outputs.dir }} - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: ${{ runner.os }}-node- - - run: npm ci --no-audit --prefer-offline - - run: npm test diff --git a/.github/workflows/test-and-lint-code.yml b/.github/workflows/test-and-lint-code.yml new file mode 100644 index 0000000000..c52cd13c61 --- /dev/null +++ b/.github/workflows/test-and-lint-code.yml @@ -0,0 +1,332 @@ +## This workflow runs all tests, audits, and linters for Mathesar's source code. +## It's set up to run for every pull request change, as well as when a pull +## request is added to the merge queue. This, combined with our branch +## protections requiring pull requests and a merge queue for `develop` and +## `master` ensures that no code is merged into those branches without +## appropriate tests having run. + +name: Test and Lint Code +on: [pull_request, merge_group] +jobs: + +################################################################################ +## FILE CHANGE CHECKERS ## +## ## +## These jobs check which files have changed so that we can call appropriate ## +## testing, auditing, and linting jobs. Jobs in this section should check for ## +## file changes that would indicate whether we need to run some particular ## +## test suite, then they should output 'true' if such file changes are found. ## +## ## +################################################################################ + + python_tests_required: + name: Check for file changes requiring python tests + runs-on: ubuntu-latest + outputs: + tests_should_run: ${{ steps.changed_files.outputs.any_changed }} + steps: + - uses: actions/checkout@v4 + - name: Get changed files + id: changed_files + uses: tj-actions/changed-files@v39 + with: + files: | + *.py + mathesar/** + db/** + + python_lint_required: + name: Check for file changes requiring python linter + runs-on: ubuntu-latest + outputs: + lint_should_run: ${{ steps.changed_files.outputs.any_changed }} + steps: + - uses: actions/checkout@v4 + - name: Get changed files + id: changed_files + uses: tj-actions/changed-files@v39 + with: + files: '**.py' + + sql_tests_required: + name: Check for file changes requiring SQL tests + runs-on: ubuntu-latest + outputs: + tests_should_run: ${{ steps.changed_files.outputs.any_changed }} + steps: + - uses: actions/checkout@v4 + - name: Get changed files + id: changed_files + uses: tj-actions/changed-files@v39 + with: + files: '**.sql' + + front_end_checks_required: + name: Check for file changes requiring front end checks + runs-on: ubuntu-latest + outputs: + checks_should_run: ${{ steps.changed_files.outputs.any_changed }} + steps: + - uses: actions/checkout@v4 + - name: Get changed files + id: changed_files + uses: tj-actions/changed-files@v39 + with: + files: 'mathesar_ui/**' + +################################################################################ +## BACK END TEST/LINT RUNNERS ## +## ## +## These jobs run tests and linters. Each job in this section should be ## +## dependent on one of the FILE CHANGE CHECKERS above, and should only run if ## +## appropriate files have changed. You can see this by using a `needs:` block ## +## to make the job dependent on the relevant file checker, and an `if:` block ## +## to ensure that the file checker returned 'true' before running the actual ## +## job. Job IDs in this section must be namespaced (so `python_tests` ## +## instead of just `tests`). ## +## ## +################################################################################ + + python_tests: + name: Run Python tests + runs-on: ubuntu-latest + needs: python_tests_required + if: needs.python_tests_required.outputs.tests_should_run == 'true' + strategy: + matrix: + pg-version: [13, 14, 15] + steps: + - uses: actions/checkout@v4 + - name: Copy env file + run: cp .env.example .env + # The code is checked out under uid 1001 - reset this to 1000 for the + # container to run tests successfully + - name: Fix permissions + run: sudo chown -R 1000:1000 . + - name: Build the stack + run: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d test-service + env: + PG_VERSION: ${{ matrix.pg-version }} + - name: Run tests with pytest + run: docker exec mathesar_service_test ./run_pytest.sh + + sql_tests: + name: Run SQL tests + runs-on: ubuntu-latest + needs: sql_tests_required + if: needs.sql_tests_required.outputs.tests_should_run == 'true' + strategy: + matrix: + pg-version: [13, 14, 15] + steps: + - uses: actions/checkout@v4 + - name: Copy env file + run: cp .env.example .env + # The code is checked out under uid 1001 - reset this to 1000 for the + # container to run tests successfully + - name: Fix permissions + run: sudo chown -R 1000:1000 . + - name: Build the test DB + run: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d dev-db + env: + PG_VERSION: ${{ matrix.pg-version }} + - name: Run tests with pg_prove + run: docker exec mathesar_dev_db /bin/bash /sql/run_tests.sh + + python_lint: + name: Run Python linter + runs-on: ubuntu-latest + needs: python_lint_required + if: needs.python_lint_required.outputs.lint_should_run == 'true' + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + - name: Run flake8 + uses: julianwachholz/flake8-action@main + with: + checkName: "flake8" + path: "." + plugins: flake8-no-types + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + vulture: + name: Find unused code + runs-on: ubuntu-latest + needs: python_lint_required + if: needs.python_lint_required.outputs.lint_should_run == 'true' + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + - name: Install Vulture + run: pip3 install vulture + - name: Run Vulture + run: vulture . + +################################################################################ +## FRONT END CHECK RUNNERS ## +## ## +## These jobs run front end checks. Each job in this section should be ## +## dependent on one of the FILE CHANGE CHECKERS above (currently only ## +## front_end_checks_required), and should only run if appropriate files have ## +## changed. You can see this by using a `needs:` block to make the job ## +## dependent on the relevant file checker, and an `if:` block to ensure that ## +## the file checker returned 'true' before running the actual job. `lint` and ## +## `tests` Job IDs in this section must be namespaced (`front_end_tests` ## +## rather than `tests`). ## +## ## +################################################################################ + + format: + runs-on: ubuntu-latest + needs: front_end_checks_required + if: needs.front_end_checks_required.outputs.checks_should_run == 'true' + defaults: + run: + working-directory: ./mathesar_ui + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - id: npm-cache-dir + run: echo "::set-output name=dir::$(npm config get cache)" + - uses: actions/cache@v3 + id: npm-cache + with: + path: ${{ steps.npm-cache-dir.outputs.dir }} + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: ${{ runner.os }}-node- + - run: npm ci --no-audit --prefer-offline + - run: npm run check-format + + front_end_lint: + name: Run front end linter + runs-on: ubuntu-latest + needs: front_end_checks_required + if: needs.front_end_checks_required.outputs.checks_should_run == 'true' + defaults: + run: + working-directory: ./mathesar_ui + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - id: npm-cache-dir + run: echo "::set-output name=dir::$(npm config get cache)" + - uses: actions/cache@v3 + id: npm-cache + with: + path: ${{ steps.npm-cache-dir.outputs.dir }} + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: ${{ runner.os }}-node- + - run: npm ci --no-audit --prefer-offline + - run: npm run lint + + front_end_typecheck: + runs-on: ubuntu-latest + needs: front_end_checks_required + if: needs.front_end_checks_required.outputs.checks_should_run == 'true' + defaults: + run: + working-directory: ./mathesar_ui + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - id: npm-cache-dir + run: echo "::set-output name=dir::$(npm config get cache)" + - uses: actions/cache@v3 + id: npm-cache + with: + path: ${{ steps.npm-cache-dir.outputs.dir }} + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: ${{ runner.os }}-node- + - run: npm ci --no-audit --prefer-offline + - run: npm run typecheck + + front_end_audit: + runs-on: ubuntu-latest + needs: front_end_checks_required + if: needs.front_end_checks_required.outputs.checks_should_run == 'true' + defaults: + run: + working-directory: ./mathesar_ui + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - id: npm-cache-dir + run: echo "::set-output name=dir::$(npm config get cache)" + - uses: actions/cache@v3 + id: npm-cache + with: + path: ${{ steps.npm-cache-dir.outputs.dir }} + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: ${{ runner.os }}-node- + - run: npm ci + - uses: oke-py/npm-audit-action@v1.8.2 + with: + audit_level: moderate + github_token: ${{ secrets.GITHUB_TOKEN }} + create_pr_comments: false + dedupe_issues: true + working_directory: './mathesar_ui' + issue_labels: 'restricted: maintainers,type: bug,work: frontend,status: triage' + production_flag: true + continue-on-error: true + + front_end_tests: + runs-on: ubuntu-latest + needs: front_end_checks_required + if: needs.front_end_checks_required.outputs.checks_should_run == 'true' + defaults: + run: + working-directory: ./mathesar_ui + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - id: npm-cache-dir + run: echo "::set-output name=dir::$(npm config get cache)" + - uses: actions/cache@v3 + id: npm-cache + with: + path: ${{ steps.npm-cache-dir.outputs.dir }} + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: ${{ runner.os }}-node- + - run: npm ci --no-audit --prefer-offline + - run: npm test + +################################################################################ +## REQUIRED TEST/LINT COLLECTORS ## +## Jobs in this section collect outputs from various testing and linting jobs ## +## above, and associate their status with required job IDs for branch ## +## protection purposes. At the moment, they only need to have each required ## +## check as a dependency. Required checks should skip themselves if no ## +## relevant files have changed. ## +## ## +################################################################################ + + tests: + runs-on: ubuntu-latest + needs: [python_tests, sql_tests, front_end_tests] + steps: + - name: Report success + run: echo "All tests succeeded or skipped!" + + lint: + runs-on: ubuntu-latest + needs: [python_lint, front_end_lint] + steps: + - name: Report success + run: echo "All linters succeeded or skipped!" From e0e8be1528515cc3356f4ed9dc309965ef4580df Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Thu, 26 Oct 2023 15:47:26 +0800 Subject: [PATCH 105/111] add small change to check front end running behavior --- .github/workflows/test-and-lint-code.yml | 2 ++ mathesar_ui/src/api/utils/recordUtils.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-and-lint-code.yml b/.github/workflows/test-and-lint-code.yml index c52cd13c61..b303dd9d0e 100644 --- a/.github/workflows/test-and-lint-code.yml +++ b/.github/workflows/test-and-lint-code.yml @@ -251,6 +251,7 @@ jobs: - run: npm run typecheck front_end_audit: + name: Audit front end code runs-on: ubuntu-latest needs: front_end_checks_required if: needs.front_end_checks_required.outputs.checks_should_run == 'true' @@ -284,6 +285,7 @@ jobs: continue-on-error: true front_end_tests: + name: Run front end tests runs-on: ubuntu-latest needs: front_end_checks_required if: needs.front_end_checks_required.outputs.checks_should_run == 'true' diff --git a/mathesar_ui/src/api/utils/recordUtils.ts b/mathesar_ui/src/api/utils/recordUtils.ts index 4dbe3db16e..161a60cd4a 100644 --- a/mathesar_ui/src/api/utils/recordUtils.ts +++ b/mathesar_ui/src/api/utils/recordUtils.ts @@ -15,7 +15,7 @@ type ColumnErrors = ImmutableMap; * about which column(s) caused the error, and sometimes we just get a generic * top-level error message. Because the API schema supports sending multiple * errors in one response, we use a data structure here that can handle both - * situations at the same time. + * situations at the same time. diff */ export interface DetailedRecordsErrors { columnErrors: ColumnErrors; From 37fcbb12e1b60e953a2ac3b561393f5a8e0133f6 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Thu, 26 Oct 2023 15:53:17 +0800 Subject: [PATCH 106/111] modify FE tests to fail (behavior check) --- mathesar_ui/src/api/utils/recordUtils.ts | 2 +- mathesar_ui/src/utils/__tests__/api.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mathesar_ui/src/api/utils/recordUtils.ts b/mathesar_ui/src/api/utils/recordUtils.ts index 161a60cd4a..4dbe3db16e 100644 --- a/mathesar_ui/src/api/utils/recordUtils.ts +++ b/mathesar_ui/src/api/utils/recordUtils.ts @@ -15,7 +15,7 @@ type ColumnErrors = ImmutableMap; * about which column(s) caused the error, and sometimes we just get a generic * top-level error message. Because the API schema supports sending multiple * errors in one response, we use a data structure here that can handle both - * situations at the same time. diff + * situations at the same time. */ export interface DetailedRecordsErrors { columnErrors: ColumnErrors; diff --git a/mathesar_ui/src/utils/__tests__/api.test.ts b/mathesar_ui/src/utils/__tests__/api.test.ts index 371998775d..4cdd55af36 100644 --- a/mathesar_ui/src/utils/__tests__/api.test.ts +++ b/mathesar_ui/src/utils/__tests__/api.test.ts @@ -14,7 +14,7 @@ test('getMostImportantRequestStatusState', () => { { state: 'success' }, { state: 'failure', errors: ['foo'] }, ]), - ).toBe('failure'); + ).toBe('failue'); expect(getMostImportantRequestStatusState([{ state: 'success' }])).toBe( 'success', From 3032705cc3d472b6a8546237d3fb92e512e7bde9 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Thu, 26 Oct 2023 16:05:53 +0800 Subject: [PATCH 107/111] reset tests to pass, format to fail --- mathesar_ui/src/api/users.ts | 6 +++--- mathesar_ui/src/utils/__tests__/api.test.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mathesar_ui/src/api/users.ts b/mathesar_ui/src/api/users.ts index ad2599105f..158b4830ca 100644 --- a/mathesar_ui/src/api/users.ts +++ b/mathesar_ui/src/api/users.ts @@ -8,13 +8,13 @@ import { type PaginatedResponse, } from './utils/requestUtils'; -export interface UnsavedUser { +export interface UnsavedUser +{ full_name: string | null; email: string | null; username: string; password: string; - display_language: Locales; -} + display_language: Locales;} export type UserRole = 'viewer' | 'editor' | 'manager'; diff --git a/mathesar_ui/src/utils/__tests__/api.test.ts b/mathesar_ui/src/utils/__tests__/api.test.ts index 4cdd55af36..371998775d 100644 --- a/mathesar_ui/src/utils/__tests__/api.test.ts +++ b/mathesar_ui/src/utils/__tests__/api.test.ts @@ -14,7 +14,7 @@ test('getMostImportantRequestStatusState', () => { { state: 'success' }, { state: 'failure', errors: ['foo'] }, ]), - ).toBe('failue'); + ).toBe('failure'); expect(getMostImportantRequestStatusState([{ state: 'success' }])).toBe( 'success', From db5cc248f67ff960282c02769671f4194d1ef14f Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Thu, 26 Oct 2023 16:25:52 +0800 Subject: [PATCH 108/111] Improve job names and ID clarity --- .github/workflows/test-and-lint-code.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-and-lint-code.yml b/.github/workflows/test-and-lint-code.yml index b303dd9d0e..cb391426c9 100644 --- a/.github/workflows/test-and-lint-code.yml +++ b/.github/workflows/test-and-lint-code.yml @@ -177,7 +177,8 @@ jobs: ## ## ################################################################################ - format: + front_end_format: + name: Check front end code format runs-on: ubuntu-latest needs: front_end_checks_required if: needs.front_end_checks_required.outputs.checks_should_run == 'true' @@ -227,6 +228,7 @@ jobs: - run: npm run lint front_end_typecheck: + name: Check front end types runs-on: ubuntu-latest needs: front_end_checks_required if: needs.front_end_checks_required.outputs.checks_should_run == 'true' From 5adc78951f47823d6623254e3a3568263771405b Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Thu, 26 Oct 2023 16:27:50 +0800 Subject: [PATCH 109/111] Remove unneeded collectors --- .github/workflows/test-and-lint-code.yml | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/.github/workflows/test-and-lint-code.yml b/.github/workflows/test-and-lint-code.yml index cb391426c9..928f05492f 100644 --- a/.github/workflows/test-and-lint-code.yml +++ b/.github/workflows/test-and-lint-code.yml @@ -310,27 +310,3 @@ jobs: restore-keys: ${{ runner.os }}-node- - run: npm ci --no-audit --prefer-offline - run: npm test - -################################################################################ -## REQUIRED TEST/LINT COLLECTORS ## -## Jobs in this section collect outputs from various testing and linting jobs ## -## above, and associate their status with required job IDs for branch ## -## protection purposes. At the moment, they only need to have each required ## -## check as a dependency. Required checks should skip themselves if no ## -## relevant files have changed. ## -## ## -################################################################################ - - tests: - runs-on: ubuntu-latest - needs: [python_tests, sql_tests, front_end_tests] - steps: - - name: Report success - run: echo "All tests succeeded or skipped!" - - lint: - runs-on: ubuntu-latest - needs: [python_lint, front_end_lint] - steps: - - name: Report success - run: echo "All linters succeeded or skipped!" From 9c4d02b89e06a2ca07a79eaa1e3b5e32379446f3 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Thu, 26 Oct 2023 16:38:16 +0800 Subject: [PATCH 110/111] restore collector for matrix-strategy tests --- .github/workflows/test-and-lint-code.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/test-and-lint-code.yml b/.github/workflows/test-and-lint-code.yml index 928f05492f..b59fbe713c 100644 --- a/.github/workflows/test-and-lint-code.yml +++ b/.github/workflows/test-and-lint-code.yml @@ -310,3 +310,20 @@ jobs: restore-keys: ${{ runner.os }}-node- - run: npm ci --no-audit --prefer-offline - run: npm test + +################################################################################ +## REQUIRED TEST/LINT COLLECTORS ## +## Jobs in this section collect outputs from matrix-strategy testing jobs, ## +## since these are otherwise impossible to capture for branch protection ## +## purposes. At the moment, they only need to have each required check as a ## +## dependency. Required checks should skip themselves if no relevant files ## +## have changed. ## +## ## +################################################################################ + + matrix_tests: + runs-on: ubuntu-latest + needs: [python_tests, sql_tests] + steps: + - name: Report success + run: echo "All tests succeeded or skipped!" From 707dcc388afb88d7b05ebffa50d576cbd109906f Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Thu, 26 Oct 2023 16:42:31 +0800 Subject: [PATCH 111/111] restore front end formatting (should pass) --- mathesar_ui/src/api/users.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mathesar_ui/src/api/users.ts b/mathesar_ui/src/api/users.ts index 158b4830ca..ad2599105f 100644 --- a/mathesar_ui/src/api/users.ts +++ b/mathesar_ui/src/api/users.ts @@ -8,13 +8,13 @@ import { type PaginatedResponse, } from './utils/requestUtils'; -export interface UnsavedUser -{ +export interface UnsavedUser { full_name: string | null; email: string | null; username: string; password: string; - display_language: Locales;} + display_language: Locales; +} export type UserRole = 'viewer' | 'editor' | 'manager';