HI Adam and Alexei, I finally got it to work. As Adam was suggesting with his solution, the main problem is that map popups are populated by means of consulting the resource index. The index() method, in turn, is not called until a resource node is modified. Once I tried modifying a resource and looking it up on the map, it did display the correct values in the popup (I have changed the default fields to be visualised in the E18 and E27 popups to two new nodes that we have implemented in-house - you may see my resource.py attached here).
Now, am I right in believing that, in order for the other resource popups to be populated correctly, i.e. with the correct nodes, I need to run an ES reindexing? Thanks, Andrea ''' ARCHES - a program developed to inventory and manage immovable cultural heritage. Copyright (C) 2013 J. Paul Getty Trust and World Monuments Fund This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. ''' from django.conf import settings import arches.app.models.models as archesmodels from arches.app.models.edit_history import EditHistory from arches.app.models.resource import Resource as ArchesResource from arches.app.search.search_engine_factory import SearchEngineFactory from arches.app.utils.betterJSONSerializer import JSONSerializer, JSONDeserializer from arches_hip.models import forms from arches.app.models.forms import DeleteResourceForm from django.utils.translation import ugettext as _ from arches.app.models.entity import Entity class Resource(ArchesResource): def __init__(self, *args, **kwargs): super(Resource, self).__init__(*args, **kwargs) description_group = { 'id': 'resource-description', 'icon':'fa-folder', 'name': _('Resource Description'), 'forms': [ forms.RelatedResourcesForm.get_info(), forms.ExternalReferenceForm.get_info() ] } self.form_groups.append(description_group) if self.entitytypeid == 'HERITAGE_RESOURCE.E18': description_group['forms'][:0] = [ forms.SummaryForm.get_info(), forms.LocationForm.get_info(), forms.MeasurementvaluesForm.get_info(), forms.Classification1Form.get_info(), forms.MeasurementForm.get_info(), forms.DescriptionForm.get_info(), forms.RelatedFilesForm.get_info(), ] elif self.entitytypeid == 'HERITAGE_RESOURCE_GROUP.E27': description_group['forms'][:0] = [ forms.SummaryForm.get_info(), forms.LocationForm.get_info(), forms.MeasurementvaluesForm.get_info(), forms.Classification1Form.get_info(), forms.MeasurementForm.get_info(), forms.DescriptionForm.get_info(), forms.RelatedFilesForm.get_info(), forms.DesignationForm.get_info(), ] elif self.entitytypeid == 'ACTIVITY.E7': description_group['forms'][:0] = [ forms.ActivitySummaryForm.get_info(), forms.DescriptionForm.get_info(), forms.LocationForm.get_info(), forms.ActivityActionsForm.get_info(), ] elif self.entitytypeid == 'ACTOR.E39': description_group['forms'][:0] = [ forms.ActorSummaryForm.get_info(), forms.DescriptionForm.get_info(), forms.LocationForm.get_info(), forms.RoleForm.get_info(), ] elif self.entitytypeid == 'HISTORICAL_EVENT.E5': description_group['forms'][:0] = [ forms.HistoricalEventSummaryForm.get_info(), forms.DescriptionForm.get_info(), forms.LocationForm.get_info(), forms.PhaseForm.get_info(), ] elif self.entitytypeid == 'INFORMATION_RESOURCE.E73': description_group['forms'][:0] = [ forms.InformationResourceSummaryForm.get_info(), forms.PublicationForm.get_info(), forms.ImageryForm.get_info(), forms.CartographyForm.get_info(), forms.CoverageForm.get_info(), forms.SharedDataForm.get_info(), forms.FileUploadForm.get_info(), forms.DescriptionForm.get_info(), ] if self.entityid != '': self.form_groups.append({ 'id': 'manage-resource', 'icon': 'fa-wrench', 'name': _('Manage Resource'), 'forms': [ EditHistory.get_info(), DeleteResourceForm.get_info() ] }) def get_primary_name(self): print 'App get_primary_name()' displayname = super(Resource, self).get_primary_name() names = self.get_names() if len(names) > 0: displayname = names[0].value return displayname def get_names(self): """ Gets the human readable name to display for entity instances """ print 'App get_names()' names = [] name_nodes = self.find_entities_by_type_id(settings.RESOURCE_TYPE_CONFIGS()[self.entitytypeid]['primary_name_lookup']['entity_type']) if len(name_nodes) > 0: for name in name_nodes: names.append(name) return names def prepare_documents_for_search_index(self): """ Generates a list of specialized resource based documents to support resource search """ print 'App prepare_documents_for_search_index()' documents = super(Resource, self).prepare_documents_for_search_index() for document in documents: document['date_groups'] = [] for nodes in self.get_nodes('BEGINNING_OF_EXISTENCE.E63', keys=['value']): document['date_groups'].append({ 'conceptid': nodes['BEGINNING_OF_EXISTENCE_TYPE_E55__value'], 'value': nodes['START_DATE_OF_EXISTENCE_E49__value'] }) for nodes in self.get_nodes('END_OF_EXISTENCE.E64', keys=['value']): document['date_groups'].append({ 'conceptid': nodes['END_OF_EXISTENCE_TYPE_E55__value'], 'value': nodes['END_DATE_OF_EXISTENCE_E49__value'] }) return documents def prepare_documents_for_map_index(self, geom_entities=[]): """ Generates a list of geojson documents to support the display of resources on a map """ print 'App prepare_documents_for_map_index()' documents = super(Resource, self).prepare_documents_for_map_index(geom_entities=geom_entities) def get_entity_data(entitytypeid, get_label=False): entity_data = _('None ') entity_nodes = self.find_entities_by_type_id(entitytypeid) if len(entity_nodes) > 0: entity_data = [] for node in entity_nodes: if get_label: entity_data.append(node.label) else: entity_data.append(node.value) entity_data = ', '.join(entity_data) return entity_data document_data = {} if self.entitytypeid == 'HERITAGE_RESOURCE.E18': document_data['certainty_type'] = get_entity_data('SITE_OVERALL_ARCHAEOLOGICAL_CERTAINTY_TYPE.E55', get_label=True) # document_data['address'] = _('None specified') # address_nodes = self.find_entities_by_type_id('PLACE_ADDRESS.E45') # for node in address_nodes: # if node.find_entities_by_type_id('ADDRESS_TYPE.E55')[0].label == 'Primary': # document_data['address'] = node.value if self.entitytypeid == 'HERITAGE_RESOURCE_GROUP.E27': document_data['certainty_type'] = get_entity_data('SITE_OVERALL_ARCHAEOLOGICAL_CERTAINTY_TYPE.E55', get_label=True) if self.entitytypeid == 'ACTIVITY.E7': document_data['resource_type'] = get_entity_data('ACTIVITY_TYPE.E55', get_label=True) if self.entitytypeid == 'HISTORICAL_EVENT.E5': document_data['resource_type'] = get_entity_data('HISTORICAL_EVENT_TYPE.E55', get_label=True) if self.entitytypeid == 'ACTOR.E39': document_data['resource_type'] = get_entity_data('ACTOR_TYPE.E55', get_label=True) if self.entitytypeid == 'INFORMATION_RESOURCE.E73': document_data['resource_type'] = get_entity_data('INFORMATION_RESOURCE_TYPE.E55', get_label=True) document_data['creation_date'] = get_entity_data('DATE_OF_CREATION.E50') document_data['publication_date'] = get_entity_data('DATE_OF_PUBLICATION.E50') if self.entitytypeid == 'HISTORICAL_EVENT.E5' or self.entitytypeid == 'ACTIVITY.E7' or self.entitytypeid == 'ACTOR.E39': document_data['start_date'] = get_entity_data('BEGINNING_OF_EXISTENCE.E63') document_data['end_date'] = get_entity_data('END_OF_EXISTENCE.E64') if self.entitytypeid == 'HERITAGE_RESOURCE.E18' or self.entitytypeid == 'HERITAGE_RESOURCE_GROUP.E27': document_data['site_type'] = get_entity_data('SITE_FUNCTION_TYPE.E55', get_label=True) for document in documents: for key in document_data: document['properties'][key] = document_data[key] return documents @staticmethod def get_report(resourceid): # get resource data for resource_id from ES, return data # with correct id for the given resource type return { 'id': 'heritage-resource', 'data': { 'hello_world': 'Hello World!' } } On Friday, May 6, 2016 at 6:41:41 PM UTC+3, [email protected] wrote: > > I will try this soon Alexei - thank you. May I ask why one has to rerun > the install command? Also, will have to rerun the install whenever I modify > the resource.py? > > > > > On Friday, May 6, 2016 at 7:50:07 AM UTC+1, Alexei Peters wrote: >> >> Andrea, >> I was able to achieve what you wanted by creating a resource.py file that >> inherits from arches_hip. >> I then only overwrite the function that you're interested in and made the >> changes you mentioned (entity_data = _('None')). >> I've attached the file here. >> >> in my settings file, nothing unusual: >> RESOURCE_MODEL = {'default': 'arches_la.models.resource.Resource'} >> >> I re-ran the install (python manage.py packages -o install) after adding >> this file and I got the result you expected. >> Hope any of this helps. >> Cheers, >> Alexei >> >> >> Director of Web Development - Farallon Geographics, Inc. - 971.227.3173 >> >> On Thu, May 5, 2016 at 9:22 AM, Adam Cox <[email protected]> wrote: >> >>> Oh, sure. In fact, you can see them here (and the rest of the app): >>> https://github.com/mradamcox/afrh/blob/master/afrh/models/resource.py >>> >>> The forms imports reference the new forms I've made for this project, so >>> leave those out... >>> >>> On Thu, May 5, 2016 at 10:17 AM, <[email protected]> wrote: >>> >>>> Thanks for this Adam. I tried applying your fixes, but clearly I must >>>> be missing some imports out, cause I get a DoesNotExist error on >>>> eamena.models.resource.Resource and, once that happens for the first time, >>>> even if I roll things back I am forced to raze elasticsearch and replace >>>> it >>>> with a backup copy. Could you by any chance post me the complete list of >>>> your imports on your app's resource.py. >>>> >>>> Thanks, >>>> >>>> Andrea >>>> >>>> On Wednesday, May 4, 2016 at 7:44:37 PM UTC+1, Adam Cox wrote: >>>>> >>>>> Ok, here's how I just got this to work: >>>>> >>>>> If you go back to the arches.models.resource file, you'll find that >>>>> there are a set of functions that should be moved together, in order for >>>>> them to correctly reference each other. The first two are bulk_index() >>>>> and >>>>> index(). Both of these functions call four other indexing functions, one >>>>> of which is prepare_documents_for_map_index(), which you are trying to >>>>> modify. So, I'd recommend copying and pasted these six functions into >>>>> your >>>>> resource.py file. >>>>> bulk_index() >>>>> index() >>>>> prepare_documents_for_search_index() >>>>> prepare_documents_for_map_index() >>>>> prepare_terms_for_search_index() >>>>> prepare_documents_for_report_index() >>>>> >>>>> You'll also have to add (at least) >>>>> from arches.app.models.entity import Entity >>>>> to the top of your resource.py file. I already had some extra import >>>>> statements in mine when I did this, so there may something missing for >>>>> you >>>>> when you try this. >>>>> >>>>> After adding those functions to my resource.py file, the map popup >>>>> info was updated as desired. Note that the index() function is called on >>>>> a >>>>> resource any time you save a new node to it, so if it's not working right >>>>> away, edit the resource, save it, and return to the map view. >>>>> >>>>> Let me know if that works. >>>>> >>>>> Adam >>>>> >>>>> On Wed, May 4, 2016 at 12:06 PM, Adam Cox <[email protected]> wrote: >>>>> >>>>>> Sounds good. The .pyc file is a compiled version of a .py file which >>>>>> means that your resource.py file has been used by the app. One thing I >>>>>> do >>>>>> all the time is add print statements within functions to double check >>>>>> that >>>>>> they are being called. Just inside the prepare_documents_for_map_index >>>>>> function, try adding print "prepare_documents_for_map_index IS BEING >>>>>> USED" >>>>>> or something. Then watch the server console output. >>>>>> >>>>>> I haven't had to modify that function yet, but if a simple >>>>>> modification to it is not reflected, you may need to do a little >>>>>> sleuthing, >>>>>> because it's possible that it is only called from inside the arches >>>>>> "site-package", in which case you may need to migrate more functions to >>>>>> your own app and change some import statements. Alexei would have a >>>>>> better >>>>>> handle on that right now than I do... >>>>>> >>>>>> Adam >>>>>> >>>>>> On Wed, May 4, 2016 at 11:51 AM, <[email protected]> wrote: >>>>>> >>>>>>> Not only did I do that Adam, I also tried deleting both resource.py >>>>>>> files from my app and the Arches-HIP folder structure. No effect >>>>>>> whatsoever. >>>>>>> >>>>>>> A small update though. It would appear that, by setting up the >>>>>>> RESOURCE_MODEL path as you indicated and after restarting Postgres.app, >>>>>>> I >>>>>>> finally got django to re-render resource.pyc in my app folder (which I >>>>>>> had >>>>>>> deleted) - so the source file was finally accessed. However, once again >>>>>>> there has been no change in the entity_data default string, which still >>>>>>> gets displayed in the Resource map popup as 'None specified' despite my >>>>>>> having changed it to 'None' in resource.py. >>>>>>> >>>>>>> I look forward to more ideas, >>>>>>> >>>>>>> Andrea >>>>>>> >>>>>>> >>>>>>> On Wednesday, May 4, 2016 at 6:39:30 PM UTC+1, Adam Cox wrote: >>>>>>>> >>>>>>>> That's very strange. Just to confirm: you copied the >>>>>>>> arches_hip/models/resource.py file, pasted it into the corresponding >>>>>>>> directory of your own app, and then changed the RESOURCE_MODEL as >>>>>>>> described >>>>>>>> above, correct? That's all you should need to do... >>>>>>>> >>>>>>>> On Wed, May 4, 2016 at 11:23 AM, <[email protected]> wrote: >>>>>>>> >>>>>>>>> Hi Alexei, I am not using Apache. I edit our app on a Mac Yosemite >>>>>>>>> installation with Postgres.app. I should add that other .py files, >>>>>>>>> like >>>>>>>>> settings.py, can be modified 'on the fly' and changes are recognised >>>>>>>>> by the >>>>>>>>> app. It would appear that resource.py is an exception. I thought it >>>>>>>>> could >>>>>>>>> be a Django cache issue, but the MIDDLEWARE parameters in the >>>>>>>>> settings.py >>>>>>>>> file of Arches do not seem to include the caching ones, so this also >>>>>>>>> proved >>>>>>>>> to be a dead end. >>>>>>>>> >>>>>>>>> Any other ideas? >>>>>>>>> >>>>>>>>> Andrea >>>>>>>>> >>>>>>>>> >>>>>>>>> On Wednesday, May 4, 2016 at 6:02:40 PM UTC+1, Alexei Peters wrote: >>>>>>>>>> >>>>>>>>>> Hi Andrea, >>>>>>>>>> If you're using Apache, make sure to restart it after editing any >>>>>>>>>> .py file. >>>>>>>>>> Cheers, >>>>>>>>>> Alexei >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Director of Web Development - Farallon Geographics, Inc. - >>>>>>>>>> 971.227.3173 >>>>>>>>>> >>>>>>>>>> On Wed, May 4, 2016 at 8:54 AM, <[email protected]> wrote: >>>>>>>>>> >>>>>>>>>>> Thanks Adam, I have tried adding the string below, - still no >>>>>>>>>>> *.pyc. I even tried commenting off the RESOURCE_MODEL in the HIP >>>>>>>>>>> settings >>>>>>>>>>> (the default there is: RESOURCE_MODEL = {'default': >>>>>>>>>>> 'arches_hip.models.resource.Resource'}), still nothing. This is >>>>>>>>>>> what the >>>>>>>>>>> top of my settings.py in my app looks like now: >>>>>>>>>>> >>>>>>>>>>> PACKAGE_ROOT = >>>>>>>>>>> os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) >>>>>>>>>>> PACKAGE_NAME = PACKAGE_ROOT.split(os.sep)[-1] >>>>>>>>>>> DATABASES['default']['NAME'] = 'arches_%s' % (PACKAGE_NAME) >>>>>>>>>>> DATABASES['default']['POSTGIS_TEMPLATE'] = 'template_postgis' >>>>>>>>>>> >>>>>>>>>>> ROOT_URLCONF = '%s.urls' % (PACKAGE_NAME) >>>>>>>>>>> >>>>>>>>>>> INSTALLED_APPS = INSTALLED_APPS + (PACKAGE_NAME,) >>>>>>>>>>> STATICFILES_DIRS = (os.path.join(PACKAGE_ROOT, 'media'),) + >>>>>>>>>>> STATICFILES_DIRS >>>>>>>>>>> TEMPLATE_DIRS = (os.path.join(PACKAGE_ROOT, >>>>>>>>>>> 'templates'),os.path.join(PACKAGE_ROOT, 'templatetags')) + >>>>>>>>>>> TEMPLATE_DIRS >>>>>>>>>>> >>>>>>>>>>> # Absolute filesystem path to the directory that will hold >>>>>>>>>>> user-uploaded files. >>>>>>>>>>> MEDIA_ROOT = os.path.join(PACKAGE_ROOT, 'uploadedfiles') >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> RESOURCE_MODEL = {'default': >>>>>>>>>>> '{}.models.resource.Resource'.format(PACKAGE_NAME)} >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks for your help. >>>>>>>>>>> >>>>>>>>>>> Andrea >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On Wednesday, May 4, 2016 at 3:00:46 PM UTC+1, Adam Cox wrote: >>>>>>>>>>>> >>>>>>>>>>>> Hi Andrea, you need to explicitly set your resource model in >>>>>>>>>>>> your settings.py file. Something like this: >>>>>>>>>>>> >>>>>>>>>>>> RESOURCE_MODEL = {'default': >>>>>>>>>>>> '{}.models.resource.Resource'.format(PACKAGE_NAME)} >>>>>>>>>>>> >>>>>>>>>>>> Once you run the app, you should see a .pyc file appear next to >>>>>>>>>>>> your app's models/resource.py file, meaning that it's now in use. >>>>>>>>>>>> >>>>>>>>>>>> Adam >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On Wed, May 4, 2016 at 6:53 AM, <[email protected]> wrote: >>>>>>>>>>>> >>>>>>>>>>>>> Hello All, >>>>>>>>>>>>> >>>>>>>>>>>>> I am having an issue with modifying resource.py both in my >>>>>>>>>>>>> installation of Arches and on the Arches-HIP. I am trying to >>>>>>>>>>>>> modify the >>>>>>>>>>>>> fields that are mapped as geojson (i.e. the section covered by >>>>>>>>>>>>> the >>>>>>>>>>>>> function prepare_documents_for_map_index()). However, whenever I >>>>>>>>>>>>> modify >>>>>>>>>>>>> something within this function, it would appear that Django does >>>>>>>>>>>>> not >>>>>>>>>>>>> re-read my .py source file. I even tried to delete resource.py >>>>>>>>>>>>> and its .pyc >>>>>>>>>>>>> , and did the same with the corresponding files in the HIP. Still >>>>>>>>>>>>> nothing. >>>>>>>>>>>>> It would seem that the py file is not called. I thought it might >>>>>>>>>>>>> be an >>>>>>>>>>>>> elasticsearch issue, but then I re-ran it and nothing changed. It >>>>>>>>>>>>> would >>>>>>>>>>>>> appear that resource.py does not get called, which is strange >>>>>>>>>>>>> since I would >>>>>>>>>>>>> have expected prepare_documents_for_map_index() to be called when >>>>>>>>>>>>> visualising records with the Location Filter. >>>>>>>>>>>>> >>>>>>>>>>>>> Please note that I tried to modify static strings such as the >>>>>>>>>>>>> default entity_data=_('None specified'), to no avail. >>>>>>>>>>>>> >>>>>>>>>>>>> Can you help? >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> >>>>>>>>>>>>> Andrea >>>>>>>>>>>>> >>>>>>>>>>>>> -- >>>>>>>>>>>>> -- To post, send email to [email protected]. To >>>>>>>>>>>>> unsubscribe, send email to [email protected]. >>>>>>>>>>>>> For more information, visit >>>>>>>>>>>>> https://groups.google.com/d/forum/archesproject?hl=en >>>>>>>>>>>>> --- >>>>>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>>>>> Google Groups "Arches Project" group. >>>>>>>>>>>>> To unsubscribe from this group and stop receiving emails from >>>>>>>>>>>>> it, send an email to [email protected]. >>>>>>>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>> -- To post, send email to [email protected]. To >>>>>>>>>>> unsubscribe, send email to [email protected]. >>>>>>>>>>> For more information, visit >>>>>>>>>>> https://groups.google.com/d/forum/archesproject?hl=en >>>>>>>>>>> --- >>>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>>> Google Groups "Arches Project" group. >>>>>>>>>>> To unsubscribe from this group and stop receiving emails from >>>>>>>>>>> it, send an email to [email protected]. >>>>>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>> -- To post, send email to [email protected]. To >>>>>>>>> unsubscribe, send email to [email protected]. For >>>>>>>>> more information, visit >>>>>>>>> https://groups.google.com/d/forum/archesproject?hl=en >>>>>>>>> --- >>>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>> Groups "Arches Project" group. >>>>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>>>> send an email to [email protected]. >>>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>> -- To post, send email to [email protected]. To >>>>>>> unsubscribe, send email to [email protected]. For >>>>>>> more information, visit >>>>>>> https://groups.google.com/d/forum/archesproject?hl=en >>>>>>> --- >>>>>>> You received this message because you are subscribed to the Google >>>>>>> Groups "Arches Project" group. >>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>> send an email to [email protected]. >>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>> >>>>>> >>>>>> >>>>> -- >>>> -- To post, send email to [email protected]. To unsubscribe, >>>> send email to [email protected]. For more information, >>>> visit https://groups.google.com/d/forum/archesproject?hl=en >>>> --- >>>> You received this message because you are subscribed to the Google >>>> Groups "Arches Project" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to [email protected]. >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>> >>> -- >>> -- To post, send email to [email protected]. To unsubscribe, >>> send email to [email protected]. For more information, >>> visit https://groups.google.com/d/forum/archesproject?hl=en >>> --- >>> You received this message because you are subscribed to the Google >>> Groups "Arches Project" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> -- -- To post, send email to [email protected]. To unsubscribe, send email to [email protected]. For more information, visit https://groups.google.com/d/forum/archesproject?hl=en --- You received this message because you are subscribed to the Google Groups "Arches Project" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
