diff --git a/front_end/messages/cs.json b/front_end/messages/cs.json
index 2eccb229a1..450b590084 100644
--- a/front_end/messages/cs.json
+++ b/front_end/messages/cs.json
@@ -1784,5 +1784,6 @@
"switchToBotAccount": "Přepnout na účet bota",
"impersonationBannerText": "Momentálně si prohlížíte Metaculus jako váš bot.",
"stopImpersonating": "Přepnout zpět na můj účet",
+ "editedOnDate": "Upraveno dne {date}",
"othersCount": "Ostatní ({count})"
}
diff --git a/front_end/messages/en.json b/front_end/messages/en.json
index f834758161..cc8d4c170e 100644
--- a/front_end/messages/en.json
+++ b/front_end/messages/en.json
@@ -1034,6 +1034,7 @@
"CPIsHidden": "Community Prediction is hidden",
"createdByUserOnDate": "Created by {user} on {date}",
"edited": "edited",
+ "editedOnDate": "Edited on {date}",
"tournamentHidePostsToMainFeed": "Hide tournament posts in main feed",
"me": "me",
"forecastDisclaimer": "Based on {predictionCount} predictions by {forecasterCount} forecasters",
diff --git a/front_end/messages/es.json b/front_end/messages/es.json
index 8bcc58af75..d24ff1c26d 100644
--- a/front_end/messages/es.json
+++ b/front_end/messages/es.json
@@ -1784,5 +1784,6 @@
"switchToBotAccount": "Cambiar a cuenta de bot",
"impersonationBannerText": "Actualmente estás viendo Metaculus como tu bot.",
"stopImpersonating": "Volver a mi cuenta",
+ "editedOnDate": "Editado el {date}",
"othersCount": "Otros ({count})"
}
diff --git a/front_end/messages/pt.json b/front_end/messages/pt.json
index f63b14ef68..f642e603c9 100644
--- a/front_end/messages/pt.json
+++ b/front_end/messages/pt.json
@@ -1782,5 +1782,6 @@
"switchToBotAccount": "Mudar para Conta de Bot",
"impersonationBannerText": "Você está visualizando o Metaculus atualmente como seu bot.",
"stopImpersonating": "Voltar para minha conta",
+ "editedOnDate": "Editado em {date}",
"othersCount": "Outros ({count})"
}
diff --git a/front_end/messages/zh-TW.json b/front_end/messages/zh-TW.json
index 3f56e705ac..bfdca86cdd 100644
--- a/front_end/messages/zh-TW.json
+++ b/front_end/messages/zh-TW.json
@@ -1781,5 +1781,6 @@
"switchToBotAccount": "切換到機器人帳戶",
"impersonationBannerText": "您目前正在以您的機器人帳戶查看 Metaculus。",
"stopImpersonating": "切換回我的帳戶",
+ "editedOnDate": "編輯於 {date}",
"withdrawAfterPercentSetting2": "問題總生命周期後撤回"
}
diff --git a/front_end/messages/zh.json b/front_end/messages/zh.json
index ef1f8fb4b7..6b3fa1773a 100644
--- a/front_end/messages/zh.json
+++ b/front_end/messages/zh.json
@@ -1786,5 +1786,6 @@
"switchToBotAccount": "切换到机器人账户",
"impersonationBannerText": "您当前正在以机器人身份查看 Metaculus。",
"stopImpersonating": "切换回我的账户",
+ "editedOnDate": "编辑于 {date}",
"othersCount": "其他({count})"
}
diff --git a/front_end/src/app/(main)/notebooks/[id]/[[...slug]]/page_compotent.tsx b/front_end/src/app/(main)/notebooks/[id]/[[...slug]]/page_compotent.tsx
index 69785b1e98..b84121b0ff 100644
--- a/front_end/src/app/(main)/notebooks/[id]/[[...slug]]/page_compotent.tsx
+++ b/front_end/src/app/(main)/notebooks/[id]/[[...slug]]/page_compotent.tsx
@@ -100,13 +100,27 @@ const IndividualNotebookPage: FC<{
- {formatDate(locale, new Date(postData.published_at))}
-
-
-
- Edited on{" "}
- {formatDate(locale, new Date(postData.notebook.edited_at))}
+ {formatDate(
+ locale,
+ new Date(postData.published_at ?? postData.notebook.created_at)
+ )}
+ {postData.notebook.edited_at &&
+ (!postData.published_at ||
+ new Date(postData.published_at) <=
+ new Date(postData.notebook.edited_at)) && (
+ <>
+
+
+ {t("editedOnDate", {
+ date: formatDate(
+ locale,
+ new Date(postData.notebook.edited_at)
+ ),
+ })}
+
+ >
+ )}
{t("estimatedReadingTime", {
diff --git a/posts/models.py b/posts/models.py
index 2294ac677c..275f08a701 100644
--- a/posts/models.py
+++ b/posts/models.py
@@ -494,7 +494,10 @@ def get_queryset(self) -> PostQuerySet:
return super().get_queryset().defer("embedding_vector")
-class Notebook(TimeStampedModel, TranslatedModel): # type: ignore
+class Notebook(TranslatedModel):
+ created_at = models.DateTimeField(default=timezone.now, editable=False)
+ edited_at = models.DateTimeField(editable=False, null=True)
+
markdown = models.TextField()
image_url = models.ImageField(null=True, blank=True, upload_to="user_uploaded")
markdown_summary = models.TextField(blank=True, default="")
diff --git a/questions/services/common.py b/questions/services/common.py
index b9b3825dfd..8c10ec998f 100644
--- a/questions/services/common.py
+++ b/questions/services/common.py
@@ -224,13 +224,15 @@ def update_conditional(
def update_notebook(notebook: Notebook, **kwargs):
+ post = getattr(notebook, "post", None)
+
+ # We want to update edited at for approved notebooks only
+ if post and post.status == post.CurationStatus.APPROVED:
+ kwargs["edited_at"] = timezone.now()
+
notebook, _ = model_update(
instance=notebook,
- fields=[
- "markdown",
- "type",
- "image_url",
- ],
+ fields=["markdown", "type", "image_url", "edited_at"],
data=kwargs,
)