def selectDiffColumns(self, recievedData): """ given a dic of data recieve about a record compare it to the data in the DB remove entries in the recieved dictionary that already exist return truncated dict""" query = Query() where = "book.book_id =" + str(self.book_id) recordData = query.getData("edit", where) remove = [] for col, val in recordData[0].items(): if val == "": recordData[0][col] = None else: recordData[0][col] = str(val) for col in recievedData: if recievedData[col] == recordData[0][col]: remove.append(col) for col in remove: del recievedData[col] return recievedData
class Report(): def __init__(self, report): self.query = Query() self.forms = HTMLutils() self.author = Author() self.when = WhenRead() self.report = report self.columns = loadYaml('columns') self.pages = loadYaml('pages') if report == 'add': page = 'edit' else: page = report self.display_names = self.getDisplayNames(page) def buildMain(self, where= None, order_by = None): '''build table seen on main page using all books. Accepts optional arguements to filter (search) or sort. Returns table''' bookData = self.query.getData('main', where, order_by) # start html table mainTable = HtmlTable(border=1, cellpadding=3) # table header, uses display name and enables sorting table_header = ['#'] for field, name in self.display_names: sortflag ='' if field == order_by: sortflag = ' ^' js = "document.form1.order_by.value='%s';" % field js += "document.form1.submit();" h = '<a onclick="javascript:%s">%s%s</a>' % (js, name, sortflag) table_header.append(h) mainTable.addHeader(table_header) # table body- build a numbered row for each record i = 0 activity = 'view' for rec in bookData: i += 1 href = '<a href="detail.py?book_id=%d&activity=%s">%s'\ % (rec['book_id'], activity, rec['title']) # format date if rec['date']: dates = '<br>'.join(['<nobr>%s</nobr>' % d.strip() for d in rec['date'].split('&')]) else: dates = '-' mainTable.addRow(\ [i, href, rec['author'] or '' , rec['notes' ] , dates]) return mainTable.getTable() def buildDetail(self, book_id): '''Static table to view book details''' where = 'book.book_id =' + str(book_id) bookData = self.query.getData('record', where) detailTable = HtmlTable(border=1, cellpadding=3) detailTable.addHeader(['Field', 'Entry']) for column, display in self.display_names: for rec in bookData: if rec[column]: data = rec[column] else: data = '-' detailTable.addRow([display, data]) return detailTable.getTable() def buildRecordForm (self, book_id = None): '''responisble for building the composite form for book records by gathering all data, calling necessary helper methods, and adding all sub-forms together. Form has 3 sub-parts: (1) the book form which holds all data fields with a 1:1 relationship to a book_id (2) the edit author from which itself has 2 sub-parts: (2a) the remove author feature (currently inactive) (2b) add author section which defaults to hidden (3) the dates read add/remove (currently inactive) form is used for adding records and editing records. If a book_id is recieved current values for that book_id are pulled from the DB and used to pre-populate form fields (used for edit). Otherwise the form is built blank, with no default values (used for add). Returns composite form as an HTML table ''' #create holder variables bookData = None authorData = None dateData = None #bring in data if book_id is present if book_id: where = 'book.book_id =' + str(book_id) bookData = self.query.getData('edit', where) authorData = self.author.getBookAuthor(book_id) dateData = self.when.getWhenRead(book_id) #call helper methods to build all sub-parts bookForm = self.buildBookForm(bookData) removeAuthor = self.buildEditAuthor(authorData) dateForm = self.buildEditDate(dateData) #put tables with many:many relationships together in a sub-table table subTs = HtmlTable(border=0, cellpadding = 20) subTs.addRow([removeAuthor]) subTs.addRow([dateForm]) subTables = subTs.getTable() #put all form tables together recordForm = HtmlTable(border=0, cellpadding=30) recordForm. addRow([bookForm, subTables]) return recordForm.getTable() def buildBookForm(self, bookData): '''Accepts bookData, which may be blank. Builds book form. If bookData !None pre-populates form with default values from bookData. returns book form HTML table ''' #initialze book from table bookForm = HtmlTable(border=1, cellpadding=3) bookForm.addHeader(['Field', 'Entry']) #loop through display names (the ordered list of column names) #for each: determine the default value and form type for column, display in self.display_names: form_type = self.columns[column][0]['form_type'] if self.report == 'edit' and bookData !=None: default = bookData[0][column] else: default = None #buld a form field of the correct type if form_type == 'text': if default == None: default = '' form_field = self.forms.getTextField(column, default) elif form_type == 'drop_down': #pull in the values from the home table to make a #list of options options = self.query.getColumnValues(column) form_field = self.forms.getDropDown(column, default, options) elif form_type == 'radio_static': if default == None and column == 'published': default = 1 #pull in status radio options from metadata options = self.columns[column][0]['radio_options'] form_field =self.forms.getStaticRadio(column, default, options) elif form_type == 'datepicker': if default == None: default = '' form_field = self.forms.getJQueryUI(column, default, form_type) elif form_type == 'autocomplete': if default == None: default = '' form_field =self.forms.getAutoComplete(column, default) else: #debug feature that will make a cell in the table declare #what form type it thinks it should be if the form type is not #found above form_field = form_type #add the display name and form field as a new row in the book form bookForm.addRow([display, form_field]) return bookForm.getTable() def buildEditAuthor(self, authorData): '''Accept authorData which may be None Build author sub-table. if authorData !None include the list of authors and set the add author section to hidden. Else set add author section to be visable. Return 2 seperate sections: remove author and add author ''' #initialize Author form editAuthorTable = HtmlTable(border=1, cellpadding=3) #create button that will toggle open the add author section add ='<button type = "button" id="authorToggle"> Add Author </button>' #add the header row of the table with the add button editAuthorTable.addHeader(['Author']) #section shows list of authors currenlty paired with the book if authorData: for author in authorData: catAuthor = '<nobr>%s %s</nobr>'\ %(author['first_name'], author['last_name']) editAuthorTable.addRow([catAuthor]) #initialize hidden add author section # addAuthor = '<div id = "addAuthor" style = "display: none">' # else: #initialize visable add author section # addAuthor = '<div id = "addAuthor" style = "display: default">' #complete the addAuthor section addAuthor = '<div id = "addAuthor" style = "display: default">' addAuthor += self.buildAddAuthor() addAuthor += '</div>' editAuthorTable.addRow([addAuthor]) return editAuthorTable.getTable() def buildAddAuthor(self): '''build a table that will be a subtable of the edit author table it will be the toggleable section for adding authors to the DB and the book record. Only called by buildEditAuthor. Returns table. This table will be interacting with the autocomplete js functions. ''' autocomplete = 'Add Author: ' + \ self.forms.getAutoComplete('author', '',) +\ '</br>(Last Name, First Name)' first_name =\ self.forms.getHidden('first_name', '') last_name = \ self.forms.getHidden('last_name', '') authorForm = autocomplete + '</br>' + first_name + '</br>'+ \ last_name return authorForm def buildEditDate(self, dateData): '''build table that will be a sub-table of the main edit table to hold dates and date addtion/subtraction features. Accepts a book id, find associated dates. Returns table''' #initilize date table editDateTable = HtmlTable(border=1, cellpadding=3) editDateTable.addHeader(['Date(s) Read']) if dateData: for d in dateData: editDateTable.addRow([str(d[0])]) addNew = 'Add Date:' addNew += self.forms.getJQueryUI('when_read', '', 'datepicker') editDateTable.addRow([addNew]) return editDateTable.getTable() def getDisplayNames(self, page): '''given a page and column attribute return a dictionary of lists: ordered_cols: columns in display order col_attributes: a list of lists featuring the col and its attribute value matching_cols: a list of columns having a feature''' ordered_cols = [] orderedColDisplay = [] #makes list of columns in display order for col in self.pages[page]: ordered_cols.append(col) if 'book_id' in ordered_cols: ordered_cols.remove('book_id') for col in ordered_cols: x = [] #adds info to correct list if col has attribute for element in self.columns[col]: if 'display' in element: x.append(col) x.append(element['display']) orderedColDisplay.append(x) return orderedColDisplay
'title' : title, 'series' : series, 'notes' : notes, 'series_num' : series_num, 'owner_status.status' : owner_status, 'published' : published, 'type' : type, 'when_read.when_read' : when_read } for k, v in formDict.items(): if v == 'None': v = 'NULL' query = Query() where = 'book_id =' + book_id results = query.getData('record', where) #build html_header if activity == 'edit': header = 'Edit Record' else: header = 'Book Record' html_header= ''' <html> <h3>%s</h3> '''%header #build debug_section debug_section = 'Book ID = %s' % (book_id)
class Report(): def __init__(self, report): self.query = Query() self.forms = HTMLutils() self.report = report self.columns = loadYaml('columns') self.pages = loadYaml('pages') if report == 'add': page = 'edit' else: page = report self.display_names = self.getDisplayNames(page) def buildMain(self, where= None, order_by = None): '''build table seen on main page using all books. Accepts optional arguements to filter (search) or sort. Returns table''' bookData = self.query.getData('main', where, order_by) # start html table mainTable = HtmlTable(border=1, cellpadding=3) # table header, uses display name and enables sorting table_header = ['#'] for field, name in self.display_names: sortflag ='' if field == order_by: sortflag = ' ^' js = "document.form1.order_by.value='%s';" % field js += "document.form1.submit();" h = '<a onclick="javascript:%s">%s%s</a>' % (js, name, sortflag) table_header.append(h) mainTable.addHeader(table_header) # table body- build a numbered row for each record i = 0 activity = 'view' for rec in bookData: i += 1 href = '<a href="detail.py?book_id=%d&activity=%s">%s'\ % (rec['book_id'], activity, rec['title']) # format dates if rec['date']: dates = '<br>'.join(['<nobr>%s</nobr>' % d.strip() for d in rec['date'].split('&')]) else: dates = '-' mainTable.addRow(\ [i, href, rec['author'] or '' , rec['notes' ] , dates]) return mainTable.getTable() def buildDetail(self, book_id): '''Static table to view book details''' where = 'book.book_id =' + str(book_id) bookData = self.query.getData('record', where) detailTable = HtmlTable(border=1, cellpadding=3) detailTable.addHeader(['Field', 'Entry']) for column, display in self.display_names: for rec in bookData: if rec[column]: data = rec[column] else: data = '-' detailTable.addRow([display, data]) return detailTable.getTable() def buildBookForm(self, book_id= None): '''dynamic composite table. made of three parts: the book form which has all form elements for all elements related to the book except the date, and author which a book has a many:many relationship with. Date is a sperate form (INACTIVE currently) Author has two parts: the edit author table holds all author information, eventually removing authors will be enabled. It has a sub table of add author. Accepts a book id, finds relevant data, calls helper methods. Returns composite table of all above sub-parts. ''' if self.report == 'edit' and book_id != None: where = 'book.book_id =' + str(book_id) bookData = self.query.getData('edit', where) bookTable = HtmlTable(border=1, cellpadding=3) bookTable.addHeader(['Field', 'Entry']) for column, display in self.display_names: form_type = self.columns[column][0]['form_type'] if self.report == 'edit': default = bookData[0][column] else: default = None if column == 'author' or column == 'when_read': pass else: #use general methods to build forms if form_type == 'text': if default == None: default = '' form_field = self.forms.getTextField(column, default) elif form_type == 'drop_down': #pull in the values from the home table to make a #list of options options = self.query.getColumnValues(column) form_field = \ self.forms.getDropDown(column, default, options) elif form_type == 'radio_static': if default == None and column == 'published': default = 1 options = self.columns[column][0]['radio_options'] form_field =\ self.forms.getStaticRadio(column, default, options) elif form_type == 'datepicker': if default == None: default = '' form_field =\ self.forms.getJQueryUI(column, default, form_type) elif form_type == 'autocomplete': if default == None: default = '' form_field =\ self.forms.getAutoComplete(column, default) else: form_field = form_type bookTable.addRow([display, form_field]) bookT = bookTable.getTable() if self.report == 'edit': authorT, authorF= self.buildEditAuthor(book_id) dateT = self.buildEditDate(book_id) else: authorT = self.buildAddAuthor() dateT = self.buildAddDate() subTables = HtmlTable(border=0, cellpadding = 20) subTables.addRow([authorT]) subTables.addRow([authorF]) subTables.addRow([dateT]) subT = subTables.getTable() editModules = HtmlTable(border=0, cellpadding=30) editModules.addRow([bookT, subT]) return editModules.getTable() def buildEditAuthor(self, book_id): '''build a table that will be a stub table of the main edit table. it will have all author information and will (eventually) be the place to remove and add authors from/to book records accepts a book id, finds all authors asscoiated with returns a table for those authors''' author = Author() bookAuthor = author.getBookAuthor(book_id) editAuthorTable = HtmlTable(border=1, cellpadding=3) add ='<button type = "button" id="authorToggle"> Add Author </button>' addAuthor = '<div id = "addAuthor" style = "display: none">' addAuthor += self.buildAddAuthor() addAuthor += '</div>' editAuthorTable.addHeader(['Author', add]) for author in bookAuthor: catAuthor = '<nobr>%s %s</nobr>'\ %(author['first_name'], author['last_name']) remove = 'Remove author %s*' %author['author_id'] editAuthorTable.addRow([catAuthor, remove]) editAuthorTable.addRow(['',\ '*remove author feature not avalible yet']) return editAuthorTable.getTable(), addAuthor def buildAddAuthor(self): '''build a table that will be a subtable of the edit author table it will be the hidden toggleable section for adding authors to the DB and the book record. Only called by buildEditAuthor. Returns table ''' autocomplete = 'Author Name: ' + \ self.forms.getAutoComplete('author', '',) + \ '(Last Name, First Name)' first_name = 'First Name: ' + \ self.forms.getTextField ('first_name', '', readonly = True) last_name = 'Last Name: '+ \ self.forms.getTextField ('last_name', '', readonly = True) authorForm = autocomplete + '</br>' + first_name + '</br>'+ \ last_name return authorForm def buildEditDate(self, book_id): '''build table that will be a sub-table of the main edit table to hold dates and date addtion/subtraction features. Accepts a book id, find associated dates. Returns table''' when = WhenRead() bookDate = when.getWhenRead(book_id) editDateTable = HtmlTable(border=1, cellpadding=3) editDateTable.addHeader(['Date', 'Add Addtional Date']) for bD in bookDate: remove = 'Forget this date' editDateTable.addRow([str(bD[0]), remove]) return editDateTable.getTable() def buildAddDate(self): ''' old method. to be incorporated into buildEditDate when ready to activate the features''' datepicker = self.forms.getJQueryUI('when_read','', 'datepicker') addDateTable = HtmlTable(border=1, cellpadding=3) addDateTable.addRow(['Date', datepicker]) return addDateTable.getTable() def getDisplayNames(self, page): '''given a page and column attribute return a dictionary of lists: ordered_cols: columns in display order col_attributes: a list of lists featuring the col and its attribute value matching_cols: a list of columns having a feature''' ordered_cols = [] orderedColDisplay = [] #makes list of columns in display order for col in self.pages[page]: ordered_cols.append(col) if 'book_id' in ordered_cols: ordered_cols.remove('book_id') for col in ordered_cols: x = [] #adds info to correct list if col has attribute for element in self.columns[col]: if 'display' in element: x.append(col) x.append(element['display']) orderedColDisplay.append(x) return orderedColDisplay
class LibraryHTML: '''Given an actitvity to prefrom on a record (view, edit, add) return a list of html building blocks to paint the page''' def __init__(self, book_id, activity): self.book_id = book_id self.activity = activity self.connection = getDictConnection() self.conn = getConnection() #bring in yaml metadata metadata = Metadata() self.columns = metadata.loadYaml('columns') self.pages = metadata.loadYaml('pages') self.list = [] if activity == 'edit': self.header = 'Edit Record' self.page = 'edit' self.new_activity = 'update' self.button_text = 'Submit' self.show_blank = '' self.cancel_button_text = 'Cancel' self.cancel_button_address = 'detail.py?book_id=%s&activity=view'\ %book_id if activity == 'view': self.header = 'Book Record' self.page = 'record' self.new_activity = 'edit' self.button_text = 'Edit' self.show_blank = '-' self.cancel_button_address = 'main.py' self.cancel_button_text = 'Back to Catalog' if activity == 'add': self.header = 'Enter New Record' self.page = 'edit' self.new_activity = 'submit_new' self.button_text = 'Save' self.show_blank = '' self.cancel_button_address = 'main.py' self.cancel_button_text = 'Cancel' # build the right query for the page and bring in the data if activity != 'add': self.query = Query() where = 'book.book_id =' + str(self.book_id) self.recordData = self.query.getData(self.page, where) def build_html_header(self): html_header= ''' <html> <link rel="stylesheet" href="//code.jquery.com/ui/1.11.1/themes/smoothness/jquery-ui.css"> <script src="//code.jquery.com/ui/1.11.1/jquery-ui.js"></script> <script src = "jquery_1.11.1.js"></script> <script src="//code.jquery.com/jquery-1.10.2.js"></script> <script src="//code.jquery.com/ui/1.11.1/jquery-ui.js"></script> <script> $(function(){ $("#autoC").autocomplete({source: %s}); }); </script> <h3>%s</h3> '''% (self.list, self.header) return html_header def build_form_header(self): form_header = ''' <form method = "POST" action = "detail.py" name = "form"> ''' return form_header def build_report(self): metadata = Metadata() display_data = metadata.interrogateMetadata(self.page, 'display') display_names = display_data['col_attributes'] table = HtmlTable(border=1, cellpadding=3) table.addHeader(['Field', 'Entry']) for column, display in display_names: if self.activity == 'view': # make a simple table, not a form for rec in self.recordData: if rec[column]: data = rec[column] else: data = self.show_blank table.addRow([display, data]) else: #use methods to build form form = self.columns[column][0]['form_type'] # type_method = {'text' :' self.getTextField(column)', # 'drop_down' : 'self.getDropDown(column)', # 'radio_static': 'self.getStaticRadio(column)', # 'autocomplete': 'self.getAutocomplete(column)' # } if form == 'text': form_field =self.getTextField(column) if form == 'drop_down': form_field =self.getDropDown(column) if form == 'radio_static': form_field =self.getStaticRadio(column) if form == 'autocomplete': form_field =self.getAutocomplete(column) table.addRow([display, form_field]) #push final product report = table.getTable() return report def build_input_button(self): input_button= '''<div> <input type = "hidden" name = "book_id" value = "%s"/> <input type = "hidden" name = "activity" value = "%s"/> <input id = switch type = "button" value = "%s" onclick = "javascript: document.form.submit()";/> </div>'''% (self.book_id, self.new_activity, self.button_text) return input_button def build_cancel_button(self): cancel_button = ''' <input type = "button" onClick = "location.href='%s'" value = "%s"> ''' %(self.cancel_button_address, self.cancel_button_text) return cancel_button def build_form_footer(self): form_footer = '</form>' return form_footer def build_html_footer(self): html_footer = '</html>' return html_footer # def build_hidden_section(self): # hidden =''' # <div id = series> # New Series: # <input type = 'text' name = 'series'> # </input> # </div> # <input type = "button" id = hide_series> Show Series </input> # <script> # $("#series").hide(); # $("#hide_series").click(function(){ # $("#series").show(); # }); # </script>''' # return hidden def getDefault(self, column): if self.recordData: default = self.recordData[0][column] else: default = None return default def getTextField(self, column): default = self.getDefault(column) if default == None: default = self.show_blank form_field = ''' <input type = "text" name = "%s" value = "%s" size = "100"> '''%(column, default) return form_field def getDropDown (self, column): default = self.getDefault(column) colData = self.columns[column][0] # pull in the values from the static table sql= '''select %s from %s ''' %(colData['drop_down_select'], colData['foreign_table']) options = execute(self.conn, sql) form_field = '<select name = %s>' %column #if there is no default build a null option Pick One - make it default if default == None: form_field += '''<option select = "selected" value = "NULL">Pick One</option>''' #check if each option should be set to default else build as normal for o in options: if o[0] == default: form_field += '''<option select = "selected" value = %d> %s </option>''' %(o[0], o[1]) else: form_field += '''<option value = %d> %s</option> ''' %(o[0], o[1]) form_field += '</select>' return form_field def getStaticRadio(self, column): options = self.columns[column][0]['radio_options'] default = self.getDefault(column) if default == None and column == 'Published': default = 1 form_field = '' # loop through options, identify default, build radio group for o in options: if o[0] == default: form_field += '''<input type = "radio" name = %s value = %d checked = "true"> %s ''' %(self.columns[column][0]['radio_group'], o[0], o[1]) else: form_field += '''<input type = "radio" name = %s value = %d > %s ''' %(self.columns[column][0]['radio_group'], o[0], o[1]) return form_field def getAutocomplete (self, column): default = self.getDefault(column) if default == None: default = self.show_blank sql = 'select %s from %s' %(column, column) autoList = execute(self.conn, sql) for item in autoList: self.list += item form_field = ''' <input id = autoC name = %s value = %s> ''' %(column, default) return form_field
table = HtmlTable(border=1, cellpadding=3) table.addHeader(['Field', 'Entry']) loadyaml = LoadYaml() columns = loadyaml.loadYaml('columns') pages = loadyaml.loadYaml('pages') query = Query() where = 'book.book_id =' + book_id if activity == 'view': page = 'record' if activity == 'edit': page = 'edit' results = query.getData(page, where) ordered_rows= [] for item in pages[page]: ordered_rows.append(item) # making a list of lists holding the col name and display names # make a list of cols that need drop down menus display_names = [] drop_down = [] for item in ordered_rows: x = [] x.append(item) for element in columns[item]: if 'foreign_table' in element: drop_down.append(item)