tolgee / tolgee-platform

Developer & translator friendly web-based localization platform

Home Page:https://tolgee.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Activity and notifications

ZuzanaOdstrcilova opened this issue · comments

Activity view on dashboard
Image

  • redesign activity view (infinite scroll, activity stream button)
  • implement logic - grouping activities (time, user, activity)
  • implement / discuss basic filters on dashboard (user, activity...)
  • hover, on click activity group in dialog
    Image
  • button activity stream will open page with all activities (needs discussion if it will be in menu)

Activity stream
Image

  • new full screen view of activities (same content like in activity on dash, but bigger, better filters)
  • filters, (infinite scroll or pagination - to be discussed)
    Image
  • there are examples of groups and tables for different content
    Image

Notifications
Image

  • design of notifiations
  • logic (notifications are grouped, hide number after opening menu, stream of last notifications, just main events and settings)
  • settings - to be discussed

Emails

  • sumarization of activities in spec time - discussion
  • specific notifications like comments could be send as one notification
  • settings
  • UI to disuss, links to platform

Mentions in comments

  • When user is mentioned in translation comment, we should notify them.

More in detail in Figma:
https://www.figma.com/design/wVmz098ZrSxswOI0nbIjQ2/Design-system-Tolgee?node-id=1111-22910&t=DjPqF3TlX7U7SGkN-1

Unification of these issues:

Notes from old issues - designed in Figma:

  • The rows have hover state, while there are not clickable
  • There is 3 dots on the right, while is suggest it will open dropdown, while it opens detail dialog instead. This should be removed and the row should be clickable
  • For larger operation (like modification of multiple fields on key) it shows ... under each section. Please get rid of it.
  • When user imports data they cannot see what data is imported
  • There is load more button, it should be probably changed to infinite scroll
  • There should exist a special view with filtering by user
  • For operations without special detail, the clicking should be disabled
  • fix issue with activity while adding screenshots
  • Add a filter by language in the Members section
  • Add a filter by language in the Activity section of the dashboard
  • problem: load more (activity), ideas: Being able to open in full width the Activity part of the dashboard, Having a pagination that ease the navigation throughout the activities
  • E-mail notification from comments
  • Filtering of activities
  • Discord
  • History - key
  • Pluralization in activity

We should also solve changes in plurals ans switching from/to plurals - how to visualize them in history and activity.
#2172

user feedback about imports activity: the absence of a history of imports feature makes it challenging to track past actions.
Well the thing that I mean was simply a history of imports in import section (with some details like the file name, date, user, number of keys if possible)

I've created this activity groups list, so we can group the activities in the list:

