pages_core 3.8.1 → 3.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +35 -0
  3. data/VERSION +1 -0
  4. data/app/assets/builds/pages_core/admin-dist.js +7 -7
  5. data/app/controllers/admin/images_controller.rb +1 -1
  6. data/app/controllers/concerns/pages_core/error_reporting.rb +2 -0
  7. data/app/javascript/components/Attachments/Attachment.jsx +2 -2
  8. data/app/javascript/components/Attachments/AttachmentEditor.jsx +2 -2
  9. data/app/javascript/components/EditableImage.jsx +1 -1
  10. data/app/javascript/components/FileUploadButton.jsx +27 -34
  11. data/app/javascript/components/ImageEditor/Form.jsx +2 -2
  12. data/app/javascript/components/ImageEditor.jsx +1 -1
  13. data/app/javascript/components/ImageGrid/GridImage.jsx +1 -1
  14. data/app/javascript/components/ImageGrid.jsx +1 -1
  15. data/app/javascript/components/ImageUploader.jsx +1 -1
  16. data/app/javascript/components/Modal.jsx +1 -1
  17. data/app/javascript/components/Toast.jsx +1 -1
  18. data/app/javascript/components.js +1 -0
  19. data/app/javascript/index.js +1 -0
  20. data/app/javascript/{components → stores}/ModalStore.jsx +0 -0
  21. data/app/javascript/{components → stores}/ToastStore.jsx +0 -0
  22. data/app/javascript/stores.js +2 -0
  23. data/app/models/concerns/pages_core/page_model/pathable.rb +1 -1
  24. data/app/models/invite.rb +0 -2
  25. data/app/models/page_category.rb +0 -1
  26. data/app/models/page_exporter.rb +2 -2
  27. data/app/models/password_reset_token.rb +0 -2
  28. data/app/models/role.rb +6 -16
  29. data/app/models/tagging.rb +0 -2
  30. data/lib/pages_core/cache_sweeper.rb +0 -9
  31. data/lib/pages_core/configuration/base.rb +3 -1
  32. data/lib/pages_core/pub_sub.rb +1 -2
  33. data/lib/pages_core/version.rb +3 -1
  34. metadata +27 -10
@@ -23,7 +23,7 @@ module Admin
23
23
  def update
24
24
  @image.update(image_params)
25
25
  respond_to do |format|
26
- format.json { render action: :show }
26
+ format.json { render_image_json(@image) }
27
27
  end
28
28
  end
29
29
 
@@ -11,6 +11,8 @@ module PagesCore
11
11
  protected
12
12
 
13
13
  def configure_sentry_context
14
+ return if Rails.env.test?
15
+
14
16
  if Object.const_defined?("Sentry")
15
17
  Sentry.set_user(current_user_context)
16
18
  Sentry.set_tags(locale: params[:locale] || I18n.default_locale.to_s)
@@ -2,8 +2,8 @@ import React from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import copyToClipboard from "../../lib/copyToClipboard";
4
4
  import AttachmentEditor from "./AttachmentEditor";
5
- import ModalStore from "../ModalStore";
6
- import ToastStore from "../ToastStore";
5
+ import ModalStore from "../../stores/ModalStore";
6
+ import ToastStore from "../../stores/ToastStore";
7
7
 
8
8
  import { useDraggable } from "../drag";
9
9
 
@@ -1,8 +1,8 @@
1
1
  import React, { useState } from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import copyToClipboard, { copySupported } from "../../lib/copyToClipboard";
4
- import ModalStore from "../ModalStore";
5
- import ToastStore from "../ToastStore";
4
+ import ModalStore from "../../stores/ModalStore";
5
+ import ToastStore from "../../stores/ToastStore";
6
6
  import { putJson } from "../../lib/request";
7
7
 
