diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/DocumentationAbsences.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/DocumentationAbsences.vue
index ef97f2ddb73cd0eb5714e1a8818e97fb54fde67a..8dbe68847629ba81e0bca1da804c516de4562bf4 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/DocumentationAbsences.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/DocumentationAbsences.vue
@@ -15,6 +15,7 @@
 
       <lesson-notes class="span-2" v-bind="documentationPartProps" />
       <participation-list
+        v-if="documentation.canEditParticipationStatus"
         :include-present="false"
         class="participation-list"
         v-bind="documentationPartProps"
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue
index 0fb5b638c873bd3f20b16ea62ab438693c9f6c8a..1e9988be2a02b91eab0eceb0a11156ce31a39ce1 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue
@@ -14,6 +14,7 @@ import {
 } from "./participationStatus.graphql";
 import SlideIterator from "aleksis.core/components/generic/SlideIterator.vue";
 import PersonalNotes from "../personal_notes/PersonalNotes.vue";
+import PersonalNoteChip from "../personal_notes/PersonalNoteChip.vue";
 import ExtraMarkChip from "../../extra_marks/ExtraMarkChip.vue";
 import TardinessChip from "./TardinessChip.vue";
 import TardinessField from "./TardinessField.vue";
@@ -31,6 +32,7 @@ export default {
     AbsenceReasonGroupSelect,
     AbsenceReasonButtons,
     PersonalNotes,
+    PersonalNoteChip,
     LessonInformation,
     MessageBox,
     MobileFullscreenDialog,
@@ -255,18 +257,12 @@ export default {
               small
               :absence-reason="item.absenceReason"
             />
-            <v-chip
+            <personal-note-chip
               v-for="note in item.notesWithNote"
               :key="'text-note-note-overview-' + note.id"
+              :note="note"
               small
-            >
-              <v-avatar left>
-                <v-icon small>mdi-note-outline</v-icon>
-              </v-avatar>
-              <span class="text-truncate" style="max-width: 30ch">
-                {{ note.note }}
-              </span>
-            </v-chip>
+            />
             <extra-mark-chip
               v-for="note in item.notesWithExtraMark"
               :key="'extra-mark-note-overview-' + note.id"
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsTrigger.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsTrigger.vue
index f587b636aab2a5f63cd9386fb22f63f5a7981ea4..963367cbddb77174251a3b2deb21f65102e3c960 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsTrigger.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsTrigger.vue
@@ -57,6 +57,17 @@ export default {
       );
     },
   },
+  computed: {
+    showLabel() {
+      return !!this.labelKey || !this.canOpenParticipation;
+    },
+    innerLabelKey() {
+      if (this.documentation.futureNoticeParticipationStatus) {
+        return "alsijil.coursebook.notes.future";
+      }
+      return this.labelKey;
+    },
+  },
 };
 </script>
 
@@ -77,9 +88,9 @@ export default {
         v-on="on"
         @click="touchDocumentation"
       >
-        <v-icon :left="!!labelKey">mdi-account-edit-outline</v-icon>
-        <template v-if="labelKey">
-          {{ $t(labelKey) }}
+        <v-icon :left="showLabel">mdi-account-edit-outline</v-icon>
+        <template v-if="showLabel">
+          {{ $t(innerLabelKey) }}
         </template>
       </v-chip>
     </template>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/coursebook.graphql b/aleksis/apps/alsijil/frontend/components/coursebook/coursebook.graphql
index 2ea83d8e6a8687a16d871979592a7d231d363444..a49b73f149129fa86e131b804e027908c84f65db 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/coursebook.graphql
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/coursebook.graphql
@@ -112,6 +112,9 @@ query documentationsForCoursebook(
     canEdit
     futureNotice
     canDelete
+    futureNoticeParticipationStatus
+    canEditParticipationStatus
+    canViewParticipationStatus
   }
 }
 
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue
index 15f4b371783f02a3efc95f7099e52e27430f0331..1a70d655e00a3bc6c85f002d417497282387af7a 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue
@@ -100,6 +100,6 @@ export default {
   gap: 1em;
 }
 .vertical {
-  grid-template-columns: 1fr;
+  grid-template-columns: minmax(0, 1fr);
 }
 </style>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonNotes.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonNotes.vue
