Compare commits

..

1 Commits

Author SHA1 Message Date
fc2c72a49b Added files, and especiall upload files facility.
Main contribution from Fabian Murer, as part of 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-16 21:03:02 +01:00
22 changed files with 3551 additions and 7754 deletions

View File

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

View File

@@ -1,44 +1,38 @@
.uploaded-files table {
.uploaded-files {
width: 100%;
border-collapse: collapse;
border: 1px solid black;
}
.uploaded-files table th {
padding: 3px 0 3px 5px;
.uploaded-files th {
padding-left: 5px;
padding-top: 3px;
padding-bottom: 3px;
}
.uploaded-files table td {
padding: 3px 0 3px 5px;
.uploaded-files td {
padding-left: 5px;
padding-top: 3px;
padding-bottom: 3px;
}
.uploaded-files a.button {
color: black;
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
}
.uploaded-files a.button:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
text-decoration: none;
}
.upload-files .center {
text-align: center;
padding: 10px;
}
.upload-files a.button {
.upload-files a.upload-button {
margin: auto;
width: 100px;
color: black;
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
}
.upload-files a.button:hover {
.upload-files a.upload-button:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
text-decoration: none;
}
/******************* Drop Zone *******************/
@@ -50,3 +44,18 @@
padding-top: 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

@@ -1,78 +0,0 @@
/*
* 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

@@ -1,413 +0,0 @@
/*
* 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,16 +1,18 @@
.uploaded-files {
table {
width: 100%;
border-collapse: collapse;
border: 1px solid black;
width: 100%;
border-collapse: collapse;
border: 1px solid black;
th {
padding: 3px 0 3px 5px;
}
th {
padding-left: 5px;
padding-top: 3px;
padding-bottom: 3px;
}
td {
padding: 3px 0 3px 5px;
}
td {
padding-left: 5px;
padding-top: 3px;
padding-bottom: 3px;
}
a.button{
@@ -18,33 +20,23 @@
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
&:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
text-decoration: none;
}
}
}
.upload-files {
.center {
text-align: center;
padding: 10px;
}
a.button{
a.upload-button{
margin: auto;
width: 100px;
color: black;
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
&:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
text-decoration: none;
}
}
}
@@ -59,5 +51,23 @@
text-align: center;
padding-top: 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

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

View File

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

View File

@@ -1,44 +1,38 @@
.uploaded-files table {
.uploaded-files {
width: 100%;
border-collapse: collapse;
border: 1px solid black;
}
.uploaded-files table th {
padding: 3px 0 3px 5px;
.uploaded-files th {
padding-left: 5px;
padding-top: 3px;
padding-bottom: 3px;
}
.uploaded-files table td {
padding: 3px 0 3px 5px;
.uploaded-files td {
padding-left: 5px;
padding-top: 3px;
padding-bottom: 3px;
}
.uploaded-files a.button {
color: black;
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
}
.uploaded-files a.button:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
text-decoration: none;
}
.upload-files .center {
text-align: center;
padding: 10px;
}
.upload-files a.button {
.upload-files a.upload-button {
margin: auto;
width: 100px;
color: black;
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
}
.upload-files a.button:hover {
.upload-files a.upload-button:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
text-decoration: none;
}
/******************* Drop Zone *******************/
@@ -50,3 +44,18 @@
padding-top: 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

@@ -1,78 +0,0 @@
/*
* 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

@@ -1,413 +0,0 @@
/*
* 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,16 +1,18 @@
.uploaded-files {
table {
width: 100%;
border-collapse: collapse;
border: 1px solid black;
width: 100%;
border-collapse: collapse;
border: 1px solid black;
th {
padding: 3px 0 3px 5px;
}
th {
padding-left: 5px;
padding-top: 3px;
padding-bottom: 3px;
}
td {
padding: 3px 0 3px 5px;
}
td {
padding-left: 5px;
padding-top: 3px;
padding-bottom: 3px;
}
a.button{
@@ -18,33 +20,23 @@
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
&:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
text-decoration: none;
}
}
}
.upload-files {
.center {
text-align: center;
padding: 10px;
}
a.button{
a.upload-button{
margin: auto;
width: 100px;
color: black;
text-decoration: none;
border: solid 1px #999;
background-color: #ddd;
padding: 2px 4px 2px 4px;
&:hover {
color: black;
border: solid 1px #06f;
background-color: #cff;
text-decoration: none;
}
}
}
@@ -59,5 +51,23 @@
text-align: center;
padding-top: 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

@@ -9,38 +9,38 @@ deferred class
feature -- Initialisation
load_assets: STRING
-- Loads all assest needed to show the editor.
load_assets : STRING
-- Loads all assest needed to show the editor
deferred
end
feature -- Javascript
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_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
deferred
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
deferred
end
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_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
do
Result := javascript_ready (javascript_replace_textarea (a_textarea))
end
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_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
local
initial_replace_code, on_select_replace_code: STRING
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)))
-- 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(
javascript_init_editor_variable (a_textarea) +
javascript_on_select (a_select_field, a_value,
@@ -55,56 +55,54 @@ feature -- Javascript
Result := initial_replace_code + " " + on_select_replace_code
end
javascript_init_editor_variable (a_textarea: WSF_FORM_TEXTAREA): STRING
-- Returns the javascript code that initializes a local variable to store the editor instance.
javascript_init_editor_variable (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- Returns the javascript code that initializes a local variable to store the editor instance
do
Result := "var " + editor_variable (a_textarea) + "; "
end
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_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
do
Result := "if($('#" + field_id (a_select_field) + "').val() == %"" + a_value + "%"){ " + a_code + " }"
end
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.
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
do
Result := "$(function() { " + a_code + " });"
end
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 `a_select_field'
-- the given string `a_value' is selected, otherwise it executes `a_else'.
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
do
Result := "$('#" + field_id (a_select_field) + "').change(function(){"
+ javascript_if_selected (a_select_field, a_value, a_then)
+ "else{"
+ a_else
+ "}"
+ "});"
Result := "$('#" + field_id (a_select_field) + "').change(function(){" +
javascript_if_selected (a_select_field, a_value, a_then) +
"else{" +
a_else +
"}" +
"});"
end
feature -- Helper
field_id (a_select_field: WSF_FORM_SELECT): STRING
-- Id of the given field.
field_id(a_select_field : WSF_FORM_SELECT) : STRING
-- Returns the id of the given field
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
else
Result := a_select_field.name + "-select"
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
do
Result := "cms_ckeditor_" + a_textarea.name
end
note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -12,7 +12,7 @@ inherit
feature -- Initialisation
load_assets: STRING
load_assets : STRING
-- <Precursor>
do
Result := "<script src=%"//cdn.ckeditor.com/4.4.7/standard/ckeditor.js%"></script>"
@@ -20,25 +20,23 @@ feature -- Initialisation
feature -- Javascript
javascript_replace_textarea (a_textarea: WSF_FORM_TEXTAREA): STRING
javascript_replace_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- <Precursor>
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.append (editor_variable (a_textarea) + " = CKEDITOR.replace(this);")
Result.append ("});")
end
javascript_restore_textarea (a_textarea: WSF_FORM_TEXTAREA): STRING
javascript_restore_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- <Precursor>
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();"
end
note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -282,9 +282,7 @@ feature -- Head customization
local
s: STRING_8
do
create s.make_from_string ("<link rel=%"stylesheet%" href=%"")
s.append (a_href)
s.append ("%" type=%"text/css%"")
s := "<link rel=%"stylesheet%" href=%""+ a_href + "%" type=%"text/css%""
if a_media /= Void then
s.append (" media=%""+ a_media + "%"")
end
@@ -292,24 +290,11 @@ feature -- Head customization
add_additional_head_line (s, False)
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)
local
s: STRING_8
do
create s.make_from_string ("<script type=%"text/javascript%" src=%"")
s.append (a_src)
s.append ("%"></script>")
s := "<script type=%"text/javascript%" src=%"" + a_src + "%"></script>"
add_additional_head_line (s, False)
end
@@ -317,9 +302,7 @@ feature -- Head customization
local
s: STRING_8
do
create s.make_from_string ("<script type=%"text/javascript%">%N")
s.append (a_script)
s.append ("%N</script>")
s := "<script type=%"text/javascript%">%N" + a_script + "%N</script>"
add_additional_head_line (s, True)
end

View File

@@ -144,17 +144,12 @@ feature -- Element change
title := s
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)
local
s: STRING_8
do
s := "<meta name=%"" + a_name + "%" content=%"" + a_content + "%" />"
add_additional_head_line (s)
head_lines.extend (s)
end
add_meta_http_equiv (a_http_equiv: STRING; a_content: STRING)
@@ -162,56 +157,39 @@ feature -- Element change
s: STRING_8
do
s := "<meta http-equiv=%"" + a_http_equiv + "%" content=%"" + a_content + "%" />"
add_additional_head_line (s)
head_lines.extend (s)
end
add_style (a_href: STRING; a_media: detachable STRING)
local
s: STRING_8
do
create s.make_from_string ("<link rel=%"stylesheet%" href=%"")
s.append (a_href)
s.append ("%" type=%"text/css%"")
s := "<link rel=%"stylesheet%" href=%""+ a_href + "%" type=%"text/css%""
if a_media /= Void then
s.append (" media=%""+ a_media + "%"")
end
s.append ("/>")
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)
head_lines.extend (s)
end
add_javascript_url (a_src: STRING)
local
s: STRING_8
do
create s.make_from_string ("<script type=%"text/javascript%" src=%"")
s.append (a_src)
s.append ("%"></script>")
add_additional_head_line (s)
s := "<script type=%"text/javascript%" src=%"" + a_src + "%"></script>"
head_lines.extend (s)
end
add_javascript_content (a_script: STRING)
local
s: STRING_8
do
create s.make_from_string ("<script type=%"text/javascript%">%N")
s.append (a_script)
s.append ("%N</script>")
add_additional_head_line (s)
s := "<script type=%"text/javascript%">%N" + a_script + "%N</script>"
head_lines.extend (s)
end
note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

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