Exemplo n.º 1
0
class TestAppointmentEndpoint(TestCase):
    def setUp(self):
        self.endpoint = AppointmentEndpoint()

    def test_list(self):
        # will raise an exception if you don't provide with params that has date or datetime key
        with self.assertRaises(Exception):
            self.endpoint.list()

        # Returns an iterator
        self.assertEqual(type(self.endpoint.list(params={'date': None})), GeneratorType)

        # request should fail, and raises a value error when trying to do response.json()
        with self.assertRaises(APIException):
            next(self.endpoint.list(params={'date': None}))
Exemplo n.º 2
0
 def load_appointments(self, doctor_timezone):
     """
     Load all of today's appointments for the logged in doctor
     """
     access_token = self.get_token()
     api = AppointmentEndpoint(access_token)
     today = datetime.datetime.now()
     today = today.strftime('%Y-%m-%d')
     appointments = api.list(date=today)
     for a in appointments:
         patient = self.get_patient(a['patient'])
         patient_name = patient['first_name'] + ' ' + patient['last_name']
         check_in_time = None
         seen_time = None
         print(a['status'])
         if a['status'] in ['In Session', 'Complete']:
             seen_time = datetime.datetime.now()
         elif a['status'] in ['Arrived', 'Checked In', 'In Room']:
             check_in_time = datetime.datetime.now()
             print('CHECKED IN')
         appointment = Appointment(
             drchrono_id=a['id'],
             doctor=a['doctor'],
             patient_name=patient_name,
             patient_id=a['patient'],
             scheduled_time=datetime.datetime.strptime(
                 a['scheduled_time'], '%Y-%m-%dT%H:%M:%S'),
             duration=a['duration'],
             status=a['status'],
             check_in_time=check_in_time,
             seen_time=seen_time)
         appointment.save()
Exemplo n.º 3
0
 def update_appointments(self, doctor_id):
     access_token = self.get_token()
     api = AppointmentEndpoint(access_token)
     today = date.today()
     params = {}
     params['doctor'] = doctor_id
     lst = list(api.list(params=params, date=today))
     for item in lst:
         Appointment.objects.update_or_create(defaults={
             'doctor':
             Doctor.objects.get(id=doctor_id),
             'duration':
             item['duration'],
             'exam_room':
             item['exam_room'],
             'office':
             item['office'],
             'patient':
             Patient.objects.get(id=item['patient']),
             'scheduled_time':
             item['scheduled_time'],
             'status':
             item['status']
         },
                                              id=item['id'])
Exemplo n.º 4
0
 def get_context_data(self, **kwargs):
     kwargs = super(DoctorWelcome, self).get_context_data(**kwargs)
     access_token = get_token()
     dt_api = DoctorEndpoint(access_token)
     ap_api = AppointmentEndpoint(access_token)
     pt_api = PatientSummaryEndpoint(access_token)
     doctor = next(dt_api.list())
     appointments = list(ap_api.list(date=dt.date.today()))
     app_list = []
     for a in appointments:
         patient_info = pt_api.fetch(id=a["patient"])
         a["patient_info"] = patient_info
         a['start_time'] = dt.datetime.strptime(a["scheduled_time"],
                                                "%Y-%m-%dT%H:%M:%S")
         a['end_time'] = a["start_time"]\
             + dt.timedelta(minutes=int(a["duration"]))
         updated_at = dt.datetime.strptime(a['updated_at'],
                                           "%Y-%m-%dT%H:%M:%S")
         wait_time = dt.datetime.now() - updated_at
         a["wait_time"] = round(wait_time.total_seconds() / 60)
         app_list.append(a)
     confirmed = filter(lambda x: x["status"] == "", app_list)
     current = filter(lambda x: x["status"] == "In Session", app_list)
     arrived = filter(lambda x: x["status"] == "Arrived", app_list)
     complete = filter(lambda x: x["status"] == "Complete", app_list)
     kwargs['doctor'] = doctor
     kwargs['confirmed'] = confirmed
     kwargs['current'] = current
     kwargs['arrived'] = arrived
     kwargs['complete'] = complete
     return kwargs
