Compare commits
47 Commits
Author | SHA1 | Date |
---|---|---|
afornerot | 442718316d | |
afornerot | 4c9b0a1db2 | |
afornerot | 88ffe47f6e | |
afornerot | 0d9caea067 | |
afornerot | 9171ecbf6c | |
afornerot | b155036347 | |
afornerot | 8bc58f6966 | |
afornerot | a2d1841631 | |
afornerot | 0249b6cfae | |
afornerot | 31876489ca | |
afornerot | e2142caa49 | |
afornerot | d9448ccfee | |
afornerot | 0b15ea51bd | |
afornerot | b530a4d8ff | |
afornerot | d2ff60af5c | |
afornerot | e98e1f2698 | |
afornerot | 8f8f53bff3 | |
afornerot | 9dc93daab8 | |
afornerot | 0acb4e1777 | |
afornerot | 0c51a19726 | |
afornerot | 13c9c8bd3d | |
afornerot | 11c6d4635f | |
afornerot | cc200a9862 | |
afornerot | b81226d125 | |
afornerot | 072afb2a1c | |
afornerot | c61312bc3d | |
afornerot | 37968a3728 | |
afornerot | 0989e4762c | |
afornerot | ab2b1e6d3f | |
afornerot | 4f88121362 | |
afornerot | 2df92a3b7f | |
afornerot | 3d949eefce | |
afornerot | 54f9156149 | |
afornerot | 94993f9a10 | |
afornerot | dae554a45d | |
afornerot | 1c572dd516 | |
afornerot | 4c77a4bcd1 | |
afornerot | 88a518ec1c | |
afornerot | 86fcff316f | |
afornerot | 8cfee4699e | |
afornerot | 652d3365a1 | |
afornerot | 8e96aee7ab | |
afornerot | 1666811787 | |
afornerot | 1714bd9a70 | |
afornerot | 70ea9bff97 | |
afornerot | 9205735d1f | |
afornerot | ecb1d43b38 |
5
.env
5
.env
|
@ -1,6 +1,7 @@
|
|||
# Symfony
|
||||
APP_ENV=PROD
|
||||
APP_SECRET=changemeinenvlocal
|
||||
APP_PROTOCOL=https
|
||||
#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
||||
#TRUSTED_HOSTS='^(localhost|example\.com)$'
|
||||
|
||||
|
@ -39,9 +40,9 @@ MAILER_NOREPLY=noreply@noreply.fr
|
|||
|
||||
|
||||
# WEBSOCKET
|
||||
WSS_USE=0
|
||||
WSS_USE=1
|
||||
WSS_PORT=5588
|
||||
|
||||
WSS_URL=ws://localhost:5588
|
||||
|
||||
# Proxy
|
||||
PROXY_USE=0
|
||||
|
|
|
@ -34,3 +34,4 @@ yarn-error.log
|
|||
/public/uploads/logo/*
|
||||
!/public/uploads/logo/logo.png
|
||||
/public/uploads/ckeditor
|
||||
/public/uploads/issues
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
update:
|
||||
git pull
|
||||
docker-compose exec ninegitea /app/misc/script/reconfigure.sh
|
|
@ -53,7 +53,11 @@
|
|||
"preferred-install": {
|
||||
"*": "dist"
|
||||
},
|
||||
"sort-packages": true
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"ocramius/package-versions": true,
|
||||
"symfony/flex": true
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
oneup_uploader:
|
||||
mappings:
|
||||
avatar:
|
||||
frontend: dropzone
|
||||
logo:
|
||||
frontend: dropzone
|
||||
document:
|
||||
frontend: dropzone
|
||||
namer: app.upload.samename
|
||||
storage:
|
||||
directory: "%kernel.project_dir%/uploads/document"
|
|
@ -1,6 +1,6 @@
|
|||
# Read the documentation: https://github.com/1up-lab/OneupUploaderBundle/blob/master/Resources/doc/index.md
|
||||
oneup_uploader:
|
||||
mappings:
|
||||
# This is a mapping example, remove it and create your own mappings.
|
||||
gallery:
|
||||
frontend: dropzone # or any uploader you use in the frontend
|
||||
avatar:
|
||||
frontend: dropzone
|
||||
logo:
|
||||
frontend: dropzone
|
|
@ -1,325 +1,374 @@
|
|||
#== Home ========================================================================================================
|
||||
app_home:
|
||||
path: /
|
||||
defaults: { _controller: App\Controller\HomeController:home }
|
||||
path: /
|
||||
defaults: { _controller: App\Controller\HomeController:home }
|
||||
|
||||
app_admin:
|
||||
path: /admin/home
|
||||
defaults: { _controller: App\Controller\HomeController:admin }
|
||||
path: /admin/home
|
||||
defaults: { _controller: App\Controller\HomeController:admin }
|
||||
|
||||
app_ckeditor_upload:
|
||||
path: /user/activity/upload
|
||||
defaults: { _controller: App\Controller\HomeController:upload }
|
||||
path: /user/activity/upload
|
||||
defaults: { _controller: App\Controller\HomeController:upload }
|
||||
|
||||
#== Security ====================================================================================================
|
||||
app_login:
|
||||
path: /login
|
||||
defaults: { _controller: App\Controller\SecurityController:login }
|
||||
path: /login
|
||||
defaults: { _controller: App\Controller\SecurityController:login }
|
||||
|
||||
app_logout:
|
||||
path: /logout
|
||||
defaults: { _controller: App\Controller\SecurityController:logout }
|
||||
path: /logout
|
||||
defaults: { _controller: App\Controller\SecurityController:logout }
|
||||
|
||||
app_login_callback:
|
||||
path: /logincallback
|
||||
defaults: { _controller: App\Controller\SecurityController:callback }
|
||||
path: /logincallback
|
||||
defaults: { _controller: App\Controller\SecurityController:callback }
|
||||
|
||||
app_casdebug:
|
||||
path: /user/casdebug
|
||||
defaults: { _controller: App\Controller\SecurityController:casdebug }
|
||||
path: /user/casdebug
|
||||
defaults: { _controller: App\Controller\SecurityController:casdebug }
|
||||
|
||||
#== Config ==============================================================================================================
|
||||
app_config:
|
||||
path: /admin/config
|
||||
defaults: { _controller: App\Controller\ConfigController:list }
|
||||
path: /admin/config
|
||||
defaults: { _controller: App\Controller\ConfigController:list }
|
||||
|
||||
app_config_render:
|
||||
path: /admin/config/render/{category}
|
||||
defaults: { _controller: App\Controller\ConfigController:listrender }
|
||||
path: /admin/config/render/{category}
|
||||
defaults: { _controller: App\Controller\ConfigController:listrender }
|
||||
|
||||
app_config_submit:
|
||||
path: /admin/config/submit
|
||||
defaults: { _controller: App\Controller\ConfigController:submit }
|
||||
path: /admin/config/submit
|
||||
defaults: { _controller: App\Controller\ConfigController:submit }
|
||||
|
||||
app_config_update:
|
||||
path: /admin/config/update/{id}
|
||||
defaults: { _controller: App\Controller\ConfigController:update }
|
||||
path: /admin/config/update/{id}
|
||||
defaults: { _controller: App\Controller\ConfigController:update }
|
||||
|
||||
app_config_delete:
|
||||
path: /admin/config/delete/{id}
|
||||
defaults: { _controller: App\Controller\ConfigController:delete }
|
||||
path: /admin/config/delete/{id}
|
||||
defaults: { _controller: App\Controller\ConfigController:delete }
|
||||
|
||||
app_config_logo:
|
||||
path: /admin/config/logo
|
||||
defaults: { _controller: App\Controller\ConfigController:logo }
|
||||
path: /admin/config/logo
|
||||
defaults: { _controller: App\Controller\ConfigController:logo }
|
||||
|
||||
#== Theme ================================================================================================================
|
||||
app_theme:
|
||||
path: /admin/theme
|
||||
defaults: { _controller: App\Controller\ThemeController:list }
|
||||
path: /admin/theme
|
||||
defaults: { _controller: App\Controller\ThemeController:list }
|
||||
|
||||
app_theme_select:
|
||||
path: /admin/theme/select/{name}
|
||||
defaults: { _controller: App\Controller\ThemeController:select, name: "" }
|
||||
path: /admin/theme/select/{name}
|
||||
defaults: { _controller: App\Controller\ThemeController:select, name: "" }
|
||||
|
||||
#== Sonde ================================================================================================================
|
||||
app_sonde:
|
||||
path: /sonde
|
||||
defaults: { _controller: App\Controller\SondeController:sonde }
|
||||
path: /sonde
|
||||
defaults: { _controller: App\Controller\SondeController:sonde }
|
||||
|
||||
#== Wss ==================================================================================================================
|
||||
app_wss_sample:
|
||||
path: /user/wss/sampble
|
||||
defaults: { _controller: App\Controller\WebsocketController:sample }
|
||||
path: /user/wss/sample
|
||||
defaults: { _controller: App\Controller\WebsocketController:sample }
|
||||
|
||||
#== Crop =================================================================================================================
|
||||
app_crop01:
|
||||
path: /user/crop01/{type}/{reportinput}
|
||||
defaults: { _controller: App\Controller\CropController:crop01 }
|
||||
path: /user/crop01/{type}/{reportinput}
|
||||
defaults: { _controller: App\Controller\CropController:crop01 }
|
||||
|
||||
app_crop02:
|
||||
path: /user/crop02/{type}/{reportinput}
|
||||
defaults: { _controller: App\Controller\CropController:crop02 }
|
||||
path: /user/crop02/{type}/{reportinput}
|
||||
defaults: { _controller: App\Controller\CropController:crop02 }
|
||||
|
||||
app_ckupload:
|
||||
path: /user/ckupload
|
||||
defaults: { _controller: App\Controller\CropController:ckupload }
|
||||
path: /user/ckupload
|
||||
defaults: { _controller: App\Controller\CropController:ckupload }
|
||||
|
||||
oneup_uploader:
|
||||
resource: .
|
||||
type: uploader
|
||||
resource: .
|
||||
type: uploader
|
||||
|
||||
#== Cron =================================================================================================================
|
||||
app_cron:
|
||||
path: /admin/cron
|
||||
defaults: { _controller: App\Controller\CronController:list }
|
||||
path: /admin/cron
|
||||
defaults: { _controller: App\Controller\CronController:list }
|
||||
|
||||
app_cron_ajax_list:
|
||||
path: /admin/cron/ajax/list
|
||||
defaults: { _controller: App\Controller\CronController:ajaxlist }
|
||||
path: /admin/cron/ajax/list
|
||||
defaults: { _controller: App\Controller\CronController:ajaxlist }
|
||||
|
||||
app_cron_update:
|
||||
path: /admin/cron/update/{id}
|
||||
defaults: { _controller: App\Controller\CronController:update }
|
||||
path: /admin/cron/update/{id}
|
||||
defaults: { _controller: App\Controller\CronController:update }
|
||||
|
||||
app_cron_exec:
|
||||
path: /admin/cron/exec/{id}
|
||||
defaults: { _controller: App\Controller\CronController:exec }
|
||||
path: /admin/cron/exec/{id}
|
||||
defaults: { _controller: App\Controller\CronController:exec }
|
||||
|
||||
app_cron_log:
|
||||
path: /admin/cron/log
|
||||
defaults: { _controller: App\Controller\CronController:log }
|
||||
path: /admin/cron/log
|
||||
defaults: { _controller: App\Controller\CronController:log }
|
||||
|
||||
app_cron_getlog:
|
||||
path: /admin/cron/getlog/{id}
|
||||
defaults: { _controller: App\Controller\CronController:getlog }
|
||||
path: /admin/cron/getlog/{id}
|
||||
defaults: { _controller: App\Controller\CronController:getlog }
|
||||
|
||||
#== User ========================================================================================================
|
||||
app_user:
|
||||
path: /admin/user
|
||||
defaults: { _controller: App\Controller\UserController:list }
|
||||
path: /admin/user
|
||||
defaults: { _controller: App\Controller\UserController:list }
|
||||
|
||||
app_user_update:
|
||||
path: /admin/user/update/{id}
|
||||
defaults: { _controller: App\Controller\UserController:update }
|
||||
path: /admin/user/update/{id}
|
||||
defaults: { _controller: App\Controller\UserController:update }
|
||||
|
||||
app_user_delete:
|
||||
path: /admin/user/delete/{id}
|
||||
defaults: { _controller: App\Controller\UserController:delete }
|
||||
path: /admin/user/delete/{id}
|
||||
defaults: { _controller: App\Controller\UserController:delete }
|
||||
|
||||
app_user_select:
|
||||
path: /user/user/select
|
||||
defaults: { _controller: App\Controller\UserController:select }
|
||||
path: /user/user/select
|
||||
defaults: { _controller: App\Controller\UserController:select }
|
||||
|
||||
app_user_info:
|
||||
path: /user/info
|
||||
defaults: { _controller: App\Controller\UserController:info }
|
||||
path: /user/info
|
||||
defaults: { _controller: App\Controller\UserController:info }
|
||||
|
||||
app_user_profil:
|
||||
path: /user/profil
|
||||
defaults: { _controller: App\Controller\UserController:profil }
|
||||
path: /user/profil
|
||||
defaults: { _controller: App\Controller\UserController:profil }
|
||||
|
||||
app_user_preference:
|
||||
path: /user/preference
|
||||
defaults: { _controller: App\Controller\UserController:preference }
|
||||
path: /user/preference
|
||||
defaults: { _controller: App\Controller\UserController:preference }
|
||||
|
||||
#== Group ========================================================================================================
|
||||
app_group:
|
||||
path: /admin/group
|
||||
defaults: { _controller: App\Controller\GroupController:list }
|
||||
path: /admin/group
|
||||
defaults: { _controller: App\Controller\GroupController:list }
|
||||
|
||||
app_group_submit:
|
||||
path: /admin/group/submit
|
||||
defaults: { _controller: App\Controller\GroupController:submit }
|
||||
path: /admin/group/submit
|
||||
defaults: { _controller: App\Controller\GroupController:submit }
|
||||
|
||||
app_group_update:
|
||||
path: /admin/group/update/{id}
|
||||
defaults: { _controller: App\Controller\GroupController:update }
|
||||
path: /admin/group/update/{id}
|
||||
defaults: { _controller: App\Controller\GroupController:update }
|
||||
|
||||
app_group_delete:
|
||||
path: /admin/group/delete/{id}
|
||||
defaults: { _controller: App\Controller\GroupController:delete }
|
||||
path: /admin/group/delete/{id}
|
||||
defaults: { _controller: App\Controller\GroupController:delete }
|
||||
|
||||
app_group_select:
|
||||
path: /user/group/select
|
||||
defaults: { _controller: App\Controller\GroupController:select }
|
||||
path: /user/group/select
|
||||
defaults: { _controller: App\Controller\GroupController:select }
|
||||
|
||||
#== Report =======================================================================================================
|
||||
app_report_list:
|
||||
path: /user/report/list/{id}
|
||||
defaults: { _controller: App\Controller\ReportController:list }
|
||||
path: /user/report/list/{id}
|
||||
defaults: { _controller: App\Controller\ReportController:list }
|
||||
|
||||
app_report_csv:
|
||||
path: /user/report/csv/{id}
|
||||
defaults: { _controller: App\Controller\ReportController:csv }
|
||||
path: /user/report/csv/{id}
|
||||
defaults: { _controller: App\Controller\ReportController:csv }
|
||||
|
||||
app_report_milestone:
|
||||
path: /user/report/milestone/{idscrum}/{mode}/{month}
|
||||
defaults: { _controller: App\Controller\ReportController:milestone }
|
||||
|
||||
app_report_test:
|
||||
path: /user/report/test/{id}
|
||||
defaults: { _controller: App\Controller\ReportController:test }
|
||||
path: /user/report/test/{id}
|
||||
defaults: { _controller: App\Controller\ReportController:test }
|
||||
|
||||
#== Scrum ========================================================================================================
|
||||
app_scrum:
|
||||
path: /user/scrum
|
||||
defaults: { _controller: App\Controller\ScrumController:list }
|
||||
|
||||
app_scrum_view:
|
||||
path: /user/scrum/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:view }
|
||||
path: /user/scrum
|
||||
defaults: { _controller: App\Controller\ScrumController:list }
|
||||
|
||||
app_scrum_submit:
|
||||
path: /master/scrum/submit
|
||||
defaults: { _controller: App\Controller\ScrumController:submit }
|
||||
|
||||
app_scrum_stat:
|
||||
path: /user/scrum/stat/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:stat }
|
||||
|
||||
app_scrum_info:
|
||||
path: /user/scrum/info/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:info }
|
||||
path: /master/scrum/submit
|
||||
defaults: { _controller: App\Controller\ScrumController:submit }
|
||||
|
||||
app_scrum_update:
|
||||
path: /master/scrum/update/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:update }
|
||||
path: /master/scrum/update/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:update }
|
||||
|
||||
app_scrum_delete:
|
||||
path: /master/scrum/delete/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:delete }
|
||||
path: /master/scrum/delete/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:delete }
|
||||
|
||||
app_scrum_view:
|
||||
path: /user/scrum/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:view }
|
||||
|
||||
app_scrum_table:
|
||||
path: /user/scrum/table/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:table }
|
||||
|
||||
app_scrum_stat:
|
||||
path: /user/scrum/stat/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:stat }
|
||||
|
||||
app_scrum_link:
|
||||
path: /user/scrum/link/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:link }
|
||||
|
||||
app_scrum_info:
|
||||
path: /user/scrum/info/{id}
|
||||
defaults: { _controller: App\Controller\ScrumController:info }
|
||||
|
||||
#== Scrumcolumn ========================================================================================================
|
||||
app_scrumcolumn_submit:
|
||||
path: /master/scrumcolumn/submit/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumcolumnController:submit }
|
||||
path: /master/scrumcolumn/submit/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumcolumnController:submit }
|
||||
|
||||
app_scrumcolumn_update:
|
||||
path: /master/scrumcolumn/update/{id}
|
||||
defaults: { _controller: App\Controller\ScrumcolumnController:update }
|
||||
path: /master/scrumcolumn/update/{id}
|
||||
defaults: { _controller: App\Controller\ScrumcolumnController:update }
|
||||
|
||||
app_scrumcolumn_delete:
|
||||
path: /master/scrumcolumn/delete/{id}
|
||||
defaults: { _controller: App\Controller\ScrumcolumnController:delete }
|
||||
path: /master/scrumcolumn/delete/{id}
|
||||
defaults: { _controller: App\Controller\ScrumcolumnController:delete }
|
||||
|
||||
app_scrumcolumn_select:
|
||||
path: /master/scrumcolumn/select/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumcolumnController:select }
|
||||
path: /master/scrumcolumn/select/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumcolumnController:select }
|
||||
|
||||
app_scrumcolumn_order:
|
||||
path: /master/scrumcolumn/order/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumcolumnController:order }
|
||||
|
||||
path: /master/scrumcolumn/order/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumcolumnController:order }
|
||||
|
||||
#== Scrumteam ========================================================================================================
|
||||
app_scrumteam_submit:
|
||||
path: /master/scrumteam/submit/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumteamController:submit }
|
||||
path: /master/scrumteam/submit/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumteamController:submit }
|
||||
|
||||
app_scrumteam_update:
|
||||
path: /master/scrumteam/update/{id}
|
||||
defaults: { _controller: App\Controller\ScrumteamController:update }
|
||||
path: /master/scrumteam/update/{id}
|
||||
defaults: { _controller: App\Controller\ScrumteamController:update }
|
||||
|
||||
app_scrumteam_delete:
|
||||
path: /master/scrumteam/delete/{id}
|
||||
defaults: { _controller: App\Controller\ScrumteamController:delete }
|
||||
path: /master/scrumteam/delete/{id}
|
||||
defaults: { _controller: App\Controller\ScrumteamController:delete }
|
||||
|
||||
app_scrumteam_select:
|
||||
path: /master/scrumteam/select/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumteamController:select }
|
||||
path: /master/scrumteam/select/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumteamController:select }
|
||||
|
||||
app_scrumteam_order:
|
||||
path: /master/scrumteam/order/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumteamController:order }
|
||||
|
||||
path: /master/scrumteam/order/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumteamController:order }
|
||||
|
||||
#== Scrumpriority ========================================================================================================
|
||||
app_scrumpriority_submit:
|
||||
path: /master/scrumpriority/submit/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumpriorityController:submit }
|
||||
path: /master/scrumpriority/submit/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumpriorityController:submit }
|
||||
|
||||
app_scrumpriority_update:
|
||||
path: /master/scrumpriority/update/{id}
|
||||
defaults: { _controller: App\Controller\ScrumpriorityController:update }
|
||||
path: /master/scrumpriority/update/{id}
|
||||
defaults: { _controller: App\Controller\ScrumpriorityController:update }
|
||||
|
||||
app_scrumpriority_delete:
|
||||
path: /master/scrumpriority/delete/{id}
|
||||
defaults: { _controller: App\Controller\ScrumpriorityController:delete }
|
||||
path: /master/scrumpriority/delete/{id}
|
||||
defaults: { _controller: App\Controller\ScrumpriorityController:delete }
|
||||
|
||||
app_scrumpriority_select:
|
||||
path: /master/scrumpriority/select/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumpriorityController:select }
|
||||
path: /master/scrumpriority/select/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumpriorityController:select }
|
||||
|
||||
app_scrumpriority_order:
|
||||
path: /master/scrumpriority/order/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumpriorityController:order }
|
||||
path: /master/scrumpriority/order/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumpriorityController:order }
|
||||
|
||||
#== Scrumsprint ========================================================================================================
|
||||
app_scrumsprint_submit:
|
||||
path: /master/scrumsprint/submit/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumsprintController:submit }
|
||||
|
||||
app_scrumsprint_update:
|
||||
path: /master/scrumsprint/update/{id}
|
||||
defaults: { _controller: App\Controller\ScrumsprintController:update }
|
||||
|
||||
app_scrumsprint_delete:
|
||||
path: /master/scrumsprint/delete/{id}
|
||||
defaults: { _controller: App\Controller\ScrumsprintController:delete }
|
||||
|
||||
app_scrumsprint_select:
|
||||
path: /master/scrumsprint/select/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumsprintController:select }
|
||||
|
||||
app_scrumsprint_order:
|
||||
path: /master/scrumsprint/order/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumsprintController:order }
|
||||
|
||||
#== Scrumtype ========================================================================================================
|
||||
app_scrumtype_submit:
|
||||
path: /master/scrumtype/submit/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumtypeController:submit }
|
||||
path: /master/scrumtype/submit/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumtypeController:submit }
|
||||
|
||||
app_scrumtype_update:
|
||||
path: /master/scrumtype/update/{id}
|
||||
defaults: { _controller: App\Controller\ScrumtypeController:update }
|
||||
path: /master/scrumtype/update/{id}
|
||||
defaults: { _controller: App\Controller\ScrumtypeController:update }
|
||||
|
||||
app_scrumtype_delete:
|
||||
path: /master/scrumtype/delete/{id}
|
||||
defaults: { _controller: App\Controller\ScrumtypeController:delete }
|
||||
path: /master/scrumtype/delete/{id}
|
||||
defaults: { _controller: App\Controller\ScrumtypeController:delete }
|
||||
|
||||
app_scrumtype_select:
|
||||
path: /master/scrumtype/select/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumtypeController:select }
|
||||
path: /master/scrumtype/select/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumtypeController:select }
|
||||
|
||||
app_scrumtype_order:
|
||||
path: /master/scrumtype/order/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumtypeController:order }
|
||||
path: /master/scrumtype/order/{scrumid}
|
||||
defaults: { _controller: App\Controller\ScrumtypeController:order }
|
||||
|
||||
#== Scrumissue ========================================================================================================
|
||||
app_scrumissue_change:
|
||||
path: /user/scrumissue/change
|
||||
defaults: { _controller: App\Controller\ScrumissueController:change }
|
||||
path: /user/scrumissue/change
|
||||
defaults: { _controller: App\Controller\ScrumissueController:change }
|
||||
|
||||
app_scrumissue_order:
|
||||
path: /user/scrumissue/order
|
||||
defaults: { _controller: App\Controller\ScrumissueController:order }
|
||||
path: /user/scrumissue/order
|
||||
defaults: { _controller: App\Controller\ScrumissueController:order }
|
||||
|
||||
app_scrumissue_info:
|
||||
path: /user/scrumissue/info
|
||||
defaults: { _controller: App\Controller\ScrumissueController:info }
|
||||
path: /user/scrumissue/info
|
||||
defaults: { _controller: App\Controller\ScrumissueController:info }
|
||||
|
||||
app_scrumissue_update:
|
||||
path: /user/scrumissue/update
|
||||
defaults: { _controller: App\Controller\ScrumissueController:update }
|
||||
path: /user/scrumissue/update
|
||||
defaults: { _controller: App\Controller\ScrumissueController:update }
|
||||
|
||||
app_scrumissue_block:
|
||||
path: /user/scrumissue/block
|
||||
defaults: { _controller: App\Controller\ScrumissueController:block }
|
||||
|
||||
app_scrumissue_unblock:
|
||||
path: /user/scrumissue/unblock
|
||||
defaults: { _controller: App\Controller\ScrumissueController:unblock }
|
||||
|
||||
app_scrumissue_color:
|
||||
path: /user/scrumissue/color
|
||||
defaults: { _controller: App\Controller\ScrumissueController:color }
|
||||
|
||||
app_scrumissue_assigne:
|
||||
path: /user/scrumissue/assigne
|
||||
defaults: { _controller: App\Controller\ScrumissueController:assigne }
|
||||
|
||||
app_scrumissue_notes:
|
||||
path: /user/scrumissue/notes
|
||||
defaults: { _controller: App\Controller\ScrumissueController:notes }
|
||||
|
||||
app_scrumissue_ctrlchange:
|
||||
path: /user/scrumissue/ctrlchange
|
||||
defaults: { _controller: App\Controller\ScrumissueController:ctrlchange }
|
||||
path: /user/scrumissue/ctrlchange
|
||||
defaults: { _controller: App\Controller\ScrumissueController:ctrlchange }
|
||||
|
||||
#== Issue ========================================================================================================
|
||||
app_issue:
|
||||
path: /user/issue
|
||||
defaults: { _controller: App\Controller\IssueController:list, id: 0 }
|
||||
app_scrumissue_view:
|
||||
path: /user/scrumissue/view/{id}
|
||||
defaults: { _controller: App\Controller\ScrumissueController:view }
|
||||
|
||||
app_issuescrum:
|
||||
path: /user/issuescrum/{id}
|
||||
defaults: { _controller: App\Controller\IssueController:list }
|
||||
#== Poker =============================================================================================================
|
||||
app_poker_get:
|
||||
path: /user/poker/{userid}/{issueid}
|
||||
defaults: { _controller: App\Controller\ScrumissueController:getpoker }
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
parameters:
|
||||
appEnv: '%env(resolve:APP_ENV)%'
|
||||
appSecret: '%env(resolve:APP_SECRET)%'
|
||||
appProtocol: '%env(resolve:APP_PROTOCOL)%'
|
||||
|
||||
appWeburl: '%env(resolve:APP_WEBURL)%'
|
||||
appAuth: '%env(resolve:APP_AUTH)%'
|
||||
|
@ -33,7 +34,7 @@ parameters:
|
|||
|
||||
wssuse: '%env(resolve:WSS_USE)%'
|
||||
wssport: '%env(resolve:WSS_PORT)%'
|
||||
wssurl: 'wss://%env(resolve:APP_WEBURL)%/wss%env(resolve:APP_ALIAS)%'
|
||||
wssurl: '%env(resolve:WSS_URL)%'
|
||||
|
||||
proxyUse: '%env(resolve:PROXY_USE)%'
|
||||
proxyHost: '%env(resolve:PROXY_HOST)%'
|
||||
|
@ -104,3 +105,8 @@ services:
|
|||
public: true
|
||||
class: App\Service\giteaService
|
||||
arguments: ["@session","%giteaUrl%"]
|
||||
|
||||
App\Websocket\MessageHandler:
|
||||
public: true
|
||||
arguments:
|
||||
- "@service_container"
|
|
@ -17,13 +17,29 @@ services:
|
|||
|
||||
ninegitea:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./misc/docker/Dockerfile
|
||||
context: .
|
||||
dockerfile: ./misc/docker/Dockerfile
|
||||
container_name: ninegitea-app
|
||||
image: reg.cadoles.com/envole/ninegitea
|
||||
ports:
|
||||
- "8000:80"
|
||||
- "8005:80"
|
||||
- "5588:5588"
|
||||
volumes:
|
||||
- ./src:/app/src:delegated
|
||||
- ./templates:/app/templates:delegated
|
||||
- ./config:/app/config:delegated
|
||||
- ./.env:/app/.env:delegated
|
||||
- ./public/uploads:/app/public/uploads:delegated
|
||||
- ./misc:/app/misc:delegated
|
||||
|
||||
adminer:
|
||||
image: adminer
|
||||
container_name: ninegitea-adminer
|
||||
restart: always
|
||||
ports:
|
||||
- 6081:8080
|
||||
|
||||
volumes:
|
||||
mariadb-data:
|
||||
|
||||
|
||||
|
|
|
@ -12,4 +12,6 @@ composer install --no-interaction
|
|||
|
||||
bin/console d:s:u --force --complete
|
||||
|
||||
bin/console app:Websocket &
|
||||
|
||||
exec $@
|
|
@ -11,7 +11,10 @@ class HomeController extends AbstractController
|
|||
{
|
||||
public function home()
|
||||
{
|
||||
return $this->redirectToRoute("app_scrum");
|
||||
if($this->getUser())
|
||||
return $this->redirectToRoute("app_scrum");
|
||||
else
|
||||
return $this->redirectToRoute("app_login");
|
||||
}
|
||||
|
||||
public function admin()
|
||||
|
|
|
@ -1,212 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
|
||||
use App\Service\giteaService;
|
||||
|
||||
class IssueController extends AbstractController
|
||||
{
|
||||
private $appKernel;
|
||||
private $data = "issue";
|
||||
private $route = "app_issue";
|
||||
private $render = "Issue/";
|
||||
private $entity = "App:Issue";
|
||||
|
||||
public function __construct(KernelInterface $appKernel,giteaService $giteaservice) {
|
||||
$this->appKernel = $appKernel;
|
||||
$this->giteaservice = $giteaservice;
|
||||
}
|
||||
|
||||
public function list($id, Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$fgcsv = $request->get("fgcsv");
|
||||
|
||||
// Récupérer les repos de gitea
|
||||
if($id==0) $scrums=$em->getRepository("App:Scrum")->findBy([],["name"=>"ASC"]);
|
||||
else $scrums=$em->getRepository("App:Scrum")->findBy(["id"=>$id],["name"=>"ASC"]);
|
||||
|
||||
$giteacategorys=[];
|
||||
$gitearepos=[];
|
||||
$giteamilestones=[];
|
||||
$giteacolumns=[];
|
||||
$giteateams=[];
|
||||
$giteaprioritys=[];
|
||||
$giteatypes=[];
|
||||
$gitealabels=[];
|
||||
$giteaassignees=$em->getRepository("App:User")->findBy([],["username"=>"ASC"]);
|
||||
$viewclosed = $request->getSession()->get("viewclosed");
|
||||
|
||||
foreach($scrums as $key => $scrum) {
|
||||
if(!in_array($scrum->getCategory(),$giteacategorys))
|
||||
array_push($giteacategorys,$scrum->getCategory());
|
||||
|
||||
$gitearepo=$this->giteaservice->getRepo($scrum->getGiteajson()["id"]);
|
||||
if(!$gitearepo) die("Probleme de connexion avec gitea veuillez vous <a href='/ninegitea/logout'>reconnecter</a>");
|
||||
|
||||
if($gitearepo->updated_at!=$scrum->getGiteajson()["updated_at"]||$gitearepo->open_issues_count!=$scrum->getGiteajson()["open_issues_count"]) {
|
||||
$scrum->setGiteajson(json_decode(json_encode($gitearepo), true));
|
||||
$em->persist($scrum);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
if($gitearepo->open_issues_count>0) {
|
||||
$giteatmp=$this->giteaservice->getMilestones($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],"?state=".($viewclosed=="true"?"all":"open"));
|
||||
foreach($giteatmp as $key => $value) {
|
||||
$giteatmp[$key]->title = $scrum->getGiteajson()["full_name"]. " = ".$giteatmp[$key]->title;
|
||||
}
|
||||
array_push($giteatmp,["id"=>$scrum->getGiteajson()["full_name"],"title"=> $scrum->getGiteajson()["full_name"]. " = Aucun Jalon"]);
|
||||
$giteamilestones=array_merge($giteamilestones,$giteatmp);
|
||||
|
||||
$giteaissues=$this->giteaservice->getIssues($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],"?state=".($viewclosed=="true"?"all":"open"));
|
||||
$json=$scrum->getGiteajson();
|
||||
$json["issues"]=$giteaissues;
|
||||
$json["category"]=$scrum->getCategory();
|
||||
foreach($json["issues"] as $key => $giteaissue) {
|
||||
$issue=$em->getRepository("App:Scrumissue")->findOneBy(["giteaid"=>$giteaissue->id]);
|
||||
if($issue) {
|
||||
$json["issues"][$key]->weight=$issue->getWeight();
|
||||
$json["issues"][$key]->issueid=$issue->getId();
|
||||
$json["issues"][$key]->scrumid=$issue->getScrum()->getId();
|
||||
}
|
||||
else {
|
||||
$json["issues"][$key]->weight=0;
|
||||
$json["issues"][$key]->issueid=0;
|
||||
$json["issues"][$key]->scrumid=0;
|
||||
}
|
||||
}
|
||||
|
||||
$tmp=[];
|
||||
foreach($scrum->getScrumcolumns() as $column) {
|
||||
array_push($tmp,$column->getGiteaid());
|
||||
if(!in_array($column->getGiteajson()["name"],$giteacolumns))
|
||||
array_push($giteacolumns,$column->getGiteajson()["name"]);
|
||||
}
|
||||
$json["columns"]=$tmp;
|
||||
array_push($gitearepos,$json);
|
||||
|
||||
foreach($scrum->getScrumteams() as $team) {
|
||||
if(!in_array($team->getGiteajson()["name"],$giteateams))
|
||||
array_push($giteateams,$team->getGiteajson()["name"]);
|
||||
}
|
||||
|
||||
foreach($scrum->getScrumprioritys() as $priority) {
|
||||
if(!in_array($priority->getGiteajson()["name"],$giteaprioritys))
|
||||
array_push($giteaprioritys,$priority->getGiteajson()["name"]);
|
||||
}
|
||||
|
||||
foreach($scrum->getScrumtypes() as $type) {
|
||||
if(!in_array($type->getGiteajson()["name"],$giteatypes))
|
||||
array_push($giteatypes,$type->getGiteajson()["name"]);
|
||||
}
|
||||
|
||||
foreach($giteaissues as $giteaissue) {
|
||||
foreach($giteaissue->labels as $label) {
|
||||
if(!in_array($label->name,$gitealabels))
|
||||
array_push($gitealabels,$label->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$keysort = array_column($giteamilestones, 'title');
|
||||
array_multisort($keysort, SORT_DESC, $giteamilestones);
|
||||
sort($giteacolumns);
|
||||
sort($giteateams);
|
||||
sort($giteaprioritys);
|
||||
sort($giteatypes);
|
||||
sort($gitealabels);
|
||||
sort($giteacategorys);
|
||||
|
||||
// Préférences utilisateur
|
||||
$filtercategorys = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtercategorys",$id);
|
||||
$filterrepos = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterrepos",$id);
|
||||
$filtermilestones = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtermilestones",$id);
|
||||
$filtercolumns = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtercolumns",$id);
|
||||
$filterteams = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterteams",$id);
|
||||
$filterprioritys = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterprioritys",$id);
|
||||
$filtertypes = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtertypes",$id);
|
||||
$filterlabels = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterlabels",$id);
|
||||
$filterassignees = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterassignees",$id);
|
||||
$filterexcludes = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterexcludes",$id);
|
||||
$showfilters = $em->getRepository("App:User")->getUserpreference($this->getUser(),"showfilters",$id);
|
||||
|
||||
if($fgcsv) {
|
||||
$dir = $this->appKernel->getProjectDir() . '/uploads/issues/';
|
||||
$file = "issues-".$id.".csv";
|
||||
$fs = new Filesystem();
|
||||
$fs->mkdir($dir);
|
||||
$csvh = fopen($dir.$file, 'w');
|
||||
$d = ';'; // this is the default but i like to be explicit
|
||||
$e = '"'; // this is the default but i like to be explicit
|
||||
|
||||
$tmp=["Projet","Jalon","Type","Id","Titre","Statut","Label"];
|
||||
fputcsv($csvh, $tmp, $d, $e);
|
||||
|
||||
foreach($gitearepos as $gitearepo) {
|
||||
foreach($gitearepo["issues"] as $giteaissue) {
|
||||
$statut="";
|
||||
$type="";
|
||||
$labels="";
|
||||
foreach($giteaissue->labels as $label) {
|
||||
if(in_array($label->id,$gitearepo["columns"]))
|
||||
$statut=$label->name;
|
||||
elseif(in_array($label->name,$giteatypes))
|
||||
$type=$label->name;
|
||||
else
|
||||
$labels=$labels.($labels!=""?"\n":"").$label->name;
|
||||
}
|
||||
$tmp=[
|
||||
$gitearepo["name"],
|
||||
(isset($giteaissue->milestone->title)?$giteaissue->milestone->title:""),
|
||||
$type,
|
||||
$giteaissue->number,
|
||||
$giteaissue->title,
|
||||
$statut,
|
||||
$labels
|
||||
];
|
||||
fputcsv($csvh, $tmp, $d, $e);
|
||||
}
|
||||
}
|
||||
fclose($csvh);
|
||||
|
||||
$response = new BinaryFileResponse($dir.$file);
|
||||
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $this->render($this->render.'list.html.twig',[
|
||||
"useheader" => true,
|
||||
"usesidebar" => false,
|
||||
"id" => $id,
|
||||
"giteacategorys" => $giteacategorys,
|
||||
"gitearepos" => $gitearepos,
|
||||
"giteamilestones" => $giteamilestones,
|
||||
"giteacolumns" => $giteacolumns,
|
||||
"giteateams" => $giteateams,
|
||||
"giteaprioritys" => $giteaprioritys,
|
||||
"giteatypes" => $giteatypes,
|
||||
"gitealabels" => $gitealabels,
|
||||
"giteaassignees" => $giteaassignees,
|
||||
"filtercategorys" => $filtercategorys,
|
||||
"filterrepos" => $filterrepos,
|
||||
"filtermilestones" => $filtermilestones,
|
||||
"filtercolumns" => $filtercolumns,
|
||||
"filterteams" => $filterteams,
|
||||
"filterprioritys" => $filterprioritys,
|
||||
"filtertypes" => $filtertypes,
|
||||
"filterlabels" => $filterlabels,
|
||||
"filterexcludes" => $filterexcludes,
|
||||
"filterassignees" => $filterassignees,
|
||||
"showfilters" => $showfilters,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,9 @@ use App\Service\giteaService;
|
|||
|
||||
class ReportController extends AbstractController
|
||||
{
|
||||
private KernelInterface $appKernel;
|
||||
private giteaService $giteaservice;
|
||||
|
||||
public function __construct(KernelInterface $appKernel, giteaService $giteaservice) {
|
||||
$this->appKernel = $appKernel;
|
||||
$this->giteaservice = $giteaservice;
|
||||
|
@ -114,6 +117,80 @@ class ReportController extends AbstractController
|
|||
|
||||
}
|
||||
|
||||
public function milestone($idscrum,$mode,$month,Request $request) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$scrum = $em->getRepository("App:Scrum")->find($idscrum);
|
||||
$datestart=new \DateTime($month."01");
|
||||
$dateend=new \DateTime($month."31");
|
||||
|
||||
$repoid = $scrum->getGiteaid();
|
||||
$repoowner = $scrum->getGiteajson()["owner"]["login"];
|
||||
$reponame = $scrum->getGiteajson()["name"];
|
||||
|
||||
//$scrumissues = $em->getRepository("App:Scrumissue")->findBy(["scrum"=>$scrum,"giteastate"=>"open"],["giteamilestonename"=>"ASC","rowid"=>"DESC"]);
|
||||
$scrumissues = $em->getRepository("App:Scrumissue")->findBy(["scrum"=>$scrum],["giteamilestonename"=>"ASC","rowid"=>"DESC"]);
|
||||
|
||||
$reportissues=[];
|
||||
foreach($scrumissues as $scrumissue) {
|
||||
$labels=array_column($scrumissue->getGiteajson()["labels"], 'name');
|
||||
$update=new \DateTime($scrumissue->getGiteajson()["updated_at"]);
|
||||
$close=new \DateTime($scrumissue->getGiteajson()["closed_at"]);
|
||||
//"created_at" => "2024-05-03T15:09:26+02:00"
|
||||
//"updated_at" => "2024-05-03T16:02:00+02:00"
|
||||
//"closed_at" => "2024-05-03T16:01:59+02:00"
|
||||
|
||||
//if(in_array("Type/Scénario",$labels)&&in_array("Statut/Backlog",$labels)) {
|
||||
//if(in_array("Type/Scénario",$labels)) {
|
||||
|
||||
// Dans le cas d'un report Propal on ne prend que les tickets ouvert de type scénario du backlog
|
||||
$ok=false;
|
||||
|
||||
if($mode=="Propal") {
|
||||
if(in_array("Type/Scénario",$labels)&&in_array("Statut/Backlog",$labels)&&$scrumissue->getGiteastate()=="open") {
|
||||
$ok=true;
|
||||
}
|
||||
}
|
||||
|
||||
// Dans le cas d'un report PV on prend tout les tickets avec une date de modification ou de cloture dans le mois
|
||||
if($mode=="PV") {
|
||||
$isstatut=false;
|
||||
$isupdate=false;
|
||||
$isclose=false;
|
||||
|
||||
if(in_array("Statut/Livré PREPROD",$labels) || in_array("Statut/A Livrer PROD",$labels) || in_array("Statut/Livré PROD",$labels)) {
|
||||
$isstatut=true;
|
||||
}
|
||||
|
||||
if(!empty($close)&&$close>=$datestart&&$close<=$dateend) $isclose=true;
|
||||
if($update>=$datestart&&$update<=$dateend) $isupdate=true;
|
||||
|
||||
if($isstatut&&($isclose||$isupdate)) $ok=true;
|
||||
}
|
||||
|
||||
if(!$ok) continue;
|
||||
|
||||
$tmp= [
|
||||
"id" => $scrumissue->getGiteanumber(),
|
||||
"title" => $scrumissue->getGiteatitle(),
|
||||
"milestone" => ($scrumissue->getGiteamilestonename()??"Aucun"),
|
||||
"statutorder" => $scrumissue->getScrumcolumn()->getRowid(),
|
||||
"statut" => $scrumissue->getScrumcolumn()->getName(),
|
||||
"issueorder" => $scrumissue->getRowid(),
|
||||
];
|
||||
array_push($reportissues,$tmp);
|
||||
}
|
||||
|
||||
$statutsort = array_column($reportissues,"statutorder");
|
||||
$issuesort = array_column($reportissues,"statutorder");
|
||||
$milestonesort = array_column($reportissues,"milestone");
|
||||
array_multisort($statutsort, SORT_ASC, $milestonesort, SORT_ASC, $issuesort, SORT_ASC, $reportissues);
|
||||
|
||||
return $this->render('Report/milestone.html.twig', [
|
||||
'useheader' => true,
|
||||
'issues' => $reportissues,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test($id,Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
|
|
@ -4,9 +4,10 @@ namespace App\Controller;
|
|||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Form\FormError;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
|
||||
use App\Entity\Scrum as Entity;
|
||||
use App\Entity\Scrumissue as Scrumissue;
|
||||
|
@ -20,6 +21,7 @@ class ScrumController extends AbstractController
|
|||
private $route = "app_scrum";
|
||||
private $render = "Scrum/";
|
||||
private $entity = "App:Scrum";
|
||||
private $giteaservice;
|
||||
|
||||
public function __construct(giteaService $giteaservice) { $this->giteaservice = $giteaservice; }
|
||||
|
||||
|
@ -28,6 +30,8 @@ class ScrumController extends AbstractController
|
|||
$em = $this->getDoctrine()->getManager();
|
||||
$scrums = $em->getRepository($this->entity)->findByUser($this->getUser());
|
||||
|
||||
$this->giteaservice->needrefresh();
|
||||
|
||||
$giteacategorys=[];
|
||||
$gitearepos=[];
|
||||
|
||||
|
@ -175,14 +179,223 @@ class ScrumController extends AbstractController
|
|||
$em = $this->getDoctrine()->getManager();
|
||||
$data=$em->getRepository($this->entity)->find($id);
|
||||
if(!$data) return $this->redirectToRoute($this->route);
|
||||
$firstcolumn=$em->getRepository('App:Scrumcolumn')->findOneBy(["scrum"=>$data], ['rowid' => 'ASC']);
|
||||
if(!$firstcolumn) return $this->redirectToRoute($this->route);
|
||||
|
||||
$forcereload=false;
|
||||
if($request->get("forcereload")) $forcereload=$request->get("forcereload");
|
||||
|
||||
// Mise à jour des issues par rapport à gitea
|
||||
$em->getRepository("App:Scrum")->getGitea($data,$giteaassignees,$giteacolumns,$giteamilestones,$giteateams,$giteaprioritys,$giteatypes,$gitealabels,$forcereload);
|
||||
|
||||
// default color priority
|
||||
$prioritycolor="#70c24a";
|
||||
if(is_array($giteaprioritys)) {
|
||||
|
||||
$priority=$em->getRepository("App:Scrumpriority")->findOneBy(["scrum"=>$data,"giteaid"=>$giteaprioritys[array_key_last($giteaprioritys)]]);
|
||||
if($priority) {
|
||||
$prioritycolor="#".$priority->getGiteajson()["color"];
|
||||
}
|
||||
}
|
||||
|
||||
// Création du tableau des issues
|
||||
$issues=$data->getScrumissues();
|
||||
$tbissues=[];
|
||||
$tbcols=[];
|
||||
$tbjals=[];
|
||||
$tbsprs=[];
|
||||
$tbestim=[];
|
||||
|
||||
$viewclosed = $this->get('session')->get("viewclosed");
|
||||
foreach($issues as $issue) {
|
||||
// bypass closed
|
||||
if($viewclosed=="false"&&($issue->getGiteastate()=="closed"||($issue->getScrumsprint()&&$issue->getScrumsprint()->getClosed()))) continue;
|
||||
|
||||
// Ids
|
||||
$idcol=($issue->getScrumcolumn()?$issue->getScrumcolumn()->getId():$firstcolumn->getId());
|
||||
$idjal=($issue->getGiteamilestone()?$issue->getGiteamilestone():-100);
|
||||
$idspr=($issue->getScrumsprint()?$issue->getScrumsprint()->getId():-100);
|
||||
|
||||
// Roworders
|
||||
$rowcol=($issue->getScrumcolumn()?$issue->getScrumcolumn()->getRowid():$firstcolumn->getRowid());
|
||||
$rowjal=($issue->getGiteaMilestonename()?$issue->getGiteaMilestonename():-100);
|
||||
$rowspr=($issue->getScrumsprint()?$issue->getScrumsprint()->getRowid():-100);
|
||||
|
||||
// Names
|
||||
$nmcol=($issue->getScrumcolumn()?$issue->getScrumcolumn()->getName():$firstcolumn->getName());
|
||||
$nmjal=($issue->getGiteaMilestonename()?$issue->getGiteaMilestonename():"Aucun");
|
||||
$nmspr=($issue->getScrumsprint()?$issue->getScrumsprint()->getName():"Aucun");
|
||||
|
||||
// Idgiteas
|
||||
$gicol=($issue->getScrumcolumn()?$issue->getScrumcolumn()->getGiteaid():$firstcolumn->getGiteaid());
|
||||
$gijal=($issue->getGiteaMilestone()?$issue->getGiteaMilestone():-100);
|
||||
|
||||
// Liste des colonnes/jalons/sprint avec des issues
|
||||
if(!in_array($idcol,$tbcols)) array_push($tbcols,$idcol);
|
||||
if(!in_array($idcol."|".$idjal,$tbjals)) array_push($tbjals,$idcol."|".$idjal);
|
||||
if(!in_array($idcol."|".$idjal."|".$idspr,$tbsprs)) array_push($tbsprs,$idcol."|".$idjal."|".$idspr);
|
||||
|
||||
// Initialisation du tableau des estimations
|
||||
if(!array_key_exists($idjal,$tbestim)) {
|
||||
$tbestim[$idjal] = [
|
||||
"rowjal" => $rowjal,
|
||||
"idjal" => $idjal,
|
||||
"nmjal" => $nmjal,
|
||||
"gijal" => $gijal,
|
||||
"nbjrs" => 0,
|
||||
"sprints" => []
|
||||
];
|
||||
}
|
||||
|
||||
if(!array_key_exists($idspr,$tbestim[$idjal]["sprints"])) {
|
||||
$tbestim[$idjal]["sprints"][$idspr] = [
|
||||
"rowspr" => $rowspr,
|
||||
"idspr" => $idspr,
|
||||
"nmspr" => $nmspr,
|
||||
"nbjrs" => 0,
|
||||
];
|
||||
}
|
||||
|
||||
// Initialisation du tableau des colonnes
|
||||
if(!array_key_exists($idcol,$tbissues)) {
|
||||
$tbissues[$idcol]=[
|
||||
"rowcol" => $rowcol,
|
||||
"idcol" => $idcol,
|
||||
"nmcol" => $nmcol,
|
||||
"gicol" => $gicol,
|
||||
"nbjrs" => 0,
|
||||
"jalons" => [],
|
||||
];
|
||||
}
|
||||
|
||||
// Initialisation du tableau des jalons de la colonne encours
|
||||
if(!array_key_exists($idjal,$tbissues[$idcol]["jalons"])) {
|
||||
$tbissues[$idcol]["jalons"][$idjal] = [
|
||||
"rowjal" => $rowjal,
|
||||
"idjal" => $idjal,
|
||||
"nmjal" => $nmjal,
|
||||
"gijal" => $gijal,
|
||||
"nbjrs" => 0,
|
||||
"sprints" => [],
|
||||
];
|
||||
}
|
||||
|
||||
// Initialisation du tableau des sprint de la colonne/jalon encours
|
||||
if(!array_key_exists($idspr,$tbissues[$idcol]["jalons"][$idjal]["sprints"])) {
|
||||
$tbissues[$idcol]["jalons"][$idjal]["sprints"][$idspr] = [
|
||||
"rowspr" => $rowspr,
|
||||
"idspr" => $idspr,
|
||||
"nmspr" => $nmspr,
|
||||
"nbjrs" => 0,
|
||||
"issues" => [],
|
||||
];
|
||||
}
|
||||
|
||||
// On cumule les estimations
|
||||
$tbissues[$idcol]["nbjrs"]+=$issue->getWeight();
|
||||
$tbissues[$idcol]["jalons"][$idjal]["nbjrs"]+=$issue->getWeight();
|
||||
$tbissues[$idcol]["jalons"][$idjal]["sprints"][$idspr]["nbjrs"]+=$issue->getWeight();
|
||||
$tbestim[$idjal]["nbjrs"]+=$issue->getWeight();
|
||||
$tbestim[$idjal]["sprints"][$idspr]["nbjrs"]+=$issue->getWeight();
|
||||
|
||||
// On sauvegarde l'issue
|
||||
array_push($tbissues[$idcol]["jalons"][$idjal]["sprints"][$idspr]["issues"],$issue);
|
||||
}
|
||||
|
||||
// On ajoute les colonnes sans issues
|
||||
$columns=$data->getScrumcolumns();
|
||||
foreach($columns as $column) {
|
||||
if(!in_array($column->getId(),$tbcols)) {
|
||||
$tbissues[$column->getId()] = [
|
||||
"rowcol" => $column->getRowid(),
|
||||
"idcol" => $column->getId(),
|
||||
"nmcol" => $column->getName(),
|
||||
"gicol" => $column->getGiteaid(),
|
||||
"nbjrs" => 0,
|
||||
"jalons" => [],
|
||||
];
|
||||
}
|
||||
|
||||
// On ajoute les jalons sans issues
|
||||
foreach($giteamilestones as $milestone) {
|
||||
if(!in_array($column->getId()."|".$milestone->id,$tbjals)) {
|
||||
$tbissues[$column->getId()]["jalons"][$milestone->id] = [
|
||||
"rowjal" => $milestone->title,
|
||||
"idjal" => $milestone->id,
|
||||
"nmjal" => $milestone->title,
|
||||
"gijal" => $milestone->id,
|
||||
"nbjrs" => 0,
|
||||
"sprints" => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// On ajoute le jalon aucun si sans issue
|
||||
if(!in_array($column->getId()."|-100",$tbjals)) {
|
||||
$tbissues[$column->getId()]["jalons"][-100] = [
|
||||
"rowjal" => -100,
|
||||
"idjal" => -100,
|
||||
"nmjal" => "Aucun",
|
||||
"gijal" => null,
|
||||
"nbjrs" => 0,
|
||||
"sprints" => [],
|
||||
];
|
||||
}
|
||||
|
||||
// On ajoutes les sprints sans issues
|
||||
foreach($tbissues[$column->getId()]["jalons"] as $jalon) {
|
||||
|
||||
$sprints=$em->getRepository("App:Scrumsprint")->findBy(["scrum"=>$data,"giteamilestone"=>$jalon["idjal"]]);
|
||||
foreach($sprints as $sprint) {
|
||||
if($viewclosed=="false"&&$sprint->getClosed()) continue;
|
||||
|
||||
if(!in_array($column->getId()."|".$jalon["idjal"]."|".$sprint->getId(),$tbsprs)) {
|
||||
$tbissues[$column->getId()]["jalons"][$jalon["idjal"]]["sprints"][$sprint->getId()] = [
|
||||
"rowspr" => $sprint->getRowid(),
|
||||
"idspr" => $sprint->getId(),
|
||||
"nmspr" => $sprint->getName(),
|
||||
"nbjrs" => 0,
|
||||
"issues" => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// On ajoute les sprint aucun sans issue
|
||||
if(!in_array($column->getId()."|".$jalon["idjal"]."|-100",$tbsprs)) {
|
||||
$tbissues[$column->getId()]["jalons"][$jalon["idjal"]]["sprints"][-100] = [
|
||||
"rowspr" => -100,
|
||||
"idspr" => -100,
|
||||
"nmspr" => "Aucun",
|
||||
"nbjrs" => 0,
|
||||
"issues" => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tri des issues par colonne/jalon/sprint/issue
|
||||
$rowcol = array_column($tbissues, 'rowcol');
|
||||
array_multisort($rowcol, SORT_ASC, $tbissues);
|
||||
foreach($tbissues as $keycol=>$column) {
|
||||
$rowjal = array_column($tbissues[$keycol]["jalons"], 'rowjal');
|
||||
array_multisort($rowjal, SORT_DESC, $tbissues[$keycol]["jalons"]);
|
||||
foreach($tbissues[$keycol]["jalons"] as $keyjal=>$jalon) {
|
||||
$rowspr = array_column($tbissues[$keycol]["jalons"][$keyjal]["sprints"], 'rowspr');
|
||||
array_multisort($rowspr, SORT_DESC, $tbissues[$keycol]["jalons"][$keyjal]["sprints"]);
|
||||
}
|
||||
}
|
||||
|
||||
$rowjal = array_column($tbestim, 'rowjal');
|
||||
array_multisort($rowjal, SORT_DESC, $tbestim);
|
||||
foreach($tbestim as $keyjal=>$jalon) {
|
||||
$rowspr = array_column($tbestim[$keyjal]["sprints"], 'rowspr');
|
||||
array_multisort($rowspr, SORT_DESC, $tbestim[$keyjal]["sprints"]);
|
||||
}
|
||||
|
||||
// Préférences utilisateur
|
||||
$viewcondensed = $em->getRepository("App:User")->getUserpreference($this->getUser(),"viewcondensed",$id);
|
||||
$filtermilestones = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtermilestones",$id);
|
||||
$filtersprints = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtersprints",$id);
|
||||
$filterteams = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterteams",$id);
|
||||
$filterprioritys = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterprioritys",$id);
|
||||
$filtertypes = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtertypes",$id);
|
||||
|
@ -191,6 +404,11 @@ class ScrumController extends AbstractController
|
|||
$filterexcludes = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterexcludes",$id);
|
||||
$showfilters = $em->getRepository("App:User")->getUserpreference($this->getUser(),"showfilters",$id);
|
||||
|
||||
// Me demandez pas pourquoi mais j'ai un décallage de 30mn
|
||||
$updatedate=$data->getUpdatedate();
|
||||
$updatedate->setTimezone(new \DateTimeZone("UTC"));
|
||||
$updatedate->add(new \DateInterval("PT30M"));
|
||||
|
||||
return $this->render($this->render.'view.html.twig', [
|
||||
'useheader' => true,
|
||||
'usesidebar' => false,
|
||||
|
@ -198,11 +416,15 @@ class ScrumController extends AbstractController
|
|||
'giteaassignees' => $giteaassignees,
|
||||
'giteacolumns' => $giteacolumns,
|
||||
'giteamilestones' => $giteamilestones,
|
||||
'sprints' => $data->getScrumsprintstosee($viewclosed),
|
||||
'giteateams' => $giteateams,
|
||||
'giteaprioritys' => $giteaprioritys,
|
||||
'prioritycolor' => $prioritycolor,
|
||||
'giteatypes' => $giteatypes,
|
||||
'gitealabels' => $gitealabels,
|
||||
'viewcondensed' => $viewcondensed,
|
||||
'filtermilestones' => $filtermilestones,
|
||||
'filtersprints' => $filtersprints,
|
||||
'filterteams' => $filterteams,
|
||||
'filterprioritys' => $filterprioritys,
|
||||
'filtertypes' => $filtertypes,
|
||||
|
@ -210,141 +432,418 @@ class ScrumController extends AbstractController
|
|||
'filterassignees' => $filterassignees,
|
||||
'filterexcludes' => $filterexcludes,
|
||||
'showfilters' => $showfilters,
|
||||
'tbissues' => $tbissues,
|
||||
'tbestim' => $tbestim,
|
||||
'updatedate' => $updatedate,
|
||||
$this->data => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
public function table($id, Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$fgcsv = $request->get("fgcsv");
|
||||
$fgpoker = $request->get("fgpoker");
|
||||
|
||||
// Récupérer les repos de gitea
|
||||
$scrum=$em->getRepository("App:Scrum")->findOneBy(["id"=>$id]);
|
||||
|
||||
$gitearepos=[];
|
||||
$giteamilestones=[];
|
||||
$giteacolumns=[];
|
||||
$giteateams=[];
|
||||
$giteaprioritys=[];
|
||||
$giteatypes=[];
|
||||
$gitealabels=[];
|
||||
$giteaassignees=$em->getRepository("App:User")->findBy([],["username"=>"ASC"]);
|
||||
$viewclosed = $request->getSession()->get("viewclosed");
|
||||
|
||||
|
||||
$gitearepo=$this->giteaservice->getRepo($scrum->getGiteajson()["id"]);
|
||||
if($gitearepo->updated_at!=$scrum->getGiteajson()["updated_at"]||$gitearepo->open_issues_count!=$scrum->getGiteajson()["open_issues_count"]) {
|
||||
$scrum->setGiteajson(json_decode(json_encode($gitearepo), true));
|
||||
$em->persist($scrum);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
$giteamilestones=$this->giteaservice->getMilestones($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],"?state=".($viewclosed=="true"?"all":"open"));
|
||||
|
||||
$giteaissues=$this->giteaservice->getIssues($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],"?state=".($viewclosed=="true"?"all":"open"));
|
||||
$json=$scrum->getGiteajson();
|
||||
$json["issues"]=$giteaissues;
|
||||
foreach($json["issues"] as $key => $giteaissue) {
|
||||
$issue=$em->getRepository("App:Scrumissue")->findOneBy(["giteaid"=>$giteaissue->id]);
|
||||
if($issue) {
|
||||
$json["issues"][$key]->weight=$issue->getWeight();
|
||||
$json["issues"][$key]->issueid=$issue->getId();
|
||||
$json["issues"][$key]->scrumid=$issue->getScrum()->getId();
|
||||
$json["issues"][$key]->sprintid=($issue->getScrumsprint()?$issue->getScrumsprint()->getId():-100);
|
||||
$json["issues"][$key]->sprintname=($issue->getScrumsprint()?$issue->getScrumsprint()->getName():"Aucun");
|
||||
}
|
||||
else {
|
||||
$json["issues"][$key]->weight=0;
|
||||
$json["issues"][$key]->issueid=0;
|
||||
$json["issues"][$key]->scrumid=0;
|
||||
$json["issues"][$key]->sprintid=-100;
|
||||
$json["issues"][$key]->sprintname="Aucun";
|
||||
}
|
||||
}
|
||||
|
||||
$tmp=[];
|
||||
foreach($scrum->getScrumcolumns() as $column) {
|
||||
array_push($tmp,$column->getGiteaid());
|
||||
if(!in_array($column->getGiteajson()["name"],$giteacolumns))
|
||||
array_push($giteacolumns,$column->getGiteajson()["name"]);
|
||||
}
|
||||
$json["columns"]=$tmp;
|
||||
array_push($gitearepos,$json);
|
||||
|
||||
foreach($scrum->getScrumteams() as $team) {
|
||||
if(!in_array($team->getGiteajson()["name"],$giteateams))
|
||||
array_push($giteateams,$team->getGiteajson()["name"]);
|
||||
}
|
||||
|
||||
foreach($scrum->getScrumprioritys() as $priority) {
|
||||
if(!in_array($priority->getGiteajson()["name"],$giteaprioritys))
|
||||
array_push($giteaprioritys,$priority->getGiteajson()["name"]);
|
||||
}
|
||||
|
||||
foreach($scrum->getScrumtypes() as $type) {
|
||||
if(!in_array($type->getGiteajson()["name"],$giteatypes))
|
||||
array_push($giteatypes,$type->getGiteajson()["name"]);
|
||||
}
|
||||
|
||||
foreach($giteaissues as $giteaissue) {
|
||||
foreach($giteaissue->labels as $label) {
|
||||
if(!in_array($label->name,$gitealabels))
|
||||
array_push($gitealabels,$label->name);
|
||||
}
|
||||
}
|
||||
|
||||
$keysort = array_column($giteamilestones, 'title');
|
||||
array_multisort($keysort, SORT_DESC, $giteamilestones);
|
||||
sort($giteacolumns);
|
||||
sort($giteateams);
|
||||
sort($giteaprioritys);
|
||||
sort($giteatypes);
|
||||
sort($gitealabels);
|
||||
|
||||
// Préférences utilisateur
|
||||
$filtercategorys = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtercategorys",$id);
|
||||
$filterrepos = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterrepos",$id);
|
||||
$filtermilestones = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtermilestones",$id);
|
||||
$filtersprints = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtersprints",$id);
|
||||
$filtercolumns = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtercolumns",$id);
|
||||
$filterteams = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterteams",$id);
|
||||
$filterprioritys = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterprioritys",$id);
|
||||
$filtertypes = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtertypes",$id);
|
||||
$filterlabels = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterlabels",$id);
|
||||
$filterassignees = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterassignees",$id);
|
||||
$filterexcludes = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterexcludes",$id);
|
||||
$showfilters = $em->getRepository("App:User")->getUserpreference($this->getUser(),"showfilters",$id);
|
||||
|
||||
if($fgcsv) {
|
||||
$dir = $this->getParameter('kernel.project_dir') . '/public/uploads/issues/';
|
||||
$file = "issues-".$id.".csv";
|
||||
$fs = new Filesystem();
|
||||
$fs->mkdir($dir);
|
||||
$csvh = fopen($dir.$file, 'w');
|
||||
$d = ';'; // this is the default but i like to be explicit
|
||||
$e = '"'; // this is the default but i like to be explicit
|
||||
|
||||
$tmp=["Projet","Jalon","Sprint","Type","Id","Titre","Statut","Label","Poid"];
|
||||
fputcsv($csvh, $tmp, $d, $e);
|
||||
|
||||
foreach($gitearepos as $gitearepo) {
|
||||
foreach($gitearepo["issues"] as $giteaissue) {
|
||||
$statut="";
|
||||
$issue=$em->getRepository("App:Scrumissue")->findOneBy(["giteaid"=>$giteaissue->id]);
|
||||
|
||||
$type="";
|
||||
$labels="";
|
||||
foreach($giteaissue->labels as $label) {
|
||||
if(in_array($label->id,$gitearepo["columns"]))
|
||||
$statut=$label->name;
|
||||
elseif(in_array($label->name,$giteatypes))
|
||||
$type=$label->name;
|
||||
else
|
||||
$labels=$labels.($labels!=""?"\n":"").$label->name;
|
||||
}
|
||||
$tmp=[
|
||||
$gitearepo["name"],
|
||||
(isset($giteaissue->milestone->title)?$giteaissue->milestone->title:""),
|
||||
($issue->getScrumsprint()?$issue->getScrumsprint()->getName():"Aucun"),
|
||||
$type,
|
||||
$giteaissue->number,
|
||||
$giteaissue->title,
|
||||
$statut,
|
||||
$labels,
|
||||
$issue->getWeight()
|
||||
];
|
||||
fputcsv($csvh, $tmp, $d, $e);
|
||||
}
|
||||
}
|
||||
fclose($csvh);
|
||||
|
||||
$response = new BinaryFileResponse($dir.$file);
|
||||
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $this->render($this->render.'table.html.twig',[
|
||||
"useheader" => true,
|
||||
"usesidebar" => false,
|
||||
"id" => $id,
|
||||
"gitearepos" => $gitearepos,
|
||||
"giteamilestones" => $giteamilestones,
|
||||
"sprints" => $scrum->getScrumsprints(),
|
||||
"giteacolumns" => $giteacolumns,
|
||||
"giteateams" => $giteateams,
|
||||
"giteaprioritys" => $giteaprioritys,
|
||||
"giteatypes" => $giteatypes,
|
||||
"gitealabels" => $gitealabels,
|
||||
"giteaassignees" => $giteaassignees,
|
||||
"filtercategorys" => $filtercategorys,
|
||||
"filterrepos" => $filterrepos,
|
||||
"filtermilestones" => $filtermilestones,
|
||||
"filtersprints" => $filtersprints,
|
||||
"filtercolumns" => $filtercolumns,
|
||||
"filterteams" => $filterteams,
|
||||
"filterprioritys" => $filterprioritys,
|
||||
"filtertypes" => $filtertypes,
|
||||
"filterlabels" => $filterlabels,
|
||||
"filterexcludes" => $filterexcludes,
|
||||
"filterassignees" => $filterassignees,
|
||||
"showfilters" => $showfilters,
|
||||
"fgpoker" => $fgpoker,
|
||||
]);
|
||||
}
|
||||
|
||||
public function stat($id,Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$scrum=$em->getRepository($this->entity)->find($id);
|
||||
if(!$scrum) return $this->redirectToRoute($this->route);
|
||||
$em->getRepository("App:Scrum")->getGitea($scrum,$giteaassignees,$giteacolumns,$giteamilestones,$giteateams,$giteaprioritys,$giteatypes,$gitealabels);
|
||||
|
||||
// Préférences utilisateur
|
||||
$filtermilestones = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtermilestones",$id);
|
||||
$filtersprints = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtersprints",$id);
|
||||
$filterbynumber = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterbynumber",$id);
|
||||
$showfilters = $em->getRepository("App:User")->getUserpreference($this->getUser(),"showfilters",$id);
|
||||
|
||||
$tbestim=$this->getEstim($scrum);
|
||||
|
||||
return $this->render($this->render.'stat.html.twig', [
|
||||
'useheader' => true,
|
||||
'usesidebar' => false,
|
||||
'usetitle' => $scrum->getName(),
|
||||
'giteamilestones' => $giteamilestones,
|
||||
'sprints' => $scrum->getScrumsprints(),
|
||||
'filtermilestones' => $filtermilestones,
|
||||
'filtersprints' => $filtersprints,
|
||||
'filterbynumber' => $filterbynumber,
|
||||
'showfilters' => $showfilters,
|
||||
$this->data => $scrum,
|
||||
'tbestim' => $tbestim,
|
||||
]);
|
||||
}
|
||||
|
||||
public function link($id,Request $request)
|
||||
{
|
||||
// Initialisation de l'enregistrement
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$data=$em->getRepository($this->entity)->find($id);
|
||||
if(!$data) return $this->redirectToRoute($this->route);
|
||||
|
||||
$em->getRepository("App:Scrum")->getGitea($data,$giteaassignees,$giteacolumns,$giteamilestones,$giteateams,$giteaprioritys,$giteatypes,$gitealabels);
|
||||
|
||||
// Préférences utilisateur
|
||||
$filtermilestones = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filtermilestones",$id);
|
||||
$filterteams = $em->getRepository("App:User")->getUserpreference($this->getUser(),"filterteams",$id);
|
||||
$showfilters = $em->getRepository("App:User")->getUserpreference($this->getUser(),"showfilters",$id);
|
||||
|
||||
$tbstat=[];
|
||||
foreach($data->getScrumIssues() as $issue) {
|
||||
|
||||
$labels=$issue->getGiteajson()["labels"];
|
||||
$haveteams=true;
|
||||
if($filterteams) {
|
||||
$haveteams=false;
|
||||
foreach($filterteams as $filterteam) {
|
||||
foreach($labels as $label) {
|
||||
if($label["id"]==$filterteam) {
|
||||
$haveteams=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($haveteams) {
|
||||
$idmilestone=($issue->getGiteamilestone()?$issue->getGiteamilestone():-100);
|
||||
$lbmilestone=($issue->getGiteamilestone()?$issue->getGiteamilestonename():"Aucun");
|
||||
if(!array_key_exists($idmilestone,$tbstat)) {
|
||||
$tbstat[$idmilestone]=["id"=>$idmilestone,"name"=>$lbmilestone,"stat"=>[]];
|
||||
}
|
||||
|
||||
if(!$issue->getScrumcolumn()) $ordercolumns=0;
|
||||
else $ordercolumns=array_search($issue->getScrumcolumn()->getGiteaid(),$giteacolumns);
|
||||
|
||||
//$ordercolumns=$issue->getScrumcolumn()->getId();
|
||||
if(!array_key_exists($ordercolumns,$tbstat[$idmilestone]["stat"])) {
|
||||
$tbstat[$idmilestone]["stat"][$ordercolumns]=[
|
||||
"id"=>$issue->getScrumcolumn()->getId(),
|
||||
"label"=>$issue->getScrumcolumn()->getName(),
|
||||
"total"=>0,
|
||||
"color"=>"#".$issue->getScrumcolumn()->getGiteajson()["color"],
|
||||
"labels"=>[],
|
||||
];
|
||||
}
|
||||
|
||||
foreach($labels as $label) {
|
||||
if($ordercolumns!=$label["id"]) {
|
||||
if(!array_key_exists($label["id"],$tbstat[$idmilestone]["stat"][$ordercolumns]["labels"])) {
|
||||
$tbstat[$idmilestone]["stat"][$ordercolumns]["labels"][$label["id"]] = [
|
||||
"id"=>$label["id"],
|
||||
"label"=>$label["name"],
|
||||
"total"=>0,
|
||||
"color"=>"#".$label["color"],
|
||||
];
|
||||
}
|
||||
$tbstat[$idmilestone]["stat"][$ordercolumns]["labels"][$label["id"]]["total"]+=$issue->getWeight();
|
||||
}
|
||||
}
|
||||
|
||||
$tbstat[$idmilestone]["stat"][$ordercolumns]["total"]+=$issue->getWeight();
|
||||
}
|
||||
}
|
||||
|
||||
foreach($tbstat as $k1=>$milestone) {
|
||||
$tmp=$tbstat[$k1]["stat"];
|
||||
ksort($tmp);
|
||||
$tbstat[$k1]["stat"]=$tmp;
|
||||
}
|
||||
|
||||
foreach($tbstat as $k1=>$milestone) {
|
||||
foreach($tbstat[$k1]["stat"] as $k2=>$statut) {
|
||||
$keysort = array_column($tbstat[$k1]["stat"][$k2]["labels"], 'label');
|
||||
array_multisort($keysort, SORT_ASC, $tbstat[$k1]["stat"][$k2]["labels"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $this->render($this->render.'stat.html.twig', [
|
||||
'useheader' => true,
|
||||
'usesidebar' => false,
|
||||
'usetitle' => $data->getName(),
|
||||
'giteaassignees' => $giteaassignees,
|
||||
'giteacolumns' => $giteacolumns,
|
||||
'giteamilestones' => $giteamilestones,
|
||||
'giteateams' => $giteateams,
|
||||
'giteaprioritys' => $giteaprioritys,
|
||||
'giteatypes' => $giteatypes,
|
||||
'gitealabels' => $gitealabels,
|
||||
'filtermilestones' => $filtermilestones,
|
||||
'filterteams' => $filterteams,
|
||||
'showfilters' => $showfilters,
|
||||
$this->data => $data,
|
||||
'tbstat' => $tbstat,
|
||||
return $this->render($this->render.'link.html.twig',[
|
||||
"useheader" => true,
|
||||
"usesidebar" => false,
|
||||
"maxwidth" => 1000,
|
||||
"scrum" => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
public function info($id,Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$viewclosed = $request->getSession()->get("viewclosed");
|
||||
$scrum=$em->getRepository($this->entity)->find($id);
|
||||
if(!$scrum) return $this->redirectToRoute($this->route);
|
||||
//$em->getRepository("App:Scrum")->getGitea($scrum,$giteaassignees,$giteacolumns,$giteamilestones,$giteateams,$giteaprioritys,$giteatypes,$gitealabels);
|
||||
|
||||
// Rechercher du scrum en cours
|
||||
$scrum=$em->getRepository("App:Scrum")->find($id);
|
||||
if(!$scrum) return new JsonResponse(['message' => 'No Issue'], 403);
|
||||
|
||||
$giteaissues=$this->giteaservice->getIssues($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],"?state=".($viewclosed=="true"?"all":"open"));
|
||||
|
||||
$weights=[];
|
||||
foreach($giteaissues as $giteaissue) {
|
||||
$scrumissue=$em->getRepository("App:Scrumissue")->findOneBy(["scrum"=>$scrum,"giteaid"=>$giteaissue->id]);
|
||||
if($scrumissue) {
|
||||
if($giteaissue->milestone) $milestoneid=$giteaissue->milestone->id;
|
||||
else $milestoneid=-100;
|
||||
|
||||
if(!array_key_exists($milestoneid,$weights)) $weights[$milestoneid]=0;
|
||||
$weights[$milestoneid]=$weights[$milestoneid]+$scrumissue->getWeight();
|
||||
}
|
||||
}
|
||||
$tbestim=$this->getEstim($scrum);
|
||||
|
||||
$output=[];
|
||||
$output["weights"]=$weights;
|
||||
|
||||
$output["tbestim"]=$tbestim;
|
||||
return new JsonResponse($output);
|
||||
}
|
||||
|
||||
private function getEstim($scrum) {
|
||||
|
||||
|
||||
// Initialisation de l'enregistrement
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$firstcolumn=$em->getRepository('App:Scrumcolumn')->findOneBy(["scrum"=>$scrum], ['rowid' => 'ASC']);
|
||||
if(!$firstcolumn) return $this->redirectToRoute($this->route);
|
||||
|
||||
|
||||
// Création du tableau des issues
|
||||
$issues=$scrum->getScrumissues();
|
||||
$tbissues=[];
|
||||
$tbcols=[];
|
||||
$tbjals=[];
|
||||
$tbsprs=[];
|
||||
$tbestim=[];
|
||||
|
||||
$viewclosed = $this->get('session')->get("viewclosed");
|
||||
if($viewclosed=="false") {
|
||||
$giteamilestones=$this->giteaservice->getMilestones($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],"?state=open");
|
||||
$giteamilestones=array_column($giteamilestones,"id");
|
||||
}
|
||||
|
||||
foreach($issues as $issue) {
|
||||
// bypass jalon closed
|
||||
if($viewclosed=="false") {
|
||||
|
||||
/*
|
||||
if(array_key_exists("milestone",$issue->getGiteajson()) && !empty($issue->getGiteajson()["milestone"]) && $issue->getGiteajson()["milestone"])
|
||||
dump($issue->getGiteajson()["milestone"]["title"]);
|
||||
*/
|
||||
if(array_key_exists("milestone",$issue->getGiteajson()) && !empty($issue->getGiteajson()["milestone"]) && !in_array($issue->getGiteajson()["milestone"]["id"],$giteamilestones))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//if($viewclosed=="false"&&($issue->getGiteastate()=="closed"||($issue->getScrumsprint()&&$issue->getScrumsprint()->getClosed()))) continue;
|
||||
|
||||
// Ids
|
||||
$idcol=($issue->getScrumcolumn()?$issue->getScrumcolumn()->getId():$firstcolumn->getId());
|
||||
$idjal=($issue->getGiteamilestone()?$issue->getGiteamilestone():-100);
|
||||
$idspr=($issue->getScrumsprint()?$issue->getScrumsprint()->getId():-100);
|
||||
|
||||
// Roworders
|
||||
$rowcol=($issue->getScrumcolumn()?$issue->getScrumcolumn()->getRowid():$firstcolumn->getRowid());
|
||||
$rowjal=($issue->getGiteaMilestonename()?$issue->getGiteaMilestonename():-100);
|
||||
$rowspr=($issue->getScrumsprint()?$issue->getScrumsprint()->getRowid():-100);
|
||||
|
||||
// Names
|
||||
$nmcol=($issue->getScrumcolumn()?$issue->getScrumcolumn()->getName():$firstcolumn->getName());
|
||||
$nmjal=($issue->getGiteaMilestonename()?$issue->getGiteaMilestonename():"Aucun");
|
||||
$nmspr=($issue->getScrumsprint()?$issue->getScrumsprint()->getName():"Aucun");
|
||||
|
||||
// Idgiteas
|
||||
$gicol=($issue->getScrumcolumn()?$issue->getScrumcolumn()->getGiteaid():$firstcolumn->getGiteaid());
|
||||
$gijal=($issue->getGiteaMilestone()?$issue->getGiteaMilestone():-100);
|
||||
|
||||
if(!array_key_exists($idjal,$tbestim)) {
|
||||
$tbestim[$idjal] = [
|
||||
"rowjal" => $rowjal,
|
||||
"idjal" => $idjal,
|
||||
"gijal" => $gijal,
|
||||
"nmjal" => $nmjal,
|
||||
"nbjrs" => 0,
|
||||
"nbiss" => 0,
|
||||
"columns" => [],
|
||||
"sprints" => [],
|
||||
];
|
||||
}
|
||||
|
||||
if(!array_key_exists($idspr,$tbestim[$idjal]["sprints"])) {
|
||||
$tbestim[$idjal]["sprints"][$idspr] = [
|
||||
"rowspr" => $rowspr,
|
||||
"idspr" => $idspr,
|
||||
"nmspr" => $nmspr,
|
||||
"nbjrs" => 0,
|
||||
"nbiss" => 0,
|
||||
"columns" => [],
|
||||
];
|
||||
}
|
||||
|
||||
if(!array_key_exists("clos",$tbestim[$idjal]["columns"])) {
|
||||
$tbestim[$idjal]["columns"]["clos"] = [
|
||||
"rowcol" => 1000,
|
||||
"idcol" => "clos",
|
||||
"gicol" => "clos",
|
||||
"nmcol" => "Clos",
|
||||
"color" => "000000",
|
||||
"nbjrs" => 0,
|
||||
"nbiss" => 0,
|
||||
];
|
||||
}
|
||||
|
||||
if(!array_key_exists($idcol,$tbestim[$idjal]["columns"])) {
|
||||
$tbestim[$idjal]["columns"][$idcol] = [
|
||||
"rowcol" => $rowcol,
|
||||
"idcol" => $idcol,
|
||||
"gicol" => $gicol,
|
||||
"nmcol" => $nmcol,
|
||||
"color" => ($issue->getScrumcolumn()?$issue->getScrumcolumn()->getGiteajson()["color"]:$firstcolumn->getGiteajson()["color"]),
|
||||
"nbjrs" => 0,
|
||||
"nbiss" => 0,
|
||||
];
|
||||
}
|
||||
|
||||
if(!array_key_exists("clos",$tbestim[$idjal]["sprints"][$idspr]["columns"])) {
|
||||
$tbestim[$idjal]["sprints"][$idspr]["columns"]["clos"] = [
|
||||
"rowcol" => 10000,
|
||||
"idcol" => "clos",
|
||||
"gicol" => "clos",
|
||||
"nmcol" => "Clos",
|
||||
"color" => "000000",
|
||||
"nbjrs" => 0,
|
||||
"nbiss" => 0,
|
||||
];
|
||||
}
|
||||
|
||||
if(!array_key_exists($idcol,$tbestim[$idjal]["sprints"][$idspr]["columns"])) {
|
||||
$tbestim[$idjal]["sprints"][$idspr]["columns"][$idcol] = [
|
||||
"rowcol" => $rowcol,
|
||||
"idcol" => $idcol,
|
||||
"gicol" => $gicol,
|
||||
"nmcol" => $nmcol,
|
||||
"color" => ($issue->getScrumcolumn()?$issue->getScrumcolumn()->getGiteajson()["color"]:$firstcolumn->getGiteajson()["color"]),
|
||||
"nbjrs" => 0,
|
||||
"nbiss" => 0,
|
||||
];
|
||||
}
|
||||
|
||||
// On cumule les estimations
|
||||
if($issue->getGiteastate()=="closed") $idcol="clos";
|
||||
|
||||
$tbestim[$idjal]["nbjrs"]+=$issue->getWeight();
|
||||
$tbestim[$idjal]["columns"][$idcol]["nbjrs"]+=$issue->getWeight();
|
||||
$tbestim[$idjal]["sprints"][$idspr]["nbjrs"]+=$issue->getWeight();
|
||||
$tbestim[$idjal]["sprints"][$idspr]["columns"][$idcol]["nbjrs"]+=$issue->getWeight();
|
||||
|
||||
$tbestim[$idjal]["nbiss"]++;
|
||||
$tbestim[$idjal]["columns"][$idcol]["nbiss"]++;
|
||||
$tbestim[$idjal]["sprints"][$idspr]["nbiss"]++;
|
||||
$tbestim[$idjal]["sprints"][$idspr]["columns"][$idcol]["nbiss"]++;
|
||||
|
||||
|
||||
|
||||
$this->formatDec($tbestim[$idjal]["nbjrs"]);
|
||||
$this->formatDec($tbestim[$idjal]["columns"][$idcol]["nbjrs"]);
|
||||
$this->formatDec($tbestim[$idjal]["sprints"][$idspr]["nbjrs"]);
|
||||
$this->formatDec($tbestim[$idjal]["sprints"][$idspr]["columns"][$idcol]["nbjrs"]);
|
||||
|
||||
}
|
||||
// dd("stop");
|
||||
|
||||
$keysort = array_column($tbestim, 'nmjal');
|
||||
array_multisort($keysort, SORT_DESC, $tbestim);
|
||||
foreach($tbestim as $keyj => $jalon) {
|
||||
$keysort = array_column($jalon["sprints"],"nmspr");
|
||||
array_multisort($keysort, SORT_DESC, $tbestim[$keyj]["sprints"]);
|
||||
}
|
||||
return $tbestim;
|
||||
}
|
||||
|
||||
private function formatDec(&$number) {
|
||||
if(strpos(strval($number), '.') !== false) $number=number_format($number,1);
|
||||
else $number=intval($number);
|
||||
}
|
||||
|
||||
protected function getErrorForm($id,$form,$request,$data,$mode) {
|
||||
if ($form->get('submit')->isClicked()&&$mode=="delete") {
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ class ScrumcolumnController extends AbstractController
|
|||
|
||||
// Récupérer les repos de gitea
|
||||
$gitealabels=$this->giteaservice->getLabels($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
if(!is_array($gitealabels)) die("Probleme de connexion avec gitea veuillez vous <a href='/ninegitea/logout'>reconnecter</a>");
|
||||
if(!is_array($gitealabels)) die("Probleme de connexion avec gitea veuillez vous <a href='/logout'>reconnecter</a>");
|
||||
|
||||
// Création du formulaire
|
||||
$form = $this->createForm(Form::class,$data,array("mode"=>"submit","gitealabels"=>$gitealabels));
|
||||
|
|
|
@ -12,6 +12,7 @@ use App\Entity\Scrumissue as Entity;
|
|||
use App\Form\ScrumissueType as Form;
|
||||
|
||||
use App\Service\giteaService;
|
||||
use stdClass;
|
||||
|
||||
class ScrumissueController extends AbstractController
|
||||
{
|
||||
|
@ -31,8 +32,10 @@ class ScrumissueController extends AbstractController
|
|||
$newcolumn=$request->get('newcolumn');
|
||||
$oldmilestone=$request->get('oldmilestone');
|
||||
$newmilestone=$request->get('newmilestone');
|
||||
$oldsprint=$request->get('oldsprint');
|
||||
$newsprint=$request->get('newsprint');
|
||||
|
||||
if($oldcolumn!=$newcolumn||$oldmilestone!=$newmilestone) {
|
||||
if($oldcolumn!=$newcolumn||$oldmilestone!=$newmilestone||$oldsprint!=$newsprint) {
|
||||
// Rechercher l'issue en cours
|
||||
$scrumissue=$em->getRepository("App:Scrumissue")->find($id);
|
||||
if(!$scrumissue) return new JsonResponse(['message' => 'No Issue'], 403);
|
||||
|
@ -69,15 +72,31 @@ class ScrumissueController extends AbstractController
|
|||
if(!$return) return new JsonResponse(['message' => 'No API patchIssue'], 403);
|
||||
}
|
||||
|
||||
// Mettre à jour le sprint
|
||||
if($oldsprint!=$newsprint) {
|
||||
$scrumissue->setScrumsprint(null);
|
||||
$sprint=$em->getRepository("App:Scrumsprint")->find($newsprint);
|
||||
if($sprint) {
|
||||
$scrumissue->setScrumsprint($sprint);
|
||||
}
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
// Récupérer l'issue modifiée pour mettre à jour la date de modification gitea
|
||||
$giteaissue=$this->giteaservice->getIssue($scrumissue->getScrum()->getGiteajson()["owner"]["login"],$scrumissue->getScrum()->getGiteajson()["name"],$scrumissue->getGiteanumber());
|
||||
if(!$giteaissue) return new JsonResponse(['message' => 'No API getIssue'], 403);
|
||||
$updatedate=new \DateTime($giteaissue->updated_at);
|
||||
if($updatedate > $scrumissue->getScrum()->getUpdatedate()) {
|
||||
$scrumissue->getScrum()->setUpdatedate(new \DateTime($giteaissue->updated_at));
|
||||
$updateissue=new \DateTime(json_decode(json_encode($giteaissue), true)["updated_at"]);
|
||||
$updateissue->setTimezone(new \DateTimeZone("UTC"));
|
||||
$em->getRepository("App:Scrum")->majissue($scrumissue,$giteaissue,false);
|
||||
|
||||
$lastupdate=$scrumissue->getScrum()->getUpdatedate();
|
||||
|
||||
|
||||
if($updateissue > $lastupdate) {
|
||||
$scrumissue->getScrum()->setUpdatedate($updateissue);
|
||||
$em->persist($scrumissue->getScrum());
|
||||
$em->flush();
|
||||
return new JsonResponse($updatedate->format("Ymd H:i:s"));
|
||||
return new JsonResponse($updateissue->format("Ymd H:i:s"));
|
||||
}
|
||||
}
|
||||
return new JsonResponse(false);
|
||||
|
@ -120,10 +139,77 @@ class ScrumissueController extends AbstractController
|
|||
|
||||
$output=[];
|
||||
$output["weight"]=$scrumissue->getWeight();
|
||||
$output["giteajson"]=$scrumissue->getGiteajson();
|
||||
$output["notes"]=$scrumissue->getNotes();
|
||||
|
||||
return new JsonResponse($output);
|
||||
}
|
||||
|
||||
public function view($id, Request $request) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$issue=$em->getRepository("App:Scrumissue")->find($id);
|
||||
$scrum = $issue->getScrum();
|
||||
|
||||
$repoid = $scrum->getGiteaid();
|
||||
$repoowner = $scrum->getGiteajson()["owner"]["login"];
|
||||
$reponame = $scrum->getGiteajson()["name"];
|
||||
|
||||
$repo=$this->giteaservice->getRepo($repoid);
|
||||
$giteaissue=$this->giteaservice->getIssue($repoowner,$reponame,$issue->getGiteanumber());
|
||||
$giteaissue->body = $this->giteaservice->markdown("/".$scrum->getGiteajson()["full_name"],"comment",$giteaissue->body);
|
||||
$giteaissue->comments=$this->giteaservice->getIssueComments($repoowner,$reponame,$giteaissue->number);
|
||||
|
||||
|
||||
$giteaissue->statuslife=$issue->getScrumcolumn()->getName();
|
||||
$giteaissue->weight=$issue->getWeight();
|
||||
$giteaissue->nineid=$issue->getId();
|
||||
|
||||
$giteaissue->sprint=($issue->getScrumsprint()?$issue->getScrumsprint()->getName():null);
|
||||
foreach($giteaissue->comments as $keycomment => $comment) {
|
||||
$giteaissue->comments[$keycomment]->body=$this->giteaservice->markdown("/".$scrum->getGiteajson()["full_name"],"comment",$giteaissue->comments[$keycomment]->body);
|
||||
}
|
||||
|
||||
$giteaissue->timelines=$this->giteaservice->getIssueTimelines($repoowner,$reponame,$giteaissue->number);
|
||||
|
||||
$giteaissue->labelhistos=[];
|
||||
$giteaissue->refs=[];
|
||||
foreach($giteaissue->timelines as $key => $timeline) {
|
||||
if($timeline->type == "label"){
|
||||
$tmp=new stdClass();
|
||||
$tmp->label=($timeline->body==1?"Ajout Label":"Suppression Label")." <i>".$timeline->label->name."<i>";
|
||||
$tmp->user=$timeline->user;
|
||||
$tmp->created_at=$timeline->created_at;
|
||||
array_push($giteaissue->labelhistos,$tmp);
|
||||
unset($giteaissue->timelines[$key]);
|
||||
}
|
||||
elseif($timeline->type == "comment_ref" || $timeline->type == "pull_ref" || $timeline->type == "issue_ref"){
|
||||
$tmp=new stdClass();
|
||||
$tmp->label ="<a href='".$timeline->ref_issue->html_url."' target='_blank'>";
|
||||
$tmp->label.=($timeline->type=="pull_ref"?"Request":"Issue")." = ";
|
||||
$tmp->label.="#".$timeline->ref_issue->number." = ".$timeline->ref_issue->title."</a></i>";
|
||||
$tmp->user=$timeline->user;
|
||||
$tmp->created_at=$timeline->created_at;
|
||||
array_push($giteaissue->refs,$tmp);
|
||||
unset($giteaissue->timelines[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Affichage du formulaire
|
||||
return $this->render('Scrum/issue.html.twig', [
|
||||
'useheader' => false,
|
||||
'usesidebar' => false,
|
||||
'maxwidth' => true,
|
||||
'repo' => $repo,
|
||||
'issue' => $giteaissue,
|
||||
]);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function update(Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
@ -154,39 +240,123 @@ class ScrumissueController extends AbstractController
|
|||
return new JsonResponse($weights);
|
||||
}
|
||||
|
||||
public function block(Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$id=$request->get('id');
|
||||
$issueblocked=$request->get('issueblocked');
|
||||
|
||||
// Rechercher l'issue en cours
|
||||
$scrumissue=$em->getRepository("App:Scrumissue")->find($id);
|
||||
if(!$scrumissue) return new JsonResponse(['message' => 'No Issue'], 403);
|
||||
|
||||
// Bloquer l'issue
|
||||
$response=$this->giteaservice->postIssueblocks($scrumissue->getScrum()->getGiteajson()["owner"]["login"],$scrumissue->getScrum()->getGiteajson()["name"],$scrumissue->getGiteanumber(),$issueblocked);
|
||||
|
||||
if(!$response) return new JsonResponse(['message' => 'Error api'], 403);
|
||||
|
||||
return new JsonResponse([]);
|
||||
}
|
||||
|
||||
public function unblock(Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$id=$request->get('id');
|
||||
|
||||
// Rechercher l'issue en cours
|
||||
$scrumissue=$em->getRepository("App:Scrumissue")->find($id);
|
||||
if(!$scrumissue) return new JsonResponse(['message' => 'No Issue'], 403);
|
||||
if(!$scrumissue->getScrumissueblock()) return new JsonResponse(['message' => 'No Issue'], 403);
|
||||
$issueblocked=$scrumissue->getScrumissueblock()->getGiteanumber();
|
||||
|
||||
// Débloquer l'issue
|
||||
$response=$this->giteaservice->deleteIssueblocks($scrumissue->getScrum()->getGiteajson()["owner"]["login"],$scrumissue->getScrum()->getGiteajson()["name"],$scrumissue->getGiteanumber(),$issueblocked);
|
||||
if(!$response) return new JsonResponse(['message' => 'Error api'], 403);
|
||||
|
||||
return new JsonResponse([]);
|
||||
}
|
||||
|
||||
|
||||
public function assigne(Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$id=$request->get('id');
|
||||
$assignees=$request->get('assignees');
|
||||
|
||||
// Rechercher l'issue en cours
|
||||
$scrumissue=$em->getRepository("App:Scrumissue")->find($id);
|
||||
if(!$scrumissue) return new JsonResponse(['message' => 'No Issue'], 403);
|
||||
|
||||
// Affecter l'issue
|
||||
$response=$this->giteaservice->patchissue($scrumissue->getScrum()->getGiteajson()["owner"]["login"],$scrumissue->getScrum()->getGiteajson()["name"],$scrumissue->getGiteanumber(),["assignees"=>($assignees?$assignees:[])]);
|
||||
if(!$response) return new JsonResponse(['message' => 'Error api'], 403);
|
||||
|
||||
return new JsonResponse([]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function notes(Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$id=$request->get('id');
|
||||
$notes=$request->get('notes');
|
||||
|
||||
// Rechercher l'issue en cours
|
||||
$scrumissue=$em->getRepository("App:Scrumissue")->find($id);
|
||||
if(!$scrumissue) return new JsonResponse(['message' => 'No Issue'], 403);
|
||||
$scrumissue->setNotes($notes);
|
||||
$em->flush();
|
||||
|
||||
return new JsonResponse([]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function color(Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$id=$request->get('id');
|
||||
$color=$request->get('color');
|
||||
|
||||
// Rechercher l'issue en cours
|
||||
$scrumissue=$em->getRepository("App:Scrumissue")->find($id);
|
||||
if(!$scrumissue) return new JsonResponse(['message' => 'No Issue'], 403);
|
||||
$scrumissue->setColor($color);
|
||||
$em->flush();
|
||||
|
||||
return new JsonResponse([]);
|
||||
}
|
||||
|
||||
public function ctrlchange(Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$id=$request->get('id');
|
||||
$lastupdate=new \DateTime($request->get('lastupdate'));
|
||||
$lastupdate->setTimezone(new \DateTimeZone("UTC"));
|
||||
$lastupdate->add(new \DateInterval("PT1M"));
|
||||
//var_dump($lastupdate->format(\DateTime::RFC3339_EXTENDED));
|
||||
|
||||
$scrum=$em->getRepository("App:Scrum")->find($id);
|
||||
if(!$scrum) return new JsonResponse(['message' => 'No Scrum'], 403);
|
||||
|
||||
$giteaissues=$this->giteaservice->getIssues($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
if(!is_array($giteaissues)) die("Probleme de connexion avec gitea veuillez vous <a href='/ninegitea/logout'>reconnecter</a>");
|
||||
$giteaissues=$this->giteaservice->getIssues($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],"?since=".urlencode($lastupdate->format(\DateTime::RFC3339_EXTENDED)));
|
||||
|
||||
foreach($giteaissues as $giteaissue) {
|
||||
// On ne prend pas les pull request
|
||||
if(!is_null($giteaissue->pull_request))
|
||||
continue;
|
||||
return new Response((!empty($giteaissues)?"1":"0"));
|
||||
}
|
||||
|
||||
$scrumissue=$em->getRepository("App:Scrumissue")->findOneBy(["scrum"=>$scrum,"giteaid"=>$giteaissue->id]);
|
||||
public function getpoker($userid,$issueid,Request $request) {
|
||||
return new Response(0);
|
||||
|
||||
if(!$scrumissue)
|
||||
return new JsonResponse(true);
|
||||
}
|
||||
|
||||
$fgissueupdated=false;
|
||||
$updatedate=new \DateTime(json_decode(json_encode($giteaissue), true)["updated_at"]);
|
||||
if($updatedate>$lastupdate) {
|
||||
$fgissueupdated=true;
|
||||
}
|
||||
public function setpoker($userid,$issueid,Request $request) {
|
||||
|
||||
if($fgissueupdated)
|
||||
return new JsonResponse(true);
|
||||
}
|
||||
|
||||
return new JsonResponse(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ class ScrumpriorityController extends AbstractController
|
|||
|
||||
// Récupérer les repos de gitea
|
||||
$gitealabels=$this->giteaservice->getLabels($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
if(!is_array($gitealabels)) die("Probleme de connexion avec gitea veuillez vous <a href='/ninegitea/logout'>reconnecter</a>");
|
||||
if(!is_array($gitealabels)) die("Probleme de connexion avec gitea veuillez vous <a href='/logout'>reconnecter</a>");
|
||||
|
||||
// Création du formulaire
|
||||
$form = $this->createForm(Form::class,$data,array("mode"=>"submit","gitealabels"=>$gitealabels));
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Form\FormError;
|
||||
|
||||
use App\Entity\Scrumsprint as Entity;
|
||||
use App\Form\ScrumsprintType as Form;
|
||||
|
||||
use App\Service\giteaService;
|
||||
|
||||
class ScrumsprintController extends AbstractController
|
||||
{
|
||||
private $data = "scrumsprint";
|
||||
private $route = "app_scrumsprint";
|
||||
private $render = "Scrumsprint/";
|
||||
private $entity = "App:Scrumsprint";
|
||||
|
||||
public function __construct(giteaService $giteaservice) { $this->giteaservice = $giteaservice; }
|
||||
|
||||
public function submit($scrumid, Request $request)
|
||||
{
|
||||
// Initialisation de l'enregistrement
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$scrum=$em->getRepository("App:Scrum")->find($scrumid);
|
||||
$data = new Entity();
|
||||
$data->setScrum($scrum);
|
||||
|
||||
$last = $em->getRepository('App:Scrumsprint')->findOneBy(["scrum"=>$scrum], ['rowid' => 'DESC']);
|
||||
if(!$last) $data->setRowid(0);
|
||||
else $data->setRowid($last->getRowid()+1);
|
||||
|
||||
// Récupérer les repos de gitea
|
||||
$giteamilestones=$this->giteaservice->getmilestones($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
if(!is_array($giteamilestones)) die("Probleme de connexion avec gitea veuillez vous <a href='/logout'>reconnecter</a>");
|
||||
|
||||
// Création du formulaire
|
||||
$form = $this->createForm(Form::class,$data,array("mode"=>"submit","giteamilestones"=>$giteamilestones));
|
||||
|
||||
// Récupération des data du formulaire
|
||||
$form->handleRequest($request);
|
||||
|
||||
// Sur erreur
|
||||
$this->getErrorForm(null,$form,$request,$data,"submit");
|
||||
|
||||
// Sur validation
|
||||
if ($form->get('submit')->isClicked() && $form->isValid()) {
|
||||
$data = $form->getData();
|
||||
$getmilestone=$this->giteaservice->getmilestone($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],$data->getGiteamilestone());
|
||||
$data->setGiteamilestonename($getmilestone->title);
|
||||
|
||||
$em->persist($data);
|
||||
$em->flush();
|
||||
|
||||
// Retour à la liste
|
||||
return $this->render($this->render.'close.html.twig');
|
||||
}
|
||||
|
||||
// Affichage du formulaire
|
||||
return $this->render($this->render.'edit.html.twig', [
|
||||
'useheader' => false,
|
||||
'usesidebar' => false,
|
||||
$this->data => $data,
|
||||
'mode' => 'submit',
|
||||
'form' => $form->createView()
|
||||
]);
|
||||
}
|
||||
|
||||
public function update($id,Request $request)
|
||||
{
|
||||
// Initialisation de l'enregistrement
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$data=$em->getRepository($this->entity)->find($id);
|
||||
$scrum=$data->getScrum();
|
||||
|
||||
// Récupérer les repos de gitea
|
||||
$giteamilestones=$this->giteaservice->getmilestones($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
|
||||
// Création du formulaire
|
||||
$form = $this->createForm(Form::class,$data,array("mode"=>"update","giteamilestones"=>$giteamilestones));
|
||||
|
||||
// Récupération des data du formulaire
|
||||
$form->handleRequest($request);
|
||||
|
||||
// Sur erreur
|
||||
$this->getErrorForm(null,$form,$request,$data,"update");
|
||||
|
||||
// Sur validation
|
||||
if ($form->get('submit')->isClicked() && $form->isValid()) {
|
||||
$data = $form->getData();
|
||||
$getmilestone=$this->giteaservice->getmilestone($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],$data->getGiteamilestone());
|
||||
$data->setGiteamilestonename($getmilestone->title);
|
||||
|
||||
$em->persist($data);
|
||||
$em->flush();
|
||||
|
||||
// Retour à la liste
|
||||
return $this->render($this->render.'close.html.twig');
|
||||
}
|
||||
|
||||
// Affichage du formulaire
|
||||
return $this->render($this->render.'edit.html.twig', [
|
||||
'useheader' => false,
|
||||
'usesidebar' => false,
|
||||
$this->data => $data,
|
||||
'mode' => 'update',
|
||||
'form' => $form->createView()
|
||||
]);
|
||||
}
|
||||
|
||||
public function delete($id,Request $request)
|
||||
{
|
||||
// Initialisation de l'enregistrement
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$data=$em->getRepository($this->entity)->find($id);
|
||||
|
||||
// Controle avant suppression
|
||||
$error=false;
|
||||
if($id<0) $error=true;
|
||||
|
||||
if($error)
|
||||
return $this->redirectToRoute($this->route."_update",["id"=>$id]);
|
||||
else {
|
||||
$em->remove($data);
|
||||
$em->flush();
|
||||
|
||||
// Retour à la liste
|
||||
return $this->render($this->render.'close.html.twig');
|
||||
}
|
||||
}
|
||||
|
||||
public function select($scrumid, Request $request)
|
||||
{
|
||||
// S'assurer que c'est un appel ajax
|
||||
if (!$request->isXmlHttpRequest()) {
|
||||
return new JsonResponse(array('message' => 'Interdit'), 400);
|
||||
}
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$scrum=$em->getRepository("App:Scrum")->find($scrumid);
|
||||
|
||||
$scrumsprints = $scrum->getScrumsprints();
|
||||
$output=array();
|
||||
foreach($scrumsprints as $scrumsprint) {
|
||||
$title = "Jalon = ".$scrumsprint->getGiteamilestonename()."<br>";
|
||||
$title.= "Sprint = ".$scrumsprint->getName();
|
||||
array_push($output,array("id"=>$scrumsprint->getId(),"name"=>$title,"closed"=>$scrumsprint->getClosed()));
|
||||
}
|
||||
|
||||
$response = new Response(json_encode($output));
|
||||
$response->headers->set('Content-Type', 'application/json');
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function order($scrumid, Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$scrumsprintids=explode(",",$request->get('lstordered'));
|
||||
$i=1;
|
||||
foreach($scrumsprintids as $id) {
|
||||
$scrumsprint=$em->getRepository($this->entity)->find($id);
|
||||
if($scrumsprint) {
|
||||
$scrumsprint->setRowid($i);
|
||||
$em->persist($scrumsprint);
|
||||
$em->flush();
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
$response = new Response();
|
||||
$response->headers->set('Content-Type', 'application/json');
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function getErrorForm($id,$form,$request,$data,$mode) {
|
||||
if ($form->get('submit')->isClicked()&&$mode=="delete") {
|
||||
}
|
||||
|
||||
if ($form->get('submit')->isClicked() && $mode=="submit") {
|
||||
}
|
||||
|
||||
if ($form->get('submit')->isClicked() && ($mode=="submit" || $mode=="update")) {
|
||||
}
|
||||
|
||||
if ($form->get('submit')->isClicked() && !$form->isValid()) {
|
||||
$this->get('session')->getFlashBag()->clear();
|
||||
|
||||
$errors = $form->getErrors();
|
||||
foreach( $errors as $error ) {
|
||||
$request->getSession()->getFlashBag()->add("error", $error->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ class ScrumteamController extends AbstractController
|
|||
|
||||
// Récupérer les repos de gitea
|
||||
$gitealabels=$this->giteaservice->getLabels($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
if(!is_array($gitealabels)) die("Probleme de connexion avec gitea veuillez vous <a href='/ninegitea/logout'>reconnecter</a>");
|
||||
if(!is_array($gitealabels)) die("Probleme de connexion avec gitea veuillez vous <a href='/logout'>reconnecter</a>");
|
||||
|
||||
// Création du formulaire
|
||||
$form = $this->createForm(Form::class,$data,array("mode"=>"submit","gitealabels"=>$gitealabels));
|
||||
|
|
|
@ -35,7 +35,7 @@ class ScrumtypeController extends AbstractController
|
|||
|
||||
// Récupérer les repos de gitea
|
||||
$gitealabels=$this->giteaservice->getLabels($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
if(!is_array($gitealabels)) die("Probleme de connexion avec gitea veuillez vous <a href='/ninegitea/logout'>reconnecter</a>");
|
||||
if(!is_array($gitealabels)) die("Probleme de connexion avec gitea veuillez vous <a href='/logout'>reconnecter</a>");
|
||||
|
||||
// Création du formulaire
|
||||
$form = $this->createForm(Form::class,$data,array("mode"=>"submit","gitealabels"=>$gitealabels));
|
||||
|
|
|
@ -135,16 +135,8 @@ class SecurityController extends AbstractController
|
|||
}
|
||||
|
||||
public function loginOAUTH() {
|
||||
/*
|
||||
OAUTH_CLIENTID=
|
||||
OAUTH_CLIENTSECRET=
|
||||
OAUTH_LOGINURL=https://forge.cadoles.com/login/oauth/authorize
|
||||
OAUTH_LOGOUTURL=https://forge.cadoles.com/user/logout
|
||||
OAUTH_TOKENURL=https://forge.cadoles.com/login/oauth/access_token
|
||||
*/
|
||||
// https://[YOUR-GITEA-URL]/login/oauth/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI& response_type=code&state=STATE
|
||||
|
||||
$callback=$this->generateUrl('app_login_callback', array(), UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
$callback=str_replace("http://",$this->getParameter("appProtocol")."://",$callback);
|
||||
$this->get('session')->set('giteacallback', $callback);
|
||||
$url=$this->getParameter("oauthLoginurl")."?client_id=".$this->getParameter("oauthClientid")."&redirect_uri=".$callback."&response_type=code&state=STATE";
|
||||
return $this->redirect($url);
|
||||
|
@ -208,10 +200,15 @@ class SecurityController extends AbstractController
|
|||
|
||||
// Redirection
|
||||
$redirect = $this->get('session')->get("_security.main.target_path");
|
||||
if($redirect)
|
||||
return $this->redirect($redirect);
|
||||
else
|
||||
return $this->redirect($this->generateUrl('app_home'));
|
||||
if($redirect) {
|
||||
$redirect=str_replace("http://",$this->getParameter("appProtocol")."://",$redirect);
|
||||
|
||||
}
|
||||
else {
|
||||
$redirect=$this->generateUrl('app_home');
|
||||
$redirect=str_replace("http://",$this->getParameter("appProtocol")."://",$redirect);
|
||||
}
|
||||
return $this->redirect($redirect);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,12 @@ class Scrum
|
|||
*/
|
||||
private $scrumcolumns;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Scrumsprint", mappedBy="scrum", cascade={"persist"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"rowid" = "ASC"})
|
||||
*/
|
||||
private $scrumsprints;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Scrumissue", mappedBy="scrum", cascade={"persist"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"giteamilestonename" = "DESC", "rowid" = "ASC"})
|
||||
|
@ -108,6 +114,18 @@ class Scrum
|
|||
return $tab;
|
||||
}
|
||||
|
||||
public function getScrumsprintstosee($viewclosed) {
|
||||
$sprints=$this->getScrumsprints();
|
||||
if($viewclosed=="false") {
|
||||
foreach($sprints as $sprint) {
|
||||
if($sprint->getClosed()) {
|
||||
$sprints->removeElement($sprint);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $sprints;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->users = new ArrayCollection();
|
||||
|
@ -117,6 +135,7 @@ class Scrum
|
|||
$this->scrumteams = new ArrayCollection();
|
||||
$this->scrumprioritys = new ArrayCollection();
|
||||
$this->scrumtypes = new ArrayCollection();
|
||||
$this->scrumsprints = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
|
@ -378,4 +397,35 @@ class Scrum
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Scrumsprint[]
|
||||
*/
|
||||
public function getScrumsprints(): Collection
|
||||
{
|
||||
return $this->scrumsprints;
|
||||
}
|
||||
|
||||
public function addScrumsprint(Scrumsprint $scrumsprint): self
|
||||
{
|
||||
if (!$this->scrumsprints->contains($scrumsprint)) {
|
||||
$this->scrumsprints[] = $scrumsprint;
|
||||
$scrumsprint->setScrum($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeScrumsprint(Scrumsprint $scrumsprint): self
|
||||
{
|
||||
if ($this->scrumsprints->contains($scrumsprint)) {
|
||||
$this->scrumsprints->removeElement($scrumsprint);
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($scrumsprint->getScrum() === $this) {
|
||||
$scrumsprint->setScrum(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -49,8 +49,8 @@ class Scrumcolumn
|
|||
private $scrum;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Scrumissue", mappedBy="scrumcolumn", cascade={"persist"}, orphanRemoval=true)
|
||||
* @ORM\OrderBy({"giteamilestonename" = "DESC", "rowid" = "ASC"})
|
||||
* @ORM\OneToMany(targetEntity="Scrumissue", mappedBy="scrumcolumn", cascade={"persist"}, orphanRemoval=false)
|
||||
* @ORM\OrderBy({"giteamilestonename" = "DESC", "scrumsprint" = "DESC", "rowid" = "ASC"})
|
||||
*/
|
||||
private $scrumissues;
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
|
@ -31,6 +33,16 @@ class Scrumissue
|
|||
*/
|
||||
private $weight=0;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
*/
|
||||
private $color;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", nullable=true)
|
||||
*/
|
||||
private $notes;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
|
@ -69,15 +81,46 @@ class Scrumissue
|
|||
private $giteajson;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Scrum", inversedBy="Scrumissues")
|
||||
* @ORM\ManyToOne(targetEntity="Scrum", inversedBy="scrumissues")
|
||||
*/
|
||||
private $scrum;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Scrumcolumn", inversedBy="Scrumissues")
|
||||
* @ORM\ManyToOne(targetEntity="Scrumcolumn", inversedBy="scrumissues")
|
||||
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
|
||||
*/
|
||||
private $scrumcolumn;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Scrumsprint", inversedBy="scrumissues")
|
||||
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
|
||||
*/
|
||||
private $scrumsprint;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Scrumissue", inversedBy="scrumissuedependencies")
|
||||
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
|
||||
*/
|
||||
private $scrumissueblock;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Scrumissue", mappedBy="scrumissueblock", cascade={"persist"}, orphanRemoval=false)
|
||||
* @ORM\OrderBy({"giteanumber" = "ASC"})
|
||||
*/
|
||||
private $scrumissuedependencies;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Userpoker", mappedBy="scrumissue", cascade={"persist"}, orphanRemoval=true)
|
||||
*/
|
||||
private $userpokers;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->userpokers = new ArrayCollection();
|
||||
$this->scrumissuedependcies = new ArrayCollection();
|
||||
$this->scrumissuedependencies = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
|
@ -215,6 +258,113 @@ class Scrumissue
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getScrumsprint(): ?Scrumsprint
|
||||
{
|
||||
return $this->scrumsprint;
|
||||
}
|
||||
|
||||
public function setScrumsprint(?Scrumsprint $scrumsprint): self
|
||||
{
|
||||
$this->scrumsprint = $scrumsprint;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Userpoker[]
|
||||
*/
|
||||
public function getUserpokers(): Collection
|
||||
{
|
||||
return $this->userpokers;
|
||||
}
|
||||
|
||||
public function addUserpoker(Userpoker $userpoker): self
|
||||
{
|
||||
if (!$this->userpokers->contains($userpoker)) {
|
||||
$this->userpokers[] = $userpoker;
|
||||
$userpoker->setScrumissue($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeUserpoker(Userpoker $userpoker): self
|
||||
{
|
||||
if ($this->userpokers->contains($userpoker)) {
|
||||
$this->userpokers->removeElement($userpoker);
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($userpoker->getScrumissue() === $this) {
|
||||
$userpoker->setScrumissue(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getScrumissueblock(): ?self
|
||||
{
|
||||
return $this->scrumissueblock;
|
||||
}
|
||||
|
||||
public function setScrumissueblock(?self $scrumissueblock): self
|
||||
{
|
||||
$this->scrumissueblock = $scrumissueblock;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Scrumissue[]
|
||||
*/
|
||||
public function getScrumissuedependencies(): Collection
|
||||
{
|
||||
return $this->scrumissuedependencies;
|
||||
}
|
||||
|
||||
public function addScrumissuedependency(Scrumissue $scrumissuedependency): self
|
||||
{
|
||||
if (!$this->scrumissuedependencies->contains($scrumissuedependency)) {
|
||||
$this->scrumissuedependencies[] = $scrumissuedependency;
|
||||
$scrumissuedependency->setScrumissue($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeScrumissuedependency(Scrumissue $scrumissuedependency): self
|
||||
{
|
||||
if ($this->scrumissuedependencies->contains($scrumissuedependency)) {
|
||||
$this->scrumissuedependencies->removeElement($scrumissuedependency);
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($scrumissuedependency->getScrumissue() === $this) {
|
||||
$scrumissuedependency->setScrumissue(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getColor(): ?string
|
||||
{
|
||||
return $this->color;
|
||||
}
|
||||
|
||||
public function setColor(?string $color): self
|
||||
{
|
||||
$this->color = $color;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNotes(): ?string
|
||||
{
|
||||
return $this->notes;
|
||||
}
|
||||
|
||||
public function setNotes(?string $notes): self
|
||||
{
|
||||
$this->notes = $notes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* Scrumcolumn
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="scrumsprint")
|
||||
*/
|
||||
class Scrumsprint
|
||||
{
|
||||
/**
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="name", type="string")
|
||||
*
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $rowid;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $closed;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer", nullable=true)
|
||||
*/
|
||||
private $giteamilestone;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
*
|
||||
*/
|
||||
private $giteamilestonename;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Scrum", inversedBy="scrumsprints")
|
||||
*/
|
||||
private $scrum;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Scrumissue", mappedBy="scrumsprint", cascade={"persist"}, orphanRemoval=false)
|
||||
*/
|
||||
private $scrumissues;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->scrumissues = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRowid(): ?int
|
||||
{
|
||||
return $this->rowid;
|
||||
}
|
||||
|
||||
public function setRowid(int $rowid): self
|
||||
{
|
||||
$this->rowid = $rowid;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getGiteamilestone(): ?int
|
||||
{
|
||||
return $this->giteamilestone;
|
||||
}
|
||||
|
||||
public function setGiteamilestone(?int $giteamilestone): self
|
||||
{
|
||||
$this->giteamilestone = $giteamilestone;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getGiteamilestonename(): ?string
|
||||
{
|
||||
return $this->giteamilestonename;
|
||||
}
|
||||
|
||||
public function setGiteamilestonename(?string $giteamilestonename): self
|
||||
{
|
||||
$this->giteamilestonename = $giteamilestonename;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getScrum(): ?Scrum
|
||||
{
|
||||
return $this->scrum;
|
||||
}
|
||||
|
||||
public function setScrum(?Scrum $scrum): self
|
||||
{
|
||||
$this->scrum = $scrum;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Scrumissue[]
|
||||
*/
|
||||
public function getScrumissues(): Collection
|
||||
{
|
||||
return $this->scrumissues;
|
||||
}
|
||||
|
||||
public function addScrumissue(Scrumissue $scrumissue): self
|
||||
{
|
||||
if (!$this->scrumissues->contains($scrumissue)) {
|
||||
$this->scrumissues[] = $scrumissue;
|
||||
$scrumissue->setScrumsprint($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeScrumissue(Scrumissue $scrumissue): self
|
||||
{
|
||||
if ($this->scrumissues->contains($scrumissue)) {
|
||||
$this->scrumissues->removeElement($scrumissue);
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($scrumissue->getScrumsprint() === $this) {
|
||||
$scrumissue->setScrumsprint(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getClosed(): ?bool
|
||||
{
|
||||
return $this->closed;
|
||||
}
|
||||
|
||||
public function setClosed(bool $closed): self
|
||||
{
|
||||
$this->closed = $closed;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -85,6 +85,11 @@ class User implements UserInterface, \Serializable
|
|||
*/
|
||||
private $preference;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Userpoker", mappedBy="user", cascade={"persist"}, orphanRemoval=true)
|
||||
*/
|
||||
private $userpokers;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Group", inversedBy="users", cascade={"persist"})
|
||||
* @ORM\JoinTable(name="usergroupe",
|
||||
|
@ -107,6 +112,7 @@ class User implements UserInterface, \Serializable
|
|||
{
|
||||
$this->groups = new ArrayCollection();
|
||||
$this->scrums = new ArrayCollection();
|
||||
$this->userpokers = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getUsername(): ?string
|
||||
|
@ -172,7 +178,7 @@ class User implements UserInterface, \Serializable
|
|||
|
||||
public function getDisplayname()
|
||||
{
|
||||
return $this->firstname." ".$this->lastname;
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function setId(int $id): self
|
||||
|
@ -336,4 +342,35 @@ class User implements UserInterface, \Serializable
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Userpoker[]
|
||||
*/
|
||||
public function getUserpokers(): Collection
|
||||
{
|
||||
return $this->userpokers;
|
||||
}
|
||||
|
||||
public function addUserpoker(Userpoker $userpoker): self
|
||||
{
|
||||
if (!$this->userpokers->contains($userpoker)) {
|
||||
$this->userpokers[] = $userpoker;
|
||||
$userpoker->setUser($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeUserpoker(Userpoker $userpoker): self
|
||||
{
|
||||
if ($this->userpokers->contains($userpoker)) {
|
||||
$this->userpokers->removeElement($userpoker);
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($userpoker->getUser() === $this) {
|
||||
$userpoker->setUser(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
/**
|
||||
* Userpoker
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="userpoker")
|
||||
*/
|
||||
class Userpoker
|
||||
{
|
||||
/**
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="name", type="integer")
|
||||
*
|
||||
*/
|
||||
private $nb;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Scrumissue", inversedBy="userpokers")
|
||||
*/
|
||||
private $scrumissue;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="User", inversedBy="userpokers")
|
||||
*/
|
||||
private $user;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getNb(): ?int
|
||||
{
|
||||
return $this->nb;
|
||||
}
|
||||
|
||||
public function setNb(int $nb): self
|
||||
{
|
||||
$this->nb = $nb;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getScrumissue(): ?Scrumissue
|
||||
{
|
||||
return $this->scrumissue;
|
||||
}
|
||||
|
||||
public function setScrumissue(?Scrumissue $scrumissue): self
|
||||
{
|
||||
$this->scrumissue = $scrumissue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUser(): ?User
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function setUser(?User $user): self
|
||||
{
|
||||
$this->user = $user;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
namespace App\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Tetranz\Select2EntityBundle\Form\Type\Select2EntityType;
|
||||
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
class ScrumsprintType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add('submit',
|
||||
SubmitType::class, [
|
||||
"label" => "Valider",
|
||||
"attr" => ["class" => "btn btn-success no-print"],
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add('name',
|
||||
TextType::class, [
|
||||
"label" =>"Nom",
|
||||
]
|
||||
);
|
||||
|
||||
$choices=["non"=>0,"oui"=>1];
|
||||
$builder->add('closed',
|
||||
ChoiceType::class, ['choices' => $choices]
|
||||
);
|
||||
|
||||
$choices=[];
|
||||
foreach($options["giteamilestones"] as $milestone) {
|
||||
$choices[$milestone->title]=$milestone->id;
|
||||
}
|
||||
|
||||
$builder->add('giteamilestone',
|
||||
ChoiceType::class, [
|
||||
"label" => "Jalon Gitea",
|
||||
"choices" => $choices,
|
||||
"disabled" => ($options["mode"]=="submit"?false:true),
|
||||
"placeholder" => "Selectionnez un label gitea",
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => 'App\Entity\Scrumsprint',
|
||||
'mode' => 'string',
|
||||
'giteamilestones' => 'string',
|
||||
));
|
||||
}
|
||||
}
|
|
@ -13,13 +13,32 @@ class ScrumRepository extends ServiceEntityRepository
|
|||
{
|
||||
private $session;
|
||||
private $firstcolumn;
|
||||
private $datescrumupdate;
|
||||
private $totalTime;
|
||||
private $startTime;
|
||||
private $showTime;
|
||||
|
||||
public function __construct(ManagerRegistry $registry,giteaService $giteaservice,SessionInterface $session)
|
||||
{
|
||||
parent::__construct($registry, Scrum::class);
|
||||
$this->giteaservice = $giteaservice;
|
||||
$this->session = $session;
|
||||
$this->showTime = false;
|
||||
}
|
||||
|
||||
private function showtime($istart,$title="") {
|
||||
if($this->showTime) {
|
||||
if($istart) {
|
||||
$this->totalTime = microtime(true);
|
||||
$this->startTime = microtime(true);
|
||||
}
|
||||
else {
|
||||
$endTime = microtime(true);
|
||||
$executionTime = $endTime - $this->startTime;
|
||||
$totalTime = $endTime - $this->totalTime;
|
||||
dump($executionTime." / ".$totalTime." = ".$title);
|
||||
$this->startTime = microtime(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function findByUser($user) {
|
||||
|
@ -36,9 +55,81 @@ class ScrumRepository extends ServiceEntityRepository
|
|||
return $scrums;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getGitea($scrum,&$giteaassignees,&$giteacolumns,&$giteamilestones,&$giteateams,&$giteaprioritys,&$giteatypes,&$gitealabels, $forcereload=false) {
|
||||
$this->showtime(true);
|
||||
$lastupdate = $scrum->getUpdatedate();
|
||||
if(!$lastupdate) $lastupdate = new \DateTime(("19000101"));
|
||||
$lastupdate->sub(new \DateInterval('PT30M'));
|
||||
|
||||
$viewclosed = $this->session->get("viewclosed");
|
||||
|
||||
// Récupérer les labels de gitea
|
||||
$gitealabels=$this->giteaservice->getLabels($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
if(!is_array($gitealabels)) die("Probleme de connexion avec gitea veuillez vous <a href='/logout'>reconnecter</a>");
|
||||
$giteaidlabels=array_column($gitealabels, 'id');
|
||||
|
||||
// Récupérer les jalons de gitea
|
||||
$giteamilestones=$this->giteaservice->getMilestones($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
if(!is_array($giteamilestones)) die("Probleme de connexion avec gitea veuillez vous <a href='/logout'>reconnecter</a>");
|
||||
$giteaidmilestones=array_column($giteamilestones, 'id');
|
||||
|
||||
// Temps d'execution
|
||||
$this->showtime(false,"Récupération gitealabels & giteamilestones");
|
||||
|
||||
// S'assurer que nos colonnes existes toujours
|
||||
$scrumcolumns=$scrum->getScrumcolumns();
|
||||
foreach($scrumcolumns as $scrumcolumn) {
|
||||
if(!in_array($scrumcolumn->getGiteaid(),$giteaidlabels)) {
|
||||
$this->_em->remove($scrumcolumn);
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
// S'assurer que nos teams existes toujours
|
||||
$scrumteams=$scrum->getScrumteams();
|
||||
foreach($scrumteams as $scrumteam) {
|
||||
if(!in_array($scrumteam->getGiteaid(),$giteaidlabels)) {
|
||||
$this->_em->remove($scrumteam);
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
// S'assurer que nos prioritys existes toujours
|
||||
$scrumprioritys=$scrum->getScrumprioritys();
|
||||
foreach($scrumprioritys as $scrumpriority) {
|
||||
if(!in_array($scrumpriority->getGiteaid(),$giteaidlabels)) {
|
||||
$this->_em->remove($scrumpriority);
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
// S'assurer que nos types existes toujours
|
||||
$scrumtypes=$scrum->getScrumtypes();
|
||||
foreach($scrumtypes as $scrumtype) {
|
||||
if(!in_array($scrumtype->getGiteaid(),$giteaidlabels)) {
|
||||
$this->_em->remove($scrumtype);
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
// Temps d'execution
|
||||
$this->showtime(false,"S'assurer que nos labels colonnes teams prioritys types existes toujours");
|
||||
|
||||
// S'assurer que nos sprint sont toujours lié à un jalon existant
|
||||
$scrumsprints=$scrum->getScrumsprints();
|
||||
foreach($scrumsprints as $scrumsprint) {
|
||||
if(!in_array($scrumsprint->getGiteamilestone(),$giteaidmilestones)) {
|
||||
$this->_em->remove($scrumsprint);
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
// Temps d'execution
|
||||
$this->showtime(false,"S'assurer que nos sprint sont toujours lié à un jalon existant");
|
||||
|
||||
// Récupérer le dernier order
|
||||
$last = $this->_em->getRepository('App:Scrumissue')->findOneBy(["scrum"=>$scrum], ['rowid' => 'DESC']);
|
||||
if(!$last) $lastrowid=-1;
|
||||
|
@ -82,54 +173,42 @@ class ScrumRepository extends ServiceEntityRepository
|
|||
else
|
||||
$giteaassignees=[];
|
||||
|
||||
$giteacollaborators=$this->giteaservice->getOrgateams($scrum->getGiteajson()["owner"]["login"]);
|
||||
if($giteacollaborators&&is_array($giteacollaborators)) {
|
||||
foreach($giteacollaborators as $team) {
|
||||
$giteamembers=$this->giteaservice->getTeammembers($team->id);
|
||||
if($giteamembers&&is_array($giteamembers)) {
|
||||
foreach($giteamembers as $giteamember) {
|
||||
if(!in_array($giteamember,$giteaassignees))
|
||||
array_push($giteaassignees,$giteamember);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$giteacollaborators=$this->giteaservice->getCollaborators($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
if(!is_array($giteacollaborators)) die("Probleme de connexion avec gitea veuillez vous <a href='/ninegitea/logout'>reconnecter</a>");
|
||||
// Temps d'execution
|
||||
$this->showtime(false,"Récupérer info ninegitea");
|
||||
|
||||
// Récupérer les intervenants
|
||||
$giteacollaborators=$this->giteaservice->getAssignees($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
if(!is_array($giteacollaborators)) die("Probleme de connexion avec gitea veuillez vous <a href='/logout'>reconnecter</a>");
|
||||
foreach($giteacollaborators as $giteacollaborator) {
|
||||
if(!in_array($giteacollaborator,$giteaassignees))
|
||||
array_push($giteaassignees,$giteacollaborator);
|
||||
}
|
||||
|
||||
// Temps d'execution
|
||||
$this->showtime(false,"Récupérer les intervenants");
|
||||
|
||||
// Récupérer les milestones de gitea
|
||||
$giteamilestones=$this->giteaservice->getMilestones($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],"?state=".($viewclosed=="true"?"all":"open"));
|
||||
if(!is_array($giteamilestones)) die("Probleme de connexion avec gitea veuillez vous <a href='/ninegitea/logout'>reconnecter</a>");
|
||||
if(!is_array($giteamilestones)) die("Probleme de connexion avec gitea veuillez vous <a href='/logout'>reconnecter</a>");
|
||||
$keysort = array_column($giteamilestones, 'title');
|
||||
array_multisort($keysort, SORT_DESC, $giteamilestones);
|
||||
|
||||
// Récupérer les labels de gitea
|
||||
$gitealabels=$this->giteaservice->getLabels($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"]);
|
||||
|
||||
if(!is_array($gitealabels)) die("Probleme de connexion avec gitea veuillez vous <a href='/ninegitea/logout'>reconnecter</a>");
|
||||
foreach($gitealabels as $key => $gitealabel) {
|
||||
if(in_array($gitealabel->id,$giteacolumns)||in_array($gitealabel->id,$giteateams)||in_array($gitealabel->id,$giteaprioritys)||in_array($gitealabel->id,$giteatypes))
|
||||
unset($gitealabels[$key]);
|
||||
}
|
||||
// Temps d'execution
|
||||
$this->showtime(false,"Récupérer les milestones");
|
||||
|
||||
// Récupérer les issues de gitea
|
||||
$giteaissues=$this->giteaservice->getIssues($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],"?state=".($viewclosed=="true"?"all":"open"));
|
||||
if(!is_array($giteaissues)) die("Probleme de connexion avec gitea veuillez vous <a href='/ninegitea/logout'>reconnecter</a>");
|
||||
$giteaissues=$this->giteaservice->getIssues($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],"?state=all".(!$forcereload?"&since=".urlencode($lastupdate->format(\DateTime::RFC3339_EXTENDED)):""));
|
||||
if(!is_array($giteaissues)) die("Probleme de connexion avec gitea veuillez vous <a href='/logout'>reconnecter</a>");
|
||||
|
||||
// Temps d'execution
|
||||
$this->showtime(false,"Récupérer les issues");
|
||||
|
||||
// Génération des issues
|
||||
$tbgiteaissues=[];
|
||||
$fgscrumupdate=false;
|
||||
$this->datescrumupdate=new \DateTime();
|
||||
$updatedates=[];
|
||||
|
||||
foreach($giteaissues as $giteaissue) {
|
||||
// On ne prend pas les pull request
|
||||
if(!is_null($giteaissue->pull_request)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$scrumissue=$this->_em->getRepository("App:Scrumissue")->findOneBy(["scrum"=>$scrum,"giteaid"=>$giteaissue->id]);
|
||||
|
||||
|
@ -139,56 +218,71 @@ class ScrumRepository extends ServiceEntityRepository
|
|||
$scrumissue->setScrum($scrum);
|
||||
$scrumissue->setRowid($lastrowid);
|
||||
$scrumissue->setGiteaid($giteaissue->id);
|
||||
$this->majissue($scrumissue,$giteaissue,true);
|
||||
}
|
||||
else {
|
||||
$fgissueupdated=false;
|
||||
if($scrumissue->getGiteajson()["updated_at"]!=json_decode(json_encode($giteaissue), true)["updated_at"])
|
||||
$fgissueupdated=true;
|
||||
if($scrumissue->getGiteajson()["closed_at"]!=json_decode(json_encode($giteaissue), true)["closed_at"])
|
||||
$fgissueupdated=true;
|
||||
if($giteaissue->milestone&&$scrumissue->getGiteamilestonename()!=$giteaissue->milestone->title)
|
||||
$fgissueupdated=true;
|
||||
if(!$giteaissue->milestone&&!is_null($scrumissue->getGiteamilestone()))
|
||||
$fgissueupdated=true;
|
||||
|
||||
$fgissueupdated=false;
|
||||
if($scrumissue->getGiteajson()["updated_at"]!=json_decode(json_encode($giteaissue), true)["updated_at"])
|
||||
$fgissueupdated=true;
|
||||
if($scrumissue->getGiteajson()["closed_at"]!=json_decode(json_encode($giteaissue), true)["closed_at"])
|
||||
$fgissueupdated=true;
|
||||
if($giteaissue->milestone&&$scrumissue->getGiteamilestonename()!=$giteaissue->milestone->title)
|
||||
$fgissueupdated=true;
|
||||
if(!$giteaissue->milestone&&!is_null($scrumissue->getGiteamilestone()))
|
||||
$fgissueupdated=true;
|
||||
if($forcereload) {
|
||||
$fgissueupdated=true;
|
||||
}
|
||||
|
||||
if($forcereload) {
|
||||
$fgissueupdated=true;
|
||||
}
|
||||
if($fgissueupdated) {
|
||||
$updateissue=new \DateTime(json_decode(json_encode($giteaissue), true)["updated_at"]);
|
||||
$updateissue->setTimezone(new \DateTimeZone("UTC"));
|
||||
array_push($updatedates,$updateissue);
|
||||
|
||||
if($fgissueupdated) {
|
||||
$fgscrumupdate=true;
|
||||
$this->majissue($scrumissue,$giteaissue);
|
||||
if($giteaissue->closed_at) {
|
||||
$closeissue=new \DateTime(json_decode(json_encode($giteaissue), true)["closed_at"]);
|
||||
$closeissue->setTimezone(new \DateTimeZone("UTC"));
|
||||
array_push($updatedates,$closeissue);
|
||||
}
|
||||
|
||||
$fgscrumupdate=true;
|
||||
$this->majissue($scrumissue,$giteaissue,false);
|
||||
}
|
||||
}
|
||||
array_push($tbgiteaissues,$giteaissue->number);
|
||||
}
|
||||
|
||||
// Bug faudrait placer à closed l'ensemble des issues vu comme open mais qui ne le sont plus
|
||||
if($viewclosed=="false") {
|
||||
$scrumissues=$scrum->getScrumissues();
|
||||
foreach($scrumissues as $scrumissue) {
|
||||
if($scrumissue->getGiteastate()=="open"&&!in_array($scrumissue->getGiteanumber(),$tbgiteaissues)) {
|
||||
$giteaissue=$this->giteaservice->getIssue($scrum->getGiteajson()["owner"]["login"],$scrum->getGiteajson()["name"],$scrumissue->getGiteanumber());
|
||||
$fgscrumupdate=true;
|
||||
$this->majissue($scrumissue,$giteaissue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Temps d'execution
|
||||
$this->showtime(false,"Traiter les issues");
|
||||
|
||||
if($fgscrumupdate) {
|
||||
$scrum->setUpdatedate($this->datescrumupdate);
|
||||
$this->_em->persist($scrum);
|
||||
// Convertir les objets DateTime en timestamps
|
||||
$timestamps = array_map(function($date) {
|
||||
return $date->getTimestamp();
|
||||
}, $updatedates);
|
||||
|
||||
// Trouver le timestamp le plus récent
|
||||
$mostRecentTimestamp = max($timestamps);
|
||||
|
||||
// Créer une nouvelle instance de DateTime à partir du timestamp le plus récent
|
||||
$mostRecentDate = (new \DateTime())->setTimestamp($mostRecentTimestamp);
|
||||
|
||||
// Mettre à jour la date update du scrum
|
||||
$scrum->setUpdatedate($mostRecentDate);
|
||||
$this->_em->flush();
|
||||
|
||||
// Temps d'execution
|
||||
$this->showtime(false,"Mettre à jour le scrum");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function majissue($scrumissue,$giteaissue) {
|
||||
if($scrumissue->getGiteajson()["updated_at"]>$this->datescrumupdate)
|
||||
$this->datescrumupdate=$scrumissue->getGiteajson()["updated_at"];
|
||||
|
||||
public function majissue($scrumissue,$giteaissue,$issubmit) {
|
||||
$scrumissue->setGiteanumber($giteaissue->number);
|
||||
$scrumissue->setGiteastate($giteaissue->state);
|
||||
$scrumissue->setGiteatitle($giteaissue->title);
|
||||
|
||||
if($giteaissue->milestone) {
|
||||
$scrumissue->setGiteamilestone($giteaissue->milestone->id);
|
||||
$scrumissue->setGiteamilestonename($giteaissue->milestone->title);
|
||||
|
@ -199,6 +293,27 @@ class ScrumRepository extends ServiceEntityRepository
|
|||
}
|
||||
$scrumissue->setGiteajson(json_decode(json_encode($giteaissue), true));
|
||||
|
||||
// Si le ticket est lié à un sprint on s'assure que ce sprint est bien lié au milestone du ticket
|
||||
if($scrumissue->getScrumsprint()) {
|
||||
if($scrumissue->getScrumsprint()->getGiteamilestone()!=$scrumissue->getGiteamilestone()) {
|
||||
$scrumissue->setScrumsprint(null);
|
||||
}
|
||||
}
|
||||
|
||||
$issueblock=$this->giteaservice->getissueblocks($scrumissue->getScrum()->getGiteajson()["owner"]["login"],$scrumissue->getScrum()->getGiteajson()["name"],$scrumissue->getGiteanumber());
|
||||
if($issueblock&&!empty($issueblock)) {
|
||||
$idblock=$issueblock[0]->number;
|
||||
if(!$scrumissue->getScrumissueblock()||$scrumissue->getScrumissueblock()->getGiteanumber()!=$idblock) {
|
||||
$scrumissueblock=$this->_em->getRepository('App:Scrumissue')->findOneBy(["scrum"=>$scrumissue->getScrum(),"giteanumber"=>$idblock]);
|
||||
$scrumissue->setScrumissueblock($scrumissueblock);
|
||||
}
|
||||
}
|
||||
elseif(empty($issueblock)&&$scrumissue->getScrumissueblock()) {
|
||||
$scrumissue->setScrumissueblock(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
$this->_em->persist($scrumissue);
|
||||
$this->_em->flush();
|
||||
|
||||
|
@ -223,4 +338,18 @@ class ScrumRepository extends ServiceEntityRepository
|
|||
$this->_em->persist($scrumissue);
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
private function getMaxDate(\DateTime ...$dates): \DateTime {
|
||||
// Initialiser la date maximale avec la première date de la liste
|
||||
$maxDate = $dates[0];
|
||||
|
||||
// Comparer chaque date avec la date maximale actuelle
|
||||
foreach ($dates as $date) {
|
||||
if ($date > $maxDate) {
|
||||
$maxDate = $date;
|
||||
}
|
||||
}
|
||||
|
||||
return $maxDate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,14 +33,56 @@ class giteaService
|
|||
|
||||
|
||||
$response=$this->api("POST",$apiurl,$body);
|
||||
|
||||
if(!$response||$response->code!="200") return false;
|
||||
else {
|
||||
$this->session->set('giteatoken', $response->body->access_token);
|
||||
$this->session->set('gitearefreshtoken', $response->body->refresh_token);
|
||||
|
||||
$date = new \DateTime();
|
||||
$date->modify('+'.$response->body->expires_in.' seconds');
|
||||
$this->session->set('gitearefreshdate',$date);
|
||||
|
||||
return $response->body->access_token;
|
||||
}
|
||||
}
|
||||
|
||||
public function refreshtoken() {
|
||||
$apiurl = $this->params->get("oauthTokenurl");
|
||||
$query= [
|
||||
"client_id" => $this->params->get("oauthClientid"),
|
||||
"client_secret" => $this->params->get("oauthClientsecret"),
|
||||
"code" => $this->session->get("giteacode"),
|
||||
"grant_type" => "refresh_token",
|
||||
"refresh_token" => $this->session->get('gitearefreshtoken'),
|
||||
];
|
||||
$body = \Unirest\Request\Body::json($query);
|
||||
|
||||
|
||||
$response=$this->api("POST",$apiurl,$body);
|
||||
if(!$response||$response->code!="200") return false;
|
||||
else {
|
||||
$this->session->set('giteatoken', $response->body->access_token);
|
||||
$this->session->set('gitearefreshtoken', $response->body->refresh_token);
|
||||
|
||||
$date = new \DateTime();
|
||||
$date->modify('+'.$response->body->expires_in.' seconds');
|
||||
$this->session->set('gitearefreshdate',$date);
|
||||
|
||||
return $response->body->access_token;
|
||||
}
|
||||
}
|
||||
|
||||
public function needrefresh() {
|
||||
$date = new \DateTime();
|
||||
|
||||
// On refresh 15 minutes avant le terme
|
||||
$refreshdate=clone $this->session->get('gitearefreshdate');
|
||||
$refreshdate->modify('-900 seconds');
|
||||
|
||||
if($date>$refreshdate) return $this->refreshtoken();
|
||||
else return $this->session->get('giteatoken');
|
||||
}
|
||||
|
||||
public function deletetoken($username) {
|
||||
$apiurl=$this->url."/users/".$username."/tokens/".$this->session->get("giteatoken");
|
||||
$response=$this->api("DELETE",$apiurl,null,$this->session->get("giteatoken"));
|
||||
|
@ -61,7 +103,7 @@ class giteaService
|
|||
$response=$this->api("POST",$apiurl,$body,$this->session->get("giteatoken"));
|
||||
if(!$response||$response->code!="200") return false;
|
||||
else {
|
||||
$response->body= str_replace($this->giteaUrl,$this->giteaUrl.$context,$response->body);
|
||||
//$response->body= str_replace($this->giteaUrl,$this->giteaUrl.$context,$response->body);
|
||||
return $response->body;
|
||||
}
|
||||
}
|
||||
|
@ -181,6 +223,13 @@ class giteaService
|
|||
else return $response->body;
|
||||
}
|
||||
|
||||
public function getassignees($owner,$name) {
|
||||
$apiurl = $this->url."/repos/$owner/$name/assignees";
|
||||
$response=$this->api("GET",$apiurl,null,$this->session->get("giteatoken"));
|
||||
if(!$response||$response->code!="200") return false;
|
||||
else return $response->body;
|
||||
}
|
||||
|
||||
public function getcollaborators($owner,$name) {
|
||||
$apiurl = $this->url."/repos/$owner/$name/collaborators";
|
||||
$response=$this->api("GET",$apiurl,null,$this->session->get("giteatoken"));
|
||||
|
@ -202,9 +251,15 @@ class giteaService
|
|||
else return $response->body;
|
||||
}
|
||||
|
||||
public function getissues($owner,$name,$state="?state=open") {
|
||||
$apiurl = $this->url."/repos/$owner/$name/issues".$state;
|
||||
public function getmilestone($owner,$name,$id) {
|
||||
$apiurl = $this->url."/repos/$owner/$name/milestones/".$id;
|
||||
$response=$this->api("GET",$apiurl,null,$this->session->get("giteatoken"));
|
||||
if(!$response||$response->code!="200") return false;
|
||||
else return $response->body;
|
||||
}
|
||||
|
||||
public function getissues($owner,$name,$state="?state=open") {
|
||||
$apiurl = $this->url."/repos/$owner/$name/issues".$state.($state==""?"?":"&")."type=issues";
|
||||
$page=1;
|
||||
$limit=20;
|
||||
$issues=[];
|
||||
|
@ -268,7 +323,6 @@ class giteaService
|
|||
else return $response->body;
|
||||
}
|
||||
|
||||
|
||||
public function getissuetimelines($owner,$name,$index) {
|
||||
$apiurl = $this->url."/repos/$owner/$name/issues/$index/timeline";
|
||||
$response=$this->api("GET",$apiurl,null,$this->session->get("giteatoken"));
|
||||
|
@ -276,13 +330,44 @@ class giteaService
|
|||
else return $response->body;
|
||||
}
|
||||
|
||||
public function getissueblocks($owner,$name,$index) {
|
||||
$apiurl = $this->url."/repos/$owner/$name/issues/$index/blocks";
|
||||
$response=$this->api("GET",$apiurl,null,$this->session->get("giteatoken"));
|
||||
if(!$response||$response->code!="200") return false;
|
||||
else return $response->body;
|
||||
}
|
||||
|
||||
public function postissueblocks($owner,$name,$index,$toblock) {
|
||||
$apiurl = $this->url."/repos/$owner/$name/issues/$index/blocks";
|
||||
$query= ["index" => $toblock,"owner" => $owner, "repo" => $name];
|
||||
$body = \Unirest\Request\Body::json($query);
|
||||
$body=str_replace('"'.$toblock.'"',$toblock,$body);
|
||||
$response=$this->api("POST",$apiurl,$body,$this->session->get("giteatoken"));
|
||||
if(!$response||($response->code!="200"&&$response->code!="201")) return false;
|
||||
else return $response->body;
|
||||
}
|
||||
|
||||
public function deleteissueblocks($owner,$name,$index,$toblock) {
|
||||
$apiurl = $this->url."/repos/$owner/$name/issues/$index/blocks";
|
||||
$query= ["index" => $toblock,"owner" => $owner, "repo" => $name];
|
||||
$body = \Unirest\Request\Body::json($query);
|
||||
$body=str_replace('"'.$toblock.'"',$toblock,$body);
|
||||
$response=$this->api("DELETE",$apiurl,$body,$this->session->get("giteatoken"));
|
||||
if(!$response||$response->code!="201") return false;
|
||||
else return $response->body;
|
||||
}
|
||||
|
||||
private function api($method,$url,$query,$token=null) {
|
||||
// Entete
|
||||
$headers = [
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
];
|
||||
if($token) $headers["Authorization"]="token ".$token;
|
||||
|
||||
if($token) {
|
||||
$token=$this->needrefresh();
|
||||
$headers["Authorization"]="token ".$token;
|
||||
}
|
||||
|
||||
// Paramétrage unirest
|
||||
\Unirest\Request::verifyPeer(false);
|
||||
|
|
|
@ -3,6 +3,7 @@ namespace App\Twig;
|
|||
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
class AppExtension extends AbstractExtension
|
||||
{
|
||||
|
@ -15,6 +16,13 @@ class AppExtension extends AbstractExtension
|
|||
];
|
||||
}
|
||||
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('microtime', [$this, 'getMicrotime']),
|
||||
];
|
||||
}
|
||||
|
||||
public function urlAvatar($avatar)
|
||||
{
|
||||
if(stripos($avatar,"http")===0)
|
||||
|
@ -23,6 +31,11 @@ class AppExtension extends AbstractExtension
|
|||
return $this->container->getParameter("appAlias")."uploads/avatar/".$avatar;
|
||||
}
|
||||
|
||||
public function getMicrotime($asFloat = true)
|
||||
{
|
||||
return microtime($asFloat);
|
||||
}
|
||||
|
||||
public function setContainer($container)
|
||||
{
|
||||
$this->container = $container;
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
resizewidth=$('#largeimg').width();
|
||||
|
||||
$('#largeimg').CropSelectJs({
|
||||
imageSrc: "/{{ appAlias }}/uploads/{{type}}/{{ file }}",
|
||||
imageSrc: "{{ asset("uploads/"~type~"/"~file) }}",
|
||||
selectionResize: function(data) { resize(data); },
|
||||
selectionMove: function(data) { move(data); },
|
||||
});
|
||||
|
|
|
@ -33,6 +33,8 @@ function ModalLoad(idmodal,title,path) {
|
|||
}
|
||||
|
||||
{% if wssuse %}
|
||||
console.log("pouet");
|
||||
|
||||
function subscribe(channeltype,channelkey,userkey) {
|
||||
console.log("== SUBSCRIBE "+channeltype+"-"+channelkey+" with userkey "+userkey);
|
||||
conn.send(JSON.stringify({
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
--colorfttitlelight-darker: {{ app.session.get('colorfttitlelight-darker')|raw }};
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
/* COLOR BODY */
|
||||
|
||||
body {
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
{% for comment in issue.comments %}
|
||||
<h3 class='mt-3'>{{comment.user.login}} le {{comment.created_at|date("d/m/Y H:i")}}</h3>
|
||||
<div class='card card-body'>
|
||||
{{comment.body|markdown_to_html}}
|
||||
{{comment.body|raw}}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
@ -86,7 +86,7 @@
|
|||
<div class='card card-body mb-3'>
|
||||
|
||||
{% for timeline in issue.timelines %}
|
||||
{% if timeline.type!="comment" and timeline.type!="project" and timeline.type!="added_deadline" and timeline.type!="modified_deadline"%}
|
||||
{% if timeline.type!="comment" and timeline.type!="project" and timeline.type!="added_deadline" and timeline.type!="modified_deadline" and timeline.type!="label" %}
|
||||
<li><b>{{timeline.user.login}} le {{timeline.created_at|date("d/m/Y H:i")}}</b><br>
|
||||
|
||||
{% if timeline.type == "change_title" %}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{% extends "base.html.twig" %}
|
||||
|
||||
{% block body %}
|
||||
{% set statut="" %}
|
||||
{% set milestone="" %}
|
||||
{% for issue in issues %}
|
||||
{% if statut!=issue.statut %}
|
||||
<p> </p>
|
||||
<h2>{{issue.statut}}</h2>
|
||||
{% set statut=issue.statut %}
|
||||
{% set milestone="" %}
|
||||
{% endif %}
|
||||
|
||||
{% if milestone!=issue.milestone %}
|
||||
<p> </p>
|
||||
<h3>{{issue.milestone}}</h3>
|
||||
{% set milestone=issue.milestone %}
|
||||
{% endif %}
|
||||
|
||||
<li>{{issue.id}} = {{ issue.title }}</li>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<i class="fa fa-pencil-alt fa-fw"></i> Informations
|
||||
</div>
|
||||
|
@ -57,6 +57,26 @@
|
|||
{{ form_row(form.users) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if mode=="update" %}
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<i class="fa fa-pencil-alt fa-fw"></i> Sprints
|
||||
<button id="addsprint" type="button" class="btn float-right fa fa-plus"></button>
|
||||
|
||||
<div class="custom-control custom-switch float-right">
|
||||
<input type="checkbox" class="custom-control-input" id="viewsprintclosed">
|
||||
<label class="custom-control-label" for="viewsprintclosed">Afficher les sprint clos</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="scrumsprints" class="card-body">
|
||||
<ol id="scrumsprints" class="list-group list-group-numbered">
|
||||
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if mode=="update" %}
|
||||
|
@ -185,6 +205,23 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mymodalsprint" class="modal" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title"></h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<iframe frameborder=0 width="100%" height="600px"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block localjavascript %}
|
||||
|
@ -196,6 +233,7 @@
|
|||
loadscrumteams();
|
||||
loadscrumprioritys();
|
||||
loadscrumtypes();
|
||||
loadscrumsprints();
|
||||
{%endif%}
|
||||
});
|
||||
|
||||
|
@ -376,6 +414,85 @@
|
|||
});
|
||||
}
|
||||
|
||||
$("#addsprint").click(function() {
|
||||
ModalLoad('mymodalsprint','Ajouter un sprint','{{path('app_scrumsprint_submit',{scrumid:scrum.id})}}');
|
||||
});
|
||||
|
||||
$('#scrumsprints').on('click', '.modsprint', function(event) {
|
||||
url="{{path('app_scrumsprint_update',{id:'xxx'})}}";
|
||||
url=url.replace("xxx",$(this).data("id"));
|
||||
ModalLoad('mymodalsprint','Modifier un sprint',url);
|
||||
});
|
||||
|
||||
$('#mymodalsprint').on('hidden.bs.modal', function () {
|
||||
loadscrumsprints();
|
||||
});
|
||||
|
||||
$('#viewsprintclosed').change(function() {
|
||||
if(this.checked) {
|
||||
$(".sprintclosed").removeClass("hidden");
|
||||
}
|
||||
else {
|
||||
$(".sprintclosed").addClass("hidden");
|
||||
}
|
||||
});
|
||||
|
||||
function loadscrumsprints() {
|
||||
$("#scrumsprints").empty();
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumsprint_select",{scrumid:scrum.id})}}",
|
||||
success: function(datas, dataType)
|
||||
{
|
||||
jQuery.each(datas, function(i, wid) {
|
||||
style='';
|
||||
classname='';
|
||||
if(wid.closed) {
|
||||
style='background-color:#cdcdcd;';
|
||||
classname='sprintclosed';
|
||||
if(!$("#viewsprintclosed").is(':checked')) {
|
||||
classname+=' hidden';
|
||||
}
|
||||
}
|
||||
|
||||
html ='<li data-id="'+wid.id+'" class="list-group-item d-flex justify-content-between '+classname+'" style="'+style+'">';
|
||||
html+='<div>';
|
||||
html+='<div class="mr-3 p-2 d-inline-block"><i class="fas fa-arrows-alt-v fa-2x"></i></div>';
|
||||
html+='<div class="d-inline-block">';
|
||||
html+=wid.name;
|
||||
html+='</div>';
|
||||
html+='</div>';
|
||||
html+='<button type="button" data-id="'+wid.id+'" class="modsprint btn float-right fa fa-file"></button>';
|
||||
html+='</li>';
|
||||
$("#scrumsprints").append(html);
|
||||
|
||||
});
|
||||
|
||||
$( "#scrumsprints" ).sortable({
|
||||
axis: "y",
|
||||
handle: ".fa-arrows-alt-v",
|
||||
update: function( event, ui ) {
|
||||
lstordered="";
|
||||
$( "#scrumsprints li" ).each(function( index ) {
|
||||
if(index==0) lstordered=$(this).data("id");
|
||||
else lstordered=lstordered+","+$(this).data("id");
|
||||
});
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumsprint_order",{scrumid:scrum.id})}}",
|
||||
data: {
|
||||
lstordered:lstordered
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$("#addtype").click(function() {
|
||||
ModalLoad('mymodaltype','Ajouter une colonne','{{path('app_scrumtype_submit',{scrumid:scrum.id})}}');
|
||||
});
|
||||
|
|
|
@ -0,0 +1,264 @@
|
|||
{% extends "base.html.twig" %}
|
||||
|
||||
{% block localstyle %}
|
||||
.issuecontent {
|
||||
width:75%;
|
||||
}
|
||||
.issuedetail {
|
||||
width:25%;
|
||||
padding-right: 10px;
|
||||
zoom:80%;
|
||||
}
|
||||
|
||||
.text-small {
|
||||
font-size:80%;
|
||||
}
|
||||
|
||||
.card-header, .card-body {
|
||||
padding:10px;
|
||||
background-color: var(--colorbgbodylight-darker);
|
||||
}
|
||||
|
||||
.issue-body {
|
||||
zoom: 80%;
|
||||
}
|
||||
|
||||
.badge {
|
||||
color: white;
|
||||
zoom:120%;
|
||||
}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<h3 id='issuetitle{{issue.number}}' class='issuetitle'>#{{issue.number}} = {{issue.title}}</h3>
|
||||
|
||||
<div id='issuediv{{issue.number}}' class='d-flex'>
|
||||
<div class='issuecontent' class='d-flex flex-column'>
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card-header d-flex">
|
||||
<div class="flex-grow-1">{{issue.user.login}}</div>
|
||||
<div class="text-small"> le {{issue.created_at|date("d/m/Y H:i")}}</div>
|
||||
</div>
|
||||
<div class='card-body issue-body'>
|
||||
{{issue.body|raw}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if issue.comments %}
|
||||
{% for comment in issue.comments %}
|
||||
<div class="card mb-3">
|
||||
<div class="card-header d-flex">
|
||||
<div class="flex-grow-1">{{comment.user.login}}</div>
|
||||
<div class="text-small"> le {{comment.created_at|date("d/m/Y H:i")}}</div>
|
||||
</div>
|
||||
|
||||
<div class='card-body issue-body'>
|
||||
{{comment.body|raw}}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class='pl-3 issuedetail'>
|
||||
<a target="_blank" class="btn btn-success w-100 mb-3" href="{{issue.html_url}}" style="zoom:120%">Modifier dans Gitea</a>
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="modissu card-header d-flex" style="cursor:pointer">
|
||||
<div class="flex-grow-1"><i class="fas fa-weight-hanging"></i></div>
|
||||
<div>{{ issue.weight }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='card mb-3'>
|
||||
<div class="card-header">Statut</div>
|
||||
<div class="card-body">
|
||||
{% if issue.closed_at %}
|
||||
Clos le {{issue.closed_at|date("d/m/Y H:i")}}
|
||||
{% else %}
|
||||
{{issue.statuslife}}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='card mb-3'>
|
||||
<div class="card-header">Jalon</div>
|
||||
<div class="card-body">
|
||||
{% if issue.milestone %}
|
||||
{{ issue.milestone.title|raw }}
|
||||
{% else %}
|
||||
Backlog
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if issue.sprint %}
|
||||
<div class='card mb-3'>
|
||||
<div class="card-header">Sprint</div>
|
||||
<div class="card-body">
|
||||
{{ issue.sprint }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if issue.refs %}
|
||||
<div class='card mb-3'>
|
||||
<div class="card-header">Références</div>
|
||||
<div class='card-body mb-3'>
|
||||
{% for histo in issue.refs %}
|
||||
<div>
|
||||
{{histo.label|raw}}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if issue.labels %}
|
||||
<div class='card mb-3'>
|
||||
<div class="card-header">Labels</div>
|
||||
<div class='card-body mb-3'>
|
||||
{% for label in issue.labels %}
|
||||
<span class='badge mr-1 mb-1 p-2' style='background-color:#{{label.color}}'>{{label.name}}</span>
|
||||
{% endfor %}
|
||||
|
||||
{% for histo in issue.labelhistos %}
|
||||
<div class="mt-1">
|
||||
<b>{{histo.user.login}} le {{histo.created_at|date("d/m/Y H:i")}}</b><br>
|
||||
{{histo.label|raw}}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if issue.timelines %}
|
||||
<div class='card mb-3'>
|
||||
<div class="card-header">Historique</div>
|
||||
<div class="card-body">
|
||||
{% for timeline in issue.timelines %}
|
||||
{% if timeline.type!="label" and timeline.type!="comment" and timeline.type!="project" and timeline.type!="added_deadline" and timeline.type!="modified_deadline"%}
|
||||
<li><b>{{timeline.user.login}} le {{timeline.created_at|date("d/m/Y H:i")}}</b><br>
|
||||
|
||||
{% if timeline.type == "change_title" %}
|
||||
<div class='pl-4'>Modification titre de <i>{{timeline.old_title}}</i> à <i>{{timeline.new_title}}</i></div>
|
||||
|
||||
{% elseif timeline.type == "milestone" %}
|
||||
{% if timeline.milestone %}
|
||||
<div class='pl-4'>Affectation au Jalon <i>{{timeline.milestone.title}}</i></div>
|
||||
{% else %}
|
||||
<div class='pl-4'>Suppression du Jalon</div>
|
||||
{% endif %}
|
||||
|
||||
{% elseif timeline.type == "comment_ref" or timeline.type == "pull_ref" or timeline.type == "issue_ref" %}
|
||||
<div class='pl-4'>Référencé le ticket <i>#{{timeline.ref_issue.number}} - {{timeline.ref_issue.title}}</i></div>
|
||||
|
||||
{% elseif timeline.type == "add_dependency" %}
|
||||
<div class='pl-4'>Ajouté dépendance au ticket <i>#{{timeline.dependent_issue.number}} - {{timeline.dependent_issue.title}}</i></div>
|
||||
|
||||
{% elseif timeline.type == "remove_dependency" %}
|
||||
<div class='pl-4'>Supprimé dépendance au ticket <i>#{{timeline.dependent_issue.number}} - {{timeline.dependent_issue.title}}</i></div>
|
||||
|
||||
{% elseif timeline.type == "pull_push" %}
|
||||
<div class='pl-4'>Ajout révision</i></div>
|
||||
|
||||
{% elseif timeline.type == "assignees" %}
|
||||
<div class='pl-4'>Affecté intervenant <i>{{timeline.assignee.login}}</i></div>
|
||||
|
||||
{% elseif timeline.type == "commit_ref" %}
|
||||
<div class='pl-4'>Référencé depuis commit <i>#{{timeline.body|replace({'href="/':'target="_blank" href="'~giteaUrl~'/'})|raw}}</i></div>
|
||||
|
||||
{% elseif timeline.type == "merge_pull" %}
|
||||
<div class='pl-4'>Révision fusionnée</div>
|
||||
|
||||
{% elseif timeline.type == "delete_branch" %}
|
||||
<div class='pl-4'>Suppression branche {{timeline.old_ref|raw}}</div>
|
||||
|
||||
{% elseif timeline.type == "close" %}
|
||||
<div class='pl-4'>Clos <i>Fermeture du ticket</i></div>
|
||||
|
||||
{% elseif timeline.type == "review" %}
|
||||
<div class='pl-4'>Revue acceptée</div>
|
||||
|
||||
{% elseif timeline.type == "review_request" %}
|
||||
<div class='pl-4'>Demande de révision</div>
|
||||
|
||||
{% elseif timeline.type == "reopen" %}
|
||||
<div class='pl-4'>Réouverture du ticket</div>
|
||||
|
||||
{% else %}
|
||||
{{ dump(timeline) }}
|
||||
{%endif%}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mymodalissue" class="modal" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Estimation</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group ">
|
||||
<label class="control-label required" for="issu_weight">
|
||||
Poid
|
||||
</label>
|
||||
<input type="hidden" id="modal-issueid" name="modal-issueid" required="required" class=" form-control" value="">
|
||||
<input type="number" placeholder="0.0" step="0.1" id="modal-issueweight" name="modal-issueweight" required="required" class=" form-control" value="">
|
||||
</div>
|
||||
<button id="issu_update" class="btn btn-success">Enregistrer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block localjavascript %}
|
||||
$(document).on('click','.modissu',function(){
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_info")}}",
|
||||
data: {
|
||||
id:{{issue.nineid}},
|
||||
},
|
||||
success: function(data) {
|
||||
$("#modal-issueweight").val(data.weight);
|
||||
$("#mymodalissue").modal('show');
|
||||
$("#modal-issueweight").focus();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
$("#issu_update").click(function(){
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_update")}}",
|
||||
data: {
|
||||
id:{{issue.nineid}},
|
||||
weight:$("#modal-issueweight").val(),
|
||||
},
|
||||
success: function(data) {
|
||||
parent.$(".issue{{issue.nineid}}-weight").html($("#modal-issueweight").val());
|
||||
window.parent.refreshinfo();
|
||||
location.reload();
|
||||
},
|
||||
error: function (request, status, error) {
|
||||
$("#mymodalissue").modal('hide');
|
||||
}
|
||||
});
|
||||
});
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<h1>{{scrum.name}}</h1>
|
||||
|
||||
<div class="form-group ">
|
||||
<label class="control-label required" for="scrum_category">
|
||||
Le ticket n°
|
||||
<span class="mandatory">*</span>
|
||||
</label>
|
||||
|
||||
<select id="issue" class="form-control">
|
||||
<option value="" selected></option>
|
||||
{% for issue in scrum.scrumissues %}
|
||||
<option value="{{issue.id}}">#{{issue.giteanumber}} = {{issue.giteatitle}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group ">
|
||||
<label class="control-label required" for="scrum_category">
|
||||
bloque / débloque le ticket n°
|
||||
<span class="mandatory">*</span>
|
||||
</label>
|
||||
|
||||
<select id="block" class="form-control">
|
||||
<option value="" selected></option>
|
||||
{% for issue in scrum.scrumissues %}
|
||||
<option value="{{issue.giteanumber}}">#{{issue.giteanumber}} = {{issue.giteatitle}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button onClick="lock()" class="btn btn-success">Bloque</button>
|
||||
<button onClick="unlock()" class="btn btn-success">Débloque</button>
|
||||
{% endblock %}
|
||||
|
||||
{% block localjavascript %}
|
||||
$(document).ready(function() {
|
||||
$("#issue").select2();
|
||||
$("#block").select2();
|
||||
});
|
||||
|
||||
function lock() {
|
||||
console.log($("#issue").val());
|
||||
console.log($("#block").val());
|
||||
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_block")}}",
|
||||
data: {
|
||||
id:$("#issue").val(),
|
||||
issueblocked:$("#block").val(),
|
||||
},
|
||||
success: function(data) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function unlock() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_unblock")}}",
|
||||
data: {
|
||||
id:$("#issue").val(),
|
||||
},
|
||||
success: function(data) {
|
||||
}
|
||||
});
|
||||
}
|
||||
{% endblock %}
|
|
@ -5,10 +5,9 @@
|
|||
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-start mt-3">
|
||||
|
||||
<div class="pr-2">
|
||||
{% if app.user and is_granted('ROLE_MASTER') %}
|
||||
<a class="btn btn-success btn-sm mt-2" href={{ path('app_scrum_submit') }}><i class="fa fa-plus mr-2"></i>Ajouter un Scrum</a>
|
||||
<a class="btn btn-success btn-sm d-flex" style="height:69px; justify-content: center; flex-direction: column" href={{ path('app_scrum_submit') }}><i class="fa fa-plus mr-2"></i>Ajouter un Scrum</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
@ -47,7 +46,7 @@
|
|||
<tr data-category="{{scrum.category}}" data-repo="{{scrum.giteaid}}">
|
||||
<td>
|
||||
<a href="{{path('app_scrum_view',{id:scrum.id})}}"><i class="fas fa-columns fa-2x mr-1"></i></a>
|
||||
<a href="{{path('app_issuescrum',{id:scrum.id})}}"><i class="fas fa-ticket-alt fa-2x mr-1"></i></a>
|
||||
<a href="{{path('app_scrum_table',{id:scrum.id})}}"><i class="fas fa-ticket-alt fa-2x mr-1"></i></a>
|
||||
<a href="{{path('app_scrum_stat',{id:scrum.id})}}"><i class="fas fa-chart-area fa-2x mr-1"></i></a>
|
||||
|
||||
{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_MODO') or is_granted('ROLE_MASTER') %}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
.flot-chart-subcontent {
|
||||
height: 200px;
|
||||
width: 40%;
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
{% endblock %}
|
||||
|
@ -37,52 +37,79 @@
|
|||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
<div style="width:100%" class="mt-3">
|
||||
<label class="control-label" style="color:var(--colorftbodydark)">Filtre EQUIPES</label>
|
||||
<select id="filterteams" multiple="multiple" class="form-control">
|
||||
{% for team in scrum.scrumteams %}
|
||||
<option value="{{team.giteaid}}">{{team.name}}</option>
|
||||
<label class="control-label" style="color:var(--colorftbodydark)">Filtre SPRINT</label>
|
||||
<select id="filtersprints" multiple="multiple" class="form-control">
|
||||
{% for sprint in sprints %}
|
||||
<option value="{{sprint.giteamilestone~"-"~sprint.id}}">{{sprint.giteamilestonename}}-{{sprint.name}}</option>
|
||||
{% endfor %}
|
||||
{% for giteamilestone in giteamilestones %}
|
||||
<option value="{{giteamilestone.id~"--100"}}">{{giteamilestone.title}}-Aucun</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style="width:100%" class="mt-3">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="filterbynumber">
|
||||
<label class="custom-control-label" for="filterbynumber" style="color:var(--colorfttitledark);">Vue par {{ (filterbynumber=="true"?"nombre":"poids") }} de tickets</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pl-3" style="width:100%;">
|
||||
<div class="mt-4 mb-3" style="zoom:80%">
|
||||
<button class="btn btn-success" onClick="showFilters()"><i class="fas fa-filter"></i></button>
|
||||
<a class="btn btn-success" href="{{path('app_scrum_view',{id:scrum.id})}}"><i class="fas fa-columns"></i></a>
|
||||
<a class="btn btn-success" href="{{path('app_issuescrum',{id:scrum.id})}}"><i class="fas fa-ticket-alt"></i></a>
|
||||
<a class="btn btn-success" href="{{path('app_scrum_table',{id:scrum.id})}}"><i class="fas fa-ticket-alt"></i></a>
|
||||
<span id="textfilters"></span>
|
||||
</div>
|
||||
|
||||
<h1>{{ scrum.name }}</h1>
|
||||
|
||||
<div class="d-flex flex-column mt-4">
|
||||
{% for milestone in tbstat %}
|
||||
<div class="flot-chart mr-4" data-milestone="{{ milestone.id }}">
|
||||
<h4>{{milestone.name}}</h4>
|
||||
<div class="mt-4">
|
||||
<div id="floatdonut{{ milestone.id }}" class="flot-chart-content" style="float:left"></div>
|
||||
<div class="mt-3 pb-3" style="width:100%">
|
||||
<div id="tbestim" class="d-flex flex-column mt-4">
|
||||
|
||||
<div class="d-flex justify-content-between mt-4">
|
||||
{% for column in milestone.stat %}
|
||||
<div style="width:250px">
|
||||
<div style="background-color:{{column.color}}; padding:3px;margin-bottom:3px;">{{ column.label }} = {{ column.total }}</div>
|
||||
<small>
|
||||
<div style="line-height:15px; width:100%">
|
||||
{% for label in column.labels %}
|
||||
<li >{{label.label}} = {{label.total}}</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</small>
|
||||
{% for jalon in tbestim %}
|
||||
{% if jalon.nbjrs>0 %}
|
||||
<div class="card mb-4" data-milestone="{{ jalon.idjal }}">
|
||||
<div class="card-header">{{jalon.nmjal}}</div>
|
||||
<div class="card-body d-flex justify-content-center">
|
||||
<div class="d-flex flex-column">
|
||||
<div class="ustify-content-center" style="display:flex" data-graphmilestone="{{ jalon.idjal }}">
|
||||
<div id="floatdonut{{ jalon.idjal }}" class="flot-chart-content"></div>
|
||||
<div style="min-width:250px; color: #ffffff; padding: 3px;">
|
||||
{% for column in jalon.columns %}
|
||||
<div style="padding: 3px; background-color:#{{column.color}}">{{column.nmcol}}<span class="float-right">{{(filterbynumber=="true"?column.nbiss:column.nbjrs)}} = {{((filterbynumber=="true"?column.nbiss:column.nbjrs) * 100 / (filterbynumber=="true"?jalon.nbiss:jalon.nbjrs))|number_format}}%</<span></div>
|
||||
{% endfor %}
|
||||
<div style="padding: 3px;color: #000">TOTAL<span class="float-right">{{(filterbynumber=="true"?jalon.nbiss:jalon.nbjrs)}} = 100%</<span></div>
|
||||
</div>
|
||||
</div>
|
||||
{%endfor%}
|
||||
<div class="d-flex flex-wrap justify-content-center">
|
||||
{% for sprint in jalon.sprints %}
|
||||
{% if jalon.nbjrs != sprint.nbjrs and sprint.nbjrs>0 %}
|
||||
<div class="card mt-4 mr-4" data-sprint="{{ jalon.idjal~"-"~sprint.idspr }}">
|
||||
<div class="card-header">{{sprint.nmspr}}</div>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<div id="floatdonut{{ jalon.idjal~"-"~sprint.idspr }}" class="flot-chart-subcontent" style="float:left"></div>
|
||||
<div class="mt-3" style="color: #ffffff;">
|
||||
{% for column in sprint.columns %}
|
||||
<div style="padding: 3px; background-color:#{{column.color}}">{{column.nmcol}}<span class="float-right">{{(filterbynumber=="true"?column.nbiss:column.nbjrs)}} = {{((filterbynumber=="true"?column.nbiss:column.nbjrs) * 100 / (filterbynumber=="true"?sprint.nbiss:sprint.nbjrs))|number_format}}%</<span></div>
|
||||
{% endfor %}
|
||||
<div style="padding: 3px;color: #000">TOTAL<span class="float-right">{{(filterbynumber=="true"?sprint.nbiss:sprint.nbjrs)}} = 100%</<span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -90,6 +117,25 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block localjavascript %}
|
||||
// View par nombre de tickets
|
||||
{% if filterbynumber %}
|
||||
$("#filterbynumber").prop( "checked", {{ filterbynumber }} )
|
||||
{% endif %}
|
||||
|
||||
$('#filterbynumber').change(function() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{ path('app_user_preference') }}",
|
||||
data: {
|
||||
key:'filterbynumber',
|
||||
id:{{scrum.id}},
|
||||
value: this.checked
|
||||
}
|
||||
}).done(function( data ) {
|
||||
location.reload();
|
||||
});
|
||||
});
|
||||
|
||||
function showFilters() {
|
||||
if($("#filters").hasClass("d-flex")) {
|
||||
toshow=0;
|
||||
|
@ -116,13 +162,28 @@
|
|||
$(document).ready(function() {
|
||||
// Apply Filter
|
||||
function showhide() {
|
||||
// Afficher masquer les jalons
|
||||
if($("#filtermilestones").val().length !== 0) {
|
||||
$("[data-milestone]").hide();
|
||||
$.each($("#filtermilestones").val(), function( index, value ) {
|
||||
$("[data-milestone="+value+"]").show();
|
||||
$("[data-graphmilestone="+value+"]").show();
|
||||
});
|
||||
}
|
||||
else $("[data-milestone]").show();
|
||||
else {
|
||||
$("[data-milestone]").show();
|
||||
$("[data-graphmilestone]").show();
|
||||
}
|
||||
|
||||
// Afficher masquer les sprints
|
||||
if($("#filtersprints").val().length !== 0) {
|
||||
$("[data-sprint]").hide();
|
||||
$("[data-graphmilestone]").hide();
|
||||
$.each($("#filtersprints").val(), function( index, value ) {
|
||||
$("[data-sprint="+value+"]").show();
|
||||
});
|
||||
}
|
||||
else if($("#filtermilestones").val().length === 0)$("[data-sprint]").show();
|
||||
|
||||
textfilters="";
|
||||
if($("#filtermilestones").val().length!==0) {
|
||||
|
@ -134,10 +195,10 @@
|
|||
});
|
||||
}
|
||||
|
||||
if($("#filterteams").val().length!==0) {
|
||||
data = $("#filterteams").select2('data');
|
||||
textfilters=textfilters+" <b>EQUIPES</b> =";
|
||||
$.each($("#filterteams").val(), function( index, value ) {
|
||||
if($("#filtersprints").val().length!==0) {
|
||||
data = $("#filtersprints").select2('data');
|
||||
textfilters=textfilters+" <b>SPRINT</b> =";
|
||||
$.each($("#filtersprints").val(), function( index, value ) {
|
||||
if(index>0)textfilters=textfilters+" &";
|
||||
textfilters=textfilters+" "+data[index].text;
|
||||
});
|
||||
|
@ -175,46 +236,47 @@
|
|||
filtermilestones();
|
||||
});
|
||||
|
||||
// Filter Teams
|
||||
function filterteams() {
|
||||
// Filter Sprints
|
||||
function filtersprints() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{ path('app_user_preference') }}",
|
||||
data: {
|
||||
key:'filterteams',
|
||||
key:'filtersprints',
|
||||
id:{{scrum.id}},
|
||||
value: $("#filterteams").val()
|
||||
value: $("#filtersprints").val()
|
||||
}
|
||||
});
|
||||
|
||||
location.reload();
|
||||
showhide();
|
||||
}
|
||||
$('#filterteams').select2();
|
||||
{% if filterteams %}
|
||||
{% for team in filterteams %}
|
||||
$("#filterteams").val($("#filterteams").val().concat("{{team}}"));
|
||||
|
||||
$('#filtersprints').select2();
|
||||
{% if filtersprints %}
|
||||
{% for sprint in filtersprints %}
|
||||
$("#filtersprints").val($("#filtersprints").val().concat("{{sprint}}"));
|
||||
{%endfor%}
|
||||
$('#filterteams').trigger('change');
|
||||
$('#filtersprints').trigger('change');
|
||||
{% endif %}
|
||||
$('#filterteams').on("select2:select", function(e) {
|
||||
filterteams();
|
||||
$('#filtersprints').on("select2:select", function(e) {
|
||||
filtersprints();
|
||||
});
|
||||
$('#filterteams').on("select2:unselect", function(e) {
|
||||
filterteams();
|
||||
$('#filtersprints').on("select2:unselect", function(e) {
|
||||
filtersprints();
|
||||
});
|
||||
|
||||
{% for milestone in tbstat %}
|
||||
{% for jalon in tbestim %}
|
||||
var data = [
|
||||
{% for data in milestone.stat %}
|
||||
{% for column in jalon.columns %}
|
||||
{
|
||||
label: "{{ data.label}}",
|
||||
data: {{ data.total }},
|
||||
color: "{{ data.color }}",
|
||||
label: "{{ column.nmcol}}",
|
||||
data: {{ column.nbiss }},
|
||||
color: "#{{ column.color }}",
|
||||
},
|
||||
{% endfor %}
|
||||
];
|
||||
|
||||
var plotObj = $.plot($("#floatdonut{{ milestone.id }}"), data, {
|
||||
var plotObj = $.plot($("#floatdonut{{ jalon.idjal }}"), data, {
|
||||
series: {
|
||||
pie: {
|
||||
show: true,
|
||||
|
@ -238,37 +300,46 @@
|
|||
},
|
||||
});
|
||||
|
||||
{% for data in milestone.stat %}
|
||||
{% for data in milestone.stat %}
|
||||
var data = [
|
||||
{% for label in data.labels %}
|
||||
{
|
||||
label: "{{ label.label}}",
|
||||
data: {{ label.total }},
|
||||
color: "{{ label.color }}",
|
||||
},
|
||||
{% endfor %}
|
||||
];
|
||||
var plotObj = $.plot($("#floatsubdonut{{ milestone.id }}-{{ data.id }}"), data, {
|
||||
series: {
|
||||
pie: {
|
||||
console.log("BY number = {{ (filterbynumber=="true" ? 'filtre par nbticket':'filtre par poids') }}");
|
||||
{% for sprint in jalon.sprints %}
|
||||
console.log("Sprint = {{sprint.nmspr}}");
|
||||
|
||||
{% for column in sprint.columns %}
|
||||
console.log({{ (filterbynumber=="true" ? column.nbiss:column.nbjrs) }});
|
||||
{% endfor %}
|
||||
var data = [
|
||||
{% for column in sprint.columns %}
|
||||
{
|
||||
label: "{{ column.nmcol}}",
|
||||
data: {{ (filterbynumber=="true" ? column.nbiss:column.nbjrs) }},
|
||||
color: "#{{ column.color }}",
|
||||
},
|
||||
{% endfor %}
|
||||
];
|
||||
|
||||
var plotObj = $.plot($("#floatdonut{{ jalon.idjal~"-"~sprint.idspr }}"), data, {
|
||||
series: {
|
||||
pie: {
|
||||
show: true,
|
||||
radius: 1,
|
||||
label: {
|
||||
show: true,
|
||||
label: {
|
||||
show: false,
|
||||
radius: 3/4,
|
||||
threshold: 0.1,
|
||||
background: {
|
||||
opacity: 0.5,
|
||||
color: '#cdcdcd',
|
||||
},
|
||||
radius: 1,
|
||||
threshold: 0.1,
|
||||
background: {
|
||||
opacity: 0.5,
|
||||
color: '#cdcdcd',
|
||||
},
|
||||
formatter: function(label, series) {
|
||||
return '<span style="color:#000; padding:3px;">' + label + '</span>';
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
});
|
||||
{% endfor %}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
});
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
|
|
|
@ -32,31 +32,15 @@
|
|||
{% block body %}
|
||||
<div class="d-flex">
|
||||
<div id="filters" class="d-flex flex-column pl-2 pr-2 " style="width:350px; background-color:var(--colorbgbodydark);min-height:1500px;">
|
||||
{% if fgpoker %}
|
||||
<div id="online" class="mt-2"></div>
|
||||
{% endif %}
|
||||
|
||||
<div style="width:100%" class="mt-3">
|
||||
<label class="control-label" style="color:var(--colorftbodydark)">Filtre TICKET</label>
|
||||
<input type="number" id="filterticket" class=" form-control">
|
||||
</div>
|
||||
|
||||
{% if id == 0 %}
|
||||
<div style="width:100%" class="mt-3">
|
||||
<label class="control-label" style="color:var(--colorftbodydark)">Filtre CATEGORIES</label>
|
||||
<select id="filtercategorys" multiple="multiple" class="form-control">
|
||||
{% for giteacategory in giteacategorys %}
|
||||
<option value="{{giteacategory}}">{{giteacategory}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style="width:100%" class="mt-3">
|
||||
<label class="control-label" style="color:var(--colorftbodydark)">Filtre PROJETS</label>
|
||||
<select id="filterrepos" multiple="multiple" class="form-control">
|
||||
{% for gitearepo in gitearepos %}
|
||||
<option value="{{gitearepo.id}}">{{gitearepo.full_name}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div style="width:100%" class="mt-3">
|
||||
<label class="control-label" style="color:var(--colorftbodydark)">Filtre JALONS</label>
|
||||
<select id="filtermilestones" multiple="multiple" class="form-control">
|
||||
|
@ -66,6 +50,18 @@
|
|||
</select>
|
||||
</div>
|
||||
|
||||
<div style="width:100%" class="mt-3">
|
||||
<label class="control-label" style="color:var(--colorftbodydark)">Filtre SPRINT</label>
|
||||
<select id="filtersprints" multiple="multiple" class="form-control">
|
||||
{% for sprint in sprints %}
|
||||
<option value="{{sprint.giteamilestone~"-"~sprint.id}}">{{sprint.giteamilestonename}}-{{sprint.name}}</option>
|
||||
{% endfor %}
|
||||
{% for giteamilestone in giteamilestones %}
|
||||
<option value="{{giteamilestone.id~"--100"}}">{{giteamilestone.title}}-Aucun</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style="width:100%" class="mt-3">
|
||||
<label class="control-label" style="color:var(--colorftbodydark)">Filtre STATUTS</label>
|
||||
<select id="filtercolumns" multiple="multiple" class="form-control">
|
||||
|
@ -143,7 +139,7 @@
|
|||
<a class="btn btn-success" href="{{path('app_scrum_stat',{id:id})}}"><i class="fas fa-chart-area"></i></a>
|
||||
{% endif %}
|
||||
<span id="textfilters"></span>
|
||||
<a class="btn btn-success float-right" href="{{path('app_issuescrum',{id:id,'fgcsv':true})}}">Export CSV</a>
|
||||
<a class="btn btn-success float-right" href="{{path('app_scrum_table',{id:id,'fgcsv':true})}}">Export CSV</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -153,15 +149,21 @@
|
|||
<th class="no-sort"></th>
|
||||
{%if id==0 %}<th style="width:100px">Projet</th>{%endif%}
|
||||
<th style="width:200px">Jalon</th>
|
||||
<th style="width:200px">Sprint</th>
|
||||
<th style="width:200px">Type</th>
|
||||
<th style="width:70px"class="no-string">N°</th>
|
||||
<th style="width:1000px">Titre</th>
|
||||
{% if (not wssuse or not fgpoker) %}
|
||||
<th style="width:200px">Equipe</th>
|
||||
<th style="width:250px">Priorité</th>
|
||||
<th style="width:70px">Poid</th>
|
||||
<th style="width:135px">Affecté à</th>
|
||||
<th style="width:135px">Statut</th>
|
||||
<th style="width:300px">Etiquettes</th>
|
||||
{% else %}
|
||||
<th style="width:300px">Poker</th>
|
||||
{% endif %}
|
||||
<th style="width:135px">Statut</th>
|
||||
<th style="width:70px">Poid</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
@ -182,19 +184,15 @@
|
|||
{% if tosee %}
|
||||
{% set dataticket = giteaissue.number %}
|
||||
{% set datarepo = gitearepo.id %}
|
||||
|
||||
{% if giteaissue.milestone %}
|
||||
{% set datamilestone = giteaissue.milestone.id %}
|
||||
{%else%}
|
||||
{% set datamilestone = gitearepo.full_name %}
|
||||
{%endif%}
|
||||
{% set datamilestone = (giteaissue.milestone?giteaissue.milestone.id:-100) %}
|
||||
{% set datasprint = datamilestone~"-"~giteaissue.sprintid %}
|
||||
|
||||
{% set statut = "Backlog" %}
|
||||
{% set teams = "" %}
|
||||
{% set types = "" %}
|
||||
{% set datateams = "" %}
|
||||
{% set datatypes = "" %}
|
||||
{% set prioritys = '<span class="btn-link tag mr-1" style="background-color:#70c24a"><i class="fas fa-tag"></i>'~giteaprioritys|last~'</span>' %}
|
||||
{% set prioritys = (not giteaprioritys?'':'<span class="btn-link tag mr-1" style="background-color:#70c24a"><i class="fas fa-tag"></i>'~giteaprioritys|last~'</span>') %}
|
||||
{% set dataprioritys = ','~giteaprioritys|last %}
|
||||
{% set labels = "" %}
|
||||
{% set datalabels = "" %}
|
||||
|
@ -221,12 +219,13 @@
|
|||
{% set dataassignees=dataassignees~','~assignee.username %}
|
||||
{% endfor %}
|
||||
|
||||
<tr data-category="{{gitearepo.category}}" data-repo="{{datarepo}}" data-milestone="{{datamilestone}}" data-ticket="{{dataticket}}" data-column="{{statut}}" data-teams="{{datateams}}" data-prioritys="{{dataprioritys}}" data-types="{{datatypes}}" data-labels="{{datalabels}}" data-assignees="{{dataassignees}}">
|
||||
<tr data-id="{{giteaissue.issueid}}" data-milestone="{{datamilestone}}" data-sprint="{{datasprint}}" data-ticket="{{dataticket}}" data-column="{{statut}}" data-teams="{{datateams}}" data-prioritys="{{dataprioritys}}" data-types="{{datatypes}}" data-labels="{{datalabels}}" data-assignees="{{dataassignees}}">
|
||||
<td>
|
||||
<a target="_blank" class="btn btn-link fa fa-file" href="{{giteaissue.html_url}}"></a>
|
||||
</td>
|
||||
{%if id==0 %}<td>{{ gitearepo.full_name }}</td>{%endif%}
|
||||
<td>{% if giteaissue.milestone %}{{ giteaissue.milestone.title }} {%endif%}</td>
|
||||
<td>{% if giteaissue.sprintid %}{{ giteaissue.sprintname }} {%endif%}</td>
|
||||
<td>{{ types|raw }}</td>
|
||||
<td>{{ giteaissue.number }}</td>
|
||||
<td>
|
||||
|
@ -235,15 +234,11 @@
|
|||
{{ giteaissue.title }}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
{% if (not wssuse or not fgpoker) %}
|
||||
<td>{{ teams|raw }}</td>
|
||||
<td>{{ prioritys|raw }}</td>
|
||||
|
||||
<td>
|
||||
<div id="modissu{{ giteaissue.issueid }}" data-issue="{{ giteaissue.issueid }}" data-giteaid="{{giteaissue.number}}" data-giteatitle="{{ giteaissue.title }}" type="button" class="modissu btn btn-link">
|
||||
<i class="fas fa-weight-hanging"></i> = <span id="issue{{giteaissue.issueid}}-weight">{{ giteaissue.weight }}</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
{% set dataorder="" %}
|
||||
{% for assignee in giteaissue.assignees %}
|
||||
{% set dataorder=dataorder~assignee.username %}
|
||||
|
@ -254,8 +249,19 @@
|
|||
<img src="{{assignee.avatar_url}}" class="assignee" title="{{assignee.username}}">
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>{{ statut }}</td>
|
||||
<td>{{ labels|raw }}</td>
|
||||
{% else %}
|
||||
<td>
|
||||
<div class="pokertd d-flex"></div>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<td>{{ statut }}</td>
|
||||
<td>
|
||||
<div id="modissu{{ giteaissue.issueid }}" data-issue="{{ giteaissue.issueid }}" data-giteaid="{{giteaissue.number}}" data-giteatitle="{{ giteaissue.title }}" type="button" class="modissu btn btn-link">
|
||||
<i class="fas fa-weight-hanging"></i> = <span id="issue{{giteaissue.issueid}}-weight">{{ giteaissue.weight }}</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
@ -320,9 +326,8 @@
|
|||
function showhide() {
|
||||
textfilters="";
|
||||
ticketfilter=$("#filterticket").val();
|
||||
categoryfilters=$("#filtercategorys").val();
|
||||
repofilters=$("#filterrepos").val();
|
||||
milestonefilters=$("#filtermilestones").val();
|
||||
sprintfilters=$("#filtersprints").val();
|
||||
columnfilters=$("#filtercolumns").val();
|
||||
teamfilters=$("#filterteams").val();
|
||||
priorityfilters=$("#filterprioritys").val();
|
||||
|
@ -340,6 +345,7 @@
|
|||
{% endif %}
|
||||
ticket= $(el).data('ticket');
|
||||
milestone = $(el).data('milestone');
|
||||
sprint = $(el).data('sprint');
|
||||
column = $(el).data('column');
|
||||
teams = $(el).data('teams').split(',');
|
||||
prioritys = $(el).data('prioritys').split(',');
|
||||
|
@ -373,6 +379,11 @@
|
|||
toreturn=false;
|
||||
}
|
||||
|
||||
|
||||
if(sprintfilters.length!==0 && jQuery.inArray(sprint.toString(), sprintfilters )<0) {
|
||||
toreturn=false;
|
||||
}
|
||||
|
||||
if(columnfilters.length!==0 && jQuery.inArray(column.toString(), columnfilters )<0) {
|
||||
toreturn=false;
|
||||
}
|
||||
|
@ -439,26 +450,6 @@
|
|||
textfilters=textfilters+" <b>TICKET</b> ="+ticketfilter;
|
||||
}
|
||||
|
||||
{% if id == 0 %}
|
||||
if(categoryfilters.length!==0) {
|
||||
data = $("#filtercategorys").select2('data');
|
||||
textfilters=textfilters+" <b>CATEGORIES</b> =";
|
||||
$.each(categoryfilters, function( index, value ) {
|
||||
if(index>0)textfilters=textfilters+" &";
|
||||
textfilters=textfilters+" "+data[index].text;
|
||||
});
|
||||
}
|
||||
|
||||
if(repofilters.length!==0) {
|
||||
data = $("#filterrepos").select2('data');
|
||||
textfilters=textfilters+" <b>PROJETS</b> =";
|
||||
$.each(repofilters, function( index, value ) {
|
||||
if(index>0)textfilters=textfilters+" &";
|
||||
textfilters=textfilters+" "+data[index].text;
|
||||
});
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
if(milestonefilters.length!==0) {
|
||||
data = $("#filtermilestones").select2('data');
|
||||
textfilters=textfilters+" <b>JALONS</b> =";
|
||||
|
@ -468,6 +459,15 @@
|
|||
});
|
||||
}
|
||||
|
||||
if(sprintfilters.length!==0) {
|
||||
data = $("#filtersprints").select2('data');
|
||||
textfilters=textfilters+" <b>SPRINTS</b> =";
|
||||
$.each(sprintfilters, function( index, value ) {
|
||||
if(index>0)textfilters=textfilters+" &";
|
||||
textfilters=textfilters+" "+data[index].text;
|
||||
});
|
||||
}
|
||||
|
||||
if(columnfilters.length!==0) {
|
||||
data = $("#filtercolumns").select2('data');
|
||||
textfilters=textfilters+" <b>STATUS</b> =";
|
||||
|
@ -537,36 +537,6 @@
|
|||
table.draw();
|
||||
}
|
||||
|
||||
{% if id == 0 %}
|
||||
function filtercategorys() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{ path('app_user_preference') }}",
|
||||
data: {
|
||||
key:'filtercategorys',
|
||||
id:{{id}},
|
||||
value: $("#filtercategorys").val()
|
||||
}
|
||||
});
|
||||
|
||||
showhide();
|
||||
}
|
||||
|
||||
function filterrepos() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{ path('app_user_preference') }}",
|
||||
data: {
|
||||
key:'filterrepos',
|
||||
id:{{id}},
|
||||
value: $("#filterrepos").val()
|
||||
}
|
||||
});
|
||||
|
||||
showhide();
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
function filtermilestones() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
|
@ -581,6 +551,20 @@
|
|||
showhide();
|
||||
}
|
||||
|
||||
function filtersprints() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{ path('app_user_preference') }}",
|
||||
data: {
|
||||
key:'filtersprints',
|
||||
id:{{id}},
|
||||
value: $("#filtersprints").val()
|
||||
}
|
||||
});
|
||||
|
||||
showhide();
|
||||
}
|
||||
|
||||
function filtercolumns() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
|
@ -732,36 +716,6 @@
|
|||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
{% if id== 0 %}
|
||||
$('#filtercategorys').select2();
|
||||
{% if filtercategorys %}
|
||||
{% for category in filtercategorys %}
|
||||
$("#filtercategorys").val($("#filtercategorys").val().concat("{{category}}"));
|
||||
{%endfor%}
|
||||
$('#filtercategorys').trigger('change');
|
||||
{% endif %}
|
||||
$('#filtercategorys').on("select2:select", function(e) {
|
||||
filtercategorys();
|
||||
});
|
||||
$('#filtercategorys').on("select2:unselect", function(e) {
|
||||
filtercategorys();
|
||||
});
|
||||
|
||||
$('#filterrepos').select2();
|
||||
{% if filterrepos %}
|
||||
{% for repo in filterrepos %}
|
||||
$("#filterrepos").val($("#filterrepos").val().concat("{{repo}}"));
|
||||
{%endfor%}
|
||||
$('#filterrepos').trigger('change');
|
||||
{% endif %}
|
||||
$('#filterrepos').on("select2:select", function(e) {
|
||||
filterrepos();
|
||||
});
|
||||
$('#filterrepos').on("select2:unselect", function(e) {
|
||||
filterrepos();
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
$("#filterticket").on("keyup", function() {
|
||||
showhide();
|
||||
});
|
||||
|
@ -780,6 +734,20 @@
|
|||
filtermilestones();
|
||||
});
|
||||
|
||||
$('#filtersprints').select2();
|
||||
{% if filtersprints %}
|
||||
{% for sprint in filtersprints %}
|
||||
$("#filtersprints").val($("#filtersprints").val().concat("{{sprint}}"));
|
||||
{%endfor%}
|
||||
$('#filtersprints').trigger('change');
|
||||
{% endif %}
|
||||
$('#filtersprints').on("select2:select", function(e) {
|
||||
filtersprints();
|
||||
});
|
||||
$('#filtersprints').on("select2:unselect", function(e) {
|
||||
filtersprints();
|
||||
});
|
||||
|
||||
$('#filtercolumns').select2();
|
||||
{% if filtercolumns %}
|
||||
{% for column in filtercolumns %}
|
||||
|
@ -894,4 +862,89 @@
|
|||
|
||||
$("#mycontent").show();
|
||||
});
|
||||
|
||||
{% if wssuse and fgpoker %}
|
||||
var conn;
|
||||
|
||||
function connect() {
|
||||
conn = new WebSocket("{{wssurl}}");
|
||||
|
||||
conn.onopen = function(e) {
|
||||
console.log("== CONNECT");
|
||||
{% set userkey = "" %}
|
||||
{% if app.user %}
|
||||
{% set userkey = app.user.apikey %}
|
||||
{%endif%}
|
||||
|
||||
subscribe("home",{{id}},"{{userkey}}");
|
||||
sendMessage({command: "alive"});
|
||||
};
|
||||
|
||||
conn.onmessage = function(e) {
|
||||
ret=JSON.parse(e.data);
|
||||
console.log("MESSAGE REU ="+ret.command);
|
||||
|
||||
switch(ret.command) {
|
||||
case "alive" :
|
||||
if(!$('#online'+ret.from.id).length) {
|
||||
img='<img id="online'+ret.from.id+'" src="'+ret.from.avatar+'" class="avatar ml-2 mr-2" title="'+ret.from.displayname+'">';
|
||||
$("#online").append(img);
|
||||
|
||||
$("tr").each(function(){
|
||||
line=$(this);
|
||||
issueid=$(this).data("id");
|
||||
url="{{path("app_poker_get",{userid:"xxx",issueid:"yyy"})}}";
|
||||
url=url.replace("xxx",ret.from.id);
|
||||
url=url.replace("yyy",issueid);
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: url,
|
||||
async: false,
|
||||
success: function(data) {
|
||||
html ='<div class="d-flex flex-column align-items-center" data-user="'+ret.from.id+'">';
|
||||
html+='<img src="'+ret.from.avatar+'" class="avatar mb-1" style="zoom:80%;" title="'+ret.from.displayname+'">';
|
||||
html+='<input class="pokervalue" id="poker-'+ret.from.id+'-'+issueid+'" data-user="'+ret.from.id+'" data-issue="'+issueid+'" type="number" style="width:60px" value="'+data+'"></input>';
|
||||
html+='</div>';
|
||||
line.find(".pokertd").append(html);
|
||||
},
|
||||
});
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
if(ret.from.id!={{app.user.id}}) {
|
||||
console.log("meto");
|
||||
sendMessage({command: "meto"});
|
||||
}
|
||||
break;
|
||||
|
||||
case "adead" :
|
||||
$('#online'+ret.from.id).remove();
|
||||
$('[data-user='+ret.from.id+']').remove();
|
||||
break;
|
||||
|
||||
case "meto" :
|
||||
if(!$('#online'+ret.from.id).length) {
|
||||
html='<img id="online'+ret.from.id+'" src="'+ret.from.avatar+'" class="avatar ml-2 mr-2" title="'+ret.from.displayname+'">';
|
||||
$("#online").append(html);
|
||||
$(".pokertd").append(html);
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
conn.onclose = function(e) {
|
||||
console.log("== DISCONNECT");
|
||||
$('#online img').remove();
|
||||
console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
|
||||
setTimeout(function() { connect(); }, 1000);
|
||||
};
|
||||
}
|
||||
|
||||
connect();
|
||||
|
||||
$("body").on("input", ".pokervalue", function () {
|
||||
console.log($(this).val());
|
||||
});
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -22,19 +22,24 @@
|
|||
|
||||
.tag {
|
||||
border-radius: 5px;
|
||||
padding: 8px 8px;
|
||||
margin-bottom: 5px;
|
||||
padding: 4px 8px;
|
||||
//margin-bottom: 2px;
|
||||
display: inline-block;
|
||||
min-width: 35px;
|
||||
text-align: center;
|
||||
color: #ffffff !important;
|
||||
zoom: 80%;
|
||||
zoom: 70%;
|
||||
}
|
||||
|
||||
.tag i {
|
||||
margin-right:5px;
|
||||
}
|
||||
|
||||
.tooltip-inner {
|
||||
text-align: left !important; /* Aligne le texte à gauche */
|
||||
white-space: pre-line; /* Conserve les retours à la ligne */
|
||||
}
|
||||
|
||||
.assignee {
|
||||
width:30px;
|
||||
margin: 5px 5px 0px 0px;
|
||||
|
@ -43,9 +48,19 @@
|
|||
.state-closed {
|
||||
background-color: #cdcdcd !important;
|
||||
}
|
||||
|
||||
.text-small { font-size:80%}
|
||||
.text-verysmall { font-size:70%}
|
||||
|
||||
.submenu a:hover {
|
||||
text-decoration: none;
|
||||
color: var(--colorfttitlelight);
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% set start = microtime(true) %}
|
||||
|
||||
<div class="d-flex">
|
||||
<div id="filters" class="d-flex flex-column pl-2 pr-2 " style="width:350px; background-color:var(--colorbgbodydark);min-height:1500px;">
|
||||
<div style="width:100%" class="mt-3">
|
||||
|
@ -58,6 +73,18 @@
|
|||
</select>
|
||||
</div>
|
||||
|
||||
<div style="width:100%" class="mt-3">
|
||||
<label class="control-label" style="color:var(--colorftbodydark)">Filtre SPRINT</label>
|
||||
<select id="filtersprints" multiple="multiple" class="form-control">
|
||||
{% for sprint in sprints %}
|
||||
<option value="{{sprint.giteamilestone~"-"~sprint.id}}">{{sprint.giteamilestonename}}-{{sprint.name}}</option>
|
||||
{% endfor %}
|
||||
{% for giteamilestone in giteamilestones %}
|
||||
<option value="{{giteamilestone.id~"--100"}}">{{giteamilestone.title}}-Aucun</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style="width:100%" class="mt-3">
|
||||
<label class="control-label" style="color:var(--colorftbodydark)">Filtre TYPES</label>
|
||||
<select id="filtertypes" multiple="multiple" class="form-control">
|
||||
|
@ -113,12 +140,14 @@
|
|||
</select>
|
||||
</div>
|
||||
|
||||
<div style="width:100%" class="mt-3">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="viewcondensed">
|
||||
<label class="custom-control-label" for="viewcondensed" style="color:var(--colorfttitledark);">Vue condensée</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="color:var(--colorftbodydark);zoom:75%;" class="mt-5">
|
||||
{% for giteamilestone in giteamilestones %}
|
||||
{{giteamilestone.title}} = <span id="total{{giteamilestone.id}}" class="totalweight">0</span><br>
|
||||
{% endfor %}
|
||||
Aucun = <span id="total-100" class="totalweight">0</span><br>
|
||||
<div id="tbestim" class="mt-5">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -130,160 +159,263 @@
|
|||
|
||||
<div class="mt-4" style="zoom:80%">
|
||||
<button class="btn btn-success" onClick="showFilters()"><i class="fas fa-filter"></i></button>
|
||||
<a class="btn btn-success" href="{{path('app_issuescrum',{id:scrum.id})}}"><i class="fas fa-ticket-alt"></i></a>
|
||||
<a class="btn btn-success" href="{{path('app_scrum_table',{id:scrum.id})}}"><i class="fas fa-ticket-alt"></i></a>
|
||||
<a class="btn btn-success" href="{{path('app_scrum_stat',{id:scrum.id})}}"><i class="fas fa-chart-area"></i></a>
|
||||
<a href="{{giteaUrl}}/{{scrum.giteajson.owner.login}}/{{scrum.giteajson.name}}/issues/new" class="btn btn-success" target="_blank">Nouveau Ticket</a>
|
||||
<span id="textfilters"></span>
|
||||
</div>
|
||||
|
||||
{% for column in scrum.scrumcolumns %}
|
||||
{% set idmiletone="-100" %}
|
||||
{% set tbidmiletone=[] %}
|
||||
{% set haveissues=false %}
|
||||
<div class="card d-inline-block mt-3 align-top mb-5" data-column="{{column.giteaid}}" style="width: 18rem;">
|
||||
<div class="card-header">{{ column.name }}</div>
|
||||
{% for column in tbissues %}
|
||||
<div class="d-inline-block mt-3 align-top mb-5 p-2" data-column="{{column.gicol}}" style="width: 18rem;">
|
||||
<h2 style="text-transform: uppercase; text-align:center; font-size:26px">{{ column.nmcol }}</h2>
|
||||
<div class="card-body p-1">
|
||||
{% for issue in column.scrumissues %}
|
||||
{% set tosee=false %}
|
||||
{% if app.session.get('viewclosed')=="true" and issue.giteastate=="closed" %}
|
||||
{% set tosee=true %}
|
||||
{% endif %}
|
||||
{% if issue.giteastate!="closed" %}
|
||||
{% set tosee=true %}
|
||||
{% endif %}
|
||||
|
||||
{% if tosee %}
|
||||
{% set haveissues=true %}
|
||||
{% if idmiletone!=issue.giteamilestone %}
|
||||
{% if idmiletone!=-100 %}</ul>{% endif %}
|
||||
|
||||
{% if issue.giteamilestone is empty %}
|
||||
{% set tbidmiletone = tbidmiletone|merge([-100]) %}
|
||||
{% set idmilestone = -100 %}
|
||||
{% set namemilestone = "Aucun" %}
|
||||
{% else %}
|
||||
{% set tbidmiletone = tbidmiletone|merge([issue.giteamilestone]) %}
|
||||
{% set idmilestone = issue.giteamilestone %}
|
||||
{% set namemilestone = issue.giteajson.milestone.title %}
|
||||
{% endif %}
|
||||
|
||||
<h3 data-milestone="{{idmilestone}}">JALON = {{namemilestone}}</h3>
|
||||
<ul class="scrumcolumn list-group" style="min-height:50px" data-column="{{column.giteaid}}" data-milestone="{{idmilestone}}">
|
||||
{% set idmiletone=issue.giteamilestone %}
|
||||
{% endif %}
|
||||
|
||||
{% set datalabels="" %}
|
||||
{% set datateams="" %}
|
||||
{% set datatypes="" %}
|
||||
{% set dataprioritys="datapriority"~giteaprioritys|last %}
|
||||
{% for label in issue.giteajson.labels %}
|
||||
{% if label.id not in giteacolumns and label.id in giteateams %}
|
||||
{% set datateams=datateams~"datateam"~label.id~" " %}
|
||||
{% endif %}
|
||||
|
||||
{% if label.id not in giteacolumns and label.id in giteatypes %}
|
||||
{% set datatypes=datatypes~"datatype"~label.id~" " %}
|
||||
{% endif %}
|
||||
|
||||
{% if label.id not in giteacolumns and label.id in giteaprioritys %}
|
||||
{% set dataprioritys="datapriority"~label.id~" " %}
|
||||
{% endif %}
|
||||
|
||||
{% if label.id not in giteacolumns and label.id not in giteateams and label.id not in giteatypes and label.id not in giteaprioritys %}
|
||||
{% set datalabels=datalabels~"datalabel"~label.id~" " %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% set dataassignees="" %}
|
||||
{% for assignee in issue.giteajson.assignees %}
|
||||
{% set dataassignees=dataassignees~"dataassignee"~assignee.id~" " %}
|
||||
{% endfor %}
|
||||
|
||||
<div id="issu{{ issue.id }}" data-id="{{ issue.id }}" data-issue="{{ issue.id }}" data-column="{{column.giteaid}}" data-milestone="{{idmilestone}}" class="card mb-1 issue issue-{{issue.id}} {{datateams}} {{datatypes}} {{dataprioritys}} {{datalabels}} {{dataassignees}} state-{{issue.giteastate}}">
|
||||
<div class="card-footer p-1" style="line-height:10px; border-top:none;">
|
||||
<div class="float-left btn btn-link p-0 m-0 fas fa-arrows-alt" style="cursor:move"></div>
|
||||
<a target="_blank" class="modcolumn btn btn-link float-right fa fa-file p-0 m-0" href="{{issue.giteajson.html_url}}"></a>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-1" style="line-height:10px;">
|
||||
{% for jalon in column.jalons %}
|
||||
{% for sprint in jalon.sprints %}
|
||||
<div class="card mb-3" data-column="{{column.gicol}}" data-milestone="{{jalon.gijal}}" data-sprint="{{sprint.idspr}}" data-millestonesprint="{{jalon.gijal~"-"~sprint.idspr}}">
|
||||
<div class="card-header p-1 d-flex" style="font-size:16px; cursor:pointer;" onClick="$(this).next('.card-body').toggle()">
|
||||
<div>
|
||||
<small>
|
||||
{{issue.giteanumber}} - {{ issue.giteatitle }}<br><br>
|
||||
<small>Crée le {{issue.giteajson.created_at|date("d/m/y")}}</small><small style ="float:right">Modifié le {{issue.giteajson.updated_at|date("d/m/y")}}</small>
|
||||
{% if issue.giteastate=="closed" %}
|
||||
<br><small>Clos le {{issue.giteajson.closed_at|date("d/m/y")}}</small>
|
||||
{% endif %}
|
||||
<br><br>
|
||||
JALON = {{jalon.nmjal}}
|
||||
{% if sprint.idspr!=-100 %}
|
||||
<br>
|
||||
SPRINT = {{sprint.nmspr}}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="ml-auto" data-weight="{{column.gicol~"-"~jalon.gijal~"-"~sprint.idspr}}">
|
||||
|
||||
|
||||
{% for label in issue.giteajson.labels %}
|
||||
{% if label.id not in giteacolumns and label.id in giteaprioritys %}
|
||||
<span class="btn-link tag" style="background-color:#{{label.color}}">
|
||||
<i class="fas fa-tag"></i>
|
||||
{{ label.name }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<br>
|
||||
{% for label in issue.giteajson.labels %}
|
||||
{% if label.id not in giteacolumns and label.id in giteatypes %}
|
||||
<span class="btn-link tag" style="background-color:#{{label.color}}">
|
||||
<i class="fas fa-tag"></i>
|
||||
{{ label.name }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<br>
|
||||
{% for label in issue.giteajson.labels %}
|
||||
{% if label.id not in giteacolumns and label.id in giteateams %}
|
||||
<span class="btn-link tag" style="background-color:#{{label.color}}">
|
||||
<i class="fas fa-tag"></i>
|
||||
{{ label.name }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<br>
|
||||
{% for label in issue.giteajson.labels %}
|
||||
{% if label.id not in giteacolumns and label.id not in giteateams and label.id not in giteaprioritys and label.id not in giteatypes %}
|
||||
<span class="btn-link tag" style="background-color:#{{label.color}}">
|
||||
<i class="fas fa-tag"></i>
|
||||
{{ label.name }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<div>
|
||||
{% for assignee in issue.giteajson.assignees %}
|
||||
<img src="{{assignee.avatar_url}}" class="assignee" title="{{assignee.username}}">
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div id="modissu{{ issue.id }}" data-issue="{{ issue.id }}" data-giteaid="{{issue.giteanumber}}" data-giteatitle="{{ issue.giteatitle }}" type="button" class="modissu btn btn-link float-right">
|
||||
<i class="fas fa-weight-hanging"></i> = <span id="issue{{issue.id}}-weight">{{ issue.weight }}</span>
|
||||
</div>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-1">
|
||||
<ul class="scrumcolumn list-group" style="min-height:50px" data-column="{{column.gicol}}" data-milestone="{{jalon.gijal}}" data-sprint="{{sprint.idspr}}" data-millestonesprint="{{jalon.gijal~"-"~sprint.idspr}}">
|
||||
{% for issue in sprint.issues %}
|
||||
{% set tosee=false %}
|
||||
{% if app.session.get('viewclosed')=="true" and issue.giteastate=="closed" %}
|
||||
{% set tosee=true %}
|
||||
{% endif %}
|
||||
{% if issue.giteastate!="closed" %}
|
||||
{% set tosee=true %}
|
||||
{% endif %}
|
||||
|
||||
{% if tosee %}
|
||||
{% set datalabels="" %}
|
||||
{% set datateams="" %}
|
||||
{% set datatypes="" %}
|
||||
{% set dataprioritys="datapriority"~giteaprioritys|last %}
|
||||
{% set issuprioritycolor=prioritycolor %}
|
||||
|
||||
{% for label in issue.giteajson.labels %}
|
||||
{% if label.id not in giteacolumns and label.id in giteateams %}
|
||||
{% set datateams=datateams~"datateam"~label.id~" " %}
|
||||
{% endif %}
|
||||
|
||||
{% if label.id not in giteacolumns and label.id in giteatypes %}
|
||||
{% set datatypes=datatypes~"datatype"~label.id~" " %}
|
||||
{% endif %}
|
||||
|
||||
{% if label.id not in giteacolumns and label.id in giteaprioritys %}
|
||||
{% set dataprioritys="datapriority"~label.id~" " %}
|
||||
{% set issuprioritycolor="#"~label.color %}
|
||||
{% endif %}
|
||||
|
||||
{% set datalabels=datalabels~"datalabel"~label.id~" " %}
|
||||
{% endfor %}
|
||||
|
||||
{% set dataassignees="" %}
|
||||
{% for assignee in issue.giteajson.assignees %}
|
||||
{% set dataassignees=dataassignees~"dataassignee"~assignee.id~" " %}
|
||||
{% endfor %}
|
||||
|
||||
{% set backcolor="" %}
|
||||
{% if not issue.color is empty %}
|
||||
{% set backcolor="background-color:"~issue.color~";" %}
|
||||
{% elseif issue.scrumissueblock and not issue.scrumissueblock.color is empty %}
|
||||
{% set backcolor="background-color:"~issue.scrumissueblock.color~";" %}
|
||||
{% endif %}
|
||||
|
||||
{% set notes=(not issue.notes is empty?issue.notes|striptags|replace({'\n': '<br>', '\r': '<br>'})|raw:"") %}
|
||||
|
||||
<div id="issu{{ issue.id }}" data-id="{{ issue.id }}" data-issue="{{ issue.id }}" data-column="{{column.gicol}}" data-milestone="{{jalon.gijal}}" data-sprint="{{sprint.idspr}}" class="card mb-1 issue issue-{{issue.id}} {{datateams}} {{datatypes}} {{dataprioritys}} {{datalabels}} {{dataassignees}} state-{{issue.giteastate}}" style="border-left: 10px solid {{issuprioritycolor}}" {{ (not notes is empty?'title='~notes:'') }}>
|
||||
<div class="card-footer p-1 d-flex" style="line-height:16px; border-top:none; {{ backcolor }}" >
|
||||
<div class="flex-grow-1 d-flex align-items-center" style="max-width:224px";>
|
||||
<div class="pr-2 issu-id" style="cursor:move">
|
||||
#{{issue.giteanumber}}
|
||||
</div>
|
||||
<div class="text-small" style="cursor:pointer; word-break: break-word;" onClick="$('#issu-detail{{ issue.id }}').toggle()">
|
||||
{% if not issue.scrumissueblock is empty %}
|
||||
<div class="text-verysmall" style="margin-bottom:-5px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis; width: 160px;">
|
||||
#{{issue.scrumissueblock.giteanumber}} = {{issue.scrumissueblock.giteatitle}}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div style="line-height:13px;">{{ issue.giteatitle }}</div>
|
||||
|
||||
{% for depend in issue.scrumissuedependencies %}
|
||||
{% if loop.first %}
|
||||
<div class="text-verysmall" style="margin-top: 5px;line-height:11px; width:160px;">
|
||||
{% endif %}
|
||||
{% set style="" %}
|
||||
{% if depend.giteastate=="closed" %}
|
||||
{% set style="text-decoration: line-through;" %}
|
||||
{% endif %}
|
||||
<div style="white-space: nowrap;overflow: hidden;text-overflow: ellipsis;{{style}}">#{{depend.giteanumber}} = {{depend.giteatitle}}</div>
|
||||
{% if loop.last %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="viewissu{{ issue.id }}" class="viewissu mb-2" onMouseenter="issuhover(this,{{ issue.id }})" data-issue="{{ issue.id }}" data-giteaid="{{issue.giteanumber}}" data-giteatitle="{{ issue.giteatitle }}" type="button" style="line-height:9px; text-align:center;">
|
||||
<i class="btn btn-link fas fa-eye p-0 m-0 fa-fw"></i>
|
||||
<br><span class="text-verysmall issue{{issue.id}}-weight">{{ issue.weight }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="submenu{{issue.id}}" class="submenu" onmouseleave="issuout(this)" style="
|
||||
position: absolute;
|
||||
left: 214px;
|
||||
top: -1px;
|
||||
width:300px;
|
||||
z-index:1200;
|
||||
display:none;
|
||||
background-color:#f7f7f7;
|
||||
flex-direction: column;
|
||||
border: 1px solid #cdcdcd;
|
||||
border-radius: .25rem;
|
||||
">
|
||||
|
||||
<div id="viewissu{{ issue.id }}" class="viewissu mb-2" data-issue="{{ issue.id }}" data-giteaid="{{issue.giteanumber}}" data-giteatitle="{{ issue.giteatitle }}">
|
||||
<i class="btn fas fa-eye p-0 m-0 fa-fw pl-1 pl-1"></i>
|
||||
<span style="cursor:pointer;">
|
||||
Aperçu Ticket
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<a target="_blank" href="{{issue.giteajson.html_url}}" style="cursor:pointer" class="modcolumn mb-2">
|
||||
<i class="btn fa fa-file fa-fw p-0 m-0 pl-1 pl-1"></i>
|
||||
<span>Modifier dans Gitea</span>
|
||||
</a>
|
||||
|
||||
<div id="modissu{{ issue.id }}" class="modissu mb-2" data-issue="{{ issue.id }}" data-giteaid="{{issue.giteanumber}}" data-giteatitle="{{ issue.giteatitle }}">
|
||||
<i class="btn fas fa-weight-hanging p-0 m-0 fa-fw pl-1 pl-1"></i>
|
||||
<span style="cursor:pointer;">
|
||||
Modifier le Poids = <span class="issue{{issue.id}}-weight">{{ issue.weight }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{% if issue.scrumissueblock is empty %}
|
||||
<div id="lockissu{{ issue.id }}" class="lockissu mb-2" data-issue="{{ issue.id }}" data-giteaid="{{issue.giteanumber}}" data-giteatitle="{{ issue.giteatitle }}">
|
||||
<i class="btn fas fa-lock p-0 m-0 fa-fw pl-1 pl-1"></i>
|
||||
<span style="cursor:pointer;">
|
||||
Ajouter ce ticket comme bloquant à
|
||||
</span>
|
||||
</div>
|
||||
{% else %}
|
||||
<div id="unlockissu{{ issue.id }}" class="unlockissu mb-2" data-issue="{{ issue.id }}" data-giteaid="{{issue.giteanumber}}" data-giteatitle="{{ issue.giteatitle }}">
|
||||
<i class="btn fas fa-lock p-0 m-0 fa-fw pl-1 pl-1"></i>
|
||||
<span style="cursor:pointer;">
|
||||
N'est plus bloquant pour #{{ issue.scrumissueblock.giteanumber}}
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="assigneissu{{ issue.id }}" class="assigneissu mb-2" data-issue="{{ issue.id }}" data-giteaid="{{issue.giteanumber}}" data-giteatitle="{{ issue.giteatitle }}">
|
||||
<i class="btn fas fa-users p-0 m-0 fa-fw pl-1 pl-1"></i>
|
||||
<span style="cursor:pointer;">
|
||||
Affecté à
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div id="notesissu{{ issue.id }}" class="notesissu mb-2" data-issue="{{ issue.id }}" data-giteaid="{{issue.giteanumber}}" data-giteatitle="{{ issue.giteatitle }}">
|
||||
<i class="btn fas fa-clipboard p-0 m-0 fa-fw pl-1 pl-1"></i>
|
||||
<span style="cursor:pointer;">
|
||||
Notes
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input type="text" id="colorissu{{ issue.id }}" data-issue="{{ issue.id }}" class="pick-a-color form-control form-control spectrum sp-colorize" value="{{issue.color}}" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="issu-detail{{ issue.id }}" class="card-body p-1 issu-detail">
|
||||
<div>
|
||||
{% for label in issue.giteajson.labels %}
|
||||
{% if label.id not in giteacolumns and label.id in giteaprioritys %}
|
||||
<span class="btn-link tag" style="background-color:#{{label.color}}">
|
||||
<i class="fas fa-clock"></i>
|
||||
{{ label.name }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% for label in issue.giteajson.labels %}
|
||||
{% if label.id not in giteacolumns and label.id in giteatypes %}
|
||||
<span class="btn-link tag" style="background-color:#{{label.color}}">
|
||||
<i class="fas fa-quote-right"></i>
|
||||
{{ label.name }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% for label in issue.giteajson.labels %}
|
||||
{% if label.id not in giteacolumns and label.id in giteateams %}
|
||||
<span class="btn-link tag" style="background-color:#{{label.color}}">
|
||||
<i class="fas fa-users"></i>
|
||||
{{ label.name }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% for label in issue.giteajson.labels %}
|
||||
{% if label.id not in giteacolumns and label.id not in giteateams and label.id not in giteaprioritys and label.id not in giteatypes %}
|
||||
<span class="btn-link tag" style="background-color:#{{label.color}}">
|
||||
<i class="fas fa-tag"></i>
|
||||
{{ label.name }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% for assignee in issue.giteajson.assignees %}
|
||||
<img src="{{assignee.avatar_url}}" class="assignee" title="{{assignee.username}}">
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div id="modissu{{ issue.id }}" class="modissu btn btn-link d-flex justify-content-end align-items-center" data-issue="{{ issue.id }}" data-giteaid="{{issue.giteanumber}}" data-giteatitle="{{ issue.giteatitle }}" type="button">
|
||||
<i class="fas fa-weight-hanging"></i> = <span class="issue{{issue.id}}-weight">{{ issue.weight }}</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex text-small">
|
||||
<div class="text-small">Crée le {{issue.giteajson.created_at|date("d/m/y")}}</div>
|
||||
<div class="text-small text-right ml-auto">Modifié le {{issue.giteajson.updated_at|date("d/m/y")}}</div>
|
||||
</div>
|
||||
|
||||
<div class="text-small">
|
||||
<div class="text-small">Par {{issue.giteajson.user.login}}</div>
|
||||
{% if issue.giteastate=="closed" %}
|
||||
<div class="text-small text-right ml-auto">
|
||||
Clos le {{issue.giteajson.closed_at|date("d/m/y")}}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
{% if haveissues %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% for giteamilestone in giteamilestones %}
|
||||
{% if giteamilestone.id not in tbidmiletone %}
|
||||
<h3 data-milestone="{{giteamilestone.id}}"> JALON = {{giteamilestone.title}}</h3>
|
||||
<ul class="scrumcolumn list-group" style="min-height:50px" data-column="{{ column.giteaid }}" data-milestone="{{giteamilestone.id}}"></ul>
|
||||
{% endif %}
|
||||
{%endfor%}
|
||||
|
||||
{% if -100 not in tbidmiletone %}
|
||||
<h3 data-milestone="-100"> JALON = Aucun</h3>
|
||||
<ul class="scrumcolumn list-group" style="min-height:50px" data-column="{{ column.giteaid }}" data-milestone="-100"></ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
@ -313,12 +445,89 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mymodalblock" class="modal" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title"></h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group ">
|
||||
<label class="control-label required" for="issu_weight">
|
||||
Le ticket en cours bloque le ticket suivant
|
||||
</label>
|
||||
<input type="hidden" id="modal-issueid" name="modal-issueid" required="required" class=" form-control" value="">
|
||||
<input type="integer" id="modal-issueblocked" name="modal-issueweight" required="required" class=" form-control" value="">
|
||||
</div>
|
||||
<button id="issu_blockupdate" class="btn btn-success">Enregistrer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mymodalassignees" class="modal" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title"></h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="modal-issueid" name="modal-issueid" required="required" class=" form-control" value="">
|
||||
|
||||
<div style="width:100%">
|
||||
<label class="control-label required" for="issu_weight">
|
||||
Affecté à
|
||||
</label>
|
||||
<select id="modal-assignees" multiple="multiple" class="form-control mb-3">
|
||||
{% for giteaassignee in giteaassignees %}
|
||||
<option value="{{giteaassignee.login}}">{{giteaassignee.login}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<button id="issu_assigne" class="btn btn-success mt-3">Enregistrer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mymodalnotes" class="modal" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title"></h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="modal-issueid" name="modal-issueid" required="required" class=" form-control" value="">
|
||||
|
||||
<div style="width:100%">
|
||||
<textarea id="modal-notes" style="width:100%; height:300px;">
|
||||
</textarea>
|
||||
</div>
|
||||
<button id="issu_notes" class="btn btn-success mt-3">Enregistrer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% set end = microtime(true) %}
|
||||
{% set duration = end - start %}
|
||||
<p>render time: {{ duration }} seconds</p>
|
||||
{% endblock %}
|
||||
|
||||
{% block localjavascript %}
|
||||
|
||||
|
||||
|
||||
function showFilters() {
|
||||
if($("#filters").hasClass("d-flex")) {
|
||||
toshow=0;
|
||||
|
@ -343,16 +552,43 @@
|
|||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$(".issue").tooltip({
|
||||
content: function() {
|
||||
return $(this).data('tooltip'); // Utilise le contenu de l'attribut data-tooltip
|
||||
},
|
||||
items: '[data-tooltip]', // Spécifie les éléments qui déclenchent le tooltip
|
||||
html: true // Autorise le HTML dans le tooltip (si nécessaire pour certains tooltips personnalisés)
|
||||
});
|
||||
|
||||
// Apply Filter
|
||||
function showhide() {
|
||||
if($("#filtermilestones").val().length !== 0) {
|
||||
// Vue condensée
|
||||
if($("#viewcondensed").is(':checked')) {
|
||||
$(".issu-detail").hide();
|
||||
}
|
||||
else {
|
||||
$(".issu-detail").show();
|
||||
}
|
||||
|
||||
// Afficher masquer les jalons
|
||||
if($("#filtermilestones").val().length !== 0 && $("#filtersprints").val().length === 0) {
|
||||
$("[data-milestone]").hide();
|
||||
$.each($("#filtermilestones").val(), function( index, value ) {
|
||||
console.log(value);
|
||||
$("[data-milestone="+value+"]").show();
|
||||
});
|
||||
}
|
||||
else $("[data-milestone]").show();
|
||||
|
||||
// Afficher masquer les sprints
|
||||
if($("#filtersprints").val().length !== 0) {
|
||||
$("[data-millestonesprint]").hide();
|
||||
$.each($("#filtersprints").val(), function( index, value ) {
|
||||
$("[data-millestonesprint="+value+"]").show();
|
||||
});
|
||||
}
|
||||
else if($("#filtermilestones").val().length === 0)$("[data-millestonesprint]").show();
|
||||
|
||||
$(".issue").show();
|
||||
|
||||
$( ".issue" ).each(function( index ) {
|
||||
|
@ -419,6 +655,15 @@
|
|||
});
|
||||
}
|
||||
|
||||
if($("#filtersprints").val().length!==0) {
|
||||
data = $("#filtersprints").select2('data');
|
||||
textfilters=textfilters+" <b>SPRINT</b> =";
|
||||
$.each($("#filtersprints").val(), function( index, value ) {
|
||||
if(index>0)textfilters=textfilters+" &";
|
||||
textfilters=textfilters+" "+data[index].text;
|
||||
});
|
||||
}
|
||||
|
||||
if($("#filterteams").val().length!==0) {
|
||||
data = $("#filterteams").select2('data');
|
||||
textfilters=textfilters+" <b>EQUIPES</b> =";
|
||||
|
@ -473,23 +718,61 @@
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
$("#textfilters").html(textfilters);
|
||||
}
|
||||
|
||||
function refreshinfo() {
|
||||
|
||||
$(document).on('click','.viewissu',function(){
|
||||
$(".submenu").hide();
|
||||
url="{{path('app_scrumissue_view',{id:"xxx"})}}";
|
||||
url=url.replace("xxx",$(this).data("issue"));
|
||||
|
||||
ModalLoad('mymodallarge','Aperçu Ticket',url);
|
||||
});
|
||||
|
||||
$(document).on('click','.lockissu',function(){
|
||||
$(".modal-title").html("#"+$(this).data("giteaid")+" - "+$(this).data("giteatitle"));
|
||||
$("#modal-issueid").val($(this).data("issue"));
|
||||
$("#modal-issueblocked").val("");
|
||||
$("#mymodalblock").modal('show');
|
||||
$("#modal-issueblocked").focus();
|
||||
});
|
||||
|
||||
$("#issu_blockupdate").click(function(){
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrum_info",{id:scrum.id})}}",
|
||||
url: "{{path("app_scrumissue_block")}}",
|
||||
data: {
|
||||
id:$("#modal-issueid").val(),
|
||||
issueblocked:$("#modal-issueblocked").val(),
|
||||
},
|
||||
success: function(data) {
|
||||
$(".totalweight").html("0");
|
||||
|
||||
Object.entries(data.weights).forEach(entry => {
|
||||
const [key, value] = entry;
|
||||
$("#total"+key).html(value);
|
||||
});
|
||||
location.reload();
|
||||
},
|
||||
error: function (request, status, error) {
|
||||
$("#issueblocked").modal('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click','.unlockissu',function(){
|
||||
if (window.confirm("Souhaitez-vous enlever le blocage ?")) {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_unblock")}}",
|
||||
data: {
|
||||
id:$(this).data("issue"),
|
||||
},
|
||||
success: function(data) {
|
||||
location.reload();
|
||||
},
|
||||
error: function (request, status, error) {
|
||||
alert("pb sur le déblocage");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click','.modissu',function(){
|
||||
$(".modal-title").html("#"+$(this).data("giteaid")+" - "+$(this).data("giteatitle"));
|
||||
|
@ -518,7 +801,7 @@
|
|||
weight:$("#modal-issueweight").val(),
|
||||
},
|
||||
success: function(data) {
|
||||
$("#issue"+$("#modal-issueid").val()+"-weight").html($("#modal-issueweight").val());
|
||||
$(".issue"+$("#modal-issueid").val()+"-weight").html($("#modal-issueweight").val());
|
||||
refreshinfo();
|
||||
$("#mymodalissue").modal('hide');
|
||||
},
|
||||
|
@ -528,6 +811,108 @@
|
|||
});
|
||||
});
|
||||
|
||||
$(".pick-a-color").on("change", function() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_color")}}",
|
||||
data: {
|
||||
id:$(this).data("issue"),
|
||||
color:$(this).val(),
|
||||
},
|
||||
success: function(data) {
|
||||
location.reload();
|
||||
},
|
||||
error: function (request, status, error) {
|
||||
alert("pb sur le set color");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click','.assigneissu',function(){
|
||||
$(".modal-title").html("#"+$(this).data("giteaid")+" - "+$(this).data("giteatitle"));
|
||||
$("#modal-issueid").val($(this).data("issue"));
|
||||
|
||||
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_info")}}",
|
||||
data: {
|
||||
id:$("#modal-issueid").val(),
|
||||
},
|
||||
success: function(data) {
|
||||
var tbassignees=[];
|
||||
if(data.giteajson.assignees) {
|
||||
for (let assignee of data.giteajson.assignees) {
|
||||
tbassignees.push(assignee.login);
|
||||
}
|
||||
}
|
||||
|
||||
$('#modal-assignees').select2();
|
||||
$('#modal-assignees').val(tbassignees);
|
||||
$('#modal-assignees').trigger('change');
|
||||
|
||||
$("#mymodalassignees").modal('show');
|
||||
$(".submenu").hide();
|
||||
$("#modal-assignees").focus();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
$("#issu_assigne").click(function(){
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_assigne")}}",
|
||||
data: {
|
||||
id:$("#modal-issueid").val(),
|
||||
assignees: $("#modal-assignees").val(),
|
||||
},
|
||||
success: function(data) {
|
||||
location.reload();
|
||||
},
|
||||
error: function (request, status, error) {
|
||||
alert("pb sur l'affectation au ticket");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click','.notesissu',function(){
|
||||
$(".modal-title").html("#"+$(this).data("giteaid")+" - "+$(this).data("giteatitle"));
|
||||
$("#modal-issueid").val($(this).data("issue"));
|
||||
|
||||
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_info")}}",
|
||||
data: {
|
||||
id:$("#modal-issueid").val(),
|
||||
},
|
||||
success: function(data) {
|
||||
$('#modal-notes').val(data.notes);
|
||||
|
||||
$("#mymodalnotes").modal('show');
|
||||
$(".submenu").hide();
|
||||
$("#modal-notes").focus();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
$("#issu_notes").click(function(){
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_notes")}}",
|
||||
data: {
|
||||
id:$("#modal-issueid").val(),
|
||||
notes: $("#modal-notes").val(),
|
||||
},
|
||||
success: function(data) {
|
||||
location.reload();
|
||||
},
|
||||
error: function (request, status, error) {
|
||||
alert("pb sur enregistrement du ticket");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Filter Milestones
|
||||
function filtermilestones() {
|
||||
$.ajax({
|
||||
|
@ -557,6 +942,35 @@
|
|||
filtermilestones();
|
||||
});
|
||||
|
||||
// Filter Sprint
|
||||
function filtersprints() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{ path('app_user_preference') }}",
|
||||
data: {
|
||||
key:'filtersprints',
|
||||
id:{{scrum.id}},
|
||||
value: $("#filtersprints").val()
|
||||
}
|
||||
});
|
||||
|
||||
showhide();
|
||||
}
|
||||
|
||||
$('#filtersprints').select2({sorter: data => data.sort((a, b) => a.text.localeCompare(b.text)),});
|
||||
{% if filtersprints %}
|
||||
{% for sprint in filtersprints %}
|
||||
$("#filtersprints").val($("#filtersprints").val().concat("{{sprint}}"));
|
||||
{%endfor%}
|
||||
$('#filtersprints').trigger('change');
|
||||
{% endif %}
|
||||
$('#filtersprints').on("select2:select", function(e) {
|
||||
filtersprints();
|
||||
});
|
||||
$('#filtersprints').on("select2:unselect", function(e) {
|
||||
filtersprints();
|
||||
});
|
||||
|
||||
// Filter Teams
|
||||
function filterteams() {
|
||||
$.ajax({
|
||||
|
@ -728,6 +1142,26 @@
|
|||
filterexcludes();
|
||||
});
|
||||
|
||||
// View condensed
|
||||
{% if viewcondensed %}
|
||||
$("#viewcondensed").prop( "checked", {{ viewcondensed }} )
|
||||
{% endif %}
|
||||
|
||||
$('#viewcondensed').change(function() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{ path('app_user_preference') }}",
|
||||
data: {
|
||||
key:'viewcondensed',
|
||||
id:{{scrum.id}},
|
||||
value: this.checked
|
||||
}
|
||||
}).done(function( data ) {
|
||||
showhide();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Resume filtre
|
||||
{% if not showfilters %}
|
||||
$("#filters").addClass("d-none");
|
||||
|
@ -739,23 +1173,28 @@
|
|||
refreshinfo();
|
||||
$("#mycontent").show();
|
||||
|
||||
lastupdate="{{scrum.updatedate|date("Ymd H:i:s")}}";
|
||||
lastupdate="{{updatedate|date("Ymd H:i")}}";
|
||||
console.log(lastupdate);
|
||||
|
||||
|
||||
// Sort columns
|
||||
$( ".scrumcolumn" ).sortable({
|
||||
handle: ".fa-arrows-alt",
|
||||
handle: ".issu-id",
|
||||
connectWith: ".scrumcolumn",
|
||||
cursor: "move",
|
||||
update: function( event, ui ) {
|
||||
start: function( event, ui ) {
|
||||
$(".submenu").hide();
|
||||
},
|
||||
stop: function( event, ui ) {
|
||||
id=$(ui.item).data("issue");
|
||||
oldcolumn=$(ui.item).data("column");
|
||||
oldmilestone=$(ui.item).data("milestone");
|
||||
oldsprint=$(ui.item).data("sprint");
|
||||
newcolumn=$(ui.item).parent().data("column");
|
||||
newmilestone=$(ui.item).parent().data("milestone");
|
||||
console.log("ID = "+id+" = Column : "+oldcolumn+">>"+newcolumn+" = Milestone : "+oldmilestone+">>"+newmilestone );
|
||||
|
||||
if(oldcolumn!=newcolumn||oldmilestone!=newmilestone) {
|
||||
newsprint=$(ui.item).parent().data("sprint");
|
||||
console.log("ID = "+id+" = Column : "+oldcolumn+">>"+newcolumn+" = Milestone : "+oldmilestone+">>"+newmilestone+" = Sprint : "+oldsprint+">>"+newsprint );
|
||||
|
||||
if(oldcolumn!=newcolumn||oldmilestone!=newmilestone||oldsprint!=newsprint) {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_change")}}",
|
||||
|
@ -763,13 +1202,17 @@
|
|||
id:id,
|
||||
oldcolumn:oldcolumn,
|
||||
oldmilestone:oldmilestone,
|
||||
oldsprint:oldsprint,
|
||||
newcolumn:newcolumn,
|
||||
newmilestone:newmilestone,
|
||||
newsprint:newsprint
|
||||
},
|
||||
success: function(data) {
|
||||
$(ui.item).data("column",newcolumn);
|
||||
$(ui.item).data("milestone",newmilestone);
|
||||
$(ui.item).data("sprint",newsprint);
|
||||
if(data) lastupdate=data;
|
||||
console.log(lastupdate);
|
||||
|
||||
refreshinfo();
|
||||
},
|
||||
|
@ -798,9 +1241,7 @@
|
|||
},
|
||||
});
|
||||
|
||||
|
||||
var intervalId = window.setInterval(function(){
|
||||
console.log(lastupdate);
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrumissue_ctrlchange")}}",
|
||||
|
@ -809,12 +1250,65 @@
|
|||
lastupdate:lastupdate
|
||||
},
|
||||
success: function(fgupdated) {
|
||||
if(fgupdated) {
|
||||
if(fgupdated=="1") {
|
||||
$("#haveupdate").show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 60000);
|
||||
}, 300000);
|
||||
|
||||
});
|
||||
|
||||
|
||||
function refreshinfo() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "{{path("app_scrum_info",{id:scrum.id})}}",
|
||||
success: function(data) {
|
||||
html="";
|
||||
$("[data-weight]").html("");
|
||||
|
||||
Object.entries(data.tbestim).forEach(entry => {
|
||||
const [keyj, jalon] = entry;
|
||||
|
||||
html+='<table style="color:var(--colorftbodydark);zoom:75%; width:100%; border:1px solid var(--colorbgbodylight)">';
|
||||
html+='<tr>';
|
||||
html+='<td class="pl-1">'+jalon.nmjal+'</td>';
|
||||
html+='<td class="pr-1" style="width:30px;text-align:right;">'+jalon.nbjrs+'</span></td>';
|
||||
html+='</tr>';
|
||||
|
||||
nofirst=false;
|
||||
Object.entries(jalon.sprints).forEach(entry => {
|
||||
const [keys, sprint] = entry;
|
||||
if(nofirst || sprint.idspr!=-100) {
|
||||
html+='<tr>';
|
||||
html+='<td class="pl-1">'+sprint.nmspr+'</td>';
|
||||
html+='<td class="pr-1" style="width:30px;text-align:right;">'+sprint.nbjrs+'</span></td>';
|
||||
html+='</tr>';
|
||||
}
|
||||
|
||||
Object.entries(sprint.columns).forEach(entry => {
|
||||
const [keys, column] = entry;
|
||||
$("[data-weight="+column.gicol+"-"+jalon.gijal+"-"+sprint.idspr+"]").html(column.nbjrs);
|
||||
|
||||
});
|
||||
nofirst=true;
|
||||
});
|
||||
|
||||
html+='</table>';
|
||||
});
|
||||
|
||||
$("#tbestim").html(html);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function issuhover(btn,idissu) {
|
||||
$(".submenu").hide();
|
||||
$("#submenu"+idissu).css("display","flex");
|
||||
}
|
||||
|
||||
function issuout(menu) {
|
||||
$(menu).css("display","none");
|
||||
}
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block localjavascript %}
|
||||
$(document).ready(function() {
|
||||
window.parent.$("#mymodalsprint").modal('hide');
|
||||
});
|
||||
{% endblock %}
|
|
@ -0,0 +1,52 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
{{ form_start(form) }}
|
||||
{{ form_widget(form.submit) }}
|
||||
<a class="btn btn-secondary" onClick="closeModal();">Annuler</a>
|
||||
|
||||
{% if mode=="update" %}
|
||||
<a href="{{ path('app_scrumsprint_delete',{'id':scrumsprint.id}) }}"
|
||||
class="btn btn-danger float-right"
|
||||
data-method="delete"
|
||||
data-confirm="Êtes-vous sûr de vouloir supprimer cet entregistrement ?">
|
||||
Supprimer
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<br><br>
|
||||
|
||||
{% if app.session.flashbag.has('error') %}
|
||||
<div class='alert alert-danger' style='margin: 5px 0px'>
|
||||
<strong>Erreur</strong><br>
|
||||
{% for flashMessage in app.session.flashbag.get('error') %}
|
||||
{{ flashMessage }}<br>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if app.session.flashbag.has('notice') %}
|
||||
<div class='alert alert-info' style='margin: 5px 0px'>
|
||||
<strong>Information</strong><br>
|
||||
{% for flashMessage in app.session.flashbag.get('notice') %}
|
||||
{{ flashMessage }}<br>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ form_row(form.name) }}
|
||||
{{ form_row(form.giteamilestone) }}
|
||||
{{ form_row(form.closed) }}
|
||||
{{ form_end(form) }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block localjavascript %}
|
||||
$(document).ready(function() {
|
||||
$("#scrumsprint_name").focus();
|
||||
});
|
||||
|
||||
function closeModal() {
|
||||
window.parent.$("#mymodalsprint").modal('hide');
|
||||
}
|
||||
{% endblock %}
|
|
@ -1,10 +1,15 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
{{wssurl}}
|
||||
<div id="chat" class="text-center mt-5">
|
||||
<div class="mb-2">online</div>
|
||||
<div id="online" style="mt-2"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block localjavascript %}
|
||||
{% if wssuse %}
|
||||
<script>
|
||||
var conn;
|
||||
|
||||
function connect() {
|
||||
|
@ -20,13 +25,14 @@
|
|||
subscribe("home",1,"{{userkey}}");
|
||||
sendMessage({command: "alive"});
|
||||
};
|
||||
|
||||
conn.onmessage = function(e) {
|
||||
ret=JSON.parse(e.data);
|
||||
console.log(ret.log);
|
||||
|
||||
switch(ret.command) {
|
||||
case "alive" :
|
||||
if(!$('#online'+ret.from.id).length) {
|
||||
console.log(ret);
|
||||
html='<img id="online'+ret.from.id+'" src="'+ret.from.avatar+'" class="avatar ml-2 mr-2" title="'+ret.from.displayname+'">';
|
||||
$("#online").append(html);
|
||||
}
|
||||
|
@ -57,5 +63,5 @@
|
|||
}
|
||||
|
||||
connect();
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -66,8 +66,6 @@
|
|||
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="nav-item"><a href="{{path("app_scrum")}}">Scrums</a></li>
|
||||
<a href="{{path("app_issue")}}">Issues</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
@ -154,6 +152,10 @@
|
|||
|
||||
{% endblock %}
|
||||
|
||||
<script>
|
||||
{{ include('Include/javascript.js.twig') }}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
||||
{% if app.session.get('viewclosed') %}
|
||||
|
|
Loading…
Reference in New Issue