Commit a8417df7 by marco

styling for recursive xblock rendering structure to be used in the container…

styling for recursive xblock rendering structure to be used in the container page, pulling from general xblock styles in a separate file.
parent 1b4388ee
......@@ -35,7 +35,6 @@ __all__ = ['OPEN_ENDED_COMPONENT_TYPES',
'ADVANCED_COMPONENT_POLICY_KEY',
'subsection_handler',
'unit_handler',
'container_handler',
'component_handler'
]
......@@ -305,159 +304,6 @@ def unit_handler(request, tag=None, package_id=None, branch=None, version_guid=N
return HttpResponseBadRequest("Only supports html requests")
@require_http_methods(["GET"])
@login_required
def container_handler(request, tag=None, package_id=None, branch=None, version_guid=None, block=None):
"""
The restful handler for unit-specific requests.
GET
html: return html page for editing a unit
json: not currently supported
"""
if 'text/html' in request.META.get('HTTP_ACCEPT', 'text/html'):
locator = BlockUsageLocator(package_id=package_id, branch=branch, version_guid=version_guid, block_id=block)
try:
old_location, course, item, lms_link = _get_item_in_course(request, locator)
except ItemNotFoundError:
return HttpResponseBadRequest()
component_templates = defaultdict(list)
for category in COMPONENT_TYPES:
component_class = _load_mixed_class(category)
# add the default template
# TODO: Once mixins are defined per-application, rather than per-runtime,
# this should use a cms mixed-in class. (cpennington)
if hasattr(component_class, 'display_name'):
display_name = component_class.display_name.default or 'Blank'
else:
display_name = 'Blank'
component_templates[category].append((
display_name,
category,
False, # No defaults have markdown (hardcoded current default)
None # no boilerplate for overrides
))
# add boilerplates
if hasattr(component_class, 'templates'):
for template in component_class.templates():
filter_templates = getattr(component_class, 'filter_templates', None)
if not filter_templates or filter_templates(template, course):
component_templates[category].append((
template['metadata'].get('display_name'),
category,
template['metadata'].get('markdown') is not None,
template.get('template_id')
))
# Check if there are any advanced modules specified in the course policy.
# These modules should be specified as a list of strings, where the strings
# are the names of the modules in ADVANCED_COMPONENT_TYPES that should be
# enabled for the course.
course_advanced_keys = course.advanced_modules
# Set component types according to course policy file
if isinstance(course_advanced_keys, list):
for category in course_advanced_keys:
if category in ADVANCED_COMPONENT_TYPES:
# Do I need to allow for boilerplates or just defaults on the
# class? i.e., can an advanced have more than one entry in the
# menu? one for default and others for prefilled boilerplates?
try:
component_class = _load_mixed_class(category)
component_templates['advanced'].append(
(
component_class.display_name.default or category,
category,
False,
None # don't override default data
)
)
except PluginMissingError:
# dhm: I got this once but it can happen any time the
# course author configures an advanced component which does
# not exist on the server. This code here merely
# prevents any authors from trying to instantiate the
# non-existent component type by not showing it in the menu
pass
else:
log.error(
"Improper format for course advanced keys! %s",
course_advanced_keys
)
components = [
loc_mapper().translate_location(
course.location.course_id, component.location, False, True
)
for component
in item.get_children()
]
# TODO (cpennington): If we share units between courses,
# this will need to change to check permissions correctly so as
# to pick the correct parent subsection
containing_subsection_locs = modulestore().get_parent_locations(old_location, None)
containing_subsection = modulestore().get_item(containing_subsection_locs[0])
containing_section_locs = modulestore().get_parent_locations(
containing_subsection.location, None
)
containing_section = modulestore().get_item(containing_section_locs[0])
# cdodge hack. We're having trouble previewing drafts via jump_to redirect
# so let's generate the link url here
# need to figure out where this item is in the list of children as the
# preview will need this
index = 1
for child in containing_subsection.get_children():
if child.location == item.location:
break
index = index + 1
preview_lms_base = settings.FEATURES.get('PREVIEW_LMS_BASE')
preview_lms_link = (
'//{preview_lms_base}/courses/{org}/{course}/'
'{course_name}/courseware/{section}/{subsection}/{index}'
).format(
preview_lms_base=preview_lms_base,
lms_base=settings.LMS_BASE,
org=course.location.org,
course=course.location.course,
course_name=course.location.name,
section=containing_section.location.name,
subsection=containing_subsection.location.name,
index=index
)
return render_to_response('container.html', {
'context_course': course,
'unit': item,
'unit_locator': locator,
'components': components,
'component_templates': component_templates,
'draft_preview_link': preview_lms_link,
'published_preview_link': lms_link,
'subsection': containing_subsection,
'release_date': (
get_default_time_display(containing_subsection.start)
if containing_subsection.start is not None else None
),
'section': containing_section,
'new_unit_category': 'vertical',
'unit_state': compute_unit_state(item),
'published_date': (
get_default_time_display(item.published_date)
if item.published_date is not None else None
),
})
else:
return HttpResponseBadRequest("Only supports html requests")
@login_required
def _get_item_in_course(request, locator):
"""
......
......@@ -66,9 +66,6 @@ domReady(function() {
}
});
// container navigation links - tooltips on overflow
$('a.navigation-link').bind('mouseenter', overflowTooltip);
// general link management - new window/tab
$('a[rel="external"]').attr('title', gettext('This link will open in a new browser window/tab')).bind('click', linkNewWindow);
......@@ -120,12 +117,6 @@ domReady(function() {
IframeUtils.iframeBinding();
});
function overflowTooltip(e) {
(e).preventDefault();
if ($(this).offsetWidth < this.scrollWidth && !this.attr('data-tooltip'))
$this.attr('data-tooltip', $this.text());
}
function smoothScrollLink(e) {
(e).preventDefault();
......
......@@ -56,7 +56,7 @@ h1 {
font-weight: 600;
color: $gray-d3;
.navigation, .navigation-divider, .subtitle {
.navigation, .subtitle {
@extend %t-title7;
position: relative;
top: ($baseline/4);
......@@ -324,38 +324,41 @@ p, ul, ol, dl {
}
}
// layout with actions
// layout with navigation
&.has-navigation {
.nav-actions {
bottom: -($baseline*1.5);
}
.navigation-link {
@extend %cont-truncated;
display: inline-block;
overflow: hidden;
max-width: 150px;
color: inherit;
text-overflow: ellipsis;
white-space: nowrap;
&:hover {
color: $blue-s1;
&.navigation-current {
@extend %ui-disabled;
color: $gray;
&:after {
color: $gray-l2;
&:before {
color: $gray;
}
}
}
.navigation-link:after {
content: "/";
margin: 0px $baseline/4;
color: inherit;
.navigation-link:before {
content: " / ";
margin: ($baseline/4);
color: $gray;
&:hover {
color: inherit;
}
&:hover {
color: $gray;
}
}
.nav-actions {
bottom: -($baseline*1.5);
.navigation .navigation-link:first-child:before {
content: "";
margin: 0;
}
}
}
......
......@@ -42,6 +42,7 @@ $gray-l3: tint($gray,60%);
$gray-l4: tint($gray,80%);
$gray-l5: tint($gray,90%);
$gray-l6: tint($gray,95%);
$gray-l7: tint($gray,99%);
$gray-d1: shade($gray,20%);
$gray-d2: shade($gray,40%);
$gray-d3: shade($gray,60%);
......
......@@ -246,4 +246,4 @@
// canned animation - use if you want out of the box/non-customized anim
%anim-flashDouble {
@include animation(flashDouble $tmg-f1 ease-in-out 1);
}
\ No newline at end of file
}
......@@ -203,6 +203,66 @@
// ====================
// UI: element actions list
%actions-header {
.actions-list {
display: inline-block;
margin-bottom: 0;
}
.action-item {
display: inline-block;
.action-button {
@include transition(all $tmg-f2 ease-in-out 0s);
border-radius: 3px;
padding: ($baseline/4) ($baseline/2);
height: ($baseline*1.5);
color: $gray-l1;
&:hover {
background-color: $blue;
color: $gray-l6;
}
.action-button-text {
padding-left: 1px;
text-transform: uppercase;
}
&.delete-button:hover {
background-color: $gray-l1;
}
}
}
}
// UI: elem is collapsible
%expand-collapse {
@include transition(all $tmg-f2 linear 0s);
display: inline-block;
color: $gray-l2;
vertical-align: top;
&:hover {
color: $blue;
}
.ui-toggle-expansion {
@include transition(all $tmg-f2 ease-in-out 0s);
@include font-size(18);
display: inline-block;
margin-right: ($baseline/4);
color: $gray-l3;
vertical-align: middle;
}
&.expand .ui-toggle-expansion {
@include transform(rotate(-90deg));
@include transform-origin(50% 50%);
}
}
// UI: drag handles
.drag-handle {
......
// studio - elements - xblock rendering
// ==========================
// extends - UI archetypes - xblock rendering
%wrap-xblock {
margin: ($baseline/2);
border: 1px solid $gray-l4;
border-radius: ($baseline/5);
background: $white;
box-shadow: 0px 1px 1px $shadow-l1;
&:hover {
box-shadow: 0 0 1px $shadow;
}
// UI: xblock header
.xblock-header {
@include box-sizing(border-box);
@include ui-flexbox();
@extend %ui-align-center-flex;
border-bottom: 1px solid $gray-l4;
border-radius: ($baseline/5) ($baseline/5) 0 0;
min-height: ($baseline*2.5);
background-color: $gray-l6;
.header-details {
@extend %cont-truncated;
@extend %ui-justify-left-flex;
@include ui-flexbox();
padding-left: flex-gutter();
width: flex-grid(6,12);
vertical-align: top;
}
.header-actions {
@include ui-flexbox();
@extend %ui-justify-right-flex;
width: flex-grid(6,12);
vertical-align: top;
}
}
// UI: xblock render
.xblock-render {
@extend %anim-fadeIn;
}
}
// ====================
// UI: xblocks - calls-to-action
.wrapper-xblock .header-actions {
@extend %actions-header;
}
// UI: xblock is collapsible
.wrapper-xblock.is-collapsible {
.expand-collapse {
@extend %expand-collapse;
margin: 0 ($baseline/4);
}
&.collapsed .xblock-render {
display: none;
}
.action-view {
.action-button-text {
padding-right: ($baseline/5);
padding-left: 0;
}
}
}
......@@ -27,6 +27,7 @@
@import 'elements/typography';
@import 'elements/icons'; // references to icons used
@import 'elements/controls'; // buttons, link styles, sliders, etc.
@import 'elements/xblocks'; // studio rendering chrome for xblocks
// base - specific views
@import 'views/account';
......
......@@ -325,24 +325,27 @@
}
}
// uses similar styling as unit.scss, static-pages.scss
.action-item {
display: inline-block;
margin: ($baseline/4) 0 ($baseline/4) ($baseline/4);
// UI: assets - calls-to-action
.actions-list {
@extend %actions-header;
.action-button {
@include transition(all $tmg-f2 ease-in-out 0s);
display: block;
height: ($baseline*1.5);
width: ($baseline*1.5);
border-radius: 3px;
color: $gray-l3;
.action-item {
display: inline-block;
margin: ($baseline/4) 0 ($baseline/4) ($baseline/4);
&:hover {
background-color: $blue;
color: $gray-l6;
.action-button {
padding: 0;
display: block;
width: ($baseline*1.5);
height: ($baseline*1.5);
color: $gray-l3;
}
}
}
}
// UI: assets - specific action styling
// TODO: this uses similar styling as unit.scss, static-pages.scss
.action-item {
[class^="icon-"] {
display: inline-block;
......
......@@ -105,34 +105,15 @@
}
// general action list styles (section and subsection)
// UI: general action list styles (section and subsection)
.expand-collapse {
@include transition(all $tmg-f2 linear 0s);
display: inline-block;
vertical-align: top;
@extend %expand-collapse;
margin: 0 ($baseline/4);
color: $gray-l2;
&:hover {
color: $blue;
}
.ui-toggle-expansion {
@include transition(all $tmg-f2 ease-in-out 0s);
@include font-size(18);
display: inline-block;
vertical-align: middle;
margin-right: ($baseline/4);
color: $gray-l3;
}
&.expand .ui-toggle-expansion {
@include transform(rotate(-90deg));
@include transform-origin(50% 50%);
}
}
// UI: element actions list
// TODO: outline page can be updated to reflect styling from %actions-header extend in _controls.scss
.actions-list {
display: inline-block;
margin-bottom: 0;
......@@ -141,7 +122,7 @@
.actions-item {
@include font-size(13);
display: inline-block;
padding: 0 4px;
padding: 0 ($baseline/5);
vertical-align: middle;
.action {
......
......@@ -132,7 +132,7 @@
.component-actions {
display: inline-block;
float: right;
float: right;
margin-right: $baseline*2;
padding: 8px 0px;
vertical-align: middle;
......
......@@ -420,6 +420,19 @@ body.course.unit,.view-unit {
}
}
// Special xBlock and xModule styling
.xblock-type-container {
.xblock-header-elementlevel {
line-height: $baseline*2;
min-height: $baseline*2;
}
.xblock-render-elementlevel {
display: none;
}
}
.xblock-student_view {
padding: 2*$baseline $baseline $baseline;
overflow-x: auto;
......@@ -1331,3 +1344,32 @@ body.unit {
div.wrapper-comp-editor.is-inactive ~ div.launch-latex-compiler{
display: none;
}
// ====================
// xblock - unit page container
body.unit .xblock-type-container {
@extend %wrap-xblock;
margin: 0;
&:hover {
@include transition(all $tmg-f2 linear 0s);
border-color: $blue;
box-shadow: 0 0 1px $shadow-d1;
}
.xblock-header {
margin-bottom: 0;
border-bottom: 0;
border-radius: ($baseline/5);
.xblock-details {
font-size: .9em;
}
}
.xblock-render {
display: none;
}
}
<%inherit file="base.html" />
<%!
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
%>
<%block name="title">${_("Container")}</%block>
<%block name="bodyclass">is-signedin course uploads view-container</%block>
<%namespace name='static' file='static_content.html'/>
<%namespace name="units" file="widgets/units.html" />
<%block name="header_extras">
% for template_name in [ ]:
<script type="text/template" id="${template_name}-tpl">
<%static:include path="js/${template_name}.underscore" />
</script>
% endfor
</%block>
<%block name="jsextra">
<script type='text/javascript'>
require(["domReady!", "jquery", "js/models/module_info", "coffee/src/views/unit", "jquery.ui"],
function(doc, $, ModuleModel, UnitEditView, ui) {
var model;
window.unit_location_analytics = '${unit_locator}';
// tabs
$('.tab-group').tabs();
model = new ModuleModel({
id: '${unit_locator}',
state: '${unit_state}'
});
new UnitEditView({
el: $('.wrapper'),
model: model
});
$('.new-component-template').each(function(){
$emptyEditor = $(this).find('.empty');
$(this).prepend($emptyEditor);
});
});
</script>
</%block>
<%block name="content">
<div class="wrapper-mast wrapper">
<header class="mast has-actions has-navigation">
<h1 class="page-header">
<small class="navigation navigation-parents">
<a href="#" class="navigation-link navigation-parent-previous">${_("Parent of Unit Page")}</a>
<a href="#" class="navigation-link navigation-parent">${_("Unit Page Super Long Title Name Goes Here Yeah Whats Up Parent")}</a>
</small>
<span class="sr">&gt; </span>
<span class="container-page-name">${_("Container")}</span>
</h1>
<nav class="nav-actions">
<h3 class="sr">${_("Page Actions")}</h3>
<ul>
<li class="nav-item">
<a href="#" class="button upload-button new-button"><i class="icon-plus"></i> ${_("Upload New File")}</a>
</li>
</ul>
</nav>
</header>
</div>
<div class="wrapper-content wrapper">
<section class="content-area">
<article class="content-primary window">
<p class="unit-name-input"><label for="unit-display-name-input">${_("Display Name:")}</label><input type="text" value="${unit.display_name_with_default | h}" id="unit-display-name-input" class="unit-display-name-input" /></p>
<ol class="components">
% for locator in components:
<li class="component" data-locator="${locator}"/>
% endfor
</ol>
</article>
<aside class="content-supplementary" role="complimentary">
<div class="bit">
<h3 class="title-3">${_("What can I do on this page?")}</h3>
<ul class="list-details">
<li class="item-detail">${_("Not much since this is read-only! TODO: need some real doc here...")}</li>
</ul>
</div>
</aside>
</section>
</div>
</%block>
<%block name="view_alerts">
<!-- alert: save confirmed with close -->
<div class="wrapper wrapper-alert wrapper-alert-confirmation" role="status">
<div class="alert confirmation">
<i class="icon-ok"></i>
<div class="copy">
<h2 class="title title-3">${_('Your file has been deleted.')}</h2>
</div>
<a href="" rel="view" class="action action-alert-close">
<i class="icon-remove-sign"></i>
<span class="label">${_('close alert')}</span>
</a>
</div>
</div>
</%block>
......@@ -17,7 +17,7 @@
<input type="text" class="embeddable-xml-input" value="<%= portable_url %>" readonly>
</td>
<td class="actions-col">
<ul>
<ul class="actions-list">
<li class="action-item action-delete">
<a href="#" data-tooltip="<%= gettext('Delete this asset') %>" class="remove-asset-button action-button"><i class="icon-remove-sign"></i> <span class="sr"><%= gettext('Delete this asset') %></span></a>
</li>
......
<%inherit file="../../base.html" />
<%block name="title">UX Style Reference</%block>
<%block name="bodyclass">is-signedin course uploads view-container</%block>
<%block name="content">
<div class="main-wrapper">
<div class="inner-wrapper">
<div class="main-column">
<article class="window unit-body">
<h1>UX Style Reference</h1>
<ol class="components">
<li class="component">
<div class="wrapper wrapper-component-action-header">
<h2>Page Types</h2>
</div>
<section class="xblock xblock-student_view xmodule_display xmodule_HtmlModule">
<ul>
<li><a href="container.html">Container page</a></li>
<li><a href="unit.html">Unit page</a></li>
</ul>
</section>
</li>
</ol>
</article>
</div>
</div>
</div>
</%block>
......@@ -70,7 +70,6 @@ urlpatterns += patterns(
url(r'(?ix)^course($|/){}$'.format(parsers.URL_RE_SOURCE), 'course_handler'),
url(r'(?ix)^subsection($|/){}$'.format(parsers.URL_RE_SOURCE), 'subsection_handler'),
url(r'(?ix)^unit($|/){}$'.format(parsers.URL_RE_SOURCE), 'unit_handler'),
url(r'(?ix)^container($|/){}$'.format(parsers.URL_RE_SOURCE), 'container_handler'),
url(r'(?ix)^checklists/{}(/)?(?P<checklist_index>\d+)?$'.format(parsers.URL_RE_SOURCE), 'checklists_handler'),
url(r'(?ix)^orphan/{}$'.format(parsers.URL_RE_SOURCE), 'orphan_handler'),
url(r'(?ix)^assets/{}(/)?(?P<asset_id>.+)?$'.format(parsers.URL_RE_SOURCE), 'assets_handler'),
......
......@@ -43,6 +43,43 @@
// ====================
// mixins - flex support
@mixin ui-flexbox() {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
// extends - justify-content right for display:flex alignment in older browsers
%ui-justify-right-flex {
-webkit-box-pack: end;
-moz-box-pack: end;
-ms-flex-pack: end;
-webkit-justify-content: end;
justify-content: flex-end;
}
// extends - justify-content left for display:flex alignment in older browsers
%ui-justify-left-flex {
-webkit-box-pack: start;
-moz-box-pack: start;
-ms-flex-pack: start;
-webkit-justify-content: start;
justify-content: flex-start;
}
// extends - align items center for display:flex alignment in older browsers
%ui-align-center-flex {
-webkit-flex-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
}
// ====================
// extends - UI - used for page/view-level wrappers (for centering/grids)
%ui-wrapper {
@include clearfix();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment