Merge pull request #6964 from opf/spike/bim-bcf

EXPERIMENTAL for BIM Edition only: BCF-XML plugin for import and export
pull/7180/head
Wieland Lindenthal 6 years ago committed by GitHub
commit 20525deede
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      Gemfile.lock
  2. 1
      Gemfile.modules
  3. 342
      app/assets/fonts/openproject_icon/openproject-icon-font.svg
  4. BIN
      app/assets/fonts/openproject_icon/openproject-icon-font.ttf
  5. BIN
      app/assets/fonts/openproject_icon/openproject-icon-font.woff
  6. BIN
      app/assets/fonts/openproject_icon/openproject-icon-font.woff2
  7. 1
      app/assets/fonts/openproject_icon/src/export-bcf.svg
  8. 53
      app/assets/fonts/openproject_icon/src/import.svg
  9. 684
      app/assets/stylesheets/fonts/_openproject_icon_definitions.scss
  10. 2
      app/assets/stylesheets/fonts/_openproject_icon_font.lsg
  11. 18
      app/assets/stylesheets/layout/_main_menu.sass
  12. 51
      app/controllers/work_packages_controller.rb
  13. 18
      app/models/attachment.rb
  14. 20
      app/models/work_package/exporter/base.rb
  15. 2
      app/models/work_package/exporter/csv.rb
  16. 4
      app/models/work_package/exporter/pdf.rb
  17. 2
      app/models/work_package/exporter/success.rb
  18. 6
      app/services/add_work_package_note_service.rb
  19. 2
      app/services/create_work_package_service.rb
  20. 16
      app/uploaders/file_uploader.rb
  21. 1
      config/locales/en.yml
  22. 23
      lib/redmine/menu_manager/menu_helper.rb
  23. 3
      lib/redmine/menu_manager/menu_item.rb
  24. 2
      modules/bcf/Gemfile
  25. 20
      modules/bcf/app/assets/stylesheets/bcf/bcf.sass
  26. 4
      modules/bcf/app/controllers/bcf/base_controller.rb
  27. 88
      modules/bcf/app/controllers/bcf/linked_issues_controller.rb
  28. 5
      modules/bcf/app/models/bcf.rb
  29. 14
      modules/bcf/app/models/bcf/comment.rb
  30. 17
      modules/bcf/app/models/bcf/initialize_with_uuid.rb
  31. 33
      modules/bcf/app/models/bcf/issue.rb
  32. 26
      modules/bcf/app/models/bcf/viewpoint.rb
  33. 30
      modules/bcf/app/views/bcf/linked_issues/import.html.erb
  34. 56
      modules/bcf/app/views/bcf/linked_issues/index.html.erb
  35. 60
      modules/bcf/app/views/bcf/linked_issues/prepare_import.html.erb
  36. 30
      modules/bcf/config/locales/en.yml
  37. 46
      modules/bcf/config/routes.rb
  38. 36
      modules/bcf/db/migrate/20181214103300_add_bcf_plugin.rb
  39. 6
      modules/bcf/lib/open_project/bcf.rb
  40. 5
      modules/bcf/lib/open_project/bcf/bcf_xml.rb
  41. 145
      modules/bcf/lib/open_project/bcf/bcf_xml/exporter.rb
  42. 14
      modules/bcf/lib/open_project/bcf/bcf_xml/file_entry.rb
  43. 67
      modules/bcf/lib/open_project/bcf/bcf_xml/importer.rb
  44. 201
      modules/bcf/lib/open_project/bcf/bcf_xml/issue_reader.rb
  45. 180
      modules/bcf/lib/open_project/bcf/bcf_xml/issue_writer.rb
  46. 84
      modules/bcf/lib/open_project/bcf/bcf_xml/markup_extractor.rb
  47. 59
      modules/bcf/lib/open_project/bcf/engine.rb
  48. 12
      modules/bcf/lib/open_project/bcf/patches/api/v3/export_formats.rb
  49. 36
      modules/bcf/lib/open_project/bcf/patches/setting_seeder_patch.rb
  50. 44
      modules/bcf/lib/open_project/bcf/patches/work_package_patch.rb
  51. 7
      modules/bcf/lib/open_project/bcf/version.rb
  52. 1
      modules/bcf/lib/openproject-bcf.rb
  53. 23
      modules/bcf/openproject-bcf.gemspec
  54. 5
      modules/bim_seeder/app/seeders/bim_seeder/basic_data/type_seeder.rb
  55. 8
      modules/bim_seeder/config/locales/en.seeders.bim.yml
  56. 2
      modules/bim_seeder/openproject-bim_seeder.gemspec
  57. 2
      modules/bim_seeder/spec/seeders/demo_data_seeder_spec.rb
  58. 9
      modules/xls_export/lib/open_project/xls_export/filename_helper.rb
  59. 4
      modules/xls_export/lib/open_project/xls_export/work_package_xls_export.rb
  60. 3
      package.json

@ -124,10 +124,19 @@ PATH
acts_as_silent_list (~> 3.0.0)
openproject-pdf_export
PATH
remote: modules/bcf
specs:
openproject-bcf (9.0.0)
activerecord-import
rails (~> 5)
rubyzip (~> 1.2)
PATH
remote: modules/bim_seeder
specs:
openproject-bim_seeder (1.0.0)
openproject-bcf
PATH
remote: modules/boards
@ -975,6 +984,7 @@ DEPENDENCIES
openproject-auth_saml!
openproject-avatars!
openproject-backlogs!
openproject-bcf!
openproject-bim_seeder!
openproject-boards!
openproject-costs!

@ -43,4 +43,5 @@ group :opf_plugins do
gem 'openproject-boards', path: 'modules/boards'
gem 'openproject-bim_seeder', path: 'modules/bim_seeder', require: !!(ENV['OPENPROJECT_EDITION'] == 'bim')
gem 'openproject-bcf', path: 'modules/bcf', require: !!(ENV['OPENPROJECT_EDITION'] == 'bim')
end

@ -229,509 +229,515 @@
<glyph glyph-name="export-atom"
unicode="&#xF14A;"
horiz-adv-x="512" d=" M210 41C210 26 198 13 182 13C167 13 154 26 154 41S167 69 182 69C198 69 210 56 210 41zM156 150V113C182 113 207 102 225 84C244 65 254 41 254 15H291C290 89 230 149 156 150zM156 221V185C249 184 325 108 326 15H362C361 128 270 220 156 221zM455 326L336 444H62V-68H455V326zM107 -22V398H317L409 306V-22H107z" />
<glyph glyph-name="export-csv"
<glyph glyph-name="export-bcf"
unicode="&#xF14B;"
horiz-adv-x="512" d=" M448 326L329 444H54V-68H448zM100 -22V398H310L402 306V-22z M142.65 106.824H174.802Q184.349 106.824 189.012 105.859Q193.731 104.9590000000001 197.4070000000001 101.999Q201.138 99.0390000000001 203.607 94.083Q206.077 89.193 206.077 83.079Q206.077 76.451 203.004 70.917Q199.986 65.383 194.774 62.617Q202.126 60.107 206.076 54.057Q210.026 48.009 210.026 39.837Q210.026 33.402 207.448 27.288Q204.924 21.24 200.48 17.572Q196.09 13.968 189.616 13.132Q185.556 12.617 170.029 12.488H142.65zM158.89 91.124V69.309H169.535Q179.027 69.309 181.331 69.6300000000001Q185.501 70.21 187.861 72.977Q190.274 75.807 190.274 80.377Q190.274 84.752 188.19 87.455Q186.16 90.222 182.1 90.801Q179.685 91.123 168.218 91.123zM158.89 53.607V28.382H173.924Q182.703 28.382 185.062 28.962Q188.683 29.734 190.932 32.694Q193.237 35.718 193.237 40.737Q193.237 44.985 191.482 47.9450000000001Q189.726 50.905 186.379 52.256Q183.087 53.607 172.004 53.607zM275.263 47.172L291.01 41.317Q287.389 25.873 278.94 18.344Q270.544 10.879 257.596 10.879Q241.575 10.879 231.26 23.685Q220.945 36.555 220.945 58.82Q220.945 82.372 231.315 95.37Q241.685 108.433 258.584 108.433Q273.343 108.433 282.56 98.202Q288.0470000000001 92.152 290.79 80.827L274.714 76.323Q273.288 83.659 268.734 87.906Q264.234 92.153 257.761 92.153Q248.817 92.153 243.221 84.6230000000001Q237.679 77.095 237.679 60.2350000000001Q237.679 42.3460000000001 243.166 34.753T257.431 27.16Q263.906 27.16 268.569 31.986Q273.233 36.8120000000001 275.263 47.172zM305.11 12.488V106.824H360.252V90.866H321.35V68.536H354.928V52.578H321.35V12.4879999999999z" />
<glyph glyph-name="export-csv"
unicode="&#xF14C;"
horiz-adv-x="512" d=" M193 33C192 33 190 33 189 32S187 30 185 29C184 28 182 27 180 26C177 25 174 24 171 24C167 24 164 25 161 27C158 28 156 30 154 33C152 35 150 39 149 42C148 46 147 51 147 56S148 65 149 69S151 76 153 79C155 81 158 84 161 85S167 87 171 87S177 87 179 86S183 85 185 84C186 83 188 82 189 81C190 81 191 80 192 80S194 81 195 81S196 82 197 83L203 91C199 96 194 99 189 101C183 103 177 105 170 105S156 103 150 101C144 98 140 95 136 91C132 86 129 81 127 75S124 63 124 56C124 48 125 41 127 35C130 29 133 24 136 20C140 16 145 13 150 10C155 8 161 7 167 7C170 7 173 7 177 8C180 8 183 9 186 10C190 12 193 13 196 15S201 20 204 23L197 31C196 32 195 33 193 33zM274 55C272 57 269 59 266 60C264 61 261 63 258 64S252 66 249 66C246 67 244 68 242 69S238 71 237 73C235 74 235 76 235 78C235 81 236 83 238 85C241 87 245 88 249 88C252 88 254 88 257 87C259 87 261 86 262 85C264 84 265 84 267 83C268 82 269 82 270 82S272 82 273 83C274 83 274 84 275 85L280 93C277 96 272 99 267 101C261 103 255 105 249 105S238 104 233 102C229 101 225 99 222 96S217 90 215 87S213 80 213 76S213 68 215 65C216 62 218 60 220 58S225 54 228 53C230 52 233 50 236 49S242 47 245 47C248 46 250 45 252 44S256 42 258 40C259 39 259 37 259 35V30L256 27C255 26 253 25 251 24C249 24 247 23 244 23S238 24 236 24C233 25 231 26 230 27C228 28 226 29 225 30C224 30 223 31 221 31C220 31 219 31 218 30S216 29 215 28L210 19C212 17 214 16 216 14C219 13 222 12 224 10C227 9 230 9 233 8C237 7 240 7 243 7C249 7 255 8 259 9C264 11 268 13 271 16C275 19 277 22 279 26S281 34 281 39C281 43 281 46 279 49C278 51 276 53 274 55zM366 103C364 103 363 103 362 102C360 101 360 100 359 99L341 48C340 45 339 42 338 40C337 37 337 34 336 31C335 34 335 37 334 40C333 42 332 45 331 48L313 99C313 100 312 101 311 102S308 103 307 103H288L325 8H346L384 103zM453 325L334 444H59V-68H453V325H452zM105 -22V398H315L407 306V-22H105z" />
<glyph glyph-name="export-pdf-descr"
unicode="&#xF14C;"
unicode="&#xF14D;"
horiz-adv-x="512" d=" M159 191H345V160H159zM160 252H346V220H160zM160 313H346V281H160zM450 326L332 444H57V-68H450V326zM103 -22V398H313L404 306V-22H103zM195 95C192 97 188 99 184 101C179 102 174 103 168 103H138V10H155V43H168C174 43 179 44 183 45C188 47 192 49 195 52C198 54 200 57 201 61C203 65 204 69 204 73C204 78 203 82 202 85C200 89 198 92 195 95zM185 66C184 64 183 62 182 61C180 60 178 58 176 58C174 57 171 56 168 56H155V90H168C171 90 174 89 176 89C178 88 180 87 182 85C183 84 184 82 185 80S186 76 186 74C186 71 186 69 185 66zM286 90C282 94 277 97 271 100C266 102 259 103 252 103H217V10H252C259 10 266 12 271 14C277 16 282 19 286 23S294 32 296 38S299 50 299 57C299 63 298 70 296 75C294 81 290 86 286 90zM279 43C278 39 276 36 274 33C271 30 268 28 264 26C261 25 257 24 252 24H234V89H252C257 89 261 89 264 87C268 86 271 83 274 81C276 78 278 74 279 70C281 66 282 62 282 57S281 47 279 43zM371 89V103H313V10H330V48H365V62H330V89z" />
<glyph glyph-name="export-pdf-with-descriptions"
unicode="&#xF14D;"
unicode="&#xF14E;"
horiz-adv-x="512" d=" M159 191H345V160H159zM160 252H346V220H160zM160 313H346V281H160zM450 326L332 444H57V-68H450V326zM103 -22V398H313L404 306V-22H103zM195 95C192 97 188 99 184 101C179 102 174 103 168 103H138V10H155V43H168C174 43 179 44 183 45C188 47 192 49 195 52C198 54 200 57 201 61C203 65 204 69 204 73C204 78 203 82 202 85C200 89 198 92 195 95zM185 66C184 64 183 62 182 61C180 60 178 58 176 58C174 57 171 56 168 56H155V90H168C171 90 174 89 176 89C178 88 180 87 182 85C183 84 184 82 185 80S186 76 186 74C186 71 186 69 185 66zM286 90C282 94 277 97 271 100C266 102 259 103 252 103H217V10H252C259 10 266 12 271 14C277 16 282 19 286 23S294 32 296 38S299 50 299 57C299 63 298 70 296 75C294 81 290 86 286 90zM279 43C278 39 276 36 274 33C271 30 268 28 264 26C261 25 257 24 252 24H234V89H252C257 89 261 89 264 87C268 86 271 83 274 81C276 78 278 74 279 70C281 66 282 62 282 57S281 47 279 43zM371 89V103H313V10H330V48H365V62H330V89z" />
<glyph glyph-name="export-pdf"
unicode="&#xF14E;"
unicode="&#xF14F;"
horiz-adv-x="512" d=" M441 326L322 444H47V-68H441V326zM93 -22V398H303L395 306V-22H93zM186 95C183 97 179 99 175 101C170 102 165 103 158 103H128V10H146V43H158C164 43 170 44 174 45C179 47 182 49 185 52C188 54 191 57 192 61C194 65 194 69 194 73C194 78 194 82 192 85C191 89 189 92 186 95zM176 66C175 64 174 62 173 61C171 60 169 58 167 58C164 57 162 56 158 56H146V90H158C162 90 164 89 167 89C169 88 171 87 173 85C174 84 175 82 176 80S177 76 177 74C177 71 177 69 176 66zM277 90C273 94 268 97 262 100C256 102 250 103 243 103H208V10H243C250 10 256 12 262 14S273 19 277 23S284 32 287 38C289 44 290 50 290 57C290 63 289 70 287 75C284 81 281 86 277 90zM270 43C269 39 267 36 264 33C262 30 259 28 255 26C252 25 248 24 243 24H225V89H243C247 89 252 89 255 87C259 86 262 83 264 81C267 78 269 74 270 70C272 66 272 62 272 57S272 47 270 43zM362 89V103H303V10H321V48H355V62H321V89z" />
<glyph glyph-name="export-xls-descr"
unicode="&#xF14F;"
unicode="&#xF150;"
horiz-adv-x="512" d=" M142 10L173 58L144 103H161C162 103 163 103 163 102C164 102 164 102 165 101L186 67V69C187 69 187 70 187 70L207 101C208 102 209 103 210 103H227L197 59L228 10H210C209 10 208 11 208 11L206 13L184 49V47L183 46L163 13C162 13 162 12 161 11C160 11 159 10 158 10zM238 10V103H255V25H292V10H238zM297 22L302 30S303 31 304 31C304 32 305 32 306 32S308 32 309 31S312 29 314 28C315 27 317 26 320 25C322 24 325 24 328 24C333 24 336 25 339 27S343 33 343 37C343 39 343 41 341 43C340 45 338 46 337 47C334 48 332 49 330 50C327 50 324 51 322 52C319 53 317 54 314 55S309 58 307 60S304 64 302 67C301 70 300 73 300 77S301 84 302 87C304 91 306 93 308 96C311 98 314 100 318 102C322 103 326 104 331 104S341 103 346 101C351 100 355 97 358 94L354 86L352 84H350C349 84 348 84 347 85C346 85 344 86 343 87S340 88 338 89S334 90 331 90C329 90 327 90 325 89S322 88 320 87C319 86 318 84 318 83C317 82 317 80 317 78S317 74 319 73C320 71 321 70 323 69S328 67 330 66C333 66 335 65 338 64S343 62 346 61C348 59 351 58 353 56S356 52 358 49C359 47 360 43 360 39S359 31 357 28C356 24 354 21 351 18S345 13 341 12C337 10 332 9 327 9C324 9 321 10 319 10L310 13C308 14 305 15 303 17C301 18 299 20 297 22zM157 191H342V160H157zM158 252H343V220H158zM158 313H343V281H158zM447 326L329 444H54V-68H448V326zM100 -22V398H310L402 306V-22H100z" />
<glyph glyph-name="export-xls-with-descriptions"
unicode="&#xF150;"
unicode="&#xF151;"
horiz-adv-x="512" d=" M142 10L173 58L144 103H161C162 103 163 103 163 102C164 102 164 102 165 101L186 67V69C187 69 187 70 187 70L207 101C208 102 209 103 210 103H227L197 59L228 10H210C209 10 208 11 208 11L206 13L184 49V47L183 46L163 13C162 13 162 12 161 11C160 11 159 10 158 10zM238 10V103H255V25H292V10H238zM297 22L302 30S303 31 304 31C304 32 305 32 306 32S308 32 309 31S312 29 314 28C315 27 317 26 320 25C322 24 325 24 328 24C333 24 336 25 339 27S343 33 343 37C343 39 343 41 341 43C340 45 338 46 337 47C334 48 332 49 330 50C327 50 324 51 322 52C319 53 317 54 314 55S309 58 307 60S304 64 302 67C301 70 300 73 300 77S301 84 302 87C304 91 306 93 308 96C311 98 314 100 318 102C322 103 326 104 331 104S341 103 346 101C351 100 355 97 358 94L354 86L352 84H350C349 84 348 84 347 85C346 85 344 86 343 87S340 88 338 89S334 90 331 90C329 90 327 90 325 89S322 88 320 87C319 86 318 84 318 83C317 82 317 80 317 78S317 74 319 73C320 71 321 70 323 69S328 67 330 66C333 66 335 65 338 64S343 62 346 61C348 59 351 58 353 56S356 52 358 49C359 47 360 43 360 39S359 31 357 28C356 24 354 21 351 18S345 13 341 12C337 10 332 9 327 9C324 9 321 10 319 10L310 13C308 14 305 15 303 17C301 18 299 20 297 22zM157 191H342V160H157zM158 252H343V220H158zM158 313H343V281H158zM447 326L329 444H54V-68H448V326zM100 -22V398H310L402 306V-22H100z" />
<glyph glyph-name="export-xls-with-relations"
unicode="&#xF151;"
unicode="&#xF152;"
horiz-adv-x="512" d=" M142 10L173 58L144 103H161C162 103 163 103 163 102C164 102 164 102 165 101L186 67V69C187 69 187 70 187 70L207 101C208 102 209 103 210 103H227L197 59L228 10H210C209 10 208 11 208 11L206 13L184 49V47L183 46L163 13C162 13 162 12 161 11C160 11 159 10 158 10H142zM238 10V103H255V25H292V10H238zM297 22L302 30C302 30 303 31 304 31C304 32 305 32 306 32S308 32 309 31S312 29 314 28C315 27 317 26 320 25C322 24 325 24 328 24C333 24 336 25 339 27S343 33 343 37C343 39 343 41 341 43C340 45 338 46 337 47C334 48 332 49 330 50C327 50 324 51 322 52C319 53 317 54 314 55S309 58 307 60S304 64 302 67C301 70 300 73 300 77S301 84 302 87C304 91 306 93 308 96C311 98 314 100 318 102C322 103 326 104 331 104S341 103 346 101C351 100 355 97 358 94L354 86L352 84H350C349 84 348 84 347 85C346 85 344 86 343 87S340 88 338 89S334 90 331 90C329 90 327 90 325 89S322 88 320 87C319 86 318 84 318 83C317 82 317 80 317 78S317 74 319 73C320 71 321 70 323 69S328 67 330 66C333 66 335 65 338 64S343 62 346 61C348 59 351 58 353 56S356 52 358 49C359 47 360 43 360 39S359 31 357 28C356 24 354 21 351 18S345 13 341 12C337 10 332 9 327 9C324 9 321 10 319 10L310 13C308 14 305 15 303 17C301 18 299 20 297 22zM447 326L329 444H54V-68H448V326H447zM100 -22V398H310L402 306V-22H100z M146.2 303.5H299.4V201.1000000000001H146.2V303.5z M155.4 294.2000000000001H290.1V269.3000000000001H155.4V294.2000000000001z M295.1 264.4L339.5 264.8L339.5 243.4L295 243.4 M367.8 252.2C351.8 241.0000000000001 332.1 221.9 319.8 201.6V302.8C332.1 282.6 351.8 263.4 367.8 252.2z" />
<glyph glyph-name="export-xls"
unicode="&#xF152;"
unicode="&#xF153;"
horiz-adv-x="512" d=" M227 103H211C209 103 208 102 207 101L188 70C187 70 187 69 187 69C187 68 186 68 186 67L165 101C165 102 164 102 164 102C163 103 162 103 161 103H144L173 58L143 10H159C160 10 161 11 161 11L163 13L184 46V47C185 48 185 48 185 49L206 13C207 13 207 12 208 11C209 11 210 10 211 10H228L197 59zM255 103H238V10H292V25H255zM358 49C357 52 355 54 353 56S349 59 346 61C344 62 341 63 338 64C336 65 333 65 331 66C328 67 326 68 324 69S320 71 319 73C318 74 317 76 317 78S318 82 318 83C319 84 320 86 321 87S324 88 325 89C327 90 329 90 332 90C334 90 336 90 338 89S342 87 343 87C345 86 346 85 347 85C348 84 349 84 350 84H352C353 85 354 85 354 86L358 94C355 97 351 100 346 101C342 103 337 104 331 104C326 104 322 103 318 102C315 100 311 98 309 96C306 93 304 90 303 87S301 81 301 77S302 70 303 67S306 62 308 60S312 56 314 55C317 54 320 53 322 52C325 51 328 50 330 50C333 49 335 48 337 47S341 44 342 43C343 41 344 39 344 37C344 33 342 29 340 27C337 25 333 24 328 24C325 24 322 24 320 25L314 28C312 29 311 30 310 31C308 32 307 32 306 32S305 32 304 31C303 31 303 30 302 30L297 22C299 20 301 18 303 17C306 15 308 14 311 13C313 12 316 11 319 10C322 10 325 9 328 9C333 9 337 10 341 12C345 13 349 15 352 18C354 21 356 24 358 28C359 31 360 35 360 39S359 46 358 49zM448 326L329 444H54V-68H448V326zM100 -22V398H310L402 306V-22H100z" />
<glyph glyph-name="export"
unicode="&#xF153;"
unicode="&#xF154;"
horiz-adv-x="512" d=" M512 188L381 320V220H191V156H381V56zM318 -68H0V444H318V284H254V380H64V-4H254V92H318z" />
<glyph glyph-name="faq"
unicode="&#xF154;"
unicode="&#xF155;"
horiz-adv-x="512" d=" M134 117V200C64 210 11 261 11 321C11 389 77 444 158 444H256C338 444 404 389 404 321C404 256 342 202 265 199zM158 403C104 403 60 366 60 321S104 239 158 239H183V199L248 239H256C311 239 355 276 355 321S311 403 256 403zM318 -9C263 -6 218 32 218 79C218 128 266 168 324 168H395C454 168 501 128 501 79C501 36 463 -1 413 -8V-68zM324 138C285 138 254 112 254 79C254 47 285 21 324 21H330L378 -9V21H395C434 21 466 47 466 79C466 112 434 138 395 138zM174 378C186 385 199 388 213 388C225 388 234 385 241 380C249 374 252 366 252 356C252 351 251 347 250 344C249 340 247 337 244 334S236 327 229 321C224 317 220 313 218 311C216 308 215 304 215 299V295H198V301C198 307 199 313 201 317C204 321 208 326 214 331C221 336 226 341 228 344S231 351 231 355C231 360 229 364 226 367C222 369 218 371 211 371C206 371 200 370 196 368C191 367 186 365 181 362zM194 266C194 275 199 280 207 280C212 280 215 279 217 276C219 274 221 271 221 266C221 262 219 259 217 256C215 254 212 252 207 252C203 252 200 254 198 256C195 258 194 262 194 266zM348 48C348 51 349 53 351 55C352 56 355 57 358 57S363 56 365 55C366 53 367 51 367 48S366 43 365 41C363 40 361 39 358 39S352 40 351 41C349 43 348 45 348 48zM348 119H367L364 66H351z" />
<glyph glyph-name="filter"
unicode="&#xF155;"
unicode="&#xF156;"
horiz-adv-x="512" d=" M511 436H1L206 172V-60L306 -11V172z" />
<glyph glyph-name="flag"
unicode="&#xF156;"
unicode="&#xF157;"
horiz-adv-x="512" d=" M378 408S293 368 208 397C115 430 74 417 34 368C27 372 19 373 12 368C1 362 -2 348 4 338L230 -29C234 -35 241 -39 249 -39C253 -39 257 -38 260 -36C271 -29 274 -16 268 -5L167 158C207 206 249 219 341 187C426 157 511 198 511 198z" />
<glyph glyph-name="folder-add"
unicode="&#xF157;"
unicode="&#xF158;"
horiz-adv-x="512" d=" M288 108V140H352V204H480V300C480 318 466 332 448 332H256C238 332 215 343 203 356L189 372C177 385 154 396 136 396H32C14 396 0 382 0 364V44C0 26 14 12 32 12H288zM512 108H448V172H384V108H320V44H384V-20H448V44H512z" />
<glyph glyph-name="folder-locked"
unicode="&#xF158;"
unicode="&#xF159;"
horiz-adv-x="512" d=" M512 -20H352V108H512zM480 108H448V140H416V108H384V172H480zM320 140H352V204H480V300C480 318 466 332 448 332H256C238 332 215 343 203 356L189 372C177 385 154 396 136 396H32C14 396 0 382 0 364V44C0 26 14 12 32 12H320z" />
<glyph glyph-name="folder-open"
unicode="&#xF159;"
unicode="&#xF15A;"
horiz-adv-x="512" d=" M40 326H237L158 404H40zM473 -28H40L1 247H512zM473 286H40V326H473z" />
<glyph glyph-name="folder-remove"
unicode="&#xF15A;"
unicode="&#xF15B;"
horiz-adv-x="512" d=" M288 92V124H480V284C480 302 466 316 448 316H256C238 316 215 327 203 340L189 356C177 369 154 380 136 380H32C14 380 0 366 0 348V28C0 10 14 -4 32 -4H288zM320 28V92H512V28z" />
<glyph glyph-name="folder"
unicode="&#xF15B;"
unicode="&#xF15C;"
horiz-adv-x="512" d=" M0 18C0 -1 16 -17 34 -17H478C496 -17 512 -1 512 18V290C512 309 496 324 478 324H273C254 324 229 336 216 350L202 367C189 381 164 392 145 392H34C16 392 0 377 0 358z" />
<glyph glyph-name="forums"
unicode="&#xF15C;"
unicode="&#xF15D;"
horiz-adv-x="512" d=" M448 284H416V252C416 203 369 156 320 156H173L128 111V92C128 60 160 28 192 28H352L448 -68V28C480 28 512 60 512 92V220C512 252 480 284 448 284zM320 444H64C32 444 0 412 0 380V252C0 220 32 188 64 188C70 188 49 188 64 188V92L160 188H320C352 188 384 220 384 252V380C384 412 352 444 320 444z" />
<glyph glyph-name="from-fullscreen"
unicode="&#xF15D;"
unicode="&#xF15E;"
horiz-adv-x="512" d=" M290 91.6L290 -36.4L322 -36.4L322 69.6L437 -49.4L463 -23.4L344 91.6L450 91.6L450 123.6L290 123.6z M51 336.6L170 221.6L64 221.6L64 189.6L224 189.6L224 349.6L192 349.6L192 243.6L77 362.6z" />
<glyph glyph-name="getting-started"
unicode="&#xF15E;"
unicode="&#xF15F;"
horiz-adv-x="512" d=" M512 85L407 147V113H0V57H407V24zM76 321C78 323 80 324 81 326C81 319 80 311 80 300V208H103V350H84L42 317L54 303C66 313 74 319 76 321zM181 229L179 231H157C155 216 154 200 150 182H166C174 201 178 217 181 229zM300 228H232V229L257 253C268 263 276 272 281 278S289 290 291 296C294 301 295 308 295 314C295 326 291 335 283 342S264 352 251 352C243 352 235 351 227 348C220 345 212 341 204 334L217 319C223 324 229 328 234 330S245 333 250 333C257 333 262 331 266 327C270 324 272 318 272 312C272 307 271 303 269 299C268 295 265 290 262 286C258 281 251 273 240 262L203 225V208H300zM348 229L347 231H325C323 216 321 200 317 182H334C342 201 345 217 348 229zM451 217C461 224 465 235 465 249C465 258 462 266 457 271C452 277 443 281 432 282V283C441 285 449 289 454 295S462 309 462 318C462 328 458 337 450 343S430 352 416 352C399 352 384 348 371 338L382 322C389 326 395 329 400 331C405 332 410 333 415 333C423 333 429 332 433 328C437 325 439 320 439 314C439 298 427 291 405 291H392V272H404C417 272 427 270 433 266C439 263 442 257 442 250C442 241 439 235 434 231C428 227 420 225 409 225C403 225 396 225 390 227C383 229 376 231 370 234V213C381 208 394 206 410 206C428 206 442 210 451 217z" />
<glyph glyph-name="glossar"
unicode="&#xF15F;"
unicode="&#xF160;"
horiz-adv-x="512" d=" M256 300C256 380 78 396 0 396V44H32V12C96 12 224 31 224 -20H288C288 31 416 12 480 12V44H512V396C434 396 256 380 256 300zM32 364C48 364 62 363 76 362H87C150 357 216 344 223 306C224 304 224 302 224 300V62C177 89 90 92 32 92zM480 92C422 92 335 89 288 62V300C288 321 322 362 480 364zM97 183L80 135H60L113 288H137L190 135H168L152 183zM148 199L132 242C129 252 127 262 124 270C122 261 119 252 116 243L101 199zM325 147L412 271H333V288H438V276L352 152H439V135H325V147z" />
<glyph glyph-name="google-plus"
unicode="&#xF160;"
unicode="&#xF161;"
horiz-adv-x="512" d=" M269 25C269 29 268 33 267 37S266 44 265 47S262 54 260 57C257 61 255 63 254 66L246 74C243 78 240 80 238 82C236 83 233 86 229 89S222 94 220 95C219 97 215 99 211 102C206 105 203 107 202 108C199 108 194 109 188 109C177 109 167 108 157 107C148 105 137 103 127 99C116 96 107 92 99 86C91 81 84 74 79 65S71 46 71 34C71 21 75 10 81 0C88 -11 97 -19 108 -24C119 -30 130 -35 142 -37C154 -40 166 -42 179 -42C190 -42 201 -41 211 -38C221 -36 230 -32 239 -27S255 -15 261 -6C266 3 269 13 269 25zM234 272C234 283 233 295 230 308C226 321 222 333 216 345S202 367 192 375S171 387 158 387C140 387 127 380 117 367S102 338 102 320C102 311 103 302 106 292C108 282 111 272 116 262C120 252 126 243 132 235S145 221 154 216S172 209 182 209C200 209 214 214 222 226C230 237 234 253 234 272zM197 407H322L283 385H245C258 376 269 364 276 349C283 333 287 317 287 301C287 286 285 274 281 263C276 252 271 243 265 237L246 218C239 213 234 207 230 201C225 195 223 188 223 181C223 176 225 172 228 167S235 158 240 153C245 149 251 144 257 139C263 135 269 129 275 124C281 118 287 111 292 105C297 98 301 90 304 80C307 71 309 61 309 50C309 20 296 -7 269 -31C240 -56 200 -68 149 -68C138 -68 126 -67 115 -65C103 -63 92 -60 80 -56C68 -51 58 -46 49 -39S33 -24 27 -14C21 -3 18 8 18 21C18 33 22 46 29 60C35 72 44 82 56 91S82 107 98 112C113 116 128 120 142 122S170 125 185 126C173 142 167 156 167 168V175C168 177 168 179 169 181C169 182 170 184 171 187C172 189 172 191 173 193C165 192 159 191 153 191C124 191 100 201 80 219C60 238 49 262 49 290C49 316 58 340 77 361C95 382 117 396 143 402C161 406 179 407 197 407zM494 334V298H421V225H384V298H311V334H384V407H421V334z" />
<glyph glyph-name="group-by"
unicode="&#xF161;"
unicode="&#xF162;"
horiz-adv-x="512" d=" M51 312H460V275H51zM52 248H461V212H52zM154 444V342H52zM51 32H460V-5H51zM52 -32H461V-68H52zM154 164V62H51z" />
<glyph glyph-name="group"
unicode="&#xF162;"
unicode="&#xF163;"
horiz-adv-x="512" d=" M506 93C496 108 496 117 465 130C433 143 426 148 426 148L425 178S437 187 441 215C448 213 456 226 456 233C457 240 455 259 446 257C448 271 450 283 449 290C447 314 423 340 386 340S325 314 323 290C322 283 323 271 325 257C316 259 315 240 315 233C316 226 323 213 331 215C334 187 346 178 346 178L320 157C335 149 373 154 381 141C386 134 398 114 395 -3H512S514 80 506 93zM345 104C334 120 299 130 264 145S220 165 220 165V198S233 208 237 240C245 238 254 252 255 260C255 268 253 288 243 286C245 302 247 316 246 323C244 350 217 379 176 379S108 350 106 323C105 316 107 302 109 286C99 288 97 268 97 260C98 252 106 238 115 240C119 209 132 198 132 198V165S123 160 88 145S18 120 7 104C-2 89 0 -3 0 -3H352S354 89 345 104z" />
<glyph glyph-name="hamburger"
unicode="&#xF163;"
unicode="&#xF164;"
horiz-adv-x="512" d=" M32 348H480V284H32zM32 220H480V156H32zM32 92H480V28H32z" />
<glyph glyph-name="headline1"
unicode="&#xF164;"
unicode="&#xF165;"
horiz-adv-x="512" d=" M0 34V341H41V204H207V341H248V34H207V174H41V34zM330 263L421 342H452V64H512V34H348V64H414V273V292L359 245C358 244 357 243 355 242H351C349 242 347 242 345 243C344 244 342 245 341 246z" />
<glyph glyph-name="headline2"
unicode="&#xF165;"
unicode="&#xF166;"
horiz-adv-x="512" d=" M0 33V339H41V203H206V339H247V33H206V173H41V33zM308 33V46C308 49 308 52 310 54C311 57 312 60 315 62L413 161C421 169 428 177 435 185C442 192 447 200 452 208C457 215 461 223 463 231C466 239 467 247 467 256S465 273 462 280C460 287 456 292 451 297C446 301 440 304 433 307C427 309 419 310 412 310C404 310 397 309 390 306C384 304 378 301 373 297S364 288 360 283C357 277 354 271 353 264C352 260 350 257 348 255C346 254 343 253 339 253H334L314 256C316 270 320 283 325 293C331 304 338 313 347 320C356 328 366 333 377 337C389 341 401 343 414 343S439 341 450 337S471 327 479 320C488 313 494 304 499 293C504 283 506 271 506 257C506 246 504 235 501 226C498 216 493 207 487 198S474 180 467 172C459 164 451 155 443 147L362 64C368 65 374 67 379 68C385 69 391 69 396 69H499C503 69 506 68 508 66C511 63 512 60 512 56V33z" />
<glyph glyph-name="headline3"
unicode="&#xF166;"
unicode="&#xF167;"
horiz-adv-x="512" d=" M0 36V340H41V204H205V340H247V36H205V174H41V36zM308 112L324 119C327 120 330 121 333 121C335 121 338 120 340 119S344 116 345 113C345 113 346 112 346 111C346 111 347 110 347 109L354 95C357 90 361 86 365 81C370 76 376 73 383 70C391 66 399 65 410 65S430 67 438 70S453 78 458 83C463 89 467 95 470 102S474 116 474 122C474 130 473 138 471 145C469 151 465 157 459 162S446 171 436 174S413 178 397 178V205C410 206 421 207 430 210C439 212 446 216 452 221S462 231 464 238C467 244 468 251 468 259C468 268 467 276 464 282C461 289 458 294 453 298C448 303 442 306 436 308C429 310 422 311 414 311C407 311 400 310 393 308C386 305 381 302 376 298S366 289 363 284C360 278 357 272 355 266C354 262 353 259 350 257C348 255 345 254 342 254H339S338 254 337 255L317 258C319 272 323 284 328 295C334 305 341 314 350 322C359 329 369 334 380 338S403 344 416 344S441 342 452 338C463 335 473 329 481 322C489 316 495 307 499 298C504 288 506 277 506 266C506 256 505 247 502 240C500 232 496 226 492 220C487 214 482 209 475 205C469 201 461 198 453 196C473 190 488 182 497 169C507 157 512 142 512 123C512 109 509 97 504 85C499 74 491 65 482 57S462 43 450 39C438 34 425 32 411 32C394 32 381 34 369 38C358 42 348 48 340 55S326 71 321 80C316 90 311 101 308 112z" />
<glyph glyph-name="headset"
unicode="&#xF167;"
unicode="&#xF168;"
horiz-adv-x="512" d=" M477 258C451 364 362 441 256 441S61 364 35 262C16 255 3 239 3 220V166C3 140 22 121 48 121H99V262H67C93 348 166 409 256 409S419 348 445 262H413V121H435C410 60 362 15 298 -1C291 15 275 28 256 28C230 28 208 6 208 -20C208 -33 211 -42 218 -49C227 -62 240 -68 256 -68C278 -68 294 -52 301 -33C381 -17 445 44 470 121C493 124 509 143 509 166V217C509 236 496 255 477 258zM256 50C330 50 387 108 387 175V223C387 294 330 348 256 348S125 294 125 223V175C125 108 182 50 256 50z" />
<glyph glyph-name="help"
unicode="&#xF168;"
unicode="&#xF169;"
horiz-adv-x="512" d=" M117 394C124 401 133 407 142 413C152 419 162 424 173 429C183 433 195 437 208 439C221 442 234 443 249 443C269 443 288 440 304 435C321 429 335 422 347 412S368 389 374 375C381 361 384 345 384 327C384 310 382 294 376 281C371 268 365 257 357 248C349 238 340 230 331 223C321 216 313 210 304 203C296 197 289 191 283 186C278 180 275 173 274 165L266 114H208L202 171V177C202 188 204 196 209 204C214 211 221 218 228 225C236 232 244 238 253 244C261 251 269 257 277 265C284 272 290 280 295 289C300 299 302 310 302 322C302 331 301 338 298 345C294 351 290 357 285 362S273 370 266 373C258 375 250 376 241 376C228 376 217 375 208 372S191 366 185 363C178 359 173 356 169 353C164 350 160 348 157 348C149 348 143 352 139 359zM189 -15C189 -8 191 -1 193 5C195 12 198 17 202 22C206 26 211 30 217 33C222 36 228 37 234 37C241 37 248 36 254 33S265 26 270 22C274 17 278 12 281 5C283 -1 285 -8 285 -15C285 -23 283 -30 281 -36C278 -42 274 -48 270 -52C265 -57 260 -61 254 -63C248 -66 241 -67 234 -67C228 -67 222 -66 217 -63C211 -61 206 -57 202 -52C198 -48 195 -42 193 -36S189 -23 189 -15z" />
<glyph glyph-name="help1"
unicode="&#xF169;"
unicode="&#xF16A;"
horiz-adv-x="512" d=" M291 141C291 133 289 132 281 132H247C239 132 238 133 238 141V199C238 210 254 212 271 218C287 223 303 233 303 258C303 279 290 291 265 291C236 291 212 275 207 275C205 275 203 278 202 280L190 311C189 313 189 315 189 316C189 328 244 344 275 344C331 344 366 308 366 257C366 198 318 182 291 173zM266 11C244 11 227 29 227 50C227 72 244 90 266 90S305 72 305 50C305 29 287 11 266 11zM256 443C115 443 1 329 1 188S115 -67 256 -67S511 47 511 188S397 443 256 443zM256 -30C136 -30 38 68 38 188S136 406 256 406S474 308 474 188S376 -30 256 -30z" />
<glyph glyph-name="help2"
unicode="&#xF16A;"
unicode="&#xF16B;"
horiz-adv-x="512" d=" M437 369C337 469 175 469 75 369C-24 270 -24 108 75 8C175 -92 337 -92 437 8C536 108 536 270 437 369zM245 -17C217 -17 195 6 195 33C195 61 217 83 245 83S295 61 295 33C295 6 272 -17 245 -17zM280 158V131C280 117 275 112 262 112H225C212 112 207 117 207 131V192C207 208 223 213 237 217C240 218 244 219 247 220C266 227 277 235 277 255C277 262 277 282 244 282C224 282 206 274 195 270C189 267 186 266 182 266C176 266 170 271 169 277L156 310C155 313 155 316 155 318C155 342 230 356 255 356C318 356 361 315 361 255C361 189 311 169 280 158z" />
<glyph glyph-name="hierarchy"
unicode="&#xF16B;"
unicode="&#xF16C;"
horiz-adv-x="512" d=" M320 124V156H256V252H192V348H160V220H224V28H320V60H256V124z" />
<glyph glyph-name="home"
unicode="&#xF16C;"
unicode="&#xF16D;"
horiz-adv-x="512" d=" M415 298V417H349V349L255 423L1 227L48 174L84 196V-47H448V196L475 174L512 227zM316 -14H183V152H316z" />
<glyph glyph-name="hosting"
unicode="&#xF16D;"
unicode="&#xF16E;"
horiz-adv-x="512" d=" M512 120C512 91 502 67 482 47S438 17 410 17H119C87 17 58 29 35 52C12 76 0 104 0 137C0 160 6 182 19 201C32 221 48 235 69 245C68 250 68 254 68 256C68 294 82 326 108 353C135 379 167 393 205 393C233 393 258 385 281 369C304 354 321 333 331 308C344 319 358 325 375 325C394 325 410 318 424 305C437 291 444 275 444 256C444 243 440 231 433 219C456 214 475 202 490 184C505 165 512 144 512 120z" />
<glyph glyph-name="image1"
unicode="&#xF16E;"
unicode="&#xF16F;"
horiz-adv-x="512" d=" M448 332V44H64V332H448M512 396H0V-20H512zM232 260C232 234 210 212 184 212C157 212 136 234 136 260C136 287 157 308 184 308C210 308 232 287 232 260zM96 76H416V192L365 284L297 135L256 177S200 156 181 124C152 140 136 124 136 124z" />
<glyph glyph-name="image2"
unicode="&#xF16F;"
unicode="&#xF170;"
horiz-adv-x="512" d=" M296 180C296 162 282 148 264 148S232 162 232 180S246 212 264 212S296 198 296 180zM192 76H416V157L381 222L332 118L304 147S265 132 252 110C231 121 220 110 220 110zM448 300V396H0V108H96V-20H512V300zM96 172H64V332H384V300H96zM448 44H160V236H448z" />
<glyph glyph-name="import"
unicode="&#xF171;"
horiz-adv-x="512" d=" M321 188L190 320L190 220L0 220L0 156L190 156L190 56z M94 444L412 444L412 -68L94 -68V92L158 92L158 -4L348 -4L348 380L158 380L158 284H94z" />
<glyph glyph-name="info1"
unicode="&#xF170;"
unicode="&#xF172;"
horiz-adv-x="512" d=" M323 71C323 67 322 66 317 66H217C212 66 212 67 212 71V97C212 101 212 102 217 102H242V223H217C212 223 211 224 211 229V254C211 259 212 260 217 260H287C291 260 292 259 292 254V102H317C322 102 323 101 323 97V71zM267 285C249 285 234 300 234 318S249 350 267 350S299 336 299 318S285 285 267 285zM256 443C115 443 1 329 1 188S115 -67 256 -67S511 47 511 188S397 443 256 443zM256 -29C136 -29 38 68 38 188S136 406 256 406S474 308 474 188S376 -29 256 -29z" />
<glyph glyph-name="info2"
unicode="&#xF171;"
unicode="&#xF173;"
horiz-adv-x="512" d=" M436 368C337 467 175 467 76 368C-24 269 -24 107 76 8C175 -92 337 -92 436 8C536 107 536 269 436 368zM252 399C279 399 301 377 301 350S279 301 252 301S203 323 203 350S224 399 252 399zM330 40C330 30 325 25 315 25H189C179 25 174 30 174 40V72C174 82 179 87 189 87H212V223H189C178 223 173 228 173 238V270C173 280 178 285 189 285H277C287 285 292 280 292 270V87H315C325 87 330 82 330 72z" />
<glyph glyph-name="installation-services"
unicode="&#xF172;"
unicode="&#xF174;"
horiz-adv-x="512" d=" M182 76H435C461 76 480 95 480 121V313C480 338 461 358 435 358H77C51 358 32 338 32 313V121C32 95 51 76 77 76zM64 121V313C64 319 70 326 77 326H435C442 326 448 319 448 313V121C448 114 442 108 435 108H77C70 108 64 114 64 121zM214 41V50H13V34C13 25 19 18 29 18H480C490 18 496 25 496 34V50H298V41M160 137C160 188 202 230 256 230C307 230 352 188 352 137H410V172H378C374 178 374 185 371 191L400 210L378 242L349 220C342 226 336 230 333 236L349 265L314 284L298 255C291 258 282 258 275 262V294H237V258C230 258 224 258 218 255L202 284L170 265L186 239C176 236 170 230 163 223L138 242L115 210L141 194C138 188 134 178 131 172H109V137z" />
<glyph glyph-name="italic"
unicode="&#xF173;"
unicode="&#xF175;"
horiz-adv-x="512" d=" M105 -55C123 -53 135 -50 142 -45C153 -37 162 -21 169 3L265 349C268 363 271 373 272 379S274 390 274 396C274 408 270 417 262 422C253 427 239 430 218 431V443H412V431C392 428 378 424 370 418S355 397 348 373L252 27C249 14 247 4 245 -4C244 -11 243 -17 243 -22C243 -34 248 -43 257 -47S279 -54 297 -55V-67H105z" />
<glyph glyph-name="key"
unicode="&#xF174;"
unicode="&#xF176;"
horiz-adv-x="512" d=" M452 322C459 283 454 246 438 212S396 158 361 152C339 148 317 148 295 151L234 52L198 46L145 -39C140 -49 133 -54 122 -56L83 -63C79 -64 75 -64 71 -61C68 -58 66 -54 65 -50L57 1C54 11 56 20 63 29L195 227C187 244 181 264 176 288C170 325 179 356 203 384S259 429 298 436C334 443 367 435 398 413C428 391 446 360 452 322M388 283C398 298 402 315 399 333S387 365 372 375C358 386 342 390 325 387C308 383 295 374 284 359L278 347C277 343 277 340 278 337S280 331 280 329C281 326 283 324 287 320C291 317 294 314 296 312C299 311 302 308 307 304C313 300 317 298 319 296S325 291 330 287C336 283 340 280 342 279C345 278 348 276 352 273S359 269 362 269H370C374 270 377 271 380 274C382 276 385 279 388 283" />
<glyph glyph-name="link"
unicode="&#xF175;"
unicode="&#xF177;"
horiz-adv-x="512" d=" M176 137H80C62 137 48 152 48 169V207C48 224 62 239 80 239H176C188 239 197 232 203 223H254C247 259 215 287 176 287H80C36 287 0 251 0 207V169C0 125 36 89 80 89H176C216 89 250 120 255 159H206C201 146 190 137 176 137zM432 287H336C297 287 265 259 258 223H309C315 232 324 239 336 239H432C450 239 464 224 464 207V175C464 157 450 143 432 143H336C324 143 315 149 309 159H258C265 122 297 95 336 95H432C476 95 512 131 512 175V207C512 251 476 287 432 287zM338 159C355 159 368 173 368 191C368 208 355 223 338 223H173C157 223 144 208 144 191C144 173 158 159 175 159H338z" />
<glyph glyph-name="loading1"
unicode="&#xF176;"
unicode="&#xF178;"
horiz-adv-x="512" d=" M288 380C288 370 280 362 271 362S254 370 254 380V425C254 435 262 443 271 443S288 435 288 425zM181 370C186 362 183 351 175 346C167 342 156 345 151 353L129 392C124 401 126 411 135 416C143 421 153 418 158 409zM105 312C114 307 117 296 113 288C108 280 97 277 88 282L50 304C41 309 38 320 43 328C47 336 58 339 67 334zM64 220C74 220 82 212 82 203S74 186 64 186H19C9 186 1 193 1 203C1 212 9 220 19 220zM74 119C82 124 93 122 98 114C102 106 99 95 91 90L52 68C43 63 33 65 28 73C23 82 27 92 35 97zM132 37C137 46 148 49 156 45C164 40 167 29 162 20L140 -18C135 -27 124 -30 116 -25C108 -21 105 -10 110 -1zM224 -4C224 6 232 14 241 14S258 6 258 -4V-49C258 -59 250 -67 241 -67S224 -59 224 -49zM325 6C320 14 322 25 330 30C338 34 349 31 354 23L376 -16C381 -25 379 -35 371 -40C362 -45 352 -42 347 -33zM407 64C398 69 395 80 399 88C404 96 415 99 424 94L462 71C471 67 474 56 469 48C465 40 454 37 445 42zM448 156C438 156 430 164 430 173C430 183 438 190 448 190H493C503 190 511 183 511 173C511 164 503 156 493 156zM438 257C430 252 419 254 414 262C410 270 413 281 421 286L460 308C469 313 479 311 484 303C489 294 486 284 477 279zM380 339C375 330 364 327 356 331C348 336 345 347 350 356L372 394C377 403 388 406 396 401C404 397 407 386 402 377z" />
<glyph glyph-name="loading2"
unicode="&#xF177;"
unicode="&#xF179;"
horiz-adv-x="512" d=" M413 393H440V444H70V393H102C106 297 142 234 203 213V160C142 139 107 77 102 -17H70V-68H440V-17H413C409 77 373 139 313 160V213C374 234 409 297 413 393zM297 138C365 121 385 48 388 -17H363L317 36L260 103L203 36L157 -17H128C131 48 151 121 219 138L228 140V233L219 235C150 252 131 327 128 393H388C385 327 366 252 297 235L287 233V140zM315 289H209L236 258L262 228L288 258z" />
<glyph glyph-name="location"
unicode="&#xF178;"
unicode="&#xF17A;"
horiz-adv-x="512" d=" M253 444C183 444 77 412 77 284C77 220 218 -4 253 -68C288 -4 429 220 429 284C429 412 323 444 253 444zM253 228C222 228 197 253 197 284S222 340 253 340S309 315 309 284S284 228 253 228z" />
<glyph glyph-name="locked"
unicode="&#xF179;"
unicode="&#xF17B;"
horiz-adv-x="512" d=" M411 242V290C411 375 341 443 256 443S101 375 101 290V242H67V-67H445V242zM280 2H223L237 81C229 86 223 94 223 105C223 121 236 133 251 133C267 133 280 121 280 105C280 94 274 86 265 81zM342 242H170V290C170 336 209 374 256 374S342 336 342 290z" />
<glyph glyph-name="logout"
unicode="&#xF17A;"
unicode="&#xF17C;"
horiz-adv-x="512" d=" M495 172C495 269 436 352 353 389V302C393 272 419 225 419 172C419 82 346 8 256 8S93 82 93 172C93 225 119 272 159 302V390C76 352 17 269 17 172C17 40 124 -67 256 -67S495 40 495 172zM305 152C305 133 290 118 271 118H241C222 118 207 133 207 152V409C207 428 222 443 241 443H271C290 443 305 428 305 409z" />
<glyph glyph-name="mail1"
unicode="&#xF17B;"
unicode="&#xF17D;"
horiz-adv-x="512" d=" M255 145L484 346C482 347 481 347 479 347H29zM511 315C511 319 510 323 509 326L348 184L507 44C510 49 511 54 511 59V315zM2 328C0 324 -1 320 -1 315V59C-1 55 0 50 2 46L163 184zM324 162L255 102L187 163L30 28L31 27H478z" />
<glyph glyph-name="mail2"
unicode="&#xF17C;"
unicode="&#xF17E;"
horiz-adv-x="512" d=" M176 106L22 209L256 398L490 209L336 106L512 -47V223L256 441L0 223V-47zM483 -65L300 95H212L29 -65z" />
<glyph glyph-name="maintenance-support"
unicode="&#xF17D;"
unicode="&#xF17F;"
horiz-adv-x="512" d=" M150 -30C147 -30 147 -26 144 -26C134 -33 118 -36 106 -36C61 -36 22 2 22 47C22 63 26 79 35 92L32 95C32 98 32 98 29 102C29 105 29 105 26 108C13 92 3 70 3 47C3 -7 48 -52 102 -52C125 -52 144 -46 160 -33C157 -33 154 -30 150 -30zM474 82S470 79 474 82C477 70 480 57 480 47C480 2 442 -36 397 -36C384 -36 371 -33 362 -26C358 -30 352 -30 349 -33C346 -33 346 -33 342 -36C358 -46 374 -52 397 -52C451 -52 496 -7 496 47C496 66 490 82 480 98C477 92 474 86 474 82zM32 281C35 284 35 284 35 287C32 300 29 310 29 322C29 367 67 406 112 406C122 406 134 402 144 399C147 399 150 402 150 402C154 402 157 406 160 406C144 418 128 422 112 422C58 422 13 377 13 322C13 303 19 284 29 268C29 271 29 271 32 274V281zM362 406C365 406 368 402 368 402C378 406 387 409 400 409C445 409 483 370 483 326C483 313 480 300 474 290C477 284 477 284 480 281C480 278 480 278 483 274C483 271 483 271 486 268C496 284 502 303 502 322C502 377 458 422 403 422C384 422 368 415 355 409C355 409 358 406 362 406zM493 143C496 156 496 172 496 188S493 220 493 233C499 204 499 172 493 143zM486 118C483 111 483 108 480 102C483 108 486 114 486 118zM323 422C301 425 278 428 256 428S211 425 189 418C234 431 278 431 323 422zM490 252C493 246 493 239 493 233C493 239 490 246 490 252zM211 -49C224 -52 240 -52 256 -52S288 -49 301 -49C272 -55 240 -55 211 -49zM22 255C19 233 16 210 16 188S19 143 26 121C13 166 13 210 22 255zM326 418C333 415 339 415 342 412C336 415 330 418 326 418zM493 143C493 137 490 130 490 124C490 130 493 137 493 143zM211 -49C205 -49 198 -46 192 -46C198 -46 205 -49 211 -49zM320 -46C314 -49 307 -49 301 -49C307 -49 314 -46 320 -46zM170 412C176 415 179 415 186 418C182 418 176 415 170 412zM342 -36C336 -39 333 -39 326 -42C330 -42 336 -39 342 -36zM186 -42C179 -39 176 -39 170 -36C176 -39 182 -42 186 -42zM26 118C26 114 29 111 29 108S29 105 32 102C29 108 26 114 26 118zM150 -30C154 -33 157 -33 163 -36H166C160 -33 154 -33 150 -30zM480 95C477 92 477 86 474 82C474 86 477 92 480 95zM32 274C32 271 32 271 29 268C29 265 26 262 26 258C26 262 29 268 32 274zM163 412L160 409C157 409 154 406 150 406C154 406 160 409 163 412zM362 406C358 406 355 409 352 409S349 409 346 412C352 409 358 406 362 406zM486 258C486 262 483 265 483 268S483 271 480 274C483 268 486 262 486 258zM486 118V121C490 127 490 134 490 140C496 169 496 201 490 233C490 239 486 246 486 252V255C483 262 483 265 480 271C480 274 480 274 477 278C464 306 448 332 426 358C410 374 390 390 368 399C365 399 362 402 362 402C358 406 352 409 349 412C346 412 346 412 342 415C336 418 330 418 326 422H323C278 434 234 434 192 422H189C182 418 176 415 170 412H163C160 409 154 406 150 406C147 406 144 402 144 402C122 390 102 377 86 358C61 335 45 310 32 281V274C29 268 26 262 26 258V255C13 210 13 166 26 124V121C29 114 29 108 32 105C32 102 32 102 35 98C48 70 64 44 86 18C106 -1 125 -14 147 -26C150 -26 150 -30 154 -30C154 -33 160 -33 163 -36C166 -36 166 -36 170 -39C176 -42 179 -42 186 -46H189C195 -49 202 -49 208 -49C237 -55 269 -55 301 -49C307 -49 314 -46 320 -46H323C330 -42 333 -42 339 -39C342 -39 342 -39 346 -36C374 -23 400 -7 426 15C445 34 458 54 470 76V79C474 82 474 89 477 92C477 95 477 95 480 98C483 108 486 114 486 118zM406 38C387 18 362 2 336 -10L314 44C352 60 381 89 397 127L451 105C442 82 426 60 406 38zM397 246C390 265 378 281 365 297C349 313 333 322 314 329L336 383C362 374 387 358 406 335C426 316 442 290 454 265zM176 383L198 329C163 313 131 281 115 246L61 268C80 319 125 364 176 383zM115 130C122 111 134 95 147 79C163 63 179 54 198 47L176 -7C150 2 125 18 106 41C86 60 70 86 58 111zM170 102C122 150 122 226 170 271C218 319 294 319 339 271C387 223 387 146 339 102C294 57 218 57 170 102z" />
<glyph glyph-name="meetings"
unicode="&#xF17E;"
unicode="&#xF180;"
horiz-adv-x="512" d=" M448 378V122H287L264 110L192 61V122H64V378H448M512 442H0V58H128V-66L308 58H512z" />
<glyph glyph-name="menu"
unicode="&#xF17F;"
unicode="&#xF181;"
horiz-adv-x="512" d=" M0 444H128V316H0zM192 444H320V316H192zM384 444H512V316H384zM0 252H128V124H0zM192 252H320V124H192zM384 252H512V124H384zM0 60H128V-68H0zM192 60H320V-68H192zM384 60H512V-68H384z" />
<glyph glyph-name="microphone"
unicode="&#xF180;"
unicode="&#xF182;"
horiz-adv-x="512" d=" M320 188C320 153 291 124 256 124S192 153 192 188V380C192 415 221 444 256 444S320 415 320 380zM416 188V252H384V188C384 117 327 60 256 60S128 117 128 188V252H96V188C96 111 151 46 224 31V-4L128 -36V-68H384V-36L288 -4V31C361 46 416 111 416 188z" />
<glyph glyph-name="milestone"
unicode="&#xF181;"
unicode="&#xF183;"
horiz-adv-x="512" d=" M2 188L256 441L509 188L256 -65z" />
<glyph glyph-name="minus1"
unicode="&#xF182;"
unicode="&#xF184;"
horiz-adv-x="512" d=" M0 228H512V148H0z" />
<glyph glyph-name="minus2"
unicode="&#xF183;"
unicode="&#xF185;"
horiz-adv-x="512" d=" M468 443H44C20 443 1 424 1 401V-24C1 -47 20 -66 44 -66H468C492 -66 511 -47 511 -24V401C511 424 492 443 468 443zM426 146H86V231H426z" />
<glyph glyph-name="mobile"
unicode="&#xF184;"
unicode="&#xF186;"
horiz-adv-x="512" d=" M326 130H35V345C35 351 42 358 48 358H422C429 358 435 351 435 345V284H461V345C461 364 445 380 426 380H45C26 380 10 364 10 345V105C10 86 26 70 45 70H326zM291 50H179C170 50 163 44 163 34C163 25 170 18 179 18H291C301 18 307 25 307 34C307 44 298 50 291 50zM496 249C493 252 490 252 486 255H374C368 255 365 252 358 249C355 246 352 239 352 233V15C352 2 362 -7 374 -7H480C493 -7 502 2 502 15V233C502 239 499 246 496 249zM486 34H371V226H486zM410 242L413 246H438C442 246 442 246 442 242C442 239 438 239 438 239H416C413 239 410 239 410 242zM429 2C426 2 422 2 422 6C419 9 419 12 419 15C419 22 426 28 432 28S445 22 445 15C445 12 442 9 442 6C435 6 432 2 429 2zM442 239C445 239 445 239 445 242C445 246 442 246 442 246H416C413 246 413 246 413 242C413 239 416 239 416 239" />
<glyph glyph-name="modules"
unicode="&#xF185;"
unicode="&#xF187;"
horiz-adv-x="512" d=" M256 437L2 364V11L256 -61L510 11V364zM236 -15L41 41V312L236 256zM471 41L276 -15V256L471 312V41zM256 291L70 344L256 397L442 344z" />
<glyph glyph-name="more"
unicode="&#xF186;"
unicode="&#xF188;"
horiz-adv-x="512" d=" M0 -2V378H100V340H50V36H100V-2zM122 94C122 104 125 112 130 117C136 123 143 126 154 126C164 126 172 123 177 117C183 111 185 103 185 94C185 83 183 75 177 70C172 64 164 61 154 61C143 61 136 64 130 69C125 75 122 83 122 94zM225 94C225 104 227 112 233 117C238 123 246 126 256 126S274 123 280 117C285 111 288 103 288 94C288 83 285 75 280 70C274 64 266 61 256 61S238 64 233 69C227 75 225 83 225 94zM327 94C327 104 330 112 335 117C341 123 348 126 358 126C369 126 377 123 382 117C388 111 390 103 390 94C390 83 387 75 382 70C377 64 369 61 358 61C348 61 341 64 335 69C330 75 327 83 327 94zM412 36H462V340H412V378H512V-2H412z" />
<glyph glyph-name="move"
unicode="&#xF187;"
unicode="&#xF189;"
horiz-adv-x="512" d=" M511 188L375 325V260C103 260 81 99 81 67C140 196 375 132 375 132V67zM1 392V-16H341V52H307V18H35V358H307V324H341V392z" />
<glyph glyph-name="movie"
unicode="&#xF188;"
unicode="&#xF18A;"
horiz-adv-x="512" d=" M0 444V-68H512V444zM64 -36H32V-4H64zM64 60H32V92H64zM64 156H32V188H64zM64 252H32V284H64zM64 348H32V380H64zM416 -4H96V156H416zM416 220H96V380H416zM480 -36H448V-4H480zM480 60H448V92H480zM480 156H448V188H480zM480 252H448V284H480zM480 348H448V380H480z" />
<glyph glyph-name="music"
unicode="&#xF189;"
unicode="&#xF18B;"
horiz-adv-x="512" d=" M134 374V70C128 71 122 71 116 71C69 71 30 40 30 2S69 -66 116 -66C161 -66 197 -39 202 -5V319L409 360V138C403 139 397 140 392 140C344 140 306 109 306 71S344 2 392 2C436 2 472 30 477 64H478V442z" />
<glyph glyph-name="new-planning-element"
unicode="&#xF18A;"
unicode="&#xF18C;"
horiz-adv-x="512" d=" M64 444H248V316H64zM0 444H32V-68H0zM64 252H512V124H64zM64 60H390V-68H64z" />
<glyph glyph-name="news"
unicode="&#xF18B;"
unicode="&#xF18D;"
horiz-adv-x="512" d=" M461 401S376 317 285 304C276 278 270 250 270 221S276 164 285 137C376 125 461 40 461 40C527 139 527 303 461 401zM231 40C214 57 206 101 207 139H231V237V303H67C31 303 2 266 2 221S31 139 67 139H115C124 118 133 91 133 73C133 40 166 -25 199 -25C231 -25 264 8 231 40zM67 172C49 172 35 190 35 213C35 235 49 254 67 254z" />
<glyph glyph-name="no-hierarchy"
unicode="&#xF18C;"
unicode="&#xF18E;"
horiz-adv-x="512" d=" M320 316V348H224V28H320V60H256V124H320V156H256V220H320V252H256V316z" />
<glyph glyph-name="no-zen-mode"
unicode="&#xF18D;"
unicode="&#xF18F;"
horiz-adv-x="512" d=" M128 338L13 457L-13 431L106 316H0V284H160V444H128zM512 284V316H406L525 431L499 457L384 338V444H352V284zM512 60V92H352V-68H384V38L499 -81L525 -55L406 60zM0 92V60H106L-13 -55L13 -81L128 38V-68H160V92z" />
<glyph glyph-name="not-supported"
unicode="&#xF18E;"
unicode="&#xF190;"
horiz-adv-x="512" d=" M256 442C116 442 2 328 2 188S116 -66 256 -66S510 48 510 188S396 442 256 442zM256 373C294 373 330 361 360 341L103 84C83 114 71 150 71 188C71 290 154 373 256 373zM256 3C217 3 181 15 152 36L408 293C429 263 441 227 441 188C441 86 358 3 256 3z" />
<glyph glyph-name="notes"
unicode="&#xF18F;"
unicode="&#xF191;"
horiz-adv-x="512" d=" M416 412V444H384V412H320V444H288V412H224V444H192V412H128V444H96V412H0V-68H512V412zM448 -4H64V348H96V316H128V348H192V316H224V348H288V316H320V348H384V316H416V348H448z" />
<glyph glyph-name="openproject"
unicode="&#xF190;"
unicode="&#xF192;"
horiz-adv-x="512" d=" M411 443H357C309 443 270 404 270 356V218H175C172 218 170 217 168 217C164 217 160 218 155 218H101C53 218 14 179 14 131V20C14 -28 53 -67 101 -67H155C203 -67 242 -28 242 20V131C242 141 240 150 237 159H270V58C270 42 283 30 299 30S328 42 328 58V159H345C349 159 353 158 357 158H411C459 158 498 197 498 245V356C498 404 459 443 411 443zM184 20C184 5 171 -8 155 -8H101C85 -8 73 4 73 20V131C73 147 85 159 101 159H155C171 159 184 147 184 131V20zM439 245C439 229 427 217 411 217H357C355 217 353 217 351 218H354H351C338 221 328 231 328 245V356C328 371 341 384 357 384H411C426 384 439 372 439 356z" />
<glyph glyph-name="ordered-list"
unicode="&#xF191;"
unicode="&#xF193;"
horiz-adv-x="512" d=" M160 380H512V316H160zM160 220H512V156H160zM160 60H512V-4H160zM20 374L48 398H61V317H78V305H27V317H45V371C45 373 46 375 46 377L32 366S31 366 31 365H29C28 365 27 365 27 366C26 366 25 366 25 367zM18 145V150V154C19 155 19 156 20 157L48 185C51 187 53 190 55 192C56 194 58 196 59 198C61 200 61 202 62 205C63 207 63 209 63 212C63 214 63 216 62 218C62 219 61 221 59 222C58 223 57 224 55 224C54 225 52 225 50 225C46 225 43 224 40 222C38 220 36 218 35 215C35 213 34 212 33 211S31 210 29 210H27L19 212C20 216 21 220 23 223C25 227 27 230 30 232C32 234 35 236 39 237S46 239 50 239C55 239 59 238 62 237C66 235 69 234 71 231C74 229 76 226 77 223C79 220 79 216 79 212C79 209 79 206 78 203S76 197 74 194C72 192 70 189 68 187C66 184 63 182 61 179L40 158C42 158 44 159 46 159S50 160 52 160H75C77 160 78 159 79 158S81 156 81 154V145zM20 7L27 10C28 10 30 11 31 11S33 10 34 10S35 9 36 8C37 6 37 5 38 3C39 2 40 1 42 0C43 -2 44 -2 46 -3S50 -4 52 -4C55 -4 57 -4 59 -3S63 -1 64 1C66 2 67 4 67 5C68 7 68 9 68 10V16C67 18 66 20 65 21C63 22 61 23 58 24C56 25 52 25 47 25V37C51 37 54 37 57 38C59 38 61 39 63 40C64 42 66 43 66 45C67 47 67 48 67 50C67 55 66 58 63 60C61 63 58 64 54 64S47 63 44 61C42 59 40 56 39 53C39 52 38 50 37 50C36 49 35 49 33 49H31L23 50C24 55 25 59 27 62S31 68 34 70C36 73 40 74 43 75C47 77 50 77 55 77C59 77 63 76 66 75S72 72 75 70C77 68 79 66 80 63C82 60 82 57 82 53C82 50 82 48 81 45C81 43 80 41 78 40C77 38 76 37 74 35L68 32C73 31 77 28 80 24C83 21 84 16 84 11S83 2 82 -1C80 -5 78 -8 75 -10C72 -13 69 -14 65 -16C61 -17 57 -17 53 -17C48 -17 44 -17 40 -16C37 -15 34 -13 31 -11C29 -9 27 -7 25 -3C23 0 22 3 20 7z" />
<glyph glyph-name="outline"
unicode="&#xF192;"
unicode="&#xF194;"
horiz-adv-x="512" d=" M451 239H298V380C298 415 269 444 234 444H64C29 444 0 415 0 380V211C0 175 29 146 64 146H205V-7C205 -40 233 -68 267 -68H451C485 -68 512 -40 512 -7V177C512 211 485 239 451 239zM16 380C16 406 38 428 64 428H234C260 428 282 406 282 380V239H267C233 239 205 211 205 177V162H64C38 162 16 184 16 211zM438 68H375V7H338V68H275V105H338V170H375V105H438zM68 313H230V277H68z" />
<glyph glyph-name="paragraph-left"
unicode="&#xF193;"
unicode="&#xF195;"
horiz-adv-x="512" d=" M512 348C512 330 498 316 480 316H256C238 316 224 330 224 348S238 380 256 380H480C498 380 512 366 512 348zM512 28C512 10 498 -4 480 -4H256C238 -4 224 10 224 28S238 60 256 60H480C498 60 512 46 512 28zM512 188C512 206 498 220 480 220H416C398 220 384 206 384 188S398 156 416 156H480C498 156 512 170 512 188zM128 156V220H288V156zM0 188L128 284V92z" />
<glyph glyph-name="paragraph-right"
unicode="&#xF194;"
unicode="&#xF196;"
horiz-adv-x="512" d=" M0 348C0 330 14 316 32 316H256C274 316 288 330 288 348S274 380 256 380H32C14 380 0 366 0 348zM128 188C128 206 114 220 96 220H32C14 220 0 206 0 188S14 156 32 156H96C114 156 128 170 128 188zM0 28C0 10 14 -4 32 -4H256C274 -4 288 10 288 28S274 60 256 60H32C14 60 0 46 0 28zM384 156V220H224V156zM512 188L384 284V92z" />
<glyph glyph-name="paragraph"
unicode="&#xF195;"
unicode="&#xF197;"
horiz-adv-x="512" d=" M475 443H147V441C85 433 37 380 37 316C37 251 85 199 147 190V-67H220V370H292V-67H365V370H475z" />
<glyph glyph-name="payment-history"
unicode="&#xF196;"
unicode="&#xF198;"
horiz-adv-x="512" d=" M244 121C221 121 201 128 186 136L176 95C189 88 212 81 235 80V47H269V83C309 90 331 116 331 147S314 197 273 212C243 223 231 230 231 242C231 252 238 261 261 261C286 261 302 253 311 250L321 289C310 294 294 299 271 300V331H237V298C199 291 178 267 178 236C178 202 203 185 240 172C266 164 277 155 277 142C277 128 264 121 244 121zM448 353C403 404 341 435 273 440C181 446 94 403 44 329L1 350L16 204L123 289L90 305C131 361 199 392 269 387C324 384 373 359 409 319C445 278 462 227 458 174C451 64 353 -19 241 -11C182 -7 127 22 91 70L50 39C94 -21 163 -58 238 -64H256C389 -64 501 37 511 170C515 237 493 302 448 353z" />
<glyph glyph-name="phone"
unicode="&#xF197;"
unicode="&#xF199;"
horiz-adv-x="512" d=" M481 45L478 51C470 70 373 98 365 99C363 99 361 99 359 98C345 95 331 83 300 56C265 72 218 114 196 140C171 167 141 213 130 247C165 278 180 291 181 306C182 314 165 414 147 425C146 425 144 427 142 428C131 435 114 446 95 442C90 441 86 439 82 437C69 429 38 407 24 379C16 362 12 203 131 68C249 -65 394 -71 416 -66H419C448 -55 473 -27 483 -15C500 6 488 31 481 45z" />
<glyph glyph-name="pin"
unicode="&#xF198;"
unicode="&#xF19A;"
horiz-adv-x="512" d=" M321 444L290 349L195 255L164 286L69 255L164 160L132 129L2 -66L195 66L227 97L177 147L321 3L353 97L321 129L416 223L510 255z" />
<glyph glyph-name="play"
unicode="&#xF199;"
unicode="&#xF19B;"
horiz-adv-x="512" d=" M436 368C337 468 175 468 76 368C-24 269 -24 107 76 8C175 -92 337 -92 436 8C536 107 536 269 436 368zM298 114L171 39V337L298 262L426 188z" />
<glyph glyph-name="plugins"
unicode="&#xF19A;"
unicode="&#xF19C;"
horiz-adv-x="512" d=" M176 338L80 220C45 172 64 98 125 47S266 -4 301 41L397 162zM297 422L329 396L256 304L223 329zM416 330L449 304L376 211L343 237zM64 -14L80 -26L134 44L125 47L118 54z" />
<glyph glyph-name="plus"
unicode="&#xF19B;"
unicode="&#xF19D;"
horiz-adv-x="512" d=" M469 443H43C20 443 1 424 1 401V-25C1 -48 20 -67 43 -67H469C492 -67 511 -48 511 -25V401C511 424 492 443 469 443zM426 145H299V18H213V145H86V231H213V358H299V231H426z" />
<glyph glyph-name="pre"
unicode="&#xF19C;"
unicode="&#xF19E;"
horiz-adv-x="512" d=" M2 60V313H22C26 313 29 310 30 306L33 284C41 294 51 301 61 307S83 316 97 316C107 316 117 314 126 310S142 299 149 291C155 283 160 273 163 261S168 235 168 220C168 206 166 193 162 181C159 169 153 158 146 150C139 141 131 134 121 129S99 121 86 121C75 121 65 123 57 127C48 131 41 136 35 144V60zM35 169C41 161 48 155 55 152S70 147 79 147C97 147 110 153 120 166C129 178 134 196 134 220C134 232 133 243 131 251C128 260 125 268 121 273C117 279 112 283 106 286C100 288 93 290 86 290C75 290 65 287 57 282S42 270 35 261zM207 124V313H226C230 313 232 312 233 311C235 309 236 307 236 304L239 275C245 288 253 298 263 305C272 312 283 316 296 316C301 316 306 315 310 314C315 313 318 311 322 309L318 286C317 283 315 281 312 281C310 281 308 282 304 283S295 285 289 285C277 285 268 281 260 275C252 268 246 258 240 245V124zM344 222C344 235 346 248 350 259S360 280 367 289C375 297 384 304 395 308C406 313 419 316 432 316C444 316 454 314 463 310C473 306 481 301 488 293C495 286 501 277 504 267C508 256 510 245 510 231C510 226 510 222 509 221C508 219 505 218 502 218H377C377 206 379 196 382 187S389 171 394 165S406 155 413 152S428 148 437 148C445 148 453 149 459 151S470 155 474 157S482 161 485 163S490 166 492 166C495 166 497 165 499 163L508 151C504 146 499 141 493 137C488 134 481 131 475 128C468 126 462 124 455 123S441 121 434 121C421 121 409 123 398 128C387 132 377 139 369 147C361 156 355 166 351 179C346 191 344 206 344 222zM378 239H481C481 247 480 254 478 260C475 267 472 272 468 277S459 285 453 288C447 290 441 292 433 292C417 292 404 287 395 278C386 268 380 255 378 239z" />
<glyph glyph-name="presentation"
unicode="&#xF19D;"
unicode="&#xF19F;"
horiz-adv-x="512" d=" M77 157C82 155 86 157 88 162L108 220L154 150L201 223L249 145L293 282C294 286 292 290 287 292C283 293 279 291 277 286L244 183L201 253L154 179L104 256L72 167C71 163 73 158 77 157zM304 412V444H240V412H16V92H240V31L113 -68H145L240 -3V-4H304V-3L399 -68H431L304 31V92H496V412zM464 124H48V340H464zM421 258C421 235 402 216 378 216C355 216 336 235 336 258S355 300 378 300C402 300 421 281 421 258zM336 188H368V156H336zM400 188H432V156H400z" />
<glyph glyph-name="preview"
unicode="&#xF19E;"
unicode="&#xF1A0;"
horiz-adv-x="512" d=" M124 78V64C208 -75 403 -75 486 64V78C403 217 208 217 124 78zM305 -13C259 -13 222 25 222 71S259 154 305 154C352 154 389 117 389 71S352 -13 305 -13zM347 71C347 48 328 29 305 29S264 48 264 71S282 113 305 113S347 94 347 71zM430 325L312 444H37V-68H164V-22H83V398H293L384 306V215H430V325z" />
<glyph glyph-name="print"
unicode="&#xF19F;"
unicode="&#xF1A1;"
horiz-adv-x="512" d=" M480 252H416V311L316 412H96V252H32L0 220V60H96V-36H416V60H512V220zM64 188H32V220H64zM384 92V-4H128V156H384zM384 252H128V380H288V284H384zM475 100H445V148H475zM352 92H160V124H352zM352 28H160V60H352z" />
<glyph glyph-name="priority"
unicode="&#xF1A0;"
unicode="&#xF1A2;"
horiz-adv-x="512" d=" M256 332C212 332 176 296 176 252S212 172 256 172S336 208 336 252S300 332 256 332zM416 252C416 263 415 273 413 283L439 311L401 319C392 338 380 355 364 369L369 407L334 391C316 401 296 408 275 410L256 444L237 410C216 408 196 401 178 391L143 407L148 369C132 355 120 338 111 319L73 311L99 283C97 273 96 263 96 252S97 231 99 221L73 193L111 185C120 166 132 149 148 135L153 130L128 -68L256 60L384 -68L359 130L364 135C380 149 392 166 401 185L439 193L413 221C415 231 416 241 416 252zM256 140C194 140 144 190 144 252S194 364 256 364S368 314 368 252S318 140 256 140z" />
<glyph glyph-name="project-types"
unicode="&#xF1A1;"
unicode="&#xF1A3;"
horiz-adv-x="512" d=" M426 325L308 444H33V-68H211V-22H79V398H289L380 306V212H426V325zM262 94L370 40L477 94L370 147zM370 20L303 53L262 40L370 -14L477 40L439 54zM370 -34L303 -1L262 -14L370 -68L477 -14L439 0z" />
<glyph glyph-name="projects"
unicode="&#xF1A2;"
unicode="&#xF1A4;"
horiz-adv-x="512" d=" M0 316L256 188L512 316L256 444zM256 141L98 220L0 188L256 60L512 188L422 222zM256 13L98 92L0 60L256 -68L512 60L422 94z" />
<glyph glyph-name="publish"
unicode="&#xF1A3;"
unicode="&#xF1A5;"
horiz-adv-x="512" d=" M256 442C115 442 1 328 1 188S115 -66 256 -66S511 48 511 188S397 442 256 442zM358 76C358 74 358 71 356 69V70C344 61 344 35 329 29C321 25 322 36 325 40C330 46 323 50 326 56C323 57 320 64 320 67C323 68 325 70 325 69C326 70 330 77 330 78C331 72 323 61 326 56C327 56 327 56 329 58C329 55 329 52 331 49C327 63 341 63 348 72C350 75 354 84 357 85C359 83 359 80 358 77C359 79 358 77 358 76zM429 240C424 249 420 263 412 269C414 267 414 265 413 262C409 263 405 266 403 269C403 271 407 267 405 272C398 271 393 278 388 282C379 283 369 275 359 280C357 282 355 289 351 285C349 283 347 283 345 283C334 287 329 296 320 296C320 292 327 286 330 284C334 282 337 271 338 280C344 277 339 269 348 272C355 269 353 280 355 283C357 282 358 277 359 275C363 272 368 273 371 270C375 266 378 259 377 254C373 255 376 250 373 246C371 242 371 241 369 237C365 236 359 234 360 228C357 224 329 204 325 210S320 226 316 233C310 235 299 249 297 254C298 264 273 282 269 283C272 270 283 263 288 253C293 244 301 224 307 222C319 223 325 203 331 199C339 193 355 211 362 209C362 200 362 197 359 187C354 166 344 157 332 141C325 131 320 124 315 114C311 105 323 88 320 83C322 70 318 62 306 55C298 50 290 45 293 36C296 26 284 25 283 19C279 11 274 6 268 3C264 2 260 2 256 2C249 2 241 3 234 3C224 15 214 28 204 40C198 47 189 60 199 69C200 75 193 89 189 94C184 103 159 122 169 133C170 139 164 146 164 152C159 156 154 146 149 155C143 164 133 162 125 156C123 155 100 151 98 153C81 168 76 193 82 213C84 222 84 237 91 243C94 252 104 261 109 268C112 272 117 272 120 276C126 282 128 289 135 295C141 300 156 309 144 311C148 318 156 326 159 334C163 337 171 336 176 338C180 347 181 346 180 352C181 355 191 358 194 358C198 360 202 364 206 367C222 371 239 374 256 374C349 374 426 306 440 218C436 226 432 236 429 240zM253 352C254 352 254 353 255 354C249 352 252 358 247 352C248 347 242 343 245 338C250 333 256 341 262 342C262 338 274 339 276 338C273 339 277 339 276 338C287 345 253 352 253 352zM244 319C244 322 241 322 239 326C244 331 236 328 240 334C238 335 236 335 233 334C232 330 235 331 230 332C229 328 234 326 233 322C233 323 232 323 231 323C230 320 231 321 231 317C223 318 227 324 221 332C227 337 209 346 211 349C199 345 221 332 218 329C212 332 216 328 213 324C207 318 208 316 200 319C200 325 215 319 208 332C204 337 201 345 195 340C188 336 177 334 172 325C169 322 149 306 149 305C157 299 188 324 195 316C195 311 189 307 189 302C191 301 192 299 194 299C204 301 202 294 209 292C222 289 212 291 220 299C222 301 236 301 237 297C237 300 243 298 237 297C243 298 249 292 254 296C257 300 259 299 262 297C273 289 269 320 269 322C266 319 243 317 244 319zM195 324C193 323 192 323 191 323C192 326 196 338 199 338C199 334 195 328 195 324zM195 324C195 327 193 324 195 324zM293 352C294 353 294 356 296 356C294 364 286 357 286 352C289 348 302 342 303 338C300 337 304 328 309 328C312 325 316 325 320 326C319 334 299 349 293 352zM309 328C305 328 311 326 309 328zM318 351C315 352 312 359 309 360C308 358 308 358 308 357C308 358 309 355 308 357C309 355 315 348 318 351zM179 340C178 339 177 339 176 338H175C177 338 178 341 179 340z" />
<glyph glyph-name="pulldown-up"
unicode="&#xF1A4;"
unicode="&#xF1A6;"
horiz-adv-x="512" d=" M512 60L256 316L0 60z" />
<glyph glyph-name="pulldown"
unicode="&#xF1A5;"
unicode="&#xF1A7;"
horiz-adv-x="512" d=" M0 316L256 60L512 316z" />
<glyph glyph-name="quote"
unicode="&#xF1A6;"
unicode="&#xF1A8;"
horiz-adv-x="512" d=" M160 -68V63C69 78 0 157 0 252C0 358 86 444 192 444H320C426 444 512 358 512 252C512 150 432 66 331 60zM192 380C121 380 64 323 64 252S121 124 192 124H224V60L309 124H320C391 124 448 181 448 252S391 380 320 380z" />
<glyph glyph-name="quote2"
unicode="&#xF1A7;"
unicode="&#xF1A9;"
horiz-adv-x="512" d=" M1 172C1 329 90 383 219 389L237 307C172 299 141 269 141 219H226V-9H1zM275 172C275 329 364 383 493 389L511 307C446 299 415 269 415 219H500V-9H275z" />
<glyph glyph-name="redo"
unicode="&#xF1A8;"
unicode="&#xF1AA;"
horiz-adv-x="512" d=" M424 248C414 273 398 295 379 315C337 357 281 380 222 380S107 357 65 315S0 218 0 158C0 99 23 43 65 2C72 -5 81 -8 89 -8C98 -8 107 -5 113 2C127 15 127 37 113 50C84 79 68 117 68 158S84 238 113 267S181 312 222 312S301 296 330 267C352 245 366 219 372 189L299 107H512V346z" />
<glyph glyph-name="relation-follows"
unicode="&#xF1A9;"
unicode="&#xF1AB;"
horiz-adv-x="512" d=" M160 269.1H497.3V43.6999999999999H160V269.0999999999999z M180.4 248.8H476.9V194H180.4V248.8z M5.7 183.1L103.6 183.9L103.6 137L5.6 137 M165.8 156.2C130.6 131.5 87.1 89.5 60.2 44.8V267.5C87.1 223.1 130.6 180.9 165.8 156.2z" />
<glyph glyph-name="relation-new-child"
unicode="&#xF1AA;"
unicode="&#xF1AC;"
horiz-adv-x="512" d=" M170 274.2000000000001H507.3V48.8H170V274.2z M190.4 253.9H486.9V199.1H190.4V253.9z M15.7 188.2L113.6 189L113.6 142.1L15.6 142.1 M175.8 161.3C140.6 136.6 97.1 94.6 70.2 49.9V272.6C97.1 228.2 140.6 186 175.8 161.3z M43.8 345.4L44.5 142.6L6.6 142.6L6.6 345.6" />
<glyph glyph-name="relation-precedes"
unicode="&#xF1AB;"
unicode="&#xF1AD;"
horiz-adv-x="512" d=" M287.1 193.6 M221 243.3L222 242.3L223 242.3L222 243.3z M35 274.4H361.2V56.4H35V274.4z M54.7 254.8H341.4V201.8H54.7V254.8z M352 191.2L446.6 192L446.6 146.6L351.9 146.6 M506.8 165.2C472.8 141.3000000000001 430.7000000000001 100.7000000000001 404.7000000000001 57.5V272.9C430.7 229.9 472.8 189.1 506.8 165.2z" />
<glyph glyph-name="relations"
unicode="&#xF1AC;"
unicode="&#xF1AE;"
horiz-adv-x="512" d=" M154 73.2000000000001C133.9 73.2000000000001 113.8 80.8000000000001 98.5 96.1C83.7 110.9 75.5 130.6 75.5 151.6C75.5 172.5 83.7 192.2 98.5 207.1C129.1 237.7 178.8 237.7 209.4 207.1C224.2 192.3 232.4 172.6 232.4 151.6C232.4 130.7000000000001 224.2 111 209.4 96.1L209.4 96.1L209.4 96.1C194.2 80.9 174.1 73.2000000000001 154 73.2000000000001zM154 193.7C143.2 193.7 132.4 189.6 124.2 181.4C116.3 173.5 111.9 162.9 111.9 151.6C111.9 140.4 116.3 129.8 124.2 121.8C132.1 113.9 142.7 109.5 154 109.5S175.8 113.9 183.8 121.8L183.8 121.8C191.7 129.6999999999999 196.1 140.3 196.1 151.6C196.1 162.8 191.7 173.4 183.8 181.4C175.5 189.6 164.8 193.7 154 193.7z M232.3 138.4C223.6 138.4 216.4 145.3 216.1 154C215.8 163 222.7 170.5 231.7 170.9L296.7000000000001 173.4C305.6 173.7 313.2000000000001 166.8 313.6 157.8C313.9000000000001 148.8 307 141.3 298 140.9L233 138.4C232.8 138.4 232.6 138.4 232.3 138.4z M414.3 122.7000000000001C434.5 142.9 434.5 175.6 414.3 195.7C394.1 215.9 361.4000000000001 215.9 341.3 195.7C321.1 175.5 321.1 142.8000000000001 341.3 122.7000000000001C361.4 102.5 394.1 102.5 414.3 122.7000000000001 M330.3 300.2000000000001C350.5 320.4 350.5 353.1 330.3 373.2000000000001C310.1 393.4 277.4 393.4 257.3 373.2000000000001C237.1 353 237.1 320.3000000000001 257.3 300.2000000000001S310.1 280 330.3 300.2000000000001 M332.3 -58.3000000000001C352.5 -38.1 352.5 -5.4000000000001 332.3 14.6999999999999C312.1 34.9 279.4 34.9 259.3 14.6999999999999S239.1 -38.2 259.3 -58.3000000000001C279.4 -78.5 312.1 -78.5 332.3 -58.3000000000001 M198.8 199.7C195.6 199.7 192.4 200.6 189.5 202.6C182.1 207.7 180.3 217.9 185.4 225.2L222.5 278.6C227.6 286 237.8 287.8 245.1 282.7000000000001C252.5 277.6 254.3 267.4 249.2 260.1L212.1 206.7C209 202.2 203.9 199.7 198.8 199.7z M241 21.1999999999999C236.1 21.1999999999999 231.3 23.4 228.1 27.5999999999999L188.7 79.3C183.3 86.4 184.6 96.5999999999999 191.8 102.0999999999999C198.9 107.4999999999999 209.1 106.1999999999999 214.6 98.9999999999999L254 47.2999999999998C259.4 40.1999999999998 258.1 29.9999999999999 250.9 24.4999999999999C247.8 22.3 244.4 21.1999999999999 241 21.1999999999999z" />
<glyph glyph-name="reload"
unicode="&#xF1AD;"
unicode="&#xF1AF;"
horiz-adv-x="512" d=" M295 404C192 404 107 332 85 236L2 237L114 56L230 235L153 236C173 295 229 338 294 338C377 338 444 270 444 188C444 105 377 38 294 38C264 38 236 48 212 63L176 8C210 -14 251 -28 294 -28C413 -28 510 69 510 188S413 404 295 404z" />
<glyph glyph-name="reminder"
unicode="&#xF1AE;"
unicode="&#xF1B0;"
horiz-adv-x="512" d=" M250 287C324 287 383 227 383 153C383 80 324 20 250 20S116 80 116 153C116 227 176 287 250 287M250 354C139 354 50 264 50 153C50 43 139 -47 250 -47S450 43 450 153C450 264 361 354 250 354zM239 144C230 144 223 151 223 160V194C223 203 230 210 239 210C249 210 256 203 256 194V160C256 151 249 144 239 144zM294 100C290 100 286 101 283 104L229 147C222 153 220 163 226 171C232 178 243 179 250 173L304 130C311 124 312 114 307 106C303 102 298 100 294 100zM491 262C520 307 515 367 476 406S377 450 332 421zM21 262C-8 307 -3 367 36 406S135 450 180 421zM442 -59C435 -65 425 -65 418 -59L371 -12C364 -5 364 6 371 12C377 19 388 19 394 12L442 -35C448 -42 448 -52 442 -59zM70 -59C77 -65 87 -65 94 -59L141 -12C148 -5 148 6 141 12C135 19 124 19 118 12L70 -35C64 -42 64 -52 70 -59z" />
<glyph glyph-name="remove"
unicode="&#xF1AF;"
unicode="&#xF1B1;"
horiz-adv-x="512" d=" M451 -64L4 383L61 440L508 -7zM507 383L60 -64L4 -8L451 439z" />
<glyph glyph-name="rename"
unicode="&#xF1B0;"
unicode="&#xF1B2;"
horiz-adv-x="512" d=" M448 252L512 316L448 380H288V444H224V380H96V252H224V220H64L0 156L64 92H224V-68H288V92H416V220H288V252z" />
<glyph glyph-name="reported-by-me"
unicode="&#xF1B1;"
unicode="&#xF1B3;"
horiz-adv-x="512" d=" M478 9C468 23 437 33 406 46C376 59 368 63 368 63V94S380 103 383 131C390 129 398 142 398 149C399 156 397 174 389 172C390 186 392 199 391 205C389 230 365 255 329 255S270 230 268 205C267 199 268 186 270 172C261 174 260 156 260 149C261 142 268 129 276 131C279 103 291 94 291 94L290 63S283 59 252 46C222 33 190 23 181 9C173 -5 175 -68 175 -68H483S486 -5 478 9zM185 102C186 105 187 109 187 113S186 121 185 124C183 128 181 131 179 134C176 136 173 138 169 140C166 141 162 142 158 142C155 142 152 141 149 140C146 138 143 136 141 134C139 131 137 128 136 124C135 121 134 117 134 113S135 105 136 102C137 98 139 95 141 93C143 90 146 88 149 87C152 85 155 84 158 84C162 84 166 85 169 87C173 88 176 90 179 93C181 95 183 98 185 102zM138 221C139 209 140 197 142 185H175C177 198 178 209 180 221C181 232 181 243 181 255V365H136V255C136 243 136 232 138 221zM74 398H284L389 293L422 325L303 444H28V-68H108V-22H74z" />
<glyph glyph-name="resizer-vertical-lines"
unicode="&#xF1B2;"
unicode="&#xF1B4;"
horiz-adv-x="512" d=" M192 412H224V-100H192V412z M256 412H288V-100H256V412z" />
<glyph glyph-name="roadmap"
unicode="&#xF1B3;"
unicode="&#xF1B5;"
horiz-adv-x="512" d=" M381 17C369 3 345 -8 327 -8H33C15 -8 0 6 0 24V352C0 369 15 384 33 384H327C345 384 369 373 381 359L502 213C514 199 514 177 502 163z" />
<glyph glyph-name="rss"
unicode="&#xF1B4;"
unicode="&#xF1B6;"
horiz-adv-x="512" d=" M138 2C138 -36 108 -66 70 -66C33 -66 2 -36 2 2C2 39 33 70 70 70C108 70 138 39 138 2zM336 -62H246C245 2 220 61 175 107C130 152 70 177 6 178V268C187 265 333 119 336 -62zM510 -62H421C418 166 234 350 7 353V442C283 440 507 215 510 -62z" />
<glyph glyph-name="rubber"
unicode="&#xF1B5;"
unicode="&#xF1B7;"
horiz-adv-x="512" d=" M503 -50C503 -59 496 -67 486 -67H45C36 -67 28 -59 28 -50S36 -33 45 -33H486C496 -33 503 -41 503 -50zM477 293L339 432C332 439 323 443 315 443C306 443 297 440 291 433L19 161C5 148 5 126 19 113L97 30C110 16 136 1 155 1H207C226 1 252 16 265 30L477 244C490 257 490 280 477 293zM237 54C231 47 217 35 207 35H155C145 35 128 47 121 54L43 134L166 259L303 122z" />
<glyph glyph-name="save"
unicode="&#xF1B6;"
unicode="&#xF1B8;"
horiz-adv-x="512" d=" M256 60H192V-4H256zM0 444V-68H448L512 -4V444zM352 -36H160V92H352zM416 188H96V412H416z" />
<glyph glyph-name="search"
unicode="&#xF1B7;"
unicode="&#xF1B9;"
horiz-adv-x="512" d=" M497 -2L361 122C361 123 361 123 360 123C386 156 401 197 401 242C401 352 311 441 201 441S2 352 2 242S91 43 201 43C241 43 278 55 309 75C310 73 311 71 313 70L448 -54C463 -68 483 -69 493 -58L504 -46C514 -35 511 -15 497 -2zM201 95C120 95 54 161 54 242S120 389 201 389C283 389 348 323 348 242S283 95 201 95z" />
<glyph glyph-name="send-mail"
unicode="&#xF1B8;"
unicode="&#xF1BA;"
horiz-adv-x="512" d=" M164 288L308 416H20zM325 396C325 398 325 401 324 403L222 313L322 225C324 228 325 231 325 234zM3 404C2 401 2 399 2 396V234C2 231 3 229 4 226L105 313zM207 299L163 261L120 299L21 214H304zM254 -40L129 101C116 115 119 136 135 148C152 159 175 157 188 142L252 71L442 303C454 318 478 321 495 311C511 300 515 279 503 264z" />
<glyph glyph-name="server-key"
unicode="&#xF1B9;"
unicode="&#xF1BB;"
horiz-adv-x="512" d=" M511 180C506 200 491 225 471 234C461 239 450 242 439 245L406 244C395 240 385 236 375 231C347 215 340 181 338 153C338 145 342 138 344 130C206 -14 236 57 203 -53L256 -68C283 -37 264 -53 322 -31L321 3L340 21L359 4L394 40L376 56L399 81L423 77C438 80 455 82 469 88C495 98 504 126 512 148C511 159 513 170 511 180zM454 169C448 163 438 162 432 168C425 174 425 183 431 189C437 196 447 196 453 190S460 175 454 169zM46 398H347V313H394V444H0V-68H132V-22H46zM101 191H287V160H101zM102 252H288V220H102zM102 313H288V281H102z" />
<glyph glyph-name="settings"
unicode="&#xF1BA;"
unicode="&#xF1BC;"
horiz-adv-x="512" d=" M482 238H411C407 251 401 264 394 276L441 323C452 334 452 352 441 363L421 383C410 394 392 394 381 383L333 335C320 343 306 348 291 352V414C291 430 279 442 263 442H235C219 442 207 430 207 414V352C190 348 175 341 161 333L121 373C110 384 92 384 81 373L61 353C50 342 50 324 61 313L102 272C93 257 87 241 83 223H30C14 223 2 211 2 195V167C2 151 14 139 30 139H87C92 122 100 106 110 92L71 53C60 42 60 24 71 13L91 -7C102 -18 120 -18 131 -7L174 36C188 29 204 24 221 21V-38C221 -54 233 -66 249 -66H277C293 -66 305 -54 305 -38V28C320 33 333 40 345 49L391 3C402 -8 420 -8 431 3L451 23C462 34 462 52 451 63L401 113C407 125 412 139 415 153H482C498 153 510 165 510 181V209C510 225 498 238 482 238zM249 117C210 117 178 149 178 188S210 259 249 259S320 227 320 188S288 117 249 117z" />
<glyph glyph-name="settings2"
unicode="&#xF1BB;"
unicode="&#xF1BD;"
horiz-adv-x="512" d=" M332 143H283C280 152 276 161 271 169L304 201C311 209 311 221 304 229L290 242C282 250 270 250 262 242L230 210C221 215 211 219 201 221V264C201 275 192 283 181 283H162C151 283 143 275 143 264V221C131 218 121 214 111 208L84 236C76 243 64 243 56 236L43 222C35 214 35 202 43 194L71 166C65 156 60 145 58 133H21C11 133 2 124 2 113V94C2 83 11 75 21 75H60C64 63 69 52 76 42L50 16C42 8 42 -4 50 -12L63 -25C71 -33 83 -33 91 -25L120 4C130 -1 141 -4 152 -6V-47C152 -57 161 -66 172 -66H191C202 -66 211 -57 211 -47V-1C220 2 230 7 238 13L269 -18C277 -26 289 -26 297 -18L310 -5C318 3 318 15 310 23L276 57C280 66 284 75 286 84H332C343 84 351 93 351 104V123C351 134 343 143 332 143zM172 60C145 60 123 82 123 109C123 135 145 157 172 157S220 135 220 109C220 82 199 60 172 60zM498 353H467C465 359 462 364 459 369L480 390C485 395 485 403 480 407L471 416C466 421 458 421 454 416L433 395C427 398 421 401 414 403V430C414 437 409 442 402 442H390C383 442 377 437 377 430V403C370 401 364 398 357 394L340 412C335 417 327 417 322 412L314 403C309 398 309 390 314 386L332 368C328 361 325 354 323 346H300C293 346 288 341 288 334V322C288 315 293 309 300 309H325C327 302 331 295 335 289L318 272C313 267 313 259 318 255L327 246C332 241 340 241 344 246L363 265C369 261 376 259 384 258V232C384 225 389 220 396 220H408C415 220 421 225 421 232V261C427 263 433 266 438 270L458 250C463 245 471 245 475 250L484 259C489 264 489 272 484 276L462 298C465 304 467 309 468 316H498C505 316 510 321 510 328V340C510 347 505 353 498 353zM396 300C379 300 365 314 365 331S379 362 396 362S427 348 427 331S413 300 396 300z" />
<glyph glyph-name="settings3"
unicode="&#xF1BC;"
unicode="&#xF1BE;"
horiz-adv-x="512" d=" M504 347L436 280L361 296L345 371L413 439C402 441 391 443 380 444C309 444 251 386 251 315C251 300 254 286 259 272L27 42C-1 15 -4 -27 19 -51C43 -75 85 -72 113 -44L347 188C348 189 348 190 349 190C358 188 369 186 379 186C450 186 508 243 508 314C508 326 506 337 504 347z" />
<glyph glyph-name="settings4"
unicode="&#xF1BD;"
unicode="&#xF1BF;"
horiz-adv-x="512" d=" M444 376V0H68V376H444M512 444H0V-68H512zM171 69H137V307H171zM273 69H239V307H273zM375 69H341V307H375zM205 256C205 247 197 239 188 239H119C110 239 102 247 102 256C102 266 110 273 119 273H188C197 273 205 266 205 256zM307 154C307 144 300 137 290 137H222C212 137 205 144 205 154C205 163 212 171 222 171H290C300 171 307 163 307 154zM410 222C410 213 402 205 393 205H324C315 205 307 213 307 222C307 232 315 239 324 239H393C402 239 410 232 410 222z" />
<glyph glyph-name="shortcuts"
unicode="&#xF1BE;"
unicode="&#xF1C0;"
horiz-adv-x="512" d=" M457 -68H55C25 -68 0 -43 0 -13V389C0 419 25 444 55 444H457C487 444 512 419 512 389V-13C512 -43 487 -68 457 -68zM55 412C42 412 32 402 32 389V-13C32 -26 42 -36 55 -36H457C470 -36 480 -26 480 -13V389C480 402 470 412 457 412zM118 17C114 16 106 13 96 13C73 13 58 29 58 52S74 93 99 93C107 93 114 90 118 89L115 78C112 80 106 81 99 81C81 81 72 69 72 53C72 35 83 24 98 24C106 24 111 26 115 28zM153 113V91H173V80H153V39C153 30 155 24 163 24C167 24 169 25 171 25L172 15C169 14 165 13 160 13C153 13 148 15 145 19C141 23 139 30 139 39V80H127V91H139V109zM188 67V91H200V76H201C204 86 213 93 222 93C224 93 225 92 226 92V79C225 79 223 80 221 80C211 80 204 72 203 62C202 60 202 58 202 55V15H188zM240 127H254V15H240zM318 98V61H354V52H318V15H308V52H272V61H308V98z" />
<glyph glyph-name="show-all-projects"
unicode="&#xF1BF;"
unicode="&#xF1C1;"
horiz-adv-x="512" d=" M160 380H512V316H160zM160 220H512V156H160zM160 60H512V-4H160zM0 396H96V300H0zM0 236H96V140H0zM0 76H96V-20H0z" />
<glyph glyph-name="show-more-horizontal"
unicode="&#xF1C0;"
unicode="&#xF1C2;"
horiz-adv-x="512" d=" M71.28998 253.40953C109.79548 253.40953 141.69999 222.60551 141.69999 182.99952C141.69999 144.49496 109.79549 112.59046 71.28998 112.59046C32.78448 112.59046 0.87997 144.49496 0.87997 182.99952C0.87997 222.6055 32.78447 253.40953 71.28998 253.40953zM253.91599 253.40953C293.52103 253.40953 324.326 222.60551 324.326 182.99952C324.326 144.49496 293.52103 112.59046 253.91599 112.59046C215.4104900000001 112.59046 183.50598 144.49496 183.50598 182.99952C183.50693 222.6055 215.41048 253.40953 253.91599 253.40953zM440.9429800000001 253.40953C479.44848 253.40953 511.35299 222.60551 511.35299 182.99952C511.35299 144.49496 479.44849 112.59046 440.9429800000001 112.59046C402.4384200000001 112.59046 370.53392 144.49496 370.53392 182.99952C370.5329700000001 222.6055 402.4374800000001 253.40953 440.9429800000001 253.40953z" />
<glyph glyph-name="show-more"
unicode="&#xF1C1;"
unicode="&#xF1C3;"
horiz-adv-x="512" d=" M326 348C326 313 298 284 262 284C227 284 198 313 198 348S227 412 262 412C298 412 326 383 326 348zM326 182C326 146 298 118 262 118C227 118 198 146 198 182C198 217 227 246 262 246C298 246 326 217 326 182zM326 12C326 -23 298 -52 262 -52C227 -52 198 -23 198 12S227 76 262 76C298 76 326 47 326 12z" />
<glyph glyph-name="sort-ascending"
unicode="&#xF1C2;"
unicode="&#xF1C4;"
horiz-adv-x="512" d=" M256 444L182 315H330zM240 315H272V-68H240z" />
<glyph glyph-name="sort-by"
unicode="&#xF1C3;"
unicode="&#xF1C5;"
horiz-adv-x="512" d=" M363 444L289 315H437zM347 315H379V-68H347zM149 -68L75 61H223zM133 444H165V61H133z" />
<glyph glyph-name="sort-descending"
unicode="&#xF1C4;"
unicode="&#xF1C6;"
horiz-adv-x="512" d=" M256 -68L182 61H330zM240 444H272V61H240z" />
<glyph glyph-name="sort-down"
unicode="&#xF1C5;"
unicode="&#xF1C7;"
horiz-adv-x="512" d=" M256 -67L31 323H481zM31 443H481V385H31z" />
<glyph glyph-name="sort-up"
unicode="&#xF1C6;"
unicode="&#xF1C8;"
horiz-adv-x="512" d=" M256 443L31 53H481zM31 -9H481V-67H31z" />
<glyph glyph-name="square"
unicode="&#xF1C7;"
unicode="&#xF1C9;"
horiz-adv-x="512" d=" M437 113L361 63V-12L437 -63L512 -12V63zM437 15L382 52L437 89L492 52zM393 439L302 378V286L393 225L485 286V378zM393 320L326 364L393 409L460 364zM158 305L0 200V42L158 -63L315 42V200zM158 101L43 177L158 254L273 177z" />
<glyph glyph-name="star"
unicode="&#xF1C8;"
unicode="&#xF1CA;"
horiz-adv-x="512" d=" M256 430L319 249L511 245L358 129L413 -54L256 55L99 -54L154 129L1 245L193 249z" />
<glyph glyph-name="status-reporting"
unicode="&#xF1C9;"
unicode="&#xF1CB;"
horiz-adv-x="512" d=" M374 101V153L448 254H374V305L448 406H374V408C374 428 355 444 331 444H180C156 444 137 428 137 408V406H63L137 305V254H63L137 153V101H63L137 1V-32C137 -52 156 -67 180 -67H331C355 -67 374 -52 374 -32V1L448 101zM324 187C324 150 294 120 257 120S190 150 190 187S220 254 257 254S324 224 324 187zM324 339C324 302 294 272 257 272S190 302 190 339S220 406 257 406S324 376 324 339zM257 -33C220 -33 190 -3 190 34S220 101 257 101S324 71 324 34S294 -33 257 -33z" />
<glyph glyph-name="status"
unicode="&#xF1CA;"
unicode="&#xF1CC;"
horiz-adv-x="512" d=" M256 380C115 380 0 265 0 124V-4H512V124C512 265 397 380 256 380zM254 316C272 316 286 302 286 284C286 276 283 268 277 262S263 252 254 252C237 252 223 266 222 283C222 302 236 316 254 316zM65 82H63C53 83 46 87 40 94C35 101 32 109 33 117C35 134 49 146 65 146H69C77 145 85 141 90 134S98 119 97 110C95 94 82 82 65 82zM124 182C117 173 107 168 97 168C91 168 84 170 79 174C72 178 67 185 66 194C64 202 66 211 71 218C80 232 101 236 115 227C130 216 133 197 124 182zM180 233C176 231 171 229 165 229C154 229 143 236 137 246C129 262 134 281 150 289C165 298 186 291 194 276S196 242 180 233zM256 12C230 12 208 34 208 60S230 108 256 108S304 86 304 60S282 12 256 12zM353 252L304 102C292 115 275 124 256 124C253 124 250 123 248 123L323 265C331 281 344 291 351 288S359 269 353 252zM387 184C382 191 380 200 381 208C383 217 387 224 394 229C409 239 429 235 439 221C444 215 446 206 444 198C443 190 438 182 431 177C426 173 419 171 413 171C402 171 393 176 387 184zM463 81C458 77 451 75 445 75C434 75 425 80 419 88C414 95 412 104 413 112C415 121 419 128 426 133C441 143 461 139 471 125C476 119 478 110 476 102C475 94 470 86 463 81z" />
<glyph glyph-name="strike-through"
unicode="&#xF1CB;"
unicode="&#xF1CD;"
horiz-adv-x="512" d=" M512 205H345C332 210 318 216 304 220C288 225 272 230 257 235S228 246 216 252S195 266 187 275C180 283 177 294 177 307C177 317 179 327 183 336C188 345 194 352 202 359C211 366 221 371 232 375C244 379 257 381 272 381C289 381 303 379 316 375C328 371 339 367 348 362C357 358 364 354 370 350C377 347 382 345 387 345C395 345 400 348 404 356L423 388C405 405 383 419 357 429S302 444 270 444C242 444 217 440 195 432S154 414 139 401S113 373 105 355C97 338 93 320 93 302C93 280 97 262 104 247C112 232 121 219 134 209C135 207 137 206 138 205H0V159H242C252 156 261 153 270 150C286 146 299 140 311 134C323 127 333 120 341 111C348 102 352 90 352 77C352 66 350 55 345 45C341 36 335 27 327 19C318 12 308 6 295 2C282 -3 267 -5 250 -5C230 -5 214 -2 201 2C187 6 176 12 167 17C158 23 150 28 143 32C137 37 130 39 125 39C119 39 114 38 110 36C106 33 103 30 101 26L80 -7C100 -25 123 -39 152 -51C180 -62 211 -68 246 -68C276 -68 303 -64 326 -56C348 -47 368 -36 384 -22S412 9 420 29C428 48 432 69 432 92C432 112 428 129 421 143C418 149 414 154 411 159H512z" />
<glyph glyph-name="text"
unicode="&#xF1CC;"
unicode="&#xF1CE;"
horiz-adv-x="512" d=" M137 -67V-37C166 -36 183 -34 189 -31C194 -29 198 -24 200 -17C203 -6 204 25 204 77V296C204 355 204 389 203 396H151C125 396 101 395 81 393C73 393 69 392 68 390C66 389 64 385 63 378C60 361 58 342 58 320H28C27 370 26 398 26 405C25 415 24 427 22 439L25 443C37 442 49 441 62 440C83 440 123 439 182 439H330C391 439 432 440 452 440C464 441 475 442 486 443L490 439C488 424 486 411 486 400C486 398 485 372 484 320H454C454 339 452 357 449 375C448 383 446 389 445 390C443 392 439 392 433 393C413 395 389 396 361 396H309C308 387 308 354 308 296V78C308 25 309 -7 312 -17C314 -24 317 -28 323 -31C328 -34 346 -36 375 -37V-67C328 -65 288 -64 256 -64C222 -64 182 -65 137 -67z" />
<glyph glyph-name="ticket-checked"
unicode="&#xF1CD;"
unicode="&#xF1CF;"
horiz-adv-x="512" d=" M279 -68L182 42C172 53 174 69 187 78C199 87 218 85 228 74L277 18L425 199C435 211 453 213 466 205C479 196 482 180 472 168zM288 398L393 293L426 325L307 444H32V-68H159V-22H78V398z" />
<glyph glyph-name="ticket-down"
unicode="&#xF1CE;"
unicode="&#xF1D0;"
horiz-adv-x="512" d=" M419 47L461 120H427V238H324V120H292L334 47L377 -26zM306 398L412 293L444 325L326 444H51V-68H278V-22H97V398z" />
<glyph glyph-name="ticket-edit"
unicode="&#xF1CF;"
unicode="&#xF1D1;"
horiz-adv-x="512" d=" M215 -50L221 -7L227 37L264 0L301 -38L258 -44zM425 111L314 0L301 12L413 124L388 148L276 37L264 49L375 161L363 173L239 49L314 -25L437 99zM476 136C483 142 483 153 476 160L426 210C419 216 408 217 402 210C401 209 401 209 401 208L400 209L377 185L451 110L475 134L474 135C475 135 476 135 476 136zM288 398L394 293L426 325L308 444H33V-68H160V-22H79V398z" />
<glyph glyph-name="ticket-minus"
unicode="&#xF1D0;"
unicode="&#xF1D2;"
horiz-adv-x="512" d=" M322 57V100H481V57zM427 326L309 444H34V-68H428V19H382V-22H80V398H290L382 306V138H428V326z" />
<glyph glyph-name="ticket-note"
unicode="&#xF1D1;"
unicode="&#xF1D3;"
horiz-adv-x="512" d=" M82 398H292L397 293L430 325L311 444H36V-68H163V-22H82zM365 241H292C231 241 182 192 182 131C182 77 222 31 274 22V-53L372 21C430 24 476 73 476 131C476 192 426 241 365 241zM365 58H359L310 21V58H292C251 58 219 91 219 131C219 172 251 205 292 205H365C406 205 439 172 439 131C439 91 406 58 365 58z" />
<glyph glyph-name="ticket"
unicode="&#xF1D2;"
unicode="&#xF1D4;"
horiz-adv-x="512" d=" M453 326L334 444H59V-68H453V326zM105 -22V398H315L407 306V-22H105z" />
<glyph glyph-name="time"
unicode="&#xF1D3;"
unicode="&#xF1D5;"
horiz-adv-x="512" d=" M256 368C355 368 436 287 436 188S355 8 256 8S76 89 76 188S157 368 256 368M256 442C116 442 2 328 2 188S116 -66 256 -66S510 48 510 188S396 442 256 442zM260 193C249 193 241 201 241 211V285C241 295 249 304 260 304C270 304 278 295 278 285V211C278 201 270 193 260 193zM352 119C348 119 344 120 341 123L248 197C240 203 239 215 245 223C252 231 263 232 271 226L364 152C372 145 373 134 367 126C363 121 358 119 352 119z" />
<glyph glyph-name="to-fullscreen"
unicode="&#xF1D4;"
unicode="&#xF1D6;"
horiz-adv-x="512" d=" M87 -55.3000000000001L215 -55.3000000000001L215 -23.3000000000001L109 -23.3000000000001L228 91.7000000000001L202 117.7000000000001L87 -1.3000000000001L87 104.7000000000001L55 104.7000000000001L55 -55.3000000000001z M320 183.7L435 302.7000000000001L435 196.7L467 196.7L467 356.7000000000001L307 356.7000000000001L307 324.7000000000001L413 324.7000000000001L294 209.7z" />
<glyph glyph-name="toggle"
unicode="&#xF1D5;"
unicode="&#xF1D7;"
horiz-adv-x="512" d=" M131 445H225V351H131zM131 236H225V142H131zM131 25H225V-69H131zM287 344H381V250H287zM287 130H381V37H287z" />
<glyph glyph-name="training-consulting"
unicode="&#xF1D6;"
unicode="&#xF1D8;"
horiz-adv-x="512" d=" M3 374V-10H512V374zM147 6H13S10 60 19 70C22 73 29 79 35 82V342H480V22H278V6zM275 70C266 82 240 89 214 102C189 111 182 118 182 118V143S192 150 195 175C198 172 205 182 205 188S205 210 195 207C195 220 198 230 198 236C198 258 176 278 147 278C115 278 96 255 93 236C93 230 93 220 96 207C86 210 86 194 86 188S93 172 99 172C102 146 112 140 112 140V114L80 98C64 92 48 86 35 79C29 76 22 73 19 66C13 54 13 2 13 2H282V18C278 38 278 63 275 70zM285 166L256 134L301 156C310 153 320 150 330 150H381C426 150 461 185 461 230C461 274 426 310 381 310H330C285 310 250 274 250 230C250 204 262 178 285 166zM330 297H381C416 297 445 268 445 233S416 169 381 169H330C294 169 266 198 266 233S294 297 330 297zM304 258H403V249H304zM304 236H403V226H304zM304 217H403V207H304z" />
<glyph glyph-name="two-factor-authentication"
unicode="&#xF1D7;"
unicode="&#xF1D9;"
horiz-adv-x="512" d=" M411 242.0000000000001V290C411 375 341 443 256 443S101 375 101 290V242.0000000000001H67V-67H445V242.0000000000001H411zM342 242.0000000000001H170V290C170 336 209 374 256 374S342 336 342 290V242.0000000000001zM214.4 2H147.7L164.1 94.5C154.7 100.4 147.7 109.7000000000001 147.7 122.6C147.7 141.3000000000001 162.9 155.4000000000001 180.5 155.4000000000001C199.2 155.4000000000001 214.4 141.4000000000001 214.4 122.6C214.4 109.7000000000001 207.4 100.4000000000001 196.8 94.5L214.4 2zM364.3 3.1999999999999H297.6L314 95.6999999999999C304.6 101.5999999999999 297.6 110.9 297.6 123.8C297.6 142.5 312.8 156.6 330.4000000000001 156.6C349.1 156.6 364.3 142.6 364.3 123.8C364.3 110.9 357.3 101.6 346.7 95.6999999999999L364.3 3.1999999999999z" />
<glyph glyph-name="types"
unicode="&#xF1D8;"
unicode="&#xF1DA;"
horiz-adv-x="512" d=" M511 347L415 443H288L1 156L224 -67L511 220zM385 266C357 266 334 289 334 317S357 368 385 368C413 367 435 345 435 317S413 266 385 266z" />
<glyph glyph-name="underline"
unicode="&#xF1D9;"
unicode="&#xF1DB;"
horiz-adv-x="512" d=" M79 174V444H139V174C139 155 142 138 147 123C152 107 160 94 170 82C180 71 192 62 207 56C221 50 238 47 256 47C275 47 291 50 305 56C320 62 332 71 342 82S360 107 365 122C370 138 373 155 373 173V444H433V174C433 148 429 124 421 102C413 81 401 62 386 46S352 17 330 8S284 -6 256 -6C229 -6 204 -1 182 8S142 30 126 46C111 62 99 81 91 102C83 124 79 148 79 174zM54 -36H458V-68H54z" />
<glyph glyph-name="undo"
unicode="&#xF1DA;"
unicode="&#xF1DC;"
horiz-adv-x="512" d=" M88 248C98 273 114 295 133 315C175 357 231 380 290 380S405 357 447 315S512 218 512 158C512 99 489 43 447 2C440 -5 431 -8 423 -8C414 -8 405 -5 399 2C385 15 385 37 399 50C428 79 444 117 444 158S428 238 399 267S331 312 290 312S211 296 182 267C160 245 146 219 140 189L213 107H0V346z" />
<glyph glyph-name="unit"
unicode="&#xF1DB;"
unicode="&#xF1DD;"
horiz-adv-x="512" d=" M480 380C480 345 380 316 256 316S32 345 32 380S132 444 256 444S480 415 480 380zM256 284C236 284 96 286 32 329V252C32 217 132 188 256 188S480 217 480 252V329C416 286 276 284 256 284zM256 156C236 156 96 158 32 201V124C32 89 132 60 256 60S480 89 480 124V201C416 158 276 156 256 156zM256 28C236 28 96 30 32 73V-4C32 -39 132 -68 256 -68S480 -39 480 -4V73C416 30 276 28 256 28z" />
<glyph glyph-name="unlocked"
unicode="&#xF1DC;"
unicode="&#xF1DE;"
horiz-adv-x="512" d=" M368 429C289 429 224 364 224 285V235H0V-53H352V235H288V285C288 329 324 365 368 365S448 329 448 285V235H512V285C512 364 447 429 368 429zM201 11H147L161 87C153 91 147 100 147 110C147 125 159 137 174 137S201 125 201 110C201 100 195 91 187 87z" />
<glyph glyph-name="unordered-list"
unicode="&#xF1DD;"
unicode="&#xF1DF;"
horiz-adv-x="512" d=" M160 380H512V316H160zM98 348C98 321 76 300 50 300C23 300 2 321 2 348S23 396 50 396C76 396 98 375 98 348zM160 220H512V156H160zM98 188C98 161 76 140 50 140C23 140 2 161 2 188S23 236 50 236C76 236 98 215 98 188zM160 60H512V-4H160zM98 28C98 1 76 -20 50 -20C23 -20 2 1 2 28S23 76 50 76C76 76 98 55 98 28z" />
<glyph glyph-name="unwatched"
unicode="&#xF1DE;"
unicode="&#xF1E0;"
horiz-adv-x="512" d=" M1 204V185C119 -11 393 -11 511 185V204C393 401 119 401 1 204zM256 77C191 77 138 130 138 195S191 312 256 312S374 260 374 195S321 77 256 77z" />
<glyph glyph-name="upload"
unicode="&#xF1DF;"
unicode="&#xF1E1;"
horiz-adv-x="512" d=" M507 238C496 300 433 330 375 325C356 433 182 434 167 324C124 325 92 297 82 255C37 249 4 216 2 169C-1 119 46 85 91 82C106 81 106 104 91 105C5 109 5 229 91 234H92C97 234 101 236 102 242C103 247 104 252 105 256C114 284 134 301 163 302H177C184 301 187 306 187 312C188 312 188 313 188 314C192 409 348 409 355 314V311C356 310 356 309 357 308C357 307 358 307 358 306C359 306 359 306 359 305C361 303 364 302 368 302H369C492 325 533 152 413 117V116C399 112 405 91 419 95C483 114 519 171 507 238zM273 239C268 246 259 246 254 239C234 211 213 183 193 155C190 150 191 145 194 142C196 140 199 138 203 138H243V-4C243 -18 252 -29 264 -29C275 -29 284 -18 284 -4V138H324C332 138 339 148 334 155C314 183 294 211 273 239z" />
<glyph glyph-name="user-minus"
unicode="&#xF1E0;"
unicode="&#xF1E2;"
horiz-adv-x="512" d=" M295 35V66H465C446 84 403 98 360 115C312 135 301 142 301 142V188S318 202 324 245C335 242 347 262 348 272C348 282 346 310 332 307C335 329 337 348 336 358C333 394 296 433 241 433C185 433 149 394 145 358C144 348 146 329 149 307C135 310 133 282 134 272C134 262 146 242 157 245C163 202 181 188 181 188L180 142S169 135 121 115C74 96 25 82 11 59C-2 39 2 -57 2 -57H295V35zM326 -26V35H511V-26z" />
<glyph glyph-name="user-plus"
unicode="&#xF1E1;"
unicode="&#xF1E3;"
horiz-adv-x="512" d=" M345 -2H281V125H345V128C324 137 318 141 318 141V188S337 202 342 247C354 244 366 264 367 275C367 286 365 315 351 312C354 334 356 353 355 364C351 402 314 442 256 442S161 402 157 364C156 353 158 334 161 312C147 315 145 286 145 275C146 264 158 244 170 247C175 202 194 188 194 188V141S182 133 132 113C83 92 33 78 18 55C5 34 9 -66 9 -66H345V-2zM440 -34H377V157H440zM313 29V93H504V29z" />
<glyph glyph-name="user"
unicode="&#xF1E2;"
unicode="&#xF1E4;"
horiz-adv-x="512" d=" M495 54C480 77 430 92 380 112C331 133 319 140 319 140L318 188S337 202 343 247C354 244 367 265 367 276C368 286 366 315 351 312C354 334 356 354 355 365C352 403 314 443 256 443S160 403 157 365C156 354 158 334 161 312C146 315 144 286 145 276C145 265 158 244 169 247C175 202 194 188 194 188L193 140S181 133 132 112C82 92 32 77 17 54C3 33 7 -67 7 -67H505S509 33 495 54z" />
<glyph glyph-name="view-fullscreen"
unicode="&#xF1E3;"
unicode="&#xF1E5;"
horiz-adv-x="512" d=" M0 348H512V-4H0z" />
<glyph glyph-name="view-list"
unicode="&#xF1E4;"
unicode="&#xF1E6;"
horiz-adv-x="512" d=" M0 348H512V284H0zM0 252H512V188H0zM0 156H512V92H0zM0 60H512V-4H0z" />
<glyph glyph-name="view-split"
unicode="&#xF1E5;"
unicode="&#xF1E7;"
horiz-adv-x="512" d=" M0 348H192V284H0zM0 252H192V188H0zM0 156H192V92H0zM0 60H192V-4H0zM224 348H512V-4H224z" />
<glyph glyph-name="view-timeline"
unicode="&#xF1E6;"
unicode="&#xF1E8;"
horiz-adv-x="512" d=" M44 368H173V317H44zM102 265H466V214H102zM271 162H369V111H271zM53 59H417V8H53zM0 368H33V8H0zM479 368H512V8H479z" />
<glyph glyph-name="warning"
unicode="&#xF1E7;"
unicode="&#xF1E9;"
horiz-adv-x="512" d=" M503 7L429 147C411 181 381 236 363 270L289 407C271 441 241 441 223 407L149 270C131 236 101 180 83 146L9 7C-9 -27 7 -57 46 -57H466C505 -57 521 -27 503 7zM291 13H221V83H291zM291 119H221V259H291z" />
<glyph glyph-name="watched"
unicode="&#xF1E8;"
unicode="&#xF1EA;"
horiz-adv-x="512" d=" M1 205V185C119 -11 393 -11 511 185V205C393 401 119 401 1 205zM256 77C191 77 138 130 138 195S191 312 256 312S374 260 374 195S321 77 256 77zM315 195C315 162 288 136 256 136S197 162 197 195C197 227 224 254 256 254S315 227 315 195z" />
<glyph glyph-name="wiki-edit"
unicode="&#xF1E9;"
unicode="&#xF1EB;"
horiz-adv-x="512" d=" M256 305C256 385 78 401 0 401V49H16C22 49 27 48 32 48V17C96 17 224 36 224 -15H288V305C288 326 322 367 480 369V178H512V401C434 401 256 385 256 305zM224 81V66C177 94 90 96 32 97V369C48 368 62 368 76 367C78 367 81 366 84 366H87C150 362 216 348 223 311C224 308 224 306 224 305zM327 13L322 -18L318 -49L349 -45L381 -40L354 -13zM479 58L470 67L389 -13L381 -4L461 76L443 94L363 14L354 23L434 103L425 112L336 23L389 -31zM471 138C466 143 458 143 453 139V137L452 138L435 120L489 67L506 84C506 85 507 85 507 85C512 90 512 98 507 103z" />
<glyph glyph-name="wiki"
unicode="&#xF1EA;"
unicode="&#xF1EC;"
horiz-adv-x="512" d=" M256 300C256 380 78 396 0 396V44H32V12C96 12 224 31 224 -20H288C288 31 416 12 480 12V44H512V396C434 396 256 380 256 300zM32 364C48 364 62 363 76 362H87C150 357 216 344 223 306C224 304 224 302 224 300V62C177 89 90 92 32 92zM480 92C422 92 335 89 288 62V300C288 321 322 362 480 364z" />
<glyph glyph-name="wiki2"
unicode="&#xF1EB;"
unicode="&#xF1ED;"
horiz-adv-x="512" d=" M239 357C178 392 69 392 69 392V86S178 86 239 51zM273 357C334 392 443 392 443 392V86S334 86 273 51zM477 358V47L273 18H239L35 47V358H1V18L239 -16H273L511 18V358z" />
<glyph glyph-name="work-packages"
unicode="&#xF1EC;"
unicode="&#xF1EE;"
horiz-adv-x="512" d=" M416 124V220H288V252H384V444H160V252H256V220H96V124H0V-68H224V124H128V188H384V124H288V-68H512V124zM192 92V60H32V92zM192 380V412H352V380zM480 60H320V92H480z" />
<glyph glyph-name="workflow"
unicode="&#xF1ED;"
unicode="&#xF1EF;"
horiz-adv-x="512" d=" M437 147L434 141C416 60 342 5 257 5C213 5 171 23 139 51L180 80L28 151L42 -12L77 11C124 -36 188 -64 257 -64C381 -64 486 16 507 135L510 147zM78 226C96 307 170 366 255 366C299 366 341 350 373 322L332 294L484 233L470 392L435 366C388 413 324 440 255 440C131 440 26 352 5 233L2 212H75z" />
<glyph glyph-name="yes"
unicode="&#xF1EE;"
unicode="&#xF1F0;"
horiz-adv-x="512" d=" M176 -46L13 140C-6 156 0 185 19 201C42 217 70 214 90 194L173 102L422 406C438 425 470 428 493 415C515 402 518 374 502 354z" />
<glyph glyph-name="zen-mode"
unicode="&#xF1EF;"
unicode="&#xF1F1;"
horiz-adv-x="512" d=" M160 412V444H0V284H32V390L147 271L173 297L54 412zM480 -14L365 105L339 79L458 -36H352V-68H512V92H480zM480 444H352V412H458L339 297L365 271L480 390V284H512V444zM147 105L32 -14V92H0V-68H160V-36H54L173 79z" />
<glyph glyph-name="zoom-auto"
unicode="&#xF1F0;"
unicode="&#xF1F2;"
horiz-adv-x="512" d=" M469.4 216.8L411.2 216.8L411.2 311.7000000000001L314.7 311.7000000000001L314.7 369.3L469.4 369.3z M104.2 216.8L46 216.8L46 369.3L202.7 369.3L202.7 311.7000000000001L104.2 311.7000000000001z M469.4 -55L314.7 -55L314.7 4.1999999999999L411.2 4.1999999999999L411.2 108.1L469.4 108.1z M202.7 -55L46 -55L46 108.1L104.2 108.1L104.2 4.1999999999999L202.7 4.1999999999999z" />
<glyph glyph-name="zoom-in"
unicode="&#xF1F1;"
unicode="&#xF1F3;"
horiz-adv-x="512" d=" M497 -2L361 122C361 123 361 123 360 123C386 156 401 197 401 242C401 352 311 441 201 441S2 352 2 242S91 43 201 43C241 43 278 55 309 75C310 73 311 71 313 70L448 -54C463 -68 483 -69 493 -58L504 -46C514 -35 511 -15 497 -2zM201 95C120 95 54 161 54 242S120 389 201 389C283 389 348 323 348 242S283 95 201 95zM222 329H181V269H122V227H181V170H222V227H281V269H222z" />
<glyph glyph-name="zoom-out"
unicode="&#xF1F2;"
unicode="&#xF1F4;"
horiz-adv-x="512" d=" M497 -2L361 122C361 123 361 123 360 123C386 156 401 197 401 242C401 352 311 441 201 441S2 352 2 242S91 43 201 43C241 43 278 55 309 75C310 73 311 71 313 70L448 -54C463 -68 483 -69 493 -58L504 -46C514 -35 511 -15 497 -2zM201 95C120 95 54 161 54 242S120 389 201 389C283 389 348 323 348 242S283 95 201 95zM122 269H281V227H122z" />
</font>
</defs>

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 116 KiB

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M448 86L329-32H54v512h394zM100 434V14h210l92 92v328z"/><g aria-label="BCF" style="line-height:1.25" font-weight="700" font-size="121.691" font-family="Arial" letter-spacing="0" word-spacing="0" stroke-width="3.042"><path d="M142.65 305.176h32.152q9.547 0 14.21.965 4.719.9 8.395 3.86 3.731 2.96 6.2 7.916 2.47 4.89 2.47 11.004 0 6.628-3.073 12.162-3.018 5.534-8.23 8.3 7.352 2.51 11.302 8.56 3.95 6.048 3.95 14.22 0 6.435-2.578 12.549-2.524 6.048-6.968 9.716-4.39 3.604-10.864 4.44-4.06.515-19.587.644H142.65zm16.24 15.7v21.815h10.645q9.492 0 11.796-.321 4.17-.58 6.53-3.347 2.413-2.83 2.413-7.4 0-4.375-2.084-7.078-2.03-2.767-6.09-3.346-2.415-.322-13.882-.322zm0 37.517v25.225h15.034q8.779 0 11.138-.58 3.621-.772 5.87-3.732 2.305-3.024 2.305-8.043 0-4.248-1.755-7.208-1.756-2.96-5.103-4.311-3.292-1.351-14.375-1.351zM275.263 364.828l15.747 5.855q-3.621 15.444-12.07 22.973-8.396 7.465-21.344 7.465-16.021 0-26.336-12.806-10.315-12.87-10.315-35.135 0-23.552 10.37-36.55 10.37-13.063 27.269-13.063 14.759 0 23.976 10.231 5.487 6.05 8.23 17.375l-16.076 4.504q-1.426-7.336-5.98-11.583-4.5-4.247-10.973-4.247-8.944 0-14.54 7.53-5.542 7.528-5.542 24.388 0 17.889 5.487 25.482t14.265 7.593q6.475 0 11.138-4.826 4.664-4.826 6.694-15.186zM305.11 399.512v-94.336h55.142v15.958H321.35v22.33h33.578v15.958h-33.578v40.09z" style="-inkscape-font-specification:'Arial Bold'"/></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 512 512"
version="1.1"
id="svg4"
sodipodi:docname="import.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview6"
showgrid="false"
inkscape:zoom="0.921875"
inkscape:cx="146.58296"
inkscape:cy="243.92363"
inkscape:current-layer="svg4" />
<path
d="M 321,224 190,92 l 0,100 -190,0 0,64 190,0 0,100 z"
id="path828"
inkscape:connector-curvature="0" />
<path
d="m 94,-32 318,0 0,512 -318,0 V 320 l 64,0 0,96 190,0 0,-384 -190,0 0,96 H 94 Z"
id="path2"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -77,6 +77,7 @@
<li><span class="icon icon-enumerations"></span>enumerations</li>
<li><span class="icon icon-error"></span>error</li>
<li><span class="icon icon-export-atom"></span>export-atom</li>
<li><span class="icon icon-export-bcf"></span>export-bcf</li>
<li><span class="icon icon-export-csv"></span>export-csv</li>
<li><span class="icon icon-export-pdf-descr"></span>export-pdf-descr</li>
<li><span class="icon icon-export-pdf-with-descriptions"></span>export-pdf-with-descriptions</li>
@ -114,6 +115,7 @@
<li><span class="icon icon-hosting"></span>hosting</li>
<li><span class="icon icon-image1"></span>image1</li>
<li><span class="icon icon-image2"></span>image2</li>
<li><span class="icon icon-import"></span>import</li>
<li><span class="icon icon-info1"></span>info1</li>
<li><span class="icon icon-info2"></span>info2</li>
<li><span class="icon icon-installation-services"></span>installation-services</li>

