def localised_nice_date(datetime_): ''' Returns a friendly localised unicode representation of a datetime. ''' now = datetime.datetime.now() date_diff = now - datetime_ days = date_diff.days if days < 1 and now > datetime_: # less than one day seconds = date_diff.seconds if seconds < 3600: # less than one hour if seconds < 60: return _('Just now') else: return ungettext('{mins} minute ago', '{mins} minutes ago', seconds / 60).format(mins=seconds / 60) else: return ungettext('{hours} hour ago', '{hours} hours ago', seconds / 3600).format(hours=seconds / 3600) # more than one day if days < 31: return ungettext('{days} day ago', '{days} days ago', days).format(days=days) # actual date month = datetime_.month day = datetime_.day year = datetime_.year month_name = _MONTH_FUNCTIONS[month - 1]() return _('{month} {day}, {year}').format(month=month_name, day=day, year=year)
def _translations(): """ Does nothing but hints message extractor to extract missing strings. """ from ckan.common import _, ungettext _("An URL-address which refers to the dataset. The automatically filled option derived" " from the title is the best option in most cases.") _("Category which represents showcase.") _("Platforms of the showcase.") _("Keywords or tags through which users are able to find this dataset easily through the" " search page or other datasets which have the same tag.") _("Author Website") _("Application Website") _("Links to stores") _("Kuvaus") _("An universal, compact and easy to understand description of the added resource." ) _("Featured") _("Icon") _("Featured Image") _("Image 1") _("Image 2") _("Image 3") _("Notifier") _("Notifier Email") _("eg. android") _("eg. visualization") _("eg. traffic") ungettext("The dataset has been added to the showcase.", "The datasets have been added to the showcase.", 2) ungettext("The dataset has been removed from the showcase.", "The datasets have been removed from the showcase.", 2)
def _translations(): """ Does nothing but hints message extractor to extract missing strings. """ from ckan.common import _, ungettext _("An URL-address which refers to the dataset. The automatically filled option derived" " from the title is the best option in most cases.") _("Category which represents showcase.") _("Platforms of the showcase.") _("Keywords or tags through which users are able to find this dataset easily through the" " search page or other datasets which have the same tag.") _("Author Website") _("Application Website") _("Links to stores") _("Kuvaus") _("An universal, compact and easy to understand description of the added resource.") _("Featured") _("Icon") _("Featured Image") _("Image 1") _("Image 2") _("Image 3") _("Notifier") _("Notifier Email") _("eg. android") _("eg. visualization") _("eg. traffic") ungettext("The dataset has been added to the showcase.", "The datasets have been added to the showcase.", 2) ungettext("The dataset has been removed from the showcase.", "The datasets have been removed from the showcase.", 2)
def hdx_popular(type_, number, min=1, title=None): ''' display a popular icon. ''' from ckan.lib.helpers import snippet as snippet if type_ == 'views': title = ungettext('{number} view', '{number} views', number) elif type_ == 'recent views': title = ungettext('{number} recent view', '{number} recent views', number) elif type_ == 'downloads': title = ungettext('{number} download', '{number} downloads', number) elif not title: raise Exception('popular() did not recieve a valid type_ or title') return snippet('snippets/popular.html', title=title, number=number, min=min)
def localised_nice_date(datetime_, show_date=False, with_hours=False): ''' Returns a friendly localised unicode representation of a datetime. :param datetime_: The date to format :type datetime_: datetime :param show_date: Show date not 2 days ago etc :type show_date: bool :param with_hours: should the `hours:mins` be shown for dates :type with_hours: bool :rtype: sting ''' if not show_date: now = datetime.datetime.now() date_diff = now - datetime_ days = date_diff.days if days < 1 and now > datetime_: # less than one day seconds = date_diff.seconds if seconds < 3600: # less than one hour if seconds < 60: return _('Just now') else: return ungettext('{mins} minute ago', '{mins} minutes ago', seconds / 60).format(mins=seconds / 60) else: return ungettext('{hours} hour ago', '{hours} hours ago', seconds / 3600).format(hours=seconds / 3600) # more than one day if days < 31: return ungettext('{days} day ago', '{days} days ago', days).format(days=days) # actual date details = { 'min': datetime_.minute, 'hour': datetime_.hour, 'day': datetime_.day, 'year': datetime_.year, 'month': _MONTH_FUNCTIONS[datetime_.month - 1](), } if with_hours: return ( # NOTE: This is for translating dates like `April 24, 2013, 10:45` _('{month} {day}, {year}, {hour:02}:{min:02}').format(**details)) else: return ( # NOTE: This is for translating dates like `April 24, 2013` _('{month} {day}, {year}').format(**details))
def _notifications_for_activities( activities: list[dict[str, Any]], user_dict: dict[str, Any]) -> list[dict[str, str]]: '''Return one or more email notifications covering the given activities. This function handles grouping multiple activities into a single digest email. :param activities: the activities to consider :type activities: list of activity dicts like those returned by ckan.logic.action.get.dashboard_activity_list() :returns: a list of email notifications :rtype: list of dicts each with keys 'subject' and 'body' ''' if not activities: return [] if not user_dict.get('activity_streams_email_notifications'): return [] # We just group all activities into a single "new activity" email that # doesn't say anything about _what_ new activities they are. # TODO: Here we could generate some smarter content for the emails e.g. # say something about the contents of the activities, or single out # certain types of activity to be sent in their own individual emails, # etc. subject = ungettext( "{n} new activity from {site_title}", "{n} new activities from {site_title}", len(activities)).format( site_title=config.get_value('ckan.site_title'), n=len(activities)) body = render_activity_email(activities) notifications = [{ 'subject': subject, 'body': body }] return notifications
def _notifications_for_activities(activities, user_dict): '''Return one or more email notifications covering the given activities. This function handles grouping multiple activities into a single digest email. :param activities: the activities to consider :type activities: list of activity dicts like those returned by ckan.logic.action.get.dashboard_activity_list() :returns: a list of email notifications :rtype: list of dicts each with keys 'subject' and 'body' ''' if not activities: return [] if not user_dict.get('activity_streams_email_notifications'): return [] # We just group all activities into a single "new activity" email that # doesn't say anything about _what_ new activities they are. # TODO: Here we could generate some smarter content for the emails e.g. # say something about the contents of the activities, or single out # certain types of activity to be sent in their own individual emails, # etc. subject = ungettext( "{n} new activity from {site_title}", "{n} new activities from {site_title}", len(activities)).format( site_title=pylons.config.get('ckan.site_title'), n=len(activities)) body = base.render( 'activity_streams/activity_stream_email_notifications.text', extra_vars={'activities': activities}) notifications = [{ 'subject': subject, 'body': body }] return notifications
def localised_nice_date(datetime_, show_date=False, with_hours=False): ''' Returns a friendly localised unicode representation of a datetime. :param datetime_: The date to format :type datetime_: datetime :param show_date: Show date not 2 days ago etc :type show_date: bool :param with_hours: should the `hours:mins` be shown for dates :type with_hours: bool :rtype: sting ''' def months_between(date1, date2): if date1 > date2: date1, date2 = date2, date1 m1 = date1.year * 12 + date1.month m2 = date2.year * 12 + date2.month months = m2 - m1 if date1.day > date2.day: months -= 1 elif date1.day == date2.day: seconds1 = date1.hour * 3600 + date1.minute + date1.second seconds2 = date2.hour * 3600 + date2.minute + date2.second if seconds1 > seconds2: months -= 1 return months if not show_date: now = datetime.datetime.utcnow() if datetime_.tzinfo is not None: now = now.replace(tzinfo=datetime_.tzinfo) else: now = now.replace(tzinfo=pytz.utc) datetime_ = datetime_.replace(tzinfo=pytz.utc) date_diff = now - datetime_ days = date_diff.days if days < 1 and now > datetime_: # less than one day seconds = date_diff.seconds if seconds < 3600: # less than one hour if seconds < 60: return _('Just now') else: return ungettext('{mins} minute ago', '{mins} minutes ago', seconds / 60).format(mins=seconds / 60) else: return ungettext('{hours} hour ago', '{hours} hours ago', seconds / 3600).format(hours=seconds / 3600) # more than one day months = months_between(datetime_, now) if months < 1: return ungettext('{days} day ago', '{days} days ago', days).format(days=days) if months < 13: return ungettext('{months} month ago', '{months} months ago', months).format(months=months) return ungettext('over {years} year ago', 'over {years} years ago', months / 12).format(years=months / 12) # actual date details = { 'min': datetime_.minute, 'hour': datetime_.hour, 'day': datetime_.day, 'year': datetime_.year, 'month': _MONTH_FUNCTIONS[datetime_.month - 1](), 'timezone': datetime_.tzinfo.zone, } if with_hours: return ( # NOTE: This is for translating dates like `April 24, 2013, 10:45 (Europe/Zurich)` _('{month} {day}, {year}, {hour:02}:{min:02} ({timezone})') \ .format(**details)) else: return ( # NOTE: This is for translating dates like `April 24, 2013` _('{month} {day}, {year}').format(**details))
def localised_nice_date(datetime_, show_date=False, with_hours=False, with_seconds=False): ''' Returns a friendly localised unicode representation of a datetime. e.g. '31 minutes ago' '1 day ago' 'April 24, 2013' (show_date=True) :param datetime_: The date to format :type datetime_: datetime :param show_date: Show 'April 24, 2013' instead of '2 days ago' :type show_date: bool :param with_hours: should the `hours:mins` be shown for dates :type with_hours: bool :param with_seconds: should the `hours:mins:seconds` be shown for dates :type with_seconds: bool :rtype: sting ''' def months_between(date1, date2): if date1 > date2: date1, date2 = date2, date1 m1 = date1.year * 12 + date1.month m2 = date2.year * 12 + date2.month months = m2 - m1 if date1.day > date2.day: months -= 1 elif date1.day == date2.day: seconds1 = date1.hour * 3600 + date1.minute + date1.second seconds2 = date2.hour * 3600 + date2.minute + date2.second if seconds1 > seconds2: months -= 1 return months if not show_date: now = datetime.datetime.now(pytz.utc) if datetime_.tzinfo is None: datetime_ = datetime_.replace(tzinfo=pytz.utc) date_diff = now - datetime_ days = date_diff.days if days < 1 and now > datetime_: # less than one day seconds = date_diff.seconds if seconds < 3600: # less than one hour if seconds < 60: return _('Just now') else: return ungettext('{mins} minute ago', '{mins} minutes ago', seconds // 60).format(mins=seconds // 60) else: return ungettext('{hours} hour ago', '{hours} hours ago', seconds // 3600).format(hours=seconds // 3600) # more than one day months = months_between(datetime_, now) if months < 1: return ungettext('{days} day ago', '{days} days ago', days).format(days=days) if months < 13: return ungettext('{months} month ago', '{months} months ago', months).format(months=months) return ungettext('over {years} year ago', 'over {years} years ago', months // 12).format(years=months // 12) # actual date details = { 'sec': int(datetime_.second), 'min': datetime_.minute, 'hour': datetime_.hour, 'day': datetime_.day, 'year': datetime_.year, 'month': _MONTH_FUNCTIONS[datetime_.month - 1](), 'timezone': datetime_.tzname(), } if with_seconds: return ( # Example output: `April 24, 2013, 10:45:21 (Europe/Zurich)` _('{month} {day}, {year}, {hour:02}:{min:02}:{sec:02} ({timezone})') \ .format(**details)) elif with_hours: return ( # Example output: `April 24, 2013, 10:45 (Europe/Zurich)` _('{month} {day}, {year}, {hour:02}:{min:02} ({timezone})') \ .format(**details)) else: return ( # Example output: `April 24, 2013` _('{month} {day}, {year}').format(**details))
def manage_datasets(self, id): ''' List datasets associated with the given showcase id. ''' context = { 'model': model, 'session': model.Session, 'user': c.user or c.author } data_dict = {'id': id} try: check_access('ckanext_showcase_update', context) except NotAuthorized: abort( 401, _('User not authorized to edit {showcase_id}').format( showcase_id=id)) # check if showcase exists try: c.pkg_dict = get_action('package_show')(context, data_dict) except NotFound: abort(404, _('Showcase not found')) except NotAuthorized: abort(401, _('Unauthorized to read showcase')) # Are we removing a showcase/dataset association? if (request.method == 'POST' and 'bulk_action.showcase_remove' in request.params): # Find the datasets to perform the action on, they are prefixed by # dataset_ in the form data dataset_ids = [] for param in request.params: if param.startswith('dataset_'): dataset_ids.append(param[8:]) if dataset_ids: for dataset_id in dataset_ids: get_action('ckanext_showcase_package_association_delete')( context, { 'showcase_id': c.pkg_dict['id'], 'package_id': dataset_id }) h.flash_success( ungettext( "The dataset has been removed from the showcase.", "The datasets have been removed from the showcase.", len(dataset_ids))) url = h.url_for( controller='ckanext.showcase.controller:ShowcaseController', action='manage_datasets', id=id) redirect(url) # Are we creating a showcase/dataset association? elif (request.method == 'POST' and 'bulk_action.showcase_add' in request.params): # Find the datasets to perform the action on, they are prefixed by # dataset_ in the form data dataset_ids = [] for param in request.params: if param.startswith('dataset_'): dataset_ids.append(param[8:]) if dataset_ids: successful_adds = [] for dataset_id in dataset_ids: try: get_action( 'ckanext_showcase_package_association_create')( context, { 'showcase_id': c.pkg_dict['id'], 'package_id': dataset_id }) except ValidationError as e: h.flash_notice(e.error_summary) else: successful_adds.append(dataset_id) if successful_adds: h.flash_success( ungettext( "The dataset has been added to the showcase.", "The datasets have been added to the showcase.", len(successful_adds))) url = h.url_for( controller='ckanext.showcase.controller:ShowcaseController', action='manage_datasets', id=id) redirect(url) self._add_dataset_search(c.pkg_dict['id'], c.pkg_dict['name']) # get showcase packages c.showcase_pkgs = get_action('ckanext_showcase_package_list')( context, { 'showcase_id': c.pkg_dict['id'] }) return render('showcase/manage_datasets.html')
def manage_datasets(self, id): ''' List datasets associated with the given showcase id. ''' context = {'model': model, 'session': model.Session, 'user': c.user or c.author} data_dict = {'id': id} try: check_access('ckanext_showcase_update', context) except NotAuthorized: abort(401, _('User not authorized to edit {showcase_id}').format( showcase_id=id)) # check if showcase exists try: c.pkg_dict = get_action('package_show')(context, data_dict) except NotFound: abort(404, _('Showcase not found')) except NotAuthorized: abort(401, _('Unauthorized to read showcase')) # Are we removing a showcase/dataset association? if (request.method == 'POST' and 'bulk_action.showcase_remove' in request.params): # Find the datasets to perform the action on, they are prefixed by # dataset_ in the form data dataset_ids = [] for param in request.params: if param.startswith('dataset_'): dataset_ids.append(param[8:]) if dataset_ids: for dataset_id in dataset_ids: get_action('ckanext_showcase_package_association_delete')( context, {'showcase_id': c.pkg_dict['id'], 'package_id': dataset_id}) h.flash_success( ungettext( "The dataset has been removed from the showcase.", "The datasets have been removed from the showcase.", len(dataset_ids))) url = h.url_for( controller='ckanext.showcase.controller:ShowcaseController', action='manage_datasets', id=id) redirect(url) # Are we creating a showcase/dataset association? elif (request.method == 'POST' and 'bulk_action.showcase_add' in request.params): # Find the datasets to perform the action on, they are prefixed by # dataset_ in the form data dataset_ids = [] for param in request.params: if param.startswith('dataset_'): dataset_ids.append(param[8:]) if dataset_ids: successful_adds = [] for dataset_id in dataset_ids: try: get_action( 'ckanext_showcase_package_association_create')( context, {'showcase_id': c.pkg_dict['id'], 'package_id': dataset_id}) except ValidationError as e: h.flash_notice(e.error_summary) else: successful_adds.append(dataset_id) if successful_adds: h.flash_success( ungettext( "The dataset has been added to the showcase.", "The datasets have been added to the showcase.", len(successful_adds))) url = h.url_for( controller='ckanext.showcase.controller:ShowcaseController', action='manage_datasets', id=id) redirect(url) self._add_dataset_search(c.pkg_dict['id'], c.pkg_dict['name']) # get showcase packages c.showcase_pkgs = get_action('ckanext_showcase_package_list')( context, {'showcase_id': c.pkg_dict['id']}) return render('showcase/manage_datasets.html')
def get_snippet_datastore_detail(activity, detail): count = activity['data']['count'] return ''.join( [' ', str(count), ' ', ungettext(_('entry'), _('entries'), count)])
def localised_nice_date(datetime_, show_date=False, with_hours=False): ''' Returns a friendly localised unicode representation of a datetime. :param datetime_: The date to format :type datetime_: datetime :param show_date: Show date not 2 days ago etc :type show_date: bool :param with_hours: should the `hours:mins` be shown for dates :type with_hours: bool :rtype: sting ''' def months_between(date1, date2): if date1 > date2: date1, date2 = date2, date1 m1 = date1.year * 12 + date1.month m2 = date2.year * 12 + date2.month months = m2 - m1 if date1.day > date2.day: months -= 1 elif date1.day == date2.day: seconds1 = date1.hour * 3600 + date1.minute + date1.second seconds2 = date2.hour * 3600 + date2.minute + date2.second if seconds1 > seconds2: months -= 1 return months if not show_date: now = datetime.datetime.now() date_diff = now - datetime_ days = date_diff.days if days < 1 and now > datetime_: # less than one day seconds = date_diff.seconds if seconds < 3600: # less than one hour if seconds < 60: return _('Just now') else: return ungettext('{mins} minute ago', '{mins} minutes ago', seconds / 60).format(mins=seconds / 60) else: return ungettext('{hours} hour ago', '{hours} hours ago', seconds / 3600).format(hours=seconds / 3600) # more than one day months = months_between(datetime_, now) if months < 1: return ungettext('{days} day ago', '{days} days ago', days).format(days=days) if months < 13: return ungettext('{months} month ago', '{months} months ago', months).format(months=months) return ungettext('over {years} year ago', 'over {years} years ago', months / 12).format(years=months / 12) # actual date details = { 'min': datetime_.minute, 'hour': datetime_.hour, 'day': datetime_.day, 'year': datetime_.year, 'month': _MONTH_FUNCTIONS[datetime_.month - 1](), } if with_hours: return ( # NOTE: This is for translating dates like `April 24, 2013, 10:45` _('{month} {day}, {year}, {hour:02}:{min:02}').format(**details)) else: return ( # NOTE: This is for translating dates like `April 24, 2013` _('{month} {day}, {year}').format(**details))