Compare commits
6 Commits
open-relea
...
djoy/discu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c049e391fe | ||
|
|
3e82152ae7 | ||
|
|
4d2bd81bf0 | ||
|
|
aca45fb26e | ||
|
|
d13bb04648 | ||
|
|
8dc7593780 |
16
docs/decisions/0009-discussions-integration.md
Normal file
16
docs/decisions/0009-discussions-integration.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Discussions Integration
|
||||||
|
|
||||||
|
The discussions project will ultimately need to embed code from a separate micro-frontend into frontend-app-learning in order to render in-context discussions. In-context, in this case, means as a sidebar to unit-level content. The idea is that the frontend-app-discussions MFE would have routes that render unit-specific discussions forum as a companion/sidebar to the main unit content.
|
||||||
|
|
||||||
|
This ADR describes some design considerations for this integration.
|
||||||
|
|
||||||
|
This integration is a forerunner to a broader project around the implementation of "experience plugins" which would allow us to load code across micro-frontends without an iframe. That said, that project hasn't kicked off yet, so in the meantime we'd like to move forward with a simple iframe-based approach, very similar to how we load the unit content from LMS.
|
||||||
|
|
||||||
|
Furthermore, we will need to revisit this if it ever becomes the case that an LTI-based discussions provider implements in-context discussions. Our approach should ideally be roughly compatible with LTI concepts and techniques, though I'd strongly suggest we _don't_ build anything LTI-specific for the foreseeable future.
|
||||||
|
|
||||||
|
The suggested implementation involves:
|
||||||
|
|
||||||
|
- Updating the sequence metadata API to include information about whether a particular unit should load in-context discussions. For now, this could take the form of a `discussions_url` added to the unit objects inside the `items` array. Longer term we'll want a way to signal to the frontend-app-learning MFE the plugins that should be available on the page, but that likely will come from some other API. I don't think we should worry about that broader plugin configuration as part of this.
|
||||||
|
- Adding a new `InContextSidebar` React component to frontend-app-learning to house the discussions integration. The medium to long-term goal is that discussions will not be the only experience plugin loaded in this sidebar, so it would be appropriate to add a thin layer of abstraction between the components that render the discussions iframe and the components that handle the sidebar's behavior.
|
||||||
|
- Have the discussions iframe load the page at `discussions_url`
|
||||||
|
- If necessary, use a postMessage-based API to communicate into the iframe and pass additional data into it. I don't know of a use-case for this for the discussions project, but wanted to mention it. The schema of these messages would ideally be LTI-friendly, though the LTI specification doesn't have a lot to say about a postMessage schema. This document suggests a reasonable message schema: https://github.com/bracken/lti_messaging
|
||||||
@@ -96,6 +96,7 @@ function SequenceLink({
|
|||||||
day="numeric"
|
day="numeric"
|
||||||
month="short"
|
month="short"
|
||||||
year="numeric"
|
year="numeric"
|
||||||
|
hour12={false}
|
||||||
timeZoneName="short"
|
timeZoneName="short"
|
||||||
value={due}
|
value={due}
|
||||||
{...timezoneFormatArgs}
|
{...timezoneFormatArgs}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ function CourseEndAlert({ payload }) {
|
|||||||
day="numeric"
|
day="numeric"
|
||||||
month="short"
|
month="short"
|
||||||
year="numeric"
|
year="numeric"
|
||||||
|
hour12={false}
|
||||||
timeZoneName="short"
|
timeZoneName="short"
|
||||||
value={endDate}
|
value={endDate}
|
||||||
{...timezoneFormatArgs}
|
{...timezoneFormatArgs}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ function CourseStartAlert({ payload }) {
|
|||||||
day="numeric"
|
day="numeric"
|
||||||
month="short"
|
month="short"
|
||||||
year="numeric"
|
year="numeric"
|
||||||
|
hour12={false}
|
||||||
timeZoneName="short"
|
timeZoneName="short"
|
||||||
value={startDate}
|
value={startDate}
|
||||||
{...timezoneFormatArgs}
|
{...timezoneFormatArgs}
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ function CourseCelebration({ intl }) {
|
|||||||
certificateData,
|
certificateData,
|
||||||
end,
|
end,
|
||||||
linkedinAddToProfileUrl,
|
linkedinAddToProfileUrl,
|
||||||
marketingUrl,
|
|
||||||
offer,
|
offer,
|
||||||
org,
|
org,
|
||||||
relatedPrograms,
|
relatedPrograms,
|
||||||
@@ -288,8 +287,7 @@ function CourseCelebration({ intl }) {
|
|||||||
{intl.formatMessage(messages.congratulationsHeader)}
|
{intl.formatMessage(messages.congratulationsHeader)}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 p-0 font-weight-normal lead text-center">
|
<div className="col-12 p-0 font-weight-normal lead text-center">
|
||||||
{intl.formatMessage(messages.completedCourseHeader)}
|
{intl.formatMessage(messages.shareHeader)}
|
||||||
{marketingUrl && ` ${intl.formatMessage(messages.shareMessage)}`}
|
|
||||||
<SocialIcons
|
<SocialIcons
|
||||||
analyticsId="edx.ui.lms.course_exit.social_share.clicked"
|
analyticsId="edx.ui.lms.course_exit.social_share.clicked"
|
||||||
className="mt-2"
|
className="mt-2"
|
||||||
|
|||||||
@@ -35,10 +35,6 @@ const messages = defineMessages({
|
|||||||
defaultMessage: 'Sample certificate',
|
defaultMessage: 'Sample certificate',
|
||||||
description: 'Alt text used to describe an image of a certificate',
|
description: 'Alt text used to describe an image of a certificate',
|
||||||
},
|
},
|
||||||
completedCourseHeader: {
|
|
||||||
id: 'courseCelebration.completedCourseHeader',
|
|
||||||
defaultMessage: 'You have completed your course.',
|
|
||||||
},
|
|
||||||
congratulationsHeader: {
|
congratulationsHeader: {
|
||||||
id: 'courseCelebration.congratulationsHeader',
|
id: 'courseCelebration.congratulationsHeader',
|
||||||
defaultMessage: 'Congratulations!',
|
defaultMessage: 'Congratulations!',
|
||||||
@@ -131,9 +127,9 @@ const messages = defineMessages({
|
|||||||
defaultMessage: 'Search our catalog',
|
defaultMessage: 'Search our catalog',
|
||||||
description: 'First part of a sentence that continues afterward',
|
description: 'First part of a sentence that continues afterward',
|
||||||
},
|
},
|
||||||
shareMessage: {
|
shareHeader: {
|
||||||
id: 'courseCelebration.shareMessage',
|
id: 'courseCelebration.shareHeader',
|
||||||
defaultMessage: 'Share your success on social media or email.',
|
defaultMessage: 'You have completed your course. Share your success on social media or email.',
|
||||||
},
|
},
|
||||||
socialMessage: {
|
socialMessage: {
|
||||||
id: 'courseExit.social.shareCompletionMessage',
|
id: 'courseExit.social.shareCompletionMessage',
|
||||||
|
|||||||
@@ -23,20 +23,6 @@ import { MMP2PLockPaywall } from '../../../experiments/mm-p2p';
|
|||||||
|
|
||||||
const LockPaywall = React.lazy(() => import('./lock-paywall'));
|
const LockPaywall = React.lazy(() => import('./lock-paywall'));
|
||||||
|
|
||||||
/**
|
|
||||||
* Feature policy for iframe, allowing access to certain courseware-related media.
|
|
||||||
*
|
|
||||||
* We must use the wildcard (*) origin for each feature, as courseware content
|
|
||||||
* may be embedded in external iframes. Notably, xblock-lti-consumer is a popular
|
|
||||||
* block that iframes external course content.
|
|
||||||
|
|
||||||
* This policy was selected in conference with the edX Security Working Group.
|
|
||||||
* Changes to it should be vetted by them (security@edx.org).
|
|
||||||
*/
|
|
||||||
const IFRAME_FEATURE_POLICY = (
|
|
||||||
'microphone *; camera *; midi *; geolocation *; encrypted-media *'
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We discovered an error in Firefox where - upon iframe load - React would cease to call any
|
* We discovered an error in Firefox where - upon iframe load - React would cease to call any
|
||||||
* useEffect hooks until the user interacts with the page again. This is particularly confusing
|
* useEffect hooks until the user interacts with the page again. This is particularly confusing
|
||||||
@@ -169,7 +155,7 @@ function Unit({
|
|||||||
: (
|
: (
|
||||||
<iframe
|
<iframe
|
||||||
title={modalOptions.title}
|
title={modalOptions.title}
|
||||||
allow={IFRAME_FEATURE_POLICY}
|
allow="microphone *; camera *; midi *; geolocation *; encrypted-media *"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
src={modalOptions.url}
|
src={modalOptions.url}
|
||||||
style={{
|
style={{
|
||||||
@@ -192,7 +178,6 @@ function Unit({
|
|||||||
id="unit-iframe"
|
id="unit-iframe"
|
||||||
title={unit.title}
|
title={unit.title}
|
||||||
src={iframeUrl}
|
src={iframeUrl}
|
||||||
allow={IFRAME_FEATURE_POLICY}
|
|
||||||
allowFullScreen
|
allowFullScreen
|
||||||
height={iframeHeight}
|
height={iframeHeight}
|
||||||
scrolling="no"
|
scrolling="no"
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faCheck } from '@fortawesome/free-solid-svg-icons';
|
import { faLock } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||||
import {
|
|
||||||
Alert, Button, Icon,
|
|
||||||
} from '@edx/paragon';
|
|
||||||
import { Locked } from '@edx/paragon/icons';
|
|
||||||
import messages from './messages';
|
import messages from './messages';
|
||||||
import certificateLocked from '../../../../generic/assets/edX_locked_certificate.png';
|
import VerifiedCert from '../../../../generic/assets/edX_certificate.png';
|
||||||
import { useModel } from '../../../../generic/model-store';
|
import { useModel } from '../../../../generic/model-store';
|
||||||
import './LockPaywall.scss';
|
|
||||||
|
|
||||||
function LockPaywall({
|
function LockPaywall({
|
||||||
intl,
|
intl,
|
||||||
@@ -46,128 +42,33 @@ function LockPaywall({
|
|||||||
pageName: 'in_course',
|
pageName: 'in_course',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const lockIcon = (
|
|
||||||
<Icon
|
|
||||||
className="float-left"
|
|
||||||
src={Locked}
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
const verifiedCertLink = (
|
|
||||||
<Alert.Link
|
|
||||||
href="https://www.edx.org/verified-certificate"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{intl.formatMessage(messages['learn.lockPaywall.list.bullet1.linktext'])}
|
|
||||||
</Alert.Link>
|
|
||||||
);
|
|
||||||
|
|
||||||
const gradedAssignments = (
|
|
||||||
<span className="font-weight-bold">
|
|
||||||
{intl.formatMessage(messages['learn.lockPaywall.list.bullet2.boldtext'])}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
const fullAccess = (
|
|
||||||
<span className="font-weight-bold">
|
|
||||||
{intl.formatMessage(messages['learn.lockPaywall.list.bullet3.boldtext'])}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
const nonProfit = (
|
|
||||||
<span className="font-weight-bold">
|
|
||||||
{intl.formatMessage(messages['learn.lockPaywall.list.bullet4.boldtext'])}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Alert variant="light" aria-live="off">
|
<div className="border border-gray rounded d-flex justify-content-between mt-2 p-3">
|
||||||
<div className="row">
|
<div>
|
||||||
<div className="col-auto px-0">
|
<h4 className="font-weight-bold mb-2">
|
||||||
{lockIcon}
|
<FontAwesomeIcon icon={faLock} className="text-black mr-2 ml-1" style={{ fontSize: '2rem' }} />
|
||||||
</div>
|
<span>{intl.formatMessage(messages['learn.lockPaywall.title'])}</span>
|
||||||
|
</h4>
|
||||||
<div className="col">
|
<p className="mb-0">
|
||||||
<h4 aria-level="3">
|
<span>{intl.formatMessage(messages['learn.lockPaywall.content'])}</span>
|
||||||
<span>{intl.formatMessage(messages['learn.lockPaywall.title'])}</span>
|
|
||||||
</h4>
|
<a className="lock_paywall_upgrade_link" href={upgradeUrl} onClick={logClick}>
|
||||||
|
|
||||||
<div className="mb-2 upgrade-intro">
|
|
||||||
{intl.formatMessage(messages['learn.lockPaywall.content'])}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="d-flex flex-row flex-wrap">
|
|
||||||
<div style={{ float: 'left' }} className="mr-3 mb-2">
|
|
||||||
<img
|
|
||||||
alt={intl.formatMessage(messages['learn.lockPaywall.example.alt'])}
|
|
||||||
src={certificateLocked}
|
|
||||||
className="border-0 certificate-image-banner"
|
|
||||||
style={{ height: '128px', width: '175px' }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mw-xs list-div">
|
|
||||||
<div className="mb-2">
|
|
||||||
{intl.formatMessage(messages['learn.lockPaywall.list.intro'])}
|
|
||||||
</div>
|
|
||||||
<ul className="fa-ul ml-4 pl-2">
|
|
||||||
<li>
|
|
||||||
<span className="fa-li"><FontAwesomeIcon icon={faCheck} /></span>
|
|
||||||
<FormattedMessage
|
|
||||||
id="gatedContent.paragraph.bulletOne"
|
|
||||||
defaultMessage="Earn a {verifiedCertLink} of completion to showcase on your resume"
|
|
||||||
values={{ verifiedCertLink }}
|
|
||||||
className="bullet-text"
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span className="fa-li"><FontAwesomeIcon icon={faCheck} /></span>
|
|
||||||
<FormattedMessage
|
|
||||||
id="gatedContent.paragraph.bulletTwo"
|
|
||||||
defaultMessage="Unlock access to all course activities, including {gradedAssignments}"
|
|
||||||
values={{ gradedAssignments }}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span className="fa-li"><FontAwesomeIcon icon={faCheck} /></span>
|
|
||||||
<FormattedMessage
|
|
||||||
id="gatedContent.paragraph.bulletThree"
|
|
||||||
defaultMessage="{fullAccess} to course content and materials, even after the course ends"
|
|
||||||
values={{ fullAccess }}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span className="fa-li"><FontAwesomeIcon icon={faCheck} /></span>
|
|
||||||
<FormattedMessage
|
|
||||||
id="gatedContent.paragraph.bulletFour"
|
|
||||||
defaultMessage="Support our {nonProfit} mission at edX"
|
|
||||||
values={{ nonProfit }}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="col-md-auto p-md-0 d-md-flex align-items-md-center mr-md-3"
|
|
||||||
style={{ textAlign: 'right' }}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
className="lock_paywall_upgrade_link"
|
|
||||||
href={upgradeUrl}
|
|
||||||
onClick={logClick}
|
|
||||||
role="link"
|
|
||||||
>
|
|
||||||
{intl.formatMessage(messages['learn.lockPaywall.upgrade.link'], {
|
{intl.formatMessage(messages['learn.lockPaywall.upgrade.link'], {
|
||||||
currencySymbol,
|
currencySymbol,
|
||||||
price,
|
price,
|
||||||
})}
|
})}
|
||||||
</Button>
|
</a>
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</Alert>
|
<div>
|
||||||
|
<img
|
||||||
|
alt={intl.formatMessage(messages['learn.lockPaywall.example.alt'])}
|
||||||
|
src={VerifiedCert}
|
||||||
|
className="border-0"
|
||||||
|
style={{ height: '70px' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
LockPaywall.propTypes = {
|
LockPaywall.propTypes = {
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
|
|
||||||
// Temporary CSS intervention until paragon list items will support icons (PAR-429)
|
|
||||||
.fa-li {
|
|
||||||
left: -31px !important;
|
|
||||||
padding-right: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width: 992px) and (max-width: 1100px) {
|
|
||||||
.list-div {
|
|
||||||
width: 62%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -101,22 +101,12 @@
|
|||||||
"learning.proctoringPanel.onboardingButtonNotOpen": "Onboarding Opens: {releaseDate}",
|
"learning.proctoringPanel.onboardingButtonNotOpen": "Onboarding Opens: {releaseDate}",
|
||||||
"learning.proctoringPanel.reviewRequirementsButton": "Review instructions and system requirements",
|
"learning.proctoringPanel.reviewRequirementsButton": "Review instructions and system requirements",
|
||||||
"learning.outline.sequence-due": "{description} في{assignmentDue}",
|
"learning.outline.sequence-due": "{description} في{assignmentDue}",
|
||||||
"progress.completion.donut.label": "completed",
|
|
||||||
"progress.completion.body": "This represents how much of the course content you have completed. Note that some content may not yet be released.",
|
|
||||||
"progress.completion.tooltip.locked": "Content that you have completed.",
|
|
||||||
"progress.completion.header": "Course completion",
|
|
||||||
"progress.completion.tooltip": "Content that you have access to and have not completed.",
|
|
||||||
"progress.completion.tooltip.complete": "Content that is locked and available only to those who upgrade.",
|
|
||||||
"progress.completion.donut.percentComplete": "You have completed {percent}% of content in this course.",
|
|
||||||
"progress.completion.donut.percentIncomplete": "You have not completed {percent}% of content in this course that you have access to.",
|
|
||||||
"progress.completion.donut.percentLocked": "{percent}% of content in this course is locked and available only for those who upgrade.",
|
|
||||||
"progress.ungradedAlert": "For progress on ungraded aspects of the course, view your {outlineLink}.",
|
"progress.ungradedAlert": "For progress on ungraded aspects of the course, view your {outlineLink}.",
|
||||||
"progress.footnotes.droppableAssignments": "The lowest {numDroppable, plural, one{# {assignmentType} score} other{# {assignmentType} scores}} will be dropped.",
|
"progress.footnotes.droppableAssignments": "The lowest {numDroppable, plural, one{# {assignmentType} score} other{# {assignmentType} scores}} will be dropped.",
|
||||||
"progress.assignmentType": "Assignment type",
|
"progress.assignmentType": "Assignment type",
|
||||||
"progress.footnotes.backToContent": "Back to content",
|
"progress.footnotes.backToContent": "Back to content",
|
||||||
"progress.courseOutline": "Course Outline",
|
"progress.courseOutline": "Course Outline",
|
||||||
"progress.detailedGrades": "Detailed grades",
|
"progress.detailedGrades": "Detailed grades",
|
||||||
"progress.detailedGrades.emptyTable": "You currently have no graded problem scores.",
|
|
||||||
"progress.footnotes.title": "Grade summary footnotes",
|
"progress.footnotes.title": "Grade summary footnotes",
|
||||||
"progress.gradeSummary": "Grade summary",
|
"progress.gradeSummary": "Grade summary",
|
||||||
"progress.gradeSummary.tooltip": "Your course assignment's weight is determined by your instructor. By multiplying your score by the weight for that assignment type, your weighted grade is calculated. Your weighted grade is what's used to determine if you pass the course.",
|
"progress.gradeSummary.tooltip": "Your course assignment's weight is determined by your instructor. By multiplying your score by the weight for that assignment type, your weighted grade is calculated. Your weighted grade is what's used to determine if you pass the course.",
|
||||||
@@ -243,10 +233,6 @@
|
|||||||
"learn.contentLock.content.locked": "محتوى مغلق",
|
"learn.contentLock.content.locked": "محتوى مغلق",
|
||||||
"learn.contentLock.complete.prerequisite": "يجب استيفاء المتطلبات الأساسية: '{priceqSectionName}' للوصول إلى هذا المحتوى.",
|
"learn.contentLock.complete.prerequisite": "يجب استيفاء المتطلبات الأساسية: '{priceqSectionName}' للوصول إلى هذا المحتوى.",
|
||||||
"learn.contentLock.goToSection": "انتقل إلى قسم المتطلبات الأساسية",
|
"learn.contentLock.goToSection": "انتقل إلى قسم المتطلبات الأساسية",
|
||||||
"gatedContent.paragraph.bulletOne": "Earn a {verifiedCertLink} of completion to showcase on your resume",
|
|
||||||
"gatedContent.paragraph.bulletTwo": "Unlock access to all course activities, including {gradedAssignments}",
|
|
||||||
"gatedContent.paragraph.bulletThree": "{fullAccess} to course content and materials, even after the course ends",
|
|
||||||
"gatedContent.paragraph.bulletFour": "Support our {nonProfit} mission at edX",
|
|
||||||
"learn.lockPaywall.title": "Graded assignments are locked",
|
"learn.lockPaywall.title": "Graded assignments are locked",
|
||||||
"learn.lockPaywall.content": "Upgrade to gain access to locked features like this one and get the most out of your course.",
|
"learn.lockPaywall.content": "Upgrade to gain access to locked features like this one and get the most out of your course.",
|
||||||
"learn.lockPaywall.upgrade.link": "Upgrade for {currencySymbol}{price}",
|
"learn.lockPaywall.upgrade.link": "Upgrade for {currencySymbol}{price}",
|
||||||
|
|||||||
@@ -101,22 +101,12 @@
|
|||||||
"learning.proctoringPanel.onboardingButtonNotOpen": "Apertura de la integración: {releaseDate}",
|
"learning.proctoringPanel.onboardingButtonNotOpen": "Apertura de la integración: {releaseDate}",
|
||||||
"learning.proctoringPanel.reviewRequirementsButton": "Revisar las instrucciones y los requisitos del sistema",
|
"learning.proctoringPanel.reviewRequirementsButton": "Revisar las instrucciones y los requisitos del sistema",
|
||||||
"learning.outline.sequence-due": "Fecha límite para {description}: {assignmentDue}",
|
"learning.outline.sequence-due": "Fecha límite para {description}: {assignmentDue}",
|
||||||
"progress.completion.donut.label": "completed",
|
|
||||||
"progress.completion.body": "This represents how much of the course content you have completed. Note that some content may not yet be released.",
|
|
||||||
"progress.completion.tooltip.locked": "Content that you have completed.",
|
|
||||||
"progress.completion.header": "Course completion",
|
|
||||||
"progress.completion.tooltip": "Content that you have access to and have not completed.",
|
|
||||||
"progress.completion.tooltip.complete": "Content that is locked and available only to those who upgrade.",
|
|
||||||
"progress.completion.donut.percentComplete": "You have completed {percent}% of content in this course.",
|
|
||||||
"progress.completion.donut.percentIncomplete": "You have not completed {percent}% of content in this course that you have access to.",
|
|
||||||
"progress.completion.donut.percentLocked": "{percent}% of content in this course is locked and available only for those who upgrade.",
|
|
||||||
"progress.ungradedAlert": "For progress on ungraded aspects of the course, view your {outlineLink}.",
|
"progress.ungradedAlert": "For progress on ungraded aspects of the course, view your {outlineLink}.",
|
||||||
"progress.footnotes.droppableAssignments": "The lowest {numDroppable, plural, one{# {assignmentType} score} other{# {assignmentType} scores}} will be dropped.",
|
"progress.footnotes.droppableAssignments": "The lowest {numDroppable, plural, one{# {assignmentType} score} other{# {assignmentType} scores}} will be dropped.",
|
||||||
"progress.assignmentType": "Assignment type",
|
"progress.assignmentType": "Assignment type",
|
||||||
"progress.footnotes.backToContent": "Back to content",
|
"progress.footnotes.backToContent": "Back to content",
|
||||||
"progress.courseOutline": "Course Outline",
|
"progress.courseOutline": "Course Outline",
|
||||||
"progress.detailedGrades": "Detailed grades",
|
"progress.detailedGrades": "Detailed grades",
|
||||||
"progress.detailedGrades.emptyTable": "You currently have no graded problem scores.",
|
|
||||||
"progress.footnotes.title": "Grade summary footnotes",
|
"progress.footnotes.title": "Grade summary footnotes",
|
||||||
"progress.gradeSummary": "Grade summary",
|
"progress.gradeSummary": "Grade summary",
|
||||||
"progress.gradeSummary.tooltip": "Your course assignment's weight is determined by your instructor. By multiplying your score by the weight for that assignment type, your weighted grade is calculated. Your weighted grade is what's used to determine if you pass the course.",
|
"progress.gradeSummary.tooltip": "Your course assignment's weight is determined by your instructor. By multiplying your score by the weight for that assignment type, your weighted grade is calculated. Your weighted grade is what's used to determine if you pass the course.",
|
||||||
@@ -243,19 +233,15 @@
|
|||||||
"learn.contentLock.content.locked": "Contenido Bloqueado",
|
"learn.contentLock.content.locked": "Contenido Bloqueado",
|
||||||
"learn.contentLock.complete.prerequisite": "Debe completar el prerrequisito: '{prereqSectionName}'para acceder a este contenido.",
|
"learn.contentLock.complete.prerequisite": "Debe completar el prerrequisito: '{prereqSectionName}'para acceder a este contenido.",
|
||||||
"learn.contentLock.goToSection": "Ir a la Sección de Prerrequisitos",
|
"learn.contentLock.goToSection": "Ir a la Sección de Prerrequisitos",
|
||||||
"gatedContent.paragraph.bulletOne": "Obtén un {verifiedCertLink} de finalización para compartirlo en tu currículum",
|
"learn.lockPaywall.title": "Graded assignments are locked",
|
||||||
"gatedContent.paragraph.bulletTwo": "Desbloquea el acceso a todas las actividades del curso, incluidas las {gradedAssignments}",
|
"learn.lockPaywall.content": "Upgrade to gain access to locked features like this one and get the most out of your course.",
|
||||||
"gatedContent.paragraph.bulletThree": "{fullAccess} al contenido y los materiales del curso, incluso después de que finalice",
|
|
||||||
"gatedContent.paragraph.bulletFour": "Apoya nuestra {nonProfit} en edX",
|
|
||||||
"learn.lockPaywall.title": "Las tareas calificadas están bloqueadas",
|
|
||||||
"learn.lockPaywall.content": "Cámbiate a la opción verificada para obtener acceso a funciones bloqueadas como esta y aprovechar al máximo tu curso.",
|
|
||||||
"learn.lockPaywall.upgrade.link": "Opción verificada {currencySymbol}{price}",
|
"learn.lockPaywall.upgrade.link": "Opción verificada {currencySymbol}{price}",
|
||||||
"learn.lockPaywall.example.alt": "Certificado de ejemplo",
|
"learn.lockPaywall.example.alt": "Certificado de ejemplo",
|
||||||
"learn.lockPaywall.list.intro": "Cuando te cambias a la opción verificada, tú:",
|
"learn.lockPaywall.list.intro": "When you upgrade, you:",
|
||||||
"learn.lockPaywall.list.bullet1.linktext": "certificado verificado",
|
"learn.lockPaywall.list.bullet1.linktext": "verified certificate",
|
||||||
"learn.lockPaywall.list.bullet2.boldtext": "tareas calificadas",
|
"learn.lockPaywall.list.bullet2.boldtext": "graded assignments",
|
||||||
"learn.lockPaywall.list.bullet3.boldtext": "Acceso completo",
|
"learn.lockPaywall.list.bullet3.boldtext": "Full access",
|
||||||
"learn.lockPaywall.list.bullet4.boldtext": "misión sin fines de lucro",
|
"learn.lockPaywall.list.bullet4.boldtext": "non-profit",
|
||||||
"learn.loading.content.lock": "Cargando la mensajería de contenido bloqueado...",
|
"learn.loading.content.lock": "Cargando la mensajería de contenido bloqueado...",
|
||||||
"learn.loading.learning.sequence": "Cargando la secuencia de aprendizaje...",
|
"learn.loading.learning.sequence": "Cargando la secuencia de aprendizaje...",
|
||||||
"learn.course.load.failure": "Hubo un error al cargar este curso.",
|
"learn.course.load.failure": "Hubo un error al cargar este curso.",
|
||||||
|
|||||||
@@ -101,22 +101,12 @@
|
|||||||
"learning.proctoringPanel.onboardingButtonNotOpen": "Onboarding Opens: {releaseDate}",
|
"learning.proctoringPanel.onboardingButtonNotOpen": "Onboarding Opens: {releaseDate}",
|
||||||
"learning.proctoringPanel.reviewRequirementsButton": "Review instructions and system requirements",
|
"learning.proctoringPanel.reviewRequirementsButton": "Review instructions and system requirements",
|
||||||
"learning.outline.sequence-due": "{description} due {assignmentDue}",
|
"learning.outline.sequence-due": "{description} due {assignmentDue}",
|
||||||
"progress.completion.donut.label": "completed",
|
|
||||||
"progress.completion.body": "This represents how much of the course content you have completed. Note that some content may not yet be released.",
|
|
||||||
"progress.completion.tooltip.locked": "Content that you have completed.",
|
|
||||||
"progress.completion.header": "Course completion",
|
|
||||||
"progress.completion.tooltip": "Content that you have access to and have not completed.",
|
|
||||||
"progress.completion.tooltip.complete": "Content that is locked and available only to those who upgrade.",
|
|
||||||
"progress.completion.donut.percentComplete": "You have completed {percent}% of content in this course.",
|
|
||||||
"progress.completion.donut.percentIncomplete": "You have not completed {percent}% of content in this course that you have access to.",
|
|
||||||
"progress.completion.donut.percentLocked": "{percent}% of content in this course is locked and available only for those who upgrade.",
|
|
||||||
"progress.ungradedAlert": "For progress on ungraded aspects of the course, view your {outlineLink}.",
|
"progress.ungradedAlert": "For progress on ungraded aspects of the course, view your {outlineLink}.",
|
||||||
"progress.footnotes.droppableAssignments": "The lowest {numDroppable, plural, one{# {assignmentType} score} other{# {assignmentType} scores}} will be dropped.",
|
"progress.footnotes.droppableAssignments": "The lowest {numDroppable, plural, one{# {assignmentType} score} other{# {assignmentType} scores}} will be dropped.",
|
||||||
"progress.assignmentType": "Assignment type",
|
"progress.assignmentType": "Assignment type",
|
||||||
"progress.footnotes.backToContent": "Back to content",
|
"progress.footnotes.backToContent": "Back to content",
|
||||||
"progress.courseOutline": "Course Outline",
|
"progress.courseOutline": "Course Outline",
|
||||||
"progress.detailedGrades": "Detailed grades",
|
"progress.detailedGrades": "Detailed grades",
|
||||||
"progress.detailedGrades.emptyTable": "You currently have no graded problem scores.",
|
|
||||||
"progress.footnotes.title": "Grade summary footnotes",
|
"progress.footnotes.title": "Grade summary footnotes",
|
||||||
"progress.gradeSummary": "Grade summary",
|
"progress.gradeSummary": "Grade summary",
|
||||||
"progress.gradeSummary.tooltip": "Your course assignment's weight is determined by your instructor. By multiplying your score by the weight for that assignment type, your weighted grade is calculated. Your weighted grade is what's used to determine if you pass the course.",
|
"progress.gradeSummary.tooltip": "Your course assignment's weight is determined by your instructor. By multiplying your score by the weight for that assignment type, your weighted grade is calculated. Your weighted grade is what's used to determine if you pass the course.",
|
||||||
@@ -243,10 +233,6 @@
|
|||||||
"learn.contentLock.content.locked": "Content Locked",
|
"learn.contentLock.content.locked": "Content Locked",
|
||||||
"learn.contentLock.complete.prerequisite": "You must complete the prerequisite: '{prereqSectionName}' to access this content.",
|
"learn.contentLock.complete.prerequisite": "You must complete the prerequisite: '{prereqSectionName}' to access this content.",
|
||||||
"learn.contentLock.goToSection": "Go To Prerequisite Section",
|
"learn.contentLock.goToSection": "Go To Prerequisite Section",
|
||||||
"gatedContent.paragraph.bulletOne": "Earn a {verifiedCertLink} of completion to showcase on your resume",
|
|
||||||
"gatedContent.paragraph.bulletTwo": "Unlock access to all course activities, including {gradedAssignments}",
|
|
||||||
"gatedContent.paragraph.bulletThree": "{fullAccess} to course content and materials, even after the course ends",
|
|
||||||
"gatedContent.paragraph.bulletFour": "Support our {nonProfit} mission at edX",
|
|
||||||
"learn.lockPaywall.title": "Graded assignments are locked",
|
"learn.lockPaywall.title": "Graded assignments are locked",
|
||||||
"learn.lockPaywall.content": "Upgrade to gain access to locked features like this one and get the most out of your course.",
|
"learn.lockPaywall.content": "Upgrade to gain access to locked features like this one and get the most out of your course.",
|
||||||
"learn.lockPaywall.upgrade.link": "Upgrade for {currencySymbol}{price}",
|
"learn.lockPaywall.upgrade.link": "Upgrade for {currencySymbol}{price}",
|
||||||
|
|||||||
@@ -101,22 +101,12 @@
|
|||||||
"learning.proctoringPanel.onboardingButtonNotOpen": "Onboarding Opens: {releaseDate}",
|
"learning.proctoringPanel.onboardingButtonNotOpen": "Onboarding Opens: {releaseDate}",
|
||||||
"learning.proctoringPanel.reviewRequirementsButton": "Review instructions and system requirements",
|
"learning.proctoringPanel.reviewRequirementsButton": "Review instructions and system requirements",
|
||||||
"learning.outline.sequence-due": "{description} due {assignmentDue}",
|
"learning.outline.sequence-due": "{description} due {assignmentDue}",
|
||||||
"progress.completion.donut.label": "completed",
|
|
||||||
"progress.completion.body": "This represents how much of the course content you have completed. Note that some content may not yet be released.",
|
|
||||||
"progress.completion.tooltip.locked": "Content that you have completed.",
|
|
||||||
"progress.completion.header": "Course completion",
|
|
||||||
"progress.completion.tooltip": "Content that you have access to and have not completed.",
|
|
||||||
"progress.completion.tooltip.complete": "Content that is locked and available only to those who upgrade.",
|
|
||||||
"progress.completion.donut.percentComplete": "You have completed {percent}% of content in this course.",
|
|
||||||
"progress.completion.donut.percentIncomplete": "You have not completed {percent}% of content in this course that you have access to.",
|
|
||||||
"progress.completion.donut.percentLocked": "{percent}% of content in this course is locked and available only for those who upgrade.",
|
|
||||||
"progress.ungradedAlert": "For progress on ungraded aspects of the course, view your {outlineLink}.",
|
"progress.ungradedAlert": "For progress on ungraded aspects of the course, view your {outlineLink}.",
|
||||||
"progress.footnotes.droppableAssignments": "The lowest {numDroppable, plural, one{# {assignmentType} score} other{# {assignmentType} scores}} will be dropped.",
|
"progress.footnotes.droppableAssignments": "The lowest {numDroppable, plural, one{# {assignmentType} score} other{# {assignmentType} scores}} will be dropped.",
|
||||||
"progress.assignmentType": "Assignment type",
|
"progress.assignmentType": "Assignment type",
|
||||||
"progress.footnotes.backToContent": "Back to content",
|
"progress.footnotes.backToContent": "Back to content",
|
||||||
"progress.courseOutline": "Course Outline",
|
"progress.courseOutline": "Course Outline",
|
||||||
"progress.detailedGrades": "Detailed grades",
|
"progress.detailedGrades": "Detailed grades",
|
||||||
"progress.detailedGrades.emptyTable": "You currently have no graded problem scores.",
|
|
||||||
"progress.footnotes.title": "Grade summary footnotes",
|
"progress.footnotes.title": "Grade summary footnotes",
|
||||||
"progress.gradeSummary": "Grade summary",
|
"progress.gradeSummary": "Grade summary",
|
||||||
"progress.gradeSummary.tooltip": "Your course assignment's weight is determined by your instructor. By multiplying your score by the weight for that assignment type, your weighted grade is calculated. Your weighted grade is what's used to determine if you pass the course.",
|
"progress.gradeSummary.tooltip": "Your course assignment's weight is determined by your instructor. By multiplying your score by the weight for that assignment type, your weighted grade is calculated. Your weighted grade is what's used to determine if you pass the course.",
|
||||||
@@ -243,10 +233,6 @@
|
|||||||
"learn.contentLock.content.locked": "Content Locked",
|
"learn.contentLock.content.locked": "Content Locked",
|
||||||
"learn.contentLock.complete.prerequisite": "You must complete the prerequisite: '{prereqSectionName}' to access this content.",
|
"learn.contentLock.complete.prerequisite": "You must complete the prerequisite: '{prereqSectionName}' to access this content.",
|
||||||
"learn.contentLock.goToSection": "Go To Prerequisite Section",
|
"learn.contentLock.goToSection": "Go To Prerequisite Section",
|
||||||
"gatedContent.paragraph.bulletOne": "Earn a {verifiedCertLink} of completion to showcase on your resume",
|
|
||||||
"gatedContent.paragraph.bulletTwo": "Unlock access to all course activities, including {gradedAssignments}",
|
|
||||||
"gatedContent.paragraph.bulletThree": "{fullAccess} to course content and materials, even after the course ends",
|
|
||||||
"gatedContent.paragraph.bulletFour": "Support our {nonProfit} mission at edX",
|
|
||||||
"learn.lockPaywall.title": "Graded assignments are locked",
|
"learn.lockPaywall.title": "Graded assignments are locked",
|
||||||
"learn.lockPaywall.content": "Upgrade to gain access to locked features like this one and get the most out of your course.",
|
"learn.lockPaywall.content": "Upgrade to gain access to locked features like this one and get the most out of your course.",
|
||||||
"learn.lockPaywall.upgrade.link": "Upgrade for {currencySymbol}{price}",
|
"learn.lockPaywall.upgrade.link": "Upgrade for {currencySymbol}{price}",
|
||||||
|
|||||||
Reference in New Issue
Block a user