Compare commits

..

3 Commits
5.1.1 ... 4

Author SHA1 Message Date
Steve Boyd
1b792b2a6d Merge branch '4.7' into 4 2024-07-11 16:14:35 +12:00
Guy Sartorelli
096f587261
Merge pull request #244 from creative-commoners/pulls/4.7/composer
DEP Bump minimum version of framework
2024-07-11 10:00:13 +12:00
Steve Boyd
4ea50b34f0 DEP Bump minimum version of framework 2024-07-10 11:38:53 +12:00
29 changed files with 3657 additions and 5554 deletions

7
.eslintrc Normal file
View File

@ -0,0 +1,7 @@
{
"extends": "airbnb",
"root": true,
"rules": {
"init-declarations": 1
}
}

View File

@ -1 +0,0 @@
module.exports = require('@silverstripe/eslint-config/.eslintrc');

View File

@ -1,10 +1,10 @@
name: Keepalive
on:
# At 8:40 PM UTC, on day 9 of the month
schedule:
- cron: '40 20 9 * *'
workflow_dispatch:
# The 4th of every month at 10:50am UTC
schedule:
- cron: '50 10 4 * *'
jobs:
keepalive:

View File

@ -1,17 +0,0 @@
name: Merge-up
on:
# At 11:30 AM UTC, only on Sunday
schedule:
- cron: '30 11 * * 0'
workflow_dispatch:
jobs:
merge-up:
name: Merge-up
# Only run cron on the silverstripe account
if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
runs-on: ubuntu-latest
steps:
- name: Merge-up
uses: silverstripe/gha-merge-up@v1

View File

@ -4,7 +4,7 @@ on:
workflow_dispatch:
# Run on a schedule of once per quarter
schedule:
- cron: '40 20 1 */3 *'
- cron: '0 0 1 */3 *'
jobs:
update-js:

2
.nvmrc
View File

@ -1 +1 @@
18
10

18
.upgrade.yml Normal file
View File

@ -0,0 +1,18 @@
mappings:
ContentReviewCompatability: SilverStripe\ContentReview\Compatibility\ContentReviewCompatability
ContentReviewCMSExtension: SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension
ContentReviewDefaultSettings: SilverStripe\ContentReview\Extensions\ContentReviewDefaultSettings
ContentReviewOwner: SilverStripe\ContentReview\Extensions\ContentReviewOwner
SiteTreeContentReview: SilverStripe\ContentReview\Extensions\SiteTreeContentReview
ContentReviewNotificationJob: SilverStripe\ContentReview\Jobs\ContentReviewNotificationJob
ContentReviewLog: SilverStripe\ContentReview\Models\ContentReviewLog
PagesDueForReviewReport: SilverStripe\ContentReview\Reports\PagesDueForReviewReport
PagesWithoutReviewScheduleReport: SilverStripe\ContentReview\Reports\PagesWithoutReviewScheduleReport
ContentReviewEmails: SilverStripe\ContentReview\Tasks\ContentReviewEmails
ContentReviewOwnerMigrationTask: SilverStripe\ContentReview\Tasks\ContentReviewOwnerMigrationTask
ContentReviewBaseTest: SilverStripe\ContentReview\Tests\ContentReviewBaseTest
ContentReviewCMSPageEditControllerTest: SilverStripe\ContentReview\Tests\ContentReviewCMSPageEditControllerTest
ContentReviewNotificationTest: SilverStripe\ContentReview\Tests\ContentReviewNotificationTest
ContentReviewReportTest: SilverStripe\ContentReview\Tests\ContentReviewReportTest
ContentReviewSettingsTest: SilverStripe\ContentReview\Tests\ContentReviewSettingsTest
SiteTreeContentReviewTest: SilverStripe\ContentReview\Tests\SiteTreeContentReviewTest

View File

