pages_core 3.12.1 → 3.12.2
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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/app/assets/builds/pages_core/admin-dist.js +59 -14
- data/app/assets/builds/pages_core/admin-dist.js.map +7 -0
- data/app/assets/builds/pages_core/admin.css +39 -0
- data/app/assets/stylesheets/pages_core/admin/components/search.css +27 -0
- data/app/assets/stylesheets/pages_core/admin/controllers/pages.css +6 -0
- data/app/controllers/admin/pages_controller.rb +12 -11
- data/app/controllers/concerns/pages_core/rss_controller.rb +17 -1
- data/app/controllers/pages_core/admin_controller.rb +6 -0
- data/app/controllers/pages_core/frontend/pages_controller.rb +9 -5
- data/app/controllers/pages_core/sitemaps_controller.rb +3 -5
- data/app/helpers/admin/pages_helper.rb +32 -0
- data/app/javascript/admin-dist.ts +2 -0
- data/app/javascript/components/Attachments/{Attachment.jsx → Attachment.tsx} +42 -33
- data/app/javascript/components/Attachments/{AttachmentEditor.jsx → AttachmentEditor.tsx} +23 -23
- data/app/javascript/components/{EditableImage.jsx → EditableImage.tsx} +27 -24
- data/app/javascript/components/{FileUploadButton.jsx → FileUploadButton.tsx} +15 -16
- data/app/javascript/components/ImageCropper/FocalPoint.tsx +94 -0
- data/app/javascript/components/ImageCropper/{Image.jsx → Image.tsx} +13 -14
- data/app/javascript/components/ImageCropper/{Toolbar.jsx → Toolbar.tsx} +16 -12
- data/app/javascript/components/ImageCropper/{useCrop.js → useCrop.ts} +80 -37
- data/app/javascript/components/{ImageCropper.jsx → ImageCropper.tsx} +17 -15
- data/app/javascript/components/ImageEditor/{Form.jsx → Form.tsx} +24 -23
- data/app/javascript/components/{ImageEditor.jsx → ImageEditor.tsx} +17 -15
- data/app/javascript/components/ImageGrid/{DragElement.jsx → DragElement.tsx} +12 -10
- data/app/javascript/components/ImageGrid/{GridImage.jsx → GridImage.tsx} +40 -30
- data/app/javascript/components/ImageGrid/{Placeholder.jsx → Placeholder.tsx} +5 -6
- data/app/javascript/components/ImageGrid.jsx +3 -4
- data/app/javascript/components/{ImageUploader.jsx → ImageUploader.tsx} +46 -41
- data/app/javascript/components/Modal.tsx +48 -0
- data/app/javascript/components/PageImages.tsx +28 -0
- data/app/javascript/components/{PageTreeDraggable.jsx → PageTree/Draggable.tsx} +79 -57
- data/app/javascript/components/{PageTreeNode.jsx → PageTree/Node.tsx} +79 -70
- data/app/javascript/components/PageTree/types.ts +15 -0
- data/app/javascript/components/PageTree.tsx +206 -0
- data/app/javascript/components/RichTextToolbarButton.tsx +17 -0
- data/app/javascript/components/TagEditor/{AddTagForm.jsx → AddTagForm.tsx} +9 -10
- data/app/javascript/components/TagEditor/{Tag.jsx → Tag.tsx} +8 -9
- data/app/javascript/components/{TagEditor.jsx → TagEditor.tsx} +12 -13
- data/app/javascript/components/Toast.tsx +61 -0
- data/app/javascript/components/drag/{draggedOrder.js → draggedOrder.ts} +22 -12
- data/app/javascript/components/drag/types.ts +28 -0
- data/app/javascript/components/drag/{useDragCollection.js → useDragCollection.ts} +40 -22
- data/app/javascript/components/drag/{useDragUploader.js → useDragUploader.ts} +34 -25
- data/app/javascript/components/drag/useDraggable.ts +21 -0
- data/app/javascript/components/{drag.js → drag.ts} +1 -0
- data/app/javascript/controllers/{EditPageController.js → EditPageController.ts} +3 -1
- data/app/javascript/controllers/{LoginController.js → LoginController.ts} +7 -3
- data/app/javascript/controllers/{MainController.js → MainController.ts} +19 -14
- data/app/javascript/{index.js → index.ts} +8 -7
- data/app/javascript/lib/{Tree.js → Tree.ts} +106 -85
- data/app/javascript/lib/{copyToClipboard.js → copyToClipboard.ts} +1 -1
- data/app/javascript/lib/{readyHandler.js → readyHandler.ts} +4 -2
- data/app/javascript/lib/{request.js → request.ts} +11 -5
- data/app/javascript/stores/useModalStore.ts +15 -0
- data/app/javascript/stores/useToastStore.ts +26 -0
- data/app/javascript/stores.ts +2 -0
- data/app/javascript/types.ts +30 -0
- data/app/policies/page_policy.rb +4 -0
- data/app/views/admin/calendars/_sidebar.html.erb +3 -0
- data/app/views/admin/news/_sidebar.html.erb +3 -0
- data/app/views/admin/pages/_list_item.html.erb +4 -22
- data/app/views/admin/pages/_search_bar.html.erb +12 -0
- data/app/views/admin/pages/index.html.erb +3 -0
- data/app/views/admin/pages/search.html.erb +54 -0
- data/app/views/feeds/pages.rss.builder +3 -9
- data/config/routes.rb +1 -0
- data/lib/pages_core/configuration/pages.rb +0 -1
- data/lib/rails/generators/pages_core/frontend/frontend_generator.rb +33 -17
- data/lib/rails/generators/pages_core/frontend/templates/application.html.erb +0 -1
- data/lib/rails/generators/pages_core/frontend/templates/javascript/lib/gridOverlay.ts +40 -0
- data/lib/rails/generators/pages_core/frontend/templates/javascript/lib/responsiveEmbeds.ts +68 -0
- data/lib/rails/generators/pages_core/frontend/templates/postcss.config.js +17 -0
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/application.postcss.css +4 -0
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/components/base.css +24 -0
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/components/layout.css +21 -0
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/config.css +5 -0
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/animation.css +5 -0
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/colors.css +18 -0
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/fonts.css +6 -0
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/grid.css +65 -0
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/typography.css +131 -0
- data/lib/rails/generators/pages_core/install/templates/pages_initializer.rb +0 -3
- metadata +68 -62
- data/app/javascript/admin-dist.js +0 -2
- data/app/javascript/components/ImageCropper/FocalPoint.jsx +0 -93
- data/app/javascript/components/Modal.jsx +0 -59
- data/app/javascript/components/PageImages.jsx +0 -25
- data/app/javascript/components/PageTree.jsx +0 -196
- data/app/javascript/components/RichTextToolbarButton.jsx +0 -20
- data/app/javascript/components/Toast.jsx +0 -72
- data/app/javascript/components/drag/useDraggable.js +0 -17
- data/app/javascript/stores/ModalStore.jsx +0 -12
- data/app/javascript/stores/ToastStore.jsx +0 -14
- data/app/javascript/stores.js +0 -2
- data/lib/rails/generators/pages_core/frontend/templates/javascript/lib/GridOverlay.js +0 -66
- data/lib/rails/generators/pages_core/frontend/templates/javascript/lib/ResponsiveEmbeds.js +0 -72
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/application.sass.scss +0 -15
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/components/base.scss +0 -12
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/config.scss +0 -26
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/framework/breakpoints.scss +0 -42
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/framework/clearfix.scss +0 -7
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/framework/fonts.scss +0 -32
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/framework/grid.scss +0 -168
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/framework/grid_overlay.scss +0 -44
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/colors.scss +0 -8
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/global/typography.scss +0 -90
- data/lib/rails/generators/pages_core/frontend/templates/stylesheets/vendor/normalize.css +0 -349
- /data/app/javascript/components/Attachments/{Placeholder.jsx → Placeholder.tsx} +0 -0
- /data/app/javascript/components/ImageGrid/{FilePlaceholder.jsx → FilePlaceholder.tsx} +0 -0
- /data/app/javascript/{components.js → components.ts} +0 -0
- /data/app/javascript/{hooks.js → hooks.ts} +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import useToastStore from "../stores/useToastStore";
|
|
4
|
+
|
|
5
|
+
interface ToastProps {
|
|
6
|
+
error: string,
|
|
7
|
+
notice: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default function Toast(props: ToastProps) {
|
|
11
|
+
const [fadeout, setFadeout] = useState(false);
|
|
12
|
+
const { toasts, error, notice, next } = useToastStore((state) => state);
|
|
13
|
+
const timerRef = useRef<number | null>(null);
|
|
14
|
+
|
|
15
|
+
const toast = toasts[0];
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (props.error) {
|
|
19
|
+
error(props.error);
|
|
20
|
+
}
|
|
21
|
+
if (props.notice) {
|
|
22
|
+
notice(props.notice);
|
|
23
|
+
}
|
|
24
|
+
}, [props.error, props.notice]);
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
setFadeout(false);
|
|
28
|
+
if (toast && !timerRef.current) {
|
|
29
|
+
timerRef.current = setTimeout(() => {
|
|
30
|
+
setFadeout(true);
|
|
31
|
+
timerRef.current = setTimeout(() => {
|
|
32
|
+
timerRef.current = null;
|
|
33
|
+
setFadeout(false);
|
|
34
|
+
next();
|
|
35
|
+
}, 500);
|
|
36
|
+
}, 4000);
|
|
37
|
+
}
|
|
38
|
+
return () => {
|
|
39
|
+
clearTimeout(timerRef.current);
|
|
40
|
+
};
|
|
41
|
+
}, [toast]);
|
|
42
|
+
|
|
43
|
+
const classNames = ["toast"];
|
|
44
|
+
|
|
45
|
+
if (toast) {
|
|
46
|
+
classNames.push(toast.type);
|
|
47
|
+
if (fadeout) {
|
|
48
|
+
classNames.push("fadeout");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div className="toast-wrapper" aria-live="polite">
|
|
54
|
+
{toast && (
|
|
55
|
+
<div className={classNames.join(" ")}>
|
|
56
|
+
{toast.message}
|
|
57
|
+
</div>
|
|
58
|
+
)}
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { Draggable, DragCollection, DragState } from "./types";
|
|
2
|
+
|
|
3
|
+
function hovering(
|
|
4
|
+
dragState: DragState,
|
|
5
|
+
target: Draggable | React.MutableRefObject<HTMLDivElement>
|
|
6
|
+
): boolean {
|
|
7
|
+
const { x, y } = dragState;
|
|
8
|
+
let rect: DOMRect;
|
|
9
|
+
if ("rect" in target) {
|
|
5
10
|
rect = target.rect;
|
|
6
|
-
} else if (target
|
|
11
|
+
} else if ("current" in target) {
|
|
7
12
|
rect = target.current.getBoundingClientRect();
|
|
8
13
|
} else {
|
|
9
14
|
return false;
|
|
@@ -12,7 +17,9 @@ function hovering(dragState, target) {
|
|
|
12
17
|
y >= rect.top && y <= rect.bottom);
|
|
13
18
|
}
|
|
14
19
|
|
|
15
|
-
export function collectionOrder(
|
|
20
|
+
export function collectionOrder(
|
|
21
|
+
collection: DragCollection, dragState: DragState
|
|
22
|
+
): Draggable[] {
|
|
16
23
|
const { draggables, ref } = collection;
|
|
17
24
|
const { dragging } = dragState;
|
|
18
25
|
|
|
@@ -36,15 +43,18 @@ export function collectionOrder(collection, dragState) {
|
|
|
36
43
|
return ordered;
|
|
37
44
|
}
|
|
38
45
|
|
|
39
|
-
export default function draggedOrder(
|
|
46
|
+
export default function draggedOrder(
|
|
47
|
+
collection: DragCollection, dragState: DragState
|
|
48
|
+
): Draggable[] {
|
|
40
49
|
let ordered = collectionOrder(collection, dragState);
|
|
41
50
|
|
|
42
51
|
if (dragState.dragging && ordered.indexOf(dragState.dragging) === -1) {
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
if (collection.ref.current &&
|
|
53
|
+
dragState.y < collection.ref.current.getBoundingClientRect().top) {
|
|
54
|
+
ordered = [dragState.dragging, ...ordered];
|
|
55
|
+
} else {
|
|
56
|
+
ordered.push(dragState.dragging);
|
|
57
|
+
}
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
return ordered;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type DraggableRecord = Record<string, unknown>;
|
|
2
|
+
|
|
3
|
+
export interface Draggable {
|
|
4
|
+
record: DraggableRecord,
|
|
5
|
+
ref: React.MutableRefObject<HTMLDivElement>,
|
|
6
|
+
rect: DOMRect | null,
|
|
7
|
+
handle: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface DragCollectionAction {
|
|
11
|
+
type: string,
|
|
12
|
+
payload?: Draggable[] | Draggable | null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DragCollection {
|
|
16
|
+
ref: React.MutableRefObject<HTMLDivElement>,
|
|
17
|
+
draggables: Draggable[],
|
|
18
|
+
dispatch: (DragCollectionAction) => void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface Position {
|
|
22
|
+
x: number | null,
|
|
23
|
+
y: number | null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface DragState extends Position {
|
|
27
|
+
dragging: Draggable | false
|
|
28
|
+
}
|
|
@@ -1,15 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
import uniqueId from "lodash
|
|
1
|
+
import { createRef, useEffect, useReducer, useRef } from "react";
|
|
2
|
+
import { uniqueId } from "lodash";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
Draggable,
|
|
6
|
+
DraggableRecord,
|
|
7
|
+
DragCollectionAction,
|
|
8
|
+
DragCollection
|
|
9
|
+
} from "./types";
|
|
10
|
+
|
|
11
|
+
type Draggables = Draggable[];
|
|
12
|
+
|
|
13
|
+
function getPosition(draggable: Draggable) {
|
|
14
|
+
if (draggable && draggable.ref && draggable.ref.current) {
|
|
6
15
|
return draggable.ref.current.getBoundingClientRect();
|
|
7
16
|
} else {
|
|
8
17
|
return null;
|
|
9
18
|
}
|
|
10
19
|
}
|
|
11
20
|
|
|
12
|
-
function hideDraggable(draggable, callback) {
|
|
21
|
+
function hideDraggable(draggable: Draggable | null, callback: () => void) {
|
|
13
22
|
if (draggable && draggable.ref && draggable.ref.current) {
|
|
14
23
|
const prevDisplay = draggable.ref.current.style.display;
|
|
15
24
|
draggable.ref.current.style.display = "none";
|
|
@@ -22,22 +31,29 @@ function hideDraggable(draggable, callback) {
|
|
|
22
31
|
}
|
|
23
32
|
}
|
|
24
33
|
|
|
25
|
-
function
|
|
34
|
+
function insertFiles(state: Draggable[], files: Draggable[]): Draggable[] {
|
|
35
|
+
const index = state.indexOf("Files");
|
|
36
|
+
if (index === -1 || !files) {
|
|
37
|
+
return state;
|
|
38
|
+
} else {
|
|
39
|
+
return [
|
|
40
|
+
...state.slice(0, index),
|
|
41
|
+
...files,
|
|
42
|
+
...state.slice(index + 1)
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function dragCollectionReducer(
|
|
48
|
+
state: Draggable[], action: DragCollectionAction
|
|
49
|
+
): Draggable[] {
|
|
26
50
|
switch (action.type) {
|
|
27
51
|
case "append":
|
|
28
|
-
return [...state, ...action.payload];
|
|
52
|
+
return [...state, ...action.payload as Draggable[]];
|
|
29
53
|
case "prepend":
|
|
30
|
-
return [...action.payload, ...state];
|
|
54
|
+
return [...action.payload as Draggable[], ...state];
|
|
31
55
|
case "insertFiles":
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (index === -1 || !action.payload) {
|
|
35
|
-
return state;
|
|
36
|
-
} else {
|
|
37
|
-
return [...state.slice(0, index),
|
|
38
|
-
...action.payload,
|
|
39
|
-
...state.slice(index + 1)];
|
|
40
|
-
}
|
|
56
|
+
return insertFiles(state, action.payload);
|
|
41
57
|
case "update":
|
|
42
58
|
return state.map(d => {
|
|
43
59
|
return (d.handle === action.payload.handle) ? action.payload : d;
|
|
@@ -59,20 +75,22 @@ function dragCollectionReducer(state, action) {
|
|
|
59
75
|
}
|
|
60
76
|
}
|
|
61
77
|
|
|
62
|
-
export function createDraggable(record) {
|
|
78
|
+
export function createDraggable(record: Record<string, unknown>): Draggable {
|
|
63
79
|
return { record: record,
|
|
64
80
|
rect: null,
|
|
65
|
-
ref:
|
|
81
|
+
ref: createRef(),
|
|
66
82
|
handle: uniqueId("draggable") };
|
|
67
83
|
}
|
|
68
84
|
|
|
69
|
-
export default function useDragCollection(
|
|
70
|
-
|
|
85
|
+
export default function useDragCollection(
|
|
86
|
+
records: DraggableRecord[]
|
|
87
|
+
): DragCollection {
|
|
88
|
+
const containerRef = useRef<HTMLElement>(null);
|
|
71
89
|
const [draggables, dispatch] = useReducer(
|
|
72
90
|
dragCollectionReducer,
|
|
73
91
|
[],
|
|
74
92
|
() => records.map(r => createDraggable(r))
|
|
75
|
-
);
|
|
93
|
+
) as [Draggables, (Draggables) => Draggable[]];
|
|
76
94
|
|
|
77
95
|
useEffect(() => {
|
|
78
96
|
dispatch({ type: "updatePositions" });
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
import { Draggable, DragCollection, DragState, Position } from "./types";
|
|
4
|
+
|
|
5
|
+
function containsFiles(evt: Event) {
|
|
6
|
+
if ("dataTransfer" in evt) {
|
|
7
|
+
const dataTransfer: DataTransfer = evt.dataTransfer;
|
|
8
|
+
if ("types" in dataTransfer) {
|
|
9
|
+
const types = dataTransfer.types;
|
|
10
|
+
for (let i = 0; i < types.length; i++) {
|
|
11
|
+
if (types[i] === "Files" || types[i] === "application/x-moz-file") {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
11
15
|
}
|
|
12
16
|
}
|
|
13
17
|
return false;
|
|
14
18
|
}
|
|
15
19
|
|
|
16
|
-
function getFiles(dt) {
|
|
17
|
-
|
|
20
|
+
function getFiles(dt: DataTransfer): File[] {
|
|
21
|
+
const files: File[] = [];
|
|
18
22
|
if (dt.items) {
|
|
19
23
|
for (let i = 0; i < dt.items.length; i++) {
|
|
20
24
|
if (dt.items[i].kind == "file") {
|
|
@@ -29,36 +33,41 @@ function getFiles(dt) {
|
|
|
29
33
|
return files;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
function mousePosition(evt) {
|
|
33
|
-
|
|
34
|
-
if (evt.type == "touchmove") {
|
|
36
|
+
function mousePosition(evt: TouchEvent | MouseEvent): Position {
|
|
37
|
+
let x: number | null, y: number | null;
|
|
38
|
+
if ("touches" in evt && evt.type == "touchmove") {
|
|
35
39
|
x = evt.touches[0].clientX;
|
|
36
40
|
y = evt.touches[0].clientY;
|
|
37
|
-
} else {
|
|
41
|
+
} else if (evt instanceof MouseEvent) {
|
|
38
42
|
x = evt.clientX;
|
|
39
43
|
y = evt.clientY;
|
|
40
44
|
}
|
|
41
45
|
return { x: x, y: y };
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
export default function useDragUploader(
|
|
45
|
-
|
|
48
|
+
export default function useDragUploader(
|
|
49
|
+
collections: DragCollection[],
|
|
50
|
+
onDragEnd: (dragState: DragState, files: File[]) => void
|
|
51
|
+
) {
|
|
52
|
+
const initialState: DragState = {
|
|
46
53
|
dragging: false,
|
|
47
54
|
x: null, y: null
|
|
48
|
-
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const [dragState, setDragState] = useState(initialState);
|
|
49
58
|
|
|
50
|
-
const updatePositions = (dragging) => {
|
|
59
|
+
const updatePositions = (dragging: Draggable | null) => {
|
|
51
60
|
collections.forEach(c => {
|
|
52
61
|
c.dispatch({ type: "updatePositions", payload: dragging });
|
|
53
62
|
});
|
|
54
63
|
};
|
|
55
64
|
|
|
56
|
-
const startDrag = (evt, draggable) => {
|
|
65
|
+
const startDrag = (evt: Event, draggable: Draggable) => {
|
|
57
66
|
updatePositions(draggable);
|
|
58
67
|
setDragState({ dragging: draggable, ...mousePosition(evt) });
|
|
59
68
|
};
|
|
60
69
|
|
|
61
|
-
const drag = (evt) => {
|
|
70
|
+
const drag = (evt: Event) => {
|
|
62
71
|
if (dragState.dragging) {
|
|
63
72
|
evt.stopPropagation();
|
|
64
73
|
evt.preventDefault();
|
|
@@ -70,13 +79,13 @@ export default function useDragUploader(collections, onDragEnd) {
|
|
|
70
79
|
}
|
|
71
80
|
};
|
|
72
81
|
|
|
73
|
-
const dragEnd = (evt) => {
|
|
82
|
+
const dragEnd = (evt: Event) => {
|
|
74
83
|
if (dragState.dragging) {
|
|
75
84
|
const prevDragState = dragState;
|
|
76
|
-
|
|
77
|
-
evt.preventDefault();
|
|
85
|
+
let files: File[] = [];
|
|
78
86
|
evt.stopPropagation();
|
|
79
|
-
|
|
87
|
+
evt.preventDefault();
|
|
88
|
+
if ("dataTransfer" in evt && dragState.dragging == "Files") {
|
|
80
89
|
files = getFiles(evt.dataTransfer);
|
|
81
90
|
}
|
|
82
91
|
setDragState({ dragging: false, x: null, y: null });
|
|
@@ -85,7 +94,7 @@ export default function useDragUploader(collections, onDragEnd) {
|
|
|
85
94
|
}
|
|
86
95
|
};
|
|
87
96
|
|
|
88
|
-
const dragLeave = (evt) => {
|
|
97
|
+
const dragLeave = (evt: Event) => {
|
|
89
98
|
if (dragState.dragging === "Files") {
|
|
90
99
|
evt.preventDefault();
|
|
91
100
|
evt.stopPropagation();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from "react";
|
|
2
|
+
import { Draggable } from "./types";
|
|
3
|
+
|
|
4
|
+
export default function useDraggable(
|
|
5
|
+
draggable: Draggable,
|
|
6
|
+
startDrag: (evt: React.MouseEvent, draggable: Draggable) => void
|
|
7
|
+
) {
|
|
8
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
9
|
+
|
|
10
|
+
const handleDrag = (evt: Event) => {
|
|
11
|
+
evt.preventDefault();
|
|
12
|
+
evt.stopPropagation();
|
|
13
|
+
startDrag(evt, draggable);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
draggable.ref.current = ref.current;
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
return { ref: ref, onDragStart: handleDrag, draggable: true };
|
|
21
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus";
|
|
2
2
|
|
|
3
|
-
export default class EditPageController extends Controller {
|
|
3
|
+
export default class EditPageController extends Controller<HTMLFormElement> {
|
|
4
|
+
readonly formTarget: HTMLFormElement;
|
|
5
|
+
|
|
4
6
|
static get targets() {
|
|
5
7
|
return ["form"];
|
|
6
8
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus";
|
|
2
2
|
|
|
3
3
|
export default class LoginController extends Controller {
|
|
4
|
+
readonly tabTargets: HTMLDivElement[];
|
|
5
|
+
|
|
4
6
|
static get targets() {
|
|
5
7
|
return ["tab"];
|
|
6
8
|
}
|
|
@@ -12,12 +14,14 @@ export default class LoginController extends Controller {
|
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
|
|
15
|
-
changeTab(evt) {
|
|
17
|
+
changeTab(evt: Event) {
|
|
16
18
|
evt.preventDefault();
|
|
17
|
-
|
|
19
|
+
if ("dataset" in evt.target && "tab" in evt.target.dataset) {
|
|
20
|
+
this.showTab(evt.target.dataset.tab);
|
|
21
|
+
}
|
|
18
22
|
}
|
|
19
23
|
|
|
20
|
-
showTab(tab) {
|
|
24
|
+
showTab(tab: string) {
|
|
21
25
|
this.tabTargets.forEach((t) => {
|
|
22
26
|
if (t.dataset.tab == tab) {
|
|
23
27
|
t.classList.remove("hidden");
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus";
|
|
2
2
|
|
|
3
3
|
export default class MainController extends Controller {
|
|
4
|
+
readonly linkTargets: HTMLLinkElement[];
|
|
5
|
+
readonly tabTargets: HTMLDivElement[];
|
|
6
|
+
|
|
4
7
|
static get targets() {
|
|
5
8
|
return ["tab", "link"];
|
|
6
9
|
}
|
|
7
10
|
|
|
8
11
|
connect() {
|
|
9
|
-
|
|
12
|
+
const tabs = this.tabNames();
|
|
10
13
|
if (tabs.length > 0) {
|
|
11
|
-
let initTab = null;
|
|
14
|
+
let initTab: string = null;
|
|
12
15
|
const tabExpression = /#(.*)$/;
|
|
13
16
|
|
|
14
17
|
if (document.location.toString().match(tabExpression)) {
|
|
15
|
-
|
|
18
|
+
const id = document.location.toString().match(tabExpression)[1];
|
|
16
19
|
if (tabs.indexOf(id) !== -1) {
|
|
17
20
|
initTab = id;
|
|
18
21
|
}
|
|
@@ -21,27 +24,29 @@ export default class MainController extends Controller {
|
|
|
21
24
|
this.showTab(initTab || tabs[0]);
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
window.addEventListener("popstate", this.stateHandler
|
|
27
|
+
window.addEventListener("popstate", this.stateHandler);
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
disconnect() {
|
|
28
|
-
window.removeEventListener("popstate", this.stateHandler
|
|
31
|
+
window.removeEventListener("popstate", this.stateHandler);
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
stateHandler(evt) {
|
|
32
|
-
if (
|
|
34
|
+
stateHandler = (evt: Event) => {
|
|
35
|
+
if ("state" in evt && "tabId" in evt.state) {
|
|
33
36
|
this.showTab(evt.state.tabId);
|
|
34
37
|
}
|
|
35
|
-
}
|
|
38
|
+
};
|
|
36
39
|
|
|
37
|
-
changeTab(evt) {
|
|
40
|
+
changeTab(evt: Event) {
|
|
38
41
|
evt.preventDefault();
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
if ("dataset" in evt.target && "tab" in evt.target.dataset) {
|
|
43
|
+
const tab = evt.target.dataset.tab as string;
|
|
44
|
+
this.showTab(tab);
|
|
45
|
+
history.pushState({ tabId: tab }, "", `${window.location.pathname}#${tab}`);
|
|
46
|
+
}
|
|
42
47
|
}
|
|
43
48
|
|
|
44
|
-
showTab(tab) {
|
|
49
|
+
showTab(tab: string | null) {
|
|
45
50
|
this.linkTargets.forEach((l) => {
|
|
46
51
|
if (l.dataset.tab == tab) {
|
|
47
52
|
l.classList.add("current");
|
|
@@ -59,7 +64,7 @@ export default class MainController extends Controller {
|
|
|
59
64
|
});
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
tabNames () {
|
|
67
|
+
tabNames (): string[] {
|
|
63
68
|
return this.linkTargets.map((l) => l.dataset.tab);
|
|
64
69
|
}
|
|
65
70
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { start as startRails } from "@rails/ujs";
|
|
2
2
|
import { Application } from "@hotwired/stimulus";
|
|
3
|
-
|
|
3
|
+
import "react_ujs";
|
|
4
|
+
import { FC } from "react";
|
|
4
5
|
|
|
5
6
|
import * as Components from "./components";
|
|
6
7
|
|
|
@@ -11,14 +12,14 @@ import PageOptionsController from "./controllers/PageOptionsController";
|
|
|
11
12
|
|
|
12
13
|
import RichText from "./features/RichText";
|
|
13
14
|
|
|
14
|
-
export function registerComponent(name, component) {
|
|
15
|
+
export function registerComponent(name: string, component: FC) {
|
|
15
16
|
window[name] = component;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export default function startPages () {
|
|
19
|
-
|
|
20
|
-
for (
|
|
21
|
-
registerComponent(name, Components[name]);
|
|
20
|
+
startRails();
|
|
21
|
+
for (const name in Components) {
|
|
22
|
+
registerComponent(name, Components[name] as FC);
|
|
22
23
|
}
|
|
23
24
|
RichText.start();
|
|
24
25
|
|
|
@@ -33,6 +34,6 @@ export * from "./components";
|
|
|
33
34
|
export * from "./hooks";
|
|
34
35
|
export * from "./stores";
|
|
35
36
|
|
|
36
|
-
export * from "./lib/request
|
|
37
|
+
export * from "./lib/request";
|
|
37
38
|
export { default as copyToClipboard,
|
|
38
39
|
copySupported } from "./lib/copyToClipboard";
|