Skip to content

Commit fca2c46

Browse files
committed
ENH CMS 6 compatibility
1 parent bfadee5 commit fca2c46

16 files changed

+1308
-1358
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Silverstripe Campaign Admin Module
22

33
[![CI](https://github.com/silverstripe/silverstripe-campaign-admin/actions/workflows/ci.yml/badge.svg)](https://github.com/silverstripe/silverstripe-campaign-admin/actions/workflows/ci.yml)
4+
[![Silverstripe supported module](https://img.shields.io/badge/silverstripe-supported-0071C4.svg)](https://www.silverstripe.org/software/addons/silverstripe-commercially-supported-module-list/)
45

56
## Overview
67

_config/config.yml

+6
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@ SilverStripe\Admin\LeftAndMain:
1212
SilverStripe\CMS\Model\SiteTree:
1313
extensions:
1414
- SilverStripe\CampaignAdmin\SiteTreeExtension
15+
16+
# Allow users only only have access to the campaign-admin, and not all CMS access
17+
# i.e. CMS_ACCESS_LeftAndMain, to still be able to manage changesets
18+
SilverStripe\Versioned\ChangeSet:
19+
required_permission:
20+
- CMS_ACCESS_CampaignAdmin

client/dist/js/bundle.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/dist/styles/bundle.css

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/src/bundles/bundle.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
require('../boot/index');
1+
import '../legacy/AddToCampaignForm';
2+
import '../boot/index';
+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* global window */
2+
import i18n from 'i18n';
3+
import jQuery from 'jquery';
4+
import React from 'react';
5+
import { createRoot } from 'react-dom/client';
6+
import { loadComponent } from 'lib/Injector';
7+
8+
const FormBuilderModal = loadComponent('FormBuilderModal');
9+
10+
jQuery.entwine('ss', ($) => {
11+
/**
12+
* Kick off an "add to campaign" dialog from the CMS actions.
13+
*/
14+
$(
15+
'.cms-content-actions .add-to-campaign-action,' +
16+
'#add-to-campaign__action'
17+
).entwine({
18+
onclick() {
19+
let dialog = $('#add-to-campaign__dialog-wrapper');
20+
21+
if (!dialog.length) {
22+
dialog = $('<div id="add-to-campaign__dialog-wrapper" />');
23+
$('body').append(dialog);
24+
}
25+
26+
dialog.open();
27+
28+
return false;
29+
},
30+
});
31+
32+
// This is required because the React version of e.preventDefault() doesn't work
33+
// this is to prevent PJAX request to occur when clicking a link the modal
34+
$('.add-to-campaign-modal .add-to-campaign-modal__nav-link').entwine({
35+
onclick: (e) => {
36+
e.preventDefault();
37+
const $link = $(e.target);
38+
window.location = $link.attr('href');
39+
},
40+
});
41+
42+
/**
43+
* Uses reactstrap in order to replicate the bootstrap styling and JavaScript behaviour.
44+
* The "add to campaign" dialog is used in a similar fashion in AssetAdmin.
45+
*/
46+
$('#add-to-campaign__dialog-wrapper').entwine({
47+
ReactRoot: null,
48+
49+
onunmatch() {
50+
// solves errors given by ReactDOM "no matched root found" error.
51+
this._clearModal();
52+
},
53+
54+
open() {
55+
this._renderModal(true);
56+
},
57+
58+
close() {
59+
this._renderModal(false);
60+
},
61+
62+
_renderModal(isOpen) {
63+
const handleHide = () => this.close();
64+
const handleSubmit = (...args) => this._handleSubmitModal(...args);
65+
const id = $('form.cms-edit-form :input[name=ID]').val();
66+
const sectionConfigKey = 'SilverStripe\\CMS\\Controllers\\CMSPageEditController';
67+
const store = window.ss.store;
68+
const sectionConfig = store.getState().config.sections
69+
.find((section) => section.name === sectionConfigKey);
70+
const modalSchemaUrl = `${sectionConfig.form.AddToCampaignForm.schemaUrl}/${id}`;
71+
const title = i18n._t('Admin.ADD_TO_CAMPAIGN', 'Add to campaign');
72+
73+
let root = this.getReactRoot();
74+
if (!root) {
75+
root = createRoot(this[0]);
76+
}
77+
root.render(
78+
<FormBuilderModal
79+
title={title}
80+
isOpen={isOpen}
81+
onSubmit={handleSubmit}
82+
onClosed={handleHide}
83+
schemaUrl={modalSchemaUrl}
84+
bodyClassName="modal__dialog"
85+
className="add-to-campaign-modal"
86+
responseClassBad="modal__response modal__response--error"
87+
responseClassGood="modal__response modal__response--good"
88+
identifier="Admin.AddToCampaign"
89+
/>
90+
);
91+
this.setReactRoot(root);
92+
},
93+
94+
_clearModal() {
95+
const root = this.getReactRoot();
96+
if (root) {
97+
root.unmount();
98+
this.setReactRoot(null);
99+
}
100+
// this.empty();
101+
},
102+
103+
_handleSubmitModal(data, action, submitFn) {
104+
return submitFn();
105+
},
106+
107+
});
108+
});

client/src/state/campaign/tests/CampaignActions-test.js

-59
This file was deleted.

composer.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
"php": "^8.3",
2525
"silverstripe/admin": "^3",
2626
"silverstripe/framework": "^6",
27-
"silverstripe/versioned": "^3",
28-
"silverstripe/vendor-plugin": "^2"
27+
"silverstripe/versioned": "^3"
2928
},
3029
"require-dev": {
3130
"phpunit/phpunit": "^11.3",

package.json

+7-12
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,20 @@
3333
"homepage": "https://github.com/silverstripe/silverstripe-campaign-admin",
3434
"dependencies": {
3535
"@popperjs/core": "^2.11.6",
36-
"bootstrap": "^4.6.2",
36+
"bootstrap": "^5.2.0",
3737
"classnames": "^2.3.2",
3838
"core-js": "^3.26.0",
3939
"deep-freeze-strict": "^1.1.1",
4040
"prop-types": "^15.8.1",
41-
"react": "^18.2.0",
42-
"react-dom": "^18.2.0",
43-
"react-redux": "^8.0.5",
44-
"react-router-dom": "^6.4.3",
45-
"reactstrap": "^8.9.0",
46-
"redux": "^4.2.0",
47-
"redux-form": "^8.3.8",
48-
"redux-mock-store": "^1.5.4",
49-
"redux-thunk": "^2.4.2"
41+
"reactstrap": "^9.2.0",
42+
"redux": "^5.0.1",
43+
"redux-form": "^8.3.10",
44+
"redux-thunk": "^3.1.0"
5045
},
5146
"devDependencies": {
5247
"@silverstripe/eslint-config": "^1.3.0",
53-
"@silverstripe/webpack-config": "^3.0.0-alpha1",
54-
"@testing-library/react": "^14.0.0",
48+
"@silverstripe/webpack-config": "^3.0.0-alpha3",
49+
"@testing-library/react": "^16.1.0",
5550
"babel-core": "^6.26.3",
5651
"babel-jest": "^29.3.0",
5752
"babel-loader": "^9.1.0",

src/AddToCampaignValidator.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace SilverStripe\CampaignAdmin;
44

5-
use SilverStripe\Forms\Validator;
5+
use SilverStripe\Forms\Validation\Validator;
66

77
class AddToCampaignValidator extends Validator
88
{

src/CampaignAdmin.php

+3-4
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@
99
use SilverStripe\Control\HTTPRequest;
1010
use SilverStripe\Control\HTTPResponse;
1111
use SilverStripe\Core\Config\Config;
12-
use SilverStripe\Core\Convert;
1312
use SilverStripe\Core\Injector\Injector;
1413
use SilverStripe\Forms\FieldList;
1514
use SilverStripe\Forms\Form;
1615
use SilverStripe\Forms\FormAction;
1716
use SilverStripe\Forms\HiddenField;
18-
use SilverStripe\Forms\RequiredFields;
17+
use SilverStripe\Forms\Validation\RequiredFieldsValidator;
1918
use SilverStripe\ORM\DataObject;
2019
use SilverStripe\ORM\FieldType\DBDatetime;
2120
use SilverStripe\Model\List\SS_List;
@@ -637,7 +636,7 @@ public function getCampaignEditForm($id)
637636
FormAction::create('cancel', _t(__CLASS__.'.CANCEL', 'Cancel'))
638637
->setUseButtonTag(true)
639638
),
640-
new RequiredFields('Name')
639+
RequiredFieldsValidator::create('Name')
641640
);
642641

643642
// Load into form
@@ -701,7 +700,7 @@ public function getCampaignCreateForm()
701700
FormAction::create('cancel', _t(__CLASS__.'.CANCEL', 'Cancel'))
702701
->setUseButtonTag(true)
703702
),
704-
new RequiredFields('Name')
703+
RequiredFieldsValidator::create('Name')
705704
);
706705

707706
// Custom form handler

tests/behat/features/manage-campaigns.feature

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Feature: Manage campaigns
55
So that I can control bulk publication of content efficiently
66

77
Background:
8-
Given a "campaign" "Test Campaign" with "Description"="this is a test"
8+
Given a "changeset" "Test Campaign" with "Description"="this is a test"
99
And the "group" "EDITOR" has permissions "Access to 'Pages' section" and "Access to 'Campaigns' section" and "Access to 'Files' section" and "FILE_EDIT_ALL"
1010
And the "group" "CAMPAIGNS_EDITOR" has permissions "Access to 'Campaigns' section"
1111

tests/behat/features/populate-campaigns.feature

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Feature: Populate campaigns
77
Background:
88
Given a "page" "About Us"
99
And a "image" "assets/folder1/file2.jpg"
10-
And a "Campaign" "Empty Campaign"
10+
And a "ChangeSet" "Empty Campaign"
1111
And a campaign "Full Campaign" with changes "image"="assets/folder1/file2.jpg" and "page"="About Us"
1212
And the "group" "EDITOR" has permissions "Access to 'Pages' section" and "Access to 'Campaigns' section" and "Access to 'Files' section" and "FILE_EDIT_ALL"
1313
And I am logged in as a member of "EDITOR" group

tests/behat/src/FixtureContext.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public function iCloseTheModal()
147147
{
148148
/** @var DocumentElement $page */
149149
$page = $this->getMainContext()->getSession()->getPage();
150-
$button = $page->find('css', '.modal-header .close');
150+
$button = $page->find('css', '.modal-header .btn-close');
151151
Assert::assertNotNull($button, 'Close button not found');
152152

153153
$button->click();

tests/php/AddToCampaignValidatorTest.php

+6
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public function testValidationFailed()
6868
'fieldName' => 'Campaign',
6969
'messageType' => 'error',
7070
'messageCast' => 'text',
71+
'modelClass' => '',
72+
'recordID' => null,
7173
]],
7274
$this->validator->getResult()->getMessages()
7375
);
@@ -83,6 +85,8 @@ public function testValidationFailed()
8385
'fieldName' => 'NewTitle',
8486
'messageType' => 'error',
8587
'messageCast' => 'text',
88+
'modelClass' => '',
89+
'recordID' => null,
8690
]],
8791
$this->validator->getResult()->getMessages()
8892
);
@@ -98,6 +102,8 @@ public function testValidationFailed()
98102
'fieldName' => 'NewTitle',
99103
'messageType' => 'error',
100104
'messageCast' => 'text',
105+
'modelClass' => '',
106+
'recordID' => null,
101107
]],
102108
$this->validator->getResult()->getMessages()
103109
);

0 commit comments

Comments
 (0)