Worklog proof of concept

This commit is contained in:
Fabian 2021-11-23 19:50:57 +01:00
parent b54cd0d1df
commit ce46c8daca
5 changed files with 288 additions and 2 deletions

10
LICENSE
View File

@ -18,5 +18,11 @@ OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Included icons are taken from KDE breeze-icons (https://invent.kde.org/frameworks/breeze-icons), Included icons (src/fime/icons) are taken from KDE breeze-icons (https://invent.kde.org/frameworks/breeze-icons),
which are licensed under LGPL 3. which are licensed under LGPL 3.
Progress indicator (src/fime/progressindicator.py):
Author: Jared P. Sutton <jpsutton@gmail.com>
License: LGPL
Note: I've licensed this code as LGPL because it was a complete translation of the code found here...
https://github.com/mojocorp/QProgressIndicator

View File

@ -0,0 +1,123 @@
"""
"""
try:
from PySide6 import QtCore, QtGui, QtWidgets
except ImportError:
from PySide2 import QtCore, QtGui, QtWidgets
class QProgressIndicator(QtWidgets.QWidget):
m_angle = None
m_timerId = None
m_delay = None
m_displayedWhenStopped = None
m_color = None
def __init__(self, parent):
# Call parent class constructor first
super().__init__(parent)
# Initialize Qt Properties
self.setProperties()
# Intialize instance variables
self.m_angle = 0
self.m_timerId = -1
self.m_delay = 40
self.m_displayedWhenStopped = False
self.m_color = QtCore.Qt.black
# Set size and focus policy
self.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
self.setFocusPolicy(QtCore.Qt.NoFocus)
# Show the widget
self.show()
def animationDelay(self):
return self.delay
def isAnimated(self):
return (self.m_timerId != -1)
def isDisplayedWhenStopped(self):
return self.displayedWhenStopped
def getColor(self):
return self.color
def sizeHint(self):
return QtCore.QSize(20, 20)
def startAnimation(self):
self.m_angle = 0
if self.m_timerId == -1:
self.m_timerId = self.startTimer(self.m_delay)
def stopAnimation(self):
if self.m_timerId != -1:
self.killTimer(self.m_timerId)
self.m_timerId = -1
self.update()
def setAnimationDelay(self, delay):
if self.m_timerId != -1:
self.killTimer(self.m_timerId)
self.m_delay = delay
if self.m_timerId != -1:
self.m_timerId = self.startTimer(self.m_delay)
def setDisplayedWhenStopped(self, state):
self.displayedWhenStopped = state
self.update()
def setColor(self, color):
self.m_color = color
self.update()
def timerEvent(self, event):
self.m_angle = (self.m_angle + 30) % 360
self.update()
def paintEvent(self, event):
if (not self.m_displayedWhenStopped) and (not self.isAnimated()):
return
width = min(self.width(), self.height())
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
outerRadius = (width - 1) * 0.5
innerRadius = (width - 1) * 0.5 * 0.38
capsuleHeight = outerRadius - innerRadius
capsuleWidth = capsuleHeight * .23 if (width > 32) else capsuleHeight * .35
capsuleRadius = capsuleWidth / 2
color = QtGui.QColor(self.m_color)
for i in range(0, 12):
if self.isAnimated():
color.setAlphaF(1.0 - (i / 12.0))
else:
color.setAlphaF(0.2)
painter.setPen(QtCore.Qt.NoPen)
painter.setBrush(color)
painter.save()
painter.translate(self.rect().center())
painter.rotate(self.m_angle - (i * 30.0))
painter.drawRoundedRect(capsuleWidth * -0.5, (innerRadius + capsuleHeight) * -1, capsuleWidth,
capsuleHeight, capsuleRadius, capsuleRadius)
painter.restore()
def setProperties(self):
self.delay = QtCore.Property(int, self.animationDelay, self.setAnimationDelay)
self.displayedWhenStopped = QtCore.Property(bool, self.isDisplayedWhenStopped, self.setDisplayedWhenStopped)
self.color = QtCore.Property(QtGui.QColor, self.getColor, self.setColor)

View File

@ -11,6 +11,13 @@ def get_screen_height(qobject):
print("unable to detect screen height falling back to default value of 1080") print("unable to detect screen height falling back to default value of 1080")
return 1080 return 1080
def get_screen_width(qobject):
if hasattr(qobject, "screen"):
return qobject.screen().size().width()
else:
print("unable to detect screen width falling back to default value of 1920")
return 1920
def get_icon(icon_name): def get_icon(icon_name):
theme_name = icon_name.replace("-light", "") # respect system theme theme_name = icon_name.replace("-light", "") # respect system theme

94
src/fime/worklog.py Normal file
View File

@ -0,0 +1,94 @@
from PySide2.QtCore import Qt, QUrl
from PySide2.QtGui import QIcon
from PySide2.QtQuickWidgets import QQuickWidget
from PySide2.QtWidgets import QLabel
from fime.ok_icon import OkIcon
from fime.progressindicator import QProgressIndicator
from fime.spinner import Spinner
try:
from PySide6 import QtCore, QtGui, QtWidgets
except ImportError:
from PySide2 import QtCore, QtGui, QtWidgets
from fime.util import get_screen_height, get_screen_width
# noinspection PyUnresolvedReferences
import fime.icons
class Worklog(QtWidgets.QDialog):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.setWindowTitle("Worklog")
self.tableWidget = QtWidgets.QTableWidget()
self.tableWidget.verticalHeader().hide()
self.tableWidget.setColumnCount(3)
self.tableWidget.setHorizontalHeaderLabels(["Task", "Comment", "Duration"])
self.header = QtWidgets.QHeaderView(QtCore.Qt.Orientation.Horizontal)
self.header.setMinimumSectionSize(1)
self.header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
self.tableWidget.setHorizontalHeader(self.header)
self.header.setSectionResizeMode(self.header.logicalIndex(1), QtWidgets.QHeaderView.Stretch)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.tableWidget)
self.setLayout(layout)
self.refresh_table()
def refresh_table(self):
self._report_data = [
["ASG-8690 Ansible - Debian 11 Support", "", "01:23"],
["ASG-8342 Ansible - MariaDB Rolle überarbeiten ", "", "03:57"],
["ASG-8685 CATS Testsystem: Debian Upgrades Server mit Version kleiner 10 ", "", "02:12"],
]
self.tableWidget.setRowCount(len(self._report_data))
for row, _ in enumerate(self._report_data):
item0 = QtWidgets.QTableWidgetItem(self._report_data[row][0])
item0.setToolTip("something has gone wrong")
self.tableWidget.setItem(row, 0, item0)
size = self.tableWidget.rowHeight(row)
if row == 1:
qpi = QProgressIndicator(self)
qpi.setMaximumSize(QtCore.QSize(size * 0.75, size * 0.75))
qpi.setAnimationDelay(70)
qpi.startAnimation()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(qpi, alignment=Qt.AlignRight | Qt.AlignVCenter)
layout.setContentsMargins(size * 0.1, size * 0.1, size * 0.1, size * 0.1)
wdgt = QtWidgets.QWidget()
wdgt.setLayout(layout)
#label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
#label.setMargin(size * 0.1)
label = wdgt
else:
label = QLabel()
if row == 0:
item_name = "dialog-ok"
elif row == 2:
item_name = "edit-delete-remove"
label.setPixmap(QIcon.fromTheme(item_name).pixmap(size * 0.75, size * 0.75))
label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
label.setMargin(size*0.1)
self.tableWidget.setCellWidget(row, 0, label)
item1 = QtWidgets.QTableWidgetItem(self._report_data[row][1])
self.tableWidget.setItem(row, 1, item1)
item2 = QtWidgets.QTableWidgetItem(self._report_data[row][2])
self.tableWidget.setItem(row, 2, item2)
#item2.setFlags(item2.flags() & QtCore.Qt.ItemIsEnabled)
self.tableWidget.resizeColumnToContents(0)
# TODO integrate entered text and max screen width
comment_width = get_screen_width(self) * 0.2
self.tableWidget.setMinimumWidth(self.tableWidget.columnWidth(0) + comment_width + self.tableWidget.columnWidth(2))
self.tableWidget.setColumnWidth(0, self.tableWidget.columnWidth(0) * 1.05)
@QtCore.Slot()
def disable_buttons(self):
pass
@QtCore.Slot()
def enable_buttons(self):
pass