8
8
  export default function AttachmentEditor(props) {
@@ -1,7 +1,7 @@
1
1
  import React, { useState } from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import ImageEditor from "./ImageEditor";
4
- import ModalStore from "./ModalStore";
4
+ import ModalStore from "../stores/ModalStore";
5
5
 
6
6
  export default function EditableImage(props) {
7
7
  const [image, setImage] = useState(props.image);
@@ -1,49 +1,42 @@
1
- import React from "react";
1
+ import React, { useRef } from "react";
2
2
  import PropTypes from "prop-types";
3
3
 
4
- export default class FileUploadButton extends React.Component {
5
- constructor(props) {
6
- super(props);
7
- this.inputRef = React.createRef();
8
- this.handleChange = this.handleChange.bind(this);
9
- this.triggerDialog = this.triggerDialog.bind(this);
10
- }
4
+ export default function FileUploadButton(props) {
5
+ const inputRef = useRef();
11
6
 
12
- handleChange(evt) {
7
+ const handleChange = (evt) => {
13
8
  let fileList = evt.target.files;
14
9
  let files = [];
15
10
  for (var i = 0; i < fileList.length; i++) {
16
11
  files.push(fileList[i]);
17
12
  }
18
13
  if (files.length > 0) {
19
- this.props.callback(files);
14
+ props.callback(files);
20
15
  }
21
- }
16
+ };
22
17
 
23
- render() {
24
- return (
25
- <div className="upload-button">
26
- <span>
27
- Drag and drop {this.props.type || "file"}
28
- {this.props.multiple && "s"} here, or
29
- {this.props.multiline && <br />}
30
- <button onClick={this.triggerDialog}>
31
- choose a file
32
- </button>
33
- </span>
34
- <input type="file"
35
- onChange={this.handleChange}
36
- ref={this.inputRef}
37
- style={{ display: "none" }}
38
- multiple={this.props.multiple || false} />
39
- </div>
40
- );
41
- }
42
-
43
- triggerDialog(evt) {
18
+ const triggerDialog = (evt) => {
44
19
  evt.preventDefault();
45
- this.inputRef.current.click();
46
- }
20
+ inputRef.current.click();
21
+ };
22
+
23
+ return (
24
+ <div className="upload-button">
25
+ <span>
26
+ Drag and drop {props.type || "file"}
27
+ {props.multiple && "s"} here, or
28
+ {props.multiline && <br />}
29
+ <button onClick={triggerDialog}>
30
+ choose a file
31
+ </button>
32
+ </span>
33
+ <input type="file"
34
+ onChange={handleChange}
35
+ ref={inputRef}
36
+ style={{ display: "none" }}
37
+ multiple={props.multiple || false} />
38
+ </div>
39
+ );
47
40
  }
48
41
 
49
42
  FileUploadButton.propTypes = {
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import PropTypes from "prop-types";
3
- import ModalStore from "../ModalStore";
4
- import ToastStore from "../ToastStore";
3
+ import ModalStore from "../../stores/ModalStore";
4
+ import ToastStore from "../../stores/ToastStore";
5
5
  import copyToClipboard, { copySupported } from "../../lib/copyToClipboard";
6
6
 
7
7
  export default function Form(props) {
@@ -1,6 +1,6 @@
1
1
  import React, { useState } from "react";
2
2
  import PropTypes from "prop-types";
3
- import ModalStore from "./ModalStore";
3
+ import ModalStore from "../stores/ModalStore";
4
4
  import { putJson } from "../lib/request";
5
5
 
6
6
  import ImageCropper, { useCrop, cropParams } from "./ImageCropper";
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import copyToClipboard from "../../lib/copyToClipboard";
4
4
  import EditableImage from "../EditableImage";
5
- import ToastStore from "../ToastStore";
5
+ import ToastStore from "../../stores/ToastStore";
6
6
  import Placeholder from "./Placeholder";
7
7
 
8
8
  import { useDraggable } from "../drag";
@@ -4,7 +4,7 @@ import FileUploadButton from "./FileUploadButton";
4
4
  import DragElement from "./ImageGrid/DragElement";
5
5
  import FilePlaceholder from "./ImageGrid/FilePlaceholder";
6
6
  import GridImage from "./ImageGrid/GridImage";
7
- import ToastStore from "./ToastStore";
7
+ import ToastStore from "../stores/ToastStore";
8
8
  import { post } from "../lib/request";
9
9
 
10
10
  import { createDraggable,
@@ -2,7 +2,7 @@ import React, { useState } from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import EditableImage from "./EditableImage";
4
4
  import FileUploadButton from "./FileUploadButton";
5
- import ToastStore from "./ToastStore";
5
+ import ToastStore from "../stores/ToastStore";
6
6
  import { post } from "../lib/request";
7
7
 
8
8
  function getFiles(dt) {
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import ModalStore from "./ModalStore";
2
+ import ModalStore from "../stores/ModalStore";
3
3
 
4
4
  export default class Modal extends React.Component {
5
5
  constructor(props) {
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import PropTypes from "prop-types";
3
- import ToastStore from "./ToastStore";
3
+ import ToastStore from "../stores/ToastStore";
4
4
 
5
5
  export default class Toast extends React.Component {
6
6
  constructor(props) {
@@ -1,6 +1,7 @@
1
1
  export { default as Attachments } from "./components/Attachments";
2
2
  export { default as DateRangeSelect } from "./components/DateRangeSelect";
3
3
  export { default as EditableImage } from "./components/EditableImage";
4
+ export { default as FileUploadButton } from "./components/FileUploadButton";
4
5
  export { default as ImageCropper } from "./components/ImageCropper";
5
6
  export { default as ImageGrid } from "./components/ImageGrid";
6
7
  export { default as ImageUploader } from "./components/ImageUploader";
@@ -31,6 +31,7 @@ export default function startPages () {
31
31
 
32
32
  export * from "./components";
33
33
  export * from "./hooks";
34
+ export * from "./stores";
34
35
 
35
36
  export * from "./lib/request.js";
36
37
  export { default as copyToClipboard,
@@ -0,0 +1,2 @@
1
+ export { default as ModalStore } from "./stores/ModalStore";
2
+ export { default as ToastStore } from "./stores/ToastStore";
@@ -107,7 +107,7 @@ module PagesCore
107
107
  siblings.reject { |p| p == self }
108
108
  .map { |p| p.localize(locale) }
109
109
  .map(&:path_segment)
110
- .reject(&:blank?)
110
+ .compact_blank
111
111
  end
112
112
  end
113
113
  end
data/app/models/invite.rb CHANGED
@@ -8,8 +8,6 @@ class Invite < ApplicationRecord
8
8
 
9
9
  before_validation :ensure_token
10
10
 
11
- validates :user_id, presence: true
12
-
13
11
  validates :email,
14
12
  presence: true,
15
13
  format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i },
@@ -3,5 +3,4 @@
3
3
  class PageCategory < ApplicationRecord
4
4
  belongs_to :page
5
5
  belongs_to :category
6
- validates :page_id, :category_id, presence: true
7
6
  end
@@ -74,7 +74,7 @@ class PageExporter
74
74
 
75
75
  def page_file_name(page)
76
76
  [page.path_segment,
77
- page.to_param[0..250]].reject(&:blank?).first
77
+ page.to_param[0..250]].compact_blank.first
78
78
  end
79
79
 
80
80
  def page_path_segment(page)
@@ -95,6 +95,6 @@ class PageExporter
95
95
 
96
96
  def write_file(path, data)
97
97
  FileUtils.mkdir_p(File.dirname(path))
98
- File.open(path, "wb") { |fh| fh.write(data) }
98
+ File.binwrite(path, data)
99
99
  end
100
100
  end
@@ -5,8 +5,6 @@ class PasswordResetToken < ApplicationRecord
5
5
  before_create :ensure_token
6
6
  before_create :ensure_expiration
7
7
 
8
- validates :user_id, presence: true
9
-
10
8
  scope :active, -> { where("expires_at >= ?", Time.now.utc) }
11
9
  scope :expired, -> { where("expires_at < ?", Time.now.utc) }
12
10
 
data/app/models/role.rb CHANGED
@@ -7,17 +7,15 @@ class Role < ApplicationRecord
7
7
  uniqueness: { scope: :user_id },
8
8
  inclusion: { in: proc { Role.roles.map(&:name) } }
9
9
 
10
+ RoleDefinition = Struct.new(:name, :description, :default)
11
+
10
12
  class << self
11
13
  def define(name, description, default: false)
12
14
  if roles.map(&:name).include?(name.to_s)
13
15
  raise ArgumentError, "Tried to define role :#{role}, " \
14
16
  "but a role by that name already exists"
15
17
  else
16
- roles << OpenStruct.new(
17
- name: name.to_s,
18
- description: description,
19
- default: default
20
- )
18
+ roles << RoleDefinition.new(name.to_s, description, default)
21
19
  end
22
20
  end
23
21
 
@@ -39,21 +37,13 @@ class Role < ApplicationRecord
39
37
  return [] unless File.exist?(config_file)
40
38
 
41
39
  YAML.load_file(config_file).map do |key, opts|
42
- OpenStruct.new(name: key.to_s,
43
- description: opts["description"],
44
- default: opts["default"])
40
+ RoleDefinition.new(key.to_s, opts["description"], opts["default"])
45
41
  end
46
42
  end
47
43
 
48
44
  def default_roles
49
- [
50
- OpenStruct.new(
51
- name: "users", description: "Can manage users", default: false
52
- ),
53
- OpenStruct.new(
54
- name: "pages", description: "Can manage pages", default: true
55
- )
56
- ]
45
+ [RoleDefinition.new("users", "Can manage users", false),
46
+ RoleDefinition.new("pages", "Can manage pages", true)]
57
47
  end
58
48
  end
59
49
 
@@ -4,10 +4,8 @@ class Tagging < ApplicationRecord
4
4
  belongs_to :tag
5
5
  belongs_to :taggable, polymorphic: true, touch: true
6
6
 
7
- validates :taggable_id, presence: true
8
7
  validates :taggable_type, presence: true
9
8
  validates :tag_id,
10
- presence: true,
11
9
  uniqueness: { scope: %i[taggable_type taggable_id] }
12
10
 
13
11
  def self.tagged_class(taggable)
@@ -16,15 +16,6 @@ module PagesCore
16
16
  disable(&block)
17
17
  PagesCore::StaticCache.handler.sweep!
18
18
  end
19
-
20
- def config
21
- ActiveSupport::Deprecation.warn(
22
- "PagesCore::CacheSweeper.config is no longer used."
23
- )
24
- configuration = OpenStruct.new(patterns: [])
25
- yield configuration if block_given?
26
- configuration
27
- end
28
19
  end
29
20
 
30
21
  self.enabled ||= true
@@ -5,12 +5,14 @@ module PagesCore
5
5
  class Base
6
6
  class InvalidConfigurationKey < StandardError; end
7
7
 
8
+ SettingStruct = Struct.new(:type, :default)
9
+
8
10
  def self.settings
9
11
  @settings ||= {}
10
12
  end
11
13
 
12
14
  def self.setting(key, type, default = nil)
13
- settings[key] = OpenStruct.new(type: type, default: default)
15
+ settings[key] = SettingStruct.new(type, default)
14
16
 
15
17
  define_method key do |*args|
16
18
  args.any? ? set(key, *args) : get(key)
@@ -4,9 +4,8 @@ module PagesCore
4
4
  module PubSub
5
5
  class << self
6
6
  def publish(name, payload = {})
7
- payload_struct = OpenStruct.new(payload)
8
7
  subscribers.select { |s| s.name == name }
9
- .each { |s| s.call(payload_struct) }
8
+ .each { |s| s.call(payload) }
10
9
  end
11
10
 
12
11
  def subscribe(name, &block)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PagesCore
4
- VERSION = "3.8.1" unless PagesCore.const_defined?("VERSION")
4
+ unless PagesCore.const_defined?("VERSION")
5
+ VERSION = File.read(File.expand_path("../../VERSION", __dir__)).strip
6
+ end
5
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pages_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.1
4
+ version: 3.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Inge Jørgensen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-17 00:00:00.000000000 Z
11
+ date: 2022-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: 3.8.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: semantic
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: shoulda-matchers
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -126,16 +140,16 @@ dependencies:
126
140
  name: timecop
127
141
  requirement: !ruby/object:Gem::Requirement
128
142
  requirements:
129
- - - "~>"
143
+ - - ">="
130
144
  - !ruby/object:Gem::Version
131
- version: 0.8.0
145
+ version: '0'
132
146
  type: :development
133
147
  prerelease: false
134
148
  version_requirements: !ruby/object:Gem::Requirement
135
149
  requirements:
136
- - - "~>"
150
+ - - ">="
137
151
  - !ruby/object:Gem::Version
138
- version: 0.8.0
152
+ version: '0'
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: rails
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -495,6 +509,7 @@ extra_rdoc_files: []
495
509
  files:
496
510
  - README.md
497
511
  - Rakefile
512
+ - VERSION
498
513
  - app/assets/builds/pages_core/admin-dist.js
499
514
  - app/assets/images/pages/admin/drag-icon.png
500
515
  - app/assets/images/pages/admin/icon.png
@@ -621,7 +636,6 @@ files:
621
636
  - app/javascript/components/ImageGrid/Placeholder.jsx
622
637
  - app/javascript/components/ImageUploader.jsx
623
638
  - app/javascript/components/Modal.jsx
624
- - app/javascript/components/ModalStore.jsx
625
639
  - app/javascript/components/PageDates.jsx
626
640
  - app/javascript/components/PageFiles.jsx
627
641
  - app/javascript/components/PageImages.jsx
@@ -634,7 +648,6 @@ files:
634
648
  - app/javascript/components/TagEditor/AddTagForm.jsx
635
649
  - app/javascript/components/TagEditor/Tag.jsx
636
650
  - app/javascript/components/Toast.jsx
637
- - app/javascript/components/ToastStore.jsx
638
651
  - app/javascript/components/drag.js
639
652
  - app/javascript/components/drag/draggedOrder.js
640
653
  - app/javascript/components/drag/useDragCollection.js
@@ -651,6 +664,9 @@ files:
651
664
  - app/javascript/lib/copyToClipboard.js
652
665
  - app/javascript/lib/readyHandler.js
653
666
  - app/javascript/lib/request.js
667
+ - app/javascript/stores.js
668
+ - app/javascript/stores/ModalStore.jsx
669
+ - app/javascript/stores/ToastStore.jsx
654
670
  - app/jobs/pages_core/autopublish_job.rb
655
671
  - app/jobs/pages_core/sweep_cache_job.rb
656
672
  - app/mailers/admin_mailer.rb
@@ -817,7 +833,8 @@ files:
817
833
  - vendor/assets/stylesheets/ReactCrop.css
818
834
  homepage: ''
819
835
  licenses: []
820
- metadata: {}
836
+ metadata:
837
+ rubygems_mfa_required: 'true'
821
838
  post_install_message:
822
839
  rdoc_options: []
823
840
  require_paths:
@@ -833,7 +850,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
833
850
  - !ruby/object:Gem::Version
834
851
  version: '0'
835
852
  requirements: []
836
- rubygems_version: 3.2.22
853
+ rubygems_version: 3.3.3
837
854
  signing_key:
838
855
  specification_version: 4
839
856
  summary: Pages Core