| @@ -8,4 +8,7 @@ | |||
| - timo@tbuddy.de | |||
| - tretslag@gmail.com | |||
| - `docker exec -it pb-php /bin/bash` | |||
| - SELECT * FROM profile WHERE JSON_CONTAINS( `teams_js`, '{"team_id":"75"}' ); | |||
| - SELECT * FROM profile WHERE JSON_CONTAINS( `teams_js`, '{"team_id":"75"}' ); | |||
| - dog@probuddy.xy | |||
| - 1337hamburg@gmail.com | |||
| - d.knudsen@spawntree.de | |||
| @@ -551,14 +551,14 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles ) | |||
| * @param profileId | |||
| * @returns {boolean} | |||
| */ | |||
| this.hasProfileIdDeclined = function( profileId ) | |||
| this.hasProfileIdDeclined = function( profileId, profileChildId = null ) | |||
| { | |||
| return ( "declined" === this.getAttendeeStatusForProfileId( profileId ) ); | |||
| return ( "declined" === this.getAttendeeStatusForProfileId( profileId, profileChildId ) ); | |||
| }; | |||
| this.isProfileIdWaiting = function( profileId ) | |||
| this.isProfileIdWaiting = function( profileId, profileChildId = null ) | |||
| { | |||
| return ( "waiting" === this.getAttendeeStatusForProfileId( profileId ) ); | |||
| return ( "waiting" === this.getAttendeeStatusForProfileId( profileId, profileChildId ) ); | |||
| }; | |||
| this.getWaitingList = function() | |||
| @@ -126,7 +126,7 @@ app.state.ConfigurationSubProfileEdit = function() | |||
| const subProfileId = $( this ).attr( 'data-subprofile-id' ); | |||
| app.core.View.confirm( | |||
| "Soll dieses Unterprofil wirklich gelöscht werden? Alle Profildaten inkl. der Terminzusagen werden unwiderrufbar gelöscht.", | |||
| "Soll dieses Unterprofil wirklich gelöscht werden? Um ein Unterprofil zu löschen, sind alle zukünftigen Terminzusagen aufzuheben.", | |||
| function() | |||
| { | |||
| @@ -141,6 +141,11 @@ app.state.ConfigurationSubProfileEdit = function() | |||
| { | |||
| app.core.View.toastSuccess( 'Unterprofile erfolgreich gelöscht' ); | |||
| app.core.Controller.reload(); | |||
| }, | |||
| function( res ) | |||
| { | |||
| app.core.View.toastError( 'Dieses Unterprofile hat noch zukünftige Terminzusagen, bitte hebe diese auf um das Unterprofil löschen zu können!' ); | |||
| app.core.Controller.reload(); | |||
| } | |||
| ); | |||
| }, | |||
| @@ -285,7 +285,7 @@ app.state.Home = function() | |||
| } | |||
| function callSetAttendanceStatus( appId, status, profileChildId = null ) | |||
| function callSetAttendanceStatus( appId, status, profileChildId = null) | |||
| { | |||
| app.core.Rpc.call( | |||
| 'Appointment', | |||
| @@ -301,11 +301,23 @@ app.state.Home = function() | |||
| { | |||
| app.core.View.toastSuccess( _lc( 'SAVED' ) ); | |||
| renderAppointmentItem( new app.model.Appointment( res.appointment, res.attendee_data ) ); | |||
| let profileContainer = profileChildId !== null ? | |||
| $('[data-row-child-profile-id="' + profileChildId + '"]') : | |||
| $('[data-row-parent="true"]'); | |||
| if (status === 'accepted') { | |||
| profileContainer.find("section").hide(); | |||
| profileContainer.find('[data-type="section-rsvp-icon-accepted"]').show(); | |||
| } else { | |||
| profileContainer.find("section").hide(); | |||
| profileContainer.find('[data-type="section-rsvp-icon-unchecked"]').show(); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| if ( res.err == 'max_reached' ) | |||
| { | |||
| $rsvpContainer = $content.find( '[data-type="appointment-rsvp-container"][data-appointment-id="' + appId + '"]' ).first(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().show(); | |||
| @@ -321,7 +333,8 @@ app.state.Home = function() | |||
| 'setAttendanceStatus', | |||
| { | |||
| appointmentId : appId, | |||
| status : 'waiting' | |||
| status : 'waiting', | |||
| profileChildId : profileChildId | |||
| }, | |||
| function( res ) | |||
| { | |||
| @@ -334,6 +347,23 @@ app.state.Home = function() | |||
| ] | |||
| ) | |||
| ); | |||
| let profileContainer = profileChildId !== null ? | |||
| $('[data-row-child-profile-id="' + profileChildId + '"]') : | |||
| $('[data-row-parent="true"]'); | |||
| profileContainer.find("section").hide(); | |||
| profileContainer.find('[data-type="section-rsvp-icon-waiting"]').show(); | |||
| // if (status === 'accepted') { | |||
| // profileContainer.find("section").hide(); | |||
| // profileContainer.find('[data-type="section-rsvp-icon-accepted"]').show(); | |||
| // } else { | |||
| // profileContainer.find("section").hide(); | |||
| // profileContainer.find('[data-type="section-rsvp-icon-unchecked"]').show(); | |||
| // } | |||
| renderAppointmentItem( newAppointment ); | |||
| } | |||
| ); | |||
| @@ -583,12 +613,12 @@ app.state.Home = function() | |||
| } | |||
| else if ( "deadline_reject_over" === res.err ) | |||
| { | |||
| app.core.View.alert( _lc( 'DEADLINE_REJECT_IS_OVER' ) ); | |||
| app.core.View.toastError( _lc( 'DEADLINE_REJECT_IS_OVER' ) ); | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| else if ( "appointment_is_cancelled" === res.err ) | |||
| { | |||
| app.core.View.alert( _lc( 'APPOINTMENT_IS_ALREADY_CANCELLED' ) ); | |||
| app.core.View.toastError( _lc( 'APPOINTMENT_IS_ALREADY_CANCELLED' ) ); | |||
| renderAppointmentItem( getAppointment( appId ) ); | |||
| } | |||
| else if ( "appointment_not_accessible" === res.err ) | |||
| @@ -620,6 +650,7 @@ app.state.Home = function() | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-accepted"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-waiting"]' ).first().hide(); | |||
| $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().show(); | |||
| app.core.View.showModal( | |||
| @@ -634,24 +665,30 @@ app.state.Home = function() | |||
| $modalRoot.on( 'click', '[data-type="rsvp-button-accept"]', function() | |||
| { | |||
| callSetAttendanceStatus( appId, "accepted", $(this).attr( 'data-child-profile-id' ) ); | |||
| app.core.View.closeModal(); | |||
| console.log('accept'); | |||
| //app.core.View.closeModal(); | |||
| //renderAppointmentItem( appointment ); | |||
| }); | |||
| $modalRoot.on( 'click', '[data-type="rsvp-button-recall"]', function() | |||
| { | |||
| callSetAttendanceStatus( appId, "declined", $(this).attr( 'data-child-profile-id' ) ); | |||
| app.core.View.closeModal(); | |||
| console.log('decline'); | |||
| //app.core.View.closeModal(); | |||
| //renderAppointmentItem( appointment ); | |||
| }); | |||
| }, | |||
| 'onHide' : function() | |||
| { | |||
| const $modalRoot = app.core.View.getModalContent(); | |||
| $modalRoot.off( 'click', '[data-type="rsvp-button-accept"]' ); | |||
| console.log('onHide - 685'); | |||
| renderAppointmentItem( getAppointment(appId) ); | |||
| }, | |||
| 'onConfirm' : function() | |||
| { | |||
| { | |||
| app.core.View.closeModal(); | |||
| renderAppointmentItem( appointment ); | |||
| console.log('onConfirm - 690'); | |||
| } | |||
| } | |||
| ); | |||
| @@ -1,5 +1,5 @@ | |||
| <% let childProfiles = currentProfile.getChildProfiles(); %> | |||
| <div class="row"> | |||
| <div class="row" data-row-parent="true"> | |||
| <div class="col" style="line-height: 68px"> | |||
| <%= currentProfile.getName() %> | |||
| </div> | |||
| @@ -64,7 +64,7 @@ | |||
| <% for ( let ci = 0; ci < childProfiles.length; ci++ ) { %> | |||
| <hr style="margin-top: 0; margin-bottom: 0" /> | |||
| <div class="row"> | |||
| <div class="row" data-row-child-profile-id="<%= childProfiles[ ci ].id %>"> | |||
| <div class="col" style="line-height: 68px"> | |||
| <i class="<%= currentProfile.getChildProfileIconByType(childProfiles[ ci ].type ) %>"></i> <%= childProfiles[ ci ].name %> | |||
| </div> | |||
| @@ -114,6 +114,7 @@ | |||
| <div style="position:relative; width:52px; height:40px;"> | |||
| <div data-type="rsvp-button-recall" | |||
| data-appointment-id="<%= a.getId() %>" | |||
| data-child-profile-id="<%= childProfiles[ ci ].id %>" | |||
| style="position: absolute;width:40px; height:40px;top:0;right:0"> | |||
| <svg class="rsvp-checkmark rsvp-chcekmark-waiting" | |||
| xmlns="http://www.w3.org/2000/svg" | |||
| @@ -171,6 +171,11 @@ class TB_Server_Control_Profile { | |||
| $subProfileId = $params->get( 'subProfileId' ); | |||
| $attendencies = TB_Shared_Ent_TeamData_Attendee::getUpcomingAttendencies($profileToUpdate->id, $subProfileId); | |||
| if ( count($attendencies) > 0 ) { | |||
| throw new \Exception( 'Sub profile has upcoming attendencies' ); | |||
| } | |||
| $profileChildProfiles = $profileToUpdate->child_profile_js; | |||
| if ( !is_array( $profileChildProfiles ) ) | |||
| { | |||
| @@ -245,6 +245,28 @@ class TB_Shared_Ent_TeamData_Attendee extends Francis_Db_Row { | |||
| } | |||
| } | |||
| public static function getUpcomingAttendencies($profileId, $subProfileId = null) | |||
| { | |||
| $dbh = self::getDbh(); | |||
| $dbParams = []; | |||
| $dbParams[':profile_id'] = $profileId; | |||
| $sql = 'SELECT att.* FROM attendee att, appointment app '; | |||
| $sql .= 'WHERE att.profile_id = :profile_id '; | |||
| $sql .= 'AND att.appointment_id = app.id '; | |||
| if (null !== $subProfileId) { | |||
| $sql .= 'AND att.profile_child_id = :sub_profile_id '; | |||
| $dbParams[':sub_profile_id'] = $subProfileId; | |||
| } | |||
| $sql .= 'AND app.deadline_reject_dt > NOW() '; | |||
| $sql .= "AND att.status != 'declined'"; | |||
| $stmt = $dbh->prepare( $sql ); | |||
| $stmt->execute( $dbParams ); | |||
| $res = $stmt->fetchAll( PDO::FETCH_ASSOC ); | |||
| return $res; | |||
| } | |||
| /** | |||
| * Return table name | |||
| * | |||