Browse Source

Merge pull request #19398 from overleaf/rh-rm-ieee-notification

[web] Remove IEEE Collabratec notification

GitOrigin-RevId: 14ec3e50ed4913b815620f5215df59b17fc03054
roo hutton 2 years ago
parent
commit
523e340a0d

+ 0 - 27
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

+ 0 - 1
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": "",

+ 0 - 3
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' ? (
         <GroupInvitationNotification notification={notification} />
-      ) : templateKey === 'notification_ieee_collabratec_retirement' ? (
-        <IEEERetirementBanner id={id} />
       ) : templateKey === 'notification_personal_and_group_subscriptions' ? (
         <Notification
           type="warning"

+ 0 - 67
services/web/frontend/js/features/project-list/components/notifications/ieee-retirement-banner.tsx

@@ -1,67 +0,0 @@
-import { useCallback, useEffect } from 'react'
-import Notification from './notification'
-import { Trans } from 'react-i18next'
-import * as eventTracking from '../../../../infrastructure/event-tracking'
-import useAsyncDismiss from './hooks/useAsyncDismiss'
-
-let viewEventSent = false
-
-type IEEERetirementBannerProps = {
-  id: number | undefined
-}
-
-export default function IEEERetirementBanner({
-  id,
-}: IEEERetirementBannerProps) {
-  const { handleDismiss } = useAsyncDismiss()
-
-  const handleClose = useCallback(() => {
-    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 (
-    <Notification
-      type="warning"
-      onDismiss={handleClose}
-      content={
-        <Trans
-          i18nKey="notification_ieee_collabratec_retirement_message"
-          components={[
-            // eslint-disable-next-line jsx-a11y/anchor-has-content,react/jsx-key
-            <a href="/user/subscription" onClick={handleClickPlans} />,
-            // eslint-disable-next-line jsx-a11y/anchor-has-content,react/jsx-key
-            <a href="mailto:authors@ieee.org" onClick={handleClickEmail} />,
-          ]}
-        />
-      }
-    />
-  )
-}

+ 0 - 1
services/web/locales/en.json

@@ -1291,7 +1291,6 @@
   "not_registered": "Not registered",
   "note_features_under_development": "<0>Please note</0> that features in this program are still being tested and actively developed. This means that they might <0>change</0>, be <0>removed</0> or <0>become part of a premium plan</0>",
   "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 plans</0>. Contact <1>authors@ieee.org</1> with any questions.",
   "notification_personal_and_group_subscriptions": "We’ve spotted that you’ve got <0>more than one active __appName__ subscription</0>. To avoid paying more than you need to, <1>review your subscriptions</1>.",
   "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": "<b>__userName__</b> would like you to join <b>__projectName__</b> <a class=\"btn btn-sm btn-info pull-right\" href=\"/project/__projectId__/invite/token/__token__\">Join Project</a>",

+ 0 - 1
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.org</0>。需要升级吗? <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": "<b>__userName__</b> 想让您加入 <b>__projectName__</b> <a class=\"btn btn-sm btn-info pull-right\" href=\"’/project/__projectId__/invite/token/__token__’\">加入项目</a>",

+ 0 - 165
services/web/scripts/add_notification_ieee_collabratec_users.js

@@ -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)
-  })

+ 0 - 196
services/web/scripts/remove_unwanted_ieee_collabratec_users.js

@@ -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)
-  })

+ 0 - 7
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<TemplateKey, 'notification_ieee_collabratec_retirement'>
-}
-
 export type Notification =
   | NotificationProjectInvite
   | NotificationWFH2020UpgradeOffer
@@ -87,7 +81,6 @@ export type Notification =
   | NotificationDropboxDuplicateProjectNames
   | NotificationDropboxUnlinkedDueToLapsedReconfirmation
   | NotificationGroupInvitation
-  | NotificationIeeeCollabratecRetirement
 
 export type Institution = {
   _id?: number