<commit_before>/*
 * Copyright (C) 2021 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import I18n from 'i18n!discussion_posts'
import PropTypes from 'prop-types'
import React, {useMemo} from 'react'

import {Menu} from '@instructure/ui-menu'
import {
  IconMoreLine,
  IconNextUnreadLine,
  IconDiscussionLine,
  IconEditLine,
  IconTrashLine,
  IconSpeedGraderLine,
  IconMarkAsReadSolid,
  IconMarkAsReadLine,
  IconWarningBorderlessSolid
} from '@instructure/ui-icons'

import {IconButton} from '@instructure/ui-buttons'
import {Text} from '@instructure/ui-text'
import {Flex} from '@instructure/ui-flex'

// Reason: <Menu> in v6 of InstUI requires a ref to bind too or errors
// are produced by the menu causing the page to scroll all over the place
export const ThreadActions = props => {
  const menuItems = useMemo(() => {
    return getMenuConfigs({
      onMarkAllAsRead: props.onMarkAllAsRead,
      onMarkAllAsUnread: props.onMarkAllAsUnread,
      isUnread: props.isUnread,
      onToggleUnread: props.onToggleUnread,
      goToTopic: props.goToTopic,
      goToParent: props.goToParent,
      onEdit: props.onEdit,
      onDelete: props.onDelete,
      onOpenInSpeedGrader: props.onOpenInSpeedGrader,
      onMarkThreadAsRead: props.onMarkThreadAsRead,
      onReport: props.onReport,
      isReported: props.isReported
    }).map(config => renderMenuItem({...config}, props.id))
  }, [props])

  return (
    <Flex justifyItems="end">
      <Flex.Item>
        {!props.isSearch && (
          <Menu
            placement="bottom"
            key={`threadActionMenu-${props.id}`}
            trigger={
              <IconButton
                size="small"
                screenReaderLabel={I18n.t('Manage Discussion')}
                renderIcon={IconMoreLine}
                withBackground={false}
                withBorder={false}
                data-testid="thread-actions-menu"
              />
            }
          >
            {menuItems}
          </Menu>
        )}
      </Flex.Item>
    </Flex>
  )
}

const getMenuConfigs = props => {
  const options = []
  if (props.onMarkAllAsRead) {
    options.push({
      key: 'markAllAsRead',
      icon: <IconNextUnreadLine />,
      label: I18n.t('Mark All as Read'),
      selectionCallback: props.onMarkAllAsRead
    })
  }
  if (props.onMarkAllAsUnread) {
    options.push({
      key: 'markAllAsUnRead',
      icon: <IconNextUnreadLine />,
      label: I18n.t('Mark All as Unread'),
      selectionCallback: props.onMarkAllAsUnread
    })
  }
  if (props.isUnread) {
    options.push({
      key: 'markAsRead',
      icon: <IconNextUnreadLine />,
      label: I18n.t('Mark as Read'),
      selectionCallback: props.onToggleUnread
    })
  } else {
    options.push({
      key: 'markAsUnread',
      icon: <IconNextUnreadLine />,
      label: I18n.t('Mark as Unread'),
      selectionCallback: props.onToggleUnread
    })
  }
  if (props.onMarkThreadAsRead) {
    options.push({
      key: 'markThreadAsRead',
      icon: <IconMarkAsReadLine />,
      label: I18n.t('Mark Thread as Read'),
      selectionCallback: () => {
        props.onMarkThreadAsRead(true)
      }
    })
  }
  if (props.onMarkThreadAsRead) {
    options.push({
      key: 'markThreadAsUnRead',
      icon: <IconMarkAsReadSolid />,
      label: I18n.t('Mark Thread as Unread'),
      selectionCallback: () => {
        props.onMarkThreadAsRead(false)
      }
    })
  }
  if (props.goToTopic) {
    options.push({
      key: 'toTopic',
      icon: <IconDiscussionLine />,
      label: I18n.t('Go To Topic'),
      selectionCallback: props.goToTopic
    })
  }
  if (props.goToParent) {
    options.push({
      key: 'toParent',
      icon: <IconDiscussionLine />,
      label: I18n.t('Go To Parent'),
      selectionCallback: props.goToParent
    })
  }
  if (props.onEdit) {
    options.push({
      key: 'edit',
      icon: <IconEditLine />,
      label: I18n.t('Edit'),
      selectionCallback: props.onEdit
    })
  }
  if (props.onDelete) {
    options.push({
      key: 'delete',
      icon: <IconTrashLine />,
      label: I18n.t('Delete'),
      selectionCallback: props.onDelete
    })
  }
  if (props.onOpenInSpeedGrader) {
    options.push({
      key: 'inSpeedGrader',
      icon: <IconSpeedGraderLine />,
      label: I18n.t('Open in SpeedGrader'),
      selectionCallback: props.onOpenInSpeedGrader
    })
  }
  if (props.onReport) {
    options.push({
      key: 'separator',
      separator: true
    })
    options.push({
      key: 'report',
      icon: <IconWarningBorderlessSolid />,
      label: props.isReported ? I18n.t('Reported') : I18n.t('Report'),
      selectionCallback: props.onReport,
      disabled: props.isReported,
      color: 'warning'
    })
  }
  return options
}

const renderMenuItem = (
  {selectionCallback, icon, label, key, separator = false, disabled = false, color = 'primary'},
  id
) => {
  return separator ? (
    <Menu.Separator key={key} />
  ) : (
    <Menu.Item
      key={`${key}-${id}`}
      onSelect={() => {
        selectionCallback(key)
      }}<commit_msg>Change Menu Text Color for Reporting Option<commit_after>/*
 * Copyright (C) 2021 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import I18n from 'i18n!discussion_posts'
import PropTypes from 'prop-types'
import React, {useMemo} from 'react'

import {Menu} from '@instructure/ui-menu'
import {
  IconMoreLine,
  IconNextUnreadLine,
  IconDiscussionLine,
  IconEditLine,
  IconTrashLine,
  IconSpeedGraderLine,
  IconMarkAsReadSolid,
  IconMarkAsReadLine,
  IconWarningBorderlessSolid
} from '@instructure/ui-icons'

import {IconButton} from '@instructure/ui-buttons'
import {Text} from '@instructure/ui-text'
import {Flex} from '@instructure/ui-flex'

// Reason: <Menu> in v6 of InstUI requires a ref to bind too or errors
// are produced by the menu causing the page to scroll all over the place
export const ThreadActions = props => {
  const menuItems = useMemo(() => {
    return getMenuConfigs({
      onMarkAllAsRead: props.onMarkAllAsRead,
      onMarkAllAsUnread: props.onMarkAllAsUnread,
      isUnread: props.isUnread,
      onToggleUnread: props.onToggleUnread,
      goToTopic: props.goToTopic,
      goToParent: props.goToParent,
      onEdit: props.onEdit,
      onDelete: props.onDelete,
      onOpenInSpeedGrader: props.onOpenInSpeedGrader,
      onMarkThreadAsRead: props.onMarkThreadAsRead,
      onReport: props.onReport,
      isReported: props.isReported
    }).map(config => renderMenuItem({...config}, props.id))
  }, [props])

  return (
    <Flex justifyItems="end">
      <Flex.Item>
        {!props.isSearch && (
          <Menu
            placement="bottom"
            key={`threadActionMenu-${props.id}`}
            trigger={
              <IconButton
                size="small"
                screenReaderLabel={I18n.t('Manage Discussion')}
                renderIcon={IconMoreLine}
                withBackground={false}
                withBorder={false}
                data-testid="thread-actions-menu"
              />
            }
          >
            {menuItems}
          </Menu>
        )}
      </Flex.Item>
    </Flex>
  )
}

const getMenuConfigs = props => {
  const options = []
  if (props.onMarkAllAsRead) {
    options.push({
      key: 'markAllAsRead',
      icon: <IconNextUnreadLine />,
      label: I18n.t('Mark All as Read'),
      selectionCallback: props.onMarkAllAsRead
    })
  }
  if (props.onMarkAllAsUnread) {
    options.push({
      key: 'markAllAsUnRead',
      icon: <IconNextUnreadLine />,
      label: I18n.t('Mark All as Unread'),
      selectionCallback: props.onMarkAllAsUnread
    })
  }
  if (props.isUnread) {
    options.push({
      key: 'markAsRead',
      icon: <IconNextUnreadLine />,
      label: I18n.t('Mark as Read'),
      selectionCallback: props.onToggleUnread
    })
  } else {
    options.push({
      key: 'markAsUnread',
      icon: <IconNextUnreadLine />,
      label: I18n.t('Mark as Unread'),
      selectionCallback: props.onToggleUnread
    })
  }
  if (props.onMarkThreadAsRead) {
    options.push({
      key: 'markThreadAsRead',
      icon: <IconMarkAsReadLine />,
      label: I18n.t('Mark Thread as Read'),
      selectionCallback: () => {
        props.onMarkThreadAsRead(true)
      }
    })
  }
  if (props.onMarkThreadAsRead) {
    options.push({
      key: 'markThreadAsUnRead',
      icon: <IconMarkAsReadSolid />,
      label: I18n.t('Mark Thread as Unread'),
      selectionCallback: () => {
        props.onMarkThreadAsRead(false)
      }
    })
  }
  if (props.goToTopic) {
    options.push({
      key: 'toTopic',
      icon: <IconDiscussionLine />,
      label: I18n.t('Go To Topic'),
      selectionCallback: props.goToTopic
    })
  }
  if (props.goToParent) {
    options.push({
      key: 'toParent',
      icon: <IconDiscussionLine />,
      label: I18n.t('Go To Parent'),
      selectionCallback: props.goToParent
    })
  }
  if (props.onEdit) {
    options.push({
      key: 'edit',
      icon: <IconEditLine />,
      label: I18n.t('Edit'),
      selectionCallback: props.onEdit
    })
  }
  if (props.onDelete) {
    options.push({
      key: 'delete',
      icon: <IconTrashLine />,
      label: I18n.t('Delete'),
      selectionCallback: props.onDelete
    })
  }
  if (props.onOpenInSpeedGrader) {
    options.push({
      key: 'inSpeedGrader',
      icon: <IconSpeedGraderLine />,
      label: I18n.t('Open in SpeedGrader'),
      selectionCallback: props.onOpenInSpeedGrader
    })
  }
  if (props.onReport) {
    options.push({
      key: 'separator',
      separator: true
    })
    options.push({
      key: 'report',
      icon: <IconWarningBorderlessSolid />,
      label: props.isReported ? I18n.t('Reported') : I18n.t('Report'),
      selectionCallback: props.onReport,
      disabled: props.isReported
    })
  }
  return options
}

const renderMenuItem = (
  {selectionCallback, icon, label, key, separator = false, disabled = false, color = 'primary'},
  id
) => {
  return separator ? (
    <Menu.Separator key={key} />
  ) : (
    <Menu.Item
      key={`${key}-${id}`}
      onSelect={() => {
        selectionCallback(key)
      }}
{'fraction_non_alphanumeric': 0.1215149921094161, 'fraction_numerical': 0.006663159740487463, 'mean_word_length': 2.595020485345099, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5939843', 'n_tokens_mistral': 3670, 'n_tokens_neox': 3580, 'n_words': 852}