Changes for page 学校ページ テンプレート
Last modified by Super Admin on 2026/04/05 18:59
From version 1.1
edited by Super Admin
on 2026/03/05 22:05
on 2026/03/05 22:05
Change comment:
There is no comment for this version
To version
3.1
edited by XWikiGuest
on 2026/03/06 00:39
on 2026/03/06 00:39
Change comment:
There is no comment for this version
Summary
Details
- Page properties
-
- Author
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki. superadmin1 +XWiki.XWikiGuest - Content
-
... ... @@ -228,6 +228,10 @@ 228 228 ## 役割バッジ 229 229 #if($authorUserRole == 'student') 230 230 <span class="badge badge-role-student"><svg class="ico" style="width:1em;height:1em;vertical-align:-0.125em;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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> 231 + #set($authorIsOfficer = $!lastAuthorDoc.getValue('isOfficer')) 232 + #if($authorIsOfficer == 'true') 233 + <span class="badge badge-role-officer"><svg class="ico" style="width:1em;height:1em;vertical-align:-0.125em;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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> 234 + #end 231 231 #elseif($authorUserRole == 'teacher') 232 232 <span class="badge badge-role-teacher"><svg class="ico" style="width:1em;height:1em;vertical-align:-0.125em;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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> 233 233 #elseif($authorUserRole == 'graduate') ... ... @@ -649,6 +649,26 @@ 649 649 #set($postGrade = $!post.getValue('authorGrade')) 650 650 #set($postSchoolCode = $!post.getValue('authorSchoolCode')) 651 651 #set($postDate = $post.getValue('createdDate')) 656 + ## 論理削除チェック 657 + #set($postDeleted = $!post.getValue('deleted')) 658 + #if($postDeleted == 1 || $postDeleted == '1') 659 + #if($viewerAccountType == 'admin') 660 + <div class="thread-post thread-post-deleted" style="opacity:0.5;border:2px dashed #9ca3af;"> 661 + <div style="padding:10px 16px;font-size:0.85em;color:var(--text-light);"> 662 + <svg class="ico" style="width:1em;height:1em;vertical-align:-0.125em;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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> 663 + <strong>投稿者により削除済み</strong>($!post.getValue('deletedAt')) 664 + <div style="margin-top:4px;font-size:0.92em;color:var(--text-mid);">$escapetool.xml($!postContent)</div> 665 + </div> 666 + </div> 667 + #else 668 + <div class="thread-post thread-post-deleted" style="opacity:0.6;"> 669 + <div style="padding:12px 16px;font-size:0.88em;color:var(--text-light);font-style:italic;"> 670 + <svg class="ico" style="width:1em;height:1em;vertical-align:-0.125em;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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> 671 + この投稿は削除されました 672 + </div> 673 + </div> 674 + #end 675 + #else 652 652 ## 通報による非表示チェック 653 653 #set($postHidden = $!post.getValue('hidden')) 654 654 #if($postHidden == 1 || $postHidden == '1') ... ... @@ -724,6 +724,10 @@ 724 724 #end 725 725 #if($postUserRole == 'student') 726 726 <span class="badge badge-role-student" style="font-size:0.75em;padding:1px 7px;"><svg class="ico" style="width:1em;height:1em;vertical-align:-0.125em;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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> 751 + #set($postIsOfficer = $!post.getValue('authorIsOfficer')) 752 + #if($postIsOfficer == 'true') 753 + <span class="badge badge-role-officer" style="font-size:0.75em;padding:1px 7px;"><svg class="ico" style="width:1em;height:1em;vertical-align:-0.125em;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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> 754 + #end 727 727 #elseif($postUserRole == 'teacher') 728 728 <span class="badge badge-role-teacher" style="font-size:0.75em;padding:1px 7px;"><svg class="ico" style="width:1em;height:1em;vertical-align:-0.125em;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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> 729 729 #elseif($postUserRole == 'graduate') ... ... @@ -734,6 +734,10 @@ 734 734 #end 735 735 </span> 736 736 <span class="thread-post-date">$!postDate</span> 765 + #set($postEdited = $!post.getValue('edited')) 766 + #if($postEdited == 1 || $postEdited == '1') 767 + <span class="post-edited-label">(編集済み)</span> 768 + #end 737 737 </div> 738 738 <div class="thread-post-body"> 739 739 $escapetool.xml($!postContent) ... ... @@ -815,10 +815,26 @@ 815 815 #end 816 816 </div> 817 817 #end 850 + ## 編集・削除ボタン(投稿者本人 or 管理者) 851 + #set($postAuthorRef = $!post.getValue('authorRef')) 852 + #set($postObjNumED = $post.number) 853 + #if($xcontext.user == $postAuthorRef || $viewerAccountType == 'admin') 854 + <div class="post-edit-actions" style="margin-top:6px;display:flex;gap:8px;"> 855 + #if($xcontext.user == $postAuthorRef) 856 + <button type="button" class="btn-post-edit" onclick="openEditPost(this, '${doc.fullName}', $postObjNumED, '$escapetool.javascript($!postContent)')" title="この投稿を編集"> 857 + <svg style="width:13px;height:13px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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> 編集 858 + </button> 859 + #end 860 + <button type="button" class="btn-post-delete" onclick="confirmDeletePost('${doc.fullName}', $postObjNumED, '${services.csrf.getToken()}')" title="この投稿を削除"> 861 + <svg style="width:13px;height:13px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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> 削除 862 + </button> 863 + </div> 864 + #end 818 818 </div> 819 819 </div> 820 820 #end## /canViewPost 821 821 #end## /postHidden 869 + #end## /postDeleted 822 822 #end 823 823 824 824 #if($xcontext.user != "XWiki.XWikiGuest") ... ... @@ -977,6 +977,71 @@ 977 977 card.classList.toggle('collapsed'); 978 978 card.classList.remove('mobile-collapse'); 979 979 } 1028 + 1029 +// 投稿の編集(インライン編集フォームを開く) 1030 +function openEditPost(btn, schoolPage, postObjNum, currentContent) { 1031 + var postEl = btn.closest('.thread-post'); 1032 + if (!postEl) return; 1033 + // 既存の編集フォームがあれば閉じる 1034 + var existing = postEl.querySelector('.post-edit-form'); 1035 + if (existing) { existing.remove(); return; } 1036 + var bodyEl = postEl.querySelector('.thread-post-body'); 1037 + if (!bodyEl) return; 1038 + var form = document.createElement('div'); 1039 + form.className = 'post-edit-form'; 1040 + form.innerHTML = '<textarea id="editContent_' + postObjNum + '">' + currentContent.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>') + '</textarea>' + 1041 + '<div class="post-edit-form-actions">' + 1042 + '<button type="button" class="btn-cancel-edit" onclick="this.closest(\'.post-edit-form\').remove()">キャンセル</button>' + 1043 + '<button type="button" class="btn-save" onclick="saveEditPost(\'' + schoolPage + '\', ' + postObjNum + ')">保存</button>' + 1044 + '</div>'; 1045 + bodyEl.parentNode.insertBefore(form, bodyEl.nextSibling); 1046 + form.querySelector('textarea').focus(); 1047 +} 1048 + 1049 +// 投稿の編集を保存 1050 +function saveEditPost(schoolPage, postObjNum) { 1051 + var textarea = document.getElementById('editContent_' + postObjNum); 1052 + if (!textarea) return; 1053 + var newContent = textarea.value.trim(); 1054 + if (!newContent) { alert('投稿内容を入力してください'); return; } 1055 + var csrfEl = document.querySelector('input[name="form_token"]'); 1056 + var csrfToken = csrfEl ? csrfEl.value : ''; 1057 + var xhr = new XMLHttpRequest(); 1058 + xhr.open('GET', '/xwiki/bin/view/SeitokaiCode/EditPost?outputSyntax=plain&schoolPage=' + encodeURIComponent(schoolPage) + '&postObj=' + postObjNum + '&newContent=' + encodeURIComponent(newContent) + '&form_token=' + encodeURIComponent(csrfToken), true); 1059 + xhr.onload = function() { 1060 + try { 1061 + var res = JSON.parse(xhr.responseText); 1062 + if (res.success) { 1063 + showToast('投稿を更新しました', 'success'); 1064 + setTimeout(function() { location.reload(); }, 800); 1065 + } else { 1066 + alert('編集に失敗しました: ' + (res.error || '')); 1067 + } 1068 + } catch(e) { alert('編集に失敗しました'); } 1069 + }; 1070 + xhr.onerror = function() { alert('通信エラーが発生しました'); }; 1071 + xhr.send(); 1072 +} 1073 + 1074 +// 投稿の削除(確認ダイアログ付き) 1075 +function confirmDeletePost(schoolPage, postObjNum, token) { 1076 + if (!confirm('この投稿を削除しますか?\\n削除後は「この投稿は削除されました」と表示されます。')) return; 1077 + var xhr = new XMLHttpRequest(); 1078 + xhr.open('GET', '/xwiki/bin/view/SeitokaiCode/DeletePost?outputSyntax=plain&schoolPage=' + encodeURIComponent(schoolPage) + '&postObj=' + postObjNum + '&form_token=' + encodeURIComponent(token), true); 1079 + xhr.onload = function() { 1080 + try { 1081 + var res = JSON.parse(xhr.responseText); 1082 + if (res.success) { 1083 + showToast('投稿を削除しました', 'success'); 1084 + setTimeout(function() { location.reload(); }, 800); 1085 + } else { 1086 + alert('削除に失敗しました: ' + (res.error || '')); 1087 + } 1088 + } catch(e) { alert('削除に失敗しました'); } 1089 + }; 1090 + xhr.onerror = function() { alert('通信エラーが発生しました'); }; 1091 + xhr.send(); 1092 +} 980 980 </script> 981 981 {{/html}} 982 982 {{/velocity}}