You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@community.apache.org by hu...@apache.org on 2016/02/07 16:33:01 UTC
svn commit: r1728977 - in /comdev/helpwanted.apache.org/site: ./ admin/ css/
js/ lib/
Author: humbedooh
Date: Sun Feb 7 15:33:01 2016
New Revision: 1728977
URL: http://svn.apache.org/viewvc?rev=1728977&view=rev
Log:
Add initial PoC code for helpwanted.apache.org, a simple task directory for Apache projects.
See https://helpwanted.apache.org/
Added:
comdev/helpwanted.apache.org/site/
comdev/helpwanted.apache.org/site/admin/
comdev/helpwanted.apache.org/site/admin/close.lua
comdev/helpwanted.apache.org/site/admin/elastic.lua
comdev/helpwanted.apache.org/site/admin/index.html
comdev/helpwanted.apache.org/site/admin/newtask.lua
comdev/helpwanted.apache.org/site/css/
comdev/helpwanted.apache.org/site/css/hw.css
comdev/helpwanted.apache.org/site/css/hw2.css
comdev/helpwanted.apache.org/site/favicon.ico (with props)
comdev/helpwanted.apache.org/site/index.html
comdev/helpwanted.apache.org/site/js/
comdev/helpwanted.apache.org/site/js/hw.js
comdev/helpwanted.apache.org/site/lib/
comdev/helpwanted.apache.org/site/lib/elastic.lua
comdev/helpwanted.apache.org/site/listitems.lua
comdev/helpwanted.apache.org/site/task.html
comdev/helpwanted.apache.org/site/widget.js
comdev/helpwanted.apache.org/site/wtest.html
Added: comdev/helpwanted.apache.org/site/admin/close.lua
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/admin/close.lua?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/admin/close.lua (added)
+++ comdev/helpwanted.apache.org/site/admin/close.lua Sun Feb 7 15:33:01 2016
@@ -0,0 +1,42 @@
+--[[
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+]]--
+
+local JSON = require 'cjson'
+local elastic = require 'elastic'
+
+function handle(r)
+ r.content_type = "text/html"
+ local t = {}
+ local now = r:clock()
+ local tnow = now
+ local get = r:parseargs()
+ local id = get.id
+ local doc = elastic.get('item', id)
+ if doc then
+ if get.reopen then
+ elastic.update('item', id, { closed = false })
+ r:puts("Task reopened!")
+ else
+ elastic.update('item', id, { closed = true })
+ r:puts("Task closed!")
+ end
+ else
+ r:puts("No such task :(")
+ end
+ return apache2.OK
+end
\ No newline at end of file
Added: comdev/helpwanted.apache.org/site/admin/elastic.lua
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/admin/elastic.lua?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/admin/elastic.lua (added)
+++ comdev/helpwanted.apache.org/site/admin/elastic.lua Sun Feb 7 15:33:01 2016
@@ -0,0 +1,148 @@
+--[[
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+]]--
+
+-- This is elastic.lua - ElasticSearch library
+
+local http = require 'socket.http'
+local JSON = require 'cjson'
+local config = {
+ es_url = "http://localhost:9200/helpwanted/",
+ maxResults = 100
+}
+local default_doc = "item"
+
+-- Standard ES query, returns $size results of any doc of type $doc, sorting by $sitem
+function getHits(query, size, doc, sitem)
+ doc = doc or "mbox"
+ sitem = sitem or "epoch"
+ size = size or 10
+ query = query:gsub(" ", "+")
+ local url = config.es_url .. doc .. "/_search?q="..query.."&sort=" .. sitem .. ":desc&size=" .. size
+ local result = http.request(url)
+ local out = {}
+ local json = JSON.decode(result)
+ local out = {}
+ if json and json.hits and json.hits.hits then
+ for k, v in pairs(json.hits.hits) do
+ v._source.request_id = v._id
+ table.insert(out, v._source)
+ end
+ end
+ return out
+end
+
+-- Get a single document
+function getDoc (ty, id)
+ local url = config.es_url .. ty .. "/" .. id
+ local result = http.request(url)
+ local out = {}
+ local json = JSON.decode(result)
+ if json and json._source then
+ json._source.request_id = json._id
+ end
+ return (json and json._source) and json._source or {}
+end
+
+-- Get results (a'la getHits), but only return email headers, not the body
+-- provides faster transport when we don't need everything
+function getHeaders(query, size, doc)
+ doc = doc or "mbox"
+ size = size or 10
+ query = query:gsub(" ", "+")
+ local url = config.es_url .. doc .. "/_search?_source_exclude=body&q="..query.."&sort=date:desc&size=" .. size
+ local result = http.request(url)
+ local out = {}
+ local json = JSON.decode(result)
+ local out = {}
+ if json and json.hits and json.hits.hits then
+ for k, v in pairs(json.hits.hits) do
+ v._source.request_id = v._id
+ table.insert(out, v._source)
+ end
+ end
+ return out
+end
+
+-- Same as above, but reverse return order
+function getHeadersReverse(query, size, doc)
+ doc = doc or "mbox"
+ size = size or 10
+ query = query:gsub(" ", "+")
+ local url = config.es_url .. doc .. "/_search?_source_exclude=body&q="..query.."&sort=epoch:desc&size=" .. size
+ local result = http.request(url)
+ local out = {}
+ local json = JSON.decode(result)
+ local out = {}
+ if json and json.hits and json.hits.hits then
+ for k, v in pairs(json.hits.hits) do
+ v._source.request_id = v._id
+ table.insert(out, 1, v._source)
+ end
+ end
+ return out
+end
+
+-- Do a raw ES query with a JSON query
+function raw(query, doctype)
+ local js = JSON.encode(query)
+ doctype = doctype or default_doc
+ local url = config.es_url .. doctype .. "/_search"
+ local result = http.request(url, js)
+ local out = {}
+ local json = JSON.decode(result)
+ return json or {}, url
+end
+
+-- Update a document
+function update(doctype, id, query)
+ local js = JSON.encode({doc = query })
+ doctype = doctype or default_doc
+ local url = config.es_url .. doctype .. "/" .. id .. "/_update"
+ local result = http.request(url, js)
+ local out = {}
+ local json = JSON.decode(result)
+ return json or {}, url
+end
+
+-- Put a new document somewhere
+function index(r, id, ty, body)
+ local js = JSON.encode(query)
+ if not id then
+ id = r:sha1(ty .. (math.random(1,99999999)*os.time()) .. ':' .. r:clock())
+ end
+ local url = config.es_url .. ty .. "/" .. id
+ local result = http.request(url, body)
+ local out = {}
+ local json = JSON.decode(result)
+ return json or {}
+end
+
+function setDefault(typ)
+ default_doc = typ
+end
+
+-- module defs
+return {
+ find = getHits,
+ findFast = getHeaders,
+ findFastReverse = getHeadersReverse,
+ get = getDoc,
+ raw = raw,
+ index = index,
+ default = setDefault,
+ update = update
+}
Added: comdev/helpwanted.apache.org/site/admin/index.html
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/admin/index.html?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/admin/index.html (added)
+++ comdev/helpwanted.apache.org/site/admin/index.html Sun Feb 7 15:33:01 2016
@@ -0,0 +1,62 @@
+ <!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf8">
+<link rel="stylesheet" href="/css/hw.css">
+<link rel="stylesheet" href="/css/hw2.css">
+<script src="/js/hw.js" type="text/javascript"></script>
+<title>Help Wanted!</title>
+
+</head>
+<body onload="populateAdminForm(); fetchItemsAdmin();">
+
+<div style="text-align: center;">
+ <h2><img src='/images/logo.png' title="Help Wanted!"/></h2>
+</div>
+
+<div id="innerpicker">
+ <form action="newtask.lua" method="post">
+ <h3>Create a new task:</h3>
+ <b>Project:</b> <select name="project" id="project"></select><br/>
+ <b>Task type:</b>
+ <select name="type">
+ <option value="programming">Programming task</option>
+ <option value="web design">Web design task</option>
+ <option value="documentation">Documentation task</option>
+ <option value="marketing">Marketing task</option>
+ <option value="community">Community task</option>
+ </select><br/>
+ <b>Title: </b> <input type="text" name="title"/><br/>
+ <b>Languages (optional): </b>
+ <select name="languages" id="languages" multiple="multiple" size="5">
+
+ </select>
+ <br/>
+ <b>Difficulty:</b>
+ <select name="difficulty">
+ <option value="0">Beginner</option>
+ <option value="1">Journeyman</option>
+ <option value="2">Intermediate</option>
+ <option value="3">Advanced</option>
+ <option value="4">Expert</option>
+ </select>
+ <br/>
+ <b>Description:</b>
+ <textarea name="description" placeholder="Description goes here..." style="width: 500px; height: 200px;"></textarea><br/>
+ <b>Additional info URL: </b> <input type="text" name="url"/><br/>
+ <b>Collaborative?: </b> <input type="checkbox" name="collaboration" value="yes"/><br/>
+ <input type="submit" value="Save task"/>
+ </form>
+</div>
+
+<div id="hwitems" class="hwitems">
+
+</div>
+
+<p style="font-size: 12px; font-style: italic; text-align: center;">
+ Managed by the <a href="https://community.apache.org/">Apache Community Development Project</a>.
+ Copyright 2016, the Apache Software Foundation.
+ Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0</a>
+</p>
+</body>
+</html>
\ No newline at end of file
Added: comdev/helpwanted.apache.org/site/admin/newtask.lua
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/admin/newtask.lua?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/admin/newtask.lua (added)
+++ comdev/helpwanted.apache.org/site/admin/newtask.lua Sun Feb 7 15:33:01 2016
@@ -0,0 +1,61 @@
+--[[
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+]]--
+
+local JSON = require 'cjson'
+local elastic = require 'elastic'
+
+function handle(r)
+ r.content_type = "text/html"
+ local t = {}
+ local now = r:clock()
+ local tnow = now
+ local get = r:parseargs()
+ local post, postm = r:parsebody()
+
+ local project = r:escape_html(post.project or "")
+ local typ = r:escape_html(post.type)
+ local title = r:escape_html(post.title)
+ local lingos = r:escape_html(table.concat(postm.languages or {'n/a'}, ","))
+ local difficulty = tonumber(post.difficulty) or 0
+ local desc = r:escape_html(post.description)
+ local url = r:escape_html(post.url)
+ local collab = (post.collaboration and post.collaboration == 'yes') and true or false
+
+
+ if project and #project > 2 and typ and title and lingos and difficulty and desc then
+ elastic.index(r, nil, 'item', JSON.encode{
+ project = project,
+ ['type'] = typ,
+ languages = lingos,
+ title = title,
+ difficulty = difficulty,
+ description = desc,
+ url = url,
+ collaboration = collab,
+ created = os.time(),
+ author = r.user or "unknown",
+ estimate = 0,
+ timeout = 0,
+ }
+ )
+ r:puts("Task saved!")
+ else
+ r:puts("Something was missing, go back!")
+ end
+ return apache2.OK
+end
Added: comdev/helpwanted.apache.org/site/css/hw.css
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/css/hw.css?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/css/hw.css (added)
+++ comdev/helpwanted.apache.org/site/css/hw.css Sun Feb 7 15:33:01 2016
@@ -0,0 +1,42 @@
+.itemNumber-yellow {
+ background: linear-gradient(to bottom, #e8cc43 0%,#cc9004 100%);
+ border-radius: 12px;
+ border: 3px solid #FFF;
+ color: #FFF;
+ box-shadow: 0px 2px 2px 0px rgba(153,153,153,1);
+ width: 20px;
+ float: left;
+ text-align: center;
+ font-family: sans-serif;
+ margin-right: 8px;
+ height: 16px;
+ font-size: 12px;
+ margin-bottom: 4px;
+ padding-top: 3px;
+ position: relative;
+ top: 0px;
+ left: 0px;
+}
+
+#picker {
+ border: 1px solid #666;
+ border-radius: 8px;
+ background: #EEE;
+}
+
+.hwitems {
+
+ margin: 0 auto;
+ width: 1000px;
+ padding: 5px;
+ text-align: center;
+}
+
+.details {
+ border: 1px solid #666;
+ border-radius: 5px;
+ background: #FFE;
+ margin: 10px;
+ padding: 5px;
+ font-size: 10pt;
+}
\ No newline at end of file
Added: comdev/helpwanted.apache.org/site/css/hw2.css
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/css/hw2.css?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/css/hw2.css (added)
+++ comdev/helpwanted.apache.org/site/css/hw2.css Sun Feb 7 15:33:01 2016
@@ -0,0 +1,295 @@
+
+
+.stepbutton {
+ text-align: center;
+ background: linear-gradient(to bottom, rgba(183,222,237,1) 0%,rgba(113,206,239,1) 50%,rgba(33,180,226,1) 51%,rgba(183,222,237,1) 100%);
+ border-radius: 15px;
+ padding: 10px 10px;
+ display: block;
+ float: left;
+ margin: 0 auto;
+ margin-right: 30px;
+ font-family: arial;
+ font-weight: bold;
+ color:#333;
+ text-decoration: none;
+ cursor: pointer;
+ border:1px solid #a7a7a7;
+ box-shadow: 0px 2px 1px white inset, 0px -2px 8px white, 0px 2px 5px rgba(0, 0, 0, 0.1), 0px 8px 10px rgba(0, 0, 0, 0.1);
+}
+
+.finishbutton {
+ text-align: center;
+ background: linear-gradient(to bottom, rgba(157,213,58,1) 0%,rgba(161,213,79,1) 50%,rgba(128,194,23,1) 51%,rgba(124,188,10,1) 100%);
+ border-radius: 15px;
+ padding: 10px 10px;
+ display: block;
+ margin: 0 auto;
+ font-family: arial;
+ font-weight: bold;
+ color:#333;
+ text-decoration: none;
+ cursor: pointer;
+ border:1px solid #a7a7a7;
+ box-shadow: 0px 2px 1px white inset, 0px -2px 8px white, 0px 2px 5px rgba(0, 0, 0, 0.1), 0px 8px 10px rgba(0, 0, 0, 0.1);
+}
+
+.dibbutton {
+ height: 24px;
+ text-align: center;
+ background: linear-gradient(to bottom, rgba(109,179,242,1) 0%,rgba(84,163,238,1) 50%,rgba(54,144,240,1) 51%,rgba(30,105,222,1) 100%);
+ border-radius: 8px;
+ padding: 2px 5px;
+ display: block;
+ margin: 10px auto;
+ font-size: 9pt;
+ font-family: arial;
+ font-weight: bold;
+ color:#EEE;
+ text-decoration: none;
+ cursor: pointer;
+ border:1px solid #a7a7a7;
+ box-shadow: 0px 2px 1px white inset, 0px -2px 8px white, 0px 2px 5px rgba(0, 0, 0, 0.1), 0px 8px 10px rgba(0, 0, 0, 0.1);
+}
+
+
+
+.infobox {
+
+ background-repeat: no-repeat;
+ background: linear-gradient(to bottom, rgba(135,224,253,1) 0%,rgba(83,203,241,1) 40%,rgba(5,171,224,1) 100%);
+ width: 600px;
+ min-height: 70px;
+ padding: 5px;
+ border: 1px solid #083051;
+}
+
+ul {
+ margin: 0px;
+ font-size: 0;
+}
+
+li {
+ font-size: 12px;
+ margin: 0;
+ padding: 0.2em;
+}
+
+
+
+
+.hwitems table a:link {
+ color: #666;
+ font-weight: bold;
+ text-decoration:none;
+}
+.hwitems table a:visited {
+ color: #999999;
+ font-weight:bold;
+ text-decoration:none;
+}
+.hwitems table a:active,
+.hwitems table a:hover {
+ color: #bd5a35;
+ text-decoration:underline;
+}
+.hwitems table, .cs {
+ font-family:Arial, Helvetica, sans-serif;
+ color:#666;
+ font-size:12px;
+ text-shadow: 1px 1px 0px #fff;
+ background:#eaebec;
+ margin:20px;
+ border:#ccc 1px solid;
+
+ -moz-border-radius:3px;
+ -webkit-border-radius:3px;
+ border-radius:3px;
+
+ -moz-box-shadow: 0 1px 2px #d1d1d1;
+ -webkit-box-shadow: 0 1px 2px #d1d1d1;
+ box-shadow: 0 1px 2px #d1d1d1;
+}
+
+#innerpicker {
+ text-align: left;
+ font-family:Arial, Helvetica, sans-serif;
+ color:#666;
+ font-size:12px;
+ text-shadow: 1px 1px 0px #fff;
+ background:#fafbfc;
+ border:#ccc 1px solid;
+ width: 600px;
+ min-height: 300px;
+ padding: 5px;
+ margin: 0 auto;
+ -moz-border-radius:3px;
+ -webkit-border-radius:3px;
+ border-radius:3px;
+
+ -moz-box-shadow: 0 1px 2px #d1d1d1;
+ -webkit-box-shadow: 0 1px 2px #d1d1d1;
+ box-shadow: 0 1px 2px #d1d1d1;
+}
+.hwitems table th {
+ padding:21px 25px 22px 25px;
+ border-top:1px solid #fafafa;
+ border-bottom:1px solid #e0e0e0;
+
+ background: #ededed;
+ background: -webkit-gradient(linear, left top, left bottom, from(#ededed), to(#ebebeb));
+ background: -moz-linear-gradient(top, #ededed, #ebebeb);
+}
+.hwitems table th:first-child {
+ text-align: left;
+ padding-left:20px;
+}
+.hwitems table tr:first-child th:first-child {
+ -moz-border-radius-topleft:3px;
+ -webkit-border-top-left-radius:3px;
+ border-top-left-radius:3px;
+}
+.hwitems table tr:first-child th:last-child {
+ -moz-border-radius-topright:3px;
+ -webkit-border-top-right-radius:3px;
+ border-top-right-radius:3px;
+}
+.hwitems table tr {
+ text-align: center;
+ padding-left:20px;
+}
+.hwitems table td:first-child {
+ text-align: left;
+ padding-left:20px;
+ border-left: 0;
+}
+
+.hwitems table td:last-child {
+ text-align: left;
+}
+
+.hwitems table td {
+ padding:12px;
+ border-top: 1px solid #ffffff;
+ border-bottom:1px solid #e0e0e0;
+ border-left: 1px solid #e0e0e0;
+
+ background: #fafafa;
+ background: -webkit-gradient(linear, left top, left bottom, from(#fbfbfb), to(#fafafa));
+ background: -moz-linear-gradient(top, #fbfbfb, #fafafa);
+
+}
+.hwitems table tr.even td {
+ background: #f6f6f6;
+ background: -webkit-gradient(linear, left top, left bottom, from(#f8f8f8), to(#f6f6f6));
+ background: -moz-linear-gradient(top, #f8f8f8, #f6f6f6);
+}
+.hwitems table tr:last-child td {
+ border-bottom:0;
+}
+.hwitems table tr:last-child td:first-child {
+ -moz-border-radius-bottomleft:3px;
+ -webkit-border-bottom-left-radius:3px;
+ border-bottom-left-radius:3px;
+}
+.hwitems table tr:last-child td:last-child {
+ -moz-border-radius-bottomright:3px;
+ -webkit-border-bottom-right-radius:3px;
+ border-bottom-right-radius:3px;
+}
+.hwitems table tr:hover td {
+ background: #f2f2f2;
+ background: -webkit-gradient(linear, left top, left bottom, from(#f2f2f2), to(#f0f0f0));
+ background: -moz-linear-gradient(top, #f2f2f2, #f0f0f0);
+}
+
+
+ .hwwidget table th {
+ padding:4px 5px 4px 5px;
+ border-top:1px solid #fafafa;
+ border-bottom:1px solid #e0e0e0;
+
+ background: #ededed;
+ background: -webkit-gradient(linear, left top, left bottom, from(#ededed), to(#ebebeb));
+ background: -moz-linear-gradient(top, #ededed, #ebebeb);
+}
+ .hwwidget table th:first-child {
+ text-align: left;
+ padding-left:3px;
+}
+ .hwwidget table tr:first-child th:first-child {
+ -moz-border-radius-topleft:3px;
+ -webkit-border-top-left-radius:3px;
+ border-top-left-radius:3px;
+}
+ .hwwidget table tr:first-child th:last-child {
+ -moz-border-radius-topright:3px;
+ -webkit-border-top-right-radius:3px;
+ border-top-right-radius:3px;
+}
+ .hwwidget table tr {
+ text-align: center;
+ padding-left:3px;
+}
+ .hwwidget table td:first-child {
+ text-align: left;
+ padding-left:3px;
+ border-left: 0;
+}
+
+ .hwwidget table td:last-child {
+ text-align: left;
+}
+
+ .hwwidget table td {
+ padding:2px;
+ border-top: 1px solid #ffffff;
+ border-bottom:1px solid #e0e0e0;
+ border-left: 1px solid #e0e0e0;
+
+ background: #fafafa;
+ background: -webkit-gradient(linear, left top, left bottom, from(#fbfbfb), to(#fafafa));
+ background: -moz-linear-gradient(top, #fbfbfb, #fafafa);
+
+}
+
+
+
+#step_menu { margin:0 auto; padding:5px; display:inline-table; list-style:none;text-shadow: none; }
+#step_menu li{ display:inline; float:left; background:url(/images/steps.png) no-repeat -50px bottom; height:41px; line-height:41px; font-size:11px; padding:0 30px 0 25px; position:relative;}
+#step_menu li span{ margin:0px; z-index:2000; background:url(/images/steps.png) no-repeat left bottom; display:block; position:absolute; height:41px; line-height:41px; width:13px; top:0; left:-10px; padding:0;}
+#step_menu li.inprogress { background-position:-50px 0px}
+#step_menu li.inprogress span, #step_menu li.lastinprogress span{background-position:left 0px }
+#step_menu li.done {background-position: -50px -41px}
+#step_menu li.done span, #step_menu li.ldone span {background-position:left -41px }
+#step_menu li.first, #step_menu li.done, #step_menu li.inprogress, #step_menu li.ldone, #step_menu li.lastinprogress { font-weight: bold; color:#333;}
+#step_menu li.first {background-position: -20px 0px }
+#step_menu li.fdone { background-position: -20px -41px }
+#step_menu li.last {background-position: right bottom }
+#step_menu li.lastinprogress { background-position: right 0}
+#step_menu li.ldone { background-position: right -41px}
+
+.itemNumber-widget {
+ background: linear-gradient(to bottom, #cce843 0%,#90cc04 100%);
+ border-radius: 12px;
+ border: 2px solid #FFF;
+ color: #FFF;
+ box-shadow: 0px 2px 2px 0px rgba(153,153,153,1);
+ width: 14px;
+ float: left;
+ text-align: center;
+ font-family: sans-serif;
+ margin-right: 7px;
+ height: 12px;
+ font-size: 9px;
+ margin-bottom: 4px;
+ padding-top: 0px;
+ position: relative;
+ top: 0px;
+ left: 0px;
+}
+
+.hwwidget img {
+ vertical-align: middle;
+ margin-right: 5px;
+}
\ No newline at end of file
Added: comdev/helpwanted.apache.org/site/favicon.ico
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/favicon.ico?rev=1728977&view=auto
==============================================================================
Binary file - no diff available.
Propchange: comdev/helpwanted.apache.org/site/favicon.ico
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: comdev/helpwanted.apache.org/site/index.html
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/index.html?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/index.html (added)
+++ comdev/helpwanted.apache.org/site/index.html Sun Feb 7 15:33:01 2016
@@ -0,0 +1,39 @@
+ <!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf8">
+<link rel="stylesheet" href="css/hw.css">
+<link rel="stylesheet" href="css/hw2.css">
+<link rel="shortcut icon" href="/favicon.ico">
+<script src="js/hw.js" type="text/javascript"></script>
+<title>Help Wanted!</title>
+
+</head>
+<body onload="wizard(1);">
+
+<div style="text-align: center;">
+ <p style="text-align: center;">
+ [<a href="/admin/">Edit tasks</a>] - [<a href="/wtest.html">Widget primer</a>]
+ </p>
+ <h2><img src='/images/logo.png' title="Help Wanted!"/></h2>
+ <p>This is in alpha test mode and what not, so...yeah.</p>
+ <p>Projects can now add a <a href='wtest.html'>widget</a> to their web sites with tasks from HW.</p>
+</div>
+
+<div id="pickerparent" style="text-align: center;">
+ <h4>Quickly find something to do:</h4>
+ <div id="innerpicker">
+
+ </div>
+</div>
+<div id="hwitems" class="hwitems">
+
+</div>
+
+<p style="font-size: 12px; font-style: italic; text-align: center;">
+ Managed by the <a href="https://community.apache.org/">Apache Community Development Project</a>.
+ Copyright 2016, the Apache Software Foundation.
+ Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0</a>
+</p>
+</body>
+</html>
\ No newline at end of file
Added: comdev/helpwanted.apache.org/site/js/hw.js
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/js/hw.js?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/js/hw.js (added)
+++ comdev/helpwanted.apache.org/site/js/hw.js Sun Feb 7 15:33:01 2016
@@ -0,0 +1,334 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+*/
+
+var diff = ['Beginner', 'Journeyman', 'Intermediate', 'Advanced', 'Expert']
+var langs = ['c','xml','c++','c-sharp','java','javascript','css','html','perl','ruby','lua','python','go','rust', 'erlang', 'swift', 'groovy', 'haskell']
+var types = ['programming', 'web design', 'marketing', 'documentation', 'community', 'translation']
+var types_long = {
+ programming: "Programming and Development",
+ 'web design': "Web Design",
+ marketing: 'Marketing and Publicity',
+ documentation: 'Documentation and Guides',
+ community: 'Community Outreach',
+ translation: 'Translation'
+}
+
+var spoken_langs = ['english', 'french', 'german', 'spanish', 'russian', 'italian', 'japanese', 'chinese']
+var website_langs = ['css','javascript','html']
+var projects = ['all projects']
+var cjson = {}
+
+langs.sort()
+types.sort()
+
+function getAsyncJSON(theUrl, xstate, callback) {
+ var xmlHttp = null;
+ if (window.XMLHttpRequest) {
+ xmlHttp = new XMLHttpRequest();
+ } else {
+ xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ xmlHttp.open("GET", theUrl, true);
+ xmlHttp.send(null);
+ xmlHttp.onreadystatechange = function(state) {
+
+ if (xmlHttp.readyState == 4 && xmlHttp.status == 200 || xmlHttp.status == 404) {
+ if (callback) {
+ if (xmlHttp.status == 404) {
+ callback({}, xstate);
+ } else {
+ window.setTimeout(callback, 0.05, JSON.parse(xmlHttp.responseText), xstate);
+ }
+ }
+ }
+ }
+}
+
+var wstate = {}
+
+function wizard(step, arg) {
+ var obj = document.getElementById('innerpicker')
+ if (!step) {
+ step = 1
+ }
+ if (step == 1) {
+ wstate = {}
+ obj.innerHTML = "<h2 style='text-align: center;'>What sort of work would you like to do?</h2>"
+ for (var i in types) {
+ obj.innerHTML += "<img style='vertical-align: middle;' src='images/icon_" + types[i].replace(/\s+/g, "") + ".png'/><big> <a href='javascript:void(0);' onclick='wizard(2, \"" + types[i] + "\");'>" + types_long[types[i]] + "</a></big><br/><br/>"
+ }
+ obj.innerHTML += "<br/><a href='javascript:void(0);' onclick='fetchItems();'><big>...Just show me everything</big></a>"
+ }
+ if (step == 2 && arg) {
+ wstate = {
+ type: arg
+ }
+
+ obj.innerHTML = "<h2 style='text-align: center;'>Which languages are you proficient in?</h2>"
+ obj.innerHTML += "<small>You don't need to pick a language, but it will help narrow down the tasks available for you.</small><br/>"
+
+ if (arg == 'programming' || arg == 'documentation') {
+ for (var i in langs) {
+ var div = document.createElement('div')
+ div.style.float = "left"
+ div.style.width = "100px"
+ var cb = document.createElement('input')
+ cb.setAttribute("type", "checkbox")
+ cb.setAttribute("id", "plang_" + langs[i])
+ var lbl = document.createElement('label')
+ lbl.setAttribute("for", "plang_" + langs[i])
+ var txt = document.createTextNode(langs[i])
+ lbl.appendChild(txt)
+ div.appendChild(cb)
+ div.appendChild(lbl)
+ obj.appendChild(div)
+ }
+ obj.appendChild(document.createElement('br'))
+ } else if (arg == 'web design') {
+ for (var i in website_langs) {
+ var div = document.createElement('div')
+ div.style.float = "left"
+ div.style.width = "100px"
+ var cb = document.createElement('input')
+ cb.setAttribute("type", "checkbox")
+ cb.setAttribute("id", "plang_" + website_langs[i])
+ var lbl = document.createElement('label')
+ lbl.setAttribute("for", "plang_" + website_langs[i])
+ var txt = document.createTextNode(website_langs[i])
+ lbl.appendChild(txt)
+ div.appendChild(cb)
+ div.appendChild(lbl)
+ obj.appendChild(div)
+ }
+ obj.appendChild(document.createElement('br'))
+ } else {
+ for (var i in spoken_langs) {
+ var div = document.createElement('div')
+ div.style.float = "left"
+ div.style.width = "100px"
+ var cb = document.createElement('input')
+ cb.setAttribute("type", "checkbox")
+ cb.setAttribute("id", "plang_" + spoken_langs[i])
+ var lbl = document.createElement('label')
+ lbl.setAttribute("for", "plang_" + spoken_langs[i])
+ var txt = document.createTextNode(spoken_langs[i].replace(/^([a-z])/, function(a) { return a.toUpperCase() }))
+ lbl.appendChild(txt)
+ div.appendChild(cb)
+ div.appendChild(lbl)
+ obj.appendChild(div)
+ }
+ obj.appendChild(document.createElement('br'))
+ }
+ obj.innerHTML += '<br/><div style="width: 100%; margin-top: 40px;"><input type="button" class="finishbutton" onclick="doForm()" value="Find me something to do!"/>' +
+ '<a onclick="wizard(1)" href="javascript:void(0);">Back to start</a></div>'
+ }
+}
+
+function populateForm() {
+ // languages
+
+ var f = document.getElementById('plang')
+ for (var i in langs) {
+ var div = document.createElement('div')
+ div.style.float = "left"
+ div.style.width = "100px"
+ var cb = document.createElement('input')
+ cb.setAttribute("type", "checkbox")
+ cb.setAttribute("id", "plang_" + langs[i])
+ var lbl = document.createElement('label')
+ lbl.setAttribute("for", "plang_" + langs[i])
+ var txt = document.createTextNode(langs[i])
+ lbl.appendChild(txt)
+ div.appendChild(cb)
+ div.appendChild(lbl)
+ f.appendChild(div)
+ }
+ f.appendChild(document.createElement('br'))
+
+ // task types
+
+ var f = document.getElementById('ptypes')
+ for (var i in types) {
+ var div = document.createElement('div')
+ div.style.float = "left"
+ div.style.width = "200px"
+ var cb = document.createElement('input')
+ cb.setAttribute("type", "checkbox")
+ cb.setAttribute("id", "ptype_" + types[i])
+ var lbl = document.createElement('label')
+ lbl.setAttribute("for", "ptype_" + types[i])
+ var txt = document.createTextNode(types[i])
+ lbl.appendChild(txt)
+ div.appendChild(cb)
+ div.appendChild(lbl)
+ f.appendChild(div)
+ }
+ f.appendChild(document.createElement('br'))
+
+ // projects - none for now
+ var f = document.getElementById('pprojects')
+ f.appendChild(document.createTextNode('All projects'))
+}
+
+function doForm() {
+ var l = []
+ var t = []
+ var p = []
+ for (var i in langs) {
+ if (document.getElementById("plang_" + langs[i]) && document.getElementById("plang_" + langs[i]).checked) {
+ l.push(langs[i])
+ }
+ }
+ for (var i in types) {
+ if (document.getElementById("ptype_" + types[i]) && document.getElementById("ptype_" + types[i]).checked) {
+ t.push(types[i])
+ }
+ }
+ if (wstate.type) {
+ t = [wstate.type]
+ }
+ if (wstate.projects) {
+ p = wstate.projects
+ }
+ fetchItems(l, t, p)
+}
+
+function sw(id) {
+ var obj = document.getElementById(id)
+ var op = obj.style.display == 'none' ? 'table-row' : 'none'
+ obj.style.display = op
+}
+
+function reallyPopulate(json) {
+ var pro = []
+ var obj = document.getElementById('project')
+ for (var i in json.committees) {
+ pro.push(i)
+ var opt = document.createElement('option')
+ opt.text = i
+ opt.setAttribute("value", i)
+ obj.appendChild(opt)
+ }
+
+ var obj = document.getElementById('languages')
+ for (var i in langs) {
+ var opt = document.createElement('option')
+ opt.text = langs[i]
+ opt.setAttribute("value", langs[i])
+ obj.appendChild(opt)
+ }
+
+ for (var i in spoken_langs) {
+ var opt = document.createElement('option')
+ opt.text = spoken_langs[i].replace(/^([a-z])/, function(a) {return a.toUpperCase()})
+ opt.setAttribute("value", spoken_langs[i])
+ obj.appendChild(opt)
+ }
+}
+
+function populateAdminForm() {
+ getAsyncJSON('https://whimsy.apache.org/public/public_ldap_committees.json', null, reallyPopulate)
+}
+
+function displayItems(json, state) {
+ cjson = json
+ var numItems = 0
+ for (var i in json) {
+ var item = json[i]
+ if (item.closed) {
+ continue
+ }
+ numItems++
+ }
+ var obj = document.getElementById('hwitems')
+
+ if (typeof(numItems) === 'undefined') {
+ obj.innerHTML = "Sorry, we couldn't find any tasks matching your criteria"
+ return
+ }
+
+ obj.innerHTML = "Found " + numItems + " item" + (numItems != 1 ? "s" : "") + ":<br/>"
+ var tbl = "<table style='text-align: left;'><tr><th></th><th>Project</th><th>Title</th><th>Languages</th><th>Difficulty</th><th>Created</th></tr>"
+ for (var i in json) {
+ var item = json[i]
+ if (item.closed) {
+ continue
+ }
+ var z = parseInt(i)+1
+ var ptype = item.type.replace(/\s+/g, "")
+ var cdate = new Date(item.created*1000).toLocaleString()
+ var lingos = (item.languages != 'n/a') ? "(" + item.languages + ") " : ""
+
+ // admin stuff
+ var add = ""
+ if (state.admin) {
+ add = " <a href='/admin/close.lua?id=" + item.request_id + "'>Mark as done</a>"
+ }
+
+ tbl += "<tr style='cursor: pointer;' onclick=\"sw('details_" + i + "');\"><td><div class='itemNumber-yellow'>" + z + "</div><img title='" + item.type + "' style='float: left;' src='/images/icon_" + ptype + ".png'/></td>" +
+ "<td>" + item.project + "</td>"+
+ "<td style='text-align: left;'>" + item.title + "</td>" +
+ "<td>" + lingos + "</td><td style='text-align: left;'><img src='/images/level_" + (parseInt(item.difficulty)+1) + ".png'/> " + diff[item.difficulty] + add + "</td><td>" + cdate + "</td></tr>"
+
+ tbl += "<tr style='display:none;' id='details_" + i + "'><td colspan='6'><b>Project:</b> " + item.project + "<br/><b>Requested by:</b> " + item.author + "@apache.org<br/><b>Created:</b> " + cdate + "<br/><b>Description:</b> <blockquote>" + item.description + "</blockquote><b>Further information: </b> <a href='" + item.url + "'>" + item.url + "</a><br/><input type='button' onclick='location.href=\"https://helpwanted.apache.org/task.html?" + item.request_id +"\";' value='I am interested in this'/></td></tr>"
+
+ }
+ tbl += "</table>"
+ obj.innerHTML += tbl
+}
+
+function fetchItems(languages, types, projects, sortBy) {
+ if (!languages) languages = []
+ if (!types) types = []
+ if (!projects) projects = []
+ getAsyncJSON("/listitems.lua?lang=" + languages.join(",") + "&type=" + types.join(",") +"&project=" + projects.join(","),
+ {
+ languages: languages,
+ types: types,
+ projects: projects,
+ sortBy: sortBy
+ }, displayItems)
+}
+
+
+function fetchItemsAdmin() {
+ getAsyncJSON("/listitems.lua", {admin: true}, displayItems)
+}
+
+function renderItem(json, state) {
+ var obj = document.getElementById('item')
+ var cdate = new Date(json.created*1000).toDateString()
+ obj.innerHTML = "<h2>Item #" + state + ": <span style='color: #369;'>" + json.title + "</span></h2>"
+ obj.innerHTML += "<p style='text-align: left;'><b>Project: </b> " + json.project + "<br/>" +
+ "<b>Created by:</b> " + json.author + "@apache.org<br/>" +
+ "<b>Task added: </b>" + cdate + "<br/>" +
+ "<b>Difficulty: </b> <img style='width: 16px; height: 16px; vertical-align: middle;' src='/images/level_" + (parseInt(json.difficulty)+1) + ".png'/> " + diff[json.difficulty] + "<br/>" +
+ "<b>Task type:</b> " + types_long[json.type] + "<br/>" +
+ "<b>Additional information:</b> <a href='" + json.url + "'>" + json.url + "</a><br/>" +
+ ((json.estimate && json.estimate.length > 0) ? "<b>Estimated time to complete:</b> " + json.estimate : "") +
+ ((json.timeout && json.timeout > 0) ? "<b>Task expires:</b> " + new Date(json.timeout*1000).toDateString() : "") +
+ "<blockquote style='text-align: left;'><q>" + json.description + "</q></blockquote>" +
+ "<br/></p>" +
+ "<h3 style='text-align: left;'>How to help:</h3><p style='text-align: left;'>" +
+ "If you want to help with this task, please get in touch with the project at: dev@" + json.project + ".apache.org!" +
+ "<br/>You should also check out the additional information URL (if such is provided above) for more information."
+ "<br/> <br/> <br/></p>"
+}
+
+function displayItem(id) {
+ getAsyncJSON("/listitems.lua?id=" + id, id, renderItem)
+}
\ No newline at end of file
Added: comdev/helpwanted.apache.org/site/lib/elastic.lua
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/lib/elastic.lua?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/lib/elastic.lua (added)
+++ comdev/helpwanted.apache.org/site/lib/elastic.lua Sun Feb 7 15:33:01 2016
@@ -0,0 +1,148 @@
+--[[
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+]]--
+
+-- This is elastic.lua - ElasticSearch library
+
+local http = require 'socket.http'
+local JSON = require 'cjson'
+local config = {
+ es_url = "http://localhost:9200/helpwanted/",
+ maxResults = 100
+}
+local default_doc = "item"
+
+-- Standard ES query, returns $size results of any doc of type $doc, sorting by $sitem
+function getHits(query, size, doc, sitem)
+ doc = doc or "mbox"
+ sitem = sitem or "epoch"
+ size = size or 10
+ query = query:gsub(" ", "+")
+ local url = config.es_url .. doc .. "/_search?q="..query.."&sort=" .. sitem .. ":desc&size=" .. size
+ local result = http.request(url)
+ local out = {}
+ local json = JSON.decode(result)
+ local out = {}
+ if json and json.hits and json.hits.hits then
+ for k, v in pairs(json.hits.hits) do
+ v._source.request_id = v._id
+ table.insert(out, v._source)
+ end
+ end
+ return out
+end
+
+-- Get a single document
+function getDoc (ty, id)
+ local url = config.es_url .. ty .. "/" .. id
+ local result = http.request(url)
+ local out = {}
+ local json = JSON.decode(result)
+ if json and json._source then
+ json._source.request_id = json._id
+ end
+ return (json and json._source) and json._source or {}
+end
+
+-- Get results (a'la getHits), but only return email headers, not the body
+-- provides faster transport when we don't need everything
+function getHeaders(query, size, doc)
+ doc = doc or "mbox"
+ size = size or 10
+ query = query:gsub(" ", "+")
+ local url = config.es_url .. doc .. "/_search?_source_exclude=body&q="..query.."&sort=date:desc&size=" .. size
+ local result = http.request(url)
+ local out = {}
+ local json = JSON.decode(result)
+ local out = {}
+ if json and json.hits and json.hits.hits then
+ for k, v in pairs(json.hits.hits) do
+ v._source.request_id = v._id
+ table.insert(out, v._source)
+ end
+ end
+ return out
+end
+
+-- Same as above, but reverse return order
+function getHeadersReverse(query, size, doc)
+ doc = doc or "mbox"
+ size = size or 10
+ query = query:gsub(" ", "+")
+ local url = config.es_url .. doc .. "/_search?_source_exclude=body&q="..query.."&sort=epoch:desc&size=" .. size
+ local result = http.request(url)
+ local out = {}
+ local json = JSON.decode(result)
+ local out = {}
+ if json and json.hits and json.hits.hits then
+ for k, v in pairs(json.hits.hits) do
+ v._source.request_id = v._id
+ table.insert(out, 1, v._source)
+ end
+ end
+ return out
+end
+
+-- Do a raw ES query with a JSON query
+function raw(query, doctype)
+ local js = JSON.encode(query)
+ doctype = doctype or default_doc
+ local url = config.es_url .. doctype .. "/_search"
+ local result = http.request(url, js)
+ local out = {}
+ local json = JSON.decode(result)
+ return json or {}, url
+end
+
+-- Update a document
+function update(doctype, id, query)
+ local js = JSON.encode({doc = query })
+ doctype = doctype or default_doc
+ local url = config.es_url .. doctype .. "/" .. id .. "/_update"
+ local result = http.request(url, js)
+ local out = {}
+ local json = JSON.decode(result)
+ return json or {}, url
+end
+
+-- Put a new document somewhere
+function index(r, id, ty, body)
+ local js = JSON.encode(query)
+ if not id then
+ id = r:sha1(ty .. (math.random(1,99999999)*os.time()) .. ':' .. r:clock())
+ end
+ local url = config.es_url .. ty .. "/" .. id
+ local result = http.request(url, body)
+ local out = {}
+ local json = JSON.decode(result)
+ return json or {}
+end
+
+function setDefault(typ)
+ default_doc = typ
+end
+
+-- module defs
+return {
+ find = getHits,
+ findFast = getHeaders,
+ findFastReverse = getHeadersReverse,
+ get = getDoc,
+ raw = raw,
+ index = index,
+ default = setDefault,
+ update = update
+}
Added: comdev/helpwanted.apache.org/site/listitems.lua
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/listitems.lua?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/listitems.lua (added)
+++ comdev/helpwanted.apache.org/site/listitems.lua Sun Feb 7 15:33:01 2016
@@ -0,0 +1,78 @@
+--[[
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+]]--
+
+local JSON = require 'cjson'
+local elastic = require 'lib/elastic'
+
+function handle(r)
+ r.content_type = "application/json"
+ local t = {}
+ local now = r:clock()
+ local tnow = now
+ local get = r:parseargs()
+ local qs = "*"
+ local domain = get.domain or ""
+ if #domain < 2 then
+ domain = "*"
+ end
+ local dd = 14
+ local maxresults = 10000
+ local listdata = {}
+
+ if get.id then
+ local doc = elastic.get('item', get.id)
+ if doc then
+ r:puts(JSON.encode(doc))
+ return apache2.OK
+ end
+ r:puts[[{}]]
+ return apache2.OK
+ end
+
+ -- Languages
+ local lingos = {}
+ for lang in (get.lang or ""):gmatch("([+#A-Za-z0-9+]+)") do
+ table.insert(lingos, lang)
+ end
+
+ -- Types
+ local types = {}
+ for typ in (get.type or ""):gmatch("([+#A-Za-z0-9+]+)") do
+ table.insert(types, typ)
+ end
+
+ -- Projects
+ local projects = {}
+ for project in (get.project or ""):gmatch("([+#A-Za-z0-9+]+)") do
+ table.insert(projects, project)
+ end
+
+ local pl = #projects > 0 and table.concat(projects, " OR ") or "*"
+ local tl = #types > 0 and table.concat(types, " OR ") or "*"
+ local ll = #lingos > 0 and table.concat(lingos, " OR ") or "*"
+
+ local dsl = ("languages:(%s) AND type:(%s) AND project:(%s)"):format(ll, tl,pl)
+
+ local doc = elastic.find(dsl, 200, 'item', 'created')
+ if doc and #doc > 0 then
+ r:puts(JSON.encode(doc))
+ else
+ r:puts[[{}]]
+ end
+ return apache2.OK
+end
Added: comdev/helpwanted.apache.org/site/task.html
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/task.html?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/task.html (added)
+++ comdev/helpwanted.apache.org/site/task.html Sun Feb 7 15:33:01 2016
@@ -0,0 +1,27 @@
+ <!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf8">
+<link rel="stylesheet" href="css/hw.css">
+<link rel="stylesheet" href="css/hw2.css">
+<script src="js/hw.js" type="text/javascript"></script>
+<title>Help Wanted!</title>
+
+</head>
+<body onload="displayItem(document.location.search.substr(1));">
+
+<div style="text-align: center;">
+ <h2><img src='/images/logo.png' title="Help Wanted!"/></h2>
+ <div id="item">
+
+ </div>
+</div>
+
+
+<p style="font-size: 12px; font-style: italic; text-align: center;">
+ Managed by the <a href="https://community.apache.org/">Apache Community Development Project</a>.
+ Copyright 2016, the Apache Software Foundation.
+ Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0</a>
+</p>
+</body>
+</html>
\ No newline at end of file
Added: comdev/helpwanted.apache.org/site/widget.js
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/widget.js?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/widget.js (added)
+++ comdev/helpwanted.apache.org/site/widget.js Sun Feb 7 15:33:01 2016
@@ -0,0 +1,151 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+*/
+var widgetobj = null
+var widgetproject = "???"
+var widgettitle = null
+var hw_json = null
+
+function getAsyncJSON(theUrl, xstate, callback) {
+ var xmlHttp = null;
+ if (window.XMLHttpRequest) {
+ xmlHttp = new XMLHttpRequest();
+ } else {
+ xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ xmlHttp.open("GET", theUrl, true);
+ xmlHttp.send(null);
+ xmlHttp.onreadystatechange = function(state) {
+
+ if (xmlHttp.readyState == 4 && xmlHttp.status == 200 || xmlHttp.status == 404) {
+ if (callback) {
+ if (xmlHttp.status == 404) {
+ callback({}, xstate);
+ } else {
+ window.setTimeout(callback, 0.05, JSON.parse(xmlHttp.responseText), xstate);
+ }
+ }
+ }
+ }
+}
+
+var hw_oldstate = ""
+function displayItemsWidget(json, state) {
+ hw_json = json ? json : hw_json
+ json = hw_json
+ var diff = ['Beginner', 'Journeyman', 'Intermediate', 'Advanced', 'Expert']
+ var numItems = 0
+ for (var i in json) {
+ var item = json[i]
+ if (item.closed) {
+ continue
+ }
+ numItems++
+ }
+ var obj = widgetobj
+ obj.setAttribute("class", "hwitems hwwidget")
+
+ if (state && typeof(state) === "string") {
+ if (hw_oldstate == state) {
+ json.sort(function(a,b) { return a[state] < b[state] })
+ hw_oldstate = ""
+ } else {
+ json.sort(function(a,b) { return a[state] > b[state] })
+ hw_oldstate = state
+ }
+
+ }
+
+ obj.innerHTML = ""
+ var tbl = "<table style='width: 100%; text-align: left;'><tr><td colspan='5' style='text-align: center;'><img src='https://helpwanted.apache.org/images/cube.png'/> Tasks " + widgettitle + " would like help with:</td></tr>" +
+ "<tr style='cursor: pointer' title='Click on a column to sort'><th onclick='displayItemsWidget(null, \"title\");'>Title</th>" +
+ "<th onclick='displayItemsWidget(null, \"languages\");'>Languages</th>" +
+ "<th onclick='displayItemsWidget(null, \"difficulty\");'>Difficulty</th>" +
+ "<th onclick='displayItemsWidget(null, \"created\");'>Created</th></tr>"
+
+ if (typeof(numItems) === 'undefined' || numItems == 0) {
+ obj.innerHTML = tbl + "<tr><td colspan='5'>Sorry, we couldn't find any tasks matching your criteria</td></tr>" +
+ "<tr><td colspan='4' style='text-align: center;'>Powered by <a href='https://helpwanted.apache.org/'>Help Wanted</a> - a task directory for Apache projects</td></tr>" +
+ "</table>"
+ return
+ }
+ for (var i in json) {
+ var item = json[i]
+ if (item.closed) {
+ continue
+ }
+ var z = parseInt(i)+1
+ var ptype = item.type.replace(/\s+/g, "")
+ var cdate = new Date(item.created*1000).toLocaleString()
+ var lingos = (item.languages != 'n/a') ? item.languages : ""
+
+ // admin stuff
+ var add = ""
+ if (state.admin) {
+ add = " <a href='/admin/close.lua?id=" + item.request_id + "'>Mark as done</a>"
+ }
+
+ tbl += "<tr style='cursor: pointer; ' onclick=\"sw('hw_details_" + i + "');\"><td style='text-align: left;'><div class='itemNumber-widget'>" + z + "</div><img title='" + item.type + "' style='width:16px; height: 16px;' float: left;' src='/images/icon_" + ptype + ".png'/>" +
+ item.title + "</td>" +
+ "<td>" + lingos + "</td><td style='text-align: left;'><img style='width:16px; height: 16px;' src='/images/level_" + (parseInt(item.difficulty)+1) + ".png'/> " + diff[item.difficulty] + add + "</td><td>" + cdate + "</td></tr>"
+ var fi = ""
+ if (item.url && item.url.length > 10) {
+ fi = "<b>Further information: </b> <a href='" + item.url + "'>" + item.url + "</a><br/>"
+ }
+
+ tbl += "<tr style='display:none;' id='hw_details_" + i + "'><td colspan='6'><b>Project:</b> " + item.project + "<br/><b>Requested by:</b> " + item.author + "@apache.org<br/><b>Created:</b> " + cdate + "<br/><b>Description:</b> <blockquote>" + item.description + "</blockquote>" + fi + "<input type='button' class='dibbutton' onclick='location.href=\"https://helpwanted.apache.org/task.html?" + item.request_id + "\";' value='I am interested in this'/></td></tr>"
+
+ }
+ tbl += "<tr><td colspan='4' style='text-align: center;'>Powered by <a href='https://helpwanted.apache.org/'>Help Wanted</a> - a task directory for Apache projects</td></tr></table>"
+ obj.innerHTML += tbl
+}
+
+function fetchItemsWidget(languages, types, projects, sortBy) {
+ if (!languages) languages = []
+ if (!types) types = []
+ if (!projects) projects = []
+ getAsyncJSON("https://helpwanted.apache.org/listitems.lua?lang=" + languages.join(",") + "&type=" + types.join(",") +"&project=" + projects.join(","),
+ {
+ languages: languages,
+ types: types,
+ projects: projects,
+ sortBy: sortBy
+ }, displayItemsWidget)
+}
+
+function sw(id) {
+ var obj = document.getElementById(id)
+ var op = obj.style.display == 'none' ? 'table-row' : 'none'
+ obj.style.display = op
+}
+
+var divs = document.getElementsByTagName('div')
+for (var i in divs) {
+ var dt = divs[i].getAttribute("type")
+ var dn = divs[i].getAttribute("project")
+ var dti = divs[i].getAttribute("description")
+ if (dt && dt == "helpwanted" && dn) {
+ widgetobj = divs[i]
+ widgetproject = dn
+ widgettitle = dti ? dti : dn
+ fetchItemsWidget([],[],[dn])
+ var css = document.createElement('link')
+ css.rel = "stylesheet";
+ css.href = "https://helpwanted.apache.org/css/hw2.css";
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(css)
+ break
+ }
+}
\ No newline at end of file
Added: comdev/helpwanted.apache.org/site/wtest.html
URL: http://svn.apache.org/viewvc/comdev/helpwanted.apache.org/site/wtest.html?rev=1728977&view=auto
==============================================================================
--- comdev/helpwanted.apache.org/site/wtest.html (added)
+++ comdev/helpwanted.apache.org/site/wtest.html Sun Feb 7 15:33:01 2016
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf8">
+<title>Help Wanted!</title>
+
+</head>
+<body>
+ <h2><img src='/images/logo.png' title="Help Wanted!"/></h2>
+ <h2>Sample widget page</h2>
+ This is a sample widget page. Just an ordinary HTML page with a widget attached by inserting the following code:
+ <pre style='background: #FFE; border: 1px solid #666;'>
+<div style="width: 700px;" type="helpwanted" project="httpd" description="the Apache HTTP Server"></div>
+<script src="https://helpwanted.apache.org/widget.js" type="text/javascript"></script>
+ </pre>
+ <div style="width: 700px;" type="helpwanted" project="httpd" description="the Apache HTTP Server"></div>
+<script src="https://helpwanted.apache.org/widget.js" type="text/javascript"></script>
+</body>
+</html>