@ -400,3 +400,21 @@ a.main-menu--parent-node
.tree-menu--title
@include varprop(color, main-menu-hover-font-color)
text-decoration: none
// Badges for menu items such as "EXPERIMENTAL" or "BETA"
$badge_offset: 4px
.menu-item--title.-has-badge
// As this is flex box with a vertical center we need this trick to undo centering the whole content including a badge.
// The goal is to leave the caption where it was before adding a badge.
margin-top: -1 * $badge_offset
.main-item--badge
font-size: 10px
vertical-align: $badge_offset
text-transform: uppercase
margin-left: 4px
font-weight: bold
font-style: italic

@ -87,29 +87,15 @@ class WorkPackagesController < ApplicationController
def export_list(mime_type)
exporter = WorkPackage::Exporter.for_list(mime_type)
export = exporter.list(@query, params)
if export.error?
flash[:error] = export.message
redirect_back(fallback_location: index_redirect_path)
else
send_data(export.content,
type: export.mime_type,
filename: export.title)
exporter.list(@query, params) do |export|
render_export_response export, fallback_path: index_redirect_path
end
end
def export_single(mime_type)
exporter = WorkPackage::Exporter.for_single(mime_type)
export = exporter.single(work_package, params)
if export.error?
flash[:error] = export.message
redirect_back(fallback_location: work_package_path(work_packages))
else
send_data(export.content,
type: export.mime_type,
filename: export.title)
exporter.single(work_package, params) do |export|
render_export_response export, fallback_path: work_package_path(work_packages)
end
end
@ -126,13 +112,36 @@ class WorkPackagesController < ApplicationController
title: "#{@project || Setting.app_title}: #{l(:label_work_package_plural)}")
end
private
def render_export_response(export, fallback_path:)
if export.error?
flash[:error] = export.message
redirect_back(fallback_location: fallback_path)
elsif export.content.is_a? File
# browsers should not try to guess the content-type
response.headers['X-Content-Type-Options'] = 'nosniff'
# TODO avoid reading the file in memory here again
# but currently the tempfile gets removed in between
send_data(export.content.read,
type: export.mime_type,
disposition: 'attachment',
filename: export.title)
else
send_data(export.content,
type: export.mime_type,
filename: export.title)
end
end
def authorize_on_work_package
deny_access unless work_package
end
def protect_from_unauthorized_export
if supported_export_formats.include?(params[:format]) &&
!User.current.allowed_to?(:export_work_packages, @project, global: @project.nil?)
!User.current.allowed_to?(:export_work_packages, @project, global: @project.nil?)
deny_access
false
@ -187,7 +196,7 @@ class WorkPackagesController < ApplicationController
.changing
.includes(:user)
.order(order).to_a
end
end
end
def index_redirect_path
@ -198,8 +207,6 @@ class WorkPackagesController < ApplicationController
end
end
private
def load_work_packages
@results = @query.results
@work_packages = if @query.valid?

