pages_core 3.12.4 → 3.12.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/app/assets/builds/pages_core/admin-dist.js +8 -43
  4. data/app/assets/builds/pages_core/admin-dist.js.map +4 -4
  5. data/app/assets/builds/pages_core/admin.css +264 -133
  6. data/app/assets/stylesheets/pages_core/admin/components/attachments.css +3 -4
  7. data/app/assets/stylesheets/pages_core/admin/components/forms.css +17 -16
  8. data/app/assets/stylesheets/pages_core/admin/components/image_editor.css +8 -4
  9. data/app/assets/stylesheets/pages_core/admin/components/image_grid.css +1 -1
  10. data/app/assets/stylesheets/pages_core/admin/components/list_table.css +11 -3
  11. data/app/assets/stylesheets/pages_core/admin/components/modal.css +9 -5
  12. data/app/assets/stylesheets/pages_core/admin/components/page_tree.css +5 -1
  13. data/app/assets/stylesheets/pages_core/admin/components/toast.css +2 -2
  14. data/app/assets/stylesheets/pages_core/admin/controllers/pages.css +4 -2
  15. data/app/assets/stylesheets/pages_core/admin/vars.css +2 -1
  16. data/app/controllers/admin/calendars_controller.rb +2 -2
  17. data/app/controllers/admin/categories_controller.rb +3 -3
  18. data/app/controllers/admin/news_controller.rb +6 -6
  19. data/app/controllers/admin/pages_controller.rb +12 -11
  20. data/app/controllers/admin/users_controller.rb +1 -1
  21. data/app/controllers/concerns/pages_core/preview_pages_controller.rb +15 -17
  22. data/app/controllers/pages_core/admin_controller.rb +2 -2
  23. data/app/controllers/pages_core/base_controller.rb +1 -8
  24. data/app/controllers/pages_core/frontend/pages_controller.rb +13 -5
  25. data/app/controllers/pages_core/frontend_controller.rb +12 -7
  26. data/app/helpers/admin/menu_helper.rb +2 -0
  27. data/app/helpers/admin/pages_helper.rb +1 -4
  28. data/app/helpers/pages_core/admin/admin_helper.rb +0 -1
  29. data/app/helpers/pages_core/admin/content_tabs_helper.rb +9 -2
  30. data/app/helpers/pages_core/application_helper.rb +2 -3
  31. data/app/helpers/pages_core/frontend_helper.rb +1 -1
  32. data/app/helpers/pages_core/head_tags_helper.rb +15 -46
  33. data/app/helpers/pages_core/images_helper.rb +76 -21
  34. data/app/helpers/pages_core/locales_helper.rb +9 -0
  35. data/app/helpers/pages_core/open_graph_tags_helper.rb +3 -5
  36. data/app/helpers/pages_core/page_path_helper.rb +1 -1
  37. data/app/javascript/components/Attachments/Attachment.tsx +55 -52
  38. data/app/javascript/components/Attachments/AttachmentEditor.tsx +45 -50
  39. data/app/javascript/components/Attachments/Placeholder.tsx +1 -2
  40. data/app/javascript/components/Attachments.jsx +69 -57
  41. data/app/javascript/components/DateRangeSelect.jsx +94 -54
  42. data/app/javascript/components/EditableImage.tsx +20 -16
  43. data/app/javascript/components/FileUploadButton.tsx +12 -12
  44. data/app/javascript/components/ImageCropper/FocalPoint.tsx +22 -20
  45. data/app/javascript/components/ImageCropper/Image.tsx +20 -16
  46. data/app/javascript/components/ImageCropper/Toolbar.tsx +35 -27
  47. data/app/javascript/components/ImageCropper/useCrop.ts +105 -91
  48. data/app/javascript/components/ImageCropper.tsx +34 -25
  49. data/app/javascript/components/ImageEditor/Form.tsx +32 -43
  50. data/app/javascript/components/ImageEditor.tsx +29 -21
  51. data/app/javascript/components/ImageGrid/DragElement.tsx +6 -4
  52. data/app/javascript/components/ImageGrid/GridImage.tsx +56 -52
  53. data/app/javascript/components/ImageGrid/Placeholder.tsx +1 -1
  54. data/app/javascript/components/ImageGrid.jsx +132 -101
  55. data/app/javascript/components/ImageUploader.tsx +59 -55
  56. data/app/javascript/components/Modal.tsx +2 -4
  57. data/app/javascript/components/PageDates.jsx +25 -20
  58. data/app/javascript/components/PageFiles.jsx +7 -5
  59. data/app/javascript/components/PageImages.tsx +9 -7
  60. data/app/javascript/components/PageTree/Draggable.tsx +46 -40
  61. data/app/javascript/components/PageTree/Node.tsx +111 -95
  62. data/app/javascript/components/PageTree/types.ts +9 -9
  63. data/app/javascript/components/PageTree.tsx +44 -29
  64. data/app/javascript/components/RichTextArea.jsx +51 -37
  65. data/app/javascript/components/RichTextToolbarButton.tsx +8 -5
  66. data/app/javascript/components/TagEditor/AddTagForm.tsx +11 -10
  67. data/app/javascript/components/TagEditor/Tag.tsx +10 -8
  68. data/app/javascript/components/TagEditor.tsx +15 -10
  69. data/app/javascript/components/Toast.tsx +3 -7
  70. data/app/javascript/components/drag/draggedOrder.ts +16 -15
  71. data/app/javascript/components/drag/types.ts +12 -12
  72. data/app/javascript/components/drag/useDragCollection.ts +36 -42
  73. data/app/javascript/components/drag/useDragUploader.ts +3 -2
  74. data/app/javascript/components/drag.ts +5 -4
  75. data/app/javascript/controllers/LoginController.ts +0 -1
  76. data/app/javascript/controllers/MainController.ts +6 -2
  77. data/app/javascript/controllers/PageOptionsController.js +7 -2
  78. data/app/javascript/features/RichText.tsx +9 -7
  79. data/app/javascript/index.ts +5 -3
  80. data/app/javascript/lib/Tree.ts +27 -24
  81. data/app/javascript/lib/copyToClipboard.ts +5 -4
  82. data/app/javascript/lib/readyHandler.ts +4 -4
  83. data/app/javascript/lib/request.ts +7 -3
  84. data/app/javascript/stores/useModalStore.ts +3 -3
  85. data/app/javascript/stores/useToastStore.ts +14 -12
  86. data/app/javascript/types.ts +22 -22
  87. data/app/models/concerns/pages_core/page_model/templateable.rb +1 -1
  88. data/app/views/admin/calendars/show.html.erb +1 -1
  89. data/app/views/admin/news/index.html.erb +1 -1
  90. data/app/views/admin/pages/_edit_files.html.erb +1 -1
  91. data/app/views/admin/pages/_edit_images.html.erb +1 -1
  92. data/app/views/admin/pages/_list_item.html.erb +1 -1
  93. data/app/views/admin/pages/_search_bar.html.erb +1 -1
  94. data/app/views/admin/pages/deleted.html.erb +2 -2
  95. data/app/views/admin/pages/edit.html.erb +3 -3
  96. data/app/views/admin/pages/index.html.erb +4 -4
  97. data/app/views/admin/pages/new.html.erb +1 -1
  98. data/app/views/admin/pages/search.html.erb +3 -3
  99. data/app/views/feeds/pages.rss.builder +2 -2
  100. data/app/views/layouts/admin/_page_header.html.erb +4 -4
  101. data/app/views/layouts/admin.html.erb +1 -2
  102. data/config/locales/en.yml +1 -0
  103. data/lib/pages_core/pages_plugin.rb +5 -3
  104. data/lib/rails/generators/pages_core/frontend/templates/application.html.erb +15 -13
  105. data/lib/tasks/pages/reports.rake +26 -0
  106. metadata +32 -4
  107. data/app/helpers/pages_core/admin/deprecated_admin_helper.rb +0 -40
  108. data/app/views/pages_core/_google_analytics.html.erb +0 -8
@@ -5,10 +5,12 @@ import Placeholder from "./Attachments/Placeholder";
5
5
  import FileUploadButton from "./FileUploadButton";
6
6
  import { post } from "../lib/request";
7
7
 
8
- import { createDraggable,
9
- draggedOrder,
10
- useDragCollection,
11
- useDragUploader } from "./drag";
8
+ import {
9
+ createDraggable,
10
+ draggedOrder,
11
+ useDragCollection,
12
+ useDragUploader
13
+ } from "./drag";
12
14
 
13
15
  function filenameToName(str) {
14
16
  return str.replace(/\.[\w\d]+$/, "").replace(/_/g, " ");
@@ -16,18 +18,20 @@ function filenameToName(str) {
16
18
 
17
19
  export default function Attachments(props) {
18
20
  const collection = useDragCollection(props.records);
19
- const locales = props.locales && props.locales.length > 0 ?
20
- Object.keys(props.locales) : [props.locale];
21
+ const locales =
22
+ props.locales && props.locales.length > 0
23
+ ? Object.keys(props.locales)
24
+ : [props.locale];
21
25
  const [deleted, setDeleted] = useState([]);
22
26
 
23
27
  const uploadAttachment = (file) => {
24
28
  let name = {};
25
- locales.forEach((l) => name[l] = file.name);
29
+ locales.forEach((l) => (name[l] = file.name));
26
30
 
27
- const draggable = createDraggable(
28
- { attachment: { filename: file.name, name: name },
29
- uploading: true }
30
- );
31
+ const draggable = createDraggable({
32
+ attachment: { filename: file.name, name: name },
33
+ uploading: true
34
+ });
31
35
 
32
36
  let data = new FormData();
33
37
 
@@ -36,14 +40,15 @@ export default function Attachments(props) {
36
40
  data.append(`attachment[name][${l}]`, filenameToName(file.name));
37
41
  });
38
42
 
39
- post("/admin/attachments.json", data)
40
- .then(json => {
41
- collection.dispatch({
42
- type: "update",
43
- payload: { ...draggable,
44
- record: { attachment: json, uploading: false } }
45
- });
43
+ post("/admin/attachments.json", data).then((json) => {
44
+ collection.dispatch({
45
+ type: "update",
46
+ payload: {
47
+ ...draggable,
48
+ record: { attachment: json, uploading: false }
49
+ }
46
50
  });
51
+ });
47
52
 
48
53
  return draggable;
49
54
  };
@@ -51,7 +56,7 @@ export default function Attachments(props) {
51
56
  const receiveFiles = (files) => {
52
57
  collection.dispatch({
53
58
  type: "append",
54
- payload: files.map(f => uploadAttachment(f))
59
+ payload: files.map((f) => uploadAttachment(f))
55
60
  });
56
61
  };
57
62
 
@@ -62,17 +67,21 @@ export default function Attachments(props) {
62
67
  });
63
68
  collection.dispatch({
64
69
  type: "insertFiles",
65
- payload: files.map(f => uploadAttachment(f))
70
+ payload: files.map((f) => uploadAttachment(f))
66
71
  });
67
72
  };
68
73
 
69
- const [dragState,
70
- dragStart,
71
- listeners] = useDragUploader([collection], dragEnd);
74
+ const [dragState, dragStart, listeners] = useDragUploader(
75
+ [collection],
76
+ dragEnd
77
+ );
72
78
 
73
79
  const position = (record) => {
74
- return [...collection.draggables.map(d => d.record),
75
- ...deleted].indexOf(record) + 1;
80
+ return (
81
+ [...collection.draggables.map((d) => d.record), ...deleted].indexOf(
82
+ record
83
+ ) + 1
84
+ );
76
85
  };
77
86
 
78
87
  const attrName = (record) => {
@@ -102,21 +111,23 @@ export default function Attachments(props) {
102
111
  const { dragging } = dragState;
103
112
 
104
113
  if (draggable === "Files") {
105
- return (<Placeholder key="placeholder" />);
114
+ return <Placeholder key="placeholder" />;
106
115
  }
107
116
 
108
117
  return (
109
- <Attachment key={draggable.handle}
110
- draggable={draggable}
111
- locale={props.locale}
112
- locales={props.locales}
113
- showEmbed={props.showEmbed}
114
- startDrag={dragStart}
115
- position={position(draggable.record)}
116
- onUpdate={update(draggable)}
117
- deleteRecord={remove(draggable)}
118
- attributeName={attrName(draggable.record)}
119
- placeholder={dragging && dragging == draggable} />
118
+ <Attachment
119
+ key={draggable.handle}
120
+ draggable={draggable}
121
+ locale={props.locale}
122
+ locales={props.locales}
123
+ showEmbed={props.showEmbed}
124
+ startDrag={dragStart}
125
+ position={position(draggable.record)}
126
+ onUpdate={update(draggable)}
127
+ deleteRecord={remove(draggable)}
128
+ attributeName={attrName(draggable.record)}
129
+ placeholder={dragging && dragging == draggable}
130
+ />
120
131
  );
121
132
  };
122
133
 
@@ -128,30 +139,31 @@ export default function Attachments(props) {
128
139
  }
129
140
 
130
141
  return (
131
- <div className={classes.join(" ")}
132
- ref={collection.ref}
133
- {...listeners}>
134
- <div className="files">
135
- {dragOrder.map(d => attachment(d))}
136
- </div>
142
+ <div className={classes.join(" ")} ref={collection.ref} {...listeners}>
143
+ <div className="files">{dragOrder.map((d) => attachment(d))}</div>
137
144
  <div className="deleted">
138
- {deleted.map(r =>
145
+ {deleted.map((r) => (
139
146
  <span className="deleted-attachment" key={r.id}>
140
- <input name={`${attrName(r)}[id]`}
141
- type="hidden"
142
- value={r.id} />
143
- <input name={`${attrName(r)}[attachment_id]`}
144
- type="hidden"
145
- value={(r.attachment && r.attachment.id) || ""} />
146
- <input name={`${attrName(r)}[_destroy]`}
147
- type="hidden"
148
- value={true} />
149
- </span>)}
147
+ <input name={`${attrName(r)}[id]`} type="hidden" value={r.id} />
148
+ <input
149
+ name={`${attrName(r)}[attachment_id]`}
150
+ type="hidden"
151
+ value={(r.attachment && r.attachment.id) || ""}
152
+ />
153
+ <input
154
+ name={`${attrName(r)}[_destroy]`}
155
+ type="hidden"
156
+ value={true}
157
+ />
158
+ </span>
159
+ ))}
150
160
  </div>
151
161
  <div className="drop-target">
152
- <FileUploadButton multiple={true}
153
- multiline={true}
154
- callback={receiveFiles} />
162
+ <FileUploadButton
163
+ multiple={true}
164
+ multiline={true}
165
+ callback={receiveFiles}
166
+ />
155
167
  </div>
156
168
  </div>
157
169
  );
@@ -6,9 +6,9 @@ export default class DateRangeSelect extends React.Component {
6
6
  super(props);
7
7
  this.state = {
8
8
  startsAt: this.parseDate(props.startsAt) || this.defaultDate(),
9
- endsAt: this.parseDate(props.endsAt) || this.defaultDate(60),
9
+ endsAt: this.parseDate(props.endsAt) || this.defaultDate(60),
10
10
  startTime: "",
11
- endTime: ""
11
+ endTime: ""
12
12
  };
13
13
  this.state.startTime = this.timeToString(this.state.startsAt);
14
14
  this.state.endTime = this.timeToString(this.state.endsAt);
@@ -33,8 +33,9 @@ export default class DateRangeSelect extends React.Component {
33
33
  defaultDate(offset = 0) {
34
34
  let coeff = 1000 * 60 * 60;
35
35
  return new Date(
36
- (Math.round((new Date()).getTime() / coeff) * coeff) + coeff +
37
- (1000 * 60 * offset)
36
+ Math.round(new Date().getTime() / coeff) * coeff +
37
+ coeff +
38
+ 1000 * 60 * offset
38
39
  );
39
40
  }
40
41
 
@@ -49,8 +50,10 @@ export default class DateRangeSelect extends React.Component {
49
50
  if (Object.prototype.hasOwnProperty.call(options, "date")) {
50
51
  newDate.setDate(options.date);
51
52
  }
52
- if (Object.prototype.hasOwnProperty.call(options, "time") &&
53
- options.time.match(/^[\d]{1,2}(:[\d]{1,2})?$/)) {
53
+ if (
54
+ Object.prototype.hasOwnProperty.call(options, "time") &&
55
+ options.time.match(/^[\d]{1,2}(:[\d]{1,2})?$/)
56
+ ) {
54
57
  newDate.setHours(options.time.split(":")[0]);
55
58
  newDate.setMinutes(options.time.split(":")[1] || 0);
56
59
  }
@@ -58,7 +61,9 @@ export default class DateRangeSelect extends React.Component {
58
61
  }
59
62
 
60
63
  parseDate(str) {
61
- if (!str) { return; }
64
+ if (!str) {
65
+ return;
66
+ }
62
67
  return new Date(str);
63
68
  }
64
69
 
@@ -75,40 +80,50 @@ export default class DateRangeSelect extends React.Component {
75
80
  }
76
81
 
77
82
  startsAtToString() {
78
- if (this.props.disabled) { return ""; }
83
+ if (this.props.disabled) {
84
+ return "";
85
+ }
79
86
  return this.state.startsAt.toJSON();
80
87
  }
81
88
 
82
89
  endsAtToString() {
83
- if (this.props.disabled) { return ""; }
90
+ if (this.props.disabled) {
91
+ return "";
92
+ }
84
93
  return this.state.endsAt.toJSON();
85
94
  }
86
95
 
87
96
  renderDateSelect(key, date, handleChange) {
88
97
  return (
89
98
  <div className="date-select">
90
- <select value={date.getMonth()}
91
- onChange={e => handleChange({ month: e.target.value })}
92
- disabled={this.props.disabled}>
99
+ <select
100
+ value={date.getMonth()}
101
+ onChange={(e) => handleChange({ month: e.target.value })}
102
+ disabled={this.props.disabled}>
93
103
  {this.monthOptions().map((m, i) => (
94
- <option key={key + "-month-" + i}
95
- value={i}>{m}</option>
104
+ <option key={key + "-month-" + i} value={i}>
105
+ {m}
106
+ </option>
96
107
  ))}
97
108
  </select>
98
- <select value={date.getDate()}
99
- onChange={e => handleChange({ date: e.target.value })}
100
- disabled={this.props.disabled}>
101
- {this.dayOptions().map(d => (
102
- <option key={key + "-date-" + d}
103
- value={d}>{d}</option>
109
+ <select
110
+ value={date.getDate()}
111
+ onChange={(e) => handleChange({ date: e.target.value })}
112
+ disabled={this.props.disabled}>
113
+ {this.dayOptions().map((d) => (
114
+ <option key={key + "-date-" + d} value={d}>
115
+ {d}
116
+ </option>
104
117
  ))}
105
118
  </select>
106
- <select value={date.getFullYear()}
107
- onChange={e => handleChange({ year: e.target.value })}
108
- disabled={this.props.disabled}>
109
- {this.yearOptions().map(y => (
110
- <option key={key + "-year-" + y}
111
- value={y}>{y}</option>
119
+ <select
120
+ value={date.getFullYear()}
121
+ onChange={(e) => handleChange({ year: e.target.value })}
122
+ disabled={this.props.disabled}>
123
+ {this.yearOptions().map((y) => (
124
+ <option key={key + "-year-" + y} value={y}>
125
+ {y}
126
+ </option>
112
127
  ))}
113
128
  </select>
114
129
  </div>
@@ -118,37 +133,49 @@ export default class DateRangeSelect extends React.Component {
118
133
  render() {
119
134
  return (
120
135
  <div className="date-range-select">
121
- <input type="hidden"
122
- name={this.props.objectName + "[starts_at]"}
123
- value={this.startsAtToString()} />
124
- <input type="hidden"
125
- name={this.props.objectName + "[ends_at]"}
126
- value={this.endsAtToString()} />
136
+ <input
137
+ type="hidden"
138
+ name={this.props.objectName + "[starts_at]"}
139
+ value={this.startsAtToString()}
140
+ />
141
+ <input
142
+ type="hidden"
143
+ name={this.props.objectName + "[ends_at]"}
144
+ value={this.endsAtToString()}
145
+ />
127
146
  <div className="date">
128
- {this.renderDateSelect("starts-at",
129
- this.state.startsAt,
130
- this.changeStartsAt)}
147
+ {this.renderDateSelect(
148
+ "starts-at",
149
+ this.state.startsAt,
150
+ this.changeStartsAt
151
+ )}
131
152
  {!this.props.disableTime && (
132
- <input type="text"
133
- size="5"
134
- value={this.state.startTime}
135
- disabled={this.props.disabled}
136
- onChange={e => this.setState({ startTime: e.target.value })}
137
- onBlur={e => this.changeStartsAt({ time: e.target.value })} />
153
+ <input
154
+ type="text"
155
+ size="5"
156
+ value={this.state.startTime}
157
+ disabled={this.props.disabled}
158
+ onChange={(e) => this.setState({ startTime: e.target.value })}
159
+ onBlur={(e) => this.changeStartsAt({ time: e.target.value })}
160
+ />
138
161
  )}
139
162
  </div>
140
163
  <span className="to">to</span>
141
164
  <div className="date">
142
- {this.renderDateSelect("ends-at",
143
- this.state.endsAt,
144
- this.changeEndsAt)}
165
+ {this.renderDateSelect(
166
+ "ends-at",
167
+ this.state.endsAt,
168
+ this.changeEndsAt
169
+ )}
145
170
  {!this.props.disableTime && (
146
- <input type="text"
147
- size="5"
148
- value={this.state.endTime}
149
- disabled={this.props.disabled}
150
- onChange={e => this.setState({ endTime: e.target.value })}
151
- onBlur={e => this.changeEndsAt({ time: e.target.value })} />
171
+ <input
172
+ type="text"
173
+ size="5"
174
+ value={this.state.endTime}
175
+ disabled={this.props.disabled}
176
+ onChange={(e) => this.setState({ endTime: e.target.value })}
177
+ onBlur={(e) => this.changeEndsAt({ time: e.target.value })}
178
+ />
152
179
  )}
153
180
  </div>
154
181
  </div>
@@ -162,13 +189,26 @@ export default class DateRangeSelect extends React.Component {
162
189
  // Returns an array with years from 2000 to 10 years from now.
163
190
  yearOptions() {
164
191
  let start = 2000;
165
- return Array.apply(null, Array((new Date()).getFullYear() - start + 11))
166
- .map((_, i) => i + start);
192
+ return Array.apply(null, Array(new Date().getFullYear() - start + 11)).map(
193
+ (_, i) => i + start
194
+ );
167
195
  }
168
196
 
169
197
  monthOptions() {
170
- return(["January", "February", "March", "April", "May", "June", "July",
171
- "August", "September", "October", "November", "December"]);
198
+ return [
199
+ "January",
200
+ "February",
201
+ "March",
202
+ "April",
203
+ "May",
204
+ "June",
205
+ "July",
206
+ "August",
207
+ "September",
208
+ "October",
209
+ "November",
210
+ "December"
211
+ ];
172
212
  }
173
213
 
174
214
  dayOptions() {
@@ -5,13 +5,13 @@ import useModalStore from "../stores/useModalStore";
5
5
  import { Locale, ImageResource } from "../types";
6
6
 
7
7
  interface EditableImageProps {
8
- image: ImageResource,
9
- src: string,
10
- caption: boolean,
11
- locale: string,
12
- locales: Record<string, Locale>,
13
- width: number,
14
- onUpdate?: (newImage: ImageResource, src: string) => void
8
+ image: ImageResource;
9
+ src: string;
10
+ caption: boolean;
11
+ locale: string;
12
+ locales: Record<string, Locale>;
13
+ width: number;
14
+ onUpdate?: (newImage: ImageResource, src: string) => void;
15
15
  }
16
16
 
17
17
  export default function EditableImage(props: EditableImageProps) {
@@ -43,7 +43,8 @@ export default function EditableImage(props: EditableImageProps) {
43
43
  caption={props.caption}
44
44
  locale={props.locale}
45
45
  locales={props.locales}
46
- onUpdate={updateImage} />
46
+ onUpdate={updateImage}
47
+ />
47
48
  );
48
49
  };
49
50
 
@@ -51,14 +52,17 @@ export default function EditableImage(props: EditableImageProps) {
51
52
 
52
53
  return (
53
54
  <div className="editable-image">
54
- {altWarning &&
55
- <span className="alt-warning" title="Alternative text is missing">
56
- <i className="fa-solid fa-triangle-exclamation icon" />
57
- </span>}
58
- <img src={src}
59
- width={props.width}
60
- height={height()}
61
- onClick={handleClick} />
55
+ {altWarning && (
56
+ <span className="alt-warning" title="Alternative text is missing">
57
+ <i className="fa-solid fa-triangle-exclamation icon" />
58
+ </span>
59
+ )}
60
+ <img
61
+ src={src}
62
+ width={props.width}
63
+ height={height()}
64
+ onClick={handleClick}
65
+ />
62
66
  </div>
63
67
  );
64
68
  }
@@ -1,10 +1,10 @@
1
1
  import React, { ChangeEvent, useRef } from "react";
2
2
 
3
3
  interface FileUploadButtonProps {
4
- callback: (files: File[]) => void,
5
- type: string,
6
- multiple: boolean,
7
- multiline: boolean
4
+ callback: (files: File[]) => void;
5
+ type: string;
6
+ multiple: boolean;
7
+ multiline: boolean;
8
8
  }
9
9
 
10
10
  export default function FileUploadButton(props: FileUploadButtonProps) {
@@ -32,15 +32,15 @@ export default function FileUploadButton(props: FileUploadButtonProps) {
32
32
  Drag and drop {props.type || "file"}
33
33
  {props.multiple && "s"} here, or
34
34
  {props.multiline && <br />}
35
- <button onClick={triggerDialog}>
36
- choose a file
37
- </button>
35
+ <button onClick={triggerDialog}>choose a file</button>
38
36
  </span>
39
- <input type="file"
40
- onChange={handleChange}
41
- ref={inputRef}
42
- style={{ display: "none" }}
43
- multiple={props.multiple || false} />
37
+ <input
38
+ type="file"
39
+ onChange={handleChange}
40
+ ref={inputRef}
41
+ style={{ display: "none" }}
42
+ multiple={props.multiple || false}
43
+ />
44
44
  </div>
45
45
  );
46
46
  }
@@ -1,16 +1,16 @@
1
1
  import React, { useRef, useState } from "react";
2
2
 
3
3
  interface Position {
4
- x: number,
5
- y: number,
4
+ x: number;
5
+ y: number;
6
6
  }
7
7
 
8
8
  interface FocalPointProps {
9
- x: number,
10
- y: number,
11
- onChange: (pos: Position) => void,
12
- width: number,
13
- height: number
9
+ x: number;
10
+ y: number;
11
+ onChange: (pos: Position) => void;
12
+ width: number;
13
+ height: number;
14
14
  }
15
15
 
16
16
  function clamp(val: number, min: number, max: number): number {
@@ -27,7 +27,10 @@ export default function FocalPoint(props: FocalPointProps) {
27
27
  const { width, height, onChange } = props;
28
28
 
29
29
  const [dragging, setDragging] = useState(false);
30
- const [position, setPosition] = useState<Position>({ x: props.x, y: props.y });
30
+ const [position, setPosition] = useState<Position>({
31
+ x: props.x,
32
+ y: props.y
33
+ });
31
34
 
32
35
  const containerRef = useRef<HTMLDivElement>();
33
36
  const pointRef = useRef<HTMLDivElement>();
@@ -49,7 +52,7 @@ export default function FocalPoint(props: FocalPointProps) {
49
52
 
50
53
  const drag = (evt: TouchEvent | MouseEvent) => {
51
54
  if (dragging) {
52
- let x: number , y: number;
55
+ let x: number, y: number;
53
56
  const containerSize = containerRef.current.getBoundingClientRect();
54
57
  evt.preventDefault();
55
58
 
@@ -78,17 +81,16 @@ export default function FocalPoint(props: FocalPointProps) {
78
81
  };
79
82
 
80
83
  return (
81
- <div className="focal-editor"
82
- ref={containerRef}
83
- onTouchStart={dragStart}
84
- onTouchEnd={dragEnd}
85
- onTouchMove={drag}
86
- onMouseDown={dragStart}
87
- onMouseUp={dragEnd}
88
- onMouseMove={drag}>
89
- <div className="focal-point"
90
- style={pointStyle}
91
- ref={pointRef} />
84
+ <div
85
+ className="focal-editor"
86
+ ref={containerRef}
87
+ onTouchStart={dragStart}
88
+ onTouchEnd={dragEnd}
89
+ onTouchMove={drag}
90
+ onMouseDown={dragStart}
91
+ onMouseUp={dragEnd}
92
+ onMouseMove={drag}>
93
+ <div className="focal-point" style={pointStyle} ref={pointRef} />
92
94
  </div>
93
95
  );
94
96
  }
@@ -5,12 +5,12 @@ import { cropSize, CropSize, CropState, Position, Size } from "./useCrop";
5
5
  import FocalPoint from "./FocalPoint";
6
6
 
7
7
  interface ImageProps {
8
- containerSize: Size,
9
- croppedImage: string,
10
- cropState: CropState,
11
- focalPoint: Position,
12
- setCrop: (crop: CropSize) => void,
13
- setFocal: (focal: Position) => void
8
+ containerSize: Size;
9
+ croppedImage: string;
10
+ cropState: CropState;
11
+ focalPoint: Position;
12
+ setCrop: (crop: CropSize) => void;
13
+ setFocal: (focal: Position) => void;
14
14
  }
15
15
 
16
16
  export default function Image(props: ImageProps) {
@@ -40,25 +40,29 @@ export default function Image(props: ImageProps) {
40
40
  if (props.cropState.cropping) {
41
41
  return (
42
42
  <div className="image-wrapper" style={style}>
43
- <ReactCrop src={props.cropState.image.uncropped_url}
44
- crop={cropSize(props.cropState)}
45
- minWidth={10}
46
- minHeight={10}
47
- onChange={props.setCrop} />
43
+ <ReactCrop
44
+ src={props.cropState.image.uncropped_url}
45
+ crop={cropSize(props.cropState)}
46
+ minWidth={10}
47
+ minHeight={10}
48
+ onChange={props.setCrop}
49
+ />
48
50
  </div>
49
51
  );
50
52
  } else {
51
53
  return (
52
54
  <div className="image-wrapper" style={style}>
53
55
  {props.focalPoint && (
54
- <FocalPoint width={width} height={height}
55
- x={props.focalPoint.x}
56
- y={props.focalPoint.y}
57
- onChange={props.setFocal} />
56
+ <FocalPoint
57
+ width={width}
58
+ height={height}
59
+ x={props.focalPoint.x}
60
+ y={props.focalPoint.y}
61
+ onChange={props.setFocal}
62
+ />
58
63
  )}
59
64
  <img src={props.croppedImage} />
60
65
  </div>
61
66
  );
62
67
  }
63
-
64
68
  }