[gen] Added a new calendar field, allowing to add a single (typed) event by day.
This commit is contained in:
		
							parent
							
								
									3bd66e3264
								
							
						
					
					
						commit
						93bde7a0f5
					
				
					 12 changed files with 523 additions and 19 deletions
				
			
		
							
								
								
									
										178
									
								
								gen/calendar.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								gen/calendar.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,178 @@
 | 
				
			||||||
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					from appy import Object
 | 
				
			||||||
 | 
					from appy.gen import Type
 | 
				
			||||||
 | 
					from DateTime import DateTime
 | 
				
			||||||
 | 
					from BTrees.IOBTree import IOBTree
 | 
				
			||||||
 | 
					from persistent.list import PersistentList
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					class Calendar(Type):
 | 
				
			||||||
 | 
					    '''This field allows to produce an agenda and view/edit events on it.'''
 | 
				
			||||||
 | 
					    jsFiles = {'view': ('widgets/calendar.js',)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, eventTypes, validator=None, default=None, show='view',
 | 
				
			||||||
 | 
					                 page='main', group=None, layouts=None, move=0,
 | 
				
			||||||
 | 
					                 specificReadPermission=False, specificWritePermission=False,
 | 
				
			||||||
 | 
					                 width=None, height=300, colspan=1, master=None,
 | 
				
			||||||
 | 
					                 masterValue=None, focus=False, mapping=None, label=None,
 | 
				
			||||||
 | 
					                 maxEventLength=50):
 | 
				
			||||||
 | 
					        Type.__init__(self, validator, (0,1), None, default, False, False,
 | 
				
			||||||
 | 
					                      show, page, group, layouts, move, False, False,
 | 
				
			||||||
 | 
					                      specificReadPermission, specificWritePermission,
 | 
				
			||||||
 | 
					                      width, height, None, colspan, master, masterValue, focus,
 | 
				
			||||||
 | 
					                      False, True, mapping, label)
 | 
				
			||||||
 | 
					        # eventTypes is a list of strings that identify the types of events
 | 
				
			||||||
 | 
					        # that are supported by this calendar.
 | 
				
			||||||
 | 
					        self.eventTypes = eventTypes
 | 
				
			||||||
 | 
					        # It is not possible to create events that span more days than
 | 
				
			||||||
 | 
					        # maxEventLength.
 | 
				
			||||||
 | 
					        self.maxEventLength = maxEventLength
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getSiblingMonth(self, month, prevNext):
 | 
				
			||||||
 | 
					        '''Gets the next or previous month (depending of p_prevNext) relative
 | 
				
			||||||
 | 
					           to p_month.'''
 | 
				
			||||||
 | 
					        dayOne = DateTime('%s/01' % month)
 | 
				
			||||||
 | 
					        if prevNext == 'previous':
 | 
				
			||||||
 | 
					            refDate = dayOne - 1
 | 
				
			||||||
 | 
					        elif prevNext == 'next':
 | 
				
			||||||
 | 
					            refDate = dayOne + 33
 | 
				
			||||||
 | 
					        return refDate.strftime('%Y/%m')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    weekDays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
 | 
				
			||||||
 | 
					    def getNamesOfDays(self, obj, short=True):
 | 
				
			||||||
 | 
					        res = []
 | 
				
			||||||
 | 
					        for day in self.weekDays:
 | 
				
			||||||
 | 
					            if short:
 | 
				
			||||||
 | 
					                suffix = '_short'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                suffix = ''
 | 
				
			||||||
 | 
					            res.append(obj.translate('day_%s%s' % (day, suffix)))
 | 
				
			||||||
 | 
					        return res
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getMonthGrid(self, month):
 | 
				
			||||||
 | 
					        '''Creates a list of lists of DateTime objects representing the calendar
 | 
				
			||||||
 | 
					           grid to render for a given p_month.'''
 | 
				
			||||||
 | 
					        # Month is a string "YYYY/mm".
 | 
				
			||||||
 | 
					        currentDay = DateTime('%s/01 12:00' % month)
 | 
				
			||||||
 | 
					        currentMonth = currentDay.month()
 | 
				
			||||||
 | 
					        res = [[]]
 | 
				
			||||||
 | 
					        dayOneNb = currentDay.dow() or 7 # This way, Sunday is 7 and not 0.
 | 
				
			||||||
 | 
					        if dayOneNb != 1:
 | 
				
			||||||
 | 
					            previousDate = DateTime(currentDay)
 | 
				
			||||||
 | 
					            # If the 1st day of the month is not a Monday, start the row with
 | 
				
			||||||
 | 
					            # the last days of the previous month.
 | 
				
			||||||
 | 
					            for i in range(1, dayOneNb):
 | 
				
			||||||
 | 
					                previousDate = previousDate - 1
 | 
				
			||||||
 | 
					                res[0].insert(0, previousDate)
 | 
				
			||||||
 | 
					        finished = False
 | 
				
			||||||
 | 
					        while not finished:
 | 
				
			||||||
 | 
					            # Insert currentDay in the grid
 | 
				
			||||||
 | 
					            if len(res[-1]) == 7:
 | 
				
			||||||
 | 
					                # Create a new row
 | 
				
			||||||
 | 
					                res.append([currentDay])
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                res[-1].append(currentDay)
 | 
				
			||||||
 | 
					            currentDay = currentDay + 1
 | 
				
			||||||
 | 
					            if currentDay.month() != currentMonth:
 | 
				
			||||||
 | 
					                finished = True
 | 
				
			||||||
 | 
					        # Complete, if needed, the last row with the first days of the next
 | 
				
			||||||
 | 
					        # month.
 | 
				
			||||||
 | 
					        if len(res[-1]) != 7:
 | 
				
			||||||
 | 
					            while len(res[-1]) != 7:
 | 
				
			||||||
 | 
					                res[-1].append(currentDay)
 | 
				
			||||||
 | 
					                currentDay = currentDay + 1
 | 
				
			||||||
 | 
					        return res
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getEventsAt(self, obj, date, asDict=True):
 | 
				
			||||||
 | 
					        '''Returns the list of events that exist at some p_date (=day).'''
 | 
				
			||||||
 | 
					        if not hasattr(obj, self.name): return
 | 
				
			||||||
 | 
					        years = getattr(obj, self.name)
 | 
				
			||||||
 | 
					        year = date.year()
 | 
				
			||||||
 | 
					        if year not in years: return
 | 
				
			||||||
 | 
					        months = years[year]
 | 
				
			||||||
 | 
					        month = date.month()
 | 
				
			||||||
 | 
					        if month not in months: return
 | 
				
			||||||
 | 
					        days = months[month]
 | 
				
			||||||
 | 
					        day = date.day()
 | 
				
			||||||
 | 
					        if day not in days: return
 | 
				
			||||||
 | 
					        if asDict:
 | 
				
			||||||
 | 
					            res = [e.__dict__ for e in days[day]]
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            res = days[day]
 | 
				
			||||||
 | 
					        return res
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def hasEventsAt(self, obj, date, otherEvents):
 | 
				
			||||||
 | 
					        '''Returns True if, at p_date, an event is found of the same type as
 | 
				
			||||||
 | 
					           p_otherEvents.'''
 | 
				
			||||||
 | 
					        if not otherEvents: return False
 | 
				
			||||||
 | 
					        events = self.getEventsAt(obj, date, asDict=False)
 | 
				
			||||||
 | 
					        if not events: return False
 | 
				
			||||||
 | 
					        return events[0].eventType == otherEvents[0]['eventType']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def createEvent(self, obj, date, handleEventSpan=True):
 | 
				
			||||||
 | 
					        '''Create a new event in the calendar, at some p_date (day). If
 | 
				
			||||||
 | 
					           p_handleEventSpan is True, we will use rq["eventSpan"] and also
 | 
				
			||||||
 | 
					           create the same event for successive days.'''
 | 
				
			||||||
 | 
					        rq = obj.REQUEST
 | 
				
			||||||
 | 
					        year, month, day = date.year(), date.month(), date.day()
 | 
				
			||||||
 | 
					        # Check that the "preferences" dict exists or not.
 | 
				
			||||||
 | 
					        if not hasattr(obj.aq_base, self.name):
 | 
				
			||||||
 | 
					            # 1st level: create a IOBTree whose keys are years.
 | 
				
			||||||
 | 
					            setattr(obj, self.name, IOBTree())
 | 
				
			||||||
 | 
					        yearsDict = getattr(obj, self.name)
 | 
				
			||||||
 | 
					        # Get the sub-dict storing months for a given year
 | 
				
			||||||
 | 
					        if year in yearsDict:
 | 
				
			||||||
 | 
					            monthsDict = yearsDict[year]
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            yearsDict[year] = monthsDict = IOBTree()
 | 
				
			||||||
 | 
					        # Get the sub-dict storing days of a given month
 | 
				
			||||||
 | 
					        if month in monthsDict:
 | 
				
			||||||
 | 
					            daysDict = monthsDict[month]
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            monthsDict[month] = daysDict = IOBTree()
 | 
				
			||||||
 | 
					        # Get the list of events for a given day
 | 
				
			||||||
 | 
					        if day in daysDict:
 | 
				
			||||||
 | 
					            events = daysDict[day]
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            daysDict[day] = events = PersistentList()
 | 
				
			||||||
 | 
					        # Create and store the event, excepted if an event already exists.
 | 
				
			||||||
 | 
					        if not events:
 | 
				
			||||||
 | 
					            event = Object(eventType=rq['eventType'])
 | 
				
			||||||
 | 
					            events.append(event)
 | 
				
			||||||
 | 
					        # Span the event on the successive days if required
 | 
				
			||||||
 | 
					        if handleEventSpan and rq['eventSpan']:
 | 
				
			||||||
 | 
					            nbOfDays = int(rq['eventSpan'])
 | 
				
			||||||
 | 
					            for i in range(nbOfDays):
 | 
				
			||||||
 | 
					                date = date + 1
 | 
				
			||||||
 | 
					                self.createEvent(obj, date, handleEventSpan=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def deleteEvent(self, obj, date, handleEventSpan=True):
 | 
				
			||||||
 | 
					        '''Deletes an event. It actually deletes all events at rq['day'].
 | 
				
			||||||
 | 
					           If p_handleEventSpan is True, we will use rq["deleteNext"] to
 | 
				
			||||||
 | 
					           delete successive events, too.'''
 | 
				
			||||||
 | 
					        rq = obj.REQUEST
 | 
				
			||||||
 | 
					        if not self.getEventsAt(obj, date): return
 | 
				
			||||||
 | 
					        daysDict = getattr(obj, self.name)[date.year()][date.month()]
 | 
				
			||||||
 | 
					        # Remember events, in case we must delete similar ones for next days.
 | 
				
			||||||
 | 
					        events = self.getEventsAt(obj, date)
 | 
				
			||||||
 | 
					        del daysDict[date.day()]
 | 
				
			||||||
 | 
					        if handleEventSpan and rq.has_key('deleteNext') and \
 | 
				
			||||||
 | 
					           (rq['deleteNext'] == 'True'):
 | 
				
			||||||
 | 
					            while True:
 | 
				
			||||||
 | 
					                date = date + 1
 | 
				
			||||||
 | 
					                if self.hasEventsAt(obj, date, events):
 | 
				
			||||||
 | 
					                    self.deleteEvent(obj, date, handleEventSpan=False)
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def process(self, obj):
 | 
				
			||||||
 | 
					        '''Processes an action coming from the calendar widget, ie, the creation
 | 
				
			||||||
 | 
					           or deletion of a calendar event.'''
 | 
				
			||||||
 | 
					        rq = obj.REQUEST
 | 
				
			||||||
 | 
					        action = rq['actionType']
 | 
				
			||||||
 | 
					        # Get the date for this action
 | 
				
			||||||
 | 
					        if action == 'createEvent':
 | 
				
			||||||
 | 
					            return self.createEvent(obj, DateTime(rq['day']))
 | 
				
			||||||
 | 
					        elif action == 'deleteEvent':
 | 
				
			||||||
 | 
					            return self.deleteEvent(obj, DateTime(rq['day']))
 | 
				
			||||||
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					@ -378,6 +378,14 @@ class FieldDescriptor:
 | 
				
			||||||
            msg.produceNiceDefault()
 | 
					            msg.produceNiceDefault()
 | 
				
			||||||
            self.generator.labels.append(msg)
 | 
					            self.generator.labels.append(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def walkCalendar(self):
 | 
				
			||||||
 | 
					        # Add i18n-specific messages
 | 
				
			||||||
 | 
					        for et in self.appyType.eventTypes:
 | 
				
			||||||
 | 
					            label = '%s_%s_event_%s' % (self.classDescr.name,self.fieldName,et)
 | 
				
			||||||
 | 
					            msg = PoMessage(label, '', et)
 | 
				
			||||||
 | 
					            msg.produceNiceDefault()
 | 
				
			||||||
 | 
					            self.generator.labels.append(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def walkAppyType(self):
 | 
					    def walkAppyType(self):
 | 
				
			||||||
        '''Walks into the Appy type definition and gathers data about the
 | 
					        '''Walks into the Appy type definition and gathers data about the
 | 
				
			||||||
           i18n labels.'''
 | 
					           i18n labels.'''
 | 
				
			||||||
| 
						 | 
					@ -435,6 +443,8 @@ class FieldDescriptor:
 | 
				
			||||||
        elif self.appyType.type == 'Pod': self.walkPod()
 | 
					        elif self.appyType.type == 'Pod': self.walkPod()
 | 
				
			||||||
        # Manage things which are specific to List types
 | 
					        # Manage things which are specific to List types
 | 
				
			||||||
        elif self.appyType.type == 'List': self.walkList()
 | 
					        elif self.appyType.type == 'List': self.walkList()
 | 
				
			||||||
 | 
					        # Manage things which are specific to Calendar types
 | 
				
			||||||
 | 
					        elif self.appyType.type == 'Calendar': self.walkCalendar()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def generate(self):
 | 
					    def generate(self):
 | 
				
			||||||
        '''Generates the i18n labels for this type.'''
 | 
					        '''Generates the i18n labels for this type.'''
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -505,6 +505,50 @@ class ZopeGenerator(Generator):
 | 
				
			||||||
            msg('object_author',        '', msg.OBJECT_AUTHOR),
 | 
					            msg('object_author',        '', msg.OBJECT_AUTHOR),
 | 
				
			||||||
            msg('action_date',          '', msg.ACTION_DATE),
 | 
					            msg('action_date',          '', msg.ACTION_DATE),
 | 
				
			||||||
            msg('action_comment',       '', msg.ACTION_COMMENT),
 | 
					            msg('action_comment',       '', msg.ACTION_COMMENT),
 | 
				
			||||||
 | 
					            msg('day_Mon_short',        '', msg.DAY_MON_SHORT),
 | 
				
			||||||
 | 
					            msg('day_Tue_short',        '', msg.DAY_TUE_SHORT),
 | 
				
			||||||
 | 
					            msg('day_Wed_short',        '', msg.DAY_WED_SHORT),
 | 
				
			||||||
 | 
					            msg('day_Thu_short',        '', msg.DAY_THU_SHORT),
 | 
				
			||||||
 | 
					            msg('day_Fri_short',        '', msg.DAY_FRI_SHORT),
 | 
				
			||||||
 | 
					            msg('day_Sat_short',        '', msg.DAY_SAT_SHORT),
 | 
				
			||||||
 | 
					            msg('day_Sun_short',        '', msg.DAY_SUN_SHORT),
 | 
				
			||||||
 | 
					            msg('day_Mon',              '', msg.DAY_MON),
 | 
				
			||||||
 | 
					            msg('day_Tue',              '', msg.DAY_TUE),
 | 
				
			||||||
 | 
					            msg('day_Wed',              '', msg.DAY_WED),
 | 
				
			||||||
 | 
					            msg('day_Thu',              '', msg.DAY_THU),
 | 
				
			||||||
 | 
					            msg('day_Fri',              '', msg.DAY_FRI),
 | 
				
			||||||
 | 
					            msg('day_Sat',              '', msg.DAY_SAT),
 | 
				
			||||||
 | 
					            msg('day_Sun',              '', msg.DAY_SUN),
 | 
				
			||||||
 | 
					            msg('ampm_am',              '', msg.AMPM_AM),
 | 
				
			||||||
 | 
					            msg('ampm_pm',              '', msg.AMPM_PM),
 | 
				
			||||||
 | 
					            msg('month_Jan_short',      '', msg.MONTH_JAN_SHORT),
 | 
				
			||||||
 | 
					            msg('month_Feb_short',      '', msg.MONTH_FEB_SHORT),
 | 
				
			||||||
 | 
					            msg('month_Mar_short',      '', msg.MONTH_MAR_SHORT),
 | 
				
			||||||
 | 
					            msg('month_Apr_short',      '', msg.MONTH_APR_SHORT),
 | 
				
			||||||
 | 
					            msg('month_May_short',      '', msg.MONTH_MAY_SHORT),
 | 
				
			||||||
 | 
					            msg('month_Jun_short',      '', msg.MONTH_JUN_SHORT),
 | 
				
			||||||
 | 
					            msg('month_Jul_short',      '', msg.MONTH_JUL_SHORT),
 | 
				
			||||||
 | 
					            msg('month_Aug_short',      '', msg.MONTH_AUG_SHORT),
 | 
				
			||||||
 | 
					            msg('month_Sep_short',      '', msg.MONTH_SEP_SHORT),
 | 
				
			||||||
 | 
					            msg('month_Oct_short',      '', msg.MONTH_OCT_SHORT),
 | 
				
			||||||
 | 
					            msg('month_Nov_short',      '', msg.MONTH_NOV_SHORT),
 | 
				
			||||||
 | 
					            msg('month_Dec_short',      '', msg.MONTH_DEC_SHORT),
 | 
				
			||||||
 | 
					            msg('month_Jan',            '', msg.MONTH_JAN),
 | 
				
			||||||
 | 
					            msg('month_Feb',            '', msg.MONTH_FEB),
 | 
				
			||||||
 | 
					            msg('month_Mar',            '', msg.MONTH_MAR),
 | 
				
			||||||
 | 
					            msg('month_Apr',            '', msg.MONTH_APR),
 | 
				
			||||||
 | 
					            msg('month_May',            '', msg.MONTH_MAY),
 | 
				
			||||||
 | 
					            msg('month_Jun',            '', msg.MONTH_JUN),
 | 
				
			||||||
 | 
					            msg('month_Jul',            '', msg.MONTH_JUL),
 | 
				
			||||||
 | 
					            msg('month_Aug',            '', msg.MONTH_AUG),
 | 
				
			||||||
 | 
					            msg('month_Sep',            '', msg.MONTH_SEP),
 | 
				
			||||||
 | 
					            msg('month_Oct',            '', msg.MONTH_OCT),
 | 
				
			||||||
 | 
					            msg('month_Nov',            '', msg.MONTH_NOV),
 | 
				
			||||||
 | 
					            msg('month_Dec',            '', msg.MONTH_DEC),
 | 
				
			||||||
 | 
					            msg('today',                '', msg.TODAY),
 | 
				
			||||||
 | 
					            msg('which_event',          '', msg.WHICH_EVENT),
 | 
				
			||||||
 | 
					            msg('event_span',           '', msg.EVENT_SPAN),
 | 
				
			||||||
 | 
					            msg('del_next_events',      '', msg.DEL_NEXT_EVENTS),
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        # Create a label for every role added by this application
 | 
					        # Create a label for every role added by this application
 | 
				
			||||||
        for role in self.getAllUsedRoles():
 | 
					        for role in self.getAllUsedRoles():
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -612,7 +612,8 @@ class BaseMixin:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getGroupedAppyTypes(self, layoutType, pageName, cssJs=None):
 | 
					    def getGroupedAppyTypes(self, layoutType, pageName, cssJs=None):
 | 
				
			||||||
        '''Returns the fields sorted by group. For every field, the appyType
 | 
					        '''Returns the fields sorted by group. For every field, the appyType
 | 
				
			||||||
           (dict version) is given.'''
 | 
					           (dict version) is given. If a dict is given in p_cssJs, we will add
 | 
				
			||||||
 | 
					           it in the css and js files required by the fields.'''
 | 
				
			||||||
        res = []
 | 
					        res = []
 | 
				
			||||||
        groups = {} # The already encountered groups
 | 
					        groups = {} # The already encountered groups
 | 
				
			||||||
        # If a dict is given in p_cssJs, we must fill it with the CSS and JS
 | 
					        # If a dict is given in p_cssJs, we must fill it with the CSS and JS
 | 
				
			||||||
| 
						 | 
					@ -1603,4 +1604,11 @@ class BaseMixin:
 | 
				
			||||||
        '''This method is a general hook for transfering processing of a request
 | 
					        '''This method is a general hook for transfering processing of a request
 | 
				
			||||||
           to a given field, whose name must be in the request.'''
 | 
					           to a given field, whose name must be in the request.'''
 | 
				
			||||||
        return self.getAppyType(self.REQUEST['name']).process(self)
 | 
					        return self.getAppyType(self.REQUEST['name']).process(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def callField(self, name, method, *args, **kwargs):
 | 
				
			||||||
 | 
					        '''This method i a general hook for calling a p_method defined on a
 | 
				
			||||||
 | 
					           field named p_name.'''
 | 
				
			||||||
 | 
					        field = self.getAppyType(name)
 | 
				
			||||||
 | 
					        exec 'res = field.%s(*args, **kwargs)' % method
 | 
				
			||||||
 | 
					        return res
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										48
									
								
								gen/po.py
									
										
									
									
									
								
							
							
						
						
									
										48
									
								
								gen/po.py
									
										
									
									
									
								
							| 
						 | 
					@ -19,8 +19,7 @@ msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
'''
 | 
					'''
 | 
				
			||||||
fallbacks = {'en': 'en-us en-ca',
 | 
					fallbacks = {'en': 'en-us en-ca',
 | 
				
			||||||
             'fr': 'fr-be fr-ca fr-lu fr-mc fr-ch fr-fr'
 | 
					             'fr': 'fr-be fr-ca fr-lu fr-mc fr-ch fr-fr'}
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
class PoMessage:
 | 
					class PoMessage:
 | 
				
			||||||
| 
						 | 
					@ -169,6 +168,51 @@ class PoMessage:
 | 
				
			||||||
    OBJECT_AUTHOR = 'Author'
 | 
					    OBJECT_AUTHOR = 'Author'
 | 
				
			||||||
    ACTION_DATE = 'Date'
 | 
					    ACTION_DATE = 'Date'
 | 
				
			||||||
    ACTION_COMMENT = 'Comment'
 | 
					    ACTION_COMMENT = 'Comment'
 | 
				
			||||||
 | 
					    DAY_MON_SHORT = 'Mon'
 | 
				
			||||||
 | 
					    DAY_TUE_SHORT = 'Tue'
 | 
				
			||||||
 | 
					    DAY_WED_SHORT = 'Wed'
 | 
				
			||||||
 | 
					    DAY_THU_SHORT = 'Thu'
 | 
				
			||||||
 | 
					    DAY_FRI_SHORT = 'Fri'
 | 
				
			||||||
 | 
					    DAY_SAT_SHORT = 'Sat'
 | 
				
			||||||
 | 
					    DAY_SUN_SHORT = 'Sun'
 | 
				
			||||||
 | 
					    DAY_MON = 'Monday'
 | 
				
			||||||
 | 
					    DAY_TUE = 'Tuesday'
 | 
				
			||||||
 | 
					    DAY_WED = 'Wednesday'
 | 
				
			||||||
 | 
					    DAY_THU = 'Thursday'
 | 
				
			||||||
 | 
					    DAY_FRI = 'Friday'
 | 
				
			||||||
 | 
					    DAY_SAT = 'Saturday'
 | 
				
			||||||
 | 
					    DAY_SUN = 'Sunday'
 | 
				
			||||||
 | 
					    AMPM_AM = 'AM'
 | 
				
			||||||
 | 
					    AMPM_PM = 'PM'
 | 
				
			||||||
 | 
					    MONTH_JAN_SHORT = 'Jan'
 | 
				
			||||||
 | 
					    MONTH_FEB_SHORT = 'Feb'
 | 
				
			||||||
 | 
					    MONTH_MAR_SHORT = 'Mar'
 | 
				
			||||||
 | 
					    MONTH_APR_SHORT = 'Apr'
 | 
				
			||||||
 | 
					    MONTH_MAY_SHORT = 'May'
 | 
				
			||||||
 | 
					    MONTH_JUN_SHORT = 'Jun'
 | 
				
			||||||
 | 
					    MONTH_JUL_SHORT = 'Jul'
 | 
				
			||||||
 | 
					    MONTH_AUG_SHORT = 'Aug'
 | 
				
			||||||
 | 
					    MONTH_SEP_SHORT = 'Sep'
 | 
				
			||||||
 | 
					    MONTH_OCT_SHORT = 'Oct'
 | 
				
			||||||
 | 
					    MONTH_NOV_SHORT = 'Nov'
 | 
				
			||||||
 | 
					    MONTH_DEC_SHORT = 'Dec'
 | 
				
			||||||
 | 
					    MONTH_JAN = 'January'
 | 
				
			||||||
 | 
					    MONTH_FEB = 'February'
 | 
				
			||||||
 | 
					    MONTH_MAR = 'March'
 | 
				
			||||||
 | 
					    MONTH_APR = 'April'
 | 
				
			||||||
 | 
					    MONTH_MAY = 'May'
 | 
				
			||||||
 | 
					    MONTH_JUN = 'June'
 | 
				
			||||||
 | 
					    MONTH_JUL = 'July'
 | 
				
			||||||
 | 
					    MONTH_AUG = 'Augustus'
 | 
				
			||||||
 | 
					    MONTH_SEP = 'September'
 | 
				
			||||||
 | 
					    MONTH_OCT = 'October'
 | 
				
			||||||
 | 
					    MONTH_NOV = 'November'
 | 
				
			||||||
 | 
					    MONTH_DEC = 'December'
 | 
				
			||||||
 | 
					    TODAY = 'Today'
 | 
				
			||||||
 | 
					    WHICH_EVENT = 'Which event type would you like to create?'
 | 
				
			||||||
 | 
					    EVENT_SPAN = 'Extend the event on the following number of days (leave ' \
 | 
				
			||||||
 | 
					                 'blank to create an event on the current day only):'
 | 
				
			||||||
 | 
					    DEL_NEXT_EVENTS = 'Also delete successive events of the same type.'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, id, msg, default, fuzzy=False, comments=[],
 | 
					    def __init__(self, id, msg, default, fuzzy=False, comments=[],
 | 
				
			||||||
                 niceDefault=False):
 | 
					                 niceDefault=False):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
</tal:comment>
 | 
					</tal:comment>
 | 
				
			||||||
<tal:ajax define="contextObj context/getParentNode;
 | 
					<tal:ajax define="contextObj context/getParentNode;
 | 
				
			||||||
                  tool contextObj/getTool;
 | 
					                  tool contextObj/getTool;
 | 
				
			||||||
 | 
					                  _ python: contextObj.translate;
 | 
				
			||||||
                  req python: request;
 | 
					                  req python: request;
 | 
				
			||||||
                  resp req/RESPONSE;
 | 
					                  resp req/RESPONSE;
 | 
				
			||||||
                  page req/page;
 | 
					                  page req/page;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -384,8 +384,10 @@ function generatePodDocument(contextUid, fieldName, podFormat, queryData) {
 | 
				
			||||||
// Functions for opening and closing a popup
 | 
					// Functions for opening and closing a popup
 | 
				
			||||||
function openPopup(popupId, msg) {
 | 
					function openPopup(popupId, msg) {
 | 
				
			||||||
  // Put the message into the popup
 | 
					  // Put the message into the popup
 | 
				
			||||||
 | 
					  if (msg) {
 | 
				
			||||||
    var confirmElem = document.getElementById('appyConfirmText');
 | 
					    var confirmElem = document.getElementById('appyConfirmText');
 | 
				
			||||||
    confirmElem.innerHTML = msg;
 | 
					    confirmElem.innerHTML = msg;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  // Open the popup
 | 
					  // Open the popup
 | 
				
			||||||
  var popup = document.getElementById(popupId);
 | 
					  var popup = document.getElementById(popupId);
 | 
				
			||||||
  // Put it at the right place on the screen
 | 
					  // Put it at the right place on the screen
 | 
				
			||||||
| 
						 | 
					@ -451,8 +453,8 @@ function doConfirm() {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var wrongTextInput = '#F0C36D none';
 | 
					var wrongTextInput = '#F9EDBE none';
 | 
				
			||||||
// Function triggered when the user ask password reinitialisation
 | 
					// Function triggered when the user asks password reinitialisation
 | 
				
			||||||
function doAskPasswordReinit() {
 | 
					function doAskPasswordReinit() {
 | 
				
			||||||
  // Check that the user has typed a login
 | 
					  // Check that the user has typed a login
 | 
				
			||||||
  var theForm = document.getElementById('askPasswordReinitForm');
 | 
					  var theForm = document.getElementById('askPasswordReinitForm');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,11 +14,6 @@
 | 
				
			||||||
                groupedWidgets python: contextObj.getGroupedAppyTypes(layoutType, page, cssJs=cssJs);"
 | 
					                groupedWidgets python: contextObj.getGroupedAppyTypes(layoutType, page, cssJs=cssJs);"
 | 
				
			||||||
    tal:on-error="structure python: tool.manageError(error)">
 | 
					    tal:on-error="structure python: tool.manageError(error)">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <tal:comment replace="nothing">Include type-specific CSS and JS.</tal:comment>
 | 
					 | 
				
			||||||
  <link tal:repeat="cssFile cssJs/css" rel="stylesheet" type="text/css"
 | 
					 | 
				
			||||||
        tal:attributes="href string:$appUrl/ui/$cssFile"/>
 | 
					 | 
				
			||||||
  <script tal:repeat="jsFile cssJs/js" type="text/javascript"
 | 
					 | 
				
			||||||
          tal:attributes="src string:$appUrl/ui/$jsFile"></script>
 | 
					 | 
				
			||||||
  <metal:prologue use-macro="context/ui/page/macros/prologue"/>
 | 
					  <metal:prologue use-macro="context/ui/page/macros/prologue"/>
 | 
				
			||||||
  <form id="appyEditForm" name="appyEditForm" method="post" enctype="multipart/form-data"
 | 
					  <form id="appyEditForm" name="appyEditForm" method="post" enctype="multipart/form-data"
 | 
				
			||||||
        tal:attributes="action python: contextObj.absolute_url()+'/do';
 | 
					        tal:attributes="action python: contextObj.absolute_url()+'/do';
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,14 @@
 | 
				
			||||||
  This macro contains global page-related Javascripts.
 | 
					  This macro contains global page-related Javascripts.
 | 
				
			||||||
</tal:comment>
 | 
					</tal:comment>
 | 
				
			||||||
<div metal:define-macro="prologue">
 | 
					<div metal:define-macro="prologue">
 | 
				
			||||||
 | 
					  <tal:comment replace="nothing">Include type-specific CSS and JS.</tal:comment>
 | 
				
			||||||
 | 
					  <tal:include condition="cssJs|nothing">
 | 
				
			||||||
 | 
					   <link tal:repeat="cssFile cssJs/css" rel="stylesheet" type="text/css"
 | 
				
			||||||
 | 
					         tal:attributes="href string:$appUrl/ui/$cssFile"/>
 | 
				
			||||||
 | 
					   <script tal:repeat="jsFile cssJs/js" type="text/javascript"
 | 
				
			||||||
 | 
					           tal:attributes="src string:$appUrl/ui/$jsFile"></script>
 | 
				
			||||||
 | 
					  </tal:include>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <tal:comment replace="nothing">Javascript messages</tal:comment>
 | 
					  <tal:comment replace="nothing">Javascript messages</tal:comment>
 | 
				
			||||||
  <script language="javascript" tal:content="tool/getJavascriptMessages"></script>
 | 
					  <script language="javascript" tal:content="tool/getJavascriptMessages"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +18,7 @@
 | 
				
			||||||
    <input type="hidden" name="action" value="Delete"/>
 | 
					    <input type="hidden" name="action" value="Delete"/>
 | 
				
			||||||
    <input type="hidden" name="objectUid"/>
 | 
					    <input type="hidden" name="objectUid"/>
 | 
				
			||||||
  </form>
 | 
					  </form>
 | 
				
			||||||
  <tal:comment replace="nothing">Global form for generating a document from a pod template.</tal:comment>
 | 
					  <tal:comment replace="nothing">Global form for generating a document from a pod template</tal:comment>
 | 
				
			||||||
  <form name="podTemplateForm" method="post"
 | 
					  <form name="podTemplateForm" method="post"
 | 
				
			||||||
        tal:attributes="action python: tool.absolute_url() + '/generateDocument'">
 | 
					        tal:attributes="action python: tool.absolute_url() + '/generateDocument'">
 | 
				
			||||||
    <input type="hidden" name="objectUid"/>
 | 
					    <input type="hidden" name="objectUid"/>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,9 +8,11 @@
 | 
				
			||||||
                layout         python: contextObj.getPageLayout(layoutType);
 | 
					                layout         python: contextObj.getPageLayout(layoutType);
 | 
				
			||||||
                phaseInfo      python: contextObj.getAppyPhases(currentOnly=True, layoutType='view');
 | 
					                phaseInfo      python: contextObj.getAppyPhases(currentOnly=True, layoutType='view');
 | 
				
			||||||
                phase          phaseInfo/name;
 | 
					                phase          phaseInfo/name;
 | 
				
			||||||
 | 
					                cssJs          python: {};
 | 
				
			||||||
                page           req/page|python:contextObj.getDefaultViewPage();
 | 
					                page           req/page|python:contextObj.getDefaultViewPage();
 | 
				
			||||||
                groupedWidgets python: contextObj.getGroupedAppyTypes(layoutType, page);"
 | 
					                groupedWidgets python: contextObj.getGroupedAppyTypes(layoutType, page, cssJs=cssJs);"
 | 
				
			||||||
    tal:on-error="structure python: tool.manageError(error)">
 | 
					    tal:on-error="structure python: tool.manageError(error)">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <metal:prologue use-macro="context/ui/page/macros/prologue"/>
 | 
					  <metal:prologue use-macro="context/ui/page/macros/prologue"/>
 | 
				
			||||||
  <metal:show use-macro="context/ui/page/macros/show"/>
 | 
					  <metal:show use-macro="context/ui/page/macros/show"/>
 | 
				
			||||||
  <metal:footer use-macro="context/ui/page/macros/footer"/>
 | 
					  <metal:footer use-macro="context/ui/page/macros/footer"/>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										49
									
								
								gen/ui/widgets/calendar.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								gen/ui/widgets/calendar.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					function askMonthView(hookId, objectUrl, fieldName, month) {
 | 
				
			||||||
 | 
					  // Sends an Ajax request for getting the view month of a calendar field
 | 
				
			||||||
 | 
					  var params = {'fieldName': fieldName, 'month': month};
 | 
				
			||||||
 | 
					  askAjaxChunk(hookId,'GET',objectUrl,'widgets/calendar','viewMonth', params);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function openEventPopup(action, fieldName, day, spansDays) {
 | 
				
			||||||
 | 
					  /* Opens the popup for creating (or deleting, depending on p_action) a
 | 
				
			||||||
 | 
					     calendar event at some p_day. When action is "del", we need to know
 | 
				
			||||||
 | 
					     (from p_spansDays) if the event spans more days, in order to propose a
 | 
				
			||||||
 | 
					     checkbox allowing to delete events for those successive days. */
 | 
				
			||||||
 | 
					  var prefix = fieldName + '_' + action + 'Event';
 | 
				
			||||||
 | 
					  var f = document.getElementById(prefix + 'Form');
 | 
				
			||||||
 | 
					  f.day.value = day;
 | 
				
			||||||
 | 
					  if (action == 'del') {
 | 
				
			||||||
 | 
					    var elem = document.getElementById(prefix + 'DelNextEvent');
 | 
				
			||||||
 | 
					    var cb = elem.getElementsByTagName('input');
 | 
				
			||||||
 | 
					    cb[0].checked = false;
 | 
				
			||||||
 | 
					    cb[1].value = 'False';
 | 
				
			||||||
 | 
					    if (spansDays == 'True') { elem.style.display = 'block' }
 | 
				
			||||||
 | 
					    else { elem.style.display = 'none' }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  openPopup(prefix + 'Popup');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function triggerCalendarEvent(action, hookId, fieldName, objectUrl) {
 | 
				
			||||||
 | 
					  /* Sends an Ajax request for triggering a calendar event (create or delete an
 | 
				
			||||||
 | 
					     event) and refreshing the view month. */
 | 
				
			||||||
 | 
					  var prefix = fieldName + '_' + action + 'Event';
 | 
				
			||||||
 | 
					  var f = document.getElementById(prefix + 'Form');
 | 
				
			||||||
 | 
					  if (action == 'new') {
 | 
				
			||||||
 | 
					    // Check that eventSpan is empty or contains a valid number
 | 
				
			||||||
 | 
					    var spanNumber = f.eventSpan.value.replace(' ', '');
 | 
				
			||||||
 | 
					    if (spanNumber) {
 | 
				
			||||||
 | 
					      if (isNaN(parseInt(spanNumber))) {
 | 
				
			||||||
 | 
					        f.eventSpan.style.background = wrongTextInput;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  var elems = f.elements;
 | 
				
			||||||
 | 
					  var params = {};
 | 
				
			||||||
 | 
					  // Put form elements into "params".
 | 
				
			||||||
 | 
					  for (var i=0; i < elems.length; i++) {
 | 
				
			||||||
 | 
					    params[elems[i].name] = elems[i].value;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  closePopup(prefix + 'Popup');
 | 
				
			||||||
 | 
					  askAjaxChunk(hookId,'POST',objectUrl,'widgets/calendar','viewMonth',params);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										163
									
								
								gen/ui/widgets/calendar.pt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								gen/ui/widgets/calendar.pt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,163 @@
 | 
				
			||||||
 | 
					<tal:comment replace="nothing">View macro</tal:comment>
 | 
				
			||||||
 | 
					<div metal:define-macro="viewMonth"
 | 
				
			||||||
 | 
					     tal:define="fieldName request/fieldName;
 | 
				
			||||||
 | 
					                 ajaxHookId python: contextObj.UID() + fieldName;
 | 
				
			||||||
 | 
					                 month request/month;
 | 
				
			||||||
 | 
					                 monthDayOne python: DateTime('%s/01' % month);
 | 
				
			||||||
 | 
					                 today python: DateTime('00:00');
 | 
				
			||||||
 | 
					                 todayMonth python: today.strftime('%Y/%m');
 | 
				
			||||||
 | 
					                 grid python: contextObj.callField(fieldName, 'getMonthGrid', month);
 | 
				
			||||||
 | 
					                 previousMonth python: contextObj.callField(fieldName, 'getSiblingMonth', month, 'previous');
 | 
				
			||||||
 | 
					                 nextMonth python: contextObj.callField(fieldName, 'getSiblingMonth', month, 'next');
 | 
				
			||||||
 | 
					                 widget python: contextObj.getAppyType(fieldName, asDict=True);
 | 
				
			||||||
 | 
					                 mayEdit python: contextObj.allows(widget['writePermission']);
 | 
				
			||||||
 | 
					                 objUrl contextObj/absolute_url"
 | 
				
			||||||
 | 
					     tal:attributes="id ajaxHookId">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<tal:comment replace="nothing">Month chooser</tal:comment>
 | 
				
			||||||
 | 
					<div style="margin-bottom: 5px">
 | 
				
			||||||
 | 
					 <img style="cursor:pointer"
 | 
				
			||||||
 | 
					      tal:attributes="src string: $appUrl/ui/arrowLeftSimple.png;
 | 
				
			||||||
 | 
					                      onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,previousMonth)"/>
 | 
				
			||||||
 | 
					 <input type="button"
 | 
				
			||||||
 | 
					        tal:attributes="value python: _('today');
 | 
				
			||||||
 | 
					                        onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,todayMonth);
 | 
				
			||||||
 | 
					                        disabled monthDayOne/isCurrentMonth"/>
 | 
				
			||||||
 | 
					 <img style="cursor:pointer"
 | 
				
			||||||
 | 
					      tal:attributes="src string: $appUrl/ui/arrowRightSimple.png;
 | 
				
			||||||
 | 
					                      onclick python: 'askMonthView(\'%s\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,objUrl,fieldName,nextMonth)"/>
 | 
				
			||||||
 | 
					 <span tal:content="python: _('month_%s' % monthDayOne.aMonth())"></span>
 | 
				
			||||||
 | 
					 <span tal:content="python: month.split('/')[0]"></span>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<tal:comment replace="nothing">Calendar month view</tal:comment>
 | 
				
			||||||
 | 
					<table cellpadding="0" cellspacing="0" width="100%" class="list" style="font-size: 95%"
 | 
				
			||||||
 | 
					       tal:define="rowHeight python: int(widget['height']/float(len(grid)))">
 | 
				
			||||||
 | 
					  <tal:comment replace="nothing">1st row: names of days</tal:comment>
 | 
				
			||||||
 | 
					  <tr height="22px">
 | 
				
			||||||
 | 
					   <th tal:repeat="dayName python: contextObj.callField(fieldName, 'getNamesOfDays', contextObj)"
 | 
				
			||||||
 | 
					       tal:content="dayName" width="14%">
 | 
				
			||||||
 | 
					   </th>
 | 
				
			||||||
 | 
					  </tr>
 | 
				
			||||||
 | 
					  <tal:comment replace="nothing">The calendar in itself</tal:comment>
 | 
				
			||||||
 | 
					  <tr tal:repeat="row grid" valign="top" tal:attributes="height rowHeight">
 | 
				
			||||||
 | 
					   <tal:cell repeat="date row">
 | 
				
			||||||
 | 
					   <td tal:define="events python: contextObj.callField(fieldName, 'getEventsAt', contextObj, date);
 | 
				
			||||||
 | 
					                   spansDays python: contextObj.callField(fieldName, 'hasEventsAt', contextObj, date+1, events);
 | 
				
			||||||
 | 
					                   mayCreate python: mayEdit and not events;
 | 
				
			||||||
 | 
					                   mayDelete python: mayEdit and events;"
 | 
				
			||||||
 | 
					       tal:attributes="style python: test(date.isCurrentDay(), 'font-weight:bold', 'font-weight:normal');
 | 
				
			||||||
 | 
					                       class python: test(date < today, 'even', 'odd');
 | 
				
			||||||
 | 
					                       onmouseover python: test(mayEdit, 'this.getElementsByTagName(\'img\')[0].style.visibility=\'visible\'', '');
 | 
				
			||||||
 | 
					                       onmouseout python: test(mayEdit, 'this.getElementsByTagName(\'img\')[0].style.visibility=\'hidden\'', '')">
 | 
				
			||||||
 | 
					    <tal:day define="day date/day;
 | 
				
			||||||
 | 
					                     dayString python: date.strftime('%Y/%m/%d')">
 | 
				
			||||||
 | 
					     <span tal:content="day"></span>
 | 
				
			||||||
 | 
					     <span tal:condition="python: day == 1"
 | 
				
			||||||
 | 
					           tal:content="python: _('month_%s_short' % date.aMonth())"></span>
 | 
				
			||||||
 | 
					     <tal:comment replace="nothing">Icon for adding an event</tal:comment>
 | 
				
			||||||
 | 
					     <img tal:condition="mayCreate" style="visibility:hidden; cursor:pointer"
 | 
				
			||||||
 | 
					          tal:attributes="src string: $appUrl/ui/plus.png;
 | 
				
			||||||
 | 
					                          onclick python: 'openEventPopup(\'new\',\'%s\',\'%s\')' % (fieldName, dayString)"/>
 | 
				
			||||||
 | 
					     <tal:comment replace="nothing">Icon for deleting an event</tal:comment>
 | 
				
			||||||
 | 
					     <img tal:condition="mayDelete" style="visibility:hidden; cursor:pointer"
 | 
				
			||||||
 | 
					          tal:attributes="src string: $appUrl/ui/delete.png;
 | 
				
			||||||
 | 
					                          onclick python: 'openEventPopup(\'del\',\'%s\',\'%s\',\'%s\')' % (fieldName, dayString, str(spansDays))"/>
 | 
				
			||||||
 | 
					     <tal:events condition="events">
 | 
				
			||||||
 | 
					       <tal:comment replace="nothing">A single event is allowed for the moment</tal:comment>
 | 
				
			||||||
 | 
					       <div tal:define="eventType python: events[0]['eventType']">
 | 
				
			||||||
 | 
					        <span style="color: grey"
 | 
				
			||||||
 | 
					              tal:content="python: _('%s_event_%s' % (widget['labelId'], eventType))"></span>
 | 
				
			||||||
 | 
					       </div>
 | 
				
			||||||
 | 
					     </tal:events>
 | 
				
			||||||
 | 
					    </tal:day>
 | 
				
			||||||
 | 
					   </td>
 | 
				
			||||||
 | 
					   </tal:cell>
 | 
				
			||||||
 | 
					  </tr>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<tal:comment replace="nothing">Popup for creating a calendar event</tal:comment>
 | 
				
			||||||
 | 
					<div tal:define="prefix python: '%s_newEvent' % fieldName;
 | 
				
			||||||
 | 
					                 popupId python: prefix + 'Popup'"
 | 
				
			||||||
 | 
					     tal:attributes="id popupId" class="popup" align="center">
 | 
				
			||||||
 | 
					 <form tal:attributes="id python: prefix + 'Form'" method="post">
 | 
				
			||||||
 | 
					  <input type="hidden" name="fieldName" tal:attributes="value fieldName"/>
 | 
				
			||||||
 | 
					  <input type="hidden" name="month" tal:attributes="value month"/>
 | 
				
			||||||
 | 
					  <input type="hidden" name="name" tal:attributes="value fieldName"/>
 | 
				
			||||||
 | 
					  <input type="hidden" name="action" value="Process"/>
 | 
				
			||||||
 | 
					  <input type="hidden" name="actionType" value="createEvent"/>
 | 
				
			||||||
 | 
					  <input type="hidden" name="day"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <div align="center" style="margin-bottom: 3px" tal:content="python: _('which_event')"></div>
 | 
				
			||||||
 | 
					  <select name="eventType">
 | 
				
			||||||
 | 
					   <option tal:repeat="eventType widget/eventTypes"
 | 
				
			||||||
 | 
					           tal:content="python: _('%s_event_%s' % (widget['labelId'], eventType))"
 | 
				
			||||||
 | 
					           tal:attributes="value eventType">
 | 
				
			||||||
 | 
					   </option>
 | 
				
			||||||
 | 
					  </select><br/><br/>
 | 
				
			||||||
 | 
					  <tal:comment replace="nothing">Span the event on several days</tal:comment>
 | 
				
			||||||
 | 
					  <div align="center" class="discreet" style="margin-bottom: 3px">
 | 
				
			||||||
 | 
					   <span tal:content="python: _('event_span')"></span>
 | 
				
			||||||
 | 
					   <input type="text" size="3" name="eventSpan"/>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					  <input type="button"
 | 
				
			||||||
 | 
					         tal:attributes="value python:_('object_save');
 | 
				
			||||||
 | 
					                         onClick python: 'triggerCalendarEvent(\'new\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,fieldName,objUrl)"/>
 | 
				
			||||||
 | 
					  <input type="button"
 | 
				
			||||||
 | 
					         tal:attributes="value python:_('object_cancel');
 | 
				
			||||||
 | 
					                         onclick python: 'closePopup(\'%s\')' % popupId"/>
 | 
				
			||||||
 | 
					 </form>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<tal:comment replace="nothing">Popup for deleting a calendar event</tal:comment>
 | 
				
			||||||
 | 
					<div tal:define="prefix python: '%s_delEvent' % fieldName;
 | 
				
			||||||
 | 
					                 popupId python: prefix + 'Popup'"
 | 
				
			||||||
 | 
					     tal:attributes="id popupId" class="popup" align="center">
 | 
				
			||||||
 | 
					 <form tal:attributes="id python: prefix + 'Form'" method="post">
 | 
				
			||||||
 | 
					  <input type="hidden" name="fieldName" tal:attributes="value fieldName"/>
 | 
				
			||||||
 | 
					  <input type="hidden" name="month" tal:attributes="value month"/>
 | 
				
			||||||
 | 
					  <input type="hidden" name="name" tal:attributes="value fieldName"/>
 | 
				
			||||||
 | 
					  <input type="hidden" name="action" value="Process"/>
 | 
				
			||||||
 | 
					  <input type="hidden" name="actionType" value="deleteEvent"/>
 | 
				
			||||||
 | 
					  <input type="hidden" name="day"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <div align="center" style="margin-bottom: 5px"
 | 
				
			||||||
 | 
					       tal:content="python: _('delete_confirm')"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <tal:comment replace="nothing">Delete successive events?</tal:comment>
 | 
				
			||||||
 | 
					  <div class="discreet" style="margin-bottom: 10px"
 | 
				
			||||||
 | 
					       tal:attributes="id python: prefix + 'DelNextEvent'">
 | 
				
			||||||
 | 
					    <input type="checkbox" name="deleteNext_cb"
 | 
				
			||||||
 | 
					           tal:attributes="id python: prefix + '_cb';
 | 
				
			||||||
 | 
					                           onClick python:'toggleCheckbox(\'%s_cb\', \'%s_hd\')' % (prefix, prefix);"/>
 | 
				
			||||||
 | 
					    <input type="hidden" tal:attributes="id python: prefix + '_hd'" name="deleteNext"/>
 | 
				
			||||||
 | 
					    <span tal:content="python: _('del_next_events')"/>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					  <input type="button"
 | 
				
			||||||
 | 
					         tal:attributes="value python:_('yes');
 | 
				
			||||||
 | 
					                         onClick python: 'triggerCalendarEvent(\'del\',\'%s\',\'%s\',\'%s\')' % (ajaxHookId,fieldName,objUrl)"/>
 | 
				
			||||||
 | 
					  <input type="button"
 | 
				
			||||||
 | 
					         tal:attributes="value python:_('no');
 | 
				
			||||||
 | 
					                         onclick python: 'closePopup(\'%s\')' % popupId"/>
 | 
				
			||||||
 | 
					 </form>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<tal:comment replace="nothing">View macro</tal:comment>
 | 
				
			||||||
 | 
					<metal:view define-macro="view"
 | 
				
			||||||
 | 
					            tal:define="now python: DateTime();
 | 
				
			||||||
 | 
					                        dummy python: request.set('fieldName', widget['name']);
 | 
				
			||||||
 | 
					                        dummy python: request.set('month', now.strftime('%Y/%m'))">
 | 
				
			||||||
 | 
					 <metal:call use-macro="app/ui/widgets/calendar/macros/viewMonth"/>
 | 
				
			||||||
 | 
					</metal:view>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<tal:comment replace="nothing">Edit macro</tal:comment>
 | 
				
			||||||
 | 
					<metal:edit define-macro="edit"></metal:edit>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<tal:comment replace="nothing">Cell macro</tal:comment>
 | 
				
			||||||
 | 
					<metal:cell define-macro="cell">
 | 
				
			||||||
 | 
					  <metal:call use-macro="app/ui/widgets/calendar/macros/view"/>
 | 
				
			||||||
 | 
					</metal:cell>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<tal:comment replace="nothing">Search macro</tal:comment>
 | 
				
			||||||
 | 
					<metal:search define-macro="search"></metal:search>
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue