Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions public_discourse_sandbox/pds_app/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from .models import UserProfile
from .models import Vote
from .utils import send_notification_to_user
from .views import format_date


@login_required
Expand Down Expand Up @@ -153,6 +154,8 @@ def serialize(reply):
else None,
"is_author": reply.user_profile.user == request.user,
"is_moderator": is_moderator,
"has_user_voted": reply.vote_set.filter(user_profile=reply.user_profile).exists(), # noqa: E501
"formated_date": format_date(reply.created_date),
"depth": int(getattr(reply, "depth", 0)),
"replies": [],
}
Expand Down
22 changes: 12 additions & 10 deletions public_discourse_sandbox/pds_app/mixins.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from django.shortcuts import get_object_or_404, redirect
from django.core.exceptions import PermissionDenied
from django.shortcuts import redirect
from django.urls import reverse
from .models import Experiment, UserProfile, ExperimentInvitation

from .models import Experiment
from .models import ExperimentInvitation


class ExperimentContextMixin:
Expand Down Expand Up @@ -85,23 +87,23 @@ def get_valid_experiment(exp):
if "experiment_identifier" in kwargs:
try:
self.experiment = Experiment.objects.get(
identifier=kwargs["experiment_identifier"]
identifier=kwargs["experiment_identifier"],
)
except Experiment.DoesNotExist:
self.experiment = None

# If not found, try last_accessed (but only if not deleted)
if not self.experiment:
self.experiment = get_valid_experiment(
getattr(request.user, "last_accessed", None)
getattr(request.user, "last_accessed", None),
)
if self.experiment:
self.should_redirect = True

# If still not found, try first available experiment
if not self.experiment:
user_profile = request.user.userprofile_set.filter(
experiment__is_deleted=False
experiment__is_deleted=False,
).first()
if user_profile:
self.experiment = user_profile.experiment
Expand All @@ -114,7 +116,7 @@ def get_valid_experiment(exp):

# Get user's profile for this experiment
self.user_profile = request.user.userprofile_set.filter(
experiment=self.experiment
experiment=self.experiment,
).first()

# Update user's last_accessed experiment if needed
Expand Down Expand Up @@ -143,7 +145,7 @@ def check_moderator_permission(self):
"""
if not self.is_moderator(self.request.user, self.experiment):
raise PermissionDenied(
"You do not have moderator permissions for this experiment."
"You do not have moderator permissions for this experiment.",
)

def get_context_data(self, **kwargs):
Expand All @@ -155,7 +157,7 @@ def get_context_data(self, **kwargs):
context["experiment"] = self.experiment
context["current_user_profile"] = self.user_profile
context["is_moderator"] = self.is_moderator(
self.request.user, self.experiment
self.request.user, self.experiment,
)
return context

Expand Down Expand Up @@ -250,7 +252,7 @@ def check_moderator_permission(self):
"""
if not self.is_moderator(self.request.user, self.experiment):
raise PermissionDenied(
"You do not have moderator permissions for this experiment."
"You do not have moderator permissions for this experiment.",
)

def get_context_data(self, **kwargs):
Expand Down Expand Up @@ -292,7 +294,7 @@ def dispatch(self, request, *args, **kwargs):

if needs_profile:
return redirect(
"create_profile", experiment_identifier=self.experiment.identifier
"create_profile", experiment_identifier=self.experiment.identifier,
)

return super().dispatch(request, *args, **kwargs)
97 changes: 86 additions & 11 deletions public_discourse_sandbox/pds_app/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import math

