Skip to content

Commit

Permalink
Merge pull request #2742 from creative-commoners/pulls/4/get-unsaved-…
Browse files Browse the repository at this point in the history
…anchors-in-current-field

Works as expected in local environment. Tests passed. MERGE
  • Loading branch information
sabina-talipova authored Jun 13, 2022
2 parents 77b5bfa + ead1d2f commit d304ba9
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 23 deletions.
2 changes: 1 addition & 1 deletion client/dist/js/TinyMCE_sslink-anchor.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion client/dist/js/bundle.js

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions client/src/components/AnchorSelectorField/AnchorSelectorField.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ class AnchorSelectorField extends SilverStripeComponent {
return Promise.resolve();
}

// Get anchors that belong to the current field
let fieldAnchors = [];
if (props.loadingState === anchorSelectorStates.FIELD_ONLY) {
fieldAnchors = this.props.anchors;
}

// Mark page updating
props.actions.anchorSelector.beginUpdating(props.pageId);

Expand All @@ -57,9 +63,11 @@ class AnchorSelectorField extends SilverStripeComponent {
return fetch(fetchURL, { credentials: 'same-origin' })
.then(response => response.json())
.then((anchors) => {
// Fold in field anchors and ensure array has only unique values
const allAnchors = [...new Set([...anchors, ...fieldAnchors])];
// Update anchors
props.actions.anchorSelector.updated(props.pageId, anchors);
return anchors;
props.actions.anchorSelector.updated(props.pageId, allAnchors);
return allAnchors;
})
.catch((error) => {
props.actions.anchorSelector.updateFailed(props.pageId);
Expand Down Expand Up @@ -174,6 +182,7 @@ function mapStateToProps(state, ownProps) {
&& (
page.loadingState === anchorSelectorStates.SUCCESS
|| page.loadingState === anchorSelectorStates.DIRTY
|| page.loadingState === anchorSelectorStates.FIELD_ONLY
)
) {
// eslint-disable-next-line prefer-destructuring
Expand Down
10 changes: 9 additions & 1 deletion client/src/legacy/TinyMCE_sslink-anchor.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import jQuery from 'jquery';
import ShortcodeSerialiser from 'lib/ShortcodeSerialiser';
import { createInsertLinkModal } from 'containers/InsertLinkModal/InsertLinkModal';
import { provideInjector } from 'lib/Injector';
import { updated } from '../state/anchorSelector/AnchorSelectorActions';
import { updatedCurrentField } from '../state/anchorSelector/AnchorSelectorActions';

const commandName = 'sslinkanchor';

Expand All @@ -30,6 +30,14 @@ const plugin = {
init(editor) {
editor.addCommand(commandName, () => {
const field = jQuery(`#${editor.id}`).entwine('ss');
// Get the anchors in the current field and save them as props for AnchorSelectorField
const currentPageID = Number(jQuery('#Form_EditForm_ID').val() || 0);
const validTargets = editor
.$('[id],[name]', editor.getBody())
.toArray()
.map((element) => element.id || element.name);
ss.store.dispatch(updatedCurrentField(currentPageID, validTargets, editor.id));
// Open the anchor link form
field.openLinkAnchorDialog();
});
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export default {
ANCHORSELECTOR_CURRENT_FIELD: 'ANCHORSELECTOR_CURRENT_FIELD',
ANCHORSELECTOR_UPDATED: 'ANCHORSELECTOR_UPDATED',
ANCHORSELECTOR_UPDATING: 'ANCHORSELECTOR_UPDATING',
ANCHORSELECTOR_UPDATE_FAILED: 'ANCHORSELECTOR_UPDATE_FAILED',
Expand Down
17 changes: 17 additions & 0 deletions client/src/state/anchorSelector/AnchorSelectorActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,23 @@ export function updated(pageId, anchors, cacheResult = false) {
};
}

/**
* Get the anchors that belong in a specific field.
* The server doesn't know about anchors that haven't been saved yet, so this allows
* a WYSIWYG field to register its own anchors.
*
* @param {Number} pageId - ID of page to query for
* @param {Array} anchors - List of anchor strings
* @param {String} fieldID - ID of the field these anchors belong to
* @returns {Object}
*/
export function updatedCurrentField(pageId, anchors, fieldID) {
return {
type: ACTION_TYPES.ANCHORSELECTOR_CURRENT_FIELD,
payload: { pageId, anchors, fieldID },
};
}

/**
* Mark a tree as failed
*
Expand Down
5 changes: 5 additions & 0 deletions client/src/state/anchorSelector/AnchorSelectorReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ export default function anchorSelectorReducer(state = initialState, action = nul
return updatePage(newSelectorLoadingState, anchors);
}

case ACTION_TYPES.ANCHORSELECTOR_CURRENT_FIELD: {
const { anchors } = action.payload;
return updatePage(anchorSelectorStates.FIELD_ONLY, anchors);
}

case ACTION_TYPES.ANCHORSELECTOR_UPDATE_FAILED: {
return updatePage(anchorSelectorStates.FAILED, []);
}
Expand Down
1 change: 1 addition & 0 deletions client/src/state/anchorSelector/AnchorSelectorStates.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export default {
SUCCESS: 'SUCCESS', // Done, or nothing selected
DIRTY: 'DIRTY', // Needs updating
FIELD_ONLY: 'FIELD_ONLY', // Has anchors from the field but needs to fetch the rest from server
UPDATING: 'UPDATING',
FAILED: 'FAILED',
};
18 changes: 0 additions & 18 deletions tests/behat/features/insert-a-link.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ So that I can link to a external website or a page on my site
Background:
Given a "page" "Home"
And a "page" "About Us" has the "Content" "<p>My awesome content</p>"
And a "page" "Details" has the "Content" "<p>My sub-par content<a name="youranchor"></a></p>"
And a "file" "file1.jpg"
And I am logged in with "ADMIN" permissions
And I go to "/admin/pages"
Expand All @@ -26,23 +25,6 @@ So that I can link to a external website or a page on my site
# Required to avoid "unsaved changes" browser dialog
Then I press the "Save" button

Scenario: I can link to an anchor in an internal page
When I select "awesome" in the "Content" HTML field
And I press the "Insert link" HTML field button
And I click "Anchor on a page" in the ".mce-menu" element
Then I should see an "form#Form_editorAnchorLink" element
And I should see "About Us" in the "#Form_editorAnchorLink_PageID_Holder .Select-multi-value-wrapper" element
When I click "About Us" in the "#Form_editorAnchorLink_PageID_Holder .Select-multi-value-wrapper" element
And I click "Details" in the "#Form_editorAnchorLink_PageID_Holder .Select-menu-outer" element
And I click "Select or enter anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-multi-value-wrapper" element
And I click "youranchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
Then I should see "youranchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-value" element
When I fill in "my desc" for "Link description"
And I press the "Insert" button
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=3]#youranchor">awesome</a>"
# Required to avoid "unsaved changes" browser dialog
Then I press the "Save" button

Scenario: I can edit a link to an internal page
Given I fill in the "Content" HTML field with "<a title='my desc' href='[sitetree_link,id=2]'>awesome</a>"
And I select "awesome" in the "Content" HTML field
Expand Down
65 changes: 65 additions & 0 deletions tests/behat/features/insert-anchor-link.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
@retry
Feature: Insert links into a page
As a cms author
I want to insert a link into my content
So that I can link to a external website or a page on my site

Background:
Given I add an extension "SilverStripe\CMS\Tests\Behaviour\AdditionalAnchorPageExtension" to the "Page" class
And a "page" "Home"
And a "page" "About Us" has the "Content" "<p>My awesome content</p>"
And a "page" "Details" has the "Content" "<p>My sub-par content<a name="youranchor"></a></p>"
And I am logged in with "ADMIN" permissions
And I go to "/admin/pages"
And I click on "About Us" in the tree

Scenario: I can link to an anchor in an internal page
When I select "awesome" in the "Content" HTML field
And I press the "Insert link" HTML field button
And I click "Anchor on a page" in the ".mce-menu" element
Then I should see an "form#Form_editorAnchorLink" element
And I should see "About Us" in the "#Form_editorAnchorLink_PageID_Holder .Select-multi-value-wrapper" element
When I click "About Us" in the "#Form_editorAnchorLink_PageID_Holder .Select-multi-value-wrapper" element
And I click "Details" in the "#Form_editorAnchorLink_PageID_Holder .Select-menu-outer" element
And I click "Select or enter anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-multi-value-wrapper" element
And I click "youranchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
Then I should see "youranchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-value" element
When I fill in "my desc" for "Link description"
And I press the "Insert" button
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=3]#youranchor">awesome</a>"
# Required to avoid "unsaved changes" browser dialog
Then I press the "Save" button

Scenario: I can link to an anchor from a dataobject on the current page
When I select "awesome" in the "Content" HTML field
And I press the "Insert link" HTML field button
And I click "Anchor on a page" in the ".mce-menu" element
Then I should see an "form#Form_editorAnchorLink" element
And I should see "About Us" in the "#Form_editorAnchorLink_PageID_Holder .Select-multi-value-wrapper" element
When I click "Select or enter anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-multi-value-wrapper" element
Then I should see "dataobject-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
When I click "dataobject-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
Then I should see "dataobject-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-value" element
When I fill in "my desc" for "Link description"
And I press the "Insert" button
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=2]#dataobject-anchor">awesome</a>"
# Required to avoid "unsaved changes" browser dialog
Then I press the "Save" button

Scenario: I can link to an unsaved anchor in the current page
Given I fill in the "Content" HTML field with "<p>My awesome content</p><p><a id='unsaved-anchor'></a>unsaved content</p>"
When I select "awesome" in the "Content" HTML field
And I press the "Insert link" HTML field button
And I click "Anchor on a page" in the ".mce-menu" element
Then I should see an "form#Form_editorAnchorLink" element
And I should see "About Us" in the "#Form_editorAnchorLink_PageID_Holder .Select-multi-value-wrapper" element
When I click "Select or enter anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-multi-value-wrapper" element
Then I should see "unsaved-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
And I should see "dataobject-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
When I click "unsaved-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
Then I should see "unsaved-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-value" element
When I fill in "my desc" for "Link description"
And I press the "Insert" button
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=2]#unsaved-anchor">awesome</a>"
# Required to avoid "unsaved changes" browser dialog
Then I press the "Save" button
Loading

0 comments on commit d304ba9

Please sign in to comment.