Merge branch 'develop' of git.digitaltelepresence.com:digital-telepresence/dtp-base into develop

master
rob 2 years ago
commit 7c62cf5515

@ -168,16 +168,11 @@ class ChatController extends SiteController {
switch (response) {
case 'accept':
await chatService.acceptRoomInvite(res.locals.invite);
displayList.showNotification(
`Chat room invite accepted`,
'success',
'top-center',
5000,
);
displayList.navigateTo(`/chat/room/${res.locals.invite.room._id}`);
break;
case 'reject':
await chatService.acceptRoomInvite(res.locals.invite);
await chatService.rejectRoomInvite(res.locals.invite);
displayList.showNotification(
`Chat room invite rejected`,
'success',

@ -64,10 +64,11 @@ class HomeController extends SiteController {
}
async getHome (req, res, next) {
const { announcement: announcementService, post: postService } = this.dtp.services;
const { announcement: announcementService, hive: hiveService, post: postService } = this.dtp.services;
try {
res.locals.announcements = await announcementService.getLatest(req.user);
res.locals.featuredPosts = await postService.getFeaturedPosts(3);
res.locals.constellationTimeline = await hiveService.getConstellationTimeline(req.user, { skip: 0, cpp: 5 });
res.locals.pagination = this.getPaginationParameters(req, 20);
res.locals.posts = await postService.getPosts(res.locals.pagination);

@ -7,10 +7,13 @@
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const RECIPIENT_TYPE_LIST = ['User','CoreUser'];
const EMITTER_TYPE_LIST = ['User','CoreUser','OAuth2Client'];
const KaleidoscopeEventSchema = new Schema({
created: { type: Date, default: Date.now, required: true, index: -1, expires: '30d' },
recipientType: { type: String, enum: RECIPIENT_TYPE_LIST },
recipient: { type: Schema.ObjectId, index: 1, refPath: 'recipientType' },
action: { type: String, required: true, lowercase: true },
label: { type: String },
content: { type: String },

@ -265,6 +265,7 @@ class ChatService extends SiteService {
skip: 0,
cpp: 50
}, pagination);
const totalPublicRooms = await ChatRoom.countDocuments({ visibility: 'public' });
const rooms = await ChatRoom
.find({ visibility: 'public' })
.sort({ lastActivity: -1, created: -1 })
@ -272,7 +273,7 @@ class ChatService extends SiteService {
.limit(pagination.cpp)
.populate(this.populateChatRoom)
.lean();
return rooms;
return { rooms, totalPublicRooms };
}
async getRoomById (roomId) {
@ -367,6 +368,8 @@ class ChatService extends SiteService {
room.owner.type = room.ownerType;
const event = {
recipientType: member.type,
recipient: member._id,
action: 'room-invite-create',
emitter: room.owner,
label: 'Chat Room Invitation',
@ -396,6 +399,19 @@ class ChatService extends SiteService {
}
async acceptRoomInvite (invite) {
if ((invite.status === 'accepted') ||
(invite.room.members.find((member) => member.member._id.equals(invite.member._id)))) {
throw SiteError(400, "You have already accepted membership in this room.");
}
this.log.debug('updating chat invite', { inviteId: invite._id, status: 'accepted' });
await ChatRoomInvite.updateOne(
{ _id: invite._id },
{
$set: { status: 'accepted' },
},
);
this.log.info('accepting invite to chat room', {
roomId: invite.room._id,
memberId: invite.member._id,
@ -403,7 +419,7 @@ class ChatService extends SiteService {
await ChatRoom.updateOne(
{ _id: invite.room._id },
{
$addToSet: {
$push: {
members: {
memberType: invite.memberType,
member: invite.member._id,
@ -411,14 +427,6 @@ class ChatService extends SiteService {
},
},
);
this.log.info('updating chat invite', { inviteId: invite._id, status: 'accepted' });
await ChatRoomInvite.updateOne(
{ _id: invite._id },
{
$set: { status: 'accepted' },
},
);
}
async rejectRoomInvite (invite) {

@ -188,6 +188,11 @@ class HiveService extends SiteService {
const event = new KaleidoscopeEvent();
event.created = NOW;
if (eventDefinition.recipientType && eventDefinition.recipient) {
event.recipientType = eventDefinition.recipientType;
event.recipient = mongoose.Types.ObjectId(eventDefinition.recipient);
}
event.action = striptags(eventDefinition.action.trim().toLowerCase());
if (eventDefinition.label) {
event.label = striptags(eventDefinition.label.trim());
@ -246,6 +251,28 @@ class HiveService extends SiteService {
return event.toObject();
}
async getConstellationTimeline (user, pagination) {
const totalEventCount = await KaleidoscopeEvent.estimatedDocumentCount();
const job = { };
if (user) {
job.search = {
$or: [
{ recipient: { $exists: false } },
{ recipient: user._id },
],
};
} else {
job.search = { recipient: { $exists: false } };
}
const events = await KaleidoscopeEvent
.find(job.search)
.sort({ created: -1 })
.skip(pagination.skip)
.limit(pagination.cpp)
.lean();
return { events, totalEventCount };
}
}
module.exports = {

@ -277,26 +277,38 @@ class UserService extends SiteService {
}
async updateSettings (user, userDefinition) {
const { crypto: cryptoService } = this.dtp.services;
const updateOp = { $set: { }, $unset: { } };
// strip characters we don't want to allow in username
userDefinition.username = striptags(userDefinition.username.trim().replace(/[^A-Za-z0-9\-_]/gi, ''));
const username_lc = userDefinition.username.toLowerCase();
updateOp.$set.username = striptags(userDefinition.username.trim().replace(/[^A-Za-z0-9\-_]/gi, ''));
if (!updateOp.$set.username || (updateOp.$set.username.length === 0)) {
throw new SiteError(400, 'Must include a username');
}
updateOp.$set.username_lc = updateOp.$set.username.toLowerCase();
userDefinition.displayName = striptags(userDefinition.displayName.trim());
userDefinition.bio = striptags(userDefinition.bio.trim());
if (userDefinition.displayName && (userDefinition.displayName.length > 0)) {
updateOp.$set.displayName = striptags(userDefinition.displayName.trim());
} else {
updateOp.$unset.displayName = 1;
}
this.log.info('updating user settings', { userDefinition });
await User.updateOne(
{ _id: user._id },
{
$set: {
username: userDefinition.username,
username_lc,
displayName: userDefinition.displayName,
bio: userDefinition.bio,
theme: userDefinition.theme || 'dtp-light',
},
},
);
if (userDefinition.bio && (userDefinition.bio.length > 0)) {
updateOp.$set.bio = striptags(userDefinition.bio.trim());
} else {
updateOp.$unset.bio = 1;
}
if (userDefinition.password && userDefinition.password.length > 0) {
updateOp.$set.passwordSalt = uuidv4();
updateOp.$set.password = cryptoService.maskPassword(updateOp.$set.passwordSalt, userDefinition.password);
}
updateOp.$set.theme = userDefinition.theme || 'dtp-light';
this.log.info('updating user settings', { userId: user._id });
await User.updateOne({ _id: user._id }, updateOp);
}
async authenticate (account, options) {

@ -5,11 +5,13 @@ block content
#site-chat-container.uk-flex.uk-flex-column.uk-height-1-1
.chat-menubar.uk-padding-small
div(uk-grid).uk-grid-small
div(uk-grid).uk-grid-small.uk-flex-middle
.uk-width-auto
img(src=`/img/icon/${site.domainKey}/icon-48x48.png`, alt=`${site.name} icon`)
.uk-width-expand
h1.uk-margin-remove #{site.name} Chat Timeline
.uk-width-auto
a(href='/chat/room').uk-button.uk-button-secondary.uk-button-small.uk-border-rounded Public Rooms
.chat-content-wrapper
#chat-message-list-wrapper.uk-height-1-1
@ -17,6 +19,4 @@ block content
each message in timeline
+renderChatMessage(message, { includeRoomInfo: true })
.chat-message-menu
button(type="button", onclick="return dtp.app.chat.resumeChatScroll(event);").chat-scroll-return Resume scrolling
//- pre= JSON.stringify(userTimeline, null, 2)
button(type="button", onclick="return dtp.app.chat.resumeChatScroll(event);").chat-scroll-return Resume scrolling

@ -1,29 +1,40 @@
extends ../layouts/room
block content
include ../../components/pagination-bar
mixin renderRoomTile (room)
div(data-room-id= room._id, data-room-name= room.name).uk-tile.uk-tile-default.uk-tile-small
.uk-tile-body
div(uk-grid).uk-grid-small
.uk-width-auto
.uk-width-expand
.uk-margin-small
div(title= room.name).uk-text-bold.uk-text-truncate= room.name
.uk-text-small.uk-text-truncate= room.description
div(uk-grid).uk-grid-small.uk-text-small.uk-text-muted.no-select
.uk-width-expand
a(href= getUserProfileUrl(room.owner))= room.owner.username
.uk-width-auto
span
i.fas.fa-users
span.uk-margin-small-left= formatCount(room.members.length)
a(href=`/chat/room/${room._id}`).uk-display-block.uk-link-reset
div(data-room-id= room._id, data-room-name= room.name).uk-tile.uk-tile-default.uk-tile-small
.uk-tile-body
div(uk-grid).uk-grid-small
.uk-width-auto
+renderProfileIcon(room.owner)
.uk-width-expand
.uk-margin-small
div(title= room.name).uk-text-bold.uk-text-truncate= room.name
.uk-text-small.uk-text-truncate= room.description
div(uk-grid).uk-grid-small.uk-text-small.uk-text-muted.no-select
.uk-width-expand
a(href= getUserProfileUrl(room.owner))= room.owner.username
.uk-width-auto
span
i.fas.fa-users
span.uk-margin-small-left= formatCount(room.members.length)
.uk-height-1-1.uk-overflow-auto
.uk-card.uk-card-default.uk-card-small
.uk-card-header
h1.uk-card-title Public Chat Rooms
h1 Public Rooms
div(uk-grid)
each room in publicRooms
.uk-width-1-3
+renderRoomTile(room)
.uk-card-body
if Array.isArray(publicRooms.rooms) && (publicRooms.rooms.length > 0)
div(uk-grid)
each room in publicRooms.rooms
div(class="uk-width-1-1 uk-width-1-2@m uk-width-1-3@l")
+renderRoomTile(room)
else
div #{site.name} has no public rooms.
pre= JSON.stringify(publicRooms, null, 2)
.uk-card-footer
+renderPaginationBar('/chat/room', publicRooms.totalRoomCount)

@ -16,6 +16,9 @@ nav(uk-navbar).uk-navbar-container.uk-position-fixed.uk-position-top
li(class={ 'uk-active': currentView === 'home' })
a(href="/", title= "Home")
+renderButtonIcon('fa-home', 'Home')
li(class={ 'uk-active': currentView === 'chat' })
a(href="/chat", title= "chat")
+renderButtonIcon('fa-comment-alt', 'Chat')
if site.shingWidgetKey && site.shingChannelSlug
li(class={ 'uk-active': currentView === 'venue' })

Loading…
Cancel
Save