diff --git a/services/web/app/src/Features/Notifications/NotificationsBuilder.js b/services/web/app/src/Features/Notifications/NotificationsBuilder.js
index 30ef8b97d5..58c4f68a1a 100644
--- a/services/web/app/src/Features/Notifications/NotificationsBuilder.js
+++ b/services/web/app/src/Features/Notifications/NotificationsBuilder.js
@@ -281,29 +281,6 @@ function personalAndGroupSubscriptions(userId) {
}
}
-/**
- * @param {string} [userId]
- */
-function ieeeCollabratecRetirement(userId) {
- return {
- key: 'notification-ieee-collabratec-retirement',
- create(callback) {
- NotificationsHandler.createNotification(
- userId,
- this.key,
- 'notification_ieee_collabratec_retirement',
- {},
- new Date('2024-08-01'),
- false,
- callback
- )
- },
- deleteAllUnread(callback) {
- NotificationsHandler.markAsReadByKeyOnlyBulk(this.key, callback)
- },
- }
-}
-
const NotificationsBuilder = {
// Note: notification keys should be url-safe
dropboxUnlinkedDueToLapsedReconfirmation,
@@ -315,7 +292,6 @@ const NotificationsBuilder = {
tpdsFileLimit,
groupInvitation,
personalAndGroupSubscriptions,
- ieeeCollabratecRetirement,
}
NotificationsBuilder.promises = {
@@ -343,9 +319,6 @@ NotificationsBuilder.promises = {
personalAndGroupSubscriptions(userId) {
return promisifyAll(personalAndGroupSubscriptions(userId))
},
- ieeeCollabratecRetirement(userId) {
- return promisifyAll(ieeeCollabratecRetirement(userId))
- },
}
module.exports = NotificationsBuilder
diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json
index 5d0e543e17..841188a7a0 100644
--- a/services/web/frontend/extracted-translations.json
+++ b/services/web/frontend/extracted-translations.json
@@ -879,7 +879,6 @@
"normally_x_price_per_year": "",
"not_managed": "",
"not_now": "",
- "notification_ieee_collabratec_retirement_message": "",
"notification_personal_and_group_subscriptions": "",
"notification_project_invite_accepted_message": "",
"notification_project_invite_message": "",
diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups/common.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups/common.tsx
index 7b305af905..328504fbda 100644
--- a/services/web/frontend/js/features/project-list/components/notifications/groups/common.tsx
+++ b/services/web/frontend/js/features/project-list/components/notifications/groups/common.tsx
@@ -10,7 +10,6 @@ import {
Notification as NotificationType,
} from '../../../../../../../types/project/dashboard/notification'
import GroupInvitationNotification from './group-invitation/group-invitation'
-import IEEERetirementBanner from '../ieee-retirement-banner'
import { debugConsole } from '@/utils/debugging'
import OLButton from '@/features/ui/components/ol/ol-button'
@@ -279,8 +278,6 @@ function CommonNotification({ notification }: CommonNotificationProps) {
/>
) : templateKey === 'notification_group_invitation' ? (
- ) : templateKey === 'notification_ieee_collabratec_retirement' ? (
-
) : templateKey === 'notification_personal_and_group_subscriptions' ? (
{
- eventTracking.sendMB('promo-dismiss', {
- name: 'ieee - retirement',
- })
- if (id) {
- handleDismiss(id)
- }
- }, [id, handleDismiss])
-
- const handleClickPlans = useCallback(() => {
- eventTracking.sendMB('promo-click', {
- name: 'ieee - retirement',
- content: 'plans',
- })
- }, [])
-
- const handleClickEmail = useCallback(() => {
- eventTracking.sendMB('promo-click', {
- name: 'ieee - retirement',
- content: 'email',
- })
- }, [])
-
- useEffect(() => {
- if (!viewEventSent) {
- eventTracking.sendMB('promo-prompt', {
- name: 'ieee - retirement',
- })
- viewEventSent = true
- }
- }, [])
-
- return (
- ,
- // eslint-disable-next-line jsx-a11y/anchor-has-content,react/jsx-key
- ,
- ]}
- />
- }
- />
- )
-}
diff --git a/services/web/locales/en.json b/services/web/locales/en.json
index b83c626d15..eb52e60f40 100644
--- a/services/web/locales/en.json
+++ b/services/web/locales/en.json
@@ -1291,7 +1291,6 @@
"not_registered": "Not registered",
"note_features_under_development": "<0>Please note0> that features in this program are still being tested and actively developed. This means that they might <0>change0>, be <0>removed0> or <0>become part of a premium plan0>",
"notification_features_upgraded_by_affiliation": "Good news! Your affiliated organization __institutionName__ has an Overleaf subscription, and you now have access to all of Overleaf’s Professional features.",
- "notification_ieee_collabratec_retirement_message": "As of April 2, 2024, free access to Overleaf Professional subscriptions via Collabratec or IEEE accounts has ended. Need to upgrade? <0>View our plans0>. Contact <1>authors@ieee.org1> with any questions.",
"notification_personal_and_group_subscriptions": "We’ve spotted that you’ve got <0>more than one active __appName__ subscription0>. To avoid paying more than you need to, <1>review your subscriptions1>.",
"notification_personal_subscription_not_required_due_to_affiliation": " Good news! Your affiliated organization __institutionName__ has an Overleaf subscription, and you now have access to Overleaf’s Professional features through your affiliation. You can cancel your individual subscription without losing access to any features.",
"notification_project_invite": "__userName__ would like you to join __projectName__ Join Project",
diff --git a/services/web/locales/zh-CN.json b/services/web/locales/zh-CN.json
index 1c751c7330..114d6768ba 100644
--- a/services/web/locales/zh-CN.json
+++ b/services/web/locales/zh-CN.json
@@ -1262,7 +1262,6 @@
"not_registered": "未注册",
"note_features_under_development": "<0>请注意0>此计划中的功能仍在测试和快速开发中。 这意味着它们可能<0>改变0>、<0>被删除0>或<0>成为高级计划的一部分0>",
"notification_features_upgraded_by_affiliation": "好消息!您的组织__institutionName__已有 Overleaf 订阅,并且您现在可以访问 Overleaf 的所有专业功能。",
- "notification_ieee_collabratec_retirement_message": "从 2024年 1 月 31日起, IEEE 不再提供 Overleaf premium 功能给协作者。有问题请联系 <0>authors@ieee.org0>。需要升级吗? <1>查看我们的订阅计划1>",
"notification_personal_and_group_subscriptions": "我们发现您有<0>多个活跃的 __appName__ 订阅0>。 为避免支付超出您需要的费用,请<1>检查您的订阅1>。",
"notification_personal_subscription_not_required_due_to_affiliation": " 好消息!您的组织 __institutionName__ 与 Overleaf 有合作关系。您可以取消您的个人订阅,而不会失去访问您的任何利益。",
"notification_project_invite": "__userName__ 想让您加入 __projectName__ 加入项目",
diff --git a/services/web/scripts/add_notification_ieee_collabratec_users.js b/services/web/scripts/add_notification_ieee_collabratec_users.js
deleted file mode 100644
index 1e31c3bb38..0000000000
--- a/services/web/scripts/add_notification_ieee_collabratec_users.js
+++ /dev/null
@@ -1,165 +0,0 @@
-const path = require('path')
-const fs = require('fs')
-const NotificationsBuilder = require('../app/src/Features/Notifications/NotificationsBuilder')
-const { waitForDb } = require('../app/src/infrastructure/mongodb')
-const { Subscription } = require('../app/src/models/Subscription')
-const minimist = require('minimist')
-const { db } = require('../app/src/infrastructure/mongodb')
-const { promiseMapWithLimit } = require('@overleaf/promise-utils')
-
-/**
- * This script is used to notify some users in the IEEEPublications group that
- * they will lose access to Overleaf.
- *
- * Parameters:
- * --filename: the filename of the JSON file containing emails of users that
- * should **not** be notified.
- * --commit: if present, the script will commit the changes to the database.
- *
- * Usage:
- * - dry run:
- * node add_notification_ieee_collabratec_users.js --filename=emails.json
- * - commit:
- * node add_notification_ieee_collabratec_users.js --filename=emails.json --commit
- */
-
-let COMMIT = false
-let EMAILS_FILENAME
-
-/**
- * The IEEE have provided us with a list of active users that should not be removed
- * (and therefore not notified). This method retrives those users.
- */
-function getActiveUserEmails(filename) {
- const data = fs.readFileSync(path.join(__dirname, filename), 'utf8')
- const emailsArray = JSON.parse(data)
- const emailsSet = new Set(emailsArray)
- console.log(
- `Read ${emailsSet.size} (${emailsArray.length} in array) emails from ${filename}`
- )
- return emailsSet
-}
-
-async function getIEEEUsers() {
- return await db.subscriptions
- .aggregate([
- { $match: { teamName: 'IEEEPublications' } },
- { $unwind: '$member_ids' },
- {
- $lookup: {
- from: 'users',
- localField: 'member_ids',
- foreignField: '_id',
- as: 'member_details',
- },
- },
- {
- $project: {
- _id: 1,
- teamName: 1,
- 'member_details._id': 1,
- 'member_details.email': 1,
- 'member_details.emails.email': 1,
- },
- },
- ])
- .toArray()
-}
-
-async function main() {
- const start = performance.now()
-
- if (!EMAILS_FILENAME) {
- throw new Error('No email filename provided')
- }
-
- await waitForDb()
- const subscription = await Subscription.findOne({
- teamName: 'IEEEPublications',
- })
-
- if (!subscription) {
- console.error(`No IEEEPublications group subscription found so quitting`)
- return
- }
-
- // First we remove all existing Collabratec retirement notifications
- if (COMMIT) {
- await db.notifications.deleteMany({
- key: 'notification-ieee-collabratec-retirement',
- })
- }
-
- let totalUsers = 0
- let totalUsersNotified = 0
-
- const usersArray = await getIEEEUsers()
- const activeUsers = getActiveUserEmails(EMAILS_FILENAME)
-
- const activeUsersFound = new Set()
-
- // Then go through each collabratec user to see if we need to notify them
- await promiseMapWithLimit(10, usersArray, async member => {
- if (totalUsers % 5000 === 0)
- console.log(
- `notified: ${totalUsersNotified} - progress: ${totalUsers} / ${usersArray.length}`
- )
-
- totalUsers = totalUsers + 1
-
- const userDetails = member.member_details[0]
-
- for (const email of userDetails.emails) {
- if (activeUsers.has(email.email)) {
- activeUsersFound.add(email.email)
- return
- }
- }
-
- if (COMMIT) {
- await NotificationsBuilder.promises
- .ieeeCollabratecRetirement(userDetails._id.toString())
- .create()
- }
-
- totalUsersNotified += 1
- })
-
- console.log(`Found ${totalUsers} users in IEEEPublications group`)
-
- console.log(
- `Found ${totalUsersNotified} users in IEEEPublications group to notify`
- )
-
- console.log(`Found ${activeUsersFound.size} active users`)
-
- const activeUsersNotFound = Array.from(activeUsers).filter(
- user => !activeUsersFound.has(user)
- )
-
- console.log(`${activeUsersNotFound.length} IEEE active users not found:`)
- console.log(activeUsersNotFound)
-
- const end = performance.now()
- console.log(`Took ${end - start} ms`)
-}
-
-const setup = () => {
- const argv = minimist(process.argv.slice(2))
- COMMIT = argv.commit !== undefined
- EMAILS_FILENAME = argv.filename
- if (!COMMIT) {
- console.warn('Doing dry run. Add --commit to commit changes')
- }
-}
-
-setup()
-
-main()
- .then(() => {
- process.exit(0)
- })
- .catch(err => {
- console.error(err)
- process.exit(1)
- })
diff --git a/services/web/scripts/remove_unwanted_ieee_collabratec_users.js b/services/web/scripts/remove_unwanted_ieee_collabratec_users.js
deleted file mode 100644
index 64d0d1a373..0000000000
--- a/services/web/scripts/remove_unwanted_ieee_collabratec_users.js
+++ /dev/null
@@ -1,196 +0,0 @@
-const path = require('path')
-const fs = require('fs')
-const AnalyticsManager = require('../app/src/Features/Analytics/AnalyticsManager')
-const { waitForDb } = require('../app/src/infrastructure/mongodb')
-const { Subscription } = require('../app/src/models/Subscription')
-const minimist = require('minimist')
-const { db } = require('../app/src/infrastructure/mongodb')
-const { promiseMapWithLimit } = require('@overleaf/promise-utils')
-const _ = require('lodash')
-
-/**
- * This script is used to remove some users from the IEEEPublications group.
- *
- * Parameters:
- * --filename: the filename of the JSON file containing emails of users that
- * should **not** be removed
- * --commit: if present, the script will commit the changes to the database.
- *
- * Usage:
- * - dry run:
- * node scripts/remove_unwanted_ieee_collabratec_users.js --filename=emails-to-keep.json
- * - commit:
- * node scripts/remove_unwanted_ieee_collabratec_users.js --filename=emails-to-keep.json --commit
- */
-
-let COMMIT = false
-let EMAILS_FILENAME
-
-/**
- * The IEEE have provided us with a list of active users that should not be removed
- * This method retrieves those users.
- */
-function getActiveUserEmails(filename) {
- const data = fs.readFileSync(path.join(__dirname, filename), 'utf8')
- const emailsArray = JSON.parse(data)
- const emailsSet = new Set(emailsArray)
- console.log(
- `Read ${emailsSet.size} (${emailsArray.length} in array) emails from ${filename}`
- )
- return emailsSet
-}
-
-async function getIEEEUsers() {
- const results = await db.subscriptions
- .aggregate([
- { $match: { teamName: 'IEEEPublications' } },
- { $unwind: '$member_ids' },
- {
- $lookup: {
- from: 'users',
- localField: 'member_ids',
- foreignField: '_id',
- as: 'member_details',
- },
- },
- {
- $project: {
- _id: 1,
- teamName: 1,
- 'member_details._id': 1,
- 'member_details.email': 1,
- 'member_details.emails.email': 1,
- },
- },
- ])
- .toArray()
-
- return results
- .map(subscription => subscription.member_details[0])
- .filter(Boolean)
-}
-
-async function main() {
- const start = performance.now()
-
- if (!EMAILS_FILENAME) {
- throw new Error('No email filename provided')
- }
-
- await waitForDb()
- const subscription = await Subscription.findOne({
- teamName: 'IEEEPublications',
- })
-
- if (!subscription) {
- console.error(`No IEEEPublications group subscription found so quitting`)
- return
- }
-
- /**
- * @type {string[]}
- */
- const oldMemberIds = subscription.member_ids.map(id => id.toString())
-
- console.log(
- `Found ${oldMemberIds.length} members_ids in IEEEPublications group`
- )
-
- const usersArray = await getIEEEUsers()
- console.log(
- `Found ${usersArray.length} users in IEEEPublications group. (${oldMemberIds.length - usersArray.length} missing)`
- )
-
- const activeUsers = getActiveUserEmails(EMAILS_FILENAME)
-
- const activeUsersFound = new Set()
-
- /**
- * @type {string[]}
- */
- const memberIdsToRemove = []
-
- let index = 0
-
- // Then go through each collabratec user to see if we need to remove them
- await promiseMapWithLimit(10, usersArray, async userDetails => {
- if (index % 1000 === 0)
- console.log(
- `progress: ${index} / ${usersArray.length} (${memberIdsToRemove.length} to remove)`
- )
-
- index = index + 1
-
- if (COMMIT) {
- await AnalyticsManager.setUserPropertyForUser(
- userDetails._id.toString(),
- 'ieee-retirement',
- true
- )
- }
-
- for (const email of userDetails.emails) {
- if (activeUsers.has(email.email)) {
- activeUsersFound.add(email.email)
- return
- }
- }
-
- memberIdsToRemove.push(userDetails._id.toString())
- })
-
- console.log(`Found ${memberIdsToRemove.length} users to remove`)
-
- /**
- * @type {string[]}
- */
- const memberIdsToKeep = _.difference(oldMemberIds, memberIdsToRemove)
-
- console.log(`Keeping ${memberIdsToKeep.length} users`)
-
- if (COMMIT) {
- await Subscription.updateOne(
- { teamName: 'IEEEPublications' },
- { member_ids: memberIdsToKeep }
- )
- }
-
- console.log(`Found ${activeUsersFound.size} active users`)
-
- const activeUsersNotFound = Array.from(activeUsers).filter(
- user => !activeUsersFound.has(user)
- )
-
- console.log(`${activeUsersNotFound.length} IEEE active users not found:`)
- console.log(activeUsersNotFound)
-
- const subscriptionAfter = await Subscription.findOne({
- teamName: 'IEEEPublications',
- })
- console.log(
- `There are now ${subscriptionAfter?.member_ids?.length} members_ids in IEEEPublications group`
- )
-
- const end = performance.now()
- console.log(`Took ${end - start} ms`)
-}
-
-const setup = () => {
- const argv = minimist(process.argv.slice(2))
- COMMIT = argv.commit !== undefined
- EMAILS_FILENAME = argv.filename
- if (!COMMIT) {
- console.warn('Doing dry run. Add --commit to commit changes')
- }
-}
-
-setup()
-
-main()
- .then(() => {
- process.exit(0)
- })
- .catch(err => {
- console.error(err)
- process.exit(1)
- })
diff --git a/services/web/types/project/dashboard/notification.ts b/services/web/types/project/dashboard/notification.ts
index 7a19eec4a6..6fc868e6ff 100644
--- a/services/web/types/project/dashboard/notification.ts
+++ b/services/web/types/project/dashboard/notification.ts
@@ -7,7 +7,6 @@ type TemplateKey =
| 'notification_dropbox_unlinked_due_to_lapsed_reconfirmation'
| 'notification_group_invitation'
| 'notification_personal_and_group_subscriptions'
- | 'notification_ieee_collabratec_retirement'
type NotificationBase = {
_id?: number
@@ -74,11 +73,6 @@ export interface NotificationGroupInvitation extends NotificationBase {
}
}
-export interface NotificationIeeeCollabratecRetirement
- extends NotificationBase {
- templateKey: Extract
-}
-
export type Notification =
| NotificationProjectInvite
| NotificationWFH2020UpgradeOffer
@@ -87,7 +81,6 @@ export type Notification =
| NotificationDropboxDuplicateProjectNames
| NotificationDropboxUnlinkedDueToLapsedReconfirmation
| NotificationGroupInvitation
- | NotificationIeeeCollabratecRetirement
export type Institution = {
_id?: number