index b91abacfdaa8557c1c9349ef25dc52c669cb4f3b..a412d39deed9232c8668e60716a3825096394347 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonNotes.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonNotes.vue
@@ -1,96 +1,238 @@
 <script setup>
 import AbsenceReasonChip from "aleksis.apps.kolego/components/AbsenceReasonChip.vue";
 import ExtraMarkChip from "../../extra_marks/ExtraMarkChip.vue";
+import ExtraMarksNote from "../personal_notes/ExtraMarksNote.vue";
 import TardinessChip from "../absences/TardinessChip.vue";
+import PersonalNoteChip from "../personal_notes/PersonalNoteChip.vue";
+import TextNoteCard from "../personal_notes/TextNoteCard.vue";
 </script>
 
 <template>
-  <div
-    class="d-flex align-center justify-space-between justify-md-end flex-wrap gap"
-  >
-    <v-chip dense color="success" outlined v-if="total > 0">
-      {{ $t("alsijil.coursebook.present_number", { present, total }) }}
-    </v-chip>
-    <absence-reason-chip
-      v-for="[reasonId, participations] in Object.entries(absences)"
-      :key="'reason-' + reasonId"
-      :absence-reason="participations[0].absenceReason"
-      dense
+  <div>
+    <div
+      class="d-flex align-center justify-space-between justify-md-end flex-wrap gap"
+      v-if="compact || documentation.canViewParticipationStatus"
     >
-      <template #append>
-        <span
-          >:
-          <span>
-            {{
-              participations
-                .slice(0, 5)
-                .map((participation) => participation.person.firstName)
-                .join(", ")
-            }}
-          </span>
-          <span v-if="participations.length > 5">
-            <!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
-            +{{ participations.length - 5 }}
-            <!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
-          </span>
-        </span>
+      <v-chip
+        dense
+        color="success"
+        outlined
+        v-if="total > 0 && documentation.canViewParticipationStatus"
+      >
+        {{
+          $t("alsijil.coursebook.participations.present_number", {
+            present,
+            total,
+          })
+        }}
+      </v-chip>
+      <v-chip
+        dense
+        color="success"
+        outlined
+        @click="$emit('open')"
+        v-bind="dialogActivator.attrs"
+        v-on="dialogActivator.on"
+        v-else-if="
+          total == 1 &&
+          present == 1 &&
+          !documentation.canViewParticipationStatus
+        "
+      >
+        {{ $t("alsijil.coursebook.participations.present") }}
+      </v-chip>
+
+      <template v-if="documentation.canViewParticipationStatus">
+        <absence-reason-chip
+          v-for="[reasonId, participations] in Object.entries(absences)"
+          :key="'reason-' + reasonId"
+          :absence-reason="participations[0].absenceReason"
+          dense
+        >
+          <template #append>
+            <span
+              >:
+              <span>
+                {{
+                  participations
+                    .slice(0, 5)
+                    .map((participation) => participation.person.firstName)
+                    .join(", ")
+                }}
+              </span>
+              <span v-if="participations.length > 5">
+                <!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
+                +{{ participations.length - 5 }}
+                <!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
+              </span>
+            </span>
+          </template>
+        </absence-reason-chip>
+      </template>
+      <template v-else>
+        <absence-reason-chip
+          v-for="[reasonId, participations] in Object.entries(absences)"
+          :key="'reason-' + reasonId"
+          :absence-reason="participations[0].absenceReason"
+          dense
+          @click="$emit('open')"
+          v-bind="dialogActivator.attrs"
+          v-on="dialogActivator.on"
+        />
       </template>
-    </absence-reason-chip>
 
