Browse Source

Merge pull request #7431 from nocodb/nc-fix/user-based-fields-update

Nc: User based fields ui updates
test/ut-fix
Raju Udava 11 months ago committed by GitHub
parent
commit
5babe434e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      packages/nc-gui/components/cell/ReadOnlyDateTimePicker.vue
  2. 6
      packages/nc-gui/components/cell/ReadOnlyUser.vue
  3. 2
      packages/nc-gui/components/cell/RichText.vue
  4. 37
      packages/nc-gui/components/cell/User.vue
  5. 19
      packages/nc-gui/components/general/UserIcon.vue
  6. 22
      packages/nc-gui/components/smartsheet/expanded-form/Comments.vue
  7. 2
      tests/playwright/pages/Dashboard/Grid/Column/UserOptionColumn.ts
  8. 7
      tests/playwright/pages/Dashboard/common/Cell/UserOptionCell.ts

4
packages/nc-gui/components/cell/ReadOnlyDateTimePicker.vue

@ -9,9 +9,9 @@ defineProps<Props>()
provide(ReadonlyInj, ref(true)) provide(ReadonlyInj, ref(true))
provide(EditModeInj, ref(true)) provide(EditModeInj, ref(false))
provide(ActiveCellInj, ref(true)) provide(ActiveCellInj, ref(false))
</script> </script>
<template> <template>

6
packages/nc-gui/components/cell/ReadOnlyUser.vue

@ -9,13 +9,13 @@ defineProps<Props>()
provide(ReadonlyInj, ref(true)) provide(ReadonlyInj, ref(true))
provide(EditModeInj, ref(true)) provide(EditModeInj, ref(false))
provide(ActiveCellInj, ref(true)) provide(ActiveCellInj, ref(false))
</script> </script>
<template> <template>
<div class="relative"> <div class="relative w-full">
<LazyCellUser class="z-0" :model-value="modelValue" /> <LazyCellUser class="z-0" :model-value="modelValue" />
<div class="w-full h-full z-1 absolute top-0 left-0"></div> <div class="w-full h-full z-1 absolute top-0 left-0"></div>
</div> </div>

2
packages/nc-gui/components/cell/RichText.vue