@ -13,11 +13,11 @@ There are two types of roles with this module.
* Website owner; (typically assigned to the Administrator group) ensures that a website is accurate and up-to-date, by delegating responsibility to content reviewers.
* Content reviewer; responsible for keeping a website or part of a website accurate and up-to-date.
## Installation
## Requirements
```sh
composer require silverstripe/contentreview
```
* Silverstripe ^4.0
**Note:** For Silverstripe 3.x, please use the [3.x release line](https://github.com/silverstripe/silverstripe-contentreview/tree/3).
## Features
@ -36,7 +36,7 @@ composer require silverstripe/contentreview
## Composer installation
```sh
composer require silverstripe/contentreview
$ composer require silverstripe/contentreview
```
You'll also need to run `dev/build`.

6
_config/legacy.yml Normal file
View File

@ -0,0 +1,6 @@
---
Name: contentreviewlegacy
---
SilverStripe\ORM\DatabaseAdmin:
classname_value_remapping:
ContentReviewLog: SilverStripe\ContentReview\Models\ContentReviewLog

View File

@ -1,6 +0,0 @@
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}

View File

@ -1 +1 @@
!function(){"use strict";var e={30:function(e,t,n){var o=a(n(754)),i=a(n(311)),s=a(n(363)),r=n(691);function a(e){return e&&e.__esModule?e:{default:e}}const l=(0,n(648).loadComponent)("FormBuilderModal");i.default.entwine("ss",(e=>{e(".cms-content-actions .content-review__button").entwine({onclick(t){t.preventDefault();let n=e("#content-review__dialog-wrapper");return n.length||(n=e('<div id="content-review__dialog-wrapper" />'),e("body").append(n)),n.open(),!1}}),e(".content-review-modal .content-review-modal__nav-link").entwine({onclick:t=>{t.preventDefault();const n=e(t.target);window.location=n.attr("href")}}),e("#content-review__dialog-wrapper").entwine({ReactRoot:null,onunmatch(){this._clearModal()},open(){this._renderModal(!0)},close(){this._renderModal(!1)},_renderModal(t){var n=this;const i=e("form.cms-edit-form :input[name=ID]").val(),a=`${window.ss.store.getState().config.sections.find((e=>"SilverStripe\\CMS\\Controllers\\CMSPageEditController"===e.name)).form.ReviewContentForm.schemaUrl}/${i}`,d=o.default._t("ContentReview.CONTENT_DUE_FOR_REVIEW","Content due for review");let c=this.getReactRoot();c||(c=(0,r.createRoot)(this[0]),this.setReactRoot(c)),c.render(s.default.createElement(l,{title:d,isOpen:t,onSubmit:function(){return n._handleSubmitModal(...arguments)},onClosed:()=>this.close(),schemaUrl:a,bodyClassName:"modal__dialog",className:"content-review-modal",responseClassBad:"modal__response modal__response--error",responseClassGood:"modal__response modal__response--good",identifier:"ContentReview.CONTENT_DUE_FOR_REVIEW"}))},_clearModal(){const e=this.getReactRoot();e&&(e.unmount(),this.setReactRoot(null))},_handleSubmitModal(t,n,o){return e(".content-review__button-holder").remove(),o()}})}))},933:function(e,t,n){var o;((o=n(311))&&o.__esModule?o:{default:o}).default.entwine("ss",(e=>{e(".cms-edit-form #Form_EditForm_ContentReviewType_Holder").entwine({onmatch(){const e=this;this.find(".optionset :input").bind("change",(t=>{e.show_option(t.target.value)}));const t=this.find("input[name=ContentReviewType]:checked").val();this.show_option(t),this._super()},onunmatch(){return this._super()},show_option(e){"Custom"===e?this._custom():"Inherit"===e?this._inherited():this._disabled()},_custom(){e(".review-settings").show(),e(".field.custom-setting").show()},_inherited(){e(".review-settings").show(),e(".field.custom-setting").hide()},_disabled(){e(".review-settings").hide()}})}))},154:function(e,t,n){var o;((o=n(311))&&o.__esModule?o:{default:o}).default.entwine("ss",(e=>{function t(t){const n=`ContentReviewOwnerID${t}`,o=e("div.subsiteSpecificOwnerID");let i=0;for(i=0;i<o.length;i++)o[i].id===n?e(o[i]).show():e(o[i]).hide()}e("#Form_EditForm_SubsiteIDWithOwner").entwine({onmatch(){t(this.value)},change(){t(this.value)}})}))},648:function(e){e.exports=Injector},363:function(e){e.exports=React},691:function(e){e.exports=ReactDomClient},754:function(e){e.exports=i18n},311:function(e){e.exports=jQuery}},t={};function n(o){var i=t[o];if(void 0!==i)return i.exports;var s=t[o]={exports:{}};return e[o](s,s.exports,n),s.exports}n(30),n(933),n(154)}();
!function(e){function n(o){if(t[o])return t[o].exports;var i=t[o]={i:o,l:!1,exports:{}};return e[o].call(i.exports,i,i.exports,n),i.l=!0,i.exports}var t={};n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:o})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="",n(n.s=4)}([function(e,n){e.exports=jQuery},function(e,n,t){"use strict";var o=t(8),i=t.n(o),r=t(0),s=t.n(r),c=t(6),a=t.n(c),u=t(7),d=t.n(u),l=t(5),f=(t.n(l),t.i(l.loadComponent)("FormBuilderModal"));s.a.entwine("ss",function(e){e(".cms-content-actions .content-review__button").entwine({onclick:function(n){n.preventDefault();var t=e("#content-review__dialog-wrapper");return t.length||(t=e('<div id="content-review__dialog-wrapper" />'),e("body").append(t)),t.open(),!1}}),e(".content-review-modal .content-review-modal__nav-link").entwine({onclick:function(n){n.preventDefault();var t=e(n.target);window.location=t.attr("href")}}),e("#content-review__dialog-wrapper").entwine({onunmatch:function(){this._clearModal()},open:function(){this._renderModal(!0)},close:function(){this._renderModal(!1)},_renderModal:function(n){var t=this,o=function(){return t.close()},r=function(){return t._handleSubmitModal.apply(t,arguments)},s=e("form.cms-edit-form :input[name=ID]").val(),c=window.ss.store,u=c.getState().config.sections.find(function(e){return"SilverStripe\\CMS\\Controllers\\CMSPageEditController"===e.name}),l=u.form.ReviewContentForm.schemaUrl+"/"+s,_=i.a._t("ContentReview.CONTENT_DUE_FOR_REVIEW","Content due for review");d.a.render(a.a.createElement(f,{title:_,isOpen:n,onSubmit:r,onClosed:o,schemaUrl:l,bodyClassName:"modal__dialog",className:"content-review-modal",responseClassBad:"modal__response modal__response--error",responseClassGood:"modal__response modal__response--good",identifier:"ContentReview.CONTENT_DUE_FOR_REVIEW"}),this[0])},_clearModal:function(){d.a.unmountComponentAtNode(this[0])},_handleSubmitModal:function(n,t,o){return e(".content-review__button-holder").remove(),o()}})})},function(e,n,t){"use strict";var o=t(0);t.n(o).a.entwine("ss",function(e){e(".cms-edit-form #Form_EditForm_ContentReviewType_Holder").entwine({onmatch:function(){var e=this;this.find(".optionset :input").bind("change",function(n){e.show_option(n.target.value)});var n=this.find("input[name=ContentReviewType]:checked").val();this.show_option(n),this._super()},onunmatch:function(){return this._super()},show_option:function(e){"Custom"===e?this._custom():"Inherit"===e?this._inherited():this._disabled()},_custom:function(){e(".review-settings").show(),e(".field.custom-setting").show()},_inherited:function(){e(".review-settings").show(),e(".field.custom-setting").hide()},_disabled:function(){e(".review-settings").hide()}})})},function(e,n,t){"use strict";var o=t(0);t.n(o).a.entwine("ss",function(e){function n(n){var t="ContentReviewOwnerID"+n,o=e("div.subsiteSpecificOwnerID"),i=0;for(i=0;i<o.length;i++)o[i].id===t?e(o[i]).show():e(o[i]).hide()}e("#Form_EditForm_SubsiteIDWithOwner").entwine({onmatch:function(){n(this.value)},change:function(){n(this.value)}})})},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),t(1),t(2),t(3)},function(e,n){e.exports=Injector},function(e,n){e.exports=React},function(e,n){e.exports=ReactDom},function(e,n){e.exports=i18n}]);

