Add userName util function to render user's name

This commit is contained in:
rijkvanzanten
2020-10-19 13:31:44 -04:00
parent 15ec099a84
commit 6c0afa9651
21 changed files with 83 additions and 80 deletions

View File

@@ -31,7 +31,7 @@ data:
cards:
icon: account_circle
title: '{{ first_name }} {{ last_name }}'
subtitle: '{{ title }}'
subtitle: '{{ email }}'
size: 4
- collection: directus_activity

View File

@@ -5,17 +5,17 @@
v-if="(display === 'avatar' || display === 'both') && src"
:src="src"
role="presentation"
:alt="value && `${value.first_name} ${value.last_name}`"
:alt="value && userName(value)"
:class="{ circle }"
/>
<img
v-else-if="(display === 'avatar' || display === 'both') && src === null"
src="../../assets/avatar-placeholder.svg"
role="presentation"
:alt="value && `${value.first_name} ${value.last_name}`"
:alt="value && userName(value)"
:class="{ circle }"
/>
<span v-if="display === 'name' || display === 'both'">{{ value.first_name }} {{ value.last_name }}</span>
<span v-if="display === 'name' || display === 'both'">{{ userName(value) }}</span>
</div>
</user-popover>
</template>
@@ -23,6 +23,7 @@
<script lang="ts">
import { defineComponent, PropType, computed } from '@vue/composition-api';
import { getRootPath } from '@/utils/get-root-path';
import { userName } from '@/utils/user-name';
type User = {
id: number;
@@ -58,7 +59,7 @@ export default defineComponent({
return null;
});
return { src };
return { src, userName };
},
});
</script>

View File

