feat: Shows the last activity, created at timestamp in the same row (#6267)
This commit is contained in:
@@ -17,9 +17,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tooltip {
|
.tooltip {
|
||||||
|
background-color: var(--black-transparent);
|
||||||
border-radius: $space-smaller;
|
border-radius: $space-smaller;
|
||||||
font-size: $font-size-mini;
|
font-size: $font-size-mini;
|
||||||
max-width: 15rem;
|
max-width: var(--space-giga);
|
||||||
padding: $space-smaller $space-small;
|
padding: $space-smaller $space-small;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<span class="time-ago">
|
<div
|
||||||
<span>{{ timeAgo }}</span>
|
v-tooltip.top="{
|
||||||
</span>
|
content: tooltipText,
|
||||||
|
delay: { show: 1500, hide: 0 },
|
||||||
|
hideOnClick: true,
|
||||||
|
}"
|
||||||
|
class="time-ago"
|
||||||
|
>
|
||||||
|
<span>{{ `${createdAtTime} • ${lastActivityTime}` }}</span>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -19,20 +26,55 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
timestamp: {
|
lastActivityTimestamp: {
|
||||||
|
type: [String, Date, Number],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
createdAtTimestamp: {
|
||||||
type: [String, Date, Number],
|
type: [String, Date, Number],
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
timeAgo: this.dynamicTime(this.timestamp),
|
lastActivityAtTimeAgo: this.dynamicTime(this.lastActivityTimestamp),
|
||||||
|
createdAtTimeAgo: this.dynamicTime(this.createdAtTimestamp),
|
||||||
timer: null,
|
timer: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
lastActivityTime() {
|
||||||
|
return this.shortTimestamp(this.lastActivityAtTimeAgo);
|
||||||
|
},
|
||||||
|
createdAtTime() {
|
||||||
|
return this.shortTimestamp(this.createdAtTimeAgo);
|
||||||
|
},
|
||||||
|
createdAt() {
|
||||||
|
const createdTimeDiff = Date.now() - this.createdAtTimestamp * 1000;
|
||||||
|
const isBeforeAMonth = createdTimeDiff > DAY_IN_MILLI_SECONDS * 30;
|
||||||
|
return !isBeforeAMonth
|
||||||
|
? `Created ${this.createdAtTimeAgo}`
|
||||||
|
: `Created at: ${this.dateFormat(this.createdAtTimestamp)}`;
|
||||||
|
},
|
||||||
|
lastActivity() {
|
||||||
|
const lastActivityTimeDiff =
|
||||||
|
Date.now() - this.lastActivityTimestamp * 1000;
|
||||||
|
const isNotActive = lastActivityTimeDiff > DAY_IN_MILLI_SECONDS * 30;
|
||||||
|
return !isNotActive
|
||||||
|
? `Last activity ${this.lastActivityAtTimeAgo}`
|
||||||
|
: `Last activity: ${this.dateFormat(this.lastActivityTimestamp)}`;
|
||||||
|
},
|
||||||
|
tooltipText() {
|
||||||
|
return `${this.createdAt}
|
||||||
|
${this.lastActivity}`;
|
||||||
|
},
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
timestamp() {
|
lastActivityTimestamp() {
|
||||||
this.timeAgo = this.dynamicTime(this.timestamp);
|
this.lastActivityAtTimeAgo = this.dynamicTime(this.lastActivityTimestamp);
|
||||||
|
},
|
||||||
|
createdAtTimestamp() {
|
||||||
|
this.createdAtTimeAgo = this.dynamicTime(this.createdAtTimestamp);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -46,12 +88,15 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
createTimer() {
|
createTimer() {
|
||||||
this.timer = setTimeout(() => {
|
this.timer = setTimeout(() => {
|
||||||
this.timeAgo = this.dynamicTime(this.timestamp);
|
this.lastActivityAtTimeAgo = this.dynamicTime(
|
||||||
|
this.lastActivityTimestamp
|
||||||
|
);
|
||||||
|
this.createdAtTimeAgo = this.dynamicTime(this.createdAtTimestamp);
|
||||||
this.createTimer();
|
this.createTimer();
|
||||||
}, this.refreshTime());
|
}, this.refreshTime());
|
||||||
},
|
},
|
||||||
refreshTime() {
|
refreshTime() {
|
||||||
const timeDiff = Date.now() - this.timestamp * 1000;
|
const timeDiff = Date.now() - this.lastActivityTimestamp * 1000;
|
||||||
if (timeDiff > DAY_IN_MILLI_SECONDS) {
|
if (timeDiff > DAY_IN_MILLI_SECONDS) {
|
||||||
return DAY_IN_MILLI_SECONDS;
|
return DAY_IN_MILLI_SECONDS;
|
||||||
}
|
}
|
||||||
@@ -71,5 +116,9 @@ export default {
|
|||||||
font-weight: var(--font-weight-normal);
|
font-weight: var(--font-weight-normal);
|
||||||
line-height: var(--space-normal);
|
line-height: var(--space-normal);
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--b-900);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -87,7 +87,10 @@
|
|||||||
</p>
|
</p>
|
||||||
<div class="conversation--meta">
|
<div class="conversation--meta">
|
||||||
<span class="timestamp">
|
<span class="timestamp">
|
||||||
<time-ago :timestamp="chat.timestamp" />
|
<time-ago
|
||||||
|
:last-activity-timestamp="chat.timestamp"
|
||||||
|
:created-at-timestamp="chat.created_at"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span class="unread">{{ unreadCount > 9 ? '9+' : unreadCount }}</span>
|
<span class="unread">{{ unreadCount > 9 ? '9+' : unreadCount }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,3 +8,38 @@ describe('#messageStamp', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#dynamicTime', () => {
|
||||||
|
it('returns correct value', () => {
|
||||||
|
expect(TimeMixin.methods.dynamicTime(1612971343)).toEqual(
|
||||||
|
'almost 2 years ago'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#dateFormat', () => {
|
||||||
|
it('returns correct value', () => {
|
||||||
|
expect(TimeMixin.methods.dateFormat(1612971343)).toEqual('Feb 10, 2021');
|
||||||
|
expect(TimeMixin.methods.dateFormat(1612971343, 'LLL d, yyyy')).toEqual(
|
||||||
|
'Feb 10, 2021'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#shortTimestamp', () => {
|
||||||
|
it('returns correct value', () => {
|
||||||
|
expect(TimeMixin.methods.shortTimestamp('less than a minute ago')).toEqual(
|
||||||
|
'now'
|
||||||
|
);
|
||||||
|
expect(TimeMixin.methods.shortTimestamp(' minute ago')).toEqual('m');
|
||||||
|
expect(TimeMixin.methods.shortTimestamp(' minutes ago')).toEqual('m');
|
||||||
|
expect(TimeMixin.methods.shortTimestamp(' hour ago')).toEqual('h');
|
||||||
|
expect(TimeMixin.methods.shortTimestamp(' hours ago')).toEqual('h');
|
||||||
|
expect(TimeMixin.methods.shortTimestamp(' day ago')).toEqual('d');
|
||||||
|
expect(TimeMixin.methods.shortTimestamp(' days ago')).toEqual('d');
|
||||||
|
expect(TimeMixin.methods.shortTimestamp(' month ago')).toEqual('mo');
|
||||||
|
expect(TimeMixin.methods.shortTimestamp(' months ago')).toEqual('mo');
|
||||||
|
expect(TimeMixin.methods.shortTimestamp(' year ago')).toEqual('y');
|
||||||
|
expect(TimeMixin.methods.shortTimestamp(' years ago')).toEqual('y');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -12,5 +12,30 @@ export default {
|
|||||||
const unixTime = fromUnixTime(time);
|
const unixTime = fromUnixTime(time);
|
||||||
return formatDistanceToNow(unixTime, { addSuffix: true });
|
return formatDistanceToNow(unixTime, { addSuffix: true });
|
||||||
},
|
},
|
||||||
|
dateFormat(time, dateFormat = 'MMM d, yyyy') {
|
||||||
|
const unixTime = fromUnixTime(time);
|
||||||
|
return format(unixTime, dateFormat);
|
||||||
|
},
|
||||||
|
shortTimestamp(time) {
|
||||||
|
const convertToShortTime = time
|
||||||
|
.replace(/about|over|almost|/g, '')
|
||||||
|
.replace('less than a minute ago', 'now')
|
||||||
|
.replace(' minute ago', 'm')
|
||||||
|
.replace(' minutes ago', 'm')
|
||||||
|
.replace('a minute ago', 'm')
|
||||||
|
.replace('an hour ago', 'h')
|
||||||
|
.replace(' hour ago', 'h')
|
||||||
|
.replace(' hours ago', 'h')
|
||||||
|
.replace(' day ago', 'd')
|
||||||
|
.replace('a day ago', 'd')
|
||||||
|
.replace(' days ago', 'd')
|
||||||
|
.replace('a month ago', 'mo')
|
||||||
|
.replace(' months ago', 'mo')
|
||||||
|
.replace(' month ago', 'mo')
|
||||||
|
.replace('a year ago', 'y')
|
||||||
|
.replace(' year ago', 'y')
|
||||||
|
.replace(' years ago', 'y');
|
||||||
|
return convertToShortTime;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
:root {
|
:root {
|
||||||
--white: #fff;
|
--white: #fff;
|
||||||
--white-transparent: rgba(255, 255, 255, 0.9);
|
--white-transparent: rgba(255, 255, 255, 0.9);
|
||||||
|
--black-transparent: rgba(0, 0, 0, 0.9);
|
||||||
|
|
||||||
--w-25: #F5FAFF;
|
--w-25: #F5FAFF;
|
||||||
--w-50: #EBF5FF;
|
--w-50: #EBF5FF;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ json.labels conversation.label_list
|
|||||||
json.muted conversation.muted?
|
json.muted conversation.muted?
|
||||||
json.snoozed_until conversation.snoozed_until
|
json.snoozed_until conversation.snoozed_until
|
||||||
json.status conversation.status
|
json.status conversation.status
|
||||||
|
json.created_at conversation.created_at.to_i
|
||||||
json.timestamp conversation.last_activity_at.to_i
|
json.timestamp conversation.last_activity_at.to_i
|
||||||
json.first_reply_created_at conversation.first_reply_created_at.to_i
|
json.first_reply_created_at conversation.first_reply_created_at.to_i
|
||||||
json.unread_count conversation.unread_incoming_messages.count
|
json.unread_count conversation.unread_incoming_messages.count
|
||||||
|
|||||||
Reference in New Issue
Block a user