View File

@ -1 +1 @@
.content-review__button{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAoCAYAAAD+MdrbAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPlJREFUeNpi/P//PwM1AeOAGPg1h3EBiOae8j+BkFoWIi22pIoLgS5rAFIFQMwPFfoIxBNAGOjaDyQZCDTsApDSx2HXRSB2wGYoEx6X6ePxmT7U5QxEGYhLMTFqMLwMdJ0AkHpPZBwYAr19gZALDUhIdgLEeplsQBcDBUjQr4A3UoARQlbGBkYMI828TN/SBkeaFMSVjwl6GaqxEUmoEZ9hA1fAjkADL8dC6hTdxYOtTgG6DGedAnQtaXUK0DCCdQo2Q5nwuGyQ1ilA15FUpwC9PVqn0LJOAUYIWRkbGDHDpU7BkSYFceVjgl6GakSpU/AZNjRKbIAAAwDhCJTckjfR5wAAAABJRU5ErkJggg==) center center no-repeat;background-position:0 0;display:inline-block;height:20px;margin:6px 4px 0 12px;padding:0;text-indent:-9999px;width:20px}.content-review__button:hover,.content-review__button:focus{background-position:0 -20px}
.content-review__button{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAoCAYAAAD+MdrbAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPlJREFUeNpi/P//PwM1AeOAGPg1h3EBiOae8j+BkFoWIi22pIoLgS5rAFIFQMwPFfoIxBNAGOjaDyQZCDTsApDSx2HXRSB2wGYoEx6X6ePxmT7U5QxEGYhLMTFqMLwMdJ0AkHpPZBwYAr19gZALDUhIdgLEeplsQBcDBUjQr4A3UoARQlbGBkYMI828TN/SBkeaFMSVjwl6GaqxEUmoEZ9hA1fAjkADL8dC6hTdxYOtTgG6DGedAnQtaXUK0DCCdQo2Q5nwuGyQ1ilA15FUpwC9PVqn0LJOAUYIWRkbGDHDpU7BkSYFceVjgl6GakSpU/AZNjRKbIAAAwDhCJTckjfR5wAAAABJRU5ErkJggg==) 50% no-repeat;background-position:0 0;display:inline-block;height:20px;margin:6px 4px 0 12px;padding:0;text-indent:-9999px;width:20px}.content-review__button:focus,.content-review__button:hover{background-position:0 -20px}

View File

@ -2,7 +2,7 @@
import i18n from 'i18n';
import jQuery from 'jquery';
import React from 'react';
import { createRoot } from 'react-dom/client';
import ReactDOM from 'react-dom';
import { loadComponent } from 'lib/Injector';
const FormBuilderModal = loadComponent('FormBuilderModal');
@ -12,7 +12,7 @@ const FormBuilderModal = loadComponent('FormBuilderModal');
* silverstripe/admin for reference.
*/
jQuery.entwine('ss', ($) => {
/**
/**
* Kick off a "content due for review" dialog from the CMS actions.
*/
$('.cms-content-actions .content-review__button').entwine({
@ -42,12 +42,10 @@ jQuery.entwine('ss', ($) => {
},
});
/**
/**
* Uses reactstrap in order to replicate the bootstrap styling and JavaScript behaviour.
*/
$('#content-review__dialog-wrapper').entwine({
ReactRoot: null,
onunmatch() {
// solves errors given by ReactDOM "no matched root found" error.
this._clearModal();
@ -72,12 +70,7 @@ jQuery.entwine('ss', ($) => {
const modalSchemaUrl = `${sectionConfig.form.ReviewContentForm.schemaUrl}/${id}`;
const title = i18n._t('ContentReview.CONTENT_DUE_FOR_REVIEW', 'Content due for review');
let root = this.getReactRoot();
if (!root) {
root = createRoot(this[0]);
this.setReactRoot(root);
}
root.render(
ReactDOM.render(
<FormBuilderModal
title={title}
isOpen={isOpen}
@ -89,16 +82,13 @@ jQuery.entwine('ss', ($) => {
responseClassBad="modal__response modal__response--error"
responseClassGood="modal__response modal__response--good"
identifier="ContentReview.CONTENT_DUE_FOR_REVIEW"
/>
/>,
this[0]
);
},
_clearModal() {
const root = this.getReactRoot();
if (root) {
root.unmount();
this.setReactRoot(null);
}
ReactDOM.unmountComponentAtNode(this[0]);
},
_handleSubmitModal(data, action, submitFn) {

View File

@ -1,5 +1,8 @@
import jQuery from 'jquery';
/**
* @todo Re-validate this with Subsites
*/
jQuery.entwine('ss', ($) => {
// Hide all owner dropdowns except the one for the current subsite
function showCorrectSubsiteIDDropdown(value) {

View File

@ -1,3 +1,3 @@
import 'bundles/ContentReviewForm';
import 'bundles/ContentReviewSettings';
import 'bundles/PagesDueForReview';
import 'bundles/ContentReviewForm.js';
import 'bundles/ContentReviewSettings.js';
import 'bundles/PagesDueForReview.js';

View File

@ -1,7 +1,7 @@
// The bell button, shows up next to the major actions (save, publish, etc) when
// viewing a page in the CMS
.content-review__button {
background: url('../images/icon-bell.png') center center no-repeat;
background: url("images/icon-bell.png") center center no-repeat;
background-position: 0 0;
display: inline-block;
height: 20px;

View File

@ -23,17 +23,17 @@
}
],
"require": {
"php": "^8.1",
"silverstripe/vendor-plugin": "^2",
"silverstripe/framework": "^5",
"silverstripe/cms": "^5",
"silverstripe/reports": "^5",
"silverstripe/siteconfig": "^5"
"php": "^7.4 || ^8.0",
"silverstripe/vendor-plugin": "^1",
"silverstripe/framework": "^4.11",
"silverstripe/cms": "^4.2",
"silverstripe/reports": "^4.2",
"silverstripe/siteconfig": "^4.2"
},
"require-dev": {
"silverstripe/recipe-testing": "^3",
"silverstripe/recipe-testing": "^2",
"squizlabs/php_codesniffer": "^3",
"symbiote/silverstripe-queuedjobs": "^5"
"symbiote/silverstripe-queuedjobs": "^4.9"
},
"suggest": {
"symbiote/silverstripe-queuedjobs": "Automatically schedules content review emails to be sent, only requiring one crontask to be created"

View File

@ -1,6 +1,6 @@
en:
SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension:
ErrorItemPermissionDenied: "It seems you don't have the necessary permissions to review this content"
ErrorItemPermissionDenied: 'It seems you don''t have the necessary permissions to review this content'
SilverStripe\ContentReview\Extensions\ContentReviewDefaultSettings:
ADDGROUP: 'Add groups'
ADDUSERS: 'Add users'
@ -51,7 +51,7 @@ en:
db_ReviewPeriodDays: 'Review period days'
has_many_ReviewLogs: 'Review logs'
SilverStripe\ContentReview\Forms\ReviewContentHandler:
ErrorReviewPermissionDenied: "It seems you don't have the necessary permissions to submit a content review"
ErrorReviewPermissionDenied: 'It seems you don''t have the necessary permissions to submit a content review'
MarkAsReviewedAction: 'Mark as reviewed'
NoComments: '(no comments)'
Placeholder: 'Add comments (optional)'

View File

@ -1,4 +1,4 @@
Copyright (c) 2017, Silverstripe Limited
Copyright (c) 2017, SilverStripe Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

View File

@ -1,9 +1,9 @@
{
"name": "silverstripe-contentreview",
"version": "4.0.0",
"description": "Flags pages for periodical author review (incl. reporting)",
"scripts": {
"build": "yarn && yarn lint && rm -rf client/dist/* && NODE_ENV=production webpack --mode production --bail --progress",
"dev": "NODE_ENV=development webpack --progress",
"build": "yarn && NODE_ENV=production webpack -p --bail --progress",
"watch": "yarn && NODE_ENV=development webpack --watch --progress",
"css": "WEBPACK_CHILD=css npm run build",
"lint": "eslint client/src; sass-lint -v"
@ -23,25 +23,22 @@
"url": "https://github.com/silverstripe/silverstripe-contentreview/issues"
},
"homepage": "https://github.com/silverstripe/silverstripe-contentreview#readme",
"engines": {
"node": "^18.x"
},
"dependencies": {
"react": "18.2.0",
"react-dom": "18.2.0",
"react-redux": "^8.0.4",
"redux": "^4.2.0"
"jquery": "^3.4.0",
"react": "15.3.1",
"react-dom": "15.3.1",
"react-redux": "^4.4.1",
"redux": "https://registry.npmjs.org/redux/-/redux-3.0.5.tgz"
},
"devDependencies": {
"@silverstripe/eslint-config": "^1.1.0",
"@silverstripe/webpack-config": "^2.0.0",
"webpack": "^5.74.0",
"webpack-cli": "^5.0.0"
"@silverstripe/webpack-config": "^0.2.5",
"babel-core": "^6.24.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-es2016": "^6.24.1",
"eslint": "^2.7.0",
"eslint-config-airbnb": "^6.2.0"
},
"resolutions": {
"colors": "1.4.0"
},
"browserslist": [
"defaults"
]
"engines": {
"node": "^10.x"
}
}

View File

@ -129,6 +129,8 @@ class ContentReviewCMSExtension extends LeftAndMainExtension
* Check if the current request has a X-Formschema-Request header set.
* Used by conditional logic that responds to validation results
*
* @todo Remove duplication. See https://github.com/silverstripe/silverstripe-admin/issues/240
*
* @return bool
*/
protected function getSchemaRequested()
@ -140,6 +142,8 @@ class ContentReviewCMSExtension extends LeftAndMainExtension
/**
* Generate schema for the given form based on the X-Formschema-Request header value
*
* @todo Remove duplication. See https://github.com/silverstripe/silverstripe-admin/issues/240
*
* @param string $schemaID ID for this schema. Required.
* @param Form $form Required for 'state' or 'schema' response
* @param ValidationResult $errors Required for 'error' response

View File

@ -20,8 +20,6 @@ use SilverStripe\Security\Permission;
* review setting.
*
* @property int $ReviewPeriodDays
* @method SilverStripe\ORM\ManyManyList<Group> ContentReviewGroups()
* @method SilverStripe\ORM\ManyManyList<Member> ContentReviewUsers()
*/
class ContentReviewDefaultSettings extends DataExtension
{

View File

@ -6,9 +6,6 @@ use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Forms\FieldList;
use SilverStripe\ORM\DataExtension;
/**
* @method SilverStripe\ORM\ManyManyList<SiteTree> SiteTreeContentReview()
*/
class ContentReviewOwner extends DataExtension
{
/**

View File

@ -50,9 +50,9 @@ use Symbiote\QueuedJobs\Services\QueuedJobService;
* @property string $LastEditedByName
* @property string $OwnerNames
*
* @method SilverStripe\ORM\ManyManyList<Group> ContentReviewGroups()
* @method SilverStripe\ORM\ManyManyList<Member> ContentReviewUsers()
* @method SilverStripe\ORM\HasManyList<ContentReviewLog> ReviewLogs()
* @method DataList ReviewLogs()
* @method DataList ContentReviewGroups()
* @method DataList ContentReviewUsers()
*/
class SiteTreeContentReview extends DataExtension implements PermissionProvider
{
@ -142,6 +142,7 @@ class SiteTreeContentReview extends DataExtension implements PermissionProvider
$groupMembers = DataObject::get(Member::class)
->where("\"Group\".\"ID\" IN (" . implode(",", $groupIDs) . ")")
->leftJoin("Group_Members", "\"Member\".\"ID\" = \"Group_Members\".\"MemberID\"")
/** @skipUpgrade */
->leftJoin('Group', "\"Group_Members\".\"GroupID\" = \"Group\".\"ID\"");
$contentReviewOwners->merge($groupMembers);

View File

@ -7,10 +7,6 @@ use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Member;
use SilverStripe\Security\Security;
/**
* @method Member Reviewer()
* @method SiteTree SiteTree()
*/
class ContentReviewLog extends DataObject
{
/**

View File

@ -179,6 +179,7 @@ class PagesDueForReviewReport extends Report
} else {
// Review date before
if (!empty($params['ReviewDateBefore'])) {
// TODO Get value from DateField->dataValue() once we have access to form elements here
$nextReviewUnixSec = strtotime(
' + 1 day',
strtotime($params['ReviewDateBefore'] ?? '')
@ -193,6 +194,7 @@ class PagesDueForReviewReport extends Report
// Review date after
if (!empty($params['ReviewDateAfter'])) {
// TODO Get value from DateField->dataValue() once we have access to form elements here
$records = $records->where(
sprintf(
"\"NextReviewDate\" >= '%s'",

View File

@ -4,6 +4,8 @@ namespace SilverStripe\ContentReview\Tests;
use SilverStripe\Dev\FunctionalTest;
use SilverStripe\CMS\Model\SiteTree;
// @todo add translatable namespace
use Translatable;
/**
* Extend this class when writing unit tests which are compatible with other modules.
@ -15,4 +17,36 @@ abstract class ContentReviewBaseTest extends FunctionalTest
* @var bool
*/
protected $translatableEnabledBefore;
protected function setUp(): void
{
parent::setUp();
/*
* We set the locale for pages explicitly, because if we don't, then we get into a situation
* where the page takes on the tester's (your) locale, and any calls to simulate subsequent requests
* (e.g. $this->post()) do not seem to get passed the tester's locale,
* but instead fallback to the default locale.
*
* So we set the pages locale to be the default locale, which will then match any subsequent requests.
*
* If creating pages in your unit tests (rather than reading from the fixtures file), you must explicitly call
* self::compat() on the page, for the same reasons as above.
*/
if (class_exists(Translatable::class)) {
$this->translatableEnabledBefore = SiteTree::has_extension(Translatable::class);
SiteTree::remove_extension(Translatable::class);
}
}
protected function tearDown(): void
{
if (class_exists(Translatable::class)) {
if ($this->translatableEnabledBefore) {
SiteTree::add_extension(Translatable::class);
}
}
parent::tearDown();
}
}

View File

@ -1,26 +1,54 @@
const Path = require('path');
const { JavascriptWebpackConfig, CssWebpackConfig } = require('@silverstripe/webpack-config');
// Import the core config
const webpackConfig = require('@silverstripe/webpack-config');
const {
resolveJS,
externalJS,
moduleJS,
pluginJS,
moduleCSS,
pluginCSS,
} = webpackConfig;
const ENV = process.env.NODE_ENV;
const PATHS = {
MODULES: 'node_modules',
FILES_PATH: '../',
ROOT: Path.resolve(),
SRC: Path.resolve('client/src'),
DIST: Path.resolve('client/dist'),
THIRDPARTY: Path.resolve('thirdparty'),
};
const config = [
// Main JS bundle
new JavascriptWebpackConfig('js', PATHS, 'silverstripe/contentreview')
.setEntry({
{
name: 'js',
entry: {
contentreview: `${PATHS.SRC}/bundles/bundle.js`,
})
.getConfig(),
// sass to css
new CssWebpackConfig('css', PATHS)
.setEntry({
},
output: {
path: PATHS.DIST,
filename: 'js/[name].js',
},
devtool: (ENV !== 'production') ? 'source-map' : '',
resolve: resolveJS(ENV, PATHS),
externals: externalJS(ENV, PATHS),
module: moduleJS(ENV, PATHS),
plugins: pluginJS(ENV, PATHS),
},
{
name: 'css',
entry: {
contentreview: `${PATHS.SRC}/styles/bundle.scss`,
})
.getConfig(),
},
output: {
path: PATHS.DIST,
filename: 'styles/[name].css'
},
devtool: (ENV !== 'production') ? 'source-map' : '',
module: moduleCSS(ENV, PATHS),
plugins: pluginCSS(ENV, PATHS),
},
];
module.exports = config;

8934
yarn.lock

File diff suppressed because it is too large Load Diff