Compare commits

..

8 Commits

Author SHA1 Message Date
a7f1f14b8a Added missing change to installed file for demo example. 2016-02-18 16:14:58 +01:00
fbda2c9eb2 Reuse improved CMS_HOOK_BLOCK_HELPER to help creation of block templates.
Fixed typo in basic auth login form.
2016-02-18 16:13:58 +01:00
ff58593bff Added functions to get link from menu or link composite.
Improved management menu, but using sub menu.
2016-02-18 12:47:21 +01:00
c65f5765d6 Removed unwanted auth.json file (wrong directory). 2016-02-17 16:11:50 +01:00
19565b9c98 Updated registration form. 2016-02-17 16:07:20 +01:00
6716cb5575 Protected cache, export and feeds menu link. 2016-02-17 15:20:38 +01:00
75332c148d Added protection/permissions. 2016-02-17 12:24:58 +01:00
b54fd85172 Added files module, with for now, a focus on upload files facility.
Contribution from Fabian Murer, as part of an ETH student project.
Supervised, refactorized and merged by Jocelyn Fiat.

Signed-off-by: Fabian Murer <fmurer@student.ethz.ch>
Signed-off-by: Jocelyn Fiat <git@djoce.net>
2016-02-17 12:03:24 +01:00
48 changed files with 7999 additions and 3707 deletions

View File

@@ -1,3 +1,4 @@
@echo off
setlocal setlocal
set ROC_CMD=call %~dp0..\..\tools\roc.bat set ROC_CMD=call %~dp0..\..\tools\roc.bat
set ROC_CMS_DIR=%~dp0 set ROC_CMS_DIR=%~dp0

View File

@@ -2,8 +2,8 @@
#navigation.region=sidebar_first #navigation.region=sidebar_first
#navigation.condition=is_front #navigation.condition=is_front
management.conditions[]=path:admin* #management.conditions[]=path:admin*
management.conditions[]=is_front #management.conditions[]=is_front
#Feeds #Feeds
feed.news.weight=3 feed.news.weight=3

View File