-    <extra-mark-chip
-      v-for="[markId, [mark, ...participations]] in Object.entries(
-        extraMarkChips,
-      )"
-      :key="'extra-mark-' + markId"
-      :extra-mark="mark"
-      dense
-    >
-      <template #append>
-        <span
-          >:
-          <span>
-            {{
-              participations
-                .slice(0, 5)
-                .map((participation) => participation.person.firstName)
-                .join(", ")
-            }}
-          </span>
-          <span v-if="participations.length > 5">
-            <!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
-            +{{ participations.length - 5 }}
-            <!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
-          </span>
-        </span>
+      <template v-if="documentation.canViewParticipationStatus">
+        <extra-mark-chip
+          v-for="[markId, [mark, ...participations]] in Object.entries(
+            extraMarkChips,
+          )"
+          :key="'extra-mark-' + markId"
+          :extra-mark="mark"
+          dense
+        >
+          <template #append>
+            <span
+              >:
+              <span>
+                {{
+                  participations
+                    .slice(0, 5)
+                    .map((participation) => participation.person.firstName)
+                    .join(", ")
+                }}
+              </span>
+              <span v-if="participations.length > 5">
+                <!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
+                +{{ participations.length - 5 }}
+                <!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
+              </span>
+            </span>
+          </template>
+        </extra-mark-chip>
+      </template>
+      <template v-else>
+        <extra-mark-chip
+          v-for="[markId, [mark, ...participations]] in Object.entries(
+            extraMarkChips,
+          )"
+          :key="'extra-mark-' + markId"
+          :extra-mark="mark"
+          dense
+          @click="$emit('open')"
+          v-bind="dialogActivator.attrs"
+          v-on="dialogActivator.on"
+        />
       </template>
-    </extra-mark-chip>
 
-    <tardiness-chip v-if="tardyParticipations.length > 0">
-      {{ $t("alsijil.personal_notes.late") }}
+      <template v-if="documentation.canViewParticipationStatus">
+        <tardiness-chip v-if="tardyParticipations.length > 0">
+          <template #default>
+            {{ $t("alsijil.personal_notes.late") }}
+          </template>
 
-      <template #append>
-        <span
-          >:
-          {{
-            tardyParticipations
-              .slice(0, 5)
-              .map((participation) => participation.person.firstName)
-              .join(", ")
-          }}
+          <template #append>
+            <span
+              >:
+              {{
+                tardyParticipations
+                  .slice(0, 5)
+                  .map((participation) => participation.person.firstName)
+                  .join(", ")
+              }}
+
+              <span v-if="tardyParticipations.length > 5">
+                <!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
+                +{{ tardyParticipations.length - 5 }}
+                <!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
+              </span>
+            </span>
+          </template>
+        </tardiness-chip>
+      </template>
+      <template v-else>
+        <tardiness-chip
+          v-if="tardyParticipations.length > 0"
+          :tardiness="
+            tardyParticipations.length == 1
+              ? tardyParticipations[0].tardiness
+              : undefined
+          "
+          @click="$emit('open')"
+          v-bind="dialogActivator.attrs"
+          v-on="dialogActivator.on"
+        />
+      </template>
 
-          <span v-if="tardyParticipations.length > 5">
-            <!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
-            +{{ tardyParticipations.length - 5 }}
-            <!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
-          </span>
-        </span>
+      <template v-if="!documentation.canViewParticipationStatus && total == 1">
+        <personal-note-chip
+          v-for="note in documentation?.participations[0]?.notesWithNote"
+          :key="'text-note-note-' + note.id"
+          :note="note"
+          @click="$emit('open')"
+          v-bind="dialogActivator.attrs"
+          v-on="dialogActivator.on"
+        />
       </template>
-    </tardiness-chip>
 
