[IFT] Add feedback links

IDEA-CR-69908

GitOrigin-RevId: f62bfc084dfaa880d9649d0e2a09633555e66128
This commit is contained in:
Alexey Merkulov
2020-12-21 15:38:09 +03:00
committed by intellij-monorepo-bot
parent 74feb42d66
commit 99db3d37c3
7 changed files with 83 additions and 25 deletions

View File

@@ -21,6 +21,7 @@ import training.lang.AbstractLangSupport
import training.learn.LearnBundle
import training.project.ProjectUtils
import training.project.ReadMeCreator
import training.util.getFeedbackLink
import java.nio.file.Path
class JavaLangSupport : AbstractLangSupport() {
@@ -35,6 +36,8 @@ class JavaLangSupport : AbstractLangSupport() {
override val projectSandboxRelativePath: String = "Sample.java"
override val langCourseFeedback get() = getFeedbackLink(this, false)
override val readMeCreator: ReadMeCreator = object : ReadMeCreator() {
private val sharedIndexesRemark: String = JavaLessonsBundle.message("readme.shared.indexes.remark")
override val indexingDescription = "${super.indexingDescription}\n\n$sharedIndexesRemark"

View File

@@ -98,5 +98,9 @@
description="Specified default delay in milliseconds before previous task will be restored if something went wrong."
defaultValue="500"
restartRequired="false"/>
<registryKey key="ift.show.feedback.link"
description="Whether IFT show feedback link in the modules panel."
defaultValue="FALSE"
restartRequired="false"/>
</extensions>
</idea-plugin>

View File

@@ -116,3 +116,6 @@ welcome.tab.header.learn.ide.features=Learn IDE Features
welcome.tab.description.learn.ide.features=Learn basic shortcuts and essential features interactively with the IDE Training Course.
completed.lessons.got.it=Finished lessons will be opened as completed. Press this button if you want to restart the lesson.
feedback.link.text=Leave feedback
feedback.link.hint=Help us make learning the IDE better for everyone

View File

@@ -1,7 +1,6 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.ui.views
import com.intellij.icons.AllIcons
import com.intellij.ide.IdeBundle
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.util.NlsSafe
@@ -21,6 +20,7 @@ import training.ui.*
import training.util.getNextLessonForCurrent
import training.util.getPreviousLessonForCurrent
import training.util.openLinkInBrowser
import training.util.wrapWithUrlPanel
import java.awt.*
import java.awt.event.ActionEvent
import javax.swing.*
@@ -106,17 +106,6 @@ class LearnPanel(val learnToolWindow: LearnToolWindow) : JPanel() {
footer.border = UISettings.instance.checkmarkShiftBorder
}
private fun LinkLabel<Any>.wrapWithUrlPanel(): JPanel {
val jPanel = JPanel()
jPanel.isOpaque = false
jPanel.layout = BoxLayout(jPanel, BoxLayout.LINE_AXIS)
jPanel.add(this, BorderLayout.CENTER)
jPanel.add(JLabel(AllIcons.Ide.External_link_arrow), BorderLayout.EAST)
jPanel.maximumSize = jPanel.preferredSize
jPanel.alignmentX = LEFT_ALIGNMENT
return jPanel
}
private fun initLessonPanel() {
lessonPanel.name = "lessonPanel"
lessonPanel.layout = lessonPanelBoxLayout

View File

@@ -1,29 +1,34 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.ui.views
import com.intellij.ui.components.labels.LinkLabel
import com.intellij.ui.components.panels.HorizontalLayout
import com.intellij.ui.components.panels.VerticalLayout
import com.intellij.util.ui.JBUI
import training.lang.LangManager
import training.learn.CourseManager
import training.learn.LearnBundle
import training.ui.UISettings
import training.util.DataLoader
import java.awt.Dimension
import training.util.openLinkInBrowser
import training.util.wrapWithUrlPanel
import java.awt.BorderLayout
import javax.swing.Box
import javax.swing.BoxLayout
import javax.swing.JLabel
import javax.swing.JPanel
import javax.swing.border.MatteBorder
class ModulesPanel : JPanel() {
private val modulesPanel = LearningItems()
init {
layout = BoxLayout(this, BoxLayout.Y_AXIS)
layout = BorderLayout()
isFocusable = false
isOpaque = true
background = UISettings.instance.backgroundColor
border = UISettings.instance.emptyBorder
initModulesPanel()
add(modulesPanel)
add(Box.createVerticalGlue())
preferredSize = Dimension(UISettings.instance.width, 100)
border = UISettings.instance.emptyBorderWithNoEastHalfNorth
revalidate()
repaint()
@@ -39,16 +44,44 @@ class ModulesPanel : JPanel() {
it.modules = modules
it.updateItems(CourseManager.instance.unfoldModuleOnInit)
}
removeAll()
add(modulesPanel, BorderLayout.CENTER)
addFooter()
}
private fun addFooter() {
val linkForFeedback = LangManager.getInstance().getLangSupport()?.langCourseFeedback ?: return
val footerContent = JPanel()
footerContent.isOpaque = false
footerContent.layout = VerticalLayout(4)
footerContent.add(Box.createVerticalStrut(8))
val linkLabel = LinkLabel<Any>(LearnBundle.message("feedback.link.text"), null) { _, _ ->
openLinkInBrowser(linkForFeedback)
}
footerContent.add(linkLabel.wrapWithUrlPanel())
footerContent.add(JLabel(LearnBundle.message("feedback.link.hint")).also {
it.foreground = UISettings.instance.moduleProgressColor
it.font = it.font.deriveFont(it.font.size2D - 1)
})
val shiftedFooter = JPanel()
shiftedFooter.name = "footerModulePanel"
shiftedFooter.layout = HorizontalLayout(1)
shiftedFooter.isFocusable = false
shiftedFooter.isOpaque = false
shiftedFooter.border = MatteBorder(JBUI.scale(1), 0, 0, 0, UISettings.instance.separatorColor)
shiftedFooter.add(footerContent)
shiftedFooter.add(Box.createHorizontalGlue())
add(shiftedFooter, BorderLayout.PAGE_END)
}
fun updateMainPanel() {
modulesPanel.removeAll()
initModulesPanel()
}
override fun getPreferredSize(): Dimension {
return Dimension(modulesPanel.minimumSize.getWidth().toInt() + (UISettings.instance.westInset + UISettings.instance.westInset),
modulesPanel.minimumSize.getHeight().toInt() + (UISettings.instance.northInset + UISettings.instance.southInset))
}
}

View File

@@ -2,6 +2,7 @@
package training.util
import com.google.common.util.concurrent.ThreadFactoryBuilder
import com.intellij.icons.AllIcons
import com.intellij.ide.DataManager
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.lang.Language
@@ -14,6 +15,7 @@ import com.intellij.openapi.ui.popup.Balloon
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.registry.Registry
import com.intellij.ui.components.labels.LinkLabel
import com.intellij.util.ui.UIUtil
import org.jetbrains.annotations.Nls
import training.lang.LangManager
@@ -24,10 +26,14 @@ import training.learn.lesson.LessonManager
import training.learn.lesson.LessonStateManager
import training.ui.LearnToolWindowFactory
import training.ui.LearningUiManager
import java.awt.BorderLayout
import java.awt.Desktop
import java.net.URI
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import javax.swing.BoxLayout
import javax.swing.JLabel
import javax.swing.JPanel
fun createNamedSingleThreadExecutor(name: String): ExecutorService =
Executors.newSingleThreadExecutor(ThreadFactoryBuilder().setNameFormat(name).build())
@@ -93,6 +99,12 @@ fun isLearningProject(project: Project, langSupport: LangSupport): Boolean {
return FileUtil.pathsEqual(project.basePath, LangManager.getInstance().getLearningProjectPath(langSupport))
}
fun getFeedbackLink(langSupport: LangSupport, ownRegistry: Boolean): String? {
val suffix = langSupport.primaryLanguage.toLowerCase()
val needToShow = Registry.`is`("ift.show.feedback.link" + if (ownRegistry) ".$suffix" else "", false)
return if (needToShow) "https://surveys.jetbrains.com/s3/features-trainer-feedback-$suffix" else null
}
val switchOnExperimentalLessons: Boolean
get() = Registry.`is`("ift.experimental.lessons", false)
@@ -112,6 +124,17 @@ fun openLinkInBrowser(link: String) {
}
}
fun LinkLabel<Any>.wrapWithUrlPanel(): JPanel {
val jPanel = JPanel()
jPanel.isOpaque = false
jPanel.layout = BoxLayout(jPanel, BoxLayout.LINE_AXIS)
jPanel.add(this, BorderLayout.CENTER)
jPanel.add(JLabel(AllIcons.Ide.External_link_arrow), BorderLayout.EAST)
jPanel.maximumSize = jPanel.preferredSize
jPanel.alignmentX = JPanel.LEFT_ALIGNMENT
return jPanel
}
fun lessonOpenedInProject(project: Project?): Lesson? {
return if (LearnToolWindowFactory.learnWindowPerProject[project] != null) LessonManager.instance.currentLesson else null
}

View File

@@ -27,6 +27,7 @@ import training.learn.exceptons.NoSdkException
import training.learn.lesson.kimpl.LessonUtil
import training.project.ProjectUtils
import training.project.ReadMeCreator
import training.util.getFeedbackLink
import java.nio.file.Path
class PythonLangSupport : AbstractLangSupport() {
@@ -40,6 +41,8 @@ class PythonLangSupport : AbstractLangSupport() {
override val filename: String = "Learning.py"
override val langCourseFeedback get() = getFeedbackLink(this, false)
override val readMeCreator = ReadMeCreator()
override fun applyToProjectAfterConfigure(): (Project) -> Unit = { project ->