@@ -1,5 +1,10 @@
{ {
"subject": "Thank you for contacting us", "subject": "Thank you for contacting us",
"forms": {
"registration": {
"application_description": "Present yourself in a few lines, otherwise your application is likely to be rejected."
}
},
"recaptcha": { "recaptcha": {
"site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD", "site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD",
"secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx" "secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx"

View File

@@ -1,39 +1,38 @@
<div> <div>
<form action="{$site_url/}account/roc-register" method="post"> <form action="{$site_url/}account/roc-register" method="post">
<fieldset> <fieldset>
<legend>Registration</legend> <legend>Registration</legend>
<div> <div>
<input type="text" id="name" name="name" value="{$name/}" required autofocus /> <input type="text" id="name" name="name" value="{$name/}" required autofocus />
<label for="name">Name</label> <label for="name">Name</label>
{if isset="$error_name"} {if isset="$error_name"}
<span><i>{$error_name/}</i></span> <br> <span><i>{$error_name/}</i></span> <br>
{/if} {/if}
</div> </div>
<div> <div>
<input type="password" id="password" name="password" value="" required/> <input type="password" id="password" name="password" value="" required/>
<label for="password">Password</label> <label for="password">Password</label>
</div> </div>
<div> <div>
<input type="email" id="email" name="email" value="{$email/}" required/> <input type="email" id="email" name="email" value="{$email/}" required/>
<label for="email">Email</label> <label for="email">Email</label>
{if isset="$error_email"} {if isset="$error_email"}
<span><i>{$error_email/}</i></span> <br> <span><i>{$error_email/}</i></span> <br/>
{/if} {/if}
</div> </div>
<div> <div>
<textarea rows="4" cols="50" name="personal_information" id="personal_information" required> <textarea rows="4" cols="50" name="personal_information" id="personal_information" required>{$personal_information/}</textarea>
{$personal_information/} <label for="personal_information">Tell us why you want to register an account</label>
</textarea> {if isset="$error_application"}
<label for="personal_information">Tell us why you want to register an account</label> <span><i>{$error_application/}</i></span><br/>
{if isset="$error_application"} {/if}
<span><i>{$error_application/}</i></span> <br> {if isset="$application_description"}
{/if} <br/>
</div> <p class="description">{$application_description/}</p>
{unless isempty="$recaptcha_site_key"} {/if}
<div class="g-recaptcha" data-sitekey="{$recaptcha_site_key/}"></div> </div>
<br/> {unless isempty="$recaptcha_site_key"}<div class="g-recaptcha" data-sitekey="{$recaptcha_site_key/}"></div><br/>{/unless}
{/unless} <button type="submit">Register</button>
<button type="submit">Register</button> </fieldset>
</fieldset> </form>
</form>
</div> </div>

View File

@@ -1,6 +1,6 @@
{unless isset="$user"} {unless isset="$user"}
<div class="login-box"> <div class="login-box">
<div class="description">The "Basic Auth" relies on the HTTP basic acces authentication.<br/>(see also: <a href="https://en.wikipedia.org/wiki/Basic_access_authentication">https://en.wikipedia.org/wiki/Basic_access_authentication</a> )</div> <div class="description">The "Basic Auth" relies on the HTTP basic access authentication.<br/>(see also: <a href="https://en.wikipedia.org/wiki/Basic_access_authentication">https://en.wikipedia.org/wiki/Basic_access_authentication</a> )</div>
<h3>Login or <a href="{$site_url/}account/roc-register">Register</a></h3> <h3>Login or <a href="{$site_url/}account/roc-register">Register</a></h3>
<div> <div>
<form name="cms_basic_auth" action="{$site_url/}roc-basic-login" method="POST"> <form name="cms_basic_auth" action="{$site_url/}roc-basic-login" method="POST">

View File

@@ -1,38 +1,44 @@
.uploaded-files { .uploaded-files table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
border: 1px solid black; border: 1px solid black;
} }
.uploaded-files th { .uploaded-files table th {
padding-left: 5px; padding: 3px 0 3px 5px;
padding-top: 3px;
padding-bottom: 3px;
} }
.uploaded-files td { .uploaded-files table td {
padding-left: 5px; padding: 3px 0 3px 5px;
padding-top: 3px;
padding-bottom: 3px;
} }
.uploaded-files a.button { .uploaded-files a.button {
color: black; color: black;
text-decoration: none; text-decoration: none;
border: solid 1px #999; border: solid 1px #999;
background-color: #ddd; background-color: #ddd;
padding: 2px 4px 2px 4px;
} }
.uploaded-files a.button:hover { .uploaded-files a.button:hover {
color: black; color: black;
text-decoration: none; border: solid 1px #06f;
background-color: #cff;
} }
.upload-files a.upload-button { .upload-files .center {
text-align: center;
padding: 10px;
}
.upload-files a.button {
margin: auto; margin: auto;
width: 100px; width: 100px;
color: black; color: black;
text-decoration: none; text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
} }
.upload-files a.upload-button:hover { .upload-files a.button:hover {
color: black; color: black;
text-decoration: none; border: solid 1px #06f;
background-color: #cff;
} }
/******************* Drop Zone *******************/ /******************* Drop Zone *******************/
@@ -44,18 +50,3 @@
padding-top: 15px; padding-top: 15px;
padding-bottom: 15px; padding-bottom: 15px;
} }
.dropzone .dz-message {
cursor: pointer;
}
.dropzone .dz-preview, .dropzone .dz-file-preview, .dropzone .dz-processing, .dropzone .dz-success,
.dropzone .dz-image-preview, .dropzone .dz-complete {
padding: 10px;
margin: 10px;
width: auto;
display: inline-block;
}
.dropzone .dz-preview {
border: 1px solid black;
border-radius: 5px;
background: #e6e6e6;
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
/*
* The MIT License
* Copyright (c) 2012 Matias Meno <m@tias.me>
*/
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
.dropzone, .dropzone * {
box-sizing: border-box;
}
.dropzone {
position: relative;
.dz-preview {
position: relative;
display: inline-block;
width: 120px;
margin: 0.5em;
.dz-progress {
display: block;
height: 15px;
border: 1px solid #aaa;
.dz-upload {
display: block;
height: 100%;
width: 0;
background: green;
}
}
.dz-error-message {
color: red;
display: none;
}
&.dz-error {
.dz-error-message, .dz-error-mark {
display: block;
}
}
&.dz-success {
.dz-success-mark {
display: block;
}
}
.dz-error-mark, .dz-success-mark {
position: absolute;
display: none;
left: 30px;
top: 30px;
width: 54px;
height: 58px;
left: 50%;
margin-left: -(54px/2);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,413 @@
/*
* The MIT License
* Copyright (c) 2012 Matias Meno <m@tias.me>
*/
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
@mixin keyframes($name) {
@-webkit-keyframes #{$name} {
@content;
}
@-moz-keyframes #{$name} {
@content;
}
@keyframes #{$name} {
@content;
}
}
@mixin prefix($map, $vendors: webkit moz ms o) {
@each $prop, $value in $map {
@if $vendors {
@each $vendor in $vendors {
#{"-" + $vendor + "-" + $prop}: #{$value};
}
}
// Dump regular property anyway
#{$prop}: #{$value};
}
}
@include keyframes(passing-through) {
0% {
opacity: 0;
@include prefix((transform: translateY(40px)));
}
30%, 70% {
opacity: 1;
@include prefix((transform: translateY(0px)));
}
100% {
opacity: 0;
@include prefix((transform: translateY(-40px)));
}
}
@include keyframes(slide-in) {
0% {
opacity: 0;
@include prefix((transform: translateY(40px)));
}
30% {
opacity: 1;
@include prefix((transform: translateY(0px)));
}
}
@include keyframes(pulse) {
0% { @include prefix((transform: scale(1))); }
10% { @include prefix((transform: scale(1.1))); }
20% { @include prefix((transform: scale(1))); }
}
.dropzone, .dropzone * {
box-sizing: border-box;
}
.dropzone {
$image-size: 120px;
$image-border-radius: 20px;
&.dz-clickable {
cursor: pointer;
* {
cursor: default;
}
.dz-message {
&, * {
cursor: pointer;
}
}
}
min-height: 150px;
border: 2px solid rgba(0, 0, 0, 0.3);
background: white;
padding: 20px 20px;
&.dz-started {
.dz-message {
display: none;
}
}
&.dz-drag-hover {
border-style: solid;
.dz-message {
opacity: 0.5;
}
}
.dz-message {
text-align: center;
margin: 2em 0;
}
.dz-preview {
position: relative;
display: inline-block;
vertical-align: top;
margin: 16px;
min-height: 100px;
&:hover {
// Making sure that always the hovered preview element is on top
z-index: 1000;
.dz-details {
opacity: 1;
}
}
&.dz-file-preview {
.dz-image {
border-radius: $image-border-radius;
background: #999;
background: linear-gradient(to bottom, #eee, #ddd);
}
.dz-details {
opacity: 1;
}
}
&.dz-image-preview {
background: white;
.dz-details {
@include prefix((transition: opacity 0.2s linear));
}
}
.dz-remove {
font-size: 14px;
text-align: center;
display: block;
cursor: pointer;
border: none;
&:hover {
text-decoration: underline;
}
}
&:hover .dz-details {
opacity: 1;
}
.dz-details {
$background-color: #444;
z-index: 20;
position: absolute;
top: 0;
left: 0;
opacity: 0;
font-size: 13px;
min-width: 100%;
max-width: 100%;
padding: 2em 1em;
text-align: center;
color: rgba(0, 0, 0, 0.9);
$width: 120px;
line-height: 150%;
.dz-size {
margin-bottom: 1em;
font-size: 16px;
}
.dz-filename {
white-space: nowrap;
&:hover {
span {
border: 1px solid rgba(200, 200, 200, 0.8);
background-color: rgba(255, 255, 255, 0.8);
}
}
&:not(:hover) {
span {
border: 1px solid transparent;
}
overflow: hidden;
text-overflow: ellipsis;
}
}
.dz-filename, .dz-size {
span {
background-color: rgba(255, 255, 255, 0.4);
padding: 0 0.4em;
border-radius: 3px;
}
}
}
&:hover {
.dz-image {
// opacity: 0.8;
img {
@include prefix((transform: scale(1.05, 1.05))); // Getting rid of that white bleed-in
@include prefix((filter: blur(8px)), webkit); // Getting rid of that white bleed-in
}
}
}
.dz-image {
border-radius: $image-border-radius;
overflow: hidden;
width: $image-size;
height: $image-size;
position: relative;
display: block;
z-index: 10;
img {
display: block;
}
}
&.dz-success {
.dz-success-mark {
@include prefix((animation: passing-through 3s cubic-bezier(0.770, 0.000, 0.175, 1.000)));
}
}
&.dz-error {
.dz-error-mark {
opacity: 1;
@include prefix((animation: slide-in 3s cubic-bezier(0.770, 0.000, 0.175, 1.000)));
}
}
.dz-success-mark, .dz-error-mark {
$image-height: 54px;
$image-width: 54px;
pointer-events: none;
opacity: 0;
z-index: 500;
position: absolute;
display: block;
top: 50%;
left: 50%;
margin-left: -($image-width/2);
margin-top: -($image-height/2);
svg {
display: block;
width: $image-width;
height: $image-height;
}
}
&.dz-processing .dz-progress {
opacity: 1;
@include prefix((transition: all 0.2s linear));
}
&.dz-complete .dz-progress {
opacity: 0;
@include prefix((transition: opacity 0.4s ease-in));
}
&:not(.dz-processing) {
.dz-progress {
@include prefix((animation: pulse 6s ease infinite));
}
}
.dz-progress {
opacity: 1;
z-index: 1000;
pointer-events: none;
position: absolute;
height: 16px;
left: 50%;
top: 50%;
margin-top: -8px;
width: 80px;
margin-left: -40px;
// border: 2px solid #333;
background: rgba(255, 255, 255, 0.9);
// Fix for chrome bug: https://code.google.com/p/chromium/issues/detail?id=157218
-webkit-transform: scale(1);
border-radius: 8px;
overflow: hidden;
.dz-upload {
background: #333;
background: linear-gradient(to bottom, #666, #444);
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 0;
@include prefix((transition: width 300ms ease-in-out));
}
}
&.dz-error {
.dz-error-message {
display: block;
}
&:hover .dz-error-message {
opacity: 1;
pointer-events: auto;
}
}
.dz-error-message {
$width: $image-size + 20px;
$color: rgb(190, 38, 38);
pointer-events: none;
z-index: 1000;
position: absolute;
display: block;
display: none;
opacity: 0;
@include prefix((transition: opacity 0.3s ease));
border-radius: 8px;
font-size: 13px;
top: $image-size + 10px;
left: -10px;
width: $width;
background: $color;
background: linear-gradient(to bottom, $color, darken($color, 5%));
padding: 0.5em 1.2em;
color: white;
// The triangle pointing up
&:after {
content: '';
position: absolute;
top: -6px;
left: $width / 2 - 6px;
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid $color;
}
}
}
}

View File

@@ -1,18 +1,16 @@
.uploaded-files { .uploaded-files {
width: 100%; table {
border-collapse: collapse; width: 100%;
border: 1px solid black; border-collapse: collapse;
border: 1px solid black;
th { th {
padding-left: 5px; padding: 3px 0 3px 5px;
padding-top: 3px; }
padding-bottom: 3px;
}
td { td {
padding-left: 5px; padding: 3px 0 3px 5px;
padding-top: 3px; }
padding-bottom: 3px;
} }
a.button{ a.button{
@@ -20,23 +18,33 @@
text-decoration: none; text-decoration: none;
border: solid 1px #999; border: solid 1px #999;
background-color: #ddd; background-color: #ddd;
padding: 2px 4px 2px 4px;
&:hover { &:hover {
color: black; color: black;
text-decoration: none; border: solid 1px #06f;
background-color: #cff;
} }
} }
} }
.upload-files { .upload-files {
a.upload-button{ .center {
text-align: center;
padding: 10px;
}
a.button{
margin: auto; margin: auto;
width: 100px; width: 100px;
color: black; color: black;
text-decoration: none; text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
&:hover { &:hover {
color: black; color: black;
text-decoration: none; border: solid 1px #06f;
background-color: #cff;
} }
} }
} }
@@ -51,23 +59,5 @@
text-align: center; text-align: center;
padding-top: 15px; padding-top: 15px;
padding-bottom: 15px; padding-bottom: 15px;
.dz-message {
cursor: pointer;
}
.dz-preview, .dz-file-preview, .dz-processing, .dz-success,
.dz-image-preview, .dz-complete {
padding: 10px;
margin: 10px;
width: auto;
display: inline-block;
}
.dz-preview {
border: 1px solid black;
border-radius: 5px;
background: #e6e6e6;
}
} }

View File

@@ -163,6 +163,22 @@ feature -- Security
feature -- Element change feature -- Element change
set_title (a_title: detachable READABLE_STRING_GENERAL)
-- Set `title' to `a_title' or `location'.
do
if a_title /= Void then
title := a_title.as_string_32
else
title := location.as_string_32
end
end
set_location (a_loc: READABLE_STRING_8)
-- Set `location' to `a_loc'.
do
location := a_loc
end
set_weight (a_weight: INTEGER) set_weight (a_weight: INTEGER)
-- Set `weight' to `a_weight'. -- Set `weight' to `a_weight'.
do do

View File

@@ -18,13 +18,82 @@ feature -- Access
deferred deferred
end end
feature -- Element change item_by_title (a_title: READABLE_STRING_GENERAL): detachable CMS_LINK
-- First link with title `a_title' if any.
do
if attached items as l_items then
across
l_items as ic
until
Result /= Void
loop
Result := ic.item
if not a_title.is_case_insensitive_equal (Result.title) then
Result := Void
end
end
end
ensure
coherent_result: Result /= Void implies Result.title.is_case_insensitive_equal_general (a_title)
end
item_by_location (a_loc: READABLE_STRING_8): detachable CMS_LINK
-- First link with location `a_loc' if any.
do
if attached items as l_items then
across
l_items as ic
until
Result /= Void
loop
Result := ic.item
if not a_loc.same_string (Result.location) then
Result := Void
end
end
end
ensure
coherent_result: Result /= Void implies Result.location.same_string (a_loc)
end
new_composite_item (a_title: detachable READABLE_STRING_GENERAL; a_location: READABLE_STRING_8): CMS_LINK_COMPOSITE
-- If exists, item with location `a_location' or title `a_title',
-- otherwise create new local link and extend to Current.
local
lnk: CMS_LOCAL_LINK
do
if attached {CMS_LINK_COMPOSITE} item_by_location (a_location) as l_parent then
Result := l_parent
elseif a_title /= Void and then attached {CMS_LINK_COMPOSITE} item_by_title (a_title) as l_parent then
Result := l_parent
else
create lnk.make (a_title, a_location)
extend (lnk)
Result := lnk
end
if attached {CMS_LOCAL_LINK} Result as l_local_lnk and then not l_local_lnk.is_expanded then
l_local_lnk.set_expandable (True)
l_local_lnk.set_collapsed (True)
end
end
feature -- Element change
extend (lnk: CMS_LINK) extend (lnk: CMS_LINK)
-- Add `lnk' as a sub link. -- Add `lnk' as a sub link.
deferred deferred
end end
extend_into (lnk: CMS_LINK; a_parent_title: detachable READABLE_STRING_GENERAL; a_parent_location: READABLE_STRING_8)
-- Extend `lnk' into local link with location `a_parent_location'.
-- If the parent is not found, create it with title `a_parent_title'.
local
l_parent: CMS_LINK_COMPOSITE
do
l_parent := new_composite_item (a_parent_title, a_parent_location)
l_parent.extend (lnk)
end
remove (lnk: CMS_LINK) remove (lnk: CMS_LINK)
-- Remove link `lnk' from Current container. -- Remove link `lnk' from Current container.
deferred deferred
@@ -68,6 +137,6 @@ feature -- status report
end end
note note
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others" copyright: "2011-2016, Javier Velilla, Jocelyn Fiat, 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)"
end end

View File

@@ -79,16 +79,6 @@ feature -- Security
feature -- Element change feature -- Element change
set_title (a_title: detachable READABLE_STRING_GENERAL)
-- Set `title' to `a_title' or `location'.
do
if a_title /= Void then
title := a_title.as_string_32
else
title := location.as_string_32
end
end
add_link (lnk: CMS_LINK) add_link (lnk: CMS_LINK)
-- <Precursor> -- <Precursor>
local local
@@ -194,6 +184,6 @@ feature {NONE} -- Implementation
invariant invariant
note note
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others" copyright: "2011-2016, Javier Velilla, Jocelyn Fiat, 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)"
end end

View File

@@ -73,7 +73,7 @@ feature -- Status report
end end
end end
feature -- Element change feature -- Element change
extend (lnk: CMS_LINK) extend (lnk: CMS_LINK)
-- <Precursor> -- <Precursor>
@@ -104,6 +104,6 @@ feature -- Access
invariant invariant
note note
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others" copyright: "2011-2016, Javier Velilla, Jocelyn Fiat, 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)"
end end

View File

@@ -103,7 +103,7 @@ feature -- Security
-- List of permission ids, used by this module, and declared. -- List of permission ids, used by this module, and declared.
do do
Result := Precursor Result := Precursor
Result.force ("manage admin") Result.force ("access admin")
Result.force ("admin users") Result.force ("admin users")
Result.force ("admin roles") Result.force ("admin roles")
Result.force ("admin modules") Result.force ("admin modules")
@@ -132,28 +132,35 @@ feature -- Hooks
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)
local local
lnk: CMS_LOCAL_LINK lnk: CMS_LOCAL_LINK
admin_lnk: CMS_LINK_COMPOSITE
do do
if if a_response.api.user_is_authenticated then
a_response.has_permission ("manage " + {CMS_ADMIN_MODULE}.name) -- Note: admin user has all permissions enabled by default. admin_lnk := a_menu_system.management_menu.new_composite_item ("Admin", "admin")
then
-- TODO: we should probably use more side menu and less primary_menu.
create lnk.make ("Admin", "admin")
lnk.set_permission_arguments (<<"manage " + {CMS_ADMIN_MODULE}.name>>)
a_menu_system.management_menu.extend (lnk)
create lnk.make ("Module", "admin/modules")
lnk.set_permission_arguments (<<"manage module">>)
admin_lnk.extend (lnk)
-- Per module cache permission!
create lnk.make ("Cache", "admin/cache")
admin_lnk.extend (lnk)
-- Per module export permission!
create lnk.make ("Export", "admin/export")
admin_lnk.extend (lnk)
-- if
-- a_response.has_permission ("access " + {CMS_ADMIN_MODULE}.name) -- Note: admin user has all permissions enabled by default.
-- then
-- lnk := admin_lnk
-- lnk.set_title ("Admin")
-- a_menu_system.management_menu.extend (lnk)
-- elseif admin_lnk.has_children then
-- a_menu_system.management_menu.extend (admin_lnk)
-- end
-- admin_lnk.set_permission_arguments (<<"access " + {CMS_ADMIN_MODULE}.name>>)
end end
create lnk.make ("Module", "admin/modules")
lnk.set_permission_arguments (<<"manage module">>)
a_menu_system.management_menu.extend (lnk)
-- Per module cache permission!
create lnk.make ("Cache", "admin/cache")
a_menu_system.management_menu.extend (lnk)
-- Per module export permission!
create lnk.make ("Export", "admin/export")
a_menu_system.management_menu.extend (lnk)
end end
note note

