Browse Source

Merge branch 'develop' into feat/kanban-view

pull/3563/head
Wing-Kam Wong 2 years ago
parent
commit
fe6b7eb574
  1. 8
      README.md
  2. 34
      packages/nc-gui/assets/style.scss
  3. 2
      packages/nc-gui/components/cell/attachment/Carousel.vue
  4. 6
      packages/nc-gui/components/cell/attachment/Modal.vue
  5. 4
      packages/nc-gui/components/cell/attachment/index.vue
  6. 33
      packages/nc-gui/components/dashboard/TreeView.vue
  7. 2
      packages/nc-gui/components/general/MiniSidebar.vue
  8. 14
      packages/nc-gui/components/general/NocoIcon.vue
  9. 6
      packages/nc-gui/layouts/base.vue
  10. 2
      packages/nc-gui/pages/[projectType]/[projectId]/index.vue
  11. 20
      packages/nc-gui/pages/[projectType]/form/[viewId]/index.vue
  12. 27
      packages/nc-gui/pages/forgot-password.vue
  13. 26
      packages/nc-gui/pages/index/index/[projectId].vue
  14. 2
      packages/nc-gui/pages/index/index/create-external.vue
  15. 24
      packages/nc-gui/pages/index/index/create.vue
  16. 4
      packages/nc-gui/pages/index/index/index.vue
  17. 8
      packages/nc-gui/pages/index/user/index.vue
  18. 27
      packages/nc-gui/pages/signin.vue
  19. 31
      packages/nc-gui/pages/signup/[[token]].vue
  20. 4
      packages/nc-gui/windi.config.ts
  21. 7
      scripts/cypress/integration/common/00_pre_configurations.js
  22. 4
      scripts/cypress/integration/common/1b_table_column_operations.js
  23. 15
      scripts/cypress/integration/common/3c_lookup_column.js
  24. 14
      scripts/cypress/integration/common/3d_rollup_column.js
  25. 8
      scripts/cypress/integration/common/3e_duration_column.js
  26. 27
      scripts/cypress/integration/common/3f_link_to_another_record.js
  27. 9
      scripts/cypress/integration/common/5a_user_role.js
  28. 4
      scripts/cypress/integration/common/9a_QuickTest.js
  29. 31
      scripts/cypress/support/commands.js
  30. 12
      scripts/cypress/support/page_objects/mainPage.js
  31. 22
      scripts/cypress/support/page_objects/navigation.js

8
README.md

@ -1,6 +1,6 @@
<h1 align="center" style="border-bottom: none">
<b>
<a href="https://www.nocodb.com">NocoDB</a><br>
<a href="https://www.nocodb.com"><img src="/packages/nc-gui/public/icon.png" width="80" /><br>NocoDB</a><br>
</b>
The Open Source Airtable Alternative <br>
</h1>
@ -263,6 +263,7 @@ Access Dashboard using : [http://localhost:8080/dashboard](http://localhost:8080
- [Contributing](#contributing)
- [Why are we building this?](#why-are-we-building-this)
- [Our Mission](#our-mission)
- [License](#license)
- [Contributors](#contributors)
# Features
@ -323,6 +324,11 @@ Most internet businesses equip themselves with either spreadsheet or a database
# Our Mission
Our mission is to provide the most powerful no-code interface for databases which is open source to every single internet business in the world. This would not only democratise access to a powerful computing tool but also bring forth a billion+ people who will have radical tinkering-and-building abilities on internet.
# License
<p>
This project is licensed under <a href="./LICENSE">AGPLv3</a>.</p>
<br>
# Contributors
[//]: contributor-faces

34
packages/nc-gui/assets/style.scss

@ -87,7 +87,7 @@ a {
}
// for highlighting toolbar menu item
.nc-active-btn > .ant-btn{
.nc-active-btn > .ant-btn {
@apply bg-primary bg-opacity-20 hover:(bg-primary bg-opacity-20);
}
@ -106,7 +106,7 @@ a {
}
.animated-bg-gradient {
background: linear-gradient(122deg, #6f3381, #81c7d4, #fedfe1, #9ee59e);
background: linear-gradient(122deg, #6f3381, #ec4899, #fedfe1, #4351e8);
background-size: 800% 800%;
-webkit-animation: gradient 4s ease infinite;
@ -174,6 +174,28 @@ a {
transform: translate(-100%, 0);
}
.slide-right-enter-active,
.slide-right-leave-active {
transition: all 400ms ease;
}
.slide-right-enter-from,
.slide-right-leave-to {
transform: translate(100%, 0%);
opacity: 0;
}
.slide-left-enter-active,
.slide-left-leave-active {
transition: all 400ms ease;
}
.slide-left-enter-from,
.slide-left-leave-to {
transform: translate(-100%, 0%);
opacity: 0;
}
.glow-enter-active,
.glow-leave-active {
@apply transition-all duration-300 ease-in-out;
@ -189,10 +211,10 @@ a {
}
.scaling-btn {
@apply z-1 relative color-transition border border-gray-300 rounded-md p-3 bg-gray-100/50 text-white;
@apply z-1 relative color-transition rounded-md px-4 py-2 text-white;
&::after {
@apply rounded-md absolute top-0 left-0 right-0 bottom-0 transition-all duration-150 ease-in-out bg-primary;
@apply ring-opacity-100 ring-[2px] ring-slate-300 rounded absolute top-0 left-0 right-0 bottom-0 transition-all duration-150 ease-in-out bg-primary bg-opacity-100;
content: '';
z-index: -1;
}
@ -239,7 +261,7 @@ a {
}
.ant-dropdown-menu-item, .ant-menu-item {
@apply !py-0 active:(ring ring-accent);
@apply !py-0 active:(ring ring-accent ring-opacity-100);
}
.ant-dropdown-menu-title-content,
@ -247,7 +269,7 @@ a {
@apply !py-0;
}
.ant-dropdown-menu-submenu-title{
.ant-dropdown-menu-submenu-title {
@apply !pr-2;
}

2
packages/nc-gui/components/cell/attachment/Carousel.vue

@ -55,7 +55,7 @@ onClickOutside(carouselRef, () => {
</div>
<div
class="select-none group hover:ring active:ring-accent cursor-pointer leading-8 inline-block px-3 py-1 bg-gray-300 text-white mb-4 text-center rounded shadow"
class="select-none group hover:ring active:ring-accent ring-opactiy-100 cursor-pointer leading-8 inline-block px-3 py-1 bg-gray-300 text-white mb-4 text-center rounded shadow"
@click.stop="downloadFile(selectedImage)"
>
<h3 class="group-hover:text-primary">{{ selectedImage && selectedImage.title }}</h3>

6
packages/nc-gui/components/cell/attachment/Modal.vue

@ -89,7 +89,7 @@ function onClick(item: Record<string, any>) {
<general-overlay
v-model="isOverDropZone"
inline
class="text-white ring ring-accent bg-gray-700/75 flex items-center justify-center gap-2 backdrop-blur-xl"
class="text-white ring ring-accent ring-opacity-100 bg-gray-700/75 flex items-center justify-center gap-2 backdrop-blur-xl"
>
<MaterialSymbolsFileCopyOutline class="text-accent" height="35" width="35" />
<div class="text-white text-3xl">Drop here</div>
@ -161,7 +161,7 @@ function onClick(item: Record<string, any>) {
.nc-attach-file {
@apply select-none cursor-pointer color-transition flex items-center gap-1 border-1 p-2 rounded
@apply hover:(bg-primary bg-opacity-10 text-primary ring);
@apply active:(ring-accent bg-primary bg-opacity-20);
@apply active:(ring-accent ring-opacity-100 bg-primary bg-opacity-20);
}
.nc-attachment-item {
@ -182,7 +182,7 @@ function onClick(item: Record<string, any>) {
}
&:active::after {
@apply ring ring-accent shadow transform scale-103;
@apply ring ring-accent ring-opacity-100 shadow transform scale-103;
}
}
}

4
packages/nc-gui/components/cell/attachment/index.vue

@ -138,7 +138,7 @@ const { isSharedForm } = useSmartsheetStoreOrThrow()
v-model="isOverDropZone"
inline
:target="currentCellRef"
class="text-white text-lg ring ring-accent bg-gray-700/75 flex items-center justify-center gap-2 backdrop-blur-xl"
class="group cursor-pointer flex gap-1 items-center active:(ring ring-accent ring-opacity-100) rounded border-1 p-1 shadow-sm hover:(bg-primary bg-opacity-10) dark:(!bg-slate-500)"
>
<MaterialSymbolsFileCopyOutline class="text-accent" /> Drop here
</general-overlay>
@ -220,7 +220,7 @@ const { isSharedForm } = useSmartsheetStoreOrThrow()
.nc-cell {
.nc-attachment-cell {
.nc-attachment {
@apply w-[50px] h-[50px] min-h-[50px] min-w-[50px];
@apply w-[50px] h-[50px] min-h-[50px] min-w-[50px] ring-1 ring-gray-300 rounded;
}
.ghost,

33
packages/nc-gui/components/dashboard/TreeView.vue

@ -14,6 +14,7 @@ import {
useProject,
useTable,
useTabs,
useToggle,
useUIPermission,
watchEffect,
} from '#imports'
@ -33,6 +34,8 @@ const { deleteTable } = useTable()
const { isUIAllowed } = useUIPermission()
const [searchActive, toggleSearchActive] = useToggle()
const isLocked = inject('TreeViewIsLockedInj')
let key = $ref(0)
@ -126,8 +129,6 @@ const contextMenuTarget = reactive<{ type?: 'table' | 'main'; value?: any }>({})
const setMenuContext = (type: 'table' | 'main', value?: any) => {
contextMenuTarget.type = type
contextMenuTarget.value = value
// $e('c:table:create:navdraw:right-click')
}
const reloadTables = async () => {
@ -215,12 +216,26 @@ function openTableCreateDialog() {
<div class="nc-treeview-container flex flex-col">
<a-dropdown :trigger="['contextmenu']" overlay-class-name="nc-dropdown-tree-view-context-menu">
<div class="pt-2 pl-2 pb-2 flex-1 overflow-y-auto flex flex-col scrollbar-thin-dull" :class="{ 'mb-[20px]': isSharedBase }">
<div class="py-1 px-3 flex w-full items-center gap-1 cursor-pointer" @contextmenu="setMenuContext('main')">
<span class="flex-1 text-bold uppercase nc-project-tree text-gray-500 font-weight-bold">
{{ $t('objects.tables') }}
<template v-if="tables?.length"> ({{ tables.length }}) </template>
</span>
<div class="min-h-[36px] py-1 px-3 flex w-full items-center gap-1 cursor-pointer" @contextmenu="setMenuContext('main')">
<Transition name="slide-left" mode="out-in">
<a-input
v-if="searchActive"
v-model:value="filterQuery"
class="flex-1 rounded"
:placeholder="$t('placeholder.searchProjectTree')"
/>
<span v-else class="flex-1 text-bold uppercase nc-project-tree text-gray-500 font-weight-bold">
{{ $t('objects.tables') }}
<template v-if="tables?.length"> ({{ tables.length }}) </template>
</span>
</Transition>
<Transition name="layout" mode="out-in">
<MdiClose v-if="searchActive" class="text-lg mx-1 mt-0.5" @click="toggleSearchActive(false)" />
<IcRoundSearch v-else class="text-lg text-primary mx-1 mt-0.5" @click="toggleSearchActive(true)" />
</Transition>
</div>
<div class="flex-1">
@ -507,7 +522,7 @@ function openTableCreateDialog() {
}
:deep(.ant-dropdown-menu-item) {
@apply !py-0 active:(ring ring-accent);
@apply !py-0 active:(ring ring-accent ring-opacity-100);
}
:deep(.ant-dropdown-menu-title-content) {

2
packages/nc-gui/components/general/MiniSidebar.vue

@ -78,7 +78,7 @@ const logout = () => {
</span>
</template>
<a-menu-item class="active:(ring ring-accent)">
<a-menu-item class="active:(ring ring-accent ring-opacity-100)">
<div
v-e="['c:project:create:xcdb']"
class="group flex items-center gap-2 py-2 hover:text-primary"

14
packages/nc-gui/components/general/NocoIcon.vue

@ -2,13 +2,21 @@
interface Props {
width?: number
height?: number
animate?: boolean
}
const { width = 90, height = 90 } = defineProps<Props>()
const { width = 90, height = 90, animate = false } = defineProps<Props>()
</script>
<template>
<div :style="{ left: `calc(50% - ${width / 2}px)`, top: `-${height / 2}px` }" class="absolute rounded-lg">
<img :width="width" :height="height" alt="NocoDB" src="~/assets/img/icons/512x512.png" />
<div :style="{ left: `calc(50% - ${width / 2}px)`, top: `-${height / 2}px` }" class="absolute rounded-lg pt-1 pl-1 -ml-1">
<div class="relative">
<img :width="width" :height="height" alt="NocoDB" src="~/assets/img/icons/512x512.png" />
<template v-if="animate">
<div class="animated-bg-gradient opacity-100 rounded-full z-0 absolute bottom-1.45 right-1.45 h-4.5 w-4.5" />
<div class="animate-ping bg-primary bg-opacity-50 rounded-full z-0 absolute bottom-0.9 right-1 h-5.5 w-5.5" />
</template>
</div>
</div>
</template>

6
packages/nc-gui/layouts/base.vue

@ -134,7 +134,7 @@ hooks.hook('page:finish', () => {
<style lang="scss">
.nc-lang-btn {
@apply color-transition flex items-center justify-center fixed bottom-10 right-10 z-99 w-12 h-12 rounded-full shadow-md shadow-gray-500 p-2 !bg-primary text-white active:(ring ring-accent) hover:(ring ring-accent);
@apply color-transition flex items-center justify-center fixed bottom-10 right-10 z-99 w-12 h-12 rounded-full shadow-md shadow-gray-500 p-2 !bg-primary text-white ring-opacity-100 active:(ring ring-accent) hover:(ring ring-accent);
&::after {
@apply rounded-full absolute top-0 left-0 right-0 bottom-0 transition-all duration-150 ease-in-out bg-primary;
@ -143,11 +143,11 @@ hooks.hook('page:finish', () => {
}
&:hover::after {
@apply transform scale-110 ring ring-accent;
@apply transform scale-110 ring ring-accent ring-opacity-100;
}
&:active::after {
@apply ring ring-accent;
@apply ring ring-accent ring-opacity-100;
}
}
</style>

2
packages/nc-gui/pages/[projectType]/[projectId]/index.vue

@ -186,7 +186,7 @@ onBeforeUnmount(reset)
>
<div
style="height: var(--header-height)"
:class="isOpen ? 'pl-6' : ''"
:class="isOpen ? 'pl-4' : ''"
class="flex items-center !bg-primary text-white px-1 gap-2"
>
<div

20
packages/nc-gui/pages/[projectType]/form/[viewId]/index.vue

@ -121,7 +121,7 @@ function isRequired(_columnObj: Record<string, any>, required = false) {
</div>
<div class="text-center my-9">
<button type="submit" class="submit" @click="submitForm">
<button type="submit" class="scaling-btn bg-opacity-100" @click="submitForm">
{{ $t('general.submit') }}
</button>
</div>
@ -162,23 +162,5 @@ function isRequired(_columnObj: Record<string, any>, required = false) {
.nc-input {
@apply w-full rounded p-2 min-h-[40px] flex items-center border-solid border-1 border-primary;
}
.submit {
@apply z-1 relative color-transition rounded p-3 text-white shadow-sm;
&::after {
@apply rounded absolute top-0 left-0 right-0 bottom-0 transition-all duration-150 ease-in-out bg-primary;
content: '';
z-index: -1;
}
&:hover::after {
@apply transform scale-110 ring ring-accent;
}
&:active::after {
@apply ring ring-accent;
}
}
}
</style>

27
packages/nc-gui/pages/forgot-password.vue

@ -55,10 +55,7 @@ function resetError() {
<div
class="bg-white mt-[60px] relative flex flex-col justify-center gap-2 w-full max-w-[500px] mx-auto p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)"
>
<LazyGeneralNocoIcon
class="color-transition hover:(ring ring-accent)"
:class="[isLoading ? 'animated-bg-gradient' : '']"
/>
<LazyGeneralNocoIcon class="color-transition hover:(ring ring-accent ring-opacity-100)" :animate="isLoading" />
<div class="self-center flex flex-col justify-center items-center text-center gap-2">
<h1 class="prose-2xl font-bold my-4 w-full">{{ $t('title.resetPassword') }}</h1>
@ -92,7 +89,7 @@ function resetError() {
</a-form-item>
<div class="self-center flex flex-col gap-4 items-center justify-center w-full">
<button class="submit" type="submit">
<button class="scaling-btn bg-opacity-100" type="submit">
<span class="flex items-center gap-2">
<MdiLogin />
{{ $t('activity.sendEmail') }}
@ -114,25 +111,7 @@ function resetError() {
.forgot-password {
.ant-input-affix-wrapper,
.ant-input {
@apply !appearance-none my-1 border-1 border-solid border-primary/50 rounded;
}
.submit {
@apply z-1 relative color-transition rounded p-3 text-white shadow;
&::after {
@apply rounded absolute top-0 left-0 right-0 bottom-0 transition-all duration-150 ease-in-out bg-primary;
content: '';
z-index: -1;
}
&:hover::after {
@apply transform scale-110 ring ring-accent;
}
&:active::after {
@apply ring ring-accent;
}
@apply !appearance-none my-1 border-1 border-solid border-primary border-opacity-50 rounded;
}
}
</style>

26
packages/nc-gui/pages/index/index/[projectId].vue

@ -19,7 +19,7 @@ useSidebar('nc-left-sidebar', { hasSidebar: false })
const route = useRoute()
const { project, loadProject, updateProject, isLoading } = useProject(route.params.projectId as string)
const { project, loadProject, updateProject, isLoading } = useProject()
await loadProject()
@ -68,7 +68,7 @@ onMounted(async () => {
<div
class="update-project bg-white relative flex-auto flex flex-col justify-center gap-2 p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)"
>
<LazyGeneralNocoIcon class="color-transition hover:(ring ring-accent)" :class="[isLoading ? 'animated-bg-gradient' : '']" />
<LazyGeneralNocoIcon class="color-transition hover:(ring ring-accent)" :animate="isLoading" />
<div
class="color-transition transform group absolute top-5 left-5 text-4xl rounded-full bg-white cursor-pointer"
@ -94,7 +94,7 @@ onMounted(async () => {
</a-form-item>
<div class="text-center">
<button v-e="['a:project:edit:rename']" type="submit" class="submit">
<button v-e="['a:project:edit:rename']" type="submit" class="scaling-btn bg-opacity-100">
<span class="flex items-center gap-2">
<MaterialSymbolsRocketLaunchOutline />
{{ $t('general.edit') }}
@ -109,25 +109,7 @@ onMounted(async () => {
.update-project {
.ant-input-affix-wrapper,
.ant-input {
@apply !appearance-none my-1 border-1 border-solid rounded;
}
.submit {
@apply z-1 relative color-transition rounded p-3 text-white shadow-sm;
&::after {
@apply rounded absolute top-0 left-0 right-0 bottom-0 transition-all duration-150 ease-in-out bg-primary;
content: '';
z-index: -1;
}
&:hover::after {
@apply transform scale-110 ring ring-accent;
}
&:active::after {
@apply ring ring-accent;
}
@apply !appearance-none my-1 border-1 border-solid border-primary border-opacity-50 rounded;
}
}
</style>

2
packages/nc-gui/pages/index/index/create-external.vue

@ -337,7 +337,7 @@ onMounted(async () => {
<div
class="create-external bg-white relative flex flex-col justify-center gap-2 w-full p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)"
>
<LazyGeneralNocoIcon class="color-transition hover:(ring ring-accent)" :class="[isLoading ? 'animated-bg-gradient' : '']" />
<LazyGeneralNocoIcon class="color-transition hover:(ring ring-accent)" :animate="isLoading" />
<div
class="color-transition transform group absolute top-5 left-5 text-4xl rounded-full bg-white cursor-pointer"

24
packages/nc-gui/pages/index/index/create.vue

@ -66,7 +66,7 @@ onMounted(async () => {
<div
class="create bg-white relative flex flex-col justify-center gap-2 w-full p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)"
>
<LazyGeneralNocoIcon class="color-transition hover:(ring ring-accent)" :class="[isLoading ? 'animated-bg-gradient' : '']" />
<LazyGeneralNocoIcon class="color-transition hover:(ring ring-accent)" :animate="isLoading" />
<div
class="color-transition transform group absolute top-5 left-5 text-4xl rounded-full bg-white cursor-pointer"
@ -92,7 +92,7 @@ onMounted(async () => {
</a-form-item>
<div class="text-center">
<button class="submit" type="submit">
<button class="scaling-btn bg-opacity-100" type="submit">
<span class="flex items-center gap-2">
<MaterialSymbolsRocketLaunchOutline />
{{ $t('general.create') }}
@ -107,25 +107,7 @@ onMounted(async () => {
.create {
.ant-input-affix-wrapper,
.ant-input {
@apply !appearance-none my-1 border-1 border-solid rounded;
}
.submit {
@apply z-1 relative color-transition rounded p-3 text-white shadow-sm;
&::after {
@apply rounded absolute top-0 left-0 right-0 bottom-0 transition-all duration-150 ease-in-out bg-primary;
content: '';
z-index: -1;
}
&:hover::after {
@apply transform scale-110 ring ring-accent;
}
&:active::after {
@apply ring ring-accent;
}
@apply !appearance-none my-1 border-1 border-solid border-primary border-opacity-50 rounded;
}
}
</style>

4
packages/nc-gui/pages/index/index/index.vue

@ -273,14 +273,14 @@ onBeforeMount(loadProjects)
<style scoped>
.nc-action-btn {
@apply text-gray-500 group-hover:text-accent active:(ring ring-accent) cursor-pointer p-2 w-[30px] h-[30px] hover:bg-gray-300/50 rounded-full;
@apply text-gray-500 group-hover:text-accent active:(ring ring-accent ring-opacity-100) cursor-pointer p-2 w-[30px] h-[30px] hover:bg-gray-300/50 rounded-full;
}
.nc-new-project-menu {
@apply cursor-pointer z-1 relative color-transition rounded-md px-3 py-2 text-white;
&::after {
@apply rounded-md absolute top-0 left-0 right-0 bottom-0 transition-all duration-150 ease-in-out bg-primary bg-opacity-100;
@apply ring-opacity-100 rounded-md absolute top-0 left-0 right-0 bottom-0 transition-all duration-150 ease-in-out bg-primary bg-opacity-100;
content: '';
z-index: -1;
}

8
packages/nc-gui/pages/index/user/index.vue

@ -111,7 +111,7 @@ const resetError = () => {
</a-form-item>
<div class="flex flex-wrap gap-4 items-center mt-4 md:justify-between w-full">
<button class="submit" type="submit">
<button class="scaling-btn bg-opacity-100" type="submit">
<span class="flex items-center gap-2">
<MdiKeyChange />
{{ $t('activity.changePwd') }}
@ -130,7 +130,7 @@ const resetError = () => {
.ant-input-affix-wrapper,
.ant-input {
@apply !appearance-none my-1 border-1 border-solid border-primary/50 rounded;
@apply !appearance-none my-1 border-1 border-solid border-primary border-opacity-50 rounded;
}
.password {
@ -138,9 +138,5 @@ const resetError = () => {
@apply !border-none;
}
}
.submit {
@apply ml-1 border border-gray-300 rounded-lg p-4 bg-gray-100/50 text-white bg-primary hover:(bg-primary bg-opacity-75);
}
}
</style>

27
packages/nc-gui/pages/signin.vue

@ -67,10 +67,7 @@ function resetError() {
<div
class="bg-white mt-[60px] relative flex flex-col justify-center gap-2 w-full max-w-[500px] mx-auto p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)"
>
<LazyGeneralNocoIcon
class="color-transition hover:(ring ring-accent)"
:class="[isLoading ? 'animated-bg-gradient' : '']"
/>
<LazyGeneralNocoIcon class="color-transition hover:(ring ring-accent ring-opacity-100)" :animate="isLoading" />
<h1 class="prose-2xl font-bold self-center my-4">{{ $t('general.signIn') }}</h1>
@ -105,7 +102,7 @@ function resetError() {
</div>
<div class="self-center flex flex-col flex-wrap gap-4 items-center mt-4 justify-center">
<button class="submit group" type="submit">
<button class="scaling-btn bg-opacity-100" type="submit">
<span class="flex items-center gap-2">
<MdiLogin />
{{ $t('general.signIn') }}
@ -133,7 +130,7 @@ function resetError() {
.signin {
.ant-input-affix-wrapper,
.ant-input {
@apply !appearance-none my-1 border-1 border-solid border-primary/50 rounded;
@apply !appearance-none my-1 border-1 border-solid border-primary border-opacity-50 rounded;
}
.password {
@ -141,23 +138,5 @@ function resetError() {
@apply !border-none !m-0;
}
}
.submit {
@apply z-1 relative color-transition rounded p-3 text-white shadow-sm;
&::after {
@apply rounded absolute top-0 left-0 right-0 bottom-0 transition-all duration-150 ease-in-out bg-primary;
content: '';
z-index: -1;
}
&:hover::after {
@apply transform scale-110 ring ring-accent;
}
&:active::after {
@apply ring ring-accent;
}
}
}
</style>

31
packages/nc-gui/pages/signup/[[token]].vue

@ -85,10 +85,7 @@ function resetError() {
<div
class="bg-white mt-[60px] relative flex flex-col justify-center gap-2 w-full max-w-[500px] mx-auto p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)"
>
<LazyGeneralNocoIcon
class="color-transition hover:(ring ring-accent)"
:class="[isLoading ? 'animated-bg-gradient' : '']"
/>
<LazyGeneralNocoIcon class="color-transition hover:(ring ring-accent) hover:(ring ring-accent ring-opacity-100)" :animate="isLoading" />
<h1 class="prose-2xl font-bold self-center my-4">
{{ $t('general.signUp') }}
@ -125,7 +122,7 @@ function resetError() {
</a-form-item>
<div class="self-center flex flex-col flex-wrap gap-4 items-center mt-4">
<button class="submit" type="submit">
<button class="scaling-btn bg-opacity-100" type="submit">
<span class="flex items-center gap-2">
<MaterialSymbolsRocketLaunchOutline />
@ -136,7 +133,7 @@ function resetError() {
<a
v-if="appInfo.googleAuthEnabled"
:href="`${api.instance.defaults.baseURL}/auth/google`"
class="submit after:(!bg-white) !text-primary border-1 border-primary !no-underline"
class="scaling-btn bg-opacity-100 after:(!bg-white) !text-primary !no-underline"
>
<span class="flex items-center gap-2">
<LogosGoogleGmail />
@ -149,7 +146,7 @@ function resetError() {
<a-switch
v-model:checked="subscribe"
size="small"
class="my-1 hover:(ring ring-accent) focus:(!ring !ring-accent)"
class="my-1 hover:(ring ring-accent ring-opacity-100) focus:(!ring !ring-accent ring-opacity-100)"
/>
<div class="prose-xs text-gray-500">Subscribe to our weekly newsletter</div>
</div>
@ -175,7 +172,7 @@ function resetError() {
.signup {
.ant-input-affix-wrapper,
.ant-input {
@apply !appearance-none my-1 border-1 border-solid border-primary/50 rounded;
@apply !appearance-none my-1 border-1 border-solid border-primary border-opacity-50 rounded;
}
.password {
@ -183,23 +180,5 @@ function resetError() {
@apply !border-none !m-0;
}
}
.submit {
@apply z-1 relative color-transition rounded p-3 text-white shadow;
&::after {
@apply rounded absolute top-0 left-0 right-0 bottom-0 transition-all duration-150 ease-in-out bg-primary;
content: '';
z-index: -1;
}
&:hover::after {
@apply transform scale-110 ring ring-accent;
}
&:active::after {
@apply ring ring-accent;
}
}
}
</style>

4
packages/nc-gui/windi.config.ts

@ -65,6 +65,10 @@ export default defineConfig({
primary: 'rgba(var(--color-primary), var(--tw-bg-opacity))',
accent: 'rgba(var(--color-accent), var(--tw-bg-opacity))',
},
ringColor: {
primary: 'rgba(var(--color-primary), var(--tw-ring-opacity))',
accent: 'rgba(var(--color-accent), var(--tw-ring-opacity))',
},
colors: {
...windiColors,
...themeColors,

7
scripts/cypress/integration/common/00_pre_configurations.js

@ -243,12 +243,7 @@ export const genTest = (apiType, dbType) => {
// wait for tab to be rendered completely
cy.wait(2000);
cy.getSettled("button.ant-tabs-tab-remove")
.should("be.visible")
.click();
cy.get("button.ant-tabs-tab-remove").should("not.exist");
cy.wait(2000);
cy.closeTableTab();
// first instance of updating local storage information
cy.saveLocalStorage();

4
scripts/cypress/integration/common/1b_table_column_operations.js

@ -75,9 +75,7 @@ export const genTest = (apiType, dbType) => {
.find(".nc-column-edit")
.click();
// fix me! wait till the modal rendering (input highlight) is completed
// focus shifts back to the input field to select text after the dropdown is rendered
cy.wait(500);
cy.inputHighlightRenderWait();
// change column type and verify
// cy.get(".nc-column-type-input").last().click();

15
scripts/cypress/integration/common/3c_lookup_column.js

@ -11,18 +11,7 @@ export const genTest = (apiType, dbType) => {
cy.get("label").contains(label).parents(".ant-row").click();
};
// Run once before test- create project (rest/graphql)
//
// before(() => {
// cy.fileHook();
// mainPage.tabReset();
// // open a table to work on views
// //
//
// // // close team & auth tab
// // cy.get('button.ant-tabs-tab-remove').should('exist').click();
//
// cy.openTableTab("City", 25);
// });
beforeEach(() => {
@ -60,9 +49,7 @@ export const genTest = (apiType, dbType) => {
.contains("Lookup")
.click();
// fix me! wait till the modal rendering (input highlight) is completed
// focus shifts back to the input field to select text after the dropdown is rendered
cy.wait(500);
cy.inputHighlightRenderWait();
// Configure Child table & column names
fetchParentFromLabel("Child table");

14
scripts/cypress/integration/common/3d_rollup_column.js

@ -11,17 +11,7 @@ export const genTest = (apiType, dbType) => {
cy.get("label").contains(label).parents(".ant-row").click();
};
// Run once before test- create project (rest/graphql)
//
// before(() => {
// cy.fileHook();
// mainPage.tabReset();
//
// // // close team & auth tab
// // cy.get('button.ant-tabs-tab-remove').should('exist').click();
// // open a table to work on views
// //
// cy.openTableTab("Country", 25);
// });
beforeEach(() => {
@ -64,9 +54,7 @@ export const genTest = (apiType, dbType) => {
.contains("Rollup")
.click();
// fix me! wait till the modal rendering (input highlight) is completed
// focus shifts back to the input field to select text after the dropdown is rendered
cy.wait(500);
cy.inputHighlightRenderWait();
// Configure Child table & column names
fetchParentFromLabel("Child table");

8
scripts/cypress/integration/common/3e_duration_column.js

@ -57,9 +57,7 @@ export const genTest = (apiType, dbType) => {
.contains("Duration")
.click();
// fix me! wait till the modal rendering (input highlight) is completed
// focus shifts back to the input field to select text after the dropdown is rendered
cy.wait(500);
cy.inputHighlightRenderWait();
// Configure Duration format
fetchParentFromLabel("Duration Format");
@ -101,9 +99,7 @@ export const genTest = (apiType, dbType) => {
.clear()
.type(newName);
// fix me! wait till the modal rendering (input highlight) is completed
// focus shifts back to the input field to select text after the dropdown is rendered
cy.wait(500);
cy.inputHighlightRenderWait();
// Configure Duration format
fetchParentFromLabel("Duration Format");

27
scripts/cypress/integration/common/3f_link_to_another_record.js

@ -6,7 +6,7 @@ export const genTest = (apiType, dbType) => {
if (!isTestSuiteActive(apiType, dbType)) return;
// tbd: this needs a proper fix
let waitTime = 2000;
let waitTime = 0;
let clear;
describe(`${apiType.toUpperCase()} api - Link to another record`, () => {
@ -185,7 +185,6 @@ export const genTest = (apiType, dbType) => {
// Click on `Add new row` button
cy.get(".nc-add-new-row-btn:visible").should("exist");
cy.get(".nc-add-new-row-btn").click();
cy.wait(waitTime);
// Title
cy.get(".nc-expand-col-Title")
@ -205,32 +204,26 @@ export const genTest = (apiType, dbType) => {
.find(".nc-action-icon")
.should("exist")
.click({ force: true });
cy.wait(waitTime);
cy.wait("@waitForCardLoad");
cy.getActiveModal(".nc-modal-link-record")
.find(".ant-card")
.should("exist")
.eq(0)
.click();
cy.wait(waitTime);
// MM
cy.get(".nc-expand-col-Sheet1.List").find(".ant-btn-primary").click();
cy.wait(waitTime);
cy.wait("@waitForCardLoad");
cy.getActiveModal(".nc-modal-link-record")
.find(".ant-card")
.should("exist")
.eq(0)
.click();
cy.wait(waitTime);
// HM
cy.get(".nc-expand-col-Link2-1hm").find(".ant-btn-primary").click();
cy.wait(waitTime);
cy.wait("@waitForCardLoad");
cy.getActiveModal().find(".ant-card").should("exist").eq(0).click();
cy.wait(waitTime);
// Save row
cy.getActiveDrawer(".nc-drawer-expanded-form")
@ -256,13 +249,11 @@ export const genTest = (apiType, dbType) => {
.getCell("Sheet1", 2)
.find(".nc-action-icon")
.click({ force: true });
cy.wait(waitTime);
cy.getActiveModal(".nc-modal-link-record")
.find(".ant-card")
.should("exist")
.eq(1)
.click();
cy.wait(waitTime);
// MM
mainPage
@ -270,13 +261,11 @@ export const genTest = (apiType, dbType) => {
.find(".nc-action-icon")
.last()
.click({ force: true });
cy.wait(waitTime);
cy.getActiveModal(".nc-modal-link-record")
.find(".ant-card")
.should("exist")
.eq(1)
.click();
cy.wait(waitTime);
// HM
mainPage
@ -284,13 +273,11 @@ export const genTest = (apiType, dbType) => {
.find(".nc-action-icon")
.last()
.click({ force: true });
cy.wait(waitTime);
cy.getActiveModal(".nc-modal-link-record")
.find(".ant-card")
.should("exist")
.eq(1)
.click();
cy.wait(waitTime);
});
// Existing row, expand record
@ -300,49 +287,37 @@ export const genTest = (apiType, dbType) => {
addRow(3, "2c");
cy.wait(waitTime);
cy.get(".nc-row-expand").eq(2).click({ force: true });
cy.wait(waitTime);
// wait for page render to complete
cy.get('button:contains("Save row"):visible').should("exist");
// BT
cy.wait(waitTime);
cy.get(".nc-expand-col-Sheet1")
.find(".nc-action-icon")
.should("exist")
.click({ force: true });
cy.wait(waitTime);
// cy.wait("@waitForCardLoad");
cy.getActiveModal(".nc-modal-link-record")
.find(".ant-card")
.should("exist")
.eq(2)
.click();
cy.wait(waitTime);
// MM
cy.get(".nc-expand-col-Sheet1.List").find(".ant-btn-primary").click();
cy.wait(waitTime);
// cy.wait("@waitForCardLoad");
cy.getActiveModal(".nc-modal-link-record")
.find(".ant-card")
.should("exist")
.eq(2)
.click();
cy.wait(waitTime);
// HM
cy.get(".nc-expand-col-Link2-1hm").find(".ant-btn-primary").click();
cy.wait(waitTime);
// cy.wait("@waitForCardLoad");
cy.getActiveModal(".nc-modal-link-record")
.find(".ant-card")
.should("exist")
.eq(2)
.click();
cy.wait(waitTime);
cy.getActiveDrawer(".nc-drawer-expanded-form")
.find("button")

9
scripts/cypress/integration/common/5a_user_role.js

@ -145,14 +145,7 @@ export const genTest = (apiType, dbType) => {
}
if (roleType === "creator") {
// kludge: wait for page load to finish
// close team & auth tab
// cy.wait(500);
// cy.get("button.ant-tabs-tab-remove").should("exist").click();
cy.getSettled("button.ant-tabs-tab-remove")
.should("be.visible")
.click();
cy.wait(2000);
cy.closeTableTab();
}
cy.saveLocalStorage();

4
scripts/cypress/integration/common/9a_QuickTest.js

@ -113,9 +113,7 @@ export const genTest = (apiType, dbType, testMode) => {
// kludge: wait for page load to finish
cy.wait(2000);
// close team & auth tab
cy.get("button.ant-tabs-tab-remove").should("exist").click();
cy.wait(2000);
cy.closeTableTab();
} else {
cy.restoreLocalStorage();
}

31
scripts/cypress/support/commands.js

@ -189,17 +189,24 @@ Cypress.Commands.add("openTableTab", (tn, rc) => {
Cypress.Commands.add("closeTableTab", (tn) => {
cy.task("log", `[closeTableTab] ${tn}`);
cy.get(".ant-tabs-tab-btn")
.contains(tn)
.should("exist")
.parent()
.parent()
.parent()
.find("button")
.click();
if (tn) {
// request to close specific tab
cy.get(".ant-tabs-tab-btn")
.contains(tn)
.should("exist")
.parent()
.parent()
.parent()
.find("button")
.click();
} else {
// lone tab active; close it
cy.getSettled("button.ant-tabs-tab-remove").should("be.visible").click();
cy.get("button.ant-tabs-tab-remove").should("not.exist");
}
// subsequent tab open commands will fail if tab is not closed completely
cy.wait(2000)
cy.wait(2000);
});
Cypress.Commands.add("openOrCreateGqlProject", (_args) => {
@ -403,6 +410,12 @@ Cypress.Commands.add("toastWait", (msg) => {
);
});
Cypress.Commands.add("inputHighlightRenderWait", (selector) => {
// fix me! wait till the modal rendering (input highlight) is completed
// focus shifts back to the input field to select text after the dropdown is rendered
cy.wait(500);
});
// vn: view name
// rc: expected row count. validate row count if rc!=0
Cypress.Commands.add("openViewsTab", (vn, rc) => {

12
scripts/cypress/support/page_objects/mainPage.js

@ -654,17 +654,7 @@ export class _mainPage {
});
}
tabReset() {
// temporary disable (kludge)
// mainPage.toolBarTopLeft(mainPage.HOME).click({ force: true });
// cy.get(".project-row").should("exist").click({ force: true });
// projectsPage.waitHomePageLoad();
// option-2
// cy.openTableTab("Country", 0);
// cy.get(".mdi-close").click({ multiple: true });
// cy.get("button.ant-tabs-tab-remove").click({ multiple: true });
// cy.get('.ant-tabs-tab-remove').should('not.exist')
}
tabReset() {}
toggleRightSidebar() {
cy.get(".nc-toggle-right-navbar").should("exist").click();

22
scripts/cypress/support/page_objects/navigation.js

@ -70,16 +70,6 @@ export class _loginPage {
loginAndOpenProject(apiType, dbType) {
loginPage.signIn(roles.owner.credentials);
projectsPage.openConfiguredProject(apiType, dbType);
// if (dbType === "mysql") {
// projectsPage.openProject(staticProjects.externalREST.basic.name);
// } else if (dbType === "xcdb") {
// projectsPage.openProject(staticProjects.sampleREST.basic.name);
// } else if (dbType === "postgres") {
// projectsPage.openProject(staticProjects.pgExternalREST.basic.name);
// }
//
// // close team & auth tab
// cy.get('button.ant-tabs-tab-remove').should('exist').click();
}
}
@ -108,9 +98,7 @@ export class _projectsPage {
cy.wait("@waitForPageLoad");
// close team & auth tab
cy.getSettled("button.ant-tabs-tab-remove").should("be.visible").click();
cy.get("button.ant-tabs-tab-remove").should("not.exist");
cy.wait(2000);
cy.closeTableTab();
}
// Open existing project
@ -151,9 +139,7 @@ export class _projectsPage {
cy.get(".nc-metadb-project-name").should("exist");
cy.contains("button", "Create").should("exist");
// fix me! wait till the modal rendering (input highlight) is completed
// focus shifts back to the input field to select text after the dropdown is rendered
cy.wait(1000);
cy.inputHighlightRenderWait();
// feed project name
cy.get(".nc-metadb-project-name", { timeout: 20000 })
@ -183,9 +169,7 @@ export class _projectsPage {
cy.get(".nc-extdb-proj-name").should("exist");
cy.get(".nc-extdb-btn-test-connection").should("exist");
// fix me! wait till the modal rendering (input highlight) is completed
// focus shifts back to the input field to select text after the dropdown is rendered
cy.wait(1000);
cy.inputHighlightRenderWait();
cy.get(".nc-extdb-proj-name").clear().type(projectName);

Loading…
Cancel
Save