Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Townsquare feed should recognize links #6298

Closed
PixelantDesign opened this issue Mar 25, 2020 · 27 comments · Fixed by #6485
Closed

Townsquare feed should recognize links #6298

PixelantDesign opened this issue Mar 25, 2020 · 27 comments · Fixed by #6485
Labels
easy-pickings This is an easy issue for the community. For Contributor good first issue This a good first issue for a community newcomer.

Comments

@PixelantDesign
Copy link
Contributor

What

Townsquare feed should recognize links - make link clickable

Why

not clickable

Screen Shot 2020-03-25 at 8 51 18 AM

@PixelantDesign PixelantDesign added easy-pickings This is an easy issue for the community. good first issue This a good first issue for a community newcomer. For Contributor labels Mar 25, 2020
@gitcoinbot
Copy link
Member

Issue Status: 1. Open 2. Started 3. Submitted 4. Done


This issue now has a funding of 0.25 ETH (33.53 USD @ $134.12/ETH) attached to it.

@gitcoinbot
Copy link
Member

gitcoinbot commented Mar 25, 2020

Issue Status: 1. Open 2. Started 3. Submitted 4. Done


Work has been started.

These users each claimed they can complete the work by 4 days, 7 hours from now.
Please review their action plans below:

1) sebastiantf has been approved to start work.

Write code to detect links in townsquare and interpret them as hyperlinks

Learn more on the Gitcoin Issue Details page.

@PixelantDesign
Copy link
Contributor Author

@sebastiantf ^ looking forward to seeing a pr!

@sebastiantf
Copy link
Contributor

Yes @PixelantDesign . I'm working on it.

@sebastiantf
Copy link
Contributor

@PixelantDesign I am not able to reproduce the issue rn. It seems the posts on Townsquare do recognize links and are clickable.

Can you please elaborate on the issue about when and how it happens?

@molecula451
Copy link
Contributor

it looks like this is a post that were made to a grant wall.

@sebastiantf
Copy link
Contributor

sebastiantf commented Mar 27, 2020

@molecula451 You mean the Activity tab on Grants page? But there too links are being recognized and clickable

Screenshot 2020-03-27 at 12 30 33 PM

@molecula451
Copy link
Contributor

@walidmujahid

@walidmujahid
Copy link
Contributor

walidmujahid commented Mar 27, 2020

I have seen the link issue resolved. I am not sure who fixed it or what commit did so, but links do work now for the wall_post activities.

I am not working on this issue, but if this issue still has problems, I am just going to copy and paste a reply I posted the other day in TownSquare that seems relevant - Edited to reflect the lines seen a few days ago:

From: https://gitcoin.co/townsquare?tab=activity:186156

@amiyatulu All wall_post activities suffer from this actually, not just those posted from Grant walls. It is actually not just the links that are an issue -which is done with the urlify function in the activity.js script-, but metadat in general does not show up, nor does the new video call feature.

It feels like only status_update activities are getting handled by any relevant css and the activity.js script, so the solution is probably to make sure that the script applies to wall_post activities as well.

