diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a3225bc..592d72f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,16 +4,25 @@ on: tags: - '3*' -name: Create Release +name: create_release jobs: build: - name: Create Release + name: create_release runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 + - name: Slack Notification on Start + uses: rtCamp/action-slack-notify@v2.2.0 + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_RELEASE }} + SLACK_CHANNEL: notify-nc3-release + SLACK_TITLE: "${{ github.repository }}" + SLACK_COLOR: "#f0ad4e" + SLACK_MESSAGE: "Start Job" + - name: Create Release id: create_release uses: actions/create-release@v1 @@ -26,3 +35,25 @@ jobs: NetCommons ${{ github.ref }} released. draft: false prerelease: false + + # テスト成功時はこちらのステップが実行される + - name: Slack Notification on Finish + uses: rtCamp/action-slack-notify@v2.2.0 + if: success() + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_RELEASE }} + SLACK_CHANNEL: notify-nc3-release + SLACK_TITLE: "${{ github.repository }}" + SLACK_COLOR: good + SLACK_MESSAGE: "Job Success" + + # テスト失敗時はこちらのステップが実行される + - name: Slack Notification on Failure + uses: rtCamp/action-slack-notify@v2.2.0 + if: failure() + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_RELEASE }} + SLACK_CHANNEL: notify-nc3-tests + SLACK_TITLE: "${{ github.repository }}" + SLACK_COLOR: danger + SLACK_MESSAGE: "Job Failure" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..6da4321 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,168 @@ +on: + push: + branches: + - main + - master + pull_request: + branches: + - main + - master + +name: tests + +jobs: + setup: + name: setup + runs-on: ubuntu-latest + steps: + - name: Slack Notification on Start + uses: rtCamp/action-slack-notify@v2.2.0 + if: env.SLACK_WEBHOOK != '' + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_TESTS }} + SLACK_CHANNEL: notify-nc3-tests + SLACK_TITLE: "${{ github.repository }}" + SLACK_COLOR: "#f0ad4e" + + tests: + name: tests + needs: setup + runs-on: ubuntu-latest + strategy: + matrix: + php: [ '7.1', '7.2', '7.3', '7.4' ] + mysql: [ '5.7', '8.0' ] + + env: + NC3_BUILD_DIR: "/opt/nc3" + NC3_DOCKER_DIR: "/opt/docker" + NC3_GIT_URL: "git://github.com/NetCommons3/NetCommons3.git" + NC3_GIT_BRANCH: "master" + PLUGIN_BUILD_DIR: ${{ github.workspace }} + PHP_VERSION: ${{ matrix.php }} + MYSQL_VERSION: ${{ matrix.mysql }} + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: cakephp_test + COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + steps: + - uses: actions/checkout@v2 + + - name: Fix up git URLs + run: echo -e '[url "https://github.com/"]\n insteadOf = "git://github.com/"' >> ~/.gitconfig + + - name: environment + run: | + echo "GITHUB_WORKSPACE=${GITHUB_WORKSPACE}" + echo "PLUGIN_BUILD_DIR=${PLUGIN_BUILD_DIR}" + echo "PHP_VERSION=${PHP_VERSION}" + echo "MYSQL_VERSION=${MYSQL_VERSION}" + ls -al ${PLUGIN_BUILD_DIR} + + - name: docker-compose install + run: | + curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > ~/docker-compose + chmod +x ~/docker-compose + sudo mv ~/docker-compose /usr/local/bin/docker-compose + docker-compose --version + + - name: git clone nc3 + run: git clone -b ${NC3_GIT_BRANCH} ${NC3_GIT_URL} ${NC3_BUILD_DIR} + + - name: git clone nc3_docker + run: git clone https://github.com/NetCommons3/nc3app-docker.git ${NC3_DOCKER_DIR} + + - name: docker-compose start + run: | + cd ${NC3_DOCKER_DIR} + docker-compose up -d + docker-compose start + + - run: docker ps + + - name: check libraries + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/start-on-docker.sh + + - name: nc3 build + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/app-build.sh + + - name: phpcs (PHP CodeSniffer) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/phpcs.sh + + - name: phpmd (PHP Mess Detector) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/phpmd.sh + + - name: phpcpd (PHP Copy/Paste Detector) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/phpcpd.sh + + - name: gjslint (JavaScript Style Check) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/gjslint.sh + + - name: phpdoc (PHP Documentor) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/phpdoc.sh + + - name: phpunit (PHP UnitTest) + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose exec -T nc3app bash /opt/scripts/phpunit.sh + sudo -s chmod a+w -R ${NC3_BUILD_DIR}/build + +# - name: push coveralls +# env: +# COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# COVERALLS_FLAG_NAME: ${{ matrix.php }} +# run: | +# cd ${NC3_BUILD_DIR} +# ls -la ${NC3_BUILD_DIR} +# vendors/bin/php-coveralls --coverage_clover=build/logs/clover.xml -v + + - name: docker-compose remove + if: always() + run: | + cd ${NC3_DOCKER_DIR} + docker-compose rm -f + + # テスト失敗時はこちらのステップが実行される + - name: Slack Notification on Failure + uses: rtCamp/action-slack-notify@v2.2.0 + if: env.SLACK_WEBHOOK != '' && failure() + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_TESTS }} + SLACK_CHANNEL: notify-nc3-tests + SLACK_TITLE: "${{ github.repository }}(php${{ matrix.php }}, mysql${{ matrix.mysql }})" + SLACK_COLOR: danger + + teardown: + name: teardown + runs-on: ubuntu-latest + needs: tests + steps: + # テスト成功時はこちらのステップが実行される + - name: Slack Notification on Success + uses: rtCamp/action-slack-notify@v2.2.0 + if: env.SLACK_WEBHOOK != '' && success() + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_TESTS }} + SLACK_CHANNEL: notify-nc3-tests + SLACK_TITLE: "${{ github.repository }}" + SLACK_COLOR: good diff --git a/.phpcpdignore b/.phpcpdignore new file mode 100644 index 0000000..ad49132 --- /dev/null +++ b/.phpcpdignore @@ -0,0 +1,2 @@ +ReservationImportController.php +ReservationPlansController.php diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index cf8d3b1..0000000 --- a/.travis.yml +++ /dev/null @@ -1,41 +0,0 @@ -language: php - -php: - - 7.0 - - 7.1 - - 7.2 - - 7.3.24 - - 7.4 - -sudo: false -dist: trusty - -env: - matrix: - - NETCOMMONS_VERSION=master DB=mysql - global: - - secure: "OfqRkPfSzBeU288mu0hEktEoWMZxxcYJN9BzrDrrXgTPCev5C7URonk+71pCB3L5+pI8fD/mBanhqFgClpe1tJdmt0m6BJ6woLMSNJT/1jdxX6C55gIaKPfutO0Of1GQ8K6ibHnlgrgsk/mGwRDH01u3k0qkL3saPNrVlBgmC5E=" - - GIT_COMMITTER_NAME=to-hashimoto-3 - - GIT_COMMITTER_EMAIL=toshihide@allcreaotr.net - - GIT_AUTHOR_NAME=AllCreator - - GIT_AUTHOR_EMAIL=info@allcreator.net - -before_script: - - export NETCOMMONS_BUILD_DIR=`dirname $TRAVIS_BUILD_DIR`/NetCommons3 - - git clone git://github.com/NetCommons3/NetCommons3 $NETCOMMONS_BUILD_DIR - - cd $NETCOMMONS_BUILD_DIR - - git checkout $NETCOMMONS_VERSION - - . tools/build/plugins/cakephp/travis/pre.sh - -script: - - . tools/build/plugins/cakephp/travis/main.sh - -after_script: - - . tools/build/plugins/cakephp/travis/post.sh - -notifications: - email: - recipients: - - netcommons3@googlegroups.com - on_success: never # default: change - on_failure: always # default: always diff --git a/Controller/ReservationFrameSettingsController.php b/Controller/ReservationFrameSettingsController.php index 1bcac62..f9441ac 100644 --- a/Controller/ReservationFrameSettingsController.php +++ b/Controller/ReservationFrameSettingsController.php @@ -120,6 +120,11 @@ public function edit() { $this->view = 'nolocation'; return; } + + // openTextの追加 + $openText = new ReservationLocationOpenText(); + $locations = $openText->openTextAdd($locations); + $this->set('locations', $locations); // 設定情報取り出し diff --git a/Controller/ReservationImportController.php b/Controller/ReservationImportController.php index b1fd4f8..07b6078 100644 --- a/Controller/ReservationImportController.php +++ b/Controller/ReservationImportController.php @@ -131,6 +131,11 @@ public function beforeFilter() { public function edit() { // 施設情報 $locations = $this->ReservationLocation->getReservableLocations(); + + // openTextの追加 + $openText = new ReservationLocationOpenText(); + $locations = $openText->openTextAdd($locations); + $this->set('locations', $locations); $frameId = Current::read('Frame.id'); diff --git a/Controller/ReservationLocationsController.php b/Controller/ReservationLocationsController.php index dddb01a..029081d 100644 --- a/Controller/ReservationLocationsController.php +++ b/Controller/ReservationLocationsController.php @@ -94,6 +94,11 @@ public function index() { 'ReservationLocation' => $query ]; $reservationLocations = $this->Paginator->paginate('ReservationLocation'); + + // openTextの追加 + $openText = new ReservationLocationOpenText(); + $reservationLocations = $openText->openTextAdd($reservationLocations); + $this->set('reservationLocations', $reservationLocations); } @@ -377,6 +382,11 @@ public function sort() { 'ReservationLocation' => $query ]; $reservationLocations = $this->Paginator->paginate('ReservationLocation'); + + // openTextの追加 + $openText = new ReservationLocationOpenText(); + $reservationLocations = $openText->openTextAdd($reservationLocations); + $this->set('reservationLocations', $reservationLocations); $this->request->data['ReservationLocations'] = $reservationLocations; diff --git a/Controller/ReservationPlansController.php b/Controller/ReservationPlansController.php index 971f3fb..3922f10 100644 --- a/Controller/ReservationPlansController.php +++ b/Controller/ReservationPlansController.php @@ -153,7 +153,7 @@ public function beforeFilter() { ReservationPermissiveRooms::setRoomPermRoles($this->roomPermRoles); // 表示のための各種共通パラメータ設定 - $this->_vars = $this->getVarsForShow(); + $this->_vars = $this->__getVarsForShow(); } /** @@ -288,6 +288,11 @@ public function delete() { public function add() { // 施設情報 $locations = $this->ReservationLocation->getReservableLocations(); + + // openTextの追加 + $openText = new ReservationLocationOpenText(); + $locations = $openText->openTextAdd($locations); + $locations = $this->__mergeApprovalUserName($locations); $this->set('locations', $locations); @@ -305,7 +310,7 @@ public function add() { $selectedRoomId = $this->request->data['ReservationActionPlan']['plan_room_id'] ?? 0; $selectedRoom = $this->ReservationSelectRoom->getSelectedRoom( $defaultRooms, - $selectedRoomId + (int)$selectedRoomId ); $this->set('selectedRoom', json_encode($selectedRoom)); @@ -330,6 +335,10 @@ public function add() { */ public function edit() { if ($this->request->is('post')) { + $editRrule = $this->ReservationActionPlan->getEditRruleForUpdate($this->request->data); + if ($editRrule == ReservationAppBehavior::CALENDAR_PLAN_EDIT_THIS) { + $this->request->data['ReservationActionPlan']['is_repeat'] = '0'; + } $this->_reservationPost(); } // 表示のための処理 @@ -343,6 +352,11 @@ public function edit() { // 施設情報 $locations = $this->ReservationLocation->getReservableLocations(); + + // openTextの追加 + $openText = new ReservationLocationOpenText(); + $locations = $openText->openTextAdd($locations); + $locations = $this->__mergeApprovalUserName($locations); $this->set('locations', $locations); @@ -360,7 +374,7 @@ public function edit() { $selectedRoomId = $this->request->data['ReservationActionPlan']['plan_room_id']; $selectedRoom = $this->ReservationSelectRoom->getSelectedRoom( $defaultRooms, - $selectedRoomId + (int)$selectedRoomId ); $this->set('selectedRoom', json_encode($selectedRoom)); } @@ -617,7 +631,7 @@ public function view() { * @return void * @throws InternalErrorException */ - public function getVarsForShow() { + private function __getVarsForShow() { $vars = array(); $this->setReservationCommonVars($vars); diff --git a/Controller/ReservationsController.php b/Controller/ReservationsController.php index bce74ec..b06c2e5 100644 --- a/Controller/ReservationsController.php +++ b/Controller/ReservationsController.php @@ -119,6 +119,11 @@ public function index() { } $categoryId = Hash::get($this->request->params['named'], 'category_id'); + if ($categoryId === '') { + // タブ切り替えや前後ページングで'カテゴリ選択'だとcategory_idが空文字になるので + // そのときはnull(カテゴリの指定無し)にする + $categoryId = null; + } $locations = $this->ReservationLocation->getLocations($categoryId); @@ -163,6 +168,7 @@ public function index() { $frameId = Current::read('Frame.id'); $languageId = Current::read('Language.id'); $this->set(compact('frameId', 'languageId', 'vars')); + $this->set('unselectedCategory', $this->ReservationLocation->getCountUnselectedCategory()); $this->render($ctpName); //$roomId = Current::read('Room.id'); @@ -232,7 +238,7 @@ protected function _getWeeklyVars($vars) { * @param array $vars カレンンダー情報 * @return array $vars 日単位(一覧)データ */ - public function getDailyListVars($vars) { + protected function _getDailyListVars($vars) { $this->setReservationCommonVars($vars); $vars['tab'] = 'list'; return $vars; @@ -261,7 +267,7 @@ protected function _getDailyVars($vars) { //if ($tab === 'timeline') { $vars = $this->_getDailyTimelineVars($vars); //} else { - // $vars = $this->getDailyListVars($vars); + // $vars = $this->_getDailyListVars($vars); //} $vars['selectRooms'] = array(); //マージ前の暫定 diff --git a/Lib/ReservationLocationOpenText.php b/Lib/ReservationLocationOpenText.php index 63b0535..845e531 100644 --- a/Lib/ReservationLocationOpenText.php +++ b/Lib/ReservationLocationOpenText.php @@ -78,4 +78,22 @@ public function openText($reservationLocation) { } return $ret; } + +/** + * openTextをセットした施設データを返す + * + * @param array $reservationLocations 施設データ + * @return array + */ + public function openTextAdd($reservationLocations) { + foreach ($reservationLocations as $key => $value) { + if (array_key_exists('time_table', $value['ReservationLocation']) && + array_key_exists('start_time', $value['ReservationLocation']) && + array_key_exists('end_time', $value['ReservationLocation']) && + array_key_exists('timezone', $value['ReservationLocation'])) { + $reservationLocations[$key]['ReservationLocation']['openText'] = $this->openText($value); + } + } + return $reservationLocations; + } } \ No newline at end of file diff --git a/Locale/jpn/LC_MESSAGES/reservations.po b/Locale/jpn/LC_MESSAGES/reservations.po index d7a3c9d..72387a5 100644 --- a/Locale/jpn/LC_MESSAGES/reservations.po +++ b/Locale/jpn/LC_MESSAGES/reservations.po @@ -1413,7 +1413,7 @@ msgid "To see details of import file item settings, please see below.
" msgstr "インポートファイルへの設定項目の詳細は、下記を参照ください。
" "なお、各項目を無指定とする場合、空白の代わりに文字列「null」を設定してください。
" "また、無指定(「null」指定)または指定外の設定をした場合、未設定 とします。" - + msgid "-- not specified --" msgstr "-- 指定しない --" @@ -1421,4 +1421,8 @@ msgid "Location not found in select category." msgstr "選択したカテゴリに登録されている施設はありません。" msgid "No locations are available." -msgstr "予約可能な施設がありません。" \ No newline at end of file +msgstr "予約可能な施設がありません。" + +msgid "Invalid input location" +msgstr "施設を選択してください。" + diff --git a/Model/Behavior/ReservationAppBehavior.php b/Model/Behavior/ReservationAppBehavior.php index 169cd01..1e180ef 100644 --- a/Model/Behavior/ReservationAppBehavior.php +++ b/Model/Behavior/ReservationAppBehavior.php @@ -175,7 +175,7 @@ public function insert(Model $model, $planParams, $rruleData, $eventData, $start if ($model->ReservationEvent->id > 0 && $createdUserWhenUpd !== null) { //saveが成功し、かつ、createdUserWhenUpd がnull以外なら、created_userを更新しておく。 //modifiedも更新されるが、saveの直後なので誤差の範囲として了とする。 - $model->ReservationEvent->saveField('created_user', $createdUserWhenUpd); + $model->ReservationEvent->saveField('created_user', $createdUserWhenUpd, ['callbacks' => false]); //UPDATEでセットしたcreatedUserWhenUpdの値をeventDataに記録しておく $rEventData['ReservationEvent']['created_user'] = $createdUserWhenUpd; } diff --git a/Model/Behavior/ReservationInsertPlanBehavior.php b/Model/Behavior/ReservationInsertPlanBehavior.php index e6122a8..dd4faf2 100644 --- a/Model/Behavior/ReservationInsertPlanBehavior.php +++ b/Model/Behavior/ReservationInsertPlanBehavior.php @@ -165,7 +165,7 @@ public function insertEventData(Model $model, $planParams, $rruleData, if ($model->ReservationEvent->id > 0 && $createdUserWhenUpd !== null) { //saveが成功し、かつ、createdUserWhenUpd がnull以外なら、created_userを更新しておく。 //modifiedも更新されるが、saveの直後なので誤差の範囲として了とする。 - $model->ReservationEvent->saveField('created_user', $createdUserWhenUpd); + $model->ReservationEvent->saveField('created_user', $createdUserWhenUpd, ['callbacks' => false]); //UPDATEでセットしたcreatedUserWhenUpdの値をeventDataに記録しておく $eventData['ReservationEvent']['created_user'] = $createdUserWhenUpd; } diff --git a/Model/Behavior/ReservationMailQueueBehavior.php b/Model/Behavior/ReservationMailQueueBehavior.php index 7c35021..60f4177 100644 --- a/Model/Behavior/ReservationMailQueueBehavior.php +++ b/Model/Behavior/ReservationMailQueueBehavior.php @@ -23,10 +23,11 @@ class ReservationMailQueueBehavior extends MailQueueBehavior { * @param Model $model モデル * @param array $sendTimes メール送信日時 配列 * @param string $typeKey メールの種類 + * @param string $sendRoomPermission 送信するルームの役割。ルームでないときは無視される * @return void */ public function saveQueue(Model $model, $sendTimes = null, - $typeKey = MailSettingFixedPhrase::DEFAULT_TYPE) { + $typeKey = MailSettingFixedPhrase::DEFAULT_TYPE, $sendRoomPermission = null) { $model->Behaviors->load('Mails.IsMailSend', $this->settings[$model->alias]); $languageId = Current::read('Language.id'); @@ -48,8 +49,11 @@ public function saveQueue(Model $model, $sendTimes = null, // --- ワークフローのstatusによって送信内容を変える // 各プラグインが承認機能=ONかどうかは、気にしなくてOK。承認機能=OFFなら status=公開が飛んでくるため。 - // 承認依頼通知, 差戻し通知, 承認完了通知メール(即時) - $this->_saveQueueNoticeMail($model, $languageId, $typeKey); + //承認ワークフローを使うときのみ承認関連のメールは送らない + if ($model->data['ReservationLocation']['use_workflow']) { + // 承認依頼通知, 差戻し通知, 承認完了通知メール(即時) + $this->_saveQueueNoticeMail($model, $languageId, $typeKey); + } $mailSettingPlugin = $this->__getMailSettingPlugin($model, $languageId, $typeKey); $isMailSend = Hash::get($mailSettingPlugin, 'MailSetting.is_mail_send'); diff --git a/Model/Behavior/ReservationPlanGenerationBehavior.php b/Model/Behavior/ReservationPlanGenerationBehavior.php index 730a9eb..2b08ed8 100644 --- a/Model/Behavior/ReservationPlanGenerationBehavior.php +++ b/Model/Behavior/ReservationPlanGenerationBehavior.php @@ -69,18 +69,22 @@ public function makeCurGenPlan(Model $model, $data, * @param string $status status 変更時の施設予約独自の新status * @param int $createdUserWhenUpd createdUserWhenUpd * @param bool $isMyPrivateRoom isMyPrivateRoom + * @param string|int $editRrule 編集ルール(この予約のみ、これ以降に指定した全ての予約、設定した全ての予約) * @return int 生成成功時 新しく生成した次世代予定($plan)を返す。失敗時 InternalErrorExceptionを投げる。 * @throws InternalErrorException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function makeNewGenPlan(Model $model, $data, $status, - $createdUserWhenUpd, $isMyPrivateRoom) { + $createdUserWhenUpd, $isMyPrivateRoom, $editRrule) { $action = 'update'; $plan = $this->__makeCommonGenPlan($model, $action, $data, $data['ReservationActionPlan']['origin_rrule_id']); //keyが同じrrule -> key同一のevents -> eventsの各子供をcopy保存する - $plan = $this->__copyRruleData($model, $plan, $createdUserWhenUpd); + $plan = $this->__copyRruleData($model, $plan, $createdUserWhenUpd, $editRrule); + + $baseDate = str_replace('-', '', $data['ReservationActionPlanForDisp']['detail_start_datetime']); unset($plan['new_event_id']); //念のため変数クリア $effectiveEvents = array(); //有効なeventだけを格納する配列を用意 @@ -90,6 +94,17 @@ public function makeNewGenPlan(Model $model, $data, $status, if ($event['exception_event_id'] >= 1) { continue; } + if ($editRrule == self::CALENDAR_PLAN_EDIT_THIS && + $data['ReservationActionPlan']['origin_event_id'] != $event['id']) { + //この予約のみの場合、自分自身の予約以外は無視する。 + continue; + } + if ($editRrule == self::CALENDAR_PLAN_EDIT_AFTER && + $data['ReservationActionPlan']['origin_event_id'] != $event['id'] && + $baseDate > $event['start_date']) { + //これ以降に指定した全ての予約の場合、基準日より過去のものは無視する。 + continue; + } $newEventId = $newEventKey = null; list($event, $newEventId, $newEventKey) = $this->__copyEventData($model, @@ -123,10 +138,11 @@ public function makeNewGenPlan(Model $model, $data, $status, * @param Model $model 実際のモデル名 * @param array $plan plan * @param int $createdUserWhenUpd createdUserWhenUpd + * @param string|int $editRrule 編集ルール(この予約のみ、これ以降に指定した全ての予約、設定した全ての予約) * @return int 生成成功時 新しい$planを返す。失敗時 InternalErrorExceptionを投げる。 * @throws InternalErrorException */ - private function __copyRruleData(Model $model, $plan, $createdUserWhenUpd) { + private function __copyRruleData(Model $model, $plan, $createdUserWhenUpd, $editRrule) { //ReservationRruleには、status, is_latest, is_activeはない。 $rruleData = array(); @@ -135,6 +151,9 @@ private function __copyRruleData(Model $model, $plan, $createdUserWhenUpd) { //次世代データの新規登録 $originRruleId = $rruleData['ReservationRrule']['id']; $rruleData['ReservationRrule']['id'] = null; + if ($editRrule == self::CALENDAR_PLAN_EDIT_THIS) { + $rruleData['ReservationRrule']['rrule'] = ''; + } //作成者・作成日は原則、元予定のデータを引き継ぐ、、、が!例外がある。 //例外追加1) @@ -249,6 +268,8 @@ private function __copyEventData(Model $model, $event, $reservationRruleId, $sta //セットするようにした。 $model->ReservationEvent->prepareLatestCreatedForIns($eventData, $createdUserWhenUpd); + // $eventDataがprepareLatestCreatedForIns()で変更されるので、再度setする + $model->ReservationEvent->set($eventData); //子もsave()で返ってくる。 $eventData = $model->ReservationEvent->save(null, false); //aaaaaaaaaaaaa if (!$eventData) { //保存のみ diff --git a/Model/Behavior/ReservationUpdatePlanBehavior.php b/Model/Behavior/ReservationUpdatePlanBehavior.php index 1abe057..d9e9b53 100644 --- a/Model/Behavior/ReservationUpdatePlanBehavior.php +++ b/Model/Behavior/ReservationUpdatePlanBehavior.php @@ -398,6 +398,8 @@ public function updateDtstartData(Model $model, $planParams, $rruleData, $eventD //is_active調整処理を行う。(eventDataの値が一部変更されます) $model->ReservationEvent->prepareActiveForUpd($eventData); + // $eventDataがprepareActiveForUpd()で変更されるので、再度setする + $model->ReservationEvent->set($eventData); if (!$model->ReservationEvent->save(null, array( 'validate' => false, diff --git a/Model/Behavior/ReservationWorkflowBehavior.php b/Model/Behavior/ReservationWorkflowBehavior.php index e67df2d..9a15ea1 100644 --- a/Model/Behavior/ReservationWorkflowBehavior.php +++ b/Model/Behavior/ReservationWorkflowBehavior.php @@ -33,9 +33,16 @@ public function beforeValidate(Model $model, $options = array()) { * * @param Model $model Model using this behavior * @param array $conditions Model::find conditions default value + * @param bool $useCommentCreatable コメントの作成権限でもチェックするかどうか * @return array Conditions data + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.BooleanArgumentFlag) */ - public function getWorkflowConditions(Model $model, $conditions = array()) { + public function getWorkflowConditions( + Model $model, + $conditions = array(), + $useCommentCreatable = false + ) { // is_active = 1は常に表示 $activeConditions = [ $model->alias . '.is_active' => true, @@ -88,14 +95,21 @@ public function getWorkflowConditions(Model $model, $conditions = array()) { * @param Model $model Model using this behavior * @param string $type Type of find operation (all / first / count / neighbors / list / threaded) * @param array $query Option fields (conditions / fields / joins / limit / offset / order / page / group / callbacks) + * @param bool $useCommentCreatable コメントの作成権限でもチェックするかどうか * @return array Conditions data + * @SuppressWarnings(PHPMD.BooleanArgumentFlag) */ - public function getWorkflowContents(Model $model, $type, $query = array()) { + public function getWorkflowContents( + Model $model, + $type, + $query = array(), + $useCommentCreatable = false + ) { //$this->log(var_export(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5), true), 'debug'); $query = Hash::merge(array( 'recursive' => -1, - 'conditions' => $this->getWorkflowConditions($model) + 'conditions' => $this->getWorkflowConditions($model, [], $useCommentCreatable) ), $query); return $model->find($type, $query); diff --git a/Model/ReservationActionPlan.php b/Model/ReservationActionPlan.php index a7d0210..72e05cc 100644 --- a/Model/ReservationActionPlan.php +++ b/Model/ReservationActionPlan.php @@ -466,6 +466,9 @@ public function validteUseLocationTimeRange($check) { $locationKey, Current::read('Language.id') ); + if (! $location) { + return false; + } $reservableTimeTable = explode('|', $location['ReservationLocation']['time_table']); $locationTimeZone = new DateTimeZone($location['ReservationLocation']['timezone']); @@ -571,7 +574,7 @@ public function validteNotExistReservation($check) { // 全ての予約を更新 $ignoreConditions = [ 'NOT' => [ - 'ReservationEvent.rrule_id' => + 'ReservationEvent.reservation_rrule_id' => Hash::get($this->data, 'ReservationActionPlan.origin_rrule_id'), 'ReservationEvent.recurrence_event_id !=' => 0, 'ReservationEvent.exception_event_id !=' => 0, @@ -756,6 +759,9 @@ public function validateStatus($check) { /** @var ReservationLocation $locationModel */ $locationModel = ClassRegistry::init('Reservations.ReservationLocation'); $location = $locationModel->getByKey($locationKey); + if (! $location) { + return false; + } if ($location['ReservationLocation']['use_workflow']) { // 承認必要 // 承認者か @@ -904,9 +910,14 @@ public function saveReservationPlan($data, $procMode, //3. isMyPrivateRoomは、変更後の公開ルームidが「編集者・承認者(=ログイン者)のプライベート」以外の場合、 //仲間の予定はプライベートの時のみ許される子情報なので、これらはcopy対象から外す(stripする)例外処理用。 // - $newPlan = $this->makeNewGenPlan($data, $status, $createdUserWhenUpd, $isMyPrivateRoom); - $editRrule = $this->getEditRruleForUpdate($data); + $newPlan = $this->makeNewGenPlan( + $data, + $status, + $createdUserWhenUpd, + $isMyPrivateRoom, + $editRrule + ); $isInfoArray = array($isOriginRepeat, $isTimeMod, $isRepeatMod, $isMyPrivateRoom); $eventId = $this->updatePlan($planParam, $newPlan, $status, $isInfoArray, $editRrule, @@ -1082,7 +1093,6 @@ public function convertToPlanParamFormat($data) { CakeLog::error($ex->getMessage()); throw($ex); //再throw } - CakeLog::debug(var_export($planParam, true)); return $planParam; } diff --git a/Model/ReservationLocation.php b/Model/ReservationLocation.php index 180b309..9866a4e 100644 --- a/Model/ReservationLocation.php +++ b/Model/ReservationLocation.php @@ -188,32 +188,6 @@ public function beforeFind($query) { return true; } -/** - * Called after each find operation. Can be used to modify any results returned by find(). - * Return value should be the (modified) results. - * - * @param mixed $results The results of the find operation - * @param bool $primary Whether this model is being queried directly (vs. being queried as an association) - * @return mixed Result of the find operation - * @SuppressWarnings(PHPMD.BooleanArgumentFlag) - * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#afterfind - */ - public function afterFind($results, $primary = false) { - if (!isset($results[0][$this->alias])) { - return $results; - } - foreach ($results as $key => $value) { - if (array_key_exists('time_table', $results[$key][$this->alias]) && - array_key_exists('start_time', $results[$key][$this->alias]) && - array_key_exists('end_time', $results[$key][$this->alias]) && - array_key_exists('timezone', $results[$key][$this->alias])) { - $openText = new ReservationLocationOpenText(); - $results[$key][$this->alias]['openText'] = $openText->openText($value); - } - } - return $results; - } - /** * Called before each save operation, after validation. Return a non-true result * to halt the save. @@ -662,6 +636,19 @@ protected function _prepareData($data) { return $data; } +/** + * カテゴリーをセットしていない施設件数を取得する + * + * @return int + */ + public function getCountUnselectedCategory() { + $count = $this->find('count', [ + 'conditions' => ['category_id' => null], + ]); + + return $count; + } + /** * getAliveCondition * 現在使用中状態であるか判断する。CleanUpプラグインで使用 diff --git a/Policy/ReservationEventPermissionPolicy.php b/Policy/ReservationEventPermissionPolicy.php index a428ae9..a325b23 100644 --- a/Policy/ReservationEventPermissionPolicy.php +++ b/Policy/ReservationEventPermissionPolicy.php @@ -31,6 +31,11 @@ class ReservationEventPermissionPolicy { */ protected $_readableRoomIds = []; +/** + * @var ReservationLocationReservable ReadableLocationReservable model + */ + private $__reservationLocationReservable; + /** * ReservationEventPermissionPolicy constructor. * @@ -38,6 +43,9 @@ class ReservationEventPermissionPolicy { */ public function __construct($event) { $this->_event = $event; + $this->__reservationLocationReservable = ClassRegistry::init( + 'Reservations.ReservationLocationReservable' + ); } /** @@ -48,19 +56,24 @@ public function __construct($event) { */ public function canEdit($userId) { $data = $this->_event; + $location = $this->_getLocationByKey($data['ReservationEvent']['location_key']); if ($userId == $data['ReservationEvent']['created_user']) { - // 自分の予約は無条件に編集可能 - return true; + // 予約権限があれば編集可 + return $this->__reservationLocationReservable->isReservableByLocation($location); } else { // 他の人の予約 - // block_permission_editable なら見られる - if (Current::read('Room.space_id') != Space::PRIVATE_SPACE_ID) { - if (Current::read('Permission.block_permission_editable.value')) { - return true; - } + // ルーム管理者なら編集可能にしていたが、システム管理者、サイト管理者のみ編集可能にする。 + // サイト管理を使えるユーザなら編集可能。 + if (Current::allowSystemPlugin('site_manager')) { + return true; } + //// block_permission_editable なら見られる + //if (Current::read('Room.space_id') != Space::PRIVATE_SPACE_ID) { + // if (Current::read('Permission.block_permission_editable.value')) { + // return true; + // } + //} - $location = $this->_getLocationByKey($data['ReservationEvent']['location_key']); $approvalUserIds = $location['approvalUserIds']; if (in_array($userId, $approvalUserIds)) { diff --git a/README.md b/README.md index 50972fa..0723cb7 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ Reservations ========= -Reservations for NetCommons3 -[![Build Status](https://travis-ci.org/NetCommons3/Reservations.svg?branch=master)](https://travis-ci.org/NetCommons3/Reservations) -[![Coverage Status](https://img.shields.io/coveralls/NetCommons3/Reservations.svg)](https://coveralls.io/r/NetCommons3/Reservations?branch=master) - -| dependencies | status | -| ------------ | ------ | -| composer.json | [![Dependency Status](https://www.versioneye.com/user/projects/58c97427e054530016372010/badge.svg?style=flat)](https://www.versioneye.com/user/projects/58c97427e054530016372010) | +[![Tests Status](https://github.com/NetCommons3/Reservations/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/NetCommons3/Reservations/actions/workflows/tests.yml) +[![Coverage Status](https://coveralls.io/repos/NetCommons3/Reservations/badge.svg?branch=master)](https://coveralls.io/r/NetCommons3/Reservations?branch=master) +[![Stable Version](https://img.shields.io/packagist/v/netcommons/reservations.svg?label=stable)](https://packagist.org/packages/netcommons/reservations) diff --git a/VERSION.txt b/VERSION.txt index 619b537..86fb650 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -3.3.3 +3.3.7 diff --git a/View/Elements/ReservationPlans/detail_edit_datetime.ctp b/View/Elements/ReservationPlans/detail_edit_datetime.ctp index 83681d2..0cba784 100644 --- a/View/Elements/ReservationPlans/detail_edit_datetime.ctp +++ b/View/Elements/ReservationPlans/detail_edit_datetime.ctp @@ -20,7 +20,7 @@ なんとなれば、ng-initの操作によるパラメータ設定が日時を先にしないとデフォルトの設定にならないから */ ?> -
+
ReservationEditDatetime->makeEditDatetimeHtml( $vars, 'datetime', @@ -29,10 +29,10 @@ 'detailStartDatetime', 'changeDetailStartDatetime' ); ?> -
+
-
+
ReservationEditDatetime->makeEditDatetimeHtml( $vars, 'date', @@ -41,7 +41,7 @@ 'detailStartDate', 'changeDetailStartDate' ); ?> -
+
@@ -76,7 +76,7 @@ 'detailEndDate', 'changeDetailEndDate' ); ?> - +
NetCommonsForm->error('ReservationActionPlan.detail_start_datetime', null, diff --git a/View/Elements/ReservationPlans/detail_edit_etc_details.ctp b/View/Elements/ReservationPlans/detail_edit_etc_details.ctp index 7153224..73181ee 100644 --- a/View/Elements/ReservationPlans/detail_edit_etc_details.ctp +++ b/View/Elements/ReservationPlans/detail_edit_etc_details.ctp @@ -19,7 +19,6 @@
-
NetCommonsForm->input('ReservationActionPlan.location', array( 'type' => 'hidden', @@ -86,7 +85,7 @@ //echo $this->NetCommonsForm->error('ReservationActionPlan.timezone'); ?>
-
+
diff --git a/View/Elements/ReservationPlans/detail_edit_mail.ctp b/View/Elements/ReservationPlans/detail_edit_mail.ctp index 5f70f06..7d9ded3 100644 --- a/View/Elements/ReservationPlans/detail_edit_mail.ctp +++ b/View/Elements/ReservationPlans/detail_edit_mail.ctp @@ -9,67 +9,19 @@ * @copyright Copyright 2014, NetCommons Project */ ?> -
- NetCommonsForm->inlineCheckbox('ReservationActionPlan.enable_email', ['label' => __d( 'reservations', 'Inform other members by e-mail?' )]); +} else { + echo $this->NetCommonsForm->hidden('ReservationActionPlan.enable_email', array('value' => false)); +} - //echo $this->NetCommonsForm->hidden('ReservationActionPlan.enable_email', array('value' => false)); - echo $this->NetCommonsForm->hidden('ReservationActionPlan.email_send_timing', array('value' => 5)); - ?> - -
- diff --git a/View/Elements/ReservationPlans/detail_edit_repeat_items.ctp b/View/Elements/ReservationPlans/detail_edit_repeat_items.ctp index da7fb1b..806070f 100644 --- a/View/Elements/ReservationPlans/detail_edit_repeat_items.ctp +++ b/View/Elements/ReservationPlans/detail_edit_repeat_items.ctp @@ -27,10 +27,10 @@ App::uses('ReservationSupport', 'Reservations.Utility'); )); ?> - +
-
@@ -59,7 +59,7 @@ App::uses('ReservationSupport', 'Reservations.Utility'); )); ?> NetCommonsForm->error('ReservationActionPlan.rrule_interval.DAILY'); ?> -
+
NetCommonsForm->error( 重複になるためコメントアウト // 'ReservationActionPlan.rrule_interval.' . ReservationsComponent::CALENDAR_REPEAT_FREQ_DAILY, null, array('div' => true)); ?> -
+
-
+
-
+
- +
'yearlyDayOfTheWeek[' . $frameId . "] = '" . $yearlyDayOfTheWeekVal . "'", )); ?> -
+
@@ -332,7 +332,7 @@ App::uses('ReservationSupport', 'Reservations.Utility'); //echo $this->NetCommonsForm->error('ReservationActionPlan.rrule_count'); ?>
- +
@@ -367,9 +367,9 @@ App::uses('ReservationSupport', 'Reservations.Utility'); )); ?> - +
- + diff --git a/View/Elements/ReservationPlans/edit_form_create.ctp b/View/Elements/ReservationPlans/edit_form_create.ctp index 653fc2e..e8cef7c 100644 --- a/View/Elements/ReservationPlans/edit_form_create.ctp +++ b/View/Elements/ReservationPlans/edit_form_create.ctp @@ -17,4 +17,4 @@ ), 'class' => 'form-horizontal', ); - echo $this->NetCommonsForm->create('ReservationActionPlan', $options); // + echo $this->NetCommonsForm->create('ReservationActionPlan', $options); \ No newline at end of file diff --git a/View/Elements/Reservations/dropdown_category.ctp b/View/Elements/Reservations/dropdown_category.ctp index e507de6..d34a899 100644 --- a/View/Elements/Reservations/dropdown_category.ctp +++ b/View/Elements/Reservations/dropdown_category.ctp @@ -13,6 +13,9 @@ // '' => 'カテゴリ選択' // '0' => カテゴリ無し //  となるように事前準備 +if (! isset($unselectedCategory)) { + $unselectedCategory = true; +} $categories = $this->get('categories'); array_unshift($categories, [ @@ -23,15 +26,28 @@ array_unshift($categories, 'name' => __d('categories', 'Select Category') ] ], - [ - 'Category' => [ - 'id' => '0', +); +if ($unselectedCategory) { + array_unshift($categories, + [ + 'Category' => [ + 'id' => null, + ], + 'CategoriesLanguage' => [ + 'name' => __d('categories', 'Select Category') + ] ], - 'CategoriesLanguage' => [ - 'name' => __d('reservations', 'no category') + [ + 'Category' => [ + 'id' => '0', + ], + 'CategoriesLanguage' => [ + 'name' => __d('reservations', 'no category') + ] ] - ] ); +} + $this->set('categories', $categories); // CategoryHelper用にムリヤリcategory_id=""をセット if (!isset($this->request->params['named']['category_id'])) { @@ -55,4 +71,4 @@ echo $this->Category->dropDownToggle(array( // ムリヤリnamedを書き換えたので元にもどす if (isset($isOverwrite)) { unset($this->request->params['named']['category_id']); -} \ No newline at end of file +} diff --git a/View/Elements/Reservations/weekly_timeline_element.ctp b/View/Elements/Reservations/weekly_timeline_element.ctp index aedf192..c5e8bd8 100644 --- a/View/Elements/Reservations/weekly_timeline_element.ctp +++ b/View/Elements/Reservations/weekly_timeline_element.ctp @@ -98,6 +98,7 @@
ReservationWeeklyTimeline->clearTimelineData(); echo $this->ReservationWeeklyTimeline->makeDailyBodyHtml($currentDayVars); $reservationPlans = $this->ReservationWeeklyTimeline->getTimelineData(); ?> diff --git a/View/Helper/ReservationPlanEditRepeatOptionHelper.php b/View/Helper/ReservationPlanEditRepeatOptionHelper.php index 1f5f1e9..18c4f56 100644 --- a/View/Helper/ReservationPlanEditRepeatOptionHelper.php +++ b/View/Helper/ReservationPlanEditRepeatOptionHelper.php @@ -106,7 +106,7 @@ public function makeEditRepeatOption( 'ng-model' => 'editRrule', 'ng-init' => "editRrule = '" . $editRrule . "'", 'ng-change' => "changeEditRrule(" . Current::read('Frame.id') . ",'" . $firstSibEditLink . "')", - 'ng-click' => 'sending=true', + //'ng-click' => 'sending=true', )); if (! $isRecurrence) { $html .= '

'; diff --git a/View/Helper/ReservationWeeklyTimelineHelper.php b/View/Helper/ReservationWeeklyTimelineHelper.php index 1b877ab..7319de0 100644 --- a/View/Helper/ReservationWeeklyTimelineHelper.php +++ b/View/Helper/ReservationWeeklyTimelineHelper.php @@ -47,6 +47,15 @@ public function getTimelineData() { return $this->_timelineData; } +/** + * TimelineDataをクリア + * + * @return array + */ + public function clearTimelineData() { + $this->_timelineData = []; + } + /** * getPlanSummariesHtml * diff --git a/View/ReservationImport/edit.ctp b/View/ReservationImport/edit.ctp index d3b6050..896b861 100644 --- a/View/ReservationImport/edit.ctp +++ b/View/ReservationImport/edit.ctp @@ -150,7 +150,6 @@ echo $this->element('Reservations.scripts'); ] ); ?> - NetCommonsForm->input( @@ -202,7 +201,7 @@ echo $this->element('Reservations.scripts');

- + element('Reservations.ReservationPlans/detail_edit_location') ?> @@ -244,7 +243,7 @@ echo $this->element('Reservations.scripts'); ?> NetCommonsForm->error('ReservationActionPlan.plan_room_id'); ?> - + element('Reservations.scripts'); style="display: ; margin-top:0.5em;">
element('Reservations.ReservationPlans/edit_plan_share', array('shareUsers', $shareUsers)); ?> -
+ - @@ -323,8 +321,8 @@ echo $this->element('Reservations.scripts'); __d('reservations', '/reservations/locale/eng/reservation_import.csv'), [ 'class' => - 'btn - btn-default + 'btn + btn-default btn-sm' ] ); ?> @@ -334,7 +332,7 @@ echo $this->element('Reservations.scripts'); - + + NetCommonsForm->end(); ?> - + Workflow->comments(); @@ -356,14 +354,9 @@ echo $this->element('Reservations.scripts'); - + - - - - - element('Reservations.scripts'); ); echo $this->Button->delete(__d('net_commons', 'Delete'), '', $deleteOptions); ?> - + NetCommonsForm->end() ?> - + diff --git a/View/ReservationPlans/detail_edit.ctp b/View/ReservationPlans/detail_edit.ctp index 8753e7b..c7f196d 100644 --- a/View/ReservationPlans/detail_edit.ctp +++ b/View/ReservationPlans/detail_edit.ctp @@ -86,7 +86,7 @@ echo $this->element('Reservations.scripts');
element('Reservations.ReservationPlans/edit_title'); ?>
- +
@@ -113,21 +113,21 @@ echo $this->element('Reservations.scripts'); //)); ?>
- +
element('Reservations.ReservationPlans/detail_edit_datetime', array('useTime' => $useTime)); ?>
-
+
element('Reservations.ReservationPlans/detail_edit_repeat_items', array('useTime' => $useTime)); ?>
-
+ @@ -166,7 +166,7 @@ echo $this->element('Reservations.scripts'); ] ); ?> - + NetCommonsForm->input( @@ -218,7 +218,7 @@ echo $this->element('Reservations.scripts'); - + element('Reservations.ReservationPlans/detail_edit_location') ?> @@ -260,7 +260,7 @@ echo $this->element('Reservations.scripts'); ?> NetCommonsForm->error('ReservationActionPlan.plan_room_id'); ?> - + element('Reservations.scripts'); style="display: ; margin-top:0.5em;">
element('Reservations.ReservationPlans/edit_plan_share', array('shareUsers', $shareUsers)); ?> -
+ - +
@@ -340,16 +340,16 @@ echo $this->element('Reservations.scripts');
Workflow->inputComment('ReservationEvent.status'); ?> -
-
+
+ - + + NetCommonsForm->end(); ?> request->params['action'] === 'edit' && $this->ReservationWorkflow->canDelete($event))) : ?> @@ -372,7 +372,7 @@ echo $this->element('Reservations.scripts'); - + Workflow->comments(); diff --git a/View/ReservationPlans/view.ctp b/View/ReservationPlans/view.ctp index 0b7943f..61620f0 100644 --- a/View/ReservationPlans/view.ctp +++ b/View/ReservationPlans/view.ctp @@ -79,14 +79,14 @@ echo $this->element('Reservations.scripts'); ReservationPlanRrule->getStringRrule($event['ReservationRrule']['rrule']); ?> - +