-    <manage-students-trigger
-      :label-key="total == 0 ? 'alsijil.coursebook.notes.show_list' : ''"
-      v-bind="documentationPartProps"
-    />
+      <manage-students-trigger
+        v-if="documentation.canEditParticipationStatus"
+        :label-key="manageStudentsLabelKey"
+        v-bind="documentationPartProps"
+      />
+    </div>
+
+    <!-- not compact -->
+    <div class="main-body" v-else>
+      <template
+        v-if="
+          tardyParticipations.length > 0 || Object.entries(absences).length > 0
+        "
+      >
+        <v-divider />
+        <div
+          class="d-flex align-center justify-space-between justify-md-end flex-wrap gap"
+        >
+          <tardiness-chip
+            v-if="tardyParticipations.length > 0"
+            :tardiness="
+              tardyParticipations.length == 1
+                ? tardyParticipations[0].tardiness
+                : undefined
+            "
+          />
+          <absence-reason-chip
+            v-for="[reasonId, participations] in Object.entries(absences)"
+            :key="'reason-' + reasonId"
+            :absence-reason="participations[0].absenceReason"
+            dense
+          />
+        </div>
+      </template>
+      <template v-if="total == 1">
+        <v-divider />
+        <extra-marks-note
+          v-bind="documentationPartProps"
+          :participation="documentation?.participations[0]"
+          :value="documentation?.participations[0].notesWithExtraMark"
+          :disabled="true"
+        />
+      </template>
+      <template
+        v-if="
+          total == 1 &&
+          documentation?.participations[0]?.notesWithNote.length > 0
+        "
+      >
+        <v-divider />
+        <div>
+          <text-note-card
+            v-for="note in documentation?.participations[0]?.notesWithNote"
+            :key="'text-note-note-' + note.id"
+            :note="note"
+          />
+        </div>
+      </template>
+    </div>
   </div>
 </template>
 
@@ -161,6 +303,12 @@ export default {
     tardyParticipations() {
       return this.documentation.participations.filter((p) => p.tardiness);
     },
+    manageStudentsLabelKey() {
+      if (this.total == 0) {
+        return "alsijil.coursebook.notes.show_list";
+      }
+      return "";
+    },
   },
 };
 </script>