Your main two files to look at for activities, in general, are the retail shared/activities.html -there are multiple shared/*.html templates and it can get very annoying for me even after staring at both code and markup/Gitcoin's codebase for a few months now.

Specifically, you want to look at these lines in the template markup:

{% elif row.activity_type == 'wall_post' %}
>
{% if row.grant %}
<a href="{{ row.grant.url }}">
{{ row.grant.title }}
</a>
{% elif row.kudos %}
<a href="{{ row.kudos.url }}">
{{ row.kudos.ui_name }}
</a>
{% elif row.other_profile %}
<a href="{{ row.other_profile.url }}">
@{{ row.other_profile.handle }}
</a>
{% endif %}
:
<b>{{ row.metadata.title }}</b>

This javascript file: https://github.com/gitcoinco/web/blob/master/app/assets/v2/js/activity.js

And a large chunk of the retail.views starting from the beginning -you may just want to read the whole thing, it can help greatly: https://github.com/gitcoinco/web/blob/master/app/retail/views.py

Oh, and here is the model and post_save signal function handler:

web/app/dashboard/models.py

Lines 2047 to 2369 in 8282370

class Activity(SuperModel):
"""Represent Start work/Stop work event.
Attributes:
ACTIVITY_TYPES (list of tuples): The valid activity types.
"""
ACTIVITY_TYPES = [
('wall_post', 'Wall Post'),
('status_update', 'Update status'),
('new_bounty', 'New Bounty'),
('start_work', 'Work Started'),
('stop_work', 'Work Stopped'),
('work_submitted', 'Work Submitted'),
('work_done', 'Work Done'),
('worker_approved', 'Worker Approved'),
('worker_rejected', 'Worker Rejected'),
('worker_applied', 'Worker Applied'),
('increased_bounty', 'Increased Funding'),
('killed_bounty', 'Canceled Bounty'),
('new_tip', 'New Tip'),
('receive_tip', 'Tip Received'),
('bounty_abandonment_escalation_to_mods', 'Escalated checkin from @gitcoinbot about bounty status'),
('bounty_abandonment_warning', 'Checkin from @gitcoinbot about bounty status'),
('bounty_removed_slashed_by_staff', 'Dinged and Removed from Bounty by Staff'),
('bounty_removed_by_staff', 'Removed from Bounty by Staff'),
('bounty_removed_by_funder', 'Removed from Bounty by Funder'),
('new_crowdfund', 'New Crowdfund Contribution'),
# Grants
('new_grant', 'New Grant'),
('update_grant', 'Updated Grant'),
('killed_grant', 'Cancelled Grant'),
('new_grant_contribution', 'Contributed to Grant'),
('new_grant_subscription', 'Subscribed to Grant'),
('killed_grant_contribution', 'Cancelled Grant Contribution'),
('new_milestone', 'New Milestone'),
('update_milestone', 'Updated Milestone'),
('new_kudos', 'New Kudos'),
('created_kudos', 'Created Kudos'),
('receive_kudos', 'Receive Kudos'),
('joined', 'Joined Gitcoin'),
('played_quest', 'Played Quest'),
('beat_quest', 'Beat Quest'),
('created_quest', 'Created Quest'),
('updated_avatar', 'Updated Avatar'),
('mini_clr_payout', 'Mini CLR Payout'),
('leaderboard_rank', 'Leaderboard Rank'),
('consolidated_leaderboard_rank', 'Consolidated Leaderboard Rank'),
('consolidated_mini_clr_payout', 'Consolidated CLR Payout'),
('hackathon_registration', 'Hackathon Registration'),
]
profile = models.ForeignKey(
'dashboard.Profile',
related_name='activities',
on_delete=models.CASCADE
)
bounty = models.ForeignKey(
'dashboard.Bounty',
related_name='activities',
on_delete=models.CASCADE,
blank=True,
null=True
)
tip = models.ForeignKey(
'dashboard.Tip',
related_name='activities',
on_delete=models.CASCADE,
blank=True,
null=True
)
kudos_transfer = models.ForeignKey(
'kudos.KudosTransfer',
related_name='activities',
on_delete=models.CASCADE,
blank=True, null=True
)
kudos = models.ForeignKey(
'kudos.Token',
related_name='activities',
on_delete=models.CASCADE,
blank=True, null=True
)
grant = models.ForeignKey(
'grants.Grant',
related_name='activities',
on_delete=models.CASCADE,
blank=True, null=True
)
subscription = models.ForeignKey(
'grants.Subscription',
related_name='activities',
on_delete=models.CASCADE,
blank=True, null=True
)
hackathonevent = models.ForeignKey(
'dashboard.HackathonEvent',
related_name='activities',
on_delete=models.CASCADE,
blank=True, null=True
)
created = models.DateTimeField(auto_now_add=True, blank=True, null=True, db_index=True)
activity_type = models.CharField(max_length=50, choices=ACTIVITY_TYPES, blank=True, db_index=True)
metadata = JSONField(default=dict, blank=True)
needs_review = models.BooleanField(default=False)
view_count = models.IntegerField(default=0, db_index=True)
other_profile = models.ForeignKey(
'dashboard.Profile',
related_name='other_activities',
on_delete=models.CASCADE,
null=True,
blank=True
)
hidden = models.BooleanField(default=False, db_index=True)
cached_view_props = JSONField(default=dict, blank=True)
# Activity QuerySet Manager
objects = ActivityQuerySet.as_manager()
def __str__(self):
"""Define the string representation of an interested profile."""
return f"{self.profile.handle} type: {self.activity_type} created: {naturalday(self.created)} " \
f"needs review: {self.needs_review}"
def get_absolute_url(self):
return self.url
@property
def video_participants_count(self):
if not self.metadata.get('video'):
return 0
try:
from app.redis_service import RedisService
redis = RedisService().redis
result = redis.get(self.pk)
if not result:
return 0
return int(result.decode('utf-8'))
except KeyError:
return 0
@property
def action_url(self):
if self.bounty:
return self.bounty.url
if self.grant:
return self.grant.url
if self.kudos:
return self.kudos.url
if self.profile:
return self.profile.url
return ""
@property
def what(self):
# returns what your wall post target is
if self.grant:
return 'grant'
if self.kudos:
return 'kudos'
if self.other_profile:
return 'profile'
return ""
@property
def url(self):
return f"{settings.BASE_URL}{self.relative_url}"
@property
def relative_url(self):
return f"townsquare?tab=activity:{self.pk}"
@property
def humanized_activity_type(self):
"""Turn snake_case into Snake Case.
Returns:
str: The humanized nameactivity_type
"""
for activity_type in self.ACTIVITY_TYPES:
if activity_type[0] == self.activity_type:
return activity_type[1]
return ' '.join([x.capitalize() for x in self.activity_type.split('_')])
def point_value(self):
"""
Returns:
int the Point value of this activity
"""
return point_values.get(self.activity_type, 0)
def i18n_name(self):
return _(next((x[1] for x in self.ACTIVITY_TYPES if x[0] == self.activity_type), 'Unknown type'))
@property
def text(self):
params = {
'row': self,
'hide_date': True,
'hide_likes': True,
}
html_str = render_to_string('shared/activity.html', params)
soup = BeautifulSoup(html_str)
txt = soup.get_text()
txt = txt.replace("\n","")
for i in range(0, 100):
txt = txt.replace(" ",' ')
return txt
def has_voted(self, user):
poll = self.metadata.get('poll_choices')
if poll:
if user.is_authenticated:
for ele in poll:
if user.profile.pk in ele['answers']:
return ele['i']
return False
def view_props_for(self, user):
# get view props
vp = self
if not user.is_authenticated:
return vp
vp.metadata['liked'] = False
if self.likes.exists():
vp.metadata['liked'] = self.likes.filter(profile=user.profile).exists()
vp.metadata['likes_title'] = "Liked by " + ",".join(self.likes.values_list('profile__handle', flat=True)) + '. '
vp.metadata['poll_answered'] = self.has_voted(user)
return vp
@property
def tip_count_usd(self):
network = 'rinkeby' if settings.DEBUG else 'mainnet'
tips = Tip.objects.filter(comments_priv=f"activity:{self.pk}", network=network)
return sum([tip.value_in_usdt for tip in tips])
@property
def tip_count_eth(self):
network = 'rinkeby' if settings.DEBUG else 'mainnet'
tips = Tip.objects.filter(comments_priv=f"activity:{self.pk}", network=network)
return sum([tip.value_in_eth for tip in tips])
@property
def secondary_avatar_url(self):
if self.metadata.get('to_username'):
return f"/dynamic/avatar/{self.metadata['to_username']}"
if self.metadata.get('worker_handle'):
return f"/dynamic/avatar/{self.metadata['worker_handle']}"
if self.metadata.get('url'):
return self.metadata['url']
if self.bounty:
return self.bounty.avatar_url
if self.metadata.get('grant_logo'):
return self.metadata['grant_logo']
if self.grant:
return self.grant.logo.url if self.grant.logo else None
return None
@property
def token_name(self):
if self.bounty:
return self.bounty.token_name
if 'token_name' in self.metadata.keys():
return self.metadata['token_name']
return None
def to_dict(self, fields=None, exclude=None):
"""Define the standard to dict representation of the object.
Args:
fields (list): The list of fields to include. If not provided,
include all fields. If not provided, all fields are included.
Defaults to: None.
exclude (list): The list of fields to exclude. If not provided,
no fields are excluded. Default to: None.
Returns:
dict: The dictionary representation of the object.
"""
kwargs = {}
if fields:
kwargs['fields'] = fields
if exclude:
kwargs['exclude'] = exclude
return model_to_dict(self, **kwargs)
@receiver(pre_save, sender=Activity, dispatch_uid="psave_activity")
def psave_activity(sender, instance, **kwargs):
if instance.bounty and instance.bounty.event:
if not instance.hackathonevent:
instance.hackathonevent = instance.bounty.event
if hasattr(instance, 'profile') and instance.profile and hasattr(instance.profile, 'user') and instance.profile.user and instance.profile.user.is_staff:
instance.metadata['staff'] = True
@receiver(post_save, sender=Activity, dispatch_uid="post_add_activity")
def post_add_activity(sender, instance, created, **kwargs):
if created:
# make sure duplicate activity feed items are removed
dupes = Activity.objects.exclude(pk=instance.pk)
dupes = dupes.filter(created_on__gte=(instance.created_on - timezone.timedelta(minutes=5)))
dupes = dupes.filter(created_on__lte=(instance.created_on + timezone.timedelta(minutes=5)))
dupes = dupes.filter(profile=instance.profile)
dupes = dupes.filter(bounty=instance.bounty)
dupes = dupes.filter(tip=instance.tip)
dupes = dupes.filter(kudos=instance.kudos)
dupes = dupes.filter(grant=instance.grant)
dupes = dupes.filter(subscription=instance.subscription)
dupes = dupes.filter(activity_type=instance.activity_type)
dupes = dupes.filter(metadata=instance.metadata)
dupes = dupes.filter(needs_review=instance.needs_review)
for dupe in dupes:
dupe.delete()

@gitcoinbot
Copy link
Member

@sebastiantf Hello from Gitcoin Core - are you still working on this issue? Please submit a WIP PR or comment back within the next 3 days or you will be removed from this ticket and it will be returned to an ‘Open’ status. Please let us know if you have questions!

  • reminder (3 days)
  • escalation to mods (6 days)

Funders only: Snooze warnings for 1 day | 3 days | 5 days | 10 days | 100 days

@sebastiantf
Copy link
Contributor

sebastiantf commented Mar 31, 2020

Yes @gitcoinbot.

@PixelantDesign Can you please clarify whether this issue still exists?

@gitcoinbot
Copy link
Member

@sebastiantf Hello from Gitcoin Core - are you still working on this issue? Please submit a WIP PR or comment back within the next 3 days or you will be removed from this ticket and it will be returned to an ‘Open’ status. Please let us know if you have questions!

  • reminder (3 days)
  • escalation to mods (6 days)

Funders only: Snooze warnings for 1 day | 3 days | 5 days | 10 days | 100 days

1 similar comment
@gitcoinbot
Copy link
Member

@sebastiantf Hello from Gitcoin Core - are you still working on this issue? Please submit a WIP PR or comment back within the next 3 days or you will be removed from this ticket and it will be returned to an ‘Open’ status. Please let us know if you have questions!

  • reminder (3 days)
  • escalation to mods (6 days)

Funders only: Snooze warnings for 1 day | 3 days | 5 days | 10 days | 100 days

@sebastiantf
Copy link
Contributor

Yes @gitcoinbot

@PixelantDesign Can you please verify whether this issue still exist?

@gitcoinbot
Copy link
Member

@sebastiantf Hello from Gitcoin Core - are you still working on this issue? Please submit a WIP PR or comment back within the next 3 days or you will be removed from this ticket and it will be returned to an ‘Open’ status. Please let us know if you have questions!

  • reminder (3 days)
  • escalation to mods (6 days)

Funders only: Snooze warnings for 1 day | 3 days | 5 days | 10 days | 100 days

@developerfred
Copy link
Contributor

developerfred commented Apr 11, 2020

Yes @gitcoinbot

@PixelantDesign Can you please verify whether this issue still exist?

@sebastiantf
this issue is still open, today I saw some links with this problem.

@sebastiantf
Copy link
Contributor

@developerfred Thanks for notifying.

Will you be able to share a link to that post you saw as not working. Or maybe a screenshot? I am not able to reproduce this issue. All links I saw on the Grants activity wall are recognized and clickable.

@developerfred
Copy link
Contributor

developerfred commented Apr 13, 2020

@sebastiant I used the Trust Wallet browser, I'm going to record a screemshoot

@developerfred
Copy link
Contributor

@sebastiantf
Copy link
Contributor

@developerfred What do you mean the pull request branch?

@developerfred
Copy link
Contributor

@developerfred What do you mean the pull request branch?

Sorry, pull request is about another issue

@sebastiantf
Copy link
Contributor

Thanks for sharing the screenshot and link @developerfred. I could reproduce the issue in Chrome too.

But I do think this has something to do with how the user has typed in / entered the url in this case which looks a bit unconventional.

Still the link is being identified and preview is being shown.

But the link is not clickable in the post. It must have something to do with how links are identified and replaced with anchor elements.

🙏🏻 Thank you for identifying this and reporting this. Appreciate this. I can now look into this issue.

@gitcoinbot
Copy link
Member

@sebastiantf Hello from Gitcoin Core - are you still working on this issue? Please submit a WIP PR or comment back within the next 3 days or you will be removed from this ticket and it will be returned to an ‘Open’ status. Please let us know if you have questions!

  • reminder (3 days)
  • escalation to mods (6 days)

Funders only: Snooze warnings for 1 day | 3 days | 5 days | 10 days | 100 days

@sebastiantf
Copy link
Contributor

Yea @gitcoinbot

@gitcoinbot
Copy link
Member

Issue Status: 1. Open 2. Started 3. Submitted 4. Done


Work for 0.25 ETH (42.98 USD @ $171.91/ETH) has been submitted by:

  1. @sebastiantf

@PixelantDesign please take a look at the submitted work:


@gitcoinbot
Copy link
Member

⚡️ A tip worth 0.03750 ETH (8.39 USD @ $223.65/ETH) has been granted to @sebastiantf for this issue from @PixelantDesign. ⚡️

Nice work @sebastiantf! Your tip has automatically been deposited in the ETH address we have on file.

@gitcoinbot
Copy link
Member

Issue Status: 1. Open 2. Started 3. Submitted 4. Done


The funding of 0.25 ETH (55.91 USD @ $223.65/ETH) attached to this issue has been approved & issued to @sebastiantf.

Additional Tips for this Bounty:

  • PixelantDesign tipped 0.0375 ETH worth 8.39 USD to sebastiantf.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
easy-pickings This is an easy issue for the community. For Contributor good first issue This a good first issue for a community newcomer.
Projects
None yet
6 participants