Skip to content

Commit

Permalink
Fix subscriptions (#2261)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fosol authored Sep 5, 2024
1 parent bd07f60 commit 460d46f
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 44 deletions.
33 changes: 21 additions & 12 deletions app/editor/src/features/admin/products/ProductSubRequests.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useFormikContext } from 'formik';
import React from 'react';
import { IProductModel, ProductRequestStatusName, Show } from 'tno-core';
import { Col, IProductModel, ProductRequestStatusName, Row, Show } from 'tno-core';

import * as styled from './styled';
import { UserApproveDeny } from './UserApproveDeny';
Expand Down Expand Up @@ -39,17 +39,26 @@ export const ProductSubRequests: React.FC = () => {
{values.subscribers.map((user, index) => {
if (user.status !== ProductRequestStatusName.RequestUnsubscribe) return null;
return (
<UserApproveDeny
key={`user-request-cancellation-${user.userId}`}
user={user}
onChange={(approve) =>
setFieldValue(`subscribers.${index}`, {
...user,
status: ProductRequestStatusName.NA,
isSubscribed: !approve,
})
}
/>
<Row key={`user-request-cancellation-${user.userId}`} gap="1rem">
<Col flex="1">
<UserApproveDeny
user={user}
onChange={(approve) =>
setFieldValue(`subscribers.${index}`, {
...user,
status: ProductRequestStatusName.NA,
isSubscribed: !approve,
})
}
/>
</Col>
<Col flex="2">
<p>
If this user is currently subscribed through a distribution list, you will need to
first remove them from the list and then approve this request.
</p>
</Col>
</Row>
);
})}
<Show
Expand Down
60 changes: 41 additions & 19 deletions app/subscriber/src/features/my-products/MyProducts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export const MyProducts: React.FC = () => {
userId={userId}
product={product}
onToggleSubscription={(userProduct) => {
console.debug(userProduct);
selectProduct(product, userProduct);
toggle();
}}
Expand All @@ -140,7 +141,7 @@ export const MyProducts: React.FC = () => {
{products
.filter((product) =>
// products which the user *IS NOT* unsubscribed to
product.subscribers.some(
product.subscribers.every(
(s) =>
!s.isSubscribed && s.status !== ProductRequestStatusName.RequestSubscription,
),
Expand All @@ -152,6 +153,7 @@ export const MyProducts: React.FC = () => {
userId={userInfo?.id}
product={product}
onToggleSubscription={(userProduct) => {
console.debug(userProduct);
selectProduct(product, userProduct);
toggle();
}}
Expand All @@ -163,27 +165,11 @@ export const MyProducts: React.FC = () => {
</PageSection>
<Modal
headerText={`Confirm change`}
body={
(active?.userProduct.status === ProductRequestStatusName.RequestSubscription
? `Are you sure you wish to ${
active.userProduct.isSubscribed ? 'unsubscribe from' : 'subscribe to'
}`
: `Are you sure you wish to cancel your pending request to ${
active?.userProduct.isSubscribed ? 'unsubscribe from' : 'subscribe to'
}`) + `"${active?.product.name}"?`
}
body={active && modalBody(active)}
isShowing={isShowing}
hide={toggle}
type="default"
confirmText={
active?.userProduct.status === ProductRequestStatusName.RequestSubscription
? `Yes, ${
active.userProduct.isSubscribed ? 'request to unsubscribe' : 'request to subscribe'
}`
: `Yes, cancel my pending request to ${
active?.userProduct.isSubscribed ? 'unsubscribe' : 'subscribe'
}`
}
confirmText={active && modalConfirmText(active)}
onConfirm={() => {
if (active) handleToggleSubscription(active.product, active.userProduct);
toggle();
Expand All @@ -192,3 +178,39 @@ export const MyProducts: React.FC = () => {
</styled.MyProducts>
);
};

const modalBody = (active: ISelectedProduct) => {
if (active.userProduct.isSubscribed) {
switch (active.userProduct.status) {
case ProductRequestStatusName.RequestUnsubscribe:
return `Are you sure you wish to unsubscribe to ${active.product.name}`;
default:
return `Are you sure you wish to cancel your pending request to unsubscribe to ${active.product.name}`;
}
} else {
switch (active.userProduct.status) {
case ProductRequestStatusName.RequestSubscription:
return `Are you sure you wish to subscribe to ${active.product.name}`;
default:
return `Are you sure you wish to cancel your pending request to subscribe to ${active.product.name}`;
}
}
};

const modalConfirmText = (active: ISelectedProduct) => {
if (active.userProduct.isSubscribed) {
switch (active.userProduct.status) {
case ProductRequestStatusName.RequestUnsubscribe:
return `Yes, request to unsubscribe`;
default:
return `Yes, cancel my pending request to unsubscribe`;
}
} else {
switch (active.userProduct.status) {
case ProductRequestStatusName.RequestSubscription:
return `Yes, request to subscribe`;
default:
return `Yes, cancel my pending request to subscribe`;
}
}
};
10 changes: 9 additions & 1 deletion app/subscriber/src/features/my-products/ProductCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ export const ProductCard: React.FC<IProductCardProps> = ({
}) => {
const [{ userInfo }] = useApp();

const userProduct: IUserProductModel = product.subscribers.find((s) => s.userId === userId) ?? {
let userProduct: IUserProductModel | undefined = product.subscribers.find(
(s) => s.userId === userId,
) ?? {
userId: userId ?? 0,
productId: product.id,
status: ProductRequestStatusName.NA,
Expand All @@ -48,6 +50,12 @@ export const ProductCard: React.FC<IProductCardProps> = ({
isEnabled: userInfo?.isEnabled ?? true,
accountType: UserAccountTypeName.Direct,
};
// Check a distribution list to see if user is subscribed this way.
if (product.subscribers.length > 1 && !userProduct?.isSubscribed) {
const distribution = product.subscribers.find((s) => s.isSubscribed);
// Switch the subscription to the user from the distribution list.
if (distribution) userProduct = { ...distribution, userId: userId ?? 0 };
}
const isSubscribed = userProduct.isSubscribed;
const isRequesting =
!userProduct.isSubscribed &&
Expand Down
29 changes: 21 additions & 8 deletions libs/net/dal/Services/ProductService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public IEnumerable<Product> FindPublic()
/// <returns></returns>
public IEnumerable<Product> Find(ProductFilter filter)
{
int[] distributionIds = Array.Empty<int>();
var query = filter.IsAvailableToUserId.HasValue == true ?
this.Context.Products.AsNoTracking() :
this.Context.Products.Include(r => r.SubscribersManyToMany).ThenInclude(s => s.User).AsNoTracking();
Expand All @@ -91,7 +92,16 @@ public IEnumerable<Product> Find(ProductFilter filter)
if (filter.SubscriberUserId.HasValue == true)
query = query.Where(r => r.SubscribersManyToMany.Any(s => s.UserId == filter.SubscriberUserId.Value));
if (filter.IsAvailableToUserId.HasValue == true)
query = query.Where(r => r.IsPublic || r.SubscribersManyToMany.Any(s => s.UserId == filter.IsAvailableToUserId.Value));
{
// Get all distribution lists this user is part of.
distributionIds = this.Context.UserDistributions
.Where(ud => ud.LinkedUserId == filter.IsAvailableToUserId.Value)
.Select(ud => ud.UserId).ToArray();

query = query.Where(r => r.IsPublic ||
r.SubscribersManyToMany.Any(s => s.UserId == filter.IsAvailableToUserId.Value) ||
r.SubscribersManyToMany.Any(s => distributionIds.Contains(s.UserId)));
}

if (filter.Sort?.Any() == true)
{
Expand Down Expand Up @@ -126,19 +136,22 @@ public IEnumerable<Product> Find(ProductFilter filter)
.FirstOrDefault(u => u.Id == filter.IsAvailableToUserId.Value) ?? throw new NoContentException();

// Fetch product subscribers only for the specified user.
var subscribers = this.Context.UserProducts.AsNoTracking().Where(up => up.UserId == filter.IsAvailableToUserId.Value).ToArray();
var subscribers = this.Context.UserProducts
.AsNoTracking()
.Include(s => s.Product)
.Include(s => s.User)
.Include(s => s.User).ThenInclude(u => u!.ReportSubscriptionsManyToMany)
.Include(s => s.User).ThenInclude(u => u!.NotificationSubscriptionsManyToMany)
.Include(s => s.User).ThenInclude(u => u!.AVOverviewSubscriptionsManyToMany)
.Where(up => up.UserId == filter.IsAvailableToUserId.Value || distributionIds.Contains(up.UserId))
.ToArray();

// For each product add the actual subscription records.
foreach (var product in products)
{
product.SubscribersManyToMany.AddRange(subscribers.Where(s => s.ProductId == product.Id));
var subscriber = product.SubscribersManyToMany.FirstOrDefault(s => s.UserId == filter.IsAvailableToUserId.Value);
if (subscriber != null)
{
subscriber.Product = product;
subscriber.User = user;
}
else
if (!product.SubscribersManyToMany.Any())
product.SubscribersManyToMany.Add(new UserProduct(user, product));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public UserProductModel() { }

/// <summary>
/// Creates a new instance of an UserProductModel, initializes with specified parameter.
/// An assumption is made in this model. If a subscription exists for either the user or a distribution group, we assume the user is subscribed.
/// </summary>
/// <param name="entity"></param>
public UserProductModel(Entities.UserProduct entity) : base(entity)
Expand Down Expand Up @@ -109,15 +110,13 @@ public UserProductModel(Entities.UserProduct entity) : base(entity)
else if (entity.Product.ProductType == Entities.ProductType.Notification)
{
var subscription = entity.User.NotificationSubscriptionsManyToMany
.FirstOrDefault(s => s.UserId == entity.UserId &&
s.NotificationId == entity.Product!.TargetProductId);
.FirstOrDefault(s => s.IsSubscribed && s.NotificationId == entity.Product!.TargetProductId);
this.IsSubscribed = subscription?.IsSubscribed ?? false;
}
else if (entity.Product.ProductType == Entities.ProductType.EveningOverview)
{
var subscription = entity.User.AVOverviewSubscriptionsManyToMany
.FirstOrDefault(s => s.UserId == entity.UserId &&
(int)s.TemplateType == entity.Product!.TargetProductId);
.FirstOrDefault(s => s.IsSubscribed && (int)s.TemplateType == entity.Product!.TargetProductId);
this.IsSubscribed = subscription?.IsSubscribed ?? false;
this.SendTo = subscription?.SendTo;
}
Expand Down

0 comments on commit 460d46f

Please sign in to comment.