diff --git a/.github/workflows/bats-test.yml b/.github/workflows/bats-test.yml new file mode 100644 index 0000000000..49e26b6e6b --- /dev/null +++ b/.github/workflows/bats-test.yml @@ -0,0 +1,55 @@ +name: Run BATS Tests + +on: + push: + paths: + - 'docker-compose/setup-script/noco.sh' + workflow_dispatch: + +jobs: + prepare: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install jq + run: | + sudo apt-get update + sudo apt-get install -y jq + + - name: Prepare matrix for test files + id: set-matrix + run: | + BATS_FILES=$(find docker-compose/setup-script/tests -name '*.bats') + MATRIX_JSON=$(echo $BATS_FILES | jq -Rsc 'split("\n") | map(select(. != ""))') + echo "matrix=$MATRIX_JSON" >> $GITHUB_ENV + + test: + needs: prepare + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + test: ${{fromJson(env.matrix)}} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install BATS + run: | + sudo apt-get update + sudo apt-get install -y bats expect + + - name: Get working directory + run: | + WORKING_DIR="$(pwd)/docker-compose/setup-script/tests" + echo "WORKING_DIR=$WORKING_DIR" >> $GITHUB_ENV + + - name: Run BATS test + run: bats ${{ matrix.test }} + env: + WORKING_DIR: ${{ env.WORKING_DIR }} + SKIP_TARE_DOWN: true diff --git a/docker-compose/setup-script/noco.sh b/docker-compose/setup-script/noco.sh index bcca10ace2..8f4855d6f3 100755 --- a/docker-compose/setup-script/noco.sh +++ b/docker-compose/setup-script/noco.sh @@ -167,8 +167,8 @@ stop_service() { show_logs_sub_menu() { clear echo "Select a replica for $1:" - for i in $(seq 1 "$2"); do - echo "$i. $1 replica $i" + for i in $(seq 1 $2); do + echo "$i. \"$1\" replica $i" done echo "A. All" echo "0. Back to Logs Menu" diff --git a/docker-compose/setup-script/tests/configure/monitor.bats b/docker-compose/setup-script/tests/configure/monitor.bats index 91a587f44c..b2e5ee739e 100755 --- a/docker-compose/setup-script/tests/configure/monitor.bats +++ b/docker-compose/setup-script/tests/configure/monitor.bats @@ -11,8 +11,12 @@ setup() { } teardown() { - cd "${WORKING_DIR}/configure" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Properly runs monitor script" { diff --git a/docker-compose/setup-script/tests/configure/restart.bats b/docker-compose/setup-script/tests/configure/restart.bats index 46787cdb7b..8e3082c67e 100755 --- a/docker-compose/setup-script/tests/configure/restart.bats +++ b/docker-compose/setup-script/tests/configure/restart.bats @@ -11,8 +11,12 @@ setup() { } teardown() { - cd "${WORKING_DIR}/configure" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Check all containers are restarted" { diff --git a/docker-compose/setup-script/tests/configure/scale.bats b/docker-compose/setup-script/tests/configure/scale.bats index 97f2393e1d..d3adb5e638 100755 --- a/docker-compose/setup-script/tests/configure/scale.bats +++ b/docker-compose/setup-script/tests/configure/scale.bats @@ -11,8 +11,12 @@ setup() { } teardown() { - cd "${WORKING_DIR}/configure" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Check NocoDB is scaled to 3 instances" { diff --git a/docker-compose/setup-script/tests/configure/start.bats b/docker-compose/setup-script/tests/configure/start.bats index 1496415521..0a1dce9414 100755 --- a/docker-compose/setup-script/tests/configure/start.bats +++ b/docker-compose/setup-script/tests/configure/start.bats @@ -11,8 +11,12 @@ setup() { } teardown() { - cd "${WORKING_DIR}/configure" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Check all containers are up" { diff --git a/docker-compose/setup-script/tests/configure/stop.bats b/docker-compose/setup-script/tests/configure/stop.bats index 043866edc1..9879a22090 100755 --- a/docker-compose/setup-script/tests/configure/stop.bats +++ b/docker-compose/setup-script/tests/configure/stop.bats @@ -11,8 +11,12 @@ setup() { } teardown() { - cd "${WORKING_DIR}/configure" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Check all containers are down" { diff --git a/docker-compose/setup-script/tests/configure/upgrade.bats b/docker-compose/setup-script/tests/configure/upgrade.bats index 3fecea5192..4092a9c148 100755 --- a/docker-compose/setup-script/tests/configure/upgrade.bats +++ b/docker-compose/setup-script/tests/configure/upgrade.bats @@ -11,8 +11,12 @@ setup() { } teardown() { - cd "${WORKING_DIR}/configure" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Check all containers are upgraded" { diff --git a/docker-compose/setup-script/tests/install/default.bats b/docker-compose/setup-script/tests/install/default.bats index dfa5216bb0..a50b6d1825 100755 --- a/docker-compose/setup-script/tests/install/default.bats +++ b/docker-compose/setup-script/tests/install/default.bats @@ -6,13 +6,17 @@ export NOCO_HOME setup() { - cd "${WORKING_DIR}/install" || exit 1 - ./setup.sh + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } teardown() { - cd "${WORKING_DIR}/install" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Check installation with all default options" { diff --git a/docker-compose/setup-script/tests/install/ip.bats b/docker-compose/setup-script/tests/install/ip.bats index 530966978e..b99d72f802 100755 --- a/docker-compose/setup-script/tests/install/ip.bats +++ b/docker-compose/setup-script/tests/install/ip.bats @@ -11,8 +11,12 @@ setup() { } teardown() { - cd "${WORKING_DIR}/install" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Check installation with custom ip" { diff --git a/docker-compose/setup-script/tests/install/redis.bats b/docker-compose/setup-script/tests/install/redis.bats index 7320e8d3e3..f604df64db 100755 --- a/docker-compose/setup-script/tests/install/redis.bats +++ b/docker-compose/setup-script/tests/install/redis.bats @@ -11,8 +11,12 @@ setup() { } teardown() { - cd "${WORKING_DIR}/install" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Check Redis is enabled when specified" { diff --git a/docker-compose/setup-script/tests/install/scale.bats b/docker-compose/setup-script/tests/install/scale.bats index cf91362299..b98b7b7ed8 100755 --- a/docker-compose/setup-script/tests/install/scale.bats +++ b/docker-compose/setup-script/tests/install/scale.bats @@ -11,8 +11,12 @@ setup() { } teardown() { - cd "${WORKING_DIR}/install" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Check if two instances of NoCoDB can be run" { diff --git a/docker-compose/setup-script/tests/install/ssl.bats b/docker-compose/setup-script/tests/install/ssl.bats index 1d44344072..705120b7af 100644 --- a/docker-compose/setup-script/tests/install/ssl.bats +++ b/docker-compose/setup-script/tests/install/ssl.bats @@ -10,8 +10,12 @@ setup() { } teardown() { - cd "${WORKING_DIR}/install" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Should create SSL certificates" { diff --git a/docker-compose/setup-script/tests/install/watchtower.bats b/docker-compose/setup-script/tests/install/watchtower.bats index b0e485aa51..67f5dfddd6 100755 --- a/docker-compose/setup-script/tests/install/watchtower.bats +++ b/docker-compose/setup-script/tests/install/watchtower.bats @@ -9,8 +9,12 @@ setup() { } teardown() { - cd "${WORKING_DIR}/install" || exit 1 - ./setup.sh + if [ -n "$SKIP_TEARDOWN" ]; then + return + fi + + cd "${WORKING_DIR}/install" || exit 1 + ./setup.sh } @test "Check WatchTower is enabled when specified" { diff --git a/packages/nc-gui/assets/nc-icons/arrow-up-right.svg b/packages/nc-gui/assets/nc-icons/arrow-up-right.svg new file mode 100644 index 0000000000..b0b9d3026b --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/arrow-up-right.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/nc-gui/assets/nc-icons/control-panel.svg b/packages/nc-gui/assets/nc-icons/control-panel.svg new file mode 100644 index 0000000000..c566e17b96 --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/control-panel.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/nc-gui/assets/nc-icons/home.svg b/packages/nc-gui/assets/nc-icons/home.svg new file mode 100644 index 0000000000..fe8bdeb742 --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/home.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/nc-gui/assets/nc-icons/office.svg b/packages/nc-gui/assets/nc-icons/office.svg new file mode 100644 index 0000000000..b2b313eaf4 --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/office.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/packages/nc-gui/assets/nc-icons/slash.svg b/packages/nc-gui/assets/nc-icons/slash.svg new file mode 100644 index 0000000000..8e7e27899e --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/slash.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packages/nc-gui/assets/nc-icons/workspace.svg b/packages/nc-gui/assets/nc-icons/workspace.svg new file mode 100644 index 0000000000..52c0757116 --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/workspace.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/nc-gui/components.d.ts b/packages/nc-gui/components.d.ts index 0b40fd5fd3..9f38e62348 100644 --- a/packages/nc-gui/components.d.ts +++ b/packages/nc-gui/components.d.ts @@ -52,6 +52,7 @@ declare module 'vue' { ARadio: typeof import('ant-design-vue/es')['Radio'] ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup'] ARate: typeof import('ant-design-vue/es')['Rate'] + AResult: typeof import('ant-design-vue/es')['Result'] ARow: typeof import('ant-design-vue/es')['Row'] ASelect: typeof import('ant-design-vue/es')['Select'] ASelectOption: typeof import('ant-design-vue/es')['SelectOption'] diff --git a/packages/nc-gui/components/account/HeaderWithSorter.vue b/packages/nc-gui/components/account/HeaderWithSorter.vue new file mode 100644 index 0000000000..c3660259ca --- /dev/null +++ b/packages/nc-gui/components/account/HeaderWithSorter.vue @@ -0,0 +1,32 @@ + + + diff --git a/packages/nc-gui/components/account/UserList.vue b/packages/nc-gui/components/account/UserList.vue index 87458a8467..bf94e14ab2 100644 --- a/packages/nc-gui/components/account/UserList.vue +++ b/packages/nc-gui/components/account/UserList.vue @@ -28,7 +28,7 @@ const { user: loggedInUser } = useGlobal() const { copy } = useCopy() -const { sorts, sortDirection, loadSorts, saveOrUpdate, handleGetSortedData } = useUserSorts('Org') +const { sorts, loadSorts, handleGetSortedData, toggleSort } = useUserSorts('Org') const users = ref([]) @@ -198,21 +198,22 @@ const openDeleteModal = (user: UserType) => {
-
- - {{ $t('objects.users') }} - - -
-
- - {{ $t('general.access') }} - - -
+ + + +
{{ $t('labels.action') }}
diff --git a/packages/nc-gui/components/account/UserMenu.vue b/packages/nc-gui/components/account/UserMenu.vue deleted file mode 100644 index 7fb5e180aa..0000000000 --- a/packages/nc-gui/components/account/UserMenu.vue +++ /dev/null @@ -1,79 +0,0 @@ - - - - - diff --git a/packages/nc-gui/components/cell/Email.vue b/packages/nc-gui/components/cell/Email.vue index 65ec91122e..d8831e794d 100644 --- a/packages/nc-gui/components/cell/Email.vue +++ b/packages/nc-gui/components/cell/Email.vue @@ -109,7 +109,7 @@ watch( { if (!n) searchVal.value = '' if (editAllowed.value) { - if (n) { + if (!n) { + aselect.value?.$el?.querySelector('input')?.blur() + } else { aselect.value?.$el?.querySelector('input')?.focus() } } diff --git a/packages/nc-gui/components/cell/Rating.vue b/packages/nc-gui/components/cell/Rating.vue index c189173351..bcc8d5114f 100644 --- a/packages/nc-gui/components/cell/Rating.vue +++ b/packages/nc-gui/components/cell/Rating.vue @@ -22,6 +22,8 @@ const column = inject(ColumnInj)! const readOnly = inject(ReadonlyInj, ref(false)) +const rowHeight = inject(RowHeightInj, ref(undefined)) + const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))! const ratingMeta = computed(() => { @@ -78,7 +80,15 @@ watch(rateDomRef, () => { :disabled="readOnly" :count="ratingMeta.max" :class="readOnly ? 'pointer-events-none' : ''" - :style="`color: ${ratingMeta.color}; padding: ${isExpandedFormOpen ? '0px 8px' : '0px 2px'};`" + :style="{ + 'color': ratingMeta.color, + 'padding': isExpandedFormOpen ? '0px 8px' : '0px 2px', + 'display': '-webkit-box', + 'max-width': '100%', + '-webkit-line-clamp': rowHeightTruncateLines(rowHeight), + '-webkit-box-orient': 'vertical', + 'overflow': 'hidden', + }" @keydown="onKeyPress" > diff --git a/packages/nc-gui/components/dashboard/TreeView/TableNode.vue b/packages/nc-gui/components/dashboard/TreeView/TableNode.vue index fe0101ed6a..d4717025c6 100644 --- a/packages/nc-gui/components/dashboard/TreeView/TableNode.vue +++ b/packages/nc-gui/components/dashboard/TreeView/TableNode.vue @@ -395,9 +395,9 @@ const deleteTable = () => { @click.stop="onExpand" >
diff --git a/packages/nc-gui/components/dashboard/settings/DataSources.vue b/packages/nc-gui/components/dashboard/settings/DataSources.vue index 400d29a878..96ef06ed9a 100644 --- a/packages/nc-gui/components/dashboard/settings/DataSources.vue +++ b/packages/nc-gui/components/dashboard/settings/DataSources.vue @@ -290,11 +290,11 @@ const isEditBaseModalOpen = computed({