Skip to content

Commit 5d10675

Browse files
committed
Init
1 parent 3d718c7 commit 5d10675

28 files changed

+1107
-1
lines changed

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/.DS_Store
2+
/.vscode
3+
4+
venv/
5+
dist/
6+
__pycache__
7+
8+
#egg's specific
9+
*.egg-info
10+
11+
db.sqlite3

.pylintrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[MASTER]
2+
disable=
3+
C0114, # missing-module-docstring
4+
C0115,
5+
C0116,

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2020 Ilya
3+
Copyright (c) 2020 Ilya Kotlyakov
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

django_editorjs/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
__version__ = "0.1.0"
2+
3+
from .fields import EditorJsTextField, EditorJsJSONField
4+
from .widgets import EditorJsWidget
5+
6+
__all__ = ("EditorJsTextField", "EditorJsJSONField",
7+
"EditorJsWidget", "__version__")

django_editorjs/config.py

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
from datetime import datetime
2+
from secrets import token_urlsafe
3+
4+
from django.conf import settings
5+
6+
EDITORJS_IMAGE_UPLOAD_PATH = str(getattr(
7+
settings,
8+
'EDITORJS_IMAGE_UPLOAD_PATH',
9+
'uploads/images/'
10+
)) + datetime.now().strftime("%Y/%m/")
11+
12+
EDITORJS_IMAGE_NAME_ORIGINAL = getattr(
13+
settings, "EDITORJS_IMAGE_NAME_ORIGINAL", False)
14+
EDITORJS_IMAGE_NAME_POSTFIX = getattr(
15+
settings, "EDITORJS_IMAGE_NAME_POSTFIX", token_urlsafe(5))
16+
EDITORJS_IMAGE_NAME = getattr(
17+
settings, "EDITORJS_IMAGE_NAME", token_urlsafe(8))
18+
19+
DEFAULT_PLUGINS = (
20+
'@editorjs/paragraph',
21+
'@editorjs/image',
22+
'@editorjs/header',
23+
'@editorjs/list',
24+
'@editorjs/checklist',
25+
'@editorjs/quote',
26+
'@editorjs/raw',
27+
'@editorjs/code',
28+
'@editorjs/inline-code',
29+
'@editorjs/embed',
30+
'@editorjs/delimiter',
31+
'@editorjs/warning',
32+
'@editorjs/link',
33+
'@editorjs/marker',
34+
'@editorjs/table'
35+
)
36+
37+
DEFAULT_CONFIG_PLUGINS = {
38+
'@editorjs/image': {
39+
'Image': {
40+
'class': 'ImageTool',
41+
'inlineToolbar': True,
42+
"config": {
43+
"endpoints": {
44+
"byFile": "/editorjs/image_upload/"
45+
}
46+
}
47+
}
48+
},
49+
'@editorjs/header': {
50+
'Header': {
51+
'class': 'Header',
52+
'inlineToolbar': True,
53+
'config': {
54+
'placeholder': 'Enter a header',
55+
'levels': [2, 3, 4],
56+
'defaultLevel': 2
57+
}
58+
}
59+
},
60+
'@editorjs/checklist': {
61+
'Checklist': {
62+
'class': 'Checklist',
63+
'inlineToolbar': True
64+
}
65+
},
66+
'@editorjs/list': {
67+
'List': {
68+
'class': 'List',
69+
'inlineToolbar': True
70+
}
71+
},
72+
'@editorjs/quote': {
73+
'Quote': {
74+
'class': 'Quote',
75+
'inlineToolbar': True
76+
}
77+
},
78+
'@editorjs/raw': {
79+
'Raw': {
80+
'class': 'RawTool'
81+
}
82+
},
83+
'@editorjs/code': {
84+
'Code': {
85+
'class': 'CodeTool'
86+
}
87+
},
88+
'@editorjs/inline-code': {
89+
'InlineCode': {
90+
'class': 'InlineCode'
91+
}
92+
},
93+
'@editorjs/embed': {
94+
'Embed': {
95+
'class': 'Embed'
96+
}
97+
},
98+
'@editorjs/delimiter': {
99+
'Delimiter': {
100+
'class': 'Delimiter'
101+
}
102+
},
103+
'@editorjs/warning': {
104+
'Warning': {
105+
'class': 'Warning',
106+
'inlineToolbar': True
107+
}
108+
},
109+
'@editorjs/link': {
110+
'LinkTool': {
111+
'class': 'LinkTool'
112+
}
113+
},
114+
'@editorjs/marker': {
115+
'Marker': {
116+
'class': 'Marker',
117+
'inlineToolbar': True
118+
}
119+
},
120+
'@editorjs/table': {
121+
'Table': {
122+
'class': 'Table',
123+
'inlineToolbar': True
124+
}
125+
}
126+
}

