mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-04 17:20:55 +07:00
[python] in-product survey about user's job for pycharm (PY-74269)
(cherry picked from commit 5ce25d3c418b54649e6a52a892bc84b837251e76) IJ-MR-148062 GitOrigin-RevId: 0f3602d64459a2632bff07243e7e166ec59e9665
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d93cc5cd2c
commit
88df1335c4
@@ -153,6 +153,8 @@
|
||||
<orderEntry type="module" module-name="intellij.libraries.ktor.client" />
|
||||
<orderEntry type="module" module-name="intellij.libraries.ktor.client.cio" />
|
||||
<orderEntry type="module" module-name="intellij.platform.util.progress" />
|
||||
<orderEntry type="module" module-name="intellij.platform.feedback" />
|
||||
<orderEntry type="library" name="kotlinx-datetime-jvm" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.remote" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.ui" />
|
||||
</component>
|
||||
|
||||
@@ -638,6 +638,10 @@ The Python plug-in provides smart editing for Python scripts. The feature set of
|
||||
key="quickfix.ranking.ml"
|
||||
defaultValue="[IN_EXPERIMENT*|ENABLED|DISABLED]"
|
||||
description="Enable ML ranking in quick fix for missing imports"/>
|
||||
|
||||
<feedback.idleFeedbackSurvey implementation="com.jetbrains.python.statistics.feedback.PythonJobSurvey"/>
|
||||
<statistics.counterUsagesCollector implementationClass="com.jetbrains.python.statistics.feedback.PythonJobStatisticsCollector"/>
|
||||
<backgroundPostStartupActivity implementation="com.jetbrains.python.statistics.feedback.PythonFirstLaunchChecker"/>
|
||||
</extensions>
|
||||
|
||||
<extensionPoints>
|
||||
|
||||
@@ -1551,4 +1551,19 @@ package.install.with.options.dialog.message=Options:
|
||||
package.install.with.options.dialog.title=Package Install with Options
|
||||
python.toolwindow.packages.collapse.all.action=Collapse All
|
||||
django.template.language=Template Language
|
||||
python.error=Error
|
||||
python.error=Error
|
||||
|
||||
|
||||
python.survey.user.job.notification.group=PyCharm Job Survey
|
||||
python.survey.user.job.notification.title=Feedback In IDE
|
||||
python.survey.user.job.notification.content=Tell us about your Python development experience. Just one question.
|
||||
|
||||
python.survey.user.job.dialog.title=Feedback
|
||||
python.survey.user.job.dialog.blocks.top=Python development
|
||||
python.survey.user.job.dialog.blocks.checkbox.group=What do you use Python for?
|
||||
python.survey.user.job.dialog.blocks.checkbox.data=Data analysis
|
||||
python.survey.user.job.dialog.blocks.checkbox.ml=Machine learning
|
||||
python.survey.user.job.dialog.blocks.checkbox.web=Web development
|
||||
python.survey.user.job.dialog.blocks.checkbox.scripts=Writing automation scripts / parsers / tests / system administration
|
||||
python.survey.user.job.dialog.blocks.checkbox.other=Other
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.statistics.feedback
|
||||
|
||||
import com.intellij.openapi.components.BaseState
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.startup.ProjectActivity
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toJavaLocalDateTime
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import java.time.Duration
|
||||
|
||||
|
||||
class PythonJobSurveyState : BaseState() {
|
||||
var firstLaunch by string()
|
||||
}
|
||||
|
||||
class PythonFirstLaunchChecker : ProjectActivity {
|
||||
override suspend fun execute(project: Project) {
|
||||
val state = PythonJobSurveyService.getInstance().state ?: return
|
||||
if (state.firstLaunch == null) {
|
||||
val dateTime = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
state.firstLaunch = LocalDateTime.Formats.ISO.format(dateTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun shouldShowSurvey(): Boolean {
|
||||
val firstLaunch = PythonJobSurveyService.getInstance().state?.firstLaunch ?: return false
|
||||
val dateTime = LocalDateTime.Formats.ISO.parse(firstLaunch)
|
||||
// Start checking on the third day of usage
|
||||
return Duration.between(dateTime.toJavaLocalDateTime(), java.time.LocalDateTime.now()).toDays() >= 3
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.statistics.feedback
|
||||
|
||||
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||
import com.intellij.internal.statistic.eventLog.events.EventFields
|
||||
import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector
|
||||
import com.intellij.internal.statistic.eventLog.events.EventId2
|
||||
import com.intellij.internal.statistic.eventLog.validator.ValidationResultType
|
||||
import com.intellij.internal.statistic.eventLog.validator.rules.EventContext
|
||||
import com.intellij.internal.statistic.eventLog.validator.rules.impl.CustomValidationRule
|
||||
|
||||
object PythonJobStatisticsCollector : CounterUsagesCollector() {
|
||||
private val GROUP = EventLogGroup("python.job.statistics", 1)
|
||||
private val USE_FOR = EventFields.StringList("use_for", listOf("data_analysis", "ml", "web_dev", "scripts"))
|
||||
private val OTHER = EventFields.StringValidatedByCustomRule<TrueValidationRule>("other")
|
||||
private val JOB_EVENT: EventId2<List<String>, String?> = GROUP.registerEvent("job.event", USE_FOR, OTHER)
|
||||
|
||||
@JvmStatic
|
||||
fun logJobEvent(useFor: List<String>, other: String?) {
|
||||
JOB_EVENT.log(useFor, other)
|
||||
}
|
||||
|
||||
override fun getGroup(): EventLogGroup {
|
||||
return GROUP
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TrueValidationRule() : CustomValidationRule() {
|
||||
override fun getRuleId(): String {
|
||||
return "python-user-job-other"
|
||||
}
|
||||
|
||||
override fun doValidate(data: String, context: EventContext): ValidationResultType {
|
||||
return ValidationResultType.ACCEPTED
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.statistics.feedback
|
||||
|
||||
import com.intellij.platform.feedback.FeedbackSurvey
|
||||
import com.intellij.platform.feedback.InIdeFeedbackSurveyConfig
|
||||
import com.intellij.platform.feedback.InIdeFeedbackSurveyType
|
||||
|
||||
class PythonJobSurvey : FeedbackSurvey() {
|
||||
override val feedbackSurveyType: InIdeFeedbackSurveyType<InIdeFeedbackSurveyConfig> =
|
||||
InIdeFeedbackSurveyType(PythonJobSurveyConfig())
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.statistics.feedback
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.feedback.InIdeFeedbackSurveyConfig
|
||||
import com.intellij.platform.feedback.dialog.BlockBasedFeedbackDialog
|
||||
import com.intellij.platform.feedback.dialog.SystemDataJsonSerializable
|
||||
import com.intellij.platform.feedback.impl.notification.RequestFeedbackNotification
|
||||
import com.intellij.util.PlatformUtils
|
||||
import com.jetbrains.python.PyBundle.message
|
||||
import kotlinx.datetime.LocalDate
|
||||
|
||||
class PythonJobSurveyConfig : InIdeFeedbackSurveyConfig {
|
||||
|
||||
override fun createFeedbackDialog(project: Project, forTest: Boolean): BlockBasedFeedbackDialog<out SystemDataJsonSerializable> {
|
||||
return PythonUserJobFeedbackDialog(project, forTest)
|
||||
}
|
||||
|
||||
override val surveyId: String = "python_user_job_survey"
|
||||
override val requireIdeEAP: Boolean = true
|
||||
override val lastDayOfFeedbackCollection: LocalDate
|
||||
get() = LocalDate(2024, 12, 31)
|
||||
|
||||
override fun checkIdeIsSuitable(): Boolean = PlatformUtils.isPyCharmCommunity()
|
||||
override fun checkExtraConditionSatisfied(project: Project): Boolean = shouldShowSurvey()
|
||||
|
||||
override fun createNotification(project: Project, forTest: Boolean): RequestFeedbackNotification {
|
||||
return RequestFeedbackNotification(
|
||||
message("python.survey.user.job.notification.group"),
|
||||
message("python.survey.user.job.notification.title"),
|
||||
message("python.survey.user.job.notification.content"),
|
||||
)
|
||||
}
|
||||
|
||||
override fun updateStateAfterNotificationShowed(project: Project) {
|
||||
|
||||
}
|
||||
|
||||
override fun updateStateAfterDialogClosedOk(project: Project) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.statistics.feedback
|
||||
|
||||
import com.intellij.openapi.components.PersistentStateComponent
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.State
|
||||
import com.intellij.openapi.components.Storage
|
||||
import com.intellij.openapi.components.service
|
||||
|
||||
@Service(Service.Level.APP)
|
||||
@State(name="PythonJobSurveyService", storages = [Storage("pycharm-job-survey-service.xml")])
|
||||
class PythonJobSurveyService : PersistentStateComponent<PythonJobSurveyState> {
|
||||
private var state = PythonJobSurveyState()
|
||||
|
||||
override fun getState(): PythonJobSurveyState? = state
|
||||
|
||||
override fun loadState(state: PythonJobSurveyState) {
|
||||
this.state = state
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(): PythonJobSurveyService = service()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.statistics.feedback
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.feedback.dialog.BlockBasedFeedbackDialog
|
||||
import com.intellij.platform.feedback.dialog.CommonFeedbackSystemData
|
||||
import com.intellij.platform.feedback.dialog.showFeedbackSystemInfoDialog
|
||||
import com.intellij.platform.feedback.dialog.uiBlocks.CheckBoxGroupBlock
|
||||
import com.intellij.platform.feedback.dialog.uiBlocks.CheckBoxItemData
|
||||
import com.intellij.platform.feedback.dialog.uiBlocks.FeedbackBlock
|
||||
import com.intellij.platform.feedback.dialog.uiBlocks.TopLabelBlock
|
||||
import com.jetbrains.python.PyBundle.message
|
||||
|
||||
class PythonUserJobFeedbackDialog(
|
||||
project: Project?,
|
||||
forTest: Boolean,
|
||||
) : BlockBasedFeedbackDialog<CommonFeedbackSystemData>(project, forTest) {
|
||||
|
||||
override val myFeedbackReportId: String
|
||||
get() = "python_user_job_survey"
|
||||
|
||||
|
||||
override val myTitle: String
|
||||
get() = message("python.survey.user.job.dialog.title")
|
||||
|
||||
|
||||
val items = listOf(
|
||||
CheckBoxItemData(message("python.survey.user.job.dialog.blocks.checkbox.data"), "data_analysis"),
|
||||
CheckBoxItemData(message("python.survey.user.job.dialog.blocks.checkbox.ml"), "ml"),
|
||||
CheckBoxItemData(message("python.survey.user.job.dialog.blocks.checkbox.web"), "web_dev"),
|
||||
CheckBoxItemData(message("python.survey.user.job.dialog.blocks.checkbox.scripts"), "scripts"),
|
||||
)
|
||||
|
||||
override val myBlocks: List<FeedbackBlock> = listOf(
|
||||
TopLabelBlock(message("python.survey.user.job.dialog.blocks.top")),
|
||||
CheckBoxGroupBlock(message("python.survey.user.job.dialog.blocks.checkbox.group"), items, "python_job_checkbox")
|
||||
.addOtherTextField(message("python.survey.user.job.dialog.blocks.checkbox.other"))
|
||||
.requireAnswer(),
|
||||
)
|
||||
|
||||
override val mySystemInfoData: CommonFeedbackSystemData
|
||||
get() = CommonFeedbackSystemData.getCurrentData()
|
||||
|
||||
override val myShowFeedbackSystemInfoDialog: () -> Unit = {
|
||||
showFeedbackSystemInfoDialog(myProject, mySystemInfoData)
|
||||
}
|
||||
|
||||
override fun sendFeedbackData() {
|
||||
super.sendFeedbackData()
|
||||
|
||||
val builder = StringBuilder()
|
||||
(myBlocks[1] as CheckBoxGroupBlock).collectBlockTextDescription(builder)
|
||||
val selectedItems = items.filter { it.property }.map { it.jsonElementName }
|
||||
val other = builder.toString().lines()[5].substringAfter(message("python.survey.user.job.dialog.blocks.checkbox.other") + ": ")
|
||||
|
||||
PythonJobStatisticsCollector.logJobEvent(selectedItems, other)
|
||||
}
|
||||
|
||||
init {
|
||||
init()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user