View File

@@ -17,22 +17,58 @@ feature -- Process
process process
local local
b: STRING b: STRING
l_admin_links: ARRAYED_LIST [TUPLE [package: READABLE_STRING_8; permissions: ARRAY [READABLE_STRING_GENERAL]; link: CMS_LINK; help: READABLE_STRING_GENERAL]]
lst: detachable ARRAYED_LIST [TUPLE [permissions: ARRAY [READABLE_STRING_GENERAL]; link: CMS_LINK; help: READABLE_STRING_GENERAL]]
categories: STRING_TABLE [ARRAYED_LIST [TUPLE [permissions: ARRAY [READABLE_STRING_GENERAL]; link: CMS_LINK; help: READABLE_STRING_GENERAL]]]
l_package: READABLE_STRING_8
do do
create l_admin_links.make (5)
l_admin_links.force (["core", <<"admin users">>, local_link ("Users", "admin/users"), "View/Edit/Add Users"])
l_admin_links.force (["core", <<"admin roles">>, local_link ("Roles", "admin/roles"), "View/Edit/Add Roles"])
l_admin_links.force (["core", <<"admin modules">>, local_link ("Modules", "admin/modules"), "(un)Install modules"])
l_admin_links.force (["support", <<"admin cache">>, local_link ("Cache", "admin/cache"), "Clear caches"])
l_admin_links.force (["support", <<"admin export">>, local_link ("Export", "admin/export"), "Export CMS contents, and modules contents."])
create categories.make_caseless (3)
across
l_admin_links as ic
loop
l_package := ic.item.package
lst := categories.item (l_package)
if lst = Void then
create lst.make (1)
categories.force (lst, l_package)
end
lst.force ([ic.item.permissions, ic.item.link, ic.item.help])
end
create b.make_empty create b.make_empty
set_title (translation ("Admin Page", Void)) set_title (translation ("Admin Page", Void))
b.append ("<ul id=%"content-types%">")
fixme ("Check how to make it configurable") fixme ("Check how to make it configurable")
if has_permissions (<< "admin users">>) then across
b.append ("<li>" + link ("Users", "admin/users", Void)) categories as cats_ic
b.append ("<div class=%"description%">View/Edit/Add Users</div>") loop
b.append ("</li>") lst := cats_ic.item
b.append ("<h3>")
b.append (html_encoded (cats_ic.key))
b.append ("</h3>")
b.append ("<ul>")
across
lst as ic
loop
if has_permissions (ic.item.permissions) then
b.append ("<li>")
if attached ic.item.link as lnk then
b.append (link (lnk.title, lnk.location, Void))
end
b.append ("<div class=%"description%">")
b.append (html_encoded (ic.item.help))
b.append ("</div>")
b.append ("</li>")
end
end
b.append ("</ul>")
end end
if has_permissions (<< "admin roles">>) then
b.append ("<li>" + link ("Roles", "admin/roles", Void))
b.append ("<div class=%"description%">View/Edit/Add Roles</div>")
b.append ("</li>")
end
b.append ("</ul>")
set_main_content (b) set_main_content (b)
end end

View File