Exemplo n.º 5
0
 def appointments_list(self,
                       params=None,
                       date=None,
                       start=None,
                       end=None,
                       **kwargs):
     """ Obtains Appointments list
         https://app.drchrono.com/api-docs/#operation/appointments_list
     Args:
         params (dict, optional):
             cursor	: string (Cursor): The pagination cursor value.
             date	: string (date)
             date_range	: string (date_range)
             doctor	: integer (doctor)
             office	: integer (office)
             page_size: integer (Page size): Number of results to return per page.
             patient	: integer (patient)
             since	: string (since)
             status	: string (status)            
         date (string, optional): Date
         start (string, optional): Start
         end (string, optional):  End
     Returns:
         list: appointments list
     """
     api = AppointmentEndpoint(self.access_token)
     g = api.list(params, date, start, end, **kwargs)
     return self.__get_list(g)
Exemplo n.º 6
0
    def get_appointments(self, doctor):
        """
        Return all appointments for today

        TODO: Performing local db sync on page load slows performance, even if by a non-negligible amount
              Write cron/celery task to periodically sync so we can remove the API call from here
        """
        access_token = self.get_token()
        api = AppointmentEndpoint(access_token)
        apts_api = api.list(params={"verbose": True, "doctor": doctor['id']}, date=self.today_date)
        for apt in apts_api:
            try:
                #  TODO: Update status locally if value from API result differs
                apt_db = Appointment.objects.get(id=apt['id'])
                #  Check if status has changed and update if needed
                # if apt_db.status != apt['status']:
                #     apt_db.status = apt['status']
                #     apt_db.save()
            except Appointment.DoesNotExist:
                Appointment.create_from_api(apt, access_token)

        # Sort appointments by status, in order of time_spent_waiting
        yesterday = datetime.today() - timedelta(days=1)
        apts_db = Appointment.objects\
            .filter(scheduled_time__gt=yesterday)\
            .exclude(status=Appointment.IN_SESSION)\
            .order_by(Appointment.ORDER_HIERARCHY)
        return apts_db
Exemplo n.º 7
0
    def clean(self):
        try:
            oauth_provider = UserSocialAuth.objects.get(provider='drchrono')
            access_token = oauth_provider.extra_data['access_token']
        except UserSocialAuth.DoesNotExist:
            raise forms.ValidationError(
                "We had a problem authenticating with the drchrono API.")

        full_name = f"{self.cleaned_data.get('first_name')} {self.cleaned_data.get('last_name')}"

        appointments_client = AppointmentEndpoint(access_token)
        patient_client = PatientEndpoint(access_token)
        self.cleaned_data['appointment_id'] = None
        self.cleaned_data['patient_id'] = None

        # get a list of patients, make a list of their full names to search through
        patients = list(patient_client.list())
        patients_full_names = [
            f"{patient.get('first_name')} {patient.get('last_name')}"
            for patient in list(patient_client.list())
        ]
        patient_found = full_name in patients_full_names
        if not patient_found:
            raise forms.ValidationError(
                "Couldn't find a patient matching your name.")

        patient = patients[patients_full_names.index(full_name)]
        self.cleaned_data['patient_id'] = patient.get('id')

        # okay, we found them. do they have an appt. ?
        today = timezone.now()
        today_str = today.strftime('%m-%d-%y')
        appointments = list(
            appointments_client.list(
                {'patient': self.cleaned_data.get('patient_id')},
                start=today_str,
                end=today_str))
        patient_has_appointment_today = len(appointments) > 0
        if not patient_has_appointment_today:
            raise forms.ValidationError(
                "Couldn't find an appointment for you today.")

        # if they have any appointments set their status to Arrived
        for appointment in appointments:
            self.cleaned_data['appointment_id'] = appointment.get('id')
            import random
            if random.randrange(20) % 4:
                appointments_client.update(self.cleaned_data['appointment_id'],
                                           {'status': 'Arrived'})

            # create a Visit object
            visit, created = Visit.objects.get_or_create(
                appointment_id=self.cleaned_data['appointment_id'],
                patient_id=self.cleaned_data['patient_id'])

            # if there was already a Visit object and it is set to Arrived, they already checked in!
            if not created and visit.status == 'Arrived':
                raise forms.ValidationError(
                    "You already checked in for your appointment today.")
Exemplo n.º 8
0
 def fetch_appointment_list(self):
     """
     Use the token we have stored in the DB to make an API request and get appointment list. 
     """
     # We can create an instance of an endpoint resource class, and use it to fetch details
     access_token = self.get_token()
     api = AppointmentEndpoint(access_token)
     # Grab all appointments from one date
     return api.list(date='2020-02-06')
