Skip to content

Commit

Permalink
Merge pull request #7406 from nocodb/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] committed Jan 11, 2024
2 parents bc434ed + fbf32cd commit c3fc911
Show file tree
Hide file tree
Showing 183 changed files with 4,437 additions and 1,297 deletions.
12 changes: 6 additions & 6 deletions packages/nc-cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 38 additions & 5 deletions packages/nc-gui/components/account/UserList.vue
Expand Up @@ -2,7 +2,16 @@
import { OrgUserRoles } from 'nocodb-sdk'
import type { OrgUserReqType, RequestParams, UserType } from 'nocodb-sdk'
import type { User } from '#imports'
import { extractSdkResponseErrorMsg, iconMap, useApi, useCopy, useDashboard, useDebounceFn, useNuxtApp } from '#imports'
import {
extractSdkResponseErrorMsg,
iconMap,
useApi,
useCopy,
useDashboard,
useDebounceFn,
useNuxtApp,
useUserSorts,
} from '#imports'
const { api, isLoading } = useApi()
Expand All @@ -19,8 +28,14 @@ const { user: loggedInUser } = useGlobal()
const { copy } = useCopy()
const { sorts, sortDirection, loadSorts, saveOrUpdate, handleGetSortedData } = useUserSorts('Org')
const users = ref<UserType[]>([])
const sortedUsers = computed(() => {
return handleGetSortedData(users.value, sorts.value) as UserType[]
})
const currentPage = ref(1)
const currentLimit = ref(10)
Expand Down Expand Up @@ -64,6 +79,7 @@ const loadUsers = useDebounceFn(async (page = currentPage.value, limit = current
onMounted(() => {
loadUsers()
loadSorts()
})
const updateRole = async (userId: string, roles: string) => {
Expand All @@ -73,6 +89,12 @@ const updateRole = async (userId: string, roles: string) => {
} as OrgUserReqType)
message.success(t('msg.success.roleUpdated'))
users.value.forEach((user) => {
if (user.id === userId) {
user.roles = roles
}
})
$e('a:org-user:role-updated', { role: roles })
} catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e))
Expand Down Expand Up @@ -176,10 +198,21 @@ const openDeleteModal = (user: UserType) => {
</div>
<div class="w-full rounded-md max-w-250 h-[calc(100%-12rem)] rounded-md overflow-hidden mt-5">
<div class="flex w-full bg-gray-50 border-1 rounded-t-md">
<div class="py-3.5 text-gray-500 font-medium text-3.5 w-2/3 text-start pl-6" data-rec="true">
{{ $t('labels.email') }}
<div
class="py-3.5 text-gray-500 font-medium text-3.5 w-2/3 text-start pl-6 flex items-center space-x-2"
data-rec="true"
>
<span>
{{ $t('labels.email') }}
</span>
<LazyAccountUserMenu :direction="sortDirection.email" field="email" :handle-user-sort="saveOrUpdate" />
</div>
<div class="py-3.5 text-gray-500 font-medium text-3.5 w-1/3 text-start flex items-center space-x-2" data-rec="true">
<span>
{{ $t('objects.role') }}
</span>
<LazyAccountUserMenu :direction="sortDirection.roles" field="roles" :handle-user-sort="saveOrUpdate" />
</div>
<div class="py-3.5 text-gray-500 font-medium text-3.5 w-1/3 text-start" data-rec="true">{{ $t('objects.role') }}</div>
<div class="flex py-3.5 text-gray-500 font-medium text-3.5 w-28 justify-end mr-4" data-rec="true">
{{ $t('labels.action') }}
</div>
Expand All @@ -193,7 +226,7 @@ const openDeleteModal = (user: UserType) => {
</div>
<section v-else class="tbody h-[calc(100%-4rem)] nc-scrollbar-md border-t-0 !overflow-auto">
<div
v-for="el of users"
v-for="el of sortedUsers"
:key="el.id"
data-testid="nc-token-list"
class="user flex py-3 justify-around px-1 border-b-1 border-l-1 border-r-1"
Expand Down
79 changes: 79 additions & 0 deletions packages/nc-gui/components/account/UserMenu.vue
@@ -0,0 +1,79 @@
<script lang="ts" setup>
import { iconMap } from '#imports'
import type { UsersSortType } from '~/lib'
const { field, direction, handleUserSort } = defineProps<{
field: UsersSortType['field']
direction: UsersSortType['direction']
handleUserSort: Function
}>()
const isOpen = ref(false)
const sortUserBy = (direction?: UsersSortType['direction']) => {
handleUserSort({
field,
direction,
})
isOpen.value = false
}
</script>

<template>
<a-dropdown
v-model:visible="isOpen"
:trigger="['click']"
placement="bottomLeft"
overlay-class-name="nc-user-menu-column-operations !border-1 rounded-lg !shadow-xl"
@click.stop="isOpen = !isOpen"
>
<div>
<GeneralIcon
:icon="direction === 'asc' || direction === 'desc' ? 'sortDesc' : 'arrowDown'"
class="text-grey h-full text-grey nc-user-menu-trigger cursor-pointer outline-0 mr-2 transition-none"
:style="{ transform: direction === 'asc' ? 'rotate(180deg)' : undefined }"
/>
</div>
<template #overlay>
<NcMenu class="flex flex-col gap-1 border-gray-200 nc-user-menu-column-options">
<NcMenuItem @click="sortUserBy('asc')">
<div class="nc-column-insert-after nc-user-menu-item">
<component
:is="iconMap.sortDesc"
class="text-gray-700 !rotate-180 !w-4.25 !h-4.25"
:style="{
transform: 'rotate(180deg)',
}"
/>

<!-- Sort Ascending -->
{{ $t('general.sortAsc') }}
</div>
</NcMenuItem>
<NcMenuItem @click="sortUserBy('desc')">
<div class="nc-column-insert-before nc-user-menu-item">
<component :is="iconMap.sortDesc" class="text-gray-700 !w-4.25 !h-4.25 ml-0.5 mr-0.25" />
<!-- Sort Descending -->
{{ $t('general.sortDesc') }}
</div>
</NcMenuItem>
</NcMenu>
</template>
</a-dropdown>
</template>

<style scoped>
.nc-user-menu-item {
@apply flex items-center gap-2;
}
.nc-user-menu-column-options {
.nc-icons {
@apply !w-5 !h-5;
}
}
:deep(.ant-dropdown-menu-item) {
@apply !hover:text-black text-gray-700;
}
</style>
6 changes: 3 additions & 3 deletions packages/nc-gui/components/cell/DatePicker.vue
Expand Up @@ -104,7 +104,7 @@ const placeholder = computed(() => {
if (isEditColumn.value && (modelValue === '' || modelValue === null)) {
return t('labels.optional')
} else if (modelValue === null && showNull.value) {
return t('general.null')
return t('general.null').toUpperCase()
} else if (isDateInvalid.value) {
return t('msg.invalidDate')
} else {
Expand Down Expand Up @@ -243,7 +243,7 @@ const clickHandler = () => {
:picker="picker"
:tabindex="0"
:bordered="false"
class="!w-full !py-1 !border-none"
class="!w-full !py-1 !border-none !text-current"
:class="{ 'nc-null': modelValue === null && showNull, '!px-2': isExpandedFormOpen, '!px-0': !isExpandedFormOpen }"
:format="dateFormat"
:placeholder="placeholder"
Expand All @@ -260,7 +260,7 @@ const clickHandler = () => {
</template>

<style scoped>
:deep(.ant-picker-input > input[disabled]) {
:deep(.ant-picker-input > input) {
@apply !text-current;
}
</style>
7 changes: 4 additions & 3 deletions packages/nc-gui/components/cell/DateTimePicker.vue
Expand Up @@ -157,7 +157,7 @@ const placeholder = computed(() => {
if (isEditColumn.value && (modelValue === '' || modelValue === null)) {
return t('labels.optional')
} else if (modelValue === null && showNull.value) {
return t('general.null')
return t('general.null').toUpperCase()
} else if (isDateInvalid.value) {
return t('msg.invalidDate')
} else {
Expand Down Expand Up @@ -253,6 +253,7 @@ useSelectedCellKeyupListener(active, (e: KeyboardEvent) => {
const cellClickHook = inject(CellClickHookInj, null)
const cellClickHandler = () => {
if (readOnly.value) return
open.value = (active.value || editable.value) && !open.value
}
Expand Down Expand Up @@ -296,7 +297,7 @@ const isColDisabled = computed(() => {
:disabled="isColDisabled"
:show-time="true"
:bordered="false"
class="!w-full !py-1 !border-none"
class="!w-full !py-1 !border-none !text-current"
:class="{ 'nc-null': modelValue === null && showNull, '!px-2': isExpandedFormOpen, '!px-0': !isExpandedFormOpen }"
:format="dateTimeFormat"
:placeholder="placeholder"
Expand All @@ -313,7 +314,7 @@ const isColDisabled = computed(() => {
</template>

<style scoped>
:deep(.ant-picker-input > input[disabled]) {
:deep(.ant-picker-input > input) {
@apply !text-current;
}
</style>
2 changes: 1 addition & 1 deletion packages/nc-gui/components/cell/Decimal.vue
Expand Up @@ -112,7 +112,7 @@ watch(isExpandedFormOpen, () => {
@selectstart.capture.stop
@mousedown.stop
/>
<span v-else-if="vModel === null && showNull" class="nc-null capitalize">{{ $t('general.null') }}</span>
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span>
<span v-else class="text-sm">{{ displayValue }}</span>
</template>

Expand Down
2 changes: 1 addition & 1 deletion packages/nc-gui/components/cell/Duration.vue
Expand Up @@ -111,7 +111,7 @@ const focus: VNodeRef = (el) =>
@mousedown.stop
/>

<span v-else-if="modelValue === null && showNull" class="nc-null capitalize">{{ $t('general.null') }}</span>
<span v-else-if="modelValue === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span>

<span v-else> {{ localState }}</span>

Expand Down
2 changes: 1 addition & 1 deletion packages/nc-gui/components/cell/MultiSelect.vue
Expand Up @@ -567,7 +567,7 @@ const onFocus = () => {
}
:deep(.ant-select-selector) {
@apply !px-0;
@apply !pl-0;
}
:deep(.ant-select-selection-search-input) {
Expand Down
2 changes: 1 addition & 1 deletion packages/nc-gui/components/cell/Percent.vue
Expand Up @@ -143,7 +143,7 @@ const onTabPress = (e: KeyboardEvent) => {
@selectstart.capture.stop
@mousedown.stop
/>
<span v-else-if="vModel === null && showNull" class="nc-null capitalize">{{ $t('general.null') }}</span>
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span>
<div v-else-if="percentMeta.is_progress === true && vModel !== null && vModel !== undefined" class="px-2">
<a-progress
:percent="Number(parseFloat(vModel.toString()).toFixed(2))"
Expand Down
22 changes: 22 additions & 0 deletions packages/nc-gui/components/cell/ReadOnlyDateTimePicker.vue
@@ -0,0 +1,22 @@
<script setup lang="ts">
import { ActiveCellInj, EditModeInj, ReadonlyInj, provide, ref } from '#imports'
interface Props {
modelValue?: string | null
}
defineProps<Props>()
provide(ReadonlyInj, ref(true))
provide(EditModeInj, ref(true))
provide(ActiveCellInj, ref(true))
</script>

<template>
<div class="relative">
<LazyCellDateTimePicker class="z-0" :model-value="modelValue" :is-pk="false" />
<div class="w-full h-full z-1 absolute top-0 left-0"></div>
</div>
</template>
22 changes: 22 additions & 0 deletions packages/nc-gui/components/cell/ReadOnlyUser.vue
@@ -0,0 +1,22 @@
<script setup lang="ts">
import { ActiveCellInj, EditModeInj, ReadonlyInj, provide, ref } from '#imports'
interface Props {
modelValue?: string | null
}
defineProps<Props>()
provide(ReadonlyInj, ref(true))
provide(EditModeInj, ref(true))
provide(ActiveCellInj, ref(true))
</script>

<template>
<div class="relative">
<LazyCellUser class="z-0" :model-value="modelValue" />
<div class="w-full h-full z-1 absolute top-0 left-0"></div>
</div>
</template>
10 changes: 8 additions & 2 deletions packages/nc-gui/components/cell/SingleSelect.vue
Expand Up @@ -322,7 +322,8 @@ const onFocus = () => {
:disabled="readOnly || !editAllowed"
:show-search="!isMobileMode && isOpen && active"
:show-arrow="hasEditRoles && !readOnly && active && (vModel === null || vModel === undefined)"
:dropdown-class-name="`nc-dropdown-single-select-cell ${isOpen && active ? 'active' : ''}`"
:dropdown-class-name="`nc-dropdown-single-select-cell !min-w-200px ${isOpen && active ? 'active' : ''}`"
:dropdown-match-select-width="true"
@select="onSelect"
@keydown="onKeydown($event)"
@search="search"
Expand Down Expand Up @@ -399,7 +400,12 @@ const onFocus = () => {
}
:deep(.ant-select-selector) {
@apply !px-0;
@apply !pl-0 !pr-4;
}
:deep(.ant-select-selector .ant-select-selection-item) {
@apply flex items-center;
text-overflow: clip;
}
:deep(.ant-select-selection-search-input) {
Expand Down
6 changes: 3 additions & 3 deletions packages/nc-gui/components/cell/TimePicker.vue
Expand Up @@ -96,7 +96,7 @@ const placeholder = computed(() => {
if (isEditColumn.value && (modelValue === '' || modelValue === null)) {
return t('labels.optional')
} else if (modelValue === null && showNull.value) {
return t('general.null')
return t('general.null').toUpperCase()
} else if (isTimeInvalid.value) {
return t('msg.invalidTime')
} else {
Expand Down Expand Up @@ -133,7 +133,7 @@ useSelectedCellKeyupListener(active, (e: KeyboardEvent) => {
:bordered="false"
use12-hours
format="HH:mm"
class="!w-full !py-1 !border-none"
class="!w-full !py-1 !border-none !text-current"
:class="{ 'nc-null': modelValue === null && showNull, '!px-2': isExpandedFormOpen, '!px-0': !isExpandedFormOpen }"
:placeholder="placeholder"
:allow-clear="!readOnly && !localState && !isPk"
Expand All @@ -148,7 +148,7 @@ useSelectedCellKeyupListener(active, (e: KeyboardEvent) => {
</template>

<style scoped>
:deep(.ant-picker-input > input[disabled]) {
:deep(.ant-picker-input > input) {
@apply !text-current;
}
</style>
2 changes: 1 addition & 1 deletion packages/nc-gui/components/cell/Url.vue
Expand Up @@ -108,7 +108,7 @@ watch(
@mousedown.stop
/>

<span v-else-if="vModel === null && showNull" class="nc-null uppercase"> $t('general.null')</span>
<span v-else-if="vModel === null && showNull" class="nc-null uppercase"> {{ $t('general.null') }}</span>

<nuxt-link
v-else-if="isValid && !cellUrlOptions?.overlay"
Expand Down

0 comments on commit c3fc911

Please sign in to comment.