enum class ActivityGroup(
  val sourceActivityTypes: List<ActivityType>,
  val allowedEntityModifications: List<EntityModification<*>>,
) {
  SET_TRANSLATION_STATE(
    listOf(ActivityType.SET_TRANSLATION_STATE, ActivityType.COMPLEX_EDIT),
    listOf(
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(Translation::state, Translation::outdated, Translation::mtProvider),
      ),
    ),
  ),

  SET_TRANSLATIONS(
    listOf(ActivityType.SET_TRANSLATIONS, ActivityType.COMPLEX_EDIT),
    listOf(
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.ADD, RevisionType.DEL, RevisionType.MOD),
      ),
    ),
  ),

  DISMISS_AUTO_TRANSLATED_STATE(
    listOf(ActivityType.DISMISS_AUTO_TRANSLATED_STATE),
    listOf(
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(Translation::auto, Translation::mtProvider),
        allowedValues = mapOf(Translation::mtProvider to null, Translation::auto to false),
      ),
    ),
  ),

  SET_OUTDATED_FLAG(
    listOf(ActivityType.SET_OUTDATED_FLAG),
    listOf(
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(Translation::outdated),
      ),
    ),
  ),

  TRANSLATION_COMMENT_ADD(
    listOf(ActivityType.TRANSLATION_COMMENT_ADD),
    listOf(
      EntityModification(
        entityClass = TranslationComment::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.ADD),
      )
    ),
  ),

  TRANSLATION_COMMENT_DELETE(
    listOf(ActivityType.TRANSLATION_COMMENT_DELETE),
    listOf(
      EntityModification(
        entityClass = TranslationComment::class,
        revisionTypes = listOf(RevisionType.DEL),
      ),
    ),
  ),

  TRANSLATION_COMMENT_EDIT(
    listOf(ActivityType.TRANSLATION_COMMENT_EDIT),
    listOf(
      EntityModification(
        entityClass = TranslationComment::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(TranslationComment::text),
      ),
    ),
  ),

  TRANSLATION_COMMENT_SET_STATE(
    listOf(ActivityType.TRANSLATION_COMMENT_SET_STATE),
    listOf(
      EntityModification(
        entityClass = TranslationComment::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(TranslationComment::state),
      ),
    ),
  ),

  SCREENSHOT_DELETE(
    listOf(ActivityType.SCREENSHOT_DELETE, ActivityType.COMPLEX_EDIT),
    listOf(
      EntityModification(
        entityClass = Screenshot::class,
        revisionTypes = listOf(RevisionType.DEL),
      ),
      EntityModification(
        entityClass = KeyScreenshotReference::class,
        revisionTypes = listOf(RevisionType.DEL),
      ),
    ),
  ),

  SCREENSHOT_ADD(
    listOf(ActivityType.SCREENSHOT_ADD, ActivityType.COMPLEX_EDIT),
    listOf(
      EntityModification(
        entityClass = Screenshot::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
      EntityModification(
        entityClass = KeyScreenshotReference::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
    ),
  ),

  KEY_TAGS_EDIT(
    listOf(
      ActivityType.KEY_TAGS_EDIT, ActivityType.COMPLEX_EDIT, ActivityType.BATCH_TAG_KEYS,
      ActivityType.BATCH_UNTAG_KEYS
    ),
    listOf(
      EntityModification(
        entityClass = KeyMeta::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(KeyMeta::tags),
      ),
      EntityModification(
        entityClass = Tag::class,
        revisionTypes = listOf(RevisionType.ADD, RevisionType.DEL),
      ),
    ),
  ),

  KEY_NAME_EDIT(
    listOf(ActivityType.KEY_NAME_EDIT, ActivityType.COMPLEX_EDIT),
    listOf(
      EntityModification(
        entityClass = Key::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(Key::name, Key::namespace),
      ),
      EntityModification(
        entityClass = Namespace::class,
        revisionTypes = listOf(RevisionType.ADD, RevisionType.DEL),
      ),
    )
  ),

  KEY_DELETE(
    listOf(ActivityType.KEY_DELETE),
    listOf(
      EntityModification(
        entityClass = Key::class,
        revisionTypes = listOf(RevisionType.DEL),
      ),
    ),
  ),

  KEY_CREATE(
    listOf(ActivityType.CREATE_KEY),
    listOf(
      EntityModification(
        entityClass = Key::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
      EntityModification(
        entityClass = KeyMeta::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
    ),
  ),

  IMPORT(
    listOf(ActivityType.IMPORT),
    listOf(
      EntityModification(
        entityClass = Key::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
      EntityModification(
        entityClass = KeyMeta::class,
        revisionTypes = listOf(RevisionType.ADD, RevisionType.MOD),
        modificationProps = listOf(KeyMeta::custom, KeyMeta::description),
      ),
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
      EntityModification(
        entityClass = Namespace::class,
        revisionTypes = listOf(RevisionType.ADD, RevisionType.DEL),
      ),
    )
  ),

  CREATE_LANGUAGE(
    listOf(ActivityType.CREATE_LANGUAGE),
    listOf(
      EntityModification(
        entityClass = Language::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
    )
  ),

  EDIT_LANGUAGE(
    listOf(ActivityType.EDIT_LANGUAGE),
    listOf(
      EntityModification(
        entityClass = Language::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(Language::name, Language::tag, Language::originalName, Language::flagEmoji),
      ),
    )
  ),

  DELETE_LANGUAGE(
    listOf(ActivityType.DELETE_LANGUAGE),
    listOf(
      EntityModification(
        entityClass = Language::class,
        revisionTypes = listOf(RevisionType.DEL),
      ),
    )
  ),

  CREATE_PROJECT(
    listOf(ActivityType.CREATE_PROJECT),
    listOf(
      EntityModification(
        entityClass = Project::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
    )
  ),

  EDIT_PROJECT(
    listOf(ActivityType.EDIT_PROJECT),
    listOf(
      EntityModification(
        entityClass = Project::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(
          Project::name,
          Project::description,
          Project::baseLanguage,
          Project::defaultNamespace,
          Project::avatarHash
        ),
      ),
    )
  ),

  NAMESPACE_EDIT(
    listOf(ActivityType.NAMESPACE_EDIT, ActivityType.BATCH_SET_KEYS_NAMESPACE),
    listOf(
      EntityModification(
        entityClass = Namespace::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(Namespace::name),
      ),
    )
  ),

  BATCH_PRE_TRANSLATE_BY_TM(
    listOf(ActivityType.BATCH_PRE_TRANSLATE_BY_TM),
    listOf(
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.MOD, RevisionType.ADD),
        modificationProps = listOf(Translation::state, Translation::text, Translation::outdated, Translation::auto),
      ),
    )
  ),

  BATCH_MACHINE_TRANSLATE(
    listOf(ActivityType.BATCH_MACHINE_TRANSLATE),
    listOf(
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.MOD, RevisionType.ADD),
        modificationProps = listOf(Translation::state, Translation::text, Translation::outdated, Translation::auto),
      ),
    )
  ),

  AUTO_TRANSLATE(
    listOf(ActivityType.AUTO_TRANSLATE),
    listOf(
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.MOD, RevisionType.ADD),
        modificationProps = listOf(Translation::state, Translation::text, Translation::outdated, Translation::auto),
      ),
    )
  ),

  BATCH_CLEAR_TRANSLATIONS(
    listOf(ActivityType.BATCH_CLEAR_TRANSLATIONS),
    listOf(
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(Translation::state, Translation::text, Translation::outdated, Translation::auto),
        allowedValues = mapOf(
          Translation::text to null,
          Translation::state to null,
          Translation::outdated to false,
          Translation::auto to false
        ),
      ),
    )
  ),

  BATCH_COPY_TRANSLATIONS(
    listOf(ActivityType.BATCH_COPY_TRANSLATIONS),
    listOf(
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.MOD, RevisionType.ADD),
        modificationProps = listOf(Translation::state, Translation::text, Translation::outdated, Translation::auto),
      ),
    )
  ),

  BATCH_SET_TRANSLATION_STATE(
    listOf(ActivityType.BATCH_SET_TRANSLATION_STATE),
    listOf(
      EntityModification(
        entityClass = Translation::class,
        revisionTypes = listOf(RevisionType.MOD),
        modificationProps = listOf(Translation::state, Translation::outdated, Translation::auto),
      ),
    )
  ),

  CONTENT_DELIVERY_CONFIG_CREATE(
    listOf(ActivityType.CONTENT_DELIVERY_CONFIG_CREATE),
    listOf(
      EntityModification(
        entityClass = ContentDeliveryConfig::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
    )
  ),

  CONTENT_DELIVERY_CONFIG_UPDATE(
    listOf(ActivityType.CONTENT_DELIVERY_CONFIG_UPDATE),
    listOf(
      EntityModification(
        entityClass = ContentDeliveryConfig::class,
        revisionTypes = listOf(RevisionType.MOD),
      ),
    )
  ),


  CONTENT_DELIVERY_CONFIG_DELETE(
    listOf(ActivityType.CONTENT_DELIVERY_CONFIG_UPDATE),
    listOf(
      EntityModification(
        entityClass = ContentDeliveryConfig::class,
        revisionTypes = listOf(RevisionType.DEL),
      ),
    )
  ),

  CONTENT_STORAGE_CREATE(
    listOf(ActivityType.CONTENT_STORAGE_CREATE),
    listOf(
      EntityModification(
        entityClass = ContentStorage::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
    )
  ),

  CONTENT_STORAGE_UPDATE(
    listOf(ActivityType.CONTENT_STORAGE_UPDATE),
    listOf(
      EntityModification(
        entityClass = ContentStorage::class,
        revisionTypes = listOf(RevisionType.MOD),
      ),
    )
  ),

  CONTENT_STORAGE_DELETE(
    listOf(ActivityType.CONTENT_STORAGE_DELETE),
    listOf(
      EntityModification(
        entityClass = ContentStorage::class,
        revisionTypes = listOf(RevisionType.DEL),
      ),
    )
  ),

  WEBHOOK_CONFIG_CREATE(
    listOf(ActivityType.WEBHOOK_CONFIG_CREATE),
    listOf(
      EntityModification(
        entityClass = WebhookConfig::class,
        revisionTypes = listOf(RevisionType.ADD),
      ),
    )
  ),

  WEBHOOK_CONFIG_UPDATE(
    listOf(ActivityType.WEBHOOK_CONFIG_CREATE),
    listOf(
      EntityModification(
        entityClass = WebhookConfig::class,
        revisionTypes = listOf(RevisionType.MOD),
      ),
    )
  ),

  WEBHOOK_CONFIG_DELETE(
    listOf(ActivityType.WEBHOOK_CONFIG_CREATE),
    listOf(
      EntityModification(
        entityClass = WebhookConfig::class,
        revisionTypes = listOf(RevisionType.DEL),
      ),
    )
  ),
}