Exemplo n.º 9
0
 def make_api_request(self):
     """
     Use the token we have stored in the DB to make an API request and get doctor details. If this succeeds, we've
     proved that the OAuth setup is working
     """
     # We can create an instance of an endpoint resource class, and use it to fetch details
     access_token = self.get_token()
     api = AppointmentEndpoint(access_token)
     # Grab the first doctor from the list; normally this would be the whole practice group, but your hackathon
     # account probably only has one doctor in it.
     return (api.list(date="2019-10-22"))
Exemplo n.º 10
0
 def get_appointments(self, date=None, start=None, end=None):
     """
     Get appointments in certain date or range
     But in this Hackathon, only TODAY's appointments are pulled. 
     Using ID as key
     """
     access_token = self.get_token()
     api = AppointmentEndpoint(access_token)
     for appointment in list(api.list(None, date, start, end)):
         self.appointments[appointment['id']] = api.fetch(
             appointment['id'], 'verbose=true')
     return self.appointments
Exemplo n.º 11
0
def make_appt_api_request(access_token):
    appt_api = AppointmentEndpoint(access_token)
    for appt in appt_api.list(date=datetime.now()):
        obj, _ = Appointment.objects.update_or_create(
            pk=appt["id"],
            defaults={
                "doctor": Doctor.objects.get(id=appt["doctor"]),
                "patient": Patient.objects.get(id=appt["patient"]),
                "status": appt["status"],
                "start_time": appt["scheduled_time"],
                "duration": appt["duration"]
            })
Exemplo n.º 12
0
 def apt_db_save(self, token):
     apt_api = AppointmentEndpoint(token)
     # Sometimes, this api cannot return all the appointments from start time to end time.
     for p in apt_api.list(start='2019-11-2', end='2019-11-10'):
         p_start_time = datetime.datetime.strptime(p[u'scheduled_time'],
                                                   '%Y-%m-%dT%H:%M:%S')
         p_end_time = p_start_time + datetime.timedelta(
             minutes=int(p[u'duration']))
         appointment = models.Appointment(apt_id=p[u'id'], doctor_id=p[u'doctor'], patient_id=p[u'patient'], \
                                          scheduled_time=p[u'scheduled_time'], duration=p[u'duration'], end_time=p_end_time,\
                                          status=p[u'status'], reason=p[u'reason'])
         appointment.save()
     return
Exemplo n.º 13
0
def list_today(request):
    """
    List Today's Appointments
    """
    api_appt = AppointmentEndpoint(ChronoOauth.get_token())
    current_date = datetime.now().strftime("%Y-%m-%d")
    try:
        appointments_data = api_appt.list(date=current_date)
        appointments_list = list(appointments_data)
    except Exception, e:
        print(e)
        return JsonResponse({
                'error' : 'D))0000MNN Could not fetch Appointments List.'
            })
Exemplo n.º 14
0
def manage_exam_room(request):
    if request.method == 'POST':
        oauth_provider = UserSocialAuth.objects.get(provider='drchrono')
        access_token = oauth_provider.extra_data['access_token']
        api = AppointmentEndpoint(access_token)
        for p in api.list(start='2019-10-25', end='2019-10-26'):
            appointment = models.Appointment(apt_id=p[u'id'], doctor_id=p[u'doctor'], patient_id=p[u'patient'], \
                                             scheduled_time=p[u'scheduled_time'], duration=p[u'duration'], \
                                             status=p[u'status'], reason=p[u'reason'], exam_room_id=p[u'exam_room'])
            appointment.save()
    else:
        pass
    appointment_db = models.Appointment.objects.all()
    return render(request, 'patient_checkin.html', {})
Exemplo n.º 15
0
def list_today_status(request):
    """
    List Today's Appointment Statuses only.
    Even though the API gets the entire Appointment Data,
    Down the road, there will be an opportunity to get partial data.
    """
    api_appt = AppointmentEndpoint(ChronoOauth.get_token())
    current_date = datetime.now().strftime("%Y-%m-%d")
    try:
        appointments_data = api_appt.list(date=current_date)
        appointments_list = list(appointments_data)
    except Exception, e:
        print(e)
        return JsonResponse(
            {
                'error' : 'D))0000MNN Could not fetch Appointments List.'
            })
