Browse Source

Merge branch 'develop' into enhancement/audits

pull/5403/head
Wing-Kam Wong 2 years ago
parent
commit
095e89b8b4
  1. 11
      packages/nc-gui/components/cell/MultiSelect.vue
  2. 2
      packages/nc-gui/components/dashboard/settings/AuditTab.vue
  3. 2
      packages/nc-gui/components/smartsheet/Pagination.vue
  4. 2
      packages/nc-gui/components/tabs/auth/UserManagement.vue
  5. 2
      packages/nc-gui/components/webhook/CallLog.vue
  6. 6
      packages/nc-gui/lang/pt_BR.json
  7. 184
      packages/nc-gui/lang/uk.json
  8. 8
      packages/nc-gui/lang/zh-Hans.json
  9. 3
      packages/noco-docs/content/en/developer-resources/webhooks.md
  10. 55
      packages/nocodb/Dockerfile.local
  11. 14
      packages/nocodb/docker/start-local.sh
  12. 23
      packages/nocodb/src/lib/db/sql-client/lib/pg/PgClient.ts
  13. 2
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts
  14. 18
      packages/nocodb/src/run/local.ts
  15. 53
      packages/nocodb/webpack.local.config.js

11
packages/nc-gui/components/cell/MultiSelect.vue

