pages_core 3.10.2 → 3.11.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/app/assets/builds/pages_core/admin-dist.js +9 -9
- data/app/helpers/pages_core/admin/admin_helper.rb +1 -0
- data/app/helpers/pages_core/admin/form_builder.rb +2 -1
- data/app/helpers/pages_core/admin/image_uploads_helper.rb +1 -1
- data/app/helpers/pages_core/admin/locales_helper.rb +26 -0
- data/app/helpers/pages_core/admin/localized_form_builder.rb +29 -0
- data/app/helpers/pages_core/form_builder.rb +1 -104
- data/app/helpers/pages_core/labelled_form_builder.rb +109 -0
- data/app/javascript/components/Attachments/Attachment.jsx +11 -8
- data/app/javascript/components/Attachments/AttachmentEditor.jsx +11 -4
- data/app/javascript/components/ImageEditor/Form.jsx +7 -1
- data/app/javascript/components/PageTree.jsx +4 -1
- data/app/javascript/components/PageTreeDraggable.jsx +14 -11
- data/app/javascript/components/PageTreeNode.jsx +31 -24
- data/app/javascript/components/RichTextArea.jsx +19 -2
- data/app/models/concerns/pages_core/humanizable_param.rb +14 -8
- data/app/models/concerns/pages_core/page_model/pathable.rb +12 -6
- data/app/views/admin/pages/_edit_files.html.erb +1 -1
- data/app/views/admin/pages/_edit_images.html.erb +1 -1
- data/app/views/admin/pages/_edit_metadata.html.erb +1 -1
- data/app/views/admin/pages/index.html.erb +1 -0
- metadata +24 -21
@@ -6,6 +6,7 @@ module PagesCore
|
|
6
6
|
include PagesCore::Admin::ContentTabsHelper
|
7
7
|
include PagesCore::Admin::DateRangeHelper
|
8
8
|
include PagesCore::Admin::ImageUploadsHelper
|
9
|
+
include PagesCore::Admin::LocalesHelper
|
9
10
|
include PagesCore::Admin::PageJsonHelper
|
10
11
|
include PagesCore::Admin::LabelledFieldHelper
|
11
12
|
include PagesCore::Admin::TagEditorHelper
|
@@ -4,12 +4,13 @@ module PagesCore
|
|
4
4
|
module Admin
|
5
5
|
class FormBuilder < PagesCore::FormBuilder
|
6
6
|
include DynamicImage::Helper
|
7
|
+
include PagesCore::Admin::LocalizedFormBuilder
|
7
8
|
|
8
9
|
def rich_text_area(attr, options = {})
|
9
10
|
@template.rich_text_area_tag(
|
10
11
|
"#{object_name}[#{attr}]",
|
11
12
|
object.send(attr),
|
12
|
-
options
|
13
|
+
localized_form_field_options(attr).merge(options)
|
13
14
|
)
|
14
15
|
end
|
15
16
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PagesCore
|
4
|
+
module Admin
|
5
|
+
module LocalesHelper
|
6
|
+
def locales_with_dir
|
7
|
+
locales = PagesCore.config.locales || {}
|
8
|
+
locales.each_with_object({}) do |(key, name), hash|
|
9
|
+
hash[key] = { name: name, dir: locale_direction(key) }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def locale_direction(locale)
|
14
|
+
rtl_locale?(locale) ? "rtl" : "ltr"
|
15
|
+
end
|
16
|
+
|
17
|
+
def rtl_locale?(locale)
|
18
|
+
rtl_locales.include?(locale.to_s)
|
19
|
+
end
|
20
|
+
|
21
|
+
def rtl_locales
|
22
|
+
%w[ar arc dv fa ha he khw ks ku ps ur yi]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PagesCore
|
4
|
+
module Admin
|
5
|
+
module LocalizedFormBuilder
|
6
|
+
include PagesCore::Admin::LocalesHelper
|
7
|
+
|
8
|
+
def text_area(method, options = {})
|
9
|
+
super(method, localized_form_field_options(method).merge(options))
|
10
|
+
end
|
11
|
+
|
12
|
+
def text_field(method, options = {})
|
13
|
+
super(method, localized_form_field_options(method).merge(options))
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def localized_form_field_options(method)
|
19
|
+
unless object.is_a?(LocalizableModel::InstanceMethods) &&
|
20
|
+
object.class.localized_attributes.include?(method.to_sym)
|
21
|
+
return {}
|
22
|
+
end
|
23
|
+
|
24
|
+
{ dir: rtl_locale?(object.locale) ? "rtl" : "ltr",
|
25
|
+
lang: object.locale }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -3,12 +3,7 @@
|
|
3
3
|
module PagesCore
|
4
4
|
class FormBuilder < ActionView::Helpers::FormBuilder
|
5
5
|
include ActionView::Helpers::TagHelper
|
6
|
-
|
7
|
-
def field_with_label(attr, str, label = nil, class_name = nil)
|
8
|
-
classes = ["field", class_name]
|
9
|
-
classes << "field-with-errors" if object.errors[attr].any?
|
10
|
-
tag.div(label_for(attr, label) + str, class: classes.compact.join(" "))
|
11
|
-
end
|
6
|
+
include PagesCore::LabelledFormBuilder
|
12
7
|
|
13
8
|
def image_file_preview(attribute)
|
14
9
|
return "" unless object.send(attribute) &&
|
@@ -22,103 +17,5 @@ module PagesCore
|
|
22
17
|
def image_file_field(attribute, options = {})
|
23
18
|
safe_join [image_file_preview(attribute), file_field(attribute, options)]
|
24
19
|
end
|
25
|
-
|
26
|
-
def label_and_errors(attribute, label_text)
|
27
|
-
return label_text unless object.errors[attribute].any?
|
28
|
-
|
29
|
-
error = tag.span(object.errors[attribute].first, class: "error")
|
30
|
-
safe_join([label_text, error], " ")
|
31
|
-
end
|
32
|
-
|
33
|
-
def label_for(attribute, label_text = nil)
|
34
|
-
label_text ||= object.class.human_attribute_name(attribute)
|
35
|
-
tag.label(label_and_errors(attribute, label_text),
|
36
|
-
for: [object.class.to_s.underscore, attribute].join("_"))
|
37
|
-
end
|
38
|
-
|
39
|
-
def labelled_check_box(
|
40
|
-
attr, label = nil, options = {}, checked = "1", unchecked = "0"
|
41
|
-
)
|
42
|
-
labelled_field(attr, label, options) do |opts|
|
43
|
-
check_box(attr, opts, checked, unchecked)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def labelled_country_select(
|
48
|
-
attr, label = nil, priority = {}, opts = {}, html_opts = {}
|
49
|
-
)
|
50
|
-
if priority.is_a?(Hash)
|
51
|
-
return labelled_field(attr, label, priority) do |options|
|
52
|
-
country_select(attr, options, opts, html_opts)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
labelled_field(attr, label, opts) do |options|
|
56
|
-
country_select(attr, priority, options, html_opts)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def labelled_date_select(attribute, label_text = nil, options = {})
|
61
|
-
labelled_field(attribute, label_text, options) do |opts|
|
62
|
-
date_select(attribute, opts)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def labelled_datetime_select(attribute, label_text = nil, options = {})
|
67
|
-
labelled_field(attribute, label_text, options) do |opts|
|
68
|
-
datetime_select(attribute, opts)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def labelled_file_field(attribute, label_text = nil, options = {})
|
73
|
-
labelled_field(attribute, label_text, options) do |opts|
|
74
|
-
file_field(attribute, opts)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def labelled_image_file_field(attribute, label_text = nil, options = {})
|
79
|
-
labelled_field(attribute, label_text, options) do |opts|
|
80
|
-
image_file_field(attribute, opts)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def labelled_password_field(attribute, label_text = nil, options = {})
|
85
|
-
labelled_field(attribute, label_text, options, "text-field") do |opts|
|
86
|
-
password_field(attribute, opts)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def labelled_select(attribute, choices, label_text = nil, options = {})
|
91
|
-
labelled_field(attribute, label_text, options) do |opts|
|
92
|
-
select(attribute, choices, opts)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def labelled_text_area(attribute, label_text = nil, options = {})
|
97
|
-
labelled_field(attribute, label_text, options, "text-area") do |opts|
|
98
|
-
text_area(attribute, opts)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def labelled_text_field(attribute, label_text = nil, options = {})
|
103
|
-
labelled_field(attribute, label_text, options, "text-field") do |opts|
|
104
|
-
text_field(attribute, opts)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def labelled_time_select(attribute, label_text = nil, options = {})
|
109
|
-
labelled_field(attribute, label_text, options) do |opts|
|
110
|
-
time_select(attribute, opts)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
protected
|
115
|
-
|
116
|
-
def labelled_field(attr, label_text = nil, options = {}, class_name = nil)
|
117
|
-
if label_text.is_a?(Hash) && options == {}
|
118
|
-
options = label_text
|
119
|
-
label_text = nil
|
120
|
-
end
|
121
|
-
field_with_label(attr, yield(options), label_text, class_name)
|
122
|
-
end
|
123
20
|
end
|
124
21
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PagesCore
|
4
|
+
module LabelledFormBuilder
|
5
|
+
def field_with_label(attr, str, label = nil, class_name = nil)
|
6
|
+
classes = ["field", class_name]
|
7
|
+
classes << "field-with-errors" if object.errors[attr].any?
|
8
|
+
tag.div(label_for(attr, label) + str, class: classes.compact.join(" "))
|
9
|
+
end
|
10
|
+
|
11
|
+
def label_and_errors(attribute, label_text)
|
12
|
+
return label_text unless object.errors[attribute].any?
|
13
|
+
|
14
|
+
error = tag.span(object.errors[attribute].first, class: "error")
|
15
|
+
safe_join([label_text, error], " ")
|
16
|
+
end
|
17
|
+
|
18
|
+
def label_for(attribute, label_text = nil)
|
19
|
+
label_text ||= object.class.human_attribute_name(attribute)
|
20
|
+
tag.label(label_and_errors(attribute, label_text),
|
21
|
+
for: [object.class.to_s.underscore, attribute].join("_"))
|
22
|
+
end
|
23
|
+
|
24
|
+
def labelled_check_box(
|
25
|
+
attr, label = nil, options = {}, checked = "1", unchecked = "0"
|
26
|
+
)
|
27
|
+
labelled_field(attr, label, options) do |opts|
|
28
|
+
check_box(attr, opts, checked, unchecked)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def labelled_country_select(
|
33
|
+
attr, label = nil, priority = {}, opts = {}, html_opts = {}
|
34
|
+
)
|
35
|
+
if priority.is_a?(Hash)
|
36
|
+
return labelled_field(attr, label, priority) do |options|
|
37
|
+
country_select(attr, options, opts, html_opts)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
labelled_field(attr, label, opts) do |options|
|
41
|
+
country_select(attr, priority, options, html_opts)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def labelled_date_select(attribute, label_text = nil, options = {})
|
46
|
+
labelled_field(attribute, label_text, options) do |opts|
|
47
|
+
date_select(attribute, opts)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def labelled_datetime_select(attribute, label_text = nil, options = {})
|
52
|
+
labelled_field(attribute, label_text, options) do |opts|
|
53
|
+
datetime_select(attribute, opts)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def labelled_file_field(attribute, label_text = nil, options = {})
|
58
|
+
labelled_field(attribute, label_text, options) do |opts|
|
59
|
+
file_field(attribute, opts)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def labelled_image_file_field(attribute, label_text = nil, options = {})
|
64
|
+
labelled_field(attribute, label_text, options) do |opts|
|
65
|
+
image_file_field(attribute, opts)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def labelled_password_field(attribute, label_text = nil, options = {})
|
70
|
+
labelled_field(attribute, label_text, options, "text-field") do |opts|
|
71
|
+
password_field(attribute, opts)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def labelled_select(attribute, choices, label_text = nil, options = {})
|
76
|
+
labelled_field(attribute, label_text, options) do |opts|
|
77
|
+
select(attribute, choices, opts)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def labelled_text_area(attribute, label_text = nil, options = {})
|
82
|
+
labelled_field(attribute, label_text, options, "text-area") do |opts|
|
83
|
+
text_area(attribute, opts)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def labelled_text_field(attribute, label_text = nil, options = {})
|
88
|
+
labelled_field(attribute, label_text, options, "text-field") do |opts|
|
89
|
+
text_field(attribute, opts)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def labelled_time_select(attribute, label_text = nil, options = {})
|
94
|
+
labelled_field(attribute, label_text, options) do |opts|
|
95
|
+
time_select(attribute, opts)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
protected
|
100
|
+
|
101
|
+
def labelled_field(attr, label_text = nil, options = {}, class_name = nil)
|
102
|
+
if label_text.is_a?(Hash) && options == {}
|
103
|
+
options = label_text
|
104
|
+
label_text = nil
|
105
|
+
end
|
106
|
+
field_with_label(attr, yield(options), label_text, class_name)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -8,7 +8,7 @@ import ToastStore from "../../stores/ToastStore";
|
|
8
8
|
import { useDraggable } from "../drag";
|
9
9
|
|
10
10
|
export default function Attachment(props) {
|
11
|
-
const { attributeName, draggable } = props;
|
11
|
+
const { attributeName, draggable, locales, locale } = props;
|
12
12
|
const { record } = draggable;
|
13
13
|
const { attachment, uploading } = record;
|
14
14
|
|
@@ -30,15 +30,15 @@ export default function Attachment(props) {
|
|
30
30
|
};
|
31
31
|
|
32
32
|
const description = () => {
|
33
|
-
if (attachment.description && attachment.description[
|
34
|
-
return attachment.description[
|
33
|
+
if (attachment.description && attachment.description[locale]) {
|
34
|
+
return attachment.description[locale];
|
35
35
|
}
|
36
36
|
return null;
|
37
37
|
};
|
38
38
|
|
39
39
|
const name = () => {
|
40
|
-
if (attachment.name && attachment.name[
|
41
|
-
return attachment.name[
|
40
|
+
if (attachment.name && attachment.name[locale]) {
|
41
|
+
return attachment.name[locale];
|
42
42
|
}
|
43
43
|
return null;
|
44
44
|
};
|
@@ -48,8 +48,8 @@ export default function Attachment(props) {
|
|
48
48
|
ModalStore.dispatch({
|
49
49
|
type: "OPEN",
|
50
50
|
payload: <AttachmentEditor attachment={attachment}
|
51
|
-
locale={
|
52
|
-
locales={
|
51
|
+
locale={locale}
|
52
|
+
locales={locales}
|
53
53
|
onUpdate={props.onUpdate} />
|
54
54
|
});
|
55
55
|
};
|
@@ -64,6 +64,8 @@ export default function Attachment(props) {
|
|
64
64
|
|
65
65
|
const icon = uploading ? "cloud-upload" : "paperclip";
|
66
66
|
|
67
|
+
const localeDir = (locales && locales[locale].dir) || "ltr";
|
68
|
+
|
67
69
|
return (
|
68
70
|
<div className={classes.join(" ")}
|
69
71
|
{...listeners}>
|
@@ -100,7 +102,8 @@ export default function Attachment(props) {
|
|
100
102
|
<a href={attachment.url}
|
101
103
|
rel="noreferrer"
|
102
104
|
target="_blank">{attachment.filename}</a>}
|
103
|
-
{!uploading && description() &&
|
105
|
+
{!uploading && description() &&
|
106
|
+
<p dir={localeDir}>{description()}</p>}
|
104
107
|
</div>}
|
105
108
|
</div>
|
106
109
|
);
|
@@ -6,7 +6,7 @@ import ToastStore from "../../stores/ToastStore";
|
|
6
6
|
import { putJson } from "../../lib/request";
|
7
7
|
|
8
8
|
export default function AttachmentEditor(props) {
|
9
|
-
const { attachment } = props;
|
9
|
+
const { attachment, locales } = props;
|
10
10
|
|
11
11
|
const [locale, setLocale] = useState(props.locale);
|
12
12
|
const [localizations, setLocalizations] = useState({
|
@@ -45,19 +45,22 @@ export default function AttachmentEditor(props) {
|
|
45
45
|
ModalStore.dispatch({ type: "CLOSE" });
|
46
46
|
};
|
47
47
|
|
48
|
+
const inputDir = (locales && locales[locale].dir) || "ltr";
|
49
|
+
|
48
50
|
return (
|
49
51
|
<div className="attachment-editor">
|
50
52
|
<form>
|
51
|
-
{props.locales && Object.keys(
|
53
|
+
{props.locales && Object.keys(locales).length > 1 && (
|
52
54
|
<div className="field">
|
53
55
|
<label>
|
54
56
|
Locale
|
55
57
|
</label>
|
56
58
|
<select name="locale"
|
59
|
+
value={locale}
|
57
60
|
onChange={e => setLocale(e.target.value)}>
|
58
|
-
{Object.keys(
|
61
|
+
{Object.keys(locales).map(key => (
|
59
62
|
<option key={`locale-${key}`} value={key}>
|
60
|
-
{
|
63
|
+
{locales[key].name}
|
61
64
|
</option>
|
62
65
|
))}
|
63
66
|
</select>
|
@@ -67,6 +70,8 @@ export default function AttachmentEditor(props) {
|
|
67
70
|
<label>Name</label>
|
68
71
|
<input type="text"
|
69
72
|
className="name"
|
73
|
+
lang={locale}
|
74
|
+
dir={inputDir}
|
70
75
|
value={localizations.name[locale] || ""}
|
71
76
|
onChange={updateLocalization("name")} />
|
72
77
|
</div>
|
@@ -74,6 +79,8 @@ export default function AttachmentEditor(props) {
|
|
74
79
|
<label>Description</label>
|
75
80
|
<textarea className="description"
|
76
81
|
value={localizations.description[locale] || ""}
|
82
|
+
lang={locale}
|
83
|
+
dir={inputDir}
|
77
84
|
onChange={updateLocalization("description")} />
|
78
85
|
</div>
|
79
86
|
<div className="field embed-code">
|
@@ -19,6 +19,8 @@ export default function Form(props) {
|
|
19
19
|
props.setLocale(evt.target.value);
|
20
20
|
};
|
21
21
|
|
22
|
+
const inputDir = (locales && locales[locale].dir) || "ltr";
|
23
|
+
|
22
24
|
return (
|
23
25
|
<form>
|
24
26
|
<div className="field embed-code">
|
@@ -44,7 +46,7 @@ export default function Form(props) {
|
|
44
46
|
onChange={handleChangeLocale}>
|
45
47
|
{Object.keys(locales).map(key => (
|
46
48
|
<option key={`locale-${key}`} value={key}>
|
47
|
-
{locales[key]}
|
49
|
+
{locales[key].name}
|
48
50
|
</option>
|
49
51
|
))}
|
50
52
|
</select>
|
@@ -59,6 +61,8 @@ export default function Form(props) {
|
|
59
61
|
</span>
|
60
62
|
<textarea
|
61
63
|
className="alternative"
|
64
|
+
lang={locale}
|
65
|
+
dir={inputDir}
|
62
66
|
value={alternative[locale] || ""}
|
63
67
|
onChange={e => props.updateLocalization("alternative", e.target.value)} />
|
64
68
|
</div>
|
@@ -68,6 +72,8 @@ export default function Form(props) {
|
|
68
72
|
Caption
|
69
73
|
</label>
|
70
74
|
<textarea
|
75
|
+
lang={locale}
|
76
|
+
dir={inputDir}
|
71
77
|
onChange={e => props.updateLocalization("caption", e.target.value)}
|
72
78
|
value={caption[locale] || ""}
|
73
79
|
className="caption" />
|
@@ -139,7 +139,9 @@ export default class PageTree extends React.Component {
|
|
139
139
|
movedPage={this.movedPage}
|
140
140
|
toggleCollapsed={this.toggleCollapsed}
|
141
141
|
updatePage={this.updatePage}
|
142
|
-
updateTree={this.updateTree}
|
142
|
+
updateTree={this.updateTree}
|
143
|
+
locale={this.props.locale}
|
144
|
+
dir={this.props.dir} />
|
143
145
|
);
|
144
146
|
}
|
145
147
|
|
@@ -189,5 +191,6 @@ export default class PageTree extends React.Component {
|
|
189
191
|
PageTree.propTypes = {
|
190
192
|
pages: PropTypes.array,
|
191
193
|
locale: PropTypes.string,
|
194
|
+
dir: PropTypes.string,
|
192
195
|
permissions: PropTypes.array
|
193
196
|
};
|
@@ -75,7 +75,7 @@ export default class PageTreeDraggable extends React.Component {
|
|
75
75
|
}
|
76
76
|
|
77
77
|
render() {
|
78
|
-
|
78
|
+
const { tree, dir, locale } = this.props;
|
79
79
|
var dragging = this.state.dragging;
|
80
80
|
|
81
81
|
if (!tree) {
|
@@ -90,16 +90,17 @@ export default class PageTreeDraggable extends React.Component {
|
|
90
90
|
<div className="page-tree">
|
91
91
|
{this.getDraggingDom()}
|
92
92
|
<PageTreeNode
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
93
|
+
tree={tree}
|
94
|
+
index={root}
|
95
|
+
key={root.id}
|
96
|
+
paddingLeft={this.props.paddingLeft}
|
97
|
+
addChild={id => this.addChild(id)}
|
98
|
+
onDragStart={(id, dom, e) => this.dragStart(id, dom, e)}
|
99
|
+
onCollapse={nodeId => this.toggleCollapse(nodeId)}
|
100
|
+
updatePage={(idx, attrs) => this.updatePage(idx, attrs)}
|
101
|
+
dragging={dragging && dragging.id}
|
102
|
+
dir={dir}
|
103
|
+
locale={locale} />
|
103
104
|
</div>
|
104
105
|
);
|
105
106
|
}
|
@@ -303,4 +304,6 @@ PageTreeDraggable.propTypes = {
|
|
303
304
|
paddingLeft: PropTypes.number,
|
304
305
|
updatePage: PropTypes.func,
|
305
306
|
updateTree: PropTypes.func,
|
307
|
+
locale: PropTypes.string,
|
308
|
+
dir: PropTypes.string
|
306
309
|
};
|
@@ -125,9 +125,7 @@ export default class PageTreeNode extends React.Component {
|
|
125
125
|
}
|
126
126
|
|
127
127
|
childNodes() {
|
128
|
-
|
129
|
-
let tree = this.props.tree;
|
130
|
-
let dragging = this.props.dragging;
|
128
|
+
const { index, tree, dragging, dir, locale } = this.props;
|
131
129
|
|
132
130
|
if (index.children && index.children.length && !index.node.collapsed) {
|
133
131
|
var childrenStyles = {};
|
@@ -139,21 +137,22 @@ export default class PageTreeNode extends React.Component {
|
|
139
137
|
return (
|
140
138
|
<div className="children" style={childrenStyles}>
|
141
139
|
{index.children.map((child) => {
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
140
|
+
var childIndex = tree.getIndex(child);
|
141
|
+
return (
|
142
|
+
<PageTreeNode
|
143
|
+
tree={tree}
|
144
|
+
index={childIndex}
|
145
|
+
key={childIndex.id}
|
146
|
+
dragging={dragging}
|
147
|
+
paddingLeft={this.props.paddingLeft}
|
148
|
+
addChild={this.props.addChild}
|
149
|
+
onCollapse={this.props.onCollapse}
|
150
|
+
onDragStart={this.props.onDragStart}
|
151
|
+
updatePage={this.props.updatePage}
|
152
|
+
dir={dir}
|
153
|
+
locale={locale} />
|
154
|
+
);
|
155
|
+
})}
|
157
156
|
</div>
|
158
157
|
);
|
159
158
|
}
|
@@ -232,11 +231,14 @@ export default class PageTreeNode extends React.Component {
|
|
232
231
|
}
|
233
232
|
|
234
233
|
pageName() {
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
234
|
+
const name = this.node().name || <i className="untitled">Untitled</i>;
|
235
|
+
|
236
|
+
return(
|
237
|
+
<span dir={this.props.dir}
|
238
|
+
lang={this.props.locale}>
|
239
|
+
{name}
|
240
|
+
</span>
|
241
|
+
);
|
240
242
|
}
|
241
243
|
|
242
244
|
render() {
|
@@ -278,6 +280,7 @@ export default class PageTreeNode extends React.Component {
|
|
278
280
|
}
|
279
281
|
|
280
282
|
renderEditNode() {
|
283
|
+
const { dir, locale } = this.props;
|
281
284
|
let self = this;
|
282
285
|
|
283
286
|
let handleNameChange = function(event) {
|
@@ -303,6 +306,8 @@ export default class PageTreeNode extends React.Component {
|
|
303
306
|
<form onSubmit={performEdit}>
|
304
307
|
<input type="text"
|
305
308
|
value={this.state.newName}
|
309
|
+
dir={dir}
|
310
|
+
lang={locale}
|
306
311
|
autoFocus
|
307
312
|
onChange={handleNameChange} />
|
308
313
|
<button className="save" type="submit">
|
@@ -407,5 +412,7 @@ PageTreeNode.propTypes = {
|
|
407
412
|
onDragStart: PropTypes.func,
|
408
413
|
paddingLeft: PropTypes.number,
|
409
414
|
tree: PropTypes.object,
|
410
|
-
updatePage: PropTypes.func
|
415
|
+
updatePage: PropTypes.func,
|
416
|
+
locale: PropTypes.string,
|
417
|
+
dir: PropTypes.string,
|
411
418
|
};
|
@@ -129,6 +129,20 @@ export default class RichTextArea extends React.Component {
|
|
129
129
|
}
|
130
130
|
}
|
131
131
|
|
132
|
+
localeOptions() {
|
133
|
+
let opts = {};
|
134
|
+
|
135
|
+
if (this.props.lang) {
|
136
|
+
opts.lang = this.props.lang;
|
137
|
+
}
|
138
|
+
|
139
|
+
if (this.props.dir) {
|
140
|
+
opts.dir = this.props.dir;
|
141
|
+
}
|
142
|
+
|
143
|
+
return opts;
|
144
|
+
}
|
145
|
+
|
132
146
|
relativeUrl(str) {
|
133
147
|
let url = null;
|
134
148
|
|
@@ -177,7 +191,8 @@ export default class RichTextArea extends React.Component {
|
|
177
191
|
value={value}
|
178
192
|
rows={rows}
|
179
193
|
onChange={this.handleChange}
|
180
|
-
onKeyDown={this.handleKeyPress}
|
194
|
+
onKeyDown={this.handleKeyPress}
|
195
|
+
{...this.localeOptions()} />
|
181
196
|
</div>
|
182
197
|
);
|
183
198
|
}
|
@@ -209,5 +224,7 @@ RichTextArea.propTypes = {
|
|
209
224
|
name: PropTypes.string,
|
210
225
|
value: PropTypes.string,
|
211
226
|
rows: PropTypes.number,
|
212
|
-
simple: PropTypes.bool
|
227
|
+
simple: PropTypes.bool,
|
228
|
+
lang: PropTypes.string,
|
229
|
+
dir: PropTypes.string
|
213
230
|
};
|