Exemplo n.º 16
0
 def get_context_data(self, **kwargs):
     kwargs = super(PatientAppointmentListView,
                    self).get_context_data(**kwargs)
     patient_id = self.kwargs['id']
     access_token = get_token()
     ap_api = AppointmentEndpoint(access_token)
     pt_api = PatientSummaryEndpoint(access_token)
     ap_params = {"patient": patient_id}
     patient_info = pt_api.fetch(id=patient_id)
     appointments = list(ap_api.list(params=ap_params,
                                     date=dt.date.today()))
     for a in appointments:
         a['start_time'] = dt.datetime.strptime(a["scheduled_time"],
                                                "%Y-%m-%dT%H:%M:%S")
         a['end_time'] = a["start_time"]\
             + dt.timedelta(minutes=int(a["duration"]))
     kwargs["patient_info"] = patient_info
     kwargs["appointments"] = appointments
     return kwargs
Exemplo n.º 17
0
def getpatientappointments(request, id):
    patientid = id
    access_token = get_token()
    api = AppointmentEndpoint(access_token)

    params = {}
    params['patient'] = patientid
    params['date'] = str(datetime.today().year) + '-' + str(
        datetime.today().month) + '-' + str(datetime.today().day)
    params['date'] = '2019-11-01'

    appointments = api.list(params=params)
    appointmentList = []

    for a in appointments:
        appointmentList.append(a)

    response = {}
    response['appointments'] = appointmentList

    return JsonResponse(response)
Exemplo n.º 18
0
    def get_all_appointments(self, first_name=None, last_name=None, date_of_birth=None, doctor_id=None):
        """
        :param : either {first_name: last_name: date_of_birth: } or {doctor_id: }
        :return: all appointments iterator
        """
        api = AppointmentEndpoint(self.access_token)

        # should be the current date.
        current_time = self.get_current_time()
        date = current_time.strftime("%Y-%m-%d")

        params = {}

        if doctor_id is not None:
            params = {'date': date, 'doctor': doctor_id}
        elif first_name is not None and last_name is not None and date_of_birth is not None:
            patient_details = self.get_patient(first_name=first_name, last_name=last_name, date_of_birth=date_of_birth)
            patient_id = patient_details["id"]
            params = {'date': date, "patient": patient_id}
        else:
            raise Exception("Must provide first name, last name and date_of_birth OR doctor id")

        return api.list(params)
Exemplo n.º 19
0
    def getAppointments(self):
        """
        Use the token we have stored in the DB to make an API request and get doctor details. If this succeeds, we've
        proved that the OAuth setup is working
        """
        # We can create an instance of an endpoint resource class, and use it to fetch details
        access_token = self.get_token()
        api = AppointmentEndpoint(access_token)

        date = datetime.strptime(self.request.GET.get('date'), '%Y-%m-%d')\
            if self.request.GET.get('date') else None
        start = datetime.strptime(self.request.GET.get('start'), '%Y-%m-%d')\
            if self.request.GET.get('start') else None
        end = datetime.strptime(self.request.GET.get('end'), '%Y-%m-%d')\
            if self.request.GET.get('end') else None

        appointments = api.list(date=date, start=start, end=end)
        appointmentsList = []

        for a in appointments:
            appointmentsList.append(a)

        return appointmentsList
Exemplo n.º 20
0
    def form_valid(self, form):
        """
            update patient info.
            if patient already has an appointment, mark status as arrived
            else create an appointment and mark status as arrived
         """
        print('\n \n form VALID !!')
        todays_date = date.today()
        access_token = utility.get_token()
        patient_api = PatientEndpoint(access_token)

        # update patient demographics
        update_resp = patient_api.update(id=str(self.kwargs['patient_id']),
                                         data=form.cleaned_data)

        # check if this patient has an appointment
        appnt_api = AppointmentEndpoint(access_token)
        appnt_list = list(
            appnt_api.list(
                date=todays_date,
                params={'patient': self.kwargs['patient_id']},
            ))
        print()
        print('appnt_list={}'.format(appnt_list))

        # if appnt doesnt exist create one
        if appnt_list == []:
            new_appt = appnt_api.create(data={
                'date': todays_date,
                'patient': self.kwargs['patient_id']
            })

            print()
            print('new_appt={}'.format(new_appt))

        return super(PatientUpdateProfile, self).form_valid(form)
