diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 5fc480801d..f6142c4bba 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -8,6 +8,7 @@ Changelog
* Added more informative error message when `|richtext` filter is applied to a non-string value (mukesh5)
* Automatic search indexing can now be disabled on a per-model basis via the `search_auto_update` attribute (Karl Hobley)
* Improved diffing of StreamFields when comparing page revisions (Karl Hobley)
+ * Highlight broken links to pages and missing documents in rich text (Brady Moe)
* Fix: Set `SERVER_PORT` to 443 in `Page.dummy_request()` for HTTPS sites (Sergey Fedoseev)
* Fix: Include port number in `Host` header of `Page.dummy_request()` (Sergey Fedoseev)
* Fix: Validation error messages in `InlinePanel` no longer count towards `max_num` when disabling the 'add' button (Todd Dembrey, Thibaud Colas)
diff --git a/client/src/components/Draftail/decorators/Document.js b/client/src/components/Draftail/decorators/Document.js
index afade79d33..9889f23734 100644
--- a/client/src/components/Draftail/decorators/Document.js
+++ b/client/src/components/Draftail/decorators/Document.js
@@ -5,18 +5,32 @@ import Icon from '../../Icon/Icon';
import TooltipEntity from '../decorators/TooltipEntity';
+import { STRINGS } from '../../../config/wagtailConfig';
+
const documentIcon = ;
+const missingDocumentIcon = ;
const Document = props => {
const { entityKey, contentState } = props;
const data = contentState.getEntity(entityKey).getData();
+ const url = data.url || null;
+ let icon;
+ let label;
+
+ if (!url) {
+ icon = missingDocumentIcon;
+ label = STRINGS.MISSING_DOCUMENT;
+ } else {
+ icon = documentIcon;
+ label = data.filename || '';
+ }
return (
);
};
diff --git a/client/src/components/Draftail/decorators/Link.js b/client/src/components/Draftail/decorators/Link.js
index 523dd1f942..5e28ce3909 100644
--- a/client/src/components/Draftail/decorators/Link.js
+++ b/client/src/components/Draftail/decorators/Link.js
@@ -5,7 +5,10 @@ import Icon from '../../Icon/Icon';
import TooltipEntity from '../decorators/TooltipEntity';
+import { STRINGS } from '../../../config/wagtailConfig';
+
const LINK_ICON = ;
+const BROKEN_LINK_ICON = ;
const MAIL_ICON = ;
const getEmailAddress = mailto => mailto.replace('mailto:', '').split('?')[0];
@@ -13,11 +16,14 @@ const getDomainName = url => url.replace(/(^\w+:|^)\/\//, '').split('/')[0];
// Determines how to display the link based on its type: page, mail, or external.
export const getLinkAttributes = (data) => {
- const url = data.url || '';
+ const url = data.url || null;
let icon;
let label;
- if (data.id) {
+ if (!url) {
+ icon = BROKEN_LINK_ICON;
+ label = STRINGS.BROKEN_LINK;
+ } else if (data.id) {
icon = LINK_ICON;
label = url;
} else if (url.startsWith('mailto:')) {
diff --git a/client/src/components/Draftail/decorators/Link.test.js b/client/src/components/Draftail/decorators/Link.test.js
index 32fda86813..cab3ed9799 100644
--- a/client/src/components/Draftail/decorators/Link.test.js
+++ b/client/src/components/Draftail/decorators/Link.test.js
@@ -64,7 +64,7 @@ describe('Link', () => {
});
it('no data', () => {
- expect(getLinkAttributes({})).toMatchObject({ url: '' });
+ expect(getLinkAttributes({})).toMatchObject({ url: null, label: 'Broken link' });
});
});
});
diff --git a/client/src/components/Draftail/decorators/TooltipEntity.js b/client/src/components/Draftail/decorators/TooltipEntity.js
index c5631b2ab3..7b7e3afa60 100644
--- a/client/src/components/Draftail/decorators/TooltipEntity.js
+++ b/client/src/components/Draftail/decorators/TooltipEntity.js
@@ -144,7 +144,11 @@ TooltipEntity.propTypes = {
PropTypes.object.isRequired,
]).isRequired,
label: PropTypes.string.isRequired,
- url: PropTypes.string.isRequired,
+ url: PropTypes.string,
+};
+
+TooltipEntity.defaultProps = {
+ url: null,
};
export default TooltipEntity;
diff --git a/client/src/components/Draftail/decorators/TooltipEntity.scss b/client/src/components/Draftail/decorators/TooltipEntity.scss
index fb86d3d528..b9c9fbd050 100644
--- a/client/src/components/Draftail/decorators/TooltipEntity.scss
+++ b/client/src/components/Draftail/decorators/TooltipEntity.scss
@@ -7,6 +7,10 @@ $icon-size: 1em;
color: $color-teal;
}
+ .icon-warning {
+ color: $color-red;
+ }
+
&__icon {
color: $color-teal;
margin-right: 0.2em;
diff --git a/client/src/components/Draftail/decorators/__snapshots__/Document.test.js.snap b/client/src/components/Draftail/decorators/__snapshots__/Document.test.js.snap
index 17b14ffb28..e24e22a549 100644
--- a/client/src/components/Draftail/decorators/__snapshots__/Document.test.js.snap
+++ b/client/src/components/Draftail/decorators/__snapshots__/Document.test.js.snap
@@ -56,14 +56,14 @@ exports[`Document no data 1`] = `
icon={
}
- label=""
+ label="Missing document"
onEdit={[Function]}
onRemove={[Function]}
- url=""
+ url={null}
>
test
diff --git a/client/tests/stubs.js b/client/tests/stubs.js
index 28724878c6..ad82e10d20 100644
--- a/client/tests/stubs.js
+++ b/client/tests/stubs.js
@@ -41,6 +41,8 @@ global.wagtailConfig = {
SHOW_LATEST_CONTENT: 'Show latest content',
SHOW_ERROR: 'Show error',
EDITOR_CRASH: 'The editor just crashed. Content has been reset to the last saved version.',
+ BROKEN_LINK: 'Broken link',
+ MISSING_DOCUMENT: 'Missing document',
},
};
diff --git a/docs/releases/2.5.rst b/docs/releases/2.5.rst
index 29afca7c2c..9b6b0a6d88 100644
--- a/docs/releases/2.5.rst
+++ b/docs/releases/2.5.rst
@@ -18,6 +18,7 @@ Other features
* Added more informative error message when ``|richtext`` filter is applied to a non-string value (mukesh5)
* Automatic search indexing can now be disabled on a per-model basis via the ``search_auto_update`` attribute (Karl Hobley)
* Improved diffing of StreamFields when comparing page revisions (Karl Hobley)
+ * Highlight broken links to pages and missing documents in rich text (Brady Moe)
Bug fixes
diff --git a/wagtail/admin/templates/wagtailadmin/admin_base.html b/wagtail/admin/templates/wagtailadmin/admin_base.html
index 136214f084..d73e1c63df 100644
--- a/wagtail/admin/templates/wagtailadmin/admin_base.html
+++ b/wagtail/admin/templates/wagtailadmin/admin_base.html
@@ -49,6 +49,8 @@
SHOW_LATEST_CONTENT: "{% trans 'Show latest content' %}",
SHOW_ERROR: "{% trans 'Show error' %}",
EDITOR_CRASH: "{% trans 'The editor just crashed. Content has been reset to the last saved version.' %}",
+ BROKEN_LINK: "{% trans 'Broken link' %}",
+ MISSING_DOCUMENT: "{% trans 'Missing document' %}"
};
wagtailConfig.ADMIN_URLS = {