{$Section->getTitle()|escape} Public Feed
+
+ {$Section->getTitle()|escape}
+
+ Public Feed
+ {if $blogTag}
+ for tag {$blogTag->getTitle()|escape}
+ {/if}
+
+
-
-
-{/block}
\ No newline at end of file
+{/block}
diff --git a/php-classes/Slate/Courses/Section.php b/php-classes/Slate/Courses/Section.php
index a6c3b60cf..8a0afbd07 100644
--- a/php-classes/Slate/Courses/Section.php
+++ b/php-classes/Slate/Courses/Section.php
@@ -6,12 +6,14 @@
use HandleBehavior;
use DuplicateKeyException;
use TableNotFoundException;
+use TagItem;
use Emergence\People\IPerson;
use Emergence\People\Person;
use Emergence\People\User;
use Emergence\Locations\Location;
use Emergence\Connectors\Mapping;
+use Emergence\CMS\BlogPost;
use Slate\Term;
use Slate\Courses\SectionParticipant;
@@ -186,7 +188,13 @@ class Section extends \VersionedRecord
,'class' => Mapping::class
,'contextClass' => __CLASS__
]
- ];
+ ,'BlogPosts' => [
+ 'type' => 'one-many'
+ ,'class' => BlogPost::class
+ ,'contextClass' => __CLASS__
+ ,'foreign' => 'ContextID'
+ ]
+ ];
public static $validators = [
'Course' => [
@@ -411,6 +419,69 @@ public function getCohorts()
}
}
+ public function findBlogTags()
+ {
+ return TagItem::getTagsSummary([
+ 'Class' => BlogPost::class,
+ 'classConditions' => [
+ 'ContextClass' => static::getStaticRootClass(),
+ 'ContextID' => $this->ID
+ ]
+ ]);
+ }
+
+ public function findBlogPosts($conditions, $limit, $offset, $tag)
+ {
+ $options = [
+ 'limit' => $limit,
+ 'offset' => $offset,
+ 'calcFoundRows' => 'yes',
+ 'conditions' => $conditions
+ ];
+
+ if ($tag!=null) {
+
+ $tagItemIDs = DB::allValues(
+ 'ContextID',
+ 'SELECT ContextID FROM `tag_items` WHERE (`ContextClass` = "%s") AND (`TagID` = %u)',
+ [
+ DB::escape(BlogPost::getStaticRootClass()),
+ $tag->ID
+ ]
+ );
+
+ $options = array_merge_recursive($options, [
+ 'conditions' => [
+ 'ID' => [
+ 'operator' => 'IN',
+ 'values' => count($tagItemIDs) ? $tagItemIDs : '0'
+ ]
+ ]
+ ]);
+ }
+
+ return BlogPost::getAllPublishedByContextObject($this, $options);
+ }
+
+ public function findLatestTeacherPost()
+ {
+ $sectionTeacherIds = array_map(function($Teacher) {
+ return $Teacher->ID;
+ }, $this->ActiveTeachers);
+
+ $latestTeacherPost = BlogPost::getAllPublishedByContextObject($this, array_merge_recursive([
+ 'conditions' => [
+ 'AuthorID' => [
+ 'operator' => 'IN',
+ 'values' => $sectionTeacherIds
+ ]
+ ],
+ 'limit' => 1
+ ]));
+
+ return count($latestTeacherPost) ? $latestTeacherPost[0] : null;
+ }
+
// search SQL generators
protected static function getTeacherSearchSql($term, $condition)
{
diff --git a/php-classes/Slate/Courses/SectionsRequestHandler.php b/php-classes/Slate/Courses/SectionsRequestHandler.php
index 85dab1894..e515043b4 100644
--- a/php-classes/Slate/Courses/SectionsRequestHandler.php
+++ b/php-classes/Slate/Courses/SectionsRequestHandler.php
@@ -5,6 +5,7 @@
use DB;
use ActiveRecord;
use DuplicateKeyException;
+use Tag;
use Emergence\People\Person;
use Emergence\People\User;
@@ -110,11 +111,53 @@ public static function handleRecordRequest(ActiveRecord $Section, $action = fals
]));
case 'students':
return static::handleStudentsRequest($Section);
+ case '':
+ case false:
+ return static::handleSectionRequest($Section, $action);
default:
return parent::handleRecordRequest($Section, $action);
}
}
+ public static function handleSectionRequest(Section $Section, $action)
+ {
+ $className = static::$recordClass;
+
+ $limit = isset($_REQUEST['limit']) && ctype_digit($_REQUEST['limit']) ? (integer)$_REQUEST['limit'] : 10;
+ $offset = isset($_REQUEST['offset']) && ctype_digit($_REQUEST['offset']) ? (integer)$_REQUEST['offset'] : 0;
+ $handle = $_REQUEST['blog-tag'];
+
+ $conditions = [];
+ $latestTeacherPost = false;
+ $tag = null;
+
+ if ($handle) {
+ $tag = Tag::getByHandle($handle);
+
+ if (!$tag) {
+ return static::throwNotFoundError('tag not found');
+ }
+ } else {
+ $latestTeacherPost = $Section->findLatestTeacherPost();
+
+ if ($latestTeacherPost) {
+ $conditions[] = sprintf('ID != %u', $latestTeacherPost->ID);
+ }
+ }
+
+ return static::respond(static::getTemplateName($className::$singularNoun), array(
+ 'success' => true
+ ,'data' => $Section
+ ,'tags' => $Section->findBlogTags()
+ ,'blogTag' => $tag
+ ,'latestTeacherPost' => $latestTeacherPost
+ ,'blogPosts' => $Section->findBlogPosts($conditions, $limit ?: 4, $offset, $tag )
+ ,'total' => DB::foundRows()
+ ,'limit' => $limit
+ ,'offset' => $offset
+ ));
+ }
+
public static function handleCohortsRequest(Section $Section)
{
return static::respond('sectionCohorts', [
diff --git a/site-root/sass/slate/_common.scss b/site-root/sass/slate/_common.scss
index 2324fc178..a60173a13 100644
--- a/site-root/sass/slate/_common.scss
+++ b/site-root/sass/slate/_common.scss
@@ -45,13 +45,33 @@ body {
}
}
-.text-left { text-align: left !important; }
-.text-right { text-align: right !important; }
-.text-center { text-align: center !important; }
-.text-justify { text-align: justify !important; }
-.text-nowrap { white-space: nowrap !important; }
-.text-nolead { margin-top: 0 !important; }
-.text-notrail { margin-bottom: 0 !important; }
+.text-left {
+ text-align: left !important;
+}
+
+.text-right {
+ text-align: right !important;
+}
+
+.text-center {
+ text-align: center !important;
+}
+
+.text-justify {
+ text-align: justify !important;
+}
+
+.text-nowrap {
+ white-space: nowrap !important;
+}
+
+.text-nolead {
+ margin-top: 0 !important;
+}
+
+.text-notrail {
+ margin-bottom: 0 !important;
+}
.sidebar-item {
margin: 1em 0 3em;
@@ -59,6 +79,40 @@ body {
.empty-text {
margin: .5em 0;
}
+
+ .sidebar-collapsible-toggle {
+ background-color: rgba($text-color, .05);
+ border-radius: .25em;
+ cursor: pointer;
+ font-size: .75em;
+ margin-top: 1em;
+ padding: .25em;
+ text-align: center;
+ text-transform: uppercase;
+
+ &:hover,
+ &:focus {
+ background-color: rgba($text-color, .1);
+ }
+ }
+
+ .collapsible-collapse-text {
+ display: none;
+ }
+
+ .sidebar-collapsible[open] {
+ >.sidebar-collapsible-toggle {
+ margin-bottom: 1em;
+ }
+
+ .collapsible-expand-text {
+ display: none;
+ }
+
+ .collapsible-collapse-text {
+ display: unset;
+ }
+ }
}
.sidebar-item-title {
@@ -94,7 +148,7 @@ body {
width: 250px;
}
- > .inner {
+ >.inner {
background-position: center;
background-repeat: no-repeat;
background-size: cover;
@@ -111,4 +165,4 @@ body {
margin: 1em 0 0;
}
}
-}
\ No newline at end of file
+}
diff --git a/site-root/sass/slate/_modules.scss b/site-root/sass/slate/_modules.scss
index e243bb362..f0956ea03 100644
--- a/site-root/sass/slate/_modules.scss
+++ b/site-root/sass/slate/_modules.scss
@@ -15,5 +15,6 @@
@import 'modules/slate-menu';
@import 'modules/source-grid';
@import 'modules/splitview';
+@import 'modules/tag-list';
@import 'modules/todo';
-@import 'modules/wizards';
\ No newline at end of file
+@import 'modules/wizards';
diff --git a/site-root/sass/slate/modules/_key-value-list.scss b/site-root/sass/slate/modules/_key-value-list.scss
index 7391c7371..cf6b8d626 100644
--- a/site-root/sass/slate/modules/_key-value-list.scss
+++ b/site-root/sass/slate/modules/_key-value-list.scss
@@ -13,6 +13,7 @@
.kv-key,
.kv-value {
margin: 0;
+ padding: 0;
}
.kv-key {
@@ -34,12 +35,16 @@
.kv-pair {
display: table-row;
}
-
+
.kv-key,
- .kv-value {
+ .kv-value,
+ > .kv-key,
+ > .kv-value {
display: table-cell;
+ padding-bottom: 0;
+ padding-top: 0;
}
-
+
.kv-key {
padding-right: 1em;
}
@@ -51,4 +56,4 @@
.kv-key {
text-align: right;
}
-}
\ No newline at end of file
+}
diff --git a/site-root/sass/slate/modules/_people.scss b/site-root/sass/slate/modules/_people.scss
index c6e271f8b..a9937d3a0 100644
--- a/site-root/sass/slate/modules/_people.scss
+++ b/site-root/sass/slate/modules/_people.scss
@@ -2,40 +2,42 @@
@include background-size(cover);
}
-$roster-avatar-size: 64px;
-$roster-item-width: $roster-avatar-size * 1.3125;
-$roster-font-size: $font-size * .6875;
-$roster-line-height: $line-height * .8;
-
.roster {
+ display: grid;
+ grid-gap: 1em .5em;
+ grid-template-columns: repeat(3, 1fr);
margin: 0;
padding: 0;
-
+
li {
- display: inline-block;
- font-size: $roster-font-size;
- height: $roster-avatar-size + (($roster-line-height * $roster-font-size) * 2.5);
- line-height: $roster-line-height;
+ font-size: .75em;
+ line-height: 1.25;
list-style: none;
- margin-bottom: .75em;
- overflow: hidden;
+ min-width: 0;
text-align: center;
- vertical-align: text-bottom;
- width: $roster-item-width;
}
-
+
a {
+ display: block;
text-decoration: none;
-
+
&:hover,
&:focus {
text-decoration: underline;
}
}
-
+
.avatar {
+ border-radius: 100%;
+ box-shadow: 0 1px 2px rgba(0,0,0,.1);
margin: 0 auto .25em;
}
+
+ .name {
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
}
.about-bio {
@@ -43,7 +45,7 @@ $roster-line-height: $line-height * .8;
color: inherit;
font-size: 1em;
}
-
+
.well-title {
color: $heading-color;
font-size: 1.2em;
@@ -58,4 +60,4 @@ $roster-line-height: $line-height * .8;
text-overflow: ellipsis;
white-space: nowrap;
}
-}
\ No newline at end of file
+}
diff --git a/site-root/sass/slate/modules/_tag-list.scss b/site-root/sass/slate/modules/_tag-list.scss
new file mode 100644
index 000000000..ba0dad9aa
--- /dev/null
+++ b/site-root/sass/slate/modules/_tag-list.scss
@@ -0,0 +1,30 @@
+.tag-list {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+
+ >li {
+ display: inline-block;
+ }
+
+ .tag {
+ background-color: rgba($link-color, .05);
+ border-radius: .25em;
+ display: block;
+ font-size: .875em;
+ margin-bottom: .25em;
+ padding: 0 .5em;
+ text-decoration: none;
+
+ &:hover,
+ &:focus {
+ background-color: rgba($link-color, .1);
+ }
+ }
+
+ .tag-count {
+ color: rgba($text-color, .4);
+ font-size: .75em;
+ font-weight: bold;
+ }
+}
{$Section->Code|escape}
- - {if $Section->Course->Description} -{$Section->Course->Description|escape|markdown}
- {/if}
-
- -
-
- Term -
- {$Section->Term->Title} -
- Schedule -
- {$Section->Schedule->Title} -
- Location -
- {$Section->Location->Title} +
- Notes -
- {$Section->Notes|escape|markdown} +
- Term +
- {$Section->Term->Title}
- Schedule +
- {$Section->Schedule->Title} +
- Location +
- {$Section->Location->Title} +
- Notes +
- {$Section->Notes|escape|markdown} +
- {personLink $Teacher photo=true} - {foreachelse} -
- {personLink $Student photo=true} - {foreachelse} -
- + {$tag.Title|escape} {$tag.itemsCount} + + {/foreach} +
- + {$tag.Title|escape} {$tag.count} + + {/foreach} +
- {personLink $Teacher photo=true} + {foreachelse} +
- {personLink $Student photo=true} + {foreachelse} +
-
-
- {if $.User}
-
-
-
-
+
+
+
+
+ {if $Section->Course->Description}
+
+
+ {if $.User}
+
{template linksEntry entry}
{if $entry.href}{/if}
@@ -135,9 +118,22 @@
{/template}
{foreach item=linkGroup from=Slate\UI\SectionProfile::getLinks($Section)}
+ {* spaces in key names here are parsed wrong *}
+ {$linksIcons = array(
+ 'CourseTools' => 'wrench',
+ 'OtherWebsites' => 'external-link',
+ )}
+ {$labelNoSpaces = str_replace(' ', '', $linkGroup.label)}
+
+
+
+ {$Section->Code|escape}
+
+
+ {if $Section->Course->Description}
+ {$Section->Course->Description|escape|markdown}
{/if}
- {if $Section->Notes}
+
-
- {/if}
-
+
+
+
+ {/if}
+
+ {if $Section->Notes}
+
+
+ {/if}
+
+
+
-
+
{/foreach}
- {linksEntry $linkGroup}
+
+
+
+
+
+ {linksEntry $linkGroup}
+
-
{foreach item=link from=$linkGroup.children}
@@ -157,27 +153,91 @@
Teacher{tif count($Section->ActiveTeachers) != 1 ? s}
--
- {foreach item=Teacher from=$Section->ActiveTeachers}
-
No instructors currently listed.
- {/foreach} -
+
{/if}
+
+
+ + + + + Blog Tags +
+ + {* if there's 10 or more, show the first five and collapse the rest *} + {if count($tags) >= 10} + {$tagsShown = array_slice($tags, 0, 5)} + {$tagsHidden = array_slice($tags, 5)} + {else} + {* less than 10, just show them all *} + {$tagsShown = $tags} + {/if} - {if $.User} -Students
--
- {foreach item=Student from=$Section->ActiveStudents}
-
No students currently listed.
- {/foreach} --
+ {foreach item=tag from=$tagsShown}
+
+
+ {/if}
+ + See all + See less +
+ +-
+ {foreach item=tag from=$tagsHidden}
+
+
+
+ {if $.User}
+
+
+ + + + + Teacher{tif count($Section->ActiveTeachers) != 1 ? s} +
+-
+ {foreach item=Teacher from=$Section->ActiveTeachers}
+
No instructors currently listed.
+ {/foreach} +
+
+ {/if}
+
+ + + + + Students +
+-
+ {foreach item=Student from=$Section->ActiveStudents}
+
No students currently listed.
+ {/foreach} +