Added url routing for /files/... and /module/{modname}/files/...
Added CMS_HOOK_RESPONSE_ALTER to give a last chance to alter the response before rendering. This hook should not be used, when there are other alternative hook that answer the need, but this is proposed for now, as a way to alter response by adding css, js url, ... Moved blog under official modules folder. Cleaned theme of demo example project. Renamed NODE_MODULE as CMS_NODE_MODULE.
This commit is contained in:
@@ -16,8 +16,9 @@
|
|||||||
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
|
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_auth_module" location="..\..\modules\auth\auth-safe.ecf" readonly="false"/>
|
<library name="cms_auth_module" location="..\..\modules\auth\auth-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
|
<library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_blog_module" location="modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
|
<library name="cms_blog_module" location="..\..\modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
|
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
|
||||||
|
<library name="cms_email_service" location="..\..\library\email\email-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
|
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20-safe.ecf" readonly="false"/>
|
<library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20-safe.ecf" readonly="false"/>
|
||||||
|
|||||||
9
examples/demo/install_modules.bat
Normal file
9
examples/demo/install_modules.bat
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
setlocal
|
||||||
|
set ROC_CMD=%~dp0..\..\tools\roc.exe
|
||||||
|
set ROC_CMS_DIR=%~dp0
|
||||||
|
|
||||||
|
%ROC_CMD% install --module ..\..\modules\auth --dir %ROC_CMS_DIR%
|
||||||
|
%ROC_CMD% install --module ..\..\modules\basic_auth --dir %ROC_CMS_DIR%
|
||||||
|
%ROC_CMD% install --module ..\..\modules\node --dir %ROC_CMS_DIR%
|
||||||
|
%ROC_CMD% install --module ..\..\modules\blog --dir %ROC_CMS_DIR%
|
||||||
|
%ROC_CMD% install --module ..\..\modules\oauth20 --dir %ROC_CMS_DIR%
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,7 +0,0 @@
|
|||||||
<div class='navbar navbar-inverse'>
|
|
||||||
<div class='navbar-inner nav-collapse' style="height: auto;">
|
|
||||||
<ul class="nav">
|
|
||||||
{$header_block/}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -5,13 +5,14 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<!-- EWF CMS -->
|
<!-- EWF CMS -->
|
||||||
<link rel="stylesheet" href="{$site_url/}theme/css/style.css">
|
<link rel="stylesheet" href="{$site_url/}theme/css/style.css">
|
||||||
<link rel="stylesheet" href="{$site_url/}theme/css/node.css">
|
|
||||||
|
|
||||||
<!-- CMS Blog Module -->
|
|
||||||
<link rel="stylesheet" href="{$site_url/}theme/css/blog.css">
|
|
||||||
|
|
||||||
|
<!-- jQuery dep -->
|
||||||
<script src="{$site_url/}theme/js/jquery-1.10.2.min.js"></script>
|
<script src="{$site_url/}theme/js/jquery-1.10.2.min.js"></script>
|
||||||
<script src="{$site_url/}theme/js/roc_auth.js"></script>
|
|
||||||
|
{if isset="$head"}{$head/}{/if}
|
||||||
|
{if isset="$styles"}{$styles/}{/if}
|
||||||
|
{if isset="$scripts"}{$scripts/}{/if}
|
||||||
|
{if isset="$head_lines"}{$head_lines/}{/if}
|
||||||
|
|
||||||
<!-- bootstrap framework -->
|
<!-- bootstrap framework -->
|
||||||
<!-- Latest compiled and minified CSS -->
|
<!-- Latest compiled and minified CSS -->
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
<h2>Help Section</h2>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<h1>Highlighted Section</h1>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<div class='span2 sidebar'>
|
|
||||||
<h3>Left Sidebar</h3>
|
|
||||||
<ul class="nav nav-tabs nav-stacked">
|
|
||||||
<li><a href='#'>Another Link 1</a></li>
|
|
||||||
<li><a href='#'>Another Link 2</a></li>
|
|
||||||
<li><a href='#'>Another Link 3</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<h2>Main Content Section</h2>
|
|
||||||
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum.<p>
|
|
||||||
|
|
||||||
<p>Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.</p>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<div id="footer">
|
|
||||||
<small>
|
|
||||||
<center>
|
|
||||||
<p class="text-muted"><a href="#" target="_blank" class="info">ROC Documentation </a>
|
|
||||||
<a href="http://www.eiffel.com/company/contact/" target="_blank" class="info">Questions? Comments? Let us know! </a></p>
|
|
||||||
<p>© Copyright 2014 Eiffel Software -- <a href="#" target="_blank" class="info">Privacy Policy</a>
|
|
||||||
</center>
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
<div class="navbar navbar-default" role="navigation">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="navbar-header">
|
|
||||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
|
||||||
<span class="sr-only">Toggle navigation</span>
|
|
||||||
</button>
|
|
||||||
<a class="navbar-brand" href="{$site_url/}" itemprop="home" rel="home">{unless isset="$site_name"}Eiffel CMS{/unless}{if isset="$site_name"}{$site_name/}{/if}</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="navbar-collapse collapse">
|
|
||||||
|
|
||||||
{if isset="$primary_nav"}
|
|
||||||
<ul class="nav navbar-nav navbar-left">
|
|
||||||
{foreach item="item" from="$primary_nav.items"}
|
|
||||||
<!-- TODO check if a menu item is active or not -->
|
|
||||||
<li class="active"><a href="{$item.location/}">{$item.title/}</a></li>
|
|
||||||
{/foreach}
|
|
||||||
</ul>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if isset="$secondary_nav"}
|
|
||||||
<ul class="nav navbar-nav navbar-right">
|
|
||||||
{foreach item="item" from="$secondary_nav.items"}
|
|
||||||
<!-- TODO check if a menu item is active or not -->
|
|
||||||
<li class="active"><a href="{$item.location/}">{$item.title/}</a></li>
|
|
||||||
{/foreach}
|
|
||||||
</ul>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
{if isset="$default_nav"}
|
|
||||||
<div class="navbar navbar-default" role="navigation">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="navbar-header">
|
|
||||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
|
||||||
<span class="sr-only">Toggle navigation</span>
|
|
||||||
</button>
|
|
||||||
<a class="navbar-brand" href="${site_url/}" itemprop="home" rel="home">{$page_title/}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="navbar-collapse collapse">
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if isset="$primary_nav"}
|
|
||||||
{$primary_nav/}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if isset="$secondary_nav"}
|
|
||||||
{$secondary_nav/}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if isset="$default_nav"}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<ul class="nav navbar-nav navbar-left">
|
|
||||||
{foreach item="item" from="$menu.items"}
|
|
||||||
<!-- TODO check if a menu item is active or not -->
|
|
||||||
<li class="active"><a href="{$item.location/}">{$item.title/}</a></li>
|
|
||||||
{/foreach}
|
|
||||||
</ul>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<div class='span2 sidebar'>
|
|
||||||
<h3>Right Sidebar</h3>
|
|
||||||
<ul class="nav nav-tabs nav-stacked">
|
|
||||||
<li><a href='#'>Another Link 1</a></li>
|
|
||||||
<li><a href='#'>Another Link 2</a></li>
|
|
||||||
<li><a href='#'>Another Link 3</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<ul class="nav navbar-nav navbar-right">
|
|
||||||
{foreach item="item" from="$menu.items"}
|
|
||||||
<!-- TODO check if a menu item is active or not -->
|
|
||||||
<li class="active"><a href="{$item.location/}">{$item.title/}</a></li>
|
|
||||||
{/foreach}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
5849
examples/demo/site/www/static/css/bootstrap.css
vendored
5849
examples/demo/site/www/static/css/bootstrap.css
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,357 +0,0 @@
|
|||||||
/*
|
|
||||||
* Base structure
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Move down content because we have a fixed navbar that is 36px tall on small screen */
|
|
||||||
body {
|
|
||||||
padding-top: 40px;
|
|
||||||
}
|
|
||||||
/* On large screen, we give it more space and the navbar is 30px tall. */
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
body {
|
|
||||||
padding-top: 45px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Global add-ons
|
|
||||||
*/
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
margin-top: initial;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2.sub-header{
|
|
||||||
margin-top: 1px;
|
|
||||||
margin-bottom: 1px;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.container .jumbotron {
|
|
||||||
padding: 10px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sidebar
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Hide for mobile, show later */
|
|
||||||
.sidebar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.sidebar {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
display: block;
|
|
||||||
padding: 70px 20px 20px;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
border-right: 1px solid #eee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sidebar navigation */
|
|
||||||
.nav-sidebar {
|
|
||||||
margin-left: -20px;
|
|
||||||
margin-right: -21px; /* 20px padding + 1px border */
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
.nav-sidebar > li > a {
|
|
||||||
padding-left: 20px;
|
|
||||||
padding-right: 20px;
|
|
||||||
}
|
|
||||||
.nav-sidebar > .active > a {
|
|
||||||
color: #fff;
|
|
||||||
background-color: #428bca;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Main content
|
|
||||||
*/
|
|
||||||
|
|
||||||
.main {
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.main {
|
|
||||||
padding-left: 15px;
|
|
||||||
padding-right: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.main .page-header {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Placeholder dashboard ideas
|
|
||||||
*/
|
|
||||||
|
|
||||||
.placeholders {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.placeholders h4 {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
.placeholder {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
.placeholder img {
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-default {
|
|
||||||
background-color:#194573;
|
|
||||||
border-color: #400040;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-brand {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-text {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-nav > li > a {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus {
|
|
||||||
color: #ffffff;
|
|
||||||
background-color: #400040;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:focus {
|
|
||||||
color: #ffffff;
|
|
||||||
background-color: #400040;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-toggle {
|
|
||||||
border-color: #400040;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus {
|
|
||||||
background-color: #400040;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-toggle .icon-bar {
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-collapse,
|
|
||||||
.navbar-default .navbar-form {
|
|
||||||
border-color: #ffffff;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-link {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-link:hover {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
|
||||||
.navbar-default .navbar-nav .open .dropdown-menu > li > a {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-nav .open .dropdown-menu > .active > a, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
|
|
||||||
color: #ffffff;
|
|
||||||
background-color: #400040;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-nav > li > a {padding-top:5px !important; padding-bottom:5px !important;}
|
|
||||||
.navbar {min-height:30px !important}
|
|
||||||
|
|
||||||
.navbar-brand {
|
|
||||||
float: left;
|
|
||||||
padding: 15px;
|
|
||||||
padding-top: 5px;
|
|
||||||
padding-right: 15px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
padding-left: 15px;
|
|
||||||
font-size: 18px;
|
|
||||||
line-height: 18px;
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Tooltips */
|
|
||||||
.blue-tooltip + .tooltip > .tooltip-inner {background-color: #FF;}
|
|
||||||
.blue-tooltip + .tooltip > .tooltip-arrow { border-bottom-color:#FF; }
|
|
||||||
|
|
||||||
|
|
||||||
.tooltip.top .tooltip-arrow {
|
|
||||||
bottom: 0;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -5px;
|
|
||||||
border-top-color: #000000;
|
|
||||||
border-width: 5px 5px 0;
|
|
||||||
}
|
|
||||||
.tooltip-inner {
|
|
||||||
text-align: left;
|
|
||||||
color: #000;
|
|
||||||
background: #fff;
|
|
||||||
border: solid 1px #000000;
|
|
||||||
max-width: 450px
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip.bottom .tooltip-arrow {
|
|
||||||
top: 0;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -5px;
|
|
||||||
border-bottom-color: #000000;
|
|
||||||
border-width: 0 5px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pre */
|
|
||||||
pre {
|
|
||||||
word-wrap: code;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
background-color:white;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Container -Fluid */
|
|
||||||
.container-fluid {
|
|
||||||
padding: 0 2px;
|
|
||||||
}
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.container-fluid {
|
|
||||||
padding: 0 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-fluid .row {
|
|
||||||
margin: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row-padding {
|
|
||||||
margin-top: 25px;
|
|
||||||
margin-bottom: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Width for the text field to enter a bug report number in the reports page.
|
|
||||||
* We put a maximum width to override the width value coming from `form-control'. */
|
|
||||||
.form-bug-number-entry {
|
|
||||||
max-width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Default width for the entries in a table like layout. */
|
|
||||||
.form-inline .form-control {
|
|
||||||
width: 95%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-inline .checkbox {
|
|
||||||
font-weight: initial;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note that there is also a class called label. */
|
|
||||||
label {
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
padding: 0px;
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label-primary-api-default {
|
|
||||||
display: inline-block;
|
|
||||||
width: 105px;
|
|
||||||
text-align: left;
|
|
||||||
background: #fff;
|
|
||||||
color: #000;
|
|
||||||
font-size: 100%;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.label-primary-api-interactions {
|
|
||||||
display: inline-block;
|
|
||||||
padding-right: 5px;
|
|
||||||
text-align: left;
|
|
||||||
color: #000;
|
|
||||||
font-size: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pre {
|
|
||||||
padding: 1.5px;
|
|
||||||
display: block;
|
|
||||||
margin: 0 0 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: monospace;
|
|
||||||
line-height: 1.428571429;
|
|
||||||
word-break: break-word;
|
|
||||||
word-wrap: break-word;
|
|
||||||
color: #333;
|
|
||||||
border: 0px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* No padding, so that nested columns are always properly aligned. */
|
|
||||||
.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12 {
|
|
||||||
padding-left: 0px;
|
|
||||||
padding-right: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td {
|
|
||||||
padding:2px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-control{
|
|
||||||
height:inherit;
|
|
||||||
padding: 1px 2px;
|
|
||||||
margin: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
padding: 1px 12px;
|
|
||||||
margin: 1px;
|
|
||||||
min-width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-toggle, .login {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pager {
|
|
||||||
margin:10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pager li>a,.pager li>span {
|
|
||||||
padding:1px 12px;
|
|
||||||
border-radius:8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.well {
|
|
||||||
padding: 9px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
min-height: 44px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-heading {
|
|
||||||
background-color: #ddeaf2 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.private-panel-border {
|
|
||||||
border: solid 1px #DBA458 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.private-panel {
|
|
||||||
background-color: #f2eadd !important;
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* EWF CMS javascript based on JQuery
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override jQuery.fn.init to guard against XSS attacks.
|
|
||||||
*
|
|
||||||
* See http://bugs.jquery.com/ticket/9521
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
var jquery_init = jQuery.fn.init;
|
|
||||||
jQuery.fn.init = function (selector, context, rootjQuery) {
|
|
||||||
// If the string contains a "#" before a "<", treat it as invalid HTML.
|
|
||||||
if (selector && typeof selector === 'string') {
|
|
||||||
var hash_position = selector.indexOf('#');
|
|
||||||
if (hash_position >= 0) {
|
|
||||||
var bracket_position = selector.indexOf('<');
|
|
||||||
if (bracket_position > hash_position) {
|
|
||||||
throw 'Syntax error, unrecognized expression: ' + selector;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return jquery_init.call(this, selector, context, rootjQuery);
|
|
||||||
};
|
|
||||||
jQuery.fn.init.prototype = jquery_init.prototype;
|
|
||||||
})();
|
|
||||||
|
|
||||||
|
|
||||||
var ROC = ROC || { };
|
|
||||||
|
|
||||||
$('body').on('click',"a[rel='node']",function(e){
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
/*
|
|
||||||
if uncomment the above line, html5 nonsupported browers won't change the url but will display the ajax content;
|
|
||||||
if commented, html5 nonsupported browers will reload the page to the specified link.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//get the link location that was clicked
|
|
||||||
pageurl = $(this).attr('href');
|
|
||||||
|
|
||||||
spinner = "<span class='loading'><h3>Loading content..</h3><img src='/static/images/ajax-loader.gif' alt='loading...' class='spinner'></span>";
|
|
||||||
//to get the ajax content and display in div with class 'main'
|
|
||||||
$.ajax({url:pageurl+'?rel=node',success: function(data){
|
|
||||||
$('.main').html(data);
|
|
||||||
}});
|
|
||||||
|
|
||||||
//to change the browser URL to the given link location
|
|
||||||
//if(pageurl!=window.location){
|
|
||||||
//window.history.pushState({path:pageurl},'',pageurl);
|
|
||||||
//}
|
|
||||||
//stop refreshing to the page given in
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('body').on('click',"a[rel='register']",function(e){
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
/*
|
|
||||||
if uncomment the above line, html5 nonsupported browers won't change the url but will display the ajax content;
|
|
||||||
if commented, html5 nonsupported browers will reload the page to the specified link.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//get the link location that was clicked
|
|
||||||
pageurl = $(this).attr('href');
|
|
||||||
|
|
||||||
spinner = "<span class='loading'><h3>Loading content..</h3><img src='/static/images/ajax-loader.gif' alt='loading...' class='spinner'></span>";
|
|
||||||
//to get the ajax content and display in div with class 'main'
|
|
||||||
$.ajax({url:pageurl+'?rel=node',success: function(data){
|
|
||||||
$('.main').html(data);
|
|
||||||
}});
|
|
||||||
|
|
||||||
//to change the browser URL to the given link location
|
|
||||||
//if(pageurl!=window.location){
|
|
||||||
//window.history.pushState({path:pageurl},'',pageurl);
|
|
||||||
//}
|
|
||||||
//stop refreshing to the page given in
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$("a[rel='node']").click(function(e){
|
|
||||||
e.preventDefault();
|
|
||||||
/*
|
|
||||||
if uncomment the above line, html5 nonsupported browers won't change the url but will display the ajax content;
|
|
||||||
if commented, html5 nonsupported browers will reload the page to the specified link.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//get the link location that was clicked
|
|
||||||
pageurl = $(this).attr('href');
|
|
||||||
|
|
||||||
spinner = "<span class='loading'><h3>Loading content..</h3><img src='/static/images/ajax-loader.gif' alt='loading...' class='spinner'></span>";
|
|
||||||
//to get the ajax content and display in div with class 'main'
|
|
||||||
$.ajax({url:pageurl+'?rel=node',success: function(data){
|
|
||||||
$('.main').html(data);
|
|
||||||
}});
|
|
||||||
|
|
||||||
//to change the browser URL to the given link location
|
|
||||||
//if(pageurl!=window.location){
|
|
||||||
//window.history.pushState({path:pageurl},'',pageurl);
|
|
||||||
//}
|
|
||||||
//stop refreshing to the page given in
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
@@ -55,19 +55,13 @@ feature -- CMS setup
|
|||||||
local
|
local
|
||||||
m: CMS_MODULE
|
m: CMS_MODULE
|
||||||
do
|
do
|
||||||
create {NODE_MODULE} m.make (a_setup)
|
|
||||||
m.enable
|
|
||||||
a_setup.register_module (m)
|
|
||||||
|
|
||||||
create {CMS_AUTHENTICATION_MODULE} m.make
|
create {CMS_AUTHENTICATION_MODULE} m.make
|
||||||
m.enable
|
m.enable
|
||||||
a_setup.register_module (m)
|
a_setup.register_module (m)
|
||||||
|
|
||||||
create {BASIC_AUTH_MODULE} m.make
|
create {BASIC_AUTH_MODULE} m.make
|
||||||
if not a_setup.module_with_same_type_registered (m) then
|
m.enable
|
||||||
m.enable
|
a_setup.register_module (m)
|
||||||
a_setup.register_module (m)
|
|
||||||
end
|
|
||||||
|
|
||||||
create {CMS_OAUTH_20_MODULE} m.make
|
create {CMS_OAUTH_20_MODULE} m.make
|
||||||
m.enable
|
m.enable
|
||||||
@@ -77,6 +71,14 @@ feature -- CMS setup
|
|||||||
m.enable
|
m.enable
|
||||||
a_setup.register_module (m)
|
a_setup.register_module (m)
|
||||||
|
|
||||||
|
create {CMS_NODE_MODULE} m.make (a_setup)
|
||||||
|
m.enable
|
||||||
|
a_setup.register_module (m)
|
||||||
|
|
||||||
|
create {CMS_BLOG_MODULE} m.make
|
||||||
|
m.enable
|
||||||
|
a_setup.register_module (m)
|
||||||
|
|
||||||
create {CMS_DEBUG_MODULE} m.make
|
create {CMS_DEBUG_MODULE} m.make
|
||||||
m.enable
|
m.enable
|
||||||
a_setup.register_module (m)
|
a_setup.register_module (m)
|
||||||
@@ -85,9 +87,6 @@ feature -- CMS setup
|
|||||||
m.enable
|
m.enable
|
||||||
a_setup.register_module (m)
|
a_setup.register_module (m)
|
||||||
|
|
||||||
create {CMS_BLOG_MODULE} m.make
|
|
||||||
m.enable
|
|
||||||
a_setup.register_module (m)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -114,10 +114,12 @@ feature -- Hooks
|
|||||||
do
|
do
|
||||||
if attached a_response.current_user (a_response.request) as u then
|
if attached a_response.current_user (a_response.request) as u then
|
||||||
create lnk.make (u.name + " (Logout)", "account/roc-logout" )
|
create lnk.make (u.name + " (Logout)", "account/roc-logout" )
|
||||||
|
lnk.set_weight (98)
|
||||||
|
a_menu_system.primary_menu.extend (lnk)
|
||||||
else
|
else
|
||||||
create lnk.make ("Login", "account/roc-login")
|
create lnk.make ("Login", "account/roc-login")
|
||||||
a_menu_system.primary_menu.extend (lnk)
|
|
||||||
lnk.set_weight (98)
|
lnk.set_weight (98)
|
||||||
|
a_menu_system.primary_menu.extend (lnk)
|
||||||
if a_response.location.starts_with ("account/") then
|
if a_response.location.starts_with ("account/") then
|
||||||
create lnk.make ("Basic Auth", "account/roc-basic-auth")
|
create lnk.make ("Basic Auth", "account/roc-basic-auth")
|
||||||
lnk.set_expandable (True)
|
lnk.set_expandable (True)
|
||||||
@@ -149,6 +151,7 @@ feature -- Hooks
|
|||||||
a_block_id.is_case_insensitive_equal_general ("login") and then
|
a_block_id.is_case_insensitive_equal_general ("login") and then
|
||||||
a_response.location.starts_with ("account/roc-basic-auth")
|
a_response.location.starts_with ("account/roc-basic-auth")
|
||||||
then
|
then
|
||||||
|
a_response.add_javascript_url (a_response.url ("module/" + name + "/files/js/roc_auth.js", Void))
|
||||||
get_block_view_login (a_block_id, a_response)
|
get_block_view_login (a_block_id, a_response)
|
||||||
elseif
|
elseif
|
||||||
a_block_id.is_case_insensitive_equal_general ("register") and then
|
a_block_id.is_case_insensitive_equal_general ("register") and then
|
||||||
@@ -177,9 +180,16 @@ feature -- Hooks
|
|||||||
local
|
local
|
||||||
r: CMS_RESPONSE
|
r: CMS_RESPONSE
|
||||||
do
|
do
|
||||||
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
if attached api.module_by_name ("basic_auth") then
|
||||||
r.set_value ("Login", "optional_content_type")
|
-- FIXME: find better solution to support a default login system.
|
||||||
r.execute
|
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
||||||
|
r.set_redirection (r.absolute_url ("/account/roc-basic-auth", Void))
|
||||||
|
r.execute
|
||||||
|
else
|
||||||
|
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
||||||
|
r.set_value ("Login", "optional_content_type")
|
||||||
|
r.execute
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
handle_login_basic_auth (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
handle_login_basic_auth (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
|||||||
321
modules/auth/site/files/js/roc_auth.js
Normal file
321
modules/auth/site/files/js/roc_auth.js
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
var ROC_AUTH = ROC_AUTH || { };
|
||||||
|
|
||||||
|
var loginURL = "/basic_auth_login";
|
||||||
|
var logoutURL = "/basic_auth_logoff";
|
||||||
|
|
||||||
|
var userAgent = navigator.userAgent.toLowerCase();
|
||||||
|
var firstLogIn = true;
|
||||||
|
|
||||||
|
ROC_AUTH.login = function() {
|
||||||
|
var form = document.forms[0];
|
||||||
|
var username = form.username.value;
|
||||||
|
var password = form.password.value;
|
||||||
|
//var host = form.host.value;
|
||||||
|
var origin = window.location.origin.concat(window.location.pathname);
|
||||||
|
var _login = function(){
|
||||||
|
|
||||||
|
|
||||||
|
if (document.getElementById('myModalFormId') !== null ) {
|
||||||
|
ROC_AUTH.remove ('myModalFormId');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (username === "" || password === "") {
|
||||||
|
if (document.getElementById('myModalFormId') === null ) {
|
||||||
|
var newdiv = document.createElement('div');
|
||||||
|
newdiv.innerHTML = "<br>Invalid Credentials</br>";
|
||||||
|
newdiv.id = 'myModalFormId';
|
||||||
|
$("body").append(newdiv);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
|
||||||
|
//Instantiate HTTP Request
|
||||||
|
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
|
||||||
|
request.open("GET", loginURL, true, username, password);
|
||||||
|
request.send(null);
|
||||||
|
|
||||||
|
//Process Response
|
||||||
|
request.onreadystatechange = function(){
|
||||||
|
if (request.readyState == 4) {
|
||||||
|
if (request.status==200) {
|
||||||
|
delete form;
|
||||||
|
window.location=origin;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (navigator.userAgent.toLowerCase().indexOf("firefox") != -1){
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById('myModalFormId') === null ) {
|
||||||
|
var newdiv = document.createElement('div');
|
||||||
|
newdiv.innerHTML = "<br>Invalid Credentials</br>";
|
||||||
|
newdiv.id = 'myModalFormId';
|
||||||
|
$("body").append(newdiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var userAgent = navigator.userAgent.toLowerCase();
|
||||||
|
if (userAgent.indexOf("firefox") != -1){ //TODO: check version number
|
||||||
|
if (firstLogIn) _login();
|
||||||
|
else logoff(_login);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
_login();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstLogIn) firstLogIn = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ROC_AUTH.login_with_redirect = function() {
|
||||||
|
var form = document.forms[2];
|
||||||
|
var username = form.username.value;
|
||||||
|
var password = form.password.value;
|
||||||
|
var host = form.host.value;
|
||||||
|
var _login = function(){
|
||||||
|
|
||||||
|
var redirectURL = form.redirect && form.redirect.value || "";
|
||||||
|
|
||||||
|
|
||||||
|
$("#imgProgressRedirect").show();
|
||||||
|
|
||||||
|
if (document.getElementById('myModalFormId') !== null ) {
|
||||||
|
ROC_AUTH.remove ('myModalFormId');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (username === "" || password === "") {
|
||||||
|
if (document.getElementById('myModalFormId') === null ) {
|
||||||
|
var newdiv = document.createElement('div');
|
||||||
|
newdiv.innerHTML = "<br>Invalid Credentials</br>";
|
||||||
|
newdiv.id = 'myModalFormId';
|
||||||
|
$("body").append(newdiv);
|
||||||
|
$("#imgProgressRedirect").hide();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
|
||||||
|
//Instantiate HTTP Request
|
||||||
|
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
|
||||||
|
request.open("GET", host.concat(loginURL), true, username, password);
|
||||||
|
request.send(null);
|
||||||
|
|
||||||
|
//Process Response
|
||||||
|
request.onreadystatechange = function(){
|
||||||
|
if (request.readyState == 4) {
|
||||||
|
if (request.status==200) {
|
||||||
|
if (redirectURL === "") {
|
||||||
|
window.location=host.concat("/");
|
||||||
|
} else {
|
||||||
|
window.location=host.concat(redirectURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (navigator.userAgent.toLowerCase().indexOf("firefox") != -1){
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById('myModalFormId') === null ) {
|
||||||
|
var newdiv = document.createElement('div');
|
||||||
|
newdiv.innerHTML = "<br>Invalid Credentials</br>";
|
||||||
|
newdiv.id = 'myModalFormId';
|
||||||
|
$("body").append(newdiv);
|
||||||
|
$("#imgProgressRedirect").hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var userAgent = navigator.userAgent.toLowerCase();
|
||||||
|
if (userAgent.indexOf("firefox") != -1){ //TODO: check version number
|
||||||
|
if (firstLogIn) _login();
|
||||||
|
else logoff(_login);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
_login();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstLogIn) firstLogIn = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ROC_AUTH.getQueryParameterByName = function (name) {
|
||||||
|
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
|
||||||
|
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
|
||||||
|
results = regex.exec(location.search);
|
||||||
|
return results === null ? " " : decodeURIComponent(results[1].replace(/\+/g, " "));
|
||||||
|
}
|
||||||
|
|
||||||
|
ROC_AUTH.logoff = function(callback){
|
||||||
|
var form = document.forms[0];
|
||||||
|
var host = form.host.value;
|
||||||
|
|
||||||
|
if (userAgent.indexOf("msie") != -1) {
|
||||||
|
document.execCommand("ClearAuthenticationCache");
|
||||||
|
}
|
||||||
|
else if (userAgent.indexOf("firefox") != -1){ //TODO: check version number
|
||||||
|
|
||||||
|
var request1 = new XMLHttpRequest();
|
||||||
|
var request2 = new XMLHttpRequest();
|
||||||
|
|
||||||
|
//Logout. Tell the server not to return the "WWW-Authenticate" header
|
||||||
|
request1.open("GET", host.concat(logoutURL) + "?prompt=false", true);
|
||||||
|
request1.send("");
|
||||||
|
request1.onreadystatechange = function(){
|
||||||
|
if (request1.readyState == 4) {
|
||||||
|
|
||||||
|
//Sign in with dummy credentials to clear the auth cache
|
||||||
|
request2.open("GET", host.concat(logoutURL), true, "logout", "logout");
|
||||||
|
request2.send("");
|
||||||
|
|
||||||
|
request2.onreadystatechange = function(){
|
||||||
|
if (request2.readyState == 4) {
|
||||||
|
if (callback!=null) { callback.call(); } else { window.location=host.concat(logoutURL);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
|
||||||
|
request.open("GET", host.concat(logoutURL), true, "logout", "logout");
|
||||||
|
request.send("");
|
||||||
|
request.onreadystatechange = function(){
|
||||||
|
if (request.status==401 || request.status==403 ) { window.location=host.concat(logoutURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ROC_AUTH.remove = function (id)
|
||||||
|
{
|
||||||
|
var element = document.getElementById(id);
|
||||||
|
element.outerHTML = "";
|
||||||
|
delete element;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
if (typeof String.prototype.contains != 'function') {
|
||||||
|
String.prototype.contains = function (str){
|
||||||
|
return this.indexOf(str) != -1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
ROC_AUTH.progressive_loging();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
ROC_AUTH.progressive_loging = function () {
|
||||||
|
|
||||||
|
ROC_AUTH.login_href();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$(document).keypress(function(e) {
|
||||||
|
if ((e.which === 13) && (e.target.localName === 'input' && e.target.id === 'password')) {
|
||||||
|
ROC_AUTH.login();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ROC_AUTH.OnOneClick = function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
if ( document.forms[0] === undefined ) {
|
||||||
|
ROC_AUTH.create_form();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
ROC_AUTH.login_href = function() {
|
||||||
|
var els = document.getElementsByTagName("a");
|
||||||
|
for (var i = 0, l = els.length; i < l; i++) {
|
||||||
|
var el = els[i];
|
||||||
|
if (el.href.contains("/basic_auth_login?destination")) {
|
||||||
|
loginURL = el.href;
|
||||||
|
var OneClick = el;
|
||||||
|
OneClick.addEventListener('click', ROC_AUTH.OnOneClick, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ROC_AUTH.create_form = function() {
|
||||||
|
|
||||||
|
// Fetching HTML Elements in Variables by ID.
|
||||||
|
var createform = document.createElement('form'); // Create New Element Form
|
||||||
|
createform.setAttribute("action", ""); // Setting Action Attribute on Form
|
||||||
|
createform.setAttribute("method", "post"); // Setting Method Attribute on Form
|
||||||
|
$("body").append(createform);
|
||||||
|
|
||||||
|
var heading = document.createElement('h2'); // Heading of Form
|
||||||
|
heading.innerHTML = "Login Form ";
|
||||||
|
createform.appendChild(heading);
|
||||||
|
|
||||||
|
var line = document.createElement('hr'); // Giving Horizontal Row After Heading
|
||||||
|
createform.appendChild(line);
|
||||||
|
|
||||||
|
var linebreak = document.createElement('br');
|
||||||
|
createform.appendChild(linebreak);
|
||||||
|
|
||||||
|
var namelabel = document.createElement('label'); // Create Label for Name Field
|
||||||
|
namelabel.innerHTML = "Username : "; // Set Field Labels
|
||||||
|
createform.appendChild(namelabel);
|
||||||
|
|
||||||
|
var inputelement = document.createElement('input'); // Create Input Field for UserName
|
||||||
|
inputelement.setAttribute("type", "text");
|
||||||
|
inputelement.setAttribute("name", "username");
|
||||||
|
inputelement.setAttribute("required","required");
|
||||||
|
createform.appendChild(inputelement);
|
||||||
|
|
||||||
|
var linebreak = document.createElement('br');
|
||||||
|
createform.appendChild(linebreak);
|
||||||
|
|
||||||
|
var passwordlabel = document.createElement('label'); // Create Label for Password Field
|
||||||
|
passwordlabel.innerHTML = "Password : ";
|
||||||
|
createform.appendChild(passwordlabel);
|
||||||
|
|
||||||
|
var passwordelement = document.createElement('input'); // Create Input Field for Password.
|
||||||
|
passwordelement.setAttribute("type", "password");
|
||||||
|
passwordelement.setAttribute("name", "password");
|
||||||
|
passwordelement.setAttribute("id", "password");
|
||||||
|
passwordelement.setAttribute("required","required");
|
||||||
|
createform.appendChild(passwordelement);
|
||||||
|
|
||||||
|
|
||||||
|
var passwordbreak = document.createElement('br');
|
||||||
|
createform.appendChild(passwordbreak);
|
||||||
|
|
||||||
|
|
||||||
|
var submitelement = document.createElement('button'); // Append Submit Button
|
||||||
|
submitelement.setAttribute("type", "button");
|
||||||
|
submitelement.setAttribute("onclick", "ROC_AUTH.login();");
|
||||||
|
submitelement.innerHTML = "Sign In ";
|
||||||
|
createform.appendChild(submitelement);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var password = document.getElementById("password")
|
||||||
|
, confirm_password = document.getElementById("confirm_password");
|
||||||
|
|
||||||
|
ROC_AUTH.validatePassword =function(){
|
||||||
|
if(password.value != confirm_password.value) {
|
||||||
|
confirm_password.setCustomValidity("Passwords Don't Match");
|
||||||
|
} else {
|
||||||
|
confirm_password.setCustomValidity('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
password.onchange = ROC_AUTH.validatePassword();
|
||||||
|
confirm_password.onkeyup = ROC_AUTH.validatePassword;
|
||||||
@@ -11,9 +11,9 @@
|
|||||||
</option>
|
</option>
|
||||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>
|
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>
|
||||||
<library name="cms" location="..\..\..\..\cms-safe.ecf" readonly="false"/>
|
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_model" location="..\..\..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_node_module" location="..\..\..\..\modules\node\node-safe.ecf" readonly="false"/>
|
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
|
||||||
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
|
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
|
||||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||||
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter-safe.ecf"/>
|
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter-safe.ecf"/>
|
||||||
@@ -20,6 +20,8 @@ inherit
|
|||||||
|
|
||||||
CMS_HOOK_MENU_SYSTEM_ALTER
|
CMS_HOOK_MENU_SYSTEM_ALTER
|
||||||
|
|
||||||
|
CMS_HOOK_RESPONSE_ALTER
|
||||||
|
|
||||||
create
|
create
|
||||||
make
|
make
|
||||||
|
|
||||||
@@ -45,11 +47,11 @@ feature {CMS_API} -- Module Initialization
|
|||||||
do
|
do
|
||||||
Precursor (api)
|
Precursor (api)
|
||||||
|
|
||||||
if attached {CMS_NODE_API} api.module_api ({NODE_MODULE}) as l_node_api then
|
if attached {CMS_NODE_API} api.module_api ({CMS_NODE_MODULE}) as l_node_api then
|
||||||
create blog_api.make (api, l_node_api)
|
create blog_api.make (api, l_node_api)
|
||||||
|
|
||||||
node_api := l_node_api
|
node_api := l_node_api
|
||||||
-- Depends on {NODE_MODULE}
|
-- Depends on {CMS_NODE_MODULE}
|
||||||
create ct
|
create ct
|
||||||
l_node_api.add_content_type (ct)
|
l_node_api.add_content_type (ct)
|
||||||
l_node_api.add_content_type_webform_manager (create {CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER}.make (ct))
|
l_node_api.add_content_type_webform_manager (create {CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER}.make (ct))
|
||||||
@@ -140,6 +142,12 @@ feature -- Hooks
|
|||||||
register_hooks (a_response: CMS_RESPONSE)
|
register_hooks (a_response: CMS_RESPONSE)
|
||||||
do
|
do
|
||||||
a_response.subscribe_to_menu_system_alter_hook (Current)
|
a_response.subscribe_to_menu_system_alter_hook (Current)
|
||||||
|
a_response.subscribe_to_response_alter_hook (Current)
|
||||||
|
end
|
||||||
|
|
||||||
|
response_alter (a_response: CMS_RESPONSE)
|
||||||
|
do
|
||||||
|
a_response.add_style (a_response.url ("/module/" + name + "/files/css/blog.css", Void), Void)
|
||||||
end
|
end
|
||||||
|
|
||||||
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
|
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
|
||||||
25
modules/blog/site/files/css/blog.css
Normal file
25
modules/blog/site/files/css/blog.css
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
ul.cms_blog_nodes {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
ul.cms_blog_nodes li.cms_type_blog {
|
||||||
|
list-style: none;
|
||||||
|
display: block;
|
||||||
|
margin-top: 20px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
border-bottom: 1px dotted black;
|
||||||
|
}
|
||||||
|
ul.cms_blog_nodes li.cms_type_blog .blog_title a {
|
||||||
|
color: black;
|
||||||
|
font-size: 18px;
|
||||||
|
text-decoration: none;
|
||||||
|
display: block;
|
||||||
|
margin: 6px 0;
|
||||||
|
}
|
||||||
|
ul.cms_blog_nodes li.cms_type_blog .blog_title a:hover {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
ul.cms_blog_nodes li.cms_type_blog .blog_list_summary a {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
30
modules/blog/site/files/scss/blog.scss
Normal file
30
modules/blog/site/files/scss/blog.scss
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
ul.cms_blog_nodes{
|
||||||
|
|
||||||
|
padding:0;
|
||||||
|
margin:0;
|
||||||
|
|
||||||
|
li.cms_type_blog{
|
||||||
|
list-style: none;
|
||||||
|
display: block;
|
||||||
|
margin-top:20px;
|
||||||
|
padding-bottom:20px;
|
||||||
|
border-bottom:1px dotted black;
|
||||||
|
|
||||||
|
.blog_title a{
|
||||||
|
color:black;
|
||||||
|
font-size:18px;
|
||||||
|
text-decoration: none;
|
||||||
|
display:block;
|
||||||
|
margin:6px 0;
|
||||||
|
|
||||||
|
&:hover{
|
||||||
|
color:#999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog_list_summary a{
|
||||||
|
margin-top:20px;
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ inherit
|
|||||||
|
|
||||||
REFACTORING_HELPER
|
REFACTORING_HELPER
|
||||||
|
|
||||||
create {NODE_MODULE}
|
create {CMS_NODE_MODULE}
|
||||||
make_with_storage
|
make_with_storage
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|||||||
227
modules/node/cms_node_module.e
Normal file
227
modules/node/cms_node_module.e
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
note
|
||||||
|
description: "CMS module that bring support for NODE management."
|
||||||
|
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||||
|
revision: "$Revision: 96616 $"
|
||||||
|
|
||||||
|
class
|
||||||
|
CMS_NODE_MODULE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
|
||||||
|
CMS_MODULE
|
||||||
|
redefine
|
||||||
|
register_hooks,
|
||||||
|
initialize,
|
||||||
|
is_installed,
|
||||||
|
install,
|
||||||
|
module_api
|
||||||
|
end
|
||||||
|
|
||||||
|
CMS_HOOK_MENU_SYSTEM_ALTER
|
||||||
|
|
||||||
|
CMS_HOOK_RESPONSE_ALTER
|
||||||
|
|
||||||
|
CMS_HOOK_BLOCK
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_setup: CMS_SETUP)
|
||||||
|
-- Create Current module, disabled by default.
|
||||||
|
do
|
||||||
|
version := "1.0"
|
||||||
|
description := "Service to manage content based on 'node'"
|
||||||
|
package := "core"
|
||||||
|
config := a_setup
|
||||||
|
end
|
||||||
|
|
||||||
|
config: CMS_SETUP
|
||||||
|
-- Node configuration.
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
name: STRING = "node"
|
||||||
|
|
||||||
|
feature {CMS_API} -- Module Initialization
|
||||||
|
|
||||||
|
initialize (a_api: CMS_API)
|
||||||
|
-- <Precursor>
|
||||||
|
local
|
||||||
|
p1,p2: CMS_PAGE
|
||||||
|
ct: CMS_PAGE_NODE_TYPE
|
||||||
|
l_node_api: like node_api
|
||||||
|
l_node_storage: CMS_NODE_STORAGE_I
|
||||||
|
do
|
||||||
|
Precursor (a_api)
|
||||||
|
|
||||||
|
-- Storage initialization
|
||||||
|
if attached {CMS_STORAGE_SQL_I} a_api.storage as l_storage_sql then
|
||||||
|
create {CMS_NODE_STORAGE_SQL} l_node_storage.make (l_storage_sql)
|
||||||
|
else
|
||||||
|
-- FIXME: in case of NULL storage, should Current be disabled?
|
||||||
|
create {CMS_NODE_STORAGE_NULL} l_node_storage.make
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Node API initialization
|
||||||
|
create l_node_api.make_with_storage (a_api, l_node_storage)
|
||||||
|
node_api := l_node_api
|
||||||
|
|
||||||
|
-- Add support for CMS_PAGE, which requires a storage extension to store the optional "parent" id.
|
||||||
|
-- For now, we only have extension based on SQL statement.
|
||||||
|
if attached {CMS_NODE_STORAGE_SQL} l_node_api.node_storage as l_sql_node_storage then
|
||||||
|
l_sql_node_storage.register_node_storage_extension (create {CMS_NODE_STORAGE_SQL_PAGE_EXTENSION}.make (l_sql_node_storage))
|
||||||
|
|
||||||
|
-- FIXME: the following code is mostly for test purpose/initialization, remove later
|
||||||
|
if l_sql_node_storage.sql_table_items_count ("page_nodes") = 0 then
|
||||||
|
if attached a_api.user_api.user_by_id (1) as u then
|
||||||
|
create ct
|
||||||
|
p1 := ct.new_node (Void)
|
||||||
|
p1.set_title ("Welcome")
|
||||||
|
p1.set_content ("Welcome, you are using the ROC Eiffel CMS", Void, Void) -- Use default format
|
||||||
|
p1.set_author (u)
|
||||||
|
l_sql_node_storage.save_node (p1)
|
||||||
|
|
||||||
|
p2 := ct.new_node (Void)
|
||||||
|
p2.set_title ("A new page example")
|
||||||
|
p2.set_content ("This is the content of a page", Void, Void) -- Use default format
|
||||||
|
p2.set_author (u)
|
||||||
|
p2.set_parent (p1)
|
||||||
|
l_sql_node_storage.save_node (p2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- FIXME: maybe provide a default solution based on file system, when no SQL storage is available.
|
||||||
|
-- IDEA: we could also have generic extension to node system, that handle generic addition field.
|
||||||
|
end
|
||||||
|
ensure then
|
||||||
|
node_api_set: node_api /= Void
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {CMS_API} -- Module management
|
||||||
|
|
||||||
|
is_installed (a_api: CMS_API): BOOLEAN
|
||||||
|
-- Is Current module installed?
|
||||||
|
do
|
||||||
|
Result := Precursor (a_api)
|
||||||
|
if Result and attached {CMS_STORAGE_SQL_I} a_api.storage as l_sql_storage then
|
||||||
|
Result := l_sql_storage.sql_table_exists ("nodes") and
|
||||||
|
l_sql_storage.sql_table_exists ("page_nodes")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
install (a_api: CMS_API)
|
||||||
|
do
|
||||||
|
-- Schema
|
||||||
|
if attached {CMS_STORAGE_SQL_I} a_api.storage as l_sql_storage then
|
||||||
|
l_sql_storage.sql_execute_file_script (a_api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended (name).appended_with_extension ("sql")), Void)
|
||||||
|
end
|
||||||
|
Precursor {CMS_MODULE}(a_api)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {CMS_API} -- Access: API
|
||||||
|
|
||||||
|
module_api: detachable CMS_MODULE_API
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
if attached node_api as l_api then
|
||||||
|
Result := l_api
|
||||||
|
else
|
||||||
|
-- Current is initialized, so node_api should be set.
|
||||||
|
check has_node_api: False end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
node_api: detachable CMS_NODE_API
|
||||||
|
-- <Precursor>
|
||||||
|
|
||||||
|
feature -- Access: router
|
||||||
|
|
||||||
|
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
if attached node_api as l_node_api then
|
||||||
|
configure_web (a_api, l_node_api, a_router)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
configure_web (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||||
|
local
|
||||||
|
l_node_handler: NODE_HANDLER
|
||||||
|
l_nodes_handler: NODES_HANDLER
|
||||||
|
l_uri_mapping: WSF_URI_MAPPING
|
||||||
|
l_trash_handler: TRASH_HANDLER
|
||||||
|
do
|
||||||
|
-- TODO: for now, focused only on web interface, add REST api later. [2015-April-29]
|
||||||
|
create l_node_handler.make (a_api, a_node_api)
|
||||||
|
create l_uri_mapping.make_trailing_slash_ignored ("/node", l_node_handler)
|
||||||
|
a_router.map (l_uri_mapping, a_router.methods_get_post)
|
||||||
|
|
||||||
|
a_router.handle ("/node/add/{type}", l_node_handler, a_router.methods_get_post)
|
||||||
|
a_router.handle ("/node/{id}/edit", l_node_handler, a_router.methods_get_post)
|
||||||
|
a_router.handle ("/node/{id}/delete", l_node_handler, a_router.methods_get_post)
|
||||||
|
a_router.handle ("/node/{id}/trash", l_node_handler, a_router.methods_get_post)
|
||||||
|
|
||||||
|
a_router.handle ("/node/{id}", l_node_handler, a_router.methods_get)
|
||||||
|
-- For now: no REST API handling... a_router.methods_get_put_delete + a_router.methods_get_post)
|
||||||
|
|
||||||
|
-- Nodes
|
||||||
|
create l_nodes_handler.make (a_api, a_node_api)
|
||||||
|
create l_uri_mapping.make_trailing_slash_ignored ("/nodes", l_nodes_handler)
|
||||||
|
a_router.map (l_uri_mapping, a_router.methods_get)
|
||||||
|
|
||||||
|
--Trash
|
||||||
|
|
||||||
|
create l_trash_handler.make (a_api, a_node_api)
|
||||||
|
create l_uri_mapping.make_trailing_slash_ignored ("/trash", l_trash_handler)
|
||||||
|
a_router.map (l_uri_mapping, a_router.methods_get)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Hooks
|
||||||
|
|
||||||
|
register_hooks (a_response: CMS_RESPONSE)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
a_response.subscribe_to_menu_system_alter_hook (Current)
|
||||||
|
a_response.subscribe_to_block_hook (Current)
|
||||||
|
a_response.subscribe_to_response_alter_hook (Current)
|
||||||
|
end
|
||||||
|
|
||||||
|
response_alter (a_response: CMS_RESPONSE)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
a_response.add_style (a_response.url ("/module/" + name + "/files/css/node.css", Void), Void)
|
||||||
|
end
|
||||||
|
|
||||||
|
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
Result := <<"node-info">>
|
||||||
|
end
|
||||||
|
|
||||||
|
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
||||||
|
local
|
||||||
|
-- b: CMS_CONTENT_BLOCK
|
||||||
|
do
|
||||||
|
-- create b.make (a_block_id, "Block::node", "This is a block test", Void)
|
||||||
|
-- a_response.add_block (b, "sidebar_second")
|
||||||
|
end
|
||||||
|
|
||||||
|
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
|
||||||
|
local
|
||||||
|
lnk: CMS_LOCAL_LINK
|
||||||
|
-- perms: detachable ARRAYED_LIST [READABLE_STRING_8]
|
||||||
|
do
|
||||||
|
create lnk.make ("List of nodes", "nodes")
|
||||||
|
a_menu_system.primary_menu.extend (lnk)
|
||||||
|
|
||||||
|
create lnk.make ("Trash", "trash")
|
||||||
|
a_menu_system.primary_menu.extend (lnk)
|
||||||
|
|
||||||
|
create lnk.make ("Create ..", "node")
|
||||||
|
a_menu_system.primary_menu.extend (lnk)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -1,218 +1,18 @@
|
|||||||
note
|
note
|
||||||
description: "CMS module that bring support for NODE management."
|
description: "Summary description for {NODE_MODULE}."
|
||||||
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
author: ""
|
||||||
revision: "$Revision: 96616 $"
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
class
|
class
|
||||||
NODE_MODULE
|
NODE_MODULE
|
||||||
|
|
||||||
|
obsolete "Use {CMS_NODE_MODULE}"
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
CMS_NODE_MODULE
|
||||||
CMS_MODULE
|
|
||||||
redefine
|
|
||||||
register_hooks,
|
|
||||||
initialize,
|
|
||||||
is_installed,
|
|
||||||
install,
|
|
||||||
module_api
|
|
||||||
end
|
|
||||||
|
|
||||||
CMS_HOOK_MENU_SYSTEM_ALTER
|
|
||||||
|
|
||||||
CMS_HOOK_BLOCK
|
|
||||||
|
|
||||||
create
|
create
|
||||||
make
|
make
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
|
||||||
|
|
||||||
make (a_setup: CMS_SETUP)
|
|
||||||
-- Create Current module, disabled by default.
|
|
||||||
do
|
|
||||||
version := "1.0"
|
|
||||||
description := "Service to manage content based on 'node'"
|
|
||||||
package := "core"
|
|
||||||
config := a_setup
|
|
||||||
end
|
|
||||||
|
|
||||||
config: CMS_SETUP
|
|
||||||
-- Node configuration.
|
|
||||||
|
|
||||||
feature -- Access
|
|
||||||
|
|
||||||
name: STRING = "node"
|
|
||||||
|
|
||||||
feature {CMS_API} -- Module Initialization
|
|
||||||
|
|
||||||
initialize (a_api: CMS_API)
|
|
||||||
-- <Precursor>
|
|
||||||
local
|
|
||||||
p1,p2: CMS_PAGE
|
|
||||||
ct: CMS_PAGE_NODE_TYPE
|
|
||||||
l_node_api: like node_api
|
|
||||||
l_node_storage: CMS_NODE_STORAGE_I
|
|
||||||
do
|
|
||||||
Precursor (a_api)
|
|
||||||
|
|
||||||
-- Storage initialization
|
|
||||||
if attached {CMS_STORAGE_SQL_I} a_api.storage as l_storage_sql then
|
|
||||||
create {CMS_NODE_STORAGE_SQL} l_node_storage.make (l_storage_sql)
|
|
||||||
else
|
|
||||||
-- FIXME: in case of NULL storage, should Current be disabled?
|
|
||||||
create {CMS_NODE_STORAGE_NULL} l_node_storage.make
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Node API initialization
|
|
||||||
create l_node_api.make_with_storage (a_api, l_node_storage)
|
|
||||||
node_api := l_node_api
|
|
||||||
|
|
||||||
-- Add support for CMS_PAGE, which requires a storage extension to store the optional "parent" id.
|
|
||||||
-- For now, we only have extension based on SQL statement.
|
|
||||||
if attached {CMS_NODE_STORAGE_SQL} l_node_api.node_storage as l_sql_node_storage then
|
|
||||||
l_sql_node_storage.register_node_storage_extension (create {CMS_NODE_STORAGE_SQL_PAGE_EXTENSION}.make (l_sql_node_storage))
|
|
||||||
|
|
||||||
-- FIXME: the following code is mostly for test purpose/initialization, remove later
|
|
||||||
if l_sql_node_storage.sql_table_items_count ("page_nodes") = 0 then
|
|
||||||
if attached a_api.user_api.user_by_id (1) as u then
|
|
||||||
create ct
|
|
||||||
p1 := ct.new_node (Void)
|
|
||||||
p1.set_title ("Welcome")
|
|
||||||
p1.set_content ("Welcome, you are using the ROC Eiffel CMS", Void, Void) -- Use default format
|
|
||||||
p1.set_author (u)
|
|
||||||
l_sql_node_storage.save_node (p1)
|
|
||||||
|
|
||||||
p2 := ct.new_node (Void)
|
|
||||||
p2.set_title ("A new page example")
|
|
||||||
p2.set_content ("This is the content of a page", Void, Void) -- Use default format
|
|
||||||
p2.set_author (u)
|
|
||||||
p2.set_parent (p1)
|
|
||||||
l_sql_node_storage.save_node (p2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- FIXME: maybe provide a default solution based on file system, when no SQL storage is available.
|
|
||||||
-- IDEA: we could also have generic extension to node system, that handle generic addition field.
|
|
||||||
end
|
|
||||||
ensure then
|
|
||||||
node_api_set: node_api /= Void
|
|
||||||
end
|
|
||||||
|
|
||||||
feature {CMS_API} -- Module management
|
|
||||||
|
|
||||||
is_installed (a_api: CMS_API): BOOLEAN
|
|
||||||
-- Is Current module installed?
|
|
||||||
do
|
|
||||||
Result := Precursor (a_api)
|
|
||||||
if Result and attached {CMS_STORAGE_SQL_I} a_api.storage as l_sql_storage then
|
|
||||||
Result := l_sql_storage.sql_table_exists ("nodes") and
|
|
||||||
l_sql_storage.sql_table_exists ("page_nodes")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
install (a_api: CMS_API)
|
|
||||||
do
|
|
||||||
-- Schema
|
|
||||||
if attached {CMS_STORAGE_SQL_I} a_api.storage as l_sql_storage then
|
|
||||||
l_sql_storage.sql_execute_file_script (a_api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended (name).appended_with_extension ("sql")), Void)
|
|
||||||
end
|
|
||||||
Precursor {CMS_MODULE}(a_api)
|
|
||||||
end
|
|
||||||
|
|
||||||
feature {CMS_API} -- Access: API
|
|
||||||
|
|
||||||
module_api: detachable CMS_MODULE_API
|
|
||||||
-- <Precursor>
|
|
||||||
do
|
|
||||||
if attached node_api as l_api then
|
|
||||||
Result := l_api
|
|
||||||
else
|
|
||||||
-- Current is initialized, so node_api should be set.
|
|
||||||
check has_node_api: False end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
node_api: detachable CMS_NODE_API
|
|
||||||
-- <Precursor>
|
|
||||||
|
|
||||||
feature -- Access: router
|
|
||||||
|
|
||||||
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
|
||||||
-- <Precursor>
|
|
||||||
do
|
|
||||||
if attached node_api as l_node_api then
|
|
||||||
configure_web (a_api, l_node_api, a_router)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
configure_web (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
|
||||||
local
|
|
||||||
l_node_handler: NODE_HANDLER
|
|
||||||
l_nodes_handler: NODES_HANDLER
|
|
||||||
l_uri_mapping: WSF_URI_MAPPING
|
|
||||||
l_trash_handler: TRASH_HANDLER
|
|
||||||
do
|
|
||||||
-- TODO: for now, focused only on web interface, add REST api later. [2015-April-29]
|
|
||||||
create l_node_handler.make (a_api, a_node_api)
|
|
||||||
create l_uri_mapping.make_trailing_slash_ignored ("/node", l_node_handler)
|
|
||||||
a_router.map (l_uri_mapping, a_router.methods_get_post)
|
|
||||||
|
|
||||||
a_router.handle ("/node/add/{type}", l_node_handler, a_router.methods_get_post)
|
|
||||||
a_router.handle ("/node/{id}/edit", l_node_handler, a_router.methods_get_post)
|
|
||||||
a_router.handle ("/node/{id}/delete", l_node_handler, a_router.methods_get_post)
|
|
||||||
a_router.handle ("/node/{id}/trash", l_node_handler, a_router.methods_get_post)
|
|
||||||
|
|
||||||
a_router.handle ("/node/{id}", l_node_handler, a_router.methods_get)
|
|
||||||
-- For now: no REST API handling... a_router.methods_get_put_delete + a_router.methods_get_post)
|
|
||||||
|
|
||||||
-- Nodes
|
|
||||||
create l_nodes_handler.make (a_api, a_node_api)
|
|
||||||
create l_uri_mapping.make_trailing_slash_ignored ("/nodes", l_nodes_handler)
|
|
||||||
a_router.map (l_uri_mapping, a_router.methods_get)
|
|
||||||
|
|
||||||
--Trash
|
|
||||||
|
|
||||||
create l_trash_handler.make (a_api, a_node_api)
|
|
||||||
create l_uri_mapping.make_trailing_slash_ignored ("/trash", l_trash_handler)
|
|
||||||
a_router.map (l_uri_mapping, a_router.methods_get)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Hooks
|
|
||||||
|
|
||||||
register_hooks (a_response: CMS_RESPONSE)
|
|
||||||
-- <Precursor>
|
|
||||||
do
|
|
||||||
a_response.subscribe_to_menu_system_alter_hook (Current)
|
|
||||||
a_response.subscribe_to_block_hook (Current)
|
|
||||||
end
|
|
||||||
|
|
||||||
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
|
||||||
-- <Precursor>
|
|
||||||
do
|
|
||||||
Result := <<"node-info">>
|
|
||||||
end
|
|
||||||
|
|
||||||
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
|
||||||
local
|
|
||||||
-- b: CMS_CONTENT_BLOCK
|
|
||||||
do
|
|
||||||
-- create b.make (a_block_id, "Block::node", "This is a block test", Void)
|
|
||||||
-- a_response.add_block (b, "sidebar_second")
|
|
||||||
end
|
|
||||||
|
|
||||||
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
|
|
||||||
local
|
|
||||||
lnk: CMS_LOCAL_LINK
|
|
||||||
-- perms: detachable ARRAYED_LIST [READABLE_STRING_8]
|
|
||||||
do
|
|
||||||
create lnk.make ("List of nodes", "nodes")
|
|
||||||
a_menu_system.primary_menu.extend (lnk)
|
|
||||||
|
|
||||||
create lnk.make ("Trash", "trash")
|
|
||||||
a_menu_system.primary_menu.extend (lnk)
|
|
||||||
|
|
||||||
create lnk.make ("Create ..", "node")
|
|
||||||
a_menu_system.primary_menu.extend (lnk)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
17
modules/node/site/files/css/node.css
Normal file
17
modules/node/site/files/css/node.css
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
ul.cms-nodes {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 3px 3px 3px 3px;
|
||||||
|
border: solid 1px #ccc;
|
||||||
|
}
|
||||||
|
ul.cms-nodes li {
|
||||||
|
border-top: dotted 1px #ccc;
|
||||||
|
}
|
||||||
|
ul.cms-nodes li:first-child {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
ul.cms-nodes li.cms_type_page a::before {
|
||||||
|
content: "[page] ";
|
||||||
|
}
|
||||||
|
ul.cms-nodes li.cms_type_blog a::before {
|
||||||
|
content: "[blog] ";
|
||||||
|
}
|
||||||
24
modules/node/site/files/scss/node.scss
Normal file
24
modules/node/site/files/scss/node.scss
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
ul.cms-nodes {
|
||||||
|
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 3px 3px 3px 3px;
|
||||||
|
border: solid 1px #ccc;
|
||||||
|
|
||||||
|
li{
|
||||||
|
border-top: dotted 1px #ccc;
|
||||||
|
&:first-child {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li.cms_type_page a::before {
|
||||||
|
content: "[page] ";
|
||||||
|
}
|
||||||
|
|
||||||
|
li.cms_type_blog a::before {
|
||||||
|
content: "[blog] ";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -63,6 +63,14 @@ feature {NONE} -- Initialization
|
|||||||
-- Can be also used to precise the "From:" value for email.
|
-- Can be also used to precise the "From:" value for email.
|
||||||
site_email := text_item_or_default ("site.email", "webmaster")
|
site_email := text_item_or_default ("site.email", "webmaster")
|
||||||
|
|
||||||
|
|
||||||
|
-- Location for public files
|
||||||
|
if attached text_item ("files-dir") as s then
|
||||||
|
create files_location.make_from_string (s)
|
||||||
|
else
|
||||||
|
files_location := site_location.extended ("files")
|
||||||
|
end
|
||||||
|
|
||||||
-- Location for modules folders.
|
-- Location for modules folders.
|
||||||
if attached text_item ("modules-dir") as s then
|
if attached text_item ("modules-dir") as s then
|
||||||
create modules_location.make_from_string (s)
|
create modules_location.make_from_string (s)
|
||||||
|
|||||||
@@ -95,6 +95,9 @@ feature -- Access: Theme
|
|||||||
site_location: PATH
|
site_location: PATH
|
||||||
-- Path to CMS site root dir.
|
-- Path to CMS site root dir.
|
||||||
|
|
||||||
|
files_location: PATH
|
||||||
|
-- Path to public "files" dir.
|
||||||
|
|
||||||
modules_location: PATH
|
modules_location: PATH
|
||||||
-- Path to modules.
|
-- Path to modules.
|
||||||
|
|
||||||
|
|||||||
31
src/hooks/cms_hook_response_alter.e
Normal file
31
src/hooks/cms_hook_response_alter.e
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
note
|
||||||
|
description: "[
|
||||||
|
Hook providing a way to alter the cms response itself.
|
||||||
|
It is recommanded to use finer cms hook, but this hook is quite general.
|
||||||
|
]"
|
||||||
|
date: "$Date: 2014-11-13 16:23:47 +0100 (jeu., 13 nov. 2014) $"
|
||||||
|
revision: "$Revision: 96085 $"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
CMS_HOOK_RESPONSE_ALTER
|
||||||
|
|
||||||
|
inherit
|
||||||
|
CMS_HOOK
|
||||||
|
|
||||||
|
feature -- Hook
|
||||||
|
|
||||||
|
response_alter (a_response: CMS_RESPONSE)
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
source: "[
|
||||||
|
Eiffel Software
|
||||||
|
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||||
|
Telephone 805-685-1006, Fax 805-685-6869
|
||||||
|
Website http://www.eiffel.com
|
||||||
|
Customer support http://support.eiffel.com
|
||||||
|
]"
|
||||||
|
end
|
||||||
@@ -347,6 +347,12 @@ feature -- Environment/ theme
|
|||||||
Result := setup.site_location
|
Result := setup.site_location
|
||||||
end
|
end
|
||||||
|
|
||||||
|
files_location: PATH
|
||||||
|
-- CMS public files location.
|
||||||
|
do
|
||||||
|
Result := setup.files_location
|
||||||
|
end
|
||||||
|
|
||||||
theme_location: PATH
|
theme_location: PATH
|
||||||
-- Active theme location.
|
-- Active theme location.
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -164,7 +164,19 @@ feature -- Settings: router
|
|||||||
end)
|
end)
|
||||||
a_router.handle ("/theme/", fhdl, router.methods_GET)
|
a_router.handle ("/theme/", fhdl, router.methods_GET)
|
||||||
|
|
||||||
|
-- "/files/.."
|
||||||
|
create fhdl.make_hidden_with_path (api.files_location)
|
||||||
|
fhdl.disable_index
|
||||||
|
fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
|
||||||
|
do
|
||||||
|
execute_default (ia_req, ia_res)
|
||||||
|
end)
|
||||||
|
a_router.handle ("/files/", fhdl, router.methods_GET)
|
||||||
|
|
||||||
|
-- files folder from specific module.
|
||||||
|
a_router.handle ("/module/{modname}/files{/vars}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_module_files), a_router.methods_get)
|
||||||
|
|
||||||
|
-- www folder. Should we keep this??
|
||||||
create fhdl.make_hidden_with_path (setup.environment.www_path)
|
create fhdl.make_hidden_with_path (setup.environment.www_path)
|
||||||
fhdl.disable_index
|
fhdl.disable_index
|
||||||
fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
|
fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
|
||||||
@@ -263,6 +275,27 @@ feature -- Execution
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
handle_module_files (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Handle files per modules.
|
||||||
|
-- i.e: "/module/{modname}/files{/vars}"
|
||||||
|
local
|
||||||
|
fhdl: WSF_FILE_SYSTEM_HANDLER
|
||||||
|
r: NOT_FOUND_ERROR_CMS_RESPONSE
|
||||||
|
do
|
||||||
|
if attached {WSF_STRING} req.path_parameter ("modname") as l_mod_name then
|
||||||
|
create fhdl.make_with_path (api.module_location_by_name (l_mod_name.url_encoded_value).extended ("files"))
|
||||||
|
fhdl.disable_index
|
||||||
|
fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
|
||||||
|
do
|
||||||
|
execute_default (ia_req, ia_res)
|
||||||
|
end)
|
||||||
|
fhdl.execute_starts_with ("/module/" + l_mod_name.url_encoded_value + "/files/", req, res)
|
||||||
|
else
|
||||||
|
create r.make (req, res, api)
|
||||||
|
r.execute
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
execute_default (req: WSF_REQUEST; res: WSF_RESPONSE)
|
execute_default (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
-- Default request handler if no other are relevant
|
-- Default request handler if no other are relevant
|
||||||
local
|
local
|
||||||
@@ -274,7 +307,7 @@ feature -- Execution
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
|
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -613,6 +613,28 @@ feature -- Hook: value alter
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature -- Hook: response
|
||||||
|
|
||||||
|
subscribe_to_response_alter_hook (h: CMS_HOOK_RESPONSE_ALTER)
|
||||||
|
-- Add `h' as subscriber of response alter hooks CMS_HOOK_RESPONSE_ALTER.
|
||||||
|
do
|
||||||
|
subscribe_to_hook (h, {CMS_HOOK_RESPONSE_ALTER})
|
||||||
|
end
|
||||||
|
|
||||||
|
invoke_response_alter (a_response: CMS_RESPONSE)
|
||||||
|
-- Invoke value table alter hook for table `a_table'.
|
||||||
|
do
|
||||||
|
if attached hook_subscribers.item ({CMS_HOOK_RESPONSE_ALTER}) as lst then
|
||||||
|
across
|
||||||
|
lst as c
|
||||||
|
loop
|
||||||
|
if attached {CMS_HOOK_RESPONSE_ALTER} c.item as h then
|
||||||
|
h.response_alter (a_response)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Hook: menu_system_alter
|
feature -- Hook: menu_system_alter
|
||||||
|
|
||||||
subscribe_to_menu_system_alter_hook (h: CMS_HOOK_MENU_SYSTEM_ALTER)
|
subscribe_to_menu_system_alter_hook (h: CMS_HOOK_MENU_SYSTEM_ALTER)
|
||||||
@@ -868,6 +890,9 @@ feature -- Generation
|
|||||||
common_prepare (page)
|
common_prepare (page)
|
||||||
custom_prepare (page)
|
custom_prepare (page)
|
||||||
|
|
||||||
|
-- Cms response
|
||||||
|
invoke_response_alter (Current)
|
||||||
|
|
||||||
-- Cms values
|
-- Cms values
|
||||||
invoke_value_table_alter (values)
|
invoke_value_table_alter (values)
|
||||||
|
|
||||||
@@ -1132,4 +1157,7 @@ feature {NONE} -- Execution
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -30,8 +30,9 @@ feature -- Execution
|
|||||||
process
|
process
|
||||||
-- Computed response message.
|
-- Computed response message.
|
||||||
do
|
do
|
||||||
-- set_title ("CMS")
|
|
||||||
-- set_page_title (Void)
|
|
||||||
end
|
end
|
||||||
|
note
|
||||||
|
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user