Browse Source

Merge pull request #5116 from nocodb/refactor/expanded-form

refactor(gui): Expanded form header changes
pull/5129/head
Raju Udava 2 years ago committed by GitHub
parent
commit
43d5bcd6ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      packages/nc-gui/assets/style.scss
  2. 1
      packages/nc-gui/components.d.ts
  3. 102
      packages/nc-gui/components/smartsheet/expanded-form/Header.vue
  4. 35
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  5. 3
      packages/nc-gui/composables/useExpandedFormStore.ts
  6. 24
      tests/playwright/pages/Dashboard/ExpandedForm/index.ts
  7. 4
      tests/playwright/tests/expandedFormUrl.spec.ts

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

@ -318,3 +318,14 @@ a {
white-space: pre;
user-select: auto;
}
.nc-drawer-expanded-form .ant-drawer-content-wrapper {
transition: width 0.3s !important;
}
.nc-icon-transition {
@apply transform transition-transform !hover:(scale-115) !active:(scale-100)
}

1
packages/nc-gui/components.d.ts vendored

@ -204,6 +204,7 @@ declare module '@vue/runtime-core' {
MdiLogout: typeof import('~icons/mdi/logout')['default']
MdiMagnify: typeof import('~icons/mdi/magnify')['default']
MdiMenu: typeof import('~icons/mdi/menu')['default']
MdiMenuArrowDown: typeof import('~icons/mdi/menu-arrow-down')['default']
MdiMenuDown: typeof import('~icons/mdi/menu-down')['default']
MdiMicrosoftTeams: typeof import('~icons/mdi/microsoft-teams')['default']
MdiMinusCircleOutline: typeof import('~icons/mdi/minus-circle-outline')['default']

102
packages/nc-gui/components/smartsheet/expanded-form/Header.vue

@ -108,7 +108,11 @@ const onConfirmDeleteRowClick = async () => {
<template #title>
<div class="text-center w-full">{{ $t('general.reload') }}</div>
</template>
<mdi-reload v-if="!isNew" class="cursor-pointer select-none text-gray-500 mx-1 min-w-4" @click="loadRow" />
<mdi-reload
v-if="!isNew"
class="nc-icon-transition cursor-pointer select-none text-gray-500 mx-1 min-w-4"
@click="loadRow"
/>
</a-tooltip>
<a-tooltip placement="bottom">
<template #title>
@ -117,7 +121,7 @@ const onConfirmDeleteRowClick = async () => {
</template>
<mdi-link
v-if="!isNew"
class="cursor-pointer select-none text-gray-500 mx-1 nc-copy-row-url min-w-4"
class="nc-icon-transition cursor-pointer select-none text-gray-500 mx-1 nc-copy-row-url min-w-4"
@click="copyRecordUrl"
/>
</a-tooltip>
@ -130,61 +134,40 @@ const onConfirmDeleteRowClick = async () => {
<MdiCommentTextOutline
v-if="isUIAllowed('rowComments') && !isNew"
v-e="['c:row-expand:comment-toggle']"
class="cursor-pointer select-none nc-toggle-comments text-gray-500 mx-1 min-w-4"
class="nc-icon-transition cursor-pointer select-none nc-toggle-comments text-gray-500 mx-1 min-w-4"
@click="commentsDrawer = !commentsDrawer"
/>
</a-tooltip>
<a-button class="!text mx-1 nc-expand-form-close-btn" @click="emit('cancel')">
<div class="flex items-center">
<MdiCloseCircleOutline class="mr-1" />
<!-- Close -->
{{ $t('general.close') }}
</div>
</a-button>
<a-dropdown>
<a-button v-e="['c:actions']" class="nc-actions-menu-btn nc-toolbar-btn">
<div class="flex gap-1 items-center">
<!-- More -->
<span class="!text-sm font-weight-medium">{{ $t('general.more') }}</span>
<MdiMenuDown class="text-grey" />
</div>
</a-button>
<template #overlay>
<div class="bg-gray-50 py-2 shadow-lg !border">
<div>
<div
v-e="['a:actions:duplicate-row']"
class="nc-menu-item"
:class="{ disabled: isNew }"
@click="!isNew && emit('duplicateRow')"
>
<MdiContentCopy class="text-gray-500" />
{{ $t('activity.duplicateRow') }}
</div>
<a-tooltip v-if="!isSqlView" placement="bottom">
<!-- Duplicate row -->
<template #title>
<div class="text-center w-full">{{ $t('activity.duplicateRow') }}</div>
</template>
<MdiContentCopy
v-if="isUIAllowed('xcDatatableEditable') && !isNew"
v-e="['c:row-expand:duplicate']"
class="nc-icon-transition cursor-pointer select-none nc-duplicate-row text-gray-500 mx-1 min-w-4"
@click="!isNew && emit('duplicateRow')"
/>
</a-tooltip>
<a-modal v-model:visible="showDeleteRowModal" title="Delete row?" @ok="onConfirmDeleteRowClick">
<p>Are you sure you want to delete this row?</p>
</a-modal>
<div
v-e="['a:actions:delete-row']"
class="nc-menu-item"
:class="{ disabled: isNew }"
@click="!isNew && onDeleteRowClick()"
>
<MdiDelete class="text-gray-500" />
{{ $t('activity.deleteRow') }}
</div>
</div>
</div>
<a-tooltip v-if="!isSqlView" placement="bottom">
<!-- Delete row -->
<template #title>
<div class="text-center w-full">{{ $t('activity.deleteRow') }}</div>
</template>
</a-dropdown>
<MdiDeleteOutline
v-if="isUIAllowed('xcDatatableEditable') && !isNew"
v-e="['c:row-expand:delete']"
class="nc-icon-transition cursor-pointer select-none nc-delete-row text-gray-500 mx-1 min-w-4"
@click="!isNew && onDeleteRowClick()"
/>
</a-tooltip>
<a-dropdown-button class="nc-expand-form-save-btn" type="primary" :disabled="!isUIAllowed('tableRowUpdate')" @click="save">
<template #icon><MdiMenuDown /></template>
<template #overlay>
<a-menu class="nc-expand-form-save-dropdown-menu">
<a-menu-item key="0" class="!py-2 flex gap-2" @click="saveRowAndStay = 0">
@ -210,5 +193,26 @@ const onConfirmDeleteRowClick = async () => {
{{ $t('activity.saveAndStay') }}
</div>
</a-dropdown-button>
<a-tooltip placement="bottom">
<!-- Close -->
<template #title>
<div class="text-center w-full">{{ $t('general.close') }}</div>
</template>
<MdiCloseCircleOutline
class="nc-icon-transition cursor-pointer select-none nc-close-form text-gray-500 mx-1 min-w-4"
@click="emit('cancel')"
/>
</a-tooltip>
<a-modal v-model:visible="showDeleteRowModal" title="Delete row?" @ok="onConfirmDeleteRowClick">
<p>Are you sure you want to delete this row?</p>
</a-modal>
</div>
</template>
<style scoped>
:deep(svg) {
@apply outline-none;
}
</style>

35
packages/nc-gui/components/smartsheet/expanded-form/index.vue

@ -163,7 +163,7 @@ export default {
<a-drawer
v-model:visible="isExpanded"
:footer="null"
width="min(90vw,800px)"
:width="commentsDrawer ? 'min(90vw,900px)' : 'min(90vw,700px)'"
:body-style="{ 'padding': 0, 'display': 'flex', 'flex-direction': 'column' }"
:closable="false"
class="nc-drawer-expanded-form"
@ -171,24 +171,23 @@ export default {
>
<SmartsheetExpandedFormHeader :view="props.view" @cancel="onClose" @duplicate-row="onDuplicateRow" />
<div class="!bg-gray-100 rounded flex-1 relative">
<template v-if="props.showNextPrevIcons">
<a-tooltip placement="bottom">
<template #title>
{{ $t('labels.nextRow') }}
</template>
<MdiChevronRight class="cursor-pointer nc-next-arrow" @click="$emit('next')" />
</a-tooltip>
<a-tooltip placement="bottom">
<template #title>
{{ $t('labels.prevRow') }}
</template>
<MdiChevronLeft class="cursor-pointer nc-prev-arrow" @click="$emit('prev')" />
</a-tooltip>
</template>
<div class="!bg-gray-100 rounded flex-1">
<div class="flex h-full nc-form-wrapper items-stretch min-h-[max(70vh,100%)]">
<div class="flex-1 overflow-auto scrollbar-thin-dull nc-form-fields-container">
<div class="flex-1 overflow-auto scrollbar-thin-dull nc-form-fields-container relative">
<template v-if="props.showNextPrevIcons">
<a-tooltip placement="bottom">
<template #title>
{{ $t('labels.nextRow') }}
</template>
<MdiChevronRight class="cursor-pointer nc-next-arrow" @click="$emit('next')" />
</a-tooltip>
<a-tooltip placement="bottom">
<template #title>
{{ $t('labels.prevRow') }}
</template>
<MdiChevronLeft class="cursor-pointer nc-prev-arrow" @click="$emit('prev')" />
</a-tooltip>
</template>
<div class="w-[500px] mx-auto">
<div v-if="duplicatingRowInProgress" class="flex items-center justify-center h-[100px]">
<a-spin size="large" />

3
packages/nc-gui/composables/useExpandedFormStore.ts

@ -190,7 +190,8 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
}
} else {
// No columns to update
return message.info(t('msg.info.noColumnsToUpdate'))
message.info(t('msg.info.noColumnsToUpdate'))
return
}
}

24
tests/playwright/pages/Dashboard/ExpandedForm/index.ts

@ -7,7 +7,8 @@ export class ExpandedFormPage extends BasePage {
readonly addNewTableButton: Locator;
readonly copyUrlButton: Locator;
readonly toggleCommentsButton: Locator;
readonly moreOptionsButton: Locator;
readonly duplicateRowButton: Locator;
readonly deleteRowButton: Locator;
constructor(dashboard: DashboardPage) {
super(dashboard.rootPage);
@ -15,7 +16,8 @@ export class ExpandedFormPage extends BasePage {
this.addNewTableButton = this.dashboard.get().locator('.nc-add-new-table');
this.copyUrlButton = this.dashboard.get().locator('.nc-copy-row-url:visible');
this.toggleCommentsButton = this.dashboard.get().locator('.nc-toggle-comments:visible');
this.moreOptionsButton = this.dashboard.get().locator('.nc-actions-menu-btn:visible').last();
this.duplicateRowButton = this.dashboard.get().locator('.nc-duplicate-row:visible');
this.deleteRowButton = this.dashboard.get().locator('.nc-delete-row:visible');
}
get() {
@ -23,10 +25,7 @@ export class ExpandedFormPage extends BasePage {
}
async clickDuplicateRow() {
await this.moreOptionsButton.click();
// wait for the menu to appear
await this.rootPage.waitForTimeout(1000);
await this.rootPage.locator('.nc-menu-item:has-text("Duplicate Row")').click();
await this.duplicateRowButton.click();
// wait for loader to disappear
// await this.dashboard.waitForLoaderToDisappear();
@ -34,22 +33,17 @@ export class ExpandedFormPage extends BasePage {
}
async clickDeleteRow() {
await this.moreOptionsButton.click();
// wait for the menu to appear
await this.rootPage.waitForTimeout(1000);
await this.rootPage.locator('.nc-menu-item:has-text("Delete Row")').click();
await this.deleteRowButton.click();
await this.rootPage.locator('.ant-btn-primary:has-text("OK")').click();
}
async isDisabledDuplicateRow() {
await this.moreOptionsButton.click();
const isDisabled = await this.rootPage.locator('.nc-menu-item.disabled:has-text("Duplicate Row")');
const isDisabled = await this.duplicateRowButton;
return await isDisabled.count();
}
async isDisabledDeleteRow() {
await this.moreOptionsButton.click();
const isDisabled = await this.rootPage.locator('.nc-menu-item.disabled:has-text("Delete Row")');
const isDisabled = await this.deleteRowButton;
return await isDisabled.count();
}
@ -139,7 +133,7 @@ export class ExpandedFormPage extends BasePage {
}
async close() {
await this.get().locator('button:has-text("Close")').last().click();
await this.get().locator('.nc-close-form').last().click();
}
async openChildCard(param: { column: string; title: string }) {

4
tests/playwright/tests/expandedFormUrl.spec.ts

@ -174,7 +174,7 @@ test.describe('Expanded record duplicate & delete options', () => {
// expand row, duplicate & verify menu
await dashboard.grid.openExpandedRow({ index: 0 });
await dashboard.expandedForm.clickDuplicateRow();
expect(await dashboard.expandedForm.isDisabledDeleteRow()).toBe(1);
expect(await dashboard.expandedForm.isDisabledDuplicateRow()).toBe(1);
expect(await dashboard.expandedForm.isDisabledDeleteRow()).toBe(0);
expect(await dashboard.expandedForm.isDisabledDuplicateRow()).toBe(0);
});
});

Loading…
Cancel
Save