source: tmcsimulator/branches/LCSv2/controllers/default.py @ 620

Revision 620, 16.6 KB checked in by jdalbey, 6 years ago (diff)

Implement #248 to enhance LCS Request page

Line 
1# added comments for testing
2# Constants
3hwys = ['','1','5', '22', '55', '57', '73', '74', '91', '133', '142', '241', '261', '405', '605']
4hwyDirections = ['','NB', 'SB', 'NB/SB','EB','WB','EB/WB']
5# Show the login page
6def index():
7    form = FORM(LABEL('Username:',_for='username', _class="label username-label"),
8                INPUT(_name='username', _size='15', _style="font-size: 18px;"), BR(),
9                INPUT(_type='submit',_value="Log in", _class=" btn btn-primary", _style="margin-top: 3%;"))
10    if form.process().accepted:
11        # Put the username entry into the session variable
12        session.username = form.vars.username
13        redirect(URL('home'))
14    return dict(form=form)
15def home():
16    return dict(name=session.username)
17def help():
18    return dict()
19# List all the current records in the database - remove in final application
20def list():
21    highways = db().select(db.closures.ALL, orderby=db.closures.lognum)
22    return dict(highways = highways)
23# Show details of a single record - remove in final application
24def show():
25    # Retrieve the requested log entry from the database
26    # Assumes the requested entry exists in the db (no error handling yet)
27    hwy = db(db.closures.lognum == request.args(0)).select().first()
28    return dict(hwy=hwy)
29# Display a search form
30def search():
31    form = FORM(LABEL('ClosureID/Log:',_for='closureid', _class="label"), 
32                INPUT(_name='closureid',_size='7', _style="margin-right: 5px;"),
33                INPUT(_name='lognum',_size='3'),
34                XML('   '), 
35                LABEL('Route: ',_for='route', _class="label"), 
36                SELECT(hwys,_name='route'), XML('   '), 
37                LABEL('Direction: ',_for='direction', _class="label"),
38                SELECT(hwyDirections,_name='direction'), BR(),BR(), 
39                LABEL('Dates:',_for='startdate', _class="label"), 
40                INPUT(_name='startdate',_class='date'), 
41                XML('   '), 
42                LABEL('  to:',_for='enddate', _class="label"), 
43                INPUT(_name='enddate',_class='date'),BR(),
44                INPUT(_value="Search", _type='submit', _class="btn btn-primary btn-default", _style="margin:  7% 45% 2% 40%;"))
45    if form.process(onvalidation=special_validation).accepted:
46        # Put the form fields into the session variables
47        session.closureid = form.vars.closureid.strip().upper()
48        session.lognum = form.vars.lognum.strip()
49        session.startdate = form.vars.startdate.strip()
50        session.enddate = form.vars.enddate.strip()
51        session.route = form.vars.route
52        session.direction = form.vars.direction
53        redirect(URL('results'))
54    return dict(form=form)
55# Search Form: Special validation check to reject lognum without closureID
56def special_validation(form):
57    # Error if a lognum was given and no closure id
58    if (len(form.vars.lognum) > 0 and len(form.vars.closureid) == 0):
59       form.errors.lognum = 'Must provide a closureID when specifying a log number'
60# Show the item that was found in the search
61def results():
62    # query object is equivalent to the where clause in query
63    query = True
64    msg = ""
65    if (len(session.closureid) != 0):
66        query = (db.closures.closureid == session.closureid)
67        msg += " Closure ID = " + session.closureid   
68    if (len(session.lognum) != 0):
69        query = query & (db.closures.lognum == session.lognum)
70        msg += " Log number = " + session.lognum   
71    if (len(session.route) != 0):
72        query = query & (db.closures.route == session.route)
73        msg += " Route = " + session.route
74    if (len(session.direction) != 0):
75        query = query & (db.closures.direction == session.direction)
76        msg += " Route = " + session.route
77    if (len(session.startdate) != 0):
78        query = query & (db.closures.startdate >= session.startdate)
79        msg += "Start date = " + session.startdate
80    if (len(session.enddate) != 0):
81        query = query & (db.closures.enddate <= session.enddate)
82        msg += "End date = " + session.enddate
83   
84    # if no restrictions entered then get all entries
85    if query == True :
86        hwy = db().select(db.closures.ALL)
87        msg = "ALL"
88    else:
89        # get entries with the matching requirements
90        hwy = db(query).select()
91
92    count = len(hwy)
93    # Show the results in table format.  Get the radio call number from supervisor name lookup
94    header = THEAD(TR(TH(''), TH('DTM',BR(),'Area'), TH('Closure ID/',BR(),'Log No.'),TH('Route & Dir/',BR(),'Type of Closure'),TH('Start Date/',BR(),'End Date/',BR(),'Est. Delay'),TH('Facility'),TH('Limits'),TH('Work'), TH('TMP:',BR(),'Cozeep/',BR(),'Detour'),TH('Requestor/',BR(),'Radio Call No.')))
95    multiform = []
96    # Iterates over all search results
97    for row in hwy:
98        statusfields = row.closureid +','+ row.lognum + ',1097,' + str(row.s1097user) +','+ str(row.startdate) + ',' + formatTime(row.starttime) +','+str(row.s1097date)+','+ formatTime(row.s1097time) + ',1098,' + str(row.s1098user) +','+ str(row.s1098date)+','+ formatTime(row.s1098time)+ ',1022,' + str(row.s1022user) +','+ str(row.s1022date)+','+ formatTime(row.s1022time)
99        # Each row contains a form with two buttons and columns with fields from database
100        multiform.append(TR(TD(
101                    XML("<button class='submit-button' onclick=\"showPopup(\'"),statusfields,XML("\')\">View History</button>"),BR(),
102                    FORM(
103                          INPUT(_type='submit',_name='btn2',_value='Show Status Form',_class="submit-button" ),
104                          INPUT(_type='hidden',_name='row',_value=row.closureid))),
105                          TD(row.closureid[0]),TD(row.closureid,HR(),row.lognum), TD(row.route,' ',row.direction,HR(),row.closuretype), TD(row.startdate,' ',formatTime(row.starttime),HR(),row.enddate,' ',formatTime(row.endtime),HR(),row.estdelay), TD(row.facility),TD(row.startlocation,HR(),row.endlocation), TD(row.worktype), TD(row.tmpcozeep,BR(),row.tmpdetour), TD(row.supervisor,HR(),db(db.supervisors.name == row.supervisor).select().first().radiocallnum) )) 
106
107    session.chosenid = request.vars.row #Pass the hidden field containing the closure ID
108    if request.vars.btn2:
109        redirect(URL('statuslist'))
110    return dict(msg=msg, count=count, highways=hwy, table=header, multiform=multiform)
111
112# Show the status box next to each search result
113def statuslist():
114    closedItems = []
115    if (session.chosenid):
116        if (type(session.chosenid) is str):
117            retrieved = db(db.closures.closureid == session.chosenid).select().first()
118            closedItems.append(retrieved) 
119        else:
120            # This logic is available to show multiple results, for possible future use.
121            for item in session.chosenid:
122                retrieved = db(db.closures.closureid == item).select().first()
123                closedItems.append(retrieved) 
124
125        form = FORM(BR(), 
126                TABLE(THEAD(TR(TH('Closure ID/',BR(),'Log No.'), TH('Route & Dir',BR(),'Type of Closure'),TH('Start Date/',BR(),'End Date/',BR(),'Est. Delay'),TH('Requestor/',BR(),'Radio Call No.'),TH('Status'))),
127                    [TR(TD(row.closureid,HR(),row.lognum),TD(row.route,' ',row.direction,HR(),row.closuretype),TD(row.startdate,HR(),row.enddate,HR(),row.estdelay),TD(row.supervisor,BR(),db(db.supervisors.name == row.supervisor).select().first().radiocallnum),TD(LABEL('1097'), INPUT(_type='checkbox', _name='statustype', _value='1097'+row.closureid),LABEL('1098'), INPUT(_type='checkbox', _name='statustype', _value='1098'+row.closureid),LABEL('1022'), INPUT(_type='checkbox', _name='statustype', _value='1022'+row.closureid),BR(), LABEL('Statuser:'),INPUT(_name='statuser',_size='9'))) for row in closedItems],
128                    _border='1', _cellpadding='5'),INPUT(_type='submit',_value="submit status form",_class="submit-button"),)
129       
130    else:
131        msg = "No items were selected.  Use the checkbox in the lefthand column."
132        form = ""
133        return dict(msg=msg,form=form)
134   
135    if form.process().accepted:
136        #session.flash = 'Status submit acknowledgement appears here.'
137        session.statustype = form.vars.statustype
138        session.statuser = form.vars.statuser
139        redirect(URL('statusAck'))
140    return dict(form=form)
141
142# show status update acknowledgement - and update database
143def statusAck():
144    if (session.statustype):
145        if (type(session.statustype) is str):
146            msg = "You submitted a status update for " + session.statustype[4:] + ": " + session.statustype[0:4] 
147#           Perform the update on the database
148            # Construct the name of the field to update
149            fieldname = "s"+session.statustype[0:4]+"user"
150            db(db.closures.closureid == session.statustype[4:]).update(**{fieldname:session.statuser})
151            import datetime 
152            now = datetime.datetime.today()
153            fieldname = "s"+session.statustype[0:4]+"date"
154            db(db.closures.closureid == session.statustype[4:]).update(**{fieldname:now.strftime("%Y%m%d")})
155            fieldname = "s"+session.statustype[0:4]+"time"
156            db(db.closures.closureid == session.statustype[4:]).update(**{fieldname:now.strftime("%H%M")})
157        else:
158            msg = "error because only checking one box is allowed."
159    else:
160        msg = "Error no statustype checkbox was checked"
161       
162    return dict(msg=msg)
163# Utility functions for formatting
164def formatTime(msg):
165    if (msg):
166        return msg[0:2]+':'+msg[2:4]
167    else:
168        return ""
169# Create a new record
170def submit():
171    # Don't name this function 'request' because it creates a name conflict with http.request
172    hournames = ['','00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23']
173    closuretypes = ['', 'Lane', 'Full', 'Moving', 'One-Way Traffic', 'Alternating Lanes', 'Traffic Break']
174    facilities = ['', 'Connector', 'Conventional_Hwy', 'Mainline', 'Off Ramp', 'On Ramp', 'Rest Area', 'Surface Street']
175    worktypes = ['','AC Paving', 'Accident Investigation', 'Attenuator Repair', 'Blasting', 'Bridge Inspection', 'Bridge Work', 'Brush Fire', 'Chip Seal Operation', 'Concrete Pour', 'Core Drilling', 'Crack Seal Operation', 'Curb/Gutter/Sidewalk Work', 'Drainage Cleaning', 'Drainage Inspection', 'Drainage Work', 'Electrical Work', 'Emergency Work', 'Falsework Installation', 'Falsework Removal', 'Fence Work', 'Filming Activity', 'Fog Seal Operation', 'Graffiti Removal', 'Grinding and Paving', 'Grinding Operation', 'Guardrail Repair', 'Guardrail Work', 'Highway Construction', 'K-rail Installation', 'K-rail Removal', 'Landscape Work', 'Litter Removal', 'Maintenance Operation', 'Median Barrier Work', 'Miscellaneous Work', 'Pavement Marker Replacement', 'Pavement Repair', 'Pavement Work', 'Paving Operation', 'Pile Driving', 'Police Investigation', 'Roadway Excavation', 'Roadway Flooding', 'Sewer Work', 'Shoulder Work', 'Sign Work', 'Slab Replacement', 'Slide Removal', 'Slope Clearing', 'Soundwall Work', 'Special Event', 'Spray Operation', 'Striping Operation', 'Survey Work', 'Sweeping Operation', 'Traffic Signal Work', 'Tree Work', 'Utility Work', 'Vegetation Spraying']
176    supervisors = ['']  # List of names for the dropdown box
177    # Obtain all the supervisor names from the database
178    for row in db().select(db.supervisors.ALL):
179        supervisors.append(row.radiocallnum + ' ' + row.name)
180    crew = ['']  # List of names for the dropdown box
181    # Obtain all the crew names from the database
182    for row in db().select(db.crew.ALL):
183        crew.append(row.radiocallnum + ' ' + row.name)
184    # Build the list of street locations and a hidden cross street lookup table
185    streets = ['']
186    streetlookup = []
187    for row in db().select(db.streets.ALL, orderby=db.streets.street):
188        streets.append(row.street)
189        streetlookup.append(row.route + ',' + row.street)
190
191    form = FORM(
192                LABEL('*Route',_for='route'), SELECT(hwys,_name='route', _id='routecombo', _onchange='routechanged()', requires=IS_LENGTH(minsize=1,error_message='route cannot be empty')), XML('&nbsp;&nbsp;&nbsp;'), 
193           LABEL('*Direction',_for='direction'), SELECT(hwyDirections,_name='direction', requires=IS_LENGTH(minsize=1,error_message='direction cannot be empty')), XML('&nbsp;&nbsp;&nbsp;'), 
194           LABEL('*Facility',_for='facility'), SELECT(facilities,_name='facility', requires=IS_LENGTH(minsize=1,error_message='facility cannot be empty')), BR(),BR(), 
195           TABLE(TR(TD(),TD(LABEL('*County')),TD(LABEL('*Location'))),
196                TR(TD(LABEL('BEGIN=')),TD(SELECT('ORA',_name='startcounty')),
197                TD(SELECT(streets,_name='startlocation',_id='startlocation')),
198           TR(TD(LABEL('END=')),TD(SELECT('ORA',_name='endcounty')),TD(SELECT(streets,_name='endlocation',_id='endlocation'))))),BR(),
199           LABEL('Date Range:'),BR(),
200           LABEL('From',_for='startdate'),INPUT(_name='startdate',_size='8',_class='date'), XML('&nbsp;&nbsp;&nbsp;'), 
201           LABEL('to:',_for='enddate'), INPUT(_name='enddate',_size='8',_class='date'),XML('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'), 
202           LABEL('Times',_for='starttime'),SELECT(hournames,_name='starttime'), 
203           LABEL(':',_for='starttimemin'),SELECT('','00','15','30','45','59',_name='starttimemin'), XML('&nbsp;&nbsp;'), 
204           LABEL('to:',_for='endtime'),SELECT(hournames,_name='endtime'), 
205           LABEL(':',_for='endtimemin'),SELECT('','00','15','30','45','59',_name='endtimemin'), BR(),BR(), 
206           TABLE(TR(TD(LABEL('*Type of Closure') ),
207                    TD(LABEL('*Type of Work')),
208                    TD(LABEL('Estimated Delay')),
209                    TD(LABEL('TMP Details'))), 
210                 TR(TD(SELECT(closuretypes,_name='closuretype',requires=IS_LENGTH(minsize=1,error_message='type of closure cannot be empty'))), 
211                    TD(SELECT(worktypes,_name='worktype', requires=IS_LENGTH(minsize=1,error_message='type of work cannot be empty'))), 
212                    TD(INPUT(_name='estdelay',_size='4',requires=IS_INT_IN_RANGE(1, 1441)),'minutes'), 
213                    TD(INPUT(_type='checkbox',_name='cozeep'),'CoZeep MaZeep/CHP',BR(), 
214                       INPUT(_type='checkbox', _name='detour'),'Detour Available')), 
215                 _width='100%' ),
216    TABLE(TR(TD(LABEL('*Supervisor')),
217            TD(LABEL('Field Rep'))), 
218                  TR(TD(SELECT(supervisors,_name='supervisor', requires=IS_LENGTH(minsize=1,error_message='supervisor cannot be empty'))),
219                     TD(SELECT(crew,_name='fieldrep')))),
220    TABLE(TR(TD( LABEL('Meeting Place/CHP Contact')),
221            TD(LABEL('Reason for Closure')),
222            TD(LABEL('Additional Remarks / Detour '))), 
223                  TR(TD(INPUT(_name='meeting', _size='25')),TD(INPUT(_name='reason',_size='25')),TD(INPUT(_name='remarks',_size='25'))) ), BR(), 
224            INPUT(_type='submit',_value='Submit Closure', _class="btn btn-primary btn-default", _style="margin:  2% 45% 2% 40%;"),
225            XML('\n'),SELECT(streetlookup,_name='stlookup', _id='stlookup', _class='hideme')) 
226
227    if form.process().accepted:
228        newID = calcNextClosure(form.vars.route)
229        # Insert the record into the database
230        newrec = db.closures.insert(closureid=newID, lognum='1', route=form.vars.route, direction=form.vars.direction, facility=form.vars.facility, startcounty=form.vars.startcounty, endcounty=form.vars.endcounty, startlocation=form.vars.startlocation, endlocation=form.vars.endlocation, startdate=form.vars.startdate, enddate=form.vars.enddate, starttime=form.vars.starttime+form.vars.starttimemin, endtime=form.vars.endtime+form.vars.endtimemin, closuretype=form.vars.closuretype, worktype=form.vars.worktype, estdelay=form.vars.estdelay, tmpcozeep=getCheckbox(form.vars.cozeep), tmpdetour=getCheckbox(form.vars.detour), supervisor=form.vars.supervisor, fieldrep=form.vars.fieldrep,  )
231        session.flash = 'New lane closure added: ' + newID
232        redirect(URL('search.html'))
233    return dict(form=form)
234
235# Calculate the closure id to assign to the new closure
236def calcNextClosure(routeNum):
237    # Retrieve any existing closures on this route
238    item = db(db.closures.closureid.startswith('T'+routeNum)).select().last() # Might need to sort these
239    if (item != None):
240        currID = item.closureid
241        lastchar = currID[-1:]  # Get last character of ID
242        lastchar = chr(ord(lastchar) + 1) # increment it to next character (need bounds check)
243        newID = currID[:-1] + lastchar  # append char to ID
244        return newID
245    else:
246        return 'T'+routeNum+'AA'  # For a non-existing route
247
248# Convert checkbox value to YES/NO
249def getCheckbox(ckBox):
250    if (ckBox == "on"):
251        return "YES"
252    else:
253        return "NO"
Note: See TracBrowser for help on using the repository browser.