@@ -12,11 +12,7 @@
>
<template #input v-if="currentUser">
<div class="preview">
<render-template
collection="directus_users"
:item="currentUser"
:template="displayTemplate"
/>
{{ userName(currentUser) }}
</div>
</template>
@@ -65,7 +61,7 @@
@click="setCurrent(item)"
>
<v-list-item-content>
<render-template collection="directus_users" :template="displayTemplate" :item="item" />
{{ userName(currentUser) }}
</v-list-item-content>
</v-list-item>
</template>
@@ -105,10 +101,6 @@ export default defineComponent({
type: String,
default: null,
},
template: {
type: String,
default: null,
},
selectMode: {
type: String as PropType<'auto' | 'dropdown' | 'modal'>,
default: 'auto',
@@ -122,7 +114,7 @@ export default defineComponent({
const { usesMenu, menuActive } = useMenu();
const { info: collectionInfo } = useCollection(ref('directus_users'));
const { selection, stageSelection, selectModalActive } = useSelection();
const { displayTemplate, onPreviewClick, requiredFields } = usePreview();
const { onPreviewClick } = usePreview();
const { totalCount, loading: usersLoading, fetchUsers, users } = useUsers();
const { setCurrent, currentUser, loading: loadingCurrent, currentPrimaryKey } = useCurrent();
@@ -134,7 +126,6 @@ export default defineComponent({
return {
collectionInfo,
currentUser,
displayTemplate,
users,
usersLoading,
loadingCurrent,
@@ -192,16 +183,10 @@ export default defineComponent({
async function fetchCurrent() {
loading.value = true;
const fields = requiredFields;
if (fields.includes('id') === false) {
fields.push('id');
}
try {
const response = await api.get(`/users/${props.value}`, {
params: {
fields: fields,
fields: ['id', 'email', 'first_name', 'last_name'],
},
});
@@ -231,11 +216,7 @@ export default defineComponent({
loading.value = true;
const fields = requiredFields;
if (fields.includes('id') === false) {
fields.push('id');
}
const fields = ['id', 'email', 'first_name', 'last_name'];
try {
const response = await api.get(`/users`, {
@@ -280,10 +261,7 @@ export default defineComponent({
}
function usePreview() {
const displayTemplate = '{{ first_name }} {{ last_name }}';
const requiredFields = ['first_name', 'last_name'];
return { onPreviewClick, displayTemplate, requiredFields };
return { onPreviewClick };
function onPreviewClick() {
if (props.disabled) return;

View File

@@ -901,6 +901,8 @@
"statuses_not_configured": "Status mapping configured incorrectly",
"status_mapping": "Status Mapping",
"unknown_user": "Unknown User",
"creating_in": "Creating Item in {collection}",
"editing_in": "Editing Item in {collection}",
"editing_in_batch": "Batch Editing {count} Items",

View File

@@ -12,7 +12,7 @@
<!-- @TODO add final design -->
<p class="type-label">User:</p>
<user-popover v-if="item.user" :user="item.user.id">
{{ item.user.first_name }} {{ item.user.last_name }}
{{ userName(item.user) }}
</user-popover>
<p class="type-label">Action:</p>
@@ -51,6 +51,7 @@ import { defineComponent, computed, toRefs, ref, watch } from '@vue/composition-
import { i18n } from '@/lang';
import router from '@/router';
import api from '@/api';
import { userName } from '@/utils/user-name';
type Values = {
[field: string]: any;
@@ -58,6 +59,7 @@ type Values = {
type ActivityRecord = {
user: {
email: string;
first_name: string;
last_name: string;
} | null;
@@ -97,6 +99,7 @@ export default defineComponent({
error,
close,
openItemLink,
userName,
};
async function loadActivity() {
@@ -107,6 +110,7 @@ export default defineComponent({
params: {
fields: [
'user.id',
'user.email',
'user.first_name',
'user.last_name',
'action',

View File

@@ -115,6 +115,7 @@ import i18n from '@/lang';
import marked from 'marked';
import localizedFormat from '@/utils/localized-format';
import api from '@/api';
import { userName } from '@/utils/user-name';
export default defineComponent({
inheritAttrs: false,
@@ -194,31 +195,31 @@ export default defineComponent({
try {
const response = await api.get(`/users/${props.file.uploaded_by}`, {
params: {
fields: ['id', 'first_name', 'last_name', 'role'],
fields: ['id', 'email', 'first_name', 'last_name', 'role'],
},
});
const { id, first_name, last_name, role } = response.data.data;
const user = response.data.data;
userCreated.value = {
id: props.file.uploaded_by,
name: first_name + ' ' + last_name,
link: `/users/${id}`,
name: userName(user),
link: `/users/${user.id}`,
};
if (props.file.modified_by) {
const response = await api.get(`/users/${props.file.modified_by}`, {
params: {
fields: ['id', 'first_name', 'last_name', 'role'],
fields: ['id', 'email', 'first_name', 'last_name', 'role'],
},
});
const { id, first_name, last_name, role } = response.data.data;
const user = response.data.data;
userModified.value = {
id: props.file.modified_by,
name: first_name + ' ' + last_name,
link: `/users/${id}`,
name: userName(user),
link: `/users/${user.id}`,
};
}
} finally {

View File

@@ -373,7 +373,6 @@ export default defineComponent({
special: ['user-created'],
interface: 'user',
options: {
template: '{{first_name}} {{last_name}}',
display: 'both',
},
readonly: true,
@@ -407,7 +406,6 @@ export default defineComponent({
special: ['user-updated'],
interface: 'user',
options: {
template: '{{first_name}} {{last_name}}',
display: 'both',
},
readonly: true,

View File

@@ -103,11 +103,12 @@ import { TranslateResult } from 'vue-i18n';
import router from '@/router';
import ValueNull from '@/views/private/components/value-null';
import PresetsInfoSidebarDetail from './components/presets-info-sidebar-detail.vue';
import { userName } from '@/utils/user-name';
type PresetRaw = {
id: number;
bookmark: null | string;
user: null | { first_name: string; last_name: string };
user: null | { email: string; first_name: string; last_name: string };
role: null | { name: string };
collection: string;
layout: string;
@@ -173,7 +174,7 @@ export default defineComponent({
}
if (preset.user) {
scope = `${preset.user.first_name} ${preset.user.last_name}`;
scope = userName(preset.user);
}
const collection = collectionsStore.getCollection(preset.collection)?.name;
@@ -200,6 +201,7 @@ export default defineComponent({
fields: [
'id',
'bookmark',
'user.email',
'user.first_name',
'user.last_name',
'role.name',

View File

@@ -102,6 +102,7 @@ import { useCollectionsStore, usePresetsStore } from '@/stores';
import { getLayouts } from '@/layouts';
import router from '@/router';
import marked from 'marked';
import { userName } from '@/utils/user-name';
type User = {
id: number;
@@ -365,12 +366,12 @@ export default defineComponent({
try {
const response = await api.get(`/users`, {
params: {
fields: ['first_name', 'last_name', 'id'],
fields: ['email', 'first_name', 'last_name', 'id'],
},
});
users.value = response.data.data.map((user: any) => ({
name: user.first_name + ' ' + user.last_name,
name: userName(user),
id: user.id,
}));
} catch (err) {

View File

@@ -102,7 +102,7 @@
<div class="user-box" v-if="isNew === false">
<div class="avatar">
<v-skeleton-loader v-if="loading || previewLoading" />
<img v-else-if="avatarSrc" :src="avatarSrc" :alt="item.first_name" />
<img v-else-if="avatarSrc" :src="avatarSrc" :alt="item.email" />
<v-icon v-else name="account_circle" outline x-large />
</div>
<div class="user-box-content">
@@ -112,7 +112,7 @@
<v-skeleton-loader type="text" />
</template>
<template v-else-if="isNew === false">
<div class="name type-title">{{ item.first_name }} {{ item.last_name }}</div>
<div class="name type-title">{{ userName(item) }}</div>
<div class="email">{{ item.email }}</div>
<v-chip :class="item.status" small>{{ roleName }}</v-chip>
</template>
@@ -179,6 +179,7 @@ import { getRootPath } from '@/utils/get-root-path';
import useShortcut from '@/composables/use-shortcut';
import { isAllowed } from '@/utils/is-allowed';
import useCollection from '@/composables/use-collection';
import { userName } from '@/utils/user-name';
type Values = {
[field: string]: any;
@@ -255,7 +256,7 @@ export default defineComponent({
if (isNew.value === false && item.value !== null) {
const user = item.value as any;
return `${user.first_name} ${user.last_name}`;
return userName(user);
}
return i18n.t('adding_user');
@@ -334,6 +335,7 @@ export default defineComponent({
archiving,
archiveTooltip,
form,
userName,
};
function useBreadcrumb() {

View File

@@ -17,6 +17,7 @@ import { defineComponent, computed, watch, ref } from '@vue/composition-api';
import api from '@/api';
import { hydrate } from '@/hydrate';
import router from '@/router';
import { userName } from '@/utils/user-name';
export default defineComponent({
setup() {
@@ -36,11 +37,11 @@ export default defineComponent({
try {
const response = await api.get(`/users/me`, {
params: {
fields: ['first_name', 'last_name', 'last_page'],
fields: ['email', 'first_name', 'last_name', 'last_page'],
},
});
name.value = response.data.data.first_name + ' ' + response.data.data.last_name;
name.value = userName(response.data.data);
lastPage.value = response.data.data.last_page;
} catch (err) {
error.value = err;

View File

@@ -3,6 +3,7 @@ import api from '@/api';
import { useLatencyStore } from '@/stores';
import { User } from '@/types';
import { userName } from '@/utils/user-name';
export const useUserStore = createStore({
id: 'userStore',
@@ -14,7 +15,7 @@ export const useUserStore = createStore({
getters: {
fullName(state) {
if (state.currentUser === null) return null;
return state.currentUser.first_name + ' ' + state.currentUser.last_name;
return userName(state.currentUser);
},
isAdmin(state) {
return state.currentUser?.role.admin_access === true || false;

View File

@@ -0,0 +1,18 @@
import { User } from '@/types';
import { i18n } from '@/lang';
export function userName(user: Partial<User>): string {
if (user.first_name && user.last_name) {
return `${user.first_name} ${user.last_name}`;
}
if (user.first_name) {
return user.first_name;
}
if (user.email) {
return user.email;
}
return i18n.t('unknown_user') as string;
}

View File

@@ -1,11 +1,7 @@
<template>
<div class="comment-header">
<v-avatar x-small>
<img
v-if="avatarSource"
:src="avatarSource"
:alt="activity.user.first_name + ' ' + activity.user.last_name"
/>
<img v-if="avatarSource" :src="avatarSource" :alt="userName(activity.user)" />
<v-icon v-else name="person_outline" />
</v-avatar>
@@ -13,7 +9,7 @@
<user-popover v-if="activity.user && activity.user.id" :user="activity.user.id">
<span>
<template v-if="activity.user && activity.user">
{{ activity.user.first_name }} {{ activity.user.last_name }}
{{ userName(activity.user) }}
</template>
<template v-else>
@@ -70,6 +66,7 @@ import { Activity } from './types';
import format from 'date-fns/format';
import i18n from '@/lang';
import getRootPath from '@/utils/get-root-path';
import { userName } from '@/utils/user-name';
import api from '@/api';
import localizedFormat from '@/utils/localized-format';
@@ -117,7 +114,7 @@ export default defineComponent({
const { confirmDelete, deleting, remove } = useDelete();
return { formattedTime, avatarSource, confirmDelete, deleting, remove, editedOnFormatted };
return { formattedTime, avatarSource, confirmDelete, deleting, remove, editedOnFormatted, userName };
function useDelete() {
const confirmDelete = ref(false);

View File

@@ -81,6 +81,7 @@ export default defineComponent({
'action',
'timestamp',
'user.id',
'user.email',
'user.first_name',
'user.last_name',
'user.avatar.id',

View File

@@ -1,14 +1,9 @@
import { Avatar } from '@/types';
import { User } from '@/types';
export type Activity = {
id: number;
action: 'comment';
user: null | {
id: number;
first_name: string;
last_name: string;
avatar: null | Avatar;
};
user: null | Partial<User>;
timestamp: string;
edited_on: null | string;
comment: null | string;

View File

@@ -21,6 +21,7 @@ import { defineComponent, PropType, computed } from '@vue/composition-api';
import { Revision } from './types';
import i18n from '@/lang';
import { format } from 'date-fns';
import { userName } from '@/utils/user-name';
export default defineComponent({
props: {
@@ -61,11 +62,7 @@ export default defineComponent({
const user = computed(() => {
if (props.revision?.activity?.user && typeof props.revision.activity.user === 'object') {
const { first_name, last_name } = props.revision.activity.user as {
first_name: string;
last_name: string;
};
return `${first_name} ${last_name}`;
return userName(props.revision.activity.user);
}
return i18n.t('private_user');

View File

@@ -131,6 +131,7 @@ export default defineComponent({
'activity.action',
'activity.timestamp',
'activity.user.id',
'activity.user.email',
'activity.user.first_name',
'activity.user.last_name',
'activity.ip',

View File

@@ -27,6 +27,7 @@ import { Revision } from './types';
import useSync from '@/composables/use-sync';
import localizedFormat from '@/utils/localized-format';
import i18n from '@/lang';
import { userName } from '@/utils/user-name';
type Option = {
text: string;
@@ -59,8 +60,8 @@ export default defineComponent({
let user = i18n.t('private_user');
if (typeof revision.activity.user === 'object') {
const { first_name, last_name } = revision.activity.user;
user = `${first_name} ${last_name}`;
const userInfo = revision.activity.user;
user = userName(userInfo);
}
const text = String(i18n.t('revision_delta_by', { date, user }));

View File

@@ -10,9 +10,10 @@ export type Revision = {
user_agent: string;
timestamp: string;
user:
| number
| string
| {
id: number;
id: string;
email: string;
first_name: string;
last_name: string;
};

View File

@@ -21,7 +21,7 @@
<v-icon name="person" outline v-else />
</v-avatar>
<div class="data">
<div class="name type-title">{{ data.first_name }} {{ data.last_name }}</div>
<div class="name type-title">{{ userName(data) }}</div>
<div class="status-role" :class="data.status">{{ $t(data.status) }} {{ data.role.name }}</div>
<div class="email">{{ data.email }}</div>
</div>
@@ -33,6 +33,7 @@
import { defineComponent, ref, watch, onUnmounted, computed } from '@vue/composition-api';
import api from '@/api';
import { getRootPath } from '@/utils/get-root-path';
import { userName } from '@/utils/user-name';
type User = {
first_name: string;
@@ -77,7 +78,7 @@ export default defineComponent({
data.value = null;
});
return { loading, error, data, active, avatarSrc };
return { loading, error, data, active, avatarSrc, userName };
async function fetchUser() {
loading.value = true;
@@ -86,7 +87,7 @@ export default defineComponent({
try {
const response = await api.get(`/users/${props.user}`, {
params: {
fields: ['first_name', 'last_name', 'avatar.id', 'role.name', 'status', 'email'],
fields: ['email', 'first_name', 'last_name', 'avatar.id', 'role.name', 'status', 'email'],
},
});
data.value = response.data.data;