Added other Jira resources
This commit is contained in:
@@ -629,7 +629,7 @@ function bindWorkflowProperties(elementId) {
|
||||
const totalWidth = properties_component.getBoundingClientRect().width
|
||||
console.debug("totalWidth", totalWidth)
|
||||
|
||||
const minPropertiesWidth = 340; // this value avoid scroll bars
|
||||
const minPropertiesWidth = 352; // this value avoid scroll bars
|
||||
|
||||
const inputSection = document.getElementById(`pi_${elementId}`);
|
||||
const propertiesSection = document.getElementById(`pp_${elementId}`);
|
||||
|
||||
@@ -196,7 +196,7 @@ class WorkflowDesigner(BaseComponent):
|
||||
def save_properties(self, component_id: str, details: dict):
|
||||
if component_id in self._state.components:
|
||||
component = self._state.components[component_id]
|
||||
component.properties = details
|
||||
component.properties |= details
|
||||
|
||||
undo_redo_attrs = UndoRedoAttrs(f"Set properties for {component.title}", on_undo=self.refresh_state)
|
||||
self._db.save_state(self._key, self._state, undo_redo_attrs)
|
||||
@@ -518,7 +518,7 @@ class WorkflowDesigner(BaseComponent):
|
||||
selected="selected" if name.value == request_type else None)
|
||||
|
||||
def _mk_input_group():
|
||||
if request_type == JiraRequestTypes.Issues.value:
|
||||
if request_type == JiraRequestTypes.Search.value:
|
||||
return Div(
|
||||
Input(type="text",
|
||||
name="request",
|
||||
@@ -538,7 +538,7 @@ class WorkflowDesigner(BaseComponent):
|
||||
)
|
||||
|
||||
def _mk_extra_parameters():
|
||||
if request_type == JiraRequestTypes.Issues.value:
|
||||
if request_type == JiraRequestTypes.Search.value:
|
||||
return Input(type="text",
|
||||
name="fields",
|
||||
value=component.properties.get("fields", DEFAULT_SEARCH_FIELDS),
|
||||
@@ -547,7 +547,7 @@ class WorkflowDesigner(BaseComponent):
|
||||
else:
|
||||
return None
|
||||
|
||||
request_type = component.properties.get("request_type", JiraRequestTypes.Issues.value)
|
||||
request_type = component.properties.get("request_type", JiraRequestTypes.Search.value)
|
||||
return Div(
|
||||
Fieldset(
|
||||
Legend("JQL", cls="fieldset-legend"),
|
||||
|
||||
@@ -186,40 +186,51 @@ class WorkflowDesignerProperties(BaseComponent):
|
||||
selected="selected" if name.value == request_type else None)
|
||||
|
||||
def _mk_input_group():
|
||||
if request_type == JiraRequestTypes.Issues.value:
|
||||
if request_type == JiraRequestTypes.Search.value or request_type == "issues": # remove issues at some point
|
||||
return [
|
||||
Div(
|
||||
Input(type="text",
|
||||
name="fields",
|
||||
value=self._component.properties.get("fields", DEFAULT_SEARCH_FIELDS),
|
||||
name=f"{request_type}_fields",
|
||||
value=self._component.properties.get(f"{request_type}_fields", DEFAULT_SEARCH_FIELDS),
|
||||
placeholder="default fields",
|
||||
cls="input w-full"),
|
||||
P("Jira fields to retrieve"),
|
||||
),
|
||||
Div(
|
||||
Input(type="text",
|
||||
name="request",
|
||||
value=self._component.properties.get("request", ""),
|
||||
name=f"{request_type}_request",
|
||||
value=self._component.properties.get(f"{request_type}_request", ""),
|
||||
placeholder="Enter JQL",
|
||||
cls="input w-full"),
|
||||
P("Write your jql code"),
|
||||
)
|
||||
]
|
||||
elif request_type == JiraRequestTypes.Comments.value:
|
||||
elif request_type in (JiraRequestTypes.Issue.value, JiraRequestTypes.Comments.value):
|
||||
return [
|
||||
Div(
|
||||
Input(type="text",
|
||||
name="request",
|
||||
value=self._component.properties.get("request", ""),
|
||||
name=f"{request_type}_request",
|
||||
value=self._component.properties.get(f"{request_type}_request", ""),
|
||||
placeholder="Issue id",
|
||||
cls="input w-full"),
|
||||
P("Put the issue id here"),
|
||||
)
|
||||
]
|
||||
elif request_type == JiraRequestTypes.Versions.value:
|
||||
return [
|
||||
Div(
|
||||
Input(type="text",
|
||||
name=f"{request_type}_request",
|
||||
value=self._component.properties.get(f"{request_type}_request", ""),
|
||||
placeholder="Project key",
|
||||
cls="input w-full"),
|
||||
P("Enter the project key"),
|
||||
)
|
||||
]
|
||||
else:
|
||||
return [Div("** Not Implemented **")]
|
||||
return [Div(f"** Not Implemented ** ('{request_type}' not supported yet)")]
|
||||
|
||||
request_type = self._component.properties.get("request_type", JiraRequestTypes.Issues.value)
|
||||
request_type = self._component.properties.get("request_type", JiraRequestTypes.Search.value)
|
||||
return Div(
|
||||
Fieldset(
|
||||
Legend("Jira", cls="fieldset-legend"),
|
||||
|
||||
@@ -191,13 +191,14 @@ class WorkflowPlayer(BaseComponent):
|
||||
component.properties["repository"],
|
||||
component.properties["table"]))
|
||||
elif key == (ProcessorTypes.Producer, "Jira"):
|
||||
request_type = component.properties["request_type"]
|
||||
engine.add_processor(
|
||||
JiraDataProducer(self._session,
|
||||
self._settings_manager,
|
||||
component.id,
|
||||
component.properties["request_type"],
|
||||
component.properties["request"],
|
||||
component.properties["fields"]))
|
||||
component.properties[f"{request_type}_request"],
|
||||
component.properties.get(f"{request_type}_fields", None)))
|
||||
elif key == (ProcessorTypes.Filter, "Default"):
|
||||
engine.add_processor(DefaultDataFilter(component.id, component.properties["filter"]))
|
||||
elif key == (ProcessorTypes.Presenter, "Default"):
|
||||
|
||||
@@ -10,7 +10,7 @@ from core.Expando import Expando
|
||||
JIRA_ROOT = "https://altares.atlassian.net/rest/api/3"
|
||||
DEFAULT_HEADERS = {"Accept": "application/json"}
|
||||
DEFAULT_SEARCH_FIELDS = "summary,status,assignee"
|
||||
logger = logging.getLogger("jql")
|
||||
logger = logging.getLogger("Jira")
|
||||
|
||||
|
||||
class NotFound(Exception):
|
||||
@@ -18,8 +18,10 @@ class NotFound(Exception):
|
||||
|
||||
|
||||
class JiraRequestTypes(Enum):
|
||||
Issues = "issues"
|
||||
Search = "search"
|
||||
Issue = "issue"
|
||||
Comments = "comments"
|
||||
Versions = "versions"
|
||||
|
||||
|
||||
class Jira:
|
||||
@@ -41,7 +43,10 @@ class Jira:
|
||||
self.fields = fields
|
||||
|
||||
def test(self):
|
||||
logger.debug(f"test with no parameters")
|
||||
|
||||
url = f"{JIRA_ROOT}/myself"
|
||||
logger.debug(f" url: {url}")
|
||||
|
||||
response = requests.request(
|
||||
"GET",
|
||||
@@ -49,16 +54,21 @@ class Jira:
|
||||
headers=DEFAULT_HEADERS,
|
||||
auth=self.auth
|
||||
)
|
||||
logger.debug(f" response: {response}")
|
||||
logger.debug(f" response.text: {response.text}")
|
||||
|
||||
return response
|
||||
|
||||
def issue(self, issue_id: str) -> Expando:
|
||||
def issue(self, issue_id: str) -> list[Expando]:
|
||||
"""
|
||||
Retrieve an issue
|
||||
:param issue_id:
|
||||
:return:
|
||||
"""
|
||||
logger.debug(f"comments with {issue_id=}")
|
||||
|
||||
url = f"{JIRA_ROOT}/issue/{issue_id}"
|
||||
logger.debug(f" url: {url}")
|
||||
|
||||
response = requests.request(
|
||||
"GET",
|
||||
@@ -66,8 +76,10 @@ class Jira:
|
||||
headers=DEFAULT_HEADERS,
|
||||
auth=self.auth
|
||||
)
|
||||
logger.debug(f" response: {response}")
|
||||
logger.debug(f" response.text: {response.text}")
|
||||
|
||||
return Expando(json.loads(response.text))
|
||||
return [Expando(json.loads(response.text))]
|
||||
|
||||
def fields(self) -> list[Expando]:
|
||||
"""
|
||||
@@ -86,14 +98,14 @@ class Jira:
|
||||
as_dict = json.loads(response.text)
|
||||
return [Expando(field) for field in as_dict]
|
||||
|
||||
def issues(self, jql: str, fields=None) -> list[Expando]:
|
||||
def search(self, jql: str, fields=None) -> list[Expando]:
|
||||
"""
|
||||
Executes a JQL and returns the list of issues
|
||||
:param jql:
|
||||
:param fields: list of fields to retrieve
|
||||
:return:
|
||||
"""
|
||||
logger.debug(f"Processing jql '{jql}'")
|
||||
logger.debug(f"search with {jql=}, {fields=}")
|
||||
|
||||
if not jql:
|
||||
raise ValueError("Jql cannot be empty.")
|
||||
@@ -102,6 +114,7 @@ class Jira:
|
||||
fields = self.fields
|
||||
|
||||
url = f"{JIRA_ROOT}/search"
|
||||
logger.debug(f" url: {url}")
|
||||
|
||||
headers = DEFAULT_HEADERS.copy()
|
||||
headers["Content-Type"] = "application/json"
|
||||
@@ -113,15 +126,19 @@ class Jira:
|
||||
"maxResults": 500, # Does not seem to be used. It's always 100 !
|
||||
"startAt": 0
|
||||
}
|
||||
logger.debug(f" payload: {payload}")
|
||||
|
||||
result = []
|
||||
while True:
|
||||
logger.debug(f"Request startAt '{payload['startAt']}'")
|
||||
logger.debug(f" Request startAt '{payload['startAt']}'")
|
||||
response = requests.request("POST",
|
||||
url,
|
||||
data=json.dumps(payload),
|
||||
headers=headers,
|
||||
auth=self.auth)
|
||||
logger.debug(f" response: {response}")
|
||||
logger.debug(f" response.text: {response.text}")
|
||||
|
||||
|
||||
if response.status_code != 200:
|
||||
raise Exception(self._format_error(response))
|
||||
@@ -130,6 +147,7 @@ class Jira:
|
||||
result += as_dict["issues"]
|
||||
|
||||
if as_dict["startAt"] + as_dict["maxResults"] >= as_dict["total"]:
|
||||
logger.debug(f" response: {response}")
|
||||
# We retrieve more than the total nuber of items
|
||||
break
|
||||
|
||||
@@ -143,12 +161,18 @@ class Jira:
|
||||
:param issue_id:
|
||||
:return:
|
||||
"""
|
||||
logger.debug(f"comments with {issue_id=}")
|
||||
|
||||
url = f"{JIRA_ROOT}/issue/{issue_id}/comment"
|
||||
logger.debug(f" url: {url}")
|
||||
|
||||
response = requests.request("GET",
|
||||
url,
|
||||
headers=DEFAULT_HEADERS,
|
||||
auth=self.auth)
|
||||
logger.debug(f" response: {response}")
|
||||
logger.debug(f" response.text: {response.text}")
|
||||
|
||||
if response.status_code != 200:
|
||||
raise Exception(self._format_error(response))
|
||||
|
||||
@@ -156,6 +180,34 @@ class Jira:
|
||||
result = as_dict["comments"]
|
||||
return [Expando(issue) for issue in result]
|
||||
|
||||
def versions(self, project_key):
|
||||
"""
|
||||
Given a project name and a version name
|
||||
returns fixVersion number in JIRA
|
||||
:param project_key:
|
||||
:return:
|
||||
"""
|
||||
logger.debug(f"versions with {project_key=}")
|
||||
|
||||
url = f"{JIRA_ROOT}/project/{project_key}/versions"
|
||||
logger.debug(f" url: {url}")
|
||||
|
||||
response = requests.request(
|
||||
"GET",
|
||||
url,
|
||||
headers=DEFAULT_HEADERS,
|
||||
auth=self.auth
|
||||
)
|
||||
|
||||
logger.debug(f" response: {response}")
|
||||
logger.debug(f" response.text: {response.text}")
|
||||
|
||||
if response.status_code != 200:
|
||||
raise NotFound()
|
||||
|
||||
as_list = json.loads(response.text)
|
||||
return [Expando(version) for version in as_list]
|
||||
|
||||
def extract(self, jql, mappings, updates=None) -> list[dict]:
|
||||
"""
|
||||
Executes a jql and returns list of dict
|
||||
@@ -188,30 +240,6 @@ class Jira:
|
||||
row = {cvs_col: issue.get(jira_path) for jira_path, cvs_col in mappings.items() if cvs_col is not None}
|
||||
yield row
|
||||
|
||||
def get_versions(self, project_key):
|
||||
"""
|
||||
Given a project name and a version name
|
||||
returns fixVersion number in JIRA
|
||||
:param project_key:
|
||||
:param version_name:
|
||||
:return:
|
||||
"""
|
||||
|
||||
url = f"{JIRA_ROOT}/project/{project_key}/versions"
|
||||
|
||||
response = requests.request(
|
||||
"GET",
|
||||
url,
|
||||
headers=DEFAULT_HEADERS,
|
||||
auth=self.auth
|
||||
)
|
||||
|
||||
if response.status_code != 200:
|
||||
raise NotFound()
|
||||
|
||||
as_list = json.loads(response.text)
|
||||
return [Expando(version) for version in as_list]
|
||||
|
||||
def get_version(self, project_key, version_name):
|
||||
"""
|
||||
Given a project name and a version name
|
||||
@@ -221,7 +249,7 @@ class Jira:
|
||||
:return:
|
||||
"""
|
||||
|
||||
for version in self.get_versions(project_key):
|
||||
for version in self.versions(project_key):
|
||||
if version.name == version_name:
|
||||
return version
|
||||
|
||||
|
||||
@@ -47,4 +47,9 @@ loggers:
|
||||
AddStuffApp:
|
||||
level: INFO
|
||||
handlers: [ console ]
|
||||
propagate: False
|
||||
|
||||
Jira:
|
||||
level: DEBUG
|
||||
handlers: [ console ]
|
||||
propagate: False
|
||||
Reference in New Issue
Block a user