Browse Source

feat: Display name for comments

pull/6464/head
DarkPhoenix2704 1 year ago
parent
commit
14dc255d87
  1. 5
      packages/nc-gui/components/general/UserIcon.vue
  2. 33
      packages/nc-gui/components/smartsheet/expanded-form/Comments.vue
  3. 6
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  4. 24
      packages/nocodb-sdk/src/lib/Api.ts
  5. 6
      packages/nocodb/src/models/Audit.ts
  6. 8
      packages/nocodb/src/schema/swagger.json

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

@ -1,6 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
const props = defineProps<{ const props = defineProps<{
size?: 'small' | 'medium' | 'large' | 'xlarge' size?: 'small' | 'medium' | 'large' | 'xlarge'
name?: string
}>() }>()
const { user } = useGlobal() const { user } = useGlobal()
@ -9,9 +10,9 @@ const backgroundColor = computed(() => (user.value?.id ? stringToColour(user.val
const size = computed(() => props.size || 'medium') const size = computed(() => props.size || 'medium')
const displayName = computed(() => user.value?.display_name ?? '') const displayName = computed(() => props.name ?? user.value?.display_name ?? '')
const email = computed(() => user.value?.email ?? '') const email = computed(() => props.name ?? user.value?.email ?? '')
const usernameInitials = computed(() => { const usernameInitials = computed(() => {
const displayNameSplit = displayName.value?.split(' ').filter((name) => name) ?? [] const displayNameSplit = displayName.value?.split(' ').filter((name) => name) ?? []

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

@ -101,11 +101,11 @@ watch(
</script> </script>
<template> <template>
<div class="flex flex-col w-full bg-gray-50 rounded-lg"> <div class="flex flex-col w-full h-[500px] bg-gray-50 rounded-lg">
<div class="bg-white rounded-t-lg border-gray-200 border-b-1"> <div class="bg-white rounded-t-lg border-gray-200 border-b-1">
<div class="flex flex-row m-2 p-1 bg-gray-100 rounded-lg"> <div class="flex flex-row gap-2 m-2 p-1 bg-gray-100 rounded-lg">
<div <div
class="tab flex-1 transition-all text-gray-600 cursor-pointer rounded-lg" class="tab flex-1 px-4 py-2 transition-all text-gray-600 cursor-pointer rounded-lg"
:class="{ :class="{
'bg-white shadow !text-brand-500 !hover:text-brand-500': tab === 'comments', 'bg-white shadow !text-brand-500 !hover:text-brand-500': tab === 'comments',
}" }"
@ -117,7 +117,7 @@ watch(
</div> </div>
</div> </div>
<div <div
class="tab flex-1 transition-all text-gray-600 cursor-pointer rounded-lg" class="tab flex-1 px-4 py-2 transition-all text-gray-600 cursor-pointer rounded-lg"
:class="{ :class="{
'bg-white shadow !text-brand-500 !hover:text-brand-500': tab === 'audits', 'bg-white shadow !text-brand-500 !hover:text-brand-500': tab === 'audits',
}" }"
@ -134,7 +134,7 @@ watch(
<div <div
v-if="tab === 'comments'" v-if="tab === 'comments'"
ref="commentsWrapperEl" ref="commentsWrapperEl"
class="flex flex-col m-1 p-1 !h-[calc(100vh-300px)] overflow-y-scroll nc-scrollbar-md space-y-2" class="flex flex-col m-1 p-1 !h-[399px] overflow-y-scroll nc-scrollbar-md space-y-2"
> >
<template v-if="comments.length === 0"> <template v-if="comments.length === 0">
<div class="flex flex-col text-center justify-center h-full"> <div class="flex flex-col text-center justify-center h-full">
@ -145,21 +145,20 @@ watch(
</div> </div>
</template> </template>
<template v-else> <template v-else>
<div v-for="(log, idx) of comments" :key="log.id"> <div v-for="log of comments" :key="log.id">
<div class="bg-white rounded-xl border-1 gap-3 border-gray-200"> <div class="bg-white rounded-xl group border-1 gap-3 border-gray-200">
<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 font-bold items-center gap-2"> <div class="flex font-bold items-center gap-2">
<GeneralUserIcon v-if="isYou(log.user)" /> <GeneralUserIcon :name="log.display_name ?? log.user" />
<MdiAccountCircleOutline v-else class="h-6 w-6" />
<span class="truncate max-w-42"> <span class="truncate max-w-42">
{{ log.user ?? 'Shared base' }} {{ log.display_name ?? log.user ?? 'Shared base' }}
</span> </span>
</div> </div>
<NcButton <NcButton
v-if="log.user === user.email && !editLog" v-if="log.user === user.email && !editLog"
type="secondary" type="secondary"
class="!px-2" class="!px-2 opacity-0 group-hover:opacity-100 transition-all"
size="sm" size="sm"
@click="editComment(log)" @click="editComment(log)"
> >
@ -181,7 +180,7 @@ watch(
<NcButton type="secondary" size="sm" @click="onCancel"> Cancel </NcButton> <NcButton type="secondary" size="sm" @click="onCancel"> Cancel </NcButton>
<NcButton size="sm" @click="onEditComment"> Save </NcButton> <NcButton size="sm" @click="onEditComment"> Save </NcButton>
</div> </div>
<div v-if="log.id !== editLog?.id" class="text-xs text-gray-500"> <div v-if="log.id !== editLog?.id" class="text-sm 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>
</div> </div>
@ -189,7 +188,7 @@ watch(
</div> </div>
</template> </template>
</div> </div>
<div v-else class="flex flex-col m-1 p-1 !h-[calc(100vh-239px)] overflow-y-scroll nc-scrollbar-md space-y-2"> <div v-else ref="commentsWrapperEl" class="flex flex-col m-1 p-1 !h-[459px] overflow-y-scroll nc-scrollbar-md space-y-2">
<template v-if="audits.length === 0"> <template v-if="audits.length === 0">
<div class="flex flex-col mb-14 text-center justify-center h-full"> <div class="flex flex-col mb-14 text-center justify-center h-full">
<div class="text-center text-3xl text-gray-600"> <div class="text-center text-3xl text-gray-600">
@ -198,20 +197,20 @@ watch(
<div class="font-bold text-center my-1 text-gray-600">See changes to this record</div> <div class="font-bold text-center my-1 text-gray-600">See changes to this record</div>
</div> </div>
</template> </template>
<div v-for="(log, idx) of audits" :key="log.id"> <div v-for="log of audits" :key="log.id">
<div class="bg-white rounded-xl border-1 gap-3 border-gray-200"> <div class="bg-white rounded-xl border-1 gap-3 border-gray-200">
<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 font-bold items-center gap-2"> <div class="flex font-bold items-center gap-2">
<GeneralUserIcon v-if="isYou(log.user)" /> <GeneralUserIcon :name="log.display_name ?? log.user" />
<MdiAccountCircleOutline v-else class="row-span-2 h-6 w-6" />
<span class="truncate max-w-50"> <span class="truncate max-w-50">
{{ log.user ?? 'Shared base' }} {{ log.user ?? 'Shared base' }}
</span> </span>
</div> </div>
</div> </div>
<div class="text-sm text-gray-700"> <div class="text-sm text-gray-700">
{{ log.description }} {{ log.description.split('.')[1] }}
</div> </div>
<div v-if="log.id !== editLog?.id" class="text-xs text-gray-500"> <div v-if="log.id !== editLog?.id" class="text-xs text-gray-500">
{{ timeAgo(log.created_at) }} {{ timeAgo(log.created_at) }}

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

@ -358,7 +358,7 @@ export default {
<MdiChevronDown class="text-md text-gray-700" /> <MdiChevronDown class="text-md text-gray-700" />
</NcButton> </NcButton>
</div> </div>
<div v-if="displayValue" class="flex items-center font-bold text-gray-800 text-xl"> <div v-if="displayValue" class="flex items-center truncate max-w-32 font-bold text-gray-800 text-xl">
{{ displayValue }} {{ displayValue }}
</div> </div>
<div class="bg-gray-100 px-2 gap-1 flex items-center rounded-md text-gray-800"> <div class="bg-gray-100 px-2 gap-1 flex items-center rounded-md text-gray-800">
@ -411,7 +411,7 @@ export default {
}" }"
> >
<div <div
class="flex flex-col h-[calc(100vh-200px)] !pb-12 nc-scrollbar-md overflow-y-scroll items-center w-full bg-white border-1 border-gray-200 rounded-xl p-4" class="flex flex-col !pb-12 nc-scrollbar-md h-[540px] overflow-y-scroll items-center w-full bg-white border-1 border-gray-200 rounded-xl p-4"
> >
<div <div
v-for="(col, i) of fields" v-for="(col, i) of fields"
@ -495,7 +495,7 @@ export default {
</div> </div>
<div <div
v-if="isUIAllowed('dataEdit')" v-if="isUIAllowed('dataEdit')"
class="w-full absolute bottom-0 bg-white flex justify-end border-1 border-gray-200 p-2 rounded-b-lg" class="w-full absolute bottom-0 z-10 bg-white flex justify-end border-1 border-gray-200 p-2 rounded-b-lg"
> >
<NcButton type="primary" size="medium" @click="save"> Save </NcButton> <NcButton type="primary" size="medium" @click="save"> Save </NcButton>
</div> </div>

24
packages/nocodb-sdk/src/lib/Api.ts

@ -98,6 +98,11 @@ export interface AuditType {
* @example w@nocodb.com * @example w@nocodb.com
*/ */
user?: string; user?: string;
/**
* The display name of user performing the action
* @example NocoDB
*/
display_name?: string;
/** /**
* IP address from the user * IP address from the user
* @example ::ffff:127.0.0.1 * @example ::ffff:127.0.0.1
@ -2903,6 +2908,25 @@ export class HttpClient<SecurityDataType = unknown> {
export class Api< export class Api<
SecurityDataType extends unknown SecurityDataType extends unknown
> extends HttpClient<SecurityDataType> { > extends HttpClient<SecurityDataType> {
userProfile = {
/**
* @description Update User Profile
*
* @tags User profile
* @name Update
* @summary Update User Profile
* @request PATCH:/api/v1/user/profile
* @response `200` `UserType`
*/
update: (data: UserType, params: RequestParams = {}) =>
this.request<UserType, any>({
path: `/api/v1/user/profile`,
method: 'PATCH',
body: data,
type: ContentType.Json,
...params,
}),
};
auth = { auth = {
/** /**
* @description Create a new user with provided email and password and first user is marked as super admin. * @description Create a new user with provided email and password and first user is marked as super admin.

6
packages/nocodb/src/models/Audit.ts

@ -140,6 +140,12 @@ export default class Audit implements AuditType {
public static async commentsList(args) { public static async commentsList(args) {
const query = Noco.ncMeta const query = Noco.ncMeta
.knex(MetaTable.AUDIT) .knex(MetaTable.AUDIT)
.join(
MetaTable.USERS,
`${MetaTable.USERS}.email`,
`${MetaTable.AUDIT}.user`,
)
.select(`${MetaTable.AUDIT}.*`, `${MetaTable.USERS}.display_name`)
.where('row_id', args.row_id) .where('row_id', args.row_id)
.where('fk_model_id', args.fk_model_id) .where('fk_model_id', args.fk_model_id)
.orderBy('created_at', 'desc'); .orderBy('created_at', 'desc');

8
packages/nocodb/src/schema/swagger.json

@ -12673,6 +12673,7 @@
{ {
"id": "adt_3sii7erfwrlegb", "id": "adt_3sii7erfwrlegb",
"user": "w@nocodb.com", "user": "w@nocodb.com",
"display_name": "NocoDB",
"ip": null, "ip": null,
"base_id": null, "base_id": null,
"project_id": "p_63b4q0qengen1x", "project_id": "p_63b4q0qengen1x",
@ -12689,6 +12690,7 @@
{ {
"id": "adt_fezs668qbxj8gc", "id": "adt_fezs668qbxj8gc",
"user": "w@nocodb.com", "user": "w@nocodb.com",
"display_name": "NocoDB",
"ip": null, "ip": null,
"base_id": null, "base_id": null,
"project_id": "p_63b4q0qengen1x", "project_id": "p_63b4q0qengen1x",
@ -15554,6 +15556,7 @@
{ {
"id": "adt_l5we7pkx70vaao", "id": "adt_l5we7pkx70vaao",
"user": "w@nocodb.com", "user": "w@nocodb.com",
"display_name": "NocoDB",
"ip": "::ffff:127.0.0.1", "ip": "::ffff:127.0.0.1",
"base_id": "ds_3l9qx8xqksenrl", "base_id": "ds_3l9qx8xqksenrl",
"project_id": "p_9sx43moxhqtjm3", "project_id": "p_9sx43moxhqtjm3",
@ -15578,6 +15581,11 @@
"description": "The user name performing the action", "description": "The user name performing the action",
"example": "w@nocodb.com" "example": "w@nocodb.com"
}, },
"display_name": {
"type": "string",
"description": "The display name of user performing the action",
"example": "NocoDB"
},
"ip": { "ip": {
"type": "string", "type": "string",
"example": "::ffff:127.0.0.1", "example": "::ffff:127.0.0.1",

Loading…
Cancel
Save