diff --git a/.env b/.env index 9fc7c719..df8553a6 100644 --- a/.env +++ b/.env @@ -19,3 +19,4 @@ REFRESH_ACCESS_TOKEN_ENDPOINT='' SEGMENT_KEY='' SITE_NAME='' USER_INFO_COOKIE_NAME='' +FEEDBACK_FORM_URL='' diff --git a/.env.development b/.env.development index 5266dd5d..c1ee024f 100644 --- a/.env.development +++ b/.env.development @@ -20,3 +20,4 @@ REFRESH_ACCESS_TOKEN_ENDPOINT='http://localhost:18000/login_refresh' SEGMENT_KEY='' SITE_NAME=localhost USER_INFO_COOKIE_NAME='edx-user-info' +FEEDBACK_FORM_URL='' diff --git a/.env.test b/.env.test index e6a9bc01..553e1106 100644 --- a/.env.test +++ b/.env.test @@ -18,3 +18,4 @@ REFRESH_ACCESS_TOKEN_ENDPOINT='http://localhost:18000/login_refresh' SEGMENT_KEY='' SITE_NAME=localhost USER_INFO_COOKIE_NAME='edx-user-info' +FEEDBACK_FORM_URL='' diff --git a/src/components/Feedback/index.jsx b/src/components/Feedback/index.jsx new file mode 100644 index 00000000..a8724edc --- /dev/null +++ b/src/components/Feedback/index.jsx @@ -0,0 +1,34 @@ +import React from 'react'; + +import { ensureConfig, getConfig } from '@edx/frontend-platform'; +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +import { Hyperlink } from '@edx/paragon'; + +import messages from './messages'; + +ensureConfig(['FEEDBACK_FORM_URL'], 'Feedback'); + +const Feedback = ({ intl, ...props }) => { + const formUrl = getConfig().FEEDBACK_FORM_URL; + + return ( + formUrl && ( + + {intl.formatMessage(messages.feedbackLink)} + + ) + ); +}; + +Feedback.propTypes = { + intl: intlShape.isRequired, +}; + +export default injectIntl(Feedback); diff --git a/src/components/Feedback/messages.js b/src/components/Feedback/messages.js new file mode 100644 index 00000000..3f92792a --- /dev/null +++ b/src/components/Feedback/messages.js @@ -0,0 +1,11 @@ +import { defineMessages } from '@edx/frontend-platform/i18n'; + +const messages = defineMessages({ + feedbackLink: { + id: 'components.feedbackLink', + defaultMessage: 'Give Feedback', + description: 'Alt description for feedback button for give feedback.', + }, +}); + +export default messages; diff --git a/src/discussions/discussions-home/DiscussionsHome.test.jsx b/src/discussions/discussions-home/DiscussionsHome.test.jsx index d7e56170..dfa49f13 100644 --- a/src/discussions/discussions-home/DiscussionsHome.test.jsx +++ b/src/discussions/discussions-home/DiscussionsHome.test.jsx @@ -3,7 +3,7 @@ import { IntlProvider } from 'react-intl'; import { Context as ResponsiveContext } from 'react-responsive'; import { MemoryRouter } from 'react-router'; -import { initializeMockApp } from '@edx/frontend-platform'; +import { getConfig, initializeMockApp, setConfig } from '@edx/frontend-platform'; import { AppProvider } from '@edx/frontend-platform/react'; import { initializeStore } from '../../store'; @@ -38,6 +38,11 @@ describe('DiscussionsHome', () => { }, }); + setConfig({ + ...getConfig(), + FEEDBACK_FORM_URL: 'test-url', + }); + store = initializeStore(); }); @@ -50,22 +55,19 @@ describe('DiscussionsHome', () => { await screen.findByTestId('topics-view'); }); - test('full view should hide close button', async () => { + test('full view should hide close button and display feedback button', async () => { renderComponent(`/${courseId}/topics`); - expect(screen.queryByText(navigationBarMessages.allTopics.defaultMessage)) - .toBeInTheDocument(); - expect(screen.queryByRole('button', { name: 'Close' })) - .not - .toBeInTheDocument(); + + expect(screen.queryByText(navigationBarMessages.allTopics.defaultMessage)).toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Close' })).not.toBeInTheDocument(); + expect(screen.queryByText('Give Feedback')).toBeInTheDocument(); }); - test('in-context view should show close button', async () => { + test('in-context view should show close button and display feedback button', async () => { renderComponent(`/${courseId}/topics?inContext`); - expect(screen.queryByText(navigationBarMessages.allTopics.defaultMessage)) - .not - .toBeInTheDocument(); - expect(screen.queryByRole('button', { name: 'Close' })) - .toBeInTheDocument(); + expect(screen.queryByText(navigationBarMessages.allTopics.defaultMessage)).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Close' })).toBeInTheDocument(); + expect(screen.queryByText('Give Feedback')).toBeInTheDocument(); }); }); diff --git a/src/discussions/posts/post-actions-bar/PostActionsBar.jsx b/src/discussions/posts/post-actions-bar/PostActionsBar.jsx index 4510953c..bed6dfb2 100644 --- a/src/discussions/posts/post-actions-bar/PostActionsBar.jsx +++ b/src/discussions/posts/post-actions-bar/PostActionsBar.jsx @@ -11,6 +11,7 @@ import { } from '@edx/paragon'; import { Close } from '@edx/paragon/icons'; +import Feedback from '../../../components/Feedback'; import { Routes } from '../../../data/constants'; import { DiscussionContext } from '../../common/context'; import { discussionsPath } from '../../utils'; @@ -29,6 +30,7 @@ function PostActionsBar({ const handleCloseInContext = () => null; return (
+ {!inContext && ( <>