From 4041868a9f923c9a46a99fe265808563b42a57c5 Mon Sep 17 00:00:00 2001
From: Sebastian Frank <frank@basiskonfiguration.de>
Date: Mon, 11 Mar 2019 18:56:29 +0100
Subject: [PATCH] collection URL instead of EntriesJSON vi fnRequest

---
 config/tree.go                                | 17 ++---
 helper/content.go                             | 69 ++++++++++++++-----
 helper/template_functions.go                  | 17 +++--
 test.rest                                     |  5 ++
 .../de/01_Navigation/01_mark2web/README.md    |  2 +-
 .../de/01_Navigation/04_Blog/config.yml       |  6 +-
 website/templates/base_blog.html              |  4 +-
 7 files changed, 85 insertions(+), 35 deletions(-)

diff --git a/config/tree.go b/config/tree.go
index fdd0665..4a130f0 100644
--- a/config/tree.go
+++ b/config/tree.go
@@ -54,15 +54,16 @@ func cleanUpMapValue(v interface{}) interface{} {
 // CollectionConfig describes a collection
 type CollectionConfig struct {
 	Name        *string `yaml:"Name"`
-	EntriesJSON *string `yaml:"EntriesJSON"`
+	URL         *string `yaml:"URL"`
 	NavTemplate *struct {
-		GoTo      string `yaml:"GoTo"`
-		Navname   string `yaml:"Navname"`
-		Body      string `yaml:"Body"`
-		DataKey   string `yaml:"DataKey"`
-		Hidden    bool   `yaml:"Hidden"`
-		Template  string `yaml:"Template"`
-		Recursive bool   `yaml:"Recursive"`
+		EntriesAttribute string `yaml:"EntriesAttribute"`
+		GoTo             string `yaml:"GoTo"`
+		Navname          string `yaml:"Navname"`
+		Body             string `yaml:"Body"`
+		DataKey          string `yaml:"DataKey"`
+		Hidden           bool   `yaml:"Hidden"`
+		Template         string `yaml:"Template"`
+		Recursive        bool   `yaml:"Recursive"`
 	} `yaml:"NavTemplate"`
 }
 
diff --git a/helper/content.go b/helper/content.go
index 61423f9..56d6fbc 100644
--- a/helper/content.go
+++ b/helper/content.go
@@ -2,7 +2,6 @@ package helper
 
 import (
 	"bytes"
-	"encoding/json"
 	"io/ioutil"
 	"os"
 	"path"
@@ -100,7 +99,7 @@ func fillNodeConfig(node *config.PathConfigTree, inBase, outBase, dir string, co
 			if colConfig.Name == nil || *colConfig.Name == "" {
 				Log.Panicf("missing Name in collection config in '%s'", inPath)
 			}
-			if colConfig.EntriesJSON == nil || *colConfig.EntriesJSON == "" {
+			if colConfig.URL == nil || *colConfig.URL == "" {
 				Log.Panicf("missing EntriesJSON in collection config in '%s'", inPath)
 			}
 		}
@@ -109,37 +108,73 @@ func fillNodeConfig(node *config.PathConfigTree, inBase, outBase, dir string, co
 			node.ColMap = make(config.MapString)
 		}
 		ctx := newContext()
-		jsonStr, err := pongo2.RenderTemplateString(*colConfig.EntriesJSON, ctx)
+		ctx["This"] = node.Config.This
+		ctx["Data"] = node.Config.Data
+
+		url, err := pongo2.RenderTemplateString(*colConfig.URL, ctx)
 		if err != nil {
-			Log.Panicf("invalid template string in '%s': %s", inPath, err)
+			Log.Panicf("invalid template string for Collection Element.URL in '%s': %s", inPath, err)
 		}
 
-		var colSlice []config.MapString
-		err = json.Unmarshal([]byte(jsonStr), &colSlice)
-		if err != nil {
-			Log.Panicf("invalid JSON in EntriesJSON in '%s': %s", inPath, err)
-		}
-		node.ColMap[*colConfig.Name] = colSlice
-		//node.ColMap[*colConfig.Name] = jsonWebRequest(*colConfig.URL)
+		colData := jsonWebRequest(url)
+		node.ColMap[*colConfig.Name] = colData
 
 		if navT := colConfig.NavTemplate; navT != nil {
-			tpl := navT.Template
-			if tpl == "" {
-				tpl = *newConfig.Template
+			var entries []interface{}
+			var ok bool
+			if navT.EntriesAttribute != "" {
+				var colDataMap map[string]interface{}
+				if colDataMap, ok = colData.(map[string]interface{}); ok {
+					entries, ok = colDataMap[navT.EntriesAttribute].([]interface{})
+					if !ok {
+						Log.Debug(spew.Sdump(colDataMap))
+						Log.Panicf("invalid json data in [%s] from url '%s' for entries", navT.EntriesAttribute, url)
+					}
+				}
+			} else {
+				entries, ok = colData.([]interface{})
+			}
+			if !ok {
+				Log.Debug(spew.Sdump(colData))
+				Log.Panicf("invalid json data from url '%s', need array of objects for entries or object with configured NavTemplate.EntriesAttribute", url)
 			}
 
 			// build navigation with detail sites
-			for _, colEl := range colSlice {
+			for idx, colEl := range entries {
 				ctxE := make(pongo2.Context)
 				err := config.Merge(&ctxE, ctx)
 				if err != nil {
 					Log.Panicf("could not merge context in '%s': %s", inPath, err)
 				}
-				err = config.Merge(&ctxE, pongo2.Context(colEl))
+				var jsonCtx map[string]interface{}
+				if jsonCtx, ok = colEl.(map[string]interface{}); !ok {
+					Log.Debug(spew.Sdump(colEl))
+					Log.Panicf("no json object for entry index %d from url '%s'", idx, url)
+				}
+				err = config.Merge(&ctxE, pongo2.Context(jsonCtx))
 				if err != nil {
 					Log.Panicf("could not merge context in '%s': %s", inPath, err)
 				}
 
+				tpl := ""
+				if navT.Template != "" {
+					tpl, err = pongo2.RenderTemplateString(navT.Template, ctxE)
+					if err != nil {
+						Log.Panicf("invalid template string for NavTemplate.Template in '%s': %s", inPath, err)
+					}
+				}
+				if tpl == "" {
+					tpl = *newConfig.Template
+				}
+
+				dataKey := ""
+				if navT.DataKey != "" {
+					dataKey, err = pongo2.RenderTemplateString(navT.DataKey, ctxE)
+					if err != nil {
+						Log.Panicf("invalid template string for NavTemplate.DataKey in '%s': %s", inPath, err)
+					}
+				}
+
 				goTo, err := pongo2.RenderTemplateString(navT.GoTo, ctxE)
 				if err != nil {
 					Log.Panicf("invalid template string for NavTemplate.GoTo in '%s': %s", inPath, err)
@@ -172,7 +207,7 @@ func fillNodeConfig(node *config.PathConfigTree, inBase, outBase, dir string, co
 					}
 				}
 
-				add2Nav(node, node.Config, tpl, goTo, navname, colEl, navT.DataKey, body, navT.Hidden)
+				add2Nav(node, node.Config, tpl, goTo, navname, colEl, dataKey, body, navT.Hidden)
 			}
 		}
 
diff --git a/helper/template_functions.go b/helper/template_functions.go
index cf4e844..b4fd1d1 100644
--- a/helper/template_functions.go
+++ b/helper/template_functions.go
@@ -10,7 +10,7 @@ import (
 	"github.com/flosch/pongo2"
 )
 
-func jsonWebRequest(url string) config.MapString {
+func jsonWebRequest(url string) interface{} {
 	Log.Noticef("requesting url via GET %s", url)
 
 	resp, err := http.Get(url)
@@ -38,13 +38,20 @@ func jsonWebRequest(url string) config.MapString {
 		Log.Panicf("is not json '%s' from url '%s'", contentType, url)
 	}
 
-	jsonMap := make(config.MapString)
+	jsonMap := make(map[string]interface{})
 	err = json.Unmarshal(body, &jsonMap)
-	if err != nil {
-		Log.Panicf("could not read json from '%s': %s", url, err)
+	if err == nil {
+		return jsonMap
 	}
 
-	return jsonMap
+	jsonArrayMap := make([]map[string]interface{}, 0)
+	err = json.Unmarshal(body, &jsonArrayMap)
+	if err == nil {
+		return jsonArrayMap
+	}
+
+	Log.Panicf("could not read json from '%s': invalid type", url)
+	return nil
 }
 
 // RequestFn will make a web request and returns map[string]interface form pongo2
diff --git a/test.rest b/test.rest
index b04dee0..1e999bc 100644
--- a/test.rest
+++ b/test.rest
@@ -3,6 +3,11 @@ GET https://mark2web.basiscms.de/api/collections/get/mark2webBlog
   &limit=101
   &token=89ff216524093123bf7a0a10f7b273
 
+###
+
+  &filter[link._id]=5c76a0f4643334fe0400039c
+  &filter[published]=true
+
 ###
 
 GET https://mark2web.basiscms.de/api/imagestyles/style/klein
diff --git a/website/content/de/01_Navigation/01_mark2web/README.md b/website/content/de/01_Navigation/01_mark2web/README.md
index bce6b1b..e50cfd7 100644
--- a/website/content/de/01_Navigation/01_mark2web/README.md
+++ b/website/content/de/01_Navigation/01_mark2web/README.md
@@ -63,4 +63,4 @@ Weitere Pakete, die verwendet wurden finden Sie in den Quellen.
 
 Diese Website wurde selbst mit mark2web generiert. Der entsprechende Quellcode, sowie die Quellen zu mark2web finden Sie unter:  
 
-**https://gitbase.de/apairon/mark2web**
\ No newline at end of file
+**[https://gitbase.de/apairon/mark2web](5c76a0f4643334fe0400039c)**
\ No newline at end of file
diff --git a/website/content/de/01_Navigation/04_Blog/config.yml b/website/content/de/01_Navigation/04_Blog/config.yml
index 527d5ae..bcce259 100644
--- a/website/content/de/01_Navigation/04_Blog/config.yml
+++ b/website/content/de/01_Navigation/04_Blog/config.yml
@@ -1,8 +1,9 @@
 This:
   Collections:
     - Name: blog1st
-      EntriesJSON: '{{ fnRequest("https://mark2web.basiscms.de/api/collections/get/mark2webBlog?token=89ff216524093123bf7a0a10f7b273&filter[published]=true&sort[date]=-1&skip=0&limit=1").entries|json }}'
+      URL: 'https://mark2web.basiscms.de/api/collections/get/mark2webBlog?token={{ Data.token }}&filter[published]=true&sort[date]=-1&skip=0&limit=1'
       NavTemplate:
+        EntriesAttribute: entries
         GoTo: '{{ date }}-{{ title }}'
         Navname: '{{ title }}'
         Body: '{{ body }}'
@@ -11,8 +12,9 @@ This:
         Hidden: true # hide from nav, but use this feature for rendering detail sites
 
     - Name: blog1skip
-      EntriesJSON: '{{ fnRequest("https://mark2web.basiscms.de/api/collections/get/mark2webBlog?token=89ff216524093123bf7a0a10f7b273&filter[published]=true&sort[date]=-1&skip=1&limit=100").entries|json }}'
+      URL: 'https://mark2web.basiscms.de/api/collections/get/mark2webBlog?token={{ Data.token }}&filter[published]=true&sort[date]=-1&skip=1&limit=100'
       NavTemplate:
+        EntriesAttribute: entries
         GoTo: '{{ date }}-{{ title }}'
         Navname: '{{ title }}'
         Body: '{{ body }}'
diff --git a/website/templates/base_blog.html b/website/templates/base_blog.html
index 4d6de88..2cd49f0 100644
--- a/website/templates/base_blog.html
+++ b/website/templates/base_blog.html
@@ -2,7 +2,7 @@
 
 {% block part0 %}
     {{ Body }}
-    {% for e in NavElement.ColMap.blog1st %}
+    {% for e in NavElement.ColMap.blog1st.entries %}
         <h2>
             {{ e.title }}
             <div class="datum">{{ e.date|datum }}</div>
@@ -18,7 +18,7 @@
     {% comment %}
         limit wird für skip in Query gebraucht
     {% endcomment %}
-    {% for e in NavElement.ColMap.blog1skip %}
+    {% for e in NavElement.ColMap.blog1skip.entries %}
         <h2>
             {{ e.title }}
             <div class="datum">{{ e.date|datum }}</div>