# Conflicts: # .DS_Store # src/client/app/tmpl/home-appointment-item.html # src/server/server/config/boot_local.phpfeature-profilechilds
| @@ -0,0 +1,57 @@ | |||||
| FROM php:7.4-apache | |||||
| ENV APACHE_DOCUMENT_ROOT /var/www/html/src | |||||
| ENV APACHE_SERVER_NAME localhost | |||||
| ENV PATH="$PATH" | |||||
| WORKDIR /var/www/html | |||||
| RUN apt-get update | |||||
| RUN apt-get install -y \ | |||||
| libfreetype6-dev \ | |||||
| libjpeg62-turbo-dev \ | |||||
| libpng-dev \ | |||||
| libicu-dev \ | |||||
| libzip-dev \ | |||||
| zip \ | |||||
| && docker-php-ext-install -j$(nproc) iconv \ | |||||
| && docker-php-ext-configure gd --with-jpeg=/usr/include/ --with-freetype=/usr/include/ \ | |||||
| && docker-php-ext-install -j$(nproc) gd \ | |||||
| && docker-php-ext-install -j$(nproc) intl \ | |||||
| && docker-php-ext-install -j$(nproc) pdo_mysql \ | |||||
| && docker-php-ext-install zip | |||||
| RUN apt-get install -y git zip | |||||
| RUN apt-get install mariadb-client -y | |||||
| RUN apt install nano | |||||
| RUN pecl install xdebug \ | |||||
| && docker-php-ext-enable xdebug \ | |||||
| && echo "xdebug.mode=debug" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \ | |||||
| && echo "xdebug.client_host = host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \ | |||||
| && echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \ | |||||
| && echo 'xdebug.discover_client_host=1' >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \ | |||||
| && echo 'xdebug.log=/var/www/var/log/xdebug.log' >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \ | |||||
| && echo 'xdebug.log_level=0' >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini | |||||
| RUN a2enmod rewrite && a2enmod headers | |||||
| RUN a2ensite 000-default | |||||
| COPY ./ /var/www/html | |||||
| RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf | |||||
| RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf | |||||
| RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" | |||||
| RUN chown -R www-data:www-data /var/www/html/ | |||||
| COPY /init.sh /init.sh | |||||
| RUN chmod 755 /init.sh | |||||
| RUN chmod +x /init.sh | |||||
| EXPOSE 80 | |||||
| ENTRYPOINT ["/init.sh"] | |||||
| CMD ["apache2-foreground"] | |||||
| @@ -0,0 +1,40 @@ | |||||
| version: '3.7' | |||||
| services: | |||||
| database: | |||||
| image: mariadb | |||||
| container_name: pb-mariadb | |||||
| ports: | |||||
| - "3398:3306" | |||||
| environment: | |||||
| # think about .env file here | |||||
| MYSQL_ROOT_PASSWORD: root | |||||
| volumes: | |||||
| - ./../.db:/var/lib/mysql | |||||
| restart: always | |||||
| networks: | |||||
| - default | |||||
| pbuddy: | |||||
| build: | |||||
| context: ./ | |||||
| dockerfile: Dockerfile | |||||
| image: 'pb_spt_image' | |||||
| container_name: pb-php | |||||
| ports: | |||||
| - '8097:80' | |||||
| volumes: | |||||
| - ./../:/var/www/html | |||||
| networks: | |||||
| - default | |||||
| phpmyadmin: | |||||
| image: phpmyadmin | |||||
| container_name: pb-phpmyadmin | |||||
| restart: always | |||||
| ports: | |||||
| - "8096:80" | |||||
| environment: | |||||
| - PMA_ARBITRARY=1 | |||||
| networks: | |||||
| - default | |||||
| networks: | |||||
| default: | |||||
| @@ -0,0 +1,13 @@ | |||||
| #!/bin/sh | |||||
| echo "create log files" | |||||
| su www-data -s /bin/bash | |||||
| mkdir /var/www/html/temp | |||||
| mkdir /var/www/html/logs | |||||
| cd /var/www/html/logs | |||||
| touch tbserver-log.txt | |||||
| touch tbserver-cron-log.txt | |||||
| echo "$@" | |||||
| docker-php-entrypoint "$@" | |||||
| @@ -0,0 +1,9 @@ | |||||
| - Client: http://localhost:8097/client/app/#/auth/start | |||||
| - Database: http://localhost:8096 | |||||
| - Template-Engine: https://github.com/cho45/micro-template.js | |||||
| - Test-Accounts: | |||||
| - dog@probuddy.xy | |||||
| - info@coaching4dogs.xx (kein Admin-Account) | |||||
| - benny@probuddy.de | |||||
| - timo@tbuddy.de | |||||
| - tretslag@gmail.com | |||||
| @@ -0,0 +1,3 @@ | |||||
| <?php | |||||
| echo md5( 'test' . 'das214!!!ede7105bdaee5fa873ec500' ); | |||||
| @@ -16,9 +16,9 @@ app.core.Dict = { | |||||
| "REGISTER_VALIDATION_ERROR_PASSWORD" : "Verwende ein Passwort von min 4 Zeichen und max 32 Zeichen", | "REGISTER_VALIDATION_ERROR_PASSWORD" : "Verwende ein Passwort von min 4 Zeichen und max 32 Zeichen", | ||||
| "REGISTER_CHOOSE_INDUSTRY" : "Wähle deinen Branche aus...", | "REGISTER_CHOOSE_INDUSTRY" : "Wähle deinen Branche aus...", | ||||
| "REGISTER_LOOKS_GOOD" : "Sieht gut aus!", | "REGISTER_LOOKS_GOOD" : "Sieht gut aus!", | ||||
| "REGISTER_VALIDATION_ERROR_TEAMNAME" : "Gebe der Gruppe einen Namen (min 5 Zeichen, max 32 Zeichen)", | |||||
| "REGISTER_VALIDATION_ERROR_EMAIL" : "Gebe eine korrekte Email Adresse ein.", | |||||
| "REGISTER_INDUSTRY_FITNESS" : "Sport- und Fitness", | |||||
| "REGISTER_VALIDATION_ERROR_TEAMNAME" : "Gib der Gruppe einen Namen (min 5 Zeichen, max 32 Zeichen)", | |||||
| "REGISTER_VALIDATION_ERROR_EMAIL" : "Gib eine korrekte Email Adresse ein.", | |||||
| "REGISTER_INDUSTRY_FITNESS" : "Sport und Fitness", | |||||
| "REGISTER_INDUSTRY_YOGA" : "Yoga", | "REGISTER_INDUSTRY_YOGA" : "Yoga", | ||||
| "REGISTER_INDUSTRY_FIREFIGHTER" : "Feuerwehr", | "REGISTER_INDUSTRY_FIREFIGHTER" : "Feuerwehr", | ||||
| "REGISTER_INDUSTRY_CHARITY" : "Gemeinnütziger Verein", | "REGISTER_INDUSTRY_CHARITY" : "Gemeinnütziger Verein", | ||||
| @@ -59,7 +59,7 @@ app.core.Dict = { | |||||
| "MEMBERS" : "Mitglieder", | "MEMBERS" : "Mitglieder", | ||||
| "INVITATION" : "Einladung", | "INVITATION" : "Einladung", | ||||
| "STATS" : "Statistik", | "STATS" : "Statistik", | ||||
| "TEAM_DETAIL_TEAMNAME_PLACEHOLDER" : "Bitte gebe deinem Firmen-/Gruppennamen ein", | |||||
| "TEAM_DETAIL_TEAMNAME_PLACEHOLDER" : "Bitte gib deinem Firmen-/Gruppennamen ein", | |||||
| "TEAM_DETAIL_TEAMDESCRIPTION_PLACEHOLDER" : "Schreibe ein paar Worte über deine Gruppe...", | "TEAM_DETAIL_TEAMDESCRIPTION_PLACEHOLDER" : "Schreibe ein paar Worte über deine Gruppe...", | ||||
| "BTN_SAVE_CHANGES" : "Änderungen speichern", | "BTN_SAVE_CHANGES" : "Änderungen speichern", | ||||
| "UNKNOWN_NAME" : "Name unbekannt", | "UNKNOWN_NAME" : "Name unbekannt", | ||||
| @@ -80,14 +80,14 @@ app.core.Dict = { | |||||
| "JOIN_WELCOME_TEXT" : "Du wurdest eingeladen, der Gruppe <strong>{0}</strong> auf <strong>Pro</strong>Buddy beizutreten.", | "JOIN_WELCOME_TEXT" : "Du wurdest eingeladen, der Gruppe <strong>{0}</strong> auf <strong>Pro</strong>Buddy beizutreten.", | ||||
| "JOIN_WELCOME_INSTRUCTIONS" : "In nur zwei Schritten bist du dabei!", | "JOIN_WELCOME_INSTRUCTIONS" : "In nur zwei Schritten bist du dabei!", | ||||
| "JOIN_STEP_1" : "Installiere die native Android- oder iOS Version.", | "JOIN_STEP_1" : "Installiere die native Android- oder iOS Version.", | ||||
| "JOIN_STEP_2" : "Starte die App und gebe die folgende ID von Gruppe '{0}' ein:", | |||||
| "JOIN_STEP_2" : "Starte die App und gib die folgende ID von Gruppe '{0}' ein:", | |||||
| "JOIN_WEB_TEXT" : "Du hast kein iOS- oder Android Gerät? Kein Problem, dann nutze die Browserversion von <strong>Pro</strong>Buddy.", | "JOIN_WEB_TEXT" : "Du hast kein iOS- oder Android Gerät? Kein Problem, dann nutze die Browserversion von <strong>Pro</strong>Buddy.", | ||||
| "JOIN_WEB_LINKTEXT" : "Zur Gruppenanmeldung", | "JOIN_WEB_LINKTEXT" : "Zur Gruppenanmeldung", | ||||
| "JOINWEB_INSTRUCTION_TEXT" : "Bitte fülle noch kurz das Formular aus.", | "JOINWEB_INSTRUCTION_TEXT" : "Bitte fülle noch kurz das Formular aus.", | ||||
| "BTN_JOINWEB" : "Beitreten", | "BTN_JOINWEB" : "Beitreten", | ||||
| "WELCOME_NEW_USER_HEADER" : "Hallo!", | "WELCOME_NEW_USER_HEADER" : "Hallo!", | ||||
| "WELCOME_NEW_USER_DESCRIPTION" : "Willkommen bei <strong>Pro</strong>Buddy.", | "WELCOME_NEW_USER_DESCRIPTION" : "Willkommen bei <strong>Pro</strong>Buddy.", | ||||
| "NEW_USER_INSTRUCTIONS" : "Bitte gebe die ID der Gruppe an, der du beitreten möchtest.", | |||||
| "NEW_USER_INSTRUCTIONS" : "Bitte gib die ID der Gruppe an, der du beitreten möchtest.", | |||||
| "TEAM_ID" : "Gruppen ID", | "TEAM_ID" : "Gruppen ID", | ||||
| "ALREADY_AN_ACCOUNT" : "Du hast bereits einen Account bei uns?", | "ALREADY_AN_ACCOUNT" : "Du hast bereits einen Account bei uns?", | ||||
| "GO_TO_LOGIN" : "Hier geht's zum Login.", | "GO_TO_LOGIN" : "Hier geht's zum Login.", | ||||
| @@ -224,7 +224,7 @@ app.core.Dict = { | |||||
| "NO_REACTION" : "Keine Reaktion", | "NO_REACTION" : "Keine Reaktion", | ||||
| "ACCEPTED" : "Zugesagt", | "ACCEPTED" : "Zugesagt", | ||||
| "DECLINED" : "Abgesagt", | "DECLINED" : "Abgesagt", | ||||
| "ANONYMOUS" : "Dieses Profile ist anonym", | |||||
| "ANONYMOUS" : "Dieses Profil ist anonym", | |||||
| "GROUP_OVERVIEW" : "Gruppenübersicht", | "GROUP_OVERVIEW" : "Gruppenübersicht", | ||||
| "YOUR_GROUPS" : "Deine Gruppen ({0})", | "YOUR_GROUPS" : "Deine Gruppen ({0})", | ||||
| "GROUP_DETAIL_VIEW" : "Gruppenansicht", | "GROUP_DETAIL_VIEW" : "Gruppenansicht", | ||||
| @@ -239,7 +239,7 @@ app.core.Dict = { | |||||
| "GROUP_NAME" : "Gruppenname", | "GROUP_NAME" : "Gruppenname", | ||||
| "GROUP_DESCRIPTION" : "Beschreibung", | "GROUP_DESCRIPTION" : "Beschreibung", | ||||
| "GROUP_INDUSTRY" : "Branche", | "GROUP_INDUSTRY" : "Branche", | ||||
| "GROUP_INDUSTRY_FITNESS" : "Sport- und Fitness", | |||||
| "GROUP_INDUSTRY_FITNESS" : "Sport und Fitness", | |||||
| "GROUP_INDUSTRY_YOGA" : "Yoga", | "GROUP_INDUSTRY_YOGA" : "Yoga", | ||||
| "GROUP_INDUSTRY_FIREFIGHTER" : "Feuerwehr", | "GROUP_INDUSTRY_FIREFIGHTER" : "Feuerwehr", | ||||
| "GROUP_INDUSTRY_CHARITY" : "Gemeinnütziger Verein", | "GROUP_INDUSTRY_CHARITY" : "Gemeinnütziger Verein", | ||||
| @@ -276,6 +276,7 @@ app.core.Dict = { | |||||
| "ACTIONMENU_CREATE_MESSAGE" : "Nachricht erstellen...", | "ACTIONMENU_CREATE_MESSAGE" : "Nachricht erstellen...", | ||||
| "ACTIONMENU_CREATE_APPOINTMENT" : "Termin erstellen...", | "ACTIONMENU_CREATE_APPOINTMENT" : "Termin erstellen...", | ||||
| "ACTIONMENU_INVITE" : "Mitglieder einladen...", | "ACTIONMENU_INVITE" : "Mitglieder einladen...", | ||||
| "ACTIONMENU_MANAGER_CONSOLE" : "Manager-Konsole", | |||||
| "FROM" : "Von", | "FROM" : "Von", | ||||
| "SUBJECT" : "Betreff", | "SUBJECT" : "Betreff", | ||||
| "DATE" : "", | "DATE" : "", | ||||
| @@ -360,7 +361,7 @@ app.core.Dict = { | |||||
| "FORMHELP_APPOINTMENT_MAX_ATTENDEES" : "Sind die Plätze im Kurs begrenzt? Dann limitiere die Zusagen durch eine Eingabe der Maximalteilnehmerzahl. Wird diese erreicht, können sich Interessierte immer noch auf eine Warteliste setzen.", | "FORMHELP_APPOINTMENT_MAX_ATTENDEES" : "Sind die Plätze im Kurs begrenzt? Dann limitiere die Zusagen durch eine Eingabe der Maximalteilnehmerzahl. Wird diese erreicht, können sich Interessierte immer noch auf eine Warteliste setzen.", | ||||
| "FORMHELP_APPOINTMENT_DEADLINE" : "Verhindere kurzfristige Zusagen, um deine Planungsicherheit zu erhöhen. Nutze hierfür die Zusagefrist zu diesem Termin.", | "FORMHELP_APPOINTMENT_DEADLINE" : "Verhindere kurzfristige Zusagen, um deine Planungsicherheit zu erhöhen. Nutze hierfür die Zusagefrist zu diesem Termin.", | ||||
| "FORMHELP_APPOINTMENT_DEADLINE_REJECT" : "Verhindere kurzfristige Absagen indem Du einen Zeitpunkt bestimmst, bis wann Mitglieder, die zugesagt haben, wieder absagen können.", | "FORMHELP_APPOINTMENT_DEADLINE_REJECT" : "Verhindere kurzfristige Absagen indem Du einen Zeitpunkt bestimmst, bis wann Mitglieder, die zugesagt haben, wieder absagen können.", | ||||
| "FORMHELP_PROFILE_PRIVACY" : "Gruppeninhaber und Admiins sind jederzeit für alle sichtbar. Als Mitglied hast du die Möglichkeit, deine Profildaten vor anderen Mitgliedern zu verstecken, indem du die entsprechende Option auswählst.", | |||||
| "FORMHELP_PROFILE_PRIVACY" : "Gruppeninhaber und Admins sind jederzeit für alle sichtbar. Als Mitglied hast du die Möglichkeit, deine Profildaten vor anderen Mitgliedern zu verstecken, indem du die entsprechende Option auswählst.", | |||||
| "STAT_MEMBERS" : "Mitglieder", | "STAT_MEMBERS" : "Mitglieder", | ||||
| "STAT_APPOINTMENTS" : "Termine", | "STAT_APPOINTMENTS" : "Termine", | ||||
| "STAT_ACCEPTED" : "Zusagen", | "STAT_ACCEPTED" : "Zusagen", | ||||
| @@ -50,7 +50,7 @@ app.util.Helper = { | |||||
| if ( text.length > ( maxChars + 3 ) ) | if ( text.length > ( maxChars + 3 ) ) | ||||
| { | { | ||||
| text = text.substring( 0, maxChars ); | text = text.substring( 0, maxChars ); | ||||
| text = '...'; | |||||
| text += '...'; | |||||
| } | } | ||||
| return text; | return text; | ||||
| @@ -30,7 +30,7 @@ | |||||
| <div class="row"> | <div class="row"> | ||||
| <div class="col"> | <div class="col"> | ||||
| <p style="margin-top: 12px"> | <p style="margin-top: 12px"> | ||||
| Bitte gebe den vierstelligen Gruppencode ein | |||||
| Bitte gib den vierstelligen Gruppencode ein | |||||
| </p> | </p> | ||||
| <form data-id="form-join-group"> | <form data-id="form-join-group"> | ||||
| <div class="form-group"> | <div class="form-group"> | ||||
| @@ -43,7 +43,7 @@ | |||||
| autocomplete="off" | autocomplete="off" | ||||
| style="text-align: center; text-transform: uppercase" | style="text-align: center; text-transform: uppercase" | ||||
| required /> | required /> | ||||
| <div class="invalid-feedback">Bitte gebe den vierstelligen Gruppencode ein</div> | |||||
| <div class="invalid-feedback">Bitte gib den vierstelligen Gruppencode ein</div> | |||||
| </div> | </div> | ||||
| <div class="form-group"> | <div class="form-group"> | ||||
| <button class="btn btn-block btn-primary" | <button class="btn btn-block btn-primary" | ||||
| @@ -23,6 +23,11 @@ | |||||
| <% var currentUser = app.model.SessionUser ? app.model.SessionUser.getUserProfile() : null; %> | <% var currentUser = app.model.SessionUser ? app.model.SessionUser.getUserProfile() : null; %> | ||||
| <% var adminGroups = app.model.SessionUser ? app.model.SessionUser.getAdminGroups() : null; %> | <% var adminGroups = app.model.SessionUser ? app.model.SessionUser.getAdminGroups() : null; %> | ||||
| <% if ( currentUser && 0 < adminGroups.length ) { %> | <% if ( currentUser && 0 < adminGroups.length ) { %> | ||||
| <li> | |||||
| <div class="action-list-item" onclick="window.open(app.core.App.getConfig('manager.url'), '_system', 'location=yes');"> | |||||
| <i class="fas fa-server"></i> <span><%= _lc( 'ACTIONMENU_MANAGER_CONSOLE' ) %></span> | |||||
| </div> | |||||
| </li> | |||||
| <li class="action-list-item"> | <li class="action-list-item"> | ||||
| <a href="<%= ( 1 < currentUser.getNumberOfGroupsWithAdminRole() ) ? '#/groups' : ( '#/group/' + ( currentUser.getGroupData()[0].team_id ) + '/invite' ) %>"> | <a href="<%= ( 1 < currentUser.getNumberOfGroupsWithAdminRole() ) ? '#/groups' : ( '#/group/' + ( currentUser.getGroupData()[0].team_id ) + '/invite' ) %>"> | ||||
| <i class="fas fa-user-plus"></i> <span><%= _lc( 'ACTIONMENU_INVITE' ) %></span> | <i class="fas fa-user-plus"></i> <span><%= _lc( 'ACTIONMENU_INVITE' ) %></span> | ||||
| @@ -38,16 +43,16 @@ | |||||
| <i class="fas fa-sliders-h"></i> <span><%= _lc( 'ACTIONMENU_CATEGORY_MANAGEMENT' ) %></span> | <i class="fas fa-sliders-h"></i> <span><%= _lc( 'ACTIONMENU_CATEGORY_MANAGEMENT' ) %></span> | ||||
| </a> | </a> | ||||
| </li> | </li> | ||||
| <li class="action-list-item"> | |||||
| <a href="#/stats/reporting"> | |||||
| <i class="fas fa-chart-line"></i> <span><%= _lc( 'ACTIONMENU_STATS' ) %></span> | |||||
| </a> | |||||
| </li> | |||||
| <li class="action-list-item"> | |||||
| <a href="#/appointment/create"> | |||||
| <i class="fas fa-calendar-plus"></i> <span><%= _lc( 'ACTIONMENU_CREATE_APPOINTMENT' ) %></span> | |||||
| </a> | |||||
| </li> | |||||
| <li class="action-list-item"> | |||||
| <a href="#/stats/reporting"> | |||||
| <i class="fas fa-chart-line"></i> <span><%= _lc( 'ACTIONMENU_STATS' ) %></span> | |||||
| </a> | |||||
| </li> | |||||
| <li class="action-list-item"> | |||||
| <a href="#/appointment/create"> | |||||
| <i class="fas fa-calendar-plus"></i> <span><%= _lc( 'ACTIONMENU_CREATE_APPOINTMENT' ) %></span> | |||||
| </a> | |||||
| </li> | |||||
| <% } %> | <% } %> | ||||
| </ul> | </ul> | ||||
| </div> | </div> | ||||
| @@ -1,6 +1,8 @@ | |||||
| <% var currentProfile = app.model.SessionUser.getUserProfile(); %> | <% var currentProfile = app.model.SessionUser.getUserProfile(); %> | ||||
| <% var mStart = a.getMomentStart(); %> | <% var mStart = a.getMomentStart(); %> | ||||
| <% var mEnd = a.getMomentEnd(); %> | <% var mEnd = a.getMomentEnd(); %> | ||||
| <% var mStartDate = mStart.format( 'D.M.Y' ); %> | |||||
| <% var mEndDate = mEnd.format( 'D.M.Y' ); %> | |||||
| <% var mDeadline = a.getMomentDeadline(); %> | <% var mDeadline = a.getMomentDeadline(); %> | ||||
| <% var mDeadlineReject = a.getMomentDeadlineReject(); %> | <% var mDeadlineReject = a.getMomentDeadlineReject(); %> | ||||
| <% var btnClass = ''; %> | <% var btnClass = ''; %> | ||||
| @@ -50,7 +52,13 @@ | |||||
| <% } %> | <% } %> | ||||
| </div> | </div> | ||||
| <div class="appointment-datetime"> | <div class="appointment-datetime"> | ||||
| <i class="far fa-clock"></i> <%= mStart.format( 'HH:mm' ) %> - <%= mEnd.format( 'HH:mm' ) %> | <i class="far fa-thumbs-up"></i> <%= a.getNumAttendeesAccepted() %> <% if ( 0 < a.getMaxAttendees() ) { %> | <%= a.getMaxAttendees() - a.getNumAttendeesAccepted() %> verfügbar <% } %> | <%= group ? group.getName() : '' %> | |||||
| <% var displayedDateStart = mStart.format( 'HH:mm' ) %> | |||||
| <% var displayedDateEnd = mEnd.format( 'HH:mm' ) %> | |||||
| <% if ( mStart.format( 'D.M.Y' ) !== mEnd.format( 'D.M.Y' )) { %> | |||||
| <% displayedDateStart = mStart.format( 'ddd' ) + ' ' + mStart.format( 'D.M.' ) + ' ' + mStart.format( 'HH:mm' ) %> | |||||
| <% displayedDateEnd = mEnd.format( 'ddd' ) + ' ' + mEnd.format( 'D.M.' ) + ' ' + mEnd.format( 'HH:mm' ) %> | |||||
| <% } %> | |||||
| <i class="far fa-clock"></i> <%= displayedDateStart %> - <%= displayedDateEnd %> | <i class="far fa-thumbs-up"></i> <%= a.getNumAttendeesAccepted() %> <% if ( 0 < a.getMaxAttendees() ) { %> | <%= a.getMaxAttendees() - a.getNumAttendeesAccepted() %> verfügbar <% } %> | <%= group ? group.getName() : '' %> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div data-type="appointment-rsvp-container" | <div data-type="appointment-rsvp-container" | ||||
| @@ -190,7 +198,7 @@ | |||||
| <%= _lc( 'DETAILS' ) %> | <%= _lc( 'DETAILS' ) %> | ||||
| </td> | </td> | ||||
| <td> | <td> | ||||
| <%=raw a.getComment() ? app.util.Helper.crop( app.util.Helper.nl2br( a.getComment() ), 100 ) : ( '<i>' + _lc( 'APPOINTMENT_NO_COMMENT' ) + '</i>' ) %> | |||||
| <%=raw a.getComment() ? app.util.Helper.crop( app.util.Helper.nl2br( a.getComment() ), 200 ) : ( '<i>' + _lc( 'APPOINTMENT_NO_COMMENT' ) + '</i>' ) %> | |||||
| </td> | </td> | ||||
| </tr> | </tr> | ||||
| </table> | </table> | ||||
| @@ -220,6 +228,7 @@ | |||||
| <i>Gelöscht</i> | <i>Gelöscht</i> | ||||
| <% } %> | <% } %> | ||||
| <% } %> | <% } %> | ||||
| <% } %> | <% } %> | ||||
| </td> | </td> | ||||
| </tr> | </tr> | ||||
| @@ -244,6 +253,7 @@ | |||||
| <i>Gelöscht</i> | <i>Gelöscht</i> | ||||
| <% } %> | <% } %> | ||||
| <% } %> | <% } %> | ||||
| <% } %> | <% } %> | ||||
| </td> | </td> | ||||
| </tr> | </tr> | ||||
| @@ -267,6 +277,7 @@ | |||||
| <i>Gelöscht</i> | <i>Gelöscht</i> | ||||
| <% } %> | <% } %> | ||||
| <% } %> | <% } %> | ||||
| <% } %> | <% } %> | ||||
| </td> | </td> | ||||
| </tr> | </tr> | ||||
| @@ -1,5 +1,6 @@ | |||||
| <h4><a href="javascript:history.back()"><i class="fas fa-chevron-left"></i></a> <%= _lc( 'SUPPORT' ) %></h4> | <h4><a href="javascript:history.back()"><i class="fas fa-chevron-left"></i></a> <%= _lc( 'SUPPORT' ) %></h4> | ||||
| <div class="card"> | <div class="card"> | ||||
| <% if ( app.model.SessionUser.isAdminOfAnyTeam() === true ) { %> | |||||
| <form class="form" | <form class="form" | ||||
| data-id="form-support"> | data-id="form-support"> | ||||
| <div class="card-header"> | <div class="card-header"> | ||||
| @@ -13,6 +14,7 @@ | |||||
| <label for="select-reason"> | <label for="select-reason"> | ||||
| <%= _lc( 'SUPPORT_REASON' ) %> | <%= _lc( 'SUPPORT_REASON' ) %> | ||||
| </label> | </label> | ||||
| <select class="form-control custom-select" | <select class="form-control custom-select" | ||||
| id="select-reason" | id="select-reason" | ||||
| data-id="select-reason"> | data-id="select-reason"> | ||||
| @@ -46,4 +48,25 @@ | |||||
| </button> | </button> | ||||
| </div> | </div> | ||||
| </form> | </form> | ||||
| <% } else { %> | |||||
| <div class="card-header"> | |||||
| <i class="far fa-life-ring"></i> <%= _lc( 'SUPPORT_HEADLINE' ) %> | |||||
| </div> | |||||
| <div class="card-body"> | |||||
| <div class="row"> | |||||
| <div class="col"> | |||||
| <strong>Wenn Du Kontakt mit dem Gruppeninhaber aufnehmen möchtest, gehe bitte wie folgt vor:</strong> | |||||
| </div> | |||||
| </div> | |||||
| <div class="row"> | |||||
| <div class="col"> | |||||
| <p>Allgemeine Frage: Nutze bitte die Kontaktoptionen auf der Gruppenübersicht <br /> | |||||
| Frage zu einem Termin: Verwende den Chat für einen bestimmten Termin über die Terminübersicht. | |||||
| </p> | |||||
| <a href="#/groups" class="btn btn-block btn-primary"><%= _lc( 'GROUP_OVERVIEW' ) %></a> | |||||
| <a href="#/home" class="btn btn-block btn-primary"><%= _lc( 'BTN_BACK_TO_HOME' ) %></a> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <% } %> | |||||
| </div> | </div> | ||||
| @@ -4,20 +4,20 @@ | |||||
| ********************************************************************************/ | ********************************************************************************/ | ||||
| // General | // General | ||||
| Francis_Utils_Config::set( 'url.client', 'http://client.tb.com' ); | |||||
| Francis_Utils_Config::set( 'url.client', 'src/client/app/' ); | |||||
| // DB settings | // DB settings | ||||
| Francis_Utils_Config::set( 'db.tbcore.host', 'localhost' ); | |||||
| Francis_Utils_Config::set( 'db.tbcore.name', 'tb_core' ); | |||||
| Francis_Utils_Config::set( 'db.tbcore.host', 'database' ); | |||||
| Francis_Utils_Config::set( 'db.tbcore.name', 'pb_core' ); | |||||
| Francis_Utils_Config::set( 'db.tbcore.user', 'root' ); | Francis_Utils_Config::set( 'db.tbcore.user', 'root' ); | ||||
| Francis_Utils_Config::set( 'db.tbcore.pass', '' ); | |||||
| Francis_Utils_Config::set( 'db.tbcore.pass', 'root' ); | |||||
| Francis_Utils_Config::set( 'db.tbteamdata.host', 'localhost' ); | |||||
| Francis_Utils_Config::set( 'db.tbteamdata.name', 'tb_teamdata' ); | |||||
| Francis_Utils_Config::set( 'db.tbteamdata.host', 'database' ); | |||||
| Francis_Utils_Config::set( 'db.tbteamdata.name', 'pb_teamdata' ); | |||||
| Francis_Utils_Config::set( 'db.tbteamdata.user', 'root' ); | Francis_Utils_Config::set( 'db.tbteamdata.user', 'root' ); | ||||
| Francis_Utils_Config::set( 'db.tbteamdata.pass', '' ); | |||||
| Francis_Utils_Config::set( 'db.tbteamdata.pass', 'root' ); | |||||
| // Paths | // Paths | ||||
| Francis_Utils_Config::set( 'path.logfile', 'C:/Users/Benny/Desktop/_SYSTEM/log/tbserver-log.txt' ); | |||||
| Francis_Utils_Config::set( 'path.cron_logfile', 'C:/Users/Benny/Desktop/_SYSTEM/log/tbserver-cron-log.txt' ); | |||||
| Francis_Utils_Config::set( 'path.backup_folder', 'C:/Users/Benny/Desktop/_SYSTEM/temp' ); | |||||
| Francis_Utils_Config::set( 'path.logfile', '/var/www/html/logs/tbserver-log.txt' ); | |||||
| Francis_Utils_Config::set( 'path.cron_logfile', '/var/www/html/logs/tbserver-cron-log.txt' ); | |||||
| Francis_Utils_Config::set( 'path.backup_folder', '/temp' ); | |||||
| @@ -21,7 +21,9 @@ Francis_Utils_Config::set( 'db.tbteamdata.pass', 'root' ); | |||||
| // Paths | // Paths | ||||
| Francis_Utils_Config::set( 'path.logfile', '/var/www/html/logs/tbserver-log.txt' ); | Francis_Utils_Config::set( 'path.logfile', '/var/www/html/logs/tbserver-log.txt' ); | ||||
| Francis_Utils_Config::set( 'path.cron_logfile', '/var/www/html/logs/tbserver-cron-log.txt' ); | Francis_Utils_Config::set( 'path.cron_logfile', '/var/www/html/logs/tbserver-cron-log.txt' ); | ||||
| Francis_Utils_Config::set( 'path.backup_folder', '/temp' ); | |||||
| Francis_Utils_Config::set( 'path.backup_folder', '/var/www/html/temp' ); | |||||
| Francis_Utils_Config::set( 'path.root', realpath( dirname( __FILE__ ) . '/../../../..' ) ); | Francis_Utils_Config::set( 'path.root', realpath( dirname( __FILE__ ) . '/../../../..' ) ); | ||||
| Francis_Core_Autoloader::attachLocator( new Francis_Core_Locator( 'TB', Francis_Utils_Config::get( 'path.root' ) . '/src/server' ) ); | Francis_Core_Autoloader::attachLocator( new Francis_Core_Locator( 'TB', Francis_Utils_Config::get( 'path.root' ) . '/src/server' ) ); | ||||
| Francis_Utils_Config::set( 'path.server.controller', Francis_Utils_Config::get( 'path.root' ) . '/src/server/server/control' ); | Francis_Utils_Config::set( 'path.server.controller', Francis_Utils_Config::get( 'path.root' ) . '/src/server/server/control' ); | ||||
| @@ -35,3 +37,6 @@ Francis_Utils_Config::set( 'slack.logWebhook', "https://hooks.slack.com/services | |||||
| // Google analytics | // Google analytics | ||||
| Francis_Utils_Config::set( 'analytics.trackingId', 'UA-139730172-1' ); | Francis_Utils_Config::set( 'analytics.trackingId', 'UA-139730172-1' ); | ||||
| // Manager console | |||||
| Francis_Utils_Config::set( 'url.manager', 'https://manager.probuddy.de/' ); | |||||
| @@ -61,9 +61,18 @@ class TB_Server_Control_Appointment { | |||||
| $maxAttendees = ( (int)$params->get( 'maxAttendee') === 0 ) ? NULL : (int)$params->get( 'maxAttendee'); | $maxAttendees = ( (int)$params->get( 'maxAttendee') === 0 ) ? NULL : (int)$params->get( 'maxAttendee'); | ||||
| $comment = _xss( $params->get( 'comment' ) ); | $comment = _xss( $params->get( 'comment' ) ); | ||||
| if ( 0 === mb_strlen( $comment ) ) | |||||
| { | |||||
| $comment = NULL; | |||||
| } | |||||
| // Link replacements | |||||
| if ( 0 === mb_strlen( $comment ) ) | if ( 0 === mb_strlen( $comment ) ) | ||||
| { | { | ||||
| $comment = NULL; | $comment = NULL; | ||||
| } else { | |||||
| $comment = TB_Server_Utils_Helper::makeUrltoLink($comment); | |||||
| } | } | ||||
| $visibility = $params->get( 'visibility', TB_Shared_Ent_TeamData_Appointment::VISIBLE_ALL ); | $visibility = $params->get( 'visibility', TB_Shared_Ent_TeamData_Appointment::VISIBLE_ALL ); | ||||
| @@ -399,9 +408,18 @@ class TB_Server_Control_Appointment { | |||||
| $maxAttendees = ( (int)$params->get( 'maxAttendee') === 0 ) ? NULL : (int)$params->get( 'maxAttendee'); | $maxAttendees = ( (int)$params->get( 'maxAttendee') === 0 ) ? NULL : (int)$params->get( 'maxAttendee'); | ||||
| $comment = _xss( $params->get( 'comment' ) ); | $comment = _xss( $params->get( 'comment' ) ); | ||||
| if ( 0 === mb_strlen( $comment ) ) | |||||
| { | |||||
| $comment = NULL; | |||||
| } | |||||
| // Link replacements | |||||
| if ( 0 === mb_strlen( $comment ) ) | if ( 0 === mb_strlen( $comment ) ) | ||||
| { | { | ||||
| $comment = NULL; | $comment = NULL; | ||||
| } else { | |||||
| $comment = TB_Server_Utils_Helper::makeUrltoLink($comment); | |||||
| } | } | ||||
| $visibility = $params->get( 'visibility', TB_Shared_Ent_TeamData_Appointment::VISIBLE_ALL ); | $visibility = $params->get( 'visibility', TB_Shared_Ent_TeamData_Appointment::VISIBLE_ALL ); | ||||
| @@ -346,7 +346,8 @@ class TB_Server_Control_Auth | |||||
| 'url' => Francis_Utils_Config::get( 'url.client' ), | 'url' => Francis_Utils_Config::get( 'url.client' ), | ||||
| 'onesignal.appId' => Francis_Utils_Config::get( 'onesignal.appId' ), | 'onesignal.appId' => Francis_Utils_Config::get( 'onesignal.appId' ), | ||||
| 'environment' => Francis_Utils_Config::get( 'environment' ), | 'environment' => Francis_Utils_Config::get( 'environment' ), | ||||
| 'version' => Francis_Utils_Config::get( 'version' ) | |||||
| 'version' => Francis_Utils_Config::get( 'version' ), | |||||
| 'manager.url' => Francis_Utils_Config::get( 'url.manager' ), | |||||
| ); | ); | ||||
| $resp->addData( 'config', $config ); | $resp->addData( 'config', $config ); | ||||
| } | } | ||||
| @@ -0,0 +1,80 @@ | |||||
| <?php | |||||
| /******************************************************************************** | |||||
| * (c)1337 aheadware.com - All rights reserved | |||||
| ********************************************************************************/ | |||||
| class TB_Server_Job_DailyDbBackup extends TB_Server_Job_Base | |||||
| { | |||||
| public function __construct( TB_Shared_Ent_TeamData_Job $jobEntity ) | |||||
| { | |||||
| $this->entity = $jobEntity; | |||||
| } | |||||
| public function execute() | |||||
| { | |||||
| // Remove old DB dumps | |||||
| $dayInSeconds = 60 * 60 * 24; | |||||
| $pastDays = 7; | |||||
| $dumpFile = Francis_Utils_Config::get( 'path.backup_folder' ) . '/dbdump'; | |||||
| while ( file_exists( $dumpFile . date( 'Y-m-d', ( time() - ( $pastDays * $dayInSeconds ) ) ) . '.zip' ) ) { | |||||
| unlink( $dumpFile . date( 'Y-m-d', ( time() - ( $pastDays * $dayInSeconds ) ) ) . '.zip' ); | |||||
| $pastDays++; | |||||
| } | |||||
| // DB Core | |||||
| $db_host = Francis_Utils_Config::get( 'db.tbcore.host' ); | |||||
| $db_user = Francis_Utils_Config::get( 'db.tbcore.user' ); | |||||
| $db_name = Francis_Utils_Config::get( 'db.tbcore.name' ); | |||||
| $db_passwd = Francis_Utils_Config::get( 'db.tbcore.pass' ); | |||||
| $sql_file = Francis_Utils_Config::get( 'path.backup_folder' ) . "/tbcore.sql"; | |||||
| //exec("mysql -u $db_name -p'$db_passwd' --allow-keywords --add-drop-table --complete-insert --quote-names --routines $db_name > $sql_file"); | |||||
| exec("mysqldump -h $db_host -u $db_user -p'$db_passwd' $db_name > $sql_file"); | |||||
| // DB Teamdata | |||||
| $db_host = Francis_Utils_Config::get( 'db.tbteamdata.host' ); | |||||
| $db_user = Francis_Utils_Config::get( 'db.tbteamdata.user' ); | |||||
| $db_name = Francis_Utils_Config::get( 'db.tbteamdata.name' ); | |||||
| $db_passwd = Francis_Utils_Config::get( 'db.tbteamdata.pass' ); | |||||
| $sql_file = Francis_Utils_Config::get( 'path.backup_folder' ) . "/tbteamdata.sql"; | |||||
| exec("mysqldump -h $db_host -u $db_user -p'$db_passwd' $db_name > $sql_file"); | |||||
| //exec("mysql -u $db_name -p'$db_passwd' --allow-keywords --add-drop-table --complete-insert --quote-names --routines $db_name > $sql_file"); | |||||
| // Zip | |||||
| $zipFilename = Francis_Utils_Config::get( 'path.backup_folder' ) . '/dbdump' . date( 'Y-m-d' ) . '.zip'; | |||||
| $zip = new ZipArchive(); | |||||
| if ( !$zip->open( $zipFilename, ZipArchive::CREATE ) ) { | |||||
| TB_Server_Utils_Log::get()->log( "Cannot zip db dump." ); | |||||
| return; | |||||
| } | |||||
| $zip->addFile( Francis_Utils_Config::get( 'path.backup_folder' ) . '/tbcore.sql' , 'tbcore.sql' ); | |||||
| $zip->addFile( Francis_Utils_Config::get( 'path.backup_folder' ) . '/tbteamdata.sql' , 'tbteamdata.sql' ); | |||||
| $zip->close(); | |||||
| // Cleanup | |||||
| $sql_file = Francis_Utils_Config::get( 'path.backup_folder' ) . "/tbcore.sql"; | |||||
| unlink( $sql_file ); | |||||
| $sql_file = Francis_Utils_Config::get( 'path.backup_folder' ) . "/tbteamdata.sql"; | |||||
| unlink( $sql_file ); | |||||
| echo 'bla'; | |||||
| } | |||||
| public function onDone() | |||||
| { | |||||
| // Reset event to start the next day | |||||
| $nowDt = new DateTime( 'now', new \DateTimeZone( "UTC" ) ); | |||||
| $nowDt->setTime( 2, 0, 0 ); | |||||
| $nowDt->modify( '+1 day' ); | |||||
| $this->entity->trigger_dt = $nowDt; | |||||
| $this->entity->job_status = TB_Shared_Ent_TeamData_Job::JOB_STATUS_READY; | |||||
| $this->entity->touch( 'job_status' ); | |||||
| $this->entity->save(); | |||||
| } | |||||
| public static function getRefId() | |||||
| { | |||||
| return 'system-daily-db-backup'; | |||||
| } | |||||
| } | |||||
| @@ -6,6 +6,6 @@ Dein Coach möchte Dich an den Termin: | |||||
| erinnern. | erinnern. | ||||
| Bitte gebe dem Coach eine kurze Rückmeldung, ob Du dabei bist oder nicht. | |||||
| Bitte gib dem Coach eine kurze Rückmeldung, ob Du dabei bist oder nicht. | |||||
| Danke. | Danke. | ||||
| @@ -27,7 +27,7 @@ Terminerinnerung</span> | |||||
| <tr> | <tr> | ||||
| <td class="eBody alignCenter pdTp32" data-color="Text" data-bgcolor="Content Background" style="margin-top: 0;margin-left: 0;margin-right: 0;margin-bottom: 0;padding-top: 32px;padding-bottom: 0;padding-left: 16px;padding-right: 16px;border-collapse: collapse;border-spacing: 0;-webkit-text-size-adjust: none;font-family: Arial, Helvetica, sans-serif;text-align: center;width: 544px;color: #54565c;background-color: #ffffff;"> | <td class="eBody alignCenter pdTp32" data-color="Text" data-bgcolor="Content Background" style="margin-top: 0;margin-left: 0;margin-right: 0;margin-bottom: 0;padding-top: 32px;padding-bottom: 0;padding-left: 16px;padding-right: 16px;border-collapse: collapse;border-spacing: 0;-webkit-text-size-adjust: none;font-family: Arial, Helvetica, sans-serif;text-align: center;width: 544px;color: #54565c;background-color: #ffffff;"> | ||||
| <p data-color="Text" style="margin-top: 0;margin-left: 0;margin-right: 0;margin-bottom: 24px;padding-top: 0;padding-bottom: 0;padding-left: 0;padding-right: 0;-webkit-text-size-adjust: none;font-family: Arial, Helvetica, sans-serif;text-align: center;font-size: 14px;line-height: 22px;"> | <p data-color="Text" style="margin-top: 0;margin-left: 0;margin-right: 0;margin-bottom: 24px;padding-top: 0;padding-bottom: 0;padding-left: 0;padding-right: 0;-webkit-text-size-adjust: none;font-family: Arial, Helvetica, sans-serif;text-align: center;font-size: 14px;line-height: 22px;"> | ||||
| TBuddy möchte Dich an einen Termin erinnern. Bitte gebe Deinem Team <?= $d[ 'team_display_name'] ?> kurz ein Feedback (Zu- oder Absage), ob Du dabei bist. </p> | |||||
| TBuddy möchte Dich an einen Termin erinnern. Bitte gib Deinem Team <?= $d[ 'team_display_name'] ?> kurz ein Feedback (Zu- oder Absage), ob Du dabei bist. </p> | |||||
| </td> | </td> | ||||
| </tr> | </tr> | ||||
| </table> | </table> | ||||
| @@ -140,6 +140,15 @@ class TB_Server_Utils_Helper { | |||||
| return $token; | return $token; | ||||
| } | } | ||||
| public static function makeUrltoLink($string) { | |||||
| // The Regular Expression filter | |||||
| $reg_pattern = "/(((http|https|ftp|ftps)\:\/\/)|(www\.))[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\:[0-9]+)?(\/\S*)?/"; | |||||
| // make the urls to hyperlinks | |||||
| $strUrlReplaced = preg_replace($reg_pattern, '<a href="$0" target="_blank" rel="noopener noreferrer">$0</a>', $string); | |||||
| return preg_replace('/href="www./', 'href="https://www.', $strUrlReplaced); | |||||
| } | |||||
| private static function generateTeamId() | private static function generateTeamId() | ||||
| { | { | ||||
| $length = 4; | $length = 4; | ||||