From a3566cd373d4c57e3ec96fbb1217f95c6cdb4298 Mon Sep 17 00:00:00 2001 From: Kiran Jonnalagadda Date: Tue, 2 Feb 2021 21:39:26 +0530 Subject: [PATCH] Rename Concierge to Promoter. Resolves #1015 (#1017) --- funnel/assets/cypress/fixtures/user.json | 6 ++-- .../integration/04_addCrewtoProject.js | 4 +-- .../integration/15_verifyConciergeRoles.js | 8 ++--- .../cypress/integration/16_setupEvent.js | 4 +-- .../cypress/integration/17_synctickets.js | 4 +-- .../assets/cypress/integration/18_checkin.js | 4 +-- .../integration/22_verifyattendeeList.js | 4 +-- .../assets/cypress/integration/27_viewCrew.js | 6 ++-- funnel/assets/js/event.js | 4 +-- funnel/assets/js/membership.js | 2 +- funnel/forms/membership.py | 6 ++-- funnel/models/notification_types.py | 4 +-- funnel/models/project.py | 6 ++-- funnel/models/project_membership.py | 30 +++++++++---------- funnel/models/rsvp.py | 10 +++---- funnel/models/sync_ticket.py | 16 +++++----- funnel/templates/js/event_checkin.js.jinja2 | 4 +-- funnel/templates/js/membership.js.jinja2 | 2 +- funnel/templates/project_admin.html.jinja2 | 10 +++---- .../templates/project_membership.html.jinja2 | 4 +-- funnel/templates/ticket_event.html.jinja2 | 2 +- funnel/views/membership.py | 2 +- funnel/views/project.py | 14 ++++----- funnel/views/ticket_event.py | 28 ++++++++--------- funnel/views/ticket_participant.py | 20 ++++++------- ...c791c09075_rename_concierge_to_promoter.py | 27 +++++++++++++++++ tests/e2e/frontend_tests_initdb.py | 10 +++---- tests/unit/models/test_notification.py | 10 +++---- .../models/test_project_crew_membership.py | 16 +++++----- 29 files changed, 147 insertions(+), 120 deletions(-) create mode 100644 migrations/versions/2cc791c09075_rename_concierge_to_promoter.py diff --git a/funnel/assets/cypress/fixtures/user.json b/funnel/assets/cypress/fixtures/user.json index 4ac697775..ba7ca0f75 100644 --- a/funnel/assets/cypress/fixtures/user.json +++ b/funnel/assets/cypress/fixtures/user.json @@ -7,9 +7,9 @@ "username": "admin-user", "password": "admin-user129_Ftz" }, - "concierge": { - "username": "concierge-user", - "password": "concierge-user34_qQE" + "promoter": { + "username": "promoter-user", + "password": "promoter-user34_qQE" }, "usher": { "username": "usher-cypress", diff --git a/funnel/assets/cypress/integration/04_addCrewtoProject.js b/funnel/assets/cypress/integration/04_addCrewtoProject.js index 50ebc30d5..ffc1e5f5f 100644 --- a/funnel/assets/cypress/integration/04_addCrewtoProject.js +++ b/funnel/assets/cypress/integration/04_addCrewtoProject.js @@ -1,7 +1,7 @@ describe('Adding crew', function () { const owner = require('../fixtures/user.json').owner; const admin = require('../fixtures/user.json').admin; - const concierge = require('../fixtures/user.json').concierge; + const promoter = require('../fixtures/user.json').promoter; const usher = require('../fixtures/user.json').usher; const editor = require('../fixtures/user.json').editor; const hguser = require('../fixtures/user.json').hguser; @@ -25,7 +25,7 @@ describe('Adding crew', function () { .find('[data-cy="role"]') .contains('Editor'); - cy.add_member(concierge.username, 'concierge'); + cy.add_member(promoter.username, 'promoter'); cy.add_member(usher.username, 'usher'); cy.add_member(editor.username, 'editor'); cy.add_member(hguser.username, 'usher', (fail = true)); diff --git a/funnel/assets/cypress/integration/15_verifyConciergeRoles.js b/funnel/assets/cypress/integration/15_verifyConciergeRoles.js index 91e35e08b..afaae7bc6 100644 --- a/funnel/assets/cypress/integration/15_verifyConciergeRoles.js +++ b/funnel/assets/cypress/integration/15_verifyConciergeRoles.js @@ -1,9 +1,9 @@ -describe('Verify roles of concierge', function () { - const concierge = require('../fixtures/user.json').concierge; +describe('Verify roles of promoter', function () { + const promoter = require('../fixtures/user.json').promoter; const project = require('../fixtures/project.json'); - it('Access available for concierge in project settings', function () { - cy.login('/', concierge.username, concierge.password); + it('Access available for promoter in project settings', function () { + cy.login('/', promoter.username, promoter.password); cy.get('[data-cy-title="' + project.title + '"]') .first() diff --git a/funnel/assets/cypress/integration/16_setupEvent.js b/funnel/assets/cypress/integration/16_setupEvent.js index 1610f3677..7ca3dc7b1 100644 --- a/funnel/assets/cypress/integration/16_setupEvent.js +++ b/funnel/assets/cypress/integration/16_setupEvent.js @@ -1,11 +1,11 @@ describe('Setup ticketed event for checkin', function () { - const concierge = require('../fixtures/user.json').concierge; + const promoter = require('../fixtures/user.json').promoter; const project = require('../fixtures/project.json'); const ticketEvents = require('../fixtures/ticket_events.json'); const ticketParticipants = require('../fixtures/ticket_participants.json'); it('Setup ticketed event for checkin', function () { - cy.login('/', concierge.username, concierge.password); + cy.login('/', promoter.username, promoter.password); cy.get('[data-cy-title="' + project.title + '"]') .first() diff --git a/funnel/assets/cypress/integration/17_synctickets.js b/funnel/assets/cypress/integration/17_synctickets.js index 82134a36f..6203a9689 100644 --- a/funnel/assets/cypress/integration/17_synctickets.js +++ b/funnel/assets/cypress/integration/17_synctickets.js @@ -1,12 +1,12 @@ describe('Sync tickets from Boxoffice', function () { - const concierge = require('../fixtures/user.json').concierge; + const promoter = require('../fixtures/user.json').promoter; const user = require('../fixtures/user.json').user; const project = require('../fixtures/project.json'); const ticketEvents = require('../fixtures/ticket_events.json'); const { ticket_client } = require('../fixtures/boxoffice.js'); it('Sync tickets from Boxoffice', function () { - cy.login('/', concierge.username, concierge.password); + cy.login('/', promoter.username, promoter.password); cy.get('[data-cy-title="' + project.title + '"]') .first() diff --git a/funnel/assets/cypress/integration/18_checkin.js b/funnel/assets/cypress/integration/18_checkin.js index c54383784..7cf4b7bbd 100644 --- a/funnel/assets/cypress/integration/18_checkin.js +++ b/funnel/assets/cypress/integration/18_checkin.js @@ -1,5 +1,5 @@ describe('Checkin of attendees', function () { - const concierge = require('../fixtures/user.json').concierge; + const promoter = require('../fixtures/user.json').promoter; const user = require('../fixtures/user.json').user; const profile = require('../fixtures/profile.json'); const project = require('../fixtures/project.json'); @@ -7,7 +7,7 @@ describe('Checkin of attendees', function () { const ticketParticipants = require('../fixtures/ticket_participants.json'); it('Checkin of attendees', function () { - cy.login('/', concierge.username, concierge.password); + cy.login('/', promoter.username, promoter.password); cy.get('[data-cy-title="' + project.title + '"]') .first() diff --git a/funnel/assets/cypress/integration/22_verifyattendeeList.js b/funnel/assets/cypress/integration/22_verifyattendeeList.js index f3c59f10c..d6852f245 100644 --- a/funnel/assets/cypress/integration/22_verifyattendeeList.js +++ b/funnel/assets/cypress/integration/22_verifyattendeeList.js @@ -1,10 +1,10 @@ describe('Verify attendee list', function () { - const concierge = require('../fixtures/user.json').concierge; + const promoter = require('../fixtures/user.json').promoter; const user = require('../fixtures/user.json').user; const project = require('../fixtures/project.json'); it('Verify list of attendees who have responded yes to attending a project', function () { - cy.login('/testcypressproject', concierge.username, concierge.password); + cy.login('/testcypressproject', promoter.username, promoter.password); cy.get('[data-cy-title="' + project.title + '"]') .first() diff --git a/funnel/assets/cypress/integration/27_viewCrew.js b/funnel/assets/cypress/integration/27_viewCrew.js index 52650848a..69d692bfa 100644 --- a/funnel/assets/cypress/integration/27_viewCrew.js +++ b/funnel/assets/cypress/integration/27_viewCrew.js @@ -1,6 +1,6 @@ describe('View crew', function () { const admin = require('../fixtures/user.json').admin; - const concierge = require('../fixtures/user.json').concierge; + const promoter = require('../fixtures/user.json').promoter; const usher = require('../fixtures/user.json').usher; const project = require('../fixtures/project.json'); @@ -19,10 +19,10 @@ describe('View crew', function () { .find('[data-cy="role"]') .contains('Editor'); cy.get('[data-cy="member"]') - .contains(concierge.username) + .contains(promoter.username) .parents('.member') .find('[data-cy="role"]') - .contains('Concierge'); + .contains('Promoter'); cy.get('[data-cy="member"]') .contains(usher.username) .parents('.member') diff --git a/funnel/assets/js/event.js b/funnel/assets/js/event.js index d561624d6..51e50301c 100644 --- a/funnel/assets/js/event.js +++ b/funnel/assets/js/event.js @@ -96,7 +96,7 @@ const Queue = function (queueName) { const ParticipantTable = { init({ - isConcierge, + IsPromoter, isUsher, checkinUrl, participantlistUrl, @@ -119,7 +119,7 @@ const ParticipantTable = { checkinUrl, checkinQ: new Queue(`${ticketEventName}-checkin-queue`), cancelcheckinQ: new Queue(`${ticketEventName}-cancelcheckin-queue`), - isConcierge, + IsPromoter, isUsher, getCsrfToken() { return $('meta[name="csrf-token"]').attr('content'); diff --git a/funnel/assets/js/membership.js b/funnel/assets/js/membership.js index abcb15b6f..bc05d25d9 100644 --- a/funnel/assets/js/membership.js +++ b/funnel/assets/js/membership.js @@ -21,7 +21,7 @@ const Membership = { rolesCount(member) { let count = 0; if (member.is_editor) count += 1; - if (member.is_concierge) count += 1; + if (member.is_promoter) count += 1; if (member.is_usher) count += 1; return count - 1; }, diff --git a/funnel/forms/membership.py b/funnel/forms/membership.py index a5ea92233..e73304b40 100644 --- a/funnel/forms/membership.py +++ b/funnel/forms/membership.py @@ -48,8 +48,8 @@ class ProjectCrewMembershipForm(forms.Form): "Can edit project details, proposal guidelines, schedule, labels and venues" ), ) - is_concierge = forms.BooleanField( - __("Concierge"), + is_promoter = forms.BooleanField( + __("Promoter"), default=False, description=__("Can manage participants and see contact info"), ) @@ -63,7 +63,7 @@ class ProjectCrewMembershipForm(forms.Form): def validate(self, extra_validators=None): is_valid = super(ProjectCrewMembershipForm, self).validate(extra_validators) - if not any([self.is_editor.data, self.is_concierge.data, self.is_usher.data]): + if not any([self.is_editor.data, self.is_promoter.data, self.is_usher.data]): self.is_usher.errors.append("Please select one or more roles") is_valid = False return is_valid diff --git a/funnel/models/notification_types.py b/funnel/models/notification_types.py index 533ecb57a..4b09175e6 100644 --- a/funnel/models/notification_types.py +++ b/funnel/models/notification_types.py @@ -231,7 +231,7 @@ class ProposalReceivedNotification(DocumentHasProfile, Notification): class RegistrationReceivedNotification(DocumentHasProfile, Notification): - """Notification to concierges of new registrations.""" + """Notification to promoters of new registrations.""" __mapper_args__ = {'polymorphic_identity': 'rsvp_received'} active = False @@ -241,7 +241,7 @@ class RegistrationReceivedNotification(DocumentHasProfile, Notification): document: Project fragment: Rsvp - roles = ['project_concierge'] + roles = ['project_promoter'] exclude_actor = True diff --git a/funnel/models/project.py b/funnel/models/project.py index 860e59f32..08b12ad34 100644 --- a/funnel/models/project.py +++ b/funnel/models/project.py @@ -174,7 +174,7 @@ class Project(UuidMixin, BaseScopedNameMixin, db.Model): db.Column(JsonDict, nullable=False, server_default='{}'), # This is an attribute, but we deliberately use `call` instead of `read` to # block this from dictionary enumeration. FIXME: Break up this dictionary into - # individual columns with `all` access for ticket embed id and `concierge` + # individual columns with `all` access for ticket embed id and `promoter` # access for ticket sync access token. call={'all'}, ) @@ -410,13 +410,13 @@ def __init__(self, **kwargs) -> None: super(Project, self).__init__(**kwargs) self.voteset = Voteset(settype=SET_TYPE.PROJECT) self.commentset = Commentset(settype=SET_TYPE.PROJECT) - # Add the creator as editor and concierge + # Add the creator as editor and promoter new_membership = ProjectCrewMembership( parent=self, user=self.user, granted_by=self.user, is_editor=True, - is_concierge=True, + is_promoter=True, ) db.session.add(new_membership) diff --git a/funnel/models/project_membership.py b/funnel/models/project_membership.py index 1d9caa2cf..1491211ae 100644 --- a/funnel/models/project_membership.py +++ b/funnel/models/project_membership.py @@ -17,7 +17,7 @@ # Roles in a project and their remapped names in objects attached to a project project_child_role_map: Dict[str, str] = { 'editor': 'project_editor', - 'concierge': 'project_concierge', + 'promoter': 'project_promoter', 'usher': 'project_usher', 'crew': 'project_crew', 'participant': 'project_participant', @@ -30,11 +30,11 @@ class ProjectCrewMembership(ImmutableMembershipMixin, db.Model): __tablename__ = 'project_crew_membership' # List of is_role columns in this model - __data_columns__ = ('is_editor', 'is_concierge', 'is_usher') + __data_columns__ = ('is_editor', 'is_promoter', 'is_usher') __roles__ = { 'all': { - 'read': {'urls', 'user', 'is_editor', 'is_concierge', 'is_usher', 'project'} + 'read': {'urls', 'user', 'is_editor', 'is_promoter', 'is_usher', 'project'} } } __datasets__ = { @@ -43,7 +43,7 @@ class ProjectCrewMembership(ImmutableMembershipMixin, db.Model): 'uuid_b58', 'offered_roles', 'is_editor', - 'is_concierge', + 'is_promoter', 'is_usher', 'user', 'project', @@ -53,7 +53,7 @@ class ProjectCrewMembership(ImmutableMembershipMixin, db.Model): 'uuid_b58', 'offered_roles', 'is_editor', - 'is_concierge', + 'is_promoter', 'is_usher', 'user', }, @@ -62,7 +62,7 @@ class ProjectCrewMembership(ImmutableMembershipMixin, db.Model): 'uuid_b58', 'offered_roles', 'is_editor', - 'is_concierge', + 'is_promoter', 'is_usher', }, } @@ -85,10 +85,10 @@ class ProjectCrewMembership(ImmutableMembershipMixin, db.Model): #: Editors can edit all common and editorial details of an event is_editor = db.Column(db.Boolean, nullable=False, default=False) - #: Concierges are responsible for logistics and have write access + #: Promoters are responsible for promotion and have write access #: to common details plus read access to everything else. Unlike #: editors, they cannot edit the schedule - is_concierge = db.Column(db.Boolean, nullable=False, default=False) + is_promoter = db.Column(db.Boolean, nullable=False, default=False) #: Ushers help participants find their way around an event and have #: the ability to scan badges at the door is_usher = db.Column(db.Boolean, nullable=False, default=False) @@ -101,7 +101,7 @@ def __table_args__(cls): db.CheckConstraint( db.or_( cls.is_editor.is_(True), - cls.is_concierge.is_(True), + cls.is_promoter.is_(True), cls.is_usher.is_(True), ), name='project_crew_membership_has_role', @@ -115,8 +115,8 @@ def offered_roles(self): roles = set() if self.is_editor: roles.add('editor') - if self.is_concierge: - roles.add('concierge') + if self.is_promoter: + roles.add('promoter') if self.is_usher: roles.add('usher') roles.add('crew') @@ -145,7 +145,7 @@ class Project: # type: ignore[no-redef] # skipcq: PYL-E0102 ), viewonly=True, ), - grants_via={'user': {'editor', 'concierge', 'usher', 'participant', 'crew'}}, + grants_via={'user': {'editor', 'promoter', 'usher', 'participant', 'crew'}}, ) active_editor_memberships = db.relationship( @@ -159,13 +159,13 @@ class Project: # type: ignore[no-redef] # skipcq: PYL-E0102 viewonly=True, ) - active_concierge_memberships = db.relationship( + active_promoter_memberships = db.relationship( ProjectCrewMembership, lazy='dynamic', primaryjoin=db.and_( ProjectCrewMembership.project_id == Project.id, ProjectCrewMembership.is_active, - ProjectCrewMembership.is_concierge.is_(True), + ProjectCrewMembership.is_promoter.is_(True), ), viewonly=True, ) @@ -183,7 +183,7 @@ class Project: # type: ignore[no-redef] # skipcq: PYL-E0102 crew = DynamicAssociationProxy('active_crew_memberships', 'user') editors = DynamicAssociationProxy('active_editor_memberships', 'user') - concierges = DynamicAssociationProxy('active_concierge_memberships', 'user') + promoters = DynamicAssociationProxy('active_promoter_memberships', 'user') ushers = DynamicAssociationProxy('active_usher_memberships', 'user') diff --git a/funnel/models/rsvp.py b/funnel/models/rsvp.py index f5b258a0b..1dcd02e8c 100644 --- a/funnel/models/rsvp.py +++ b/funnel/models/rsvp.py @@ -36,7 +36,7 @@ class Rsvp(UuidMixin, NoIdMixin, db.Model): db.relationship( Project, backref=db.backref('rsvps', cascade='all', lazy='dynamic') ), - read={'owner', 'project_concierge'}, + read={'owner', 'project_promoter'}, grants_via={None: project_child_role_map}, ) user_id = db.Column( @@ -46,7 +46,7 @@ class Rsvp(UuidMixin, NoIdMixin, db.Model): db.relationship( User, backref=db.backref('rsvps', cascade='all', lazy='dynamic') ), - read={'owner', 'project_concierge'}, + read={'owner', 'project_promoter'}, grants={'owner'}, ) @@ -59,12 +59,12 @@ class Rsvp(UuidMixin, NoIdMixin, db.Model): ) state = with_roles( StateManager('_state', RSVP_STATUS, doc="RSVP answer"), - call={'owner', 'project_concierge'}, + call={'owner', 'project_promoter'}, ) __datasets__ = {'primary': {'project', 'user', 'response'}, 'related': {'response'}} - @with_roles(read={'owner', 'project_concierge'}) # type: ignore[misc] + @with_roles(read={'owner', 'project_promoter'}) # type: ignore[misc] @property def response(self): """Return RSVP response as a raw value.""" @@ -105,7 +105,7 @@ def rsvp_no(self, unsubscribe_comments: bool = False): def rsvp_maybe(self): pass - @with_roles(call={'owner', 'project_concierge'}) + @with_roles(call={'owner', 'project_promoter'}) def user_email(self): """User's preferred email address for this registration.""" return self.user.transport_for_email(self.project.profile) diff --git a/funnel/models/sync_ticket.py b/funnel/models/sync_ticket.py index 214508a78..0db80eeb9 100644 --- a/funnel/models/sync_ticket.py +++ b/funnel/models/sync_ticket.py @@ -143,32 +143,32 @@ class TicketParticipant(EmailAddressMixin, UuidMixin, BaseMixin, db.Model): fullname = with_roles( db.Column(db.Unicode(80), nullable=False), - read={'concierge', 'subject', 'scanner'}, + read={'promoter', 'subject', 'scanner'}, ) #: Unvalidated phone number phone = with_roles( db.Column(db.Unicode(80), nullable=True), - read={'concierge', 'subject', 'scanner'}, + read={'promoter', 'subject', 'scanner'}, ) #: Unvalidated Twitter id twitter = with_roles( db.Column(db.Unicode(80), nullable=True), - read={'concierge', 'subject', 'scanner'}, + read={'promoter', 'subject', 'scanner'}, ) #: Job title job_title = with_roles( db.Column(db.Unicode(80), nullable=True), - read={'concierge', 'subject', 'scanner'}, + read={'promoter', 'subject', 'scanner'}, ) #: Company company = with_roles( db.Column(db.Unicode(80), nullable=True), - read={'concierge', 'subject', 'scanner'}, + read={'promoter', 'subject', 'scanner'}, ) #: Participant's city city = with_roles( db.Column(db.Unicode(80), nullable=True), - read={'concierge', 'subject', 'scanner'}, + read={'promoter', 'subject', 'scanner'}, ) # public key puk = db.Column( @@ -185,7 +185,7 @@ class TicketParticipant(EmailAddressMixin, UuidMixin, BaseMixin, db.Model): project_id = db.Column(None, db.ForeignKey('project.id'), nullable=False) project = with_roles( db.relationship(Project), - read={'concierge', 'subject', 'scanner'}, + read={'promoter', 'subject', 'scanner'}, grants_via={None: project_child_role_map}, ) @@ -194,7 +194,7 @@ class TicketParticipant(EmailAddressMixin, UuidMixin, BaseMixin, db.Model): # Since 'email' comes from the mixin, it's not available to be annotated using # `with_roles`. Instead, we have to specify the roles that can access it in here: __roles__ = { - 'concierge': {'read': {'email'}}, + 'promoter': {'read': {'email'}}, 'subject': {'read': {'email'}}, 'scanner': {'read': {'email'}}, } diff --git a/funnel/templates/js/event_checkin.js.jinja2 b/funnel/templates/js/event_checkin.js.jinja2 index 2d4a3b751..b84f56857 100644 --- a/funnel/templates/js/event_checkin.js.jinja2 +++ b/funnel/templates/js/event_checkin.js.jinja2 @@ -21,7 +21,7 @@ {{ company }}