From da9ba3a78ea1dc32cb743864d727f06b1ab6ea16 Mon Sep 17 00:00:00 2001
From: Brandon Rodriguez <brodriguez8774@gmail.com>
Date: Sun, 13 Aug 2023 21:43:05 -0400
Subject: [PATCH] Add handling for "pillars" section, plus example output of
 such

---
 .../fixtures/resume_manager/contact_info.json |  13 ++
 .../resume_manager/education_instances.json   |  45 ++++++
 .../resume_manager/experience_instances.json  |  60 ++++++++
 .../resume_manager/pillar_categories.json     |  35 +++++
 .../resume_manager/pillar_instances.json      |  62 +++++++++
 .../resume_manager/resume_sections.json       | 129 +++++++++++++++++-
 .../fixtures/resume_manager/resumes.json      |  13 ++
 .../resume_manager_core__loadfixtures.py      |  14 ++
 .../commands/resume_manager_core__seed.py     |  20 +++
 resume_manager_core/models.py                 |  49 ++++++-
 .../css/sass/src/_general_styles.scss         |  17 ++-
 .../css/sass/src/_resume_blocky.scss          |   5 +
 .../css/sass/src/_text_styles.scss            |   5 -
 .../resume_manager/_display_recurse.html      |   4 +-
 .../resume_manager/include/pillars.html       |  27 ++++
 .../resume_manager/include/skills.html        |   2 +-
 resume_manager_core/views.py                  |  46 ++++---
 17 files changed, 510 insertions(+), 36 deletions(-)
 create mode 100644 resume_manager_core/fixtures/resume_manager/pillar_categories.json
 create mode 100644 resume_manager_core/fixtures/resume_manager/pillar_instances.json
 create mode 100644 resume_manager_core/templates/resume_manager/include/pillars.html

diff --git a/resume_manager_core/fixtures/resume_manager/contact_info.json b/resume_manager_core/fixtures/resume_manager/contact_info.json
index babecc0..0cae8b9 100644
--- a/resume_manager_core/fixtures/resume_manager/contact_info.json
+++ b/resume_manager_core/fixtures/resume_manager/contact_info.json
@@ -23,5 +23,18 @@
         "date_created": "2023-01-01T08:00:00.000Z",
         "date_modified": "2023-01-01T08:00:00.000Z"
     }
+},
+{
+    "model": "resume_manager_core.contactinfo",
+    "pk": 3,
+    "fields": {
+        "resume": 3,
+        "phone_number": 9255550100,
+        "email": "email@example.com",
+        "website": "www.brandon-rodriguez.com",
+        "linkedin": "example-user",
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
 }
 ]
diff --git a/resume_manager_core/fixtures/resume_manager/education_instances.json b/resume_manager_core/fixtures/resume_manager/education_instances.json
index c76b29a..10c25dd 100644
--- a/resume_manager_core/fixtures/resume_manager/education_instances.json
+++ b/resume_manager_core/fixtures/resume_manager/education_instances.json
@@ -115,5 +115,50 @@
         "date_created": "2023-01-01T08:00:00.000Z",
         "date_modified": "2023-01-01T08:00:00.000Z"
     }
