Skip to content

Commit 730f038

Browse files
Bernhard ReiterBernhard Reiter
authored andcommitted
Adding missing files from last commit (of 2010-11-08T11:21:02)...
...for fixing expressing filters for multilinkgs, see issue2550648.
1 parent 2986750 commit 730f038

File tree

2 files changed

+284
-0
lines changed

2 files changed

+284
-0
lines changed

roundup/cgi/KeywordsExpr.py

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# This module is free software, you may redistribute it
2+
# and/or modify under the same terms as Python.
3+
4+
WINDOW_CONTENT = '''\
5+
<h3>Keyword Expression Editor:</h3>
6+
<hr/>
7+
<div id="content"></div>
8+
<script type="text/javascript">
9+
<!--
10+
11+
var NOT_OP = "-2";
12+
var AND_OP = "-3";
13+
var OR_OP = "-4";
14+
15+
var original = "%(original)s";
16+
var current = original;
17+
var undo = [];
18+
19+
var KEYWORDS = [
20+
%(keywords)s
21+
];
22+
23+
function find_keyword(x) {
24+
for (var i = 0; i < KEYWORDS.length; ++i) {
25+
if (KEYWORDS[i][0] == x) {
26+
return KEYWORDS[i][1];
27+
}
28+
}
29+
return "unknown";
30+
}
31+
32+
function Equals(x) {
33+
this.x = x;
34+
this.brackets = false;
35+
36+
this.infix = function() {
37+
return find_keyword(this.x);
38+
}
39+
40+
this.postfix = function() {
41+
return this.x;
42+
}
43+
}
44+
45+
function Not(x) {
46+
this.x = x;
47+
this.brackets = false;
48+
49+
this.infix = function() {
50+
return this.x.brackets
51+
? "NOT(" + this.x.infix() + ")"
52+
: "NOT " + this.x.infix();
53+
}
54+
55+
this.postfix = function() {
56+
return this.x.postfix() + "," + NOT_OP;
57+
}
58+
}
59+
60+
function And(x, y) {
61+
this.x = x;
62+
this.y = y;
63+
this.brackets = true;
64+
65+
this.infix = function() {
66+
var a = this.x.brackets ? "(" + this.x.infix() + ")" : this.x.infix();
67+
var b = this.y.brackets ? "(" + this.y.infix() + ")" : this.y.infix();
68+
return a + " AND " + b;
69+
}
70+
this.postfix = function() {
71+
return this.x.postfix() + "," + this.y.postfix() + "," + AND_OP;
72+
}
73+
}
74+
75+
function Or(x, y) {
76+
this.x = x;
77+
this.y = y;
78+
this.brackets = true;
79+
80+
this.infix = function() {
81+
var a = this.x.brackets ? "(" + this.x.infix() + ")" : this.x.infix();
82+
var b = this.y.brackets ? "(" + this.y.infix() + ")" : this.y.infix();
83+
return a + " OR " + b;
84+
}
85+
86+
this.postfix = function() {
87+
return this.x.postfix() + "," + this.y.postfix() + "," + OR_OP;
88+
}
89+
}
90+
91+
function trim(s) {
92+
return s.replace (/^\s+/, '').replace(/\s+$/, '');
93+
}
94+
95+
function parse(s) {
96+
var operators = s.split(",");
97+
var stack = [];
98+
for (var i = 0; i < operators.length; ++i) {
99+
var operator = trim(operators[i]);
100+
if (operator == "") continue;
101+
if (operator == NOT_OP) {
102+
stack.push(new Not(stack.pop()));
103+
}
104+
else if (operator == AND_OP) {
105+
var a = stack.pop();
106+
var b = stack.pop();
107+
stack.push(new And(b, a));
108+
}
109+
else if (operator == OR_OP) {
110+
var a = stack.pop();
111+
var b = stack.pop();
112+
stack.push(new Or(b, a));
113+
}
114+
else {
115+
stack.push(new Equals(operator));
116+
}
117+
}
118+
return stack.length > 0 ? stack.pop() : null;
119+
}
120+
121+
function render_select(handler) {
122+
var out = '<select name="keyword" id="keyword"';
123+
if (handler != null) {
124+
out += ' onchange="' + handler + '"';
125+
}
126+
out += '>';
127+
out += '<option value="-1"><\/option>';
128+
for (var i = 0; i < KEYWORDS.length; ++i) {
129+
out += '<option value="' + KEYWORDS[i][0] +
130+
'">' + KEYWORDS[i][1] + "<\/option>";
131+
}
132+
out += '<\/select>';
133+
return out;
134+
}
135+
136+
function first_select() {
137+
var value = document.getElementById("keyword").value;
138+
current = value;
139+
set_content();
140+
}
141+
142+
function not_clicked() {
143+
var expr = parse(current);
144+
if (expr == null) return;
145+
undo.push(current);
146+
current = expr instanceof Not
147+
? expr.x.postfix()
148+
: new Not(expr).postfix();
149+
set_content();
150+
}
151+
152+
function not_b_wrap(expr) {
153+
var value = document.getElementById("not_b").checked;
154+
return value ? new Not(expr) : expr;
155+
}
156+
157+
function and_clicked() {
158+
var expr = parse(current);
159+
if (expr == null) return;
160+
var value = document.getElementById("keyword").value;
161+
if (value == "-1") return;
162+
undo.push(current);
163+
current = new And(expr, not_b_wrap(new Equals(value))).postfix();
164+
set_content();
165+
}
166+
167+
function or_clicked() {
168+
var expr = parse(current);
169+
if (expr == null) return;
170+
var value = document.getElementById("keyword").value;
171+
if (value == "-1") return;
172+
undo.push(current);
173+
current = new Or(expr, not_b_wrap(new Equals(value))).postfix();
174+
set_content();
175+
}
176+
177+
function undo_clicked() {
178+
current = undo.length > 0
179+
? undo.pop()
180+
: original;
181+
set_content();
182+
}
183+
184+
function enable_and_or() {
185+
var value = document.getElementById("keyword").value;
186+
value = value == "-1";
187+
document.getElementById("and").disabled = value;
188+
document.getElementById("or").disabled = value;
189+
document.getElementById("not_b").disabled = value;
190+
}
191+
192+
function create() {
193+
var expr = parse(current);
194+
var out = "";
195+
if (expr == null) {
196+
out += "Keyword: ";
197+
out += render_select("first_select();");
198+
}
199+
else {
200+
out += '<table><tr>'
201+
out += '<td><input type="button" name="not" onclick="not_clicked();" value="NOT"\/><\/td>';
202+
out += "<td><tt><strong>" + expr.infix() + "<\/strong><\/tt><\/td>";
203+
out += '<td><table>';
204+
out += '<tr><td><input type="button" id="and" name="and" onclick="and_clicked();"'
205+
+ ' value="AND" disabled="disabled"\/><\/td><\/tr>';
206+
out += '<tr><td><input type="button" id="or" name="or" onclick="or_clicked();"'
207+
+ ' value="OR" disabled="disabled"\/><\/td><\/tr>';
208+
out += '<\/table><\/td>';
209+
out += '<td><label for="not_b">NOT<\/label><br/>'
210+
+ '<input type="checkbox" name="not_b" id="not_b" disabled="disabled"\/><\/td>';
211+
out += '<td>' + render_select("enable_and_or();") + '<\/td>';
212+
out += '<\/tr><\/table>'
213+
}
214+
out += '<hr\/>';
215+
if (undo.length > 0 || (undo.length == 0 && current != original)) {
216+
out += '<input type="button" onclick="undo_clicked();" value="Undo"\/>';
217+
}
218+
out += '<input type="button" onclick="modify_main();" value="Apply"\/>'
219+
+ '<input type="button" onclick="window.close();" value="Close Window"\/>';
220+
return out;
221+
}
222+
223+
function main_content() {
224+
var out = '';
225+
out += '<input type="hidden" name="%(prop)s" value="' + current + '"\/>';
226+
out += parse(current).infix();
227+
return out;
228+
}
229+
230+
function modify_main() {
231+
main = window.opener.document.getElementById("keywords_%(prop)s");
232+
main.innerHTML = main_content();
233+
}
234+
235+
function set_content() {
236+
document.getElementById("content").innerHTML = create();
237+
}
238+
239+
set_content();
240+
//-->
241+
</script>
242+
'''
243+
244+
def list_nodes(request):
245+
prop = request.form.getfirst("property")
246+
cls = request.client.db.getclass(prop)
247+
items = []
248+
for nodeid in cls.getnodeids():
249+
l = cls.getnode(nodeid).items()
250+
l = dict([x for x in l if len(x) == 2])
251+
try:
252+
items.append((l['id'], l['name']))
253+
except KeyError:
254+
pass
255+
items.sort(key=lambda x: int(x[0]))
256+
return items
257+
258+
def items_to_keywords(items):
259+
return ',\n '.join(['["%s", "%s"]' % x for x in items])
260+
261+
262+
def render_keywords_expression_editor(request):
263+
prop = request.form.getfirst("property")
264+
265+
window_content = WINDOW_CONTENT % {
266+
'prop' : prop,
267+
'keywords': items_to_keywords(list_nodes(request)),
268+
'original': ''
269+
}
270+
271+
return window_content
272+
273+
# vim: set et sts=4 sw=4 :
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2+
<html>
3+
<head>
4+
<link rel="stylesheet" type="text/css" href="@@file/style.css" />
5+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8;" />
6+
<title tal:content="string:Roundup Keywords Expression Editor"></title>
7+
</head>
8+
<body class="body"
9+
tal:content="structure python:utils.keywords_expressions(request)">
10+
</body>
11+
</html>

0 commit comments

Comments
 (0)