@@ -169,4 +317,9 @@ export default {
 .gap {
   gap: 0.25em;
 }
+.main-body {
+  display: grid;
+  grid-template-columns: minmax(0, 1fr);
+  gap: 1em;
+}
 </style>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarkNoteCheckbox.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarkNoteCheckbox.vue
index 1f31f9ee1cf6c557ee2fe7b86134793629f9063f..e6985a1f854b9915d6effb282674b0ca9bd478f0 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarkNoteCheckbox.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarkNoteCheckbox.vue
@@ -88,7 +88,7 @@ export default {
     :label="value.name"
     :value="value.id"
     v-model="model"
-    :disabled="loading"
+    :disabled="$attrs?.disabled || loading"
     :true-value="true"
     :false-value="false"
   >
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarksNote.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarksNote.vue
index fd5f2c6d20597375e3f1e126cb7b78c7835adbbe..f6bed5bb8f03e7442aebad04ec01346eee801fbd 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarksNote.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/ExtraMarksNote.vue
@@ -20,7 +20,7 @@ export default {
     <extra-mark-note-checkbox
       v-for="extraMark in extraMarks"
       :key="'checkbox-extramark-' + extraMark.id"
-      v-bind="personalNoteRelatedProps"
+      v-bind="{ ...personalNoteRelatedProps, ...$attrs }"
       :value="extraMark"
       :personal-note="value.find((pn) => pn.extraMark.id === extraMark.id)"
     />
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNoteChip.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNoteChip.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5d7326894ecbd367b83ac08b385732d17e2a5310
--- /dev/null
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNoteChip.vue
@@ -0,0 +1,45 @@
+<script>
+export default {
+  name: "PersonalNoteChip",
+  props: {
+    note: {
+      type: Object,
+      required: true,
+    },
+    loading: {
+      type: Boolean,
+      required: false,
+      default: false,
+    },
+  },
+  extends: "v-chip",
+};
+</script>
+
+<template>
+  <v-tooltip bottom>
+    <template #activator="{ on, attrs }">
+      <v-chip
+        dense
+        outlined
+        v-bind="{ ...$attrs, ...attrs }"
+        v-on="{ ...$listeners, ...on }"
+      >
+        <v-avatar left>
+          <v-icon small>mdi-note-outline</v-icon>
+        </v-avatar>
+        <slot name="prepend" />
+        <slot>
+          <span class="text-truncate" style="max-width: 30ch">
+            {{ note.note }}
+          </span>
+        </slot>
+        <slot name="append" />
+        <v-avatar right v-if="loading">
+          <v-progress-circular indeterminate :size="16" :width="2" />
+        </v-avatar>
+      </v-chip>
+    </template>
+    <span v-text="note.note" />
+  </v-tooltip>
+</template>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNoteCard.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNoteCard.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f180603b7563f36f5ecd59bcce134d586bae0bda
--- /dev/null
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNoteCard.vue
@@ -0,0 +1,27 @@
+<template>
+  <v-card
+    outlined
+    dense
+    rounded="lg"
+    class="mb-2"
+    v-bind="$attrs"
+    v-on="$listeners"
+  >
+    <v-card-title class="text-subtitle-2 pb-1 font-weight-medium">
+      {{ $t("alsijil.personal_notes.card.title") }}
+    </v-card-title>
+    <v-card-text>{{ note.note || "–" }}</v-card-text>
+  </v-card>
+</template>
+
+<script>
+export default {
+  name: "TextNoteCard",
+  props: {
+    note: {
+      type: Object,
+      required: true,
+    },
+  },
+};
+</script>
diff --git a/aleksis/apps/alsijil/frontend/messages/en.json b/aleksis/apps/alsijil/frontend/messages/en.json
index 0d39f282a34715bfc115554003999f943b9ca547..706ffbea77429f694154d96390aab829148e35db 100644
--- a/aleksis/apps/alsijil/frontend/messages/en.json
+++ b/aleksis/apps/alsijil/frontend/messages/en.json
@@ -77,7 +77,8 @@
         }
       },
       "notes": {
-        "show_list": "List of participants"
+        "show_list": "List of participants",
+        "future": "Lesson is in the future"
       },
       "notices": {
         "future": "Editing this lesson isn't allowed as this lesson is in the future.",
@@ -100,9 +101,12 @@
           "field": "Edit subject"
         }
       },
-      "present_number": "{present}/{total} present",
       "no_data": "No lessons for the selected groups and courses in this period",
       "no_results": "No search results for {search}",
+      "participations": {
+        "present_number": "{present}/{total} present",
+        "present": "Present"
+      },
       "absences": {
         "action_for_selected": "Mark selected participant as: | Mark {count} selected participants as",
         "title": "Register absences",
@@ -119,6 +123,9 @@
       }
     },
     "personal_notes": {
+      "card": {
+        "title": "Personal note"
+      },
       "note": "Note",
       "create_personal_note": "Add another note",
       "tardiness": "Tardiness",
diff --git a/aleksis/apps/alsijil/models.py b/aleksis/apps/alsijil/models.py
index ed1da5ee7538b53ac64b5a9d152ce38f1425ebe7..5303a40e57e3bf7ac6bbeba98da2f6e206be6007 100644
--- a/aleksis/apps/alsijil/models.py
+++ b/aleksis/apps/alsijil/models.py
@@ -535,6 +535,7 @@ class Documentation(CalendarEvent):
         events: list,
         incomplete: Optional[bool] = False,
         absences_exist: Optional[bool] = False,
+        request: Optional[HttpRequest] = None,
     ) -> tuple:
         """Get all the documentations for the events.
         Create dummy documentations if none exist.
@@ -566,11 +567,22 @@ class Documentation(CalendarEvent):
 
             doc = next(existing_documentations_event, None)
             if doc:
-                if (incomplete and doc.topic) or (
-                    absences_exist
-                    and (
-                        not doc.participations.all()
-                        or not [d for d in doc.participations.all() if d.absence_reason]
+                if (
+                    (incomplete and doc.topic)
+                    or (
+                        not request.user.has_perm(
+                            "alsijil.edit_participation_status_for_documentation_rule", doc
+                        )
+                        and not doc.participations.filter(
+                            person__pk=request.user.person.pk, absence_reason__isnull=False
+                        ).exists()
+                    )
+                    or (
+                        absences_exist
+                        and (
+                            not doc.participations.all()
+                            or not [d for d in doc.participations.all() if d.absence_reason]
+                        )
                     )
                 ):
                     continue
@@ -609,6 +621,7 @@ class Documentation(CalendarEvent):
         start: datetime,
         end: datetime,
         incomplete: Optional[bool] = False,
+        request: Optional[HttpRequest] = None,
     ) -> tuple:
         """Get all the documentations for the person from start to end datetime.
         Create dummy documentations if none exist.