Exemplo n.º 21
0
 def get_appointments_on_date(self, on_date):
     access_token = utility.get_token()
     appnt_api = AppointmentEndpoint(access_token)
     return appnt_api.list(date=on_date)
Exemplo n.º 22
0
 def fetch_appointment(self, today=None):
     if not today:
         today = "2019-10-25"
     todays_date = date.today().strftime("%Y-%m-%d")
     api = AppointmentEndpoint(self.get_token())
     return api.list(date=today)
Exemplo n.º 23
0
 def get_appointments_on_date(self, date):
     auth_token = get_token()
     appointments = AppointmentEndpoint(auth_token)
     return appointments.list(date=date)
    def verify_patient_has_appointment(params):
        """
        Verify that a patient has a confirmed appointment with the doctor before
        asking for their Demographics information.
        
        parameters = {
            'patient_id',
            'first_name',
            'last_name',
            'appointment_id',
            'override_late'  # Will not exclude this appointment from 
            }
        """

        current_date = datetime.now().strftime("%Y-%m-%d")

        # Check if the patient actually exists.
        patient_api = PatientEndpoint(ChronoOauth.get_token())
        patient = None
        if 'patient_id' in params:
            patient = patient_api.fetch(id=params['patient_id'])
        elif 'first_name' in params and 'last_name' in params:
            patient = PatientService.find_patient_by_name(
                params['first_name'], params['last_name'])

        if not patient:
            return {'error': 'Patient not found in the Doctor\'s database.'}

        api_appt = AppointmentEndpoint(ChronoOauth.get_token())
        if 'appointment_id' in params and params['appointment_id']:
            """
            Check a patient into a specific appointment.
            """
            target_appointment = api_appt.fetch(id=params['appointment_id'])

        else:
            """
            Grab a list of the nearest available Appointment.
            """

            current_appointments = api_appt.list(date=current_date)
            current_appointments_list = list(current_appointments)

            # Determine whether a patient can be seen by the doctor.
            # The api automatically sorts the schedules by the time.
            #TODO: Do not yet factor Early Checkin or Late Arrivals. Just deal with a single status.
            target_appointment = None
            for appointment in current_appointments_list:

                # If a patient has multiple schedules throughout the day,
                # that patient cannot be 'checked_in' twice.
                if appointment['patient'] == patient['id'] and \
                    appointment['status'] in settings.DRCHRONO_VALID_SEEABLE_PATIENTS:
                    break

                if appointment['patient'] == patient['id'] and \
                    appointment['status'] in settings.DRCHRONO_VALID_APPOINTMENTS:

                    # No time to debug this extra functionality...
                    #if 'override_late' not in params or not params['override_late']:
                    #    # If this appointment time is later than the Doctors Practice's
                    #    # Late limit, then skip this appointment.
                    #    scheduled_time = datetime.strptime (appointment['scheduled_time'], "%Y-%m-%dT%H:%M:%S")
                    #    schedule_epoch = (scheduled_time - datetime(1970, 1, 1)).total_seconds()
                    #
                    #    late_time = time.time() - schedule_epoch
                    #    if late_time > settings.PATIENT_LATE_CUTOFF_TIME*60:
                    #        print('wut? {} {}'.format(late_time, settings.PATIENT_LATE_CUTOFF_TIME))
                    #        continue

                    target_appointment = appointment
                    break

                elif appointment['patient'] == patient['id']:
                    pass

        if not target_appointment:
            return {
                'error' : 'Were sorry, it appears you have either: not confirmed an appointment, '+\
                        'have already checked in, are Late (over {} Minutes), rescheduled, etc'.\
                            format(settings.PATIENT_LATE_CUTOFF_TIME)
            }

        return target_appointment