56
src/fime/worklog_.py Normal file
View File

@ -0,0 +1,56 @@
import os
from datetime import date, datetime
import requests
from fime.config import Config
class Worklog:
def __init__(self, config: Config):
self.config = config
self.user_url = os.path.join(config.jira_url, "rest/api/2/myself")
self.issue_url = os.path.join(config.jira_url, "rest/api/2/issue/{}")
self.worklog_url = os.path.join(config.jira_url, "rest/api/2/issue/{}/worklog")
self.worklog_update_url = os.path.join(config.jira_url, "rest/api/2/issue/{issue}/worklog/{worklog}")
self.user = self.get_user()
def get_user(self):
resp = requests.get(self.user_url,
headers={
"Authorization": f"Bearer {self.config.jira_token}",
"Accept": "application/json",
},
)
user = resp.json()["key"]
print(user)
return user
def get(self, issue_key: str, date: date):
resp = requests.get(self.issue_url.format(issue_key),
headers={
"Authorization": f"Bearer {self.config.jira_token}",
"Accept": "application/json",
},
)
if resp.status_code != 200:
raise RuntimeError("issue does not exist")
resp = requests.get(self.worklog_url.format(issue_key),
headers={
"Authorization": f"Bearer {self.config.jira_token}",
"Accept": "application/json",
},
)
worklogs = resp.json()["worklogs"]
found = False
for log in worklogs:
if log["author"]["key"] == self.user \
and datetime.strptime(log["started"], "%Y-%m-%dT%H:%M:%S.%f%z").date() == date:
print(log["id"])
print(log["comment"])
found = True
break
print(found)