ReservationCategory->getCategoryName($vars, $event); ?>

-
+ ReservationShareUsers->isShareEvent($event)): ?> @@ -100,14 +100,14 @@ echo $this->element('Reservations.scripts');

-
+

-
+ @@ -115,18 +115,18 @@ echo $this->element('Reservations.scripts');

- +

DisplayUser->handleLink($event, array('avatar' => true)); ?>

-
+

toUserDatetime($event['ReservationEvent']['modified'])); ?>

-
+ diff --git a/View/Reservations/all_weekly.ctp b/View/Reservations/all_weekly.ctp index 226cfa1..cdace31 100644 --- a/View/Reservations/all_weekly.ctp +++ b/View/Reservations/all_weekly.ctp @@ -25,7 +25,7 @@ echo $this->element('Reservations.scripts'); ReservationTurnReservation->getTurnReservationOperationsWrap('week', 'top', $vars); ?> -
+
全施設週表示 diff --git a/View/Reservations/daily_by_category.ctp b/View/Reservations/daily_by_category.ctp index e6f35f9..f88b9fc 100644 --- a/View/Reservations/daily_by_category.ctp +++ b/View/Reservations/daily_by_category.ctp @@ -15,28 +15,12 @@ echo $this->NetCommonsHtml->script(array( )); ?> - -
NetCommonsHtml->script(array( ?>
@@ -174,3 +159,15 @@ echo $this->NetCommonsHtml->script(array( + diff --git a/View/Reservations/weekly_by_location.ctp b/View/Reservations/weekly_by_location.ctp index 615b5ae..70876af 100644 --- a/View/Reservations/weekly_by_location.ctp +++ b/View/Reservations/weekly_by_location.ctp @@ -39,7 +39,8 @@ echo $this->element('Reservations.scripts'); $startTime = date('G', strtotime($userNow) - 60 * 60); } ?> -
+
diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 9fa015a..ea4c766 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -3,9 +3,6 @@ - - - app/Plugin/Reservations @@ -20,5 +17,6 @@ + diff --git a/webroot/js/reservations.js b/webroot/js/reservations.js index dd98d2e..3d5aef5 100644 --- a/webroot/js/reservations.js +++ b/webroot/js/reservations.js @@ -139,46 +139,53 @@ NetCommonsApp.controller('ReservationSchedule', ['$scope', function($scope) { }]); NetCommonsApp.controller('ReservationsTimeline', ['$scope', function($scope) { - //タイムラインdiv - var coordinateOrigins = $('.reservation-vertical-timeline'); - - //指定時間のindex値を、タイムラインdivの属性から取り出し - var idx = $(coordinateOrigins[0]).attr('data-daily-start-time-idx') - 0; - - //00:00の行のtop 誤差をなくすため2300に変更 - //var row0 = $('.reservation-daily-timeline-0000'); - //var row0Top = row0[0].getBoundingClientRect().top; - - //01:00の行のtop - var row1 = $('.reservation-daily-timeline-0100'); - var row1Top = row1[0].getBoundingClientRect().top; - - //23:00の行のtop - var row23 = $('.reservation-daily-timeline-2300'); - var row23Top = row23[0].getBoundingClientRect().top; - - //1行(=1時間)の高さ - //var rowHeight = row1Top - row0Top; - var rowHeight = (row23Top - row1Top) / 22; - //指定時間が最初になるよう、divの縦スクロールを移動 - // coordinateOrigins[0].scrollTop = rowHeight * idx; - $('.reservation-vertical-timeline tbody').scrollTop(rowHeight * idx); - //$scope.origin = coordinateOrigins[0].scrollTop; - $scope.rowHeight = rowHeight; - - //0:00高さ固定 - $('.reservation-timeline-data-area').height(rowHeight); - - var row1Width = row1[0].getBoundingClientRect().width; - $scope.rowWidth = row1Width; - console.log('rowWitdh %d', row1Width); - - //初期化 - $scope.prevMargin = 0; - $scope.maxLineNum = 0; - $scope.Column = []; - $scope.Column[0] = []; + /** + * イニシャライズ処理 + * + * @param {string} frameId + * @return {void} + */ + $scope.initialize = function(frameId) { + //タイムラインdiv + var coordinateOrigins = $('#frame-' + frameId + ' .reservation-vertical-timeline'); + + //指定時間のindex値を、タイムラインdivの属性から取り出し + var idx = $(coordinateOrigins[0]).attr('data-daily-start-time-idx') - 0; + + //00:00の行のtop 誤差をなくすため2300に変更 + //var row0 = $('.reservation-daily-timeline-0000'); + //var row0Top = row0[0].getBoundingClientRect().top; + + //01:00の行のtop + var row1 = $('#frame-' + frameId + ' .reservation-daily-timeline-0100'); + var row1Top = row1[0].getBoundingClientRect().top; + + //23:00の行のtop + var row23 = $('#frame-' + frameId + ' .reservation-daily-timeline-2300'); + var row23Top = row23[0].getBoundingClientRect().top; + + //1行(=1時間)の高さ + //var rowHeight = row1Top - row0Top; + var rowHeight = (row23Top - row1Top) / 22; + //指定時間が最初になるよう、divの縦スクロールを移動 + // coordinateOrigins[0].scrollTop = rowHeight * idx; + $('.reservation-vertical-timeline tbody').scrollTop(rowHeight * idx); + //$scope.origin = coordinateOrigins[0].scrollTop; + $scope.rowHeight = rowHeight; + + //0:00高さ固定 + $('#frame-' + frameId + ' .reservation-timeline-data-area').height(rowHeight); + var row1Width = row1[0].getBoundingClientRect().width; + $scope.rowWidth = row1Width; + console.log('rowWitdh %d', row1Width); + + //初期化 + $scope.prevMargin = 0; + $scope.maxLineNum = 0; + $scope.Column = []; + $scope.Column[0] = []; + }; }]); NetCommonsApp.controller('ReservationsTimelinePlan', ['$scope', function($scope) { @@ -684,7 +691,7 @@ NetCommonsApp.controller('Reservations.selectLocation', var url = NC3_URL + '/reservations/reservations/index' + '?style=' + displayStyle + '&frame_id=' + $scope.frameId; url = url + '&location_key=' + $scope.selectLocation.ReservationLocation.key; - console.log(url); + //console.log(url); // $location.path(url); // $location.html5Mode(true); // console.log($location.search()); @@ -779,7 +786,14 @@ NetCommonsApp.controller('ReservationsDetailEdit', $scope.setupButtons = function() { // console.log($scope.selectLocation); // 承認不要のケースもあるな - if ($scope.selectLocation.ReservationLocation.use_workflow) { + if (! $scope.selectLocation) { + $scope.buttons = { + draft: false, + disapproved: false, + approvalWaiting: false, + published: false + }; + } else if ($scope.selectLocation.ReservationLocation.use_workflow) { if ($scope.selectLocation.approvalUserIds.hasOwnProperty(Number($scope.data.userId))) { // 承認ユーザ // 要承認 承認権限ありなら 一時保存と公開 ただしステータスが公開待ち(2)の時だけ一時保存→差し戻し @@ -838,6 +852,10 @@ NetCommonsApp.controller('ReservationsDetailEdit', $scope.changeLocation = function() { $scope.setupButtons(); + if (! $scope.selectLocation) { + $scope.selectedRoom = []; + return; + } var url = NC3_URL + '/reservations/reservations/fetch_rooms_to_publish_reservation.json'; let locationKey = $scope.selectLocation.ReservationLocation.key; $('#ReservationActionPlanPlanRoomId').prop('disabled', true); diff --git a/webroot/js/reservations_timeline.js b/webroot/js/reservations_timeline.js index 393430c..f1955bc 100644 --- a/webroot/js/reservations_timeline.js +++ b/webroot/js/reservations_timeline.js @@ -9,56 +9,64 @@ * */ NetCommonsApp.controller('ReservationsHorizonTimeline', ['$scope', function($scope) { - //タイムラインdiv - var coordinateOrigins = $('.reservation-horizon-timeline'); + /** + * イニシャライズ処理 + * + * @param {string} frameId + * @return {void} + */ + $scope.initialize = function(frameId) { + //タイムラインdiv + var coordinateOrigins = $('#frame-' + frameId + ' .reservation-horizon-timeline'); - //指定時間のindex値を、タイムラインdivの属性から取り出し - var idx = $(coordinateOrigins[0]).attr('data-daily-start-time-idx') - 0; + //指定時間のindex値を、タイムラインdivの属性から取り出し + var idx = $(coordinateOrigins[0]).attr('data-daily-start-time-idx') - 0; - //00:00の行のtop 誤差をなくすため2300に変更 - //var row0 = $('.reservation-daily-timeline-0000'); - //var row0Top = row0[0].getBoundingClientRect().top; + //00:00の行のtop 誤差をなくすため2300に変更 + //var row0 = $('.reservation-daily-timeline-0000'); + //var row0Top = row0[0].getBoundingClientRect().top; - //01:00の行のtop - var row1 = $('.reservation-daily-timeline-0100'); - var row1Top = row1[0].getBoundingClientRect().top; - var row1Left = row1[0].getBoundingClientRect().left; + //01:00の行のtop + var row1 = $('#frame-' + frameId + ' .reservation-daily-timeline-0100'); + var row1Top = row1[0].getBoundingClientRect().top; + var row1Left = row1[0].getBoundingClientRect().left; - //23:00の行のtop - var row23 = $('.reservation-daily-timeline-2300'); - var row23Top = row23[0].getBoundingClientRect().top; - var row23Left = row23[0].getBoundingClientRect().left; + //23:00の行のtop + var row23 = $('#frame-' + frameId + ' .reservation-daily-timeline-2300'); + var row23Top = row23[0].getBoundingClientRect().top; + var row23Left = row23[0].getBoundingClientRect().left; - //1列(1時間)の幅 - var rowWidth = (row23Left - row1Left) / 22; + //1列(1時間)の幅 + var rowWidth = (row23Left - row1Left) / 22; - ////1行(=1時間)の高さ - ////var rowHeight = row1Top - row0Top; - //var rowHeight = (row23Top - row1Top) / 22; + ////1行(=1時間)の高さ + ////var rowHeight = row1Top - row0Top; + //var rowHeight = (row23Top - row1Top) / 22; - //指定時間が最初になるよう、divの横スクロールを移動 - coordinateOrigins[0].scrollLeft = rowWidth * idx; + //指定時間が最初になるよう、divの横スクロールを移動 + coordinateOrigins[0].scrollLeft = rowWidth * idx; - ////指定時間が最初になるよう、divの縦スクロールを移動 - //coordinateOrigins[0].scrollTop = rowHeight * idx; + ////指定時間が最初になるよう、divの縦スクロールを移動 + //coordinateOrigins[0].scrollTop = rowHeight * idx; - //$scope.origin = coordinateOrigins[0].scrollTop; - //$scope.rowHeight = rowHeight; - $scope.rowWidth = rowWidth; + //$scope.origin = coordinateOrigins[0].scrollTop; + //$scope.rowHeight = rowHeight; + $scope.rowWidth = rowWidth; - //0:00幅固定 - $('.reservation-timeline-data-area').width(rowWidth); - ////0:00高さ固定 - //$('.reservation-timeline-data-area').height(rowHeight); + //0:00幅固定 + $('#frame-' + frameId + ' .reservation-timeline-data-area').width(rowWidth); + ////0:00高さ固定 + //$('.reservation-timeline-data-area').height(rowHeight); - var row1Top = row1[0].getBoundingClientRect().top; - $scope.rowTop = row1Top; + var row1Top = row1[0].getBoundingClientRect().top; + $scope.rowTop = row1Top; - //初期化 - $scope.prevMargin = 0; - $scope.maxLineNum = 0; - $scope.Column = []; - $scope.Column[0] = []; + //初期化 + $scope.prevMargin = 0; + $scope.maxLineNum = 0; + $scope.Column = []; + $scope.Column[0] = []; + }; }]);