From 26cd05e0582a1eec403936fc003569dca4978169 Mon Sep 17 00:00:00 2001 From: Renato Oliveira Date: Sat, 20 Jun 2020 08:58:55 -0300 Subject: [PATCH 1/6] Adds basic website generator (WIP). --- .gitignore | 1 + Pipfile | 15 +++ Pipfile.lock | 107 ++++++++++++++++++ content/posts/2020/demo.yaml | 0 content/projects.yaml | 22 ++++ images/icon.png | Bin 0 -> 14595 bytes index.html | 52 +++++---- makefile | 2 + ...larative-rollup-summaries-for-lookups.html | 99 ++++++++++++++++ .../dogeforce-s-website-this-site.html | 98 ++++++++++++++++ pages/projects/mass-action-scheduler.html | 98 ++++++++++++++++ src/scripts/main.py | 51 +++++++++ src/templates/base.html | 27 +++++ src/templates/footer.html | 19 ++++ src/templates/header.html | 29 +++++ src/templates/post.html | 0 src/templates/project.html | 38 +++++++ src/templates/repositorylist.html | 7 ++ 18 files changed, 645 insertions(+), 20 deletions(-) create mode 100644 .gitignore create mode 100644 Pipfile create mode 100644 Pipfile.lock create mode 100644 content/posts/2020/demo.yaml create mode 100644 content/projects.yaml create mode 100644 images/icon.png create mode 100644 makefile create mode 100644 pages/projects/declarative-rollup-summaries-for-lookups.html create mode 100644 pages/projects/dogeforce-s-website-this-site.html create mode 100644 pages/projects/mass-action-scheduler.html create mode 100644 src/scripts/main.py create mode 100644 src/templates/base.html create mode 100644 src/templates/footer.html create mode 100644 src/templates/header.html create mode 100644 src/templates/post.html create mode 100644 src/templates/project.html create mode 100644 src/templates/repositorylist.html diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..496ee2c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..e014c9c --- /dev/null +++ b/Pipfile @@ -0,0 +1,15 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +markdown2 = "*" +jinja2 = "*" +pyyaml = "*" +python-slugify = "*" + +[requires] +python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..1d9c9e3 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,107 @@ +{ + "_meta": { + "hash": { + "sha256": "ddd49b79d5101a7e5acc3a5dbf516008a553d9c82b4286d8ee1ae193cc01f26f" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.8" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "jinja2": { + "hashes": [ + "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", + "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" + ], + "index": "pypi", + "version": "==2.11.2" + }, + "markdown2": { + "hashes": [ + "sha256:89526090907ae5ece66d783c434b35c29ee500c1986309e306ce2346273ada6a", + "sha256:e6b401ec80b75e76a6b3dbb2c8ade513156fa55fa6c30b9640a1abf6184a07c8" + ], + "index": "pypi", + "version": "==2.3.9" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.1" + }, + "python-slugify": { + "hashes": [ + "sha256:a8fc3433821140e8f409a9831d13ae5deccd0b033d4744d94b31fea141bdd84c" + ], + "index": "pypi", + "version": "==4.0.0" + }, + "pyyaml": { + "hashes": [ + "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97", + "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76", + "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2", + "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648", + "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf", + "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f", + "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2", + "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee", + "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d", + "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c", + "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a" + ], + "index": "pypi", + "version": "==5.3.1" + }, + "text-unidecode": { + "hashes": [ + "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", + "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93" + ], + "version": "==1.3" + } + }, + "develop": {} +} diff --git a/content/posts/2020/demo.yaml b/content/posts/2020/demo.yaml new file mode 100644 index 0000000..e69de29 diff --git a/content/projects.yaml b/content/projects.yaml new file mode 100644 index 0000000..7c45ecb --- /dev/null +++ b/content/projects.yaml @@ -0,0 +1,22 @@ +# Each project should have the following format: +# +# title: Project's Title +# location: github +# url: github.com/repos/url + +projects: + - + title: Declarative Rollup Summaries for Lookups + location: github + url: https://github.com/afawcett/declarative-lookup-rollup-summaries/ + description: |- + This is a long text that should be properly escaped, + even though it has many lines! + - + title: Mass Action Scheduler + location: github + url: https://github.com/douglascayers-org/sfdx-mass-action-scheduler + - + title: Dogeforce's Website (this site!) + location: github + url: https://github.com/Dogeforce/dogeforce.github.io/ diff --git a/images/icon.png b/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e84157f6437dfd23fce5729e20dc0000681e4d40 GIT binary patch literal 14595 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 literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 55b27a0..8a34a37 100644 --- a/index.html +++ b/index.html @@ -1,11 +1,14 @@ + + The Dogeforce Project + - +
@@ -13,9 +16,11 @@

- + +

+

+ Dogeforce

-

Dogeforce

@@ -27,27 +32,31 @@ -
+
-
-
    -
  1. -

    Page A

    -
  2. -
  3. -

    Page B

    -
  4. -
  5. -

    Page C

    -
  6. -
+ -
+

Content goes here...

@@ -60,7 +69,10 @@
-

Copyright® Dogeforce Project Collaborators

+

+ Copyright® Dogeforce Project Collaborators + @ +

@@ -69,7 +81,7 @@
-
- +
+ \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..257353f --- /dev/null +++ b/makefile @@ -0,0 +1,2 @@ +build: + python src/scripts/main.py > index.html diff --git a/pages/projects/declarative-rollup-summaries-for-lookups.html b/pages/projects/declarative-rollup-summaries-for-lookups.html new file mode 100644 index 0000000..433c6fd --- /dev/null +++ b/pages/projects/declarative-rollup-summaries-for-lookups.html @@ -0,0 +1,99 @@ + + + + + + + + The Dogeforce Project + + + + + +
+
+
+
+

+ +

+

+ Dogeforce +

+
+
+
+ +
+
+
+ + + + +
+ +
+ + + + + +
+ + +
+

Declarative Rollup Summaries for Lookups

+ +

Website: https://github.com/afawcett/declarative-lookup-rollup-summaries/

+ +

This is a long text that should be properly escaped, +even though it has many lines!

+
+ + + +
+
+ +
+ + + +
+
+
+
+

+ Copyright® Dogeforce Project Collaborators + @ 2020-06-19 +

+
+
+ +
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/pages/projects/dogeforce-s-website-this-site.html b/pages/projects/dogeforce-s-website-this-site.html new file mode 100644 index 0000000..c039223 --- /dev/null +++ b/pages/projects/dogeforce-s-website-this-site.html @@ -0,0 +1,98 @@ + + + + + + + + The Dogeforce Project + + + + + +
+
+
+
+

+ +

+

+ Dogeforce +

+
+
+
+ +
+
+
+ + + + +
+ +
+ + + + + +
+ + +
+

Dogeforce's Website (this site!)

+ +

Website: https://github.com/Dogeforce/dogeforce.github.io/

+ +

+
+ + + +
+
+ +
+ + + +
+
+
+
+

+ Copyright® Dogeforce Project Collaborators + @ 2020-06-19 +

+
+
+ +
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/pages/projects/mass-action-scheduler.html b/pages/projects/mass-action-scheduler.html new file mode 100644 index 0000000..7807d6c --- /dev/null +++ b/pages/projects/mass-action-scheduler.html @@ -0,0 +1,98 @@ + + + + + + + + The Dogeforce Project + + + + + +
+
+
+
+

+ +

+

+ Dogeforce +

+
+
+
+ +
+
+
+ + + + +
+ +
+ + + + + +
+ + +
+

Mass Action Scheduler

+ +

Website: https://github.com/douglascayers-org/sfdx-mass-action-scheduler

+ +

+
+ + + +
+
+ +
+ + + +
+
+
+
+

+ Copyright® Dogeforce Project Collaborators + @ 2020-06-19 +

+
+
+ +
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/src/scripts/main.py b/src/scripts/main.py new file mode 100644 index 0000000..4b4a346 --- /dev/null +++ b/src/scripts/main.py @@ -0,0 +1,51 @@ +import yaml +from slugify import slugify +from markdown2 import markdown +from jinja2 import Environment, FileSystemLoader +from datetime import datetime + +def slugify_url(item): + item['slug'] = slugify(item['title']) + return item + +env = Environment(loader=FileSystemLoader(searchpath='src/templates')) + +test_template = env.get_template('base.html') + +content = yaml.load(open('content/projects.yaml').read(), Loader=yaml.SafeLoader) +# posts = yaml.load(open('content/posts.yaml').read(), Loader=yaml.SafeLoader) + +content['projects'] = [slugify_url(x) for x in content['projects']] + +project_page_template = env.get_template('project.html') +post_page_template = env.get_template('post.html') +repositories = env.get_template('repositorylist.html').render(items=content['projects']) + +# for post in content['posts']: +# with open('pages/posts/{}.html'.format(post['slug']), 'w') as page: +# post['repositories'] = repositories +# page.write(post_page_template.render( +# detail=post +# )) + +today = datetime.today().date().isoformat() + +for project in content['projects']: + with open('pages/projects/{}.html'.format(project['slug']), 'w') as page: + project['repositories'] = repositories + project_page_render = project_page_template.render( + detail=project, + build_date=today + ) + # print(project['description'].replace('\n', '
') if 'description' in project else '') + page.write(project_page_render) + page.close() + +r = test_template.render(page={ + 'content': 'Hello world', + 'repositories': repositories, + 'build_date': today +}) + +with open('index.html', 'w') as index_file: + index_file.write(r) diff --git a/src/templates/base.html b/src/templates/base.html new file mode 100644 index 0000000..876800a --- /dev/null +++ b/src/templates/base.html @@ -0,0 +1,27 @@ + + + + {% include 'header.html' %} + + +
+ +
+ + +
+ {{ page.repositories }} +
+ + +
+

Content goes here...

+
+
+ +
+ + +{% include 'footer.html' %} + + diff --git a/src/templates/footer.html b/src/templates/footer.html new file mode 100644 index 0000000..06ab60a --- /dev/null +++ b/src/templates/footer.html @@ -0,0 +1,19 @@ + +
+
+
+
+

+ Copyright® Dogeforce Project Collaborators + @ {{ build_date }} +

+
+
+ +
+
+ +
+
+
+
\ No newline at end of file diff --git a/src/templates/header.html b/src/templates/header.html new file mode 100644 index 0000000..9f61168 --- /dev/null +++ b/src/templates/header.html @@ -0,0 +1,29 @@ + + + + + The Dogeforce Project + + + + + +
+
+
+
+

+ +

+

+ Dogeforce +

+
+
+
+ +
+
+
+ + \ No newline at end of file diff --git a/src/templates/post.html b/src/templates/post.html new file mode 100644 index 0000000..e69de29 diff --git a/src/templates/project.html b/src/templates/project.html new file mode 100644 index 0000000..c14ac1e --- /dev/null +++ b/src/templates/project.html @@ -0,0 +1,38 @@ + + + + {% include 'header.html' %} + + +
+ +
+ + +
+ {{ detail.repositories }} +
+ + +
+ + {% block content %} +
+

{{ detail.title }}

+ +

Website: {{ detail.url }}

+ +

{{ detail.description }}

+
+ + {% endblock %} + +
+
+ +
+ + +{% include 'footer.html' %} + + diff --git a/src/templates/repositorylist.html b/src/templates/repositorylist.html new file mode 100644 index 0000000..00818c9 --- /dev/null +++ b/src/templates/repositorylist.html @@ -0,0 +1,7 @@ + \ No newline at end of file From 8aed09ad6a3a2ce53b1984fd32a4c7e24f119902 Mon Sep 17 00:00:00 2001 From: Renato Oliveira Date: Sat, 20 Jun 2020 09:35:16 -0300 Subject: [PATCH 2/6] Adopt template extension and inclusion. --- content/posts/2020-06-20-a-demo.html | 19 ++++++++ content/posts/2020/demo.yaml | 0 content/source/posts/2020-06-20-a-demo.md | 14 ++++++ index.html | 15 ++++-- ...larative-rollup-summaries-for-lookups.html | 17 +++---- .../dogeforce-s-website-this-site.html | 17 +++---- pages/projects/mass-action-scheduler.html | 17 +++---- src/scripts/main.py | 21 ++++++--- src/templates/base.html | 8 ++-- src/templates/home.html | 11 +++++ src/templates/post.html | 3 ++ src/templates/project.html | 46 +++++-------------- 12 files changed, 117 insertions(+), 71 deletions(-) create mode 100644 content/posts/2020-06-20-a-demo.html delete mode 100644 content/posts/2020/demo.yaml create mode 100644 content/source/posts/2020-06-20-a-demo.md create mode 100644 src/templates/home.html diff --git a/content/posts/2020-06-20-a-demo.html b/content/posts/2020-06-20-a-demo.html new file mode 100644 index 0000000..15a1f5d --- /dev/null +++ b/content/posts/2020-06-20-a-demo.html @@ -0,0 +1,19 @@ +
+

The DLRS (Declarative Lookup Rollup Summaries) tool

+ +

Use cases

+ +
    +
  • Can't use native rollup summaries.
  • +
  • Job needs to be done by an administrator.
  • +
+ +

Considerations

+ +

The tool has gone through a big migration in the past. It used to use custom settings for managing rollups, but since Salesforce introduced Custom Metadata Types, the tool uses them.

+ +

Repository

+ +

The source code can be found on GitHub.

+ +
\ No newline at end of file diff --git a/content/posts/2020/demo.yaml b/content/posts/2020/demo.yaml deleted file mode 100644 index e69de29..0000000 diff --git a/content/source/posts/2020-06-20-a-demo.md b/content/source/posts/2020-06-20-a-demo.md new file mode 100644 index 0000000..e7966d9 --- /dev/null +++ b/content/source/posts/2020-06-20-a-demo.md @@ -0,0 +1,14 @@ +# The DLRS (Declarative Lookup Rollup Summaries) tool + +## Use cases + +* Can't use native rollup summaries. +* Job needs to be done by an administrator. + +## Considerations + +The tool has gone through a big migration in the past. It used to use custom settings for managing rollups, but since Salesforce introduced Custom Metadata Types, the tool uses them. + +## Repository + +The source code can be found [on GitHub](https://github.com/afawcett/declarative-lookup-rollup-summaries/). diff --git a/index.html b/index.html index 8a34a37..9a3545d 100644 --- a/index.html +++ b/index.html @@ -38,7 +38,8 @@
-
-
-

Content goes here...

+
+ + + + +

Posts go here!

+ + +
diff --git a/pages/projects/declarative-rollup-summaries-for-lookups.html b/pages/projects/declarative-rollup-summaries-for-lookups.html index 433c6fd..0524079 100644 --- a/pages/projects/declarative-rollup-summaries-for-lookups.html +++ b/pages/projects/declarative-rollup-summaries-for-lookups.html @@ -38,7 +38,8 @@
-
-
-

Declarative Rollup Summaries for Lookups

+
+

Declarative Rollup Summaries for Lookups

-

Website: https://github.com/afawcett/declarative-lookup-rollup-summaries/

+

Website: https://github.com/afawcett/declarative-lookup-rollup-summaries/

-

This is a long text that should be properly escaped, +

This is a long text that should be properly escaped, even though it has many lines!

-
+
-
@@ -83,7 +84,7 @@

Copyright® Dogeforce Project Collaborators - @ 2020-06-19 + @ 2020-06-20

diff --git a/pages/projects/dogeforce-s-website-this-site.html b/pages/projects/dogeforce-s-website-this-site.html index c039223..0bc33b3 100644 --- a/pages/projects/dogeforce-s-website-this-site.html +++ b/pages/projects/dogeforce-s-website-this-site.html @@ -38,7 +38,8 @@
-
-
-

Dogeforce's Website (this site!)

+ +

+
-
@@ -82,7 +83,7 @@

Copyright® Dogeforce Project Collaborators - @ 2020-06-19 + @ 2020-06-20

diff --git a/pages/projects/mass-action-scheduler.html b/pages/projects/mass-action-scheduler.html index 7807d6c..91642b4 100644 --- a/pages/projects/mass-action-scheduler.html +++ b/pages/projects/mass-action-scheduler.html @@ -38,7 +38,8 @@
-
- -
@@ -82,7 +83,7 @@

Copyright® Dogeforce Project Collaborators - @ 2020-06-19 + @ 2020-06-20

diff --git a/src/scripts/main.py b/src/scripts/main.py index 4b4a346..9d4a96b 100644 --- a/src/scripts/main.py +++ b/src/scripts/main.py @@ -10,7 +10,7 @@ def slugify_url(item): env = Environment(loader=FileSystemLoader(searchpath='src/templates')) -test_template = env.get_template('base.html') +home_template = env.get_template('home.html') content = yaml.load(open('content/projects.yaml').read(), Loader=yaml.SafeLoader) # posts = yaml.load(open('content/posts.yaml').read(), Loader=yaml.SafeLoader) @@ -28,22 +28,31 @@ def slugify_url(item): # detail=post # )) +with open('content/source/posts/2020-06-20-a-demo.md', 'r') as post: + with open('content/posts/2020-06-20-a-demo.html', 'w') as rendered_post: + render = post_page_template.render( + content={ + 'text': markdown(post.read()) + } + ) + rendered_post.write(render) + rendered_post.close() + post.close() + today = datetime.today().date().isoformat() for project in content['projects']: with open('pages/projects/{}.html'.format(project['slug']), 'w') as page: - project['repositories'] = repositories + project['sidebar'] = repositories project_page_render = project_page_template.render( detail=project, build_date=today ) - # print(project['description'].replace('\n', '
') if 'description' in project else '') page.write(project_page_render) page.close() -r = test_template.render(page={ - 'content': 'Hello world', - 'repositories': repositories, +r = home_template.render(page={ + 'sidebar': repositories, 'build_date': today }) diff --git a/src/templates/base.html b/src/templates/base.html index 876800a..e2d702a 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -10,12 +10,14 @@
- {{ page.repositories }} + {% block sidebar %} {% endblock %}
-
-

Content goes here...

+
+ + {% block content %} {% endblock %} +
diff --git a/src/templates/home.html b/src/templates/home.html new file mode 100644 index 0000000..7b9e304 --- /dev/null +++ b/src/templates/home.html @@ -0,0 +1,11 @@ +{% extends 'base.html' %} +{% block sidebar %} + {{ page.sidebar }} +{% endblock %} + +{% block content %} + + +

Posts go here!

+ +{% endblock %} diff --git a/src/templates/post.html b/src/templates/post.html index e69de29..3031e98 100644 --- a/src/templates/post.html +++ b/src/templates/post.html @@ -0,0 +1,3 @@ +
+ {{ content.text }} +
\ No newline at end of file diff --git a/src/templates/project.html b/src/templates/project.html index c14ac1e..d9a4822 100644 --- a/src/templates/project.html +++ b/src/templates/project.html @@ -1,38 +1,14 @@ - - +{% extends 'base.html' %} +{% block sidebar %} + {{ detail.sidebar }} +{% endblock %} - {% include 'header.html' %} +{% block content %} +
+

{{ detail.title }}

- -
+

Website: {{ detail.url }}

-
- - -
- {{ detail.repositories }} -
- - -
- - {% block content %} -
-

{{ detail.title }}

- -

Website: {{ detail.url }}

- -

{{ detail.description }}

-
- - {% endblock %} - -
-
- -
- - -{% include 'footer.html' %} - - +

{{ detail.description }}