django_editorjs/fields.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from django.db.models import Field, JSONField
2+
from django.forms import Textarea
3+
4+
from django_editorjs.widgets import EditorJsWidget
5+
6+
7+
class EditorJsFieldMixin:
8+
def __init__(self, *args, plugins=None, tools=None, **kwargs):
9+
self.plugins = plugins
10+
self.tools = tools
11+
self.version = kwargs.pop('version', '2.18.0')
12+
self.use_editor_js = kwargs.pop('use_editor_js', True)
13+
super().__init__(*args, **kwargs)
14+
15+
def formfield(self, **kwargs):
16+
if self.use_editor_js:
17+
widget = EditorJsWidget(
18+
plugins=self.plugins, tools=self.tools, version=self.version)
19+
else:
20+
widget = Textarea()
21+
22+
defaults = {'widget': widget}
23+
defaults.update(kwargs)
24+
25+
# pylint: disable=no-member
26+
return super().formfield(**defaults)
27+
28+
29+
class EditorJsTextField(EditorJsFieldMixin, Field):
30+
def get_internal_type(self):
31+
return "TextField"
32+
33+
34+
class EditorJsJSONField(EditorJsFieldMixin, JSONField):
35+
pass
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
div[data-editorjs-holder] {
2+
display: inline-block;
3+
width: 100%;
4+
max-width: 750px;
5+
padding: 1.5em 1em;
6+
border: 1px solid #cccccc;
7+
border-radius: 4px;
8+
background-color: #fcfeff;
9+
}
10+
11+
.codex-editor .ce-rawtool__textarea {
12+
background-color: #010e15;
13+
color: #ccced2;
14+
}
15+
16+
.codex-editor .cdx-list {
17+
margin: 0;
18+
padding-left: 32px;
19+
outline: none;
20+
}
21+
22+
.codex-editor .cdx-list__item {
23+
padding: 8px;
24+
line-height: 1.4em;
25+
list-style: inherit;
26+
}
27+
28+
.codex-editor .cdx-checklist__item-text {
29+
align-self: center;
30+
}
31+
32+
.codex-editor .ce-header {
33+
padding: 1em 0;
34+
margin: 0;
35+
margin-bottom: -1em;
36+
line-height: 1.4em;
37+
outline: none;
38+
background: transparent;
39+
color: #000;
40+
font-weight: 800;
41+
text-transform: initial;
42+
}
43+
44+
.codex-editor h2.ce-header {
45+
font-size: 1.5em;
46+
}
47+
48+
.codex-editor h3.ce-header {
49+
font-size: 1.3em;
50+
}
51+
52+
.codex-editor h4.ce-header {
53+
font-size: 1.1em;
54+
}
55+
56+
.codex-editor blockquote {
57+
border: initial;
58+
margin: initial;
59+
color: initial;
60+
font-size: inherit;
61+
}
62+
63+
.codex-editor .wrapper .cdx-button {
64+
display: none;
65+
}
66+
67+
.codex-editor .link-tool__progress {
68+
float: initial;
69+
width: 100%;
70+
line-height: initial;
71+
padding: initial;
72+
}
73+
74+
@media (max-width: 767px) {
75+
div[data-editorjs-holder] {
76+
width: auto;
77+
}
78+
79+
.aligned .form-row,
80+
.aligned .form-row > div {
81+
flex-direction: column;
82+
}
83+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
function initEditorJsField(field_id, tools) {
2+
var textarea = document.getElementById(field_id)
3+
var holder = textarea.nextElementSibling
4+
5+
var data = textarea.value.trim()
6+
7+
if (data) {
8+
try {
9+
data = JSON.parse(data)
10+
} catch (error) {
11+
console.log(error)
12+
holder.remove()
13+
return false
14+
}
15+
}
16+
17+
textarea.style.display = "none"
18+
19+
if (tools) {
20+
for (const plugin in tools) {
21+
var cls = tools[plugin].class
22+
if (cls && window[cls] != undefined) {
23+
tools[plugin].class = eval(cls)
24+
}
25+
}
26+
}
27+
28+
const editor = new EditorJS({
29+
autofocus: true,
30+
holder: holder,
31+
tools: tools || {},
32+
data: data || undefined,
33+
onChange: function () {
34+
editor
35+
.save()
36+
.then(function (data) {
37+
textarea.value = JSON.stringify(data)
38+
})
39+
.catch(function (error) {
40+
console.log("save error: ", error)
41+
})
42+
},
43+
})
44+
}

django_editorjs/urls.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from django.contrib.admin.views.decorators import staff_member_required
2+
from django.urls import path
3+
4+
from django_editorjs.views import ImageUploadView
5+
6+
urlpatterns = [
7+
path('image_upload/', staff_member_required(ImageUploadView.as_view()),
8+
name='editorjs_image_upload'),
9+
]

django_editorjs/utils.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from django.conf import settings
2+
from django.utils.module_loading import import_string
3+
4+
5+
def get_storage_class():
6+
return import_string(
7+
getattr(
8+
settings,
9+
'EDITORJS_STORAGE_BACKEND',
10+
'django.core.files.storage.DefaultStorage'
11+
)
12+
)()
13+
14+
15+
storage = get_storage_class()

0 commit comments

Comments
 (0)