Exemplo n.º 25
0
    def get_context_data(self, **kwargs):
        """

        :param kwargs:
        :return:
        """
        kwargs = super(DoctorWelcome, self).get_context_data(**kwargs)

        # look for oauth user, so we can use it's access_token
        oauth_provider = get_object_or_404(UserSocialAuth, provider='drchrono')

        # check if token is about to expire, and refresh it if so
        if self.is_access_token_expired(
                oauth_provider.extra_data['access_token']):
            oauth_provider.refresh_token(load_strategy())

        access_token = oauth_provider.extra_data['access_token']
        patient_client = PatientEndpoint(access_token)
        appointments_client = AppointmentEndpoint(access_token)

        # information about the doctor
        kwargs['doctor'] = next(DoctorEndpoint(access_token).list())

        # list of patients
        patients = list(patient_client.list())

        # list of today's appointments
        today_str = timezone.now().strftime('%m-%d-%y')
        todays_appointments = list(
            appointments_client.list({}, start=today_str, end=today_str))
        for appointment in todays_appointments:
            patient = [
                patient for patient in patients
                if patient.get('id') == appointment.get('patient')
            ][0]
            appointment['first_name'] = patient.get('first_name')
            appointment['last_name'] = patient.get('last_name')
        kwargs['appointments'] = todays_appointments

        # fetch information about patients who have checked in
        visits = Visit.objects.filter(status='Arrived',
                                      arrival_time__isnull=False,
                                      start_time__isnull=True).all()
        for visit in visits:
            visit.wait_since_arrived = visit.get_wait_duration().seconds
            patient = [
                patient for patient in patients
                if patient.get('id') == visit.patient_id
            ][0]
            visit.first_name = patient.get('first_name')
            visit.last_name = patient.get('last_name')
        kwargs['arrived'] = visits

        # fetch information about our current appointment
        current_appointment = Visit.objects.filter(
            status='In Session',
            arrival_time__isnull=False,
            start_time__isnull=False).first()
        if current_appointment:
            kwargs['current_appointment'] = current_appointment
            current_appointment.visit_duration = current_appointment.get_visit_duration(
            ).seconds
            patient = [
                patient for patient in patients
                if patient.get('id') == current_appointment.patient_id
            ][0]
            current_appointment.first_name = patient.get('first_name')
            current_appointment.last_name = patient.get('last_name')
            current_appointment.date_of_birth = patient.get('date_of_birth')
            current_appointment.date_of_last_appointment = patient.get(
                'date_of_last_appointment')
            current_appointment.race = patient.get('race')
            current_appointment.gender = patient.get('gender')
            current_appointment.ethnicity = patient.get('ethnicity')

        # create list of past visit, and use it to generate average wait and visit duration
        past_visits = Visit.objects.filter(status="Finished",
                                           arrival_time__isnull=False,
                                           start_time__isnull=False).all()
        if len(past_visits) > 0:
            avg_wait_time = sum(
                [(visit.start_time - visit.arrival_time).seconds
                 for visit in past_visits]) / len(past_visits)
            kwargs['avg_wait_duration'] = math.ceil(avg_wait_time)

            avg_visit_duration = sum(
                [(visit.end_time - visit.start_time).seconds
                 for visit in past_visits]) / len(past_visits)
            kwargs['avg_visit_duration'] = math.ceil(avg_visit_duration)
            kwargs['avg_wait_duration'] = "You have no arrivals! - 0"
            kwargs['avg_visit_duration'] = "You have no visits! - 0"
        else:
            kwargs['avg_wait_duration'] = "You have no arrivals! - 0"
            kwargs['avg_visit_duration'] = "You have no visits! - 0"

        # creating altair visualization

        # create a df with list of times and durations
        visit_data = [{
            'start_time': visit.arrival_time,
            'arrival_time': visit.start_time,
            'wait_duration': visit.get_visit_duration().seconds,
            'visit_duration': visit.get_wait_duration().seconds,
        } for visit in past_visits]
        visit_data_df = pd.DataFrame(visit_data)

        # https://altair-viz.github.io/user_guide/interactions.html#selections-building-blocks-of-interactions
        brush = alt.selection_interval(encodings=['x'])
        chart = alt.Chart(visit_data_df).mark_bar().properties(
            width=300, height=150).add_selection(brush)

        # combine two charts one with wait duration and one with visit duration
        kwargs['chart'] = alt.hconcat(
            chart.encode(x=alt.X(
                'start_time:T', axis=alt.Axis(title='Time the visit started')),
                         y=alt.Y('wait_duration:Q',
                                 axis=alt.Axis(title='Wait Duration')),
                         color=alt.condition(brush, alt.value('black'),
                                             alt.value('lightgray'))),
            chart.encode(
                x=alt.X('start_time:T',
                        axis=alt.Axis(title='Time the visit started')),
                y=alt.Y('visit_duration:Q',
                        axis=alt.Axis(title='Visit Duration')),
                color=alt.condition(
                    brush, alt.value('black'),
                    alt.value('lightgray')))).resolve_scale(y='shared')

        return kwargs