mirror of
https://github.com/e1fueg0/intellij-gitea-plugin.git
synced 2024-10-27 20:34:04 +00:00
Initial code commit
This commit is contained in:
parent
f21e823eec
commit
1db06a0ad3
3
.gitignore
vendored
3
.gitignore
vendored
@ -21,3 +21,6 @@
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
.idea/
|
||||
out/
|
||||
|
@ -1 +1 @@
|
||||
# intellij-gitea-plugin
|
||||
# Gitea issue tracker integration plugin (http://gitea.io) for Jetbrains IDE platform.
|
13
gitea_plugin.iml
Normal file
13
gitea_plugin.iml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PLUGIN_MODULE" version="4">
|
||||
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/resources/META-INF/plugin.xml" />
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
28
resources/META-INF/plugin.xml
Normal file
28
resources/META-INF/plugin.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<idea-plugin>
|
||||
<id>biz.elfuego.idea.issues.gitea</id>
|
||||
<name>Gitea issues plugin</name>
|
||||
<version>1.0</version>
|
||||
<vendor email="support@elfuego.biz" url="http://elfuego.biz">elfuego.biz</vendor>
|
||||
|
||||
<description><![CDATA[
|
||||
Gitea issue tracker integration plugin (http://gitea.io)
|
||||
]]></description>
|
||||
|
||||
<change-notes><![CDATA[
|
||||
First implementation.<br>
|
||||
]]>
|
||||
</change-notes>
|
||||
|
||||
<idea-version since-build="173.0"/>
|
||||
|
||||
<depends>com.intellij.modules.lang</depends>
|
||||
<depends>com.intellij.tasks</depends>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<tasks.repositoryType implementation="biz.elfuego.idea.issues.gitea.GiteaRepositoryType"/>
|
||||
</extensions>
|
||||
|
||||
<actions>
|
||||
</actions>
|
||||
|
||||
</idea-plugin>
|
BIN
resources/resources/gitea.png
Normal file
BIN
resources/resources/gitea.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 610 B |
346
src/biz/elfuego/idea/issues/gitea/GiteaRepository.java
Normal file
346
src/biz/elfuego/idea/issues/gitea/GiteaRepository.java
Normal file
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright © 2018 by elfuego.biz
|
||||
*/
|
||||
package biz.elfuego.idea.issues.gitea;
|
||||
|
||||
import biz.elfuego.idea.issues.gitea.model.GiteaProject;
|
||||
import biz.elfuego.idea.issues.gitea.model.GiteaTask;
|
||||
import biz.elfuego.idea.issues.gitea.util.Consts;
|
||||
import biz.elfuego.idea.issues.gitea.util.Consts.CommentFields;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.tasks.Comment;
|
||||
import com.intellij.tasks.CustomTaskState;
|
||||
import com.intellij.tasks.Task;
|
||||
import com.intellij.tasks.impl.BaseRepositoryImpl;
|
||||
import com.intellij.tasks.impl.SimpleComment;
|
||||
import com.intellij.util.xmlb.annotations.AbstractCollection;
|
||||
import com.intellij.util.xmlb.annotations.Tag;
|
||||
import com.intellij.util.xmlb.annotations.Transient;
|
||||
import org.apache.commons.httpclient.HttpMethod;
|
||||
import org.apache.commons.httpclient.HttpStatus;
|
||||
import org.apache.commons.httpclient.auth.AuthPolicy;
|
||||
import org.apache.commons.httpclient.methods.GetMethod;
|
||||
import org.apache.commons.httpclient.methods.PostMethod;
|
||||
import org.apache.commons.httpclient.methods.StringRequestEntity;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static biz.elfuego.idea.issues.gitea.util.Utils.*;
|
||||
|
||||
/**
|
||||
* @author Roman Pedchenko <elfuego@elfuego.biz>
|
||||
* @date 2018.06.30
|
||||
*/
|
||||
@Tag("Gitea")
|
||||
class GiteaRepository extends BaseRepositoryImpl {
|
||||
private String userId = null;
|
||||
private List<GiteaProject> projects = new ArrayList<>();
|
||||
private GiteaProject selectedProject = null;
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public GiteaRepository() {
|
||||
super();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration", "WeakerAccess"})
|
||||
public GiteaRepository(GiteaRepositoryType type) {
|
||||
super(type);
|
||||
setUseHttpAuthentication(true);
|
||||
setUrl(Consts.Url.DEFAULT);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration", "WeakerAccess"})
|
||||
public GiteaRepository(GiteaRepository other) {
|
||||
super(other);
|
||||
userId = other.userId;
|
||||
projects = other.projects;
|
||||
selectedProject = other.selectedProject;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Task findTask(@NotNull String s) throws Exception {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task[] getIssues(@Nullable String query, int offset, int limit, boolean withClosed, @NotNull ProgressIndicator cancelled) throws Exception {
|
||||
return getIssues();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@SuppressWarnings("CloneDoesntCallSuperClone")
|
||||
public GiteaRepository clone() {
|
||||
return new GiteaRepository(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CancellableConnection createCancellableConnection() {
|
||||
return new CancellableConnection() {
|
||||
@Override
|
||||
protected void doTest() throws Exception {
|
||||
GiteaRepository.this.doTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
//Jetbrains left this method blank in their generic task repo as well. Just let it time out?
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String extractId(@NotNull String taskName) {
|
||||
Matcher matcher = Pattern.compile("(d+)").matcher(taskName);
|
||||
return matcher.find() ? matcher.group(1) : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<CustomTaskState> getAvailableTaskStates(@NotNull Task task) {
|
||||
Set<CustomTaskState> result = new HashSet<>();
|
||||
for (Consts.States state : Consts.States.values()) {
|
||||
String name = state.name().toLowerCase();
|
||||
result.add(new CustomTaskState(name, name));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception {
|
||||
GiteaTaskImpl giteaTask = null;
|
||||
if (task instanceof GiteaTaskImpl) {
|
||||
giteaTask = (GiteaTaskImpl) task;
|
||||
} else {
|
||||
Task[] tasks = getIssues();
|
||||
for (Task t : tasks) {
|
||||
if (task.getId().equals(t.getId())) {
|
||||
giteaTask = (GiteaTaskImpl) t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (giteaTask == null) {
|
||||
throw new Exception("Task not found");
|
||||
}
|
||||
|
||||
giteaTask.task.setState(state.getId());
|
||||
JsonObject jsonData = new JsonObject();
|
||||
jsonData.addProperty("state", state.getId());
|
||||
StringRequestEntity data = new StringRequestEntity(
|
||||
jsonData.toString(),
|
||||
"application/json",
|
||||
"UTF-8"
|
||||
);
|
||||
HttpMethod patchTask = getPatchMethod(getApiUrl() + Consts.EndPoint.REPOS + selectedProject.getName()
|
||||
+ Consts.EndPoint.ISSUES + "/" + giteaTask.getId(), data);
|
||||
executeMethod(patchTask);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFeatures() {
|
||||
return NATIVE_SEARCH | STATE_UPDATING;
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
userId = null;
|
||||
checkSetup();
|
||||
JsonElement response = executeMethod(new GetMethod(getApiUrl() + Consts.EndPoint.ME));
|
||||
final JsonObject obj = getObject(response);
|
||||
if (obj.has("id") && obj.has("login"))
|
||||
return;
|
||||
throw new Exception(Consts.ERROR);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getApiUrl() {
|
||||
return getUrl() + Consts.EndPoint.API;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfigured() {
|
||||
boolean result = true;
|
||||
if (!super.isConfigured()) {
|
||||
result = false;
|
||||
}
|
||||
if (result && StringUtil.isEmpty(this.getUrl())) {
|
||||
result = false;
|
||||
}
|
||||
if (result && StringUtil.isEmpty(this.getUsername())) {
|
||||
result = false;
|
||||
}
|
||||
if (result && StringUtil.isEmpty(this.getPassword())) {
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void checkSetup() throws Exception {
|
||||
String result = "";
|
||||
int errors = 0;
|
||||
if (StringUtil.isEmpty(getUrl())) {
|
||||
result += "Server";
|
||||
errors++;
|
||||
}
|
||||
if (StringUtil.isEmpty(getUsername())) {
|
||||
result += !StringUtils.isEmpty(result) ? " & " : "";
|
||||
result += "Username";
|
||||
errors++;
|
||||
}
|
||||
if (StringUtil.isEmpty(getPassword())) {
|
||||
result += !StringUtils.isEmpty(result) ? " & " : "";
|
||||
result += "Password";
|
||||
errors++;
|
||||
}
|
||||
if (!result.isEmpty()) {
|
||||
throw new Exception(result + ((errors > 1) ? " are required" : " is required"));
|
||||
}
|
||||
}
|
||||
|
||||
private Task[] getIssues() throws Exception {
|
||||
if (ifNoSelectedProj()) return new Task[]{};
|
||||
ensureUserId();
|
||||
List<GiteaTaskImpl> result = new ArrayList<>();
|
||||
|
||||
final String url = getApiUrl() + Consts.EndPoint.REPOS + selectedProject.getName() + Consts.EndPoint.ISSUES;
|
||||
final JsonElement response = executeMethod(new GetMethod(url));
|
||||
JsonArray tasks = getArray(response);
|
||||
for (int i = 0; i < tasks.size(); i++) {
|
||||
JsonObject current = tasks.get(i).getAsJsonObject();
|
||||
GiteaTask raw = new GiteaTask(selectedProject, current);
|
||||
if (!raw.isValid()) {
|
||||
continue;
|
||||
}
|
||||
GiteaTaskImpl mapped = new GiteaTaskImpl(this, raw);
|
||||
result.add(mapped);
|
||||
}
|
||||
Collections.sort(result);
|
||||
Task[] primArray = new Task[result.size()];
|
||||
return result.toArray(primArray);
|
||||
}
|
||||
|
||||
private boolean ifNoSelectedProj() {
|
||||
return selectedProject == null || selectedProject.getId().equals("-1");
|
||||
}
|
||||
|
||||
public Comment[] getComments(GiteaTaskImpl task) throws Exception {
|
||||
if (ifNoSelectedProj()) return new Comment[]{};
|
||||
ensureUserId();
|
||||
List<SimpleComment> result = new ArrayList<>();
|
||||
|
||||
final String url = getApiUrl() + Consts.EndPoint.REPOS + selectedProject.getName() + Consts.EndPoint.ISSUES
|
||||
+ "/" + task.getId() + Consts.EndPoint.COMMENTS;
|
||||
final JsonElement response = executeMethod(new GetMethod(url));
|
||||
JsonArray comments = getArray(response);
|
||||
for (int i = 0; i < comments.size(); i++) {
|
||||
JsonObject current = comments.get(i).getAsJsonObject();
|
||||
Date date = getDate(current, CommentFields.DATE);
|
||||
String text = getString(current, CommentFields.TEXT, "");
|
||||
JsonObject user = getObject(current, CommentFields.USER);
|
||||
String author = getString(user, CommentFields.FULLNAME, "");
|
||||
if (author.isEmpty())
|
||||
author = getString(user, CommentFields.USERNAME, "");
|
||||
result.add(new SimpleComment(date, author, text));
|
||||
}
|
||||
Comment[] primArray = new Comment[result.size()];
|
||||
return result.toArray(primArray);
|
||||
}
|
||||
|
||||
private JsonElement executeMethod(@NotNull HttpMethod method) throws Exception {
|
||||
method.addRequestHeader("Content-type", "application/json");
|
||||
List authPrefs = Collections.singletonList(AuthPolicy.BASIC);
|
||||
method.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
|
||||
getHttpClient().executeMethod(method);
|
||||
|
||||
if (method.getStatusCode() != HttpStatus.SC_OK && method.getStatusCode() != HttpStatus.SC_CREATED) {
|
||||
throw new Exception("Request failed with HTTP error: " + method.getStatusText());
|
||||
}
|
||||
|
||||
return new JsonParser().parse(new InputStreamReader(method.getResponseBodyAsStream(), "UTF-8"));
|
||||
}
|
||||
|
||||
private HttpMethod getPatchMethod(String url, StringRequestEntity data) {
|
||||
PostMethod patchMethod = new PostMethod(url) {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "PATCH";
|
||||
}
|
||||
};
|
||||
patchMethod.setRequestEntity(data);
|
||||
return patchMethod;
|
||||
}
|
||||
|
||||
private void ensureUserId() throws Exception {
|
||||
if (userId == null || userId.isEmpty()) {
|
||||
JsonElement result = executeMethod(new GetMethod(getApiUrl() + Consts.EndPoint.ME));
|
||||
userId = result.getAsJsonObject().get("login").getAsJsonPrimitive().getAsString();
|
||||
}
|
||||
}
|
||||
|
||||
@Transient
|
||||
List<GiteaProject> getProjectList() throws Exception {
|
||||
ensureUserId();
|
||||
if (projects == null || projects.isEmpty()) {
|
||||
JsonElement response = executeMethod(new GetMethod(getApiUrl() + Consts.EndPoint.REPOS_SEARCH + userId));
|
||||
JsonArray query = getOkData(response);
|
||||
List<GiteaProject> result = new ArrayList<>();
|
||||
for (int i = 0; i < query.size(); i++) {
|
||||
JsonObject current = getObject(query.get(i));
|
||||
GiteaProject project = new GiteaProject().setId(getString(current, "id", ""))
|
||||
.setName(getString(current, "full_name", ""));
|
||||
if (!project.isValid()) {
|
||||
continue;
|
||||
}
|
||||
result.add(project);
|
||||
}
|
||||
projects = result;
|
||||
}
|
||||
return projects;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public GiteaProject getSelectedProject() {
|
||||
return selectedProject;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public void setSelectedProject(GiteaProject selectedProject) {
|
||||
this.selectedProject = selectedProject;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
@AbstractCollection(surroundWithTag = false, elementTag = "GiteaProject", elementTypes = GiteaProject.class)
|
||||
public List<GiteaProject> getProjects() {
|
||||
return projects;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public void setProjects(List<GiteaProject> projects) {
|
||||
this.projects = projects;
|
||||
}
|
||||
}
|
104
src/biz/elfuego/idea/issues/gitea/GiteaRepositoryEditor.java
Normal file
104
src/biz/elfuego/idea/issues/gitea/GiteaRepositoryEditor.java
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright © 2018 by elfuego.biz
|
||||
*/
|
||||
package biz.elfuego.idea.issues.gitea;
|
||||
|
||||
import biz.elfuego.idea.issues.gitea.model.GiteaProject;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.tasks.config.BaseRepositoryEditor;
|
||||
import com.intellij.tasks.impl.TaskUiUtil;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ui.FormBuilder;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Roman Pedchenko <elfuego@elfuego.biz>
|
||||
* @date 2018.06.30
|
||||
*/
|
||||
public class GiteaRepositoryEditor extends BaseRepositoryEditor<GiteaRepository> {
|
||||
private JBLabel projectLabel;
|
||||
private ComboBox projectBox;
|
||||
|
||||
GiteaRepositoryEditor(GiteaRepository repository, Project project, Consumer<GiteaRepository> consumer) {
|
||||
super(project, repository, consumer);
|
||||
|
||||
installListener(projectBox);
|
||||
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
initialize();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
if (myRepository.isConfigured()) {
|
||||
new FetchProjectsTask().queue();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent createCustomPanel() {
|
||||
projectBox = new ComboBox(300);
|
||||
projectBox.setRenderer(new TaskUiUtil.SimpleComboBoxRenderer("Set URL, username, and password"));
|
||||
projectLabel = new JBLabel("Project:", SwingConstants.RIGHT);
|
||||
projectLabel.setLabelFor(projectBox);
|
||||
|
||||
return new FormBuilder().setAlignLabelOnRight(true)
|
||||
.addLabeledComponent(projectLabel, projectBox)
|
||||
.getPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAnchor(@Nullable JComponent anchor) {
|
||||
super.setAnchor(anchor);
|
||||
projectLabel.setAnchor(anchor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterTestConnection(boolean connectionSuccessful) {
|
||||
if (connectionSuccessful) {
|
||||
new FetchProjectsTask().queue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
super.apply();
|
||||
myRepository.setSelectedProject((GiteaProject) projectBox.getSelectedItem());
|
||||
myTestButton.setEnabled(myRepository.isConfigured());
|
||||
}
|
||||
|
||||
private class FetchProjectsTask extends TaskUiUtil.ComboBoxUpdater<GiteaProject> {
|
||||
private FetchProjectsTask() {
|
||||
super(GiteaRepositoryEditor.this.myProject, "Downloading Gitea projects...", projectBox);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GiteaProject getExtraItem() {
|
||||
return GiteaProject.UNSPECIFIED_PROJECT;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GiteaProject getSelectedItem() {
|
||||
return myRepository.getSelectedProject();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<GiteaProject> fetch(@NotNull ProgressIndicator indicator) throws Exception {
|
||||
return myRepository.getProjectList();
|
||||
}
|
||||
}
|
||||
}
|
49
src/biz/elfuego/idea/issues/gitea/GiteaRepositoryType.java
Normal file
49
src/biz/elfuego/idea/issues/gitea/GiteaRepositoryType.java
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright © 2018 by elfuego.biz
|
||||
*/
|
||||
package biz.elfuego.idea.issues.gitea;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.tasks.TaskRepository;
|
||||
import com.intellij.tasks.config.TaskRepositoryEditor;
|
||||
import com.intellij.tasks.impl.BaseRepositoryType;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Roman Pedchenko <elfuego@elfuego.biz>
|
||||
* @date 2018.06.30
|
||||
*/
|
||||
public class GiteaRepositoryType extends BaseRepositoryType<GiteaRepository> {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Gitea";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return IconLoader.getIcon("/resources/gitea.png");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TaskRepositoryEditor createEditor(GiteaRepository repository, Project project, Consumer<GiteaRepository> consumer) {
|
||||
return new GiteaRepositoryEditor(repository, project, consumer);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TaskRepository createRepository() {
|
||||
return new GiteaRepository(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<GiteaRepository> getRepositoryClass() {
|
||||
return GiteaRepository.class;
|
||||
}
|
||||
}
|
120
src/biz/elfuego/idea/issues/gitea/GiteaTaskImpl.java
Normal file
120
src/biz/elfuego/idea/issues/gitea/GiteaTaskImpl.java
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright © 2018 by elfuego.biz
|
||||
*/
|
||||
package biz.elfuego.idea.issues.gitea;
|
||||
|
||||
import biz.elfuego.idea.issues.gitea.model.GiteaProject;
|
||||
import biz.elfuego.idea.issues.gitea.model.GiteaTask;
|
||||
import biz.elfuego.idea.issues.gitea.util.Consts;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.tasks.Comment;
|
||||
import com.intellij.tasks.Task;
|
||||
import com.intellij.tasks.TaskRepository;
|
||||
import com.intellij.tasks.TaskType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Roman Pedchenko <elfuego@elfuego.biz>
|
||||
* @date 2018.06.30
|
||||
*/
|
||||
public class GiteaTaskImpl extends Task implements Comparable<GiteaTaskImpl> {
|
||||
private GiteaProject project;
|
||||
private GiteaRepository repository;
|
||||
private Comment[] comments;
|
||||
GiteaTask task;
|
||||
|
||||
GiteaTaskImpl(@NotNull GiteaRepository repository, @NotNull GiteaTask task) {
|
||||
this.repository = repository;
|
||||
this.task = task;
|
||||
this.project = task.getProject();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getId() {
|
||||
return task.getId();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getSummary() {
|
||||
return task.getTitle();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return task.getDescription();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Comment[] getComments() {
|
||||
if (comments == null) {
|
||||
try {
|
||||
comments = repository.getComments(this);
|
||||
} catch(Exception ignored) {}
|
||||
if (comments == null)
|
||||
comments = new Comment[0];
|
||||
}
|
||||
return comments;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return IconLoader.getIcon("/resources/gitea.png");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TaskType getType() {
|
||||
return TaskType.OTHER;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Date getUpdated() {
|
||||
return task.getUpdatedAt();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Date getCreated() {
|
||||
return task.getCreatedAt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return Consts.States.CLOSED.name().toLowerCase().equals(task.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIssue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TaskRepository getRepository() {
|
||||
return repository;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getIssueUrl() {
|
||||
return repository.getUrl() + "/" + project.getName() + Consts.EndPoint.ISSUES + "/" + task.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull GiteaTaskImpl o) {
|
||||
int me = Integer.parseInt(this.task.getId());
|
||||
int them = Integer.parseInt(o.task.getId());
|
||||
|
||||
return Integer.compare(me, them);
|
||||
}
|
||||
}
|
71
src/biz/elfuego/idea/issues/gitea/model/GiteaProject.java
Normal file
71
src/biz/elfuego/idea/issues/gitea/model/GiteaProject.java
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright © 2018 by elfuego.biz
|
||||
*/
|
||||
package biz.elfuego.idea.issues.gitea.model;
|
||||
|
||||
import biz.elfuego.idea.issues.gitea.util.Consts;
|
||||
|
||||
/**
|
||||
* @author Roman Pedchenko <elfuego@elfuego.biz>
|
||||
* @date 2018.06.30
|
||||
*/
|
||||
public class GiteaProject {
|
||||
private String id;
|
||||
private String name;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public GiteaProject setId(String mProjectId) {
|
||||
this.id = mProjectId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public GiteaProject setName(String mProjectTitle) {
|
||||
this.name = mProjectTitle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return !(id.equals("") || name.equals(""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name != null ? name : super.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
GiteaProject that = (GiteaProject) o;
|
||||
|
||||
return (id != null ? id.equals(that.id) : that.id == null) && (name != null ? name.equals(that.name) : that.name == null);
|
||||
}
|
||||
|
||||
public static final GiteaProject UNSPECIFIED_PROJECT = new GiteaProject() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "-- Select A Project (Required) --";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return Consts.UNSPEC_PROJ_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
};
|
||||
}
|
136
src/biz/elfuego/idea/issues/gitea/model/GiteaTask.java
Normal file
136
src/biz/elfuego/idea/issues/gitea/model/GiteaTask.java
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright © 2018 by elfuego.biz
|
||||
*/
|
||||
package biz.elfuego.idea.issues.gitea.model;
|
||||
|
||||
import biz.elfuego.idea.issues.gitea.util.Consts.TaskFields;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.apache.http.util.TextUtils;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static biz.elfuego.idea.issues.gitea.util.Utils.getDate;
|
||||
import static biz.elfuego.idea.issues.gitea.util.Utils.getString;
|
||||
|
||||
/**
|
||||
* @author Roman Pedchenko <elfuego@elfuego.biz>
|
||||
* @date 2018.06.30
|
||||
*/
|
||||
public class GiteaTask {
|
||||
private GiteaProject project;
|
||||
private String id;
|
||||
private String title;
|
||||
private String description;
|
||||
private Date createdAt;
|
||||
private Date updatedAt;
|
||||
private String state;
|
||||
private String assignee;
|
||||
|
||||
public GiteaTask(GiteaProject project, JsonObject json) {
|
||||
this.project = project;
|
||||
this.fromJson(json);
|
||||
}
|
||||
|
||||
public GiteaProject getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
public void setProject(GiteaProject project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Date getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public void setCreatedAt(Date createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Date getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public void setUpdatedAt(Date updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public String getAssignee() {
|
||||
return assignee;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public void setAssignee(String assignee) {
|
||||
this.assignee = assignee;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return !(TextUtils.isEmpty(id) ||
|
||||
TextUtils.isEmpty(title) ||
|
||||
(createdAt == null) ||
|
||||
(updatedAt == null) ||
|
||||
TextUtils.isEmpty(state));
|
||||
}
|
||||
|
||||
private void fromJson(JsonObject current) {
|
||||
if (current.has(TaskFields.ID)) {
|
||||
this.setId(getString(current, TaskFields.ID, ""));
|
||||
}
|
||||
if (current.has(TaskFields.TITLE)) {
|
||||
this.setTitle(getString(current, TaskFields.TITLE, ""));
|
||||
}
|
||||
if (current.has(TaskFields.DESCRIPTION)) {
|
||||
this.setDescription(getString(current, TaskFields.DESCRIPTION, ""));
|
||||
}
|
||||
if (current.has(TaskFields.CREATEDAT)) {
|
||||
this.setCreatedAt(getDate(current, TaskFields.CREATEDAT));
|
||||
}
|
||||
if (current.has(TaskFields.UPDATEDAT)) {
|
||||
this.setUpdatedAt(getDate(current, TaskFields.UPDATEDAT));
|
||||
}
|
||||
if (current.has(TaskFields.STATE)) {
|
||||
this.setState(getString(current, TaskFields.STATE, ""));
|
||||
}
|
||||
if (current.has(TaskFields.ASSIGNEE)) {
|
||||
this.setAssignee(getString(current, TaskFields.ASSIGNEE, ""));
|
||||
}
|
||||
}
|
||||
}
|
48
src/biz/elfuego/idea/issues/gitea/util/Consts.java
Normal file
48
src/biz/elfuego/idea/issues/gitea/util/Consts.java
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright © 2018 by elfuego.biz
|
||||
*/
|
||||
package biz.elfuego.idea.issues.gitea.util;
|
||||
|
||||
/**
|
||||
* @author Roman Pedchenko <elfuego@elfuego.biz>
|
||||
* @date 2018.06.30
|
||||
*/
|
||||
public class Consts {
|
||||
public static final String ERROR = "Error communicating to the server";
|
||||
public static final String UNSPEC_PROJ_ID = "--";
|
||||
|
||||
public interface Url {
|
||||
String DEFAULT = "https://git2.elfuego.biz:444";
|
||||
}
|
||||
|
||||
public interface EndPoint {
|
||||
String API = "/api/v1";
|
||||
String ME = "/user";
|
||||
String REPOS = "/repos/";
|
||||
String ISSUES = "/issues";
|
||||
String COMMENTS = "/comments";
|
||||
String REPOS_SEARCH = REPOS + "search?uid=";
|
||||
}
|
||||
|
||||
public enum States {
|
||||
OPEN, CLOSED;
|
||||
}
|
||||
|
||||
public interface TaskFields {
|
||||
static final String ID = "id";
|
||||
static final String TITLE = "title";
|
||||
static final String DESCRIPTION = "body";
|
||||
static final String CREATEDAT = "created_at";
|
||||
static final String UPDATEDAT = "updated_at";
|
||||
static final String STATE = "state";
|
||||
static final String ASSIGNEE = "assignee";
|
||||
}
|
||||
|
||||
public interface CommentFields {
|
||||
static final String DATE = "updated_at";
|
||||
static final String TEXT = "body";
|
||||
static final String USER = "user";
|
||||
static final String FULLNAME = "full_name";
|
||||
static final String USERNAME = "username";
|
||||
}
|
||||
}
|
90
src/biz/elfuego/idea/issues/gitea/util/Utils.java
Normal file
90
src/biz/elfuego/idea/issues/gitea/util/Utils.java
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright © 2018 by elfuego.biz
|
||||
*/
|
||||
package biz.elfuego.idea.issues.gitea.util;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Roman Pedchenko <elfuego@elfuego.biz>
|
||||
* @date 2018.06.30
|
||||
*/
|
||||
public class Utils {
|
||||
private static final String OK = "ok";
|
||||
private static final String DATA = "data";
|
||||
|
||||
public static String getString(JsonObject object, String fieldName, String defaultValue) {
|
||||
String result = defaultValue;
|
||||
if (object.has(fieldName) && object.get(fieldName).isJsonPrimitive()) {
|
||||
result = object.get(fieldName).getAsJsonPrimitive().getAsString();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Date getDate(JsonObject object, String fieldName) {
|
||||
Date result = null;
|
||||
if (object.has(fieldName) && object.get(fieldName).isJsonPrimitive()) {
|
||||
result = parseDateISO8601(object.get(fieldName).getAsJsonPrimitive().getAsString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Date parseDateISO8601(String input) {
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz");
|
||||
if (input.endsWith("Z")) {
|
||||
input = input.substring(0, input.length() - 1) + "GMT-00:00";
|
||||
} else {
|
||||
int inset = 6;
|
||||
|
||||
String s0 = input.substring(0, input.length() - inset);
|
||||
String s1 = input.substring(input.length() - inset, input.length());
|
||||
|
||||
input = s0 + "GMT" + s1;
|
||||
}
|
||||
try {
|
||||
return df.parse(input);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static JsonObject getObject(JsonElement el) throws Exception {
|
||||
if (el.isJsonObject()) {
|
||||
return el.getAsJsonObject();
|
||||
}
|
||||
throw new Exception(Consts.ERROR + ", getObject: " + el.toString());
|
||||
}
|
||||
|
||||
public static JsonObject getObject(JsonObject object, String fieldName) throws Exception {
|
||||
if (object.has(fieldName) && object.get(fieldName).isJsonObject()) {
|
||||
return object.get(fieldName).getAsJsonObject();
|
||||
}
|
||||
throw new Exception(Consts.ERROR + ", getObject2: " + object.toString());
|
||||
}
|
||||
|
||||
public static JsonArray getArray(JsonElement el) throws Exception {
|
||||
if (el.isJsonArray()) {
|
||||
return el.getAsJsonArray();
|
||||
}
|
||||
throw new Exception(Consts.ERROR + ", getArray: " + el.toString());
|
||||
}
|
||||
|
||||
public static JsonArray getOkData(JsonElement el) throws Exception {
|
||||
if (el.isJsonObject()) {
|
||||
JsonObject obj = el.getAsJsonObject();
|
||||
if (obj.has(OK) && obj.get(OK).isJsonPrimitive() && obj.get(OK).getAsBoolean()) {
|
||||
if (obj.has(DATA) && obj.get(DATA).isJsonArray())
|
||||
return obj.get(DATA).getAsJsonArray();
|
||||
}
|
||||
}
|
||||
throw new Exception(Consts.ERROR + ", getOkData: " + el.toString());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user