Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<textarea id="comments-callback">
<textarea id="comments-callback-with-mentions">
<h2>Welcome to Tiny Comments!</h2>
<p>Please try out this demo of our Tiny Comments premium plugin with @mentions support.</p>
<ol>
Expand Down
284 changes: 158 additions & 126 deletions modules/ROOT/examples/live-demos/comments-callback-with-mentions/index.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,73 @@
import ('https://cdn.jsdelivr.net/npm/@faker-js/faker@9/dist/index.min.js').then(({ faker }) => {
const adminUser = {
id: 'johnsmith',
name: 'John Smith',
fullName: 'John Smith',
description: 'Company Founder',
image: "https://i.pravatar.cc/150?img=11"
const userDb = {
'michaelcook': {
id: 'michaelcook',
name: 'Michael Cook',
fullName: 'Michael Cook',
description: 'Product Owner',
image: "{{imagesdir}}/avatars/michaelcook.png"
},
'kalebwilson': {
id: 'kalebwilson',
name: 'Kaleb Wilson',
fullName: 'Kaleb Wilson',
description: 'Marketing Director',
image: "{{imagesdir}}/avatars/kalebwilson.png"
}
};

const currentUser = {
id: 'jennynichols',
name: 'Jenny Nichols',
fullName: 'Jenny Nichols',
description: 'Marketing Director',
image: "https://i.pravatar.cc/150?img=10"

const currentUid = 'kalebwilson';
const adminUid = 'michaelcook';

const currentUser = userDb[currentUid];
const adminUser = userDb[adminUid];

const now = new Date();
const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000).toISOString();
const anhourago = new Date(now.getTime() - 60 * 60 * 1000).toISOString();

const fillAuthorInfo = (id, fullName, image) => ({
author: id,
authorName: fullName,
authorAvatar: image,
});

const getAuthorInfo = (uid) => {
const user = userDb[uid];
if (user) {
return fillAuthorInfo(user.id, user.fullName, user.image);
}
return {
author: uid,
authorName: uid,
};
};

const conversationDb = {
'mce-conversation_19679600221621399703915': {
uid: 'mce-conversation_19679600221621399703915',
comments: [{
uid: 'mce-conversation_19679600221621399703915',
author: currentUser.id,
authorName: currentUser.fullName,
authorAvatar: currentUser.image,
content: `What do you think about this @${adminUser.id}?`,
createdAt: '2021-05-19T04:48:23.914Z',
modifiedAt: '2021-05-19T04:48:23.914Z'
},
{
...getAuthorInfo(currentUid),
content: `What do you think about this? @${adminUser.id}?`,
createdAt: yesterday,
modifiedAt: yesterday
}, {
uid: 'mce-conversation_19679600221621399703917',
author: adminUser.id,
authorName: adminUser.fullName,
authorAvatar: adminUser.image,
...getAuthorInfo(adminUid),
content: `I think this is a great idea @${currentUser.id}!`,
createdAt: "2024-05-28T12:54:24.126Z",
modifiedAt: "2024-05-28T12:54:24.126Z",
createdAt: anhourago,
modifiedAt: anhourago,
}]
},
'mce-conversation_420304606321716900864126': {
uid: 'mce-conversation_420304606321716900864126',
comments: [{
uid: 'mce-conversation_420304606321716900864126',
author: adminUser.id,
authorName: adminUser.fullName,
authorAvatar: adminUser.image,
...getAuthorInfo(adminUid),
content: `@${currentUser.id} Please revise this sentence, exclamation points are unprofessional!`,
createdAt: '2024-05-28T12:54:24.126Z',
modifiedAt: '2024-05-28T12:54:24.126Z'
createdAt: yesterday,
modifiedAt: anhourago
}]
}
};
Expand Down Expand Up @@ -122,6 +143,10 @@ import ('https://cdn.jsdelivr.net/npm/@faker-js/faker@9/dist/index.min.js').then

const fakeServer = setupFakeServer();

/********************************
* Mentions functions *
********************************/

const mentions_fetch = (query, success) => {
if (!fetchedUsers) {
fetchedUsers = true;
Expand Down Expand Up @@ -162,6 +187,11 @@ import ('https://cdn.jsdelivr.net/npm/@faker-js/faker@9/dist/index.min.js').then
}
};

/********************************
* Tiny Comments functions *
* (must call "done" or "fail") *
********************************/

const tinycomments_create = (req, done, fail) => {
if (req.content === 'fail') {
fail(new Error('Something has gone wrong...'));
Expand All @@ -170,131 +200,132 @@ import ('https://cdn.jsdelivr.net/npm/@faker-js/faker@9/dist/index.min.js').then
conversationDb[uid] = {
uid,
comments: [{
uid,
authorName: currentUser.fullName,
authorAvatar: currentUser.image,
author: currentUser.name,
content: req.content,
createdAt: req.createdAt,
modifiedAt: req.createdAt
uid,
...getAuthorInfo(currentUid),
content: req.content,
createdAt: req.createdAt,
modifiedAt: req.createdAt
}]
};

setTimeout(() => {
done({
conversationUid: uid
});
}, fakeDelay);
setTimeout(() => done({ conversationUid: uid }), fakeDelay);
}
};

const tinycomments_reply = (req, done) => {
const replyUid = 'annotation-' + randomString();
const current = conversationDb[req.conversationUid];
current.comments.push(
{
uid: replyUid,
authorName: currentUser.fullName,
authorAvatar: currentUser.image,
author: currentUser.name,
content: req.content,
createdAt: req.createdAt,
modifiedAt: req.createdAt
}
);

setTimeout(() => {
done({
commentUid: replyUid
});
}, fakeDelay);
conversationDb[req.conversationUid].comments.push({
uid: replyUid,
...getAuthorInfo(currentUid),
content: req.content,
createdAt: req.createdAt,
modifiedAt: req.createdAt
});
setTimeout(() => done({ commentUid: replyUid }), fakeDelay);
};

const tinycomments_delete = (req, done) => {
delete conversationDb[req.conversationUid];

setTimeout(() => {
done({
canDelete: true
});
}, fakeDelay);
if (currentUid === adminUid) { // Replace wth your own logic, e.g. check if user created the conversation
delete conversationDb[req.conversationUid];
setTimeout(() => done({ canDelete: true }), fakeDelay);
} else {
setTimeout(() => done({ canDelete: false, reason: 'Must be admin user' }), fakeDelay);
}
};

const tinycomments_resolve = (req, done) => {
resolvedConversationDb[req.conversationUid] = conversationDb[req.conversationUid];
delete conversationDb[req.conversationUid];

setTimeout(() => {
done({
canResolve: true
});
}, fakeDelay);
const conversation = conversationDb[req.conversationUid];
if (currentUid === conversation.comments[0].author) { // Replace wth your own logic, e.g. check if user has admin priveleges
delete conversationDb[req.conversationUid];
setTimeout(() => done({ canResolve: true }), fakeDelay);
} else {
setTimeout(() => done({ canResolve: false, reason: 'Must be conversation author' }), fakeDelay);
}
};

const tinycomments_delete_comment = (req, done) => {
const current = conversationDb[req.conversationUid];
// Should be supported on browsers ...
current.comments = current.comments.filter((f) => {
return f.uid !== req.commentUid;
const oldcomments = conversationDb[req.conversationUid].comments;
let reason = 'Comment not found';

const newcomments = oldcomments.filter((comment) => {
if (comment.uid === req.commentUid) { // Found the comment to delete
if (currentUid === comment.author) { // Replace with your own logic, e.g. check if user has admin privileges
return false; // Remove the comment
} else {
reason = 'Not authorised to delete this comment'; // Update reason
}
}
return true; // Keep the comment
});

setTimeout(() => {
done({
canDelete: true
});
}, fakeDelay);
if (newcomments.length === oldcomments.length) {
setTimeout(() => done({ canDelete: false, reason }), fakeDelay);
} else {
conversationDb[req.conversationUid].comments = newcomments;
setTimeout(() => done({ canDelete: true }), fakeDelay);
}
};

const tinycomments_edit_comment = (req, done) => {
const current = conversationDb[req.conversationUid];
// Should be supported on browsers ...
current.comments = current.comments.map((f) => {
return f.uid === req.commentUid ? {
...f,
content: req.content,
modifiedAt: new Date().toISOString()
} : f;
const oldcomments = conversationDb[req.conversationUid].comments;
let reason = 'Comment not found';
let canEdit = false;

const newcomments = oldcomments.map((comment) => {
if (comment.uid === req.commentUid) { // Found the comment to delete
if (currentUid === comment.author) { // Replace with your own logic, e.g. check if user has admin privileges
canEdit = true; // User can edit the comment
return { ...comment, content: req.content, modifiedAt: new Date().toISOString() }; // Update the comment
} else {
reason = 'Not authorised to edit this comment'; // Update reason
}
}
return comment; // Keep the comment
});

setTimeout(() => {
done({
canEdit: true
});
}, fakeDelay);

if (canEdit) {
conversationDb[req.conversationUid].comments = newcomments;
setTimeout(() => done({ canEdit }), fakeDelay);
} else {
setTimeout(() => done({ canEdit, reason }), fakeDelay);
}
};

const tinycomments_delete_all = (req, done) => {
Object.keys(conversationDb).forEach((k) => {
delete conversationDb[k];
});

setTimeout(() => {
done({
canDelete: true
});
}, fakeDelay);
const conversation = conversationDb[req.conversationUid];
if (currentUid === conversation.comments[0].author) { // Replace wth your own logic, e.g. check if user has admin priveleges
delete conversationDb[req.conversationUid];
setTimeout(() => done({ canDelete: true }), fakeDelay);
} else {
setTimeout(() => done({ canDelete: false, reason: 'Must be conversation author' }), fakeDelay);
}
};

const tinycomments_lookup = (req, done) => {
setTimeout(() => {
done({
conversation: {
uid: conversationDb[req.conversationUid].uid,
comments: conversationDb[req.conversationUid].comments.slice(0)
uid: conversationDb[req.conversationUid].uid,
comments: [...conversationDb[req.conversationUid].comments]
}
});
}, fakeDelay);
};

const tinycomments_fetch = (_, done) => {
setTimeout(() => done({
conversations: conversationDb
}), fakeDelay);

const tinycomments_fetch = (conversationUids, done) => {
const fetchedConversations = {};
conversationUids.forEach((uid) => {
const conversation = conversationDb[uid];
if (conversation) {
fetchedConversations[uid] = {...conversation};
}
});
setTimeout(() => done({ conversations: fetchedConversations }), fakeDelay);
};


// Read the above `getAuthorInfo` function to see how this could be implemented
const tinycomments_fetch_author_info = (done) => done(getAuthorInfo(currentUid));

tinymce.init({
selector: 'textarea#comments-callback',
selector: 'textarea#comments-callback-with-mentions',
license_key: 'gpl',
toolbar: 'addcomment showcomments code | bold italic underline',
menubar: 'file edit view insert format tools tc help',
Expand Down Expand Up @@ -331,5 +362,6 @@ import ('https://cdn.jsdelivr.net/npm/@faker-js/faker@9/dist/index.min.js').then
tinycomments_delete_comment,
tinycomments_edit_comment,
tinycomments_fetch,
tinycomments_fetch_author_info
});
});
Loading