@@ -627,7 +640,7 @@ class Documentation(CalendarEvent):
             with_reference_object=True,
         )
 
-        return Documentation.get_documentations_for_events(start, end, events, incomplete)
+        return Documentation.get_documentations_for_events(start, end, events, incomplete, request)
 
     @classmethod
     def parse_dummy(
diff --git a/aleksis/apps/alsijil/rules.py b/aleksis/apps/alsijil/rules.py
index 8b8e15e7b0250c76651144190ea4153b4e5717df..171a0765737f8b68164af78b3823c96481eef044 100644
--- a/aleksis/apps/alsijil/rules.py
+++ b/aleksis/apps/alsijil/rules.py
@@ -431,11 +431,19 @@ add_perm(
     view_participation_status_for_documentation_predicate,
 )
 
-edit_participation_status_for_documentation_predicate = (
+edit_participation_status_for_documentation_with_time_range_predicate = (
     has_person
     & (has_global_perm("alsijil.change_participationstatus") | can_edit_participation_status)
     & is_in_allowed_time_range_for_participation_status
 )
+add_perm(
+    "alsijil.edit_participation_status_for_documentation_with_time_range_rule",
+    edit_participation_status_for_documentation_with_time_range_predicate,
+)
+
+edit_participation_status_for_documentation_predicate = has_person & (
+    has_global_perm("alsijil.change_participationstatus") | can_edit_participation_status
+)
 add_perm(
     "alsijil.edit_participation_status_for_documentation_rule",
     edit_participation_status_for_documentation_predicate,
diff --git a/aleksis/apps/alsijil/schema/__init__.py b/aleksis/apps/alsijil/schema/__init__.py
index 97ec4f187e036a246772b709c75942018fb1d4d9..ceb9bbd4bd9e1593f7dd19a21795dd5192ad2ee3 100644
--- a/aleksis/apps/alsijil/schema/__init__.py
+++ b/aleksis/apps/alsijil/schema/__init__.py
@@ -141,6 +141,7 @@ class Query(graphene.ObjectType):
             events,
             incomplete,
             absences_exist,
+            info.context,
         )
         return docs + dummies
 
@@ -218,6 +219,7 @@ class Query(graphene.ObjectType):
                 person,
                 start,
                 end,
+                info.context,
             )
 
             lessons_for_person.append(LessonsForPersonType(id=person, lessons=docs + dummies))
diff --git a/aleksis/apps/alsijil/schema/documentation.py b/aleksis/apps/alsijil/schema/documentation.py
index 4f6436297e9ecdb0cc93223bbe960286ca54fe9f..cdb2eaca122330f70bd75023a463f2dc1dc0e8e7 100644
--- a/aleksis/apps/alsijil/schema/documentation.py
+++ b/aleksis/apps/alsijil/schema/documentation.py
@@ -4,7 +4,14 @@ import graphene
 from graphene_django.types import DjangoObjectType
 from reversion import create_revision, set_comment, set_user
 
-from aleksis.apps.alsijil.util.predicates import can_edit_documentation, is_in_allowed_time_range
+from aleksis.apps.alsijil.util.predicates import (
+    can_edit_documentation,
+    is_in_allowed_time_range,
+    is_in_allowed_time_range_for_participation_status,
+)
+from aleksis.apps.alsijil.util.predicates import (
+    can_edit_participation_status as can_edit_participation_status_predicate,
+)
 from aleksis.apps.chronos.schema import LessonEventType
 from aleksis.apps.cursus.models import Subject
 from aleksis.apps.cursus.schema import CourseType, SubjectType
@@ -13,6 +20,7 @@ from aleksis.core.schema.base import (
     DjangoFilterMixin,
     PermissionsTypeMixin,
 )
+from aleksis.core.util.core_helpers import has_person
 
 from ..models import Documentation
 from .participation_status import ParticipationStatusType
@@ -46,6 +54,10 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp
     participations = graphene.List(ParticipationStatusType, required=False)
 
     future_notice = graphene.Boolean(required=False)
+    future_notice_participation_status = graphene.Boolean(required=False)
+
+    can_edit_participation_status = graphene.Boolean(required=False)
+    can_view_participation_status = graphene.Boolean(required=False)
 
     old_id = graphene.ID(required=False)
 
@@ -68,15 +80,36 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp
         )
 
     @staticmethod
