Browse files

Merge branch 'release/v0.24'

  • Loading branch information...
2 parents 345d6db + 2fea923 commit 3070242bcc515c31e385786029d1f829c5397d42 @szabgab committed Dec 8, 2011
View
5 Changes
@@ -1,5 +1,10 @@
Changes to the Dwimmer system. See http://dwimmer.org/
+v0.24 2011.11.08
+
+ - Add RSS feed with basic testing (#30)
+ - integrated the CLEditor Javascript based html editor (#15)
+
v0.23 2011.11.20
- Eliminate duplicate files from distribution
View
3 Makefile.PL
@@ -28,9 +28,11 @@ my %prereq = (
'DBIx::RunSQL' => 0,
'Email::Valid' => 0,
'Encode' => 0,
+ 'Fcntl' => 0,
'File::ShareDir' => '1.00',
'File::Slurp' => 0,
'Getopt::Long' => 0,
+ 'List::Util' => 0,
'JSON' => 0,
'MIME::Lite' => 0,
'Moose' => 0,
@@ -39,6 +41,7 @@ my %prereq = (
'Template' => 0,
'XML::Feed' => 0,
'XML::RSS' => 0,
+ 'XML::Simple' => 0,
'YAML' => 0,
);
View
79 lib/Dwimmer.pm
@@ -3,14 +3,17 @@ use Dancer ':syntax';
use 5.008005;
-our $VERSION = '0.23';
+our $VERSION = '0.24';
use Data::Dumper qw(Dumper);
use Dwimmer::DB;
use Dwimmer::Tools qw(_get_db _get_site read_file $SCHEMA_VERSION);
-use Fcntl qw(:flock);
+use Encode qw(decode);
+use Fcntl qw(:flock);
+use List::Util qw(min);
use Template;
+use XML::RSS;
load_app 'Dwimmer::Admin', prefix => "/_dwimmer";
@@ -82,7 +85,56 @@ sub route_index {
return Dwimmer::Admin::render_response( 'error', { page_does_not_exist => 1 } );
}
}
-}
+};
+
+get '/update.rss' => sub {
+ my $db = _get_db();
+ my ( $site_name, $site ) = _get_site();
+
+ my $host = request->uri_base;
+ my $rss = XML::RSS->new( version => '1.0' );
+ my $year = 1900 + (localtime)[5];
+ $rss->channel(
+ title => "Dwimmer.org",
+ link => $host,
+ description => "A Dwimmer based site",
+ dc => {
+ language => 'en-us',
+ publisher => 'szabgab@gmail.com',
+ rights => "Copyright $year",
+ },
+ syn => {
+ updatePeriod => "hourly",
+ updateFrequency => "1",
+ updateBase => "1901-01-01T00:00+00:00",
+ }
+ );
+
+ my @pages = $db->resultset('Page')->search( { siteid => $site->id } );
+ #my @urls = map { { loc => [ $host . $_->filename ] } } @res;
+
+ my $RSS = 10;
+
+ # TODO this whole thing should be a single query and not one for each item!
+ foreach my $p (reverse @pages[-min($RSS, scalar @pages) .. -1]) {
+ my $page = $db->resultset('PageHistory')->find( { siteid => $site->id, pageid => $p->id, revision => $p->revision } );
+ my $text = $page->body;
+# $text =~ s{"/}{"$host/}g;
+ $rss->add_item(
+ title => decode('utf-8', $page->title),
+ link => $host . $page->filename,
+ description => decode('utf-8', $text),
+ dc => {
+ creator => $page->author->name,
+ date => POSIX::strftime("%Y-%m-%dT%H:%M:%S+00:00", localtime $page->timestamp), # 2008-05-14T13:43:49+00:00
+ subject => $page->title,
+ }
+ );
+ }
+
+ return $rss->as_string;
+};
+
# http://www.sitemaps.org/protocol.html
get '/sitemap.xml' => sub {
@@ -96,21 +148,14 @@ get '/sitemap.xml' => sub {
# changefreq
# priority
my $host = request->uri_base;
- my @urls = map { { loc => [ $host . $_->filename ] } } @res;
- my %urlset = (
- xmlns => 'http://www.sitemaps.org/schemas/sitemap/0.9',
- url => \@urls
- );
-
- require XML::Simple;
- my $xs = XML::Simple->new(
- KeepRoot => 1,
- ForceArray => 0,
- KeyAttr => { urlset => 'xmlns' },
- XMLDecl => '<?xml version="1.0" encoding="UTF-8"?>'
- );
- my $xml = $xs->XMLout( { urlset => \%urlset } );
+ my $xml = qq(<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n);
+ foreach my $r (@res) {
+ $xml .= qq( <url>\n);
+ $xml .= qq( <loc>$host) . $r->filename . qq(</loc>\n);
+ $xml .= qq( </url>\n);
+ }
+ $xml .= qq(</urlset>);
content_type "text/xml";
return $xml;
View
19 lib/Dwimmer/Admin.pm
@@ -3,7 +3,7 @@ use Dancer ':syntax';
use 5.008005;
-our $VERSION = '0.23';
+our $VERSION = '0.24';
use Data::Dumper qw(Dumper);
use Email::Valid ();
@@ -717,8 +717,25 @@ sub _set_site_config {
}
}
+get '/search.json' => sub {
+ my ($site_name, $site) = _get_site();
+ my %params = _clean_params(qw(text));
+ return to_json { error => 'no_search_text' } if not $params{text};
+ my $db = _get_db();
+
+ # in each page (last
+ my @history = map { {
+ revision => $_->revision,
+ timestamp => $_->timestamp,
+ author => $_->author->name,
+# filename => $path,
+ } }
+ $db->resultset('PageHistory')->search( { siteid => $site->id, filename => $params{text} } );
+# title, body, description, abstract, filename
+
+};
true;
View
3 lib/Dwimmer/Client.pm
@@ -8,7 +8,7 @@ has host => ( is => 'ro', isa => 'Str', required => 1 );
has mech => ( is => 'rw', isa => 'WWW::Mechanize', default => sub { WWW::Mechanize->new } );
-our $VERSION = '0.23';
+our $VERSION = '0.24';
# get_user parameters can be id => 1
@@ -34,6 +34,7 @@ my %GET = map { $_ => $_ } qw(
list_users
logout
register_email
+ search
session
site_config
sites
View
2 lib/Dwimmer/Tools.pm
@@ -9,7 +9,7 @@ use YAML;
use Dwimmer::DB;
-our $VERSION = '0.23';
+our $VERSION = '0.24';
our $SCHEMA_VERSION = 1;
View
BIN public/cleditor/images/buttons.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN public/cleditor/images/toolbar.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
24 public/cleditor/jquery.cleditor.css
@@ -0,0 +1,24 @@
+.cleditorMain {border:1px solid #999; padding:0 1px 1px; background-color:white}
+.cleditorMain iframe {border:none; margin:0; padding:0}
+.cleditorMain textarea {border:none; margin:0; padding:0; overflow-y:scroll; font:10pt Arial,Verdana; resize:none; outline:none /* webkit grip focus */}
+.cleditorToolbar {background: url('images/toolbar.gif') repeat}
+.cleditorGroup {float:left; height:26px}
+.cleditorButton {float:left; width:24px; height:24px; margin:1px 0 1px 0; background: url('images/buttons.gif')}
+.cleditorDisabled {opacity:0.3; filter:alpha(opacity=30)}
+.cleditorDivider {float:left; width:1px; height:23px; margin:1px 0 1px 0; background:#CCC}
+.cleditorPopup {border:solid 1px #999; background-color:white; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}
+.cleditorList div {padding:2px 4px 2px 4px}
+.cleditorList p,
+.cleditorList h1,
+.cleditorList h2,
+.cleditorList h3,
+.cleditorList h4,
+.cleditorList h5,
+.cleditorList h6,
+.cleditorList font {padding:0; margin:0; background-color:Transparent}
+.cleditorColor {width:150px; padding:1px 0 0 1px}
+.cleditorColor div {float:left; width:14px; height:14px; margin:0 1px 1px 0}
+.cleditorPrompt {background-color:#F6F7F9; padding:4px; font-size:8.5pt}
+.cleditorPrompt input,
+.cleditorPrompt textarea {font:8.5pt Arial,Verdana;}
+.cleditorMsg {background-color:#FDFCEE; width:150px; padding:4px; font-size:8.5pt}
View
31 public/cleditor/jquery.cleditor.min.js
@@ -0,0 +1,31 @@
+/*
+ CLEditor WYSIWYG HTML Editor v1.3.0
+ http://premiumsoftware.net/cleditor
+ requires jQuery v1.4.2 or later
+
+ Copyright 2010, Chris Landowski, Premium Software, LLC
+ Dual licensed under the MIT or GPL Version 2 licenses.
+*/
+(function(e){function aa(a){var b=this,c=a.target,d=e.data(c,x),h=s[d],f=h.popupName,i=p[f];if(!(b.disabled||e(c).attr(n)==n)){var g={editor:b,button:c,buttonName:d,popup:i,popupName:f,command:h.command,useCSS:b.options.useCSS};if(h.buttonClick&&h.buttonClick(a,g)===false)return false;if(d=="source"){if(t(b)){delete b.range;b.$area.hide();b.$frame.show();c.title=h.title}else{b.$frame.hide();b.$area.show();c.title="Show Rich Text"}setTimeout(function(){u(b)},100)}else if(!t(b))if(f){var j=e(i);if(f==
+"url"){if(d=="link"&&M(b)===""){z(b,"A selection is required when inserting a link.",c);return false}j.children(":button").unbind(q).bind(q,function(){var k=j.find(":text"),o=e.trim(k.val());o!==""&&v(b,g.command,o,null,g.button);k.val("http://");r();w(b)})}else f=="pastetext"&&j.children(":button").unbind(q).bind(q,function(){var k=j.find("textarea"),o=k.val().replace(/\n/g,"<br />");o!==""&&v(b,g.command,o,null,g.button);k.val("");r();w(b)});if(c!==e.data(i,A)){N(b,i,c);return false}return}else if(d==
+"print")b.$frame[0].contentWindow.print();else if(!v(b,g.command,g.value,g.useCSS,c))return false;w(b)}}function O(a){a=e(a.target).closest("div");a.css(H,a.data(x)?"#FFF":"#FFC")}function P(a){e(a.target).closest("div").css(H,"transparent")}function ba(a){var b=a.data.popup,c=a.target;if(!(b===p.msg||e(b).hasClass(B))){var d=e.data(b,A),h=e.data(d,x),f=s[h],i=f.command,g,j=this.options.useCSS;if(h=="font")g=c.style.fontFamily.replace(/"/g,"");else if(h=="size"){if(c.tagName=="DIV")c=c.children[0];
+g=c.innerHTML}else if(h=="style")g="<"+c.tagName+">";else if(h=="color")g=Q(c.style.backgroundColor);else if(h=="highlight"){g=Q(c.style.backgroundColor);if(l)i="backcolor";else j=true}b={editor:this,button:d,buttonName:h,popup:b,popupName:f.popupName,command:i,value:g,useCSS:j};if(!(f.popupClick&&f.popupClick(a,b)===false)){if(b.command&&!v(this,b.command,b.value,b.useCSS,d))return false;r();w(this)}}}function C(a){for(var b=1,c=0,d=0;d<a.length;++d){b=(b+a.charCodeAt(d))%65521;c=(c+b)%65521}return c<<
+16|b}function R(a,b,c,d,h){if(p[a])return p[a];var f=e(m).hide().addClass(ca).appendTo("body");if(d)f.html(d);else if(a=="color"){b=b.colors.split(" ");b.length<10&&f.width("auto");e.each(b,function(i,g){e(m).appendTo(f).css(H,"#"+g)});c=da}else if(a=="font")e.each(b.fonts.split(","),function(i,g){e(m).appendTo(f).css("fontFamily",g).html(g)});else if(a=="size")e.each(b.sizes.split(","),function(i,g){e(m).appendTo(f).html("<font size="+g+">"+g+"</font>")});else if(a=="style")e.each(b.styles,function(i,
+g){e(m).appendTo(f).html(g[1]+g[0]+g[1].replace("<","</"))});else if(a=="url"){f.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');c=B}else if(a=="pastetext"){f.html("Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>");c=B}if(!c&&!d)c=S;f.addClass(c);l&&f.attr(I,"on").find("div,font,p,h1,h2,h3,h4,h5,h6").attr(I,"on");if(f.hasClass(S)||h===true)f.children().hover(O,P);p[a]=f[0];
+return f[0]}function T(a,b){if(b){a.$area.attr(n,n);a.disabled=true}else{a.$area.removeAttr(n);delete a.disabled}try{if(l)a.doc.body.contentEditable=!b;else a.doc.designMode=!b?"on":"off"}catch(c){}u(a)}function v(a,b,c,d,h){D(a);if(!l){if(d===undefined||d===null)d=a.options.useCSS;a.doc.execCommand("styleWithCSS",0,d.toString())}d=true;var f;if(l&&b.toLowerCase()=="inserthtml")y(a).pasteHTML(c);else{try{d=a.doc.execCommand(b,0,c||null)}catch(i){f=i.description;d=false}d||("cutcopypaste".indexOf(b)>
+-1?z(a,"For security reasons, your browser does not support the "+b+" command. Try using the keyboard shortcut or context menu instead.",h):z(a,f?f:"Error executing the "+b+" command.",h))}u(a);return d}function w(a){setTimeout(function(){t(a)?a.$area.focus():a.$frame[0].contentWindow.focus();u(a)},0)}function y(a){if(l)return J(a).createRange();return J(a).getRangeAt(0)}function J(a){if(l)return a.doc.selection;return a.$frame[0].contentWindow.getSelection()}function Q(a){var b=/rgba?\((\d+), (\d+), (\d+)/.exec(a),
+c=a.split("");if(b)for(a=(b[1]<<16|b[2]<<8|b[3]).toString(16);a.length<6;)a="0"+a;return"#"+(a.length==6?a:c[1]+c[1]+c[2]+c[2]+c[3]+c[3])}function r(){e.each(p,function(a,b){e(b).hide().unbind(q).removeData(A)})}function U(){var a=e("link[href$='jquery.cleditor.css']").attr("href");return a.substr(0,a.length-19)+"images/"}function K(a){var b=a.$main,c=a.options;a.$frame&&a.$frame.remove();var d=a.$frame=e('<iframe frameborder="0" src="javascript:true;">').hide().appendTo(b),h=d[0].contentWindow,f=
+a.doc=h.document,i=e(f);f.open();f.write(c.docType+"<html>"+(c.docCSSFile===""?"":'<head><link rel="stylesheet" type="text/css" href="'+c.docCSSFile+'" /></head>')+'<body style="'+c.bodyStyle+'"></body></html>');f.close();l&&i.click(function(){w(a)});E(a);if(l){i.bind("beforedeactivate beforeactivate selectionchange keypress",function(g){if(g.type=="beforedeactivate")a.inactive=true;else if(g.type=="beforeactivate"){!a.inactive&&a.range&&a.range.length>1&&a.range.shift();delete a.inactive}else if(!a.inactive){if(!a.range)a.range=
+[];for(a.range.unshift(y(a));a.range.length>2;)a.range.pop()}});d.focus(function(){D(a)})}(e.browser.mozilla?i:e(h)).blur(function(){V(a,true)});i.click(r).bind("keyup mouseup",function(){u(a)});L?a.$area.show():d.show();e(function(){var g=a.$toolbar,j=g.children("div:last"),k=b.width();j=j.offset().top+j.outerHeight()-g.offset().top+1;g.height(j);j=(/%/.test(""+c.height)?b.height():parseInt(c.height))-j;d.width(k).height(j);a.$area.width(k).height(ea?j-2:j);T(a,a.disabled);u(a)})}function u(a){if(!L&&
+e.browser.webkit&&!a.focused){a.$frame[0].contentWindow.focus();window.focus();a.focused=true}var b=a.doc;if(l)b=y(a);var c=t(a);e.each(a.$toolbar.find("."+W),function(d,h){var f=e(h),i=e.cleditor.buttons[e.data(h,x)],g=i.command,j=true;if(a.disabled)j=false;else if(i.getEnabled){j=i.getEnabled({editor:a,button:h,buttonName:i.name,popup:p[i.popupName],popupName:i.popupName,command:i.command,useCSS:a.options.useCSS});if(j===undefined)j=true}else if((c||L)&&i.name!="source"||l&&(g=="undo"||g=="redo"))j=
+false;else if(g&&g!="print"){if(l&&g=="hilitecolor")g="backcolor";if(!l||g!="inserthtml")try{j=b.queryCommandEnabled(g)}catch(k){j=false}}if(j){f.removeClass(X);f.removeAttr(n)}else{f.addClass(X);f.attr(n,n)}})}function D(a){l&&a.range&&a.range[0].select()}function M(a){D(a);if(l)return y(a).text;return J(a).toString()}function z(a,b,c){var d=R("msg",a.options,fa);d.innerHTML=b;N(a,d,c)}function N(a,b,c){var d,h,f=e(b);if(c){var i=e(c);d=i.offset();h=--d.left;d=d.top+i.height()}else{i=a.$toolbar;
+d=i.offset();h=Math.floor((i.width()-f.width())/2)+d.left;d=d.top+i.height()-2}r();f.css({left:h,top:d}).show();if(c){e.data(b,A,c);f.bind(q,{popup:b},e.proxy(ba,a))}setTimeout(function(){f.find(":text,textarea").eq(0).focus().select()},100)}function t(a){return a.$area.is(":visible")}function E(a,b){var c=a.$area.val(),d=a.options,h=d.updateFrame,f=e(a.doc.body);if(h){var i=C(c);if(b&&a.areaChecksum==i)return;a.areaChecksum=i}c=h?h(c):c;c=c.replace(/<(?=\/?script)/ig,"&lt;");if(d.updateTextArea)a.frameChecksum=
+C(c);if(c!=f.html()){f.html(c);e(a).triggerHandler(F)}}function V(a,b){var c=e(a.doc.body).html(),d=a.options,h=d.updateTextArea,f=a.$area;if(h){var i=C(c);if(b&&a.frameChecksum==i)return;a.frameChecksum=i}c=h?h(c):c;if(d.updateFrame)a.areaChecksum=C(c);if(c!=f.val()){f.val(c);e(a).triggerHandler(F)}}e.cleditor={defaultOptions:{width:500,height:250,controls:"bold italic underline strikethrough subscript superscript | font size style | color highlight removeformat | bullets numbering | outdent indent | alignleft center alignright justify | undo redo | rule image link unlink | cut copy paste pastetext | print source",
+colors:"FFF FCC FC9 FF9 FFC 9F9 9FF CFF CCF FCF CCC F66 F96 FF6 FF3 6F9 3FF 6FF 99F F9F BBB F00 F90 FC6 FF0 3F3 6CC 3CF 66C C6C 999 C00 F60 FC3 FC0 3C0 0CC 36F 63F C3C 666 900 C60 C93 990 090 399 33F 60C 939 333 600 930 963 660 060 366 009 339 636 000 300 630 633 330 030 033 006 309 303",fonts:"Arial,Arial Black,Comic Sans MS,Courier New,Narrow,Garamond,Georgia,Impact,Sans Serif,Serif,Tahoma,Trebuchet MS,Verdana",sizes:"1,2,3,4,5,6,7",styles:[["Paragraph","<p>"],["Header 1","<h1>"],["Header 2","<h2>"],
+["Header 3","<h3>"],["Header 4","<h4>"],["Header 5","<h5>"],["Header 6","<h6>"]],useCSS:false,docType:'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',docCSSFile:"",bodyStyle:"margin:4px; font:10pt Arial,Verdana; cursor:text"},buttons:{init:"bold,,|italic,,|underline,,|strikethrough,,|subscript,,|superscript,,|font,,fontname,|size,Font Size,fontsize,|style,,formatblock,|color,Font Color,forecolor,|highlight,Text Highlight Color,hilitecolor,color|removeformat,Remove Formatting,|bullets,,insertunorderedlist|numbering,,insertorderedlist|outdent,,|indent,,|alignleft,Align Text Left,justifyleft|center,,justifycenter|alignright,Align Text Right,justifyright|justify,,justifyfull|undo,,|redo,,|rule,Insert Horizontal Rule,inserthorizontalrule|image,Insert Image,insertimage,url|link,Insert Hyperlink,createlink,url|unlink,Remove Hyperlink,|cut,,|copy,,|paste,,|pastetext,Paste as Text,inserthtml,|print,,|source,Show Source"},
+imagesPath:function(){return U()}};e.fn.cleditor=function(a){var b=e([]);this.each(function(c,d){if(d.tagName=="TEXTAREA"){var h=e.data(d,Y);h||(h=new cleditor(d,a));b=b.add(h)}});return b};var H="backgroundColor",A="button",x="buttonName",F="change",Y="cleditor",q="click",n="disabled",m="<div>",I="unselectable",W="cleditorButton",X="cleditorDisabled",ca="cleditorPopup",S="cleditorList",da="cleditorColor",B="cleditorPrompt",fa="cleditorMsg",l=e.browser.msie,ea=/msie\s6/i.test(navigator.userAgent),
+L=/iphone|ipad|ipod/i.test(navigator.userAgent),p={},Z,s=e.cleditor.buttons;e.each(s.init.split("|"),function(a,b){var c=b.split(","),d=c[0];s[d]={stripIndex:a,name:d,title:c[1]===""?d.charAt(0).toUpperCase()+d.substr(1):c[1],command:c[2]===""?d:c[2],popupName:c[3]===""?d:c[3]}});delete s.init;cleditor=function(a,b){var c=this;c.options=b=e.extend({},e.cleditor.defaultOptions,b);var d=c.$area=e(a).hide().data(Y,c).blur(function(){E(c,true)}),h=c.$main=e(m).addClass("cleditorMain").width(b.width).height(b.height),
+f=c.$toolbar=e(m).addClass("cleditorToolbar").appendTo(h),i=e(m).addClass("cleditorGroup").appendTo(f);e.each(b.controls.split(" "),function(g,j){if(j==="")return true;if(j=="|"){e(m).addClass("cleditorDivider").appendTo(i);i=e(m).addClass("cleditorGroup").appendTo(f)}else{var k=s[j],o=e(m).data(x,k.name).addClass(W).attr("title",k.title).bind(q,e.proxy(aa,c)).appendTo(i).hover(O,P),G={};if(k.css)G=k.css;else if(k.image)G.backgroundImage="url("+U()+k.image+")";if(k.stripIndex)G.backgroundPosition=
+k.stripIndex*-24;o.css(G);l&&o.attr(I,"on");k.popupName&&R(k.popupName,b,k.popupClass,k.popupContent,k.popupHover)}});h.insertBefore(d).append(d);if(!Z){e(document).click(function(g){g=e(g.target);g.add(g.parents()).is("."+B)||r()});Z=true}/auto|%/.test(""+b.width+b.height)&&e(window).resize(function(){K(c)});K(c)};var $=cleditor.prototype;e.each([["clear",function(a){a.$area.val("");E(a)}],["disable",T],["execCommand",v],["focus",w],["hidePopups",r],["sourceMode",t,true],["refresh",K],["select",
+function(a){setTimeout(function(){t(a)?a.$area.select():v(a,"selectall")},0)}],["selectedHTML",function(a){D(a);a=y(a);if(l)return a.htmlText;var b=e("<layer>")[0];b.appendChild(a.cloneContents());return b.innerHTML},true],["selectedText",M,true],["showMessage",z],["updateFrame",E],["updateTextArea",V]],function(a,b){$[b[0]]=function(){for(var c=[this],d=0;d<arguments.length;d++)c.push(arguments[d]);c=b[1].apply(this,c);if(b[2])return c;return this}});$.change=function(a){var b=e(this);return a?b.bind(F,
+a):b.trigger(F)}})(jQuery);
View
2 public/css/style.css
@@ -223,7 +223,7 @@ font-size: 10px;
#manage-bar {
top: 40px;
- height: 300px;
+ height: 400px;
background-color: #FFF;
border-bottom: 3px solid #222;
color: #000;
View
39 public/javascripts/dwimmer.js
@@ -104,8 +104,7 @@ $(document).ready(function() {
});
$("form.login").submit(function() {
- var url = "/_dwimmer/login.json";
- $.post(url, $(this).serialize(), function(resp) {
+ $.post(_url("/_dwimmer/login.json"), $(this).serialize(), function(resp) {
if (resp["success"] == 1) {
$('#guest_bar').hide();
$('#logged_in_bar').show();
@@ -177,7 +176,7 @@ $(document).ready(function() {
$('#create').val( 1 );
$('#admin-editor').show();
$('#admin-editor-filename').show();
- $('#editor_body').keyup(); // update preview
+// $('#editor_body').keyup(); // update preview
return false;
});
@@ -189,7 +188,7 @@ $(document).ready(function() {
$('#admin-editor').show();
$('#filename').val( $(location).attr('pathname') );
$('#admin-editor-filename').show();
- $('#editor_body').keyup(); // update preview
+// $('#editor_body').keyup(); // update preview
return false;
});
@@ -220,8 +219,7 @@ $(document).ready(function() {
// submit the form
function submit_form(obj, file) {
- var url = "/_dwimmer/" + file + ".json";
- $.post(url, $(obj).serialize(), function(resp) {
+ $.post(_url("/_dwimmer/" + file + ".json"), $(obj).serialize(), function(resp) {
if (resp["success"] == 1) {
alert('added');
} else {
@@ -345,8 +343,7 @@ function submit_form(obj, file) {
$(".show_history").click(function(){
manage_bar();
- var url = _url('/_dwimmer/history.json') + '&filename=' + $(location).attr('pathname');
- $.getJSON(url, function(resp) {
+ $.getJSON(_url('/_dwimmer/history.json') + '&filename=' + $(location).attr('pathname'), function(resp) {
//$('#admin-editor').show();
var html = '<ul>';
for(var i=0; i < resp["rows"].length; i++) {
@@ -357,8 +354,7 @@ function submit_form(obj, file) {
$('#manage-display-content').html(html);
$(".show_page_rev").click(function() {
- var url = _url( $(this).attr('href') );
- $.getJSON(url, function(resp) {
+ $.getJSON(_url( $(this).attr('href') ), function(resp) {
// alert(dumper(resp));
if (resp["error"]) {
alert(resp["error"] + " " + resp["details"]);
@@ -389,15 +385,18 @@ function submit_form(obj, file) {
$(".edit_this_page").click(function() {
manage_bar();
original_content = $('#content').html();
- var url = _url('/_dwimmer/page.json') + '&filename=' + $(location).attr('pathname');
- $.getJSON(url, function(resp) {
+ $.getJSON(_url('/_dwimmer/page.json') + '&filename=' + $(location).attr('pathname'), function(resp) {
$('#admin-editor').show();
$('#admin-editor-filename').hide();
$('#create').val( 0 );
$('#filename').val( resp["page"]["filename"] );
$('#editor_title').val( resp["page"]["title"] );
$('#editor_body').val( resp["page"]["body"] );
- $('#editor_body').keyup(); // update preview
+ // $('#editor_body').keyup(); // update preview
+ $('#editor_body').cleditor({
+ width: 700,
+ height: 300,
+ });
});
return false;
});
@@ -415,11 +414,9 @@ function submit_form(obj, file) {
$('#save').click(function(){
var body = $('#editor_body').val();
var title = $('#editor_title').val();
-
- var url = '/_dwimmer/save_page.json';
var data = $("#editor_form").serialize();
- $.post(url, data, function(resp) {
+ $.post(_url('/_dwimmer/save_page.json'), data, function(resp) {
var data = eval('(' + resp + ')');
if (data["error"] == "no_file_supplied") {
alert("Internal error, no filename supplied. Not saved.");
@@ -433,11 +430,11 @@ function submit_form(obj, file) {
return false;
});
- $('#editor_body').keyup(function(){
- var body = $('#editor_body').val();
- var html = markup(body);
- $('#content').html(html); // preview
- });
+// $('#editor_body').keyup(function(){
+// var body = $('#editor_body').val();
+// var html = markup(body);
+// $('#content').html(html); // preview
+// });
View
127 script/dwimmer_poll.pl
@@ -0,0 +1,127 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+# step:
+# 1) replace IP and SID with counter values and save as single json (this file can already be shared).
+# 2) filter duplicate SIDs or duplicate IPs (the user can choose), create new file.
+# 3) Collect stats (all the other items) and save them as a json file.
+# 4) Generate pie graphs from the choice based questions.
+# 5) Allow the listing of all the "other" and free-text fields.
+# *) at some place we should let the owner remove some textual responses or fix them (assuming typos and grammar errors)
+
+
+use Data::Dumper qw(Dumper);
+use File::Slurp qw(read_file write_file);
+use JSON qw(from_json to_json);
+use Params::Util qw(_SCALAR _ARRAY _STRING _NUMBER);
+use Pod::Usage qw(pod2usage);
+use Getopt::Long qw(GetOptions);
+
+=head1 NAME
+
+Sanitize a poll file
+
+=head1 SYNOPSIS
+
+
+PARAMETERS:
+ --clean (replace IP and SID with counter values on same IP same
+ counter mapping to allow identificating duplicates
+ without the privacy issues.)
+ --filter [SID|IP|all]
+
+ --report generate report from the already cleaned and filtered data
+
+ --pollid id of the poll
+
+=cut
+
+my %opt;
+GetOptions(\%opt,
+ 'pollid=s',
+ 'clean',
+ 'filter=s',
+);
+
+pod2usage if not $opt{pollid};
+my $poll_file = "polls/$opt{pollid}.json";
+my $in_file = "polls/$opt{pollid}.txt";
+my $out_file = "polls/$opt{pollid}.out";
+die "Could not find poll file '$poll_file'" if not -e $poll_file;
+die "Could not find in file '$in_file'" if not -e $in_file;
+die "There is already an out file '$out_file'" if -e $out_file;
+
+my $poll = from_json scalar read_file $poll_file;
+
+if ($opt{filter}) {
+ die "Invalid --filter" if $opt{filter} !~ /^(SID|IP|all)$/;
+} else {
+ $opt{filter} = '';
+}
+#die Dumper \%opt;
+
+#pod2usage if not $result;
+clean() if $opt{clean};
+#print Dumper \%DUPLICATE;
+exit;
+
+
+sub clean {
+ my $raw_data = read_file($in_file);
+ my @p = split /^$/m, $raw_data;
+ #print scalar @p;
+ #print $p[0];
+
+ my %MAP;
+ my %count = (SID => 0, IP => 0);
+ my %DUPLICATE;
+ my @all;
+ my %RESULT;
+
+ foreach my $json (@p) {
+ next if $json =~ /^\s*$/;
+ # print $json;
+ # print "-----------------------\n";
+ my $d = from_json($json);
+ foreach my $f (qw(SID IP)) {
+ if (not $MAP{$f}{ $d->{$f} }) {
+ $count{$f}++;
+ $MAP{$f}{ $d->{$f} } = $count{$f};
+ } else {
+ $DUPLICATE{$f}++;
+ next if $f eq 'SID' and ($opt{filter} eq 'SID' or $opt{filter} eq 'all');
+ next if $f eq 'IP' and ($opt{filter} eq 'IP' or $opt{filter} eq 'all');
+ }
+ $d->{$f} = $MAP{$f}{ $d->{$f} };
+ push @all, $d;
+ }
+
+ }
+ write_file($out_file, to_json \@all, { pretty => 1, utf8 => 1 });
+}
+
+sub report {
+ foreach my $key (keys %$d) {
+ next if $key =~ /^(SID|TS|IP|id)$/;
+ next if not defined $d->{$key}; # TODO report error
+ next if $d->{$key} eq '';
+
+ if ($key =~ /^other__/) {
+ push @{ $RESULT{$key} }, $d->{$key};
+ } elsif (_ARRAY($d->{$key})) {
+ $RESULT{ $key }{$_}++ for @{ $d->{$key} };
+ } elsif (defined _STRING($d->{$key})) {
+ # source_of_perl_news
+ $RESULT{ $key }{$_}++ for $d->{$key};
+ } else {
+ #die ref $d->{$key};
+ die "Unhandled key: '$key' " . Dumper $d;
+ }
+ }
+ write_file($report_file, to_json \%RESULT, { pretty => 1, utf8 => 1 });
+}
+
+
+
+
View
109 t/003_client.t
@@ -18,7 +18,7 @@ plan( skip_all => 'Unsupported OS' ) if not $run;
my $url = "http://localhost:$ENV{DWIMMER_PORT}";
-plan( tests => 51 );
+plan( tests => 55 );
my @pages = (
{},
@@ -40,6 +40,27 @@ $w->get_ok("$url/other");
$w->content_like( qr{Page does not exist}, 'content of missing pages is ok' );
$w->content_unlike( qr{Would you like to create it}, 'no creation offer' );
+require LWP::Simple;
+require XML::Simple;
+
+test_rss(
+ {
+ 'dc:creator' => 'admin',
+ 'link' => 'http://localhost:3001/',
+ 'rdf:about' => 'http://localhost:3001/',
+ 'dc:subject' => 'Welcome to your Dwimmer installation',
+ 'title' => 'Welcome to your Dwimmer installation',
+ 'dc:date' => ignore(), #'2011-12-07T17:53:48+00:00',
+ 'description' => '<h1>Dwimmer</h1>'
+ },
+);
+
+test_sitemap(
+ {
+ 'loc' => 'http://localhost:3001/'
+ }
+);
+
my $u = Test::WWW::Mechanize->new;
$u->get_ok($url);
$u->post_ok(
@@ -307,6 +328,8 @@ cmp_deeply(
$w->get_ok("$url$pages[2]{filename}");
$w->content_like(qr{$pages[2]{body}});
+#diag(explain($admin->search( text => 'xyz' )));
+
my $user = Dwimmer::Client->new( host => $url );
is_deeply(
@@ -412,3 +435,87 @@ is_deeply(
'user logged in with new password'
);
+test_rss([
+ {
+ 'dc:creator' => 'admin',
+ 'link' => 'http://localhost:3001/space and.dot and $@% too',
+ 'rdf:about' => 'http://localhost:3001/space and.dot and $@% too',
+ 'dc:subject' => 'dotspace',
+ 'title' => 'dotspace',
+ 'dc:date' => ignore(),
+ 'description' => 'File with space and dot'
+ },
+ {
+ 'dc:creator' => 'admin',
+ 'link' => 'http://localhost:3001/xyz',
+ 'rdf:about' => 'http://localhost:3001/xyz',
+ 'dc:subject' => 'New title of xyz',
+ 'title' => 'New title of xyz',
+ 'dc:date' => ignore(),
+ 'description' => 'New text'
+ },
+ {
+ 'dc:creator' => 'admin',
+ 'link' => 'http://localhost:3001/',
+ 'rdf:about' => 'http://localhost:3001/',
+ 'dc:subject' => 'New main title',
+ 'title' => 'New main title',
+ 'dc:date' => ignore(),
+ 'description' => 'New text [link] here and [space and.dot and $@% too] here'
+ }
+]);
+test_sitemap([
+ {
+ 'loc' => 'http://localhost:3001/'
+ },
+ {
+ 'loc' => 'http://localhost:3001/xyz'
+ },
+ {
+ 'loc' => 'http://localhost:3001/space and.dot and $@% too'
+ }
+ ]);
+
+exit;
+
+sub test_rss {
+ my ($expected_items) = @_;
+
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+ my $rss_str = LWP::Simple::get("$url/update.rss");
+ #diag($rss_str);
+ my $xml = XML::Simple->new(
+ KeepRoot => 1,
+ ForceArray => 0,
+ KeyAttr => { urlset => 'xmlns' },
+ );
+ my $rss = $xml->XMLin( $rss_str );
+# diag(Dumper $rss);
+# diag(Dumper $rss->{'rdf:RDF'}{channel});
+# diag(Dumper $rss->{'rdf:RDF'}{item});
+ cmp_deeply($rss->{'rdf:RDF'}{item}, $expected_items);
+
+ return;
+}
+
+
+sub test_sitemap {
+ my ($expected) = @_;
+
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ my $sitemap_str = LWP::Simple::get("$url/sitemap.xml");
+ #diag($sitemap_str);
+ my $xml = XML::Simple->new(
+ KeepRoot => 1,
+ ForceArray => 0,
+ KeyAttr => { urlset => 'xmlns' },
+ );
+ my $sitemap = $xml->XMLin( $sitemap_str );
+ #diag(Dumper $sitemap);
+ #diag(Dumper $sitemap->{urlset}{url});
+ cmp_deeply($sitemap->{urlset}{url}, $expected, 'sitemap');
+
+ return;
+}
+
View
5 views/layouts/main.tt
@@ -5,13 +5,16 @@
<meta http-equiv="Content-type" content="text/html; charset=<% settings.charset %>" />
<title><% page.title %></title>
<link rel="stylesheet" href="<% request.uri_base %>/css/style.css" />
+<link rel="stylesheet" href="<% request.uri_base %>/cleditor/jquery.cleditor.css" />
<script type="text/javascript" src="<% request.uri_base %>/javascripts/jquery-1.6.3.min.js"></script>
<script type="text/javascript" src="<% request.uri_base %>/javascripts/jquery.a-tools-1.5.2.min.js"></script>
<script type="text/javascript" src="<% request.uri_base %>/javascripts/jquery-ui-1.8.16.custom.min.js"></script>
<script type="text/javascript" src="<% request.uri_base %>/javascripts/dwimmer.js"></script>
<script type="text/javascript" src="<% request.uri_base %>/javascripts/scriptbreaker-dropdownpanel-1.0.js"></script>
+<script type="text/javascript" src="<% request.uri_base %>/cleditor/jquery.cleditor.min.js"></script>
+
</head>
<body>
<div id="admin">
@@ -118,10 +121,12 @@
<form id="editor_form" action="/_dwimmer/save" method="POST">
<input type="button" id="save" value="Save" />
<input type="button" id="cancel" value="Cancel" />
+<!--
<br />
<input type="button" id="editor-bold" title="bold" value="b" />
<input type="button" id="editor-italic" title="italic" value="i" />
<input type="button" id="editor-link" title="add link" value="Link" />
+-->
<div id="admin-editor-filename">
Filename: <input id="filename" name="filename" />
</div>

0 comments on commit 3070242

Please sign in to comment.