from django.conf import settings
from django.contrib import messages
from django.contrib.auth import get_user_model
Expand All @@ -8,7 +10,6 @@
from django.core.mail import send_mail
from django.db import models
from django.db import transaction
from django.db.models import Count
from django.http import HttpResponseRedirect
from django.http import JsonResponse
from django.shortcuts import redirect
Expand Down Expand Up @@ -134,6 +135,7 @@ def get_active_posts(
post.has_user_voted = post.vote_set.filter(
user_profile__user=request.user,
).exists()
post.formated_date = format_date(post.created_date)

# Add follow state for each post
if current_user_profile and post.user_profile.user != request.user:
Expand Down Expand Up @@ -225,6 +227,10 @@ class PostDetailsView(

def get(self, request, *args, **kwargs):
self.object = self.get_object()
self.object.has_user_voted = self.object.vote_set.filter(
user_profile=self.object.user_profile,
).exists()
self.object.formated_date = format_date(self.object.created_date)
experiment_identifier = kwargs.get("experiment_identifier")

experiment = Experiment.objects.get(identifier=experiment_identifier)
Expand Down Expand Up @@ -261,12 +267,20 @@ def get_context_data(self, **kwargs):
)
"""

context["replies"] = Post.all_objects.filter(
posts = Post.all_objects.filter(
parent_post=self.object,
depth=self.object.depth + 1,
is_deleted=False,
).order_by("-created_date")

for post in posts:
post.has_user_voted = post.vote_set.filter(
user_profile=post.user_profile,
).exists()
post.formated_date = format_date(post.created_date)

context["replies"] = posts

return context


Expand Down Expand Up @@ -1290,6 +1304,66 @@ def get(self, request, *args, **kwargs):
},
)

from datetime import UTC
from datetime import datetime


def format_date(date):
if isinstance(date, str):
date_obj = datetime.fromisoformat(date.replace("Z", "+00:00"))
elif isinstance(date, datetime):
date_obj = date
else:
return ""

now = datetime.now(UTC)

if date_obj.tzinfo is None:
date_obj = date_obj.replace(tzinfo=UTC)

seconds_diff = round((date_obj-now).total_seconds())

unit_in_sec = [
60,
3600,
86400,
86400 * 7,
86400 * 30,
86400 * 365,
float("inf"),
]

unit_strings = [
"second",
"minute",
"hour",
"day",
"week",
"month",
"year",
]

unit_index = next(
i for i, cutoff in enumerate(unit_in_sec)
if cutoff > abs(seconds_diff)
)

divisor = unit_in_sec[unit_index-1] if unit_index else 1

if abs(seconds_diff) > 23*3600:
if date_obj.year != now.year:
return date_obj.strftime("%b %d, %Y")
return date_obj.strftime("%b %d")

value = math.floor(seconds_diff/divisor)
unit = unit_strings[unit_index]

if value == 0:
return "now"
if value > 0:
return f"in {value} {unit}{'' if abs(value) == 1 else 's'}"
return f"{abs(value)} {unit}{'' if abs(value) == 1 else 's'} ago"


class UserProfileDetailView(
LoginRequiredMixin,
Expand Down Expand Up @@ -1328,13 +1402,13 @@ def get_context_data(self, **kwargs):
source_node=self.object,
).count()

context["post_leaderboard"] = (
UserProfile.objects.filter(experiment=self.experiment)
.exclude(dorm_name__isnull=True)
.values("dorm_name")
.annotate(post_count=Count("post"))
.order_by("-post_count")[:3]
)
# context["post_leaderboard"] = (
# UserProfile.objects.filter(experiment=self.experiment)
# .exclude(dorm_name__isnull=True)
# .values("dorm_name")
# .annotate(post_count=Count("post"))
# .order_by("-post_count")[:3]
# )

# context["user_leaderboard"] = (
# UserProfile.objects.filter(experiment=self.experiment)
Expand Down Expand Up @@ -1418,6 +1492,7 @@ def get_context_data(self, **kwargs):
post.has_user_voted = post.vote_set.filter(
user_profile__user=current_user,
).exists()
post.formated_date = format_date(post.created_date)

# Add follow state for each post
if current_user_profile and post.user_profile.user != current_user:
Expand Down Expand Up @@ -1590,8 +1665,8 @@ def generate_external_api_token_view(request):
if request.method == "POST":
token = AuthApiToken.objects.create(user=request.user)
token_msg = mark_safe(
f"Token: {token} has been generated.<br/>"
"Keep it in safe environment as you won't be able to see it again.",
f"Here is your new generated api key: {token}<br/>"
"Keep it in a safe environment as you won't be able to see it again.",
)
messages.success(request, token_msg)

Expand Down
48 changes: 1 addition & 47 deletions public_discourse_sandbox/static/js/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,50 +180,4 @@ document.body.addEventListener("htmx:afterSwap", function (evt) {
if (container) {
makeHashtagsClickable(container);
}
});

function formatDate(date) {
const dateObject = new Date(date);
const secondsDiff = Math.round((dateObject - Date.now()) / 1000);

const unitsInSec = [
60,
3600,
86400,
86400 * 7,
86400 * 30,
86400 * 365,
Infinity,
];
const unitStrings = [
"second",
"minute",
"hour",
"day",
"week",
"month",
"year",
];

const unitIndex = unitsInSec.findIndex(
(cutoff) => cutoff > Math.abs(secondsDiff),
);
const divisor = unitIndex ? unitsInSec[unitIndex - 1] : 1;

if (Math.abs(secondsDiff) > 23 * 3600) {
const options = { month: "short", day: "numeric" };

if (dateObject.getFullYear() !== new Date().getFullYear()) {
options.year = "numeric";
}

return dateObject.toLocaleDateString("en-US", options);
} else {
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
const relativeTime = rtf.format(
Math.floor(secondsDiff / divisor),
unitStrings[unitIndex],
);
return relativeTime;
}
}
});
30 changes: 2 additions & 28 deletions public_discourse_sandbox/templates/components/comment_modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,33 +66,7 @@ <h2>Reply</h2>
function closeCommentModal() {
document.getElementById('commentModal').style.display = 'none';
}

function formatDate(date) {
const dateObject = new Date(date)
const secondsDiff = Math.round((dateObject - Date.now()) / 1000);

const unitsInSec = [60, 3600, 86400, 86400 * 7, 86400 * 30, 86400 * 365, Infinity];
const unitStrings = ["second", "minute", "hour", "day", "week", "month", "year"];

const unitIndex = unitsInSec.findIndex((cutoff) => cutoff > Math.abs(secondsDiff));
const divisor = unitIndex ? unitsInSec[unitIndex - 1] : 1;

if (Math.abs(secondsDiff) > 23 * 3600) {
const options = { month: "short", day: "numeric" };

if (dateObject.getFullYear() !== new Date().getFullYear()) {
options.year = "numeric";
}

return dateObject.toLocaleDateString("en-US", options)
} else {
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
const relativeTime = rtf.format(Math.floor(secondsDiff / divisor), unitStrings[unitIndex]);
return relativeTime
}
}



function createReplyForm(parentId, isNested = false) {
const template = document.getElementById('replyFormTemplate');
const form = template.content.cloneNode(true);
Expand Down Expand Up @@ -221,7 +195,7 @@ <h2>Reply</h2>
<a href="${profileLink}" class="user-name">${reply.display_name}</a>
<a href="${profileLink}" class="user-handle">@${reply.username}</a>
<span class="dot">·</span>
<span class="time">${formatDate(reply.created_date)}</span>
<span class="time">${reply.formated_date}</span>
</div>
</div>
${menuHtml}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@
{% include 'components/ban_modal.html' %}

<script src="{% static 'js/shared.js' %}"></script>
<script>
document.querySelectorAll('.time').forEach(el => {
const dt = el.getAttribute('datetime');
el.textContent = formatDate(dt)
});

<script>
function togglePostMenu(postId) {
const menu = document.getElementById(`post-menu-${postId}`);
const allMenus = document.querySelectorAll('.post-menu-dropdown');
Expand Down
Loading