@@ -16,6 +16,8 @@ inherit
CMS_HOOK_MENU_SYSTEM_ALTER CMS_HOOK_MENU_SYSTEM_ALTER
CMS_HOOK_BLOCK_HELPER
SHARED_LOGGER SHARED_LOGGER
feature {NONE} -- Initialization feature {NONE} -- Initialization
@@ -86,23 +88,4 @@ feature -- Hooks
end end
end end
feature {NONE} -- Helpers
template_block (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE): detachable CMS_SMARTY_TEMPLATE_BLOCK
-- Smarty content block for `a_block_id'
local
p: detachable PATH
do
create p.make_from_string ("templates")
p := p.extended ("block_").appended (a_block_id).appended_with_extension ("tpl")
p := a_response.api.module_theme_resource_location (Current, p)
if p /= Void then
if attached p.entry as e then
create Result.make (a_block_id, Void, p.parent, e)
else
create Result.make (a_block_id, Void, p.parent, p)
end
end
end
end end

View File

@@ -21,6 +21,8 @@ inherit
CMS_HOOK_BLOCK CMS_HOOK_BLOCK
CMS_HOOK_BLOCK_HELPER
CMS_HOOK_MENU_SYSTEM_ALTER CMS_HOOK_MENU_SYSTEM_ALTER
SHARED_EXECUTION_ENVIRONMENT SHARED_EXECUTION_ENVIRONMENT
@@ -192,7 +194,7 @@ feature -- Hooks configuration
-- Add the link to the taxonomy to the main menu -- Add the link to the taxonomy to the main menu
if a_response.has_permission ("admin registration") then if a_response.has_permission ("admin registration") then
create lnk.make ("Registration", "admin/pending-registrations/") create lnk.make ("Registration", "admin/pending-registrations/")
a_menu_system.management_menu.extend (lnk) a_menu_system.management_menu.extend_into (lnk, "Admin", "admin")
end end
end end
@@ -208,7 +210,7 @@ feature -- Handler
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create b.make_empty create b.make_empty
l_user := r.user l_user := r.user
if attached template_block ("account_info", r) as l_tpl_block then if attached template_block (Current, "account_info", api) as l_tpl_block then
l_tpl_block.set_weight (-10) l_tpl_block.set_weight (-10)
r.add_block (l_tpl_block, "content") r.add_block (l_tpl_block, "content")
else else
@@ -246,7 +248,7 @@ feature -- Handler
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create b.make_empty create b.make_empty
l_user := r.user l_user := r.user
if attached template_block ("account_edit", r) as l_tpl_block then if attached template_block (Current, "account_edit", api) as l_tpl_block then
l_tpl_block.set_weight (-10) l_tpl_block.set_weight (-10)
r.add_block (l_tpl_block, "content") r.add_block (l_tpl_block, "content")
else else
@@ -831,7 +833,7 @@ feature -- Handler
block_list: ITERABLE [like {CMS_BLOCK}.name] block_list: ITERABLE [like {CMS_BLOCK}.name]
do do
Result := <<"register", "reactivate", "new_password", "reset_password", "registration">> Result := <<"register", "reactivate", "new_password", "reset_password">>
end end
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
@@ -847,8 +849,6 @@ feature -- Handler
get_block_view_new_password (a_block_id, a_response) get_block_view_new_password (a_block_id, a_response)
elseif a_block_id.is_case_insensitive_equal_general ("reset_password") and then loc.starts_with ("account/reset-password") then elseif a_block_id.is_case_insensitive_equal_general ("reset_password") and then loc.starts_with ("account/reset-password") then
get_block_view_reset_password (a_block_id, a_response) get_block_view_reset_password (a_block_id, a_response)
elseif a_block_id.is_case_insensitive_equal_general ("registration") and then loc.starts_with ("admin/pending-registrations") then
get_block_view_registration (a_block_id, a_response)
end end
end end
@@ -923,32 +923,24 @@ feature {NONE} -- Token Generation
Result := l_token Result := l_token
end end
feature {NONE} -- Helpers
template_block (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE): detachable CMS_SMARTY_TEMPLATE_BLOCK
-- Smarty content block for `a_block_id'
local
p: detachable PATH
do
create p.make_from_string ("templates")
p := p.extended ("block_").appended (a_block_id).appended_with_extension ("tpl")
p := a_response.api.module_theme_resource_location (Current, p)
if p /= Void then
if attached p.entry as e then
create Result.make (a_block_id, Void, p.parent, e)
else
create Result.make (a_block_id, Void, p.parent, p)
end
end
end
feature {NONE} -- Block views feature {NONE} -- Block views
get_block_view_register (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) get_block_view_register (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
do do
if a_response.has_permission ("account register") then if a_response.has_permission ("account register") then
if a_response.request.is_get_request_method then if
if attached template_block (a_block_id, a_response) as l_tpl_block then a_response.request.is_get_request_method
or else (
a_response.values.has ("error_name")
or else a_response.values.has ("error_email")
)
then
if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
-- l_tpl_block.set_value (a_response.values.item ("error_name"), "error_name")
-- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email")
-- l_tpl_block.set_value (a_response.values.item ("email"), "email")
-- l_tpl_block.set_value (a_response.values.item ("name"), "name")
l_tpl_block.set_value (form_registration_application_description (a_response.api), "application_description")
if attached recaptcha_site_key (a_response.api) as l_recaptcha_site_key then if attached recaptcha_site_key (a_response.api) as l_recaptcha_site_key then
l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key") l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key")
end end
@@ -959,28 +951,11 @@ feature {NONE} -- Block views
end end
end end
elseif a_response.request.is_post_request_method then elseif a_response.request.is_post_request_method then
if a_response.values.has ("error_name") or else a_response.values.has ("error_email") then if attached template_block (Current, "post_register", a_response.api) as l_tpl_block then
if attached template_block (a_block_id, a_response) as l_tpl_block then a_response.add_block (l_tpl_block, "content")
-- l_tpl_block.set_value (a_response.values.item ("error_name"), "error_name")
-- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email")
-- l_tpl_block.set_value (a_response.values.item ("email"), "email")
-- l_tpl_block.set_value (a_response.values.item ("name"), "name")
if attached recaptcha_site_key (a_response.api) as l_recaptcha_site_key then
l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key")
end
a_response.add_block (l_tpl_block, "content")
else
debug ("cms")
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
end
end
else else
if attached template_block ("post_register", a_response) as l_tpl_block then debug ("cms")
a_response.add_block (l_tpl_block, "content") a_response.add_warning_message ("Error with block [" + a_block_id + "]")
else
debug ("cms")
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
end
end end
end end
end end
@@ -990,7 +965,7 @@ feature {NONE} -- Block views
get_block_view_reactivate (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) get_block_view_reactivate (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
do do
if a_response.request.is_get_request_method then if a_response.request.is_get_request_method then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
else else
debug ("cms") debug ("cms")
@@ -999,7 +974,7 @@ feature {NONE} -- Block views
end end
elseif a_response.request.is_post_request_method then elseif a_response.request.is_post_request_method then
if a_response.values.has ("error_email") or else a_response.values.has ("is_active") then if a_response.values.has ("error_email") or else a_response.values.has ("is_active") then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
-- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email") -- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email")
-- l_tpl_block.set_value (a_response.values.item ("email"), "email") -- l_tpl_block.set_value (a_response.values.item ("email"), "email")
-- l_tpl_block.set_value (a_response.values.item ("is_active"), "is_active") -- l_tpl_block.set_value (a_response.values.item ("is_active"), "is_active")
@@ -1010,7 +985,7 @@ feature {NONE} -- Block views
end end
end end
else else
if attached template_block ("post_reactivate", a_response) as l_tpl_block then if attached template_block (Current, "post_reactivate", a_response.api) as l_tpl_block then
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
else else
debug ("cms") debug ("cms")
@@ -1024,7 +999,7 @@ feature {NONE} -- Block views
get_block_view_new_password (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) get_block_view_new_password (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
do do
if a_response.request.is_get_request_method then if a_response.request.is_get_request_method then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
else else
debug ("cms") debug ("cms")
@@ -1033,7 +1008,7 @@ feature {NONE} -- Block views
end end
elseif a_response.request.is_post_request_method then elseif a_response.request.is_post_request_method then
if a_response.values.has ("error_email") or else a_response.values.has ("error_username") then if a_response.values.has ("error_email") or else a_response.values.has ("error_username") then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
-- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email") -- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email")
-- l_tpl_block.set_value (a_response.values.item ("email"), "email") -- l_tpl_block.set_value (a_response.values.item ("email"), "email")
-- l_tpl_block.set_value (a_response.values.item ("error_username"), "error_username") -- l_tpl_block.set_value (a_response.values.item ("error_username"), "error_username")
@@ -1045,7 +1020,7 @@ feature {NONE} -- Block views
end end
end end
else else
if attached template_block ("post_password", a_response) as l_tpl_block then if attached template_block (Current, "post_password", a_response.api) as l_tpl_block then
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
else else
debug ("cms") debug ("cms")
@@ -1059,7 +1034,7 @@ feature {NONE} -- Block views
get_block_view_reset_password (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) get_block_view_reset_password (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
do do
if a_response.request.is_get_request_method then if a_response.request.is_get_request_method then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
-- l_tpl_block.set_value (a_response.values.item ("token"), "token") -- l_tpl_block.set_value (a_response.values.item ("token"), "token")
-- l_tpl_block.set_value (a_response.values.item ("error_token"), "error_token") -- l_tpl_block.set_value (a_response.values.item ("error_token"), "error_token")
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
@@ -1070,7 +1045,7 @@ feature {NONE} -- Block views
end end
elseif a_response.request.is_post_request_method then elseif a_response.request.is_post_request_method then
if a_response.values.has ("error_token") or else a_response.values.has ("error_password") then if a_response.values.has ("error_token") or else a_response.values.has ("error_password") then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
-- l_tpl_block.set_value (a_response.values.item ("error_token"), "error_token") -- l_tpl_block.set_value (a_response.values.item ("error_token"), "error_token")
-- l_tpl_block.set_value (a_response.values.item ("error_password"), "error_password") -- l_tpl_block.set_value (a_response.values.item ("error_password"), "error_password")
-- l_tpl_block.set_value (a_response.values.item ("token"), "token") -- l_tpl_block.set_value (a_response.values.item ("token"), "token")
@@ -1081,7 +1056,7 @@ feature {NONE} -- Block views
end end
end end
else else
if attached template_block ("post_reset", a_response) as l_tpl_block then if attached template_block (Current, "post_reset", a_response.api) as l_tpl_block then
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
else else
debug ("cms") debug ("cms")
@@ -1092,11 +1067,19 @@ feature {NONE} -- Block views
end end
end end
get_block_view_registration (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) feature -- Access: configuration
do
end
feature -- Recaptcha form_registration_application_description (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key.
local
utf: UTF_CONVERTER
do
if attached api.module_configuration (Current, Void) as cfg then
if attached cfg.text_item ("forms.registration.application_description") as l_desc and then not l_desc.is_whitespace then
Result := utf.utf_32_string_to_utf_8_string_8 (l_desc)
end
end
end
recaptcha_secret_key (api: CMS_API): detachable READABLE_STRING_8 recaptcha_secret_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key. -- Get recaptcha security key.
@@ -1129,6 +1112,7 @@ feature -- Response Alter
a_response.add_javascript_url ("https://www.google.com/recaptcha/api.js") a_response.add_javascript_url ("https://www.google.com/recaptcha/api.js")
a_response.add_style (a_response.url ("/module/" + name + "/files/css/auth.css", Void), Void) a_response.add_style (a_response.url ("/module/" + name + "/files/css/auth.css", Void), Void)
end end
feature {NONE} -- Implementation feature {NONE} -- Implementation
is_captcha_verified (a_secret, a_response: READABLE_STRING_8): BOOLEAN is_captcha_verified (a_secret, a_response: READABLE_STRING_8): BOOLEAN

View File

@@ -1,8 +0,0 @@
{
"email": "webmaster@example.com",
"subjet_register": "Thank you for regitering with us, activate account",
"subjet_activate": "New account ativation token",
"subjet_password": "Password Recovery!!!",
"subjet_oauth": "Welcome",
"smtp": "127.0.0.1"
}

View File

@@ -1,5 +1,10 @@
{ {
"subject": "Thank you for contacting us", "subject": "Thank you for contacting us",
"forms": {
"registration": {
"application_description": "Present yourself in a few lines, otherwise your application is likely to be rejected."
}
},
"recaptcha": { "recaptcha": {
"site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD", "site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD",
"secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx" "secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx"

View File

@@ -1,39 +1,38 @@
<div> <div>
<form action="{$site_url/}account/roc-register" method="post"> <form action="{$site_url/}account/roc-register" method="post">
<fieldset> <fieldset>
<legend>Registration</legend> <legend>Registration</legend>
<div> <div>
<input type="text" id="name" name="name" value="{$name/}" required autofocus /> <input type="text" id="name" name="name" value="{$name/}" required autofocus />
<label for="name">Name</label> <label for="name">Name</label>
{if isset="$error_name"} {if isset="$error_name"}
<span><i>{$error_name/}</i></span> <br> <span><i>{$error_name/}</i></span> <br>
{/if} {/if}
</div> </div>
<div> <div>
<input type="password" id="password" name="password" value="" required/> <input type="password" id="password" name="password" value="" required/>
<label for="password">Password</label> <label for="password">Password</label>
</div> </div>
<div> <div>
<input type="email" id="email" name="email" value="{$email/}" required/> <input type="email" id="email" name="email" value="{$email/}" required/>
<label for="email">Email</label> <label for="email">Email</label>
{if isset="$error_email"} {if isset="$error_email"}
<span><i>{$error_email/}</i></span> <br> <span><i>{$error_email/}</i></span> <br/>
{/if} {/if}
</div> </div>
<div> <div>
<textarea rows="4" cols="50" name="personal_information" id="personal_information" required> <textarea rows="4" cols="50" name="personal_information" id="personal_information" required>{$personal_information/}</textarea>
{$personal_information/} <label for="personal_information">Tell us why you want to register an account</label>
</textarea> {if isset="$error_application"}
<label for="personal_information">Tell us why you want to register an account</label> <span><i>{$error_application/}</i></span><br/>
{if isset="$error_application"} {/if}
<span><i>{$error_application/}</i></span> <br> {if isset="$application_description"}
{/if} <br/>
</div> <p class="description">{$application_description/}</p>
{unless isempty="$recaptcha_site_key"} {/if}
<div class="g-recaptcha" data-sitekey="{$recaptcha_site_key/}"></div> </div>
<br/> {unless isempty="$recaptcha_site_key"}<div class="g-recaptcha" data-sitekey="{$recaptcha_site_key/}"></div><br/>{/unless}
{/unless} <button type="submit">Register</button>
<button type="submit">Register</button> </fieldset>
</fieldset> </form>
</form>
</div> </div>

View File

@@ -118,7 +118,7 @@ feature {NONE} -- Implementation: routes
r.add_error_message ("You are already signed in!") r.add_error_message ("You are already signed in!")
r.set_main_content (r.link ("Logout", "account/roc-logout", Void)) r.set_main_content (r.link ("Logout", "account/roc-logout", Void))
else else
if attached template_block ("login", r) as l_tpl_block then if attached template_block (Current, "login", api) as l_tpl_block then
r.add_javascript_url (r.url ("module/" + name + "/files/js/roc_basic_auth.js", Void)) r.add_javascript_url (r.url ("module/" + name + "/files/js/roc_basic_auth.js", Void))
create vals.make (1) create vals.make (1)
@@ -170,7 +170,7 @@ feature {NONE} -- Block views
local local
vals: CMS_VALUE_TABLE vals: CMS_VALUE_TABLE
do do
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
create vals.make (1) create vals.make (1)
-- add the variable to the block -- add the variable to the block
a_response.api.hooks.invoke_value_table_alter (vals, a_response) a_response.api.hooks.invoke_value_table_alter (vals, a_response)

View File

@@ -1,6 +1,6 @@
{unless isset="$user"} {unless isset="$user"}
<div class="login-box"> <div class="login-box">
<div class="description">The "Basic Auth" relies on the HTTP basic acces authentication.<br/>(see also: <a href="https://en.wikipedia.org/wiki/Basic_access_authentication">https://en.wikipedia.org/wiki/Basic_access_authentication</a> )</div> <div class="description">The "Basic Auth" relies on the HTTP basic access authentication.<br/>(see also: <a href="https://en.wikipedia.org/wiki/Basic_access_authentication">https://en.wikipedia.org/wiki/Basic_access_authentication</a> )</div>
<h3>Login or <a href="{$site_url/}account/roc-register">Register</a></h3> <h3>Login or <a href="{$site_url/}account/roc-register">Register</a></h3>
<div> <div>
<form name="cms_basic_auth" action="{$site_url/}roc-basic-login" method="POST"> <form name="cms_basic_auth" action="{$site_url/}roc-basic-login" method="POST">

View File

@@ -181,7 +181,7 @@ feature -- Hooks
if a_block_id.is_case_insensitive_equal_general ("contact") then if a_block_id.is_case_insensitive_equal_general ("contact") then
-- "contact", "post_contact" -- "contact", "post_contact"
if a_response.request.is_get_request_method then if a_response.request.is_get_request_method then
if attached template_block (Current, a_block_id, a_response) as l_tpl_block then if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
if attached recaptcha_site_key (a_response.api) as l_recaptcha_site_key then if attached recaptcha_site_key (a_response.api) as l_recaptcha_site_key then
l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key") l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key")
end end
@@ -201,7 +201,7 @@ feature -- Hooks
f: CMS_FORM f: CMS_FORM
do do
a_response.add_style (a_response.url ("/module/" + name + "/files/css/contact.css", Void), Void) a_response.add_style (a_response.url ("/module/" + name + "/files/css/contact.css", Void), Void)
if attached template_block (Current, "contact", a_response) as l_tpl_block then if attached template_block (Current, "contact", api) as l_tpl_block then
if attached recaptcha_site_key (api) as l_recaptcha_site_key then if attached recaptcha_site_key (api) as l_recaptcha_site_key then
l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key") l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key")
end end
@@ -339,7 +339,7 @@ feature -- Hooks
r.values.force (True, "has_error") r.values.force (True, "has_error")
vars.put ("True", "has_error") vars.put ("True", "has_error")
end end
if attached template_block_with_values (Current, "post_contact", r, vars) as l_tpl_block then if attached template_block_with_values (Current, "post_contact", api, vars) as l_tpl_block then
across across
r.values as tb r.values as tb
loop loop
@@ -354,7 +354,7 @@ feature -- Hooks
-- send a bad request status code and redisplay the form with the previous data loaded. -- send a bad request status code and redisplay the form with the previous data loaded.
r.set_value (False, "error") r.set_value (False, "error")
r.set_status_code ({HTTP_STATUS_CODE}.bad_request) r.set_status_code ({HTTP_STATUS_CODE}.bad_request)
if attached template_block_with_values (Current, "contact", r, vars) as l_tpl_block then if attached template_block_with_values (Current, "contact", api, vars) as l_tpl_block then
across across
r.values as tb r.values as tb
loop loop
@@ -377,7 +377,7 @@ feature -- Hooks
write_error_log (generator + ".handle_post_contact: Internal Server error") write_error_log (generator + ".handle_post_contact: Internal Server error")
r.values.force (True, "has_error") r.values.force (True, "has_error")
r.set_status_code ({HTTP_CONSTANTS}.internal_server_error) r.set_status_code ({HTTP_CONSTANTS}.internal_server_error)
if attached template_block_with_values (Current, "post_contact", r, vars) as l_tpl_block then if attached template_block_with_values (Current, "post_contact", api, vars) as l_tpl_block then
across across
r.values as tb r.values as tb
loop loop
@@ -422,18 +422,6 @@ feature {NONE} -- Helpers
feature {NONE} -- Contact Message feature {NONE} -- Contact Message
template_block_with_values (a_module: CMS_MODULE; a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE; a_values: STRING_TABLE [ANY]): like template_block
do
Result := template_block (a_module, a_block_id, a_response)
if Result /= Void then
across
a_values as ic
loop
Result.set_value (ic.item, ic.key)
end
end
end
email_html_message (a_message_id: READABLE_STRING_8; a_response: CMS_RESPONSE; a_html_encoded_values: STRING_TABLE [READABLE_STRING_8]): STRING email_html_message (a_message_id: READABLE_STRING_8; a_response: CMS_RESPONSE; a_html_encoded_values: STRING_TABLE [READABLE_STRING_8]): STRING
-- html message related to `a_message_id'. -- html message related to `a_message_id'.
local local

View File

@@ -346,9 +346,11 @@ feature -- Hook
-- Hook execution on collection of menu contained by `a_menu_system' -- Hook execution on collection of menu contained by `a_menu_system'
-- for related response `a_response'. -- for related response `a_response'.
do do
a_menu_system.navigation_menu.extend (create {CMS_LOCAL_LINK}.make ("Feeds", "feed_aggregation/")) if a_response.is_authenticated then
if a_response.has_permission (permission__manage_feed_aggregator) then a_menu_system.navigation_menu.extend (create {CMS_LOCAL_LINK}.make ("Feeds", "feed_aggregation/"))
a_menu_system.management_menu.extend (create {CMS_LOCAL_LINK}.make ("Feeds (admin)", "admin/feed_aggregator/")) if a_response.has_permission (permission__manage_feed_aggregator) then
a_menu_system.management_menu.extend_into (create {CMS_LOCAL_LINK}.make ("Feeds (admin)", "admin/feed_aggregator/"), "Admin", "admin")
end
end end
end end

View File

@@ -103,7 +103,7 @@ feature -- Storage
end end
end end
save_uploaded_file (f: CMS_UPLOADED_FILE) save_uploaded_file (uf: CMS_UPLOADED_FILE)
local local
p: PATH p: PATH
ut: FILE_UTILITIES ut: FILE_UTILITIES
@@ -113,9 +113,9 @@ feature -- Storage
finished: BOOLEAN finished: BOOLEAN
do do
reset_error reset_error
create original_name.make_from_string (f.filename) create original_name.make_from_string (uf.filename)
p := f.location p := uf.location
if not p.is_absolute then if not p.is_absolute then
p := uploads_directory.extended_path (p) p := uploads_directory.extended_path (p)
end end
@@ -128,8 +128,8 @@ feature -- Storage
finished finished
loop loop
if ut.file_path_exists (p) then if ut.file_path_exists (p) then
f.set_new_location_with_number (n) uf.set_new_location_with_number (n)
p := f.location p := uf.location
if p.is_absolute then if p.is_absolute then
else else
p := uploads_directory.extended_path (p) p := uploads_directory.extended_path (p)
@@ -139,13 +139,15 @@ feature -- Storage
finished := True finished := True
end end
end end
stored := f.move_to (p) stored := uf.move_to (p)
else else
-- move file to path -- move file to path
stored := f.move_to (p) stored := uf.move_to (p)
end end
if not stored then if stored then
save_metadata_from_uploaded_file (uf, cms_api.user)
else
error_handler.add_custom_error (-1, "uploaded file storage failed", "Issue occurred when saving uploaded file!") error_handler.add_custom_error (-1, "uploaded file storage failed", "Issue occurred when saving uploaded file!")
end end
end end
@@ -156,7 +158,7 @@ feature -- Storage
h_date: HTTP_DATE h_date: HTTP_DATE
retried: BOOLEAN retried: BOOLEAN
do do
if not retried then if retried then
-- FIXME: Report error? -- FIXME: Report error?
if f /= Void and then not f.is_closed then if f /= Void and then not f.is_closed then
f.close f.close
@@ -172,7 +174,7 @@ feature -- Storage
end end
-- insert username -- insert username
if u /= Void then if u /= Void then
f.put_integer_64 (u.id) f.put_string (u.id.out)
f.put_new_line f.put_new_line
-- f.put_string (utf.utf_32_string_to_utf_8_string_8 (u.name)) -- f.put_string (utf.utf_32_string_to_utf_8_string_8 (u.name))
-- f.put_new_line -- f.put_new_line
@@ -182,7 +184,7 @@ feature -- Storage
end end
-- insert uploaded_time -- insert uploaded_time
create h_date.make_now_utc create h_date.make_now_utc
f.put_integer_64 (h_date.timestamp) f.put_string (h_date.timestamp.out)
f.put_new_line f.put_new_line
-- insert size of file -- insert size of file

View File

@@ -43,10 +43,15 @@ feature -- Access
-- List of permission ids, used by this module, and declared. -- List of permission ids, used by this module, and declared.
do do
Result := Precursor Result := Precursor
Result.force ("admin files") Result.force (admin_files_permission)
Result.force ("upload files") Result.force (upload_files_permission)
Result.force (browse_files_permission)
end end
admin_files_permission: STRING = "admin files"
upload_files_permission: STRING = "upload files"
browse_files_permission: STRING = "browse files"
feature {CMS_API} -- Module Initialization feature {CMS_API} -- Module Initialization
initialize (api: CMS_API) initialize (api: CMS_API)
@@ -92,7 +97,7 @@ feature -- Access: router
do do
map_uri_template_agent (a_router, "/" + uploads_location, agent execute_upload (?, ?, a_api), Void) -- Accepts any method GET, HEAD, POST, PUT, DELETE, ... map_uri_template_agent (a_router, "/" + uploads_location, agent execute_upload (?, ?, a_api), Void) -- Accepts any method GET, HEAD, POST, PUT, DELETE, ...
map_uri_template_agent (a_router, "/" + uploads_location + "{filename}", agent display_uploaded_file_info (?, ?, a_api), a_router.methods_get) map_uri_template_agent (a_router, "/" + uploads_location + "{filename}", agent display_uploaded_file_info (?, ?, a_api), a_router.methods_get)
map_uri_template_agent (a_router, "/" + uploads_location + "remove/{filename}", agent remove (?, ?, a_api), a_router.methods_get) map_uri_template_agent (a_router, "/" + uploads_location + "remove/{filename}", agent remove_file (?, ?, a_api), a_router.methods_get)
end end
uploads_location: STRING = "upload/" uploads_location: STRING = "upload/"
@@ -109,7 +114,7 @@ feature -- Hooks
link: CMS_LOCAL_LINK link: CMS_LOCAL_LINK
do do
-- login in demo did somehow not work -- login in demo did somehow not work
if a_response.has_permission ("upload files") then if a_response.has_permission (upload_files_permission) then
create link.make ("Upload files", uploads_location) create link.make ("Upload files", uploads_location)
a_menu_system.navigation_menu.extend (link) a_menu_system.navigation_menu.extend (link)
end end
@@ -133,13 +138,17 @@ feature -- Handler
fn: READABLE_STRING_32 fn: READABLE_STRING_32
do do
check req.is_get_request_method end check req.is_get_request_method end
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) if not api.has_permission (browse_files_permission) then
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.add_error_message ("You are not allowed to browse CMS files!")
elseif attached {WSF_STRING} req.path_parameter ("filename") as p_filename then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
-- add style -- add style
r.add_style (r.url ("/module/" + name + "/files/css/files.css", Void), Void) r.add_style (r.url ("/module/" + name + "/files/css/files.css", Void), Void)
create body.make_empty
create body.make_empty
if attached {WSF_STRING} req.path_parameter ("filename") as p_filename then
fn := p_filename.value fn := p_filename.value
r.set_page_title ({STRING_32} "File %"" + fn + {STRING_32} "%"") r.set_page_title ({STRING_32} "File %"" + fn + {STRING_32} "%"")
body.append ("<div class=%"uploaded-files%">%N") -- To ease css customization. body.append ("<div class=%"uploaded-files%">%N") -- To ease css customization.
@@ -207,9 +216,13 @@ feature -- Handler
body.append ("</div>%N") -- Overview body.append ("</div>%N") -- Overview
end end
body.append ("</div>%N") body.append ("</div>%N")
r.add_to_primary_tabs (create {CMS_LOCAL_LINK}.make ("Uploaded files", uploads_location))
r.set_main_content (body)
else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.set_main_content ("Missing 'filename' field value!")
end end
r.add_to_primary_tabs (create {CMS_LOCAL_LINK}.make ("Uploaded files", uploads_location))
r.set_main_content (body)
r.execute r.execute
end end
@@ -229,8 +242,9 @@ feature -- Handler
-- add JS for dropzone -- add JS for dropzone
r.add_javascript_url (r.url ("/module/" + name + "/files/js/dropzone.js", void)) r.add_javascript_url (r.url ("/module/" + name + "/files/js/dropzone.js", void))
r.add_style (r.url ("/module/" + name + "/files/js/dropzone.css", void), void)
if r.has_permission ("upload files") then if api.has_permission (upload_files_permission) then
-- create body -- create body
body.append ("<p>Please choose some file(s) to upload.</p>") body.append ("<p>Please choose some file(s) to upload.</p>")
@@ -238,7 +252,7 @@ feature -- Handler
body.append ("<div class=%"upload-files%">") body.append ("<div class=%"upload-files%">")
body.append ("<form action=%"" + r.url (uploads_location, Void) + "%" class=%"dropzone%">") body.append ("<form action=%"" + r.url (uploads_location, Void) + "%" class=%"dropzone%">")
body.append ("</form>%N") body.append ("</form>%N")
body.append ("<a class=%"button%" href=%""+ r.url (uploads_location, Void) +"%">Upload Files</a>") body.append ("<div class=%"center%"><a class=%"button%" href=%""+ r.url (uploads_location, Void) +"%">Upload Files</a></div>")
body.append ("</div>") body.append ("</div>")
if req.is_post_request_method then if req.is_post_request_method then
process_uploaded_files (req, api, body) process_uploaded_files (req, api, body)
@@ -248,8 +262,11 @@ feature -- Handler
end end
-- Build the response. -- Build the response.
if r.has_permission (browse_files_permission) then
append_uploaded_file_album_to (req, api, body) append_uploaded_file_album_to (req, api, body)
else
r.add_warning_message ("You are not allowed to browse files!")
end
r.set_main_content (body) r.set_main_content (body)
else else
@@ -259,7 +276,9 @@ feature -- Handler
end end
process_uploaded_files (req: WSF_REQUEST; api: CMS_API; a_output: STRING) process_uploaded_files (req: WSF_REQUEST; api: CMS_API; a_output: STRING)
-- show all newly uploaded files -- Process http request uploaded files.
require
has_permission: api.has_permission (upload_files_permission)
local local
l_uploaded_file: CMS_UPLOADED_FILE l_uploaded_file: CMS_UPLOADED_FILE
uf: WSF_UPLOADED_FILE uf: WSF_UPLOADED_FILE
@@ -277,14 +296,12 @@ feature -- Handler
a_output.append ("<li>") a_output.append ("<li>")
a_output.append (api.html_encoded (l_uploaded_file.filename)) a_output.append (api.html_encoded (l_uploaded_file.filename))
-- store the just uploaded file
l_files_api.save_uploaded_file (l_uploaded_file)
-- create medadata file -- create medadata file
l_uploaded_file.set_size (uf.size) l_uploaded_file.set_size (uf.size)
l_uploaded_file.set_type (uf.content_type) l_uploaded_file.set_type (uf.content_type)
l_files_api.save_metadata_from_uploaded_file (l_uploaded_file, api.current_user (req)) -- store the just uploaded file
l_files_api.save_uploaded_file (l_uploaded_file)
if l_files_api.has_error then if l_files_api.has_error then
a_output.append (" <span class=%"error%">: upload failed!</span>") a_output.append (" <span class=%"error%">: upload failed!</span>")
@@ -303,14 +320,14 @@ feature -- Handler
p: PATH p: PATH
rel: PATH rel: PATH
md: detachable CMS_FILE_METADATA md: detachable CMS_FILE_METADATA
size: INTEGER
do do
if attached files_api as l_files_api then if attached files_api as l_files_api then
rel := l_files_api.uploads_relative_path rel := l_files_api.uploads_relative_path
p := l_files_api.uploads_directory p := l_files_api.uploads_directory
a_output.append ("<div class=%"uploaded-files%">%N")
a_output.append ("<strong>Uploaded files:</strong>%N") a_output.append ("<strong>Uploaded files:</strong>%N")
a_output.append ("<table class=%"uploaded-files%">%N") a_output.append ("<table>%N")
a_output.append ("<tr><th>Filename</th><th>Uploading Time</th><th>User</th><th>Size</th><th></th><th></th></tr>%N") a_output.append ("<tr><th>Filename</th><th>Uploading Time</th><th>User</th><th>Size</th><th></th><th></th></tr>%N")
create d.make_with_path (p) create d.make_with_path (p)
@@ -361,18 +378,7 @@ feature -- Handler
-- add size -- add size
a_output.append ("<td class=%"size%">") a_output.append ("<td class=%"size%">")
if md.size > 0 then if md.size > 0 then
size := md.size a_output.append (file_size_human_string (md.size))
if size >= 1000000 then
size := size // 1000000
a_output.append (size.out + " MB")
else
if size >= 1000 then
size := size // 1000
a_output.append (size.out + " kB")
else
a_output.append (size.out + " bytes")
end
end
else else
a_output.append ("NA") a_output.append ("NA")
end end
@@ -381,12 +387,12 @@ feature -- Handler
-- add download link -- add download link
a_output.append ("<td>") a_output.append ("<td>")
a_output.append ("<button><a class=%"download-button%" href=%"" + req.script_url ("/" + l_files_api.file_link (f).location) + "%" download>Download</a></button>%N") a_output.append ("<a class=%"button%" href=%"" + req.script_url ("/" + l_files_api.file_link (f).location) + "%" download>Download</a>%N")
a_output.append ("</td>%N") a_output.append ("</td>%N")
-- add remove button -- add remove button
a_output.append ("<td>") a_output.append ("<td>")
a_output.append ("<button><a class=%"download-button%" href=%"" + req.script_url ("/" + uploads_location + "remove/" + f.filename) + "%">Remove</a></button>%N") a_output.append ("<a class=%"button%" href=%"" + req.script_url ("/" + uploads_location + "remove/" + f.filename) + "%">Remove</a>%N")
a_output.append ("</td>%N") a_output.append ("</td>%N")
a_output.append ("</tr>%N") a_output.append ("</tr>%N")
@@ -414,18 +420,21 @@ feature -- Handler
end end
end end
a_output.append ("</table>%N") a_output.append ("</table>%N")
a_output.append ("</div>%N")
end end
end end
remove (req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API) remove_file (req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API)
local local
body: STRING body: STRING
r: CMS_RESPONSE r: CMS_RESPONSE
err: BOOLEAN err: BOOLEAN
do do
if attached files_api as l_files_api then if attached files_api as l_files_api then
if attached {WSF_STRING} req.path_parameter ("filename") as p_filename then if not api.has_permission (admin_files_permission) then
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.add_error_message ("You are not allowed to remove file!")
elseif attached {WSF_STRING} req.path_parameter ("filename") as p_filename then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
l_files_api.delete_file (p_filename.value) l_files_api.delete_file (p_filename.value)

View File

@@ -1,38 +1,44 @@
.uploaded-files { .uploaded-files table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
border: 1px solid black; border: 1px solid black;
} }
.uploaded-files th { .uploaded-files table th {
padding-left: 5px; padding: 3px 0 3px 5px;
padding-top: 3px;
padding-bottom: 3px;
} }
.uploaded-files td { .uploaded-files table td {
padding-left: 5px; padding: 3px 0 3px 5px;
padding-top: 3px;
padding-bottom: 3px;
} }
.uploaded-files a.button { .uploaded-files a.button {
color: black; color: black;
text-decoration: none; text-decoration: none;
border: solid 1px #999; border: solid 1px #999;
background-color: #ddd; background-color: #ddd;
padding: 2px 4px 2px 4px;
} }
.uploaded-files a.button:hover { .uploaded-files a.button:hover {
color: black; color: black;
text-decoration: none; border: solid 1px #06f;
background-color: #cff;
} }
.upload-files a.upload-button { .upload-files .center {
text-align: center;
padding: 10px;
}
.upload-files a.button {
margin: auto; margin: auto;
width: 100px; width: 100px;
color: black; color: black;
text-decoration: none; text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
} }
.upload-files a.upload-button:hover { .upload-files a.button:hover {
color: black; color: black;
text-decoration: none; border: solid 1px #06f;
background-color: #cff;
} }
/******************* Drop Zone *******************/ /******************* Drop Zone *******************/
@@ -44,18 +50,3 @@
padding-top: 15px; padding-top: 15px;
padding-bottom: 15px; padding-bottom: 15px;
} }
.dropzone .dz-message {
cursor: pointer;
}
.dropzone .dz-preview, .dropzone .dz-file-preview, .dropzone .dz-processing, .dropzone .dz-success,
.dropzone .dz-image-preview, .dropzone .dz-complete {
padding: 10px;
margin: 10px;
width: auto;
display: inline-block;
}
.dropzone .dz-preview {
border: 1px solid black;
border-radius: 5px;
background: #e6e6e6;
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
/*
* The MIT License
* Copyright (c) 2012 Matias Meno <m@tias.me>
*/
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
.dropzone, .dropzone * {
box-sizing: border-box;
}
.dropzone {
position: relative;
.dz-preview {
position: relative;
display: inline-block;
width: 120px;
margin: 0.5em;
.dz-progress {
display: block;
height: 15px;
border: 1px solid #aaa;
.dz-upload {
display: block;
height: 100%;
width: 0;
background: green;
}
}
.dz-error-message {
color: red;
display: none;
}
&.dz-error {
.dz-error-message, .dz-error-mark {
display: block;
}
}
&.dz-success {
.dz-success-mark {
display: block;
}
}
.dz-error-mark, .dz-success-mark {
position: absolute;
display: none;
left: 30px;
top: 30px;
width: 54px;
height: 58px;
left: 50%;
margin-left: -(54px/2);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,413 @@
/*
* The MIT License
* Copyright (c) 2012 Matias Meno <m@tias.me>
*/
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
@mixin keyframes($name) {
@-webkit-keyframes #{$name} {
@content;
}
@-moz-keyframes #{$name} {
@content;
}
@keyframes #{$name} {
@content;
}
}
@mixin prefix($map, $vendors: webkit moz ms o) {
@each $prop, $value in $map {
@if $vendors {
@each $vendor in $vendors {
#{"-" + $vendor + "-" + $prop}: #{$value};
}
}
// Dump regular property anyway
#{$prop}: #{$value};
}
}
@include keyframes(passing-through) {
0% {
opacity: 0;
@include prefix((transform: translateY(40px)));
}
30%, 70% {
opacity: 1;
@include prefix((transform: translateY(0px)));
}
100% {
opacity: 0;
@include prefix((transform: translateY(-40px)));
}
}
@include keyframes(slide-in) {
0% {
opacity: 0;
@include prefix((transform: translateY(40px)));
}
30% {
opacity: 1;
@include prefix((transform: translateY(0px)));
}
}
@include keyframes(pulse) {
0% { @include prefix((transform: scale(1))); }
10% { @include prefix((transform: scale(1.1))); }
20% { @include prefix((transform: scale(1))); }
}
.dropzone, .dropzone * {
box-sizing: border-box;
}
.dropzone {
$image-size: 120px;
$image-border-radius: 20px;
&.dz-clickable {
cursor: pointer;
* {
cursor: default;
}
.dz-message {
&, * {
cursor: pointer;
}
}
}
min-height: 150px;
border: 2px solid rgba(0, 0, 0, 0.3);
background: white;
padding: 20px 20px;
&.dz-started {
.dz-message {
display: none;
}
}
&.dz-drag-hover {
border-style: solid;
.dz-message {
opacity: 0.5;
}
}
.dz-message {
text-align: center;
margin: 2em 0;
}
.dz-preview {
position: relative;
display: inline-block;
vertical-align: top;
margin: 16px;
min-height: 100px;
&:hover {
// Making sure that always the hovered preview element is on top
z-index: 1000;
.dz-details {
opacity: 1;
}
}
&.dz-file-preview {
.dz-image {
border-radius: $image-border-radius;
background: #999;
background: linear-gradient(to bottom, #eee, #ddd);
}
.dz-details {
opacity: 1;
}
}
&.dz-image-preview {
background: white;
.dz-details {
@include prefix((transition: opacity 0.2s linear));
}
}
.dz-remove {
font-size: 14px;
text-align: center;
display: block;
cursor: pointer;
border: none;
&:hover {
text-decoration: underline;
}
}
&:hover .dz-details {
opacity: 1;
}
.dz-details {
$background-color: #444;
z-index: 20;
position: absolute;
top: 0;
left: 0;
opacity: 0;
font-size: 13px;
min-width: 100%;
max-width: 100%;
padding: 2em 1em;
text-align: center;
color: rgba(0, 0, 0, 0.9);
$width: 120px;
line-height: 150%;
.dz-size {
margin-bottom: 1em;
font-size: 16px;
}
.dz-filename {
white-space: nowrap;
&:hover {
span {
border: 1px solid rgba(200, 200, 200, 0.8);
background-color: rgba(255, 255, 255, 0.8);
}
}
&:not(:hover) {
span {
border: 1px solid transparent;
}
overflow: hidden;
text-overflow: ellipsis;
}
}
.dz-filename, .dz-size {
span {
background-color: rgba(255, 255, 255, 0.4);
padding: 0 0.4em;
border-radius: 3px;
}
}
}
&:hover {
.dz-image {
// opacity: 0.8;
img {
@include prefix((transform: scale(1.05, 1.05))); // Getting rid of that white bleed-in
@include prefix((filter: blur(8px)), webkit); // Getting rid of that white bleed-in
}
}
}
.dz-image {
border-radius: $image-border-radius;
overflow: hidden;
width: $image-size;
height: $image-size;
position: relative;
display: block;
z-index: 10;
img {
display: block;
}
}
&.dz-success {
.dz-success-mark {
@include prefix((animation: passing-through 3s cubic-bezier(0.770, 0.000, 0.175, 1.000)));
}
}
&.dz-error {
.dz-error-mark {
opacity: 1;
@include prefix((animation: slide-in 3s cubic-bezier(0.770, 0.000, 0.175, 1.000)));
}
}
.dz-success-mark, .dz-error-mark {
$image-height: 54px;
$image-width: 54px;
pointer-events: none;
opacity: 0;
z-index: 500;
position: absolute;
display: block;
top: 50%;
left: 50%;
margin-left: -($image-width/2);
margin-top: -($image-height/2);
svg {
display: block;
width: $image-width;
height: $image-height;
}
}
&.dz-processing .dz-progress {
opacity: 1;
@include prefix((transition: all 0.2s linear));
}
&.dz-complete .dz-progress {
opacity: 0;
@include prefix((transition: opacity 0.4s ease-in));
}
&:not(.dz-processing) {
.dz-progress {
@include prefix((animation: pulse 6s ease infinite));
}
}
.dz-progress {
opacity: 1;
z-index: 1000;
pointer-events: none;
position: absolute;
height: 16px;
left: 50%;
top: 50%;
margin-top: -8px;
width: 80px;
margin-left: -40px;
// border: 2px solid #333;
background: rgba(255, 255, 255, 0.9);
// Fix for chrome bug: https://code.google.com/p/chromium/issues/detail?id=157218
-webkit-transform: scale(1);
border-radius: 8px;
overflow: hidden;
.dz-upload {
background: #333;
background: linear-gradient(to bottom, #666, #444);
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 0;
@include prefix((transition: width 300ms ease-in-out));
}
}
&.dz-error {
.dz-error-message {
display: block;
}
&:hover .dz-error-message {
opacity: 1;
pointer-events: auto;
}
}
.dz-error-message {
$width: $image-size + 20px;
$color: rgb(190, 38, 38);
pointer-events: none;
z-index: 1000;
position: absolute;
display: block;
display: none;
opacity: 0;
@include prefix((transition: opacity 0.3s ease));
border-radius: 8px;
font-size: 13px;
top: $image-size + 10px;
left: -10px;
width: $width;
background: $color;
background: linear-gradient(to bottom, $color, darken($color, 5%));
padding: 0.5em 1.2em;
color: white;
// The triangle pointing up
&:after {
content: '';
position: absolute;
top: -6px;
left: $width / 2 - 6px;
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid $color;
}
}
}
}

View File

@@ -1,18 +1,16 @@
.uploaded-files { .uploaded-files {
width: 100%; table {
border-collapse: collapse; width: 100%;
border: 1px solid black; border-collapse: collapse;
border: 1px solid black;
th { th {
padding-left: 5px; padding: 3px 0 3px 5px;
padding-top: 3px; }
padding-bottom: 3px;
}
td { td {
padding-left: 5px; padding: 3px 0 3px 5px;
padding-top: 3px; }
padding-bottom: 3px;
} }
a.button{ a.button{
@@ -20,23 +18,33 @@
text-decoration: none; text-decoration: none;
border: solid 1px #999; border: solid 1px #999;
background-color: #ddd; background-color: #ddd;
padding: 2px 4px 2px 4px;
&:hover { &:hover {
color: black; color: black;
text-decoration: none; border: solid 1px #06f;
background-color: #cff;
} }
} }
} }
.upload-files { .upload-files {
a.upload-button{ .center {
text-align: center;
padding: 10px;
}
a.button{
margin: auto; margin: auto;
width: 100px; width: 100px;
color: black; color: black;
text-decoration: none; text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
&:hover { &:hover {
color: black; color: black;
text-decoration: none; border: solid 1px #06f;
background-color: #cff;
} }
} }
} }
@@ -51,23 +59,5 @@
text-align: center; text-align: center;
padding-top: 15px; padding-top: 15px;
padding-bottom: 15px; padding-bottom: 15px;
.dz-message {
cursor: pointer;
}
.dz-preview, .dz-file-preview, .dz-processing, .dz-success,
.dz-image-preview, .dz-complete {
padding: 10px;
margin: 10px;
width: auto;
display: inline-block;
}
.dz-preview {
border: 1px solid black;
border-radius: 5px;
background: #e6e6e6;
}
} }

View File

@@ -114,7 +114,7 @@ feature -- Handler
attached l_search.last_result as l_result and then attached l_search.last_result as l_result and then
l_result.status = 200 l_result.status = 200
then then
if attached template_block (Current, "search", r) as l_tpl_block then if attached template_block (Current, "search", api) as l_tpl_block then
l_tpl_block.set_value (l_result, "result") l_tpl_block.set_value (l_result, "result")
r.add_block (l_tpl_block, "content") r.add_block (l_tpl_block, "content")
end end

View File

@@ -243,7 +243,7 @@ feature -- Hooks
a_response.location.same_string ("account") a_response.location.same_string ("account")
then then
if if
attached template_block ("account_info", a_response) as l_tpl_block and then attached template_block (Current, "account_info", a_response.api) as l_tpl_block and then
attached a_response.user as l_user attached a_response.user as l_user
then then
associate_account (l_user, a_response.values) associate_account (l_user, a_response.values)
@@ -323,7 +323,7 @@ feature {NONE} -- Block views
local local
vals: CMS_VALUE_TABLE vals: CMS_VALUE_TABLE
do do
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
create vals.make (1) create vals.make (1)
-- add the variable to the block -- add the variable to the block
a_response.api.hooks.invoke_value_table_alter (vals, a_response) a_response.api.hooks.invoke_value_table_alter (vals, a_response)

View File

@@ -270,7 +270,7 @@ feature {NONE} -- Block views
local local
vals: CMS_VALUE_TABLE vals: CMS_VALUE_TABLE
do do
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
create vals.make (1) create vals.make (1)
-- add the variable to the block -- add the variable to the block
a_response.api.hooks.invoke_value_table_alter (vals, a_response) a_response.api.hooks.invoke_value_table_alter (vals, a_response)

View File

@@ -141,7 +141,7 @@ feature {NONE} -- Implementation: routes
if api.user_is_authenticated then if api.user_is_authenticated then
r.add_error_message ("You are already signed in!") r.add_error_message ("You are already signed in!")
else else
if attached template_block ("login", r) as l_tpl_block then if attached template_block (Current, "login", api) as l_tpl_block then
create vals.make (1) create vals.make (1)
-- add the variable to the block -- add the variable to the block
l_tpl_block.set_value (api.user, "user") l_tpl_block.set_value (api.user, "user")
@@ -223,7 +223,7 @@ feature {NONE} -- Implementation: routes
end end
else else
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if attached template_block ("login", r) as l_tpl_block then if attached template_block (Current, "login", api) as l_tpl_block then
l_tpl_block.set_value (l_username.value, "username") l_tpl_block.set_value (l_username.value, "username")
l_tpl_block.set_value ("Wrong: Username or password ", "error") l_tpl_block.set_value ("Wrong: Username or password ", "error")
r.add_block (l_tpl_block, "content") r.add_block (l_tpl_block, "content")
@@ -232,7 +232,7 @@ feature {NONE} -- Implementation: routes
r.execute r.execute
else else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api) create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
if attached template_block ("login", r) as l_tpl_block then if attached template_block (Current, "login", api) as l_tpl_block then
if attached {WSF_STRING} req.form_parameter ("username") as l_username then if attached {WSF_STRING} req.form_parameter ("username") as l_username then
l_tpl_block.set_value (l_username.value, "username") l_tpl_block.set_value (l_username.value, "username")
end end
@@ -272,7 +272,7 @@ feature {NONE} -- Block views
local local
vals: CMS_VALUE_TABLE vals: CMS_VALUE_TABLE
do do
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (Current, a_block_id, a_response.api) as l_tpl_block then
create vals.make (1) create vals.make (1)
-- add the variable to the block -- add the variable to the block
a_response.api.hooks.invoke_value_table_alter (vals, a_response) a_response.api.hooks.invoke_value_table_alter (vals, a_response)

View File

@@ -187,7 +187,7 @@ feature -- Hooks
-- Add the link to the taxonomy to the main menu -- Add the link to the taxonomy to the main menu
if a_response.has_permission ("admin taxonomy") then if a_response.has_permission ("admin taxonomy") then
create lnk.make ("Taxonomy", "admin/taxonomy/") create lnk.make ("Taxonomy", "admin/taxonomy/")
a_menu_system.management_menu.extend (lnk) a_menu_system.management_menu.extend_into (lnk, "Admin", "admin")
end end
end end

View File

@@ -26,6 +26,6 @@ feature -- Hook
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2016, 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)"
end end