@ -128,19 +128,33 @@ class Attachment < ActiveRecord::Base
container.present?
end
##
# Retrieve a local file,
# this may result in downloading the file first
def diskfile
file.local_file
end
##
# Retrieve the local file path,
# this may result in downloading the file first to a tmpdir
def local_path
diskfile.path
end
def filename
attributes['file']
end
def file=(file)
super.tap do
set_content_type file
set_file_size file
set_digest file
set_content_type file
if File.readable? file.path
set_digest file
end
end
end

@ -37,14 +37,17 @@ class WorkPackage::Exporter::Base
self.options = options
end
def self.list(query, options = {})
new(query, options).list
def self.list(query, options = {}, &block)
new(query, options).list(&block)
end
def self.single(work_package, options = {})
new(work_package, options).single
def self.single(work_package, options = {}, &block)
new(work_package, options).single(&block)
end
# Provide means to clean up after the export
def cleanup; end
def page
options[:page] || 1
end
@ -58,6 +61,15 @@ class WorkPackage::Exporter::Base
alias :query :object
alias :work_package :object
# Remove characters that could cause problems on popular OSses
def sane_filename(name)
parts = name.split /(?<=.)\.(?=[^.])(?!.*\.[^.])/m
parts.map! { |s| s.gsub /[^a-z0-9\-]+/i, '_' }
parts.join '.'
end
def work_packages
@work_packages ||= query
.results

@ -45,7 +45,7 @@ class WorkPackage::Exporter::CSV < WorkPackage::Exporter::Base
end
end
success(serialized)
yield success(serialized)
end
def self.encode_csv_columns(columns, encoding = l(:general_csv_encoding))

@ -31,7 +31,7 @@
class WorkPackage::Exporter::PDF < WorkPackage::Exporter::Base
# Returns a PDF string of a list of work_packages
def list
::WorkPackage::PdfExport::WorkPackageListToPdf
yield ::WorkPackage::PdfExport::WorkPackageListToPdf
.new(query,
options)
.render!
@ -39,7 +39,7 @@ class WorkPackage::Exporter::PDF < WorkPackage::Exporter::Base
# Returns a PDF string of a single work_package
def single
::WorkPackage::PdfExport::WorkPackageToPdf
yield ::WorkPackage::PdfExport::WorkPackageToPdf
.new(work_package)
.render!
end

@ -34,7 +34,7 @@ class WorkPackage::Exporter::Success < WorkPackage::Exporter::Result
:content,
:mime_type
def initialize(format:, title:, content:, mime_type:)
def initialize(format:, title:, content: nil, mime_type:)
self.format = format
self.title = title
self.content = content

@ -45,12 +45,12 @@ class AddWorkPackageNoteService
JournalManager.with_send_notifications send_notifications do
work_package.add_journal(user, notes)
result, errors = validate_and_yield(work_package, user) do
success, errors = validate_and_yield(work_package, user) do
work_package.save_journals
end
ServiceResult.new(success: result,
errors: errors)
journal = work_package.journals.last if success
ServiceResult.new(success: success, result: journal, errors: errors)
end
end
end

@ -61,5 +61,7 @@ class CreateWorkPackageService
def assign_defaults(work_package)
work_package.author ||= user
work_package.priority ||= IssuePriority.active.default
work_package.status ||= Status.default
end
end

@ -31,6 +31,20 @@ module FileUploader
base.extend ClassMethods
end
##
# Returns an URL if the attachment is stored in an external (fog) attachment storage
# or nil otherwise.
def external_url
url = URI.parse download_url
url if url.host
rescue URI::InvalidURIError
nil
end
def external_storage?
!external_url.nil?
end
def local_file
file.to_file
end
@ -48,7 +62,7 @@ module FileUploader
end
# store! nil's the cache_id after it finishes so we need to remember it for deletion
def remember_cache_id(_new_file)
def remember_cache_id(_new_file)
@cache_id_was = cache_id
end

@ -1304,6 +1304,7 @@ en:
label_equals: "is"
label_everywhere: "everywhere"
label_example: "Example"
label_import: "Import"
label_export_to: "Also available in:"
label_expanded_click_to_collapse: "Expanded. Click to collapse"
label_f_hour: "%{value} hour"

@ -184,14 +184,21 @@ module Redmine::MenuManager::MenuHelper
end
def render_single_menu_node(item, caption, url, selected)
link_text = ''.html_safe
link_text << op_icon(item.icon) if item.icon.present?
link_text << you_are_here_info(selected)
link_text << content_tag(:span, caption, class: 'menu-item--title ellipsis', lang: menu_item_locale(item))
link_text << content_tag(:span,
class: "menu-item--title ellipsis #{item.badge.present? ? '-has-badge' : ''}",
lang: menu_item_locale(item)) do
''.html_safe + caption + badge_for(item)
end
link_text << ' '.html_safe + op_icon(item.icon_after) if item.icon_after.present?
html_options = item.html_options(selected: selected)
html_options[:title] ||= selected ? t(:description_current_position) + caption : caption
link_to link_text, url, html_options
link_to url, html_options do
link_text
end
end
def render_unattached_menu_item(menu_item, project)
@ -265,10 +272,10 @@ module Redmine::MenuManager::MenuHelper
end
if project
return user && user.allowed_to?(node.url, project)
user && user.allowed_to?(node.url, project)
else
# outside a project, all menu items allowed
return true
true
end
end
@ -309,4 +316,12 @@ module Redmine::MenuManager::MenuHelper
def wiki_prefix?
current_menu_item.to_s.match? /^wiki-/
end
def badge_for(item)
badge = ''.html_safe
if item.badge.present?
badge += ' '.html_safe + content_tag('span', I18n.t(item.badge), class: 'main-item--badge')
end
badge
end
end

@ -29,7 +29,7 @@
class Redmine::MenuManager::MenuItem < Redmine::MenuManager::TreeNode
include Redmine::I18n
attr_reader :name, :url, :param, :icon, :icon_after, :context, :condition, :parent, :child_menus, :last, :partial
attr_reader :name, :url, :param, :icon, :icon_after, :context, :condition, :parent, :child_menus, :last, :partial, :badge
def initialize(name, url, options)
raise ArgumentError, "Invalid option :if for menu item '#{name}'" if options[:if] && !options[:if].respond_to?(:call)
@ -53,6 +53,7 @@ class Redmine::MenuManager::MenuItem < Redmine::MenuManager::TreeNode
@child_menus = options[:children]
@last = options[:last] || false
@partial = options[:partial]
@badge = options[:badge]
super @name.to_sym
end

@ -0,0 +1,2 @@
source 'https://rubygems.org'
gemspec

@ -0,0 +1,20 @@
.bcf--issues
display: flex
flex-direction: row
flex-wrap: wrap
> div
flex: 0 0 250px
margin: 10px
padding: 10px
img
width: 100%
.bcf--import-listing
margin-bottom: 50px
table.attributes-table
td,th
padding: 5px
text-align: center

@ -0,0 +1,4 @@
module ::Bcf
class BaseController < ApplicationController
end
end

@ -0,0 +1,88 @@
module ::Bcf
class LinkedIssuesController < BaseController
include PaginationHelper
before_action :find_project_by_project_id
before_action :authorize
before_action :check_file_param, only: %i[prepare_import]
before_action :get_persisted_file, only: %i[perform_import]
before_action :persist_file, only: %i[prepare_import]
before_action :build_importer, only: %i[prepare_import perform_import]
before_action :get_issue_type
menu_item :bcf
def index
@issues = ::Bcf::Issue.in_project(@project)
.with_markup
.includes(:comments, :work_package, viewpoints: :attachments)
.page(page_param)
.per_page(per_page_param)
end
def import; end
def prepare_import
@bcf_file = params[:bcf_file]
begin
@listing = @importer.get_extractor_list! @bcf_file.path
@issues = ::Bcf::Issue
.with_markup
.includes(work_package: %i[status priority assigned_to])
.where(uuid: @listing.map { |e| e[:uuid] })
rescue StandardError => e
flash[:error] = I18n.t('bcf.bcf_xml.import_failed', error: e.message)
redirect_to action: :index
end
end
def perform_import
begin
result = @importer.import! @bcf_attachment.local_path
flash[:notice] = I18n.t('bcf.bcf_xml.import_successful', count: result)
rescue StandardError => e
flash[:error] = I18n.t('bcf.bcf_xml.import_failed', error: e.message)
end
@bcf_attachment.destroy
redirect_to action: :index
end
private
def build_importer
@importer = ::OpenProject::Bcf::BcfXml::Importer.new @project, current_user: current_user
end
def get_issue_type
@issue_type = @project.types.find_by(name: 'Issue [BCF]')
end
def get_persisted_file
@bcf_attachment = Attachment.find_by! id: session[:bcf_file_id], author: current_user
rescue ActiveRecord::RecordNotFound
render_404 'BCF file not found'
end
def persist_file
file = params[:bcf_file]
@bcf_attachment = Attachment.create! file: file, description: file.original_filename, author: current_user
session[:bcf_file_id] = @bcf_attachment.id
rescue StandardError => e
flash[:error] = "Failed to persist BCF file: #{e.message}"
redirect_to action: :index
end
def check_file_param
path = params[:bcf_file]&.path
unless path && File.readable?(path)
flash[:error] = I18n.t('bcf.bcf_xml.import_failed', error: 'File missing or not readable')
redirect_to action: :import
end
end
end
end

@ -0,0 +1,5 @@
module Bcf
def self.table_name_prefix
'bcf_'
end
end

@ -0,0 +1,14 @@
module Bcf
class Comment < ActiveRecord::Base
include InitializeWithUuid
belongs_to :journal
belongs_to :issue, foreign_key: :issue_id, class_name: "Bcf::Issue"
validates_presence_of :uuid
def self.has_uuid?(uuid)
where(uuid: uuid).exists?
end
end
end

@ -0,0 +1,17 @@
module Bcf
##
# Module to set an initial UUID on the model
# whenever it is created
module InitializeWithUuid
extend ActiveSupport::Concern
included do
after_initialize :set_initial_uuid, if: :new_record?
end
def set_initial_uuid
self.uuid ||= SecureRandom.uuid
end
end
end

@ -0,0 +1,33 @@
module Bcf
class Issue < ActiveRecord::Base
include InitializeWithUuid
belongs_to :work_package
belongs_to :project
class << self
def in_project(project)
where(project_id: project.try(:id) || project)
end
def with_markup
select '*',
extract_xml('/Markup/Topic/Title/text()', 'title'),
extract_xml('/Markup/Topic/Description/text()', 'description'),
extract_xml('/Markup/Topic/Priority/text()', 'priority_text'),
extract_xml('/Markup/Topic/@TopicStatus', 'status_text'),
extract_xml('/Markup/Topic/AssignedTo/text()', 'assignee_text'),
extract_xml('/Markup/Topic/DueDate/text()', 'due_date_text')
end
private
def extract_xml(path, as)
"(xpath('#{path}', markup))[1] AS #{as}"
end
end
has_many :viewpoints, foreign_key: :issue_id, class_name: "Bcf::Viewpoint"
has_many :comments, foreign_key: :issue_id, class_name: "Bcf::Comment"
end
end

@ -0,0 +1,26 @@
module Bcf
class Viewpoint < ActiveRecord::Base
include InitializeWithUuid
acts_as_attachable view_permission: :view_linked_issues,
delete_permission: :manage_bcf,
add_on_new_permission: :manage_bcf,
add_on_persisted_permission: :manage_bcf
def self.has_uuid?(uuid)
where(uuid: uuid).exists?
end
belongs_to :issue, foreign_key: :issue_id, class_name: "Bcf::Issue"
delegate :project, :project_id, to: :issue, allow_nil: true
def snapshot
attachments.find_by_description('snapshot')
end
def snapshot=(file)
snapshot&.destroy
attach_files('first' => { 'file' => file, 'description' => 'snapshot' })
end
end
end

@ -0,0 +1,30 @@
<%= toolbar title: t('bcf.bcf_xml.import_title') %>
<% unless @issue_type %>
<div class="notification-box -error">
<div class="notification-box--content">
<p>
<%= t('bcf.bcf_xml.type_not_active') %>
<%= link_to t(:label_project_settings), settings_project_path(@project, tab: :types) %>
</p>
</div>
</div>
<% end %>
<%= form_tag({ action: :prepare_import }, multipart: true, method: :post) do %>
<div class="form--field">
<%= styled_label_tag 'bcf_file', t('bcf.bcf_xml.xml_file') %>
<div class="form--field-container">
<%= styled_file_field_tag :bcf_file, required: true %>
</div>
<div class="form--field-instructions">
<p><%= t('bcf.bcf_xml.import.description') %></p>
</div>
</div>
<%= submit_tag t('bcf.bcf_xml.import.button_prepare'), class: 'button -highlight' %>
<%= link_to t(:button_cancel),
{ action: :index },
class: 'button' %>
<% end %>

@ -0,0 +1,56 @@
<%= stylesheet_link_tag 'bcf/bcf.css' %>
<link rel="stylesheet" href="/highlighting/styles.css" />
<%= toolbar title: t('bcf.linked_issues'), html: {class: '-with-dropdown'} do %>
<li class="toolbar-item drop-down">
</li>
<li class="toolbar-item">
<%= link_to({ action: 'import' },
title: I18n.t(:label_import),
class: 'button import-bcf-button') do %>
<%= op_icon('button--icon icon-import') %>
<span class="button--text"><%= l(:label_import) %></span>
<% end %>
</li>
<% if @issue_type && @issues.present? %>
<li class="toolbar-item">
<% query = { f: [filter_object('type', '=', @issue_type.id)] } %>
<%= link_to(project_work_packages_with_query_path(@project, query, format: :bcf),
title: t('bcf.bcf_xml.export'),
class: 'button export-bcf-button') do %>
<%= op_icon('button--icon icon-export') %>
<span class="button--text"><%= t('bcf.bcf_xml.export') %></span>
<% end %>
</li>
<% end %>
<% end %>
<% if @issues.present? %>
<div class="bcf--issues">
<% @issues.each do |issue| %>
<% status_id = issue.work_package&.status_id %>
<% hl_classname = status_id.present? ? "__hl_row_status_#{status_id}" : '' %>
<div class="<%= hl_classname %>">
<p>
<strong><%= issue.title %></strong>
<br/>
<% if issue.work_package %>
<%= link_to_work_package(issue.work_package) %>
<br/>
<% end %>
</p>
<% if issue.viewpoints.empty? %>
<p>(No viewpoints)</p>
<% end %>
<% issue.viewpoints.each do |vp| %>
<img src="<%= attachment_path(vp.snapshot.id) %>" />
<% end %>
</div>
<% end %>
</div>
<% else %>
<%= no_results_box %>
<% end %>
<%= pagination_links_full @issues %>

@ -0,0 +1,60 @@
<%= stylesheet_link_tag 'bcf/bcf.css' %>
<%= toolbar title: t('bcf.bcf_xml.import_title') %>
<p><%= t('bcf.bcf_xml.import.num_issues_found', x_bcf_issues: t('bcf.x_bcf_issues', count: @listing.count)) %></p>
<% @listing.each do |entry| %>
<% issue = @issues.detect { |bcf| bcf.uuid == entry[:uuid] } %>
<div class="bcf--import-listing">
<h3><%= entry[:title] %></h3>
<table class="attributes-table">
<thead>
<tr>
<th>Work package</th>
<th>Title</th>
<th>Status</th>
<th>Priority</th>
<th>Assignee</th>
<th>Due date</th>
<th># Viewpoints</th>
<th># Comments</th>
</tr>
</thead>
<tbody>
<tr>
<% if issue && issue.work_package %>
<td><%= link_to_work_package issue.work_package %></td>
<% else %>
<td>(will be created)</td>
<% end %>
<td><%= entry[:title] || '-' %></td>
<td><%= entry[:status] || '-' %></td>
<td><%= entry[:priority] || '-' %></td>
<td><%= entry[:assignee] || '-' %></td>
<td><%= format_date(entry[:due_date]) || '-' %></td>
<td><%= entry[:viewpoint_count] %></td>
<td><%= entry[:comments_count] %></td>
</tr>
<% if issue&.work_package %>
<td></td>
<td><%= issue.work_package.subject %></td>
<td><%= issue.work_package.status.name %></td>
<td><%= issue.work_package.priority.name %></td>
<td><%= issue.work_package.assigned_to&.name %></td>
<td><%= format_date(issue.work_package.due_date) %></td>
<td><%= issue.viewpoints.count %></td>
<td><%= issue.comments.count %></td>
<% end %>
</tbody>
</table>
</div>
<% end %>
<%= form_tag({ action: :perform_import }, multipart: true, method: :post) do %>
<p><%= t('bcf.bcf_xml.import.perform_description') %></p>
<%= submit_tag t('bcf.bcf_xml.import.button_perform_import'), class: 'button -highlight' %>
<%= link_to t(:button_cancel),
{ action: :index },
class: 'button' %>
<% end %>

@ -0,0 +1,30 @@
# English strings go here for Rails i18n
en:
bcf:
label_bcf: 'BCF'
linked_issues: "Linked issues"
experimental_badge: "Experimental"
x_bcf_issues:
zero: 'No BCF issues'
one: 'One BCF issue'
other: '%{count} BCF issues'
bcf_xml:
xml_file: 'BCF XML File'
import_title: 'Import from BCF file'
export: 'Export all to BCF-XML'
import_update_comment: '(Updated in BCF import)'
import_failed: 'Cannot import BCF file: %{error}'
import_successful: 'Imported %{count} BCF issues'
type_not_active: "The issue type is not activated for this project."
import:
num_issues_found: '%{x_bcf_issues} are contained in the BCF-XML file, their details are listed below.'
button_prepare: 'Prepare import'
button_perform_import: 'Confirm import'
description: "Provide a BCF-XML v2.1 file to import into this project. You can examine its contents before performing the import."
perform_description: "Do you want to import or update the issues listed above?"
export:
format:
bcf: "BCF-XML"

@ -0,0 +1,46 @@
#-- copyright
# OpenProject Backlogs Plugin
#
# Copyright (C)2013-2014 the OpenProject Foundation (OPF)
# Copyright (C)2011 Stephan Eckardt, Tim Felgentreff, Marnen Laibow-Koser, Sandro Munda
# Copyright (C)2010-2011 friflaj
# Copyright (C)2010 Maxime Guilbot, Andrew Vit, Joakim Kolsjö, ibussieres, Daniel Passos, Jason Vasquez, jpic, Emiliano Heyns
# Copyright (C)2009-2010 Mark Maglana
# Copyright (C)2009 Joe Heck, Nate Lowrie
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License version 3.
#
# OpenProject Backlogs is a derivative work based on ChiliProject Backlogs.
# The copyright follows:
# Copyright (C) 2010-2011 - Emiliano Heyns, Mark Maglana, friflaj
# Copyright (C) 2011 - Jens Ulferts, Gregor Schmidt - Finn GmbH - Berlin, Germany
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
OpenProject::Application.routes.draw do
scope '', as: 'bcf' do
scope 'projects/:project_id', as: 'project' do
resources :linked_issues, controller: 'bcf/linked_issues' do
get :import, action: :import, on: :collection
post :prepare_import, action: :prepare_import, on: :collection
post :import, action: :perform_import, on: :collection
end
end
end
end

@ -0,0 +1,36 @@
class AddBcfPlugin < ActiveRecord::Migration[5.1]
def change
create_table :bcf_issues do |t|
t.text :uuid, index: true
t.column :markup, :xml
t.references :project, foreign_key: { on_delete: :cascade }, index: true
t.references :work_package, foreign_key: { on_delete: :cascade }, index: { unique: true }
end
create_table :bcf_viewpoints do |t|
t.text :uuid, index: true
t.column :viewpoint, :xml
t.text :viewpoint_name
t.references :issue,
foreign_key: { to_table: :bcf_issues, on_delete: :cascade }
# Create unique index on issue and uuid to avoid duplicates on resynchronization
t.index %i[uuid issue_id], unique: true
end
create_table :bcf_comments do |t|
t.text :uuid, index: true
t.references :journal, index: true
t.references :issue,
foreign_key: { to_table: :bcf_issues, on_delete: :cascade },
index: true
# Create unique index on issue and uuid to avoid duplicates on resynchronization
t.index %i[uuid issue_id], unique: true
end
end
end

@ -0,0 +1,6 @@
module OpenProject
module Bcf
require "open_project/bcf/engine"
require "open_project/bcf/bcf_xml"
end
end

@ -0,0 +1,5 @@
module OpenProject::Bcf
module Bcf
require_relative './bcf_xml/importer'
end
end

@ -0,0 +1,145 @@
require 'fileutils'
module OpenProject::Bcf::BcfXml
class Exporter < ::WorkPackage::Exporter::Base
include Redmine::I18n
def current_user
User.current
end
def work_packages
super.includes(:journals, bcf_issue: [:comments, { viewpoints: :attachments }])
end
def list
Dir.mktmpdir do |dir|
files = create_bcf! dir
zip = zip_folder dir, files
yield success(zip)
end
rescue StandardError => e
Rails.logger.error "Failed to export work package list #{e} #{e.message}"
raise e
end
def success(zip)
WorkPackage::Exporter::Success
.new format: :xls,
content: zip,
title: bcf_filename,
mime_type: 'application/octet-stream'
end
def bcf_filename
# We often have an internal query name that is not meant
# for public use or was given by a user.
if query.name.present? && query.name != '_'
return sane_filename("#{query.name}.bcfzip")
end
sane_filename(
"#{Setting.app_title} #{I18n.t(:label_work_package_plural)} \
#{format_time_as_date(Time.now, '%Y-%m-%d')}.bcfzip"
)
end
def zip_folder(dir, files)
zip_file = File.join(dir, bcf_filename)
Zip::File.open(zip_file, Zip::File::CREATE) do |zip|
files.each do |file|
name = file.sub("#{dir}/", "")
zip.add name, file
end
end
File.open(zip_file, 'r')
end
def create_bcf!(bcf_folder)
manifest_file = write_manifest(bcf_folder)
files = [manifest_file]
work_packages.find_each do |wp|
# Update or create the BCF issue from the given work package
issue = IssueWriter.update_from!(wp)
# Create a folder for the issue
issue_folder = topic_folder_for(bcf_folder, issue)
# Append the markup itself
files << topic_markup_file(issue_folder, issue)
# Append any viewpoints
files.concat viewpoints_for(issue_folder, issue)
# TODO additional files such as BIM snippets
end
files
end
##
# Write the manifest file <dir>/bcf.version
def write_manifest(dir)
File.join(dir, "bcf.version").tap do |manifest_file|
dump_file manifest_file, manifest_xml
end
end
##
# Create and return the issue folder
# /dir/<uuid>/
def topic_folder_for(dir, issue)
File.join(dir, issue.uuid).tap do |issue_dir|
Dir.mkdir issue_dir
end
end
##
# Write each work package BCF
def topic_markup_file(issue_dir, issue)
File.join(issue_dir, 'markup.bcf').tap do |file|
dump_file file, issue.markup
end
end
##
# Write viewpoints
def viewpoints_for(issue_dir, issue)
[].tap do |files|
issue.viewpoints.find_each do |vp|
vp_file = File.join(issue_dir, vp.viewpoint_name)
snapshot_file = File.join(issue_dir, vp.snapshot.filename)
# Copy the files
dump_file vp_file, vp.viewpoint
FileUtils.cp vp.snapshot.local_path, snapshot_file
files << vp_file << snapshot_file
end
end
end
def manifest_xml
Nokogiri::XML::Builder.new do |xml|
xml.comment created_by_comment
xml.Version "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema", "VersionId" => "2.1" do
xml.DetailedVersion "2.1"
end
end.to_xml
end
def dump_file(path, content)
File.open(path, "w") do |f|
f.write content
end
end
def created_by_comment
" Created by #{Setting.app_title} #{OpenProject::VERSION} at #{Time.now} "
end
end
end

@ -0,0 +1,14 @@
##
# Helper class to provide uploads from IO streams.
module OpenProject::Bcf::BcfXml
class FileEntry < StringIO
def initialize(stream, filename:)
super(stream.read)
@original_filename = filename
end
attr_reader :original_filename
alias :path :original_filename
end
end

@ -0,0 +1,67 @@
require 'activerecord-import'
require_relative 'issue_reader'
module OpenProject::Bcf::BcfXml
class Importer
attr_reader :project, :zip, :current_user
def initialize(project, current_user:)
@project = project
@current_user = current_user
end
##
# Get a list of issues contained in a BCF
# but do not perform the import
def get_extractor_list!(file)
Zip::File.open(file) do |zip|
yield_topic_entries(zip)
.map do |entry|
to_listing(MarkupExtractor.new(entry))
end
end
end
def import!(file)
Zip::File.open(file) do |zip|
# Extract all topics of the zip and save them
synchronize_topics(zip)
# TODO: Extract documents
# TODO: Extract BIM snippets
end
rescue => e
Rails.logger.error "Failed to import BCF Zip #{file}: #{e} #{e.message}"
Rails.logger.debug { e.backtrace.join("\n") }
raise e
end
private
def to_listing(extractor)
keys = %i[uuid title priority status description author assignee modified_author due_date]
Hash[keys.map { |k| [k, extractor.public_send(k)] }].tap do |attributes|
attributes[:viewpoint_count] = extractor.viewpoints.count
attributes[:comments_count] = extractor.comments.count
end
end
def synchronize_topics(zip)
yield_topic_entries(zip)
.map do |entry|
issue = IssueReader.new(project, zip, entry, current_user: current_user).extract!
issue.save
end
.count
end
##
# Yields topic entries and their uuid from the ZIP files
# while skipping all other entries
def yield_topic_entries(zip)
zip.select { |entry| entry.name.end_with?('markup.bcf') }
end
end
end

@ -0,0 +1,201 @@
##
# Extracts sections of a BCF markup file
# manually. If we want to extract the entire markup,
# this should be turned into a representable/xml decorator
require_relative 'file_entry'
module OpenProject::Bcf::BcfXml
class IssueReader
attr_reader :zip, :entry, :issue, :extractor, :project, :user, :type
def initialize(project, zip, entry, current_user:)
@zip = zip
@entry = entry
@project = project
@user = current_user
@issue = find_or_initialize_issue
@extractor = MarkupExtractor.new(entry)
# TODO fixed type
@type = ::Type.find_by(name: 'Issue [BCF]')
end
def extract!
issue.markup = extractor.markup
# Viewpoints will be extended on import
build_viewpoints
# Synchronize with a work package
synchronize_with_work_package
# Comments will be extended on import
build_comments
issue
end
private
def synchronize_with_work_package
call =
if issue.work_package
update_work_package
else
create_work_package
end
if call.success?
wp = call.result
issue.work_package = wp
create_comment(user, I18n.t('bcf.bcf_xml.import_update_comment')) unless wp.previous_changes.empty?
else
Rails.logger.error "Failed to synchronize BCF #{issue.uuid} with work package: #{call.errors.full_messages.join("; ")}"
end
end
def create_work_package
wp = WorkPackage.new work_package_attributes
CreateWorkPackageService
.new(user: user)
.call(wp, send_notifications: false)
end
def update_work_package
WorkPackages::UpdateService
.new(user: user, work_package: issue.work_package)
.call(attributes: work_package_attributes, send_notifications: false)
end
##
# Get mapped and raw attributes from MarkupExtractor
# and return all values that are non-nil
def work_package_attributes
{
# Fixed attributes we know
project: project,
type: type,
# Native attributes from the extractor
subject: extractor.title,
description: extractor.description,
due_date: extractor.due_date,
# Mapped attributes
author: find_user_in_project(extractor.author),
assigned_to: find_user_in_project(extractor.assignee),
status_id: statuses.fetch(extractor.status, statuses[:default]),
priority_id: priorities.fetch(extractor.priority, priorities[:default]),
}.compact
end
##
# Extend comments with new or updated values from XML
def build_comments
extractor.comments.each do |data|
next if issue.comments.has_uuid?(data[:uuid])
comment = issue.comments.build data.slice(:uuid)
# Cannot link to a journal when no work package
next if issue.work_package.nil?
author = get_comment_author(data)
call = create_comment(author, data[:comment])
if call.success?
comment.journal = call.result
else
Rails.logger.error "Failed to create comment for BCF #{issue.uuid}: #{call.errors.full_messages.join("; ")}"
end
end
end
##
# Try to find an author with the given mail address
def get_comment_author(comment)
author = find_user_in_project(comment[:author])
# If none found, use the current user
return user if author.nil?
# If found, check if the author can comment
return user unless author.allowed_to?(:add_work_package_notes, project)
author
end
##
# Try to find the given user by mail in the project
def find_user_in_project(mail)
project.users.find_by(mail: mail)
end
def create_comment(author, content)
::AddWorkPackageNoteService
.new(user: author, work_package: issue.work_package)
.call(content)
end
##
# Extract viewpoints from XML
def build_viewpoints
extractor.viewpoints.each do |vp|
next if issue.viewpoints.has_uuid?(vp[:uuid])
issue.viewpoints.build(
issue: issue,
uuid: vp[:uuid],
# Save the viewpoint as XML
viewpoint: read_entry(vp[:viewpoint]),
viewpoint_name: vp[:viewpoint],
# Save the snapshot as file attachment
snapshot: as_file_entry(vp[:snapshot])
)
end
end
##
# Find existing issue or create new
def find_or_initialize_issue
::Bcf::Issue.find_or_initialize_by(uuid: topic_uuid, project_id: project.id)
end
##
# Get the topic name of an entry
def topic_uuid
entry.name.split('/').first
end
##
# Get an entry within the uuid
def as_file_entry(filename)
entry = zip.find_entry [topic_uuid, filename].join('/')
if entry
FileEntry.new(entry.get_input_stream, filename: filename)
end
end
##
# Read an entry as string
def read_entry(filename)
entry = zip.find_entry [topic_uuid, filename].join('/')
entry.get_input_stream.read
end
##
# Keep a hash map of current status ids for faster lookup
def statuses
@statuses ||= Hash[Status.pluck(:name, :id)].merge(default: Status.default.id)
end
##
# Keep a hash map of current status ids for faster lookup
def priorities
@priorities ||= Hash[IssuePriority.pluck(:name, :id)].merge(default: IssuePriority.default.try(:id))
end
end
end

@ -0,0 +1,180 @@
##
# Creates or updates a BCF issue and markup from a work package
module OpenProject::Bcf::BcfXml
class IssueWriter
attr_reader :work_package, :issue, :markup_doc, :markup_node
def self.update_from!(work_package)
writer = new(work_package)
writer.update
writer.issue
end
def initialize(work_package)
@work_package = work_package
@issue = find_or_initialize_issue
# Read the existing markup XML or build an empty one
@markup_doc = build_markup_document
# Remember root markup node for easier access
@markup_node = @markup_doc.at_xpath('/Markup')
end
def update
# Replace topic node
replace_topic
# Override all current comments
replace_comments
# Override all current Viewpoints
replace_viewpoints
# Replace the markup XML
issue.markup = markup_doc.to_xml
# Save issue and potential new associations
issue.save!
end
private
##
# Get the nokogiri document from the markup xml
def build_markup_document
if issue.markup
Nokogiri::XML issue.markup
else
build_initial_markup_xml.doc
end
end
##
# Initial markup file as basic BCF compliant xml
def build_initial_markup_xml
Nokogiri::XML::Builder.new do |xml|
xml.comment created_by_comment
xml.Markup "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema"
end
end
##
# Replace the topic node, if any
def replace_topic
markup_node.xpath('./Topic').remove
Nokogiri::XML::Builder.with(markup_node) do |xml|
topic xml
end
end
##
# Render the topic of the work package
def topic(xml)
xml.Topic "Guid" => issue.uuid,
"TopicType" => work_package.type.name,
"TopicStatus" => work_package.status.name do
xml.Title work_package.subject
xml.CreationDate to_bcf_datetime(work_package.created_at)
xml.ModifiedDate to_bcf_datetime(work_package.updated_at)
xml.Description work_package.description
xml.CreationAuthor work_package.author.mail
xml.ReferenceLink url_helpers.work_package_url(work_package)
if priority = work_package.priority
xml.Priority priority.name
end
if work_package.due_date
xml.DueDate to_bcf_date(work_package.due_date)
end
if journal = work_package.journals.select(:user_id).last
xml.ModifiedAuthor journal.user.mail if journal.user_id
end
if assignee = work_package.assigned_to
xml.AssignedTo assignee.mail
end
end
end
def replace_comments
markup_node.xpath('./Comment').remove
Nokogiri::XML::Builder.with(markup_node) do |xml|
comments xml
end
end
def replace_viewpoints
markup_node.xpath('./Viewpoints').remove
Nokogiri::XML::Builder.with(markup_node) do |xml|
viewpoints xml
end
end
##
# Render the comments of the work package as XML nodes
def comments(xml)
comments = issue.comments.group_by(&:journal_id)
work_package.journals.select(:id, :notes, :user_id, :created_at).map do |journal|
next if journal.notes.empty?
# Create BCF comment reference for the journal
comment = comments[journal.id]&.first || issue.comments.build(issue_id: issue, journal_id: journal.id)
comment_node xml, comment.uuid, journal, work_package
end
end
##
# Create a single topic node
def comment_node(xml, uuid, journal, work_package)
xml.Comment "Guid" => uuid do
xml.Date to_bcf_datetime(journal.created_at)
xml.Author journal.user.mail if journal.user_id
xml.Comment journal.notes
end
end
##
# Write the current set of viewpoints
def viewpoints(xml)
issue.viewpoints.find_each do |vp|
xml.Viewpoints "Guid" => vp.uuid do
xml.Viewpoint vp.viewpoint_name
xml.Snapshot vp.snapshot.filename
end
end
end
##
#
def created_by_comment
" Created by #{Setting.app_title} #{OpenProject::VERSION} at #{Time.now} "
end
##
# Find existing issue or create new
def find_or_initialize_issue
::Bcf::Issue.find_or_initialize_by(work_package: work_package, project_id: work_package.project_id)
end
def to_bcf_datetime(date_time)
date_time.utc.iso8601
end
def to_bcf_date(date)
date.iso8601
end
def url_helpers
@url_helpers ||= OpenProject::StaticRouting::StaticUrlHelpers.new
end
end
end

@ -0,0 +1,84 @@
##
# Extracts sections of a BCF markup file
# manually. If we want to extract the entire markup,
# this should be turned into a representable/xml decorator
module OpenProject::Bcf::BcfXml
class MarkupExtractor
attr_reader :entry, :markup, :doc
def initialize(entry)
@markup = entry.get_input_stream.read
@doc = Nokogiri::XML markup
end
def uuid
extract_non_empty :@Guid, attribute: true
end
def title
extract_non_empty :Title
end
def priority
extract_non_empty :Priority
end
def status
extract_non_empty :@TopicStatus, attribute: true
end
def description
extract_non_empty :Description
end
def author
extract_non_empty :CreationAuthor
end
def assignee
extract_non_empty :AssignedTo
end
def modified_author
extract_non_empty :ModifiedAuthor
end
def due_date
date = extract_non_empty :DueDate
Date.iso8601(date) unless date.nil?
rescue ArgumentError
nil
end
def viewpoints
doc.xpath('/Markup/Viewpoints').map do |node|
{
uuid: node['Guid'],
viewpoint: node.xpath('Viewpoint/text()').to_s,
snapshot: node.xpath('Snapshot/text()').to_s
}
end
end
def comments
doc.xpath('/Markup/Comment').map do |node|
{
uuid: node['Guid'],
date: node.xpath('Date/text()').to_s,
author: node.xpath('Author/text()').to_s,
comment: node.xpath('Comment/text()').to_s
}
end
end
private
def extract_non_empty(path, prefix: '/Markup/Topic/'.freeze, attribute: false)
suffix = attribute ? '' : '/text()'.freeze
path = [prefix, path.to_s, suffix].join('')
doc.xpath(path).to_s.presence
end
end
end

@ -0,0 +1,59 @@
require 'open_project/plugins'
module OpenProject::Bcf
class Engine < ::Rails::Engine
engine_name :openproject_bcf
include OpenProject::Plugins::ActsAsOpEngine
register 'openproject-bcf',
author_url: 'https://openproject.com',
settings: {
default: {
}
} do
project_module :bcf do
permission :view_linked_issues,
'bcf/linked_issues': :index
permission :manage_bcf,
'bcf/linked_issues': %i[index import prepare_import perform_import]
end
menu :project_menu,
:bcf,
{ controller: '/bcf/linked_issues', action: :index },
caption: :'bcf.label_bcf',
param: :project_id,
icon: 'icon2 icon-backlogs',
badge: 'bcf.experimental_badge'
end
assets %w(bcf/bcf.css)
patches %i[WorkPackage]
patch_with_namespace :BasicData, :SettingSeeder
extend_api_response(:v3, :work_packages, :work_package_collection) do
require_relative 'patches/api/v3/export_formats'
prepend Patches::Api::V3::ExportFormats
end
initializer 'bcf.register_hooks' do
# don't use require_dependency to not reload hooks in development mode
require 'open_project/xls_export/hooks/work_package_hook.rb'
end
initializer 'bcf.register_mimetypes' do
Mime::Type.register "application/octet-stream", :bcf unless Mime::Type.lookup_by_extension(:bcf)
end
config.to_prepare do
WorkPackage::Exporter
.register_for_list(:bcf, OpenProject::Bcf::BcfXml::Exporter)
end
end
end

@ -0,0 +1,12 @@
module OpenProject::Bcf::Patches
module Api::V3::ExportFormats
def representation_formats
super + [representation_format_bcf]
end
def representation_format_bcf
representation_format :bcf,
mime_type: 'application/octet-stream'
end
end
end

@ -0,0 +1,36 @@
#-- copyright
# OpenProject Costs Plugin
#
# Copyright (C) 2009 - 2014 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#++
module OpenProject::Bcf::Patches::SettingSeederPatch
def self.included(base) # :nodoc:
base.prepend InstanceMethods
end
module InstanceMethods
def data
original_data = super
unless original_data['default_projects_modules'].include? 'bcf'
original_data['default_projects_modules'] << 'bcf'
end
original_data
end
end
end

@ -0,0 +1,44 @@
#-- copyright
# OpenProject Backlogs Plugin
#
# Copyright (C)2013-2014 the OpenProject Foundation (OPF)
# Copyright (C)2011 Stephan Eckardt, Tim Felgentreff, Marnen Laibow-Koser, Sandro Munda
# Copyright (C)2010-2011 friflaj
# Copyright (C)2010 Maxime Guilbot, Andrew Vit, Joakim Kolsjö, ibussieres, Daniel Passos, Jason Vasquez, jpic, Emiliano Heyns
# Copyright (C)2009-2010 Mark Maglana
# Copyright (C)2009 Joe Heck, Nate Lowrie
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License version 3.
#
# OpenProject Backlogs is a derivative work based on ChiliProject Backlogs.
# The copyright follows:
# Copyright (C) 2010-2011 - Emiliano Heyns, Mark Maglana, friflaj
# Copyright (C) 2011 - Jens Ulferts, Gregor Schmidt - Finn GmbH - Berlin, Germany
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
require_dependency 'work_package'
module OpenProject::Bcf::Patches::WorkPackagePatch
def self.included(base)
base.class_eval do
has_one :bcf_issue, class_name: 'Bcf::Issue', foreign_key: 'work_package_id'
end
end
end

@ -0,0 +1,7 @@
require 'open_project/version'
module OpenProject
module Bcf
VERSION = ::OpenProject::VERSION.to_semver
end
end

@ -0,0 +1 @@
require 'open_project/bcf'

@ -0,0 +1,23 @@
# encoding: UTF-8
$:.push File.expand_path("../lib", __FILE__)
$:.push File.expand_path("../../lib", __dir__)
require "open_project/bcf/version"
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "openproject-bcf"
s.version = OpenProject::Bcf::VERSION
s.authors = "OpenProject GmbH"
s.email = "info@openproject.com"
s.homepage = "https://community.openproject.org/"
s.summary = "OpenProject BCF import/export"
s.description = "This OpenProject plugin introduces BCF functionality"
s.files = Dir["{app,config,db,lib}/**/*", "CHANGELOG.md", "README.rdoc"]
s.test_files = Dir["spec/**/*"]
s.add_dependency 'rails', '~> 5'
s.add_dependency 'rubyzip', '~> 1.2'
s.add_dependency 'activerecord-import'
end

@ -32,7 +32,7 @@ module BimSeeder
module BasicData
class TypeSeeder < ::BasicData::TypeSeeder
def type_names
%i[task milestone phase building_model defect approval]
%i[task milestone phase building_model defect approval bcf_issue]
end
def type_table
@ -42,7 +42,8 @@ module BimSeeder
phase: [3, true, :default_color_blue_dark, false, false, :default_type_phase],
building_model: [4, true, :default_color_blue, true, false, 'seeders.bim.default_type_building_model'],
defect: [5, true, :default_color_red, true, false, 'seeders.bim.default_type_defect'],
approval: [6, true, :default_color_grey_dark, true, false, 'seeders.bim.default_type_approval']
approval: [6, true, :default_color_grey_dark, true, false, 'seeders.bim.default_type_approval'],
bcf_issue: [6, true, :default_color_grey_red, true, false, 'seeders.bim.default_type_bcf_issue']
}
end
end

@ -31,6 +31,7 @@ en:
default_type_building_model: Building model
default_type_defect: Defect
default_type_approval: Approval
default_type_bcf_issue: Issue [BCF]
demo_data:
welcome:
title: "Welcome to OpenProject BIM Edition!"
@ -57,6 +58,7 @@ en:
- work_package_tracking
- news
- wiki
- bcf
news:
- title: Welcome to your demo project
summary: >
@ -70,6 +72,7 @@ en:
- 'seeders.bim.default_type_building_model'
- 'seeders.bim.default_type_defect'
- 'seeders.bim.default_type_approval'
- 'seeders.bim.default_type_bcf_issue'
categories:
- Category 1 (to be changed in Project settings)
queries:
@ -105,6 +108,9 @@ en:
- type
- status
- assigned_to
- name: Issues [BCF]
status: open
type: 'seeders.bim.default_type_bcf_issue'
work_packages:
- subject: Project kick-off
description: Plan and execute the project kick-off.
@ -181,10 +187,10 @@ en:
Please activate further [Modules](%{base_url}/projects/demo-project/settings/modules) in the Project settings in order to have more features in your project.
**You can:**
* add a Scrum module (Backlogs),
* add time tracking, reporting, and budgets (Time Tracking, Cost Reports, Budgets),
* add a wiki,
* add meetings,
* add BCF import/export,
* and more.
**Visuals:**

@ -15,4 +15,6 @@ Gem::Specification.new do |s|
s.version = "1.0.0"
s.files = Dir["{app,lib,config}/**/*"] + %w(CHANGELOG.md README.md)
s.add_dependency "openproject-bcf"
end

@ -59,7 +59,7 @@ describe 'seeds' do
expect(Project.count).to eq 1
expect(WorkPackage.count).to eq 18
expect(Wiki.count).to eq 1
expect(Query.count).to eq 4
expect(Query.count).to eq 5
ensure
ActionMailer::Base.perform_deliveries = perform_deliveries
end

@ -1,9 +0,0 @@
module OpenProject::XlsExport
class FilenameHelper
# Remove characters that could cause problems on popular OSses
# => A string that does not start with a space or dot and does not contain any of \/:*?"<>|
def self.sane_filename(str)
str.gsub(/^[ \.]/,"").gsub(/[\\\/:\*\?"<>|"]/, "_")
end
end
end

@ -29,7 +29,7 @@ module OpenProject
enable! WithDescription if with_descriptions
enable! WithRelations if with_relations
success(spreadsheet.xls)
yield success(spreadsheet.xls)
end
def success(content)
@ -107,7 +107,7 @@ module OpenProject
end
def xls_export_filename
FilenameHelper.sane_filename(
sane_filename(
"#{Setting.app_title} #{I18n.t(:label_work_package_plural)} \
#{format_time_as_date(Time.now, '%Y-%m-%d')}.xls"
)

@ -13,5 +13,8 @@
"private": true,
"engines": {
"node": "~8.12.0"
},
"dependencies": {
"webfonts-generator": "^0.4.0"
}
}

Loading…
Cancel
Save