aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etherpad/src/plugins/twitterStyleTags/templates/tagBrowser.ejs52
-rw-r--r--etherpad/src/plugins/urlIndexer/controllers/urlBrowser.js132
-rw-r--r--etherpad/src/plugins/urlIndexer/hooks.js5
-rw-r--r--etherpad/src/plugins/urlIndexer/main.js3
-rw-r--r--etherpad/src/plugins/urlIndexer/templates/urlBrowser.ejs53
5 files changed, 220 insertions, 25 deletions
diff --git a/etherpad/src/plugins/twitterStyleTags/templates/tagBrowser.ejs b/etherpad/src/plugins/twitterStyleTags/templates/tagBrowser.ejs
index 1dddce7..c5b6215 100644
--- a/etherpad/src/plugins/twitterStyleTags/templates/tagBrowser.ejs
+++ b/etherpad/src/plugins/twitterStyleTags/templates/tagBrowser.ejs
@@ -71,34 +71,38 @@ limitations under the License. */ %>
<% template.define('contentArea', function() { var ejs_data=''; %>
<div id="editorcontainer">
<div class="query-refiner">
- <h1>Search for pads that have the tag</h1>
- <% for (i = 0; i < newTags.length; i++) { %>
- <a href="/ep/tag/?query=<%= tagQuery.tagsToQuery(tags.concat([newTags[i].tagname]),antiTags) %>" class="padtag" title="<%= newTags[i].matches %> matches">#<%= newTags[i].tagname %></a>
- <% } %>
+ <%: template.use('queryRefiner', function() { var ejs_data=''; %>
+ <h1>Search for pads that have the tag</h1>
+ <% for (i = 0; i < newTags.length; i++) { %>
+ <a href="/ep/tag/?query=<%= tagQuery.tagsToQuery(tags.concat([newTags[i].tagname]),antiTags) %>" class="padtag" title="<%= newTags[i].matches %> matches">#<%= newTags[i].tagname %></a>
+ <% } %>
- <h1>Search for pads that <em>don't</em> have the tag</h1>
- <% for (i = 0; i < newTags.length; i++) { %>
- <a href="/ep/tag/?query=<%= tagQuery.tagsToQuery(tags,antiTags.concat([newTags[i].tagname])) %>" class="anti_padtag" title="<%= newTags[i].antimatches %> matches">!#<%= newTags[i].tagname %></a>
- <% } %>
+ <h1>Search for pads that <em>don't</em> have the tag</h1>
+ <% for (i = 0; i < newTags.length; i++) { %>
+ <a href="/ep/tag/?query=<%= tagQuery.tagsToQuery(tags,antiTags.concat([newTags[i].tagname])) %>" class="anti_padtag" title="<%= newTags[i].antimatches %> matches">!#<%= newTags[i].tagname %></a>
+ <% } %>
+ <% return ejs_data; }); %>
</div>
<dl>
- <% for (i = 0; i < matchingPads.length; i++) { %>
- <%
- var matchingPadId = matchingPads[i].ID;
- var matchingPadUrl = matchingPadId;
- if (!inArray('writable', matchingPads[i].TAGS)) {
- matchingPadId = padIdToReadonly(matchingPads[i].ID);
- matchingPadUrl = 'ep/pad/view/' + matchingPadId + '/latest';
- }
- %>
- <dt><a href="/<%= matchingPadUrl %>"><%= matchingPadId %></a><dt>
- <dd>
- <% for (j = 0; j < matchingPads[i].TAGS.length; j++) { %>
- <a href="/ep/tag/?query=<%= tagQuery.tagsToQuery(tags.concat([matchingPads[i].TAGS[j]]), antiTags) %>" class="padtag" title="<%= matchingPads[i].TAGS[j] %> matches">#<%= matchingPads[i].TAGS[j] %></a>
- <% } %>
- </dd>
- <% } %>
+ <%: template.use('queryResult', function() { var ejs_data=''; %>
+ <% for (i = 0; i < matchingPads.length; i++) { %>
+ <%
+ var matchingPadId = matchingPads[i].ID;
+ var matchingPadUrl = matchingPadId;
+ if (!inArray('writable', matchingPads[i].TAGS)) {
+ matchingPadId = padIdToReadonly(matchingPads[i].ID);
+ matchingPadUrl = 'ep/pad/view/' + matchingPadId + '/latest';
+ }
+ %>
+ <dt><a href="/<%= matchingPadUrl %>"><%= matchingPadId %></a><dt>
+ <dd>
+ <% for (j = 0; j < matchingPads[i].TAGS.length; j++) { %>
+ <a href="/ep/tag/?query=<%= tagQuery.tagsToQuery(tags.concat([matchingPads[i].TAGS[j]]), antiTags) %>" class="padtag" title="<%= matchingPads[i].TAGS[j] %> matches">#<%= matchingPads[i].TAGS[j] %></a>
+ <% } %>
+ </dd>
+ <% } %>
+ <% return ejs_data; }); %>
</dl>
</div>
<% return ejs_data; }); %>
diff --git a/etherpad/src/plugins/urlIndexer/controllers/urlBrowser.js b/etherpad/src/plugins/urlIndexer/controllers/urlBrowser.js
new file mode 100644
index 0000000..ebd39bd
--- /dev/null
+++ b/etherpad/src/plugins/urlIndexer/controllers/urlBrowser.js
@@ -0,0 +1,132 @@
+/**
+ * Copyright 2009 RedHog, Egil Möller <egil.moller@piratpartiet.se>
+ * Copyright 2010 Pita, Peter Martischka <petermartischka@googlemail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS-IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import("plugins.twitterStyleTags.models.tagQuery");
+
+import("faststatic");
+import("dispatch.{Dispatcher,PrefixMatcher,forward}");
+
+import("etherpad.utils.*");
+import("etherpad.collab.server_utils");
+import("etherpad.globals.*");
+import("etherpad.log");
+import("etherpad.pad.padusers");
+import("etherpad.pro.pro_utils");
+import("etherpad.helpers");
+import("etherpad.pro.pro_accounts.getSessionProAccount");
+import("sqlbase.sqlbase");
+import("sqlbase.sqlcommon");
+import("sqlbase.sqlobj");
+import("etherpad.pad.padutils");
+
+function urlSql(querySql, limit, offset) {
+ var sql = '' +
+ 'select ' +
+ ' u.URL, ' +
+ ' m.id as ID, ' +
+ ' DATE_FORMAT(m.lastWriteTime, \'%a, %d %b %Y %H:%i:%s GMT\') as lastWriteTime, ' +
+ ' c.TAGS ' +
+ 'from ' +
+ querySql.sql + ' as q ' +
+ ' join PAD_SQLMETA as m on ' +
+ ' m.id = q.ID ' +
+ ' join PAD_TAG_CACHE as c on ' +
+ ' c.PAD_ID = q.ID ' +
+ ' join PAD_URL as u on ' +
+ ' u.PAD_ID = q.ID ' +
+ 'where ' +
+ ' m.id NOT LIKE \'%$%\'' +
+ 'order by ' +
+ ' u.URL asc ';
+ if (limit != undefined)
+ sql += 'limit ' + limit + " ";
+ if (offset != undefined)
+ sql += 'offset ' + offset + " ";
+ return {
+ sql: sql,
+ params: querySql.params
+ };
+}
+
+function onRequest() {
+ var tags = tagQuery.queryToTags(request.params.query);
+
+ /* Create the pad filter sql */
+ var querySql = tagQuery.getQueryToSql(tags.tags.concat(['public']), tags.antiTags);
+
+ /* Use the pad filter sql to figure out which tags to show in the tag browser this time. */
+ var queryNewTagsSql = tagQuery.newTagsSql(querySql);
+ var newTags = sqlobj.executeRaw(queryNewTagsSql.sql, queryNewTagsSql.params);
+
+ urlSql = urlSql(querySql, 10);
+ var matchingUrls = sqlobj.executeRaw(urlSql.sql, urlSql.params);
+
+ for (i = 0; i < matchingUrls.length; i++) {
+ matchingUrls[i].TAGS = matchingUrls[i].TAGS.split('#');
+ }
+
+ var isPro = pro_utils.isProDomainRequest();
+ var userId = padusers.getUserId();
+
+ helpers.addClientVars({
+ userAgent: request.headers["User-Agent"],
+ debugEnabled: request.params.djs,
+ clientIp: request.clientAddr,
+ colorPalette: COLOR_PALETTE,
+ serverTimestamp: +(new Date),
+ isProPad: isPro,
+ userIsGuest: padusers.isGuest(userId),
+ userId: userId,
+ });
+
+ var isProUser = (isPro && ! padusers.isGuest(userId));
+
+ padutils.setOptsAndCookiePrefs(request);
+ var prefs = helpers.getClientVar('cookiePrefsToSet');
+ var bodyClass = (prefs.isFullWidth ? "fullwidth" : "limwidth")
+
+ var info = {
+ prefs: prefs,
+ config: appjet.config,
+ tagQuery: tagQuery,
+ padIdToReadonly: server_utils.padIdToReadonly,
+ tags: tags.tags,
+ antiTags: tags.antiTags,
+ newTags: newTags,
+ matchingPads: [],
+ matchingUrls: matchingUrls,
+ bodyClass: 'nonpropad',
+ isPro: isPro,
+ isProAccountHolder: isProUser,
+ account: getSessionProAccount(), // may be falsy
+ };
+
+ var format = "html";
+ if (request.params.format != undefined)
+ format = request.params.format;
+
+ if (format == "html")
+ renderHtml("urlBrowser.ejs", info, ['urlIndexer', 'twitterStyleTags']);
+ else if (format == "rss") {
+ response.setContentType("application/xml; charset=utf-8");
+ response.write(renderTemplateAsString("tagRss.ejs", info, 'urlIndexer'));
+ if (request.acceptsGzip) {
+ response.setGzip(true);
+ }
+ }
+ return true;
+}
diff --git a/etherpad/src/plugins/urlIndexer/hooks.js b/etherpad/src/plugins/urlIndexer/hooks.js
index 1429895..45d37f1 100644
--- a/etherpad/src/plugins/urlIndexer/hooks.js
+++ b/etherpad/src/plugins/urlIndexer/hooks.js
@@ -1,6 +1,11 @@
import("etherpad.log");
import("dispatch.{Dispatcher,PrefixMatcher,forward}");
import("sqlbase.sqlobj");
+import("plugins.urlIndexer.controllers.urlBrowser");
+
+function handlePath() {
+ return [[PrefixMatcher('/ep/url'), forward(urlBrowser)]];
+}
REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/;
REGEX_URLCHAR = new RegExp('('+/[-:@a-zA-Z0-9_.,~%+\/\\?=&#;()$]/.source+'|'+REGEX_WORDCHAR.source+')');
diff --git a/etherpad/src/plugins/urlIndexer/main.js b/etherpad/src/plugins/urlIndexer/main.js
index 79bb019..0b2847f 100644
--- a/etherpad/src/plugins/urlIndexer/main.js
+++ b/etherpad/src/plugins/urlIndexer/main.js
@@ -4,9 +4,10 @@ import("sqlbase.sqlobj");
import("sqlbase.sqlcommon");
function init() {
- this.hooks = ['padModelWriteToDB'];
+ this.hooks = ['padModelWriteToDB', 'handlePath'];
this.description = 'Indexes URLs linked to in pads so that they can be displayed outside pads, searched for etc.';
this.padModelWriteToDB = hooks.padModelWriteToDB;
+ this.handlePath = hooks.handlePath;
this.install = install;
this.uninstall = uninstall;
diff --git a/etherpad/src/plugins/urlIndexer/templates/urlBrowser.ejs b/etherpad/src/plugins/urlIndexer/templates/urlBrowser.ejs
new file mode 100644
index 0000000..a254dc1
--- /dev/null
+++ b/etherpad/src/plugins/urlIndexer/templates/urlBrowser.ejs
@@ -0,0 +1,53 @@
+<% /*
+Copyright 2009 Google Inc.
+Copyright 2010 Pita, Peter Martischka <petermartischka@googlemail.com>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS-IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License. */ %>
+<%
+ template.inherit('tagBrowser.ejs');
+ helpers.setHtmlTitle("EtherPad: Browse URLs by tags");
+ helpers.includeCss("plugins/twitterStyleTags/tagBrowser.css");
+ helpers.includeCss("plugins/twitterStyleTags/pad.css");
+ helpers.addToHead('\n<link rel="alternate" href="/ep/url/?query=' + tagQuery.tagsToQuery(tags, antiTags) + '&format=rss" type="application/rss+xml" title="Query results as RSS" />\n');
+
+ function inArray(item, arr) {
+ for (var i = 0; i < arr.length; i++)
+ if (arr[i] == item)
+ return true;
+ return false;
+ }
+%>
+
+<% template.define('docBarTitle', function() { var ejs_data=''; %>
+ <td id="docbarpadtitle"><span>Browse URLs by tags</span></td>
+<% return ejs_data; }); %>
+
+<% template.define('queryResult', function() { var ejs_data=''; %>
+ <% for (i = 0; i < matchingUrls.length; i++) { %>
+ <%
+ var matchingPadId = matchingUrls[i].ID;
+ var matchingPadUrl = matchingPadId;
+ if (!inArray('writable', matchingUrls[i].TAGS)) {
+ matchingPadId = padIdToReadonly(matchingUrls[i].ID);
+ matchingPadUrl = 'ep/pad/view/' + matchingPadId + '/latest';
+ }
+ %>
+ <dt><a href="<%= matchingUrls[i].URL %>"><%= matchingUrls[i].URL %></a><dt>
+ <dd>
+ <a href="<%= matchingPadUrl %>"><%= matchingPadId %></a>:
+ <% for (j = 0; j < matchingUrls[i].TAGS.length; j++) { %>
+ <a href="/ep/url/?query=<%= tagQuery.tagsToQuery(tags.concat([matchingUrls[i].TAGS[j]]), antiTags) %>" class="padtag" title="<%= matchingUrls[i].TAGS[j] %> matches">#<%= matchingUrls[i].TAGS[j] %></a>
+ <% } %>
+ </dd>
+ <% } %>
+<% return ejs_data; }); %>