View File

@@ -6,17 +6,17 @@ note
deferred class deferred class
CMS_HOOK_BLOCK_HELPER CMS_HOOK_BLOCK_HELPER
feature -- Factory feature {NONE} -- Factory
template_block (a_module: CMS_MODULE; a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE): detachable CMS_SMARTY_TEMPLATE_BLOCK template_block (a_module: CMS_MODULE; a_block_id: READABLE_STRING_8; a_cms_api: CMS_API): detachable CMS_SMARTY_TEMPLATE_BLOCK
-- Smarty content block for `a_block_id' in the context of `a_module' and `a_response'. -- Smarty content block for `a_block_id' in the context of `a_module' and `a_cms_api'.
local local
res: PATH res: PATH
p: detachable PATH p: detachable PATH
do do
create res.make_from_string ("templates") create res.make_from_string ("templates")
res := res.extended ("block_").appended (a_block_id).appended_with_extension ("tpl") res := res.extended ("block_").appended (a_block_id).appended_with_extension ("tpl")
p := a_response.api.module_theme_resource_location (a_module, res) p := a_cms_api.module_theme_resource_location (a_module, res)
if p /= Void then if p /= Void then
if attached p.entry as e then if attached p.entry as e then
create Result.make (a_block_id, Void, p.parent, e) create Result.make (a_block_id, Void, p.parent, e)
@@ -26,6 +26,20 @@ feature -- Factory
end end
end end
template_block_with_values (a_module: CMS_MODULE; a_block_id: READABLE_STRING_8; a_cms_api: CMS_API; a_values: STRING_TABLE [ANY]): like template_block
-- Smarty content block for `a_block_id' in the context of `a_module' and `a_cms_api',
-- With additional `a_values'.
do
Result := template_block (a_module, a_block_id, a_cms_api)
if Result /= Void then
across
a_values as ic
loop
Result.set_value (ic.item, ic.key)
end
end
end
note note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2016, 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)"

View File

@@ -9,38 +9,38 @@ deferred class
feature -- Initialisation feature -- Initialisation
load_assets : STRING load_assets: STRING
-- Loads all assest needed to show the editor -- Loads all assest needed to show the editor.
deferred deferred
end end
feature -- Javascript feature -- Javascript
javascript_replace_textarea (a_textarea : WSF_FORM_TEXTAREA): STRING javascript_replace_textarea (a_textarea: WSF_FORM_TEXTAREA): STRING
-- Javascript code that replaces a textarea with the editor. The editor instance should be saved in editor_variable -- Javascript code that replaces a textarea with the editor. The editor instance should be saved in editor_variable.
deferred deferred
end end
javascript_restore_textarea (a_textarea : WSF_FORM_TEXTAREA): STRING javascript_restore_textarea (a_textarea: WSF_FORM_TEXTAREA): STRING
-- Javascript code that restores a textarea -- Javascript code that restores a textarea
deferred deferred
end end
javascript_textarea_to_editor (a_textarea : WSF_FORM_TEXTAREA): STRING javascript_textarea_to_editor (a_textarea: WSF_FORM_TEXTAREA): STRING
-- Javascript code to display the textarea as a WYSIWIG editor as soon as the document is loaded -- Javascript code to display the textarea as a WYSIWIG editor as soon as the document is loaded.
do do
Result := javascript_ready (javascript_replace_textarea (a_textarea)) Result := javascript_ready (javascript_replace_textarea (a_textarea))
end end
javascript_textarea_to_editor_if_selected (a_textarea: WSF_FORM_TEXTAREA; a_select_field : WSF_FORM_SELECT; a_value : STRING) : STRING javascript_textarea_to_editor_if_selected (a_textarea: WSF_FORM_TEXTAREA; a_select_field: WSF_FORM_SELECT; a_value: STRING): STRING
-- Javascript code to display the textarea as a WYSIWIG editor if a_select_field has a_value -- Javascript code to display the textarea as a WYSIWIG editor if a_select_field has a_value,
local local
initial_replace_code, on_select_replace_code: STRING initial_replace_code, on_select_replace_code: STRING
do do
-- Javascript that replaces the textarea if a_value is selected at load time -- Javascript that replaces the textarea if a_value is selected at load time
initial_replace_code := javascript_ready (javascript_if_selected (a_select_field, a_value, javascript_replace_textarea (a_textarea))) initial_replace_code := javascript_ready (javascript_if_selected (a_select_field, a_value, javascript_replace_textarea (a_textarea)))
-- Javascript code that replaces the textarea as soon as value is selected at a_select_field -- Javascript code that replaces the textarea as soon as value is selected at a_select_field
on_select_replace_code := javascript_ready( on_select_replace_code := javascript_ready(
javascript_init_editor_variable (a_textarea) + javascript_init_editor_variable (a_textarea) +
javascript_on_select (a_select_field, a_value, javascript_on_select (a_select_field, a_value,
@@ -55,54 +55,56 @@ feature -- Javascript
Result := initial_replace_code + " " + on_select_replace_code Result := initial_replace_code + " " + on_select_replace_code
end end
javascript_init_editor_variable (a_textarea : WSF_FORM_TEXTAREA) : STRING javascript_init_editor_variable (a_textarea: WSF_FORM_TEXTAREA): STRING
-- Returns the javascript code that initializes a local variable to store the editor instance -- Returns the javascript code that initializes a local variable to store the editor instance.
do do
Result := "var " + editor_variable (a_textarea) + "; " Result := "var " + editor_variable (a_textarea) + "; "
end end
javascript_if_selected (a_select_field : WSF_FORM_SELECT; a_value : STRING; a_code : STRING) : STRING javascript_if_selected (a_select_field: WSF_FORM_SELECT; a_value: STRING; a_code: STRING): STRING
-- Javascript that executes a_code if a_value is selected at a_select_field -- Javascript that executes a_code if a_value is selected at a_select_field.
do do
Result := "if($('#" + field_id (a_select_field) + "').val() == %"" + a_value + "%"){ " + a_code + " }" Result := "if($('#" + field_id (a_select_field) + "').val() == %"" + a_value + "%"){ " + a_code + " }"
end end
javascript_ready (a_code : STRING) : STRING javascript_ready (a_code: STRING): STRING
-- Wraps the given javascript code with a ready statement, such that it's executed when the document has loaded -- Wraps the given javascript code with a ready statement,
-- such that it's executed when the document has loaded.
do do
Result := "$(function() { " + a_code + " });" Result := "$(function() { " + a_code + " });"
end end
javascript_on_select (a_select_field : WSF_FORM_SELECT; a_value : STRING; a_then : STRING; a_else : STRING) : STRING javascript_on_select (a_select_field: WSF_FORM_SELECT; a_value: STRING; a_then: STRING; a_else: STRING): STRING
-- Javascript code that executes a_then if at the given select_field the given string value is selected, otherwise it executes a_else -- Javascript code that executes `a_then' if at the given `a_select_field'
-- the given string `a_value' is selected, otherwise it executes `a_else'.
do do
Result := "$('#" + field_id (a_select_field) + "').change(function(){" + Result := "$('#" + field_id (a_select_field) + "').change(function(){"
javascript_if_selected (a_select_field, a_value, a_then) + + javascript_if_selected (a_select_field, a_value, a_then)
"else{" + + "else{"
a_else + + a_else
"}" + + "}"
"});" + "});"
end end
feature -- Helper feature -- Helper
field_id(a_select_field : WSF_FORM_SELECT) : STRING field_id (a_select_field: WSF_FORM_SELECT): STRING
-- Returns the id of the given field -- Id of the given field.
do do
if attached a_select_field.css_id as a_id then if attached a_select_field.css_id as a_id then
Result := a_id Result := a_id
else else
Result := a_select_field.name + "-select" Result := a_select_field.name + "-select"
end end
end end
editor_variable (a_textarea : WSF_FORM_TEXTAREA) : STRING editor_variable (a_textarea: WSF_FORM_TEXTAREA): STRING
-- Returns the variable name that stores the editor instance of the given textarea -- Returns the variable name that stores the editor instance of the given textarea
do do
Result := "cms_ckeditor_" + a_textarea.name Result := "cms_ckeditor_" + a_textarea.name
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2016, 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)"
end end