@ -314,9 +314,14 @@ const handleClose = (e: MouseEvent) => {
useEventListener(document, 'click', handleClose, true)
// todo: maintain order
const selectedOpts = computed(() => {
return options.value.filter((o) => vModel.value.includes(o.value!))
return options.value.reduce<(SelectOptionType & { index: number })[]>((selectedOptions, option) => {
const index = vModel.value.indexOf(option.value!)
if (index !== -1) {
selectedOptions.push({ ...option, index })
}
return selectedOptions
}, [])
})
</script>
@ -324,7 +329,7 @@ const selectedOpts = computed(() => {
<div class="nc-multi-select h-full w-full flex items-center" :class="{ 'read-only': readOnly }" @click="toggleMenu">
<div v-if="!editable && !active" class="flex flex-nowrap">
<template v-for="selectedOpt of selectedOpts" :key="selectedOpt.value">
<a-tag class="rounded-tag" :color="selectedOpt.color">
<a-tag class="rounded-tag" :color="selectedOpt.color" :style="{ order: selectedOpt.index }">
<span
:style="{
'color': tinycolor.isReadable(selectedOpt.color || '#ccc', '#fff', { level: 'AA', size: 'large' })

2
packages/nc-gui/components/dashboard/settings/AuditTab.vue

@ -104,7 +104,7 @@ const columns = [
<a-pagination
v-model:current="currentPage"
:page-size="currentLimit"
v-model:page-size="currentLimit"
:total="totalRows"
show-less-items
@change="loadAudits"

2
packages/nc-gui/components/smartsheet/Pagination.vue

@ -28,10 +28,10 @@ const page = computed({
<a-pagination
v-if="count !== Infinity"
v-model:current="page"
v-model:page-size="size"
size="small"
class="!text-xs !m-1 nc-pagination"
:total="count"
:page-size="size"
show-less-items
:show-size-changer="false"
/>

2
packages/nc-gui/components/tabs/auth/UserManagement.vue

@ -369,9 +369,9 @@ const isSuperAdmin = (user: { main_roles?: string }) => {
<a-pagination
v-model:current="currentPage"
v-model:page-size="currentLimit"
hide-on-single-page
class="mt-4"
:page-size="currentLimit"
:total="totalRows"
show-less-items
@change="loadUsers"

2
packages/nc-gui/components/webhook/CallLog.vue

@ -159,7 +159,7 @@ onBeforeMount(async () => {
<a-layout-footer class="!bg-white text-center">
<a-pagination
v-model:current="currentPage"
:page-size="currentLimit"
v-model:page-size="currentLimit"
:total="totalRows"
show-less-items
@change="loadHookLogs"

6
packages/nc-gui/lang/pt_BR.json

@ -101,7 +101,7 @@
"form": "Formulário",
"kanban": "Kanban",
"calendar": "Calendário",
"map": "Map"
"map": "Mapa"
},
"user": "Do utilizador",
"users": "Comercial",
@ -210,7 +210,7 @@
"advancedSettings": "Configurações avançadas",
"codeSnippet": "Código Snippet",
"keyboardShortcut": "Atalhos de teclado",
"generateRandomName": "Generate Random Name",
"generateRandomName": "Gerar um código aleatório",
"findRowByScanningCode": "Find row by scanning a QR or Barcode"
},
"labels": {
@ -472,7 +472,7 @@
"map": {
"mappedBy": "Mapped By",
"chooseMappingField": "Choose a Mapping Field",
"openInGoogleMaps": "Google Maps",
"openInGoogleMaps": "Google Mapas",
"openInOpenStreetMap": "OSM"
},
"toggleMobileMode": "Toggle Mobile Mode"

184
packages/nc-gui/lang/uk.json

@ -22,12 +22,12 @@
"update": "Оновити",
"rename": "Перейменувати",
"reload": "Перезавантажити",
"reset": "Скинути",
"reset": "Відновити",
"install": "Встановити",
"show": "Показати",
"hide": "Приховати",
"hide": "Сховати",
"showAll": "Показати все",
"hideAll": "Приховати все",
"hideAll": "Сховати все",
"showMore": "Показати більше",
"showOptions": "Показати опції",
"hideOptions": "Сховати опції",
@ -52,7 +52,7 @@
"event": "Подія",
"condition": "Стан",
"after": "Після",
"before": "Раніше",
"before": "До",
"search": "Пошук",
"notification": "Сповіщення",
"reference": "Посилання",
@ -133,7 +133,7 @@
"Time": "Час",
"PhoneNumber": "Номер телефону",
"Email": "Пошта",
"URL": "URL",
"URL": "URL-посилання",
"Number": "Число",
"Decimal": "Дробове",
"Currency": "Валюта",
@ -148,7 +148,7 @@
"DateTime": "Дата і час",
"CreateTime": "Час створення",
"LastModifiedTime": "Час останньої зміни",
"AutoNumber": "Автоматичне число",
"AutoNumber": "Автоматичне прирощування",
"Barcode": "Штрих-код",
"Button": "Кнопка",
"Password": "Пароль",
@ -182,10 +182,10 @@
"teamAndAuth": "Команда та автор",
"rolesUserMgmt": "Ролі та управління користувачами",
"userMgmt": "Керування користувачами",
"apiTokenMgmt": "Управління токенами API",
"apiTokenMgmt": "Керування токенами API",
"rolesMgmt": "Керування ролями",
"projMeta": "Метадані проєкту",
"metaMgmt": "Метаменеджмент",
"metaMgmt": "Керування метаданими",
"metadata": "Метадані",
"exportImportMeta": "Експорт/Імпорт метаданих",
"uiACL": "Контроль доступу до інтерфейсу",
@ -240,7 +240,7 @@
"operation": "Операція",
"operationSub": "Субоперація",
"operationType": "Тип операції",
"operationSubType": "Підтип операції",
"operationSubType": "Тип субоперації",
"description": "Опис",
"authentication": "Автентифікація",
"token": "Токен",
@ -272,11 +272,11 @@
"requriedIdentity": "Потрібна ідентифікація",
"inflection": {
"tableName": "Перехрестя - Назва таблиці",
"columnName": "Перехрестя - Назва стовпця"
"columnName": "Перехрестя - назва стовпця"
},
"community": {
"starUs1": "Оцінити",
"starUs2": "ми на GitHub",
"starUs2": "нас на GitHub",
"bookDemo": "Забронюйте безкоштовну демонстрацію",
"getAnswered": "Отримайте відповіді на запитання",
"joinDiscord": "Ми є в Discord",
@ -338,30 +338,30 @@
"deleteProject": "Видалити проєкт",
"refreshProject": "Оновити проєкти",
"saveProject": "Зберегти проєкт",
"deleteKanbanStack": "Видалити стек?",
"deleteKanbanStack": "Видалити табличку?",
"createProjectExtended": {
"extDB": "Створити підключення <br>до зовнішньої бази даних",
"extDB": "Створити підключення<br>до зовнішньої бази даних",
"excel": "Створити проєкт з Excel",
"template": "Створити проєкт з шаблону"
},
"OkSaveProject": "Підтвердити & Зберегти",
"OkSaveProject": "Зберегти",
"upgrade": {
"available": "Доступне оновлення",
"releaseNote": "Список змін",
"howTo": "Як оновитися?"
"howTo": "Як оновитись?"
},
"translate": "Допоможіть з перекладом",
"translate": "Допомогти з перекладом",
"account": {
"authToken": "Копіювати токен авторизації",
"authToken": "Скопіювати токен",
"swagger": "Swagger: REST API",
"projInfo": "Скопіювати інформацію про проект",
"projInfo": "Скопіювати інформацію про проєкт",
"themes": "Теми"
},
"sort": "Сортувати",
"addSort": "Додати параметри сортування",
"filter": "Фільтр",
"addFilter": "Додати фільтр",
"share": "Поділитися",
"share": "Поділитись",
"shareBase": {
"disable": "Вимкнути спільну базу",
"enable": "Будь-хто, хто має посилання",
@ -374,10 +374,10 @@
"inviteToken": "Токен запрошення",
"newUser": "Новий користувач",
"editUser": "Редагувати користувача",
"deleteUser": "Видалити користувача з проєкту",
"resendInvite": "Повторно надіслати запрошення на пошту",
"copyInviteURL": "Скопіювати URL-адресу запрошення",
"copyPasswordResetURL": "Скопіювати URL-адресу для оновлення паролю",
"deleteUser": "Видалити користувача",
"resendInvite": "Повторно надіслати запрошення",
"copyInviteURL": "Скопіювати URL-посилання для запрошення",
"copyPasswordResetURL": "Скопіювати URL-посилання для відновлення паролю",
"newRole": "Нова роль",
"reloadRoles": "Перезавантажити ролі",
"nextPage": "Наступна сторінка",
@ -390,7 +390,7 @@
"renameTable": "Перейменувати таблицю",
"deleteTable": "Видалити таблицю",
"addField": "Додати нове поле до цієї таблиці",
"setDisplay": "Встановити як значення для відображення",
"setDisplay": "Встановити як значення для показу",
"addRow": "Додати новий рядок",
"saveRow": "Зберегти рядок",
"saveAndExit": "Зберегти та вийти",
@ -416,20 +416,20 @@
"fillByCodeScan": "Заповнити за допомогою сканування",
"listSharedView": "Список спільних виглядів",
"ListView": "Список виглядів",
"copyView": "Копіювати вигляд",
"copyView": "Скопіювати вигляд",
"renameView": "Перейменувати вигляд",
"deleteView": "Видалити вигляд",
"createGrid": "Створіть вигляд сітки",
"createGallery": "Створити вигляд галереї",
"createCalendar": "Створити вигляд календаря",
"createKanban": "Створити Kanban вигляд",
"createKanban": "Створити табличний вигляд",
"createForm": "Створити вигляд форми",
"showSystemFields": "Показати системні поля",
"copyUrl": "Копіювати URL-адресу",
"openTab": "Відкрийте нову вкладку",
"iFrame": "Копіювати вбудований HTML-код",
"addWebhook": "Додати новий Webhook",
"enableWebhook": "Увімкнути вебхук",
"addWebhook": "Додати новий вебхук",
"enableWebhook": "Ввімкнути вебхук",
"testWebhook": "Перевірити вебхук",
"copyWebhook": "Скопіювати вебхук",
"deleteWebhook": "Видалити вебхук",
@ -439,8 +439,8 @@
"metaSync": "Синхронізувати",
"settings": "Налаштування",
"previewAs": "Попередній перегляд як",
"resetReview": "Скинути попередній перегляд",
"testDbConn": "Тестове з'єднання з базою даних",
"resetReview": "Відновити попередній перегляд",
"testDbConn": "Тестове зʼєднання з базою даних",
"removeDbFromEnv": "Видалити базу даних з середовища",
"editConnJson": "Редагувати підключення JSON",
"sponsorUs": "Спонсорувати нас",
@ -460,38 +460,38 @@
"showPkAndFk": "Показати первинні та зовнішні ключі",
"showSqlViews": "Показати SQL вигляд",
"showMMTables": "Показати таблиці \"багато-до-багатьох\"",
"showJunctionTableNames": "Показати ім'я таблиці для з'єднання"
"showJunctionTableNames": "Показати імʼя таблиці для зʼєднання"
},
"kanban": {
"collapseStack": "Згорнути стек",
"deleteStack": "Видалити стек",
"stackedBy": "Групувати по",
"chooseGroupingField": "Виберіть поле групування",
"addOrEditStack": "Додати / Редагувати стек"
"addOrEditStack": "Додати/Редагувати табличку"
},
"map": {
"mappedBy": "Mapped By",
"mappedBy": "Мапувати по",
"chooseMappingField": "Виберіть поле для мапування",
"openInGoogleMaps": "Google Maps",
"openInOpenStreetMap": "OSM"
"openInOpenStreetMap": "Відкрити в Google Maps"
},
"toggleMobileMode": "Увімкнути мобільний режим"
"toggleMobileMode": "Ввімкнути мобільний режим"
},
"tooltip": {
"saveChanges": "Зберегти зміни",
"xcDB": "Створити новий проєкт",
"extDB": "Підтримує MySQL, PostgreSQL, SQL Server та SQLite",
"apiRest": "Доступно через REST API",
"apiGQL": "Доступно через API GraphQL",
"apiGQL": "Доступно через GraphQL API",
"theme": {
"dark": "Він доступний у чорному кольорі (^⇧B)",
"light": "Чи є він у чорному кольорі? (^⇧B)"
},
"addTable": "Додати нову таблицю",
"inviteMore": "Запросіть більше користувачів",
"toggleNavDraw": "Ввімвкнути висувне меню",
"toggleNavDraw": "Ввімкнути висувне меню",
"reloadApiToken": "Перезавантажити API токен",
"generateNewApiToken": "Створити новий API токен",
"generateNewApiToken": "Згенерувати API токен",
"addRole": "Додати нову роль",
"reloadList": "Перезавантажити список",
"metaSync": "Синхронізувати метаданні",
@ -538,13 +538,13 @@
"info": {
"pasteNotSupported": "Операція вставки не підтримується в активній комірці",
"roles": {
"orgCreator": "Розробник може створювати нові проєкти та мати доступ до будь-якого відкритого проєкту.",
"orgViewer": "Глядач не може створювати нові проєкти, але він може отримати доступ до будь-якого відкритого проєкту."
"orgCreator": "Розробник може створювати нові проєкти та мати доступ до будь-якого публічного проєкту.",
"orgViewer": "Глядач не може створювати нові проєкти, але він може отримати доступ до будь-якого публічного проєкту."
},
"codeScanner": {
"loadingScanner": "Завантаження сканера...",
"selectColumn": "Виберіть стовпець, QR-код або штрих-код, який ви хочете використовувати для пошуку рядка за допомогою сканування.",
"moreThanOneRowFoundForCode": "Для цього коду знайдено більше одного рядка. Наразі підтримуються лише унікальні коди.",
"moreThanOneRowFoundForCode": "Для цього коду знайдено декілька рядків. Наразі підтримуються лише унікальні коди",
"noRowFoundForCode": "Для цього коду не знайдено жодного рядка у вибраному стовпчику"
},
"map": {
@ -558,19 +558,19 @@
"excelSupport": "Підтримуються: .xls, .xlsx, .xlsm, .ods, .ots",
"excelURL": "Введіть посилання до файлу Excel",
"csvURL": "Введіть посилання до файлу CSV",
"footMsg": "# рядків, які потрібно проаналізувати, щоб вивести тип даних",
"footMsg": "К-сть рядків для аналізу, щоб визначити тип даних",
"excelImport": "аркуш(і) які доступні для імпорту",
"exportMetadata": "Ви хочете експортувати метадані з мета-таблиць?",
"importMetadata": "Ви хочете імпортувати метадані з мета-таблиць?",
"clearMetadata": "Ви хочете очистити метадані з мета-таблиць?",
"projectEmptyMessage": "Почніть зі створення нового проекту",
"projectEmptyMessage": "Почніть зі створення нового проєкту",
"stopProject": "Ви хочете зупинити проєкт?",
"startProject": "Ви хочете розпочати проєкт?",
"restartProject": "Ви хочете перезапустити проєкт?",
"deleteProject": "Ви хочете видалити проєкт?",
"shareBasePrivate": "Створіть загальнодоступну базу, доступну лише для читання",
"shareBasePublic": "Будь-хто в Інтернеті може переглядати за допомогою цього посилання",
"userInviteNoSMTP": "Схоже, ви ще не налаштували SMTP! Будь ласка, скопіюйте посилання на запрошення та надішліть його на адресу",
"userInviteNoSMTP": "Схоже, ви ще не налаштували SMTP! Будь ласка, скопіюйте посилання на запрошення та надішліть його на пошту.",
"dragDropHide": "Перетягніть поля сюди, щоб приховати",
"formInput": "Введіть назву форми для введення",
"formHelpText": "Додайте допоміжний текст",
@ -578,7 +578,7 @@
"formDesc": "Додати опис форми",
"beforeEnablePwd": "Обмежити доступ за допомогою пароля",
"afterEnablePwd": "Доступ обмежено паролем",
"privateLink": им переглядом поділилися через приватне посилання",
"privateLink": ей перегляд доступний за приватним посиланням",
"privateLinkAdditionalInfo": "Люди з приватним посиланням можуть бачити лише клітини, видимі в цьому вигляді",
"afterFormSubmitted": "Після надсилання форми",
"apiOptions": "Доступ до проєкту через",
@ -593,9 +593,9 @@
"collabView": "Учасники з дозволом на редагування або вище можуть змінювати конфігурацію перегляду.",
"lockedView": "Ніхто не може відредагувати конфігурацію перегляду, доки вона не розблокована.",
"personalView": "Тільки ви можете відредагувати конфігурацію. Іншим учасникам прихована зміна переглядів за замовчуванням.",
"ownerDesc": "Може додавати/видаляти редакторів. Також може повністю редагувати структури та поля бази даних.",
"ownerDesc": "Може додавати або видаляти редакторів. Також може повністю редагувати структури та поля бази даних.",
"creatorDesc": "Може повністю редагувати структуру бази даних та значення.",
"editorDesc": "Може редагувати записи, але не може змінити структуру бази даних/полів.",
"editorDesc": "Може редагувати записи, але не може змінити структуру бази даних або полів.",
"commenterDesc": "Може переглядати та коментувати записи, але нічого не може редагувати",
"viewerDesc": "Може переглядати записи, але нічого не може редагувати",
"addUser": "Додати нового користувача",
@ -606,14 +606,14 @@
"metaNoChange": "Не виявлено жодних змін",
"sqlMigration": "Схема міграції буде створена автоматично. Створіть таблицю та оновіть цю сторінку.",
"dbConnectionStatus": "Середовище перевірено",
"dbConnected": 'єднання успішне",
"dbConnected": ʼєднання успішне",
"notifications": {
"no_new": "Немає нових повідомлень",
"clear": "Очистити"
},
"sponsor": {
"header": "Ви можете допомогти нам!",
"message": "Ми - невелика команда, яка працює на повну ставку, щоб зробити NocoDB відкритим. Ми віримо, що такий інструмент, як NocoDB, повинен бути доступним безкоштовно для кожного розв'язувача проблем в Інтернеті."
"message": "Ми - невелика команда, яка працює на повну ставку, щоб зробити NocoDB відкритим. Ми віримо, що такий інструмент, як NocoDB, повинен бути доступним безкоштовно для кожного розвʼязувача проблем в Інтернеті."
},
"loginMsg": "Увійти до NocoDB",
"passwordRecovery": {
@ -623,22 +623,22 @@
},
"signUp": {
"superAdmin": "Ви будете \"Власником\"",
"alreadyHaveAccount": "Вже є обліковий запис?",
"alreadyHaveAccount": "Вже зареєстровані?",
"workEmail": "Введіть робочу адресу електронної пошти",
"enterPassword": "Введіть ваш пароль",
"forgotPassword": "Забули власний пароль?",
"forgotPassword": "Забули пароль?",
"dontHaveAccount": "Не маєте облікового запису?"
},
"addView": {
"grid": "Додати вигляд сітки",
"gallery": "Додати вигляд галереї",
"form": "Додати вигляд форми",
"kanban": "Додати вигляд Kanban",
"kanban": "Додати вигляд таблички",
"map": "Додати вид мапи",
"calendar": "Додати вигляд календаря"
},
"tablesMetadataInSync": "Таблиці метаданих синхронізуються",
"addMultipleUsers": "Ви можете додати кілька електронних адрес, розділених комами(,)",
"addMultipleUsers": "Ви можете додати кілька електронних адрес через кому",
"enterTableName": "Введіть назву таблиці",
"addDefaultColumns": "Додайте стовпці за замовчуванням",
"tableNameInDb": "Назва таблиці, збережена в базі даних",
@ -648,7 +648,7 @@
"import": {
"clickOrDrag": "Клацніть або перетягніть файл у цю область, щоб завантажити його"
},
"metaDataRecreated": "Метадані таблиці успішно відтворено",
"metaDataRecreated": "Метадані таблиці відтворено",
"invalidCredentials": "Недійсні облікові дані",
"downloadingMoreFiles": "Завантажте інші файли",
"copiedToClipboard": "Скопійовано в буфер обміну",
@ -658,7 +658,7 @@
"editingPKnotSupported": "Редагування первинного ключа не підтримується",
"deletedCache": "Кеш успішно видалено",
"cacheEmpty": "Кеш порожній",
"exportedCache": "Кеш успішно експортовано",
"exportedCache": "Кеш експортовано",
"valueAlreadyInList": "Це значення вже є у списку",
"noColumnsToUpdate": "Немає стовпців для оновлення",
"tableDeleted": "Таблицю успішно видалено",
@ -668,26 +668,26 @@
"showM2mTables": "Показати M2M таблиці",
"showM2mTablesDesc": "Звʼязок \"багато-до-багатьох\" підтримується через таблицю зʼєднань і за замовчуванням прихований. Увімкніть цю опцію, щоб перерахувати всі такі таблиці разом з існуючими.",
"showNullInCells": "Показати NULL в комірках",
"showNullInCellsDesc": "Відображати тег 'NULL' у клітинках, що містять NULL-значення. Це допомагає відрізнити клітинки, що містять ПУСТИЙ рядок.",
"showNullInCellsDesc": "Відображати тег \"NULL\" у клітинках, що містять NULL-значення. Це допомагає відрізнити клітинки, що містять пустий рядок.",
"showNullAndEmptyInFilter": "Показувати NULL та EMPTY у фільтрі",
"showNullAndEmptyInFilterDesc": "Увімкніть \"додаткові\" фільтри для розрізнення полів, що містять NULL та порожні рядки. За замовчуванням підтримка пропусків однаково обробляє як NULL, так і порожні рядки.",
"deleteKanbanStackConfirmation": "Видалення цього стека також вилучить опцію вибору `{stackToBeDeleted}` зі стека `{groupingField}`. Записи буде переміщено до не категоризованого стека.",
"showNullAndEmptyInFilterDesc": "Ввімкніть \"додаткові\" фільтри для розрізнення полів, що містять NULL та порожні рядки. За замовчуванням підтримка пропусків однаково обробляє як NULL, так і порожні рядки.",
"deleteKanbanStackConfirmation": "Видалення цієї таблички також вилучить опцію вибору `{stackToBeDeleted}` з таблички `{groupingField}`. Записи буде переміщено до не категоризованої таблички.",
"computedFieldEditWarning": "Обчислюване поле: вміст доступний лише для читання. Використовуйте меню редагування стовпця для зміни конфігурації",
"computedFieldDeleteWarning": "Обчислюване поле: вміст доступний лише для читання. Не вдалося очистити вміст.",
"noMoreRecords": "Більше записів немає"
},
"error": {
"searchProject": "За вашим запитом {search} не знайдено жодного результату",
"invalidChar": "Недійсний символ у шляху до теки.",
"invalidChar": "Недійсний символ у шляху.",
"invalidDbCredentials": "Неправильні облікові дані бази даних.",
"unableToConnectToDb": "Неможливо під'єднатися до бази даних, будь ласка, перевірте, чи працює ваша база даних.",
"unableToConnectToDb": "Неможливо підʼєднатися до бази даних, будь ласка, перевірте, чи працює ваша база даних.",
"userDoesntHaveSufficientPermission": "Користувач не існує або не має достатніх прав для створення конфігурації.",
"dbConnectionStatus": "Неправильні параметри бази даних",
"dbConnectionFailed": "Помилка з’єднання:",
"signUpRules": {
"emailReqd": "E-mail є обов'язковим полем",
"emailInvalid": "E-mail має невірний формат",
"passwdRequired": "Пароль є обов'язковим",
"emailReqd": "Пошта є обовʼязковим полем",
"emailInvalid": "Пошта має невірний формат",
"passwdRequired": "Пароль є обовʼязковим",
"passwdLength": "Пароль має складатися хоча б з 8 символів",
"passwdMismatch": "Паролі не збігаються",
"completeRuleSet": "Щонайменше 8 символів з однією великою літерою, однією цифрою та одним спеціальним символом",
@ -704,7 +704,7 @@
"fileUploadFailed": "Не вдалося завантажити файл",
"primaryColumnUpdateFailed": "Не вдалося оновити основний стовпець",
"formDescriptionTooLong": "Занадто довгі дані для опису форми",
"columnsRequired": "Обов'язковими є наступні стовпці",
"columnsRequired": "Обовʼязковими є наступні стовпці",
"selectAtleastOneColumn": "Принаймні один стовпець має бути вибраний",
"columnDescriptionNotFound": "Не вдається знайти стовпець призначення для",
"duplicateMappingFound": "Знайдено дублікат схеми, будь ласка, видаліть одну зі схем",
@ -723,7 +723,7 @@
"setFormDataFailed": "Не вдалося встановити дані форми",
"formViewUpdateFailed": "Не вдалося оновити вигляд форми",
"tableNameRequired": "Ім'я таблиці є обов'язковим",
"nameShouldStartWithAnAlphabetOr_": "Ім'я повинно починатися з літери або _",
"nameShouldStartWithAnAlphabetOr_": "Імʼя повинно починатися з літери або _",
"followingCharactersAreNotAllowed": "Наступні символи не допускаються",
"columnNameRequired": "Ім'я стовпця є обов'язковим",
"columnNameExceedsCharacters": "Довжина назви стовпця перевищує максимальну кількість в {value} символів",
@ -741,52 +741,52 @@
"copyToClipboardError": "Не вдалося скопіювати в буфер обміну"
},
"toast": {
"exportMetadata": "Метадані проєкту успішно експортовано",
"importMetadata": "Метадані проєкту успішно імпортовано",
"clearMetadata": "Метадані проєкту успішно очищено",
"stopProject": "Проєкт успішно зупинений",
"startProject": "Проєкт успішно запущений",
"restartProject": "Проєкт успішно перезапущений",
"deleteProject": "Проєкт успішно видалений",
"exportMetadata": "Метадані проєкту експортовано",
"importMetadata": "Метадані проєкту імпортовано",
"clearMetadata": "Метадані проєкту очищено",
"stopProject": "Проєкт зупинений",
"startProject": "Проєкт запущений",
"restartProject": "Проєкт перезапущений",
"deleteProject": "Проєкт видалений",
"authToken": "Токен авторизації скопійовано в буфер обміну",
"projInfo": "Інформацію про проєкт скопійовано до буфера обміну",
"inviteUrlCopy": "Скопійовано запрошення URL в буфер обміну",
"createView": "Вигляд створено успішно",
"formEmailSMTP": "Будь ласка, активуйте плагін SMTP в Магазині додатків, щоб увімкнути повідомлення електронної пошти",
"collabView": "Успішно переведено в режим спільної роботи",
"lockedView": "Успішно перемкнуто на заблокований вигляд",
"createView": "Вигляд створено",
"formEmailSMTP": "Будь ласка, активуйте плагін SMTP в магазині додатків, щоб ввімкнути повідомлення на електронну пошту",
"collabView": "Переведено в режим спільної роботи",
"lockedView": "Переведено в заблокований режим",
"futureRelease": "Незабаром!"
},
"success": {
"columnDuplicated": "Стовпець успішно продубльовано",
"rowDuplicatedWithoutSavedYet": "Рядок продубльовано (не збережено)",
"rowDuplicatedWithoutSavedYet": "Рядок продубльовано, але не збережено",
"updatedUIACL": "Успішно оновлено UI ACL для таблиць",
"pluginUninstalled": "Плагін успішно видалено",
"pluginSettingsSaved": "Налаштування плагіну успішно збережено",
"pluginSettingsSaved": "Налаштування плагіну збережено",
"pluginTested": "Успішно протестовані налаштування плагіну",
"tableRenamed": "Таблицю успішно перейменовано",
"viewDeleted": "Вигляд успішно видалено",
"viewDeleted": "Вигляд видалено",
"primaryColumnUpdated": "Успішно оновлено як основний стовпець",
"tableDataExported": "Успішно експортовано всі дані таблиці",
"updated": "Успішно оновлено",
"sharedViewDeleted": "Успішно видалено спільний перегляд",
"sharedViewDeleted": "Спільний перегляд видалено",
"userDeleted": "Користувача успішно видалено",
"viewRenamed": "Вигляд успішно перейменовано",
"viewRenamed": "Вигляд перейменовано",
"tokenGenerated": "Токен успішно згенеровано",
"tokenDeleted": "Токен успішно видалено",
"userAddedToProject": "Користувача успішно додано до проєкту",
"userAdded": "Користувача успішно додано",
"userDeletedFromProject": "Користувача успішно видалено з проєкту",
"inviteEmailSent": "Лист запрошення успішно відправлено на електронну пошту",
"inviteURLCopied": "URL запрошення скопійоване в буфер обміну",
"commentCopied": "Коментар скопійовано до буфера обміну",
"userAddedToProject": "Користувача додано до проєкту",
"userAdded": "Користувача додано",
"userDeletedFromProject": "Користувача видалено з проєкту",
"inviteEmailSent": "Лист запрошення відправлено на електронну пошту",
"inviteURLCopied": "URL-посилання для запрошення скопійовано",
"commentCopied": "Коментар скопійовано в буфер обміну",
"passwordResetURLCopied": "URL-адресу скидання пароля скопійовано в буфер обміну",
"shareableURLCopied": "URL адресу спільної бази скопійовано в буфер обміну!",
"shareableURLCopied": "URL-посилання спільної бази скопійовано!",
"embeddableHTMLCodeCopied": "Скопійовано вбудований HTML-код!",
"userDetailsUpdated": "Дані користувача успішно оновлено",
"tableDataImported": "Дані таблиці успішно імпортовано",
"webhookUpdated": "Дані Webhook успішно оновлено",
"webhookDeleted": "Hook успішно видалено",
"userDetailsUpdated": "Дані користувача оновлено",
"tableDataImported": "Дані таблиці імпортовано",
"webhookUpdated": "Дані вебхуку оновлено",
"webhookDeleted": "Вебхук видалено",
"webhookTested": "Webhook успішно протестовано",
"columnUpdated": "Стовпець оновлено",
"columnCreated": "Стовпець створено",

8
packages/nc-gui/lang/zh-Hans.json

@ -238,7 +238,7 @@
"action": "操作",
"actions": "操作",
"operation": "操作",
"operationSub": "Sub Operation",
"operationSub": "子操作",
"operationType": "操作类型",
"operationSubType": "子操作类型",
"description": "描述",
@ -471,11 +471,11 @@
},
"map": {
"mappedBy": "Mapped By",
"chooseMappingField": "Choose a Mapping Field",
"chooseMappingField": "选择映射字段",
"openInGoogleMaps": "谷歌地图",
"openInOpenStreetMap": "OSM"
},
"toggleMobileMode": "Toggle Mobile Mode"
"toggleMobileMode": "切换移动模式"
},
"tooltip": {
"saveChanges": "保存更改",
@ -779,7 +779,7 @@
"userDeletedFromProject": "踢出用户成功",
"inviteEmailSent": "邀请邮件发送成功",
"inviteURLCopied": "邀请URL已复制到剪贴板",
"commentCopied": "Comment copied to clipboard",
"commentCopied": "已复制评论到剪贴板",
"passwordResetURLCopied": "密码重置网址已复制到剪贴板",
"shareableURLCopied": "已将可共享的基础URL复制到剪贴板!",
"embeddableHTMLCodeCopied": "已复制可嵌入的 HTML 代码!",

3
packages/noco-docs/content/en/developer-resources/webhooks.md

@ -28,7 +28,8 @@ Some types of notifications can be triggered by a webhook after a particular eve
- Webhook Conditional Trigger
- Only records meeting the criteria will trigger webhook
![Screenshot 2022-09-14 at 10 35 39 AM](https://user-images.githubusercontent.com/86527202/190064668-37245025-81f6-491c-b639-83c8fd131bc3.png)
<!-- ![Screenshot 2022-09-14 at 10 35 39 AM](https://user-images.githubusercontent.com/86527202/190064668-37245025-81f6-491c-b639-83c8fd131bc3.png) -->
![Screenshot 2023-04-06 at 11 39 49 AM](https://user-images.githubusercontent.com/86527202/230288581-c613e591-1c32-4151-a2d1-df2bbf1367fd.png)
<!-- ![image](https://user-images.githubusercontent.com/35857179/166660248-a3c81a34-4334-48c2-846a-65759d761559.png) -->

55
packages/nocodb/Dockerfile.local

@ -0,0 +1,55 @@
###########
# Builder
###########
FROM node:16.17.0-alpine3.15 as builder
WORKDIR /usr/src/app
# install node-gyp dependencies
RUN apk add --no-cache python3 make g++
# Copy application dependency manifests to the container image.
# A wildcard is used to ensure both package.json AND package-lock.json are copied.
# Copying this separately prevents re-running npm ci on every code change.
COPY ./package*.json ./
COPY ./docker/nc-gui/ ./docker/nc-gui/
COPY ./docker/main.js ./docker/index.js
COPY ./docker/start-local.sh /usr/src/appEntry/start.sh
COPY ./src/lib/public/css/*.css ./docker/public/css/
COPY ./src/lib/public/js/*.js ./docker/public/js/
COPY ./src/lib/public/favicon.ico ./docker/public/
# install production dependencies,
# reduce node_module size with modclean & removing sqlite deps,
# package built code into app.tar.gz & add execute permission to start.sh
RUN npm ci --omit=dev --quiet \
&& npx modclean --patterns="default:*" --ignore="nc-lib-gui/**,dayjs/**,express-status-monitor/**,@azure/msal-node/dist/**" --run \
&& rm -rf ./node_modules/sqlite3/deps \
&& tar -czf ../appEntry/app.tar.gz ./* \
&& chmod +x /usr/src/appEntry/start.sh
##########
# Runner
##########
FROM alpine:3.15
WORKDIR /usr/src/app
ENV NC_DOCKER 0.6
ENV NODE_ENV production
ENV PORT 8080
ENV NC_TOOL_DIR=/usr/app/data/
RUN apk --update --no-cache add \
nodejs \
tar \
dumb-init \
curl \
jq
# Copy packaged production code & main entry file
COPY --from=builder /usr/src/appEntry/ /usr/src/appEntry/
EXPOSE 8080
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
# Start Nocodb
CMD ["/usr/src/appEntry/start.sh"]

14
packages/nocodb/docker/start-local.sh

@ -0,0 +1,14 @@
#!/bin/sh
FILE="/usr/src/app/package.json"
if [ ! -z "${NC_TOOL_DIR}" ]; then
mkdir -p $NC_TOOL_DIR
fi
if [ ! -f "$FILE" ]
then
tar -xzf /usr/src/appEntry/app.tar.gz -C /usr/src/app/
fi
node docker/index.js

23
packages/nocodb/src/lib/db/sql-client/lib/pg/PgClient.ts

@ -474,17 +474,22 @@ class PGClient extends KnexClient {
]);
}
// if (this.connectionConfig.searchPath && this.connectionConfig.searchPath[0]) {
const schemaName = this.connectionConfig.searchPath?.[0] || 'public';
// Check schemaExists because `CREATE SCHEMA IF NOT EXISTS` requires permissions of `CREATE ON DATABASE`
const schemaExists = !!(
await this.sqlClient.raw(
` CREATE SCHEMA IF NOT EXISTS ?? AUTHORIZATION ?? `,
[
(this.connectionConfig.searchPath &&
this.connectionConfig.searchPath[0]) ||
'public',
this.connectionConfig.connection.user,
]
`SELECT schema_name FROM information_schema.schemata WHERE schema_name = ?`,
[schemaName]
)
).rows?.[0];
if (!schemaExists) {
await this.sqlClient.raw(
`CREATE SCHEMA IF NOT EXISTS ?? AUTHORIZATION ?? `,
[schemaName, this.connectionConfig.connection.user]
);
// }
}
// this.sqlClient = knex(this.connectionConfig);
} catch (e) {

2
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts

@ -656,7 +656,7 @@ async function _formulaQueryBuilder(
} else if (pt.type === 'Identifier') {
const { builder } = await aliasToColumn?.[pt.name]?.();
if (typeof builder === 'function') {
return { builder: knex.raw(`??${colAlias}`, await builder(pt.fnName)) };
return { builder: knex.raw(`??${colAlias}`, builder(pt.fnName)) };
}
return { builder: knex.raw(`??${colAlias}`, [builder || pt.name]) };
} else if (pt.type === 'BinaryExpression') {

18
packages/nocodb/src/run/local.ts

@ -0,0 +1,18 @@
import path from 'path';
import cors from 'cors';
import express from 'express';
import Noco from '../lib/Noco';
const server = express();
server.enable('trust proxy');
server.use(cors());
server.use('/dashboard', express.static(path.join(__dirname, 'nc-gui')));
server.set('view engine', 'ejs');
(async () => {
const httpServer = server.listen(process.env.PORT || 8080, () => {
console.log(`App started successfully.\nVisit -> ${Noco.dashboardUrl}`);
});
server.use(await Noco.init({}, httpServer, server));
})().catch((e) => console.log(e));

53
packages/nocodb/webpack.local.config.js

@ -0,0 +1,53 @@
const nodeExternals = require('webpack-node-externals');
const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const path = require('path');
module.exports = {
entry: './src/run/local.ts',
// devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: {
loader: 'ts-loader',
options: {
transpileOnly: true
}
},
},
],
},
optimization: {
minimize: true, //Update this to true or false
minimizer: [new TerserPlugin()],
nodeEnv: false
},
externals: [nodeExternals({
allowlist: ['nocodb-sdk']
})],
resolve: {
extensions: ['.tsx', '.ts', '.js', '.json'],
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'docker'),
library: 'libs',
libraryTarget: 'umd',
globalObject: "typeof self !== 'undefined' ? self : this"
},
node: {
fs: 'empty',
__dirname: false,
},
plugins: [
new webpack.EnvironmentPlugin([
'EE'
]),
],
target: 'node',
};
Loading…
Cancel
Save