Compare commits

..

No commits in common. "4.2.0" and "3" have entirely different histories.
4.2.0 ... 3

47 changed files with 7084 additions and 4697 deletions

View File

@ -1 +0,0 @@
<!-- Blank templates are for use by maintainers only! If you aren't a maintainer, please go back and pick one of the issue templates. -->

View File

@ -1,72 +0,0 @@
name: 🪳 Bug Report
description: Tell us if something isn't working the way it's supposed to
body:
- type: markdown
attributes:
value: |
We strongly encourage you to [submit a pull request](https://docs.silverstripe.org/en/contributing/code/) which fixes the issue.
Bug reports which are accompanied with a pull request are a lot more likely to be resolved quickly.
- type: input
id: affected-versions
attributes:
label: Module version(s) affected
description: |
What version of _this module_ have you reproduced this bug on?
Run `composer info` to see the specific version of each module installed in your project.
If you don't have access to that, check inside the help menu in the bottom left of the CMS.
placeholder: x.y.z
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: A clear and concise description of the problem
validations:
required: true
- type: textarea
id: how-to-reproduce
attributes:
label: How to reproduce
description: |
⚠️ This is the most important part of the report ⚠️
Without a way to easily reproduce your issue, there is little chance we will be able to help you and work on a fix.
- Please, take the time to show us some code and/or configuration that is needed for others to reproduce the problem easily.
- If the bug is too complex to reproduce with some short code samples, please reproduce it in a public repository and provide a link to the repository along with steps for setting up and reproducing the bug using that repository.
- If part of the bug includes an error or exception, please provide a full stack trace.
- If any user interaction is required to reproduce the bug, please add an ordered list of steps that are required to reproduce it.
- Be as clear as you can, but don't miss any steps out. Simply saying "create a page" is less useful than guiding us through the steps you're taking to create a page, for example.
placeholder: |
#### Code sample
```php
```
#### Reproduction steps
1.
validations:
required: true
- type: textarea
id: possible-solution
attributes:
label: Possible Solution
description: |
*Optional: only if you have suggestions on a fix/reason for the bug*
Please consider [submitting a pull request](https://docs.silverstripe.org/en/contributing/code/) with your solution! It helps get faster feedback and greatly increases the chance of the bug being fixed.
- type: textarea
id: additional-context
attributes:
label: Additional Context
description: "*Optional: any other context about the problem: log messages, screenshots, etc.*"
- type: checkboxes
id: validations
attributes:
label: Validations
description: "Before submitting the issue, please make sure you do the following:"
options:
- label: Check that there isn't already an issue that reports the same bug
required: true
- label: Double check that your reproduction steps work in a fresh installation of [`silverstripe/installer`](https://github.com/silverstripe/silverstripe-installer) (with any code examples you've provided)
required: true

View File

@ -1,35 +0,0 @@
name: 🚀 Feature Request
description: Submit a feature request (but only if you're planning on implementing it)
body:
- type: markdown
attributes:
value: |
Please only submit feature requests if you plan on implementing the feature yourself.
See the [contributing code documentation](https://docs.silverstripe.org/en/contributing/code/#make-or-find-a-github-issue) for more guidelines about submitting feature requests.
- type: textarea
id: description
attributes:
label: Description
description: A clear and concise description of the new feature, and why it belongs in core
validations:
required: true
- type: textarea
id: more-info
attributes:
label: Additional context or points of discussion
description: |
*Optional: Any additional context, points of discussion, etc that might help validate and refine your idea*
- type: checkboxes
id: validations
attributes:
label: Validations
description: "Before submitting the issue, please confirm the following:"
options:
- label: You intend to implement the feature yourself
required: true
- label: You have read the [contributing guide](https://docs.silverstripe.org/en/contributing/code/)
required: true
- label: You strongly believe this feature should be in core, rather than being its own community module
required: true
- label: You have checked for existing issues or pull requests related to this feature (and didn't find any)
required: true

View File

@ -1,8 +0,0 @@
blank_issues_enabled: true
contact_links:
- name: Security Vulnerability
url: https://docs.silverstripe.org/en/contributing/issues_and_bugs/#reporting-security-issues
about: ⚠️ We do not use GitHub issues to track security vulnerability reports. Click "open" on the right to see how to report security vulnerabilities.
- name: Support Question
url: https://www.silverstripe.org/community/
about: We use GitHub issues only to discuss bugs and new features. For support questions, please use one of the support options available in our community channels.

View File

@ -1,39 +0,0 @@
<!--
Thanks for contributing, you're awesome! ⭐
Please read https://docs.silverstripe.org/en/contributing/code/ if you haven't contributed to this project recently.
-->
## Description
<!--
Please describe expected and observed behaviour, and what you're fixing.
For visual fixes, please include tested browsers and screenshots.
-->
## Manual testing steps
<!--
Include any manual testing steps here which a reviewer can perform to validate your pull request works correctly.
Note that this DOES NOT replace unit or end-to-end tests.
-->
## Issues
<!--
List all issues here that this pull request fixes/resolves.
If there is no issue already, create a new one! You must link your pull request to at least one issue.
-->
- #
## Pull request checklist
<!--
PLEASE check each of these to ensure you have done everything you need to do!
If there's something in this list you need help with, please ask so that we can assist you.
-->
- [ ] The target branch is correct
- See [picking the right version](https://docs.silverstripe.org/en/contributing/code/#picking-the-right-version)
- [ ] All commits are relevant to the purpose of the PR (e.g. no debug statements, unrelated refactoring, or arbitrary linting)
- Small amounts of additional linting are usually okay, but if it makes it hard to concentrate on the relevant changes, ask for the unrelated changes to be reverted, and submitted as a separate PR.
- [ ] The commit messages follow our [commit message guidelines](https://docs.silverstripe.org/en/contributing/code/#commit-messages)
- [ ] The PR follows our [contribution guidelines](https://docs.silverstripe.org/en/contributing/code/)
- [ ] Code changes follow our [coding conventions](https://docs.silverstripe.org/en/contributing/coding_conventions/)
- [ ] This change is covered with tests (or tests aren't necessary for this change)
- [ ] Any relevant User Help/Developer documentation is updated; for impactful changes, information is added to the changelog for the intended release
- [ ] CI is green

View File

@ -1,10 +1,10 @@
name: Keepalive
on:
# At 2:10 AM UTC, on day 11 of the month
schedule:
- cron: '10 2 11 * *'
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 12:20 PM UTC, only on Saturday
schedule:
- cron: '20 12 * * 6'
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: '10 2 1 */3 *'
- cron: '0 0 1 */3 *'
jobs:
update-js:

2
.nvmrc
View File

@ -1 +1 @@
18
10

33
.upgrade.yml Normal file
View File

@ -0,0 +1,33 @@
mappings:
GridFieldCategorisationConfig: SilverStripe\Blog\Admin\GridFieldCategorisationConfig
GridFieldFormAction: SilverStripe\Blog\Admin\GridFieldFormAction
GridFieldMergeAction: SilverStripe\Blog\Admin\GridFieldMergeAction
BlogCommentExtension: SilverStripe\Blog\Model\BlogCommentExtension
BlogFilter: SilverStripe\Blog\Model\BlogFilter
BlogFilter_GridField: SilverStripe\Blog\Model\BlogFilter\BlogFilterGridField
BlogMemberExtension: SilverStripe\Blog\Model\BlogMemberExtension
BlogPostFilter: SilverStripe\Blog\Model\BlogPostFilter
BlogPostNotifications: SilverStripe\Blog\Model\BlogPostNotifications
Blog: SilverStripe\Blog\Model\Blog
Blog_Controller: SilverStripe\Blog\Model\BlogController
BlogController: SilverStripe\Blog\Model\BlogController
BlogCategory: SilverStripe\Blog\Model\BlogCategory
BlogPost: SilverStripe\Blog\Model\BlogPost
BlogPost_Controller: SilverStripe\Blog\Model\BlogPostController
BlogPostController: SilverStripe\Blog\Model\BlogPostController
BlogTag: SilverStripe\Blog\Model\BlogTag
CategorisationObject: SilverStripe\Blog\Model\CategorisationObject
BlogAdminSidebar: SilverStripe\Blog\Forms\BlogAdminSidebar
GridFieldAddByDBField: SilverStripe\Blog\Forms\GridField\GridFieldAddByDBField
GridFieldBlogPostState: SilverStripe\Blog\Forms\GridField\GridFieldBlogPostState
GridFieldConfig_BlogPost: SilverStripe\Blog\Forms\GridField\GridFieldConfigBlogPost
BlogArchiveWidget: SilverStripe\Blog\Widgets\BlogArchiveWidget
BlogArchiveWidget_Controller: SilverStripe\Blog\Widgets\BlogArchiveWidgetController
BlogCategoriesWidget: SilverStripe\Blog\Widgets\BlogCategoriesWidget
BlogCategoriesWidget_Controller: SilverStripe\Blog\Widgets\BlogCategoriesWidgetController
BlogRecentPostsWidget: SilverStripe\Blog\Widgets\BlogRecentPostsWidget
BlogRecentPostsWidget_Controller: SilverStripe\Blog\Widgets\BlogRecentPostsWidgetController
BlogTagsCloudWidget: SilverStripe\Blog\Widgets\BlogTagsCloudWidget
BlogTagsCloudWidget_Controller: SilverStripe\Blog\Widgets\BlogTagsCloudWidgetController
BlogTagsWidget: SilverStripe\Blog\Widgets\BlogTagsWidget
BlogTagsWidget_Controller: SilverStripe\Blog\Widgets\BlogTagsWidgetController

View File

@ -8,6 +8,16 @@
* [User guide](docs/en/userguide/index.md)
* [Developer documentation](docs/en/index.md)
## Requirements
* Silverstripe CMS 4.0+
* Silverstripe Lumberjack Module 2.0+
* Silverstripe Tag Field Module 2.0+
* Silverstripe Assets 1.0+
* Silverstripe Asset Admin Module 1.0+
Note: this version is compatible with Silverstripe 4. For Silverstripe 3, please see [the 2.x release line](https://github.com/silverstripe/silverstripe-blog/tree/2).
### Suggested Modules
* Silverstripe Widgets Module
@ -18,3 +28,13 @@
```
composer require silverstripe/blog
```
## Upgrading
### Upgrading from 2.x to 3.x
Aside from the framework and CMS upgrades required the blog module should not require anything extra to be completed.
### Upgrading legacy blog to 2.x
If you're upgrading from blog version 1.0 to 2.x you will need to run the `BlogMigrationTask`. Run the task using `dev/tasks/BlogMigrationTask` either via the browser or sake CLI to migrate your legacy blog to the new version data structure.

14
_config/legacy.yml Normal file
View File

@ -0,0 +1,14 @@
---
Name: bloglegacy
---
SilverStripe\ORM\DatabaseAdmin:
classname_value_remapping:
Blog: SilverStripe\Blog\Model\Blog
BlogCategory: SilverStripe\Blog\Model\BlogCategory
BlogPost: SilverStripe\Blog\Model\BlogPost
BlogTag: SilverStripe\Blog\Model\BlogTag
BlogArchiveWidget: SilverStripe\Blog\Widgets\BlogArchiveWidget
BlogCategoriesWidget: SilverStripe\Blog\Widgets\BlogCategoriesWidget
BlogRecentPostsWidget: SilverStripe\Blog\Widgets\BlogRecentPostsWidget
BlogTagsCloudWidget: SilverStripe\Blog\Widgets\BlogTagsCloudWidget
BlogTagsWidget: SilverStripe\Blog\Widgets\BlogTagsWidget

View File

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

View File

@ -1 +1 @@
!function(){"use strict";var t={949:function(t,e,n){var i;((i=n(311))&&i.__esModule?i:{default:i}).default.entwine("ss",(t=>{t(".cms-content-fields > #Form_EditForm_error").entwine({onadd(){const e=t(".blog-admin-outer");1===e.length&&e.prepend(this)}}),t(".toggle-description").entwine({onadd(){const e=t(this);if(e.hasClass("toggle-description-enabled"))return;e.addClass("toggle-description-enabled");let n=!1;const i=e.closest(".field").find(".form-text");e.on("click",(()=>{i[n?"hide":"show"](),e.toggleClass("toggle-description-shown"),n=!n})),i.hide(),e.parent().addClass("toggle-description-correct-right"),e.parent().prev(".middleColumn").addClass("toggle-description-correct-middle"),e.parent().next(".description").addClass("toggle-description-correct-description")}}),t(".MergeAction").entwine({onadd(){const e=t(this);e.on("click","select",(()=>!1)),e.children("button").each(((e,n)=>{const i=t(n),s=i.prev("select");i.before(`<input type="hidden" name="${i.attr("data-target")}" value="${s.val()}" />`)})),e.on("change","select",(e=>{const n=t(e.target);n.next("input").val(n.val())})),e.children("button, select").hide(),e.on("click",".MergeActionReveal",(e=>{const n=t(e.target);return n.parent().children("button, select").show(),n.hide(),!1}))}}),t(".blog-admin-sidebar.cms-panel").entwine({MinInnerWidth:620,onadd(){this._super(),this.updateLayout(),!this.hasClass("collapsed")&&t(".blog-admin-outer").width()<this.getMinInnerWidth()&&this.collapsePanel();const e=()=>{this.updateLayout()};e.bind(this),window.onresize=e},togglePanel(t,e){this._super(t,e),this.updateLayout()},updateLayout(){t(this).css("height","100%");const e=t(this).outerHeight(),n=t(".cms-content-actions").eq(0).outerHeight();t(this).css("height",e-n+"px"),t(this).css("bottom",`${n}px`),t(".cms-container").updateLayoutOptions({minContentWidth:820+this.width()})}})}))},997:function(t,e,n){var i;((i=n(311))&&i.__esModule?i:{default:i}).default.entwine("ss",(t=>{t(".add-existing-autocompleter input.text").entwine({onkeydown(e){if(13===e.which){t(this).parents(".add-existing-autocompleter").find('button[type="submit"]').click(),e.preventDefault()}}})}))},311:function(t){t.exports=jQuery}},e={};function n(i){var s=e[i];if(void 0!==s)return s.exports;var o=e[i]={exports:{}};return t[i](o,o.exports,n),o.exports}n(949),n(997)}();
!function(t){function e(i){if(n[i])return n[i].exports;var o=n[i]={i:i,l:!1,exports:{}};return t[i].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var n={};e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,i){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:i})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s="./client/src/main.js")}({"./client/src/bundles/cms.js":function(t,e,n){"use strict";var i=n(0);n.n(i).a.entwine("ss",function(t){t(".cms-content-fields > #Form_EditForm_error").entwine({onadd:function(){var e=t(".blog-admin-outer");1===e.length&&e.prepend(this)}}),t(".toggle-description").entwine({onadd:function(){var e=t(this);if(!e.hasClass("toggle-description-enabled")){e.addClass("toggle-description-enabled");var n=!1,i=e.closest(".field").find(".form-text");e.on("click",function(){i[n?"hide":"show"](),e.toggleClass("toggle-description-shown"),n=!n}),i.hide(),e.parent().addClass("toggle-description-correct-right"),e.parent().prev(".middleColumn").addClass("toggle-description-correct-middle"),e.parent().next(".description").addClass("toggle-description-correct-description")}}}),t(".MergeAction").entwine({onadd:function(){var e=t(this);e.on("click","select",function(){return!1}),e.children("button").each(function(e,n){var i=t(n),o=i.prev("select");i.before('<input type="hidden" name="'+i.attr("data-target")+'" value="'+o.val()+'" />')}),e.on("change","select",function(e){var n=t(e.target);n.next("input").val(n.val())}),e.children("button, select").hide(),e.on("click",".MergeActionReveal",function(e){var n=t(e.target);return n.parent().children("button, select").show(),n.hide(),!1})}}),t(".blog-admin-sidebar.cms-panel").entwine({MinInnerWidth:620,onadd:function(){var e=this;this._super(),this.updateLayout(),!this.hasClass("collapsed")&&t(".blog-admin-outer").width()<this.getMinInnerWidth()&&this.collapsePanel();var n=function(){e.updateLayout()};n.bind(this),window.onresize=n},togglePanel:function(t,e){this._super(t,e),this.updateLayout()},updateLayout:function(){t(this).css("height","100%");var e=t(this).outerHeight(),n=t(".cms-content-actions").eq(0).outerHeight();t(this).css("height",e-n+"px"),t(this).css("bottom",n+"px"),t(".cms-container").updateLayoutOptions({minContentWidth:820+this.width()})}})})},"./client/src/bundles/gridfieldaddbydbfield.js":function(t,e,n){"use strict";var i=n(0);n.n(i).a.entwine("ss",function(t){t(".add-existing-autocompleter input.text").entwine({onkeydown:function(e){13===e.which&&(t(this).parents(".add-existing-autocompleter").find('button[type="submit"]').click(),e.preventDefault())}})})},"./client/src/main.js":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),n("./client/src/bundles/cms.js"),n("./client/src/bundles/gridfieldaddbydbfield.js")},0:function(t,e){t.exports=jQuery}});

View File

@ -1 +1 @@
.no-sidebar .content-container.size3of4{width:75%}.blog-entry .post-image img{width:98.75%}.blog-sidebar .WidgetHolder ul{margin-left:0}.blog-sidebar .WidgetHolder ul li{list-style-type:none}ul.blogTagCloud{list-style-type:none;clear:both}ul.blogTagCloud li{float:left;display:inline;padding-right:8px}ul.blogTagCloud li a span{float:left;line-height:30px;text-align:center;padding:0}ul.blogTagCloud .tagCount10{font-size:26pt}ul.blogTagCloud .tagCount9{font-size:24pt}ul.blogTagCloud .tagCount8{font-size:22pt}ul.blogTagCloud .tagCount7{font-size:20pt}ul.blogTagCloud .tagCount6{font-size:18pt}ul.blogTagCloud .tagCount5{font-size:16pt}ul.blogTagCloud .tagCount4{font-size:14pt}ul.blogTagCloud .tagCount3{font-size:12pt}ul.blogTagCloud .tagCount2{font-size:10pt}ul.blogTagCloud .tagCount1{font-size:8pt}#FeaturedImage .middleColumn{clear:none;float:left}.has-panel .cms-content-tools.blog-admin-sidebar{width:280px;border-right:0;border-left:1px solid #c0c0c2;position:absolute !important;right:0;top:0;height:100%}.has-panel .cms-content-tools.blog-admin-sidebar .cms-panel-toggle a{text-align:left;margin:0}.has-panel .cms-content-tools.blog-admin-sidebar .cms-panel-toggle.south{border-top:1px solid #aaa}.has-panel .cms-content-tools.blog-admin-sidebar~.blog-admin-outer{width:100%;padding-right:280px;position:absolute;height:100%;overflow-y:hidden;overflow-x:hidden;box-sizing:border-box}.has-panel .cms-content-tools.blog-admin-sidebar~.blog-admin-outer>.ss-tabset{position:relative;overflow:auto;height:100%;width:100%}.has-panel .cms-content-tools.blog-admin-sidebar~.blog-admin-outer>.ss-tabset #Title label{float:none}.has-panel .cms-content-tools.blog-admin-sidebar~.blog-admin-outer>.ss-tabset #Title .middleColumn,.has-panel .cms-content-tools.blog-admin-sidebar~.blog-admin-outer>.ss-tabset #Title input{width:100%;max-width:100%;margin-left:0}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field+.field{margin-top:10px}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.urlsegment .preview{padding-top:0;line-height:25px}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.urlsegment .edit{float:right}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.datetime>.middleColumn>.date{width:60%}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.datetime>.middleColumn>.time{width:36%;float:right}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.datetime>.middleColumn .middleColumn,.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.datetime>.middleColumn input{width:100%}.has-panel .cms-content-tools.blog-admin-sidebar.collapsed~.blog-admin-outer{padding-right:41px}.has-panel .cms-content-tools.blog-admin-sidebar.collapsed~.blog-admin-outer #Root_Main{margin-right:15px}.has-panel .cms-content-tools.blog-admin-sidebar.cms-content-tools .cms-panel-content{width:auto}.toggle-description{display:inline-block;font-size:1.2rem;width:20px;height:20px;margin-top:1px;cursor:pointer}.middleColumn.toggle-description-correct-middle{margin-left:0;float:left;width:416px}.tab-content .field p.toggle-description-correct-right{display:inline-block;margin-left:0;padding-left:0;clear:none;float:left}.description.toggle-description-correct-description{width:416px;padding:12px 0}.custom-summary .ui-accordion-content,.custom-summary .ui-accordion-content .field{padding:0}.cms table.ss-gridfield-table tr td.MergeAction{width:225px}.cms table.ss-gridfield-table tr td.MergeAction a{display:block;height:100%;width:100%}.cms table.ss-gridfield-table tr td.MergeAction select{width:150px}.blog-cms-categorisation .toolbar--content{margin-top:0}.blog-cms-categorisation .MergeActionReveal:after{content:"@";font-family:silverstripe;display:inline-block;position:relative;margin-left:10px;top:3px}.blog-cms-categorisation .blog-merge-action{margin-top:5px}
.no-sidebar .content-container.size3of4{width:75%}.blog-entry .post-image img{width:98.75%}.blog-sidebar .WidgetHolder ul{margin-left:0}.blog-sidebar .WidgetHolder ul li,ul.blogTagCloud{list-style-type:none}ul.blogTagCloud{clear:both}ul.blogTagCloud li{float:left;display:inline;padding-right:8px}ul.blogTagCloud li a span{float:left;line-height:30px;text-align:center;padding:0}ul.blogTagCloud .tagCount10{font-size:26pt}ul.blogTagCloud .tagCount9{font-size:24pt}ul.blogTagCloud .tagCount8{font-size:22pt}ul.blogTagCloud .tagCount7{font-size:20pt}ul.blogTagCloud .tagCount6{font-size:18pt}ul.blogTagCloud .tagCount5{font-size:16pt}ul.blogTagCloud .tagCount4{font-size:14pt}ul.blogTagCloud .tagCount3{font-size:12pt}ul.blogTagCloud .tagCount2{font-size:10pt}ul.blogTagCloud .tagCount1{font-size:8pt}#FeaturedImage .middleColumn{clear:none;float:left}.has-panel .cms-content-tools.blog-admin-sidebar{width:280px;border-right:0;border-left:1px solid #c0c0c2;position:absolute!important;right:0;top:0;height:100%}.has-panel .cms-content-tools.blog-admin-sidebar .cms-panel-toggle a{text-align:left;margin:0}.has-panel .cms-content-tools.blog-admin-sidebar .cms-panel-toggle.south{border-top:1px solid #aaa}.has-panel .cms-content-tools.blog-admin-sidebar~.blog-admin-outer{width:100%;padding-right:280px;position:absolute;height:100%;overflow-y:hidden;overflow-x:hidden;-webkit-box-sizing:border-box;box-sizing:border-box}.has-panel .cms-content-tools.blog-admin-sidebar~.blog-admin-outer>.ss-tabset{position:relative;overflow:auto;height:100%;width:100%}.has-panel .cms-content-tools.blog-admin-sidebar~.blog-admin-outer>.ss-tabset #Title label{float:none}.has-panel .cms-content-tools.blog-admin-sidebar~.blog-admin-outer>.ss-tabset #Title .middleColumn,.has-panel .cms-content-tools.blog-admin-sidebar~.blog-admin-outer>.ss-tabset #Title input{width:100%;max-width:100%;margin-left:0}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field+.field{margin-top:10px}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.urlsegment .preview{padding-top:0;line-height:25px}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.urlsegment .edit{float:right}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.datetime>.middleColumn>.date{width:60%}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.datetime>.middleColumn>.time{width:36%;float:right}.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.datetime>.middleColumn .middleColumn,.has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view>.field.datetime>.middleColumn input{width:100%}.has-panel .cms-content-tools.blog-admin-sidebar.collapsed~.blog-admin-outer{padding-right:41px}.has-panel .cms-content-tools.blog-admin-sidebar.collapsed~.blog-admin-outer #Root_Main{margin-right:15px}.has-panel .cms-content-tools.blog-admin-sidebar.cms-content-tools .cms-panel-content{width:auto}.toggle-description{display:inline-block;font-size:1.2rem;width:20px;height:20px;margin-top:1px;cursor:pointer}.middleColumn.toggle-description-correct-middle{margin-left:0;float:left;width:416px}.tab-content .field p.toggle-description-correct-right{display:inline-block;margin-left:0;padding-left:0;clear:none;float:left}.description.toggle-description-correct-description{width:416px;padding:12px 0}.custom-summary .ui-accordion-content,.custom-summary .ui-accordion-content .field{padding:0}.custom-summary .ui-icon-triangle-1-e{background-position:-16px -128px}.cms table.ss-gridfield-table tr td.MergeAction{width:225px}.cms table.ss-gridfield-table tr td.MergeAction a{display:block;height:100%;width:100%}.cms table.ss-gridfield-table tr td.MergeAction select{width:150px}.blog-cms-categorisation .toolbar--content{margin-top:0}.blog-cms-categorisation .MergeActionReveal:after{content:"@";font-family:silverstripe;display:inline-block;position:relative;margin-left:10px;top:3px}.blog-cms-categorisation .blog-merge-action{margin-top:5px}

View File

@ -2,141 +2,141 @@
import jQuery from 'jquery';
jQuery.entwine('ss', ($) => {
/**
/**
* The page success/error message sits outside of the html block
* containing the sidebar and cms fields. This means it overflows
* underneath the sidebar.
*
* @see https://github.com/silverstripe/silverstripe-blog/issues/210
*/
$('.cms-content-fields > #Form_EditForm_error').entwine({
onadd() {
const $target = $('.blog-admin-outer');
if ($target.length === 1) {
$target.prepend(this);
}
}
});
$('.cms-content-fields > #Form_EditForm_error').entwine({
onadd() {
const $target = $('.blog-admin-outer');
if ($target.length === 1) {
$target.prepend(this);
}
}
});
/**
/**
* Register expandable help text functions with fields.
*/
$('.toggle-description').entwine({
onadd() {
const $this = $(this);
$('.toggle-description').entwine({
onadd() {
const $this = $(this);
/**
/**
* Prevent multiple events being added.
*/
if ($this.hasClass('toggle-description-enabled')) {
return;
}
if ($this.hasClass('toggle-description-enabled')) {
return;
}
$this.addClass('toggle-description-enabled');
$this.addClass('toggle-description-enabled');
/**
/**
* Toggle next description when button is clicked.
*/
let shown = false;
const $helpInfo = $this.closest('.field').find('.form-text');
let shown = false;
const $helpInfo = $this.closest('.field').find('.form-text');
$this.on('click', () => {
$helpInfo[shown ? 'hide' : 'show']();
$this.toggleClass('toggle-description-shown');
shown = !shown;
});
$this.on('click', () => {
$helpInfo[shown ? 'hide' : 'show']();
$this.toggleClass('toggle-description-shown');
shown = !shown;
});
/**
/**
* Hide next description by default.
*/
$helpInfo.hide();
$helpInfo.hide();
/**
/**
* Add classes to correct inherited layout issues in a small context.
*/
$this.parent().addClass('toggle-description-correct-right');
$this.parent().prev('.middleColumn').addClass('toggle-description-correct-middle');
$this.parent().next('.description').addClass('toggle-description-correct-description');
}
});
$this.parent().addClass('toggle-description-correct-right');
$this.parent().prev('.middleColumn').addClass('toggle-description-correct-middle');
$this.parent().next('.description').addClass('toggle-description-correct-description');
}
});
/**
/**
* Custom merge actions for tags and categories
*/
$('.MergeAction').entwine({
onadd() {
const $this = $(this);
$('.MergeAction').entwine({
onadd() {
const $this = $(this);
$this.on('click', 'select', () => false);
$this.on('click', 'select', () => false);
$this.children('button').each((i, button) => {
const $button = $(button);
const $select = $button.prev('select');
$this.children('button').each((i, button) => {
const $button = $(button);
const $select = $button.prev('select');
$button.before(`<input type="hidden" name="${$button.attr('data-target')}" value="${$select.val()}" />`);
});
$button.before(`<input type="hidden" name="${$button.attr('data-target')}" value="${$select.val()}" />`);
});
$this.on('change', 'select', (e) => {
const $target = $(e.target);
$this.on('change', 'select', (e) => {
const $target = $(e.target);
$target.next('input').val($target.val());
});
$target.next('input').val($target.val());
});
$this.children('button, select').hide();
$this.children('button, select').hide();
$this.on('click', '.MergeActionReveal', (e) => {
const $target = $(e.target);
$this.on('click', '.MergeActionReveal', (e) => {
const $target = $(e.target);
$target.parent().children('button, select').show();
$target.hide();
$target.parent().children('button, select').show();
$target.hide();
return false;
});
}
});
return false;
});
}
});
/**
/**
* Customise the cms-panel behaviour for blog sidebar
*
* see LeftAndMain.Panel.js for base behaviour
*/
$('.blog-admin-sidebar.cms-panel').entwine({
MinInnerWidth: 620,
onadd() {
this._super();
this.updateLayout();
$('.blog-admin-sidebar.cms-panel').entwine({
MinInnerWidth: 620,
onadd() {
this._super();
this.updateLayout();
// Contract panel if it's open and the left hand column is smaller than the minimum
if (!this.hasClass('collapsed') && ($('.blog-admin-outer').width() < this.getMinInnerWidth())) {
this.collapsePanel();
}
// Contract panel if it's open and the left hand column is smaller than the minimum
if (!this.hasClass('collapsed') && ($('.blog-admin-outer').width() < this.getMinInnerWidth())) {
this.collapsePanel();
}
const onresize = () => {
this.updateLayout();
};
onresize.bind(this);
const onresize = () => {
this.updateLayout();
};
onresize.bind(this);
window.onresize = onresize;
},
togglePanel(bool, silent) {
this._super(bool, silent);
this.updateLayout();
},
/**
window.onresize = onresize;
},
togglePanel(bool, silent) {
this._super(bool, silent);
this.updateLayout();
},
/**
* Adjust minimum width of content to account for extra panel
*
* @returns {undefined}
*/
updateLayout() {
$(this).css('height', '100%');
const currentHeight = $(this).outerHeight();
const bottomHeight = $('.cms-content-actions').eq(0).outerHeight();
$(this).css('height', `${currentHeight - bottomHeight}px`);
$(this).css('bottom', `${bottomHeight}px`);
updateLayout() {
$(this).css('height', '100%');
const currentHeight = $(this).outerHeight();
const bottomHeight = $('.cms-content-actions').eq(0).outerHeight();
$(this).css('height', `${currentHeight - bottomHeight}px`);
$(this).css('bottom', `${bottomHeight}px`);
$('.cms-container').updateLayoutOptions({
minContentWidth: 820 + this.width()
});
}
});
$('.cms-container').updateLayoutOptions({
minContentWidth: 820 + this.width()
});
}
});
});

View File

@ -1,16 +1,16 @@
import jQuery from 'jquery';
jQuery.entwine('ss', ($) => {
/**
/**
* Prevent the CMS hijacking the return key
*/
$('.add-existing-autocompleter input.text').entwine({
onkeydown(e) {
if (e.which === 13) {
const $parent = $(this).parents('.add-existing-autocompleter');
$parent.find('button[type="submit"]').click();
e.preventDefault();
}
}
});
$('.add-existing-autocompleter input.text').entwine({
onkeydown(e) {
if (e.which === 13) {
const $parent = $(this).parents('.add-existing-autocompleter');
$parent.find('button[type="submit"]').click();
e.preventDefault();
}
}
});
});

View File

@ -142,6 +142,11 @@
.ui-accordion-content .field {
padding: 0;
}
// Change the caret to a plus icon
.ui-icon-triangle-1-e {
background-position: -16px -128px;
}
}
.cms table.ss-gridfield-table {

View File

@ -8,21 +8,19 @@
],
"type": "silverstripe-vendormodule",
"require": {
"php": "^8.1",
"silverstripe/cms": "^5",
"silverstripe/lumberjack": "^3.0",
"silverstripe/tagfield": "^3.0",
"silverstripe/assets": "^2.0",
"silverstripe/asset-admin": "^2.0"
"php": "^7.4 || ^8.0",
"silverstripe/cms": "^4.0",
"silverstripe/lumberjack": "^2.0",
"silverstripe/tagfield": "^2.0",
"silverstripe/assets": "^1.0",
"silverstripe/asset-admin": "^1.0"
},
"require-dev": {
"silverstripe/recipe-testing": "^3",
"squizlabs/php_codesniffer": "^3",
"silverstripe/widgets": "^3",
"silverstripe/comments": "^4",
"silverstripe/content-widget": "^3",
"silverstripe/standards": "^1",
"phpstan/extension-installer": "^1.3"
"silverstripe/recipe-testing": "^2",
"squizlabs/php_codesniffer": "^3.0",
"silverstripe/widgets": "^2",
"silverstripe/comments": "^3.7",
"silverstripe/content-widget": "^2"
},
"extra": {
"expose": [
@ -57,4 +55,4 @@
},
"minimum-stability": "dev",
"prefer-stable": true
}
}

View File

@ -8,7 +8,7 @@ en:
Add: 'Add {name}'
AddFail: 'Unable to save {class} to the database.'
ButtonName: '{name}'
PermissionFail: "You don't have permission to create a {class}."
PermissionFail: 'You don''t have permission to create a {class}.'
SilverStripe\Blog\Forms\GridField\GridFieldBlogPostState:
Draft: 'Saved as Draft on {date}'
Modified: Modified
@ -47,7 +47,7 @@ en:
PostedIn: 'Posted in'
PostsByUser: 'Posts by {firstname} {surname} for {title}'
PostsPerPage: 'Posts Per Page'
ReadMoreAbout: "Read more about '{title}'..."
ReadMoreAbout: 'Read more about ''{title}''...'
SINGULARNAME: Blog
Tag: Tag
Tagged: Tagged
@ -85,7 +85,7 @@ en:
SilverStripe\Blog\Model\BlogPost:
AUTHOR: Author
AdditionalCredits: 'Additional Credits'
AdditionalCredits_Description: "If some authors of this post don't have CMS access, enter their name(s) here. You can separate multiple names with a comma."
AdditionalCredits_Description: 'If some authors of this post don''t have CMS access, enter their name(s) here. You can separate multiple names with a comma.'
Authors: Authors
CUSTOMSUMMARY: 'Add A Custom Summary'
Categories: Categories

View File

View File

@ -1,8 +1,9 @@
{
"name": "silverstripe-blog",
"version": "3.0.0",
"description": "A fresh take on blogging in Silverstripe set out to tackle the issue of a cluttered Site Tree",
"scripts": {
"build": "yarn && yarn lint && rm -rf client/dist/* && NODE_ENV=production webpack --mode production --bail --progress",
"build": "yarn && yarn lint && NODE_ENV=production webpack -p --bail --progress",
"dev": "NODE_ENV=development webpack --progress",
"watch": "NODE_ENV=development webpack --watch --progress",
"css": "WEBPACK_CHILD=css npm run build",
@ -27,16 +28,11 @@
},
"homepage": "https://github.com/silverstripe/silverstripe-blog#readme",
"dependencies": {},
"peerDependencies": {
"jquery": "^3"
},
"devDependencies": {
"@silverstripe/eslint-config": "^1.1.0",
"@silverstripe/webpack-config": "^2.0.0",
"webpack": "^5.74.0",
"webpack-cli": "^5.0.0"
},
"resolutions": {
"colors": "1.4.0"
},
"browserslist": [
"defaults"
]
"@silverstripe/eslint-config": "^0.0.5",
"@silverstripe/webpack-config": "^1.3"
}
}

View File

@ -1,3 +0,0 @@
parameters:
paths:
- src

View File

@ -226,6 +226,7 @@ class GridFieldAddByDBField implements GridField_ActionProvider, GridField_HTMLP
'add',
'add'
);
$addAction->setAttribute('data-icon', 'add');
$addAction->addExtraClass('btn btn-primary');
$forTemplate = ArrayData::create([]);

View File

@ -31,11 +31,11 @@ use SilverStripe\View\Requirements;
/**
* Blog Holder
*
* @method HasManyList<BlogCategory> Categories()
* @method ManyManyList<Member> Contributors()
* @method ManyManyList<Member> Editors()
* @method HasManyList<BlogTag> Tags()
* @method ManyManyList<Member> Writers()
* @method HasManyList Tags() List of tags in this blog
* @method HasManyList Categories() List of categories in this blog
* @method ManyManyList Editors() List of editors
* @method ManyManyList Writers() List of writers
* @method ManyManyList Contributors() List of contributors
*/
class Blog extends Page implements PermissionProvider
{
@ -533,7 +533,7 @@ class Blog extends Page implements PermissionProvider
* @param null|int $month
* @param null|int $day
*
* @return DataList<BlogPost>
* @return DataList
*/
public function getArchivedBlogPosts($year, $month = null, $day = null)
{
@ -574,7 +574,7 @@ class Blog extends Page implements PermissionProvider
/**
* Return blog posts.
*
* @return DataList<BlogPost> of BlogPost objects
* @return DataList of BlogPost objects
*/
public function getBlogPosts()
{

View File

@ -7,10 +7,12 @@ use SilverStripe\ORM\DataObject;
/**
* A blog category for generalising blog posts.
*
*
* @method Blog Blog()
*
* @property string $Title
* @property string $URLSegment
* @property int $BlogID
* @method Blog Blog()
*/
class BlogCategory extends DataObject implements CategorisationObject
{
@ -31,8 +33,6 @@ class BlogCategory extends DataObject implements CategorisationObject
*/
private static $table_name = 'BlogCategory';
private static bool $allow_urlsegment_multibyte = true;
/**
* @var array
*/

View File

@ -2,13 +2,10 @@
namespace SilverStripe\Blog\Model;
use SilverStripe\Comments\Model\Comment;
use SilverStripe\ORM\DataExtension;
/**
* Adds Blog specific behaviour to Comment.
*
* @extends DataExtension<Comment>
*/
class BlogCommentExtension extends DataExtension
{

View File

@ -11,15 +11,9 @@ use SilverStripe\ORM\DataList;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\PaginatedList;
use SilverStripe\Security\Member;
use SilverStripe\Blog\Model\BlogTag;
use SilverStripe\Blog\Model\BlogCategory;
use SilverStripe\View\Parsers\URLSegmentFilter;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\ORM\SS_List;
/**
* @extends PageController<Blog>
*/
class BlogController extends PageController
{
/**
@ -62,7 +56,7 @@ class BlogController extends PageController
/**
* The current Blog Post DataList query.
*
* @var DataList<BlogPost>
* @var DataList
*/
protected $blogPosts;
@ -71,6 +65,9 @@ class BlogController extends PageController
*/
public function index(HTTPRequest $request)
{
/**
* @var Blog $dataRecord
*/
$dataRecord = $this->dataRecord;
$this->blogPosts = $dataRecord->getBlogPosts();
@ -129,7 +126,7 @@ class BlogController extends PageController
/**
* Get posts related to the current Member profile.
*
* @return null|DataList<BlogPost>
* @return null|DataList
*/
public function getCurrentProfilePosts()
{
@ -271,7 +268,6 @@ class BlogController extends PageController
$tag = $this->request->param('Tag');
if ($tag) {
$filter = URLSegmentFilter::create();
$filter->setAllowMultibyte(BlogTag::config()->get('allow_urlsegment_multibyte'));
// url encode unless it's multibyte (already pre-encoded in the database)
// see https://github.com/silverstripe/silverstripe-cms/pull/2384
if (!$filter->getAllowMultibyte()) {
@ -322,7 +318,6 @@ class BlogController extends PageController
$category = $this->request->param('Category');
if ($category) {
$filter = URLSegmentFilter::create();
$filter->setAllowMultibyte(BlogCategory::config()->get('allow_urlsegment_multibyte'));
// url encode unless it's multibyte (already pre-encoded in the database)
// see https://github.com/silverstripe/silverstripe-cms/pull/2384
if (!$filter->getAllowMultibyte()) {
@ -444,7 +439,7 @@ class BlogController extends PageController
/**
* Returns a list of paginated blog posts based on the BlogPost dataList.
*
* @return PaginatedList<SS_List, BlogPost>
* @return PaginatedList
*/
public function PaginatedList()
{

View File

@ -16,6 +16,7 @@ use SilverStripe\Versioned\Versioned;
/**
* This class is responsible for filtering the SiteTree when necessary and also overlaps into
* filtering only published posts.
*
*/
class BlogFilter extends Lumberjack
{

View File

@ -10,7 +10,6 @@ use SilverStripe\Forms\GridField\GridFieldAddNewButton;
use SilverStripe\Forms\Tab;
use SilverStripe\Forms\TextareaField;
use SilverStripe\ORM\DataExtension;
use SilverStripe\ORM\ManyManyList;
use SilverStripe\Security\Member;
use SilverStripe\View\Parsers\URLSegmentFilter;
use SilverStripe\View\Requirements;
@ -18,10 +17,6 @@ use SilverStripe\View\Requirements;
/**
* This class is responsible for add Blog specific behaviour to Members.
*
* @method ManyManyList<BlogPost> BlogPosts()
* @method Image BlogProfileImage()
*
* @extends DataExtension<Member>
*/
class BlogMemberExtension extends DataExtension
{

View File

@ -21,7 +21,7 @@ trait BlogObject
{
/**
* @param int|array|null $id Optional ID(s) for parent of this relation, if not the current record
* @return DataList<BlogPost>
* @return DataList
*/
public function BlogPosts($id = null)
{
@ -181,7 +181,12 @@ trait BlogObject
{
$increment = (int) $increment;
$filter = URLSegmentFilter::create();
$filter->setAllowMultibyte($this->config()->get('allow_urlsegment_multibyte') ?? true);
// Setting this to on. Because of the UI flow, it would be quite a lot of work
// to support turning this off. (ie. the add by title flow would not work).
// If this becomes a problem we can approach it then.
// @see https://github.com/silverstripe/silverstripe-blog/issues/376
$filter->setAllowMultibyte(true);
$this->URLSegment = $filter->filter($this->Title);

View File

@ -31,15 +31,17 @@ use SilverStripe\View\Requirements;
/**
* An individual blog post.
*
* @method ManyManyList Categories()
* @method ManyManyList Tags()
* @method ManyManyList Authors()
* @method Blog Parent()
* @method Image FeaturedImage()
*
* @property string $PublishDate
* @property string $AuthorNames
* @property string $Summary
* @property int $ParentID
* @property int $FeaturedImageID
* @method ManyManyList<Member> Authors()
* @method ManyManyList<BlogCategory> Categories()
* @method Image FeaturedImage()
* @method ManyManyList<BlogTag> Tags()
*/
class BlogPost extends Page
{
@ -332,6 +334,8 @@ class BlogPost extends Page
? $parent->Tags()
: BlogTag::get();
// @todo: Reimplement the sidebar
// $options = BlogAdminSidebar::create(
$fields->addFieldsToTab(
'Root.PostOptions',
[
@ -356,6 +360,9 @@ class BlogPost extends Page
$authorNames
]
);
// )->setTitle('Post Options');
// $options->setName('blog-admin-sidebar');
// $fields->insertBefore($options, 'Root');
$fields->fieldByName('Root.PostOptions')
->setTitle(_t(__CLASS__ . '.PostOptions', 'Post Options'));

View File

@ -4,9 +4,6 @@ namespace SilverStripe\Blog\Model;
use PageController;
/**
* @extends PageController<BlogPost>
*/
class BlogPostController extends PageController
{

View File

@ -8,8 +8,6 @@ use SilverStripe\Forms\CheckboxField;
/**
* Adds a checkbox field for featured blog posts widget.
*
* @extends DataExtension<BlogPost>
*/
class BlogPostFeaturedExtension extends DataExtension
{

View File

@ -17,7 +17,6 @@ use SilverStripe\Versioned\Versioned;
* This is responsible for filtering only published posts to users who do not have permission to
* view non-published posts.
*
* @extends DataExtension<BlogPost>
*/
class BlogPostFilter extends DataExtension
{

View File

@ -12,8 +12,6 @@ use SilverStripe\Security\Member;
* Customise blog post to support comment notifications.
*
* Extends {@see BlogPost} with extensions to {@see CommentNotifiable}.
*
* @extends DataExtension<BlogPost>
*/
class BlogPostNotifications extends DataExtension
{

View File

@ -7,17 +7,17 @@ use SilverStripe\ORM\DataObject;
/**
* A blog tag for keyword descriptions of a blog post.
*
*
* @method Blog Blog()
*
* @property string $Title
* @property string $URLSegment
* @property int $BlogID
* @method Blog Blog()
*/
class BlogTag extends DataObject implements CategorisationObject
{
use BlogObject;
private static bool $allow_urlsegment_multibyte = true;
/**
* Use an exception code so that attempted writes can continue on
* duplicate errors.

View File

@ -108,7 +108,7 @@ class BlogArchiveWidget extends Widget
/**
* Returns a list of months where blog posts are present.
*
* @return ArrayList<ArrayData>
* @return ArrayList
*/
public function getArchive()
{

View File

@ -3,7 +3,6 @@
namespace SilverStripe\Blog\Widgets;
use SilverStripe\Blog\Model\Blog;
use SilverStripe\Blog\Model\BlogCategory;
use SilverStripe\Core\Convert;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FieldList;
@ -107,7 +106,7 @@ class BlogCategoriesWidget extends Widget
}
/**
* @return DataList<BlogCategory>
* @return DataList
*/
public function getCategories()
{

View File

@ -84,7 +84,7 @@ class BlogFeaturedPostsWidget extends Widget
return $blog->getBlogPosts()
->filter('ID:not', Director::get_current_page()->ID)
->filter('FeaturedInWidget', true)
->shuffle()
->sort('RAND()')
->limit($this->NumberOfPosts);
}

View File

@ -9,7 +9,6 @@ use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DB;
use SilverStripe\Widgets\Model\Widget;
use SilverStripe\Control\Controller;
if (!class_exists(Widget::class)) {
return;
@ -99,7 +98,7 @@ class BlogTagsCloudWidget extends Widget
foreach ($records as $record) {
$tag = DataObject::create();
$tag->TagName = $record['Title'];
$link = Controller::join_links($bloglink, 'tag', $record['URLSegment']);
$link = $bloglink.'tag/'.$record['URLSegment'];
$tag->Link = $link;
if ($record['TagCount'] > $maxTagCount) {
$maxTagCount = $record['TagCount'];

View File

@ -3,7 +3,6 @@
namespace SilverStripe\Blog\Widgets;
use SilverStripe\Blog\Model\Blog;
use SilverStripe\Blog\Model\BlogTag;
use SilverStripe\Core\Convert;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FieldList;
@ -107,7 +106,7 @@ class BlogTagsWidget extends Widget
}
/**
* @return DataList<BlogTag>
* @return DataList
*/
public function getTags()
{

View File

@ -47,7 +47,7 @@ Feature: Create a blog
And I press the "Log in as someone else" button
Scenario: Create a blog post
Given I am logged in as a member of "EDITOR" group
# Create a new blog post called "New Post"
When I go to "/admin/pages"
@ -65,8 +65,8 @@ Feature: Create a blog
# Add categories and tags
And I click the "Post Options" CMS tab
And I add "My Category" to the "#Form_EditForm_Categories_Holder" tag field
And I add "My Tag" to the "#Form_EditForm_Tags_Holder" tag field
And I add "My Category" to the "Categories" tag field
And I add "My Tag" to the "Tags" tag field
# Publish the blog post and logout
And I press the "Publish" button

View File

@ -11,6 +11,8 @@ class BlogFunctionalTest extends FunctionalTest
{
protected static $fixture_file = 'BlogFunctionalTest.yml';
protected static $use_draft_site = true;
protected function setUp(): void
{
Config::modify()->set(URLSegmentFilter::class, 'default_allow_multibyte', true);
@ -21,16 +23,14 @@ class BlogFunctionalTest extends FunctionalTest
public function testBlogWithMultibyteUrl()
{
$this->logInWithPermission('VIEW_DRAFT_CONTENT');
$result = $this->get(rawurlencode('آبید') . '?stage=Stage');
$result = $this->get(rawurlencode('آبید'));
$this->assertEquals(200, $result->getStatusCode());
}
public function testMemberProfileWithMultibyteUrlAndName()
{
$this->logInWithPermission('VIEW_DRAFT_CONTENT');
$result = $this->get(rawurlencode('آبید') . '/profile/' . rawurlencode('عبّاس-آبان') . '?stage=Stage');
$result = $this->get(rawurlencode('آبید') . '/profile/' . rawurlencode('عبّاس-آبان'));
$this->assertEquals(200, $result->getStatusCode());
$this->assertStringContainsString('My Blog Post', $result->getBody());
@ -38,8 +38,7 @@ class BlogFunctionalTest extends FunctionalTest
public function testMemberProfileWithMultibyteUrlAndEnglishName()
{
$this->logInWithPermission('VIEW_DRAFT_CONTENT');
$result = $this->get(rawurlencode('آبید') . '/profile/bob-jones' . '?stage=Stage');
$result = $this->get(rawurlencode('آبید') . '/profile/bob-jones');
$this->assertEquals(200, $result->getStatusCode());
$this->assertStringContainsString('My Blog Post', $result->getBody());

View File

@ -11,6 +11,8 @@ class BlogControllerFunctionalTest extends FunctionalTest
{
protected static $fixture_file = 'BlogControllerFunctionalTest.yml';
protected static $use_draft_site = true;
protected function setUp(): void
{
Config::modify()->set(URLSegmentFilter::class, 'default_allow_multibyte', true);
@ -21,8 +23,7 @@ class BlogControllerFunctionalTest extends FunctionalTest
public function testGetCategoriesWithMultibyteUrl()
{
$this->logInWithPermission('VIEW_DRAFT_CONTENT');
$result = $this->get('my-blog/category/' . rawurlencode('آبید') . '?stage=Stage');
$result = $this->get('my-blog/category/' . rawurlencode('آبید'));
$this->assertEquals(200, $result->getStatusCode());
$this->assertStringContainsString('آبید', $result->getBody());
@ -30,8 +31,7 @@ class BlogControllerFunctionalTest extends FunctionalTest
public function testGetTagsWithMultibyteUrl()
{
$this->logInWithPermission('VIEW_DRAFT_CONTENT');
$result = $this->get('my-blog/tag/' . rawurlencode('برتراند') . '?stage=Stage');
$result = $this->get('my-blog/tag/' . rawurlencode('برتراند'));
$this->assertEquals(200, $result->getStatusCode());
$this->assertStringContainsString('برتراند', $result->getBody());

View File

@ -1,31 +1,55 @@
const Path = require('path');
const { JavascriptWebpackConfig, CssWebpackConfig } = require('@silverstripe/webpack-config');
const webpack = require('webpack');
// 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 = {
ROOT: Path.resolve(),
MODULES: 'node_modules',
FILES_PATH: '../',
THIRDPARTY: 'thirdparty',
SRC: Path.resolve('client/src'),
DIST: Path.resolve('client/dist'),
};
const config = [
// Main JS bundle
new JavascriptWebpackConfig('js', PATHS, 'silverstripe/blog')
.setEntry({
main: `${PATHS.SRC}/main.js`
})
.mergeConfig({
output: {
filename: 'js/[name].bundle.js',
},
})
.getConfig(),
// sass to css
new CssWebpackConfig('css', PATHS)
.setEntry({
main: `${PATHS.SRC}/main.scss`
})
.getConfig(),
{
name: 'bundle',
entry: {
main: `${PATHS.SRC}/main.js`
},
output: {
path: PATHS.DIST,
filename: 'js/[name].bundle.js',
},
devtool: (ENV !== 'production') ? 'source-map' : '',
resolve: resolveJS(ENV, PATHS),
externals: externalJS(ENV, PATHS),
module: moduleJS(ENV, PATHS),
plugins: pluginJS(ENV, PATHS),
},
{
name: 'bundle',
entry: {
main: `${PATHS.SRC}/main.scss`
},
output: {
path: PATHS.DIST,
filename: 'styles/[name].css'
},
devtool: (ENV !== 'production') ? 'source-map' : '',
module: moduleCSS(ENV, PATHS),
plugins: pluginCSS(ENV, PATHS),
},
];
module.exports = config;

11081
yarn.lock

File diff suppressed because it is too large Load Diff