Wiki source code of 学校ページ テンプレート
Last modified by Super Admin on 2026/04/05 18:59
Hide last authors
| author | version | line-number | content |
|---|---|---|---|
| |
1.1 | 1 | {{velocity}} |
| 2 | ## ===== 学校ページ テンプレート ===== | ||
| |
70.1 | 3 | ## ゲストが ?sheet= 付きURL(編集フォーム等)に直接アクセスした場合、ログインページへリダイレクト |
| 4 | #if($xcontext.user == 'XWiki.XWikiGuest' && $request.sheet && $request.sheet != '') | ||
| 5 | #set($currentUrl = $doc.getURL('view', "sheet=${request.sheet}")) | ||
| 6 | $response.sendRedirect("/bin/login/XWiki/XWikiLogin?srid=$escapetool.url($currentUrl)") | ||
| 7 | #stop | ||
| 8 | #end | ||
| |
27.1 | 9 | {{html clean="false"}} |
| |
109.1 | 10 | ## --- OGP メタタグ(SNSシェア対応) --- |
| 11 | #set($ogTitle = "$!{schoolName} — 生徒会Wiki") | ||
| 12 | #set($ogDesc = "$!{schoolName}の生徒会活動情報。全国の高校の生徒会活動事例を集積・共有するプラットフォーム。") | ||
| 13 | #set($ogUrl = "https://${request.serverName}${doc.getURL('view')}") | ||
| 14 | <meta property="og:type" content="article" /> | ||
| 15 | <meta property="og:title" content="$escapetool.xml($ogTitle)" /> | ||
| 16 | <meta property="og:description" content="$escapetool.xml($ogDesc)" /> | ||
| 17 | <meta property="og:url" content="$escapetool.xml($ogUrl)" /> | ||
| 18 | <meta property="og:site_name" content="生徒会Wiki" /> | ||
| 19 | <meta property="og:locale" content="ja_JP" /> | ||
| 20 | <meta name="twitter:card" content="summary" /> | ||
| 21 | <meta name="twitter:title" content="$escapetool.xml($ogTitle)" /> | ||
| 22 | <meta name="twitter:description" content="$escapetool.xml($ogDesc)" /> | ||
| |
27.1 | 23 | ## メンテナンスバナー({{include}}ではなくインラインで記述し、<p>タグ挿入を回避) |
| 24 | #set($bannerDoc = $xwiki.getDocument('SeitokaiAdmin.MaintenanceBanner')) | ||
| 25 | #set($bannerObj = $bannerDoc.getObject('SeitokaiCode.MaintenanceBannerClass')) | ||
| 26 | #if($bannerObj && $bannerObj.getValue('enabled') == 1) | ||
| 27 | #set($bannerMsg = $bannerObj.getValue('message')) | ||
| 28 | #set($bannerLevel = $bannerObj.getValue('level')) | ||
| 29 | #if(!$bannerLevel || $bannerLevel == '')#set($bannerLevel = 'warning')#end | ||
| 30 | <div class="maintenance-banner active maintenance-${bannerLevel}" id="maintenance-banner"> | ||
| 31 | <div class="maintenance-banner-inner"> | ||
| 32 | <span class="maintenance-icon">#if($bannerLevel == 'urgent')<svg class="ico-banner" viewBox="0 0 24 24"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>#elseif($bannerLevel == 'info')<svg class="ico-banner" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>#else<svg class="ico-banner" viewBox="0 0 24 24"><path d="M14.7 6.3a1 1 0 000 1.4l1.6 1.6a1 1 0 001.4 0l3.77-3.77a6 6 0 01-7.94 7.94l-6.91 6.91a2.12 2.12 0 01-3-3l6.91-6.91a6 6 0 017.94-7.94l-3.76 3.76z"/></svg>#end</span> | ||
| 33 | <span class="maintenance-text">$!escapetool.xml($bannerMsg)</span> | ||
| 34 | <button class="maintenance-close" onclick="document.getElementById('maintenance-banner').style.display='none'">×</button> | ||
| 35 | </div> | ||
| 36 | </div> | ||
| 37 | #end | ||
| |
1.1 | 38 | ## --- 学校基本情報フィールド --- |
| 39 | #set($schoolCode = $doc.getValue('schoolCode')) | ||
| 40 | #set($schoolName = $doc.getValue('schoolName')) | ||
| 41 | #set($prefecture = $doc.getValue('prefecture')) | ||
| 42 | #set($city = $doc.getValue('city')) | ||
| 43 | #set($classCount = $doc.getValue('classCount')) | ||
| 44 | #set($studentCount = $doc.getValue('studentCount')) | ||
| 45 | #set($coeducation = $doc.getValue('coeducation')) | ||
| 46 | #set($establishment = $doc.getValue('establishment')) | ||
| 47 | #set($schoolLevel = $doc.getValue('schoolLevel')) | ||
| 48 | #set($schoolSystem = $doc.getValue('schoolSystem')) | ||
| 49 | #set($website = $doc.getValue('website')) | ||
| |
73.1 | 50 | #set($schoolPhoto = $doc.getValue('schoolPhoto')) |
| |
83.1 | 51 | #set($schoolDescription = $doc.getValue('schoolDescription')) |
| |
1.1 | 52 | |
| |
81.1 | 53 | ## --- 生徒会組織 --- |
| |
1.1 | 54 | #set($orgChart = $doc.getValue('orgChart')) |
| 55 | #set($orgChartImage = $doc.getValue('orgChartImage')) | ||
| 56 | |||
| 57 | ## --- 日常の活動・選挙・定例活動 --- | ||
| 58 | #set($dailyActivities = $doc.getValue('dailyActivities')) | ||
| 59 | #set($dailyActivitiesNote = $doc.getValue('dailyActivitiesNote')) | ||
| 60 | #set($electionExists = $doc.getValue('electionExists')) | ||
| 61 | #set($electionType = $doc.getValue('electionType')) | ||
| 62 | #set($electionNote = $doc.getValue('electionNote')) | ||
| 63 | #set($meetingFrequency = $doc.getValue('meetingFrequency')) | ||
| 64 | #set($regularActivitiesNote = $doc.getValue('regularActivitiesNote')) | ||
| 65 | |||
| 66 | ## --- 予算 --- | ||
| 67 | #set($budgetProcess = $doc.getValue('budgetProcess')) | ||
| 68 | #set($studentFee = $doc.getValue('studentFee')) | ||
| 69 | #set($budgetScale = $doc.getValue('budgetScale')) | ||
| 70 | #set($budgetAllocation = $doc.getValue('budgetAllocation')) | ||
| 71 | #set($budgetNote = $doc.getValue('budgetNote')) | ||
| 72 | |||
| |
90.1 | 73 | ## --- 校則・生徒会会則の見直し --- |
| |
1.1 | 74 | #set($ruleReviewStatus = $doc.getValue('ruleReviewStatus')) |
| 75 | #set($ruleReviewContent = $doc.getValue('ruleReviewContent')) | ||
| 76 | #set($ruleReviewProposer = $doc.getValue('ruleReviewProposer')) | ||
| 77 | #set($ruleReviewImplementer = $doc.getValue('ruleReviewImplementer')) | ||
| 78 | #set($ruleReviewSystem = $doc.getValue('ruleReviewSystem')) | ||
| 79 | |||
| |
94.1 | 80 | ## --- 活動環境 --- |
| 81 | #set($activityPlace = $doc.getValue('activityPlace')) | ||
| 82 | #set($activityRoomEquipment = $doc.getValue('activityRoomEquipment')) | ||
| 83 | #set($activityRoomImage = $doc.getValue('activityRoomImage')) | ||
| |
98.1 | 84 | #set($ictTools = $doc.getValue('ictTools')) |
| |
94.1 | 85 | #set($ictUsage = $doc.getValue('ictUsage')) |
| 86 | |||
| 87 | ## --- 生徒総会 --- | ||
| 88 | #set($assemblyFormat = $doc.getValue('assemblyFormat')) | ||
| 89 | #set($assemblyCount = $doc.getValue('assemblyCount')) | ||
| 90 | #set($assemblyAgenda = $doc.getValue('assemblyAgenda')) | ||
| 91 | #set($assemblyTopics = $doc.getValue('assemblyTopics')) | ||
| 92 | #set($assemblyNote = $doc.getValue('assemblyNote')) | ||
| 93 | |||
| 94 | ## --- 広報 --- | ||
| 95 | #set($publicityMethod = $doc.getValue('publicityMethod')) | ||
| 96 | #set($publicityFrequency = $doc.getValue('publicityFrequency')) | ||
| 97 | #set($publicityNote = $doc.getValue('publicityNote')) | ||
| 98 | |||
| 99 | ## --- 外部連携 --- | ||
| 100 | #set($externalCooperation = $doc.getValue('externalCooperation')) | ||
| 101 | #set($externalOrgName = $doc.getValue('externalOrgName')) | ||
| 102 | #set($socialParticipation = $doc.getValue('socialParticipation')) | ||
| 103 | |||
| 104 | ## --- 年間主要行事 --- | ||
| 105 | #set($eventApril = $doc.getValue('eventApril')) | ||
| 106 | #set($eventMay = $doc.getValue('eventMay')) | ||
| 107 | #set($eventJune = $doc.getValue('eventJune')) | ||
| 108 | #set($eventJuly = $doc.getValue('eventJuly')) | ||
| 109 | #set($eventAugust = $doc.getValue('eventAugust')) | ||
| 110 | #set($eventSeptember = $doc.getValue('eventSeptember')) | ||
| 111 | #set($eventOctober = $doc.getValue('eventOctober')) | ||
| 112 | #set($eventNovember = $doc.getValue('eventNovember')) | ||
| 113 | #set($eventDecember = $doc.getValue('eventDecember')) | ||
| 114 | #set($eventJanuary = $doc.getValue('eventJanuary')) | ||
| 115 | #set($eventFebruary = $doc.getValue('eventFebruary')) | ||
| 116 | #set($eventMarch = $doc.getValue('eventMarch')) | ||
| 117 | |||
| |
1.1 | 118 | ## --- 課題・連絡先 --- |
| 119 | #set($challenges = $doc.getValue('challenges')) | ||
| 120 | #set($contactInfo = $doc.getValue('contactInfo')) | ||
| 121 | #set($seitokaiWebsite = $doc.getValue('seitokaiWebsite')) | ||
| 122 | #set($seitokaiTwitter = $doc.getValue('seitokaiTwitter')) | ||
| 123 | #set($seitokaiInstagram = $doc.getValue('seitokaiInstagram')) | ||
| 124 | #set($seitokaiYoutube = $doc.getValue('seitokaiYoutube')) | ||
| 125 | #set($seitokaiOtherSns = $doc.getValue('seitokaiOtherSns')) | ||
| 126 | |||
| |
43.1 | 127 | ## --- 現在の年度を計算(4月始まり) --- |
| |
1.1 | 128 | #set($nowFY = $datetool.date) |
| 129 | #set($currentFYMonth = $mathtool.toInteger($datetool.format('MM', $nowFY))) | ||
| 130 | #set($currentFYYear = $mathtool.toInteger($datetool.format('yyyy', $nowFY))) | ||
| 131 | #if($currentFYMonth >= 4) | ||
| 132 | #set($currentFiscalYear = $currentFYYear) | ||
| 133 | #else | ||
| 134 | #set($currentFiscalYear = $mathtool.sub($currentFYYear, 1)) | ||
| 135 | #end | ||
| 136 | |||
| 137 | ## --- 公開範囲フィールド --- | ||
| 138 | #set($visibilityOrgChart = $!doc.getValue('visibilityOrgChart')) | ||
| 139 | #set($visibilityBudget = $!doc.getValue('visibilityBudget')) | ||
| 140 | #set($visibilityRuleReview = $!doc.getValue('visibilityRuleReview')) | ||
| 141 | #set($visibilityChallenges = $!doc.getValue('visibilityChallenges')) | ||
| |
96.1 | 142 | #set($visibilityDailyActivities = $!doc.getValue('visibilityDailyActivities')) |
| 143 | #set($visibilityElection = $!doc.getValue('visibilityElection')) | ||
| 144 | #set($visibilityMeeting = $!doc.getValue('visibilityMeeting')) | ||
| 145 | #set($visibilityActivityEnv = $!doc.getValue('visibilityActivityEnv')) | ||
| 146 | #set($visibilityAssembly = $!doc.getValue('visibilityAssembly')) | ||
| 147 | #set($visibilityPublicity = $!doc.getValue('visibilityPublicity')) | ||
| 148 | #set($visibilityExternal = $!doc.getValue('visibilityExternal')) | ||
| 149 | #set($visibilityAnnualEvents = $!doc.getValue('visibilityAnnualEvents')) | ||
| |
1.1 | 150 | ## デフォルト値(未設定なら全体公開) |
| 151 | #if(!$visibilityOrgChart || $visibilityOrgChart == '') #set($visibilityOrgChart = 'public') #end | ||
| 152 | #if(!$visibilityBudget || $visibilityBudget == '') #set($visibilityBudget = 'public') #end | ||
| 153 | #if(!$visibilityRuleReview || $visibilityRuleReview == '') #set($visibilityRuleReview = 'public') #end | ||
| 154 | #if(!$visibilityChallenges || $visibilityChallenges == '') #set($visibilityChallenges = 'public') #end | ||
| 155 | |||
| 156 | ## --- 閲覧者情報(公開範囲チェック用) --- | ||
| 157 | #set($viewerUser = $xcontext.user) | ||
| 158 | #set($isGuest = $viewerUser == 'XWiki.XWikiGuest') | ||
| 159 | #set($isViewerAdmin = false) | ||
| 160 | #set($viewerSchoolCode = '') | ||
| |
99.1 | 161 | #set($viewerSecondaryGraduated = false) |
| |
1.1 | 162 | #if(!$isGuest) |
| 163 | #set($viewerDoc = $xwiki.getDocument($viewerUser)) | ||
| 164 | #set($viewerAccountType = $!viewerDoc.getValue('accountType')) | ||
| 165 | #set($viewerSchoolCode = $!viewerDoc.getValue('schoolCode')) | ||
| |
72.1 | 166 | #set($viewerSecondarySchoolCode = $!viewerDoc.getValue('secondarySchoolCode')) |
| 167 | #set($viewerUserRole = $!viewerDoc.getValue('userRole')) | ||
| |
1.1 | 168 | #if($viewerAccountType == 'admin') |
| 169 | #set($isViewerAdmin = true) | ||
| 170 | #end | ||
| |
99.1 | 171 | ## 第2所属校の在学年数超過チェック |
| 172 | #set($viewerSecEnrollYear = $!viewerDoc.getValue('secondaryEnrollmentYear')) | ||
| 173 | #if($viewerSecondarySchoolCode && $viewerSecondarySchoolCode != '' && $viewerSecEnrollYear && $viewerSecEnrollYear != '') | ||
| 174 | #set($vNow = $datetool.date) | ||
| 175 | #set($vCurYear = $mathtool.toInteger($datetool.format('yyyy', $vNow))) | ||
| 176 | #set($vCurMonth = $mathtool.toInteger($datetool.format('MM', $vNow))) | ||
| 177 | #if($vCurMonth >= 4)#set($vSchoolYear = $vCurYear)#else#set($vSchoolYear = $mathtool.sub($vCurYear, 1))#end | ||
| 178 | #set($vSecEnroll = $mathtool.toInteger($viewerSecEnrollYear)) | ||
| 179 | #set($vSecMax = 3) | ||
| 180 | #if($viewerSecondarySchoolCode.length() >= 2) | ||
| 181 | #set($vSecType = $viewerSecondarySchoolCode.substring(0, 2)) | ||
| 182 | #if($vSecType == 'C2')#set($vSecMax = 9)#elseif($vSecType == 'D2')#set($vSecMax = 6)#end | ||
| 183 | #end | ||
| 184 | #set($vSecGrade = $mathtool.add($mathtool.sub($vSchoolYear, $vSecEnroll), 1)) | ||
| 185 | #if($vSecGrade > $vSecMax) | ||
| 186 | #set($viewerSecondaryGraduated = true) | ||
| 187 | #end | ||
| 188 | #end | ||
| |
1.1 | 189 | #end |
| 190 | |||
| |
66.1 | 191 | ## --- 関連校(中高一貫校)情報 --- |
| 192 | #set($affiliatedSchoolCode = $!doc.getValue('affiliatedSchoolCode')) | ||
| 193 | #set($affiliatedSchoolName = $!doc.getValue('affiliatedSchoolName')) | ||
| 194 | #set($isAffiliated = false) | ||
| |
72.1 | 195 | #if($affiliatedSchoolCode && $affiliatedSchoolCode != '') |
| 196 | #if($viewerSchoolCode == $affiliatedSchoolCode) | ||
| 197 | #set($isAffiliated = true) | ||
| |
99.1 | 198 | #elseif($viewerSecondarySchoolCode && $viewerSecondarySchoolCode != '' && $viewerSecondarySchoolCode == $affiliatedSchoolCode && !$viewerSecondaryGraduated) |
| |
72.1 | 199 | #set($isAffiliated = true) |
| 200 | #end | ||
| |
66.1 | 201 | #end |
| 202 | |||
| |
72.1 | 203 | ## --- 校内判定(卒業生を除外、secondarySchoolCodeも含む) --- |
| 204 | #set($isSchoolMember = false) | ||
| 205 | #if(!$isGuest && $viewerUserRole != 'graduate') | ||
| 206 | #if($viewerSchoolCode == $schoolCode || $isAffiliated) | ||
| 207 | #set($isSchoolMember = true) | ||
| |
99.1 | 208 | #elseif($viewerSecondarySchoolCode && $viewerSecondarySchoolCode != '' && $viewerSecondarySchoolCode == $schoolCode && !$viewerSecondaryGraduated) |
| |
72.1 | 209 | #set($isSchoolMember = true) |
| 210 | #end | ||
| 211 | #end | ||
| 212 | ## 卒業生の母校判定(投稿バッジ用) | ||
| 213 | #set($isAlumniOfSchool = false) | ||
| 214 | #if(!$isGuest && $viewerUserRole == 'graduate') | ||
| 215 | #if($viewerSchoolCode == $schoolCode || ($affiliatedSchoolCode != '' && $viewerSchoolCode == $affiliatedSchoolCode)) | ||
| 216 | #set($isAlumniOfSchool = true) | ||
| 217 | #end | ||
| 218 | #end | ||
| 219 | |||
| |
48.1 | 220 | ## --- 学校ページ非表示チェック --- |
| 221 | #set($schoolHidden = $doc.getValue('hidden')) | ||
| 222 | #if($schoolHidden == 1) | ||
| 223 | #if($isViewerAdmin) | ||
| 224 | ## 管理者: 黄色バナー + ページ内容は通常表示(プレビュー) | ||
| 225 | <div class="school-hidden-banner admin"> | ||
| 226 | <svg class="ico" viewBox="0 0 24 24"><path d="M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 01-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg> | ||
| 227 | <div> | ||
| 228 | <strong>このページは非表示になっています</strong>(管理者のみ閲覧可能) | ||
| 229 | #set($hBy = $!doc.getValue('hiddenBy')) | ||
| 230 | #set($hAt = $!doc.getValue('hiddenAt')) | ||
| 231 | #set($hReason = $!doc.getValue('hiddenReason')) | ||
| 232 | <div class="school-hidden-detail"> | ||
| 233 | 非表示: $!escapetool.xml($hAt) / $!escapetool.xml($hBy) | ||
| 234 | #if($hReason && $hReason != '') ・ 理由: $!escapetool.xml($hReason)#end | ||
| 235 | </div> | ||
| 236 | <a href="$xwiki.getURL('SeitokaiAdmin.SchoolManagement', 'view')" style="color:#92400e;text-decoration:underline">学校ページ管理へ</a> | ||
| 237 | </div> | ||
| 238 | </div> | ||
| 239 | #else | ||
| 240 | ## 一般ユーザー・ゲスト: 非公開メッセージを表示して停止 | ||
| 241 | <div class="school-hidden-public"> | ||
| 242 | <svg class="ico" viewBox="0 0 24 24" style="width:2.5em;height:2.5em"><path d="M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 01-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg> | ||
| 243 | <h2>このページは現在公開されていません</h2> | ||
| 244 | <p>このページは管理者により非公開に設定されています。</p> | ||
| 245 | <a href="$xwiki.getURL('Schools.WebHome', 'view')" class="btn-back-list">学校一覧に戻る</a> | ||
| 246 | </div> | ||
| 247 | #stop | ||
| 248 | #end | ||
| 249 | #end | ||
| 250 | |||
| |
1.1 | 251 | ## --- 投稿固定/解除処理 --- |
| 252 | #set($pinAction = $!request.action) | ||
| |
72.1 | 253 | #if(($pinAction == 'pin' || $pinAction == 'unpin') && ($viewerAccountType == 'admin' || ($viewerAccountType == 'verified' && $isSchoolMember)) && $services.csrf.isTokenValid($request.form_token)) |
| |
45.1 | 254 | #set($pinPostObjStr = $!request.postObj) |
| 255 | #if(!$pinPostObjStr.matches('^\d+$')) | ||
| 256 | ## 不正な値 → 無視 | ||
| 257 | #else | ||
| 258 | #set($postObjNum = $mathtool.toInteger($pinPostObjStr)) | ||
| |
1.1 | 259 | #set($postObj = $doc.getObject('SeitokaiCode.ActivityPostClass', $postObjNum)) |
| 260 | #if($postObj) | ||
| 261 | #if($pinAction == 'pin') | ||
| 262 | $postObj.set('pinned', '1') | ||
| 263 | #set($pinnerDoc = $xwiki.getDocument($xcontext.user)) | ||
| 264 | #set($pinnerName = $!pinnerDoc.getValue('displayName')) | ||
| 265 | #if(!$pinnerName || $pinnerName == '')#set($pinnerName = $xwiki.getUserName($xcontext.user))#end | ||
| 266 | $postObj.set('pinnedBy', $pinnerName) | ||
| 267 | $postObj.set('pinnedDate', $datetool.format('yyyy/MM/dd HH:mm', $datetool.date)) | ||
| 268 | $doc.saveWithProgrammingRights('投稿を固定') | ||
| 269 | #else | ||
| 270 | $postObj.set('pinned', '') | ||
| 271 | $postObj.set('pinnedBy', '') | ||
| 272 | $postObj.set('pinnedDate', '') | ||
| 273 | $doc.saveWithProgrammingRights('投稿の固定を解除') | ||
| 274 | #end | ||
| 275 | $response.sendRedirect($doc.getURL('view')) | ||
| 276 | #stop | ||
| 277 | #end | ||
| |
45.1 | 278 | #end## /matches |
| |
1.1 | 279 | #end |
| 280 | |||
| 281 | ## --- 特色ある活動 選定/解除処理 --- | ||
| 282 | #set($featAction = $!request.action) | ||
| |
72.1 | 283 | #if(($featAction == 'feature' || $featAction == 'unfeature') && ($viewerAccountType == 'admin' || (($viewerAccountType == 'verified' || $viewerAccountType == 'referred') && $isSchoolMember)) && $services.csrf.isTokenValid($request.form_token)) |
| |
45.1 | 284 | #set($featActObjStr = $!request.actObj) |
| 285 | #if($featActObjStr.matches('^\d+$')) | ||
| 286 | #set($actObjNum = $mathtool.toInteger($featActObjStr)) | ||
| |
1.1 | 287 | #set($actObj = $doc.getObject('SeitokaiCode.ActivityClass', $actObjNum)) |
| 288 | #if($actObj) | ||
| 289 | #if($featAction == 'feature') | ||
| 290 | ## 上限3件チェック | ||
| 291 | #set($allActs = $doc.getObjects('SeitokaiCode.ActivityClass')) | ||
| 292 | #set($featCount = 0) | ||
| 293 | #if($allActs) | ||
| 294 | #foreach($fa in $allActs) | ||
| 295 | #if($!fa.getValue('featured') == '1') | ||
| 296 | #set($featCount = $featCount + 1) | ||
| 297 | #end | ||
| 298 | #end | ||
| 299 | #end | ||
| 300 | #if($featCount < 3) | ||
| 301 | $actObj.set('featured', '1') | ||
| 302 | #set($featurerDoc = $xwiki.getDocument($xcontext.user)) | ||
| 303 | #set($featurerName = $!featurerDoc.getValue('displayName')) | ||
| 304 | #if(!$featurerName || $featurerName == '')#set($featurerName = $xwiki.getUserName($xcontext.user))#end | ||
| 305 | $actObj.set('featuredBy', $featurerName) | ||
| 306 | $actObj.set('featuredDate', $datetool.format('yyyy/MM/dd HH:mm', $datetool.date)) | ||
| 307 | $doc.saveWithProgrammingRights('特色ある活動に選定') | ||
| 308 | #end | ||
| 309 | #else | ||
| 310 | $actObj.set('featured', '') | ||
| 311 | $actObj.set('featuredBy', '') | ||
| 312 | $actObj.set('featuredDate', '') | ||
| 313 | $doc.saveWithProgrammingRights('特色ある活動の選定を解除') | ||
| 314 | #end | ||
| 315 | $response.sendRedirect($doc.getURL('view')) | ||
| 316 | #stop | ||
| 317 | #end | ||
| |
45.1 | 318 | #end## /matches |
| |
1.1 | 319 | #end |
| 320 | |||
| 321 | ## --- ユーザー情報取得 --- | ||
| 322 | ## displayName: Wiki上の表示名(ニックネーム)。本名(firstName/lastName)は管理者のみ閲覧可能。 | ||
| 323 | #set($lastAuthor = $doc.author) | ||
| |
30.1 | 324 | #set($lastAuthorDoc = $xwiki.getDocument($lastAuthor)) |
| |
1.1 | 325 | #set($authorAccountType = '') |
| 326 | #set($authorUserRole = '') | ||
| 327 | #set($authorUserStatus = '') | ||
| 328 | #set($authorEnrollmentYear = '') | ||
| 329 | #set($authorGrade = '') | ||
| 330 | #set($authorDisplayName = '') | ||
| 331 | #if($lastAuthorDoc) | ||
| 332 | #set($authorAccountType = $!lastAuthorDoc.getValue('accountType')) | ||
| 333 | #set($authorUserRole = $!lastAuthorDoc.getValue('userRole')) | ||
| 334 | #set($authorUserStatus = $!lastAuthorDoc.getValue('userStatus')) | ||
| 335 | #set($authorEnrollmentYear = $!lastAuthorDoc.getValue('enrollmentYear')) | ||
| 336 | #set($authorDisplayName = $!lastAuthorDoc.getValue('displayName')) | ||
| 337 | #if(!$authorDisplayName || $authorDisplayName == '') | ||
| |
25.1 | 338 | ## false引数でプレーンテキスト(HTMLリンクなし)を取得 |
| 339 | #set($authorDisplayName = $xwiki.getUserName($doc.author, false)) | ||
| |
1.1 | 340 | #end |
| 341 | ## --- 学年の動的計算(学校種別対応) --- | ||
| 342 | ## 日本の学校年度: 4月始まり。currentSchoolYear = (月>=4) ? 今年 : 去年 | ||
| 343 | ## 学年 = currentSchoolYear - enrollmentYear + 1 | ||
| 344 | ## 在学年数超過: 卒業生として表示 | ||
| 345 | #set($authorSchoolCode = $!lastAuthorDoc.getValue('schoolCode')) | ||
| 346 | #if($authorEnrollmentYear && $authorEnrollmentYear != '' && $authorUserRole == 'student') | ||
| 347 | #set($now = $datetool.date) | ||
| 348 | #set($currentYear = $datetool.format('yyyy', $now)) | ||
| 349 | #set($currentMonth = $datetool.format('MM', $now)) | ||
| 350 | #set($currentYearInt = $mathtool.toInteger($currentYear)) | ||
| 351 | #set($currentMonthInt = $mathtool.toInteger($currentMonth)) | ||
| 352 | #set($enrollYearInt = $mathtool.toInteger($authorEnrollmentYear)) | ||
| 353 | #if($currentMonthInt >= 4) | ||
| 354 | #set($schoolYear = $currentYearInt) | ||
| 355 | #else | ||
| 356 | #set($schoolYear = $mathtool.sub($currentYearInt, 1)) | ||
| 357 | #end | ||
| 358 | ## 学校種別から在学年数を判定: C1=中学(3年), C2=義務教育(9年), D1=高校(3年), D2=中等教育(6年) | ||
| 359 | #set($authorMaxYears = 3) | ||
| 360 | #if($authorSchoolCode && $authorSchoolCode.length() >= 2) | ||
| 361 | #set($authorSchoolType = $authorSchoolCode.substring(0, 2)) | ||
| 362 | #if($authorSchoolType == 'C2') | ||
| 363 | #set($authorMaxYears = 9) | ||
| 364 | #elseif($authorSchoolType == 'D2') | ||
| 365 | #set($authorMaxYears = 6) | ||
| 366 | #end | ||
| 367 | #end | ||
| 368 | #set($gradeNum = $mathtool.add($mathtool.sub($schoolYear, $enrollYearInt), 1)) | ||
| 369 | #if($gradeNum >= 1 && $gradeNum <= $authorMaxYears) | ||
| 370 | #set($authorGrade = "${gradeNum}年生") | ||
| 371 | #elseif($gradeNum > $authorMaxYears) | ||
| 372 | #set($authorGrade = "卒業生") | ||
| 373 | #end | ||
| 374 | #end | ||
| 375 | #end | ||
| 376 | |||
| |
37.1 | 377 | ## --- 学校名見出し(XWikiデフォルトタイトルを非表示にし、学校名を表示) --- |
| 378 | #if($schoolName && $schoolName != '') | ||
| |
38.1 | 379 | <style>.document-header { display: none !important; }</style> |
| |
37.1 | 380 | <h1 class="school-page-title">$!escapetool.xml($schoolName)</h1> |
| 381 | #end | ||
| 382 | |||
| |
33.1 | 383 | ## --- 編集ボタン(権限があるユーザーのみ表示) --- |
| 384 | #set($canEditSchool = false) | ||
| |
93.1 | 385 | #if(!$isGuest && ($isViewerAdmin || $isSchoolMember || $isAlumniOfSchool)) |
| |
33.1 | 386 | #set($canEditSchool = true) |
| 387 | #end | ||
| 388 | #if($canEditSchool) | ||
| 389 | <div style="text-align:right; margin-bottom:12px;"> | ||
| |
117.1 | 390 | <a href="$doc.getURL('view', 'sheet=SeitokaiCode.SchoolEditForm')" class="btn-school-edit"><svg class="ico" viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></svg> 情報を編集</a> |
| |
1.1 | 391 | </div> |
| |
33.1 | 392 | #end |
| |
1.1 | 393 | |
| |
66.1 | 394 | ## --- 関連校(中高一貫校)バナー --- |
| 395 | #if($affiliatedSchoolCode && $affiliatedSchoolCode != '') | ||
| 396 | #set($affiliatedPageRef = "Schools.${affiliatedSchoolCode}.WebHome") | ||
| 397 | #set($affiliatedPageExists = $xwiki.exists($affiliatedPageRef)) | ||
| 398 | <div class="affiliated-school-banner"> | ||
| 399 | <svg class="ico" viewBox="0 0 24 24" stroke-width="1.5"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> | ||
| 400 | <div> | ||
| 401 | <strong>中高一貫校</strong>: | ||
| 402 | #if($affiliatedPageExists) | ||
| 403 | <a href="$xwiki.getURL($affiliatedPageRef, 'view')">$!escapetool.xml($affiliatedSchoolName)</a> | ||
| 404 | #else | ||
| 405 | $!escapetool.xml($affiliatedSchoolName) | ||
| 406 | #end | ||
| 407 | と連携しています | ||
| 408 | </div> | ||
| 409 | </div> | ||
| 410 | #end | ||
| 411 | |||
| |
50.1 | 412 | ## --- ① 学校基本情報 --- |
| 413 | <div class="school-info-card collapsed" id="card-basic-info"> | ||
| 414 | <h2 role="button" tabindex="0" aria-expanded="false" onclick="toggleInfoCard('card-basic-info')" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();toggleInfoCard('card-basic-info')}"><span><svg class="ico ico-md" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 016.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/></svg> 学校基本情報</span><span class="collapse-toggle"><span class="collapse-label-open">たたむ</span><span class="collapse-label-closed">開く</span> <span class="collapse-arrow">▼</span></span></h2> | ||
| |
73.1 | 415 | <div class="school-basic-info-layout"> |
| 416 | <div class="school-basic-info-table"> | ||
| 417 | <table class="wiki-table school-info-table"> | ||
| 418 | <tr><th>学校コード</th><td>$!escapetool.xml($!schoolCode)</td></tr> | ||
| 419 | <tr><th>学校名</th><td>$!escapetool.xml($!schoolName)</td></tr> | ||
| 420 | <tr><th>所在地</th><td>$!escapetool.xml($!prefecture) #if($city && $city != '')$!escapetool.xml($city)#end</td></tr> | ||
| 421 | <tr><th>学級数・生徒数</th><td>#if($classCount && $classCount != '')${classCount}学級#end #if($studentCount && $studentCount != '')/ 約${studentCount}名#end</td></tr> | ||
| |
119.1 | 422 | <tr><th>共学・別学</th><td> |
| 423 | #if($coeducation && $coeducation != '') | ||
| 424 | <div class="selection-display"> | ||
| 425 | #foreach($ceo in ["共学","男子校","女子校","その他"]) | ||
| 426 | #if($coeducation == $ceo) | ||
| 427 | <span class="selection-item">$!escapetool.xml($ceo)</span> | ||
| 428 | #else | ||
| 429 | <span class="selection-item selection-item-off">$!escapetool.xml($ceo)</span> | ||
| 430 | #end | ||
| 431 | #end | ||
| 432 | </div> | ||
| 433 | #end | ||
| 434 | </td></tr> | ||
| |
73.1 | 435 | <tr><th>設置者</th><td>$!escapetool.xml($!establishment)</td></tr> |
| 436 | <tr><th>学校種</th><td>$!escapetool.xml($!schoolLevel)</td></tr> | ||
| 437 | <tr><th>課程</th><td>#if($schoolSystem && !$schoolSystem.isEmpty())#foreach($ss in $schoolSystem)#if($foreach.count > 1) / #end$!escapetool.xml($ss)#end#end</td></tr> | ||
| 438 | <tr><th>公式サイト</th><td>#if($website && $website != '')<a href="$!escapetool.xml($website)" target="_blank" rel="noopener">$!escapetool.xml($website)</a>#else<span class="text-placeholder">未登録</span>#end</td></tr> | ||
| 439 | </table> | ||
| 440 | </div> | ||
| 441 | #if($schoolPhoto && $schoolPhoto != '') | ||
| 442 | <div class="school-photo-area"> | ||
| 443 | <img src="$doc.getAttachmentURL($schoolPhoto)" alt="$!escapetool.xml($schoolName)" class="school-photo" /> | ||
| 444 | </div> | ||
| 445 | #end | ||
| 446 | </div> | ||
| |
83.1 | 447 | #if($schoolDescription && $schoolDescription.trim() != '') |
| 448 | <div class="free-note" style="margin-top:var(--sp-4);">$!escapetool.xml($schoolDescription)</div> | ||
| 449 | #end | ||
| |
87.1 | 450 | |
| |
1.1 | 451 | </div> |
| 452 | |||
| |
92.1 | 453 | ## --- ② 生徒会情報(折りたたみカード) --- |
| |
52.1 | 454 | <div class="school-info-card" id="card-seitokai-info"> |
| |
92.1 | 455 | <h2 role="button" tabindex="0" aria-expanded="true" onclick="toggleInfoCard('card-seitokai-info')" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();toggleInfoCard('card-seitokai-info')}"><span><svg class="ico ico-md" viewBox="0 0 24 24"><path d="M3 21h18"/><path d="M5 21V7l7-4 7 4v14"/><path d="M9 21v-4h6v4"/></svg> 生徒会情報</span><span class="collapse-toggle"><span class="collapse-label-open">たたむ</span><span class="collapse-label-closed">開く</span> <span class="collapse-arrow">▼</span></span></h2> |
| |
50.1 | 456 | <div class="seitokai-info-body"> |
| |
1.1 | 457 | |
| |
81.1 | 458 | ## --- 生徒会組織 --- |
| |
50.1 | 459 | #set($hasOrgContent = ($orgChart && $orgChart != '') || ($orgChartImage && $orgChartImage != '')) |
| 460 | #if($hasOrgContent) | ||
| 461 | #set($canViewOrgChart = true) | ||
| |
72.1 | 462 | #if($visibilityOrgChart == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewOrgChart = false) |
| 463 | #elseif($visibilityOrgChart == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewOrgChart = false) | ||
| |
50.1 | 464 | #end |
| 465 | #if($canViewOrgChart) | ||
| 466 | <div class="seitokai-subsection"> | ||
| |
85.1 | 467 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><path d="M3 21h18"/><path d="M5 21V7l7-4 7 4v14"/><path d="M9 21v-4h6v4"/><line x1="9" y1="10" x2="9" y2="10.01"/><line x1="15" y1="10" x2="15" y2="10.01"/><line x1="9" y1="14" x2="9" y2="14.01"/><line x1="15" y1="14" x2="15" y2="14.01"/></svg> 生徒会組織 #if($visibilityOrgChart != 'public')<span class="visibility-badge visibility-${visibilityOrgChart}">#if($visibilityOrgChart == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> |
| |
50.1 | 468 | <div class="seitokai-subsection-content"> |
| 469 | #if($orgChartImage && $orgChartImage != '') | ||
| 470 | <div class="school-org-img-wrap"><img src="$doc.getAttachmentURL($orgChartImage)" alt="組織図" class="org-chart-img" /></div> | ||
| 471 | #end | ||
| |
82.1 | 472 | #if($orgChart && $orgChart != '')<div class="free-note">$!escapetool.xml($orgChart)</div>#end |
| |
50.1 | 473 | </div> |
| 474 | </div> | ||
| 475 | #else | ||
| |
81.1 | 476 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 生徒会組織は #if($visibilityOrgChart == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> |
| |
50.1 | 477 | #end |
| |
1.1 | 478 | #end |
| 479 | |||
| |
111.1 | 480 | ## --- 活動環境 --- |
| 481 | #set($hasActivityEnv = ($activityPlace && !$activityPlace.isEmpty()) || ($activityRoomEquipment && $activityRoomEquipment != '') || ($activityRoomImage && $activityRoomImage != '') || ($ictTools && !$ictTools.isEmpty()) || ($ictUsage && !$ictUsage.isEmpty())) | ||
| 482 | #if($hasActivityEnv) | ||
| 483 | #set($canViewAE = true) | ||
| 484 | #if($visibilityActivityEnv == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewAE = false) | ||
| 485 | #elseif($visibilityActivityEnv == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewAE = false) | ||
| 486 | #end | ||
| 487 | #if($canViewAE) | ||
| 488 | <div class="seitokai-subsection"> | ||
| 489 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg> 生徒会の活動環境 #if($visibilityActivityEnv != '' && $visibilityActivityEnv != 'public')<span class="visibility-badge visibility-${visibilityActivityEnv}">#if($visibilityActivityEnv == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> | ||
| 490 | <div class="seitokai-subsection-content"> | ||
| 491 | #if($activityPlace && !$activityPlace.isEmpty()) | ||
| 492 | <div class="info-row"> | ||
| 493 | <span class="info-label">普段の活動場所</span> | ||
| 494 | <span class="info-value"> | ||
| 495 | <div class="selection-display"> | ||
| |
119.1 | 496 | #foreach($apo in ["専用の生徒会室","他の部活・委員会と併用した教室","空き教室を活用","インターネット中心","その他"]) |
| 497 | #if($activityPlace.contains($apo)) | ||
| 498 | <span class="selection-item">$!escapetool.xml($apo)</span> | ||
| 499 | #else | ||
| 500 | <span class="selection-item selection-item-off">$!escapetool.xml($apo)</span> | ||
| 501 | #end | ||
| |
111.1 | 502 | #end |
| 503 | </div> | ||
| 504 | </span> | ||
| 505 | </div> | ||
| 506 | #end | ||
| 507 | #if($activityRoomEquipment && $activityRoomEquipment != '') | ||
| 508 | <div class="info-row"> | ||
| 509 | <span class="info-label">生徒会室の設備</span> | ||
| 510 | <span class="info-value free-text-value">$!escapetool.xml($activityRoomEquipment)</span> | ||
| 511 | </div> | ||
| 512 | #end | ||
| 513 | #if($activityRoomImage && $activityRoomImage != '') | ||
| 514 | <div class="info-row"> | ||
| 515 | <span class="info-label">活動場所の写真</span> | ||
| 516 | <span class="info-value"><div class="school-org-img-wrap"><img src="$doc.getAttachmentURL($activityRoomImage)" alt="活動場所の写真" class="org-chart-img" /></div></span> | ||
| 517 | </div> | ||
| 518 | #end | ||
| 519 | #if($ictTools && !$ictTools.isEmpty()) | ||
| 520 | <div class="info-row"> | ||
| 521 | <span class="info-label">利用しているICTツール</span> | ||
| 522 | <span class="info-value"> | ||
| 523 | #set($ictCatDisplay = [ | ||
| 524 | ["連絡ツール", ["メール","LINE","LINE WORKS","Discord","Slack","Microsoft Teams","Google Chat","InstagramのDM","XのDM","その他(連絡)"]], | ||
| 525 | ["ドキュメント作成・共有", ["Googleドキュメント","Googleスプレッドシート","Googleスライド","Googleドライブ","Word","Excel","PowerPoint","OneDrive","SharePoint","Notion","Pages","Numbers","Keynote","Dropbox","Box","その他(ドキュメント)"]], | ||
| 526 | ["タスク管理", ["Googleカレンダー","Google ToDoリスト","Trello","Asana","Excel等スプレッドシート","その他(タスク管理)"]], | ||
| 527 | ["ビデオ会議ツール", ["Zoom","Google Meet","その他(ビデオ会議)"]], | ||
| 528 | ["アンケート", ["Googleフォーム","Microsoft Forms","その他(アンケート)"]], | ||
| 529 | ["デザイン・クリエイティブ", ["Canva","各種Adobe","CapCut","LumaFusion","AviUtl","ibisPaint","その他(デザイン)"]], | ||
| 530 | ["その他", ["独自のWebシステム・自作アプリ"]] | ||
| 531 | ]) | ||
| 532 | #foreach($catD in $ictCatDisplay) | ||
| 533 | #set($catHasItems = false) | ||
| 534 | #foreach($t in $catD.get(1)) | ||
| 535 | #if($ictTools.contains($t)) #set($catHasItems = true) #end | ||
| 536 | #end | ||
| 537 | #if($catHasItems) | ||
| 538 | <div style="margin-bottom:6px"> | ||
| 539 | <span style="font-size:0.8em;font-weight:600;color:var(--text-mid)">$catD.get(0):</span> | ||
| 540 | <div class="selection-display" style="margin-top:2px"> | ||
| 541 | #foreach($t in $catD.get(1)) | ||
| 542 | #if($ictTools.contains($t)) | ||
| 543 | <span class="selection-item">$!escapetool.xml($t)</span> | ||
| 544 | #end | ||
| 545 | #end | ||
| 546 | </div> | ||
| 547 | </div> | ||
| 548 | #end | ||
| 549 | #end | ||
| 550 | </span> | ||
| 551 | </div> | ||
| 552 | #end | ||
| 553 | #if($ictUsage && !$ictUsage.isEmpty()) | ||
| 554 | <div class="info-row"> | ||
| 555 | <span class="info-label">ICT活用している場面</span> | ||
| 556 | <span class="info-value"> | ||
| 557 | <div class="selection-display"> | ||
| 558 | #foreach($iu in $ictUsage) | ||
| 559 | <span class="selection-item">$!escapetool.xml($iu.trim())</span> | ||
| 560 | #end | ||
| 561 | </div> | ||
| 562 | </span> | ||
| 563 | </div> | ||
| 564 | #end | ||
| 565 | </div> | ||
| 566 | </div> | ||
| 567 | #else | ||
| 568 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 活動環境情報は #if($visibilityActivityEnv == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> | ||
| 569 | #end | ||
| 570 | #end | ||
| 571 | |||
| 572 | ## --- 年間主要行事 --- | ||
| 573 | #set($months = [["4月", $eventApril], ["5月", $eventMay], ["6月", $eventJune], ["7月", $eventJuly], ["8月", $eventAugust], ["9月", $eventSeptember], ["10月", $eventOctober], ["11月", $eventNovember], ["12月", $eventDecember], ["1月", $eventJanuary], ["2月", $eventFebruary], ["3月", $eventMarch]]) | ||
| 574 | #set($hasAnyEvent = false) | ||
| 575 | #foreach($m in $months) | ||
| 576 | #if($m.get(1) && $m.get(1) != '') #set($hasAnyEvent = true) #end | ||
| 577 | #end | ||
| 578 | #if($hasAnyEvent) | ||
| 579 | #set($canViewAN = true) | ||
| 580 | #if($visibilityAnnualEvents == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewAN = false) | ||
| 581 | #elseif($visibilityAnnualEvents == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewAN = false) | ||
| 582 | #end | ||
| 583 | #if($canViewAN) | ||
| 584 | <div class="seitokai-subsection"> | ||
| 585 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg> 年間主要行事 #if($visibilityAnnualEvents != '' && $visibilityAnnualEvents != 'public')<span class="visibility-badge visibility-${visibilityAnnualEvents}">#if($visibilityAnnualEvents == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> | ||
| 586 | <div class="seitokai-subsection-content"> | ||
| 587 | <table class="wiki-table school-info-table" style="margin:0"> | ||
| 588 | #foreach($m in $months) | ||
| 589 | #if($m.get(1) && $m.get(1) != '') | ||
| 590 | <tr><td style="width:60px;font-weight:600;white-space:nowrap">$m.get(0)</td><td>$!escapetool.xml($m.get(1))</td></tr> | ||
| 591 | #end | ||
| 592 | #end | ||
| 593 | </table> | ||
| 594 | </div> | ||
| 595 | </div> | ||
| 596 | #else | ||
| 597 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 年間主要行事情報は #if($visibilityAnnualEvents == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> | ||
| 598 | #end | ||
| 599 | #end | ||
| 600 | |||
| |
50.1 | 601 | ## --- 日常の活動 --- |
| 602 | #if($dailyActivities && !$dailyActivities.isEmpty()) | ||
| |
97.1 | 603 | #set($canViewDA = true) |
| 604 | #if($visibilityDailyActivities == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewDA = false) | ||
| 605 | #elseif($visibilityDailyActivities == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewDA = false) | ||
| 606 | #end | ||
| 607 | #if($canViewDA) | ||
| |
50.1 | 608 | <div class="seitokai-subsection"> |
| |
97.1 | 609 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg> 日常の活動 #if($visibilityDailyActivities != '' && $visibilityDailyActivities != 'public')<span class="visibility-badge visibility-${visibilityDailyActivities}">#if($visibilityDailyActivities == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> |
| |
50.1 | 610 | <div class="seitokai-subsection-content"> |
| |
86.1 | 611 | <p class="activity-hint">活動時間が多い3つ</p> |
| |
119.1 | 612 | <div class="selection-display"> |
| 613 | #foreach($dao in ["文化祭","体育祭","生徒会企画","歓送迎会","その他学校行事","校則改正","選挙","総会","予算編成・会計活動","教員との連携","他校との連携","地域との連携","ボランティア","広報","引き継ぎ","DX","目安箱","委員会","学級・HRとの連携","アンケート","三者協議会等","企業との連携","保護者との連携","その他"]) | ||
| 614 | #if($dailyActivities.contains($dao)) | ||
| 615 | <span class="selection-item">$!escapetool.xml($dao)</span> | ||
| 616 | #else | ||
| 617 | <span class="selection-item selection-item-off">$!escapetool.xml($dao)</span> | ||
| 618 | #end | ||
| |
50.1 | 619 | #end |
| 620 | </div> | ||
| 621 | #if($dailyActivitiesNote && $dailyActivitiesNote.trim() != '') | ||
| 622 | <div class="free-note">$!escapetool.xml($dailyActivitiesNote)</div> | ||
| |
1.1 | 623 | #end |
| 624 | </div> | ||
| 625 | </div> | ||
| |
97.1 | 626 | #else |
| 627 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 日常の活動情報は #if($visibilityDailyActivities == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> | ||
| 628 | #end | ||
| |
50.1 | 629 | #end |
| |
1.1 | 630 | |
| |
50.1 | 631 | ## --- 定例活動 --- |
| 632 | #if($meetingFrequency && $meetingFrequency != '') | ||
| |
97.1 | 633 | #set($canViewMT = true) |
| 634 | #if($visibilityMeeting == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewMT = false) | ||
| 635 | #elseif($visibilityMeeting == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewMT = false) | ||
| 636 | #end | ||
| 637 | #if($canViewMT) | ||
| |
50.1 | 638 | <div class="seitokai-subsection"> |
| |
97.1 | 639 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg> 定例活動 #if($visibilityMeeting != '' && $visibilityMeeting != 'public')<span class="visibility-badge visibility-${visibilityMeeting}">#if($visibilityMeeting == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> |
| |
50.1 | 640 | <div class="seitokai-subsection-content"> |
| 641 | <div class="info-row"> | ||
| 642 | <span class="info-label">役員定例会の頻度</span> | ||
| 643 | <span class="info-value">$!escapetool.xml($!meetingFrequency)</span> | ||
| 644 | </div> | ||
| 645 | #if($regularActivitiesNote && $regularActivitiesNote.trim() != '') | ||
| 646 | <div class="free-note">$!escapetool.xml($regularActivitiesNote)</div> | ||
| 647 | #end | ||
| |
1.1 | 648 | </div> |
| 649 | </div> | ||
| |
97.1 | 650 | #else |
| 651 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 定例活動情報は #if($visibilityMeeting == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> | ||
| 652 | #end | ||
| |
50.1 | 653 | #end |
| |
1.1 | 654 | |
| |
111.1 | 655 | ## --- 生徒総会 --- |
| 656 | #set($hasAssembly = ($assemblyFormat && $assemblyFormat != '') || ($assemblyCount && $assemblyCount > 0) || ($assemblyAgenda && !$assemblyAgenda.isEmpty()) || ($assemblyTopics && !$assemblyTopics.isEmpty()) || ($assemblyNote && $assemblyNote != '')) | ||
| 657 | #if($hasAssembly) | ||
| 658 | #set($canViewAS = true) | ||
| 659 | #if($visibilityAssembly == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewAS = false) | ||
| 660 | #elseif($visibilityAssembly == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewAS = false) | ||
| |
1.1 | 661 | #end |
| |
111.1 | 662 | #if($canViewAS) |
| |
50.1 | 663 | <div class="seitokai-subsection"> |
| |
111.1 | 664 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg> 生徒総会 #if($visibilityAssembly != '' && $visibilityAssembly != 'public')<span class="visibility-badge visibility-${visibilityAssembly}">#if($visibilityAssembly == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> |
| |
50.1 | 665 | <div class="seitokai-subsection-content"> |
| |
111.1 | 666 | #if($assemblyFormat && $assemblyFormat != '') |
| |
50.1 | 667 | <div class="info-row"> |
| |
111.1 | 668 | <span class="info-label">開催方式</span> |
| |
119.1 | 669 | <span class="info-value"> |
| 670 | <div class="selection-display"> | ||
| 671 | #foreach($afo in ["全生徒の対面開催","オンラインと併用","完全オンライン開催","開催なし","その他"]) | ||
| 672 | #if($assemblyFormat == $afo) | ||
| 673 | <span class="selection-item">$!escapetool.xml($afo)</span> | ||
| 674 | #else | ||
| 675 | <span class="selection-item selection-item-off">$!escapetool.xml($afo)</span> | ||
| 676 | #end | ||
| 677 | #end | ||
| 678 | </div> | ||
| 679 | </span> | ||
| |
50.1 | 680 | </div> |
| 681 | #end | ||
| |
111.1 | 682 | #if($assemblyCount && $assemblyCount > 0) |
| |
50.1 | 683 | <div class="info-row"> |
| |
111.1 | 684 | <span class="info-label">開催回数(年)</span> |
| 685 | <span class="info-value">$!escapetool.xml($assemblyCount)回</span> | ||
| |
50.1 | 686 | </div> |
| 687 | #end | ||
| |
111.1 | 688 | #if($assemblyAgenda && !$assemblyAgenda.isEmpty()) |
| |
50.1 | 689 | <div class="info-row"> |
| |
111.1 | 690 | <span class="info-label">議案の集め方</span> |
| 691 | <span class="info-value"> | ||
| 692 | <div class="selection-display"> | ||
| |
119.1 | 693 | #foreach($aao in ["教員からの提案","執行部からの提案","クラスごとの討議","目安箱","アンケート","総会時の発議","その他"]) |
| 694 | #if($assemblyAgenda.contains($aao)) | ||
| 695 | <span class="selection-item">$!escapetool.xml($aao)</span> | ||
| 696 | #else | ||
| 697 | <span class="selection-item selection-item-off">$!escapetool.xml($aao)</span> | ||
| 698 | #end | ||
| |
111.1 | 699 | #end |
| 700 | </div> | ||
| 701 | </span> | ||
| |
50.1 | 702 | </div> |
| 703 | #end | ||
| |
111.1 | 704 | #if($assemblyTopics && !$assemblyTopics.isEmpty()) |
| |
50.1 | 705 | <div class="info-row"> |
| |
111.1 | 706 | <span class="info-label">扱う内容</span> |
| |
50.1 | 707 | <span class="info-value"> |
| 708 | <div class="selection-display"> | ||
| |
119.1 | 709 | #foreach($ato in ["生徒会決算案","生徒会予算案","会則/校則の改正","生徒会の活動方針","学校への要望事項","外部へのアピール(宣言の採択など)","その他"]) |
| 710 | #if($assemblyTopics.contains($ato)) | ||
| 711 | <span class="selection-item">$!escapetool.xml($ato)</span> | ||
| 712 | #else | ||
| 713 | <span class="selection-item selection-item-off">$!escapetool.xml($ato)</span> | ||
| 714 | #end | ||
| |
50.1 | 715 | #end |
| 716 | </div> | ||
| 717 | </span> | ||
| 718 | </div> | ||
| 719 | #end | ||
| |
111.1 | 720 | #if($assemblyNote && $assemblyNote != '') |
| 721 | <div class="info-row"> | ||
| 722 | <span class="info-label">自由記述</span> | ||
| 723 | <span class="info-value free-text-value">$!escapetool.xml($assemblyNote)</span> | ||
| 724 | </div> | ||
| |
50.1 | 725 | #end |
| |
1.1 | 726 | </div> |
| |
50.1 | 727 | </div> |
| 728 | #else | ||
| |
111.1 | 729 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 生徒総会情報は #if($visibilityAssembly == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> |
| |
1.1 | 730 | #end |
| 731 | #end | ||
| 732 | |||
| |
111.1 | 733 | ## --- 選挙 --- |
| 734 | #if($electionExists && $electionExists != '') | ||
| 735 | #set($canViewEL = true) | ||
| 736 | #if($visibilityElection == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewEL = false) | ||
| 737 | #elseif($visibilityElection == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewEL = false) | ||
| 738 | #end | ||
| 739 | #if($canViewEL) | ||
| 740 | <div class="seitokai-subsection"> | ||
| 741 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M7 13l3 3 7-7"/></svg> 選挙 #if($visibilityElection != '' && $visibilityElection != 'public')<span class="visibility-badge visibility-${visibilityElection}">#if($visibilityElection == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> | ||
| 742 | <div class="seitokai-subsection-content"> | ||
| 743 | <div class="info-row"> | ||
| 744 | <span class="info-label">役員選挙</span> | ||
| 745 | <span class="info-value">$!escapetool.xml($!electionExists)</span> | ||
| 746 | </div> | ||
| 747 | #if($electionType && $electionType != '') | ||
| 748 | <div class="info-row"> | ||
| 749 | <span class="info-label">直近の選挙方式</span> | ||
| 750 | <span class="info-value">$!escapetool.xml($!electionType)</span> | ||
| 751 | </div> | ||
| 752 | #end | ||
| 753 | #if($electionNote && $electionNote.trim() != '') | ||
| 754 | <div class="free-note">$!escapetool.xml($electionNote)</div> | ||
| 755 | #end | ||
| 756 | </div> | ||
| 757 | </div> | ||
| 758 | #else | ||
| 759 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 選挙情報は #if($visibilityElection == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> | ||
| 760 | #end | ||
| 761 | #end | ||
| 762 | |||
| |
90.1 | 763 | ## --- 校則・生徒会会則の見直し --- |
| |
50.1 | 764 | #if($ruleReviewStatus && $ruleReviewStatus != '') |
| 765 | #set($canViewRuleReview = true) | ||
| |
72.1 | 766 | #if($visibilityRuleReview == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewRuleReview = false) |
| 767 | #elseif($visibilityRuleReview == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewRuleReview = false) | ||
| |
50.1 | 768 | #end |
| 769 | #if($canViewRuleReview) | ||
| 770 | <div class="seitokai-subsection"> | ||
| |
90.1 | 771 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><path d="M16 4h2a2 2 0 012 2v12a2 2 0 01-2 2h-2"/><path d="M8 4H6a2 2 0 00-2 2v12a2 2 0 002 2h2"/><line x1="12" y1="4" x2="12" y2="8"/><line x1="12" y1="16" x2="12" y2="20"/><line x1="8" y1="8" x2="16" y2="8"/><line x1="8" y1="16" x2="16" y2="16"/></svg> 校則・生徒会会則の見直し #if($visibilityRuleReview != 'public')<span class="visibility-badge visibility-${visibilityRuleReview}">#if($visibilityRuleReview == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> |
| |
50.1 | 772 | <div class="seitokai-subsection-content"> |
| 773 | <div class="info-row"> | ||
| 774 | <span class="info-label">見直しの有無(3年以内)</span> | ||
| 775 | <span class="info-value"><span class="tag tag-primary tag-sm">$!escapetool.xml($!ruleReviewStatus)</span></span> | ||
| |
1.1 | 776 | </div> |
| |
91.1 | 777 | #if($ruleReviewStatus != '実施なし') |
| |
50.1 | 778 | #if($ruleReviewContent && !$ruleReviewContent.isEmpty()) |
| 779 | <div class="info-row"> | ||
| 780 | <span class="info-label">見直しの内容</span> | ||
| 781 | <span class="info-value"> | ||
| 782 | <div class="selection-display"> | ||
| |
119.1 | 783 | #foreach($rco in ["服飾規定(制服など)","持ち物規定","校則改正の仕組み","生徒会の仕組み","その他"]) |
| 784 | #if($ruleReviewContent.contains($rco)) | ||
| 785 | <span class="selection-item">$!escapetool.xml($rco)</span> | ||
| 786 | #else | ||
| 787 | <span class="selection-item selection-item-off">$!escapetool.xml($rco)</span> | ||
| 788 | #end | ||
| |
50.1 | 789 | #end |
| 790 | </div> | ||
| 791 | </span> | ||
| |
1.1 | 792 | </div> |
| |
50.1 | 793 | #end |
| 794 | #if($ruleReviewProposer && !$ruleReviewProposer.isEmpty()) | ||
| 795 | <div class="info-row"> | ||
| 796 | <span class="info-label">見直しの提案者</span> | ||
| 797 | <span class="info-value"> | ||
| 798 | <div class="selection-display"> | ||
| |
119.1 | 799 | #foreach($rpo in ["教員","生徒会役員","専門委員会","その他の生徒","その他"]) |
| 800 | #if($ruleReviewProposer.contains($rpo)) | ||
| 801 | <span class="selection-item">$!escapetool.xml($rpo)</span> | ||
| 802 | #else | ||
| 803 | <span class="selection-item selection-item-off">$!escapetool.xml($rpo)</span> | ||
| 804 | #end | ||
| |
50.1 | 805 | #end |
| 806 | </div> | ||
| 807 | </span> | ||
| |
1.1 | 808 | </div> |
| |
50.1 | 809 | #end |
| 810 | #if($ruleReviewImplementer && !$ruleReviewImplementer.isEmpty()) | ||
| 811 | <div class="info-row"> | ||
| 812 | <span class="info-label">見直しの実施者</span> | ||
| 813 | <span class="info-value"> | ||
| 814 | <div class="selection-display"> | ||
| |
119.1 | 815 | #foreach($rio in ["教員","生徒会役員","専門委員会","その他の生徒","その他"]) |
| 816 | #if($ruleReviewImplementer.contains($rio)) | ||
| 817 | <span class="selection-item">$!escapetool.xml($rio)</span> | ||
| 818 | #else | ||
| 819 | <span class="selection-item selection-item-off">$!escapetool.xml($rio)</span> | ||
| 820 | #end | ||
| |
50.1 | 821 | #end |
| 822 | </div> | ||
| 823 | </span> | ||
| 824 | </div> | ||
| 825 | #end | ||
| |
91.1 | 826 | #end |
| |
50.1 | 827 | #if($ruleReviewSystem && $ruleReviewSystem != '') |
| 828 | <div class="info-row"> | ||
| 829 | <span class="info-label">見直しの仕組み</span> | ||
| 830 | <span class="info-value">$!escapetool.xml($!ruleReviewSystem)</span> | ||
| 831 | </div> | ||
| 832 | #end | ||
| 833 | </div> | ||
| |
1.1 | 834 | </div> |
| |
50.1 | 835 | #else |
| |
90.1 | 836 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 校則・生徒会会則の見直し情報は #if($visibilityRuleReview == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> |
| |
50.1 | 837 | #end |
| |
1.1 | 838 | #end |
| |
50.1 | 839 | |
| |
111.1 | 840 | ## --- 予算 --- |
| 841 | #set($hasBudget = ($budgetProcess && !$budgetProcess.isEmpty()) || ($studentFee && $studentFee != '') || ($budgetScale && $budgetScale != '')) | ||
| 842 | #if($hasBudget) | ||
| 843 | #set($canViewBudget = true) | ||
| 844 | #if($visibilityBudget == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewBudget = false) | ||
| 845 | #elseif($visibilityBudget == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewBudget = false) | ||
| |
97.1 | 846 | #end |
| |
111.1 | 847 | #if($canViewBudget) |
| |
94.1 | 848 | <div class="seitokai-subsection"> |
| |
111.1 | 849 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/></svg> 予算 #if($visibilityBudget != 'public')<span class="visibility-badge visibility-${visibilityBudget}">#if($visibilityBudget == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> |
| |
94.1 | 850 | <div class="seitokai-subsection-content"> |
| |
111.1 | 851 | #if($budgetProcess && !$budgetProcess.isEmpty()) |
| |
94.1 | 852 | <div class="info-row"> |
| |
111.1 | 853 | <span class="info-label">作成過程の生徒関与</span> |
| |
95.1 | 854 | <span class="info-value"> |
| 855 | <div class="selection-display"> | ||
| |
111.1 | 856 | #set($allBpOpts = ["各部・委員会等への予算希望額調査","予算額調整(折衝等)","生徒会予算案の作成","生徒総会での議決","生徒関与なし","その他"]) |
| 857 | #foreach($bpOpt in $allBpOpts) | ||
| 858 | #if($budgetProcess.contains($bpOpt)) | ||
| 859 | <span class="selection-item">$!escapetool.xml($bpOpt)</span> | ||
| 860 | #else | ||
| 861 | <span class="selection-item selection-item-off">$!escapetool.xml($bpOpt)</span> | ||
| 862 | #end | ||
| |
95.1 | 863 | #end |
| 864 | </div> | ||
| 865 | </span> | ||
| |
94.1 | 866 | </div> |
| 867 | #end | ||
| |
111.1 | 868 | #if($studentFee && $studentFee != '') |
| |
94.1 | 869 | <div class="info-row"> |
| |
111.1 | 870 | <span class="info-label">生徒会費(年額)</span> |
| 871 | <span class="info-value">$!escapetool.xml($!studentFee)</span> | ||
| |
94.1 | 872 | </div> |
| 873 | #end | ||
| |
111.1 | 874 | #if($budgetScale && $budgetScale != '') |
| |
94.1 | 875 | <div class="info-row"> |
| |
111.1 | 876 | <span class="info-label">予算規模</span> |
| 877 | <span class="info-value">$!escapetool.xml($!budgetScale)</span> | ||
| |
94.1 | 878 | </div> |
| 879 | #end | ||
| |
111.1 | 880 | #if($budgetAllocation && !$budgetAllocation.isEmpty()) |
| |
98.1 | 881 | <div class="info-row"> |
| |
111.1 | 882 | <span class="info-label">主な予算配分</span> |
| |
98.1 | 883 | <span class="info-value"> |
| |
94.1 | 884 | <div class="selection-display"> |
| |
119.1 | 885 | #foreach($bao in ["行事費用","部活動","寄付","HR活動","執行部等","委員会活動","その他"]) |
| 886 | #if($budgetAllocation.contains($bao)) | ||
| 887 | <span class="selection-item">$!escapetool.xml($bao)</span> | ||
| 888 | #else | ||
| 889 | <span class="selection-item selection-item-off">$!escapetool.xml($bao)</span> | ||
| 890 | #end | ||
| |
94.1 | 891 | #end |
| 892 | </div> | ||
| 893 | </span> | ||
| 894 | </div> | ||
| 895 | #end | ||
| |
111.1 | 896 | #if($budgetNote && $budgetNote.trim() != '') |
| 897 | <div class="free-note">$!escapetool.xml($budgetNote)</div> | ||
| |
94.1 | 898 | #end |
| 899 | </div> | ||
| 900 | </div> | ||
| |
97.1 | 901 | #else |
| |
111.1 | 902 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 予算情報は #if($visibilityBudget == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> |
| |
97.1 | 903 | #end |
| |
94.1 | 904 | #end |
| 905 | |||
| 906 | ## --- 広報 --- | ||
| 907 | #set($hasPublicity = ($publicityMethod && !$publicityMethod.isEmpty()) || ($publicityFrequency && $publicityFrequency != '') || ($publicityNote && $publicityNote != '')) | ||
| 908 | #if($hasPublicity) | ||
| |
97.1 | 909 | #set($canViewPB = true) |
| 910 | #if($visibilityPublicity == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewPB = false) | ||
| 911 | #elseif($visibilityPublicity == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewPB = false) | ||
| 912 | #end | ||
| 913 | #if($canViewPB) | ||
| |
94.1 | 914 | <div class="seitokai-subsection"> |
| |
97.1 | 915 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg> 広報 #if($visibilityPublicity != '' && $visibilityPublicity != 'public')<span class="visibility-badge visibility-${visibilityPublicity}">#if($visibilityPublicity == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> |
| |
94.1 | 916 | <div class="seitokai-subsection-content"> |
| 917 | #if($publicityMethod && !$publicityMethod.isEmpty()) | ||
| 918 | <div class="info-row"> | ||
| 919 | <span class="info-label">方法</span> | ||
| 920 | <span class="info-value"> | ||
| 921 | <div class="selection-display"> | ||
| 922 | #foreach($pm in $publicityMethod) | ||
| 923 | <span class="selection-item">$!escapetool.xml($pm.trim())</span> | ||
| 924 | #end | ||
| 925 | </div> | ||
| 926 | </span> | ||
| 927 | </div> | ||
| 928 | #end | ||
| 929 | #if($publicityFrequency && $publicityFrequency != '') | ||
| 930 | <div class="info-row"> | ||
| 931 | <span class="info-label">頻度</span> | ||
| 932 | <span class="info-value"><span class="tag tag-primary tag-sm">$!escapetool.xml($publicityFrequency)</span></span> | ||
| 933 | </div> | ||
| 934 | #end | ||
| 935 | #if($publicityNote && $publicityNote != '') | ||
| 936 | <div class="info-row"> | ||
| 937 | <span class="info-label">自由記述</span> | ||
| 938 | <span class="info-value free-text-value">$!escapetool.xml($publicityNote)</span> | ||
| 939 | </div> | ||
| 940 | #end | ||
| 941 | </div> | ||
| 942 | </div> | ||
| |
97.1 | 943 | #else |
| 944 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 広報情報は #if($visibilityPublicity == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> | ||
| 945 | #end | ||
| |
94.1 | 946 | #end |
| 947 | |||
| 948 | ## --- 外部連携 --- | ||
| 949 | #set($hasExternal = ($externalCooperation && $externalCooperation != '') || ($externalOrgName && $externalOrgName != '') || ($socialParticipation && !$socialParticipation.isEmpty())) | ||
| 950 | #if($hasExternal) | ||
| |
97.1 | 951 | #set($canViewEX = true) |
| 952 | #if($visibilityExternal == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewEX = false) | ||
| 953 | #elseif($visibilityExternal == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewEX = false) | ||
| 954 | #end | ||
| 955 | #if($canViewEX) | ||
| |
94.1 | 956 | <div class="seitokai-subsection"> |
| |
97.1 | 957 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg> 外部連携 #if($visibilityExternal != '' && $visibilityExternal != 'public')<span class="visibility-badge visibility-${visibilityExternal}">#if($visibilityExternal == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> |
| |
94.1 | 958 | <div class="seitokai-subsection-content"> |
| 959 | #if($externalCooperation && $externalCooperation != '') | ||
| 960 | <div class="info-row"> | ||
| 961 | <span class="info-label">他校の生徒会との連携</span> | ||
| |
119.1 | 962 | <span class="info-value"> |
| 963 | <div class="selection-display"> | ||
| 964 | #foreach($eco in ["定期的な連盟等の会合への参加","自治体等が主催するイベントへの参加","個別学校との交流","なし","その他"]) | ||
| 965 | #if($externalCooperation == $eco) | ||
| 966 | <span class="selection-item">$!escapetool.xml($eco)</span> | ||
| 967 | #else | ||
| 968 | <span class="selection-item selection-item-off">$!escapetool.xml($eco)</span> | ||
| 969 | #end | ||
| 970 | #end | ||
| 971 | </div> | ||
| 972 | </span> | ||
| |
94.1 | 973 | </div> |
| 974 | #end | ||
| 975 | #if($externalOrgName && $externalOrgName != '') | ||
| 976 | <div class="info-row"> | ||
| 977 | <span class="info-label">参加している生徒会団体の名前</span> | ||
| 978 | <span class="info-value">$!escapetool.xml($externalOrgName)</span> | ||
| 979 | </div> | ||
| 980 | #end | ||
| 981 | #if($socialParticipation && !$socialParticipation.isEmpty()) | ||
| 982 | <div class="info-row"> | ||
| 983 | <span class="info-label">社会参加・地域連携・ボランティア</span> | ||
| 984 | <span class="info-value"> | ||
| 985 | <div class="selection-display"> | ||
| |
119.1 | 986 | #foreach($spo in ["三者協議会等","学校運営協議会等","町内会や商工会等との意見交換","企業や地域との商品開発","ゴミ拾い・地域清掃","募金","あいさつ運動","地域のお祭り・イベント等への協力・出展","その他"]) |
| 987 | #if($socialParticipation.contains($spo)) | ||
| 988 | <span class="selection-item">$!escapetool.xml($spo)</span> | ||
| 989 | #else | ||
| 990 | <span class="selection-item selection-item-off">$!escapetool.xml($spo)</span> | ||
| 991 | #end | ||
| |
94.1 | 992 | #end |
| 993 | </div> | ||
| 994 | </span> | ||
| 995 | </div> | ||
| 996 | #end | ||
| 997 | </div> | ||
| 998 | </div> | ||
| |
97.1 | 999 | #else |
| 1000 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 外部連携情報は #if($visibilityExternal == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> | ||
| 1001 | #end | ||
| |
94.1 | 1002 | #end |
| 1003 | |||
| |
50.1 | 1004 | ## --- 生徒会の課題意識 --- |
| 1005 | #if($challenges && $challenges != '') | ||
| 1006 | #set($canViewChallenges = true) | ||
| |
72.1 | 1007 | #if($visibilityChallenges == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewChallenges = false) |
| 1008 | #elseif($visibilityChallenges == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewChallenges = false) | ||
| |
50.1 | 1009 | #end |
| 1010 | #if($canViewChallenges) | ||
| 1011 | <div class="seitokai-subsection"> | ||
| |
85.1 | 1012 | <h3 class="seitokai-subsection-title"><svg class="ico" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg> 生徒会の課題意識 #if($visibilityChallenges != 'public')<span class="visibility-badge visibility-${visibilityChallenges}">#if($visibilityChallenges == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</span>#end</h3> |
| |
50.1 | 1013 | <div class="seitokai-subsection-content"> |
| 1014 | <div class="challenge-text">$!escapetool.xml($challenges)</div> | ||
| 1015 | </div> | ||
| |
1.1 | 1016 | </div> |
| |
50.1 | 1017 | #else |
| |
56.1 | 1018 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> 課題情報は #if($visibilityChallenges == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> |
| |
50.1 | 1019 | #end |
| |
1.1 | 1020 | #end |
| 1021 | |||
| |
50.1 | 1022 | </div>## seitokai-info-body 終了 |
| 1023 | </div>## card-seitokai-info 終了 | ||
| |
1.1 | 1024 | |
| |
53.1 | 1025 | ## --- ③ SNS・連絡先 --- |
| |
51.1 | 1026 | <div class="school-info-card collapsed" id="card-contact"> |
| |
53.1 | 1027 | <h2 role="button" tabindex="0" aria-expanded="false" onclick="toggleInfoCard('card-contact')" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();toggleInfoCard('card-contact')}"><span><svg class="ico ico-md" viewBox="0 0 24 24"><path d="M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07 19.5 19.5 0 01-6-6 19.79 19.79 0 01-3.07-8.67A2 2 0 014.11 2h3a2 2 0 012 1.72c.127.96.361 1.903.7 2.81a2 2 0 01-.45 2.11L8.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0122 16.92z"/></svg> SNS・連絡先</span><span class="collapse-toggle"><span class="collapse-label-open">たたむ</span><span class="collapse-label-closed">開く</span> <span class="collapse-arrow">▼</span></span></h2> |
| |
51.1 | 1028 | <table class="wiki-table school-info-table"> |
| 1029 | <tr><th>問い合わせ先</th><td>#if($contactInfo && $contactInfo != '')$!escapetool.xml($contactInfo)#else<span class="text-placeholder">未登録</span>#end</td></tr> | ||
| 1030 | <tr><th>生徒会Web</th><td>#if($seitokaiWebsite && $seitokaiWebsite != '')<a href="$!escapetool.xml($seitokaiWebsite)" target="_blank" rel="noopener"><svg class="ico" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></svg> $!escapetool.xml($seitokaiWebsite)</a>#else<span class="text-placeholder">未登録</span>#end</td></tr> | ||
| 1031 | <tr><th>X (Twitter)</th><td>#if($seitokaiTwitter && $seitokaiTwitter != '')<a href="https://x.com/$!escapetool.url($seitokaiTwitter)" target="_blank" rel="noopener">𝕏 @$!escapetool.xml($seitokaiTwitter)</a>#else<span class="text-placeholder">未登録</span>#end</td></tr> | ||
| 1032 | <tr><th>Instagram</th><td>#if($seitokaiInstagram && $seitokaiInstagram != '')<a href="https://instagram.com/$!escapetool.url($seitokaiInstagram)" target="_blank" rel="noopener"><svg class="ico" viewBox="0 0 24 24"><path d="M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z"/><circle cx="12" cy="13" r="4"/></svg> @$!escapetool.xml($seitokaiInstagram)</a>#else<span class="text-placeholder">未登録</span>#end</td></tr> | ||
| 1033 | <tr><th>YouTube</th><td>#if($seitokaiYoutube && $seitokaiYoutube != '')<a href="$!escapetool.xml($seitokaiYoutube)" target="_blank" rel="noopener"><svg class="ico" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> YouTubeチャンネル</a>#else<span class="text-placeholder">未登録</span>#end</td></tr> | ||
| 1034 | <tr><th>その他SNS</th><td>#if($seitokaiOtherSns && $seitokaiOtherSns != '')$!escapetool.xml($seitokaiOtherSns)#else<span class="text-placeholder">未登録</span>#end</td></tr> | ||
| 1035 | </table> | ||
| |
87.1 | 1036 | #set($infoEditDate = $!doc.getValue('lastInfoEditedDate')) |
| 1037 | #set($infoEditBy = $!doc.getValue('lastInfoEditedBy')) | ||
| 1038 | #if($infoEditDate && $infoEditDate != '') | ||
| 1039 | <div class="info-last-updated"><svg class="ico" viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></svg> 基本情報の最終更新: $!escapetool.xml($infoEditBy) — $!escapetool.xml($infoEditDate)</div> | ||
| 1040 | #end | ||
| |
51.1 | 1041 | </div> |
| 1042 | |||
| |
1.1 | 1043 | {{/html}} |
| 1044 | |||
| |
54.1 | 1045 | ---- |
| 1046 | |||
| |
1.1 | 1047 | ## --- ⑩ 活動報告一覧(スレッド型・年度タブ付き) --- |
| |
5.1 | 1048 | = 活動報告 = |
| |
1.1 | 1049 | |
| |
55.1 | 1050 | ## --- 年度タブ + 投稿者ステータス凡例 --- |
| |
1.1 | 1051 | {{html clean="false"}} |
| 1052 | |||
| 1053 | ## --- 年度タブ --- | ||
| 1054 | ## 全活動から年度一覧を収集 | ||
| 1055 | #set($activities = $doc.getObjects('SeitokaiCode.ActivityClass')) | ||
| 1056 | #set($allPosts = $doc.getObjects('SeitokaiCode.ActivityPostClass')) | ||
| 1057 | #set($fySet = []) | ||
| 1058 | #if($activities && $activities.size() > 0) | ||
| 1059 | #foreach($act in $activities) | ||
| 1060 | #set($aFY = $!act.getValue('fiscalYear')) | ||
| 1061 | #if($aFY && $aFY != '' && !$fySet.contains($aFY)) | ||
| 1062 | #set($discard = $fySet.add($aFY)) | ||
| 1063 | #end | ||
| 1064 | #end | ||
| 1065 | #end | ||
| 1066 | ## 現在の年度が含まれていなければ追加 | ||
| 1067 | #set($currentFYStr = $currentFiscalYear.toString()) | ||
| 1068 | #if(!$fySet.contains($currentFYStr)) | ||
| 1069 | #set($discard = $fySet.add($currentFYStr)) | ||
| 1070 | #end | ||
| 1071 | ## ソート(降順にしたいが Velocity にはないので JS で制御) | ||
| 1072 | |||
| |
55.1 | 1073 | <div class="activity-toolbar"> |
| 1074 | <div class="activity-fy-tabs"> | ||
| |
113.1 | 1075 | <button class="activity-fy-tab" onclick="switchActivityFY('$currentFYStr', this)">$currentFYStr 年度</button> |
| |
55.1 | 1076 | #foreach($fy in $fySet) |
| 1077 | #if($fy != $currentFYStr) | ||
| 1078 | <button class="activity-fy-tab" onclick="switchActivityFY('$fy', this)">$fy 年度</button> | ||
| 1079 | #end | ||
| |
1.1 | 1080 | #end |
| |
113.1 | 1081 | <button class="activity-fy-tab active" onclick="switchActivityFY('all', this)">全期間</button> |
| |
55.1 | 1082 | </div> |
| |
65.1 | 1083 | <div class="activity-toolbar-right"> |
| 1084 | <button class="btn-view-toggle" id="btnViewToggle" onclick="toggleCompactView()" title="タイトルのみ表示"> | ||
| 1085 | <svg class="ico-list" viewBox="0 0 24 24" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg> | ||
| 1086 | <svg class="ico-detail" viewBox="0 0 24 24" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg> | ||
| 1087 | <span class="toggle-label">一覧表示</span> | ||
| 1088 | </button> | ||
| 1089 | </div> | ||
| |
55.1 | 1090 | <div class="author-legend-wrapper"> |
| 1091 | <button class="author-legend-toggle" onclick="this.classList.toggle('open');this.nextElementSibling.classList.toggle('open')"><svg class="ico" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg> バッジの見方 <span class="chevron">▼</span></button> | ||
| 1092 | <div class="author-legend-body"> | ||
| 1093 | <div class="author-legend"> | ||
| 1094 | <span class="author-legend-title">投稿者の信頼度:</span> | ||
| |
69.1 | 1095 | <span class="author-legend-item"><span class="bar bar-admin"></span> 管理者 <span class="text-hint">— 運営スタッフ</span></span> |
| 1096 | <span class="author-legend-item"><span class="bar bar-verified"></span> 承認済み <span class="text-hint">— 本人確認済みのユーザー</span></span> | ||
| 1097 | <span class="author-legend-item"><span class="bar bar-referred"></span> 紹介 <span class="text-hint">— 承認済みユーザーからの紹介</span></span> | ||
| 1098 | <span class="author-legend-item"><span class="bar bar-general"></span> 一般 <span class="text-hint">— 一般登録ユーザー</span></span> | ||
| |
55.1 | 1099 | </div> |
| 1100 | <div class="author-legend"> | ||
| 1101 | <span class="author-legend-title">所属:</span> | ||
| |
69.1 | 1102 | <span class="author-legend-item"><span class="badge badge-school-internal-confirmed badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内(確認済)</span> <span class="text-hint">所属が確認されたこの学校のユーザー</span></span> |
| 1103 | <span class="author-legend-item"><span class="badge badge-school-internal badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内</span> <span class="text-hint">この学校に所属登録しているユーザー</span></span> | ||
| |
72.1 | 1104 | <span class="author-legend-item"><span class="badge badge-alumni badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M22 10l-10-5L2 10l10 5 10-5z"/><path d="M6 12v5c0 1.66 2.69 3 6 3s6-1.34 6-3v-5"/></svg> 卒業生</span> <span class="text-hint">この学校の卒業生</span></span> |
| |
69.1 | 1105 | <span class="author-legend-item"><span class="badge badge-school-external badge-sm"><svg class="ico" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></svg> 他校</span> <span class="text-hint">別の学校に所属しているユーザー</span></span> |
| 1106 | <span class="author-legend-item text-hint">※一般アカウントは所属バッジが表示されません</span> | ||
| |
55.1 | 1107 | </div> |
| 1108 | <div class="author-legend"> | ||
| 1109 | <span class="author-legend-title">役割:</span> | ||
| 1110 | <span class="author-legend-item"><span class="badge badge-role-student badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c0 2 4 3 6 3s6-1 6-3v-5"/></svg> 生徒</span></span> | ||
| |
69.1 | 1111 | <span class="author-legend-item"><span class="badge badge-role-officer badge-sm"><svg class="ico" viewBox="0 0 24 24"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg> 役員</span> <span class="text-hint">生徒会役員</span></span> |
| |
55.1 | 1112 | <span class="author-legend-item"><span class="badge badge-role-teacher badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> 教員</span></span> |
| 1113 | </div> | ||
| 1114 | </div> | ||
| 1115 | </div> | ||
| |
1.1 | 1116 | </div> |
| 1117 | |||
| 1118 | {{/html}} | ||
| 1119 | |||
| |
114.1 | 1120 | ## 活動を「年度降順 + 特色あり先頭」で並び替え |
| |
115.1 | 1121 | ## Step1: fySet から年度を降順ソート(Velocity ネイティブ実装) |
| |
114.1 | 1122 | #set($fyNums = []) |
| 1123 | #foreach($fy in $fySet) | ||
| 1124 | #if($fy && $fy != '' && $fy != 'unknown') | ||
| |
118.1 | 1125 | #set($fyInt = $mathtool.toInteger($fy)) |
| 1126 | #if($fyInt) | ||
| 1127 | #set($discard = $fyNums.add($fyInt)) | ||
| 1128 | #end | ||
| |
114.1 | 1129 | #end |
| 1130 | #end | ||
| |
115.1 | 1131 | ## 最大値を順番に取り出して降順リストを構築(最大20年度まで対応) |
| |
114.1 | 1132 | #set($fyDesc = []) |
| |
115.1 | 1133 | #set($fyRemaining = []) |
| 1134 | #foreach($fy in $fyNums) | ||
| 1135 | #set($discard = $fyRemaining.add($fy)) | ||
| |
114.1 | 1136 | #end |
| |
115.1 | 1137 | #foreach($dummy in [1..20]) |
| 1138 | #if($fyRemaining.isEmpty())#break#end | ||
| 1139 | #set($fyMax = $fyRemaining.get(0)) | ||
| 1140 | #foreach($fy in $fyRemaining) | ||
| 1141 | #if($fy > $fyMax)#set($fyMax = $fy)#end | ||
| 1142 | #end | ||
| 1143 | #set($discard = $fyDesc.add($fyMax)) | ||
| 1144 | #set($fyNextRem = []) | ||
| 1145 | #set($fyMaxRemoved = false) | ||
| 1146 | #foreach($fy in $fyRemaining) | ||
| 1147 | #if(!$fyMaxRemoved && $fy == $fyMax) | ||
| 1148 | #set($fyMaxRemoved = true) | ||
| 1149 | #else | ||
| 1150 | #set($discard = $fyNextRem.add($fy)) | ||
| 1151 | #end | ||
| 1152 | #end | ||
| 1153 | #set($fyRemaining = $fyNextRem) | ||
| |
114.1 | 1154 | #end |
| |
115.1 | 1155 | ## 年度未設定の活動は末尾に表示(fySetに'unknown'は入らないため無条件追加) |
| 1156 | #set($discard = $fyDesc.add('unknown')) | ||
| |
114.1 | 1157 | ## Step2: 年度降順で featured → normal の順にインデックスを収集 |
| 1158 | #set($orderedActivityIndices = []) | ||
| 1159 | #foreach($curFY in $fyDesc) | ||
| 1160 | ## 同年度の特色あり活動を先頭に | ||
| 1161 | #set($actIdx2 = 0) | ||
| |
1.1 | 1162 | #foreach($act in $activities) |
| |
114.1 | 1163 | #set($aFY2 = $!act.getValue('fiscalYear')) |
| 1164 | #if(!$aFY2 || $aFY2 == '') #set($aFY2 = 'unknown') #end | ||
| 1165 | #if($aFY2 == $curFY && $act.getValue('featured') == '1') | ||
| 1166 | #set($discard = $orderedActivityIndices.add($actIdx2)) | ||
| |
1.1 | 1167 | #end |
| |
114.1 | 1168 | #set($actIdx2 = $actIdx2 + 1) |
| |
1.1 | 1169 | #end |
| |
114.1 | 1170 | ## 同年度の通常活動 |
| 1171 | #set($actIdx2 = 0) | ||
| 1172 | #foreach($act in $activities) | ||
| 1173 | #set($aFY2 = $!act.getValue('fiscalYear')) | ||
| 1174 | #if(!$aFY2 || $aFY2 == '') #set($aFY2 = 'unknown') #end | ||
| 1175 | #if($aFY2 == $curFY && $act.getValue('featured') != '1') | ||
| 1176 | #set($discard = $orderedActivityIndices.add($actIdx2)) | ||
| 1177 | #end | ||
| 1178 | #set($actIdx2 = $actIdx2 + 1) | ||
| 1179 | #end | ||
| |
1.1 | 1180 | #end |
| 1181 | |||
| 1182 | #if($activities && $activities.size() > 0) | ||
| 1183 | #foreach($actIdx in $orderedActivityIndices) | ||
| 1184 | #set($activity = $activities.get($actIdx)) | ||
| 1185 | #set($actTitle = $activity.getValue('title')) | ||
| 1186 | #set($actCommittee = $activity.getValue('committee')) | ||
| 1187 | #set($actPeriod = $activity.getValue('period')) | ||
| 1188 | #set($actFY = $!activity.getValue('fiscalYear')) | ||
| 1189 | #set($actFeatured = $!activity.getValue('featured')) | ||
| 1190 | #if(!$actFY || $actFY == '') #set($actFY = 'unknown') #end | ||
| 1191 | ## この活動に紐づく投稿を収集(固定投稿を先頭に) | ||
| 1192 | #set($pinnedPosts = []) | ||
| 1193 | #set($normalPosts = []) | ||
| 1194 | #if($allPosts) | ||
| 1195 | #foreach($post in $allPosts) | ||
| 1196 | #if($post.getValue('activityIndex') == $actIdx) | ||
| 1197 | #set($isPinned = $!post.getValue('pinned')) | ||
| 1198 | #if($isPinned == '1') | ||
| 1199 | #set($discard = $pinnedPosts.add($post)) | ||
| 1200 | #else | ||
| 1201 | #set($discard = $normalPosts.add($post)) | ||
| 1202 | #end | ||
| 1203 | #end | ||
| 1204 | #end | ||
| 1205 | #end | ||
| 1206 | #set($threadPosts = []) | ||
| 1207 | #set($discard = $threadPosts.addAll($pinnedPosts)) | ||
| 1208 | #set($discard = $threadPosts.addAll($normalPosts)) | ||
| |
22.1 | 1209 | ## report/comment カウント |
| 1210 | #set($reportCount = 0) | ||
| 1211 | #set($commentCount = 0) | ||
| 1212 | #foreach($tp in $threadPosts) | ||
| 1213 | #set($tpType = $!tp.getValue('postType')) | ||
| 1214 | #if($tpType == 'comment') | ||
| 1215 | #set($commentCount = $commentCount + 1) | ||
| 1216 | #else | ||
| 1217 | #set($reportCount = $reportCount + 1) | ||
| 1218 | #end | ||
| 1219 | #end | ||
| |
1.1 | 1220 | |
| 1221 | {{html clean="false"}} | ||
| |
6.1 | 1222 | <div class="activity-thread" data-fiscal-year="$!escapetool.xml($actFY)"> |
| |
1.1 | 1223 | <div class="activity-thread-header"> |
| 1224 | <div class="activity-thread-title"> | ||
| |
79.1 | 1225 | <h3 #if($actFeatured == '1')class="featured-title"#end>#if($actFeatured == '1')<svg class="ico ico-fixed-14 ico-star-offset" viewBox="0 0 24 24" fill="currentColor" stroke="none"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg> #end$!escapetool.xml($!actTitle)</h3> |
| |
78.1 | 1226 | <div class="activity-meta-line"> |
| 1227 | <span class="activity-meta">$!escapetool.xml($!actCommittee) | $!escapetool.xml($!actPeriod) #if($actFY != 'unknown')| $!escapetool.xml($actFY)年度#end</span> | ||
| 1228 | #set($actTagsList = $activity.getValue('tags')) | ||
| 1229 | #if($actTagsList && !$actTagsList.isEmpty()) | ||
| 1230 | #foreach($tagItem in $actTagsList) | ||
| 1231 | #if($tagItem && $tagItem.trim() != '')<span class="activity-tag-badge">$escapetool.xml($tagItem)</span>#end | ||
| 1232 | #end | ||
| |
60.1 | 1233 | #end |
| |
78.1 | 1234 | </div> |
| |
1.1 | 1235 | </div> |
| |
80.1 | 1236 | <div class="thread-meta-right"> |
| |
22.1 | 1237 | <span class="thread-post-count">${reportCount}件の報告 ・ ${commentCount}件のコメント</span> |
| |
1.1 | 1238 | #if($viewerAccountType == 'admin' || $viewerAccountType == 'verified' || $viewerAccountType == 'referred') |
| 1239 | #if($actFeatured == '1') | ||
| |
7.1 | 1240 | <a href="$doc.getURL('view', "action=unfeature&actObj=${actIdx}&form_token=${services.csrf.getToken()}")" class="btn-featured-toggle btn-unfeature" title="特色ある活動の選定を解除"><svg class="ico ico-fixed-14" viewBox="0 0 24 24" fill="currentColor" stroke="none"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg> 特色解除</a> |
| |
1.1 | 1241 | #else |
| |
7.1 | 1242 | <a href="$doc.getURL('view', "action=feature&actObj=${actIdx}&form_token=${services.csrf.getToken()}")" class="btn-featured-toggle btn-feature" title="特色ある活動に選定(最大3件)"><svg class="ico ico-fixed-14" viewBox="0 0 24 24"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg> 特色設定</a> |
| |
1.1 | 1243 | #end |
| 1244 | #end | ||
| 1245 | </div> | ||
| 1246 | </div> | ||
| 1247 | |||
| |
22.1 | 1248 | ## --- 活動報告セクション --- |
| |
1.1 | 1249 | #foreach($post in $threadPosts) |
| |
22.1 | 1250 | #set($thisPostType = $!post.getValue('postType')) |
| 1251 | #if($thisPostType != 'comment') | ||
| |
1.1 | 1252 | #set($postContent = $post.getValue('content')) |
| 1253 | #set($postAuthor = $post.getValue('author')) | ||
| 1254 | #set($postAccountType = $!post.getValue('authorAccountType')) | ||
| 1255 | #set($postUserRole = $!post.getValue('authorUserRole')) | ||
| 1256 | #set($postGrade = $!post.getValue('authorGrade')) | ||
| 1257 | #set($postSchoolCode = $!post.getValue('authorSchoolCode')) | ||
| 1258 | #set($postDate = $post.getValue('createdDate')) | ||
| |
2.1 | 1259 | ## 論理削除チェック |
| 1260 | #set($postDeleted = $!post.getValue('deleted')) | ||
| 1261 | #if($postDeleted == 1 || $postDeleted == '1') | ||
| 1262 | #if($viewerAccountType == 'admin') | ||
| |
14.1 | 1263 | <div class="thread-post thread-post-deleted thread-post-admin-deleted"> |
| 1264 | <div class="thread-post-admin-deleted-content"> | ||
| |
7.1 | 1265 | <svg class="ico" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg> |
| |
2.1 | 1266 | <strong>投稿者により削除済み</strong>($!post.getValue('deletedAt')) |
| |
14.1 | 1267 | <div class="thread-post-restored-content">$!escapetool.xml($!postContent)</div> |
| |
2.1 | 1268 | </div> |
| 1269 | </div> | ||
| 1270 | #else | ||
| |
14.1 | 1271 | <div class="thread-post thread-post-deleted thread-post-user-deleted"> |
| 1272 | <div class="thread-post-user-deleted-content"> | ||
| |
7.1 | 1273 | <svg class="ico" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg> |
| |
2.1 | 1274 | この投稿は削除されました |
| 1275 | </div> | ||
| 1276 | </div> | ||
| 1277 | #end | ||
| 1278 | #else | ||
| |
1.1 | 1279 | ## 通報による非表示チェック |
| 1280 | #set($postHidden = $!post.getValue('hidden')) | ||
| 1281 | #if($postHidden == 1 || $postHidden == '1') | ||
| 1282 | #if($viewerAccountType == 'admin') | ||
| |
14.1 | 1283 | <div class="thread-post thread-post-admin-hidden"> |
| 1284 | <div class="thread-post-admin-hidden-content"> | ||
| |
7.1 | 1285 | <svg class="ico" viewBox="0 0 24 24"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg> |
| |
6.1 | 1286 | <strong>通報により非表示中</strong>(理由: $!escapetool.xml($!post.getValue('hiddenReason'))) |
| |
14.1 | 1287 | <div class="thread-post-restored-content">$!escapetool.xml($!postContent)</div> |
| |
1.1 | 1288 | </div> |
| 1289 | </div> | ||
| 1290 | #end | ||
| 1291 | #else | ||
| 1292 | ## 投稿の公開範囲チェック | ||
| 1293 | #set($postVis = $!post.getValue('visibility')) | ||
| 1294 | #if(!$postVis || $postVis == '') #set($postVis = 'public') #end | ||
| 1295 | #set($canViewPost = true) | ||
| |
72.1 | 1296 | #if($postVis == 'school' && ($isGuest || (!$isViewerAdmin && !$isSchoolMember))) #set($canViewPost = false) |
| 1297 | #elseif($postVis == 'school_trusted' && ($isGuest || (!$isViewerAdmin && ((!$isSchoolMember) || ($viewerAccountType != 'verified' && $viewerAccountType != 'referred'))))) #set($canViewPost = false) | ||
| |
1.1 | 1298 | #end |
| 1299 | #if(!$canViewPost) | ||
| 1300 | <div class="thread-post visibility-restricted-post"> | ||
| |
56.1 | 1301 | <div class="visibility-restricted-notice"><svg class="ico" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> この投稿は #if($postVis == 'school_trusted')校内の承認済み・紹介メンバー#else校内メンバー#end のみ閲覧可能です</div> |
| |
1.1 | 1302 | </div> |
| 1303 | #else | ||
| 1304 | ## 投稿者のアカウント種別に基づいたCSSクラス | ||
| 1305 | #set($postAuthorClass = 'author-general') | ||
| 1306 | #if($postAccountType == 'admin') | ||
| 1307 | #set($postAuthorClass = 'author-admin') | ||
| 1308 | #elseif($postAccountType == 'verified') | ||
| 1309 | #set($postAuthorClass = 'author-verified') | ||
| 1310 | #elseif($postAccountType == 'referred') | ||
| 1311 | #set($postAuthorClass = 'author-referred') | ||
| 1312 | #end | ||
| 1313 | |||
| 1314 | #set($isPinned = $!post.getValue('pinned')) | ||
| 1315 | <div class="thread-post $postAuthorClass #if($isPinned == '1')thread-post-pinned#end"> | ||
| 1316 | <div class="thread-post-sidebar"><div class="thread-post-bar"></div></div> | ||
| 1317 | <div class="thread-post-content"> | ||
| 1318 | <div class="thread-post-header"> | ||
| 1319 | #if($isPinned == '1') | ||
| |
7.1 | 1320 | <span class="pin-badge"><svg class="ico ico-fixed-14" viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M16 2l-4 4-2-1-5 5 3 3-6 6h4l4-4 3 3 5-5-1-2 4-4-5-5z"/></svg> 固定</span> |
| |
1.1 | 1321 | #end |
| 1322 | #set($postAuthorRef = $!post.getValue('authorRef')) | ||
| 1323 | <span class="thread-post-author"> | ||
| 1324 | #if($postAuthorRef && $postAuthorRef != '') | ||
| |
6.1 | 1325 | <a href="$xwiki.getURL('SeitokaiCode.UserProfile', 'view', "user=${escapetool.url($postAuthorRef)}")">$!escapetool.xml($!postAuthor)</a> |
| |
1.1 | 1326 | #else |
| |
6.1 | 1327 | $!escapetool.xml($!postAuthor) |
| |
1.1 | 1328 | #end |
| 1329 | </span> | ||
| 1330 | <span class="author-badge"> | ||
| 1331 | #if($postAccountType == 'admin') | ||
| |
14.1 | 1332 | <span class="badge badge-admin badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 管理者</span> |
| |
1.1 | 1333 | #elseif($postAccountType == 'verified') |
| |
14.1 | 1334 | <span class="badge badge-verified badge-sm"><svg class="ico" viewBox="0 0 24 24" stroke-width="2.5"><path d="M20 6L9 17l-5-5"/></svg> 承認済み</span> |
| |
1.1 | 1335 | #elseif($postAccountType == 'referred') |
| |
14.1 | 1336 | <span class="badge badge-referred badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71"/></svg> 紹介</span> |
| |
1.1 | 1337 | #else |
| |
14.1 | 1338 | <span class="badge badge-general badge-sm">一般</span> |
| |
1.1 | 1339 | #end |
| 1340 | ## 所属バッジ(投稿者の学校コードとページの学校コードを比較) | ||
| |
72.1 | 1341 | #set($postIsSchoolMatch = ($postSchoolCode == $schoolCode || ($affiliatedSchoolCode != '' && $postSchoolCode == $affiliatedSchoolCode))) |
| |
1.1 | 1342 | #if($postSchoolCode && $postSchoolCode != '' && $postAccountType != 'general') |
| |
72.1 | 1343 | #if($postUserRole == 'graduate' && $postIsSchoolMatch) |
| 1344 | <span class="badge badge-alumni badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M22 10l-10-5L2 10l10 5 10-5z"/><path d="M6 12v5c0 1.66 2.69 3 6 3s6-1.34 6-3v-5"/></svg> 卒業生</span> | ||
| 1345 | #elseif($postIsSchoolMatch && $postUserRole != 'graduate') | ||
| |
1.1 | 1346 | #if($postAccountType == 'verified' || $postAccountType == 'admin') |
| |
14.1 | 1347 | <span class="badge badge-school-internal-confirmed badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内(確認済)</span> |
| |
1.1 | 1348 | #else |
| |
14.1 | 1349 | <span class="badge badge-school-internal badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内</span> |
| |
1.1 | 1350 | #end |
| 1351 | #else | ||
| |
14.1 | 1352 | <span class="badge badge-school-external badge-sm"><svg class="ico" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></svg> 他校</span> |
| |
1.1 | 1353 | #end |
| 1354 | #end | ||
| 1355 | #if($postUserRole == 'student') | ||
| |
14.1 | 1356 | <span class="badge badge-role-student badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M22 10l-10-5L2 10l10 5 10-5z"/><path d="M6 12v5c0 1.66 2.69 3 6 3s6-1.34 6-3v-5"/></svg> 生徒</span> |
| |
2.1 | 1357 | #set($postIsOfficer = $!post.getValue('authorIsOfficer')) |
| 1358 | #if($postIsOfficer == 'true') | ||
| |
14.1 | 1359 | <span class="badge badge-role-officer badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg> 役員</span> |
| |
2.1 | 1360 | #end |
| |
1.1 | 1361 | #elseif($postUserRole == 'teacher') |
| |
14.1 | 1362 | <span class="badge badge-role-teacher badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 016.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/></svg> 教員</span> |
| |
1.1 | 1363 | #elseif($postUserRole == 'graduate') |
| |
14.1 | 1364 | <span class="badge badge-role-graduate badge-sm"><svg class="ico" viewBox="0 0 24 24"><path d="M22 10l-10-5L2 10l10 5 10-5z"/><path d="M6 12v5c0 1.66 2.69 3 6 3s6-1.34 6-3v-5"/></svg> 卒業生</span> |
| |
1.1 | 1365 | #end |
| 1366 | </span> | ||
| 1367 | <span class="thread-post-date">$!postDate</span> | ||
| |
2.1 | 1368 | #set($postEdited = $!post.getValue('edited')) |
| 1369 | #if($postEdited == 1 || $postEdited == '1') | ||
| 1370 | <span class="post-edited-label">(編集済み)</span> | ||
| 1371 | #end | ||
| |
76.1 | 1372 | #set($postAuthorRefH = $!post.getValue('authorRef')) |
| 1373 | #set($postObjNumH = $post.number) | ||
| 1374 | #if(!$isGuest && $xcontext.user != $postAuthorRefH) | ||
| 1375 | <button type="button" class="btn-post-report btn-post-report-header" onclick="openReportDialog(this, '${doc.fullName}', $postObjNumH, '${services.csrf.getToken()}')" title="この投稿を通報"> | ||
| 1376 | <svg class="ico ico-fixed-14" viewBox="0 0 24 24"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></svg> 通報 | ||
| 1377 | </button> | ||
| 1378 | #end | ||
| |
1.1 | 1379 | </div> |
| 1380 | <div class="thread-post-body"> | ||
| |
6.1 | 1381 | $!escapetool.xml($!postContent) |
| |
1.1 | 1382 | #set($postImages = $!post.getValue('images')) |
| 1383 | #if($postImages && $postImages.trim() != '') | ||
| 1384 | <div class="post-images"> | ||
| 1385 | #set($imageList = $postImages.trim().split("\n")) | ||
| 1386 | #set($imageCount = $imageList.size()) | ||
| 1387 | #if($imageCount > 4)#set($imageCount = 4)#end | ||
| 1388 | <div class="post-image-grid post-image-count-${imageCount}"> | ||
| 1389 | #foreach($imgFile in $imageList) | ||
| 1390 | #if($foreach.count <= 4) | ||
| 1391 | #set($imgName = $imgFile.trim()) | ||
| 1392 | #if($imgName != '') | ||
| 1393 | <div class="post-image-item"> | ||
| 1394 | <a href="$doc.getAttachmentURL($imgName)" target="_blank"> | ||
| |
6.1 | 1395 | <img src="$doc.getAttachmentURL($imgName)" alt="$!escapetool.xml($imgName)" loading="lazy"/> |
| |
1.1 | 1396 | </a> |
| 1397 | </div> | ||
| 1398 | #end | ||
| 1399 | #end | ||
| 1400 | #end | ||
| 1401 | </div> | ||
| 1402 | </div> | ||
| 1403 | #end | ||
| 1404 | ## ファイル添付の表示 | ||
| 1405 | #set($postFiles = $!post.getValue('files')) | ||
| 1406 | #if($postFiles && $postFiles.trim() != '') | ||
| 1407 | <div class="post-files"> | ||
| 1408 | #set($fileList = $postFiles.trim().split("\n")) | ||
| 1409 | #foreach($attachFile in $fileList) | ||
| 1410 | #if($foreach.count <= 2) | ||
| 1411 | #set($fName = $attachFile.trim()) | ||
| 1412 | #if($fName != '') | ||
| 1413 | #set($fLower = $fName.toLowerCase()) | ||
| 1414 | #set($fIcon = 'file') | ||
| 1415 | #set($fColor = '#64748b') | ||
| 1416 | #if($fLower.endsWith('.pdf'))#set($fIcon = 'pdf')#set($fColor = '#dc2626')#end | ||
| 1417 | #if($fLower.endsWith('.docx'))#set($fIcon = 'word')#set($fColor = '#2563eb')#end | ||
| 1418 | #if($fLower.endsWith('.xlsx'))#set($fIcon = 'excel')#set($fColor = '#16a34a')#end | ||
| 1419 | #if($fLower.endsWith('.pptx'))#set($fIcon = 'ppt')#set($fColor = '#ea580c')#end | ||
| 1420 | ## ファイル名からプレフィックス(file_YYYYMMDDHHMMSS_N_)を除去して表示 | ||
| 1421 | #set($displayName = $fName) | ||
| 1422 | #if($fName.matches('file_\d{14}_\d+_.*')) | ||
| 1423 | #set($displayName = $fName.replaceFirst('file_\d{14}_\d+_', '')) | ||
| 1424 | #end | ||
| 1425 | <div class="post-file-item"> | ||
| |
6.1 | 1426 | <a href="$doc.getAttachmentURL($fName)" target="_blank" download="$!escapetool.xml($displayName)"> |
| |
14.1 | 1427 | #if($fIcon == 'pdf')<svg class="ico ico-md" style="color:${fColor};" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><path d="M9 15v-2h1.5a1.5 1.5 0 010 3H9"/></svg> |
| 1428 | #elseif($fIcon == 'word')<svg class="ico ico-md" style="color:${fColor};" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><path d="M8 15l1.5-5 1.5 5 1.5-5 1.5 5"/></svg> | ||
| 1429 | #elseif($fIcon == 'excel')<svg class="ico ico-md" style="color:${fColor};" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="8" y1="13" x2="16" y2="13"/><line x1="8" y1="17" x2="16" y2="17"/><line x1="12" y1="13" x2="12" y2="17"/></svg> | ||
| 1430 | #elseif($fIcon == 'ppt')<svg class="ico ico-md" style="color:${fColor};" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><rect x="8" y="12" width="8" height="6" rx="1"/></svg> | ||
| 1431 | #else<svg class="ico ico-md" style="color:${fColor};" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/></svg> | ||
| |
1.1 | 1432 | #end |
| |
6.1 | 1433 | <span class="post-file-name">$!escapetool.xml($displayName)</span> |
| |
1.1 | 1434 | </a> |
| 1435 | </div> | ||
| 1436 | #end | ||
| 1437 | #end | ||
| 1438 | #end | ||
| 1439 | </div> | ||
| 1440 | #end | ||
| 1441 | </div> | ||
| 1442 | #if($postVis != 'public') | ||
| |
85.1 | 1443 | <div class="visibility-badge visibility-${postVis} post-action-mt">#if($postVis == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</div> |
| |
1.1 | 1444 | #end |
| |
108.1 | 1445 | ## いいねボタン |
| 1446 | #set($postLikeCount = $!post.getValue('likeCount')) | ||
| 1447 | #if(!$postLikeCount || $postLikeCount == '') #set($postLikeCount = 0) #end | ||
| 1448 | #set($postLikedBy = $!post.getValue('likedBy')) | ||
| 1449 | #set($isLikedByMe = false) | ||
| 1450 | #if($postLikedBy && $postLikedBy.contains($xcontext.user)) #set($isLikedByMe = true) #end | ||
| 1451 | <div class="post-like-row post-action-mt"> | ||
| 1452 | #if($xcontext.user != 'XWiki.XWikiGuest') | ||
| 1453 | <button type="button" class="btn-like #if($isLikedByMe)liked#end" data-page="$escapetool.xml($doc.fullName)" data-obj="$post.number" data-csrf="$services.csrf.getToken()" onclick="toggleLike(this)"> | ||
| 1454 | <svg class="ico ico-fixed-14" viewBox="0 0 24 24" #if($isLikedByMe)fill="currentColor" stroke="none"#end><path d="M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z"/></svg> | ||
| 1455 | <span class="like-count">$postLikeCount</span> | ||
| 1456 | </button> | ||
| 1457 | #else | ||
| 1458 | <span class="btn-like disabled"> | ||
| 1459 | <svg class="ico ico-fixed-14" viewBox="0 0 24 24"><path d="M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z"/></svg> | ||
| 1460 | <span class="like-count">$postLikeCount</span> | ||
| 1461 | </span> | ||
| 1462 | #end | ||
| 1463 | </div> | ||
| |
75.1 | 1464 | ## 固定/編集/削除/通報/非表示ボタン(横並び) |
| |
74.1 | 1465 | #set($postAuthorRef = $!post.getValue('authorRef')) |
| 1466 | #set($postObjNumED = $post.number) | ||
| 1467 | #set($showPinBtn = ($viewerAccountType == 'admin' || $viewerAccountType == 'verified')) | ||
| 1468 | #set($showEditDeleteBtn = ($xcontext.user == $postAuthorRef || $viewerAccountType == 'admin')) | ||
| |
75.1 | 1469 | #set($showHideBtn = ($viewerAccountType == 'admin')) |
| |
76.1 | 1470 | #if($showPinBtn || $showEditDeleteBtn || $showHideBtn) |
| |
74.1 | 1471 | <div class="post-edit-actions post-action-mt"> |
| 1472 | #if($showPinBtn) | ||
| 1473 | #set($postObjNum = $post.number) | ||
| |
1.1 | 1474 | #if($isPinned == '1') |
| 1475 | <a href="$doc.getURL('view', "action=unpin&postObj=${postObjNum}&form_token=${services.csrf.getToken()}")" class="btn-pin-toggle btn-unpin" title="固定を解除"> | ||
| |
7.1 | 1476 | <svg class="ico ico-fixed-14" viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M16 2l-4 4-2-1-5 5 3 3-6 6h4l4-4 3 3 5-5-1-2 4-4-5-5z"/></svg> 固定を解除 |
| |
1.1 | 1477 | </a> |
| 1478 | #else | ||
| 1479 | <a href="$doc.getURL('view', "action=pin&postObj=${postObjNum}&form_token=${services.csrf.getToken()}")" class="btn-pin-toggle btn-pin" title="この投稿を固定"> | ||
| |
7.1 | 1480 | <svg class="ico ico-fixed-14" viewBox="0 0 24 24"><path d="M16 2l-4 4-2-1-5 5 3 3-6 6h4l4-4 3 3 5-5-1-2 4-4-5-5z"/></svg> 固定する |
| |
1.1 | 1481 | </a> |
| 1482 | #end | ||
| |
74.1 | 1483 | #end |
| 1484 | #if($showEditDeleteBtn) | ||
| |
2.1 | 1485 | #if($xcontext.user == $postAuthorRef) |
| |
84.1 | 1486 | #set($editImages = $!post.getValue('images')) |
| 1487 | #set($editFiles = $!post.getValue('files')) | ||
| 1488 | <button type="button" class="btn-post-edit" data-school="${doc.fullName}" data-obj="$postObjNumED" data-content="$!escapetool.xml($!postContent)" data-images="$!escapetool.xml($!editImages)" data-files="$!escapetool.xml($!editFiles)" data-post-type="$!post.getValue('postType')" onclick="openEditPost(this)" title="この投稿を編集"> | ||
| |
7.1 | 1489 | <svg class="ico ico-fixed-14" viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></svg> 編集 |
| |
2.1 | 1490 | </button> |
| 1491 | #end | ||
| 1492 | <button type="button" class="btn-post-delete" onclick="confirmDeletePost('${doc.fullName}', $postObjNumED, '${services.csrf.getToken()}')" title="この投稿を削除"> | ||
| |
7.1 | 1493 | <svg class="ico ico-fixed-14" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg> 削除 |
| |
2.1 | 1494 | </button> |
| |
74.1 | 1495 | #end |
| |
75.1 | 1496 | #if($showHideBtn) |
| 1497 | <button type="button" class="btn-post-hide" onclick="openHideDialog(this, '${doc.fullName}', $postObjNumED, '${services.csrf.getToken()}')" title="この投稿を非表示にする"> | ||
| 1498 | <svg class="ico ico-fixed-14" viewBox="0 0 24 24"><path d="M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 11-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg> 非表示 | ||
| 1499 | </button> | ||
| 1500 | #end | ||
| |
2.1 | 1501 | </div> |
| 1502 | #end | ||
| |
1.1 | 1503 | </div> |
| 1504 | </div> | ||
| 1505 | #end## /canViewPost | ||
| 1506 | #end## /postHidden | ||
| |
2.1 | 1507 | #end## /postDeleted |
| |
22.1 | 1508 | #end## /postType != comment |
| 1509 | #end## /foreach reports | ||
| 1510 | |||
| 1511 | ## --- コメントセクション(折りたたみ) --- | ||
| 1512 | #if($commentCount > 0) | ||
| 1513 | <details class="thread-comments-section"> | ||
| 1514 | <summary class="thread-comments-toggle"> | ||
| 1515 | <svg class="ico" viewBox="0 0 24 24"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/></svg> ${commentCount}件のコメント | ||
| 1516 | </summary> | ||
| 1517 | #foreach($post in $threadPosts) | ||
| 1518 | #set($thisPostType = $!post.getValue('postType')) | ||
| 1519 | #if($thisPostType == 'comment') | ||
| 1520 | #set($postContent = $post.getValue('content')) | ||
| 1521 | #set($postAuthor = $post.getValue('author')) | ||
| 1522 | #set($postAccountType = $!post.getValue('authorAccountType')) | ||
| 1523 | #set($postDate = $post.getValue('createdDate')) | ||
| 1524 | #set($postDeleted = $!post.getValue('deleted')) | ||
| 1525 | #if($postDeleted == 1 || $postDeleted == '1') | ||
| 1526 | <div class="thread-comment thread-comment-deleted"> | ||
| 1527 | <span class="thread-comment-meta">このコメントは削除されました</span> | ||
| 1528 | </div> | ||
| 1529 | #else | ||
| 1530 | #set($postHidden = $!post.getValue('hidden')) | ||
| 1531 | #if($postHidden == 1 || $postHidden == '1') | ||
| 1532 | <div class="thread-comment thread-comment-hidden"> | ||
| 1533 | <span class="thread-comment-meta">このコメントは非表示にされました</span> | ||
| 1534 | </div> | ||
| 1535 | #else | ||
| 1536 | <div class="thread-comment"> | ||
| 1537 | <span class="thread-comment-author">$!escapetool.xml($postAuthor)</span> | ||
| 1538 | <span class="thread-comment-date">$!postDate</span> | ||
| 1539 | <div class="thread-comment-body">$!escapetool.xml($postContent)</div> | ||
| 1540 | </div> | ||
| 1541 | #end | ||
| 1542 | #end | ||
| 1543 | #end | ||
| 1544 | #end | ||
| 1545 | </details> | ||
| |
1.1 | 1546 | #end |
| 1547 | |||
| 1548 | #if($xcontext.user != "XWiki.XWikiGuest") | ||
| 1549 | <div class="thread-add-post"> | ||
| |
93.1 | 1550 | #if($isSchoolMember || $isAlumniOfSchool || $isViewerAdmin) |
| |
101.1 | 1551 | <a href="/bin/SeitokaiCode/ActivityPostForm?schoolPage=${doc.fullName}&activityIndex=${actIdx}&schoolCode=$!escapetool.url($schoolCode)&postType=report" class="btn-thread-add"> |
| |
1.1 | 1552 | + 活動報告を追加 |
| 1553 | </a> | ||
| |
77.1 | 1554 | #end |
| |
101.1 | 1555 | <a href="/bin/SeitokaiCode/ActivityPostForm?schoolPage=${doc.fullName}&activityIndex=${actIdx}&schoolCode=$!escapetool.url($schoolCode)&postType=comment" class="btn-thread-comment"> |
| |
7.1 | 1556 | <svg class="ico" viewBox="0 0 24 24"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/></svg> コメントを書く |
| |
1.1 | 1557 | </a> |
| 1558 | </div> | ||
| 1559 | #end | ||
| 1560 | </div> | ||
| 1561 | {{/html}} | ||
| 1562 | #end | ||
| 1563 | #else | ||
| 1564 | {{html clean="false"}} | ||
| 1565 | <div class="empty-state"> | ||
| |
14.1 | 1566 | <div class="empty-state-icon"><svg class="ico" viewBox="0 0 24 24" stroke-width="1.5"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg></div> |
| |
1.1 | 1567 | <div class="empty-state-title">活動報告はまだありません</div> |
| 1568 | <div class="empty-state-desc">この学校の活動を記録して、他校と共有しましょう。<br>「活動を追加」ボタンから最初の活動を作成できます。</div> | ||
| 1569 | </div> | ||
| 1570 | {{/html}} | ||
| 1571 | #end | ||
| 1572 | |||
| 1573 | ## --- 活動追加ボタン --- | ||
| 1574 | #if($xcontext.user != "XWiki.XWikiGuest") | ||
| 1575 | {{html clean="false"}} | ||
| 1576 | <div class="activity-add-section"> | ||
| |
101.1 | 1577 | <a href="/bin/SeitokaiCode/ActivityForm?schoolPage=${doc.fullName}&schoolCode=$!escapetool.url($schoolCode)" class="btn btn-primary btn-add-activity"> |
| |
7.1 | 1578 | <svg class="ico" viewBox="0 0 24 24" stroke-width="2.5"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> 活動を追加 |
| |
1.1 | 1579 | </a> |
| 1580 | </div> | ||
| 1581 | {{/html}} | ||
| 1582 | #end | ||
| 1583 | |||
| |
108.1 | 1584 | ## --- OGP / SNSシェア対応 --- |
| 1585 | #set($ogpTitle = "${schoolName} — 生徒会Wiki") | ||
| 1586 | #set($ogpDesc = "${schoolName}の生徒会活動情報。") | ||
| 1587 | #if($prefecture && $prefecture != '') #set($ogpDesc = "${ogpDesc}${prefecture}") #end | ||
| 1588 | #if($city && $city != '') #set($ogpDesc = "${ogpDesc}${city}。") #end | ||
| 1589 | #if($dailyActivities && $dailyActivities != '') #set($ogpDesc = "${ogpDesc} 主な活動: ${dailyActivities}") #end | ||
| 1590 | #set($ogpUrl = "https://${request.serverName}${doc.getURL()}") | ||
| 1591 | |||
| |
1.1 | 1592 | ## --- 年度タブ切り替え JavaScript --- |
| 1593 | {{html clean="false"}} | ||
| 1594 | <script> | ||
| |
108.1 | 1595 | // OGPメタタグ挿入 |
| 1596 | (function() { | ||
| 1597 | var ogp = { | ||
| 1598 | 'og:title': '$escapetool.javascript($ogpTitle)', | ||
| 1599 | 'og:description': '$escapetool.javascript($ogpDesc)', | ||
| 1600 | 'og:type': 'article', | ||
| 1601 | 'og:url': '$escapetool.javascript($ogpUrl)', | ||
| 1602 | 'og:site_name': '生徒会Wiki', | ||
| 1603 | 'twitter:card': 'summary' | ||
| 1604 | }; | ||
| 1605 | for (var p in ogp) { | ||
| 1606 | var meta = document.createElement('meta'); | ||
| 1607 | meta.setAttribute('property', p); | ||
| 1608 | meta.setAttribute('content', ogp[p]); | ||
| 1609 | document.head.appendChild(meta); | ||
| 1610 | } | ||
| 1611 | // twitter用 | ||
| 1612 | var tw = document.createElement('meta'); | ||
| 1613 | tw.setAttribute('name', 'twitter:card'); | ||
| 1614 | tw.setAttribute('content', 'summary'); | ||
| 1615 | document.head.appendChild(tw); | ||
| 1616 | })(); | ||
| |
65.1 | 1617 | // コンパクト表示(タイトルのみ)トグル |
| |
108.1 | 1618 | // いいねトグル |
| 1619 | function toggleLike(btn) { | ||
| 1620 | var page = btn.getAttribute('data-page'); | ||
| 1621 | var obj = btn.getAttribute('data-obj'); | ||
| 1622 | var csrf = btn.getAttribute('data-csrf'); | ||
| 1623 | btn.disabled = true; | ||
| 1624 | var fd = new FormData(); | ||
| 1625 | fd.append('page', page); | ||
| 1626 | fd.append('obj', obj); | ||
| 1627 | fd.append('form_token', csrf); | ||
| 1628 | fetch('/bin/SeitokaiCode/LikePost', { method: 'POST', body: fd }) | ||
| 1629 | .then(function(r) { return r.json(); }) | ||
| 1630 | .then(function(data) { | ||
| 1631 | btn.querySelector('.like-count').textContent = data.count; | ||
| 1632 | if (data.action === 'liked') { | ||
| 1633 | btn.classList.add('liked'); | ||
| 1634 | btn.querySelector('svg').setAttribute('fill', 'currentColor'); | ||
| 1635 | btn.querySelector('svg').setAttribute('stroke', 'none'); | ||
| 1636 | } else { | ||
| 1637 | btn.classList.remove('liked'); | ||
| 1638 | btn.querySelector('svg').removeAttribute('fill'); | ||
| 1639 | btn.querySelector('svg').setAttribute('stroke', 'currentColor'); | ||
| 1640 | } | ||
| 1641 | }) | ||
| 1642 | .catch(function() { alert('エラーが発生しました'); }) | ||
| 1643 | .finally(function() { btn.disabled = false; }); | ||
| 1644 | } | ||
| 1645 | |||
| |
65.1 | 1646 | function toggleCompactView() { |
| 1647 | var container = document.querySelector('.xwiki-content') || document.body; | ||
| 1648 | var isCompact = container.classList.toggle('activity-compact-view'); | ||
| 1649 | var btn = document.getElementById('btnViewToggle'); | ||
| 1650 | if (btn) { | ||
| 1651 | btn.querySelector('.toggle-label').textContent = isCompact ? '詳細表示' : '一覧表示'; | ||
| 1652 | btn.title = isCompact ? '詳細表示に戻す' : 'タイトルのみ表示'; | ||
| 1653 | } | ||
| 1654 | // コンパクトモードでは各スレッドヘッダーをクリックで個別展開可能にする | ||
| 1655 | document.querySelectorAll('.activity-thread').forEach(function(thread) { | ||
| 1656 | if (isCompact) { | ||
| 1657 | thread.classList.remove('compact-expanded'); | ||
| 1658 | } | ||
| 1659 | }); | ||
| 1660 | } | ||
| 1661 | |||
| 1662 | // コンパクトモードで個別スレッドを展開/折りたたみ | ||
| 1663 | function toggleThreadExpand(e) { | ||
| 1664 | var container = document.querySelector('.xwiki-content') || document.body; | ||
| 1665 | if (!container.classList.contains('activity-compact-view')) return; | ||
| 1666 | // リンクやボタンのクリックはスルー | ||
| 1667 | if (e.target.closest('a, button, .btn-featured-toggle')) return; | ||
| 1668 | var thread = e.target.closest('.activity-thread'); | ||
| 1669 | if (thread) { | ||
| 1670 | thread.classList.toggle('compact-expanded'); | ||
| 1671 | } | ||
| 1672 | } | ||
| 1673 | |||
| |
1.1 | 1674 | function switchActivityFY(fy, btn) { |
| 1675 | // タブのアクティブ状態を切り替え | ||
| 1676 | document.querySelectorAll('.activity-fy-tab').forEach(function(t) { t.classList.remove('active'); }); | ||
| 1677 | btn.classList.add('active'); | ||
| 1678 | // 活動スレッドの表示切り替え | ||
| 1679 | document.querySelectorAll('.activity-thread[data-fiscal-year]').forEach(function(thread) { | ||
| |
22.1 | 1680 | if (fy === 'all' || thread.getAttribute('data-fiscal-year') === fy) { |
| 1681 | thread.classList.remove('fy-hidden'); | ||
| |
1.1 | 1682 | } else { |
| |
22.1 | 1683 | thread.classList.add('fy-hidden'); |
| |
1.1 | 1684 | } |
| 1685 | }); | ||
| 1686 | } | ||
| |
35.1 | 1687 | // ページ読み込み時の初期化 |
| |
1.1 | 1688 | document.addEventListener('DOMContentLoaded', function() { |
| |
116.1 | 1689 | // 年度タブを降順にソート(「全期間」タブは先頭に固定) |
| |
71.1 | 1690 | var tabContainer = document.querySelector('.activity-fy-tabs'); |
| 1691 | if (tabContainer) { | ||
| 1692 | var tabs = Array.from(tabContainer.querySelectorAll('.activity-fy-tab')); | ||
| 1693 | var allTab = null; | ||
| 1694 | var fyTabs = []; | ||
| 1695 | tabs.forEach(function(t) { | ||
| 1696 | var onclickStr = t.getAttribute('onclick') || ''; | ||
| 1697 | if (onclickStr.indexOf("'all'") !== -1) { allTab = t; } | ||
| 1698 | else { fyTabs.push(t); } | ||
| 1699 | }); | ||
| 1700 | // 年度タブを数値の降順でソート | ||
| 1701 | fyTabs.sort(function(a, b) { | ||
| 1702 | var aYear = parseInt(a.textContent) || 0; | ||
| 1703 | var bYear = parseInt(b.textContent) || 0; | ||
| 1704 | return bYear - aYear; | ||
| 1705 | }); | ||
| |
116.1 | 1706 | // DOM再配置(全期間を先頭、年度タブを降順で続ける) |
| 1707 | if (allTab) { tabContainer.appendChild(allTab); } | ||
| |
71.1 | 1708 | fyTabs.forEach(function(t) { tabContainer.appendChild(t); }); |
| 1709 | } | ||
| |
113.1 | 1710 | // デフォルトで全期間を表示 |
| |
1.1 | 1711 | var defaultTab = document.querySelector('.activity-fy-tab.active'); |
| 1712 | if (defaultTab) { defaultTab.click(); } | ||
| 1713 | // 保存成功時のトースト通知 | ||
| 1714 | if (window.location.search.indexOf('saved=1') !== -1) { | ||
| 1715 | showToast('学校情報を保存しました', 'success'); | ||
| 1716 | // URLパラメータをクリーンアップ(リロード時に再表示されないよう) | ||
| 1717 | if (window.history.replaceState) { | ||
| 1718 | window.history.replaceState({}, document.title, window.location.pathname); | ||
| 1719 | } | ||
| 1720 | } | ||
| |
65.1 | 1721 | // コンパクトモード: スレッドヘッダークリックで個別展開 |
| 1722 | document.querySelectorAll('.activity-thread-header').forEach(function(header) { | ||
| 1723 | header.addEventListener('click', toggleThreadExpand); | ||
| 1724 | }); | ||
| |
68.1 | 1725 | // 長文投稿の折りたたみ初期化(max-height: 12em 超で省略) |
| |
57.1 | 1726 | document.querySelectorAll('.thread-post-body').forEach(function(body) { |
| |
68.1 | 1727 | // pre-wrapのまま高さを測定し、max-height(12em ≒ ~200px)を超える場合に折りたたむ |
| |
59.1 | 1728 | var fullH = body.scrollHeight; |
| |
68.1 | 1729 | // 12em を px に変換(font-size × line-height × 行数 の近似値ではなくCSSと同じ値を取得) |
| |
59.1 | 1730 | body.classList.add('truncated'); |
| |
68.1 | 1731 | var maxH = body.clientHeight; // max-height: 12em 適用後の高さ |
| |
59.1 | 1732 | body.classList.remove('truncated'); |
| |
68.1 | 1733 | if (fullH > maxH + 30) { |
| |
57.1 | 1734 | body.classList.add('truncated'); |
| 1735 | var btn = document.createElement('button'); | ||
| 1736 | btn.className = 'btn-read-more'; | ||
| |
58.1 | 1737 | btn.textContent = '広げて読む ▼'; |
| |
57.1 | 1738 | btn.addEventListener('click', function() { |
| 1739 | var isExpanded = body.classList.toggle('expanded'); | ||
| |
58.1 | 1740 | btn.textContent = isExpanded ? '折りたたむ ▲' : '広げて読む ▼'; |
| |
57.1 | 1741 | }); |
| 1742 | body.parentNode.insertBefore(btn, body.nextSibling); | ||
| 1743 | } | ||
| 1744 | }); | ||
| |
1.1 | 1745 | }); |
| 1746 | |||
| 1747 | // トースト通知表示 | ||
| 1748 | function showToast(message, type) { | ||
| 1749 | type = type || 'success'; | ||
| 1750 | var container = document.getElementById('toast-container'); | ||
| 1751 | if (!container) { | ||
| 1752 | container = document.createElement('div'); | ||
| 1753 | container.id = 'toast-container'; | ||
| 1754 | container.className = 'toast-container'; | ||
| 1755 | document.body.appendChild(container); | ||
| 1756 | } | ||
| 1757 | var icons = { | ||
| |
14.1 | 1758 | success: '<svg class="ico ico-md" viewBox="0 0 24 24" stroke-width="2.5"><path d="M20 6L9 17l-5-5"/></svg>', |
| 1759 | error: '<svg class="ico ico-md" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>' | ||
| |
1.1 | 1760 | }; |
| 1761 | var toast = document.createElement('div'); | ||
| 1762 | toast.className = 'toast toast-' + type; | ||
| |
106.1 | 1763 | var iconSvg = icons[type] || ''; |
| 1764 | if (iconSvg) { | ||
| 1765 | var iconSpan = document.createElement('span'); | ||
| 1766 | iconSpan.innerHTML = iconSvg; | ||
| 1767 | toast.appendChild(iconSpan); | ||
| 1768 | } | ||
| 1769 | var msgSpan = document.createElement('span'); | ||
| 1770 | msgSpan.textContent = message; | ||
| 1771 | toast.appendChild(msgSpan); | ||
| |
1.1 | 1772 | container.appendChild(toast); |
| 1773 | setTimeout(function() { toast.remove(); }, 3200); | ||
| 1774 | } | ||
| 1775 | |||
| 1776 | // 学校基本情報・連絡先の折りたたみトグル | ||
| 1777 | function toggleInfoCard(cardId) { | ||
| 1778 | var card = document.getElementById(cardId); | ||
| 1779 | if (!card) return; | ||
| 1780 | card.classList.toggle('collapsed'); | ||
| |
46.1 | 1781 | var isCollapsed = card.classList.contains('collapsed'); |
| 1782 | var h2 = card.querySelector('h2[role="button"]'); | ||
| 1783 | if (h2) h2.setAttribute('aria-expanded', !isCollapsed); | ||
| |
1.1 | 1784 | } |
| |
2.1 | 1785 | |
| 1786 | // 投稿の編集(インライン編集フォームを開く) | ||
| |
84.1 | 1787 | function openEditPost(btn) { |
| |
2.1 | 1788 | var postEl = btn.closest('.thread-post'); |
| 1789 | if (!postEl) return; | ||
| 1790 | var existing = postEl.querySelector('.post-edit-form'); | ||
| 1791 | if (existing) { existing.remove(); return; } | ||
| 1792 | var bodyEl = postEl.querySelector('.thread-post-body'); | ||
| 1793 | if (!bodyEl) return; | ||
| |
84.1 | 1794 | |
| 1795 | var schoolPage = btn.getAttribute('data-school'); | ||
| 1796 | var postObjNum = btn.getAttribute('data-obj'); | ||
| 1797 | var currentContent = btn.getAttribute('data-content') || ''; | ||
| 1798 | var currentImages = btn.getAttribute('data-images') || ''; | ||
| 1799 | var currentFiles = btn.getAttribute('data-files') || ''; | ||
| 1800 | var postType = btn.getAttribute('data-post-type') || 'report'; | ||
| 1801 | |||
| |
2.1 | 1802 | var form = document.createElement('div'); |
| 1803 | form.className = 'post-edit-form'; | ||
| |
84.1 | 1804 | form.setAttribute('data-school', schoolPage); |
| 1805 | form.setAttribute('data-obj', postObjNum); | ||
| 1806 | |||
| 1807 | var html = '<textarea id="editContent_' + postObjNum + '">' + currentContent.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>') + '</textarea>'; | ||
| 1808 | |||
| 1809 | // コメント以外は添付ファイル編集を表示 | ||
| |
106.1 | 1810 | function escAttr(s) { return s.replace(/&/g,'&').replace(/"/g,'"').replace(/'/g,''').replace(/</g,'<').replace(/>/g,'>'); } |
| |
84.1 | 1811 | if (postType !== 'comment') { |
| 1812 | // 既存画像 | ||
| 1813 | html += '<div class="edit-attachments">'; | ||
| 1814 | if (currentImages.trim()) { | ||
| 1815 | html += '<div class="edit-attach-section"><span class="edit-attach-label">画像</span>'; | ||
| 1816 | var imgs = currentImages.trim().split('\n'); | ||
| 1817 | for (var i = 0; i < imgs.length; i++) { | ||
| 1818 | var img = imgs[i].trim(); | ||
| 1819 | if (!img) continue; | ||
| |
106.1 | 1820 | html += '<div class="edit-attach-item" data-name="' + escAttr(img) + '">' + |
| |
84.1 | 1821 | '<img src="/xwiki/bin/download/' + schoolPage.replace(/\./g,'/') + '/' + encodeURIComponent(img) + '" class="edit-attach-thumb" />' + |
| 1822 | '<button type="button" class="edit-attach-remove" onclick="removeEditAttach(this)" title="削除">✕</button>' + | ||
| |
106.1 | 1823 | '<input type="hidden" name="keepImages" value="' + escAttr(img) + '" />' + |
| |
84.1 | 1824 | '</div>'; |
| 1825 | } | ||
| 1826 | html += '</div>'; | ||
| 1827 | } | ||
| 1828 | // 既存ファイル | ||
| 1829 | if (currentFiles.trim()) { | ||
| 1830 | html += '<div class="edit-attach-section"><span class="edit-attach-label">ファイル</span>'; | ||
| 1831 | var files = currentFiles.trim().split('\n'); | ||
| 1832 | for (var j = 0; j < files.length; j++) { | ||
| 1833 | var f = files[j].trim(); | ||
| 1834 | if (!f) continue; | ||
| 1835 | var displayName = f; | ||
| 1836 | if (/^file_\d{14}_\d+_/.test(f)) displayName = f.replace(/^file_\d{14}_\d+_/, ''); | ||
| |
106.1 | 1837 | html += '<div class="edit-attach-item" data-name="' + escAttr(f) + '">' + |
| 1838 | '<span class="edit-attach-fname">' + escAttr(displayName) + '</span>' + | ||
| |
84.1 | 1839 | '<button type="button" class="edit-attach-remove" onclick="removeEditAttach(this)" title="削除">✕</button>' + |
| |
106.1 | 1840 | '<input type="hidden" name="keepFiles" value="' + escAttr(f) + '" />' + |
| |
84.1 | 1841 | '</div>'; |
| 1842 | } | ||
| 1843 | html += '</div>'; | ||
| 1844 | } | ||
| 1845 | // 新規追加 | ||
| 1846 | html += '<div class="edit-attach-add">' + | ||
| 1847 | '<label class="form-label-sm">画像を追加(最大4枚まで)</label>' + | ||
| 1848 | '<input type="file" name="editNewImages" accept="image/*" multiple class="form-file-input-sm" />' + | ||
| 1849 | '<div class="form-hint">JPEG / PNG / GIF / WebP、各5MBまで</div>' + | ||
| 1850 | '<label class="form-label-sm" style="margin-top:8px;">ファイルを追加(最大2つまで)</label>' + | ||
| 1851 | '<input type="file" name="editNewFiles" accept=".pdf,.docx,.xlsx,.pptx" multiple class="form-file-input-sm" />' + | ||
| 1852 | '<div class="form-hint">PDF / Word / Excel / PowerPoint、各10MBまで</div>' + | ||
| 1853 | '</div>'; | ||
| 1854 | html += '</div>'; | ||
| 1855 | } | ||
| 1856 | |||
| 1857 | html += '<div class="post-edit-form-actions">' + | ||
| |
2.1 | 1858 | '<button type="button" class="btn-cancel-edit" onclick="this.closest(\'.post-edit-form\').remove()">キャンセル</button>' + |
| |
84.1 | 1859 | '<button type="button" class="btn-save" onclick="saveEditPost(this)">保存</button>' + |
| |
2.1 | 1860 | '</div>'; |
| |
84.1 | 1861 | |
| 1862 | form.innerHTML = html; | ||
| |
2.1 | 1863 | bodyEl.parentNode.insertBefore(form, bodyEl.nextSibling); |
| 1864 | form.querySelector('textarea').focus(); | ||
| 1865 | } | ||
| 1866 | |||
| |
84.1 | 1867 | function removeEditAttach(btn) { |
| 1868 | var item = btn.closest('.edit-attach-item'); | ||
| 1869 | if (item) item.remove(); | ||
| 1870 | } | ||
| 1871 | |||
| |
2.1 | 1872 | // 投稿の編集を保存 |
| |
84.1 | 1873 | function saveEditPost(btn) { |
| 1874 | var formEl = btn.closest('.post-edit-form'); | ||
| 1875 | if (!formEl) return; | ||
| 1876 | var schoolPage = formEl.getAttribute('data-school'); | ||
| 1877 | var postObjNum = formEl.getAttribute('data-obj'); | ||
| 1878 | var textarea = formEl.querySelector('textarea'); | ||
| |
2.1 | 1879 | if (!textarea) return; |
| 1880 | var newContent = textarea.value.trim(); | ||
| 1881 | if (!newContent) { alert('投稿内容を入力してください'); return; } | ||
| |
84.1 | 1882 | |
| |
2.1 | 1883 | var csrfEl = document.querySelector('input[name="form_token"]'); |
| 1884 | var csrfToken = csrfEl ? csrfEl.value : ''; | ||
| |
84.1 | 1885 | |
| 1886 | var fd = new FormData(); | ||
| 1887 | fd.append('schoolPage', schoolPage); | ||
| 1888 | fd.append('postObj', postObjNum); | ||
| 1889 | fd.append('newContent', newContent); | ||
| 1890 | fd.append('form_token', csrfToken); | ||
| 1891 | |||
| 1892 | // 残す画像・ファイル | ||
| 1893 | formEl.querySelectorAll('input[name="keepImages"]').forEach(function(el) { fd.append('keepImages', el.value); }); | ||
| 1894 | formEl.querySelectorAll('input[name="keepFiles"]').forEach(function(el) { fd.append('keepFiles', el.value); }); | ||
| 1895 | |||
| 1896 | // 新規画像 | ||
| 1897 | var newImgInput = formEl.querySelector('input[name="editNewImages"]'); | ||
| 1898 | if (newImgInput && newImgInput.files) { | ||
| 1899 | for (var i = 0; i < newImgInput.files.length; i++) { fd.append('editNewImages', newImgInput.files[i]); } | ||
| 1900 | } | ||
| 1901 | // 新規ファイル | ||
| 1902 | var newFileInput = formEl.querySelector('input[name="editNewFiles"]'); | ||
| 1903 | if (newFileInput && newFileInput.files) { | ||
| 1904 | for (var j = 0; j < newFileInput.files.length; j++) { fd.append('editNewFiles', newFileInput.files[j]); } | ||
| 1905 | } | ||
| 1906 | |||
| 1907 | btn.disabled = true; | ||
| 1908 | btn.textContent = '保存中...'; | ||
| 1909 | |||
| |
2.1 | 1910 | var xhr = new XMLHttpRequest(); |
| |
62.1 | 1911 | xhr.open('POST', '/bin/get/SeitokaiCode/EditPost?outputSyntax=plain', true); |
| |
2.1 | 1912 | xhr.onload = function() { |
| 1913 | try { | ||
| 1914 | var res = JSON.parse(xhr.responseText); | ||
| 1915 | if (res.success) { | ||
| 1916 | showToast('投稿を更新しました', 'success'); | ||
| 1917 | setTimeout(function() { location.reload(); }, 800); | ||
| 1918 | } else { | ||
| |
84.1 | 1919 | btn.disabled = false; btn.textContent = '保存'; |
| |
2.1 | 1920 | alert('編集に失敗しました: ' + (res.error || '')); |
| 1921 | } | ||
| |
84.1 | 1922 | } catch(e) { btn.disabled = false; btn.textContent = '保存'; alert('編集に失敗しました'); } |
| |
2.1 | 1923 | }; |
| |
84.1 | 1924 | xhr.onerror = function() { btn.disabled = false; btn.textContent = '保存'; alert('通信エラーが発生しました'); }; |
| 1925 | xhr.send(fd); | ||
| |
2.1 | 1926 | } |
| 1927 | |||
| 1928 | // 投稿の削除(確認ダイアログ付き) | ||
| 1929 | function confirmDeletePost(schoolPage, postObjNum, token) { | ||
| 1930 | if (!confirm('この投稿を削除しますか?\\n削除後は「この投稿は削除されました」と表示されます。')) return; | ||
| 1931 | var xhr = new XMLHttpRequest(); | ||
| |
62.1 | 1932 | xhr.open('POST', '/bin/get/SeitokaiCode/DeletePost?outputSyntax=plain', true); |
| |
42.1 | 1933 | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); |
| 1934 | var deletePostData = 'schoolPage=' + encodeURIComponent(schoolPage) + '&postObj=' + postObjNum + '&form_token=' + encodeURIComponent(token); | ||
| |
2.1 | 1935 | xhr.onload = function() { |
| 1936 | try { | ||
| 1937 | var res = JSON.parse(xhr.responseText); | ||
| 1938 | if (res.success) { | ||
| 1939 | showToast('投稿を削除しました', 'success'); | ||
| 1940 | setTimeout(function() { location.reload(); }, 800); | ||
| 1941 | } else { | ||
| 1942 | alert('削除に失敗しました: ' + (res.error || '')); | ||
| 1943 | } | ||
| 1944 | } catch(e) { alert('削除に失敗しました'); } | ||
| 1945 | }; | ||
| 1946 | xhr.onerror = function() { alert('通信エラーが発生しました'); }; | ||
| |
42.1 | 1947 | xhr.send(deletePostData); |
| |
2.1 | 1948 | } |
| |
75.1 | 1949 | |
| 1950 | /* --- 通報ダイアログ --- */ | ||
| 1951 | function openReportDialog(btn, targetPage, postObjNum, token) { | ||
| 1952 | if (document.getElementById('report-dialog-overlay')) return; | ||
| 1953 | var reasons = ['宣伝・スパム','不適切な内容','個人情報の露出','誹謗中傷','誤情報','その他']; | ||
| 1954 | var overlay = document.createElement('div'); | ||
| 1955 | overlay.id = 'report-dialog-overlay'; | ||
| 1956 | overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.5);z-index:9999;display:flex;align-items:center;justify-content:center;'; | ||
| 1957 | var dialog = document.createElement('div'); | ||
| 1958 | dialog.style.cssText = 'background:#fff;border-radius:12px;padding:24px;max-width:400px;width:90%;max-height:80vh;overflow-y:auto;'; | ||
| 1959 | var html = '<h3 style="margin:0 0 16px;font-size:1.1em;">投稿を通報</h3>'; | ||
| 1960 | html += '<p style="margin:0 0 12px;font-size:0.9em;color:#4b5563;">通報された投稿は管理者が確認するまで一時的に非表示になります。</p>'; | ||
| 1961 | html += '<label style="display:block;margin-bottom:8px;font-weight:600;font-size:0.9em;">通報理由</label>'; | ||
| 1962 | html += '<select id="report-reason" style="width:100%;padding:8px;border:1px solid #d1d5db;border-radius:8px;margin-bottom:12px;font-size:0.9em;">'; | ||
| 1963 | for (var i=0; i<reasons.length; i++) html += '<option value="'+reasons[i]+'">'+reasons[i]+'</option>'; | ||
| 1964 | html += '</select>'; | ||
| 1965 | html += '<label style="display:block;margin-bottom:8px;font-weight:600;font-size:0.9em;">補足コメント(任意)</label>'; | ||
| 1966 | html += '<textarea id="report-detail" rows="3" maxlength="500" style="width:100%;padding:8px;border:1px solid #d1d5db;border-radius:8px;resize:vertical;font-size:0.9em;box-sizing:border-box;" placeholder="具体的な内容があればご記入ください"></textarea>'; | ||
| 1967 | html += '<div style="display:flex;gap:8px;margin-top:16px;justify-content:flex-end;">'; | ||
| 1968 | html += '<button type="button" id="report-cancel-btn" style="padding:8px 16px;border:1px solid #d1d5db;border-radius:8px;background:#fff;cursor:pointer;">キャンセル</button>'; | ||
| 1969 | html += '<button type="button" id="report-submit-btn" style="padding:8px 16px;border:none;border-radius:8px;background:#dc2626;color:#fff;cursor:pointer;font-weight:600;">通報する</button>'; | ||
| 1970 | html += '</div>'; | ||
| 1971 | dialog.innerHTML = html; | ||
| 1972 | overlay.appendChild(dialog); | ||
| 1973 | document.body.appendChild(overlay); | ||
| 1974 | overlay.addEventListener('click', function(e) { if (e.target === overlay) overlay.remove(); }); | ||
| 1975 | document.getElementById('report-cancel-btn').addEventListener('click', function() { overlay.remove(); }); | ||
| 1976 | document.getElementById('report-submit-btn').addEventListener('click', function() { | ||
| 1977 | var reason = document.getElementById('report-reason').value; | ||
| 1978 | var detail = document.getElementById('report-detail').value; | ||
| 1979 | var submitBtn = document.getElementById('report-submit-btn'); | ||
| 1980 | submitBtn.disabled = true; submitBtn.textContent = '送信中...'; | ||
| 1981 | var xhr = new XMLHttpRequest(); | ||
| 1982 | xhr.open('POST', '/bin/get/SeitokaiCode/ReportAction?outputSyntax=plain', true); | ||
| 1983 | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); | ||
| 1984 | var data = 'targetPage=' + encodeURIComponent(targetPage) + '&targetPost=' + postObjNum + '&reason=' + encodeURIComponent(reason) + '&detail=' + encodeURIComponent(detail) + '&form_token=' + encodeURIComponent(token); | ||
| 1985 | xhr.onload = function() { | ||
| 1986 | overlay.remove(); | ||
| 1987 | showToast('通報を受け付けました', 'success'); | ||
| 1988 | setTimeout(function() { location.reload(); }, 1000); | ||
| 1989 | }; | ||
| 1990 | xhr.onerror = function() { overlay.remove(); alert('通信エラーが発生しました'); }; | ||
| 1991 | xhr.send(data); | ||
| 1992 | }); | ||
| 1993 | } | ||
| 1994 | |||
| 1995 | /* --- 非表示ダイアログ(管理者用) --- */ | ||
| 1996 | function openHideDialog(btn, targetPage, postObjNum, token) { | ||
| 1997 | if (document.getElementById('hide-dialog-overlay')) return; | ||
| 1998 | var overlay = document.createElement('div'); | ||
| 1999 | overlay.id = 'hide-dialog-overlay'; | ||
| 2000 | overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.5);z-index:9999;display:flex;align-items:center;justify-content:center;'; | ||
| 2001 | var dialog = document.createElement('div'); | ||
| 2002 | dialog.style.cssText = 'background:#fff;border-radius:12px;padding:24px;max-width:400px;width:90%;'; | ||
| 2003 | var html = '<h3 style="margin:0 0 16px;font-size:1.1em;">投稿を非表示にする</h3>'; | ||
| 2004 | html += '<label style="display:block;margin-bottom:8px;font-weight:600;font-size:0.9em;">非表示の理由</label>'; | ||
| 2005 | html += '<input type="text" id="hide-reason" style="width:100%;padding:8px;border:1px solid #d1d5db;border-radius:8px;margin-bottom:12px;font-size:0.9em;box-sizing:border-box;" placeholder="理由を入力" />'; | ||
| 2006 | html += '<div style="display:flex;gap:8px;margin-top:16px;justify-content:flex-end;">'; | ||
| 2007 | html += '<button type="button" id="hide-cancel-btn" style="padding:8px 16px;border:1px solid #d1d5db;border-radius:8px;background:#fff;cursor:pointer;">キャンセル</button>'; | ||
| 2008 | html += '<button type="button" id="hide-submit-btn" style="padding:8px 16px;border:none;border-radius:8px;background:#d97706;color:#fff;cursor:pointer;font-weight:600;">非表示にする</button>'; | ||
| 2009 | html += '<button type="button" id="hide-warn-btn" style="padding:8px 16px;border:none;border-radius:8px;background:#dc2626;color:#fff;cursor:pointer;font-weight:600;">非表示+警告</button>'; | ||
| 2010 | html += '</div>'; | ||
| 2011 | dialog.innerHTML = html; | ||
| 2012 | overlay.appendChild(dialog); | ||
| 2013 | document.body.appendChild(overlay); | ||
| 2014 | overlay.addEventListener('click', function(e) { if (e.target === overlay) overlay.remove(); }); | ||
| 2015 | document.getElementById('hide-cancel-btn').addEventListener('click', function() { overlay.remove(); }); | ||
| 2016 | function doHide(action) { | ||
| 2017 | var reason = document.getElementById('hide-reason').value || '管理者判断'; | ||
| 2018 | window.location.href = '/bin/view/SeitokaiCode/ModerationAction?action=' + action + '&targetPage=' + encodeURIComponent(targetPage) + '&targetPost=' + postObjNum + '&reason=' + encodeURIComponent(reason) + '&form_token=' + encodeURIComponent(token); | ||
| 2019 | } | ||
| 2020 | document.getElementById('hide-submit-btn').addEventListener('click', function() { doHide('hide'); }); | ||
| 2021 | document.getElementById('hide-warn-btn').addEventListener('click', function() { doHide('hide-warn'); }); | ||
| 2022 | } | ||
| |
1.1 | 2023 | </script> |
| 2024 | {{/html}} | ||
| 2025 | {{/velocity}} |