@ -8,7 +8,7 @@ import { generateJSON } from '@tiptap/html'
import Underline from '@tiptap/extension-underline' import Underline from '@tiptap/extension-underline'
import { TaskItem } from '@/helpers/dbTiptapExtensions/task-item' import { TaskItem } from '@/helpers/dbTiptapExtensions/task-item'
import { Link } from '@/helpers/dbTiptapExtensions/links' import { Link } from '@/helpers/dbTiptapExtensions/links'
import { RowHeightInj, IsExpandedFormOpenInj } from '#imports' import { IsExpandedFormOpenInj, RowHeightInj } from '#imports'
const props = defineProps<{ const props = defineProps<{
value?: string | null value?: string | null

37
packages/nc-gui/components/cell/User.vue

@ -281,7 +281,7 @@ const filterOption = (input: string, option: any) => {
}" }"
> >
<template v-for="selectedOpt of vModel" :key="selectedOpt.value"> <template v-for="selectedOpt of vModel" :key="selectedOpt.value">
<a-tag class="rounded-tag max-w-full" color="'#ccc'"> <a-tag class="rounded-tag max-w-full !pl-0" color="'#ccc'">
<span <span
:style="{ :style="{
'color': tinycolor.isReadable('#ccc' || '#ccc', '#fff', { level: 'AA', size: 'large' }) 'color': tinycolor.isReadable('#ccc' || '#ccc', '#fff', { level: 'AA', size: 'large' })
@ -289,8 +289,17 @@ const filterOption = (input: string, option: any) => {
: tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(), : tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'font-size': '13px', 'font-size': '13px',
}" }"
class="flex items-stretch gap-2"
:class="{ 'text-sm': isKanban }" :class="{ 'text-sm': isKanban }"
> >
<div class="flex-none">
<GeneralUserIcon
size="auto"
:name="!selectedOpt.label?.includes('@') ? selectedOpt.label.trim() : ''"
:email="selectedOpt.label"
class="!text-[0.65rem]"
/>
</div>
<NcTooltip class="truncate max-w-full" show-on-truncate-only> <NcTooltip class="truncate max-w-full" show-on-truncate-only>
<template #title> <template #title>
{{ selectedOpt.label }} {{ selectedOpt.label }}
@ -349,13 +358,20 @@ const filterOption = (input: string, option: any) => {
: tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(), : tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'font-size': '13px', 'font-size': '13px',
}" }"
class="flex items-center gap-2" class="flex items-stretch gap-2"
:class="{ 'text-sm': isKanban }" :class="{ 'text-sm': isKanban }"
> >
<GeneralUserIcon size="medium" :email="op.email" /> <div>
<GeneralUserIcon
size="auto"
:name="op.display_name?.trim() ? op.display_name?.trim() : ''"
:email="op.email"
class="!text-[0.65rem]"
/>
</div>
<NcTooltip class="truncate max-w-full" show-on-truncate-only> <NcTooltip class="truncate max-w-full" show-on-truncate-only>
<template #title> <template #title>
{{ op.display_name?.length ? op.display_name : op.email }} {{ op.display_name?.trim() || op.email }}
</template> </template>
<span <span
class="text-ellipsis overflow-hidden" class="text-ellipsis overflow-hidden"
@ -365,7 +381,7 @@ const filterOption = (input: string, option: any) => {
display: 'inline', display: 'inline',
}" }"
> >
{{ op.display_name?.length ? op.display_name : op.email }} {{ op.display_name?.trim() || op.email }}
</span> </span>
</NcTooltip> </NcTooltip>
</span> </span>
@ -376,7 +392,7 @@ const filterOption = (input: string, option: any) => {
<template #tagRender="{ label, value: val, onClose }"> <template #tagRender="{ label, value: val, onClose }">
<a-tag <a-tag
v-if="options.find((el) => el.id === val)" v-if="options.find((el) => el.id === val)"
class="rounded-tag nc-selected-option" class="rounded-tag nc-selected-option !pl-0"
:style="{ display: 'flex', alignItems: 'center' }" :style="{ display: 'flex', alignItems: 'center' }"
color="'#ccc'" color="'#ccc'"
:closable="editAllowed && ((vModel?.length ?? 0) > 1 || !column?.rqd)" :closable="editAllowed && ((vModel?.length ?? 0) > 1 || !column?.rqd)"
@ -394,8 +410,17 @@ const filterOption = (input: string, option: any) => {
: tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(), : tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'font-size': '13px', 'font-size': '13px',
}" }"
class="flex items-stretch gap-2"
:class="{ 'text-sm': isKanban }" :class="{ 'text-sm': isKanban }"
> >
<div>
<GeneralUserIcon
size="auto"
:name="!label?.includes('@') ? label.trim() : ''"
:email="label"
class="!text-[0.65rem]"
/>
</div>
{{ label }} {{ label }}
</span> </span>
</a-tag> </a-tag>

19
packages/nc-gui/components/general/UserIcon.vue

@ -3,28 +3,24 @@ import { isColorDark, stringToColor } from '~/utils/colorsUtils'
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
size?: 'small' | 'medium' | 'base' | 'large' | 'xlarge' size?: 'small' | 'medium' | 'base' | 'large' | 'xlarge' | 'auto'
name?: string name?: string
email?: string email?: string
}>(), }>(),
{ {
size: 'medium',
name: '',
email: '', email: '',
}, },
) )
const size = computed(() => props.size || 'medium') const { size, email } = toRefs(props)
const displayName = computed(() => props.name ?? '') const displayName = computed(() => props.name?.trim() || '')
const email = computed(() => props?.email ?? '')
const backgroundColor = computed(() => { const backgroundColor = computed(() => {
// in comments we need to generate user icon from email // in comments we need to generate user icon from email
if (email.value.length) { return displayName.value ? stringToColor(displayName.value) : email.value ? stringToColor(email.value) : '#FFFFFF'
return stringToColor(email.value)
}
return email.value ? stringToColor(email.value) : '#FFFFFF'
}) })
const usernameInitials = computed(() => { const usernameInitials = computed(() => {
@ -46,6 +42,7 @@ const usernameInitials = computed(() => {
<div <div
class="flex nc-user-avatar font-bold" class="flex nc-user-avatar font-bold"
:class="{ :class="{
'h-full min-h-5 aspect-square': size === 'auto',
'min-w-4 min-h-4': size === 'small', 'min-w-4 min-h-4': size === 'small',
'min-w-6 min-h-6': size === 'medium', 'min-w-6 min-h-6': size === 'medium',
'w-8 h-8 !text-md': size === 'base', 'w-8 h-8 !text-md': size === 'base',
@ -62,6 +59,6 @@ const usernameInitials = computed(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.nc-user-avatar { .nc-user-avatar {
@apply rounded-full text-xs flex items-center justify-center uppercase; @apply rounded-full text-xs flex items-center justify-center uppercase;
} }
</style> </style>

22
packages/nc-gui/components/smartsheet/expanded-form/Comments.vue

@ -215,12 +215,24 @@ const onClickAudit = () => {
<div class="flex flex-col p-4 gap-3"> <div class="flex flex-col p-4 gap-3">
<div class="flex justify-between"> <div class="flex justify-between">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<GeneralUserIcon size="base" :name="log.display_name ?? log.user" :email="log.user" /> <GeneralUserIcon size="base" :name="log.display_name" :email="log.user" />
<div class="flex flex-col"> <div class="flex flex-col">
<span class="truncate font-bold max-w-42"> <NcTooltip class="truncate max-w-42" show-on-truncate-only>
{{ log.display_name ?? log.user.split('@')[0] ?? 'Shared source' }} <template #title>
</span> {{ log.display_name?.trim() || log.user || 'Shared source' }}
</template>
<span
class="text-ellipsis overflow-hidden font-bold"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ log.display_name?.trim() || log.user || 'Shared source' }}
</span>
</NcTooltip>
<div v-if="log.id !== editLog?.id" class="text-xs font-medium text-gray-500"> <div v-if="log.id !== editLog?.id" class="text-xs font-medium text-gray-500">
{{ log.created_at !== log.updated_at ? `Edited ${timeAgo(log.updated_at)}` : timeAgo(log.created_at) }} {{ log.created_at !== log.updated_at ? `Edited ${timeAgo(log.updated_at)}` : timeAgo(log.created_at) }}
</div> </div>
@ -298,7 +310,7 @@ const onClickAudit = () => {
<div class="flex flex-col p-4 gap-3"> <div class="flex flex-col p-4 gap-3">
<div class="flex justify-between"> <div class="flex justify-between">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<GeneralUserIcon size="base" :email="log.user" /> <GeneralUserIcon size="base" :email="log.user" :name="log.display_name" />
<div class="flex flex-col"> <div class="flex flex-col">
<NcTooltip class="truncate max-w-50" show-on-truncate-only> <NcTooltip class="truncate max-w-50" show-on-truncate-only>

2
tests/playwright/pages/Dashboard/Grid/Column/UserOptionColumn.ts

@ -111,7 +111,7 @@ export class UserOptionColumnPageObject extends BasePage {
let counter = 0; let counter = 0;
for (const option of options) { for (const option of options) {
await expect(defaultValueSelector.locator(`.nc-selected-option`).nth(counter)).toHaveText(option); await expect(defaultValueSelector.locator(`.nc-selected-option`).nth(counter)).toContainText(option);
counter++; counter++;
} }

7
tests/playwright/pages/Dashboard/common/Cell/UserOptionCell.ts

@ -101,8 +101,7 @@ export class UserOptionCellPageObject extends BasePage {
const locator = this.cell.get({ index, columnHeader }).locator('.ant-tag'); const locator = this.cell.get({ index, columnHeader }).locator('.ant-tag');
await locator.waitFor({ state: 'visible' }); await locator.waitFor({ state: 'visible' });
const text = await locator.allInnerTexts(); return expect(locator).toContainText(option);
return expect(text).toContain(option);
} }
async verifyNoOptionsSelected({ index, columnHeader }: { index: number; columnHeader: string }) { async verifyNoOptionsSelected({ index, columnHeader }: { index: number; columnHeader: string }) {
@ -134,7 +133,7 @@ export class UserOptionCellPageObject extends BasePage {
let counter = 0; let counter = 0;
for (const option of options) { for (const option of options) {
await expect(this.rootPage.locator(`div.ant-select-item-option`).nth(counter)).toHaveText(option); await expect(this.rootPage.locator(`div.ant-select-item-option`).nth(counter)).toContainText(option);
counter++; counter++;
} }
await this.rootPage.keyboard.press('Escape'); await this.rootPage.keyboard.press('Escape');
@ -155,7 +154,7 @@ export class UserOptionCellPageObject extends BasePage {
let counter = 0; let counter = 0;
for (const option of options) { for (const option of options) {
await expect(selectCell.locator(`.nc-selected-option`).nth(counter)).toHaveText(option); await expect(selectCell.locator(`.nc-selected-option`).nth(counter)).toContainText(option);
counter++; counter++;
} }
} }

Loading…
Cancel
Save