[Feedback] Implement sending feedback to zendesk
authorDmitry Pogrebnoy <dmitry.pogrebnoy@jetbrains.com>
Sat, 23 Oct 2021 10:32:51 +0000 (13:32 +0300)
committerintellij-monorepo-bot <intellij-monorepo-bot-no-reply@jetbrains.com>
Sat, 23 Oct 2021 10:44:24 +0000 (10:44 +0000)
GitOrigin-RevId: 6fce1555987c275991c2a58ae6fff3f7e56cc593

platform/feedback/intellij.platform.feedback.iml
platform/feedback/resources/forms/ProjectCreationFeedbackForm.xml [new file with mode: 0644]
platform/feedback/src/com/intellij/feedback/dialog/ProjectCreationFeedbackDialog.kt
platform/feedback/src/com/intellij/feedback/dialog/ProjectCreationFeedbackSystemInfo.kt
platform/feedback/src/com/intellij/feedback/dialog/ProjectCreationFeedbackSystemInfoData.kt [new file with mode: 0644]

index 66d2a25421c8360f8fd010d90b138f7b9bc83f91..8849486a0cb6d2a525e6cbd23d0b204dd09814d4 100644 (file)
@@ -33,5 +33,6 @@
     <orderEntry type="module" module-name="intellij.platform.ide.impl" />
     <orderEntry type="library" name="kotlinx-datetime" level="project" />
     <orderEntry type="library" name="kotlinx-datetime-jvm" level="project" />
+    <orderEntry type="module" module-name="intellij.platform.util.xmlDom" />
   </component>
 </module>
\ No newline at end of file
diff --git a/platform/feedback/resources/forms/ProjectCreationFeedbackForm.xml b/platform/feedback/resources/forms/ProjectCreationFeedbackForm.xml
new file mode 100644 (file)
index 0000000..3baa7a6
--- /dev/null
@@ -0,0 +1,8 @@
+<feedback url="https://www.jetbrains.com/feedback/feedback.jsp?product=IDEA&amp;build=$BUILD&amp;timezone=$TIMEZONE&amp;eval=$EVAL"
+          zendesk-form-id="360003391800" zendesk-url="https://jbs1454063113.zendesk.com">
+  <field id="360023122899" type="rating"/>
+  <field id="360000123480" type="project_type"/>
+  <field id="1900000924754" type="problems"/>
+  <field id="360003446920" type="problems_other"/>
+  <field id="1900000924774" type="system_info"/>
+</feedback>
\ No newline at end of file
index 4364c306f091f5ab14f0a0cccfc07c1f10a00b31..c8422aa4e5fc5875fcc4a301d51c13d9ef05c103 100644 (file)
@@ -2,10 +2,14 @@
 package com.intellij.feedback.dialog
 
 import com.intellij.feedback.bundle.FeedbackBundle
+import com.intellij.feedback.dialog.ProjectCreationFeedbackSystemInfoData.Companion.createProjectCreationFeedbackSystemInfoData
 import com.intellij.feedback.notification.ThanksForFeedbackNotification
 import com.intellij.ide.BrowserUtil
 import com.intellij.ide.feedback.RatingComponent
+import com.intellij.ide.feedback.ZenDeskRequests
 import com.intellij.openapi.application.ApplicationBundle
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.application.impl.ZenDeskForm
 import com.intellij.openapi.observable.properties.GraphPropertyImpl.Companion.graphProperty
 import com.intellij.openapi.observable.properties.PropertyGraph
 import com.intellij.openapi.project.Project
@@ -20,10 +24,13 @@ import com.intellij.ui.dsl.builder.*
 import com.intellij.ui.dsl.builder.panel
 import com.intellij.ui.dsl.gridLayout.Gaps
 import com.intellij.ui.layout.*
+import com.intellij.util.readXmlAsModel
 import com.intellij.util.ui.JBEmptyBorder
 import com.intellij.util.ui.JBFont
 import com.intellij.util.ui.JBUI
 import com.intellij.util.ui.UIUtil
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
 import java.awt.Dimension
 import java.awt.GridLayout
 import java.awt.event.ActionEvent
@@ -33,12 +40,27 @@ import javax.swing.JPanel
 
 class ProjectCreationFeedbackDialog(
   private val project: Project?,
-  private val createdProjectTypeName: String
+  createdProjectTypeName: String
 ) : DialogWrapper(project) {
 
   private val PRIVACY_POLICY_URL: String = "https://www.jetbrains.com/legal/docs/privacy/privacy.html"
   private val PRIVACY_POLICY_THIRD_PARTIES_URL = "https://www.jetbrains.com/legal/docs/privacy/third-parties.html"
 
+  private val DEFAULT_NO_EMAIL_ZENDESK_REQUESTER: String = "no_mail@jetbrains.com"
+
+  private val PATH_TO_FEEDBACK_FORM_XML = "forms/ProjectCreationFeedbackForm.xml"
+
+  private val TICKET_TITLE_ZENDESK = "Project Creation Feedback"
+  private val TICKET_DEFAULT_TEXT_ZENDESK = "This is an automatically created ticket by the feedback collection system in the IDE. " +
+                                            "All data is in custom fields."
+
+  private val TICKET_PROBLEMS_MULTISELECT_EMPTY_PROJECT_ID = "in-ide_empty_project"
+  private val TICKET_PROBLEMS_MULTISELECT_HARD_TO_FIND_ID = "in-ide_hard_to_find"
+  private val TICKET_PROBLEMS_MULTISELECT_LACK_OF_FRAMEWORK_ID = "in-ide_lack_of_framework"
+  private val TICKET_PROBLEMS_MULTISELECT_OTHER_ID = "in-ide_other_problem"
+
+  private val systemInfoData: ProjectCreationFeedbackSystemInfoData = createProjectCreationFeedbackSystemInfoData(createdProjectTypeName)
+
   private val propertyGraph = PropertyGraph()
   private val ratingProperty = propertyGraph.graphProperty { 0 }
   private val checkBoxNoProblemProperty = propertyGraph.graphProperty { false }
@@ -63,6 +85,8 @@ class ProjectCreationFeedbackDialog(
   private val textFieldOtherColumnSize = 41
   private val textAreaOverallFeedbackColumnSize = 42
 
+  private val jsonConverter = Json { prettyPrint = true }
+
   private val checkBoxFrameworkComponentPredicate = object : ComponentPredicate() {
     override fun addListener(listener: (Boolean) -> Unit) {
       checkBoxFrameworkProperty.afterChange {
@@ -83,7 +107,48 @@ class ProjectCreationFeedbackDialog(
 
   override fun doOKAction() {
     super.doOKAction()
-    ThanksForFeedbackNotification().notify(project)
+    ApplicationManager.getApplication().executeOnPooledThread {
+      val stream = ProjectCreationFeedbackDialog::class.java.classLoader.getResourceAsStream(PATH_TO_FEEDBACK_FORM_XML)
+                   ?: throw RuntimeException("Resource not found: $PATH_TO_FEEDBACK_FORM_XML")
+      val xmlElement = readXmlAsModel(stream)
+      val form = ZenDeskForm.parse(xmlElement)
+      ZenDeskRequests().submit(
+        form,
+        if (checkBoxEmailProperty.get()) textFieldEmailProperty.get() else DEFAULT_NO_EMAIL_ZENDESK_REQUESTER,
+        TICKET_TITLE_ZENDESK,
+        textAreaOverallFeedbackProperty.get().ifBlank { TICKET_DEFAULT_TEXT_ZENDESK },
+        mapOf("rating" to ratingProperty.get(),
+              "project_type" to systemInfoData.createdProjectTypeName,
+              "problems" to createProblemsResultList(),
+              "problems_other" to if (checkBoxOtherProperty.get()) textFieldOtherProblemProperty.get() else "",
+              "system_info" to jsonConverter.encodeToString(systemInfoData)),
+        {},
+        {}
+      )
+    }
+    ApplicationManager.getApplication().invokeLater {
+      ThanksForFeedbackNotification().notify(project)
+    }
+  }
+
+  private fun createProblemsResultList(): List<String> {
+    val problemsList = mutableListOf<String>()
+    if (checkBoxNoProblemProperty.get()) {
+      // TODO: Need 'No problems' option in zendesk field
+    }
+    if (checkBoxEmptyProjectDontWorkProperty.get()) {
+      problemsList.add(TICKET_PROBLEMS_MULTISELECT_EMPTY_PROJECT_ID)
+    }
+    if (checkBoxHardFindDesireProjectProperty.get()) {
+      problemsList.add(TICKET_PROBLEMS_MULTISELECT_HARD_TO_FIND_ID)
+    }
+    if (checkBoxFrameworkProperty.get()) {
+      problemsList.add(TICKET_PROBLEMS_MULTISELECT_LACK_OF_FRAMEWORK_ID)
+    }
+    if (checkBoxOtherProperty.get()) {
+      problemsList.add(TICKET_PROBLEMS_MULTISELECT_OTHER_ID)
+    }
+    return problemsList
   }
 
   override fun createCenterPanel(): JComponent {
@@ -110,7 +175,7 @@ class ProjectCreationFeedbackDialog(
 
         missingRatingTooltip = label(FeedbackBundle.message("dialog.created.project.rating.required")).applyToComponent {
           border = JBUI.Borders.compound(PopupBorder.Factory.createColored(JBUI.CurrentTheme.Validator.errorBorderColor()),
-            JBUI.Borders.empty(JBUI.scale(4), JBUI.scale(8)))
+                                         JBUI.Borders.empty(JBUI.scale(4), JBUI.scale(8)))
           background = JBUI.CurrentTheme.Validator.errorBackgroundColor()
           isVisible = false
           isOpaque = true
@@ -200,20 +265,20 @@ class ProjectCreationFeedbackDialog(
           layout = GridLayout(3, 1, 0, 0)
 
           add(createLineOfConsent(FeedbackBundle.message("dialog.created.project.consent.1.1"),
-            FeedbackBundle.message("dialog.created.project.consent.1.2"),
-            FeedbackBundle.message("dialog.created.project.consent.1.3")) {
-            ProjectCreationFeedbackSystemInfo(project, createdProjectTypeName).show()
+                                  FeedbackBundle.message("dialog.created.project.consent.1.2"),
+                                  FeedbackBundle.message("dialog.created.project.consent.1.3")) {
+            ProjectCreationFeedbackSystemInfo(project, systemInfoData).show()
           })
 
           add(createLineOfConsent(FeedbackBundle.message("dialog.created.project.consent.2.1"),
-            FeedbackBundle.message("dialog.created.project.consent.2.2"),
-            FeedbackBundle.message("dialog.created.project.consent.2.3")) {
+                                  FeedbackBundle.message("dialog.created.project.consent.2.2"),
+                                  FeedbackBundle.message("dialog.created.project.consent.2.3")) {
             BrowserUtil.browse(PRIVACY_POLICY_THIRD_PARTIES_URL, project)
           })
 
           add(createLineOfConsent("",
-            FeedbackBundle.message("dialog.created.project.consent.3.2"),
-            FeedbackBundle.message("dialog.created.project.consent.3.3")) {
+                                  FeedbackBundle.message("dialog.created.project.consent.3.2"),
+                                  FeedbackBundle.message("dialog.created.project.consent.3.3")) {
             BrowserUtil.browse(PRIVACY_POLICY_URL, project)
           })
         })
@@ -231,7 +296,7 @@ class ProjectCreationFeedbackDialog(
     val text = HtmlBuilder()
       .append(prefixTest) //NON-NLS
       .append(HtmlChunk.tag("hyperlink")
-        .addText(linkText)) //NON-NLS
+                .addText(linkText)) //NON-NLS
       .append(postfix) //NON-NLS
     val label = HyperlinkLabel().apply {
       setTextWithHyperlink(text.toString())
index 91517513eb49b2dcf47f20b4c985cf704ea4ab68..cd17bc7edc05094c2c24bedaf8be047c5adc2878 100644 (file)
@@ -2,34 +2,18 @@
 package com.intellij.feedback.dialog
 
 import com.intellij.feedback.bundle.FeedbackBundle
-import com.intellij.ide.nls.NlsMessages
-import com.intellij.ide.plugins.IdeaPluginDescriptor
-import com.intellij.ide.plugins.PluginManagerCore
-import com.intellij.openapi.application.ApplicationNamesInfo
-import com.intellij.openapi.application.ex.ApplicationInfoEx
 import com.intellij.openapi.project.Project
 import com.intellij.openapi.ui.DialogWrapper
 import com.intellij.openapi.ui.ex.MultiLineLabel
-import com.intellij.openapi.util.SystemInfo
-import com.intellij.openapi.util.SystemInfo.JAVA_RUNTIME_VERSION
-import com.intellij.openapi.util.SystemInfo.OS_ARCH
-import com.intellij.openapi.util.io.FileUtilRt
-import com.intellij.openapi.util.registry.Registry
-import com.intellij.openapi.util.registry.RegistryValue
-import com.intellij.openapi.util.text.StringUtil
-import com.intellij.ui.LicensingFacade
 import com.intellij.ui.components.JBScrollPane
 import com.intellij.ui.layout.*
 import com.intellij.util.ui.JBEmptyBorder
-import java.text.SimpleDateFormat
-import java.util.*
-import java.util.stream.Collectors
 import javax.swing.Action
 import javax.swing.JComponent
 
 class ProjectCreationFeedbackSystemInfo(
   project: Project?,
-  private val createdProjectTypeName: String) : DialogWrapper(project) {
+  private val systemInfoData: ProjectCreationFeedbackSystemInfoData) : DialogWrapper(project) {
 
   init {
     init()
@@ -43,7 +27,7 @@ class ProjectCreationFeedbackSystemInfo(
           label(FeedbackBundle.message("dialog.created.project.system.info.panel.project.type"))
         }
         cell {
-          label(createdProjectTypeName) //NON-NLS
+          label(systemInfoData.createdProjectTypeName) //NON-NLS
         }
       }
       row {
@@ -51,7 +35,7 @@ class ProjectCreationFeedbackSystemInfo(
           label(FeedbackBundle.message("dialog.created.project.system.info.panel.os.version"))
         }
         cell {
-          label(SystemInfo.OS_NAME + " " + SystemInfo.OS_VERSION) //NON-NLS
+          label(systemInfoData.osVersion) //NON-NLS
         }
       }
       row {
@@ -59,7 +43,7 @@ class ProjectCreationFeedbackSystemInfo(
           label(FeedbackBundle.message("dialog.created.project.system.info.panel.memory"))
         }
         cell {
-          label((Runtime.getRuntime().maxMemory() / FileUtilRt.MEGABYTE).toString() + "M") //NON-NLS
+          label(systemInfoData.getMemorySizeForDialog()) //NON-NLS
         }
       }
       row {
@@ -67,7 +51,7 @@ class ProjectCreationFeedbackSystemInfo(
           label(FeedbackBundle.message("dialog.created.project.system.info.panel.cores"))
         }
         cell {
-          label(Runtime.getRuntime().availableProcessors().toString())
+          label(systemInfoData.coresNumber.toString()) //NON-NLS
         }
       }
       row {
@@ -75,7 +59,7 @@ class ProjectCreationFeedbackSystemInfo(
           label(FeedbackBundle.message("dialog.created.project.system.info.panel.app.version"))
         }
         cell {
-          MultiLineLabel(getAppVersionWithBuild())() //NON-NLS
+          MultiLineLabel(systemInfoData.appVersionWithBuild)() //NON-NLS
         }
       }
       row {
@@ -83,7 +67,7 @@ class ProjectCreationFeedbackSystemInfo(
           label(FeedbackBundle.message("dialog.created.project.system.info.panel.license"))
         }
         cell {
-          MultiLineLabel(getLicenseInfo())() //NON-NLS
+          MultiLineLabel(systemInfoData.getLicenseInfoForDialog())() //NON-NLS
         }
       }
       row {
@@ -91,7 +75,7 @@ class ProjectCreationFeedbackSystemInfo(
           label(FeedbackBundle.message("dialog.created.project.system.info.panel.runtime.version"))
         }
         cell {
-          label(JAVA_RUNTIME_VERSION + OS_ARCH) //NON-NLS
+          label(systemInfoData.runtimeVersion) //NON-NLS
         }
       }
       row {
@@ -99,7 +83,7 @@ class ProjectCreationFeedbackSystemInfo(
           label(FeedbackBundle.message("dialog.created.project.system.info.panel.registry"))
         }
         cell {
-          MultiLineLabel(getRegistryKeys())() //NON-NLS
+          MultiLineLabel(systemInfoData.getRegistryKeysForDialog())() //NON-NLS
         }
       }
       row {
@@ -107,7 +91,7 @@ class ProjectCreationFeedbackSystemInfo(
           label(FeedbackBundle.message("dialog.created.project.system.info.panel.disabled.plugins"))
         }
         cell {
-          MultiLineLabel(getDisabledPlugins())() //NON-NLS
+          MultiLineLabel(systemInfoData.getDisabledBundledPluginsForDialog())() //NON-NLS
         }
       }
       row {
@@ -115,7 +99,7 @@ class ProjectCreationFeedbackSystemInfo(
           label(FeedbackBundle.message("dialog.created.project.system.info.panel.nonbundled.plugins"))
         }
         cell {
-          MultiLineLabel(getNonBundledPlugins())() //NON-NLS
+          MultiLineLabel(systemInfoData.getNonBundledPluginsForDialog())() //NON-NLS
         }
         largeGapAfter()
       }
@@ -128,83 +112,6 @@ class ProjectCreationFeedbackSystemInfo(
     }
   }
 
-  private fun getAppVersionWithBuild(): String {
-    val appInfoEx = ApplicationInfoEx.getInstanceEx()
-
-    var appVersion: String = appInfoEx.fullApplicationName
-    val edition = ApplicationNamesInfo.getInstance().editionName
-    if (edition != null) {
-      appVersion += " ($edition)"
-    }
-    val appBuild = appInfoEx.build
-    appVersion += " " + FeedbackBundle.message("dialog.created.project.system.info.panel.app.version.build", appBuild.asString())
-    val timestamp: Date = appInfoEx.buildDate.time
-    if (appBuild.isSnapshot) {
-      val time = SimpleDateFormat("HH:mm").format(timestamp)
-      appVersion += FeedbackBundle.message("dialog.created.project.system.info.panel.app.version.build.date.time",
-        NlsMessages.formatDateLong(timestamp), time)
-    }
-    else {
-      appVersion += FeedbackBundle.message("dialog.created.project.system.info.panel.app.version.build.date",
-        NlsMessages.formatDateLong(timestamp))
-    }
-    return appVersion
-  }
-
-  private fun getLicenseInfo(): String {
-    val licensingFacade = LicensingFacade.getInstance()
-    return if (licensingFacade != null) {
-      val licenseInfoList = ArrayList<String>()
-      val licensedTo = licensingFacade.licensedToMessage
-      if (licensedTo != null) {
-        licenseInfoList.add(licensedTo)
-      }
-      licenseInfoList.addAll(licensingFacade.licenseRestrictionsMessages)
-      licenseInfoList.joinToString("\n")
-    }
-    else {
-      FeedbackBundle.message("dialog.created.project.system.info.panel.license.no.info")
-    }
-  }
-
-  private fun getRegistryKeys(): String {
-    val registryKeys: String = Registry.getAll().stream().filter { obj: RegistryValue -> obj.isChangedFromDefault }
-      .map { v: RegistryValue -> v.key + "=" + v.asString() }.collect(Collectors.joining("\n"))
-    val registryKeysValue = if (!StringUtil.isEmpty(registryKeys)) {
-      registryKeys
-    }
-    else {
-      FeedbackBundle.message("dialog.created.project.system.info.panel.registry.empty")
-    }
-    return registryKeysValue
-  }
-
-  private fun getDisabledPlugins(): String {
-    return getPluginsNamesWithVersion { p: IdeaPluginDescriptor ->
-      !p.isEnabled
-    }
-  }
-
-  private fun getNonBundledPlugins(): String {
-    return getPluginsNamesWithVersion { p: IdeaPluginDescriptor ->
-      !p.isBundled
-    }
-  }
-
-  private fun getPluginsNamesWithVersion(filter: (IdeaPluginDescriptor) -> Boolean): String {
-    val nonBundledPlugins: String = PluginManagerCore.getLoadedPlugins().stream()
-      .filter { filter(it) }
-      .map { p: IdeaPluginDescriptor -> p.pluginId.idString + " (" + p.version + ")" }
-      .collect(Collectors.joining("\n"))
-    val nonBundledPluginsValue = if (!StringUtil.isEmpty(nonBundledPlugins)) {
-      nonBundledPlugins
-    }
-    else {
-      FeedbackBundle.message("dialog.created.project.system.info.panel.nonbundled.plugins.empty")
-    }
-    return nonBundledPluginsValue
-  }
-
   override fun createActions(): Array<Action> {
     return arrayOf(okAction)
   }
diff --git a/platform/feedback/src/com/intellij/feedback/dialog/ProjectCreationFeedbackSystemInfoData.kt b/platform/feedback/src/com/intellij/feedback/dialog/ProjectCreationFeedbackSystemInfoData.kt
new file mode 100644 (file)
index 0000000..3046716
--- /dev/null
@@ -0,0 +1,144 @@
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.feedback.dialog
+
+import com.intellij.feedback.bundle.FeedbackBundle
+import com.intellij.ide.nls.NlsMessages
+import com.intellij.ide.plugins.IdeaPluginDescriptor
+import com.intellij.ide.plugins.PluginManagerCore
+import com.intellij.openapi.application.ApplicationNamesInfo
+import com.intellij.openapi.application.ex.ApplicationInfoEx
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.openapi.util.io.FileUtilRt
+import com.intellij.openapi.util.registry.Registry
+import com.intellij.openapi.util.registry.RegistryValue
+import com.intellij.openapi.util.text.StringUtil
+import com.intellij.ui.LicensingFacade
+import kotlinx.serialization.Serializable
+import java.text.SimpleDateFormat
+import java.util.*
+import kotlin.streams.toList
+
+@Serializable
+data class ProjectCreationFeedbackSystemInfoData(
+  val createdProjectTypeName: String,
+  val osVersion: String,
+  private val memorySize: Long, // in megabytes
+  val coresNumber: Int,
+  val appVersionWithBuild: String,
+  private val licenseInfo: List<String>,
+  val runtimeVersion: String,
+  private val registry: List<String>,
+  private val disabledBundledPlugins: List<String>,
+  private val nonBundledPlugins: List<String>
+) {
+  companion object {
+    fun createProjectCreationFeedbackSystemInfoData(createdProjectTypeName: String): ProjectCreationFeedbackSystemInfoData {
+      return ProjectCreationFeedbackSystemInfoData(
+        createdProjectTypeName,
+        getOsVersion(),
+        getMemorySize(),
+        getCoresNumber(),
+        getAppVersionWithBuild(),
+        getLicenseInfo(),
+        getRuntimeVersion(),
+        getRegistryKeys(),
+        getDisabledPlugins(),
+        getNonBundledPlugins()
+      )
+    }
+
+    private fun getOsVersion() = SystemInfo.OS_NAME + " " + SystemInfo.OS_VERSION
+    private fun getMemorySize() = Runtime.getRuntime().maxMemory() / FileUtilRt.MEGABYTE
+    private fun getCoresNumber() = Runtime.getRuntime().availableProcessors()
+    private fun getAppVersionWithBuild(): String {
+      val appInfoEx = ApplicationInfoEx.getInstanceEx()
+
+      var appVersion: String = appInfoEx.fullApplicationName
+      val edition = ApplicationNamesInfo.getInstance().editionName
+      if (edition != null) {
+        appVersion += " ($edition)"
+      }
+      val appBuild = appInfoEx.build
+      appVersion += FeedbackBundle.message("dialog.created.project.system.info.panel.app.version.build", appBuild.asString())
+      val timestamp: Date = appInfoEx.buildDate.time
+      if (appBuild.isSnapshot) {
+        val time = SimpleDateFormat("HH:mm").format(timestamp)
+        appVersion += FeedbackBundle.message("dialog.created.project.system.info.panel.app.version.build.date.time",
+                                             NlsMessages.formatDateLong(timestamp), time)
+      }
+      else {
+        appVersion += FeedbackBundle.message("dialog.created.project.system.info.panel.app.version.build.date",
+                                             NlsMessages.formatDateLong(timestamp))
+      }
+      return appVersion
+    }
+
+    private fun getLicenseInfo(): List<String> {
+      val licensingFacade = LicensingFacade.getInstance()
+      return if (licensingFacade != null) {
+        val licenseInfoList = ArrayList<String>()
+        val licensedTo = licensingFacade.licensedToMessage
+        if (licensedTo != null) {
+          licenseInfoList.add(licensedTo)
+        }
+        licenseInfoList.addAll(licensingFacade.licenseRestrictionsMessages)
+        licenseInfoList
+      }
+      else {
+        emptyList()
+      }
+    }
+
+    private fun getRuntimeVersion() = SystemInfo.JAVA_RUNTIME_VERSION + SystemInfo.OS_ARCH
+    private fun getRegistryKeys(): List<String> = Registry.getAll().stream().filter { obj: RegistryValue -> obj.isChangedFromDefault }
+      .map { v: RegistryValue -> v.key + "=" + v.asString() }.toList()
+
+
+    private fun getDisabledPlugins(): List<String> = getPluginsNamesWithVersion { p: IdeaPluginDescriptor -> !p.isEnabled }
+
+    private fun getNonBundledPlugins(): List<String> = getPluginsNamesWithVersion { p: IdeaPluginDescriptor -> !p.isBundled }
+
+    private fun getPluginsNamesWithVersion(filter: (IdeaPluginDescriptor) -> Boolean): List<String> =
+      PluginManagerCore.getLoadedPlugins().stream()
+        .filter { filter(it) }
+        .map { p: IdeaPluginDescriptor -> p.pluginId.idString + " (" + p.version + ")" }
+        .toList()
+  }
+
+  fun getMemorySizeForDialog() = memorySize.toString() + "M"
+  fun getLicenseInfoForDialog() = if (licenseInfo.isEmpty())
+    FeedbackBundle.message("dialog.created.project.system.info.panel.license.no.info")
+  else
+    licenseInfo.joinToString("\n")
+
+  fun getRegistryKeysForDialog(): String {
+    val registryKeys: String = registry.joinToString("\n")
+    return if (!StringUtil.isEmpty(registryKeys)) {
+      registryKeys
+    }
+    else {
+      FeedbackBundle.message("dialog.created.project.system.info.panel.registry.empty")
+    }
+  }
+
+  fun getDisabledBundledPluginsForDialog(): String {
+    val disabledPlugins = disabledBundledPlugins.joinToString("\n")
+    return if (!StringUtil.isEmpty(disabledPlugins)) {
+      disabledPlugins
+    }
+    else {
+      FeedbackBundle.message("dialog.created.project.system.info.panel.disabled.plugins.empty")
+    }
+  }
+
+  fun getNonBundledPluginsForDialog(): String {
+    val nonBundledPluginsString = nonBundledPlugins.joinToString("\n")
+    return if (!StringUtil.isEmpty(nonBundledPluginsString)) {
+      nonBundledPluginsString
+    }
+    else {
+      FeedbackBundle.message("dialog.created.project.system.info.panel.nonbundled.plugins.empty")
+    }
+  }
+
+}