Просмотр исходного кода

wip appointments subs

feature-profilechilds
Daniel 3 лет назад
Родитель
Сommit
357224069c
7 измененных файлов: 89 добавлений и 16 удалений
  1. +4
    -1
      README.md
  2. +4
    -4
      src/client/app/js/app/model/Appointment.js
  3. +6
    -1
      src/client/app/js/app/state/ConfigurationSubProfileEdit.js
  4. +45
    -8
      src/client/app/js/app/state/Home.js
  5. +3
    -2
      src/client/app/tmpl/home-modal-appointment-subprofile.html
  6. +5
    -0
      src/server/server/control/TB_Server_Control_Profile.php
  7. +22
    -0
      src/server/shared/ent/teamdata/TB_Shared_Ent_TeamData_Attendee.php

+ 4
- 1
README.md Просмотреть файл

@@ -8,4 +8,7 @@
- timo@tbuddy.de - timo@tbuddy.de
- tretslag@gmail.com - tretslag@gmail.com
- `docker exec -it pb-php /bin/bash` - `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

+ 4
- 4
src/client/app/js/app/model/Appointment.js Просмотреть файл

@@ -551,14 +551,14 @@ app.model.Appointment = function( appData, attendees, attendeeProfiles )
* @param profileId * @param profileId
* @returns {boolean} * @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() this.getWaitingList = function()


+ 6
- 1
src/client/app/js/app/state/ConfigurationSubProfileEdit.js Просмотреть файл

@@ -126,7 +126,7 @@ app.state.ConfigurationSubProfileEdit = function()
const subProfileId = $( this ).attr( 'data-subprofile-id' ); const subProfileId = $( this ).attr( 'data-subprofile-id' );
app.core.View.confirm( 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() function()
{ {
@@ -141,6 +141,11 @@ app.state.ConfigurationSubProfileEdit = function()
{ {
app.core.View.toastSuccess( 'Unterprofile erfolgreich gelöscht' ); app.core.View.toastSuccess( 'Unterprofile erfolgreich gelöscht' );
app.core.Controller.reload(); 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();
} }
); );
}, },


+ 45
- 8
src/client/app/js/app/state/Home.js Просмотреть файл

@@ -285,7 +285,7 @@ app.state.Home = function()
} }
function callSetAttendanceStatus( appId, status, profileChildId = null )
function callSetAttendanceStatus( appId, status, profileChildId = null)
{ {
app.core.Rpc.call( app.core.Rpc.call(
'Appointment', 'Appointment',
@@ -301,11 +301,23 @@ app.state.Home = function()
{ {
app.core.View.toastSuccess( _lc( 'SAVED' ) ); app.core.View.toastSuccess( _lc( 'SAVED' ) );
renderAppointmentItem( new app.model.Appointment( res.appointment, res.attendee_data ) ); 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 else
{ {
if ( res.err == 'max_reached' ) 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-loading"]' ).first().hide();
$rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().show(); $rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).first().show();
@@ -321,7 +333,8 @@ app.state.Home = function()
'setAttendanceStatus', 'setAttendanceStatus',
{ {
appointmentId : appId, appointmentId : appId,
status : 'waiting'
status : 'waiting',
profileChildId : profileChildId
}, },
function( res ) 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 ); renderAppointmentItem( newAppointment );
} }
); );
@@ -583,12 +613,12 @@ app.state.Home = function()
} }
else if ( "deadline_reject_over" === res.err ) 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 ) ); renderAppointmentItem( getAppointment( appId ) );
} }
else if ( "appointment_is_cancelled" === res.err ) 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 ) ); renderAppointmentItem( getAppointment( appId ) );
} }
else if ( "appointment_not_accessible" === res.err ) 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-accepted"]' ).first().hide();
$rsvpContainer.find( '[data-type="section-rsvp-icon-unchecked"]' ).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(); $rsvpContainer.find( '[data-type="section-rsvp-icon-loading"]' ).first().show();
app.core.View.showModal( app.core.View.showModal(
@@ -634,24 +665,30 @@ app.state.Home = function()
$modalRoot.on( 'click', '[data-type="rsvp-button-accept"]', function() $modalRoot.on( 'click', '[data-type="rsvp-button-accept"]', function()
{ {
callSetAttendanceStatus( appId, "accepted", $(this).attr( 'data-child-profile-id' ) ); 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() $modalRoot.on( 'click', '[data-type="rsvp-button-recall"]', function()
{ {
callSetAttendanceStatus( appId, "declined", $(this).attr( 'data-child-profile-id' ) ); callSetAttendanceStatus( appId, "declined", $(this).attr( 'data-child-profile-id' ) );
app.core.View.closeModal();
console.log('decline');
//app.core.View.closeModal();
//renderAppointmentItem( appointment );
}); });
}, },
'onHide' : function() 'onHide' : function()
{ {
const $modalRoot = app.core.View.getModalContent(); const $modalRoot = app.core.View.getModalContent();
$modalRoot.off( 'click', '[data-type="rsvp-button-accept"]' ); $modalRoot.off( 'click', '[data-type="rsvp-button-accept"]' );
console.log('onHide - 685');
renderAppointmentItem( getAppointment(appId) );
}, },
'onConfirm' : function() 'onConfirm' : function()
{
{
app.core.View.closeModal(); app.core.View.closeModal();
renderAppointmentItem( appointment );
console.log('onConfirm - 690');
} }
} }
); );


+ 3
- 2
src/client/app/tmpl/home-modal-appointment-subprofile.html Просмотреть файл

@@ -1,5 +1,5 @@
<% let childProfiles = currentProfile.getChildProfiles(); %> <% let childProfiles = currentProfile.getChildProfiles(); %>
<div class="row">
<div class="row" data-row-parent="true">
<div class="col" style="line-height: 68px"> <div class="col" style="line-height: 68px">
<%= currentProfile.getName() %> <%= currentProfile.getName() %>
</div> </div>
@@ -64,7 +64,7 @@
<% for ( let ci = 0; ci < childProfiles.length; ci++ ) { %> <% for ( let ci = 0; ci < childProfiles.length; ci++ ) { %>
<hr style="margin-top: 0; margin-bottom: 0" /> <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"> <div class="col" style="line-height: 68px">
<i class="<%= currentProfile.getChildProfileIconByType(childProfiles[ ci ].type ) %>"></i>&nbsp;<%= childProfiles[ ci ].name %> <i class="<%= currentProfile.getChildProfileIconByType(childProfiles[ ci ].type ) %>"></i>&nbsp;<%= childProfiles[ ci ].name %>
</div> </div>
@@ -114,6 +114,7 @@
<div style="position:relative; width:52px; height:40px;"> <div style="position:relative; width:52px; height:40px;">
<div data-type="rsvp-button-recall" <div data-type="rsvp-button-recall"
data-appointment-id="<%= a.getId() %>" data-appointment-id="<%= a.getId() %>"
data-child-profile-id="<%= childProfiles[ ci ].id %>"
style="position: absolute;width:40px; height:40px;top:0;right:0"> style="position: absolute;width:40px; height:40px;top:0;right:0">
<svg class="rsvp-checkmark rsvp-chcekmark-waiting" <svg class="rsvp-checkmark rsvp-chcekmark-waiting"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"


+ 5
- 0
src/server/server/control/TB_Server_Control_Profile.php Просмотреть файл

@@ -171,6 +171,11 @@ class TB_Server_Control_Profile {
$subProfileId = $params->get( 'subProfileId' ); $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; $profileChildProfiles = $profileToUpdate->child_profile_js;
if ( !is_array( $profileChildProfiles ) ) if ( !is_array( $profileChildProfiles ) )
{ {


+ 22
- 0
src/server/shared/ent/teamdata/TB_Shared_Ent_TeamData_Attendee.php Просмотреть файл

@@ -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 * Return table name
* *


Загрузка…
Отмена
Сохранить