-    def resolve_participations(root: Documentation, info, **kwargs):
-        if not info.context.user.has_perm(
+    def resolve_future_notice_participation_status(root: Documentation, info, **kwargs):
+        """Shows whether the user can edit all participation statuses based on the current time.
+
+        This checks whether the documentation is in the future.
+        """
+        return not is_in_allowed_time_range_for_participation_status(info.context.user, root)
+
+    @staticmethod
+    def resolve_can_edit_participation_status(root: Documentation, info, **kwargs):
+        """Shows whether the user can edit all participation statuses of the documentation"""
+        return can_edit_participation_status_predicate(info.context.user, root)
+
+    @staticmethod
+    def resolve_can_view_participation_status(root: Documentation, info, **kwargs):
+        """Shows whether the user can view all participation statuses of the documentation"""
+        return info.context.user.has_perm(
             "alsijil.view_participation_status_for_documentation_rule", root
-        ):
-            return []
+        )
 
+    @staticmethod
+    def resolve_participations(root: Documentation, info, **kwargs):
         # A dummy documentation will not have any participations
         if str(root.pk).startswith("DUMMY") or not hasattr(root, "participations"):
             return []
+        elif not info.context.user.has_perm(
+            "alsijil.view_participation_status_for_documentation_rule", root
+        ):
+            if has_person(info.context.user):
+                return root.participations.filter(person=info.context.user.person)
+            return []
         return root.participations.all()
 
 
@@ -147,7 +180,8 @@ class TouchDocumentationMutation(graphene.Mutation):
         )
 
         if not info.context.user.has_perm(
-            "alsijil.edit_participation_status_for_documentation_rule", documentation
+            "alsijil.edit_participation_status_for_documentation_with_time_range_rule",
+            documentation,
         ):
             raise PermissionDenied()
 
diff --git a/aleksis/apps/alsijil/schema/participation_status.py b/aleksis/apps/alsijil/schema/participation_status.py
index 2b9ebb25f37fabcc58415da613980d171114996d..fcf15df815619fcc808770116347458d8f7daf02 100644
--- a/aleksis/apps/alsijil/schema/participation_status.py
+++ b/aleksis/apps/alsijil/schema/participation_status.py
@@ -73,7 +73,8 @@ class ParticipationStatusBatchPatchMutation(BaseBatchPatchMutation):
     @classmethod
     def after_update_obj(cls, root, info, input, obj, full_input):  # noqa: A002
         if not info.context.user.has_perm(
-            "alsijil.edit_participation_status_for_documentation_rule", obj.related_documentation
+            "alsijil.edit_participation_status_for_documentation_with_time_range_rule",
+            obj.related_documentation,
         ):
             raise PermissionDenied()