View File

@@ -12,7 +12,7 @@ inherit
feature -- Initialisation feature -- Initialisation
load_assets : STRING load_assets: STRING
-- <Precursor> -- <Precursor>
do do
Result := "<script src=%"//cdn.ckeditor.com/4.4.7/standard/ckeditor.js%"></script>" Result := "<script src=%"//cdn.ckeditor.com/4.4.7/standard/ckeditor.js%"></script>"
@@ -20,23 +20,25 @@ feature -- Initialisation
feature -- Javascript feature -- Javascript
javascript_replace_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING javascript_replace_textarea (a_textarea: WSF_FORM_TEXTAREA): STRING
-- <Precursor> -- <Precursor>
do do
-- Replaces the textarea with an editor instance. Save the instance in a variable -- Replaces the textarea with an editor instance.
-- Save the instance in a variable.
Result := "$(%"textarea[name="+ a_textarea.name +"]%").each(function() {" Result := "$(%"textarea[name="+ a_textarea.name +"]%").each(function() {"
Result.append (editor_variable (a_textarea) + " = CKEDITOR.replace(this);") Result.append (editor_variable (a_textarea) + " = CKEDITOR.replace(this);")
Result.append ("});") Result.append ("});")
end end
javascript_restore_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING javascript_restore_textarea (a_textarea: WSF_FORM_TEXTAREA): STRING
-- <Precursor> -- <Precursor>
do do
-- Replaces the textarea with an editor instance. Save the instance in a variable -- Replaces the textarea with an editor instance.
-- Save the instance in a variable.
Result := "if (" + editor_variable (a_textarea) + " != undefined) " + editor_variable (a_textarea) + ".destroy();" Result := "if (" + editor_variable (a_textarea) + " != undefined) " + editor_variable (a_textarea) + ".destroy();"
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2016, 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)"
end end

