* Add SiteConfig.feed_pinned_article and validation * Display pinned article at the top of feed * Add (basic) functionality to pin/unpin post * Admins can pin other users posts as well * Hide the button if looking at the non pinned post * Add pinned/unpinned snackbar message * Rename SiteConfig usage to Settings::General * Add pinned article to the Admin articles index * Show the pin post button when there's no pinned article * Move pinning to a separate controller * Fix SiteConfig reference * Hide PinController actions to unauthorized users * PinnedArticlesController#show action and refactor some of the code * Add Modal interaction * Fix modal-pinned checkbox interaction * Fixed pin/unpin post * Add ArticleDecorator#pinned? specs * Add PinnedArticlePolicy and PinnedArticlesController specs * Add ability to actually pin an article from the admin after submit * Add partial Cypress pin/unpin spec * Fix pinned article and add basic Cypress interaction tests * Add Crayons styling to modal * Only render the pinned article on the default Feed page * Use persisted? * Add some comments * Update app/javascript/articles/Article.jsx Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Update app/javascript/packs/homePageFeed.jsx Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Fix Cypress tests * Update app/javascript/admin/controllers/article_controller.js Co-authored-by: Ridhwana <Ridhwana.Khan16@gmail.com> * Fix pinning in article show page * Used PinnedArticle domain model * Fix spec * Update cypress/integration/adminFlows/articles/pinArticle.spec.js Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Update cypress/integration/adminFlows/articles/pinArticle.spec.js Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Update cypress/integration/adminFlows/articles/pinArticle.spec.js Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Update cypress/integration/adminFlows/articles/pinArticle.spec.js Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Update cypress/integration/adminFlows/articles/pinArticle.spec.js Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Update cypress/integration/articleFlows/pinArticle.spec.js Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Update cypress/integration/articleFlows/pinArticle.spec.js Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Update app/views/admin/articles/index.html.erb Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Fix merge woes * Add missing article pin post flows * Add missing admin article flows * Add Unpin to Admin as well * Add Audit::Log entries for pin/unpin actions * Update app/controllers/stories/feeds_controller.rb Co-authored-by: Michael Kohl <citizen428@dev.to> * Do not rate limit in E2E tests * Use .find instead of .filter * Rename ArticleIdValidator to ExistingArticleIdValidator * Treat draft and deleted articles the same * Make sure posts can be pinned after the pinned article is unpublished or deleted * Use .get directly * Fix spec and fix PinnedArticlesController#show * Strengthen pinArticle Cypress tests * Add Cypress test heading guard * Add another Cypress test heading guard * Remove duplicate validator * Try using the Tools: header instead of the article title Co-authored-by: Suzanne Aitchison <suzanne@forem.com> Co-authored-by: Ridhwana <Ridhwana.Khan16@gmail.com> Co-authored-by: Michael Kohl <citizen428@dev.to>
127 lines
4.3 KiB
JavaScript
127 lines
4.3 KiB
JavaScript
/* global filterXSS */
|
|
function initializeProfileImage(user) {
|
|
if (!document.getElementById('comment-primary-user-profile--avatar')) return;
|
|
document.getElementById('comment-primary-user-profile--avatar').src =
|
|
user.profile_image_90;
|
|
}
|
|
|
|
function addRelevantButtonsToArticle(user) {
|
|
var articleContainer = document.getElementById('article-show-container');
|
|
if (articleContainer) {
|
|
let actions = [];
|
|
const published = JSON.parse(articleContainer.dataset.published);
|
|
|
|
if (parseInt(articleContainer.dataset.authorId, 10) === user.id) {
|
|
actions.push(
|
|
`<a class="crayons-btn crayons-btn--s crayons-btn--secondary" href="${articleContainer.dataset.path}/edit" rel="nofollow">Edit</a>`,
|
|
);
|
|
|
|
let clickToEditButton = document.getElementById('author-click-to-edit');
|
|
if (clickToEditButton) {
|
|
clickToEditButton.style.display = 'inline-block';
|
|
}
|
|
|
|
if (published === true) {
|
|
actions.push(
|
|
`<a class="crayons-btn crayons-btn--s crayons-btn--secondary ml-1" href="${articleContainer.dataset.path}/manage" rel="nofollow">Manage</a>`,
|
|
);
|
|
}
|
|
|
|
actions.push(
|
|
`<a class="crayons-btn crayons-btn--s crayons-btn--secondary ml-1" href="${articleContainer.dataset.path}/stats" rel="nofollow">Stats</a>`,
|
|
);
|
|
}
|
|
|
|
const { articleId, pinnedArticleId } = articleContainer.dataset;
|
|
|
|
// we hide the buttons for draft articles, for non admins and
|
|
// if there's already a pinned post different from the current one
|
|
if (
|
|
published &&
|
|
user.admin &&
|
|
(articleId === pinnedArticleId || !pinnedArticleId)
|
|
) {
|
|
const isArticlePinned = articleContainer.hasAttribute('data-pinned');
|
|
const { pinPath } = articleContainer.dataset;
|
|
|
|
actions.push(
|
|
`<button
|
|
id="js-${isArticlePinned ? 'unpin' : 'pin'}-article"
|
|
class="crayons-btn crayons-btn--s crayons-btn--secondary ml-1"
|
|
data-path="${pinPath}"
|
|
data-article-id="${articleId}">${
|
|
isArticlePinned ? 'Unpin' : 'Pin'
|
|
} Post</button>`,
|
|
);
|
|
}
|
|
|
|
document.getElementById('action-space').innerHTML = actions.join('');
|
|
}
|
|
}
|
|
|
|
function addRelevantButtonsToComments(user) {
|
|
if (document.getElementById('comments-container')) {
|
|
// buttons are actually <span>'s
|
|
var settingsButts = document.getElementsByClassName('comment-actions');
|
|
|
|
for (let i = 0; i < settingsButts.length; i += 1) {
|
|
let butt = settingsButts[i];
|
|
const { action, commentableUserId, userId } = butt.dataset;
|
|
if (parseInt(userId, 10) === user.id && action === 'settings-button') {
|
|
butt.innerHTML =
|
|
'<a href="' +
|
|
butt.dataset.path +
|
|
'" rel="nofollow" class="crayons-link crayons-link--block" data-no-instant>Settings</a>';
|
|
butt.classList.remove('hidden');
|
|
butt.classList.add('block');
|
|
}
|
|
|
|
if (
|
|
action === 'hide-button' &&
|
|
parseInt(commentableUserId, 10) === user.id
|
|
) {
|
|
butt.classList.remove('hidden');
|
|
butt.classList.add('block');
|
|
}
|
|
}
|
|
|
|
if (user.trusted) {
|
|
var modButts = document.getElementsByClassName('mod-actions');
|
|
for (let i = 0; i < modButts.length; i += 1) {
|
|
let butt = modButts[i];
|
|
if (butt.classList.contains('mod-actions-comment-button')) {
|
|
butt.innerHTML =
|
|
'<a href="' +
|
|
butt.dataset.path +
|
|
'" rel="nofollow" class="crayons-link crayons-link--block">Moderate</a>';
|
|
}
|
|
butt.className = 'mod-actions';
|
|
butt.classList.remove('hidden');
|
|
butt.classList.add('block');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function setCurrentUserToNavBar(user) {
|
|
const userNavLink = document.getElementById('first-nav-link');
|
|
userNavLink.href = `/${user.username}`;
|
|
userNavLink.getElementsByTagName('span')[0].textContent = user.name;
|
|
userNavLink.getElementsByTagName(
|
|
'small',
|
|
)[0].textContent = `@${user.username}`;
|
|
document.getElementById('nav-profile-image').src = user.profile_image_90;
|
|
if (user.admin) {
|
|
document
|
|
.getElementsByClassName('js-header-menu-admin-link')[0]
|
|
.classList.remove('hidden');
|
|
}
|
|
}
|
|
|
|
function initializeBaseUserData() {
|
|
const user = userData();
|
|
setCurrentUserToNavBar(user);
|
|
initializeProfileImage(user);
|
|
addRelevantButtonsToArticle(user);
|
|
addRelevantButtonsToComments(user);
|
|
}
|