+},
+{
+    "model": "resume_manager_core.educationinstance",
+    "pk": 9,
+    "fields": {
+        "resume": 3,
+        "name": "Example Associate's Institution",
+        "degree": "Introductory Basket Weaving",
+        "gpa": 4.0,
+        "date_start": "2015-08-26",
+        "date_end": "2017-05-14",
+        "order": 3,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.educationinstance",
+    "pk": 10,
+    "fields": {
+        "resume": 3,
+        "name": "Example Master's Institution",
+        "degree": "Extreme Basket Weaving",
+        "gpa": 3.45,
+        "date_start": "2021-01-09",
+        "date_end": "2023-05-15",
+        "order": 1,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.educationinstance",
+    "pk": 11,
+    "fields": {
+        "resume": 3,
+        "name": "Example Bachelor's Institution",
+        "degree": "Computer Science",
+        "gpa": "2.88",
+        "date_start": "2017-08-26",
+        "date_end": "2020-12-07",
+        "order": 2,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
 }
 ]
diff --git a/resume_manager_core/fixtures/resume_manager/experience_instances.json b/resume_manager_core/fixtures/resume_manager/experience_instances.json
index 40678ca..8e37a12 100644
--- a/resume_manager_core/fixtures/resume_manager/experience_instances.json
+++ b/resume_manager_core/fixtures/resume_manager/experience_instances.json
@@ -58,5 +58,65 @@
         "date_created": "2023-01-01T08:00:00.000Z",
         "date_modified": "2023-01-01T08:00:00.000Z"
     }
+},
+{
+    "model": "resume_manager_core.experienceinstance",
+    "pk": 5,
+    "fields": {
+        "resume": 3,
+        "name": "Bob's Basket Weaving Shenanigans",
+        "position": "Intern Basket Weaver",
+        "description": "Intern one one of several teams weaving vibranium interlaced bamboo baskets. Responsible for learning company workflow, and being able to keep up with employee output by first two months.",
+        "date_start": "2015-08-26",
+        "date_end": "2016-05-14",
+        "order": 4,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.experienceinstance",
+    "pk": 6,
+    "fields": {
+        "resume": 3,
+        "name": "Bob's Basket Weaving Shenanigans",
+        "position": "Sr Basket Weaver",
+        "description": "Leader of basket weaving operations. Includes overseeing supply-ordering and quality control of incoming materials, interviewing and training of all incoming new hires, as well as all functions of previous role.",
+        "date_start": "2021-01-09",
+        "date_end": "2023-05-15",
+        "order": 1,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.experienceinstance",
+    "pk": 7,
+    "fields": {
+        "resume": 3,
+        "name": "Paper & Co's Paper Bussiness",
+        "position": "Paper Shuffler",
+        "description": "Part of a team to research, test, and evaluate papers in search of ideal stacking and shuffling qualities. Tasks included shuffling papers in various environmental conditions to test quality and handling, as well as occasionally acting as the office receptionist to handle incoming day-to-day phone calls.",
+        "date_start": "2018-08-26",
+        "date_end": "2020-12-07",
+        "order": 3,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.experienceinstance",
+    "pk": 8,
+    "fields": {
+        "resume": 3,
+        "name": "Bob's Basket Weaving Shenanigans",
+        "position": "Basket Weaver Production Assistant",
+        "description": "Integral part of team producing multiple types of high-end woven baskets. Helped run day-to-day operations, and acted as a second opinion for decisions affecting future workflow.",
+        "date_start": "2016-05-14",
+        "date_end": "2021-01-08",
+        "order": 2,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
 }
 ]
diff --git a/resume_manager_core/fixtures/resume_manager/pillar_categories.json b/resume_manager_core/fixtures/resume_manager/pillar_categories.json
new file mode 100644
index 0000000..eaf4983
--- /dev/null
+++ b/resume_manager_core/fixtures/resume_manager/pillar_categories.json
@@ -0,0 +1,35 @@
+[
+{
+    "model": "resume_manager_core.pillarcategory",
+    "pk": 1,
+    "fields": {
+        "resume": 3,
+        "name": "Pillar One",
+        "order": 1,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.pillarcategory",
+    "pk": 2,
+    "fields": {
+        "resume": 3,
+        "name": "Pillar Two",
+        "order": 2,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.pillarcategory",
+    "pk": 3,
+    "fields": {
+        "resume": 3,
+        "name": "Pillar Three",
+        "order": 3,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+}
+]
diff --git a/resume_manager_core/fixtures/resume_manager/pillar_instances.json b/resume_manager_core/fixtures/resume_manager/pillar_instances.json
new file mode 100644
index 0000000..41a2b35
--- /dev/null
+++ b/resume_manager_core/fixtures/resume_manager/pillar_instances.json
@@ -0,0 +1,62 @@
+[
+{
+    "model": "resume_manager_core.pillarinstance",
+    "pk": 1,
+    "fields": {
+        "category": 1,
+        "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec elementum molestie euismod. Suspendisse rutrum, lacus non luctus lacinia, ante erat porttitor mauris, id vestibulum lacus turpis et purus. Phasellus odio diam, blandit sit amet mauris sed, molestie gravida ex. Vivamus augue dui, vehicula nec pellentesque in, scelerisque a mauris.",
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.pillarinstance",
+    "pk": 2,
+    "fields": {
+        "category": 1,
+        "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec elementum molestie euismod. Suspendisse rutrum, lacus non luctus lacinia, ante erat porttitor mauris, id vestibulum lacus turpis et purus. Phasellus odio diam, blandit sit amet mauris sed, molestie gravida ex. Vivamus augue dui, vehicula nec pellentesque in, scelerisque a mauris.",
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.pillarinstance",
+    "pk": 3,
+    "fields": {
+        "category": 1,
+        "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec elementum molestie euismod. Suspendisse rutrum, lacus non luctus lacinia, ante erat porttitor mauris, id vestibulum lacus turpis et purus. Phasellus odio diam, blandit sit amet mauris sed, molestie gravida ex. Vivamus augue dui, vehicula nec pellentesque in, scelerisque a mauris.",
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.pillarinstance",
+    "pk": 4,
+    "fields": {
+        "category": 2,
+        "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec elementum molestie euismod. Suspendisse rutrum, lacus non luctus lacinia, ante erat porttitor mauris, id vestibulum lacus turpis et purus. Phasellus odio diam, blandit sit amet mauris sed, molestie gravida ex. Vivamus augue dui, vehicula nec pellentesque in, scelerisque a mauris.",
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.pillarinstance",
+    "pk": 5,
+    "fields": {
+        "category": 2,
+        "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec elementum molestie euismod. Suspendisse rutrum, lacus non luctus lacinia, ante erat porttitor mauris, id vestibulum lacus turpis et purus. Phasellus odio diam, blandit sit amet mauris sed, molestie gravida ex. Vivamus augue dui, vehicula nec pellentesque in, scelerisque a mauris.",
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.pillarinstance",
+    "pk": 6,
+    "fields": {
+        "category": 2,
+        "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec elementum molestie euismod. Suspendisse rutrum, lacus non luctus lacinia, ante erat porttitor mauris, id vestibulum lacus turpis et purus. Phasellus odio diam, blandit sit amet mauris sed, molestie gravida ex. Vivamus augue dui, vehicula nec pellentesque in, scelerisque a mauris.",
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+}
+]
diff --git a/resume_manager_core/fixtures/resume_manager/resume_sections.json b/resume_manager_core/fixtures/resume_manager/resume_sections.json
index d450d23..0f807a3 100644
--- a/resume_manager_core/fixtures/resume_manager/resume_sections.json
+++ b/resume_manager_core/fixtures/resume_manager/resume_sections.json
@@ -82,7 +82,6 @@
         "name": "Contact Info",
         "css": [3, 16],
         "display_category": 3,
-        "separator_before": true,
         "date_created": "2023-01-01T08:00:00.000Z",
         "date_modified": "2023-01-01T08:00:00.000Z"
     }
@@ -209,7 +208,6 @@
         "name": "Contact Info",
         "css": [3, 16],
         "display_category": 3,
-        "separator_before": true,
         "date_created": "2023-01-01T08:00:00.000Z",
         "date_modified": "2023-01-01T08:00:00.000Z"
     }
@@ -331,5 +329,132 @@
         "date_created": "2023-01-01T08:00:00.000Z",
         "date_modified": "2023-01-01T08:00:00.000Z"
     }
+},
+{
+    "model": "resume_manager_core.resumesection",
+    "pk": 27,
+    "fields": {
+        "resume": 3,
+        "parent_section": null,
+        "name": "Page",
+        "css": [1],
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.resumesection",
+    "pk": 28,
+    "fields": {
+        "resume": 3,
+        "parent_section": 27,
+        "name": "Header Section",
+        "css": [2, 18, 19, 27],
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.resumesection",
+    "pk": 29,
+    "fields": {
+        "resume": 3,
+        "parent_section": 27,
+        "name": "Body Section",
+        "css": [3, 12, 19],
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.resumesection",
+    "pk": 30,
+    "fields": {
+        "resume": 3,
+        "parent_section": 27,
+        "name": "Footer Section",
+        "css": [2, 18, 19, 27, 41],
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.resumesection",
+    "pk": 31,
+    "fields": {
+        "resume": 3,
+        "parent_section": 28,
+        "name": "Header Left",
+        "css": [20, 29],
+        "display_category": 1,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.resumesection",
+    "pk": 32,
+    "fields": {
+        "resume": 3,
+        "parent_section": 28,
+        "name": "Header Right",
+        "css": [22, 29],
+        "display_category": 2,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.resumesection",
+    "pk": 33,
+    "fields": {
+        "resume": 3,
+        "parent_section": 29,
+        "name": "Contact Info",
+        "css": [3, 16],
+        "display_category": 3,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.resumesection",
+    "pk": 34,
+    "fields": {
+        "resume": 3,
+        "parent_section": 29,
+        "name": "Body SubSection",
+        "css": [2, 12],
+        "separator_before": true,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.resumesection",
+    "pk": 35,
+    "fields": {
+        "resume": 3,
+        "parent_section": 34,
+        "name": "Pillars",
+        "css": [3, 11, 16],
+        "display_category": 8,
+        "separator_after": true,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
+},
+{
+    "model": "resume_manager_core.resumesection",
+    "pk": 36,
+    "fields": {
+        "resume": 3,
+        "parent_section": 34,
+        "name": "Experience",
+        "css": [3, 5, 16],
+        "display_category": 5,
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
 }
 ]
diff --git a/resume_manager_core/fixtures/resume_manager/resumes.json b/resume_manager_core/fixtures/resume_manager/resumes.json
index 0707fa7..a7f460a 100644
--- a/resume_manager_core/fixtures/resume_manager/resumes.json
+++ b/resume_manager_core/fixtures/resume_manager/resumes.json
@@ -24,5 +24,18 @@
         "date_created": "2023-01-01T08:00:00.000Z",
         "date_modified": "2023-01-01T08:00:00.000Z"
     }
+},
+{
+    "model": "resume_manager_core.resume",
+    "pk": 3,
+    "fields": {
+        "name": "Example Blocky-Purple Resume - Pillars",
+        "user": 1,
+        "theme": 1,
+        "profession": "Full Stack <br> Software Engineer",
+        "last_activity": "2023-01-01",
+        "date_created": "2023-01-01T08:00:00.000Z",
+        "date_modified": "2023-01-01T08:00:00.000Z"
+    }
 }
 ]
diff --git a/resume_manager_core/management/commands/resume_manager_core__loadfixtures.py b/resume_manager_core/management/commands/resume_manager_core__loadfixtures.py
index 2e01d58..93295a4 100644
--- a/resume_manager_core/management/commands/resume_manager_core__loadfixtures.py
+++ b/resume_manager_core/management/commands/resume_manager_core__loadfixtures.py
@@ -45,6 +45,8 @@ class Command(BaseCommand):
         self.populate_skill_categories()
         self.populate_skill_instances()
         self.populate_reference_instances()
+        self.populate_pillar_categories()
+        self.populate_pillar_instances()
 
         print('{0}RESUME_MANAGER_CORE{1}: {2}Fixture Loading{3} complete.\n'.format(
             ConsoleColors.purple,
@@ -112,3 +114,15 @@ class Command(BaseCommand):
         Loads fixtures for ReferenceInstance models.
         """
         call_command('loaddata', 'resume_manager/reference_instances.json')
+
+    def populate_pillar_categories(self):
+        """
+        Loads fixtures for PillarCategory models.
+        """
+        call_command('loaddata', 'resume_manager/pillar_categories.json')
+
+    def populate_pillar_instances(self):
+        """
+        Loads fixtures for PillarInstance models.
+        """
+        call_command('loaddata', 'resume_manager/pillar_instances.json')
diff --git a/resume_manager_core/management/commands/resume_manager_core__seed.py b/resume_manager_core/management/commands/resume_manager_core__seed.py
index 173997e..85c9b26 100644
--- a/resume_manager_core/management/commands/resume_manager_core__seed.py
+++ b/resume_manager_core/management/commands/resume_manager_core__seed.py
@@ -59,6 +59,8 @@ class Command(BaseCommand):
         self.create_skill_categories(model_count)
         self.create_skill_instances(model_count)
         self.create_reference_instances(model_count)
+        self.create_pillar_categories(model_count)
+        self.create_pillar_instances(model_count)
 
         print('{0}RESUME_MANAGER{1}: {2}Seeding{3} complete.\n'.format(
             ConsoleColors.purple,
@@ -156,3 +158,21 @@ class Command(BaseCommand):
         app_fixtures.populate_reference_instances()
 
         # Seed logic goes here.
+
+    def create_pillar_categories(self, model_count):
+        """
+        Create seeds for PillarCategory models.
+        """
+        # Load preset fixtures.
+        app_fixtures.populate_pillar_categories()
+
+        # Seed logic goes here.
+
+    def create_pillar_instances(self, model_count):
+        """
+        Create seeds for PillarInstance models.
+        """
+        # Load preset fixtures.
+        app_fixtures.populate_pillar_instances()
+
+        # Seed logic goes here.
diff --git a/resume_manager_core/models.py b/resume_manager_core/models.py
index 49656be..dd4f380 100644
--- a/resume_manager_core/models.py
+++ b/resume_manager_core/models.py
@@ -85,6 +85,7 @@ class ResumeSection(WorkspaceModel):
     DISPLAY_CATEGORY__EXPERIENCE = 5
     DISPLAY_CATEGORY__SKILLS = 6
     DISPLAY_CATEGORY__REFERENCES = 7
+    DISPLAY_CATEGORY__PILLARS = 8
     DISPLAY_CATEGORY_CHOICES = (
         (DISPLAY_CATEGORY__NONE, 'None'),
         (DISPLAY_CATEGORY__CONTACT, 'Name'),
@@ -94,6 +95,7 @@ class ResumeSection(WorkspaceModel):
         (DISPLAY_CATEGORY__EXPERIENCE, 'Experience'),
         (DISPLAY_CATEGORY__SKILLS, 'Skills'),
         (DISPLAY_CATEGORY__REFERENCES, 'References'),
+        (DISPLAY_CATEGORY__PILLARS, 'Pillars'),
     )
 
     # Relationship Keys.
@@ -117,7 +119,6 @@ class ResumeSection(WorkspaceModel):
     display_category.help_text = 'Indicates what content (if any) should display in section.'
     separator_before.help_text = 'Indicates if a separator should be placed before section elements.'
     separator_after.help_text = 'indicates if a separator should be placed after section elements.'
-
     class Meta:
         verbose_name = 'Resume Section'
         verbose_name_plural = 'Resume Sections'
@@ -336,3 +337,49 @@ class ReferenceInstance(WorkspaceModel):
 
     def __str__(self):
         return '{0} - {1}'.format(self.resume, self.name)
+
+
+class PillarCategory(WorkspaceModel):
+    """An instance of an overall talking point "pillar"."""
+
+    # Relationship Keys.
+    resume = models.ForeignKey('Resume', on_delete=models.CASCADE)
+
+    # Model fields.
+    name = models.CharField(max_length=settings.MAX_LENGTH)
+    order = SmallIntegerRangeField(default=0, min_value=0, max_value=100)
+
+    # Field helper text.
+    name.help_text = 'Category\'s name.'
+    order.help_text = 'Ordering in relation to other pillar categories in the same resume.'
+
+    class Meta:
+        verbose_name = 'Pillar Category'
+        verbose_name_plural = 'Pillar Categories'
+        ordering = ('resume', 'order', 'id')
+
+    def __str__(self):
+        return '{0} - {1}'.format(self.resume, self.name)
+
+
+class PillarInstance(WorkspaceModel):
+    """An instance of a specific talking point in a "pillar"."""
+
+    # Relationship Keys.
+    category = models.ForeignKey('PillarCategory', on_delete=models.CASCADE)
+
+    # Model fields.
+    text = models.CharField(max_length=settings.MAX_LENGTH)
+    order = SmallIntegerRangeField(default=0, min_value=0, max_value=100)
+
+    # Field helper text.
+    text.help_text = 'Talking point display text.'
+    order.help_text = 'Ordering in relation to other pillar categories in the same resume.'
+
+    class Meta:
+        verbose_name = 'Pillar Instance'
+        verbose_name_plural = 'Pillar Instances'
+        ordering = ('category', 'order', 'id')
+
+    def __str__(self):
+        return '{0} - {1}'.format(self.category, self.order)
diff --git a/resume_manager_core/static/resume_manager_core/css/sass/src/_general_styles.scss b/resume_manager_core/static/resume_manager_core/css/sass/src/_general_styles.scss
index 476b461..d3128db 100644
--- a/resume_manager_core/static/resume_manager_core/css/sass/src/_general_styles.scss
+++ b/resume_manager_core/static/resume_manager_core/css/sass/src/_general_styles.scss
@@ -91,15 +91,16 @@ html {
       padding: 0;
     }
 
-    div {
-      padding: 5px;
-    }
-
     > div {
+      padding: 5px;
       padding-right: 15px;
       padding-left: 15px;
     }
 
+    > div > div {
+      padding: 5px;
+    }
+
     p {
       margin: 0;
       padding: 0;
@@ -143,7 +144,7 @@ html {
     .flex-horizontal {
       flex-direction: row;
 
-      hr {
+      > hr {
         height: 95%;
         margin-top: 20px;
         margin-right: 15px;
@@ -155,7 +156,7 @@ html {
     .flex-vertical {
       flex-direction: column;
 
-      hr {
+      > hr {
         width: 98%;
       }
     }
@@ -196,6 +197,10 @@ html {
       text-decoration: underline;
     }
 
+    .no-underline {
+      text-decoration: none !important;
+    }
+
     .color-section {
       h2, h3, h4, h5, h6 {
         text-align: center;
diff --git a/resume_manager_core/static/resume_manager_core/css/sass/src/_resume_blocky.scss b/resume_manager_core/static/resume_manager_core/css/sass/src/_resume_blocky.scss
index 74c919b..1fd2527 100644
--- a/resume_manager_core/static/resume_manager_core/css/sass/src/_resume_blocky.scss
+++ b/resume_manager_core/static/resume_manager_core/css/sass/src/_resume_blocky.scss
@@ -77,6 +77,11 @@ html {
 
         h2, h3, h4, h5, h6, p {
           color: #fff;
+
+        }
+
+        h2, h3, h4, h5, h6 {
+          text-decoration: underline;
         }
 
         span.bold {
diff --git a/resume_manager_core/static/resume_manager_core/css/sass/src/_text_styles.scss b/resume_manager_core/static/resume_manager_core/css/sass/src/_text_styles.scss
index eb61ad2..06de083 100644
--- a/resume_manager_core/static/resume_manager_core/css/sass/src/_text_styles.scss
+++ b/resume_manager_core/static/resume_manager_core/css/sass/src/_text_styles.scss
@@ -68,11 +68,6 @@ html {
     }
 
   }
-
-  // Purple blocky theme styles.
-  .theme-blocky.purple .page {
-
-  }
 }
 
 //===============================//
diff --git a/resume_manager_core/templates/resume_manager/_display_recurse.html b/resume_manager_core/templates/resume_manager/_display_recurse.html
index 2659f71..6cda0a4 100644
--- a/resume_manager_core/templates/resume_manager/_display_recurse.html
+++ b/resume_manager_core/templates/resume_manager/_display_recurse.html
@@ -9,7 +9,7 @@
 
   <div class="{{ data.section_css }}">
     {% if data.display_category == 'Name' %}
-      <h2 class="padding-00">{{ content.name }}</h2>
+      <h2 class="padding-00 no-underline">{{ content.name }}</h2>
     {% elif data.display_category == 'Profession' %}
       <div class="flex flex-vertical flex-justify-space-evenly flex-align-end padding-00">
         {% if content.profession2 %}
@@ -29,6 +29,8 @@
       {% include 'resume_manager/include/skills.html' with data=content.skills description=data.description %}
     {% elif data.display_category == 'References' %}
       {% include 'resume_manager/include/references.html' with data=content.references description=data.description %}
+    {% elif data.display_category == 'Pillars' %}
+      {% include 'resume_manager/include/pillars.html' with data=content.pillars description=data.description %}
     {% endif %}
 
     {% include 'resume_manager/_display_recurse.html' with data_subsection=data.section_children name=name profession=profession %}
diff --git a/resume_manager_core/templates/resume_manager/include/pillars.html b/resume_manager_core/templates/resume_manager/include/pillars.html
new file mode 100644
index 0000000..a6daa6b
--- /dev/null
+++ b/resume_manager_core/templates/resume_manager/include/pillars.html
@@ -0,0 +1,27 @@
+
+{% if description %}
+  <p class="emphasis">{{ description }}</p>
+{% endif %}
+
+
+<div class="flex flex-vertical">
+  {% if data %}
+    {% for category in data %}
+      <div class="flex flex-vertical flex-justify-space-between">
+        <h3 class="align-left emphasis padding-05">{{ category.category }}</h3>
+        {% if category.pillars %}
+          <ul class="flex flex-vertical flex-align-start">
+            {% for pillar in category.pillars %}
+              <li class="padding-05"><p class="align-justify font-size-small"> - {{ pillar }}</p></li>
+            {% endfor %}
+          </ul>
+        {% else %}
+          <p>No pillar contents yet.</p>
+        {% endif %}
+      </div>
+    {% endfor %}
+  {% else %}
+    <h3 class="underline">Talking Point Pillars</h3>
+    <p>No pillars yet.</p>
+  {% endif %}
+</div>
diff --git a/resume_manager_core/templates/resume_manager/include/skills.html b/resume_manager_core/templates/resume_manager/include/skills.html
index 8aacffa..544d735 100644
--- a/resume_manager_core/templates/resume_manager/include/skills.html
+++ b/resume_manager_core/templates/resume_manager/include/skills.html
@@ -1,5 +1,5 @@
 
-<h3 class="underline">Skills & Technologies</h3>
+<h3>Skills & Technologies</h3>
 
 
 {% if description %}
diff --git a/resume_manager_core/views.py b/resume_manager_core/views.py
index 197ced4..6ddab9e 100644
--- a/resume_manager_core/views.py
+++ b/resume_manager_core/views.py
@@ -26,6 +26,8 @@ from .models import (
     ReferenceInstance,
     SkillCategory,
     SkillInstance,
+    PillarCategory,
+    PillarInstance,
 )
 
 
@@ -150,6 +152,7 @@ class DisplayResume(DetailView):
             })
 
         # Organize resume data into parse-able structures.
+        # Handle "skills" section, if present.
         skill_categories = SkillCategory.objects.filter(resume=self.resume)
         skills = SkillInstance.objects.filter(category__in=skill_categories)
         skill_data = []
@@ -161,7 +164,7 @@ class DisplayResume(DetailView):
                     'skills': [],
                 }
 
-                # Add all skills that
+                # Add all skills that match category.
                 for skill in skills:
                     if skill.category == category:
                         # Add skill to category.
@@ -169,6 +172,26 @@ class DisplayResume(DetailView):
 
                 skill_data.append(category_data)
 
+        # Handle "pillars" section, if present.
+        pillar_categories = PillarCategory.objects.filter(resume=self.resume)
+        pillars = PillarInstance.objects.filter(category__in=pillar_categories)
+        pillar_data = []
+        if len(pillars) > 0:
+            for category in pillar_categories:
+
+                category_data = {
+                    'category': category.name,
+                    'pillars': [],
+                }
+
+                # Add all pillars that match category.
+                for pillar in pillars:
+                    if pillar.category == category:
+                        # Add pillar to category.
+                        category_data['pillars'].append(pillar.text)
+
+                pillar_data.append(category_data)
+
         # Pull together possible resume content.
         resume_content = {
             'name': user_name,
@@ -180,6 +203,7 @@ class DisplayResume(DetailView):
             'experience': ExperienceInstance.objects.filter(resume=self.resume) or None,
             'skills': skill_data,
             'references': ReferenceInstance.objects.filter(resume=self.resume) or None,
+            'pillars': pillar_data,
         }
 
         # Update template context.
@@ -194,7 +218,7 @@ class DisplayResume(DetailView):
         return context
 
     def build_resume_data(self, current_section, all_sections):
-        """Recursive function to format resume data structure for template output."""
+        """Recursive function to parse meta-data and format structure for template output."""
         # Get all related children.
         section_children = all_sections.filter(
             parent_section=current_section
@@ -214,21 +238,6 @@ class DisplayResume(DetailView):
                 section_css_data.add(css_class)
         section_css_data = ' '.join(list(section_css_data))
 
-    #     # Get all headers for section.
-    #     section_header = DataSectionHeader.objects.filter(
-    #         resume_section=current_section,
-    #     )
-    #
-    #     # Get all key-value pairs for section.
-    #     section_key_value_pairs = DataKeyValue.objects.filter(
-    #         resume_section=current_section,
-    #     )
-    #
-    #     # Get all items for section.
-    #     section_items = DataItem.objects.filter(
-    #         resume_section=current_section,
-    #     )
-
         # Organize data value.
         return {
             'section': current_section,
@@ -238,7 +247,4 @@ class DisplayResume(DetailView):
             'separator_before': current_section.separator_before,
             'separator_after': current_section.separator_after,
             'display_category': ResumeSection.DISPLAY_CATEGORY_CHOICES[current_section.display_category][1],
-            # 'section_header': section_header,
-            # 'section_key_value_pairs': section_key_value_pairs,
-            # 'section_items': section_items,
         }
-- 
GitLab