Browse Source

Add save function

Updates `static/slides.json` (copies backup `archive/`)
master
The Dod 1 year ago
parent
commit
2b39ed5705

+ 1
- 0
.gitignore View File

1
 venv/
1
 venv/
2
 __pycache__/
2
 __pycache__/
3
+archive/*.json
3
 work/
4
 work/
4
 .env
5
 .env
5
 *.swp
6
 *.swp

+ 28
- 15
app.py View File

4
 from glob import glob
4
 from glob import glob
5
 import json
5
 import json
6
 import os
6
 import os
7
+import sys
8
+import time
9
+import shutil
7
 
10
 
8
 def preprocess_payload(payload):
11
 def preprocess_payload(payload):
9
-    for column in payload.get('columns', []):
10
-        md = column.get('markdown')
12
+    for column in payload.get("columns", []):
13
+        md = column.get("markdown")
11
         if md:
14
         if md:
12
-            column['content'] = markdown(md)
13
-        for slide in column.get('slides', []):
14
-            md = slide.get('markdown')
15
+            column["content"] = markdown(md)
16
+        for slide in column.get("slides", []):
17
+            md = slide.get("markdown")
15
             if md:
18
             if md:
16
-                slide['content'] = markdown(md)
19
+                slide["content"] = markdown(md)
17
 
20
 
18
 load_dotenv()
21
 load_dotenv()
19
-payload = json.load(open("static/slides.json"))
20
-preprocess_payload(payload)
21
 
22
 
22
 application = Flask(__name__)
23
 application = Flask(__name__)
23
 
24
 
24
 @application.get("/")
25
 @application.get("/")
25
 def home():
26
 def home():
27
+    payload = json.load(open("static/slides.json"))
28
+    preprocess_payload(payload)
26
     return render_template("slides.html", **payload)
29
     return render_template("slides.html", **payload)
27
 
30
 
28
-@application.get("/choices/<topic>")
31
+@application.post("/update")
32
+def update():
33
+    shutil.copy(
34
+        "static/slides.json",
35
+        time.strftime(
36
+            "archive/slides-%Y-%m-%d-%H.%M.%S.json",
37
+            time.localtime()))
38
+    payload = request.get_json()
39
+    print(type(payload))
40
+    json.dump(payload, sys.stdout, indent=4)
41
+    json.dump(payload, open("static/slides.json", "w"), indent=4)
42
+    return({"status": "success"})
43
+
44
+@application.get("/enum/<topic>")
29
 def choices(topic):
45
 def choices(topic):
30
     if topic in ["img", "bg"]:
46
     if topic in ["img", "bg"]:
31
         return {"type": "string", "enum": glob("static/{}/*.*".format(topic))}
47
         return {"type": "string", "enum": glob("static/{}/*.*".format(topic))}
35
 def schema():
51
 def schema():
36
     return render_template("slides.schema.json", backgrounds=choices("bg"))
52
     return render_template("slides.schema.json", backgrounds=choices("bg"))
37
 
53
 
38
-def home():
39
-    return render_template("slides.html", **payload)
40
-
41
 @application.get("/editor")
54
 @application.get("/editor")
42
 def editor():
55
 def editor():
43
     return render_template("editor.html")
56
     return render_template("editor.html")
44
 
57
 
45
-@application.route('/favicon.ico')
58
+@application.route("/favicon.ico")
46
 def favicon():
59
 def favicon():
47
-    return send_from_directory(os.path.join(application.root_path, 'static'),
48
-                               'favicon.ico', mimetype='image/vnd.microsoft.icon')
60
+    return send_from_directory(os.path.join(application.root_path, "static"),
61
+                               "favicon.ico", mimetype="image/vnd.microsoft.icon")

+ 1
- 0
archive/README.md View File

1
+This is where we keep old versions of `slides.json`

BIN
static/bg/bekir-donmez-stones-4.png View File


BIN
static/bg/bekir-donmez-stones-5.png View File


BIN
static/bg/bekir-donmez-stones-6.png View File


BIN
static/bg/bekir-donmez-stones-7.png View File


BIN
static/bg/bekir-donmez-stones-8.png View File


BIN
static/bg/cat-resting.png View File


+ 1805
- 0
static/bg/twilight-1.svg
File diff suppressed because it is too large
View File


+ 13
- 12
static/slides.json View File

1
 {
1
 {
2
-    "title": "Joe's farewell ceremony",
2
+    "title": "My Farewell Ceremony",
3
     "columns": [
3
     "columns": [
4
         {
4
         {
5
-            "id": "",
6
-            "title": "Goodbye from George",
5
+            "id": "welcome",
6
+            "title": "Goodbye, mates",
7
             "params": {
7
             "params": {
8
-                "theme": "sky",
9
-                "background-image": "static/img/valley-1.svg",
8
+                "theme": "simple",
9
+                "background-image": "static/bg/valley-1.svg",
10
                 "background-opacity": "0.25"
10
                 "background-opacity": "0.25"
11
             },
11
             },
12
-            "markdown": "This is my **farewell ceremony**.\n\nI [love](https://en.wikipedia.org/wiki/Love) you all."
12
+            "markdown": "Welcome, friends.\n\nWe're about to begin."
13
         },
13
         },
14
         {
14
         {
15
             "id": "memory",
15
             "id": "memory",
16
             "title": "How I'd like to be remembered",
16
             "title": "How I'd like to be remembered",
17
             "params": {
17
             "params": {
18
                 "theme": "solarized",
18
                 "theme": "solarized",
19
-                "background-image": "static/img/valley-1.svg",
19
+                "background-image": "static/bg/valley-1.svg",
20
                 "background-opacity": "0.25"
20
                 "background-opacity": "0.25"
21
             },
21
             },
22
-            "markdown": "I've done many things. Some of them I'm proud of:",
22
+            "markdown": "I've done many things.\n\nSome of them I'm proud of:",
23
             "slides": [
23
             "slides": [
24
                 {
24
                 {
25
                     "id": "work",
25
                     "id": "work",
26
                     "title": "My work",
26
                     "title": "My work",
27
                     "params": {
27
                     "params": {
28
-                        "background-image": "static/img/valley-1.svg",
28
+                        "background-image": "static/bg/valley-1.svg",
29
                         "background-opacity": "0.25"
29
                         "background-opacity": "0.25"
30
                     },
30
                     },
31
                     "markdown": "### I've worked like a horse.\n\n![A horse (of course)|w-50 centered](static/img/horse.png)"
31
                     "markdown": "### I've worked like a horse.\n\n![A horse (of course)|w-50 centered](static/img/horse.png)"
35
                     "title": "The rest",
35
                     "title": "The rest",
36
                     "params": {
36
                     "params": {
37
                         "theme": "moon",
37
                         "theme": "moon",
38
-                        "background-image": "static/img/particles-1.png",
38
+                        "background-image": "static/bg/twilight-1.svg",
39
                         "background-size": "contain"
39
                         "background-size": "contain"
40
                     },
40
                     },
41
                     "markdown": "#### I've rested like a cat.\n\n![A cat resting|w-66 centered](static/img/cat-resting.png)"
41
                     "markdown": "#### I've rested like a cat.\n\n![A cat resting|w-66 centered](static/img/cat-resting.png)"
47
             "title": "Who I seek forgiveness from",
47
             "title": "Who I seek forgiveness from",
48
             "params": {
48
             "params": {
49
                 "theme": "league",
49
                 "theme": "league",
50
-                "background-image": "static/img/particles-1.svg",
50
+                "background-image": "static/bg/particles-1.svg",
51
                 "background-opacity": "0.25"
51
                 "background-opacity": "0.25"
52
             },
52
             },
53
             "markdown": "I've made many mistakes.\n\nI hope you can forgive me:",
53
             "markdown": "I've made many mistakes.\n\nI hope you can forgive me:",
55
                 {
55
                 {
56
                     "id": "horse",
56
                     "id": "horse",
57
                     "title": "My horse",
57
                     "title": "My horse",
58
+                    "params": {},
58
                     "markdown": "![My horse|w-50 float-right](static/img/horse2.png)\n\nPlease forgive me, horse, for this and that."
59
                     "markdown": "![My horse|w-50 float-right](static/img/horse2.png)\n\nPlease forgive me, horse, for this and that."
59
                 },
60
                 },
60
                 {
61
                 {
68
             ]
69
             ]
69
         }
70
         }
70
     ]
71
     ]
71
-}
72
+}

+ 29
- 5
static/slides.schema.json View File

7
     },
7
     },
8
     "columns": {
8
     "columns": {
9
       "type": "array",
9
       "type": "array",
10
-      "title": "Columns",
10
+      "title": "Chapters",
11
+      "options": {
12
+        "collapsed": "true"
13
+      },
11
       "items": {
14
       "items": {
12
         "type": "object",
15
         "type": "object",
13
-        "title": "Column",
16
+        "title": "Chapter",
14
         "properties": {
17
         "properties": {
15
           "id": {
18
           "id": {
16
             "type": "string"
19
             "type": "string"
26
           },
29
           },
27
           "slides": {
30
           "slides": {
28
             "type": "array",
31
             "type": "array",
32
+            "title": "Pages",
29
             "options": {
33
             "options": {
30
               "collapsed": "true"
34
               "collapsed": "true"
31
             },
35
             },
32
             "items": {
36
             "items": {
33
               "type": "object",
37
               "type": "object",
34
-              "title": "Slide",
38
+              "title": "Page",
35
               "properties": {
39
               "properties": {
36
                 "id": {
40
                 "id": {
37
                   "type": "string"
41
                   "type": "string"
89
           "default": "simple"
93
           "default": "simple"
90
         },
94
         },
91
         "background-image": {
95
         "background-image": {
92
-          "$ref": "/choices/bg",
96
+          "$ref": "/enum/bg",
93
           "title": "Background image",
97
           "title": "Background image",
94
           "links": [
98
           "links": [
95
             {
99
             {
124
     "markdown": {
128
     "markdown": {
125
       "type": "string",
129
       "type": "string",
126
       "title": "Content",
130
       "title": "Content",
127
-      "format": "markdown"
131
+      "format": "markdown",
132
+      "options": {
133
+        "simplemde": {
134
+          "renderingConfig": {
135
+            "singleLineBreaks": false
136
+          },
137
+          "toolbar": [
138
+            "bold",
139
+            "italic",
140
+            "heading",
141
+            "|",
142
+            "ordered-list",
143
+            "unordered-list",
144
+            "|",
145
+            "link",
146
+            "quote",
147
+            "|",
148
+            "preview"
149
+          ]
150
+        }
151
+      }
128
     }
152
     }
129
   }
153
   }
130
 }
154
 }

+ 11
- 4
templates/editor.html View File

16
     <div class="container">
16
     <div class="container">
17
       <h1>Presentation editor</h1>
17
       <h1>Presentation editor</h1>
18
       <div id='editor_holder'></div>
18
       <div id='editor_holder'></div>
19
-      <button class="btn btn-success" id='submit'>Submit (console.log)</button>
19
+      <div class="btn-group mt-2">
20
+        <button class="btn btn-success" id='submit'>Submit</button>
21
+        <a class="btn btn-secondary" href="/">Cancel</a>
22
+      </div>
20
     </div>
23
     </div>
21
     <script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
24
     <script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
22
     <script src="https://cdn.jsdelivr.net/npm/@json-editor/json-editor@latest/dist/jsoneditor.min.js"></script>
25
     <script src="https://cdn.jsdelivr.net/npm/@json-editor/json-editor@latest/dist/jsoneditor.min.js"></script>
25
       fetch("/static/slides.schema.json")
28
       fetch("/static/slides.schema.json")
26
         .then(res => res.json())
29
         .then(res => res.json())
27
         .then(schema => {
30
         .then(schema => {
28
-          console.log(schema);
29
           fetch("/static/slides.json")
31
           fetch("/static/slides.json")
30
             .then(res => res.json())
32
             .then(res => res.json())
31
             .then(slides => {
33
             .then(slides => {
32
-              console.log(slides);
33
               // Initialize the editor with a JSON schema
34
               // Initialize the editor with a JSON schema
34
               var editor = new JSONEditor(
35
               var editor = new JSONEditor(
35
                 document.getElementById('editor_holder'), {
36
                 document.getElementById('editor_holder'), {
42
               // Hook up the submit button to log to the console
43
               // Hook up the submit button to log to the console
43
               document.getElementById('submit').addEventListener('click',() => {
44
               document.getElementById('submit').addEventListener('click',() => {
44
                 // Get the value from the editor
45
                 // Get the value from the editor
45
-                console.log(editor.getValue());
46
+                fetch("/update", {
47
+                  method: "POST",
48
+                  body: JSON.stringify(editor.getValue()),
49
+                  headers: {
50
+                      "Content-type": "application/json; charset=UTF-8"
51
+                  }
52
+                }).then((response) => { location.replace('/') });
46
               });
53
               });
47
             });
54
             });
48
           });
55
           });

+ 7
- 7
templates/slides.html View File

23
 	</head>
23
 	</head>
24
 	<body>
24
 	<body>
25
                 <div id="custom-nav">
25
                 <div id="custom-nav">
26
-                  <a href="#/" title="Home">
27
                   <!-- the zero-width-space is a tweak against tidy removing empty tags -->
26
                   <!-- the zero-width-space is a tweak against tidy removing empty tags -->
28
-                   <i class="fa fa-home">​</i></a> <a id="top-link" title="Section top"
29
-	                  disabled="disabled"><i class="fa fa-angle-double-up">​</i></a>
27
+                  <a href="#/" title="Home"><i class="fa fa-home">​</i></a>
28
+                  <a id="top-link" title="Section top" disabled="disabled"><i class="fa fa-angle-double-up">​</i></a>
29
+                  <a href="/editor" title="Edit"><i class="fa fa-user-edit">​</i></a>
30
                 </div>
30
                 </div>
31
 		<div class="reveal">
31
 		<div class="reveal">
32
 			<div class="slides">
32
 			<div class="slides">
33
                           {% for column in columns %}
33
                           {% for column in columns %}
34
 				<section{% if column.params %}{% for key, value in column.params|dictsort %} data-{{key}}="{{value}}"{% endfor %}{% endif %}>
34
 				<section{% if column.params %}{% for key, value in column.params|dictsort %} data-{{key}}="{{value}}"{% endfor %}{% endif %}>
35
-                                    <section id="{{column.id|default('home')}}">
35
+                                    <section id="{{column.id}}">
36
                                         {# column's top slide #}
36
                                         {# column's top slide #}
37
                                         <h3 class="title slide_title">{{column.title}}</h3>
37
                                         <h3 class="title slide_title">{{column.title}}</h3>
38
                                         {% if column.content %}{{ column.content|safe }}{% endif %}
38
                                         {% if column.content %}{{ column.content|safe }}{% endif %}
39
-                                        {# Main column (no id) shows links to other columns #}
40
-                                        {% if not column.id %}
39
+                                        {# Main column shows links to other columns #}
40
+                                        {% if loop.first %}
41
                                             <ul>
41
                                             <ul>
42
                                                 {% for other in columns %}
42
                                                 {% for other in columns %}
43
-                                                    {% if other.id %}<li><a href="#/{{other.id}}">{{other.title}}</a></li>{% endif %}
43
+                                                    {% if not loop.first %}<li><a href="#/{{other.id}}">{{other.title}}</a></li>{% endif %}
44
                                                 {% endfor %}
44
                                                 {% endfor %}
45
                                             </ul>
45
                                             </ul>
46
                                         {% endif %}
46
                                         {% endif %}

Loading…
Cancel
Save