├── .github └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── .java-version ├── .travis.yml ├── LICENSE ├── README.md ├── examples └── listeners │ └── sendHtmlEmailOnIssueComment.groovy ├── js ├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .gitignore ├── config │ └── polyfills.js ├── flow-typed │ ├── AJS.js │ ├── atlaskit-icon.js │ ├── npm │ │ ├── @atlaskit │ │ │ ├── css-reset_vx.x.x.js │ │ │ └── util-shared-styles_vx.x.x.js │ │ ├── classnames_v2.x.x.js │ │ ├── codemirror_vx.x.x.js │ │ ├── fast-memoize_vx.x.x.js │ │ ├── jquery_v3.x.x.js │ │ ├── lodash_v4.x.x.js │ │ ├── react-addons-update_vx.x.x.js │ │ ├── react-codemirror2_vx.x.x.js │ │ ├── react-popover_vx.x.x.js │ │ ├── react-redux_v5.x.x.js │ │ ├── react-router-dom_v4.x.x.js │ │ ├── react-router_v4.x.x.js │ │ ├── react-string-replace_vx.x.x.js │ │ ├── redux_v4.x.x.js │ │ └── reselect_v4.x.x.js │ └── stubs.js ├── package.json ├── src │ ├── app-admin │ │ ├── AdminForm.js │ │ ├── AdminRoute.js │ │ ├── AdminScript.js │ │ ├── ConnectedAdminScriptPage.js │ │ ├── PropField.js │ │ ├── RunDialog.js │ │ ├── ViewAdminScript.js │ │ ├── customRenderers.js │ │ ├── index.js │ │ └── types.js │ ├── app-audit │ │ ├── ActionIcon.js │ │ ├── AuditLog.js │ │ ├── AuditLogFilter.js │ │ ├── AuditLogRoute.js │ │ ├── index.js │ │ └── types.js │ ├── app-console │ │ ├── ConsoleRoute.js │ │ ├── ScriptConsole.js │ │ ├── ScriptConsole.less │ │ ├── index.js │ │ └── types.js │ ├── app-fields │ │ ├── CustomFieldForm.js │ │ ├── FieldScript.js │ │ ├── FieldsRoute.js │ │ ├── ViewFieldScript.js │ │ ├── index.js │ │ ├── selectors.js │ │ └── types.js │ ├── app-go │ │ ├── GlobalObjectForm.js │ │ ├── GlobalObjectRoute.js │ │ ├── GlobalObjectScript.js │ │ ├── index.js │ │ └── types.js │ ├── app-jql │ │ ├── JqlForm.js │ │ ├── JqlRoute.js │ │ ├── JqlScript.js │ │ ├── ViewJqlScript.js │ │ ├── index.js │ │ └── types.js │ ├── app-listeners │ │ ├── ConditionPicker.js │ │ ├── ConditionPicker.less │ │ ├── Listener.js │ │ ├── ListenerForm.js │ │ ├── ListenerRegistry.less │ │ ├── ListenersRoute.js │ │ ├── index.js │ │ └── types.js │ ├── app-main │ │ ├── MainApp.js │ │ ├── MainApp.less │ │ ├── NavigationController.js │ │ ├── PageCard.js │ │ ├── PageCard.less │ │ └── index.js │ ├── app-registry │ │ ├── DraggableRegistryScript.js │ │ ├── Loader.js │ │ ├── RegistryRoute.js │ │ ├── RegistryScript.js │ │ ├── ScriptDirectory.js │ │ ├── ScriptDirectory.less │ │ ├── ScriptDirectoryActions.js │ │ ├── ScriptDirectoryDialog.js │ │ ├── ScriptForm.js │ │ ├── ScriptForm.less │ │ ├── ScriptRegistry.js │ │ ├── ScriptRegistry.less │ │ ├── UsageStatusFlag.js │ │ ├── ViewScript.js │ │ ├── WorkflowsDialog.js │ │ ├── index.js │ │ ├── redux │ │ │ ├── actions.js │ │ │ ├── index.js │ │ │ ├── reducer.js │ │ │ ├── selectors.js │ │ │ └── thunk.js │ │ └── types.js │ ├── app-rest │ │ ├── RestForm.js │ │ ├── RestRoute.js │ │ ├── RestScript.js │ │ ├── index.js │ │ └── types.js │ ├── app-scheduled │ │ ├── RunNowDialog.js │ │ ├── ScheduledRoute.js │ │ ├── ScheduledTask.js │ │ ├── ScheduledTaskForm.js │ │ ├── ScheduledTaskRegistry.less │ │ ├── index.js │ │ └── types.js │ ├── app-workflow │ │ ├── FormEditor.js │ │ ├── FormEditor.less │ │ ├── RegistryPicker.js │ │ ├── index.js │ │ ├── types.js │ │ └── workflow.less │ ├── common │ │ ├── EventTypes.js │ │ ├── ScrollToTop.js │ │ ├── ak │ │ │ ├── AsyncLoadingMultiSelect.js │ │ │ ├── AsyncPicker.js │ │ │ ├── CheckedEditorField.js │ │ │ ├── EditorField.js │ │ │ ├── EditorField.less │ │ │ ├── FieldError.js │ │ │ ├── FieldError.less │ │ │ ├── FormField.js │ │ │ ├── JqlInput.js │ │ │ ├── LargeSelect.js │ │ │ ├── Loader.js │ │ │ ├── LoadingSpinner.js │ │ │ ├── LoadingSpinner.less │ │ │ ├── MultiSelect.js │ │ │ ├── RouterLink.js │ │ │ ├── SingleSelect.js │ │ │ ├── StaticField.js │ │ │ ├── StaticField.less │ │ │ ├── index.js │ │ │ ├── messages.js │ │ │ └── types.js │ │ ├── bindings.js │ │ ├── classNames.js │ │ ├── editor │ │ │ ├── Binding.js │ │ │ ├── Bindings.js │ │ │ ├── CM.js │ │ │ ├── ClassDocViewer.js │ │ │ ├── ClassDocViewer.less │ │ │ ├── Editor.js │ │ │ ├── Editor.less │ │ │ ├── EditorThemeContext.js │ │ │ ├── GlobalBindings.js │ │ │ ├── editor.reducer.js │ │ │ ├── index.js │ │ │ └── types.js │ │ ├── error.js │ │ ├── fixStyle.js │ │ ├── lazyRender.js │ │ ├── react-select-common.less │ │ ├── redux │ │ │ ├── actions.js │ │ │ ├── index.js │ │ │ └── selectors.js │ │ ├── script-list │ │ │ ├── ConnectedScriptPage.js │ │ │ ├── DeleteDialog.js │ │ │ ├── ItemViewPage.js │ │ │ ├── NotFoundPage.js │ │ │ ├── ScriptForm.js │ │ │ ├── ScriptForm.less │ │ │ ├── ScriptList.js │ │ │ ├── ScriptPage.js │ │ │ ├── breadcrumbs.js │ │ │ ├── focusOnRender.js │ │ │ ├── index.js │ │ │ └── types.js │ │ ├── script │ │ │ ├── Changelog.js │ │ │ ├── ExecutionBar.js │ │ │ ├── ExecutionBar.less │ │ │ ├── ExecutionDialog.js │ │ │ ├── Script.js │ │ │ ├── Script.less │ │ │ ├── ScriptParameters.js │ │ │ ├── WatchableScript.js │ │ │ ├── index.js │ │ │ └── types.js │ │ └── types.js │ ├── const.less │ ├── flex.less │ ├── i18n │ │ ├── admin.i18n.js │ │ ├── audit.i18n.js │ │ ├── cf.i18n.js │ │ ├── common.i18n.js │ │ ├── console.i18n.js │ │ ├── listener.i18n.js │ │ ├── registry.i18n.js │ │ ├── rest.i18n.js │ │ └── scheduled.i18n.js │ └── service │ │ ├── adminScript.service.js │ │ ├── ajaxHelper.js │ │ ├── auditLogService.js │ │ ├── binding.service.js │ │ ├── console.service.js │ │ ├── execution.service.js │ │ ├── extrasService.js │ │ ├── fieldConfig.service.js │ │ ├── go.service.js │ │ ├── index.js │ │ ├── jira.service.js │ │ ├── jqlScript.service.js │ │ ├── listener.service.js │ │ ├── preference.service.js │ │ ├── registry.service.js │ │ ├── rest.service.js │ │ ├── scheduledTask.service.js │ │ ├── types.js │ │ └── watcher.service.js ├── webpack.config.js └── yarn.lock ├── pom.xml └── src ├── examples └── groovy │ ├── admin-param.groovy │ ├── inject-field.groovy │ ├── inject-var.groovy │ ├── rest-simple.groovy │ ├── stc-bug.groovy │ ├── test-deprecation.groovy │ ├── tests │ ├── GroovyDocTest.groovy │ ├── ScriptedFunction.groovy │ ├── ScriptedFunctionWithDeps.groovy │ ├── ScriptedValuesFunction.groovy │ ├── basicRest.groovy │ ├── binding-test.groovy │ ├── classNameListenerEvent.groovy │ ├── containerService.groovy │ ├── dateExtension.groovy │ ├── go │ │ ├── BorkedObject.groovy │ │ ├── GlobalObject.groovy │ │ ├── NonExistingImport.groovy │ │ ├── SlowGlobalObject.groovy │ │ ├── WithGoDependency.groovy │ │ ├── WithJswModule.groovy │ │ ├── WithPluginModule.groovy │ │ ├── WithStandardModule.groovy │ │ ├── admin-param-go.groovy │ │ └── injection-go.groovy │ ├── jql │ │ ├── borkedFunc.groovy │ │ └── go.groovy │ ├── jsonSlurper.groovy │ ├── jswModule.groovy │ ├── listener.groovy │ ├── logging.groovy │ ├── pluginClassNameListenerEvent.groovy │ ├── pluginModule.groovy │ ├── pluginModuleWithScriptParam.groovy │ ├── scriptField.groovy │ ├── standardModule.groovy │ ├── stc-error.groovy │ ├── stc-getat-object-failure.groovy │ └── withPlugin.groovy │ └── wf-boolParam.groovy ├── main ├── antlr4 │ └── ru │ │ └── mail │ │ └── jira │ │ └── plugins │ │ └── groovy │ │ └── impl │ │ └── jql │ │ └── antlr │ │ ├── AggregateExpressionQuery.g4 │ │ ├── CommentedQuery.g4 │ │ └── DateComparisonQuery.g4 ├── java │ └── ru │ │ └── mail │ │ └── jira │ │ └── plugins │ │ └── groovy │ │ ├── api │ │ ├── PluginLauncher.java │ │ ├── dao │ │ │ ├── FieldConfigDao.java │ │ │ ├── GlobalObjectDao.java │ │ │ ├── ListenerDao.java │ │ │ └── RegistryDao.java │ │ ├── dto │ │ │ ├── CacheStatsDto.java │ │ │ ├── ChangelogDto.java │ │ │ ├── JiraIssueReference.java │ │ │ ├── JiraUser.java │ │ │ ├── Page.java │ │ │ ├── PickerOption.java │ │ │ ├── PickerResultSet.java │ │ │ ├── ScriptDescription.java │ │ │ ├── ScriptForm.java │ │ │ ├── ScriptParamDto.java │ │ │ ├── StaticCheckForm.java │ │ │ ├── admin │ │ │ │ ├── AdminScriptDto.java │ │ │ │ ├── AdminScriptForm.java │ │ │ │ └── AdminScriptOutcome.java │ │ │ ├── audit │ │ │ │ ├── AuditLogEntryDto.java │ │ │ │ └── AuditLogEntryForm.java │ │ │ ├── cf │ │ │ │ ├── FieldConfigDto.java │ │ │ │ ├── FieldConfigForm.java │ │ │ │ ├── FieldScriptDto.java │ │ │ │ ├── PreviewForm.java │ │ │ │ └── PreviewResult.java │ │ │ ├── console │ │ │ │ ├── ConsoleResponse.java │ │ │ │ └── ScriptRequest.java │ │ │ ├── directory │ │ │ │ ├── ParentForm.java │ │ │ │ ├── RegistryScriptDto.java │ │ │ │ ├── RegistryScriptForm.java │ │ │ │ ├── ScriptDirectoryDto.java │ │ │ │ └── ScriptDirectoryForm.java │ │ │ ├── docs │ │ │ │ ├── ClassDoc.java │ │ │ │ ├── MethodDoc.java │ │ │ │ ├── ParameterDoc.java │ │ │ │ └── TypeDoc.java │ │ │ ├── error │ │ │ │ ├── CompilationMessage.java │ │ │ │ └── PositionedCompilationMessage.java │ │ │ ├── execution │ │ │ │ ├── ScriptExecutionDto.java │ │ │ │ └── ScriptExecutionSummary.java │ │ │ ├── global │ │ │ │ ├── GlobalObjectDto.java │ │ │ │ └── GlobalObjectForm.java │ │ │ ├── jql │ │ │ │ ├── JqlFunctionForm.java │ │ │ │ └── JqlFunctionScriptDto.java │ │ │ ├── listener │ │ │ │ ├── ConditionDescriptor.java │ │ │ │ ├── ConditionType.java │ │ │ │ ├── EventListenerDto.java │ │ │ │ ├── EventListenerForm.java │ │ │ │ ├── IssueEventType.java │ │ │ │ └── ScriptedEventListener.java │ │ │ ├── notification │ │ │ │ └── NotificationDto.java │ │ │ ├── rest │ │ │ │ ├── HttpMethod.java │ │ │ │ ├── RestScriptDto.java │ │ │ │ ├── RestScriptForm.java │ │ │ │ └── Script.java │ │ │ ├── scheduled │ │ │ │ ├── RunInfo.java │ │ │ │ ├── ScheduledTaskDto.java │ │ │ │ ├── ScheduledTaskForm.java │ │ │ │ ├── TaskResult.java │ │ │ │ └── TransitionOptionsDto.java │ │ │ └── workflow │ │ │ │ ├── WorkflowActionDto.java │ │ │ │ ├── WorkflowActionItem.java │ │ │ │ ├── WorkflowDto.java │ │ │ │ └── WorkflowScriptType.java │ │ ├── e │ │ │ └── UnableToLoadPluginException.java │ │ ├── entity │ │ │ ├── AbstractChangelog.java │ │ │ ├── AbstractScript.java │ │ │ ├── AdminScript.java │ │ │ ├── AdminScriptChangelog.java │ │ │ ├── AuditLogEntry.java │ │ │ ├── AuditLogIssueRelation.java │ │ │ ├── Changelog.java │ │ │ ├── EntityAction.java │ │ │ ├── EntityType.java │ │ │ ├── FieldConfigChangelog.java │ │ │ ├── FieldScript.java │ │ │ ├── GlobalObject.java │ │ │ ├── GlobalObjectChangelog.java │ │ │ ├── JqlFunctionScript.java │ │ │ ├── JqlFunctionScriptChangelog.java │ │ │ ├── Listener.java │ │ │ ├── ListenerChangelog.java │ │ │ ├── RestChangelog.java │ │ │ ├── RestScript.java │ │ │ ├── ScheduledTask.java │ │ │ ├── ScheduledTaskChangelog.java │ │ │ ├── ScheduledTaskType.java │ │ │ ├── Script.java │ │ │ ├── ScriptDirectory.java │ │ │ ├── ScriptExecution.java │ │ │ └── Watcher.java │ │ ├── jql │ │ │ ├── CustomFunction.java │ │ │ ├── CustomQueryFunction.java │ │ │ ├── ScriptedJqlFunction.java │ │ │ ├── ScriptedJqlQueryFunction.java │ │ │ └── ScriptedJqlValuesFunction.java │ │ ├── repository │ │ │ ├── AdminScriptRepository.java │ │ │ ├── AuditLogRepository.java │ │ │ ├── EventListenerRepository.java │ │ │ ├── ExecutionRepository.java │ │ │ ├── FieldConfigRepository.java │ │ │ ├── GlobalObjectRepository.java │ │ │ ├── JqlFunctionRepository.java │ │ │ ├── RestRepository.java │ │ │ ├── ScheduledTaskRepository.java │ │ │ └── ScriptRepository.java │ │ ├── script │ │ │ ├── CompiledScript.java │ │ │ ├── ExecutionContext.java │ │ │ ├── GlobalObjectModule.java │ │ │ ├── ParamType.java │ │ │ ├── ParseContext.java │ │ │ ├── PluginModule.java │ │ │ ├── ResolvedConstructorArgument.java │ │ │ ├── ScriptExecutionOutcome.java │ │ │ ├── ScriptInjection.java │ │ │ ├── ScriptParam.java │ │ │ ├── ScriptParamFactory.java │ │ │ ├── ScriptType.java │ │ │ ├── StandardModule.java │ │ │ ├── WithParam.java │ │ │ ├── WithPlugin.java │ │ │ ├── binding │ │ │ │ ├── BindingDescriptor.java │ │ │ │ ├── BindingDescriptorImpl.java │ │ │ │ ├── BindingProvider.java │ │ │ │ └── LazyDocBindingDescriptorImpl.java │ │ │ └── statik │ │ │ │ └── WarningMessage.java │ │ ├── service │ │ │ ├── GroovyDocService.java │ │ │ ├── InjectionResolver.java │ │ │ ├── JqlFunctionService.java │ │ │ ├── NotificationService.java │ │ │ ├── PluginDataService.java │ │ │ ├── ScheduledTaskService.java │ │ │ ├── ScriptInvalidationService.java │ │ │ ├── ScriptService.java │ │ │ ├── SentryService.java │ │ │ ├── SingletonFactory.java │ │ │ ├── TestHelperService.java │ │ │ ├── WatcherService.java │ │ │ └── admin │ │ │ │ ├── AdminScriptService.java │ │ │ │ ├── BuiltInScript.java │ │ │ │ └── BuiltInScriptManager.java │ │ └── util │ │ │ ├── PluginLifecycleAware.java │ │ │ └── WithPluginLoader.java │ │ ├── impl │ │ ├── AuditService.java │ │ ├── InjectionResolverImpl.java │ │ ├── NotificationServiceImpl.java │ │ ├── OldExecutionDeletionScheduler.java │ │ ├── PermissionHelper.java │ │ ├── PluginDataServiceImpl.java │ │ ├── PluginLauncherImpl.java │ │ ├── ScriptClosure.java │ │ ├── ScriptServiceImpl.java │ │ ├── WatcherServiceImpl.java │ │ ├── admin │ │ │ ├── AdminScriptServiceImpl.java │ │ │ ├── BuiltInScriptManagerImpl.java │ │ │ └── builtIn │ │ │ │ ├── AddFavouriteDashboard.java │ │ │ │ ├── ClearCache.java │ │ │ │ ├── DeleteAllExecutions.java │ │ │ │ ├── FindScriptByUuid.java │ │ │ │ ├── FindScriptText.java │ │ │ │ ├── FixResolution.java │ │ │ │ ├── RecentErrors.java │ │ │ │ ├── SentryConfiguration.java │ │ │ │ ├── SwitchUser.java │ │ │ │ └── TransferOwnership.java │ │ ├── cf │ │ │ ├── DateScriptedCFType.java │ │ │ ├── DateTimeScriptedCFType.java │ │ │ ├── FieldPreviewService.java │ │ │ ├── FieldValueCache.java │ │ │ ├── FieldValueExtractor.java │ │ │ ├── MultiUserScriptedCFType.java │ │ │ ├── NumberCFType.java │ │ │ ├── ScriptedCFType.java │ │ │ ├── ScriptedFieldConfigItemType.java │ │ │ ├── TemplateScriptedCFType.java │ │ │ ├── TextScriptedCFType.java │ │ │ ├── UserScriptedCFType.java │ │ │ └── ValueHolder.java │ │ ├── dao │ │ │ ├── FieldConfigDaoImpl.java │ │ │ ├── GlobalObjectDaoImpl.java │ │ │ ├── ListenerDaoImpl.java │ │ │ └── RegistryDaoImpl.java │ │ ├── groovy │ │ │ ├── ExecutionContextHolder.java │ │ │ ├── InjectionExtension.java │ │ │ ├── InjectionVisitor.java │ │ │ ├── LoadClassesExtension.java │ │ │ ├── PackageCustomizer.java │ │ │ ├── ParamExtension.java │ │ │ ├── ParseContextHolder.java │ │ │ ├── WithPluginExtension.java │ │ │ ├── WithPluginVisitor.java │ │ │ ├── log │ │ │ │ ├── ContextAwareScriptLogger.java │ │ │ │ ├── ContextLogSink.java │ │ │ │ ├── LogTransformer.java │ │ │ │ └── LogTransformerImpl.java │ │ │ ├── statik │ │ │ │ ├── CompileStaticExtension.java │ │ │ │ ├── DeprecatedAstVisitor.java │ │ │ │ ├── ExtendedStaticCompileTransformation.java │ │ │ │ ├── TypeBasedTypeCheckingExtension.java │ │ │ │ └── TypeUtil.java │ │ │ └── var │ │ │ │ ├── GlobalObjectClassLoader.java │ │ │ │ └── GlobalObjectsBindingProvider.java │ │ ├── jql │ │ │ ├── CustomClauseQueryFactory.java │ │ │ ├── JqlFieldSearcher.java │ │ │ ├── JqlFunctionCFType.java │ │ │ ├── JqlFunctionServiceImpl.java │ │ │ ├── JqlInitializer.java │ │ │ ├── ModuleManager.java │ │ │ ├── ModuleReplicationService.java │ │ │ ├── function │ │ │ │ ├── QueryFunctionAdapter.java │ │ │ │ ├── ScriptedFunctionAdapter.java │ │ │ │ ├── ValuesFunctionAdapter.java │ │ │ │ └── builtin │ │ │ │ │ ├── AbstractBuiltInQueryFunction.java │ │ │ │ │ ├── AbstractCommentQueryFunction.java │ │ │ │ │ ├── AbstractEpicFunction.java │ │ │ │ │ ├── AbstractIssueLinkFunction.java │ │ │ │ │ ├── AbstractLinkedIssuesOfRecursiveFunction.java │ │ │ │ │ ├── AbstractSubTaskFunction.java │ │ │ │ │ ├── AbstractSubTaskRelationFunction.java │ │ │ │ │ ├── CommentedFunction.java │ │ │ │ │ ├── DateCompareFunction.java │ │ │ │ │ ├── EpicsOfFunction.java │ │ │ │ │ ├── HasCommentsFunction.java │ │ │ │ │ ├── HasLinkTypeFunction.java │ │ │ │ │ ├── HasLinksFunction.java │ │ │ │ │ ├── HasRemoteLinksFunction.java │ │ │ │ │ ├── HasSubTasksFunction.java │ │ │ │ │ ├── IssueFieldMatch.java │ │ │ │ │ ├── IssuesInEpics.java │ │ │ │ │ ├── LastCommentFunction.java │ │ │ │ │ ├── LastUpdatedFunction.java │ │ │ │ │ ├── LinkedIssueCollector.java │ │ │ │ │ ├── LinkedIssuesOfFunction.java │ │ │ │ │ ├── LinkedIssuesOfRecursive.java │ │ │ │ │ ├── LinkedIssuesOfRecursiveLimited.java │ │ │ │ │ ├── LinkedIssuesOfRemoteFunction.java │ │ │ │ │ ├── MemberOfRoleFunction.java │ │ │ │ │ ├── ParentsOfFunction.java │ │ │ │ │ ├── SearchHelper.java │ │ │ │ │ ├── SubTasksOfFunction.java │ │ │ │ │ ├── WorkLoggedFunction.java │ │ │ │ │ ├── aggregate │ │ │ │ │ └── AggregateExpressionFunction.java │ │ │ │ │ ├── expression │ │ │ │ │ ├── AllVariableExpressionsVisitor.java │ │ │ │ │ ├── AllVariablesMemorizerExtension.java │ │ │ │ │ ├── DateExtractor.java │ │ │ │ │ ├── DateTimeExtractor.java │ │ │ │ │ ├── DoubleCFExtractor.java │ │ │ │ │ ├── DoubleExtractor.java │ │ │ │ │ ├── ExpressionFunction.java │ │ │ │ │ ├── ExpressionIssueIdCollector.java │ │ │ │ │ ├── JqlFunctionValidationException.java │ │ │ │ │ ├── LuceneFieldValueExtractor.java │ │ │ │ │ ├── MillisecondsExtractor.java │ │ │ │ │ ├── ShellUtils.java │ │ │ │ │ ├── UserExtractor.java │ │ │ │ │ └── WorkRatioExtractor.java │ │ │ │ │ ├── jsw │ │ │ │ │ ├── AbstractSprintHistoryFunction.java │ │ │ │ │ ├── AddedAfterSprintStartFunction.java │ │ │ │ │ ├── RemovedAfterSprintStartFunction.java │ │ │ │ │ └── SprintHistoryCollector.java │ │ │ │ │ ├── query │ │ │ │ │ ├── AbstractEntityQueryParser.java │ │ │ │ │ ├── CommentQueryParser.java │ │ │ │ │ ├── JqlFunctionParser.java │ │ │ │ │ ├── LastUpdatedQueryParser.java │ │ │ │ │ ├── QueryParseResult.java │ │ │ │ │ ├── QueryUtil.java │ │ │ │ │ └── WorkLogQueryParser.java │ │ │ │ │ └── version │ │ │ │ │ ├── AbstractVersionFunction.java │ │ │ │ │ ├── ReleaseDateFunction.java │ │ │ │ │ └── StartDateFunction.java │ │ │ └── indexers │ │ │ │ ├── AdditionalFieldsCommentExtractor.java │ │ │ │ ├── LastUpdatedByIndexer.java │ │ │ │ └── RemoteLinksIndexer.java │ │ ├── jsw │ │ │ ├── DelegatingJiraSoftwareHelper.java │ │ │ ├── JiraSoftwareHelper.java │ │ │ ├── JiraSoftwareHelperFactory.java │ │ │ └── JiraSoftwareHelperImpl.java │ │ ├── listener │ │ │ └── EventListenerInvoker.java │ │ ├── param │ │ │ ├── ScriptParamFactoryImpl.java │ │ │ └── ScriptParamImpl.java │ │ ├── repository │ │ │ ├── AdminScriptRepositoryImpl.java │ │ │ ├── AuditLogRepositoryImpl.java │ │ │ ├── EventListenerRepositoryImpl.java │ │ │ ├── ExecutionRepositoryImpl.java │ │ │ ├── FieldConfigRepositoryImpl.java │ │ │ ├── GlobalObjectRepositoryImpl.java │ │ │ ├── JqlFunctionRepositoryImpl.java │ │ │ ├── RestRepositoryImpl.java │ │ │ ├── ScheduledTaskRepositoryImpl.java │ │ │ ├── ScriptRepositoryImpl.java │ │ │ ├── ValidationUtils.java │ │ │ └── querydsl │ │ │ │ ├── QAbstractChangelog.java │ │ │ │ ├── QAbstractScript.java │ │ │ │ ├── QAuditLogEntry.java │ │ │ │ ├── QAuditLogIssueRelation.java │ │ │ │ ├── QFieldConfig.java │ │ │ │ └── QScriptExecution.java │ │ ├── scheduled │ │ │ ├── JobUtil.java │ │ │ └── ScheduledTaskServiceImpl.java │ │ ├── sentry │ │ │ └── SentryServiceImpl.java │ │ ├── service │ │ │ ├── GroovyDocServiceImpl.java │ │ │ ├── ScriptInvalidationServiceImpl.java │ │ │ └── SingletonFactoryImpl.java │ │ ├── upgrade │ │ │ └── Upgrade001CreateAuditLogIssueRelation.java │ │ ├── var │ │ │ ├── HttpClientBindingDescriptor.java │ │ │ ├── LoggerBindingDescriptor.java │ │ │ ├── ScriptTypeBindingProvider.java │ │ │ └── TemplateEngineBindingDescriptor.java │ │ └── workflow │ │ │ ├── ScriptDescriptor.java │ │ │ ├── ScriptedCondition.java │ │ │ ├── ScriptedFunction.java │ │ │ ├── ScriptedValidator.java │ │ │ ├── WorkflowHelper.java │ │ │ ├── inline │ │ │ ├── InlineScriptConditionFactory.java │ │ │ ├── InlineScriptFunctionFactory.java │ │ │ ├── InlineScriptValidatorFactory.java │ │ │ └── InlineScriptWorkflowPluginFactory.java │ │ │ ├── registry │ │ │ ├── RegistryScriptConditionFactory.java │ │ │ ├── RegistryScriptFunctionFactory.java │ │ │ ├── RegistryScriptValidatorFactory.java │ │ │ └── RegistryScriptWorkflowPluginFactory.java │ │ │ └── search │ │ │ ├── AllScriptUsageCollector.java │ │ │ ├── ScriptUsageCollector.java │ │ │ ├── WorkflowSearchCollector.java │ │ │ └── WorkflowSearchService.java │ │ ├── rest │ │ ├── AdminScriptResource.java │ │ ├── AuditLogResource.java │ │ ├── BindingResource.java │ │ ├── ConsoleResource.java │ │ ├── CustomRestResource.java │ │ ├── ExecutionResource.java │ │ ├── ExtrasResource.java │ │ ├── FieldConfigResource.java │ │ ├── GlobalObjectResource.java │ │ ├── JiraApiResource.java │ │ ├── JqlFunctionResource.java │ │ ├── ListenerResource.java │ │ ├── RegistryResource.java │ │ ├── RestResource.java │ │ ├── ScheduledTaskResource.java │ │ ├── StaticCheckResource.java │ │ └── WatcherResource.java │ │ ├── servlet │ │ ├── GroovyServlet.java │ │ └── IssuePanelContextProvider.java │ │ └── util │ │ ├── AnnotationUtil.java │ │ ├── AntlrUtil.java │ │ ├── Base64Util.java │ │ ├── ChangelogHelper.java │ │ ├── Const.java │ │ ├── CustomFieldHelper.java │ │ ├── ExceptionHelper.java │ │ ├── FieldUtil.java │ │ ├── JsonMapper.java │ │ ├── ObjectUtil.java │ │ ├── PluginComponentUtil.java │ │ ├── QueryDslTables.java │ │ ├── RestExecutor.java │ │ ├── RestExecutorSupplier.java │ │ ├── RestFieldException.java │ │ ├── ScriptUtil.java │ │ ├── UserMapper.java │ │ ├── ValidationException.java │ │ ├── cl │ │ ├── ClassLoaderUtil.java │ │ ├── ContextAwareClassLoader.java │ │ ├── DelegatingClassLoader.java │ │ ├── WithPluginLoaderBeanProcessor.java │ │ └── WithPluginLoaderInterceptor.java │ │ ├── compat │ │ ├── ArchivingHelper.java │ │ ├── ArchivingHelperFactory.java │ │ ├── ArchivingHelperImpl.java │ │ └── StubArchivingHelper.java │ │ ├── func │ │ ├── ExceptionalConsumer.java │ │ ├── ExceptionalFunction.java │ │ └── ExceptionalPredicate.java │ │ ├── lucene │ │ ├── IssueIdCollector.java │ │ ├── IssueIdJoinQueryFactory.java │ │ └── QueryUtil.java │ │ ├── spring │ │ └── ProxiedBeanPostProcessor.java │ │ └── tx │ │ ├── TestHelperServiceImpl.java │ │ ├── TransactionalAnnotationProcessor.java │ │ └── TransactionalInterceptor.java └── resources │ ├── AdditionalArithmeticOperators.groovy │ ├── META-INF │ ├── services │ │ └── org.codehaus.groovy.transform.ASTTransformation │ └── spring │ │ └── plugin-context.xml │ ├── atlassian-plugin.xml │ ├── images │ ├── pluginIcon.png │ └── pluginLogo.png │ └── ru │ └── mail │ └── jira │ └── plugins │ └── groovy │ ├── .gitignore │ ├── i18n.js │ ├── i18n.properties │ └── templates │ ├── inline-script-edit.vm │ ├── inline-script-view.vm │ ├── issue-panel.vm │ ├── main.vm │ ├── notification.vm │ ├── registry-script-edit.vm │ ├── registry-script-view.vm │ └── template-cf.vm └── test ├── java ├── it │ └── ru │ │ └── mail │ │ └── jira │ │ └── plugins │ │ └── groovy │ │ ├── BasicJqlQueryIT.java │ │ ├── BasicJqlValuesIT.java │ │ ├── BasicRestIT.java │ │ ├── ClassListenerIT.java │ │ ├── ClassLoaderIT.java │ │ ├── GlobalObjectIT.java │ │ ├── GlobalObjectWithModulesIT.java │ │ ├── InlineWorkflowIT.java │ │ ├── IssueListenerIT.java │ │ ├── JqlModulesIT.java │ │ ├── JqlQueryWithDepsIT.java │ │ ├── LauncherIT.java │ │ ├── PluginClassListenerIT.java │ │ ├── ScriptFieldIT.java │ │ ├── ScriptServiceIT.java │ │ ├── TransactionIT.java │ │ ├── crud │ │ ├── FieldConfigCrudIT.java │ │ ├── FieldConfigWithTemplateCrudIT.java │ │ ├── GlobalObjectCrudIT.java │ │ ├── ListenerCrudIT.java │ │ └── RegistryCrudIT.java │ │ └── util │ │ ├── ArquillianUtil.java │ │ ├── AuditLogHelper.java │ │ ├── ChangeLogHelper.java │ │ ├── CustomFieldHelper.java │ │ ├── Forms.java │ │ ├── HttpUtil.java │ │ ├── IssueHelper.java │ │ ├── ProjectHelper.java │ │ └── UserHelper.java └── ru │ └── mail │ └── jira │ └── plugins │ └── groovy │ └── impl │ ├── FileUtil.java │ ├── MockInjectionResolver.java │ └── ScriptServiceImplTest.java └── resources ├── arquillian.xml └── test_workflow.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea 3 | target 4 | .DS_Store 5 | src/main/resources/ru/mail/jira/plugins/groovy/js 6 | src/main/resources/META-INF/plugin-descriptors/wr-defs.xml 7 | -------------------------------------------------------------------------------- /.java-version: -------------------------------------------------------------------------------- 1 | 1.8 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | matrix: 2 | include: 3 | - language: java 4 | jdk: oraclejdk8 5 | cache: 6 | yarn: true 7 | directories: 8 | - $HOME/.m2/repository 9 | - js/node_modules 10 | install: true 11 | script: 12 | - mvn -B package 13 | - language: node_js 14 | node_js: 8 15 | cache: 16 | yarn: true 17 | directories: 18 | - js/node_modules 19 | install: true 20 | script: 21 | - cd js 22 | - yarn install --frozen-lockfile 23 | - yarn build-prod 24 | - yarn flow check --max-warnings=0 25 | notifications: 26 | email: 27 | recipients: 28 | - a.belostotskiy@corp.mail.ru 29 | on_success: always 30 | on_failure: always 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MyGroovy plugin 2 | 3 | [Atlassian marketplace](https://marketplace.atlassian.com/1218755) 4 | 5 | [Documentation](https://github.com/atlascommunity/jira-plugins-groovy/wiki) 6 | 7 | [Script examples](https://github.com/mailru/jira-scripts) 8 | -------------------------------------------------------------------------------- /js/.eslintignore: -------------------------------------------------------------------------------- 1 | src/vendor/* 2 | config/* 3 | flow-typed/* 4 | webpack.config.js 5 | -------------------------------------------------------------------------------- /js/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | .*/node_modules/jsonlint/.* 3 | 4 | [untyped] 5 | #todo: remove when select flow issues are resolved in atlaskit 6 | .*/node_modules/react-select 7 | 8 | [include] 9 | 10 | [libs] 11 | 12 | [lints] 13 | all=warn 14 | sketchy-null-string=off 15 | sketchy-null-bool=off 16 | sketchy-null-number=off 17 | deprecated-type=off 18 | unclear-type=off 19 | 20 | [options] 21 | suppress_comment=\\(.\\|\n\\)*\\$ExpectError 22 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe 23 | module.name_mapper.extension='less' -> 'less' 24 | experimental.const_params=true 25 | include_warnings=true 26 | 27 | [strict] 28 | -------------------------------------------------------------------------------- /js/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /js/config/polyfills.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | if (typeof Promise === 'undefined') { 4 | // Rejection tracking prevents a common issue where React gets into an 5 | // inconsistent state due to an error, but it gets swallowed by a Promise, 6 | // and the user has no idea what causes React's erratic future behavior. 7 | require('promise/lib/rejection-tracking').enable(); 8 | window.Promise = require('promise/lib/es6-extensions.js'); 9 | } 10 | 11 | // fetch() polyfill for making API calls. 12 | require('whatwg-fetch'); 13 | 14 | // Object.assign() is commonly used with React. 15 | // It will use the native implementation if it's present and isn't buggy. 16 | Object.assign = require('object-assign'); 17 | -------------------------------------------------------------------------------- /js/flow-typed/AJS.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | declare module 'AJS' { 3 | declare type FlagParameters = { 4 | title?: string, 5 | type?: 'success' | 'info' | 'warning' | 'error', 6 | body?: string, 7 | close?: 'auto' | 'manual' | 'never' 8 | }; 9 | 10 | declare interface Meta { 11 | get(string): string 12 | } 13 | 14 | declare type FlagType = { 15 | close(): void 16 | }; 17 | 18 | declare export default { 19 | contextPath(): string; 20 | flag(FlagParameters): FlagType; 21 | toInit: (() => void) => void; 22 | $: JQueryStatic; 23 | Meta: Meta; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /js/flow-typed/npm/@atlaskit/css-reset_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a4d2041b1c1369b143cb13596d463e9a 2 | // flow-typed version: <>/@atlaskit/css-reset_v^3.0.1/flow_v0.81.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * '@atlaskit/css-reset' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module '@atlaskit/css-reset' { 17 | declare module.exports: any; 18 | } 19 | -------------------------------------------------------------------------------- /js/flow-typed/npm/classnames_v2.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: cf86673cc32d185bdab1d2ea90578d37 2 | // flow-typed version: 614bf49aa8/classnames_v2.x.x/flow_>=v0.25.x 3 | 4 | type $npm$classnames$Classes = 5 | | string 6 | | { [className: string]: * } 7 | | false 8 | | void 9 | | null; 10 | 11 | declare module "classnames" { 12 | declare module.exports: ( 13 | ...classes: Array<$npm$classnames$Classes | $npm$classnames$Classes[]> 14 | ) => string; 15 | } 16 | 17 | declare module "classnames/bind" { 18 | declare module.exports: $Exports<"classnames">; 19 | } 20 | 21 | declare module "classnames/dedupe" { 22 | declare module.exports: $Exports<"classnames">; 23 | } 24 | -------------------------------------------------------------------------------- /js/flow-typed/npm/fast-memoize_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: c863339ce92b5c229d2b05908ea874a6 2 | // flow-typed version: <>/fast-memoize_v^2.3.2/flow_v0.67.1 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'fast-memoize' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'fast-memoize' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'fast-memoize/src/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'fast-memoize/src/index.js' { 31 | declare module.exports: $Exports<'fast-memoize/src/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /js/flow-typed/npm/react-codemirror2_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 09f8b562454ea5b4d3425944e962cc8a 2 | // flow-typed version: <>/react-codemirror2_v^5.1.0/flow_v0.81.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'react-codemirror2' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'react-codemirror2' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'react-codemirror2/index' { 29 | declare module.exports: $Exports<'react-codemirror2'>; 30 | } 31 | declare module 'react-codemirror2/index.js' { 32 | declare module.exports: $Exports<'react-codemirror2'>; 33 | } 34 | -------------------------------------------------------------------------------- /js/flow-typed/npm/react-string-replace_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 417ff657534869b9fa013c8156c48c99 2 | // flow-typed version: <>/react-string-replace_v^0.4.1/flow_v0.81.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'react-string-replace' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'react-string-replace' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'react-string-replace/index' { 29 | declare module.exports: $Exports<'react-string-replace'>; 30 | } 31 | declare module 'react-string-replace/index.js' { 32 | declare module.exports: $Exports<'react-string-replace'>; 33 | } 34 | -------------------------------------------------------------------------------- /js/flow-typed/stubs.js: -------------------------------------------------------------------------------- 1 | declare module 'less' { 2 | declare module.exports: void; 3 | } 4 | 5 | declare module 'external-i18n' { 6 | declare module.exports: any; 7 | } 8 | 9 | declare module 'extDefine' { 10 | declare module.exports: any; //todo 11 | } -------------------------------------------------------------------------------- /js/src/app-admin/ConnectedAdminScriptPage.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import {connect} from 'react-redux'; 3 | 4 | import memoizeOne from 'memoize-one'; 5 | import {createSelector} from 'reselect'; 6 | 7 | import orderBy from 'lodash/orderBy'; 8 | 9 | import {ScriptPage} from '../common/script-list'; 10 | 11 | import {orderedItemsSelector, updateFilter} from '../common/redux'; 12 | 13 | 14 | const itemsSelector = orderedItemsSelector(); 15 | //put built-in scripts in beginning of list 16 | const reorderedItemsSelector = createSelector( 17 | [itemsSelector], 18 | items => orderBy(items, 'builtIn', 'desc') 19 | ); 20 | 21 | export const ConnectedAdminScriptPage = connect( 22 | memoizeOne( 23 | ({watches, isReady, ...state}) => ({ 24 | items: reorderedItemsSelector(state), 25 | filter: state.filter, 26 | watches, isReady 27 | }) 28 | ), 29 | { updateFilter } 30 | )(ScriptPage); 31 | -------------------------------------------------------------------------------- /js/src/app-admin/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | export {AdminRoute} from './AdminRoute'; 3 | -------------------------------------------------------------------------------- /js/src/app-admin/types.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import type {ScriptEntity} from '../common/types'; 3 | import type {ParamType} from '../app-workflow/types'; 4 | 5 | 6 | export type AdminScriptType = ScriptEntity & { 7 | uuid: string, 8 | html: boolean, 9 | builtIn: boolean, 10 | builtInKey: ?string, 11 | resultWidth: ?('small' | 'medium' | 'large' | 'x-large'), 12 | params: ?Array, 13 | defaultValues: ?{[string]: any} 14 | }; 15 | 16 | export type AdminScriptOutcomeType = { 17 | success: boolean, 18 | message: ?string 19 | }; 20 | -------------------------------------------------------------------------------- /js/src/app-audit/AuditLogRoute.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React from 'react'; 3 | 4 | import {AuditLog} from './AuditLog'; 5 | 6 | 7 | // eslint-disable-next-line react/prefer-stateless-function 8 | export class AuditLogRoute extends React.PureComponent<{}> { 9 | render() { 10 | return ; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /js/src/app-audit/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {AuditLogRoute} from './AuditLogRoute'; 4 | -------------------------------------------------------------------------------- /js/src/app-audit/types.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import type {EntityAction, EntityType, Page} from '../common/types'; 3 | import type {JiraUser} from '../common/script/types'; 4 | import type {SingleValueType} from '../common/ak/types'; 5 | 6 | 7 | export type AuditLogEntry = { 8 | id: number, 9 | date: string, 10 | action: EntityAction, 11 | category: EntityType, 12 | user: JiraUser, 13 | deleted: boolean, 14 | scriptId: ?number, 15 | description: ?string, 16 | parentName: ?string, 17 | scriptName: ?string 18 | }; 19 | 20 | export type AuditLogData = Page; 21 | 22 | export type AuditLogFilterType = { 23 | users: $ReadOnlyArray, 24 | categories: $ReadOnlyArray, 25 | actions: $ReadOnlyArray 26 | }; 27 | -------------------------------------------------------------------------------- /js/src/app-console/ConsoleRoute.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React, {type Node} from 'react'; 3 | 4 | import Page from '@atlaskit/page'; 5 | import PageHeader from '@atlaskit/page-header'; 6 | import Breadcrumbs from '@atlaskit/breadcrumbs'; 7 | 8 | import {ScriptConsole} from './ScriptConsole'; 9 | 10 | import {PageTitleMessages} from '../i18n/common.i18n'; 11 | import {withRoot} from '../common/script-list/breadcrumbs'; 12 | import {ScrollToTop} from '../common/ScrollToTop'; 13 | 14 | 15 | export function ConsoleRoute(): Node { 16 | return ( 17 | 18 | {withRoot([])}} 20 | > 21 | {PageTitleMessages.console} 22 | 23 | 24 | 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /js/src/app-console/ScriptConsole.less: -------------------------------------------------------------------------------- 1 | @import (reference) "../flex"; 2 | @import (reference) "../const"; 3 | @import (reference) "~@atlaskit/util-shared-styles/src/borders"; 4 | 5 | 6 | .ScriptConsole { 7 | .flex-column; 8 | 9 | .result { 10 | .kipLyu { 11 | max-height: none; //very naive way to override styled components class value 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /js/src/app-console/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {ConsoleRoute} from './ConsoleRoute'; 4 | -------------------------------------------------------------------------------- /js/src/app-console/types.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export type ConsoleResult = { 4 | result: string, 5 | log: ?string, 6 | time: number 7 | }; 8 | -------------------------------------------------------------------------------- /js/src/app-fields/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {FieldsRoute} from './FieldsRoute'; 4 | -------------------------------------------------------------------------------- /js/src/app-fields/selectors.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import {createSelector} from 'reselect'; 3 | 4 | 5 | export const fieldConfigSelectorFactory = () => 6 | createSelector( 7 | [state => state.items, (_state, props) => props.id], 8 | (items, id) => items.find(it => it.id === id) 9 | ); 10 | -------------------------------------------------------------------------------- /js/src/app-fields/types.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import type {ChangelogType} from '../common/script/types'; 3 | 4 | 5 | export type FieldConfig = { 6 | id: number, 7 | name: string, 8 | description: ?string, 9 | uuid: string, 10 | customFieldName: string, 11 | contextName: string, 12 | scriptBody: string, 13 | changelogs: Array, 14 | cacheable: boolean, 15 | velocityParamsEnabled: boolean, 16 | needsTemplate: boolean, 17 | type: string, 18 | expectedType: string, 19 | searcher: ?string, 20 | template: ?string 21 | }; 22 | 23 | export type FieldConfigPreviewResult = { 24 | time: number, 25 | htmlResult: string 26 | }; 27 | 28 | export type FieldConfigItem = FieldConfig & { 29 | customFieldId: number, 30 | errorCount: number, 31 | warningCount: number 32 | }; 33 | -------------------------------------------------------------------------------- /js/src/app-go/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {GlobalObjectRoute} from './GlobalObjectRoute'; 4 | -------------------------------------------------------------------------------- /js/src/app-go/types.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import type {ScriptEntity} from '../common/types'; 3 | 4 | 5 | export type GlobalObjectScriptType = ScriptEntity & { 6 | uuid: string 7 | }; 8 | -------------------------------------------------------------------------------- /js/src/app-jql/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {JqlRoute} from './JqlRoute'; 4 | -------------------------------------------------------------------------------- /js/src/app-jql/types.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import type {ScriptEntity} from '../common/types'; 3 | 4 | 5 | export type JqlScriptType = ScriptEntity & { 6 | uuid: string 7 | }; 8 | -------------------------------------------------------------------------------- /js/src/app-listeners/ConditionPicker.less: -------------------------------------------------------------------------------- 1 | @import (reference) "../flex"; 2 | 3 | .ConditionPicker { 4 | .flex-column; 5 | 6 | border-radius: 3px; 7 | border: 1px solid #cccccc; 8 | 9 | padding: 3px; 10 | 11 | .ConditionPicker{ 12 | margin-bottom: 5px; 13 | 14 | &:hover { 15 | border-color: #8c8c8c; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /js/src/app-listeners/ListenerRegistry.less: -------------------------------------------------------------------------------- 1 | @import (reference) "../flex.less"; 2 | 3 | .Condition { 4 | border-radius: 2px; 5 | border: 1px solid #cccccc; 6 | padding: 4px; 7 | 8 | &.flex-row { 9 | > .ConditionName { 10 | .flex-vertical-middle; 11 | } 12 | 13 | > .ConditionBody { 14 | .flex-grow; 15 | margin-left: 10px; 16 | 17 | > .Condition:not(:first-child) { 18 | margin-top: 4px; 19 | } 20 | } 21 | } 22 | 23 | &:not(:last-child) { 24 | margin-bottom: 5px; 25 | } 26 | 27 | &:hover { 28 | border-color: #8c8c8c; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /js/src/app-listeners/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {ListenersRoute} from './ListenersRoute'; 4 | -------------------------------------------------------------------------------- /js/src/app-listeners/types.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import type {ScriptEntity} from '../common/types'; 3 | 4 | 5 | export type ConditionType = { 6 | type: 'CLASS_NAME' | 'ISSUE', 7 | typeIds: $ReadOnlyArray, 8 | projectIds: $ReadOnlyArray, 9 | className: ?string, 10 | pluginKey: ?string 11 | }; 12 | 13 | export type ConditionInputType = { 14 | type: ?'CLASS_NAME' | 'ISSUE', 15 | typeIds: $ReadOnlyArray, 16 | projectIds: $ReadOnlyArray, 17 | className: ?string, 18 | pluginKey: ?string 19 | }; 20 | 21 | export type ListenerType = ScriptEntity & { 22 | uuid: string, 23 | condition: ConditionType, 24 | alwaysTrack: boolean, 25 | initialized: boolean 26 | }; 27 | 28 | export type ListenerInputType = ScriptEntity & { 29 | uuid: string, 30 | condition: ConditionInputType 31 | }; 32 | -------------------------------------------------------------------------------- /js/src/app-main/MainApp.less: -------------------------------------------------------------------------------- 1 | @import (reference) '~@atlaskit/util-shared-styles/src/grid'; 2 | @import (reference) '../flex'; 3 | 4 | .MainApp { 5 | .flex-row; 6 | 7 | flex-wrap: wrap; 8 | 9 | > * { 10 | margin: @ak-grid-size; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /js/src/app-main/PageCard.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React, {type Node} from 'react'; 3 | 4 | import {RouterLink} from '../common/ak/RouterLink'; 5 | 6 | import './PageCard.less'; 7 | 8 | 9 | type Props = { 10 | title: string, 11 | href: string, 12 | description?: string 13 | }; 14 | 15 | export function PageCard({title, href, description}: Props): Node { 16 | return ( 17 | 18 |

19 | {title} 20 |

21 | {description && 22 |
23 | {description} 24 |
25 | } 26 |
27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /js/src/app-main/PageCard.less: -------------------------------------------------------------------------------- 1 | @import (reference) '~@atlaskit/util-shared-styles/src/borders'; 2 | @import (reference) '~@atlaskit/util-shared-styles/src/grid'; 3 | @import (reference) '../const'; 4 | @import (reference) '../flex'; 5 | 6 | 7 | .PageCard { 8 | .flex-column; 9 | 10 | width: 300px; 11 | 12 | border: 1px solid @border-color; 13 | border-radius: @ak-border-radius; 14 | padding: @ak-grid-size; 15 | 16 | &:hover { 17 | text-decoration: none; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /js/src/app-registry/Loader.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React, {Fragment, type ComponentType, type Element} from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {withRouter} from 'react-router-dom'; 5 | 6 | import memoizeOne from 'memoize-one'; 7 | 8 | import {LoadingSpinner} from '../common/ak/LoadingSpinner'; 9 | 10 | 11 | type Props = { 12 | ready: boolean, 13 | children: Node 14 | }; 15 | 16 | export class LoaderInternal extends React.PureComponent { 17 | render() { 18 | const {ready, children} = this.props; 19 | 20 | if (ready) { 21 | return {children}; 22 | } 23 | 24 | return ; 25 | } 26 | } 27 | 28 | export const Loader: ComponentType<{children: Element}> = ( 29 | withRouter(connect(memoizeOne(({ready}) => ({ready})))(LoaderInternal)) 30 | ); 31 | -------------------------------------------------------------------------------- /js/src/app-registry/ScriptDirectory.less: -------------------------------------------------------------------------------- 1 | @import (reference) '../flex'; 2 | 3 | .ScriptDirectoryActionsPlaceholder { 4 | .flex-row; 5 | 6 | width: 390px; 7 | height: 28px; 8 | margin-top: 4px; 9 | 10 | .ButtonPlaceholder { 11 | .flex-row; 12 | padding: 0 8px; 13 | } 14 | 15 | .ButtonContentPlaceholder { 16 | height: 20px; 17 | background-color: currentcolor; 18 | border-radius: 4px; 19 | opacity: 0.15; 20 | margin: 2px 4px; 21 | width: 136px; 22 | } 23 | 24 | .ButtonIcon { 25 | margin: 0 4px; 26 | } 27 | 28 | .IconButtonPlaceholder { 29 | margin: 0 8px; 30 | } 31 | } -------------------------------------------------------------------------------- /js/src/app-registry/ScriptForm.less: -------------------------------------------------------------------------------- 1 | @import (reference) '~@atlaskit/util-shared-styles/src/grid'; 2 | @import (reference) '../flex'; 3 | 4 | .ScriptForm { 5 | .flex-column; 6 | 7 | .formButtons { 8 | margin-top: @ak-grid-size*2; 9 | } 10 | 11 | .fit-content-width { 12 | width: fit-content; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /js/src/app-registry/UsageStatusFlag.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React from 'react'; 3 | 4 | import {connect} from 'react-redux'; 5 | 6 | import Flag, {FlagGroup} from '@atlaskit/flag'; 7 | import Spinner from '@atlaskit/spinner'; 8 | 9 | 10 | type Props = { 11 | ready: boolean 12 | }; 13 | 14 | class UsageStatusFlagInternal extends React.PureComponent { 15 | render() { 16 | const {ready} = this.props; 17 | 18 | if (ready) { 19 | return null; 20 | } 21 | 22 | return ( 23 | 24 | } 27 | title="Collecting script usage info" 28 | appearance="info" 29 | /> 30 | 31 | ); 32 | } 33 | } 34 | 35 | export const UsageStatusFlag = connect( 36 | state => ({ 37 | ready: state.scriptUsage.ready 38 | }) 39 | )(UsageStatusFlagInternal); 40 | -------------------------------------------------------------------------------- /js/src/app-registry/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {RegistryRoute} from './RegistryRoute'; 4 | -------------------------------------------------------------------------------- /js/src/app-registry/redux/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export * from './actions'; 4 | export * from './thunk'; 5 | export * from './reducer'; 6 | export * from './selectors'; 7 | -------------------------------------------------------------------------------- /js/src/app-rest/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {RestRoute} from './RestRoute'; 4 | -------------------------------------------------------------------------------- /js/src/app-rest/types.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import type {HttpMethod, ScriptEntity} from '../common/types'; 3 | 4 | 5 | export type RestScriptType = ScriptEntity & { 6 | uuid: string, 7 | methods: $ReadOnlyArray, 8 | groups: $ReadOnlyArray 9 | }; 10 | -------------------------------------------------------------------------------- /js/src/app-scheduled/ScheduledTaskRegistry.less: -------------------------------------------------------------------------------- 1 | @import (reference) "../flex"; 2 | @import (reference) "~@atlaskit/util-shared-styles/src/colors.less"; 3 | 4 | .TaskRunMessage { 5 | .flex-vertical-middle; 6 | 7 | font-weight: 500; 8 | padding: 0 5px; 9 | } 10 | -------------------------------------------------------------------------------- /js/src/app-scheduled/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {ScheduledRoute} from './ScheduledRoute'; 4 | -------------------------------------------------------------------------------- /js/src/app-workflow/FormEditor.less: -------------------------------------------------------------------------------- 1 | .hidden { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /js/src/app-workflow/types.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export type ParamTypeEnum = 'BOOLEAN' | 'STRING' | 'TEXT' | 'LONG' | 'DOUBLE' | 'CUSTOM_FIELD' | 'USER' | 'GROUP' | 'RESOLUTION' | 'SCRIPT'; 4 | 5 | export type ParamType = { 6 | name: string, 7 | displayName: string, 8 | paramType: ParamTypeEnum, 9 | optional: boolean 10 | }; 11 | 12 | export type ScriptType = 'CONDITION' | 'VALIDATOR' | 'FUNCTION'; 13 | 14 | export type ScriptDescriptionType = { 15 | id: number, 16 | name: string, 17 | description: ?string, 18 | params: ?Array 19 | }; 20 | -------------------------------------------------------------------------------- /js/src/app-workflow/workflow.less: -------------------------------------------------------------------------------- 1 | .criteria-item .scriptRow { 2 | margin-right: 20px; 3 | } 4 | -------------------------------------------------------------------------------- /js/src/common/EventTypes.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export type InputEvent = SyntheticEvent; 4 | -------------------------------------------------------------------------------- /js/src/common/ScrollToTop.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React from 'react'; 3 | 4 | import {withRouter, type Location} from 'react-router-dom'; 5 | 6 | 7 | class ScrollToTopInternal extends React.PureComponent<{location: Location}> { 8 | componentDidMount() { 9 | const {location} = this.props; 10 | 11 | if (!(location.state && location.state.focus)) { 12 | window.scrollTo(0, 0); 13 | // eslint-disable-next-line no-console 14 | console.log('scrolling to top'); 15 | } 16 | } 17 | 18 | render() { 19 | return null; 20 | } 21 | } 22 | 23 | export const ScrollToTop = withRouter(ScrollToTopInternal); 24 | -------------------------------------------------------------------------------- /js/src/common/ak/EditorField.less: -------------------------------------------------------------------------------- 1 | @import (reference) "~@atlaskit/util-shared-styles/src/borders"; 2 | 3 | 4 | .ak-editor { 5 | .cm-s-eclipse { 6 | background-color: transparent; 7 | } 8 | 9 | .react-codemirror2 { 10 | width: 100%; 11 | } 12 | 13 | .CodeMirror { 14 | border-radius: @ak-border-radius; 15 | 16 | .CodeMirror-gutters { 17 | //wasn't good idea 18 | //background: transparent; 19 | border-bottom-left-radius: @ak-border-radius; 20 | border-top-left-radius: @ak-border-radius; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /js/src/common/ak/FieldError.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React, {type Node} from 'react'; 3 | 4 | import ErrorIcon from '@atlaskit/icon/glyph/error'; 5 | 6 | import './FieldError.less'; 7 | 8 | 9 | type FieldErrorProps = { 10 | error: Node 11 | }; 12 | 13 | export function FieldError({error}: FieldErrorProps): Node { 14 | return ( 15 |
16 | 17 | {error} 18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /js/src/common/ak/FieldError.less: -------------------------------------------------------------------------------- 1 | @import (reference) "~@atlaskit/util-shared-styles/src/grid"; 2 | @import (reference) "~@atlaskit/util-shared-styles/src/colors"; 3 | @import (reference) '../../flex.less'; 4 | 5 | .FieldError { 6 | .flex-row; 7 | 8 | align-items: center; 9 | color: @ak-color-R400; 10 | margin-top: @ak-grid-size; 11 | } 12 | -------------------------------------------------------------------------------- /js/src/common/ak/FormField.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React, {type Node} from 'react'; 3 | 4 | import {Field} from '@atlaskit/form'; 5 | 6 | 7 | type Props = {| 8 | label: string, 9 | isRequired?: boolean, 10 | isLabelHidden: boolean, 11 | 12 | isInvalid?: boolean, 13 | invalidMessage?: Node, 14 | 15 | children: Node, 16 | 17 | helperText?: string 18 | |}; 19 | 20 | export class FormField extends React.PureComponent { 21 | static defaultProps = { 22 | isLabelHidden: false 23 | }; 24 | 25 | render() { 26 | const {children, isInvalid, invalidMessage, ...etc} = this.props; 27 | 28 | return ( 29 | 39 | {children} 40 | 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /js/src/common/ak/Loader.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React, {Fragment, type Element, type ComponentType} from 'react'; 3 | import {connect} from 'react-redux'; 4 | import {withRouter} from 'react-router-dom'; 5 | 6 | import memoizeOne from 'memoize-one'; 7 | 8 | import {LoadingSpinner} from './LoadingSpinner'; 9 | 10 | 11 | type Props = { 12 | isReady: boolean, 13 | children: Element 14 | }; 15 | 16 | export class LoaderInternal extends React.PureComponent { 17 | render() { 18 | const {isReady, children} = this.props; 19 | 20 | if (isReady) { 21 | return {children}; 22 | } 23 | 24 | return ; 25 | } 26 | } 27 | 28 | export const Loader: ComponentType<{children: Element}> = withRouter(connect( 29 | memoizeOne( 30 | ({isReady}): {isReady: boolean} => ({isReady}), 31 | ) 32 | )(LoaderInternal)); 33 | -------------------------------------------------------------------------------- /js/src/common/ak/LoadingSpinner.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React, {type Node} from 'react'; 3 | 4 | import Spinner from '@atlaskit/spinner'; 5 | 6 | import './LoadingSpinner.less'; 7 | 8 | 9 | export function LoadingSpinner(): Node { 10 | return ( 11 |
12 |
13 | 14 |
15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /js/src/common/ak/LoadingSpinner.less: -------------------------------------------------------------------------------- 1 | @import (reference) '../../flex.less'; 2 | 3 | 4 | .LoadingSpinner { 5 | .flex-vertical-middle; 6 | height: 100px; 7 | } 8 | -------------------------------------------------------------------------------- /js/src/common/ak/RouterLink.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React, {type Node} from 'react'; 3 | import {Link} from 'react-router-dom'; 4 | 5 | 6 | type Props = { 7 | children: Node, 8 | className?: string, 9 | href: string, 10 | onMouseEnter?: (SyntheticEvent) => void, 11 | onMouseLeave?: (SyntheticEvent) => void, 12 | }; 13 | 14 | export class RouterLink extends React.PureComponent { 15 | render() { 16 | const { 17 | children, 18 | className, 19 | href, 20 | onMouseEnter, 21 | onMouseLeave, 22 | } = this.props; 23 | 24 | return ( 25 | 31 | {children} 32 | 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /js/src/common/ak/SingleSelect.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React from 'react'; 3 | 4 | import {Label} from '@atlaskit/field-base'; 5 | 6 | import {LargeSelect} from './LargeSelect'; 7 | 8 | import type {OldSelectItem, OldSelectValue} from './types'; 9 | 10 | import type {FieldProps, MutableFieldProps} from '../types'; 11 | 12 | 13 | type SingleSelectProps = {| 14 | ...FieldProps, 15 | ...MutableFieldProps>, 16 | options: Array>, 17 | name?: string 18 | |}; 19 | 20 | export class SingleSelect extends React.PureComponent> { 21 | render() { 22 | const {label, isRequired, isLabelHidden, options, value, onChange, ...props} = this.props; 23 | 24 | return ( 25 |
26 |
29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /js/src/common/ak/StaticField.less: -------------------------------------------------------------------------------- 1 | @import (reference) '~@atlaskit/util-shared-styles/src/grid'; 2 | @import (reference) '~@atlaskit/util-shared-styles/src/fonts'; 3 | 4 | .static-field { 5 | align-items: center; 6 | box-sizing: border-box; 7 | display: flex; 8 | flex: 1 0 auto; 9 | font-size: @ak-font-size-default; 10 | justify-content: space-between; 11 | line-height: @ak-grid-size * 2.5; 12 | max-width: 100%; 13 | overflow: hidden; 14 | word-wrap: break-word; 15 | padding: @ak-grid-size + 2px 0; 16 | } 17 | -------------------------------------------------------------------------------- /js/src/common/ak/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {Loader} from './Loader'; 4 | export {LoadingSpinner} from './LoadingSpinner'; 5 | export {EditorField} from './EditorField'; 6 | export {CheckedEditorField} from './CheckedEditorField'; 7 | export {FormField} from './FormField'; 8 | export {FieldError} from './FieldError'; 9 | export {RouterLink} from './RouterLink'; 10 | export {StaticField} from './StaticField'; 11 | export {ErrorMessage, InfoMessage, SuccessMessage} from './messages'; 12 | export {JqlInput} from './JqlInput'; 13 | 14 | export {AsyncPicker} from './AsyncPicker'; 15 | export {MultiSelect} from './MultiSelect'; 16 | export {AsyncLoadingMultiSelect} from './AsyncLoadingMultiSelect'; 17 | 18 | export type {StaticCheckScriptType} from './CheckedEditorField'; 19 | -------------------------------------------------------------------------------- /js/src/common/ak/messages.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React, {type Node} from 'react'; 3 | 4 | import SectionMessage from '@atlaskit/section-message'; 5 | 6 | 7 | type MessageProps = {| 8 | title?: string, 9 | children?: Node 10 | |}; 11 | 12 | export function InfoMessage(props: MessageProps): Node { 13 | return ( 14 | 19 | ); 20 | } 21 | 22 | export function ErrorMessage(props: MessageProps): Node { 23 | return ( 24 | 29 | ); 30 | } 31 | 32 | export function SuccessMessage(props: MessageProps): Node { 33 | return ( 34 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /js/src/common/ak/types.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export type OldSelectValue = string | number; 4 | 5 | export type OldSelectItem = { 6 | +value: T, 7 | +label: string 8 | }; 9 | 10 | export type SingleValueType = { 11 | +value: any, 12 | +label: string, 13 | +imgSrc?: string 14 | }; 15 | -------------------------------------------------------------------------------- /js/src/common/classNames.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export function extractShortClassName(className: string): string { 4 | if (className.indexOf('.') !== -1) { 5 | const tokens = className.split('.'); 6 | return tokens[tokens.length-1]; 7 | } 8 | return className; 9 | } 10 | -------------------------------------------------------------------------------- /js/src/common/editor/CM.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React from 'react'; 3 | 4 | import {Controlled} from 'react-codemirror2'; 5 | 6 | 7 | /*export class CodeMirror extends React.Component { 8 | cm = null; 9 | 10 | _setEditor = (editor) => { 11 | const {editorDidMount} = this.props; 12 | 13 | this.cm = editor; 14 | 15 | if (editorDidMount) { 16 | editorDidMount(editor); 17 | } 18 | }; 19 | 20 | componentWillReceiveProps(props) { 21 | if (props.value !== this.cm.getValue()) { 22 | //this.cm.setValue(props.value); 23 | console.log(props.value); 24 | console.log(this.cm.getValue()); 25 | } 26 | } 27 | 28 | render() { 29 | const {editorDidMount, value, ...props} = this.props; 30 | 31 | return ; 32 | } 33 | }*/ 34 | 35 | export class CodeMirror extends React.PureComponent { 36 | render() { 37 | return ; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /js/src/common/editor/ClassDocViewer.less: -------------------------------------------------------------------------------- 1 | .myGroovyDoc { 2 | line-height: 2em; 3 | 4 | dl { 5 | margin: 0; 6 | } 7 | 8 | &.returnType { 9 | max-width: 300px; 10 | word-break: break-word; 11 | } 12 | 13 | .docDescription { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /js/src/common/editor/editor.reducer.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import {preferenceService} from '../../service'; 3 | 4 | 5 | const SWITCH_THEME = 'SWITCH_THEME'; 6 | 7 | export const EditorActionCreators = { 8 | switchTheme: (isLight: boolean) => ({ 9 | type: SWITCH_THEME, 10 | isLight: isLight 11 | }) 12 | }; 13 | 14 | type State = { 15 | isLight: boolean 16 | }; 17 | 18 | export function editorReducer(state: State, action: typeof EditorActionCreators.switchTheme): State { 19 | if (state === undefined) { 20 | return { 21 | isLight: !(preferenceService.get('ru.mail.groovy.isLight') === 'false') 22 | }; 23 | } 24 | 25 | if (action === SWITCH_THEME) { 26 | return { 27 | ...state, 28 | isLight: action.isLight 29 | }; 30 | } 31 | 32 | return state; 33 | } 34 | 35 | export function subscribeToChanges(store: any, stateKey: string) { 36 | store.subscribe(() => { 37 | preferenceService.put('ru.mail.groovy.isLight', store.state[stateKey].isLight); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /js/src/common/editor/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {Editor as default, transformMarkers} from './Editor'; 4 | export {EditorThemeContext, EditorThemeContextConsumer} from './EditorThemeContext'; 5 | export type {EditorThemeContextType} from './EditorThemeContext'; 6 | export type {AnnotationType, CodeMirrorType, ValidationState, LinterType} from './Editor'; 7 | 8 | export * from './types'; 9 | -------------------------------------------------------------------------------- /js/src/common/error.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import type {SyntaxError} from './types'; 3 | import type {MarkerType} from './editor/types'; 4 | 5 | 6 | export function getMarkers(errors: $ReadOnlyArray): $ReadOnlyArray { 7 | return errors.map((error: SyntaxError): MarkerType => { 8 | if (error.startLine) { 9 | return { 10 | startRow: error.startLine - 1, 11 | endRow: error.endLine - 1, 12 | startCol: error.startColumn - 1, 13 | endCol: error.endColumn - 1, 14 | severity: error.type || 'error', 15 | message: error.message 16 | }; 17 | } else { 18 | return { 19 | startRow: 0, 20 | endRow: 0, 21 | startCol: 0, 22 | endCol: 0, 23 | severity: error.type || 'error', 24 | message: error.message 25 | }; 26 | } 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /js/src/common/fixStyle.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export function fixStyle() { 4 | const contentEl = document.getElementById('react-content'); 5 | 6 | if (contentEl && contentEl.parentElement) { 7 | //$FlowFixMe 8 | contentEl.parentElement.style.paddingTop = '0'; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /js/src/common/react-select-common.less: -------------------------------------------------------------------------------- 1 | //@import "~react-select/dist/react-select.css"; 2 | /* 3 | form.aui .Select { 4 | max-width: 250px; 5 | 6 | &.long-field { 7 | max-width: 500px; 8 | } 9 | 10 | &.full-width-field { 11 | max-width: 100%; 12 | } 13 | } 14 | 15 | .Select-control { 16 | border-radius: 3.01px; 17 | height: 30px; 18 | } 19 | 20 | .Select-placeholder, 21 | .Select--single > .Select-control .Select-value { 22 | line-height: 28px; 23 | } 24 | 25 | .Select-input { 26 | line-height: 28px; 27 | height: 28px; 28 | 29 | > input { 30 | padding: 6px 0 8px; 31 | } 32 | } 33 | 34 | .Select-menu-outer { 35 | z-index: 3001; 36 | } 37 | 38 | .Select--multi { 39 | .Select-value { 40 | line-height: 1; 41 | } 42 | 43 | .Select-value-icon { 44 | padding: 1px 5px 0; 45 | } 46 | } 47 | */ -------------------------------------------------------------------------------- /js/src/common/redux/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export * from './actions'; 4 | export * from './selectors'; 5 | -------------------------------------------------------------------------------- /js/src/common/script-list/ConnectedScriptPage.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import {connect} from 'react-redux'; 3 | 4 | import memoizeOne from 'memoize-one'; 5 | 6 | import {ScriptPage} from './ScriptPage'; 7 | 8 | import {orderedItemsSelector, updateFilter} from '../redux'; 9 | 10 | 11 | const itemsSelector = orderedItemsSelector(); 12 | 13 | export const ConnectedScriptPage = connect( 14 | memoizeOne( 15 | ({watches, isReady, ...state}) => ({ 16 | items: itemsSelector(state), 17 | filter: state.filter, 18 | watches, isReady 19 | }) 20 | ), 21 | { updateFilter } 22 | )(ScriptPage); 23 | -------------------------------------------------------------------------------- /js/src/common/script-list/NotFoundPage.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React from 'react'; 3 | 4 | import EmptyState from '@atlaskit/empty-state'; 5 | 6 | 7 | // eslint-disable-next-line react/prefer-stateless-function 8 | export class NotFoundPage extends React.PureComponent<{}> { 9 | render() { 10 | return ; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /js/src/common/script-list/ScriptForm.less: -------------------------------------------------------------------------------- 1 | @import (reference) '~@atlaskit/util-shared-styles/src/grid'; 2 | 3 | .formButtons { 4 | margin-top: @ak-grid-size*2; 5 | } 6 | -------------------------------------------------------------------------------- /js/src/common/script-list/breadcrumbs.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React, {type Element} from 'react'; 3 | 4 | import {BreadcrumbsItem} from '@atlaskit/breadcrumbs'; 5 | 6 | import {RouterLink} from '../ak'; 7 | 8 | 9 | export const withRoot = (breadcrumbs: Array>): Array> => [ 10 | , 17 | ...breadcrumbs 18 | ]; 19 | -------------------------------------------------------------------------------- /js/src/common/script-list/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export {withRoot} from './breadcrumbs'; 4 | export {ItemViewPage} from './ItemViewPage'; 5 | export {DeleteDialog, ConnectedDeleteDialog} from './DeleteDialog'; 6 | export {NotFoundPage} from './NotFoundPage'; 7 | export {ScriptPage} from './ScriptPage'; 8 | export {ConnectedScriptPage} from './ConnectedScriptPage'; 9 | export {focusOnRender} from './focusOnRender'; 10 | -------------------------------------------------------------------------------- /js/src/common/script/ExecutionBar.less: -------------------------------------------------------------------------------- 1 | @import (reference) "../../flex"; 2 | @import (reference) "../../const"; 3 | @import (reference) "~@atlaskit/util-shared-styles/src/borders"; 4 | @import (reference) "~@atlaskit/util-shared-styles/src/colors"; 5 | 6 | .executionBar { 7 | .flex-row; 8 | 9 | flex-wrap: wrap; 10 | margin-bottom: -1px; 11 | } 12 | 13 | .executionItem { 14 | .flex-none; 15 | .flex-vertical-middle; 16 | 17 | cursor: pointer; 18 | padding: 0 1px; 19 | margin: 0 1px; 20 | 21 | border: none; 22 | border-radius: @ak-border-radius; 23 | background-color: @ak-color-N30A; 24 | 25 | &:hover { 26 | background-color: @ak-color-N40A; 27 | } 28 | } -------------------------------------------------------------------------------- /js/src/common/script/ScriptParameters.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import React, {type Node} from 'react'; 3 | 4 | import {Label} from '@atlaskit/field-base'; 5 | 6 | 7 | export type ScriptParam = { 8 | label: string, 9 | value: Node 10 | }; 11 | 12 | type ScriptParametersProps = { 13 | params: Array 14 | }; 15 | 16 | export class ScriptParameters extends React.PureComponent { 17 | render() { 18 | const {params} = this.props; 19 | 20 | return ( 21 |
22 | {params.filter(Boolean).map((param, i) => 23 |
24 |
25 |
27 |
28 | {param.value} 29 |
30 |
31 | )} 32 |
33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /js/src/common/script/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import './Script.less'; 3 | 4 | 5 | export {Script as default} from './Script'; 6 | export {ScriptParameters} from './ScriptParameters'; 7 | -------------------------------------------------------------------------------- /js/src/const.less: -------------------------------------------------------------------------------- 1 | @import (reference) '~@atlaskit/util-shared-styles/src/colors'; 2 | 3 | @border-color: @ak-color-N40; 4 | -------------------------------------------------------------------------------- /js/src/i18n/admin.i18n.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | // eslint-disable-next-line import/no-extraneous-dependencies 3 | import i18n from 'external-i18n'; 4 | 5 | import type {I18nMessages} from '../common/types'; 6 | 7 | 8 | export const AdminScriptMessages: I18nMessages = { 9 | noParams: i18n.adminScript.noParams, 10 | builtIn: i18n.adminScript.builtIn, 11 | runAgain: i18n.adminScript.runAgain, 12 | modifyAndRun: i18n.adminScript.modifyAndRun 13 | }; 14 | -------------------------------------------------------------------------------- /js/src/i18n/audit.i18n.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | // eslint-disable-next-line import/no-extraneous-dependencies 3 | import i18n from 'external-i18n'; 4 | 5 | import type {I18nMessages} from '../common/types'; 6 | 7 | 8 | export const AuditMessages: I18nMessages = { 9 | user: i18n.audit.user, 10 | category: i18n.audit.category, 11 | action: i18n.audit.action, 12 | description: i18n.audit.description, 13 | script: i18n.audit.script, 14 | restore: i18n.audit.restore, 15 | noItems: i18n.audit.noItems 16 | }; 17 | 18 | export const CategoryNameMessages: I18nMessages = { 19 | ADMIN_SCRIPT: i18n.audit.adminScript, 20 | REGISTRY_SCRIPT: i18n.audit.registryScript, 21 | REGISTRY_DIRECTORY: i18n.audit.registryDirectory, 22 | LISTENER: i18n.audit.listener, 23 | REST: i18n.audit.rest, 24 | CUSTOM_FIELD: i18n.audit.cf, 25 | SCHEDULED_TASK: i18n.audit.scheduledTask, 26 | JQL_FUNCTION: i18n.audit.jqlFunction, 27 | GLOBAL_OBJECT: i18n.audit.globalObject 28 | }; 29 | -------------------------------------------------------------------------------- /js/src/i18n/cf.i18n.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | // eslint-disable-next-line import/no-extraneous-dependencies 3 | import i18n from 'external-i18n'; 4 | 5 | import type {I18nFunction} from '../common/types'; 6 | 7 | 8 | export const ScriptFieldMessages: {[string]: string, scriptFor: I18nFunction} = { 9 | scriptFor: i18n.field.scriptFor, 10 | noFields: i18n.field.noFields 11 | }; 12 | -------------------------------------------------------------------------------- /js/src/i18n/console.i18n.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | // eslint-disable-next-line import/no-extraneous-dependencies 3 | import i18n from 'external-i18n'; 4 | 5 | import type {I18nFunction} from '../common/types'; 6 | 7 | 8 | export const ConsoleMessages: {[string]: string, executedIn: I18nFunction} = { 9 | execute: i18n.console.execute, 10 | //todo: move to common 11 | executedIn: i18n.console.executedIn 12 | }; 13 | -------------------------------------------------------------------------------- /js/src/i18n/listener.i18n.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | // eslint-disable-next-line import/no-extraneous-dependencies 3 | import i18n from 'external-i18n'; 4 | 5 | import type {I18nMessages} from '../common/types'; 6 | 7 | 8 | export const ListenerMessages: I18nMessages = { 9 | addListener: i18n.listener.addListener, 10 | editListener: i18n.listener.editListener, 11 | addCondition: i18n.listener.addCondition, 12 | createListener: i18n.listener.createListener, 13 | updateListener: i18n.listener.updateListener, 14 | deleteListener: i18n.listener.deleteListener, 15 | noListeners: i18n.listener.noListeners 16 | }; 17 | 18 | export const ListenerTypeMessages: I18nMessages = { 19 | CLASS_NAME: i18n.listener.type.className, 20 | ISSUE: i18n.listener.type.issueEvent 21 | }; 22 | -------------------------------------------------------------------------------- /js/src/i18n/registry.i18n.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | // eslint-disable-next-line import/no-extraneous-dependencies 3 | import i18n from 'external-i18n'; 4 | 5 | import type {I18nMessages} from '../common/types'; 6 | 7 | 8 | export const RegistryMessages: I18nMessages = { 9 | addScript: i18n.registry.addScript, 10 | addDirectory: i18n.registry.addDirectory, 11 | editScript: i18n.registry.editScript, 12 | editDirectory: i18n.registry.editDirectory, 13 | deleteScript: i18n.registry.deleteScript, 14 | deleteDirectory: i18n.registry.deleteDirectory, 15 | noScripts: i18n.registry.noScripts, 16 | findWorkflows: i18n.registry.findWorkflows, 17 | onlyUnused: i18n.registry.onlyUnused 18 | }; 19 | -------------------------------------------------------------------------------- /js/src/i18n/rest.i18n.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | // eslint-disable-next-line import/no-extraneous-dependencies 3 | import i18n from 'external-i18n'; 4 | 5 | import type {I18nMessages} from '../common/types'; 6 | 7 | 8 | export const RestMessages: I18nMessages = { 9 | nameDescription: i18n.rest.nameDescription, 10 | addScript: i18n.rest.addScript, 11 | createScript: i18n.rest.createScript, 12 | updateScript: i18n.rest.updateScript, 13 | deleteScript: i18n.rest.deleteScript, 14 | noScripts: i18n.rest.noScripts, 15 | noGroups: i18n.rest.noGroups 16 | }; 17 | -------------------------------------------------------------------------------- /js/src/service/auditLogService.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import $ from 'jquery'; 3 | 4 | import {ajaxGet, getPluginBaseUrl} from './ajaxHelper'; 5 | 6 | import type {AuditLogData} from '../app-audit/types'; 7 | import type {EntityAction, EntityType} from '../common/types'; 8 | 9 | 10 | export class AuditLogService { 11 | getAuditLogPage( 12 | offset: number, 13 | user: $ReadOnlyArray, 14 | category: $ReadOnlyArray, 15 | action: $ReadOnlyArray 16 | ): Promise { 17 | return ajaxGet(`${getPluginBaseUrl()}/auditLog/all?${$.param({ offset, user, category, action })}`); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /js/src/service/binding.service.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import {ajaxGet, getPluginBaseUrl} from './ajaxHelper'; 3 | 4 | import type {ClassDoc} from '../common/editor/types'; 5 | 6 | 7 | export class BindingService { 8 | getGlobalBindingTypes(): Promise<{string: ClassDoc}> { 9 | return ajaxGet(`${getPluginBaseUrl()}/binding/all`); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /js/src/service/console.service.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import {ajaxPost, getPluginBaseUrl} from './ajaxHelper'; 3 | 4 | import type {ConsoleResult} from '../app-console/types'; 5 | 6 | 7 | export class ConsoleService { 8 | executeScript(script: string): Promise { 9 | return ajaxPost(`${getPluginBaseUrl()}/scripts/execute`, {script}); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /js/src/service/execution.service.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | import {ajaxGet, getPluginBaseUrl} from './ajaxHelper'; 4 | 5 | import type {ExecutionType} from '../common/script/types'; 6 | 7 | 8 | export class ExecutionService { 9 | getExecutions(isInline?: boolean, scriptId: (number|string), onlyLast: boolean): Promise> { 10 | return ajaxGet(`${getPluginBaseUrl()}/execution/${isInline ? 'forInline' : 'forRegistry'}/${scriptId}${onlyLast ? '/last' : ''}`); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /js/src/service/extrasService.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import {getPluginBaseUrl, ajaxPost} from './ajaxHelper'; 3 | 4 | import type {SyntaxError} from '../common/types'; 5 | 6 | 7 | export class ExtrasService { 8 | clearCache(): Promise { 9 | return ajaxPost(`${getPluginBaseUrl()}/extras/clearCache`); 10 | } 11 | 12 | checkScript(scriptBody: string, scriptType: string, additionalParams: {[string]: string} = {}): Promise<$ReadOnlyArray> { 13 | return ajaxPost(`${getPluginBaseUrl()}/staticCheck`, { scriptBody, scriptType, additionalParams }); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /js/src/service/jira.service.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import {ajaxGet, ajaxPost, getBaseUrl, getPluginBaseUrl} from './ajaxHelper'; 3 | 4 | import type {JqlQueryValidationResult} from './types'; 5 | 6 | import type {ProjectType, IssueEventType} from '../common/types'; 7 | 8 | 9 | export class JiraService { 10 | getAllProjects(): Promise> { 11 | return ajaxGet(`${getBaseUrl()}/rest/api/2/project`); 12 | } 13 | 14 | getEventTypes(): Promise> { 15 | return ajaxGet(`${getPluginBaseUrl()}/jira-api/eventType`); 16 | } 17 | 18 | validateQuery(query: string): Promise { 19 | return ajaxPost( 20 | `${getBaseUrl()}/rest/api/2/search`, 21 | { 22 | jql: query, 23 | validateQuery: true, 24 | maxResults: 0 25 | } 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /js/src/service/preference.service.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export class PreferenceService { 4 | get(key: string): ?string { 5 | return localStorage.getItem(key); 6 | } 7 | 8 | put(key: string, value: string) { 9 | try { 10 | localStorage.setItem(key, value); 11 | } catch (e) { 12 | console.error(`unable to setItem ${key} in localStorage`, e); 13 | } 14 | } 15 | 16 | remove(key: string) { 17 | localStorage.removeItem(key); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /js/src/service/types.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | export type JqlQueryValidationResult = { 4 | total: number 5 | }; 6 | -------------------------------------------------------------------------------- /js/src/service/watcher.service.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | import {ajaxDelete, ajaxGet, ajaxPost, getPluginBaseUrl} from './ajaxHelper'; 3 | 4 | import type {EntityType} from '../common/types'; 5 | 6 | 7 | export class WatcherService { 8 | getAllWatches(type: EntityType): Promise> { 9 | return ajaxGet(`${getPluginBaseUrl()}/watch/${type}/all`); 10 | } 11 | 12 | startWatching(type: EntityType, id: number|string): Promise { 13 | return ajaxPost(`${getPluginBaseUrl()}/watch/${type}/${id}`); 14 | } 15 | 16 | stopWatching(type: EntityType, id: number|string): Promise { 17 | return ajaxDelete(`${getPluginBaseUrl()}/watch/${type}/${id}`); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/examples/groovy/admin-param.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.user.ApplicationUser 2 | import ru.mail.jira.plugins.groovy.api.script.ParamType 3 | import ru.mail.jira.plugins.groovy.api.script.WithParam 4 | 5 | @WithParam(displayName="User", type=ParamType.USER) 6 | ApplicationUser user 7 | 8 | return user.displayName 9 | -------------------------------------------------------------------------------- /src/examples/groovy/inject-field.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.security.JiraAuthenticationContext 2 | import com.atlassian.jira.user.ApplicationUser 3 | import groovy.transform.Field 4 | import ru.mail.jira.plugins.groovy.api.script.StandardModule 5 | 6 | @StandardModule @Field 7 | JiraAuthenticationContext authenticationContext 8 | 9 | return getCu() 10 | 11 | ApplicationUser getCu() { 12 | return authenticationContext.loggedInUser 13 | } 14 | -------------------------------------------------------------------------------- /src/examples/groovy/inject-var.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.security.JiraAuthenticationContext 2 | import ru.mail.jira.plugins.groovy.api.script.StandardModule 3 | 4 | @StandardModule 5 | JiraAuthenticationContext authenticationContext 6 | 7 | return authenticationContext.loggedInUser 8 | -------------------------------------------------------------------------------- /src/examples/groovy/rest-simple.groovy: -------------------------------------------------------------------------------- 1 | import javax.ws.rs.core.Response 2 | 3 | return Response.ok("ok").build() 4 | -------------------------------------------------------------------------------- /src/examples/groovy/stc-bug.groovy: -------------------------------------------------------------------------------- 1 | String content = 'asd' 2 | 3 | OutputStream outputStream = new ByteArrayOutputStream() 4 | 5 | outputStream.withWriter{ 6 | it.write(content) 7 | it.flush() 8 | } 9 | -------------------------------------------------------------------------------- /src/examples/groovy/test-deprecation.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.component.ComponentAccessor 2 | import com.atlassian.jira.security.JiraAuthenticationContext 3 | import com.atlassian.jira.web.SessionKeys; 4 | 5 | ComponentAccessor.jiraAuthenticationContext.getUser() 6 | ComponentAccessor.jiraAuthenticationContext.user 7 | ComponentAccessor.userUtil.activeUserCount 8 | ComponentAccessor.getOsgiComponentReference(JiraAuthenticationContext) 9 | 10 | return SessionKeys.TEMP_ATTACHMENTS 11 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/GroovyDocTest.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.user.ApplicationUser 2 | import com.atlassian.jira.user.util.* 3 | import ru.mail.jira.plugins.groovy.api.script.StandardModule 4 | 5 | /** 6 | * some description 7 | */ 8 | class GroovyDocTest { 9 | private final UserManager userManager; 10 | 11 | GroovyDocTest(@StandardModule UserManager userManager) { 12 | this.userManager = userManager; 13 | } 14 | 15 | /** 16 | * Returns user for current name 17 | * @param name user name 18 | * @return user for name 19 | */ 20 | ApplicationUser getUserByName(String name) { 21 | return userManager.getUserByName(name) 22 | } 23 | 24 | void voidMethod() {} 25 | 26 | void withPrimitiveType(String a, String b, int c) {} 27 | 28 | //these should be ignored 29 | private void privateMethod() {} 30 | 31 | static void staticMethod() {} 32 | } 33 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/basicRest.groovy: -------------------------------------------------------------------------------- 1 | import javax.ws.rs.core.MediaType 2 | import javax.ws.rs.core.Response 3 | 4 | return Response.ok("kek ${currentUser.name}".toString()).type(MediaType.TEXT_PLAIN).build() 5 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/binding-test.groovy: -------------------------------------------------------------------------------- 1 | user.getName() 2 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/classNameListenerEvent.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.event.project.VersionCreateEvent 2 | import com.atlassian.jira.project.ProjectManager 3 | import com.atlassian.jira.project.UpdateProjectParameters 4 | import com.atlassian.jira.project.version.Version 5 | import ru.mail.jira.plugins.groovy.api.script.StandardModule 6 | 7 | @StandardModule 8 | ProjectManager projectManager 9 | 10 | VersionCreateEvent event = event 11 | 12 | Version version = event.version 13 | 14 | projectManager.updateProject( 15 | UpdateProjectParameters 16 | .forProject(version.projectId) 17 | .name("updatedProject") 18 | ) 19 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/containerService.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.greenhopper.manager.issuelink.EpicLinkManager 2 | import ru.mail.jira.plugins.groovy.api.script.PluginModule 3 | import ru.mail.jira.plugins.groovy.api.script.WithPlugin 4 | 5 | @WithPlugin("com.pyxis.greenhopper.jira") 6 | @PluginModule 7 | EpicLinkManager epicLinkManager 8 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/dateExtension.groovy: -------------------------------------------------------------------------------- 1 | new Date()+1 2 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/go/BorkedObject.groovy: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.scripts.go 2 | 3 | public class BorkedObject$TS$ { 4 | void Test() { 5 | log.info('test') 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/go/GlobalObject.groovy: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.scripts.go 2 | 3 | import com.atlassian.jira.component.ComponentAccessor 4 | import com.atlassian.jira.user.ApplicationUser 5 | 6 | public class GlobalObject$TS$ { 7 | ApplicationUser getAdmin() { 8 | return ComponentAccessor.userManager.getUserByName('admin') 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/go/NonExistingImport.groovy: -------------------------------------------------------------------------------- 1 | import ru.mail.jira.plugins.groovy.api.script.WithPlugin 2 | 3 | @WithPlugin("does.not.exist") 4 | class WithNonExistingImport { 5 | void test() {} 6 | } 7 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/go/SlowGlobalObject.groovy: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.scripts.go 2 | 3 | import com.atlassian.jira.component.ComponentAccessor 4 | import com.atlassian.jira.user.ApplicationUser 5 | 6 | public class GlobalObject$TS$ { 7 | GlobalObject$TS$() { 8 | Thread.sleep(10000); 9 | } 10 | 11 | ApplicationUser getAdmin() { 12 | return ComponentAccessor.userManager.getUserByName('admin') 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/go/WithGoDependency.groovy: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.scripts.go 2 | 3 | import ru.mail.jira.plugins.groovy.api.script.GlobalObjectModule 4 | import ru.mail.jira.scripts.go.$INJECTED_GO_CLASSNAME$ 5 | 6 | import com.atlassian.jira.component.ComponentAccessor 7 | import com.atlassian.jira.user.ApplicationUser 8 | 9 | public class GlobalObject$TS$ { 10 | private final $INJECTED_GO_CLASSNAME$ injectedGo; 11 | 12 | public GlobalObject$TS$(@GlobalObjectModule $INJECTED_GO_CLASSNAME$ injectedGo) { 13 | this.injectedGo = injectedGo; 14 | } 15 | 16 | ApplicationUser getAdmin() { 17 | return injectedGo.getAdmin() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/go/WithJswModule.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.greenhopper.api.customfield.ManagedCustomFieldsService 2 | import com.atlassian.jira.bc.ServiceOutcome 3 | import com.atlassian.jira.issue.fields.CustomField 4 | import ru.mail.jira.plugins.groovy.api.script.PluginModule 5 | import ru.mail.jira.plugins.groovy.api.script.WithPlugin 6 | 7 | @WithPlugin("com.pyxis.greenhopper.jira") 8 | class JswGlobalObject { 9 | private final ManagedCustomFieldsService managedCustomFieldsService; 10 | 11 | JswGlobalObject(@PluginModule ManagedCustomFieldsService managedCustomFieldsService) { 12 | this.managedCustomFieldsService = managedCustomFieldsService 13 | } 14 | 15 | ServiceOutcome getRankField() { 16 | return managedCustomFieldsService.getRankCustomField() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/go/WithPluginModule.groovy: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.groovy.testgo 2 | 3 | import ru.mail.jira.plugins.groovy.api.script.PluginModule 4 | import ru.mail.jira.plugins.groovy.api.script.WithPlugin 5 | import ru.mail.jira.plugins.jsincluder.ScriptManager 6 | import ru.mail.jira.plugins.jsincluder.Script 7 | import ru.mail.jira.plugins.commons.LocalUtils 8 | 9 | @WithPlugin("ru.mail.jira.plugins.jsincluder") 10 | class JsIncluderGlobalObject { 11 | private final ScriptManager scriptManager; 12 | 13 | JsIncluderGlobalObject(@PluginModule ScriptManager scriptManager) { 14 | this.scriptManager = scriptManager 15 | } 16 | 17 | Script[] getScripts() { 18 | return scriptManager.getScripts() 19 | } 20 | 21 | String testStatics() { 22 | return LocalUtils.numberToCaption(0); 23 | } 24 | 25 | static String testStaticMethod() { 26 | return LocalUtils.numberToCaption(0) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/go/WithStandardModule.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.security.JiraAuthenticationContext 2 | import com.atlassian.jira.user.ApplicationUser 3 | import ru.mail.jira.plugins.groovy.api.script.StandardModule 4 | 5 | class WithStandardModule { 6 | private final JiraAuthenticationContext authenticationContext; 7 | 8 | WithStandardModule(@StandardModule JiraAuthenticationContext authenticationContext) { 9 | this.authenticationContext = authenticationContext; 10 | } 11 | 12 | ApplicationUser getCu() { 13 | return authenticationContext.loggedInUser 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/go/admin-param-go.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.user.ApplicationUser 2 | import ru.mail.jira.plugins.groovy.api.script.ParamType 3 | import ru.mail.jira.plugins.groovy.api.script.WithParam 4 | 5 | @WithParam(displayName="User", type=ParamType.USER) 6 | ApplicationUser $goName 7 | 8 | return $goName.name 9 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/go/injection-go.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.security.JiraAuthenticationContext 2 | import ru.mail.jira.plugins.groovy.api.script.StandardModule 3 | 4 | @StandardModule 5 | JiraAuthenticationContext $goName 6 | 7 | return $goName.loggedInUser.name 8 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/jql/go.groovy: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.scripts.go; 2 | 3 | class MyGlobObj$TS${ 4 | public static myMethod() { 5 | return "Open"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/jsonSlurper.groovy: -------------------------------------------------------------------------------- 1 | import groovy.json.JsonSlurper 2 | 3 | return new JsonSlurper().parseText('{"test": "value"}') 4 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/jswModule.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.greenhopper.api.customfield.ManagedCustomFieldsService 2 | import ru.mail.jira.plugins.groovy.api.script.PluginModule 3 | import ru.mail.jira.plugins.groovy.api.script.WithPlugin 4 | 5 | @WithPlugin("com.pyxis.greenhopper.jira") 6 | @PluginModule 7 | ManagedCustomFieldsService managedCustomFieldsService 8 | 9 | return managedCustomFieldsService != null 10 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/listener.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.component.ComponentAccessor 2 | import com.atlassian.jira.event.issue.IssueEvent 3 | import com.atlassian.jira.issue.comments.CommentManager 4 | 5 | IssueEvent event = event 6 | 7 | CommentManager commentManager = ComponentAccessor.commentManager 8 | 9 | commentManager.create(event.issue, event.getUser(), "test comment ${event.eventTypeId}", true) 10 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/logging.groovy: -------------------------------------------------------------------------------- 1 | log.trace('test trace') 2 | log.debug('test debug') 3 | log.info('test info') 4 | log.warn('test warn') 5 | log.error('test error') 6 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/pluginClassNameListenerEvent.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.greenhopper.api.events.board.BoardCreatedEvent 2 | import com.atlassian.greenhopper.manager.rapidview.RapidViewManager 3 | import com.atlassian.greenhopper.model.rapid.RapidView 4 | import ru.mail.jira.plugins.groovy.api.script.PluginModule 5 | import ru.mail.jira.plugins.groovy.api.script.WithPlugin 6 | 7 | @WithPlugin("com.pyxis.greenhopper.jira") 8 | @PluginModule 9 | RapidViewManager rapidViewManager 10 | 11 | BoardCreatedEvent event = event 12 | 13 | rapidViewManager.update(new RapidView.RapidViewBuilder(event.getBoard()).name("kek").build()) 14 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/pluginModule.groovy: -------------------------------------------------------------------------------- 1 | import ru.mail.jira.plugins.jsincluder.ScriptManager 2 | import ru.mail.jira.plugins.groovy.api.script.PluginModule 3 | import ru.mail.jira.plugins.groovy.api.script.WithPlugin 4 | 5 | @WithPlugin("ru.mail.jira.plugins.jsincluder") 6 | @PluginModule 7 | ScriptManager scriptManager 8 | 9 | return scriptManager.getScripts() != null 10 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/pluginModuleWithScriptParam.groovy: -------------------------------------------------------------------------------- 1 | import ru.mail.jira.plugins.groovy.api.script.ParamType 2 | import ru.mail.jira.plugins.groovy.api.script.WithParam 3 | import ru.mail.jira.plugins.jsincluder.ScriptManager 4 | import ru.mail.jira.plugins.groovy.api.script.PluginModule 5 | import ru.mail.jira.plugins.groovy.api.script.WithPlugin 6 | import ru.mail.jira.plugins.groovy.api.script.ScriptParam 7 | 8 | @WithParam(displayName = "aaa", type = ParamType.SCRIPT, optional = false) 9 | ScriptParam script 10 | 11 | assert Objects.equals(script.runScript(new HashMap()), "test ok") 12 | 13 | @WithPlugin("ru.mail.jira.plugins.jsincluder") 14 | @PluginModule 15 | ScriptManager scriptManager 16 | 17 | return scriptManager.getScripts() != null 18 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/scriptField.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.issue.Issue 2 | 3 | import java.util.concurrent.TimeUnit 4 | 5 | Issue issue = issue 6 | 7 | return issue.created.time - TimeUnit.MINUTES.toMillis(10L) 8 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/standardModule.groovy: -------------------------------------------------------------------------------- 1 | import com.atlassian.jira.security.JiraAuthenticationContext 2 | import ru.mail.jira.plugins.groovy.api.script.StandardModule 3 | 4 | @StandardModule 5 | JiraAuthenticationContext authenticationContext 6 | 7 | return authenticationContext.loggedInUser 8 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/stc-error.groovy: -------------------------------------------------------------------------------- 1 | user.someMethod() 2 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/stc-getat-object-failure.groovy: -------------------------------------------------------------------------------- 1 | def getAt(Object key) { 2 | return 'test' + key 3 | } 4 | 5 | Object test = 3233i 6 | 7 | return this[test] 8 | -------------------------------------------------------------------------------- /src/examples/groovy/tests/withPlugin.groovy: -------------------------------------------------------------------------------- 1 | import ru.mail.jira.plugins.groovy.api.script.WithPlugin 2 | 3 | @WithPlugin('testPlugin') 4 | String test 5 | 6 | return 'ok' 7 | -------------------------------------------------------------------------------- /src/examples/groovy/wf-boolParam.groovy: -------------------------------------------------------------------------------- 1 | import ru.mail.jira.plugins.groovy.api.script.ParamType 2 | import ru.mail.jira.plugins.groovy.api.script.WithParam 3 | 4 | @WithParam(displayName = "Toggle", type = ParamType.BOOLEAN) 5 | boolean isKappa 6 | 7 | if (isKappa) { 8 | logger.info('Kappa') 9 | } else { 10 | logger.info('Keepo') 11 | } 12 | -------------------------------------------------------------------------------- /src/main/antlr4/ru/mail/jira/plugins/groovy/impl/jql/antlr/DateComparisonQuery.g4: -------------------------------------------------------------------------------- 1 | grammar DateComparisonQuery; 2 | 3 | operation_expr: LT | GT | GTE | LTE | EQ; 4 | date_field_expr: UQSTRING | STRING; 5 | 6 | duration: DURATION; 7 | 8 | sign_expr: PLUS | MINUS; 9 | 10 | date_expr: date_field_expr (sign_expr duration)?; 11 | 12 | date_comparison_query: date_expr operation_expr date_expr EOF; 13 | 14 | LT: '<'; 15 | GT: '>'; 16 | GTE: '>='; 17 | LTE: '<='; 18 | EQ: '='; 19 | PLUS: '+'; 20 | MINUS: '-'; 21 | 22 | SHORT_DAYS: 'd'; 23 | SHORT_WEEKS: 'w'; 24 | NUMBER: '0'..'9'+; 25 | 26 | DURATION_UNIT: SHORT_DAYS | SHORT_WEEKS; 27 | 28 | DURATION: NUMBER DURATION_UNIT; 29 | 30 | STRING: DQSTRING | SQSTRING; 31 | 32 | DQSTRING: '"' ( '\\"' | . )*? '"'; 33 | SQSTRING: '\'' ( '\\\'' | . )*? '\''; 34 | 35 | WS : [ \r\t\n]+ -> skip ; 36 | 37 | UQSTRING: ('a'..'z' | 'A'..'Z' | '0'..'9' | '_')+; 38 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/PluginLauncher.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api; 2 | 3 | import ru.mail.jira.plugins.groovy.api.util.PluginLifecycleAware; 4 | 5 | import java.util.List; 6 | 7 | public interface PluginLauncher { 8 | boolean isInitialized(); 9 | 10 | List getLifecycleAwareObjects(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dao/FieldConfigDao.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dao; 2 | 3 | import com.atlassian.activeobjects.tx.Transactional; 4 | import com.atlassian.jira.issue.fields.config.FieldConfig; 5 | import com.atlassian.jira.user.ApplicationUser; 6 | import ru.mail.jira.plugins.groovy.api.dto.cf.FieldConfigForm; 7 | import ru.mail.jira.plugins.groovy.api.entity.FieldConfigChangelog; 8 | import ru.mail.jira.plugins.groovy.api.entity.FieldScript; 9 | 10 | public interface FieldConfigDao { 11 | FieldScript findByConfigId(long id); 12 | 13 | FieldConfigChangelog[] getChangelogs(long id); 14 | 15 | @Transactional 16 | FieldScript createConfig(ApplicationUser user, FieldConfig jiraFieldConfig, FieldConfigForm form); 17 | 18 | @Transactional 19 | FieldScript updateConfig(ApplicationUser user, int id, FieldConfig jiraFieldConfig, FieldConfigForm form); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dao/ListenerDao.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dao; 2 | 3 | import com.atlassian.activeobjects.tx.Transactional; 4 | import com.atlassian.jira.user.ApplicationUser; 5 | import ru.mail.jira.plugins.groovy.api.dto.listener.EventListenerForm; 6 | import ru.mail.jira.plugins.groovy.api.entity.Listener; 7 | 8 | public interface ListenerDao { 9 | @Transactional 10 | Listener createEventListener(ApplicationUser user, EventListenerForm form); 11 | 12 | @Transactional 13 | Listener updateEventListener(ApplicationUser user, int id, EventListenerForm form); 14 | 15 | @Transactional 16 | void deleteEventListener(ApplicationUser user, int id); 17 | 18 | @Transactional 19 | void restoreEventListener(ApplicationUser user, int id); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/CacheStatsDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @AllArgsConstructor @XmlRootElement @Getter 10 | public class CacheStatsDto { 11 | @XmlElement 12 | private final long hitCount; 13 | @XmlElement 14 | private final long missCount; 15 | @XmlElement 16 | private final long loadSuccessCount; 17 | @XmlElement 18 | private final long loadFailureCount; 19 | @XmlElement 20 | private final long totalLoadTime; 21 | @XmlElement 22 | private final long evictionCount; 23 | @XmlElement 24 | private final long evictionWeight; 25 | @XmlElement 26 | private final long estimatedSize; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/ChangelogDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | import java.util.Set; 9 | 10 | @Getter @Setter 11 | @XmlRootElement 12 | public class ChangelogDto { 13 | @XmlElement 14 | private int id; 15 | @XmlElement 16 | String uuid; 17 | @XmlElement 18 | private String comment; 19 | @XmlElement 20 | private String diff; 21 | @XmlElement 22 | private String templateDiff; 23 | @XmlElement 24 | private JiraUser author; 25 | @XmlElement 26 | private String date; 27 | @XmlElement 28 | private Set issueReferences; 29 | 30 | @XmlElement 31 | private long warnings; 32 | @XmlElement 33 | private long errors; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/JiraIssueReference.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | import java.util.Objects; 10 | 11 | @XmlRootElement 12 | @Getter @Setter 13 | @AllArgsConstructor 14 | public class JiraIssueReference { 15 | @XmlElement 16 | private final String key; 17 | @XmlElement 18 | private final String summary; 19 | 20 | @Override 21 | public boolean equals(Object o) { 22 | if (this == o) return true; 23 | if (o == null || getClass() != o.getClass()) return false; 24 | JiraIssueReference that = (JiraIssueReference) o; 25 | return Objects.equals(key, that.key); 26 | } 27 | 28 | @Override 29 | public int hashCode() { 30 | 31 | return Objects.hash(key); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/JiraUser.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | 11 | @Getter @Setter 12 | @AllArgsConstructor @NoArgsConstructor 13 | @XmlRootElement 14 | public class JiraUser { 15 | @XmlElement 16 | private String name; 17 | @XmlElement 18 | private String avatarUrl; 19 | @XmlElement 20 | private String displayName; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/Page.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto; 2 | 3 | import lombok.Getter; 4 | 5 | import javax.xml.bind.annotation.XmlElement; 6 | import javax.xml.bind.annotation.XmlRootElement; 7 | import java.util.List; 8 | 9 | @Getter 10 | @XmlRootElement 11 | public class Page { 12 | @XmlElement 13 | private final int offset; 14 | @XmlElement 15 | private final int limit; 16 | @XmlElement 17 | private final long total; 18 | @XmlElement 19 | private final int size; 20 | @XmlElement 21 | private final boolean isLast; 22 | @XmlElement 23 | private final List values; 24 | 25 | public Page(int offset, int limit, long total, List values) { 26 | this.offset = offset; 27 | this.limit = limit; 28 | this.total = total; 29 | this.size = values.size(); 30 | this.isLast = offset + this.size == total; 31 | this.values = values; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/PickerOption.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | 11 | @Getter @Setter 12 | @AllArgsConstructor @NoArgsConstructor 13 | @XmlRootElement 14 | public class PickerOption { 15 | @XmlElement 16 | private String label; 17 | @XmlElement 18 | private String value; 19 | @XmlElement() 20 | private String imgSrc; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/PickerResultSet.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto; 2 | 3 | import lombok.Getter; 4 | 5 | import javax.xml.bind.annotation.XmlElement; 6 | import javax.xml.bind.annotation.XmlRootElement; 7 | import java.util.List; 8 | 9 | @Getter 10 | @XmlRootElement 11 | public class PickerResultSet { 12 | @XmlElement 13 | private final List options; 14 | @XmlElement 15 | private final boolean complete; 16 | 17 | public PickerResultSet(List options, boolean complete) { 18 | this.options = options; 19 | this.complete = complete; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/ScriptDescription.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.workflow.WorkflowScriptType; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | @Getter @Setter 13 | @XmlRootElement 14 | public class ScriptDescription { 15 | @XmlElement 16 | private int id; 17 | @XmlElement 18 | private String name; 19 | @XmlElement 20 | private String description; 21 | @XmlElement 22 | private List params; 23 | @XmlElement 24 | private Set types; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/ScriptForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | import java.util.Objects; 9 | 10 | @Getter @Setter 11 | @XmlRootElement 12 | public class ScriptForm { 13 | @XmlElement 14 | private String name; 15 | @XmlElement 16 | private String description; 17 | @XmlElement 18 | private String scriptBody; 19 | @XmlElement 20 | private String comment; 21 | 22 | public boolean matches(ScriptForm other) { 23 | return Objects.equals(name, other.name) 24 | && Objects.equals(description, other.description) 25 | && Objects.equals(scriptBody, other.scriptBody); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/StaticCheckForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.script.ScriptType; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | import java.util.Map; 10 | 11 | //todo: support multiple types 12 | @XmlRootElement 13 | @Getter @Setter 14 | public class StaticCheckForm { 15 | @XmlElement 16 | private ScriptType scriptType; 17 | @XmlElement 18 | private String scriptBody; 19 | @XmlElement 20 | private Map additionalParams; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/admin/AdminScriptForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.admin; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ScriptForm; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | 10 | @XmlRootElement 11 | @Getter @Setter 12 | public class AdminScriptForm extends ScriptForm { 13 | @XmlElement 14 | private boolean html; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/admin/AdminScriptOutcome.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.admin; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | 10 | @XmlRootElement 11 | @Getter @Setter @AllArgsConstructor 12 | public class AdminScriptOutcome { 13 | @XmlElement 14 | private boolean success; 15 | @XmlElement 16 | private T message; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/audit/AuditLogEntryDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.audit; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.JiraUser; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | 10 | @Getter @Setter 11 | @XmlRootElement 12 | public class AuditLogEntryDto extends AuditLogEntryForm { 13 | @XmlElement 14 | private Integer id; 15 | @XmlElement 16 | private String date; 17 | @XmlElement 18 | private String scriptName; 19 | @XmlElement 20 | private String parentName; 21 | @XmlElement 22 | private Boolean deleted; 23 | @XmlElement 24 | private Integer scriptId; 25 | @XmlElement 26 | private JiraUser user; 27 | @XmlElement 28 | private String url; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/audit/AuditLogEntryForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.audit; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import ru.mail.jira.plugins.groovy.api.entity.EntityAction; 8 | import ru.mail.jira.plugins.groovy.api.entity.EntityType; 9 | 10 | import javax.xml.bind.annotation.XmlElement; 11 | import javax.xml.bind.annotation.XmlRootElement; 12 | 13 | @Getter @Setter 14 | @AllArgsConstructor @NoArgsConstructor 15 | @XmlRootElement 16 | public class AuditLogEntryForm { 17 | @XmlElement 18 | private EntityType category; 19 | @XmlElement 20 | private Integer entityId; 21 | @XmlElement 22 | private EntityAction action; 23 | @XmlElement 24 | private String description; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/cf/FieldScriptDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.cf; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | 11 | @Getter @Setter 12 | @AllArgsConstructor @NoArgsConstructor 13 | @XmlRootElement 14 | public class FieldScriptDto { 15 | @XmlElement 16 | private String id; 17 | @XmlElement 18 | private String scriptBody; 19 | @XmlElement 20 | private String description; 21 | @XmlElement 22 | private String template; 23 | @XmlElement 24 | private boolean cacheable; 25 | @XmlElement 26 | private boolean withVelocityParams; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/cf/PreviewForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.cf; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @Getter @Setter 10 | @XmlRootElement 11 | public class PreviewForm { 12 | @XmlElement 13 | private FieldConfigForm configForm; 14 | @XmlElement 15 | private String issueKey; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/cf/PreviewResult.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.cf; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | 11 | @Getter @Setter 12 | @AllArgsConstructor @NoArgsConstructor 13 | @XmlRootElement 14 | public class PreviewResult { 15 | @XmlElement 16 | private String htmlResult; 17 | @XmlElement 18 | private long time; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/console/ConsoleResponse.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.console; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | 10 | @Getter @Setter 11 | @AllArgsConstructor 12 | @XmlRootElement 13 | public class ConsoleResponse { 14 | @XmlElement 15 | private String result; 16 | @XmlElement 17 | private String log; 18 | @XmlElement 19 | private long time; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/console/ScriptRequest.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.console; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @Getter @Setter 10 | @XmlRootElement 11 | public class ScriptRequest { 12 | @XmlElement 13 | private String script; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/directory/ParentForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.directory; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @Getter @Setter 10 | @XmlRootElement 11 | public class ParentForm { 12 | @XmlElement 13 | private Integer parentId; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/directory/RegistryScriptDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.directory; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ChangelogDto; 6 | import ru.mail.jira.plugins.groovy.api.dto.ScriptParamDto; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | import java.util.List; 11 | 12 | @Getter @Setter 13 | @XmlRootElement 14 | public class RegistryScriptDto extends RegistryScriptForm { 15 | @XmlElement 16 | private Integer id; 17 | @XmlElement 18 | private String uuid; 19 | @XmlElement 20 | private boolean deleted; 21 | @XmlElement 22 | private String parentName; 23 | @XmlElement 24 | private List changelogs; 25 | @XmlElement 26 | private List params; 27 | @XmlElement 28 | private Long errorCount; 29 | @XmlElement 30 | private Long warningCount; 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/directory/RegistryScriptForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.directory; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ScriptForm; 6 | import ru.mail.jira.plugins.groovy.api.dto.workflow.WorkflowScriptType; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | import java.util.Objects; 11 | import java.util.Set; 12 | 13 | @Getter @Setter 14 | @XmlRootElement 15 | public class RegistryScriptForm extends ScriptForm { 16 | @XmlElement 17 | private Integer directoryId; 18 | @XmlElement 19 | private Set types; 20 | 21 | public boolean matches(RegistryScriptForm other) { 22 | return super.matches(other) 23 | && Objects.equals(directoryId, other.directoryId) 24 | && Objects.equals(types, other.types); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/directory/ScriptDirectoryDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.directory; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @Getter @Setter 10 | @XmlRootElement 11 | public class ScriptDirectoryDto extends ScriptDirectoryForm { 12 | @XmlElement 13 | private Integer id; 14 | @XmlElement 15 | private String fullName; 16 | @XmlElement 17 | private String parentName; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/directory/ScriptDirectoryForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.directory; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @Getter @Setter 10 | @XmlRootElement 11 | public class ScriptDirectoryForm { 12 | @XmlElement 13 | private String name; 14 | @XmlElement 15 | private Integer parentId; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/docs/MethodDoc.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.docs; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | import java.util.List; 10 | 11 | @Getter 12 | @ToString @EqualsAndHashCode 13 | @XmlRootElement 14 | public class MethodDoc { 15 | @XmlElement 16 | private final String name; 17 | @XmlElement 18 | private final String description; 19 | @XmlElement 20 | private final TypeDoc returnType; 21 | @XmlElement 22 | private final List parameters; 23 | 24 | public MethodDoc(String name, String description, TypeDoc returnType, List parameters) { 25 | this.name = name; 26 | this.description = description; 27 | this.returnType = returnType; 28 | this.parameters = parameters; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/docs/ParameterDoc.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.docs; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | 10 | @Getter 11 | @ToString @EqualsAndHashCode 12 | @XmlRootElement 13 | public class ParameterDoc { 14 | @XmlElement 15 | private final TypeDoc type; 16 | @XmlElement 17 | private final String name; 18 | 19 | public ParameterDoc(TypeDoc type, String name) { 20 | this.type = type; 21 | this.name = name; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/docs/TypeDoc.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.docs; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | 10 | @Getter 11 | @ToString @EqualsAndHashCode 12 | @XmlRootElement 13 | public class TypeDoc { 14 | @XmlElement 15 | private final String className; 16 | @XmlElement 17 | private final String link; 18 | 19 | public TypeDoc(String className) { 20 | this.className = className; 21 | this.link = null; 22 | } 23 | 24 | public TypeDoc(String className, String link) { 25 | this.className = className; 26 | this.link = link; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/error/CompilationMessage.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.error; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | 11 | @Getter @Setter 12 | @AllArgsConstructor @NoArgsConstructor 13 | @XmlRootElement 14 | public class CompilationMessage { 15 | @XmlElement 16 | private String type; 17 | @XmlElement 18 | private String message; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/execution/ScriptExecutionDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.execution; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.codehaus.jackson.annotate.JsonRawValue; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | 10 | @Getter @Setter 11 | @XmlRootElement 12 | public class ScriptExecutionDto { 13 | @XmlElement 14 | private int id; 15 | @XmlElement 16 | private String scriptId; 17 | @XmlElement 18 | private long time; 19 | @XmlElement 20 | private boolean success; 21 | @XmlElement 22 | private boolean slow; 23 | @XmlElement 24 | private String date; 25 | @XmlElement 26 | private String error; 27 | @XmlElement 28 | private String log; 29 | @XmlElement @JsonRawValue 30 | private String extraParams; 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/execution/ScriptExecutionSummary.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.execution; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.entity.EntityType; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | 10 | @XmlRootElement 11 | @Getter @Setter 12 | public class ScriptExecutionSummary { 13 | @XmlElement 14 | private String url; 15 | @XmlElement 16 | private String name; 17 | @XmlElement 18 | private EntityType type; 19 | @XmlElement 20 | private long errorCount; 21 | @XmlElement 22 | private String lastErrorDate; 23 | @XmlElement 24 | private long lastErrorTimestamp; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/global/GlobalObjectDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.global; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ChangelogDto; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | import java.util.List; 10 | 11 | @XmlRootElement 12 | @Getter @Setter 13 | public class GlobalObjectDto extends GlobalObjectForm { 14 | @XmlElement 15 | private int id; 16 | @XmlElement 17 | private String uuid; 18 | @XmlElement 19 | private boolean deleted; 20 | @XmlElement 21 | private List changelogs; 22 | @XmlElement 23 | private Integer errorCount; 24 | @XmlElement 25 | private Integer warningCount; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/global/GlobalObjectForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.global; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ScriptForm; 6 | 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @XmlRootElement 10 | @Getter @Setter 11 | public class GlobalObjectForm extends ScriptForm { 12 | private String dependencies; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/jql/JqlFunctionForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.jql; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ScriptForm; 6 | 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @Getter @Setter 10 | @XmlRootElement 11 | public class JqlFunctionForm extends ScriptForm { 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/jql/JqlFunctionScriptDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.jql; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ChangelogDto; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | import java.util.List; 10 | 11 | @Getter @Setter 12 | @XmlRootElement 13 | public class JqlFunctionScriptDto extends JqlFunctionForm { 14 | @XmlElement 15 | private int id; 16 | @XmlElement 17 | private String uuid; 18 | @XmlElement 19 | private boolean deleted; 20 | 21 | @XmlElement 22 | private List changelogs; 23 | @XmlElement 24 | private Integer errorCount; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/listener/ConditionType.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.listener; 2 | 3 | public enum ConditionType { 4 | CLASS_NAME, 5 | ISSUE 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/listener/EventListenerDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.listener; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ChangelogDto; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | import java.util.List; 10 | 11 | @Getter @Setter 12 | @XmlRootElement 13 | public class EventListenerDto extends EventListenerForm { 14 | @XmlElement 15 | private int id; 16 | @XmlElement 17 | private String uuid; 18 | @XmlElement 19 | private boolean initialized; 20 | @XmlElement 21 | private List changelogs; 22 | @XmlElement 23 | private Integer errorCount; 24 | @XmlElement 25 | private Integer warningCount; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/listener/EventListenerForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.listener; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ScriptForm; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | 10 | @Getter @Setter 11 | @XmlRootElement 12 | public class EventListenerForm extends ScriptForm { 13 | @XmlElement 14 | private ConditionDescriptor condition; 15 | @XmlElement 16 | private boolean alwaysTrack; 17 | 18 | public boolean matches(EventListenerForm other) { 19 | return super.matches(other) 20 | && condition.equals(other.condition); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/listener/IssueEventType.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.listener; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @Getter @Setter 10 | @XmlRootElement 11 | public class IssueEventType { 12 | @XmlElement 13 | private Long id; 14 | @XmlElement 15 | private String name; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/listener/ScriptedEventListener.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.listener; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public class ScriptedEventListener { 9 | private final int id; 10 | private final String script; 11 | private final String uuid; 12 | private final boolean alwaysTrack; 13 | private final ConditionDescriptor condition; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/notification/NotificationDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.notification; 2 | 3 | import com.atlassian.jira.user.ApplicationUser; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import ru.mail.jira.plugins.groovy.api.entity.EntityAction; 7 | import ru.mail.jira.plugins.groovy.api.entity.EntityType; 8 | 9 | @AllArgsConstructor @Getter 10 | public class NotificationDto { 11 | private final ApplicationUser user; 12 | private final EntityAction action; 13 | private final EntityType entityType; 14 | private final String entityName; 15 | private final Integer entityId; 16 | private final String diff; 17 | private final String templateDiff; 18 | private final String comment; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/rest/HttpMethod.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.rest; 2 | 3 | public enum HttpMethod { 4 | GET, 5 | POST, 6 | PUT, 7 | DELETE 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/rest/RestScriptDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.rest; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ChangelogDto; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | import java.util.List; 10 | 11 | @Getter @Setter 12 | @XmlRootElement 13 | public class RestScriptDto extends RestScriptForm { 14 | @XmlElement 15 | private Integer id; 16 | @XmlElement 17 | private String uuid; 18 | @XmlElement 19 | private boolean deleted; 20 | @XmlElement 21 | private List changelogs; 22 | @XmlElement 23 | private Integer errorCount; 24 | @XmlElement 25 | private Integer warningCount; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/rest/RestScriptForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.rest; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ScriptForm; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | import java.util.Set; 10 | 11 | @Getter @Setter 12 | @XmlRootElement 13 | public class RestScriptForm extends ScriptForm { 14 | @XmlElement 15 | private Set methods; 16 | @XmlElement 17 | private Set groups; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/rest/Script.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.rest; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import java.util.Set; 8 | 9 | @Getter @Setter @AllArgsConstructor 10 | public class Script { 11 | private String id; 12 | private String script; 13 | private Set groupNames; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/scheduled/RunInfo.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.scheduled; 2 | 3 | import com.atlassian.scheduler.status.RunOutcome; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | 10 | @Getter @Setter 11 | @XmlRootElement 12 | public class RunInfo { 13 | @XmlElement 14 | private String startDate; 15 | @XmlElement 16 | private long duration; 17 | @XmlElement 18 | private RunOutcome outcome; 19 | @XmlElement 20 | private String message; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/scheduled/ScheduledTaskDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.scheduled; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ChangelogDto; 6 | import ru.mail.jira.plugins.groovy.api.dto.PickerOption; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | import java.util.List; 11 | 12 | @Getter @Setter 13 | @XmlRootElement 14 | public class ScheduledTaskDto extends ScheduledTaskForm { 15 | @XmlElement 16 | private int id; 17 | @XmlElement 18 | private String uuid; 19 | @XmlElement 20 | private PickerOption user; 21 | @XmlElement 22 | private PickerOption issueWorkflow; 23 | @XmlElement 24 | private PickerOption issueWorkflowAction; 25 | @XmlElement 26 | private boolean enabled; 27 | @XmlElement 28 | private RunInfo lastRunInfo; 29 | @XmlElement 30 | private String nextRunDate; 31 | @XmlElement 32 | private List changelogs; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/scheduled/ScheduledTaskForm.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.scheduled; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ScriptForm; 6 | import ru.mail.jira.plugins.groovy.api.entity.ScheduledTaskType; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | 11 | @Getter @Setter 12 | @XmlRootElement 13 | public class ScheduledTaskForm extends ScriptForm { 14 | @XmlElement 15 | private String scheduleExpression; 16 | @XmlElement 17 | private ScheduledTaskType type; 18 | @XmlElement 19 | private String userKey; 20 | @XmlElement 21 | private String issueJql; 22 | @XmlElement 23 | private String issueWorkflowName; 24 | @XmlElement 25 | private Integer issueWorkflowActionId; 26 | @XmlElement 27 | private TransitionOptionsDto transitionOptions; 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/scheduled/TaskResult.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.scheduled; 2 | 3 | import com.atlassian.scheduler.JobRunnerResponse; 4 | import com.atlassian.scheduler.status.RunOutcome; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | 11 | @Getter @Setter 12 | @XmlRootElement 13 | public class TaskResult { 14 | @XmlElement 15 | private long time; 16 | @XmlElement 17 | private RunOutcome runOutcome; 18 | @XmlElement 19 | private String message; 20 | 21 | public static TaskResult fromJobRunnerResponse(JobRunnerResponse response, long time) { 22 | TaskResult result = new TaskResult(); 23 | result.setTime(time); 24 | result.setRunOutcome(response.getRunOutcome()); 25 | result.setMessage(response.getMessage()); 26 | return result; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/workflow/WorkflowActionDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.workflow; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | import java.util.List; 11 | 12 | @AllArgsConstructor @NoArgsConstructor 13 | @Getter @Setter 14 | @XmlRootElement 15 | public class WorkflowActionDto { 16 | @XmlElement 17 | private Integer id; 18 | @XmlElement 19 | private Integer stepId; 20 | @XmlElement 21 | private String name; 22 | @XmlElement 23 | private List items; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/workflow/WorkflowActionItem.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.workflow; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | 11 | @AllArgsConstructor @NoArgsConstructor 12 | @Getter @Setter 13 | @XmlRootElement 14 | public class WorkflowActionItem { 15 | @XmlElement 16 | private WorkflowScriptType type; 17 | @XmlElement 18 | private Integer order; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/workflow/WorkflowDto.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.workflow; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlRootElement; 10 | import java.util.List; 11 | 12 | @AllArgsConstructor @NoArgsConstructor 13 | @Getter @Setter 14 | @XmlRootElement 15 | public class WorkflowDto { 16 | @XmlElement 17 | private String name; 18 | @XmlElement 19 | private boolean active; 20 | @XmlElement 21 | private boolean hasDraft; 22 | @XmlElement 23 | private List actions; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/dto/workflow/WorkflowScriptType.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.dto.workflow; 2 | 3 | import lombok.Getter; 4 | import ru.mail.jira.plugins.groovy.util.Const; 5 | 6 | @Getter 7 | public enum WorkflowScriptType { 8 | CONDITION(Const.REGISTRY_CONDITION_KEY), 9 | VALIDATOR(Const.REGISTRY_VALIDATOR_KEY), 10 | FUNCTION(Const.REGISTRY_FUNCTION_KEY); 11 | 12 | private String moduleKey; 13 | 14 | WorkflowScriptType(String moduleKey) { 15 | this.moduleKey = moduleKey; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/e/UnableToLoadPluginException.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.e; 2 | 3 | public class UnableToLoadPluginException extends RuntimeException { 4 | public UnableToLoadPluginException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/AbstractChangelog.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.Entity; 4 | import net.java.ao.Polymorphic; 5 | import net.java.ao.schema.NotNull; 6 | import net.java.ao.schema.StringLength; 7 | 8 | import java.sql.Timestamp; 9 | 10 | @Polymorphic 11 | public interface AbstractChangelog extends Entity { 12 | @NotNull 13 | void setAuthorKey(String authorKey); 14 | String getAuthorKey(); 15 | 16 | @NotNull 17 | void setDate(Timestamp date); 18 | Timestamp getDate(); 19 | 20 | @NotNull 21 | @StringLength(StringLength.UNLIMITED) 22 | void setDiff(String diff); 23 | String getDiff(); 24 | 25 | @NotNull 26 | void setComment(String comment); 27 | String getComment(); 28 | 29 | void setUuid(String uuid); 30 | String getUuid(); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/AbstractScript.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.Entity; 4 | import net.java.ao.Polymorphic; 5 | import net.java.ao.schema.NotNull; 6 | import net.java.ao.schema.StringLength; 7 | 8 | @Polymorphic 9 | public interface AbstractScript extends Entity { 10 | @NotNull 11 | void setName(String name); 12 | String getName(); 13 | 14 | @StringLength(StringLength.UNLIMITED) 15 | void setDescription(String description); 16 | String getDescription(); 17 | 18 | @NotNull 19 | boolean isDeleted(); 20 | void setDeleted(boolean deleted); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/AdminScript.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.OneToMany; 4 | import net.java.ao.schema.NotNull; 5 | import net.java.ao.schema.StringLength; 6 | 7 | import java.util.Map; 8 | 9 | public interface AdminScript extends AbstractScript { 10 | @NotNull 11 | void setUuid(String uuid); 12 | String getUuid(); 13 | 14 | @NotNull 15 | @StringLength(StringLength.UNLIMITED) 16 | void setScriptBody(String scriptBody); 17 | String getScriptBody(); 18 | 19 | boolean isHtml(); 20 | void setHtml(boolean html); 21 | 22 | @StringLength(StringLength.UNLIMITED) 23 | void setParameters(String parameters); 24 | String getParameters(); 25 | 26 | @OneToMany(reverse = "getScript") 27 | AdminScriptChangelog[] getChangelogs(); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/AdminScriptChangelog.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.schema.NotNull; 4 | import net.java.ao.schema.Table; 5 | 6 | @Table("A_SCRIPT_CHANGELOG") 7 | public interface AdminScriptChangelog extends AbstractChangelog { 8 | @NotNull 9 | void setScript(AdminScript script); 10 | AdminScript getScript(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/AuditLogEntry.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.Entity; 4 | import net.java.ao.schema.NotNull; 5 | 6 | import java.sql.Timestamp; 7 | 8 | public interface AuditLogEntry extends Entity { 9 | @NotNull 10 | void setDate(Timestamp date); 11 | Timestamp getDate(); 12 | 13 | @NotNull 14 | void setUserKey(String userKey); 15 | String getUserKey(); 16 | 17 | @NotNull 18 | void setCategory(EntityType category); 19 | EntityType getCategory(); 20 | 21 | void setEntityId(Integer entityId); 22 | Integer getEntityId(); 23 | 24 | @NotNull 25 | void setAction(EntityAction action); 26 | EntityAction getAction(); 27 | 28 | void setDescription(String description); 29 | String getDescription(); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/AuditLogIssueRelation.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.Entity; 4 | import net.java.ao.schema.Indexed; 5 | import net.java.ao.schema.NotNull; 6 | import net.java.ao.schema.Table; 7 | 8 | @Table("AUDIT_ISSUE_REL") 9 | public interface AuditLogIssueRelation extends Entity { 10 | @NotNull 11 | AuditLogEntry getAuditLog(); 12 | 13 | @NotNull 14 | @Indexed 15 | Long getIssueId(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/Changelog.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.schema.NotNull; 4 | 5 | public interface Changelog extends AbstractChangelog { 6 | @NotNull 7 | void setScript(Script script); 8 | Script getScript(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/EntityAction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import lombok.Getter; 4 | 5 | public enum EntityAction { 6 | CREATED("ru.mail.jira.plugins.groovy.audit.action.created"), 7 | UPDATED("ru.mail.jira.plugins.groovy.audit.action.updated"), 8 | DELETED("ru.mail.jira.plugins.groovy.audit.action.deleted"), 9 | RESTORED("ru.mail.jira.plugins.groovy.audit.action.restored"), 10 | ENABLED("ru.mail.jira.plugins.groovy.audit.action.enabled"), 11 | DISABLED("ru.mail.jira.plugins.groovy.audit.action.disabled"), 12 | MOVED("ru.mail.jira.plugins.groovy.audit.action.moved"); 13 | 14 | @Getter 15 | private final String i18nName; 16 | 17 | EntityAction(String i18nName) { 18 | this.i18nName = i18nName; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/FieldConfigChangelog.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.schema.NotNull; 4 | import net.java.ao.schema.StringLength; 5 | import net.java.ao.schema.Table; 6 | 7 | @Table("FIELD_CHANGELOG") 8 | public interface FieldConfigChangelog extends AbstractChangelog { 9 | @NotNull 10 | void setFieldConfig(FieldScript fieldScript); 11 | FieldScript getFieldConfig(); 12 | 13 | @StringLength(StringLength.UNLIMITED) 14 | String getTemplateDiff(); 15 | void setTemplateDiff(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/GlobalObject.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.OneToMany; 4 | import net.java.ao.schema.NotNull; 5 | import net.java.ao.schema.StringLength; 6 | import net.java.ao.schema.Unique; 7 | 8 | import javax.annotation.Nonnull; 9 | 10 | public interface GlobalObject extends AbstractScript { 11 | @NotNull 12 | @Unique 13 | void setLowerName(String lowerName); 14 | String getLowerName(); 15 | 16 | @NotNull 17 | void setUuid(String uuid); 18 | String getUuid(); 19 | 20 | @NotNull 21 | @StringLength(StringLength.UNLIMITED) 22 | void setScriptBody(String scriptBody); 23 | String getScriptBody(); 24 | 25 | @StringLength(StringLength.UNLIMITED) 26 | void setDependencies(String dependencies); 27 | String getDependencies(); 28 | 29 | @OneToMany(reverse = "getScript") 30 | GlobalObjectChangelog[] getChangelogs(); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/GlobalObjectChangelog.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.schema.NotNull; 4 | import net.java.ao.schema.Table; 5 | 6 | @Table("GO_CHANGELOG") 7 | public interface GlobalObjectChangelog extends AbstractChangelog { 8 | @NotNull 9 | void setScript(GlobalObject script); 10 | GlobalObject getScript(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/JqlFunctionScript.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.OneToMany; 4 | import net.java.ao.schema.NotNull; 5 | import net.java.ao.schema.StringLength; 6 | import net.java.ao.schema.Unique; 7 | 8 | public interface JqlFunctionScript extends AbstractScript { 9 | @NotNull 10 | @Unique 11 | void setName(String name); 12 | String getName(); 13 | 14 | @NotNull 15 | @Unique 16 | void setLowerName(String lowerName); 17 | String getLowerName(); 18 | 19 | @NotNull 20 | void setUuid(String uuid); 21 | String getUuid(); 22 | 23 | @NotNull 24 | @StringLength(StringLength.UNLIMITED) 25 | void setScriptBody(String scriptBody); 26 | String getScriptBody(); 27 | 28 | @OneToMany(reverse = "getScript") 29 | JqlFunctionScriptChangelog[] getChangelogs(); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/JqlFunctionScriptChangelog.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.schema.NotNull; 4 | import net.java.ao.schema.Table; 5 | 6 | @Table("JQL_CHANGELOG") 7 | public interface JqlFunctionScriptChangelog extends AbstractChangelog { 8 | @NotNull 9 | void setScript(JqlFunctionScript script); 10 | JqlFunctionScript getScript(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/Listener.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.OneToMany; 4 | import net.java.ao.schema.NotNull; 5 | import net.java.ao.schema.StringLength; 6 | 7 | public interface Listener extends AbstractScript { 8 | @NotNull 9 | String getUuid(); 10 | void setUuid(String uuid); 11 | 12 | @NotNull 13 | @StringLength(StringLength.UNLIMITED) 14 | String getScriptBody(); 15 | void setScriptBody(String scriptBody); 16 | 17 | @NotNull 18 | @StringLength(StringLength.UNLIMITED) 19 | String getCondition(); 20 | void setCondition(String condition); 21 | 22 | Boolean isAlwaysTrack(); 23 | void setAlwaysTrack(Boolean alwaysTrack); 24 | 25 | @OneToMany(reverse = "getListener") 26 | ListenerChangelog[] getChangelogs(); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/ListenerChangelog.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.schema.NotNull; 4 | 5 | public interface ListenerChangelog extends AbstractChangelog { 6 | @NotNull 7 | void setListener(Listener listener); 8 | Listener getListener(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/RestChangelog.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.schema.NotNull; 4 | 5 | public interface RestChangelog extends AbstractChangelog { 6 | @NotNull 7 | void setScript(RestScript script); 8 | RestScript getScript(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/RestScript.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.OneToMany; 4 | import net.java.ao.schema.NotNull; 5 | import net.java.ao.schema.StringLength; 6 | import net.java.ao.schema.Unique; 7 | 8 | public interface RestScript extends AbstractScript { 9 | @NotNull 10 | @Unique 11 | void setName(String name); 12 | String getName(); 13 | 14 | @NotNull 15 | void setUuid(String uuid); 16 | String getUuid(); 17 | 18 | //comma separated http method names 19 | @NotNull 20 | void setMethods(String methods); 21 | String getMethods(); 22 | 23 | @NotNull 24 | @StringLength(StringLength.UNLIMITED) 25 | void setScriptBody(String scriptBody); 26 | String getScriptBody(); 27 | 28 | @StringLength(StringLength.UNLIMITED) 29 | void setGroups(String groups); 30 | String getGroups(); 31 | 32 | @OneToMany(reverse = "getScript") 33 | RestChangelog[] getChangelogs(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/ScheduledTaskChangelog.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.schema.NotNull; 4 | import net.java.ao.schema.Table; 5 | 6 | @Table("S_TASK_CHANGELOG") 7 | public interface ScheduledTaskChangelog extends AbstractChangelog { 8 | @NotNull 9 | void setTask(ScheduledTask task); 10 | ScheduledTask getTask(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/ScheduledTaskType.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | public enum ScheduledTaskType { 4 | BASIC_SCRIPT, 5 | ISSUE_JQL_SCRIPT, 6 | ISSUE_JQL_TRANSITION, 7 | DOCUMENT_ISSUE_JQL_SCRIPT 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/ScriptDirectory.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.Entity; 4 | import net.java.ao.Preload; 5 | import net.java.ao.schema.NotNull; 6 | 7 | //https://ecosystem.atlassian.net/browse/AO-3454 FK column directory_id isn't preloaded by default, so we must specify all columns 8 | @Preload({"ID", "NAME", "PARENT_ID", "DELETED"}) 9 | public interface ScriptDirectory extends Entity { 10 | @NotNull 11 | void setName(String name); 12 | String getName(); 13 | 14 | void setParent(ScriptDirectory directory); 15 | ScriptDirectory getParent(); 16 | 17 | @NotNull 18 | void setDeleted(boolean deleted); 19 | boolean isDeleted(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/entity/Watcher.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.entity; 2 | 3 | import net.java.ao.Entity; 4 | import net.java.ao.schema.Index; 5 | import net.java.ao.schema.Indexes; 6 | import net.java.ao.schema.NotNull; 7 | 8 | @Indexes({ 9 | @Index(name = "entity_type_id", methodNames = {"setEntityId", "setType"}), 10 | @Index(name = "for_user", methodNames = {"setEntityId", "setType", "setUserKey"}) 11 | }) 12 | public interface Watcher extends Entity { 13 | @NotNull 14 | void setEntityId(Integer id); 15 | Integer getEntityId(); 16 | 17 | @NotNull 18 | void setType(EntityType type); 19 | EntityType getType(); 20 | 21 | @NotNull 22 | void setUserKey(String userKey); 23 | String getUserKey(); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/jql/CustomFunction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.jql; 2 | 3 | import com.atlassian.jira.plugin.jql.function.JqlFunction; 4 | 5 | public interface CustomFunction extends JqlFunction { 6 | String getModuleKey(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/jql/CustomQueryFunction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.jql; 2 | 3 | import com.atlassian.jira.jql.query.ClauseQueryFactory; 4 | 5 | public interface CustomQueryFunction extends CustomFunction, ClauseQueryFactory { 6 | String getModuleKey(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/jql/ScriptedJqlFunction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.jql; 2 | 3 | import com.atlassian.jira.JiraDataType; 4 | import com.atlassian.jira.JiraDataTypeImpl; 5 | import com.atlassian.jira.user.ApplicationUser; 6 | import com.atlassian.jira.util.MessageSet; 7 | import com.atlassian.jira.util.MessageSetImpl; 8 | import com.atlassian.query.clause.TerminalClause; 9 | import com.atlassian.query.operand.FunctionOperand; 10 | import ru.mail.jira.plugins.groovy.impl.jql.JqlFunctionCFType; 11 | 12 | import javax.annotation.Nonnull; 13 | 14 | public interface ScriptedJqlFunction { 15 | @Nonnull 16 | default JiraDataType getDataType() { 17 | return new JiraDataTypeImpl(JqlFunctionCFType.class); 18 | } 19 | 20 | @Nonnull 21 | default MessageSet validate(ApplicationUser applicationUser, @Nonnull FunctionOperand functionOperand, @Nonnull TerminalClause terminalClause) { 22 | return new MessageSetImpl(); 23 | } 24 | 25 | default int getMinimumNumberOfExpectedArguments() { 26 | return 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/jql/ScriptedJqlQueryFunction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.jql; 2 | 3 | import com.atlassian.jira.jql.query.QueryCreationContext; 4 | import com.atlassian.query.operand.FunctionOperand; 5 | import org.apache.lucene.search.Query; 6 | 7 | import javax.annotation.Nonnull; 8 | 9 | public interface ScriptedJqlQueryFunction extends ScriptedJqlFunction { 10 | Query getQuery(@Nonnull QueryCreationContext queryCreationContext, @Nonnull FunctionOperand operand); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/jql/ScriptedJqlValuesFunction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.jql; 2 | 3 | import com.atlassian.jira.jql.operand.QueryLiteral; 4 | import com.atlassian.jira.jql.query.QueryCreationContext; 5 | import com.atlassian.query.clause.TerminalClause; 6 | import com.atlassian.query.operand.FunctionOperand; 7 | 8 | import java.util.List; 9 | 10 | public interface ScriptedJqlValuesFunction extends ScriptedJqlFunction { 11 | List getValues(QueryCreationContext queryCreationContext, FunctionOperand functionOperand, TerminalClause terminalClause); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/repository/FieldConfigRepository.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.repository; 2 | 3 | import com.atlassian.jira.user.ApplicationUser; 4 | import ru.mail.jira.plugins.groovy.api.dto.ChangelogDto; 5 | import ru.mail.jira.plugins.groovy.api.dto.cf.FieldScriptDto; 6 | import ru.mail.jira.plugins.groovy.api.dto.cf.FieldConfigDto; 7 | import ru.mail.jira.plugins.groovy.api.dto.cf.FieldConfigForm; 8 | 9 | import java.util.List; 10 | 11 | public interface FieldConfigRepository { 12 | List getAllConfigs(); 13 | 14 | List getChangelogs(long id); 15 | 16 | FieldConfigDto getConfig(long id, boolean includeChangelogs); 17 | 18 | FieldConfigDto updateConfig(ApplicationUser user, long id, FieldConfigForm form); 19 | 20 | FieldScriptDto getScript(long fieldConfigId); 21 | 22 | void invalidateAll(); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/repository/GlobalObjectRepository.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.repository; 2 | 3 | import com.atlassian.jira.user.ApplicationUser; 4 | import ru.mail.jira.plugins.groovy.api.dto.ChangelogDto; 5 | import ru.mail.jira.plugins.groovy.api.dto.global.GlobalObjectDto; 6 | import ru.mail.jira.plugins.groovy.api.dto.global.GlobalObjectForm; 7 | 8 | import java.util.List; 9 | 10 | public interface GlobalObjectRepository { 11 | List getAll(); 12 | GlobalObjectDto get(int id); 13 | List getChangelogs(int id); 14 | 15 | GlobalObjectDto create(ApplicationUser user, GlobalObjectForm form); 16 | GlobalObjectDto update(ApplicationUser user, int id, GlobalObjectForm form); 17 | void delete(ApplicationUser user, int id); 18 | void restore(ApplicationUser user, int id); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/CompiledScript.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class CompiledScript { 7 | private final Class scriptClass; 8 | private final ParseContext parseContext; 9 | 10 | public CompiledScript(Class scriptClass, ParseContext parseContext) { 11 | this.scriptClass = scriptClass; 12 | this.parseContext = parseContext; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/ExecutionContext.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import lombok.Getter; 4 | import org.apache.log4j.spi.LoggingEvent; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class ExecutionContext { 10 | @Getter 11 | private List logEntries = new ArrayList<>(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/GlobalObjectModule.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | @Retention(RetentionPolicy.RUNTIME) 7 | public @interface GlobalObjectModule { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/ParamType.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import com.atlassian.crowd.embedded.api.Group; 4 | import com.atlassian.jira.issue.fields.CustomField; 5 | import com.atlassian.jira.issue.resolution.Resolution; 6 | import com.atlassian.jira.user.ApplicationUser; 7 | import lombok.Getter; 8 | 9 | import java.util.List; 10 | 11 | @Getter 12 | public enum ParamType { 13 | BOOLEAN(Boolean.class), 14 | STRING(String.class), 15 | TEXT(String.class), 16 | LONG(Long.class), 17 | DOUBLE(Double.class), 18 | CUSTOM_FIELD(CustomField.class), //todo: system fields, script, current workflow action 19 | USER(ApplicationUser.class), 20 | GROUP(Group.class), 21 | RESOLUTION(Resolution.class), 22 | SCRIPT(ScriptParam.class), 23 | MULTI_USER(List.class); 24 | 25 | private final Class type; 26 | 27 | ParamType(Class type) { 28 | this.type = type; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/ParseContext.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import ru.mail.jira.plugins.groovy.api.dto.ScriptParamDto; 6 | import ru.mail.jira.plugins.groovy.api.script.statik.WarningMessage; 7 | 8 | import java.util.*; 9 | 10 | @Getter 11 | public class ParseContext { 12 | @Setter 13 | private boolean compileStatic; 14 | @Setter 15 | private boolean extended; 16 | @Setter 17 | private boolean singleton; 18 | @Setter 19 | private Map types; 20 | @Setter 21 | private List warnings; 22 | private final List parameters = new ArrayList<>(); 23 | private final Set plugins = new HashSet<>(); 24 | private final List injections = new ArrayList<>(); 25 | private final Set completedExtensions = new HashSet<>(); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/PluginModule.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | @Retention(RetentionPolicy.RUNTIME) 7 | public @interface PluginModule { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/ResolvedConstructorArgument.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter @AllArgsConstructor 7 | public class ResolvedConstructorArgument { 8 | private ArgumentType argumentType; 9 | private Object object; 10 | 11 | public enum ArgumentType { 12 | PLUGIN, 13 | STANDARD, 14 | GLOBAL_OBJECT 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/ScriptExecutionOutcome.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Getter @AllArgsConstructor 8 | public class ScriptExecutionOutcome { 9 | private final Object result; 10 | private final ExecutionContext executionContext; 11 | private final long time; 12 | 13 | @Setter 14 | private Exception error; 15 | 16 | public boolean isSuccessful() { 17 | return error == null; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/ScriptParam.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import java.util.Map; 4 | 5 | public interface ScriptParam { 6 | Object runScript(Map params) throws Exception; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/ScriptParamFactory.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import ru.mail.jira.plugins.groovy.api.dto.ScriptParamDto; 4 | 5 | public interface ScriptParamFactory { 6 | Object getParamObject(ScriptParamDto paramDto, String value); 7 | 8 | Object getParamFormValue(ScriptParamDto paramDto, String value); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/ScriptType.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | public enum ScriptType { 4 | WORKFLOW_FUNCTION, 5 | WORKFLOW_VALIDATOR, 6 | WORKFLOW_CONDITION, 7 | WORKFLOW_GENERIC, //used for static checking 8 | LISTENER, 9 | CONSOLE, 10 | REST, 11 | CUSTOM_FIELD, 12 | SCHEDULED_TASK, 13 | ADMIN_SCRIPT, 14 | PARAM, 15 | JQL, 16 | GLOBAL_OBJECT 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/StandardModule.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | @Retention(RetentionPolicy.RUNTIME) 7 | public @interface StandardModule { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/WithParam.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | public @interface WithParam { 4 | String displayName(); 5 | 6 | ParamType type(); 7 | 8 | boolean optional() default false; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/WithPlugin.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | @Retention(RetentionPolicy.RUNTIME) 7 | public @interface WithPlugin { 8 | String[] value(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/binding/BindingDescriptor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script.binding; 2 | 3 | import ru.mail.jira.plugins.groovy.api.dto.docs.ClassDoc; 4 | import ru.mail.jira.plugins.groovy.api.script.ScriptType; 5 | 6 | import javax.annotation.Nonnull; 7 | 8 | public interface BindingDescriptor { 9 | T getValue(ScriptType type, String scriptId); 10 | 11 | @Nonnull 12 | Class getType(); 13 | 14 | @Nonnull 15 | ClassDoc getDoc(); 16 | 17 | void dispose() throws Exception; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/binding/BindingDescriptorImpl.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script.binding; 2 | 3 | import ru.mail.jira.plugins.groovy.api.dto.docs.ClassDoc; 4 | import ru.mail.jira.plugins.groovy.api.script.ScriptType; 5 | 6 | import javax.annotation.Nonnull; 7 | 8 | public class BindingDescriptorImpl implements BindingDescriptor { 9 | private final T object; 10 | private final Class type; 11 | 12 | public BindingDescriptorImpl(T object, Class type) { 13 | this.object = object; 14 | this.type = type; 15 | } 16 | 17 | @Override 18 | public T getValue(ScriptType scriptType, String scriptId) { 19 | return object; 20 | } 21 | 22 | @Nonnull 23 | @Override 24 | public Class getType() { 25 | return type; 26 | } 27 | 28 | @Nonnull 29 | @Override 30 | public ClassDoc getDoc() { 31 | return null; 32 | } 33 | 34 | @Override 35 | public void dispose() { 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/binding/BindingProvider.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script.binding; 2 | 3 | import java.util.Map; 4 | 5 | public interface BindingProvider { 6 | Map> getBindings(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/binding/LazyDocBindingDescriptorImpl.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script.binding; 2 | 3 | import io.atlassian.fugue.Suppliers; 4 | import ru.mail.jira.plugins.groovy.api.dto.docs.ClassDoc; 5 | 6 | import javax.annotation.Nonnull; 7 | import java.util.function.Supplier; 8 | 9 | public class LazyDocBindingDescriptorImpl extends BindingDescriptorImpl { 10 | private final Supplier docSupplier; 11 | 12 | public LazyDocBindingDescriptorImpl(T object, Class type, Supplier docSupplier) { 13 | super(object, type); 14 | 15 | this.docSupplier = Suppliers.memoize(docSupplier); 16 | } 17 | 18 | @Nonnull 19 | @Override 20 | public ClassDoc getDoc() { 21 | return docSupplier.get(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/script/statik/WarningMessage.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.script.statik; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class WarningMessage { 7 | private final String message; 8 | private final int startLine; 9 | private final int startColumn; 10 | private final int endLine; 11 | private final int endColumn; 12 | 13 | public WarningMessage(String message, int startLine, int startColumn, int endLine, int endColumn) { 14 | this.message = message; 15 | this.startLine = startLine; 16 | this.startColumn = startColumn; 17 | this.endLine = endLine; 18 | this.endColumn = endColumn; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/GroovyDocService.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service; 2 | 3 | import ru.mail.jira.plugins.groovy.api.dto.docs.ClassDoc; 4 | import ru.mail.jira.plugins.groovy.api.util.WithPluginLoader; 5 | 6 | public interface GroovyDocService { 7 | @WithPluginLoader 8 | ClassDoc parseDocs(String canonicalName, String className, String source) throws Exception; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/JqlFunctionService.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service; 2 | 3 | import com.atlassian.jira.user.ApplicationUser; 4 | import ru.mail.jira.plugins.groovy.api.dto.jql.JqlFunctionForm; 5 | import ru.mail.jira.plugins.groovy.api.dto.jql.JqlFunctionScriptDto; 6 | 7 | public interface JqlFunctionService { 8 | JqlFunctionScriptDto createScript(ApplicationUser user, JqlFunctionForm form); 9 | 10 | JqlFunctionScriptDto updateScript(ApplicationUser user, int id, JqlFunctionForm form); 11 | 12 | void deleteScript(ApplicationUser user, int id); 13 | 14 | void restoreScript(ApplicationUser user, int id); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/NotificationService.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service; 2 | 3 | import com.atlassian.jira.user.ApplicationUser; 4 | import ru.mail.jira.plugins.groovy.api.dto.notification.NotificationDto; 5 | 6 | import java.util.List; 7 | 8 | public interface NotificationService { 9 | void sendNotifications(NotificationDto notificationDto, List recipients); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/PluginDataService.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service; 2 | 3 | public interface PluginDataService { 4 | boolean isSentryEnabled(); 5 | void setSentryEnabled(boolean enabled); 6 | 7 | String getSentryDsn(); 8 | void setSentryDsn(String dsn); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/ScheduledTaskService.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service; 2 | 3 | import com.atlassian.jira.user.ApplicationUser; 4 | import ru.mail.jira.plugins.groovy.api.dto.scheduled.ScheduledTaskForm; 5 | import ru.mail.jira.plugins.groovy.api.dto.scheduled.ScheduledTaskDto; 6 | import ru.mail.jira.plugins.groovy.api.dto.scheduled.TaskResult; 7 | 8 | public interface ScheduledTaskService { 9 | ScheduledTaskDto createTask(ApplicationUser user, ScheduledTaskForm form); 10 | 11 | ScheduledTaskDto updateTask(ApplicationUser user, int id, ScheduledTaskForm form); 12 | 13 | void deleteTask(ApplicationUser user, int id); 14 | 15 | void restoreTask(ApplicationUser user, int id); 16 | 17 | void setEnabled(ApplicationUser user, int id, boolean enabled); 18 | 19 | TaskResult runNow(ApplicationUser user, int id); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/ScriptInvalidationService.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service; 2 | 3 | public interface ScriptInvalidationService { 4 | @Deprecated 5 | void invalidate(String scriptId); 6 | 7 | void invalidateAll(); 8 | 9 | void invalidateField(long fieldId); 10 | 11 | void invalidateAllFields(); 12 | 13 | void invalidateGlobalObjects(); 14 | 15 | void invalidateSentry(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/SentryService.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service; 2 | 3 | import io.sentry.event.User; 4 | import io.sentry.event.interfaces.HttpInterface; 5 | 6 | import java.util.Map; 7 | 8 | public interface SentryService { 9 | void registerException(String id, User user, Throwable e, HttpInterface httpInterface, Map metaData); 10 | 11 | void updateSettings(boolean enabled, String dsn); 12 | 13 | boolean isEnabled(); 14 | String getDsn(); 15 | 16 | void invalidateSettings(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/SingletonFactory.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service; 2 | 3 | import ru.mail.jira.plugins.groovy.api.script.CompiledScript; 4 | import ru.mail.jira.plugins.groovy.api.script.ResolvedConstructorArgument; 5 | 6 | public interface SingletonFactory { 7 | Object[] getConstructorArguments(CompiledScript type) throws IllegalArgumentException; 8 | 9 | ResolvedConstructorArgument[] getExtendedConstructorArguments(CompiledScript type) throws IllegalArgumentException; 10 | 11 | T createInstance(CompiledScript type); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/TestHelperService.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service; 2 | 3 | import com.atlassian.activeobjects.external.ActiveObjects; 4 | import com.atlassian.activeobjects.tx.Transactional; 5 | import com.atlassian.jira.user.ApplicationUser; 6 | 7 | public interface TestHelperService { 8 | ActiveObjects getActiveObjects(); 9 | 10 | @Transactional 11 | void transactional(ApplicationUser user, String directoryName); 12 | 13 | void nonTransactional(ApplicationUser user, String directoryName); 14 | 15 | T getCompilationExceptionCause(Exception e); 16 | 17 | Class loadClass(String name) throws ClassNotFoundException; 18 | 19 | void deinitializeGlobalObjects(); 20 | 21 | void flushJqlModules(); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/WatcherService.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service; 2 | 3 | import com.atlassian.jira.user.ApplicationUser; 4 | import ru.mail.jira.plugins.groovy.api.entity.EntityType; 5 | 6 | import java.util.List; 7 | 8 | public interface WatcherService { 9 | void addWatcher(EntityType type, Integer id, ApplicationUser user); 10 | 11 | void removeWatcher(EntityType type, Integer id, ApplicationUser user); 12 | 13 | List getWatchers(EntityType type, Integer id); 14 | 15 | List getWatches(EntityType type, ApplicationUser user); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/admin/AdminScriptService.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service.admin; 2 | 3 | import com.atlassian.jira.user.ApplicationUser; 4 | import ru.mail.jira.plugins.groovy.api.dto.admin.AdminScriptOutcome; 5 | 6 | import java.util.Map; 7 | 8 | public interface AdminScriptService { 9 | AdminScriptOutcome runBuiltInScript(ApplicationUser user, String key, Map params) throws Exception; 10 | 11 | AdminScriptOutcome runUserScript(ApplicationUser user, Integer id, Map params) throws Exception; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/admin/BuiltInScript.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service.admin; 2 | 3 | import com.atlassian.jira.user.ApplicationUser; 4 | import com.google.common.collect.ImmutableMap; 5 | import ru.mail.jira.plugins.groovy.api.dto.ScriptParamDto; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public interface BuiltInScript { 11 | T run(ApplicationUser currentUser, Map params) throws Exception; 12 | 13 | String getKey(); 14 | 15 | String getI18nKey(); 16 | 17 | default String getResultWidth() { 18 | return "medium"; 19 | } 20 | 21 | boolean isHtml(); 22 | 23 | List getParams(); 24 | 25 | default Map getDefaultValues() { 26 | return ImmutableMap.of(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/service/admin/BuiltInScriptManager.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.service.admin; 2 | 3 | import ru.mail.jira.plugins.groovy.api.dto.admin.AdminScriptDto; 4 | 5 | import java.util.List; 6 | 7 | public interface BuiltInScriptManager { 8 | List getAllScripts(); 9 | 10 | BuiltInScript getScript(String key); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/util/PluginLifecycleAware.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.util; 2 | 3 | public interface PluginLifecycleAware { 4 | void onStart(); 5 | 6 | void onStop(); 7 | 8 | int getInitOrder(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/api/util/WithPluginLoader.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.api.util; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface WithPluginLoader { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/ScriptClosure.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl; 2 | 3 | import groovy.lang.Binding; 4 | import groovy.lang.Closure; 5 | import org.codehaus.groovy.runtime.InvokerHelper; 6 | 7 | import java.util.Map; 8 | 9 | public class ScriptClosure extends Closure { 10 | private final Class scriptClass; 11 | 12 | public ScriptClosure(Class scriptClass) { 13 | super(null); 14 | this.scriptClass = scriptClass; 15 | } 16 | 17 | public Object doCall(Map params) { 18 | return InvokerHelper.createScript(scriptClass, new Binding(params)).run(); 19 | } 20 | 21 | public Class getScriptClass() { 22 | return this.scriptClass; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/cf/ValueHolder.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.cf; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | import java.util.Map; 7 | 8 | @AllArgsConstructor 9 | @Getter 10 | public class ValueHolder { 11 | private final long lastModified; 12 | private final T value; 13 | private final Map velocityParams; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/groovy/ExecutionContextHolder.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.groovy; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import ru.mail.jira.plugins.groovy.api.script.ExecutionContext; 6 | 7 | public class ExecutionContextHolder { 8 | private final Logger logger = LoggerFactory.getLogger(ExecutionContextHolder.class); 9 | private final ThreadLocal context = ThreadLocal.withInitial(ExecutionContext::new); 10 | 11 | public ExecutionContext get() { 12 | if (logger.isTraceEnabled()) { 13 | logger.trace("accessing execution context"); 14 | } 15 | return context.get(); 16 | } 17 | 18 | public void reset() { 19 | context.remove(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/groovy/PackageCustomizer.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.groovy; 2 | 3 | import org.codehaus.groovy.ast.ClassNode; 4 | import org.codehaus.groovy.classgen.GeneratorContext; 5 | import org.codehaus.groovy.control.CompilationFailedException; 6 | import org.codehaus.groovy.control.CompilePhase; 7 | import org.codehaus.groovy.control.SourceUnit; 8 | import org.codehaus.groovy.control.customizers.CompilationCustomizer; 9 | 10 | 11 | public class PackageCustomizer extends CompilationCustomizer { 12 | public PackageCustomizer() { 13 | super(CompilePhase.CONVERSION); 14 | } 15 | 16 | @Override 17 | public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { 18 | if (!classNode.hasPackageName()) { 19 | String className = classNode.getName(); 20 | classNode.setName("mygroovy.scripts." + className); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/groovy/ParseContextHolder.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.groovy; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import ru.mail.jira.plugins.groovy.api.script.ParseContext; 6 | 7 | public class ParseContextHolder { 8 | private final Logger logger = LoggerFactory.getLogger(ParseContextHolder.class); 9 | private final ThreadLocal context = ThreadLocal.withInitial(ParseContext::new); 10 | 11 | public ParseContext get() { 12 | if (logger.isTraceEnabled()) { 13 | logger.trace("accessing parse context"); 14 | } 15 | return context.get(); 16 | } 17 | 18 | public void reset() { 19 | context.remove(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/groovy/log/ContextLogSink.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.groovy.log; 2 | 3 | import org.slf4j.event.LoggingEvent; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class ContextLogSink { 9 | private final List events = new ArrayList<>(); 10 | 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/groovy/log/LogTransformer.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.groovy.log; 2 | 3 | import org.apache.log4j.spi.LoggingEvent; 4 | 5 | import java.util.List; 6 | 7 | public interface LogTransformer { 8 | String formatLog(List events); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/groovy/log/LogTransformerImpl.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.groovy.log; 2 | 3 | import org.apache.log4j.Layout; 4 | import org.apache.log4j.PatternLayout; 5 | import org.apache.log4j.spi.LoggingEvent; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.List; 9 | import java.util.stream.Collectors; 10 | 11 | @Component 12 | public class LogTransformerImpl implements LogTransformer { 13 | private final Layout layout = new PatternLayout("%d %-5p [%t]: %m%n"); 14 | 15 | @Override 16 | public String formatLog(List events) { 17 | if (events == null || events.size() == 0) { 18 | return null; 19 | } 20 | 21 | return events 22 | .stream() 23 | .map(layout::format) 24 | .collect(Collectors.joining("")); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/groovy/var/GlobalObjectClassLoader.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.groovy.var; 2 | 3 | public class GlobalObjectClassLoader extends ClassLoader { 4 | private final GlobalObjectsBindingProvider globalObjectsBindingProvider; 5 | 6 | public GlobalObjectClassLoader(GlobalObjectsBindingProvider globalObjectsBindingProvider) { 7 | this.globalObjectsBindingProvider = globalObjectsBindingProvider; 8 | } 9 | 10 | @Override 11 | protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { 12 | Class result = globalObjectsBindingProvider.getTypes().get(name); 13 | 14 | if (result == null) { 15 | throw new ClassNotFoundException(); 16 | } 17 | 18 | return result; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/JqlFunctionCFType.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql; 2 | 3 | import com.atlassian.jira.issue.Issue; 4 | import com.atlassian.jira.issue.customfields.impl.CalculatedCFType; 5 | import com.atlassian.jira.issue.customfields.impl.FieldValidationException; 6 | import com.atlassian.jira.issue.fields.CustomField; 7 | 8 | import javax.annotation.Nullable; 9 | 10 | public class JqlFunctionCFType extends CalculatedCFType { 11 | @Override 12 | public String getStringFromSingularObject(Void aVoid) { 13 | return null; 14 | } 15 | 16 | @Override 17 | public Void getSingularObjectFromString(String s) throws FieldValidationException { 18 | return null; 19 | } 20 | 21 | @Nullable 22 | @Override 23 | public Void getValueFromIssue(CustomField customField, Issue issue) { 24 | return null; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/AbstractCommentQueryFunction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin; 2 | 3 | import com.atlassian.jira.jql.query.QueryCreationContext; 4 | import ru.mail.jira.plugins.groovy.impl.jql.function.builtin.query.CommentQueryParser; 5 | import ru.mail.jira.plugins.groovy.impl.jql.function.builtin.query.QueryParseResult; 6 | 7 | public abstract class AbstractCommentQueryFunction extends AbstractBuiltInQueryFunction { 8 | private CommentQueryParser commentQueryParser; 9 | 10 | public AbstractCommentQueryFunction( 11 | CommentQueryParser commentQueryParser, 12 | String name, int minimumArgs 13 | ) { 14 | super(name, minimumArgs); 15 | 16 | this.commentQueryParser = commentQueryParser; 17 | } 18 | 19 | protected QueryParseResult parseParameters( 20 | QueryCreationContext queryCreationContext, String queryString 21 | ) { 22 | return commentQueryParser.parseParameters(queryCreationContext, queryString); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/LinkedIssuesOfRecursive.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin; 2 | 3 | import com.atlassian.jira.issue.link.IssueLinkTypeManager; 4 | import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class LinkedIssuesOfRecursive extends AbstractLinkedIssuesOfRecursiveFunction { 10 | @Autowired 11 | public LinkedIssuesOfRecursive( 12 | @ComponentImport IssueLinkTypeManager issueLinkTypeManager, 13 | SearchHelper searchHelper 14 | ) { 15 | super( 16 | issueLinkTypeManager, searchHelper, 17 | "linkedIssuesOfRecursive", 1 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/LinkedIssuesOfRecursiveLimited.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin; 2 | 3 | import com.atlassian.jira.issue.link.IssueLinkTypeManager; 4 | import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class LinkedIssuesOfRecursiveLimited extends AbstractLinkedIssuesOfRecursiveFunction { 10 | @Autowired 11 | public LinkedIssuesOfRecursiveLimited( 12 | @ComponentImport IssueLinkTypeManager issueLinkTypeManager, 13 | SearchHelper searchHelper 14 | ) { 15 | super( 16 | issueLinkTypeManager, searchHelper, 17 | "linkedIssuesOfRecursiveLimited", 2 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/ParentsOfFunction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin; 2 | 3 | import com.atlassian.jira.config.SubTaskManager; 4 | import com.atlassian.jira.issue.link.Direction; 5 | import com.atlassian.jira.issue.link.IssueLinkTypeManager; 6 | import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class ParentsOfFunction extends AbstractSubTaskRelationFunction { 12 | @Autowired 13 | protected ParentsOfFunction( 14 | @ComponentImport IssueLinkTypeManager issueLinkTypeManager, 15 | @ComponentImport SubTaskManager subTaskManager, 16 | SearchHelper searchHelper 17 | ) { 18 | super(issueLinkTypeManager, subTaskManager, searchHelper, "parentsOf"); 19 | } 20 | 21 | @Override 22 | protected Direction getDirection() { 23 | return Direction.IN; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/SubTasksOfFunction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin; 2 | 3 | import com.atlassian.jira.config.SubTaskManager; 4 | import com.atlassian.jira.issue.link.Direction; 5 | import com.atlassian.jira.issue.link.IssueLinkTypeManager; 6 | import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class SubTasksOfFunction extends AbstractSubTaskRelationFunction { 12 | @Autowired 13 | protected SubTasksOfFunction( 14 | @ComponentImport IssueLinkTypeManager issueLinkTypeManager, 15 | @ComponentImport SubTaskManager subTaskManager, 16 | SearchHelper searchHelper 17 | ) { 18 | super(issueLinkTypeManager, subTaskManager, searchHelper, "subTasksOf"); 19 | } 20 | 21 | @Override 22 | protected Direction getDirection() { 23 | return Direction.OUT; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/expression/DateExtractor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.expression; 2 | 3 | import org.apache.lucene.document.Document; 4 | 5 | import java.sql.Timestamp; 6 | import java.time.LocalDate; 7 | 8 | public class DateExtractor implements LuceneFieldValueExtractor { 9 | private final String indexFieldName; 10 | 11 | public DateExtractor(String indexFieldName) { 12 | this.indexFieldName = indexFieldName; 13 | } 14 | 15 | @Override 16 | public Timestamp extract(Document document) { 17 | LocalDate localDate = LocalDate.ofEpochDay(document.getField(indexFieldName).numericValue().longValue()); 18 | return Timestamp.valueOf(localDate.atStartOfDay()); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/expression/DateTimeExtractor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.expression; 2 | 3 | import org.apache.lucene.document.Document; 4 | 5 | import java.sql.Timestamp; 6 | 7 | public class DateTimeExtractor implements LuceneFieldValueExtractor { 8 | private final String indexFieldName; 9 | 10 | public DateTimeExtractor(String indexFieldName) { 11 | this.indexFieldName = indexFieldName; 12 | } 13 | 14 | @Override 15 | public Timestamp extract(Document document) { 16 | return new Timestamp(document.getField(indexFieldName).numericValue().longValue()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/expression/DoubleCFExtractor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.expression; 2 | 3 | import com.atlassian.jira.issue.customfields.converters.DoubleConverter; 4 | import org.apache.lucene.document.Document; 5 | 6 | public class DoubleCFExtractor implements LuceneFieldValueExtractor { 7 | private final String indexFieldName; 8 | private final DoubleConverter doubleConverter; 9 | 10 | public DoubleCFExtractor(String indexFieldName, DoubleConverter doubleConverter) { 11 | this.indexFieldName = indexFieldName; 12 | this.doubleConverter = doubleConverter; 13 | } 14 | 15 | @Override 16 | public Object extract(Document document) { 17 | String fieldValue = document.getField(indexFieldName).stringValue(); 18 | return doubleConverter.getDouble(fieldValue); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/expression/DoubleExtractor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.expression; 2 | 3 | import com.atlassian.jira.lucenelegacy.NumberTools; 4 | import org.apache.lucene.document.Document; 5 | 6 | public class DoubleExtractor implements LuceneFieldValueExtractor { 7 | private final String indexFieldName; 8 | public DoubleExtractor(String indexFieldName) { 9 | this.indexFieldName = indexFieldName; 10 | } 11 | @Override 12 | public Long extract(Document document) { 13 | String fieldValue = document.getField(indexFieldName).stringValue(); 14 | return fieldValue != null ? NumberTools.stringToLong(fieldValue) : 0L; 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/expression/JqlFunctionValidationException.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.expression; 2 | 3 | import com.atlassian.jira.util.MessageSet; 4 | 5 | public class JqlFunctionValidationException extends RuntimeException { 6 | public JqlFunctionValidationException(MessageSet messageSet) { 7 | super(String.join("\n", messageSet.getErrorMessages())); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/expression/LuceneFieldValueExtractor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.expression; 2 | 3 | import org.apache.lucene.document.Document; 4 | 5 | public interface LuceneFieldValueExtractor { 6 | Object extract(Document document); 7 | } -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/expression/MillisecondsExtractor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.expression; 2 | 3 | import com.atlassian.jira.issue.index.indexers.FieldIndexer; 4 | import com.atlassian.jira.lucenelegacy.NumberTools; 5 | import org.apache.lucene.document.Document; 6 | 7 | public class MillisecondsExtractor implements LuceneFieldValueExtractor { 8 | private final String indexFieldName; 9 | 10 | public MillisecondsExtractor(String indexFieldName) { 11 | this.indexFieldName = indexFieldName; 12 | } 13 | 14 | @Override 15 | public Long extract(Document document) { 16 | String fieldValue = document.getField(indexFieldName).stringValue(); 17 | if (fieldValue == null || FieldIndexer.NO_VALUE_INDEX_VALUE.equals(fieldValue)) { 18 | return 0L; 19 | } else { 20 | return NumberTools.stringToLong(fieldValue); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/expression/UserExtractor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.expression; 2 | 3 | import org.apache.lucene.document.Document; 4 | 5 | public class UserExtractor implements LuceneFieldValueExtractor { 6 | private final String indexFieldName; 7 | private final String emptyIndexValue; 8 | 9 | public UserExtractor(String indexFieldName, String emptyIndexValue) { 10 | this.indexFieldName = indexFieldName; 11 | this.emptyIndexValue = emptyIndexValue; 12 | } 13 | 14 | @Override 15 | public String extract(Document document) { 16 | String fieldValue = document.getField(indexFieldName).stringValue(); 17 | if (fieldValue == null) 18 | return null; 19 | if (emptyIndexValue.equals(fieldValue)) 20 | return null; 21 | 22 | return fieldValue; 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/expression/WorkRatioExtractor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.expression; 2 | 3 | import org.apache.lucene.document.Document; 4 | 5 | public class WorkRatioExtractor implements LuceneFieldValueExtractor { 6 | private final String indexFieldName; 7 | 8 | public WorkRatioExtractor(String indexFieldName) { 9 | this.indexFieldName = indexFieldName; 10 | } 11 | @Override 12 | public Double extract(Document document) { 13 | String fieldValue = document.getField(indexFieldName).stringValue(); 14 | return Double.parseDouble(fieldValue != null ? fieldValue : "0") / 100; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/jsw/AddedAfterSprintStartFunction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.jsw; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | import ru.mail.jira.plugins.groovy.impl.jql.function.builtin.SearchHelper; 6 | import ru.mail.jira.plugins.groovy.impl.jsw.JiraSoftwareHelper; 7 | import ru.mail.jira.plugins.groovy.impl.jsw.JiraSoftwareHelperFactory; 8 | 9 | @Component 10 | public class AddedAfterSprintStartFunction extends AbstractSprintHistoryFunction { 11 | @Autowired 12 | public AddedAfterSprintStartFunction( 13 | JiraSoftwareHelperFactory jiraSoftwareHelperFactory, 14 | SearchHelper searchHelper 15 | ) { 16 | super(jiraSoftwareHelperFactory, searchHelper, "addedAfterSprintStart", true); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/jsw/RemovedAfterSprintStartFunction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.jsw; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | import ru.mail.jira.plugins.groovy.impl.jql.function.builtin.SearchHelper; 6 | import ru.mail.jira.plugins.groovy.impl.jsw.JiraSoftwareHelper; 7 | import ru.mail.jira.plugins.groovy.impl.jsw.JiraSoftwareHelperFactory; 8 | 9 | @Component 10 | public class RemovedAfterSprintStartFunction extends AbstractSprintHistoryFunction { 11 | @Autowired 12 | public RemovedAfterSprintStartFunction( 13 | JiraSoftwareHelperFactory jiraSoftwareHelperFactory, 14 | SearchHelper searchHelper 15 | ) { 16 | super(jiraSoftwareHelperFactory, searchHelper, "removedAfterSprintStart", false); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jql/function/builtin/query/QueryParseResult.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jql.function.builtin.query; 2 | 3 | import com.atlassian.jira.util.MessageSet; 4 | import lombok.Getter; 5 | import org.apache.lucene.search.Query; 6 | 7 | @Getter 8 | public class QueryParseResult { 9 | private final Query query; 10 | private final MessageSet messageSet; 11 | 12 | public QueryParseResult(Query query, MessageSet messageSet) { 13 | this.query = query; 14 | this.messageSet = messageSet; 15 | } 16 | 17 | public boolean hasErrors() { 18 | return messageSet.hasAnyErrors(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/jsw/JiraSoftwareHelperFactory.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.jsw; 2 | 3 | import java.util.Optional; 4 | 5 | public interface JiraSoftwareHelperFactory { 6 | Optional get(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/param/ScriptParamImpl.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.param; 2 | 3 | import ru.mail.jira.plugins.groovy.api.script.ScriptParam; 4 | import ru.mail.jira.plugins.groovy.api.script.ScriptType; 5 | import ru.mail.jira.plugins.groovy.api.service.ScriptService; 6 | 7 | import java.util.Map; 8 | 9 | public class ScriptParamImpl implements ScriptParam { 10 | private final ScriptService scriptService; 11 | private final String body; 12 | 13 | public ScriptParamImpl(ScriptService scriptService, String body) { 14 | this.scriptService = scriptService; 15 | this.body = body; 16 | } 17 | 18 | @Override 19 | public Object runScript(Map params) throws Exception { 20 | return scriptService.executeScript(null, body, ScriptType.PARAM, params); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/repository/querydsl/QAbstractChangelog.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.repository.querydsl; 2 | 3 | import com.atlassian.pocketknife.spi.querydsl.EnhancedRelationalPathBase; 4 | import com.querydsl.core.types.dsl.NumberPath; 5 | import com.querydsl.core.types.dsl.StringPath; 6 | 7 | public class QAbstractChangelog extends EnhancedRelationalPathBase { 8 | public final StringPath UUID = createStringCol("UUID").build(); 9 | public final NumberPath SCRIPT_ID; 10 | 11 | public QAbstractChangelog(String tableName, String scriptColumn) { 12 | super(QAbstractChangelog.class, "AO_2FC5DA_" + tableName); 13 | 14 | this.SCRIPT_ID = createIntegerCol(scriptColumn).build(); 15 | } 16 | 17 | public QAbstractChangelog(String tableName) { 18 | this(tableName, "SCRIPT_ID"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/repository/querydsl/QAbstractScript.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.repository.querydsl; 2 | 3 | import com.atlassian.pocketknife.spi.querydsl.EnhancedRelationalPathBase; 4 | import com.querydsl.core.types.dsl.BooleanPath; 5 | import com.querydsl.core.types.dsl.NumberPath; 6 | import com.querydsl.core.types.dsl.StringPath; 7 | 8 | public class QAbstractScript extends EnhancedRelationalPathBase { 9 | public final NumberPath ID = createIntegerCol("ID").asPrimaryKey().build(); 10 | public final StringPath UUID = createStringCol("UUID").build(); 11 | public final StringPath NAME = createStringCol("NAME").build(); 12 | public final StringPath SCRIPT_BODY = createStringCol("SCRIPT_BODY").build(); 13 | public final BooleanPath DELETED = createBooleanCol("DELETED").build(); 14 | 15 | public QAbstractScript(String tableName) { 16 | super(QAbstractScript.class, "AO_2FC5DA_" + tableName); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/repository/querydsl/QAuditLogIssueRelation.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.repository.querydsl; 2 | 3 | import com.atlassian.pocketknife.spi.querydsl.EnhancedRelationalPathBase; 4 | import com.querydsl.core.types.dsl.NumberPath; 5 | 6 | public class QAuditLogIssueRelation extends EnhancedRelationalPathBase { 7 | public final NumberPath ID = createIntegerCol("ID").asPrimaryKey().build(); 8 | public final NumberPath AUDIT_LOG_ID = createIntegerCol("AUDIT_LOG_ID").build(); 9 | public final NumberPath ISSUE_ID = createLongCol("ISSUE_ID").build(); 10 | 11 | public QAuditLogIssueRelation() { 12 | super(QAuditLogIssueRelation.class, "AO_2FC5DA_AUDIT_ISSUE_REL"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/repository/querydsl/QFieldConfig.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.repository.querydsl; 2 | 3 | import com.atlassian.pocketknife.spi.querydsl.EnhancedRelationalPathBase; 4 | import com.querydsl.core.types.dsl.NumberPath; 5 | import com.querydsl.core.types.dsl.StringPath; 6 | 7 | public class QFieldConfig extends EnhancedRelationalPathBase { 8 | public final NumberPath ID = createIntegerCol("ID").asPrimaryKey().build(); 9 | public final StringPath UUID = createStringCol("UUID").build(); 10 | public final NumberPath FIELD_CONFIG_ID = createIntegerCol("FIELD_CONFIG_ID").build(); 11 | public final StringPath SCRIPT_BODY = createStringCol("SCRIPT_BODY").build(); 12 | 13 | public QFieldConfig() { 14 | super(QFieldConfig.class, "AO_2FC5DA_FIELD_CONFIG"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/scheduled/JobUtil.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.scheduled; 2 | 3 | import com.atlassian.scheduler.config.JobId; 4 | 5 | public final class JobUtil { 6 | private static final String JOB_ID_PREFIX = "ru.mail.jira.groovy.script."; 7 | 8 | private JobUtil() {} 9 | 10 | public static JobId getJobId(int jobId) { 11 | return JobId.of(JOB_ID_PREFIX + jobId); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/workflow/ScriptDescriptor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.workflow; 2 | 3 | import lombok.*; 4 | 5 | import java.util.Map; 6 | 7 | @Getter @Setter 8 | @ToString 9 | @AllArgsConstructor @NoArgsConstructor 10 | public class ScriptDescriptor { 11 | private String id; 12 | private String uuid; 13 | private boolean fromRegistry; 14 | private String scriptBody; 15 | private Map params; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/workflow/inline/InlineScriptConditionFactory.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.workflow.inline; 2 | 3 | import com.atlassian.jira.plugin.workflow.WorkflowPluginConditionFactory; 4 | import com.opensymphony.workflow.loader.AbstractDescriptor; 5 | import com.opensymphony.workflow.loader.ConditionDescriptor; 6 | import ru.mail.jira.plugins.groovy.api.repository.ExecutionRepository; 7 | 8 | import java.util.Map; 9 | 10 | public class InlineScriptConditionFactory extends InlineScriptWorkflowPluginFactory implements WorkflowPluginConditionFactory { 11 | public InlineScriptConditionFactory(ExecutionRepository executionRepository) { 12 | super(executionRepository); 13 | } 14 | 15 | @Override 16 | protected Map getArgs(AbstractDescriptor descriptor) { 17 | return ((ConditionDescriptor) descriptor).getArgs(); 18 | } 19 | 20 | @Override 21 | protected String getModuleKey() { 22 | return "ru.mail.jira.plugins.groovyinline-script-condition"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/workflow/inline/InlineScriptFunctionFactory.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.workflow.inline; 2 | 3 | import com.atlassian.jira.plugin.workflow.WorkflowPluginFunctionFactory; 4 | import com.opensymphony.workflow.loader.AbstractDescriptor; 5 | import com.opensymphony.workflow.loader.FunctionDescriptor; 6 | import ru.mail.jira.plugins.groovy.api.repository.ExecutionRepository; 7 | 8 | import java.util.Map; 9 | 10 | public class InlineScriptFunctionFactory extends InlineScriptWorkflowPluginFactory implements WorkflowPluginFunctionFactory { 11 | public InlineScriptFunctionFactory(ExecutionRepository executionRepository) { 12 | super(executionRepository); 13 | } 14 | 15 | @Override 16 | protected Map getArgs(AbstractDescriptor descriptor) { 17 | return ((FunctionDescriptor) descriptor).getArgs(); 18 | } 19 | 20 | @Override 21 | protected String getModuleKey() { 22 | return "ru.mail.jira.plugins.groovyinline-script-function"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/workflow/inline/InlineScriptValidatorFactory.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.workflow.inline; 2 | 3 | import com.atlassian.jira.plugin.workflow.WorkflowPluginValidatorFactory; 4 | import com.opensymphony.workflow.loader.AbstractDescriptor; 5 | import com.opensymphony.workflow.loader.ValidatorDescriptor; 6 | import ru.mail.jira.plugins.groovy.api.repository.ExecutionRepository; 7 | 8 | import java.util.Map; 9 | 10 | public class InlineScriptValidatorFactory extends InlineScriptWorkflowPluginFactory implements WorkflowPluginValidatorFactory { 11 | public InlineScriptValidatorFactory(ExecutionRepository executionRepository) { 12 | super(executionRepository); 13 | } 14 | 15 | @Override 16 | protected Map getArgs(AbstractDescriptor descriptor) { 17 | return ((ValidatorDescriptor) descriptor).getArgs(); 18 | } 19 | 20 | @Override 21 | protected String getModuleKey() { 22 | return "ru.mail.jira.plugins.groovyinline-script-validator"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/impl/workflow/search/WorkflowSearchCollector.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.impl.workflow.search; 2 | 3 | import com.atlassian.jira.workflow.JiraWorkflow; 4 | import com.opensymphony.workflow.loader.ActionDescriptor; 5 | import com.opensymphony.workflow.loader.ConditionDescriptor; 6 | import com.opensymphony.workflow.loader.FunctionDescriptor; 7 | import com.opensymphony.workflow.loader.ValidatorDescriptor; 8 | 9 | public interface WorkflowSearchCollector { 10 | void setWorkflow(JiraWorkflow workflow); 11 | void workflowComplete(); 12 | void setAction(ActionDescriptor action); 13 | void actionComplete(); 14 | void collect(ConditionDescriptor descriptor); 15 | void collect(ValidatorDescriptor descriptor, int order); 16 | void collect(FunctionDescriptor descriptor, int order); 17 | 18 | default boolean isAborted() { 19 | return false; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/AntlrUtil.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util; 2 | 3 | public final class AntlrUtil { 4 | private AntlrUtil() {} 5 | 6 | public static String unescapeString(String string) { 7 | if (string.startsWith("'") || string.startsWith("\"")) { 8 | return string.substring(1, string.length() - 1); 9 | } 10 | return string; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/Base64Util.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util; 2 | 3 | import java.util.Base64; 4 | 5 | public final class Base64Util { 6 | private static final String BASE64_PREFIX = "b64_"; 7 | 8 | private Base64Util() {}; 9 | 10 | public static String encode(String value) { 11 | if (value == null) { 12 | return null; 13 | } 14 | 15 | return BASE64_PREFIX + Base64.getEncoder().encodeToString(value.getBytes()); 16 | } 17 | 18 | public static String decode(String value) { 19 | if (value == null) { 20 | return null; 21 | } 22 | 23 | if (value.startsWith(BASE64_PREFIX)) { 24 | return new String(Base64.getDecoder().decode(value.substring(BASE64_PREFIX.length()))); 25 | } else { 26 | return value; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/FieldUtil.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util; 2 | 3 | import com.atlassian.jira.issue.customfields.CustomFieldSearcher; 4 | import com.atlassian.jira.issue.fields.CustomField; 5 | 6 | import java.util.Optional; 7 | 8 | public final class FieldUtil { 9 | private FieldUtil() {} 10 | 11 | public static Optional getSearcherKey(CustomField field) { 12 | CustomFieldSearcher searcher = field.getCustomFieldSearcher(); 13 | if (searcher != null) { 14 | return Optional.of(searcher.getDescriptor().getCompleteKey()); 15 | } 16 | 17 | return Optional.empty(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/ObjectUtil.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util; 2 | 3 | import java.util.Arrays; 4 | import java.util.Objects; 5 | 6 | public final class ObjectUtil { 7 | private ObjectUtil() {} 8 | 9 | public static boolean allNonNull(Object ...objects) { 10 | return Arrays.stream(objects).allMatch(Objects::nonNull); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/PluginComponentUtil.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util; 2 | 3 | import com.atlassian.jira.component.ComponentAccessor; 4 | import com.atlassian.plugin.ModuleDescriptor; 5 | import com.atlassian.plugin.Plugin; 6 | 7 | import java.util.List; 8 | 9 | public class PluginComponentUtil { 10 | public static T getPluginComponent(Plugin plugin, Class componentClass) { 11 | T component = ComponentAccessor.getOSGiComponentInstanceOfType(componentClass); 12 | 13 | if (component == null) { 14 | List> modules = plugin.getModuleDescriptorsByModuleClass(componentClass); 15 | if (modules.size() > 0) { 16 | component = modules.get(0).getModule(); 17 | } 18 | } 19 | 20 | return component; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/RestExecutorSupplier.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util; 2 | 3 | @FunctionalInterface 4 | public interface RestExecutorSupplier { 5 | T get() throws Exception; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/RestFieldException.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util; 2 | 3 | @Deprecated 4 | public class RestFieldException extends IllegalArgumentException { 5 | private final String field; 6 | 7 | public RestFieldException(String message, String field) { 8 | super(message); 9 | this.field = field; 10 | } 11 | 12 | public String getField() { 13 | return this.field; 14 | } 15 | 16 | @Override 17 | public String getMessage() { 18 | if (field != null) { 19 | return field + ": " + super.getMessage(); 20 | } 21 | 22 | return super.getMessage(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/ValidationException.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import lombok.Getter; 5 | 6 | import java.util.List; 7 | import java.util.stream.Collectors; 8 | 9 | //todo: migrate everything to ValidationException 10 | @Getter 11 | public class ValidationException extends RuntimeException { 12 | private final List messages; 13 | private final String field; 14 | 15 | public ValidationException(List messages, String field) { 16 | super(messages.stream().collect(Collectors.joining("; "))); 17 | this.messages = messages; 18 | this.field = field; 19 | } 20 | 21 | public ValidationException(String message, String field) { 22 | this(ImmutableList.of(message), field); 23 | } 24 | 25 | public ValidationException(String message) { 26 | this(message, null); 27 | } 28 | 29 | public ValidationException(List messages) { 30 | this(messages, null); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/cl/WithPluginLoaderBeanProcessor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util.cl; 2 | 3 | import org.springframework.stereotype.Component; 4 | import ru.mail.jira.plugins.groovy.util.spring.ProxiedBeanPostProcessor; 5 | 6 | @Component 7 | public class WithPluginLoaderBeanProcessor extends ProxiedBeanPostProcessor { 8 | public WithPluginLoaderBeanProcessor() { 9 | super(WithPluginLoaderInterceptor.ANNOTATION_CLASS, new WithPluginLoaderInterceptor()); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/compat/ArchivingHelper.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util.compat; 2 | 3 | import com.atlassian.jira.project.Project; 4 | 5 | public interface ArchivingHelper { 6 | boolean isProjectArchived(Project project); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/compat/ArchivingHelperImpl.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util.compat; 2 | 3 | import com.atlassian.jira.project.Project; 4 | 5 | public class ArchivingHelperImpl implements ArchivingHelper { 6 | @Override 7 | public boolean isProjectArchived(Project project) { 8 | return project.isArchived(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/compat/StubArchivingHelper.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util.compat; 2 | 3 | import com.atlassian.jira.project.Project; 4 | 5 | public class StubArchivingHelper implements ArchivingHelper { 6 | @Override 7 | public boolean isProjectArchived(Project project) { 8 | return false; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/func/ExceptionalConsumer.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util.func; 2 | 3 | import java.util.function.Consumer; 4 | 5 | @FunctionalInterface 6 | public interface ExceptionalConsumer { 7 | void apply(T t) throws Exception; 8 | 9 | static Consumer makeSafe(ExceptionalConsumer exceptionalFunction) { 10 | return t -> { 11 | try { 12 | exceptionalFunction.apply(t); 13 | } catch (Exception e) { 14 | throw new RuntimeException(e); 15 | } 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/func/ExceptionalFunction.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util.func; 2 | 3 | import java.util.function.Function; 4 | 5 | @FunctionalInterface 6 | public interface ExceptionalFunction { 7 | R apply(T t) throws Exception; 8 | 9 | static Function makeSafe(ExceptionalFunction exceptionalFunction) { 10 | return t -> { 11 | try { 12 | return exceptionalFunction.apply(t); 13 | } catch (Exception e) { 14 | throw new RuntimeException(e); 15 | } 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/func/ExceptionalPredicate.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util.func; 2 | 3 | import java.util.function.Predicate; 4 | 5 | @FunctionalInterface 6 | public interface ExceptionalPredicate { 7 | boolean apply(T t) throws Exception; 8 | 9 | static Predicate makeSafe(ExceptionalPredicate exceptionalFunction) { 10 | return t -> { 11 | try { 12 | return exceptionalFunction.apply(t); 13 | } catch (Exception e) { 14 | throw new RuntimeException(e); 15 | } 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/lucene/QueryUtil.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util.lucene; 2 | 3 | import com.atlassian.jira.issue.index.DocumentConstants; 4 | import org.apache.lucene.search.*; 5 | import org.apache.lucene.util.BytesRef; 6 | 7 | import java.util.Collection; 8 | import java.util.Set; 9 | import java.util.stream.Collectors; 10 | 11 | public class QueryUtil { 12 | public static Query createIssueIdQuery(Set issueIds) { 13 | return createIssueIdQuery(issueIds.stream().map(BytesRef::new).collect(Collectors.toList())); 14 | } 15 | 16 | public static Query createIssueIdQuery(Collection issueIds) { 17 | return createMultiTermQuery(DocumentConstants.ISSUE_ID, issueIds); 18 | } 19 | 20 | public static Query createMultiTermQuery(String field, Collection terms) { 21 | return new TermInSetQuery(field, terms); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ru/mail/jira/plugins/groovy/util/tx/TransactionalAnnotationProcessor.java: -------------------------------------------------------------------------------- 1 | package ru.mail.jira.plugins.groovy.util.tx; 2 | 3 | import org.springframework.stereotype.Component; 4 | import ru.mail.jira.plugins.groovy.util.spring.ProxiedBeanPostProcessor; 5 | 6 | @Component 7 | public final class TransactionalAnnotationProcessor extends ProxiedBeanPostProcessor { 8 | public TransactionalAnnotationProcessor() { 9 | super(TransactionalInterceptor.ANNOTATION_CLASS, new TransactionalInterceptor()); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/AdditionalArithmeticOperators.groovy: -------------------------------------------------------------------------------- 1 | import java.sql.Timestamp 2 | 3 | void registerAdditionalArithmeticOps() { 4 | Timestamp.metaClass.plus { Long l -> 5 | new Timestamp(new Date((delegate as Timestamp).time + l).time) 6 | } 7 | 8 | Timestamp.metaClass.minus { Long l -> 9 | new Timestamp(new Date((delegate as Timestamp).time - l).time) 10 | } 11 | 12 | Timestamp.metaClass.minus { Timestamp t -> 13 | (((delegate as Timestamp).time - t.time)) as Long 14 | } 15 | 16 | Timestamp.metaClass.plus { Timestamp t -> 17 | (((delegate as Timestamp).time + t.time)) as Long 18 | } 19 | 20 | Long.metaClass.plus { Timestamp t -> 21 | new Timestamp(t.time + (delegate as Long)) 22 | } 23 | 24 | Long.metaClass.minus { Timestamp t -> 25 | new Timestamp(t.time - (delegate as Long)) 26 | } 27 | } 28 | 29 | registerAdditionalArithmeticOps() -------------------------------------------------------------------------------- /src/main/resources/images/pluginIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atlascommunity/jira-plugins-groovy/ef39c5118d1b36aac531c9d03ba06aeaa03ead2e/src/main/resources/images/pluginIcon.png -------------------------------------------------------------------------------- /src/main/resources/images/pluginLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atlascommunity/jira-plugins-groovy/ef39c5118d1b36aac531c9d03ba06aeaa03ead2e/src/main/resources/images/pluginLogo.png -------------------------------------------------------------------------------- /src/main/resources/ru/mail/jira/plugins/groovy/.gitignore: -------------------------------------------------------------------------------- 1 | /js 2 | /css 3 | -------------------------------------------------------------------------------- /src/main/resources/ru/mail/jira/plugins/groovy/templates/inline-script-view.vm: -------------------------------------------------------------------------------- 1 | #* @vtlvariable name="escapeJs" type="java.util.function.Function" *# 2 | Groovy inline script 3 |
4 |
5 | 6 | $webResourceManager.requireResourcesForContext("ru.mail.jira.plugins.groovy.workflow") 7 | 8 | 22 | -------------------------------------------------------------------------------- /src/main/resources/ru/mail/jira/plugins/groovy/templates/main.vm: -------------------------------------------------------------------------------- 1 | 2 | 3 | MyGroovy 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 | 12 | $webResourceManager.requireResourcesForContext("ru.mail.jira.plugins.groovy.main") 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/ru/mail/jira/plugins/groovy/templates/registry-script-edit.vm: -------------------------------------------------------------------------------- 1 | #* @vtlvariable name="type" type="ru.mail.jira.plugins.groovy.api.dto.workflow.WorkflowScriptType" *# 2 |
3 | 4 |
5 | 6 | $webResourceManager.requireResourcesForContext("ru.mail.jira.plugins.groovy.workflow") 7 | 8 | 22 | -------------------------------------------------------------------------------- /src/main/resources/ru/mail/jira/plugins/groovy/templates/template-cf.vm: -------------------------------------------------------------------------------- 1 | #disable_html_escaping() 2 | #if ($template) 3 | #evaluate($template) 4 | #end 5 | -------------------------------------------------------------------------------- /src/test/java/it/ru/mail/jira/plugins/groovy/util/Forms.java: -------------------------------------------------------------------------------- 1 | package it.ru.mail.jira.plugins.groovy.util; 2 | 3 | import ru.mail.jira.plugins.groovy.api.dto.global.GlobalObjectForm; 4 | import ru.mail.jira.plugins.groovy.impl.FileUtil; 5 | 6 | import java.io.IOException; 7 | import java.util.regex.Pattern; 8 | 9 | public final class Forms { 10 | private Forms() {} 11 | 12 | public static GlobalObjectForm globalObject(String sourcePath) throws IOException { 13 | return globalObjectFromSource(FileUtil.readArquillianExample(sourcePath)); 14 | } 15 | 16 | public static GlobalObjectForm globalObjectFromSource(String source) { 17 | long ts = System.currentTimeMillis(); 18 | String globalObjectName = "testObject" + ts; 19 | 20 | GlobalObjectForm form = new GlobalObjectForm(); 21 | form.setName(globalObjectName); 22 | form.setScriptBody(source.replaceAll(Pattern.quote("$TS$"), String.valueOf(ts))); 23 | 24 | return form; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/it/ru/mail/jira/plugins/groovy/util/HttpUtil.java: -------------------------------------------------------------------------------- 1 | package it.ru.mail.jira.plugins.groovy.util; 2 | 3 | import com.google.common.io.BaseEncoding; 4 | import org.apache.http.Header; 5 | import org.apache.http.HttpHeaders; 6 | import org.apache.http.message.BasicHeader; 7 | 8 | public final class HttpUtil { 9 | private HttpUtil() {} 10 | 11 | public static Header basicAuthHeader(String username, String password) { 12 | return new BasicHeader( 13 | HttpHeaders.AUTHORIZATION, 14 | "Basic " + BaseEncoding.base64().encode((username + ":" + password).getBytes()) 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/resources/arquillian.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | jira 9 | 10 | 11 | 12 | --------------------------------------------------------------------------------