+
+{% endblock %} From 8c774483403cd2aaf11183ce61dab5879f2b9bdf Mon Sep 17 00:00:00 2001 From: Renato Oliveira Date: Sat, 20 Jun 2020 19:00:26 -0300 Subject: [PATCH 3/6] Greatly improves rendering for project description pages. Also adds images to the description of the site. --- Pipfile | 1 + Pipfile.lock | 10 +- content/projects.yaml | 6 +- content/source/posts/2020-06-20-a-demo.md | 11 ++ content/source/projects/dlrs.md | 13 +++ content/source/projects/dogeforce.md | 15 +++ content/source/projects/mas.md | 7 ++ images/no_logs_no_crime.jpg | Bin 0 -> 77160 bytes images/sticker_on_laptop.jpg | Bin 0 -> 43159 bytes index.html | 24 ++-- .../2020-06-20-a-demo.html | 44 ++++--- ...larative-rollup-summaries-for-lookups.html | 109 ++++++++++++++++++ .../dogeforce-s-website-this-site.html | 35 ++++-- .../mass-action-scheduler.html | 33 ++++-- src/scripts/main.py | 24 ++-- src/scripts/md2lds.py | 27 +++++ src/templates/base.html | 2 +- src/templates/footer.html | 12 +- src/templates/header.html | 2 +- src/templates/home.html | 2 +- src/templates/post.html | 13 ++- src/templates/project.html | 6 +- src/templates/repositorylist.html | 2 +- 23 files changed, 321 insertions(+), 77 deletions(-) create mode 100644 content/source/projects/dlrs.md create mode 100644 content/source/projects/dogeforce.md create mode 100644 content/source/projects/mas.md create mode 100644 images/no_logs_no_crime.jpg create mode 100644 images/sticker_on_laptop.jpg rename pages/projects/declarative-rollup-summaries-for-lookups.html => posts/2020-06-20-a-demo.html (53%) create mode 100644 projects/declarative-rollup-summaries-for-lookups.html rename {pages/projects => projects}/dogeforce-s-website-this-site.html (52%) rename {pages/projects => projects}/mass-action-scheduler.html (62%) create mode 100644 src/scripts/md2lds.py diff --git a/Pipfile b/Pipfile index e014c9c..92cbfc1 100644 --- a/Pipfile +++ b/Pipfile @@ -10,6 +10,7 @@ markdown2 = "*" jinja2 = "*" pyyaml = "*" python-slugify = "*" +markdown = "*" [requires] python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock index 1d9c9e3..4254227 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "ddd49b79d5101a7e5acc3a5dbf516008a553d9c82b4286d8ee1ae193cc01f26f" + "sha256": "719ef99c515ec3308012eb136b0bfb0c444e2cefcd3f82d73a5ef4a223bb19f5" }, "pipfile-spec": 6, "requires": { @@ -24,6 +24,14 @@ "index": "pypi", "version": "==2.11.2" }, + "markdown": { + "hashes": [ + "sha256:1fafe3f1ecabfb514a5285fca634a53c1b32a81cb0feb154264d55bf2ff22c17", + "sha256:c467cd6233885534bf0fe96e62e3cf46cfc1605112356c4f9981512b8174de59" + ], + "index": "pypi", + "version": "==3.2.2" + }, "markdown2": { "hashes": [ "sha256:89526090907ae5ece66d783c434b35c29ee500c1986309e306ce2346273ada6a", diff --git a/content/projects.yaml b/content/projects.yaml index 7c45ecb..c5020a5 100644 --- a/content/projects.yaml +++ b/content/projects.yaml @@ -7,16 +7,16 @@ projects: - title: Declarative Rollup Summaries for Lookups + description: dlrs.md location: github url: https://github.com/afawcett/declarative-lookup-rollup-summaries/ - description: |- - This is a long text that should be properly escaped, - even though it has many lines! - title: Mass Action Scheduler + description: mas.md location: github url: https://github.com/douglascayers-org/sfdx-mass-action-scheduler - title: Dogeforce's Website (this site!) + description: dogeforce.md location: github url: https://github.com/Dogeforce/dogeforce.github.io/ diff --git a/content/source/posts/2020-06-20-a-demo.md b/content/source/posts/2020-06-20-a-demo.md index e7966d9..df4e443 100644 --- a/content/source/posts/2020-06-20-a-demo.md +++ b/content/source/posts/2020-06-20-a-demo.md @@ -9,6 +9,17 @@ The tool has gone through a big migration in the past. It used to use custom settings for managing rollups, but since Salesforce introduced Custom Metadata Types, the tool uses them. +This is a second paragraph. + ## Repository The source code can be found [on GitHub](https://github.com/afawcett/declarative-lookup-rollup-summaries/). + +### Footnotes + +Lorem ipsum! + + +``` +this is some code +``` \ No newline at end of file diff --git a/content/source/projects/dlrs.md b/content/source/projects/dlrs.md new file mode 100644 index 0000000..ef0a637 --- /dev/null +++ b/content/source/projects/dlrs.md @@ -0,0 +1,13 @@ +## About the tool + +The DLRS is a tool that offers a feature set that extends a feature called "rollup summaries" on the Salesforce platform. It deploys Apex code to your organization and enables administrators to deploy automatically generated code to the org (even a production environment, yes). + +The tool code operates using custom metadata records managed by a Visualforce page on the project. From there an administrator or a developer can create custom metadata records for the tool to use when running its triggers (the code deployed which was mentioned before). + +When a record with a DLRS trigger is saved, it activates the DLRS tool which then gets the custom setting for the specific object. Then it queries the object and its related record(s) to update its rollup summary. + +### Example + +A rollup is created on Custom Object A (`CustomObjectA__c`) to count how many Custom Object B's (`CustomObjectB__c`) records are related to it through a common lookup field (not a master-detail relationship, that is). + +When a new object B is created, updated or deleted, the tool analyzes the criteria defined on its custom setting (the custom metadata type) and evaluates whether or not to update the counter on the parent (object A) field. diff --git a/content/source/projects/dogeforce.md b/content/source/projects/dogeforce.md new file mode 100644 index 0000000..7ad4e20 --- /dev/null +++ b/content/source/projects/dogeforce.md @@ -0,0 +1,15 @@ +## About this site + +This is an open-source website with the goal to aggregate Salesforce resources such as open source projects (like the DLRS or the Mass Action Scheduler) and comment about them, talk about their use cases, but mostly because the creator had too much free time on a weekend. + +You can check out the source code at the github repository in the link above. This website is hosted at GitHub as well. It's source is generated by a Python script that gathers the sources from many folders and "compiles" them to HTML which is then served by GitHub. The script is also custom made too (which is why it might look a little too ugly - *PR's are welcome*). + +### The Doge logo + +This amazing image was made by a member of the Salesforce Discord Exchange (SFXD). Even stickers were made of it: + +![](/images/no_logs_no_crime.jpg) + +Can you imagine being at a meeting with this guy looking at ya? + +![](/images/sticker_on_laptop.jpg) diff --git a/content/source/projects/mas.md b/content/source/projects/mas.md new file mode 100644 index 0000000..333f7eb --- /dev/null +++ b/content/source/projects/mas.md @@ -0,0 +1,7 @@ +## A quote from the project itself: + +>Mass Action Scheduler is a free-as-in-speech and open source developed passion project of Doug Ayers. + +And its goal is to give administrators the power to use Batch Apex's power, which is mostly in the hands of developers. + +With this tool an administrator can declaratively schedule a series of process automations (such as email alerts, workflow rules and flows). diff --git a/images/no_logs_no_crime.jpg b/images/no_logs_no_crime.jpg new file mode 100644 index 0000000000000000000000000000000000000000..616d9a4354c73070207fc94af16d491a7b542486 GIT binary patch literal 77160 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 literal 0 HcmV?d00001 diff --git a/images/sticker_on_laptop.jpg b/images/sticker_on_laptop.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ac55357c7db3651f117f709d94b998bfbebc1497 GIT binary patch literal 43159 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 CvbeJV literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 9a3545d..01c8a05 100644 --- a/index.html +++ b/index.html @@ -1,7 +1,7 @@ - + @@ -32,7 +32,7 @@ -
+
@@ -42,15 +42,15 @@ @@ -63,7 +63,7 @@ -

Posts go here!

+

Recent posts go here!

@@ -78,13 +78,15 @@
-

- Copyright® Dogeforce Project Collaborators - @ -

+
- +
+

+ Copyright® Dogeforce Project Collaborators + @ +

+
diff --git a/pages/projects/declarative-rollup-summaries-for-lookups.html b/posts/2020-06-20-a-demo.html similarity index 53% rename from pages/projects/declarative-rollup-summaries-for-lookups.html rename to posts/2020-06-20-a-demo.html index 0524079..e3e5cea 100644 --- a/pages/projects/declarative-rollup-summaries-for-lookups.html +++ b/posts/2020-06-20-a-demo.html @@ -1,7 +1,7 @@ - + @@ -32,7 +32,7 @@ -
+
@@ -42,15 +42,15 @@ @@ -61,16 +61,26 @@
-
-

Declarative Rollup Summaries for Lookups

- -

Website: https://github.com/afawcett/declarative-lookup-rollup-summaries/

-

This is a long text that should be properly escaped, -even though it has many lines!

+
+

The DLRS (Declarative Lookup Rollup Summaries) tool

+

Use cases

+
    +
  • Can't use native rollup summaries.
  • +
  • Job needs to be done by an administrator.
  • +
+

Considerations

+

The tool has gone through a big migration in the past. It used to use custom settings for managing rollups, but since Salesforce introduced Custom Metadata Types, the tool uses them.

+

This is a second paragraph.

+

Repository

+

The source code can be found on GitHub.

+

Footnotes

+

Lorem ipsum!

+

this is some code

+
@@ -82,13 +92,15 @@
-

- Copyright® Dogeforce Project Collaborators - @ 2020-06-20 -

+
- +
+

+ Copyright® Dogeforce Project Collaborators + @ 2020-06-20 +

+
diff --git a/projects/declarative-rollup-summaries-for-lookups.html b/projects/declarative-rollup-summaries-for-lookups.html new file mode 100644 index 0000000..952b79a --- /dev/null +++ b/projects/declarative-rollup-summaries-for-lookups.html @@ -0,0 +1,109 @@ + + + + + + + + The Dogeforce Project + + + + + +
+
+
+
+

+ +

+

+ Dogeforce +

+
+
+
+ +
+
+
+ + + + +
+ +
+ + + + + +
+ + +
+

Declarative Rollup Summaries for Lookups

+ +

Website: https://github.com/afawcett/declarative-lookup-rollup-summaries/

+ +
+

About the tool

+

The DLRS is a tool that offers a feature set that extends a feature called "rollup summaries" on the Salesforce platform. It deploys Apex code to your organization and enables administrators to deploy automatically generated code to the org (even a production environment, yes).

+

The tool code operates using custom metadata records managed by a Visualforce page on the project. From there an administrator or a developer can create custom metadata records for the tool to use when running its triggers (the code deployed which was mentioned before).

+

When a record with a DLRS trigger is saved, it activates the DLRS tool which then gets the custom setting for the specific object. Then it queries the object and its related record(s) to update its rollup summary.

+

Example

+

A rollup is created on Custom Object A (CustomObjectA__c) to count how many Custom Object B's (CustomObjectB__c) records are related to it through a common lookup field (not a master-detail relationship, that is).

+

When a new object B is created, updated or deleted, the tool analyzes the criteria defined on its custom setting (the custom metadata type) and evaluates whether or not to update the counter on the parent (object A) field.

+
+
+ + +
+
+ +
+ + + +
+
+
+
+ +
+
+
+

+ Copyright® Dogeforce Project Collaborators + @ 2020-06-20 +

+
+
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/pages/projects/dogeforce-s-website-this-site.html b/projects/dogeforce-s-website-this-site.html similarity index 52% rename from pages/projects/dogeforce-s-website-this-site.html rename to projects/dogeforce-s-website-this-site.html index 0bc33b3..e36b85e 100644 --- a/pages/projects/dogeforce-s-website-this-site.html +++ b/projects/dogeforce-s-website-this-site.html @@ -1,7 +1,7 @@ - + @@ -32,7 +32,7 @@ -
+
@@ -42,15 +42,15 @@ @@ -62,11 +62,20 @@
-

Dogeforce's Website (this site!)

+

Dogeforce's Website (this site!)

Website: https://github.com/Dogeforce/dogeforce.github.io/

-

+
+

About this site

+

This is an open-source website with the goal to aggregate Salesforce resources such as open source projects (like the DLRS or the Mass Action Scheduler) and comment about them, talk about their use cases, but mostly because the creator had too much free time on a weekend.

+

You can check out the source code at the github repository in the link above. This website is hosted at GitHub as well. It's source is generated by a Python script that gathers the sources from many folders and "compiles" them to HTML which is then served by GitHub. The script is also custom made too (which is why it might look a little too ugly - PR's are welcome).

+

The Doge logo

+

This amazing image was made by a member of the Salesforce Discord Exchange (SFXD). Even stickers were made of it:

+

+

Can you imagine being at a meeting with this guy looking at ya?

+

+
@@ -81,13 +90,15 @@
-

- Copyright® Dogeforce Project Collaborators - @ 2020-06-20 -

+
- +
+

+ Copyright® Dogeforce Project Collaborators + @ 2020-06-20 +

+
diff --git a/pages/projects/mass-action-scheduler.html b/projects/mass-action-scheduler.html similarity index 62% rename from pages/projects/mass-action-scheduler.html rename to projects/mass-action-scheduler.html index 91642b4..1309205 100644 --- a/pages/projects/mass-action-scheduler.html +++ b/projects/mass-action-scheduler.html @@ -1,7 +1,7 @@ - + @@ -32,7 +32,7 @@ -
+
@@ -42,15 +42,15 @@ @@ -62,11 +62,18 @@
-

Mass Action Scheduler

+

Mass Action Scheduler

Website: https://github.com/douglascayers-org/sfdx-mass-action-scheduler

-

+
+

A quote from the project itself:

+
+

Mass Action Scheduler is a free-as-in-speech and open source developed passion project of Doug Ayers.

+
+

And its goal is to give administrators the power to use Batch Apex's power, which is mostly in the hands of developers.

+

With this tool an administrator can declaratively schedule a series of process automations (such as email alerts, workflow rules and flows).

+
@@ -81,13 +88,15 @@
-

- Copyright® Dogeforce Project Collaborators - @ 2020-06-20 -

+
- +
+

+ Copyright® Dogeforce Project Collaborators + @ 2020-06-20 +

+
diff --git a/src/scripts/main.py b/src/scripts/main.py index 9d4a96b..3d69a43 100644 --- a/src/scripts/main.py +++ b/src/scripts/main.py @@ -1,13 +1,15 @@ import yaml from slugify import slugify -from markdown2 import markdown +from markdown import markdown as md from jinja2 import Environment, FileSystemLoader from datetime import datetime +from md2lds import Md2Lds def slugify_url(item): item['slug'] = slugify(item['title']) return item +TODAY = datetime.today().date().isoformat() env = Environment(loader=FileSystemLoader(searchpath='src/templates')) home_template = env.get_template('home.html') @@ -29,31 +31,35 @@ def slugify_url(item): # )) with open('content/source/posts/2020-06-20-a-demo.md', 'r') as post: - with open('content/posts/2020-06-20-a-demo.html', 'w') as rendered_post: + with open('posts/2020-06-20-a-demo.html', 'w') as rendered_post: render = post_page_template.render( + sidebar=repositories, content={ - 'text': markdown(post.read()) - } + 'text': md(post.read(), extensions=[Md2Lds()]) + }, + build_date=TODAY ) rendered_post.write(render) rendered_post.close() post.close() -today = datetime.today().date().isoformat() - for project in content['projects']: - with open('pages/projects/{}.html'.format(project['slug']), 'w') as page: + with open('projects/{}.html'.format(project['slug']), 'w') as page: + with open('content/source/projects/{}'.format(project['description'])) as project_md: + project['description'] = md(project_md.read(), extensions=[Md2Lds()]) + project_md.close() + project['sidebar'] = repositories project_page_render = project_page_template.render( detail=project, - build_date=today + build_date=TODAY ) page.write(project_page_render) page.close() r = home_template.render(page={ 'sidebar': repositories, - 'build_date': today + 'build_date': TODAY }) with open('index.html', 'w') as index_file: diff --git a/src/scripts/md2lds.py b/src/scripts/md2lds.py new file mode 100644 index 0000000..98b90d8 --- /dev/null +++ b/src/scripts/md2lds.py @@ -0,0 +1,27 @@ +from markdown.extensions import Extension +from markdown.treeprocessors import Treeprocessor + + +class LDSProcessor(Treeprocessor): + + def run(self, root): + for child in root: + self._apply(child) + + def _apply(self, el): + if el.tag == 'h1': + el.set('class', 'slds-text-heading_large slds-m-bottom_medium slds-m-top_medium') + elif el.tag == 'h2': + el.set('class', 'slds-text-heading_medium slds-m-bottom_medium slds-m-top_medium') + elif el.tag == 'h3': + el.set('class', 'slds-text-heading_small slds-m-bottom_medium slds-m-top_medium') + elif el.tag == 'p': + el.set('class', 'slds-m-bottom_medium') + elif el.tag == 'blockquote': + el.set('class', 'slds-border_left slds-p-left_small') + + + +class Md2Lds(Extension): + def extendMarkdown(self, md): + md.treeprocessors.register(LDSProcessor(), 'LDSProcessor', 100) diff --git a/src/templates/base.html b/src/templates/base.html index e2d702a..582140c 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -4,7 +4,7 @@ {% include 'header.html' %} -
+
diff --git a/src/templates/footer.html b/src/templates/footer.html index 06ab60a..b50288b 100644 --- a/src/templates/footer.html +++ b/src/templates/footer.html @@ -3,13 +3,15 @@
-

- Copyright® Dogeforce Project Collaborators - @ {{ build_date }} -

+
- +
+

+ Copyright® Dogeforce Project Collaborators + @ {{ build_date }} +

+
diff --git a/src/templates/header.html b/src/templates/header.html index 9f61168..83b349a 100644 --- a/src/templates/header.html +++ b/src/templates/header.html @@ -1,4 +1,4 @@ - + diff --git a/src/templates/home.html b/src/templates/home.html index 7b9e304..dcd9c06 100644 --- a/src/templates/home.html +++ b/src/templates/home.html @@ -6,6 +6,6 @@ {% block content %} -

Posts go here!

+

Recent posts go here!

{% endblock %} diff --git a/src/templates/post.html b/src/templates/post.html index 3031e98..9bfbf55 100644 --- a/src/templates/post.html +++ b/src/templates/post.html @@ -1,3 +1,12 @@ -
+{% extends 'base.html' %} +{% block sidebar %} + {{ sidebar }} +{% endblock %} + +{% block content %} + +
{{ content.text }} -
\ No newline at end of file +
+ +{% endblock %} diff --git a/src/templates/project.html b/src/templates/project.html index d9a4822..559301d 100644 --- a/src/templates/project.html +++ b/src/templates/project.html @@ -5,10 +5,12 @@ {% block content %}
-

{{ detail.title }}

+

{{ detail.title }}

Website: {{ detail.url }}

-

{{ detail.description }}

+
+ {{ detail.description }} +
{% endblock %} diff --git a/src/templates/repositorylist.html b/src/templates/repositorylist.html index 00818c9..3919dd6 100644 --- a/src/templates/repositorylist.html +++ b/src/templates/repositorylist.html @@ -1,7 +1,7 @@ \ No newline at end of file From 71cf6e8fc7cbb1911d8473a2db672411b1fa11a0 Mon Sep 17 00:00:00 2001 From: Renato Oliveira Date: Sun, 21 Jun 2020 19:12:52 -0300 Subject: [PATCH 4/6] Adds first post. --- Pipfile | 1 - Pipfile.lock | 10 +- content/source/posts/2020-06-20-a-demo.md | 25 --- content/source/posts/patch_method.md | 111 +++++++++ css/site.css | 9 + index.html | 23 +- posts/2020-06-20-a-demo.html | 112 ---------- posts/2020-12-25-patch_method.html | 210 ++++++++++++++++++ ...larative-rollup-summaries-for-lookups.html | 9 +- projects/dogeforce-s-website-this-site.html | 9 +- projects/mass-action-scheduler.html | 9 +- src/scripts/main.py | 67 +++--- src/scripts/mdmetadata.py | 50 +++++ src/templates/base.html | 7 +- src/templates/home.html | 14 +- src/templates/post.html | 9 +- 16 files changed, 489 insertions(+), 186 deletions(-) delete mode 100644 content/source/posts/2020-06-20-a-demo.md create mode 100644 content/source/posts/patch_method.md delete mode 100644 posts/2020-06-20-a-demo.html create mode 100644 posts/2020-12-25-patch_method.html create mode 100644 src/scripts/mdmetadata.py diff --git a/Pipfile b/Pipfile index 92cbfc1..ac1c483 100644 --- a/Pipfile +++ b/Pipfile @@ -6,7 +6,6 @@ verify_ssl = true [dev-packages] [packages] -markdown2 = "*" jinja2 = "*" pyyaml = "*" python-slugify = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 4254227..9e81ad3 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "719ef99c515ec3308012eb136b0bfb0c444e2cefcd3f82d73a5ef4a223bb19f5" + "sha256": "20c17e4799c7c276ea4a45a2611e76cc79bc0e474a9d87b518f0b3197baa4342" }, "pipfile-spec": 6, "requires": { @@ -32,14 +32,6 @@ "index": "pypi", "version": "==3.2.2" }, - "markdown2": { - "hashes": [ - "sha256:89526090907ae5ece66d783c434b35c29ee500c1986309e306ce2346273ada6a", - "sha256:e6b401ec80b75e76a6b3dbb2c8ade513156fa55fa6c30b9640a1abf6184a07c8" - ], - "index": "pypi", - "version": "==2.3.9" - }, "markupsafe": { "hashes": [ "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", diff --git a/content/source/posts/2020-06-20-a-demo.md b/content/source/posts/2020-06-20-a-demo.md deleted file mode 100644 index df4e443..0000000 --- a/content/source/posts/2020-06-20-a-demo.md +++ /dev/null @@ -1,25 +0,0 @@ -# The DLRS (Declarative Lookup Rollup Summaries) tool - -## Use cases - -* Can't use native rollup summaries. -* Job needs to be done by an administrator. - -## Considerations - -The tool has gone through a big migration in the past. It used to use custom settings for managing rollups, but since Salesforce introduced Custom Metadata Types, the tool uses them. - -This is a second paragraph. - -## Repository - -The source code can be found [on GitHub](https://github.com/afawcett/declarative-lookup-rollup-summaries/). - -### Footnotes - -Lorem ipsum! - - -``` -this is some code -``` \ No newline at end of file diff --git a/content/source/posts/patch_method.md b/content/source/posts/patch_method.md new file mode 100644 index 0000000..cb2edf4 --- /dev/null +++ b/content/source/posts/patch_method.md @@ -0,0 +1,111 @@ +--- +title: Salesforce’s Apex does not support the PATCH method. What to do if I need to call an endpoint with PATCH? +author: @renatoliveira +publish_date: 2020-12-25 +preview: I needed to call a Microsoft Azure endpoint from Salesforce using the PATCH HTTP verb. The problem is, as mentioned in the title, that Apex does not support this verb. +--- +I had a requirement once. A proof of concept. I needed to call a Microsoft Azure endpoint from Salesforce using the PATCH HTTP verb. The problem is, as mentioned in the title, that Apex does not support this verb. + +If we are trying to call a Salesforce endpoint, there’s a trick: append `?_HttpMethod=PATCH` to the end of the URL. This is a workaround that Salesforce. This doesn’t help us because we are not calling a Salesforce endpoint. Another workaround would be setting the X-HTTP-Method-Override as PATCH in the request’s header. This is a convention that some servers follow, but this does not guarantee that the server being called will accept our request as a patch. +Let’s write a simple proxy that is hosted on Heroku! + +Leveraging a Heroku app in another cloud (technically another Salesforce cloud since 2010) we are able to forward our request to its final destination. + +>1. Salesforce calls our Heroku app endpoint +>2. The app forwards the request with the correct verb +>3. The app receives the response from Azure and forwards it back to Salesforce + +To do that, I’m going to use Python with the Flask and requests libraries. Flask will handle the “web app” part, while requests is going to be used to forward our request. + +NOTE: I am not going to cover the part where we get Azure’s access token because that doesn’t involve an unsupported verb. + +Assuming that our Salesforce code will send a request with the access token, the payload and the target URL, it will probably look like this: + + { + "token": "V2VsbCBhcmVuJ3QgeW91IGN1cmlvdXM/DQoNCiBMb3JlbSBpcHN1bSBkb2xvciBzaXQgYW1ldCwgY29uc2VjdGV0dXIgYWRpcGlzY2luZyBlbGl0LiBOdWxsYW0gcGVsbGVudGVzcXVlIHRvcnRvciBhYyBlbmltIGxhb3JlZXQsIGFjIGVsZW1lbnR1bSB0dXJwaXMgdWx0cmljaWVzLiBJbnRlZ2VyIGludGVyZHVtIHJpc3VzIGxhY3VzLCBlZ2V0IGNvbnNlcXVhdCBsaWd1bGEgZmVybWVudHVtIHZpdGFlLiBFdGlhbSBzb2RhbGVzLCBsaWJlcm8gdml0YWUgZGlnbmlzc2ltIGx1Y3R1cywgbGliZXJvIGFyY3UgdnVscHV0YXRlIHF1YW0sIGF0IG1hdHRpcyBkdWkgbWFnbmEgbmVjIG1hc3NhLiBEb25lYyBpcHN1bSBkb2xvciwgZnJpbmdpbGxhIHZpdGFlIG5pYmggYXQsIHJob25jdXMgc2NlbGVyaXNxdWUgZXN0LiBEb25lYyBuZWMgc29kYWxlcyByaXN1cy4gUGVsbGVudGVzcXVlIHF1aXMgZnJpbmdpbGxhIGVyb3MuIFBlbGxlbnRlc3F1ZSBoYWJpdGFudCBtb3JiaSB0cmlzdGlxdWUgc2VuZWN0dXMgZXQgbmV0dXMgZXQgbWFsZXN1YWRhIGZhbWVzIGFjIHR1cnBpcyBlZ2VzdGFzLiBOYW0gcnV0cnVtIG1ldHVzIG1hdXJpcywgYWMgdWxsYW1jb3JwZXIgdGVsbHVzIGF1Y3RvciBpbi4gVXQgYWNjdW1zYW4gc2NlbGVyaXNxdWUgc29kYWxlcy4gRnVzY2UgdmFyaXVzIG5lcXVlIGVzdCwgc2VkIHB1bHZpbmFyIHNlbSBzY2VsZXJpc3F1ZSBub24uIA==", + "payload": "IFNlZCB2ZW5lbmF0aXMgZXQgbWV0dXMgbm9uIGx1Y3R1cy4gUGVsbGVudGVzcXVlIGFjIGV1aXNtb2QgbWV0dXMsIG5lYyB0ZW1wb3IgZHVpLiBOYW0gYSB2ZXN0aWJ1bHVtIGZlbGlzLiBOdW5jIG1hZ25hIGxpZ3VsYSwgY29uZ3VlIG5lYyBpbXBlcmRpZXQgdXQsIGNvbmd1ZSB2dWxwdXRhdGUgcXVhbS4gTWFlY2VuYXMgYmxhbmRpdCwgZmVsaXMgbmVjIHNlbXBlciBkYXBpYnVzLCB0ZWxsdXMgaXBzdW0gdm9sdXRwYXQgYXVndWUsIGFjIGVnZXN0YXMgbmlzbCBvcmNpIG5lYyBzYXBpZW4uIEV0aWFtIGEgdnVscHV0YXRlIGVyb3MuIEN1cmFiaXR1ciBsYWNpbmlhIHNjZWxlcmlzcXVlIG5pc2wgc2VkIHZvbHV0cGF0LiBNYXVyaXMgdml0YWUgZXJhdCBwZWxsZW50ZXNxdWUsIGxhY2luaWEgdHVycGlzIHV0LCB0ZW1wb3Igc2FwaWVuLiBJbnRlZ2VyIHZlbCBsb2JvcnRpcyBkdWkuIEN1cmFiaXR1ciBpbXBlcmRpZXQgbWF0dGlzIGZlbGlzLiBQaGFzZWxsdXMgY29tbW9kbyBtYXNzYSBldSB2ZWxpdCBkYXBpYnVzIHRyaXN0aXF1ZSBhIGV1IGxpYmVyby4gRnVzY2UgaW4gcmlzdXMgZW5pbS4gRnVzY2UgZmVybWVudHVtIGV0IHB1cnVzIGV0IGNvbmRpbWVudHVtLiBJbiBzY2VsZXJpc3F1ZSBwb3N1ZXJlIGVsaXQsIHZpdGFlIGludGVyZHVtIHR1cnBpcyBjb25zZWN0ZXR1ciBhdC4g", + "url": "https://outlook.office.com/api/beta/me/contacts/31d14663-8cf4-4acf-b1c8-556b8e62107d" + } + +The app will receive this and interpret it as “okay, I’ve got this encoded payload, and I shall use this token to send it to this endpoint”: + + # Import the required libraries + # Flask is the web framework for dealing with web stuff (such as serving the app and handling + # the connections) We need to import the main "Flask" to run the app, and also its + # request and Response method and class to handle the request properly + from flask import Flask, Response, request + + # requests is a simple http request library to handle... requests. + import requests + + # Base64 is a standard module to help us encode/decode Base 64 strings + import base64 + # Json is a standar dmodule to help us handle JSON in Python (converting it from/to + # dictionaries - which are also known as maps in some other languages) + import json + # OS is a standard module to handle dealing with the OS directly (we use it just to check + # an environment variable at the end of the script) + import os + + + # Lets first create the app. This is an empty app which does nothing. + # The app will do what we want as we define the methods/routes below, with (for example) + # the `app.route` decorator (which specifies the route and allowed methods) + app = Flask(__name__) + + # This route defines that the app can receive POST requests in the `/contact/` endpoint. So + # when deployed, if the app is named `quiet-waters-12345`, its Heroku URL will be + # `https://quiet-waters-12345.herokuapp.com/` and we should hit that endpoint, adding the + # `/contact/` at the end. + @app.route('/contact/', methods=['POST']) + def contact(): + # First lets deserialize the request's JSON data into a dictionary. + request_data = request.get_json() + + # We check if there are the required attributes we need + if 'token' in request_data and 'payload' in request_data and 'url' in request_data: + try: + # We try to decode the payload + payload = base64.b64decode(request_data['payload']).decode('utf-8') + + # Assign the original payload to a new attribute named `original_payload` + # in our dictionary + request_data['original_payload'] = payload + + # Define the headers as required by the Azure endpoint + headers = { + 'Authorization': 'Bearer ' + request_data['token'], + 'Content-Type': 'application/json' + } + + # Try to call external endpoint using the requests library. Note that we + # use the `patch` method here. + azure_request = requests.patch( + url=request_data['url'], + data=payload, + headers=headers + ) + # When the request is finished, its result is stored in `azure_request`, + # which we can use to get the JSON response. + result = { + "azure_response": azure_request.json() + } + # We basically dump the request's result into a new Response and we return + # it to the service who called us in the first place. + resp = Response(json.dumps(result), status=azure_request.status_code, mimetype='applcation/json') + return resp + except Exception as e: + resp = Response(json.dumps({'error': e.args}), status=500, mimetype='applcation/json') + + # Returns an error response because there is missing data in the payload. + return Response(json.dumps({'error':'No token or payload data informed'}), status=400, mimetype='application/json') + + # Checks if the `IS_HEROKU` variable is set. If it is (in our dyno) then the app is running on + # Heroku's cloud. Otherwise it is running locally in our machine, so we want it to run in our + # localhost, on port 8080 instead (and with debug mode active). + if not os.environ.get('IS_HEROKU', None) and __name__ == '__main__': + app.run(host='localhost', port='8080', debug=True) + +And with this small web app hosted in Heroku we are not limited to a single URL. This transforms any POST request to a PATCH request. I’ve used this to call an Outlook endpoint (hence why the apps’ route was named /contacts/) but it can be renamed as needed. + +An idea would be to have all HTTP verbs available as endpoints, such as /post, /get, /delete, etc. This way the app will look more like an endpoint bus though… diff --git a/css/site.css b/css/site.css index 13a04b6..b553a6e 100644 --- a/css/site.css +++ b/css/site.css @@ -7,4 +7,13 @@ left: 0; bottom: 0; width: 100%; +} + +div > pre { + white-space: pre-wrap; + word-wrap: anywhere; +} + +.dgf-footer-space { + height: 10vh; } \ No newline at end of file diff --git a/index.html b/index.html index 01c8a05..4bf03ea 100644 --- a/index.html +++ b/index.html @@ -58,18 +58,33 @@
-
+
- -

Recent posts go here!

+ + +
+ +
+
@@ -84,7 +99,7 @@

Copyright® Dogeforce Project Collaborators - @ + @ 2020-06-21

diff --git a/posts/2020-06-20-a-demo.html b/posts/2020-06-20-a-demo.html deleted file mode 100644 index e3e5cea..0000000 --- a/posts/2020-06-20-a-demo.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - The Dogeforce Project - - - - - -
-
-
-
-

- -

-

- Dogeforce -

-
-
-
- -
-
-
- - - - -
- -
- - - - - -
- - - -
-

The DLRS (Declarative Lookup Rollup Summaries) tool

-

Use cases

-
    -
  • Can't use native rollup summaries.
  • -
  • Job needs to be done by an administrator.
  • -
-

Considerations

-

The tool has gone through a big migration in the past. It used to use custom settings for managing rollups, but since Salesforce introduced Custom Metadata Types, the tool uses them.

-

This is a second paragraph.

-

Repository

-

The source code can be found on GitHub.

-

Footnotes

-

Lorem ipsum!

-

this is some code

-
- - - -
-
- -
- - - -
-
-
-
- -
-
-
-

- Copyright® Dogeforce Project Collaborators - @ 2020-06-20 -

-
-
-
- -
-
-
-
- - \ No newline at end of file diff --git a/posts/2020-12-25-patch_method.html b/posts/2020-12-25-patch_method.html new file mode 100644 index 0000000..4aa7cec --- /dev/null +++ b/posts/2020-12-25-patch_method.html @@ -0,0 +1,210 @@ + + + + + + + + The Dogeforce Project + + + + + +
+
+
+
+

+ +

+

+ Dogeforce +

+
+
+
+ +
+
+
+ + + + +
+ +
+ + + + + +
+ + + +
+
+
Salesforce’s Apex does not support the PATCH method. What to do if I need to call an endpoint with PATCH?
+
by @renatoliveira
+
when: 2020-12-25
+
+
+

I had a requirement once. A proof of concept. I needed to call a Microsoft Azure endpoint from Salesforce using the PATCH HTTP verb. The problem is, as mentioned in the title, that Apex does not support this verb.

+

If we are trying to call a Salesforce endpoint, there’s a trick: append ?_HttpMethod=PATCH to the end of the URL. This is a workaround that Salesforce. This doesn’t help us because we are not calling a Salesforce endpoint. Another workaround would be setting the X-HTTP-Method-Override as PATCH in the request’s header. This is a convention that some servers follow, but this does not guarantee that the server being called will accept our request as a patch. +Let’s write a simple proxy that is hosted on Heroku!

+

Leveraging a Heroku app in another cloud (technically another Salesforce cloud since 2010) we are able to forward our request to its final destination.

+
+
    +
  1. Salesforce calls our Heroku app endpoint
  2. +
  3. The app forwards the request with the correct verb
  4. +
  5. The app receives the response from Azure and forwards it back to Salesforce
  6. +
+
+

To do that, I’m going to use Python with the Flask and requests libraries. Flask will handle the “web app” part, while requests is going to be used to forward our request.

+

NOTE: I am not going to cover the part where we get Azure’s access token because that doesn’t involve an unsupported verb.

+

Assuming that our Salesforce code will send a request with the access token, the payload and the target URL, it will probably look like this:

+
{
+    "token": "V2VsbCBhcmVuJ3QgeW91IGN1cmlvdXM/DQoNCiBMb3JlbSBpcHN1bSBkb2xvciBzaXQgYW1ldCwgY29uc2VjdGV0dXIgYWRpcGlzY2luZyBlbGl0LiBOdWxsYW0gcGVsbGVudGVzcXVlIHRvcnRvciBhYyBlbmltIGxhb3JlZXQsIGFjIGVsZW1lbnR1bSB0dXJwaXMgdWx0cmljaWVzLiBJbnRlZ2VyIGludGVyZHVtIHJpc3VzIGxhY3VzLCBlZ2V0IGNvbnNlcXVhdCBsaWd1bGEgZmVybWVudHVtIHZpdGFlLiBFdGlhbSBzb2RhbGVzLCBsaWJlcm8gdml0YWUgZGlnbmlzc2ltIGx1Y3R1cywgbGliZXJvIGFyY3UgdnVscHV0YXRlIHF1YW0sIGF0IG1hdHRpcyBkdWkgbWFnbmEgbmVjIG1hc3NhLiBEb25lYyBpcHN1bSBkb2xvciwgZnJpbmdpbGxhIHZpdGFlIG5pYmggYXQsIHJob25jdXMgc2NlbGVyaXNxdWUgZXN0LiBEb25lYyBuZWMgc29kYWxlcyByaXN1cy4gUGVsbGVudGVzcXVlIHF1aXMgZnJpbmdpbGxhIGVyb3MuIFBlbGxlbnRlc3F1ZSBoYWJpdGFudCBtb3JiaSB0cmlzdGlxdWUgc2VuZWN0dXMgZXQgbmV0dXMgZXQgbWFsZXN1YWRhIGZhbWVzIGFjIHR1cnBpcyBlZ2VzdGFzLiBOYW0gcnV0cnVtIG1ldHVzIG1hdXJpcywgYWMgdWxsYW1jb3JwZXIgdGVsbHVzIGF1Y3RvciBpbi4gVXQgYWNjdW1zYW4gc2NlbGVyaXNxdWUgc29kYWxlcy4gRnVzY2UgdmFyaXVzIG5lcXVlIGVzdCwgc2VkIHB1bHZpbmFyIHNlbSBzY2VsZXJpc3F1ZSBub24uIA==",
+    "payload": "IFNlZCB2ZW5lbmF0aXMgZXQgbWV0dXMgbm9uIGx1Y3R1cy4gUGVsbGVudGVzcXVlIGFjIGV1aXNtb2QgbWV0dXMsIG5lYyB0ZW1wb3IgZHVpLiBOYW0gYSB2ZXN0aWJ1bHVtIGZlbGlzLiBOdW5jIG1hZ25hIGxpZ3VsYSwgY29uZ3VlIG5lYyBpbXBlcmRpZXQgdXQsIGNvbmd1ZSB2dWxwdXRhdGUgcXVhbS4gTWFlY2VuYXMgYmxhbmRpdCwgZmVsaXMgbmVjIHNlbXBlciBkYXBpYnVzLCB0ZWxsdXMgaXBzdW0gdm9sdXRwYXQgYXVndWUsIGFjIGVnZXN0YXMgbmlzbCBvcmNpIG5lYyBzYXBpZW4uIEV0aWFtIGEgdnVscHV0YXRlIGVyb3MuIEN1cmFiaXR1ciBsYWNpbmlhIHNjZWxlcmlzcXVlIG5pc2wgc2VkIHZvbHV0cGF0LiBNYXVyaXMgdml0YWUgZXJhdCBwZWxsZW50ZXNxdWUsIGxhY2luaWEgdHVycGlzIHV0LCB0ZW1wb3Igc2FwaWVuLiBJbnRlZ2VyIHZlbCBsb2JvcnRpcyBkdWkuIEN1cmFiaXR1ciBpbXBlcmRpZXQgbWF0dGlzIGZlbGlzLiBQaGFzZWxsdXMgY29tbW9kbyBtYXNzYSBldSB2ZWxpdCBkYXBpYnVzIHRyaXN0aXF1ZSBhIGV1IGxpYmVyby4gRnVzY2UgaW4gcmlzdXMgZW5pbS4gRnVzY2UgZmVybWVudHVtIGV0IHB1cnVzIGV0IGNvbmRpbWVudHVtLiBJbiBzY2VsZXJpc3F1ZSBwb3N1ZXJlIGVsaXQsIHZpdGFlIGludGVyZHVtIHR1cnBpcyBjb25zZWN0ZXR1ciBhdC4g",
+    "url": "https://outlook.office.com/api/beta/me/contacts/31d14663-8cf4-4acf-b1c8-556b8e62107d"
+}
+
+

The app will receive this and interpret it as “okay, I’ve got this encoded payload, and I shall use this token to send it to this endpoint”:

+
# Import the required libraries
+# Flask is the web framework for dealing with web stuff (such as serving the app and handling
+# the connections) We need to import the main "Flask" to run the app, and also its
+# request and Response method and class to handle the request properly
+from flask import Flask, Response, request
+
+# requests is a simple http request library to handle... requests.
+import requests
+
+# Base64 is a standard module to help us encode/decode Base 64 strings
+import base64
+# Json is a standar dmodule to help us handle JSON in Python (converting it from/to
+# dictionaries - which are also known as maps in some other languages)
+import json
+# OS is a standard module to handle dealing with the OS directly (we use it just to check
+# an environment variable at the end of the script)
+import os
+
+
+# Lets first create the app. This is an empty app which does nothing.
+# The app will do what we want as we define the methods/routes below, with (for example)
+# the `app.route` decorator (which specifies the route and allowed methods)
+app = Flask(__name__)
+
+# This route defines that the app can receive POST requests in the `/contact/` endpoint. So
+# when deployed, if the app is named `quiet-waters-12345`, its Heroku URL will be
+# `https://quiet-waters-12345.herokuapp.com/` and we should hit that endpoint, adding the
+# `/contact/` at the end.
+@app.route('/contact/', methods=['POST'])
+def contact():
+    # First lets deserialize the request's JSON data into a dictionary.
+    request_data = request.get_json()
+
+    # We check if there are the required attributes we need
+    if 'token' in request_data and 'payload' in request_data and 'url' in request_data:
+        try:
+            # We try to decode the payload
+            payload = base64.b64decode(request_data['payload']).decode('utf-8')
+
+            # Assign the original payload to a new attribute named `original_payload`
+            # in our dictionary
+            request_data['original_payload'] = payload
+
+            # Define the headers as required by the Azure endpoint
+            headers = {
+                'Authorization': 'Bearer ' + request_data['token'],
+                'Content-Type': 'application/json'
+            }
+
+            # Try to call external endpoint using the requests library. Note that we
+            # use the `patch` method here.
+            azure_request = requests.patch(
+                url=request_data['url'],
+                data=payload,
+                headers=headers
+            )
+            # When the request is finished, its result is stored in `azure_request`,
+            # which we can use to get the JSON response.
+            result = {
+                "azure_response": azure_request.json()
+            }
+            # We basically dump the request's result into a new Response and we return
+            # it to the service who called us in the first place.
+            resp = Response(json.dumps(result), status=azure_request.status_code, mimetype='applcation/json')
+            return resp
+        except Exception as e:
+            resp = Response(json.dumps({'error': e.args}), status=500, mimetype='applcation/json')
+
+    # Returns an error response because there is missing data in the payload.
+    return Response(json.dumps({'error':'No token or payload data informed'}), status=400, mimetype='application/json')
+
+# Checks if the `IS_HEROKU` variable is set. If it is (in our dyno) then the app is running on
+# Heroku's cloud. Otherwise it is running locally in our machine, so we want it to run in our
+# localhost, on port 8080 instead (and with debug mode active).
+if not os.environ.get('IS_HEROKU', None) and __name__ == '__main__':
+    app.run(host='localhost', port='8080', debug=True)
+
+

And with this small web app hosted in Heroku we are not limited to a single URL. This transforms any POST request to a PATCH request. I’ve used this to call an Outlook endpoint (hence why the apps’ route was named /contacts/) but it can be renamed as needed.

+

An idea would be to have all HTTP verbs available as endpoints, such as /post, /get, /delete, etc. This way the app will look more like an endpoint bus though…

+
+
+ + + +
+ +
+ +
+
+ + +
+ + + +
+
+
+
+ +
+
+
+

+ Copyright® Dogeforce Project Collaborators + @ 2020-06-21 +

+
+
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/projects/declarative-rollup-summaries-for-lookups.html b/projects/declarative-rollup-summaries-for-lookups.html index 952b79a..54e3d69 100644 --- a/projects/declarative-rollup-summaries-for-lookups.html +++ b/projects/declarative-rollup-summaries-for-lookups.html @@ -58,7 +58,7 @@
-
+
@@ -78,9 +78,14 @@

Examp

+
+ +
+
+
@@ -95,7 +100,7 @@

Examp

Copyright® Dogeforce Project Collaborators - @ 2020-06-20 + @ 2020-06-21

diff --git a/projects/dogeforce-s-website-this-site.html b/projects/dogeforce-s-website-this-site.html index e36b85e..973af6e 100644 --- a/projects/dogeforce-s-website-this-site.html +++ b/projects/dogeforce-s-website-this-site.html @@ -58,7 +58,7 @@
-
+
@@ -79,9 +79,14 @@

The D

+
+ +
+
+
@@ -96,7 +101,7 @@

The D

Copyright® Dogeforce Project Collaborators - @ 2020-06-20 + @ 2020-06-21

diff --git a/projects/mass-action-scheduler.html b/projects/mass-action-scheduler.html index 1309205..117008d 100644 --- a/projects/mass-action-scheduler.html +++ b/projects/mass-action-scheduler.html @@ -58,7 +58,7 @@
-
+
@@ -77,9 +77,14 @@

A qu

+
+ +
+
+
@@ -94,7 +99,7 @@

A qu

Copyright® Dogeforce Project Collaborators - @ 2020-06-20 + @ 2020-06-21

diff --git a/src/scripts/main.py b/src/scripts/main.py index 3d69a43..19718cb 100644 --- a/src/scripts/main.py +++ b/src/scripts/main.py @@ -1,47 +1,60 @@ +import os +from datetime import datetime +from operator import attrgetter +from dataclasses import dataclass + import yaml from slugify import slugify from markdown import markdown as md from jinja2 import Environment, FileSystemLoader -from datetime import datetime + from md2lds import Md2Lds +from mdmetadata import parse_markdown + def slugify_url(item): item['slug'] = slugify(item['title']) return item + TODAY = datetime.today().date().isoformat() env = Environment(loader=FileSystemLoader(searchpath='src/templates')) home_template = env.get_template('home.html') content = yaml.load(open('content/projects.yaml').read(), Loader=yaml.SafeLoader) -# posts = yaml.load(open('content/posts.yaml').read(), Loader=yaml.SafeLoader) content['projects'] = [slugify_url(x) for x in content['projects']] project_page_template = env.get_template('project.html') post_page_template = env.get_template('post.html') repositories = env.get_template('repositorylist.html').render(items=content['projects']) +posts = [] -# for post in content['posts']: -# with open('pages/posts/{}.html'.format(post['slug']), 'w') as page: -# post['repositories'] = repositories -# page.write(post_page_template.render( -# detail=post -# )) - -with open('content/source/posts/2020-06-20-a-demo.md', 'r') as post: - with open('posts/2020-06-20-a-demo.html', 'w') as rendered_post: - render = post_page_template.render( - sidebar=repositories, - content={ - 'text': md(post.read(), extensions=[Md2Lds()]) - }, - build_date=TODAY - ) - rendered_post.write(render) - rendered_post.close() - post.close() + +for dire, fol, files in os.walk('content/source/posts'): + for file in files: + with open('{}/{}'.format(dire, file), 'r') as post: + post_data = parse_markdown(post) + fname = '{}-{}.html'.format(post_data.publish_date, file.replace('.md', '')) + post_data.metadata['url'] = 'posts/{}'.format(fname) + + with open('{}/{}'.format('posts', fname), 'w') as rendered_post: + print('Rendering post {} as {}...'.format(file, fname), end='') + rendered_html = md(''.join(post_data.content), extensions=[Md2Lds()]) + render = post_page_template.render( + sidebar=repositories, + content=rendered_html, + build_date=TODAY, + metadata=post_data.metadata + ) + rendered_post.write(render) + rendered_post.close() + post.close() + posts.append(post_data) + print(' OK') + +posts.sort(key=attrgetter('publish_date'), reverse=True) for project in content['projects']: with open('projects/{}.html'.format(project['slug']), 'w') as page: @@ -57,10 +70,14 @@ def slugify_url(item): page.write(project_page_render) page.close() -r = home_template.render(page={ - 'sidebar': repositories, - 'build_date': TODAY -}) + +r = home_template.render( + build_date=TODAY, + page={ + 'sidebar': repositories, + 'recent_posts': posts[:5] + } +) with open('index.html', 'w') as index_file: index_file.write(r) diff --git a/src/scripts/mdmetadata.py b/src/scripts/mdmetadata.py new file mode 100644 index 0000000..3d5b6b6 --- /dev/null +++ b/src/scripts/mdmetadata.py @@ -0,0 +1,50 @@ +from io import TextIOWrapper +from datetime import datetime, date + + +class MarkdownWithMetadata: + metadata: dict + content: str + + def __init__(self, md, c): + self.metadata = md + self.content = c + + def __str__(self): + return '{} attributes: {}'.format(len(list(self.metadata)), ', '.join(list(self.metadata))) + + def __getattr__(self, attrname): + if attrname in self.metadata: + if 'date' in attrname and type(self.metadata[attrname]) != date: + datestrs = self.metadata[attrname].split('-')[-3:] + self.metadata[attrname] = datetime( + int(datestrs[0]), + int(datestrs[1]), + int(datestrs[2]) + ).date() + return self.metadata[attrname] + return '' + + +def parse_markdown(md: TextIOWrapper): + parsing = False + metadata = {} + lines = [] + for line in md.readlines(): + if line == '---\n' and not parsing and len(lines) == 0: + parsing = not parsing + continue + elif line == '---\n' and parsing: + parsing = not parsing + continue + + if parsing: + line_data = line.split(': ') + attr = line_data[0] + attr_data = ''.join(line_data[1:]) + metadata[attr] = attr_data.replace('\n', '') + + else: + lines.append(line) + + return MarkdownWithMetadata(metadata, ''.join(lines)) diff --git a/src/templates/base.html b/src/templates/base.html index 582140c..6bf8906 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -14,13 +14,18 @@
-
+
{% block content %} {% endblock %}
+ +
+ +
+
diff --git a/src/templates/home.html b/src/templates/home.html index dcd9c06..eec5176 100644 --- a/src/templates/home.html +++ b/src/templates/home.html @@ -5,7 +5,17 @@ {% block content %} - -

Recent posts go here!

+ {% endblock %} diff --git a/src/templates/post.html b/src/templates/post.html index 9bfbf55..fa555a6 100644 --- a/src/templates/post.html +++ b/src/templates/post.html @@ -6,7 +6,14 @@ {% block content %}
- {{ content.text }} +
+
{{ metadata.title }}
+
by {{ metadata.author }}
+
when: {{ metadata.publish_date }}
+
+
+ {{ content }} +
{% endblock %} From f78dd755eeb342dd9ac6787b3a05569bedc9ee74 Mon Sep 17 00:00:00 2001 From: Renato Oliveira Date: Sun, 21 Jun 2020 19:37:22 -0300 Subject: [PATCH 5/6] Adds body CSS and SFXD button. --- css/site.css | 5 +++++ src/templates/base.html | 2 +- src/templates/header.html | 11 ++++++++++- src/templates/project.html | 2 ++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/css/site.css b/css/site.css index b553a6e..6802e2c 100644 --- a/css/site.css +++ b/css/site.css @@ -2,7 +2,12 @@ width: 100px; } +.dgf-body { + min-height: 80vh; +} + .dgf-footer { + min-height: 10vh; position: fixed; left: 0; bottom: 0; diff --git a/src/templates/base.html b/src/templates/base.html index 6bf8906..1895a69 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -4,7 +4,7 @@ {% include 'header.html' %} -
+
diff --git a/src/templates/header.html b/src/templates/header.html index 83b349a..4289e55 100644 --- a/src/templates/header.html +++ b/src/templates/header.html @@ -20,9 +20,18 @@

-
diff --git a/src/templates/project.html b/src/templates/project.html index 559301d..77880f8 100644 --- a/src/templates/project.html +++ b/src/templates/project.html @@ -4,6 +4,7 @@ {% endblock %} {% block content %} +

{{ detail.title }}

@@ -13,4 +14,5 @@ {{ detail.description }}
+ {% endblock %} From 1c9c2a87157049caa0e25bb23665d33e23cf9bec Mon Sep 17 00:00:00 2001 From: Renato Oliveira Date: Sun, 21 Jun 2020 19:37:48 -0300 Subject: [PATCH 6/6] Adds contribution information and regenerates the posts. --- content/source/projects/dogeforce.md | 19 +++++++++++++- index.html | 13 ++++++++-- makefile | 5 +++- posts/2020-12-25-patch_method.html | 13 ++++++++-- ...larative-rollup-summaries-for-lookups.html | 15 +++++++++-- projects/dogeforce-s-website-this-site.html | 25 +++++++++++++++++-- projects/mass-action-scheduler.html | 15 +++++++++-- 7 files changed, 93 insertions(+), 12 deletions(-) diff --git a/content/source/projects/dogeforce.md b/content/source/projects/dogeforce.md index 7ad4e20..68b3410 100644 --- a/content/source/projects/dogeforce.md +++ b/content/source/projects/dogeforce.md @@ -4,6 +4,23 @@ This is an open-source website with the goal to aggregate Salesforce resources s You can check out the source code at the github repository in the link above. This website is hosted at GitHub as well. It's source is generated by a Python script that gathers the sources from many folders and "compiles" them to HTML which is then served by GitHub. The script is also custom made too (which is why it might look a little too ugly - *PR's are welcome*). +### Contributing + +This website's source is open [on GitHub](https://github.com/Dogeforce/dogeforce.github.io/), so anyone with Python 3.8+ installed can contribute (because it is necessary to generate the files locally and push them). Just create a pull request with the content or improvements to the site's (like the CSS). The project uses [Pipenv](https://pipenv.pypa.io/en/latest/) to manage dependencies, so one can easily create a virtual Python environment to use the libraries (the four packages listed on the Pipfile). + +To write an article, create the markdown file inside the `content > source > posts` folder, and do not forget to add the metadata information on the beginning of the file, such as: + + --- + title: The title of the article + author: your @ on github or maybe twitter (or none) + publish_date: 2020-12-25 + preview: A small text explaining what the article is about + --- + +Then you can use the `make build` command to generate the necessary files. The script reads the files inside the `content > source > posts` folder and turns them into `.html` files on the `posts` folder. Alternatively, if there is no `make` command available one just needs to run the `src/scripts/main.py` file with `python` from the root folder. + +It is possible to preview the content using `make serve` to start a simple http server on the folder, so one is able to access a site version locally. + ### The Doge logo This amazing image was made by a member of the Salesforce Discord Exchange (SFXD). Even stickers were made of it: @@ -12,4 +29,4 @@ This amazing image was made by a member of the Salesforce Discord Exchange (SFXD Can you imagine being at a meeting with this guy looking at ya? -![](/images/sticker_on_laptop.jpg) +![](/images/sticker_on_laptop.jpg) \ No newline at end of file diff --git a/index.html b/index.html index 4bf03ea..cb1910b 100644 --- a/index.html +++ b/index.html @@ -23,16 +23,25 @@

-
-
+
diff --git a/makefile b/makefile index 257353f..6880440 100644 --- a/makefile +++ b/makefile @@ -1,2 +1,5 @@ build: - python src/scripts/main.py > index.html + python src/scripts/main.py + +serve: + python -m http.server diff --git a/posts/2020-12-25-patch_method.html b/posts/2020-12-25-patch_method.html index 4aa7cec..f6189c3 100644 --- a/posts/2020-12-25-patch_method.html +++ b/posts/2020-12-25-patch_method.html @@ -23,16 +23,25 @@

-
-
+
diff --git a/projects/declarative-rollup-summaries-for-lookups.html b/projects/declarative-rollup-summaries-for-lookups.html index 54e3d69..10f0b5f 100644 --- a/projects/declarative-rollup-summaries-for-lookups.html +++ b/projects/declarative-rollup-summaries-for-lookups.html @@ -23,16 +23,25 @@

-
-
+
@@ -61,6 +70,7 @@
+

Declarative Rollup Summaries for Lookups

@@ -78,6 +88,7 @@

Examp

+
diff --git a/projects/dogeforce-s-website-this-site.html b/projects/dogeforce-s-website-this-site.html index 973af6e..15f3f81 100644 --- a/projects/dogeforce-s-website-this-site.html +++ b/projects/dogeforce-s-website-this-site.html @@ -23,16 +23,25 @@

-
-
+
@@ -61,6 +70,7 @@
+

Dogeforce's Website (this site!)

@@ -70,6 +80,16 @@

About this site

This is an open-source website with the goal to aggregate Salesforce resources such as open source projects (like the DLRS or the Mass Action Scheduler) and comment about them, talk about their use cases, but mostly because the creator had too much free time on a weekend.

You can check out the source code at the github repository in the link above. This website is hosted at GitHub as well. It's source is generated by a Python script that gathers the sources from many folders and "compiles" them to HTML which is then served by GitHub. The script is also custom made too (which is why it might look a little too ugly - PR's are welcome).

+

Contributing

+

This website's source is open on GitHub, so anyone with Python 3.8+ installed can contribute (because it is necessary to generate the files locally and push them). Just create a pull request with the content or improvements to the site's (like the CSS). The project uses Pipenv to manage dependencies, so one can easily create a virtual Python environment to use the libraries (the four packages listed on the Pipfile).

+

To write an article, create the markdown file inside the content > source > posts folder, and do not forget to add the metadata information on the beginning of the file, such as:

+
---
+title: The title of the article
+author: your @ on github or maybe twitter (or none)
+publish_date: 2020-12-25
+preview: A small text explaining what the article is about
+---
+

The Doge logo

This amazing image was made by a member of the Salesforce Discord Exchange (SFXD). Even stickers were made of it:

@@ -79,6 +99,7 @@

The D

+
diff --git a/projects/mass-action-scheduler.html b/projects/mass-action-scheduler.html index 117008d..71bceb5 100644 --- a/projects/mass-action-scheduler.html +++ b/projects/mass-action-scheduler.html @@ -23,16 +23,25 @@

-
-
+
@@ -61,6 +70,7 @@
+

Mass Action Scheduler

@@ -77,6 +87,7 @@

A qu

+