View File

@@ -282,7 +282,9 @@ feature -- Head customization
local local
s: STRING_8 s: STRING_8
do do
s := "<link rel=%"stylesheet%" href=%""+ a_href + "%" type=%"text/css%"" create s.make_from_string ("<link rel=%"stylesheet%" href=%"")
s.append (a_href)
s.append ("%" type=%"text/css%"")
if a_media /= Void then if a_media /= Void then
s.append (" media=%""+ a_media + "%"") s.append (" media=%""+ a_media + "%"")
end end
@@ -290,11 +292,24 @@ feature -- Head customization
add_additional_head_line (s, False) add_additional_head_line (s, False)
end end
add_style_content (a_style_content: STRING)
-- Add style content `a_style_content' in the head, using <style> tag.
local
s: STRING_8
do
create s.make_from_string ("<style>%N")
s.append (a_style_content)
s.append ("%N</style>")
add_additional_head_line (s, True)
end
add_javascript_url (a_src: STRING) add_javascript_url (a_src: STRING)
local local
s: STRING_8 s: STRING_8
do do
s := "<script type=%"text/javascript%" src=%"" + a_src + "%"></script>" create s.make_from_string ("<script type=%"text/javascript%" src=%"")
s.append (a_src)
s.append ("%"></script>")
add_additional_head_line (s, False) add_additional_head_line (s, False)
end end
@@ -302,7 +317,9 @@ feature -- Head customization
local local
s: STRING_8 s: STRING_8
do do
s := "<script type=%"text/javascript%">%N" + a_script + "%N</script>" create s.make_from_string ("<script type=%"text/javascript%">%N")
s.append (a_script)
s.append ("%N</script>")
add_additional_head_line (s, True) add_additional_head_line (s, True)
end end

View File

@@ -144,12 +144,17 @@ feature -- Element change
title := s title := s
end end
add_additional_head_line (s: READABLE_STRING_8)
do
head_lines.extend (s)
end
add_meta_name_content (a_name: STRING; a_content: STRING) add_meta_name_content (a_name: STRING; a_content: STRING)
local local
s: STRING_8 s: STRING_8
do do
s := "<meta name=%"" + a_name + "%" content=%"" + a_content + "%" />" s := "<meta name=%"" + a_name + "%" content=%"" + a_content + "%" />"
head_lines.extend (s) add_additional_head_line (s)
end end
add_meta_http_equiv (a_http_equiv: STRING; a_content: STRING) add_meta_http_equiv (a_http_equiv: STRING; a_content: STRING)
@@ -157,39 +162,56 @@ feature -- Element change
s: STRING_8 s: STRING_8
do do
s := "<meta http-equiv=%"" + a_http_equiv + "%" content=%"" + a_content + "%" />" s := "<meta http-equiv=%"" + a_http_equiv + "%" content=%"" + a_content + "%" />"
head_lines.extend (s) add_additional_head_line (s)
end end
add_style (a_href: STRING; a_media: detachable STRING) add_style (a_href: STRING; a_media: detachable STRING)
local local
s: STRING_8 s: STRING_8
do do
s := "<link rel=%"stylesheet%" href=%""+ a_href + "%" type=%"text/css%"" create s.make_from_string ("<link rel=%"stylesheet%" href=%"")
s.append (a_href)
s.append ("%" type=%"text/css%"")
if a_media /= Void then if a_media /= Void then
s.append (" media=%""+ a_media + "%"") s.append (" media=%""+ a_media + "%"")
end end
s.append ("/>") s.append ("/>")
head_lines.extend (s) add_additional_head_line (s)
end
add_style_content (a_style_content: STRING)
-- Add style content `a_style_content' in the head, using <style> tag.
local
s: STRING_8
do
create s.make_from_string ("<style>%N")
s.append (a_style_content)
s.append ("%N</style>")
add_additional_head_line (s)
end end
add_javascript_url (a_src: STRING) add_javascript_url (a_src: STRING)
local local
s: STRING_8 s: STRING_8
do do
s := "<script type=%"text/javascript%" src=%"" + a_src + "%"></script>" create s.make_from_string ("<script type=%"text/javascript%" src=%"")
head_lines.extend (s) s.append (a_src)
s.append ("%"></script>")
add_additional_head_line (s)
end end
add_javascript_content (a_script: STRING) add_javascript_content (a_script: STRING)
local local
s: STRING_8 s: STRING_8
do do
s := "<script type=%"text/javascript%">%N" + a_script + "%N</script>" create s.make_from_string ("<script type=%"text/javascript%">%N")
head_lines.extend (s) s.append (a_script)
s.append ("%N</script>")
add_additional_head_line (s)
end end
note note
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others" copyright: "2011-2016, 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

View File

@@ -30,7 +30,7 @@ set ROC_TOOL_PATH=%~dp0
goto START goto START
:START :START
echo Calling %ROC_TOOL_PATH%roc.exe %* rem echo Calling %ROC_TOOL_PATH%roc.exe %*
call %ROC_TOOL_PATH%roc.exe %* call %ROC_TOOL_PATH%roc.exe %*
goto END goto END