Timeline settings

This commit is contained in:
Nick Beckley 2026-06-03 10:26:38 +01:00
parent 2ad5865c58
commit 69fb21c5eb
84 changed files with 1098 additions and 337 deletions

View File

@ -1,5 +0,0 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSTwY7cKBCGX8XibDyAMTa+jXp2ldYkO61klKz2hqkijeKBFsaTRKN+9xXujpLJLTdUUFV/fX/xQoJ5QjKS29Ppr2cMeSE1yX4LCSYUZYoy8SjYyMXY6UawXnWD+I/UxN/jdzKSXlrLrUbaokIqgXV0ap2lAKg548BEJ0tN83kh4wsxvgF89habuHzEtPgYyEg++QDxa+ltfGPnuEKT4oz7sGQTbBHzz353T9/eHh4fDpdXCy4lufFARtK1YHopGDWDslQ6ZHSYnKNKaQlKdpINcEnzIWMKZm4W+PKzP8QcMNtRNKJtGBWanGsCJpsieTILPn4/FRUborsSr7fwdhxfyDMmMor6B8xLuRs7+xsbn55MgBvng1+OpCanFE+YsscNxzbhPJvsY6iuTXazx5BJTR4+VIfZZBfT0ytGHy6j7/9g8nfGHn3Aan9HRsI4CmgHpE5wReUAhpqu1VSpVjnkVveCk5rsYsg+rHFdqn3I+DltKslI/jbzghd9t8kefUab11Sk/6uK1/jN512EEmCkJocUYbW5+ombs4Y1LSuXD2s+rbl6j+AT2oxlpse0Xsv/liKU2JJ2a0oYcnUw+Vi9McuRjESbwXKjjTZGWeuwY+gYMKNYD6hAIUgBPcgNi2ZWSTNxCabjkyuRoru4W20LNYAQnUNNBQhOJWigRrUTVQxagMG5blCvsFYPc8kzdmASoaUaHVCpuaFati2FtjO9UK7vhfsFydVxzgpvwOfL19gUKIABQXEqJO+o1JrTQXc9nfph0pMasLNF8z2mgPMvoN55m+ISXa6uC1O9Qvd+DeV7V9vyfPWBftssu4v2C6aqWG58KNt8dfl8Pp//BwAA//8DAJt2xo0lBAAA

View File

@ -1,5 +0,0 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSTQW/cNhCF/4owZ1EmKYoSdTPWKbpwEy+SRVr0RnFGMWGZWlCUk8DY/x5Qu0Hi3noRhAEf571vhq8Q7DNBD7en07sXCmmBEpLfSpJLzbhmXB4l74XsG1NJrnSnzb9Qgr+n79BDq5wTzhCrSRNTyBs21KNjiGQEF8hlo/Kd9ssC/StYXyG9eEfVvHymuPg5QA9/+4Dz19zb+spN84pVnCfahyXZ4LKZD/vdPfvr9nB8OFxOLbRkceURemhqtK2SnNlOO6ZG4qwbxpFpbRRq1Sje4UXmQ6IY7FQt+PSrP84pUHK9rGRdcSYNnEtAm2y2PNiFjt9P2cWG6C7Xy628/fav8EIReln+hHm57sZN/uZ5GVY/4c3lm+zylFOe4nyimDxtTLaY02STn0Nx7bSbPIUEJTx8Kg6TTeMcn9+A+nTJv/8f8Y+5+7tv5NZEuJvXkKAHoTSU8N66Rx+o2N9BD1yQxLojNkqhmerQMtvUhmld65GEM60UUMJuDsmHdV6XYh8SfYlbAOjhDzstdLF+G92jT+TSGnOqf3TehUOccXWp+MVf8IpXNedZtKbTmoqPhD6SS5TzHeN6ve8/EqnlJtqtMVJIxcGmx+JPuzxCD8Z2TlhjjbXauZEaTiNHbjVvkTRqQiWxRbUhMtxpZQeh0DZiGHMFSqA87mLbMMt1I0Sj2EiNY6rtJDMGFaPREklXt13TvuFYPEybznVcEdbM0IhMGWGZUXXNsG5sK/XYtnL8Dcl1+oJnwEgvl7eyOdCIHaEWTCrRMGWMYJ1pWja03WAG3VHjsud7ioGm30C99y7Oyzym4ro8xRt0H9eQ33uxLdJXH9i3bUZ3s3uiWOQZWx/yel/Hej6fzz8AAAD//wMAR26UADYEAAA=

View File

@ -1,5 +0,0 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUW2/cNhCF/4rAZ1Hm/aI3w25Rw02ziI226NuIM4qFaKWFRG0aGP7vBbVbJO5b34SBzvDwmzN8ZRMcibXs9nT66UxTXlnN8rCXlFCOC8eFelailbq1sfFGhxjsX6xmwyN9Yy3zJiWZInFNjrhBYXmn+8QRKUohUShrSk/4vLL2lcHQIJ2HRM28/k7LOswTa9kfw4Tz13I2DE0a5w2bZR7pYVozTKmY+e3h7pH/ent4/ni4/LXSWsTNgMWqtjH2aHgM0HPjlePBoeGKgk0gAgQDF9kwZVomGJsVv3w/H+c8UU6tapRuBFeRvdUMIUOx3MFKz99OxcWO6L7U6728f7av7EwLa1X9L8xLu5s0Djfr1o10pvEEy0rLTZqPR5iQ1ey0zCda8kA7ljMt3bwOuRBNyUMIUmIAb6zHoK3SHrUgDMJbjBjBGderZG2PXYje9AaVNOjImM6zmu3gxhHyME/V1fvdONCUWc0+PlWHEXI/L8d36J8uRB/+B9Bim7VMC6ud92S01hBdpwShd8k51SUQvu8UyUTCRuOj9ELqqETU1vngEURMrGYfIL0ME1UP96xlQpJCHYj3SjpuAgIHqyN3TrueZIpeSVazu3nKw7TN21o9TJk+L/t9Wct+hnGly01vl/QyZEp5WwqEP10J42GZcUu5+h4AKRrRaCGKaMunLVefCIeFUqaC43nZrv3+I1FO7aK7bVloytUB8kv1C6wvrGURQpIQIQK4lHqygnqBApzwSA4doVHo0USDzkSRnIFOGgQru75UWM2o5K3aI05Sd0II5N75npvO9DwEQh5sTFo4DWD9O47Vx7HoIAVhCDWP1CM3UQKPRmuO2oJXrvde9T8guYZFigIY6XxZ1t2BQwyETnJlpOUmRslDtJ53PnSxc4FsKp4faZlo/AHUhyEt8zr3ubpmrXqH7tM2lQen2nP3dZj43/uM7uf0hZaqzBiGqezXdaxvNTsSrNtCx/29al/ZoSxX9bw/W8o3ToZQs6cMS95O17IJjXXGvr29vf0DAAD//wMARwDop/QEAAA=

View File

@ -1,5 +0,0 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUTW/cNhCG/4rAsyjz+0M3w25R1029iBdp0duIHNlCtNKCojYNjP3vAbUbJO6tF0EYcGZePvMO38gEByQtuT0efznhlBdSkzxsIcGEocxQJvaCtVy22jeWScO4/ofUZHjEr6QlVoXAg0cq0SBVkWnayT7QGNFzxiMTWpWa8LKQ9o3A0EQ8DQGbefmEaRnmibTkr2GK85fSG4YmjPMamzSP+DAtGaZQxPz5cPdI/7jd7Z92l1MLLiW5GWKRKrX3fVTUO+ipssJQZ6KiAp0OwBw4BZe0YcqYJhibJX7+0T/OecIcWtEI2TAqPDnXJEKGIrmDBfdfj0XFhui+xOstvP22b+SEibSi/g7zUu4mjMNNno8jnnA8Qlow3YT5cIApkpoc03zElAfcsGw3HUfIwzxV12Z344BTJjV5eq52I+R+Tod3rJ4vCB7+B4ETpo60RDItjbWopJTgTScYRmuCMaILwGzfCeQBmfbKem4Zl14wL7WxzkZgPpCavIxzB+Pvy8bPC9a5yKwwAhV6oYzxgaF02GuLLIIxnXHBR+msUC46CR6A+w5t8CYUg3yA8DpMWD3ck5YwjiJKh7QX3FDlIlDQ0lNjpOmRB28FJzW5m6c8TOu8LtXDlPElbfxIS36FccELudsUXoeMIa+pQP3blGa7NMc15OqHAzhrWCMZK0lrPq65+ohxSBgyFrz7tF7r/SdFGLEl3a0p4ZSrHeTX6jdYXgsVcIGDL1c1IfSoGfYsMjDMRjTRYFQi2qi8ikZ5FoyCjqsImnd9iZCaYDFctXncg+5602uqZPkYgdRxzqhF7kSURnbaveNYPY0lD4JjCqOkHvtIledAvZKSRqnBCtNbK/qfkFzNx1kBHPF02dZNgYnRYTScCsU1Vd5z6ry2tLOu851xqEPR/IhpwvEnUB+GkOZl7nN19W71Dt3HdSovTrX5+Msw0X+3Gd3P4TOmqswYhqks2HWs55ocEJY14WF7sNo3sivbVe23d0vYxnDnavKcIeX1eA0r12ij9Pl8Pn8DAAD//wMAZQmTEfUEAAA=

View File

@ -1,5 +0,0 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUTW/jNhCG/4rAs6hQFEWJuqVOFzWy2Rgbd1v0NiJHDhGZNCgq2yDwf19QdhBnFz30Joz4zsczL/lKHOyRdOT6cPj9GV2cSE6iXUKccUmZpIxvOevKqqtV0TR1xcr2H5ITe4svpCON0LrUCmmFEqkwrKZ9NWhqDKqSlYbxWqScsJtI90rAFgafrcbCT98wTNY70pG/rDP+e6oNttCjn00R/IhrN0VwOjXzZb26pZ+vN9v7zenUhFMSF9akVqtaqcEIqloYqGi4pK00gnJsaw2shVbASWZdxOBgLCbz9F7f+Ogw6o4XvCoY5Yocc2IgQmq5hwm3L4fUxYLoJsXzJbx8dq/kGQPpeP4G85TuSo/2aj/1sx3N1eh3O+t2K+8Gu5sDxFQ4J4fgDxiixQXOb9ZBePnsd7uUj3yCcUKSky2GvXUwnn7c4ADzGB/8HBYyk3n6rzOkIzBHT3KykBzHpWx2HmY1WnTxF+1F4fuHbDNCHHzYf1jSw4n9+n+gvwP9aB1m6xvSEVYiN1WLdOClpKI1QKGuFJWykgOWWjW8JDlZeRetm/08ZWsXcXem9qG/66AfbUQd55Bm+lsms22CN7OO2fuCS1awomIsieZ4mGP2FY0NqCOmIbZhPuf7ScIlX0Sf7Ii/4FnNIaCL2QbiY/YHTI+kIwpaXYICBSC1HrBmODDDQLLGoDQSjeCmMUIJI4ViWgroS2GgLvshRUhOMJksW3zNjBiMrBQFUTMq+NDTViOjptZVrRhP4Q9ws/sx6UC3TKCpqMLBUKFKoEpUFTVVDQ2XQ9Pw4YLT2RAlS9QvTfjnhObspS8na7/NbvD5dI+XPqUxLRpZUi7KmgqlStqquqF90/aqly3WOk228m7ybyC/Yej9ZGN6RO6ss3sYfz7yvplbDA7Hi+3cWR385IeYnW2ZfdjX19mlVyxbLPrdOvrvYowbr58wZMlYYN3FMo/H4/EHAAAA//8DAHDfcRcMBQAA

View File

@ -1,5 +0,0 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRTwW7UMBD9lcjnOLUdx4lzq7YgVgW6ohUgbrOeCWuROivHKaBq/x05uwjKjZv17Dfz5r3xMwvwSKxn18fjqycKaWYlS36FlFCGC8OFelCil7oXorJS61qpL6xk/pZ+sp612jnpLPGaDHGNouH7enAckawUEoVqdK4JX2fWPzPwFdKTd1RN80eKs58C69knH3D6nnuDr9w4LVjFaaRtmBMEl8W8325u+dvr3cPd7vxqpjmTK49Zat1YO6DmtoOB61YZ3hnUXFHXOBAddBrONB8SxQBjNeO3P/1xSoGS61Wl6kpwZdmpZAgJsuQ9zPTw85hVrBbdZLxc4fXYP7MniqxX5W8zz+Wu3Oiv3PT4CAGvBh/8fGAlO8bpSDF5Wu1YJxxHSH4KxaXJZvQUEivZ3X2xGyENU3x84dH9efTtf0z+DtzBByq2N6xnQpLCuiM+KGm47hA4NLXlxtRmIOlsqyQr2WYKyYdlWuZiGxJ9jatK1rPXMM501ncd3cEncmmJWfpnk7OmHz5tJsyAYCXbxQkXl4o/dktRiaoW+fJuScclFR8IfSSXKM/0EJdL+X8oyqiVtFlipJCKHaRD8QbmA+uZhc5JsGABjHMDNYIGgQKMaJEMGkKtsEVtNRpthTMa9lIjNHI/ZCTrzukW60KBA4GmG7hqasW1dIJ3lgyXRlmwlgwYfGFrcTeeeZ3QhDW3NCDXVgK3uq451g20ygxtq4a/LLkkLkX2G+np/DVWBQaxIzSSKy0brq2VvLNNy/dtt7d701HjsuZbioHGv4x6512c5mlIxWVhihfWfVhC/t7FujzffeA/1shuJveNYpEjBx/yNl9SPp1Op18AAAD//wMATZ4i4iUEAAA=

View File

@ -1,5 +0,0 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRUwW7bOhD8FYFnU6EoihJ1C5wWz8hrY7RGW/S24q4aIgplkFTaIPC/F5RdpDk9vAtBrDjL2ZmhXpiHR2I9uz4e3z2RT5FtWHJrSQqpudBcyIMUfaV6IUojtGpq8Z1tmLulZ9azVllbWUO8Jk1coWj4UI+WI5KpRIVCNir3hB+R9S8MXIn05CyVc/xCIbrZs559dR7nn/lucKWd5gXLME+08zGBt5nMx932lv97vT/c7c+nIsUMLh1mqnVjzIiKmw5GrlqpeadRcUldY0F00Ck4w5xPFDxMZcSH1/txTp6S7WUp61JwadhpwxASZMoDRDo8HzOLVaKbXN+s5XXbv7AnCqyXmz9inttd2cldPcZhcRNendcE8SGu6wg2zeGZbdgxzEcKydGqz3WM9DhMzweID+/PZ/I2vvtFdkmE23nxifWsqg3bsFWgaYLkZl9cOG4nRz6tH1NwPjr7X72yP3efi/0EaZzD4xs/Pp9l3v0PlT+AvXeeit0N65moSGLdER9lpbnqEDg0teFa13qkyppWVmzDtrNPzi/zEoudT/QjrCOxnr2HKdKZ33Ww9y6RTUvIc37Tmfc+zLjYVLx6WYlSlLUQGbSk45KKT4QukE2UhziE5dLvy1uI1HIFbZcQyKdiD+m++AfiPeuZgc5WYMAAaGtHagSNAgVo0SJp1IRKYovKKNTKCKsVDJVCaKphzBW2YZSjU6xpbQ3JVirBqTaKq7EZuaG25dQhiU4rlKu5rzoWd1PGge2EIqy5oRG5MhVwo+qaY91AK/XYtnL8S5JLHiqRBUZ6Or+7lYFG7Ah1xaWqGq6MqXhnmpYPbTeYQXfU2MzgloKn6S+hPjgb5jiPqbgkpHgj3afF539Hsablp/P81+rRzWwfKBTZY3A+P5WLrafT6fQbAAD//wMAYoXgq4IEAAA=

View File

@ -1,5 +0,0 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACoxUXU/lNhD9K5FfGwd/xYnzRoFVrygf2nvVVn2b2BNwCc6V48AixH9fORcK7KpSX6JobM85c+bMPJMA90g6crzfnz1gSDMpSfJrSDChKdOUiZ1gHVcdY5XhSnFp/iYl8ef4RDrSKGu5NUglaqTKsZr2crDUOTScccdErXJOuJlJ90zAVw4fvMVqmv/AOPspkI786YObHjM2+MqO0+KqOI24CXOCYDOZy83JOf39+Hp3dX24NeOcH1feZaqyNmZwipoWBqoaoWmrnaIC29oCa6FVcHjmQ8IYYKxmd/eO76YUMNlOVEJWjApDXkriIEGm3MOMu6d9ZrFKdJrj5Rpef7tn8oCRdKJ8E/OQ7siO/uh+7hc/uqP1S0qyj9MeY/K4qnG1Ld5JcFaxSmjBGCnJBdhbH7DYnBZXYy4RbMsUOkkNDo4qw4EaJSV1soZG6KFpxEBKco4x4Pgh64W3cZqnIRWvIhefcLbHJ2cB+hEzxhcYZyQl2czbBMHBOAU8+4Z2SYdcu7jk45MpJB+WaZmLTUh4E+H1/O39yRIjhlRcQ7otfoP5lnTEQGs5GDAA2toBa4YDcww0axxqp9Ep4RqnjHJaGWa1gp4rBzXvhxwhJfk1a7hdrMV5fmezmmQcVw7Fa59ORo8hfZKRdIRxFE62SAfBNVWtAwq1NFRrqQfk1jSCv8HsIN5gIh0Z2r7vmbW9UIZbEAakG5h0ejBCNA2oQdaNElrXrAHrmkZw5WSDFuQgWStISa7j5Babfmy1XBtwHad/0KYsFemIrblpWl5LUdeybViPqm6g1oyJRjPkRtZONtK5QbWmbWBwChrUqh14z4Rwb/TPwo0PeOrn/QhPH3DbSlfyFwvQ8gHeRT1c/xLhHh+neHd5sHF1ebYjJfm6hLwRik22yKMP9JvOE32xjMnvbiOCQ3cxOfzZR5jHpVgnVOZmS4V0kMJRJaSggKDpgLbFFq1xLJM/newdxiI7DHzIU/VvsqttcRztrU9o0xIzv79WHlfb4nqENEzx/tMm+VDYjwJUQnKWO+Pw4bCNVo7auRad5lQoXlNlDKetqRvaN21vet1ibbNiV0vaL6n4is5HtGmt+NWLK+bJLdq7n8V4c8GrRTnLXtsettgq7f9aYi8luUeYl4j367bunskmBIwr8ulyGMVNuPDj6Ge0U3Az6ThXuhLC6FeG/3lPMFYxWdcvLy8v3wEAAP//AwC4eGIfGwYAAA==

View File

@ -1,5 +0,0 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACoxUTW/bOBD9KwLPokJRFCUK2IPhtFgjTWMk7u5ibxQ5jInIokFRToMi/31BSa6dooe9CaP5eO/NG/5AvTwAatDqePx0gj4MKEXBTiFKKMeEY0J3lDQ5awjJaJGXlNN/UYrsHbyhBlVMqVwJwAVwwEyTEreFUVhrEDnJNaEliz3l84CaH0jaTMPJKsjc8Bf4wboeNehv22v3GmdLm6nOjTrzroNNPwTZqwjm62Z9h7+struH7Zw1wBCLM6sj1KIUwmiGRS0NZhXluOaaYQp1qSSpZc3kXGb7AL6XXTbol8t87UIPQTU0o0VGMBXoPUVaBhkht3KA3dsxopgkuo3xdApPn80PdAKPGpqexZzb3ajO3hyGdrSdvgnSP0MwXh7g1fkXOMkOpejo3RF8sDBp8/CUXCDlJCMZ5ZQQlKJ7qfa2h2Rzmzx0kbBUNWGgCyzAaMxELrFgRYF1UcqKclNV1KAU3YHvobvqem+Vd4MzIVkkTz7MWbs+2H5045Bs+gDPXoa57rPsBkAp2o5tZ4f9I0j9tnOPY/zXj13ksh69hz4kWxn2yZ9y2KMGCVmrXAoppORKGSgJGKKJ5KTSwDUHzaiuNBNMcyaI4ky2OdOyzFsTIyhFD2M4juGs//crEDtvDwfQFwS7SeNtJ4Nx/rDR0AdrbFzNOWMyVNdNrJKl57qz0IcPIqMGkRyoLmrAhuYcs1pLLMtCYM4LbiBXoqL5LJixz+NPnYgxmhWmrGveijYnQE1VM1KZlmhlCiV02UJFK1LVUAtFSFuyvG6FIhrykunIzjs9qvCrFYppQY9jH68z2UTar7bH3zm7KLL1Ljjlurgw28HT2xDg8Lutrd3h6AYbIn+zrPbbAPeuj3+X+180W4pXLlxiEO8gmU5PStnSquW4NabFDEyBa2grXFaUGVrTquaR1a1TL+CTaDBp+2knZ089PCUrr/Y2gAqjj5P/mUjN6/x8PpmLHtnXT7u187A6HtMl+scpijQ3Oxvgw7vybYjpezdEFsGPVz56gs6ccV25ScNpfqlsDHKta9A8x5TlJWZC5LgWZYXbqm5Fy2so1cWtySNo60GFqd9unrYI+ztbrnywRqowxNv54tTkpsWeS8qvIK+29rN6Hn61ucVJS6ecRMc+ze/mZKD/9Wy+v7+//wcAAP//AwAXRjOgJwYAAA==

View File

@ -1,5 +0,0 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRTTW/cNhD9KwLPokxSFCXqZqxTdOEmXiSLtOhtxBnFhGVqQVFOAmP/e0DtBk5664UgBnwz72P4ygI8E+vZ7en07oVCWljJkt9KSijDheFCHZXope6FqKzotLLNv6xk/p6+s5612jnpLPGaDHGNouFDPTqOSFYKiUI1OveELwvrXxn4CunFO6rm5TPFxc+B9exvH3D+mmeDr9w0r1jFeaJ9WBIEl8l82O/u+V+3h+PD4fJqoSWDK4+Zat1YO6LmtoOR61YZ3hnUXFHXOBAddBouMB8SxQBTteDT23ycU6DkelWpuhJcWXYuGUKCTHmAhY7fT5nFZtFdrpdbebv2r+yFIutV+dPMS7sbN/mb52VY/YQ3lzPB8pRVnuJ8opg8bZ5sMqcJkp9DcZ20mzyFxEr28Kk4TJDGOT7/ZtSni/79/5B/zNPffSO3JsLdvIbEeiZ1zUr2HtyjD1Ts71jPhCSFdUd8VNJw3SFwaGrLjanNSNLZVklWst0ckg/rvC7FPiT6EjcBrGd/wLTQhfptdI8+kUtrzKr+MXkXDnHG1aXizX8pKlHVQmTQmk5rKj4S+kguUdZ3jOu1338gyqgNtFtjpJCKA6TH4k9YHlnPLHROggULYJwbqRE0ChRgRItk0BBqhS1qq9FoK5zRMEiN0MhhzBVWMspxF9uGDSMSNcJy0cqRa6kUt7JtuGxtO1jROqkzkTcfi4cp48B1QhPW3NKIXFsJ3Oq65lg30Coztq0af7Hkmr4U2WCkl8tf2RgYxI7QSK60bLi2VvLONi0f2m6wg+mocZnzPcVA0y9Gvfcuzss8puK6PMVv1n1cQ/7vxbZIX33g37aM7mb3RLHIGYMPeb2vsZ7P5/MPAAAA//8DANBOlYk2BAAA

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUTW/cNhCG/4owZ1HmlyhRN2OdoAs39SJZpEFuFDmKCcvUgqScGIb/e0HtFo5PRS8EMeIM33nmpV4gmEeEAa5Ppw9PGHKCGrLfQpxyRagiVBypHmg3MNX0VAql+Xeowd/iMwzQSWuZ1UgEKiTS0ZaMYrLEOdSMMkd5K0tN8yPB8ALGNw6fvMVmSV8xJr8EGOBvH9zys9xtfGPnZXVNXGbch5RNsEXMX/vdLfnz+nC8O5xPJUwlufEOBjBUWWaoJq0YOyJ7y0iv+olYzTrLrZxGPZ7TfMgYg5mb5B7e7ndLDpjtwBsuGkq4htcanMmmSB5NwuPzqajYEN2UeL2Ft+3wAk8YYeD1vzDP5a7s7K8e07j62V2d12zSQ9rWydi8xGeo4RSXE8bsceNznRI+jvPz0aSHj+czZZs+/EK7ZnS7ZQ0ZBhAcatj4zLPJfgnVReJu9hjy9jFHH5K3/1VKQQ13X6rDbPK0xMd34/hyprz/H5A/GXvvA1b7GxiAMuRO9EgmzhSRvTPEtEITpYSakFndcQY17JaQfViXNVX7kPFH3FqCAT6aOeFZ33W09z6jzWssfX5TxVaHuLjV5uptlIw2tBGUlqQ1n9ZcfUbnI9qMpYljXC/1vr5P4YpvSbs1Rgy5Oph8X/1h0j0MoE1vmdFGG6OsnbClOFFHjaKdQ+UUOsld56SWTklNrZJmZNKZlo1TiUANWJxTbWYVSnV0YiPRWnEiBUWiOycIFZ1go9SMTqW1N47V3bzxtz2V6ATRODkiNTNESyGIE63puJq6jk+/Ibn4gdEC2OHT+dltCpRzPTrFCJesJVJrRnrddmTs+lGPqsfWFs23GAPOv4H65G1c0jLl6uKQ6h26z2sov45qc8tPH8ivbUY3i33AWJUZGx/KS7mM9fX19fUfAAAA//8DAEdV7PeBBAAA

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRTTW/cNhD9K8KcRZmkKErUzVin6MJNvEgWadEbxRnFhGVqQVFOAmP/e0DtBol764UgBnwz72P4CsE+E/Rwezq9e6GQFigh+a0kudSMa8brIzc9b3uhq47rzsj2XyjB39N36KFVzglniNWkiSnkDRvq0TFEMoIL5LJRuaf9skD/CtZXSC/eUTUvnykufg7Qw98+4Pw1z7a+ctO8YhXnifZhSTa4TObDfnfP/ro9HB8Ol1cLLRlceYQeLNdOWG5YUw8tU50TrNPdyJwRrZNOjYMZLjAfEsVgp2rBp1/zcU6BkutlJeuKM2ngXALaZDPlwS50/H7KLDaL7nK93MrbtX+FF4rQy/KnmZd2N27yN8/LsPoJby5nsstTVnmK84li8rR5ssmcJpv8HIrrpN3kKSQo4eFTcZhsGuf4/MaoTxf9+/8h/5inv/tGbk2Eu3kNCXqoOyjhvXWPPlCxv4MeuCCJdUdslEIz1aFltqkN07rWIwlnWimghN0ckg/rvC7FPiT6Ejf+0MMfdlrowvw2ukefyKU1ZlH/6LwKhzjj6lLxy37BK17VnGfQmk5rKj4S+kguUZZ3jOu1338gUssNtFtjpJCKg02PxZ92eYQejO2csMYaa7VzIzWcRo7cat4iadSESmKLyijUynCnlR2EQtuIYcwVKIFy2sW2YE42DUeNDK0bmFLWsc7ZkbVSDY1tVKMGfONj8TBtybiOK8KaGRqRKSMsM6quGdaNbaUe21aOv1lyDV/wbDDSy+WrbAw0YkeoBZNKNEwZI1hnmpYNbTeYQXfUuMz5nmKg6Tej3nsX52UeU3HdneKNdR/XkL97se3RVx/Yty2ju9k9USxyxtaHvN3XWM/n8/kHAAAA//8DAC/YO0o1BAAA

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSTT2/cIBDFv4rF2TiAMQbfok2rrtI0q2bVVr1hGGdRvLDCOH8U7Xev8G6VpLferCfPzJvfG16R13tAHbo8HD49gk8TKlFyi8QIE5gITOotUR1pOyoqSWStSPMblchdwwvqUMuNoUYBrkEA5pY0uK8Hg60FRQm1hDU899T3E+pekXaVhUdnoArTD4iTCx516KfzNjzl2dpVZgyzrWIYYe2npL3JZr6tV9f46+Vme7s5/TXBlIsrZ1GHNBGGaqJwU/ct5tJQLIUcsFG0NczwoVf9qcz5BNHrsZrsw9t8G5KHZDpWsboimCl0LJHVSWfLvZ5g+3LILhZEV1kvF3n57F7RI0TUsfIvzFO7CzO6CxP2e+3txeC8m3aoRIcYDhCTgwXHsuE46uSCL85DVqMDn1CJbu+KzajTEOL+A6O70+rr/9j8Rpud81Csr1CHCAVmawl4YFRgLq3GuqkVFqIWA1CjWkZRiVbBJ+fnME/F2ie4j4tL1KHPepzg5O8ymp1LYNIcs/VfImcNzy6tgs1C7rOJwc4mFW+4KalIVROSe8zpMKfiO1gXwSTIO23jfG7/TwkTbClazTGCT8VGp13xRU871CGlpaFaaaW1MGaAhsBALNGCtBaEFWA5s63lilvBFTGC655yqxvaD1nJvnO6xXJQvdSKG2NwL5nEXDGOe1FT3LYDAdEPLWvlB6zF7bjEYSThYGusYLCYK6qx4nWNbd3olomhbdnwDsk5cUoyJwuPp6exOBDWSrCCYsZpg7lSFEvVtLhvZa96IaEx2fM1RA/jO1A3zsQwhSEV54MpPqD7Pvv8vIvleJ6cx89LZFfBPEAscuTa+XzN55SPx+PxDwAAAP//AwCX2JfEJQQAAA==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUTW/cNhCG/4rAsyjzS/zQzbBb1HVTL+JFWvRGcUa2EC21oKhNA2P/e0DtBol7600YaGZePvPOvJHoD0g6cns8/nLCmBdSkzxuIcGEpkxTJvfMdcx0vG2ctqJ19h9Sk/ERv5KOGBUCDw6pRI1UAWtpL4dAAdBxxoGJVpWa/mUh3RvxYwN4GgM28/IJ0zLOkXTkrzHC/KX09mMTpnmFJs0TPsQl+xiKmD8f7h7pH7e7/dPu8teCS0luRiAd8UwH7pmjrewNVTZwarUdaHDcBBHU0Lv+kjbGjCn6qVng84/+MOeIOXSiEbJhVDhyrgn47Ivk3i+4/3osKjZE9yVeb+Hts3sjJ0ykE/V3mJdyN2Eab/J8nPCE09GnBdNNmA8HH4HU5JjmI6Y84oZle+k0+TzOsbo2u5tGjJnU5Om52k0+D3M6vGP1fEHw8D8InDD1RSCgBwTrwaJSTspBOtRGeGutBuV6z5mRFoztATl3vRjQBBlEO0BQUAb6Ms29n35fNn5OsN4CM0ILVOiE0toFhtLi0Bpk4LXutQ0OpDVCWbDSO++569EEp0Op98GH1zFi9XBPOsI4CpAW6SC4psqCp76Vjmot9YA8OCM4qcndHPMY13ldqoeY8SVt/EhHfvXTghdytym8jhlDXlOB+rcuzXZphjXk6ocDOGtYIxkrSWs+rrn6iDAmDBkL3n1ar/X+kyK02JLu1pQw5mrn82v1m19eCxVvA/euPFWHMGDLcGDAvGYGUINGUAIMKKdAK8eCVr7nCnzL+6FESE2wGK7aPC697h0TjgbjFFUYBuqk81RDGwwXrZBGvuNYPU2bM4JlCkFShwNQ5binTklJQbbeCD0YI4afkFzNx1kBDHi6bOumQANYBM2pULylyjlOrWsN7Y3tXa8ttqFofsQUcfoJ1IcxpHmZh1xdvVu9Q/dxjeXiVJuPv4yR/rvN6H4OnzFVZcZ+jGXBrmM91+SAflkTHraD1b2RXdmuar/dLSGblnNdk+fsU16P17BUDTdWn8/n8zcAAAD//wMA7yR7Y/UEAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUW2/cNhCF/4rAZ1HmTbzozbBb1HDTLGKjLfo24oxiIVppQVGbBob/e0HtBqn71jdhoMM58/FwXtkMR2Iduz2dfjrTnFdWszzuJSWU5cJyoZ9F6ITrpG2EMNK58Ber2fhI31jHnIlRxkBckyVuULS810PkiBSkkChUa8qZ8Hll3SuDsUE6j5GaZf2d0jouM+vYH+OMy9fSG8YmTsuGTVomepjXDHMsZn57uHvkv94enj8eLn+ttBZxMyLrGAgbJYjAW907bnyU3Fs/8BikiyqaoQ/9RTbOmdIMU7Pilx/9cckz5dipRulGcBXYW80QMhTLPaz0/O1UXOyI7ku93sv7Z/fKzpRYp+rvMC/H3cRpvFm3fqIzTSdIK6WbuByPMCOr2SktJ0p5pB3LmVK/rGMuRGN04L2U6MGZ1qHXrdIOtSD0wrUYMIA1dlCxbQfsfXBmMKikQUvG9I7VbAc3TZDHZa6u3u+mkebMavbxqTpMkIclHd+hf7oQffgfQIvtMi8SIKEH9GRM0HrQgaxT4L23aEIPUjjt0fkeScrQq4Fc1FG1A0aDJR8fIL6MM1UP96xjQpJC7YkPSlpuPAKHVgdurbYDyRickqxmd8ucx3lbtrV6mDN9Tvu8rGM/w7TSZdLbFF/GTDFvqUD405Zmh7TgFnP1IwBSNKLRQhTRlk9brj4RjolipoLjOW3X8/4jUVbtorstJZpzdYD8Uv0C6wvrWAAfJQQIADbGgVpBg0ABVjgki5bQKHRogkFrgojWQC8NQiv7oVRYzajkrbpE3LQmgHM8IAVuhjjwAFryFtANJCVCGN5xrD5Ouy56YQg1DzQgN0ECD0ZrjroFp+zgnCq670iuYZGiAEY6Xx7r7sAiekIruTKy5SYEyX1oHe+d70NvPbWxeH6kNNP0L1AfxpiWdRlydc1a9Q7dp20uC6fac/d1nPnf+x3dL/ELparcMYxzeV/Xa32r2ZFg3RId933VvbJDeVzV8762lG5aKW3NnjKkvJ2uZW0a6bx9e3t7+wcAAP//AwCJe8b/9AQAAA==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRU0W7jKBT9FYtn4wLG2Pitm+5oo06n0TQ7u9o3DNcpqgMR4M5WVf59hJOq6Yz2Yd+sa869555z4BU5tQfUo+vD4fdncCmiEiW7lBhhAhOBSb0lsidtX5OKMdoxUf+DSmRv4QX1qOVaUy0B1yAAc0MaPNSjxsaApIQawhqee6pdRP0rUrYy8Gw1VD5+gxCtd6hHf1ln/Pc8W9lKT342VfATrF1MyulM5st6dYs/X2+295vTqQgxgytrUI9GzrkikuOaqg7zZhiwasSIa01BUyoEYe0JZl2C4NRURfP0Pt/45CDpnlWsrghmEh1LZFRSmfKgImxfDpnFItFNrpdLefnsX9EzBNSz8k3MU7srPdmrfRxmO5mrye921u1W3o12NweV8uASHYI/QEgWFnF+s06Fl89+t8v90Cc1RUAl2kLYW6em048bGNU8pQc/h0WZaJ7+6wzqkZqTRyValJymZWxxXmY1WXDpF+zF4PuHYjOpNPqw/2DSw0n79f+Q/k7pR+ugWN+gHhEKzNQd4JFRgXlnFFZNLbEQtRiBatkyikq08i5ZN/s5FmuXYHdW7QO/66AfbQKd5pB3+lvksG2CN7NOxbvBlFSkqgnJoDkd5lR8BWMD6AR5iW2Yz/1+gjDBFtAnO8Ev8qzmEMClYqPSY/GHio+oR1J1miqppFJC6xEaAiMxRAnSGhBGgOHMtIZLbgSXRAuuBsqNaugw5goqEeSQFUuuB9WNrBs6THndYC6ZxB0FgrlgQzt0YyO0/CBucT9lnNId4WBqLGE0mEuqsOR1jU3dqJaJsW3ZeKHTORCUZNUvQ/hnBHPO0pdTtN92N/B8uscLT2FMB0ZQzDjNPCXFnWxaPLTdIAfRQbPwXHkX/ZuQ3yAMPtqUH5E76+xeTT8feXfmFoKD6cKdO6uDj35MxTmWxQe/vs4uv2LFEtHv1uF/l2DceP0EocjBUtZdmHk8Ho8/AAAA//8DANuwUiYMBQAA

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUTW/cNhCG/4rAsyjzS/zQzbBb1HVTL+JFWvQ2JEe2EK20oKhNA2P/e0DtBol7600Y6J0ZPvPOvJEJDkg6cns8/nLCKS+kJnnYQoIJTZmmTO6Z65jpJGu4skwY9w+pyfCIX0lHjAqBB4dUokaqImupl32gMaLjjEcmWlVywstCujcCQxPxNARs5uUTpmWYJ9KRv4Ypzl9KbRiaMM5rbNI84sO0ZJhCaebPh7tH+sftbv+0u/y14FLEzRBJR3qlFDCnqORgqWq9p9DqnsrAMXCuNRPmIhumjGmCsVni5x/145wnzKETjZANo8KRc00iZCgte1hw//VYutgQ3Zd4vYW3z+6NnDCRTtTfYV7S3YRxuMnzccQTjkdIC6abMB8OMEVSk2Oaj5jygBuW7aXjCHmYp+pa7G4ccMqkJk/P1W6E3M/p8I7V8wXBw/8gcMLkSUda3XqUvRXaa4jgpO05oHQxeKlbtN5Ei8ZIISG0gVkeuOEtONO2RkvBSU1extnD+Puy8XOCeRuZEVqgQieU1i4wlBb71iCLoLXXNrgorRHKRivBAXDn0QSnQzHIBwivw4TVwz3pCOMoorRIe8E1VTYChVY6qrXUPfLgzNbD3TzlYVrndakepowvaeNHOvIrjAteyN2m8DpkDHlNBerfuhTbpTmuIVc/HMBZwxrJWBGt+bjm6iPGIWHIWPDu03rN9x+J0GIT3a0p4ZSrHeTX6jdYXgsVsIGDK0/VIfTYMuxZZKCZiaijxqhENFE5FbVyLGgFnqsILfd9iZCaYDFctXncYXDRy5aythdUKTTUe6upNRpYtMCNNe84Vk9j0UGwTGGU1GEfqXIcqFNS0ihbMEL3xoj+JyRX83FWAEc8XbZ160DHaDFqToXiLVXOcWpda6g31juvLbah9PyIacLxJ1AfhpDmZe5zdfVu9Q7dx3UqF6fafPxlmOi/24zu5/AZU1VmDMNUFuw61nNNDgjLmvCwHazujezKdlX77W4J3WinVE2eM6S8Hq9hqRujLT+fz+dvAAAA//8DAAhT0Xb1BAAA

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUT2/cNhDFv4rAsyjzP0XdDLtFF27qRbxog95G5DAWopUWFLVpYOx3L6jdInFvuQkDveHjb97wjUxwRNKR+9PplzNOeSE1ycNWEkwYygxl8sBcx2wnWcNbZbV2f5OaDE/4jXTEKu+5d0glGqQqME17GT0NAR1nPDChVekJnxfSvREYmoDnwWMzL39iWoZ5Ih35a5jC/LWcDUPjx3kNTZpH3E1LhskXM3/sHp7o7/f7w/P++teCSxE3QyAdiUopYE5RyaGlSvc9BW0ilZ6j59wYJuxVNkwZ0wRjs4Qv388Pc54w+040QjaMCkcuNQmQoVjuYcHDt1NxsSF6LPV6K2+f3Rs5YyKdqP+DeW1358fhbln7Ec84niAtmO78fDzCFEhNTmk+YcoDbljOmPp5GXIhKvreSyOcUkq1MUQbDRqjnYkgdRSM8dBrJXvXCo6tMYDKe4hGCQjOcE1qsoEbR8jDPFU37w/jgFMmNXl+qfYj5Din4zv0L1eiu58AWmyTjmije5SxFaY3EMDJNnJA6YLvpdHY9ja0aK0UErz2rOWeW67BWa2tkYKTmnwA/zpMWO0eSUcYRxFkizQKbqhqA1DQ0lFjpInIvbOb5mGe8jCt87pUuynj57Tdl3TkVxgXvN70PvnXIaPPayoQPpkSxn2aw+pz9T0AnDWskYwV0ZpPa64+YhgS+owFxyGtt37/kwgjNtHDmhJOudpDfq1+g+WVdMRB6zk4cADG+4iaYWSBgWE2oAkGgxLBBuVUMMoxbxT0XAXQvI+lQmqCJW/VFnHXIyBGRq12nirnLXWCSYqaxT5E3zLw7zhWz2PRgW+ZwiCpwxiochyoU1LSIDVYYaK1Iv6A5BYWzgrggOfrsm4OTAgtBsOpUFxT5RynrdOW9rbtXW9a1L54fsI04fgDqA+DT/Myx1zdsla9Q/dxncqDU225+zpM9J9tRo+z/4KpKjOGYSr7dRvrpSZHhGVNeNzeq+6N7MtyVYft2RKmMU6pmrxkSHk93crSNNa0/HK5XP4FAAD//wMApDY/gfQEAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACoxUS2/jNhD+KwLPokJKFCUK6MFwdlEjm42ReNuiN4ocxkRk0qAoZ4NF/ntB2V472x56E0bz+h7DH8jJHaAOLfb7TwdwcUQ5inYOlaTkmHBMqg0RHWm6ihRt3VS8Kf9GObJ38IY61DClqBKAK+CAmSY17iujsNYgKKGalDVLPeXziLofSNpCw8EqKPz4B4TReoc69Kd12r+m2dIWavCTLoIfYOXGKJ1Ky3xdLe/wl8V687A+Zo0wpuLCatQhwxiTRDBcUdliVvc9ljU3uFIUFKWck7I5llkXITg5FKN+uczXPjqIqiuLsioILgV6z5GWUaaVeznC5m2ftpgpuk3xfA7Pn90PdICAujI/k3lsd6MGe7Mb+8kO+ibK8AzRBLmDVx9e4CAHlKN98HsI0cLMzcNTdlmJkoIUJS8JQTm6l2prHWSr2+xhSIClagkDXWEBRmMmqMSCVRXWVS2bkpumKQ3K0R0EB8NV13urgh+9idmJ8uzDnKV30brJT2O2chGeg4zHus9yGAHlaD31gx23jyD128Y/Tumfm4aEZTmFAC5maxm32e9y3KIOCdkqKoUUUnKlDNQEDNFEctJo4JqDZqVuNBNMcyaI4kz2lGlZ096kCMrRwxT3Uzzz//1qiU2wux3oywabmeP1IKPxYbfS4KI1NklzzpgNNQwzquzUczlYcPEDyahDhEKpqxawKSnHrNUSy7oSmPOKG6BKNCU9Embs8/STJ2KMZpWp25b3oqcEStO0jDSmJ1qZSgld99CUDWlaaIUipK8ZbXuhiAZaM53QBa8nFX+1QjUL9Di5dJ3ZKsF+tQ5/5+zCyDr46JUfLoD/pdfS7/Z+tDEhNydRv41w7136e7r8j8ULHy8xSBeQzUfHpGa9YoAVJQIzAjVuRUuwVr2o2jrp2qMc3Xr1AiFL1pLWzWqc3fTwlC2C2toIKk4hTf5rhnMU8vP5WC5MFF8/bZY+wGK/z0/R3w6JnmOzs/QfXpRvY0rf+jGhiGG6ctATDOa815WPNByOb5RNQa51C5pTXDJaYyYExa2oG9w3bS963kKtLj7NHkHbACrO/TbHaSdi/8uQixCtkSqO6Wq+eDX76GTMU8qvS16p9rP6OPxKuZOHTp0oSV59Or6Ys3X+14P5/v7+/g8AAAD//wMA9GOVPyEGAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRVTW/jNhD9KwKvtbT8kChKwB5Sx9sa28RBbHSL3kbkKGYjkwZFZTcN8t8LSXbj7KKHXiRqSM48Pr55eiEODkhqcnU8rp7QxZ4sSLRTiFMuUypTKna0qmlZC5ZRrpjKiz/JgtjP+ExqUuZaM11hKlBimhtapI1odWoMVowyQ3mRjznhoSf1CwGbGXyyGjPf/46ht96RmnyxzvivY22wme78YLLgO1y7PoLTI5jb9fJz+tvV3W5zN6/qsR83Z9aQmrR5ngOt8lQwUGleNE0KhWxToRlqxqSkvJy3WRcxOOiy3jy+1Tc+Ooy65hkXGU15RV4XxECEEXIDPe6ejyOKiaLrMb6YwtOwfiFPGEjNF2cy53QfdGc/HPpmsJ35MD3JghyDP2KIFic2NtvkDQSjGc245JSSBbkBvbcOk/V1sunGI4JWNEcj0gpbk+YVg7TKhUiNKKDksi1L3pIF+YzBYXeR9cbq4HvfxuREcvKuzvZquXLQdDjW+ARdj2RB1v02gjPQeYerb6iHOOfahWGcXnoXrRv80CdrF/EhwGn+vH85hIAuJncQ98mv0O9JTSpQmkEFFYDUusWCYksNBUlLg9JINDk3pcmr3Mi8olrm0LDcQMGadoyQBfl55HA7aI19f4l2VEnXTSCS00UtO4suvuOR1IQy5EYoTFvOZJorAykUokqlFLJFpquSs3OdHYQHjKQmhSwaFK3ispFgoBKqZYCiMroRskDVlEZhWQouQBeaKqZZyQqoyqIopZgS3gVvBh2/v2sx3cBd8H+hjiNXpCaipMB5aRiYXBWCKsWhKvKmUK2UpmlBy0pX2Oi2BVGaEhvFuJCMlkyJSqoz/JV7sA6vbX/s4PmirspkJn7SAIq18MbqvPxTgAN+9eHxdtZxdrvakQW5H9xoCcl61MhX69Jvcmzpm6GLdrcPCAbNjTf4o5Bw7JdkalHOheJU6ZQXSoz6lWlFyyYtZSFaU1JjKk0W5NrrRwzJKDGwbmyrf5NttslV0HsbUcchjPj+mHBstsldB7H14fDOSi4O9j0BGReMcrIgBp9mO5owSmMUGslSnrMizauKpaoqyrQpVVM1UmGhR8Y2QzwOMblHYwPqOJ341BqfwHZDwCVEfPBh9MdN3GM4o1nuUT/+SNNZHyfxMjqKZjsb3Pp/+NsqBB+WfhhtvL78WrvWJy/J0h+OtsOQfEwWyU0/QfoFHQboLkOrJ+iGuZ0uo2cjeLc7wHE/BXbQP06DrXm8x953Txj6KXCLcWvmudvhF4zT6I2OeQKifcKd953eg51LLL3BKwfdc2/nRPfwt5+xfzm20/uqP96eEk48Jx8TlryO5n1A6IeAh+mXVr+QtXMYpqLXw+xXa3dju872qL0zPakVyzNV5vnpqv5zWUkzmfPy9fX19R8AAAD//wMAv9ZPsz4HAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRTS2/cNhD+KwLPosy3RN2MdYou3MSLZJEWvY3IUUxYphYU5SQw9r8H1G7gpLdeCGLAmflefCURnpH05PZ0eveCMS+kJjlsJcGEocxQJo/M9qztJW+YUEq35l9Sk3CP30lPWuUcdxapRINUeabpIEdHvUfLGfdMaFVmwpeF9K8EQuPxJThs5uUzpiXMkfTk7xD9/LXshtC4aV59k+YJ93HJEF0B82G/u6d/3R6OD4fLqwWX0twET3oyKqWAWUUlh44qPQwUtBmpdBwd58Yw0V7aQsyYIkzN4p/e9vs5R8yuF42QDaPCknNNPGQokAdY8Pj9VFBsEt2Ver2Vt2v/Sl4wkV7UP8W8jLtxU7h5XoY1TP7mcmZYngrLU5pPmHLATZON5jRBDnOsrpt2U8CYSU0ePlWHCfI4p+ffhPp04b//H/SPZfu7b+jWjH43rzEX/xipyXtwjyFitb8jPWEchZcd0lFwQ1XngYKWlhojzYjc2VZwUpPdHHOI67wu1T5m/JI2/KQnf8C04AX5bXKPIaPLayqk/jElCoc0+9Xl6k1+zhrWSFaQPKz5tObqI/qQ0GUs9I5pvc77T4swYmvarSlhzNUB8mP1JyyPpCcWOsfBggUwzo2oGY7MMzCs9Wi8Qa+Eb72yyhtlmTMKBq48aD6MpUJqgsXtaguYMpIPppVUGtBUDVpQi3qgoxNacS61FiUTbzpWD1PpA9cxhV5Si6OnynKgVklJvdTQCjO2rRh/keRqPmdFYI8vl6+yITDed+gNp0JxTZW1nHZWt3Rou8EOpkPtCuZ7TBGnX4R6H1yal3nM1TU71W/SfVxj+e7VlqOvIdJvm0d3s3vCVBWPIcSS7qut5/P5/AMAAP//AwCRcyO5NQQAAA==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRTTW/UMBT8K5HP69RfceLcqi2IVYGuaAWIm+P3wlqk9spxCqja/46cXVTgxi0aZebNm3l+JsE+IunJ9fH46glDnsmGZL9CgglNmaZMPjDTs7aXvGaiER1TX8iG+Fv8SXrSKue4M0glaqQKWEMHOToKgIYzDkw0qmjarzPpn4n1NeCTd1jH+SOm2cdAevLJB4jfy2zrazfFBeoUJ9yFOdvgipn3u+0tfXu9f7jbn/+acS7k2gPpyaiUsswoKrntqGqGgdpGj1Q6jo5zrZlozzQfMqZgp3qGby/zIeaA2fWiFrJmVBhy2hCw2RbLg53x4eexuFgjuin4ZoXXz/6ZPGEivdj8DvMsd+Umf+Xi46MNcDX64OcD2ZBjikdM2eMax7rhNNnsY6guQ7aTx5DJhtzdV/vJ5jGmx78yuj+vvvuPzd9Zd/ABq90N6QnjKEB2SEfBNVUdWGobaajWUo/InWkFJxuyjSH7sMRlrnYh49e0uiQ9eW2nGc/+rpM7+IwuL6lY/6xL1/jD522EAhSdfYqwuFy9xM1ZzWrJWNFY8nHJ1QcEn9BlLDs9pOUi/w9FaLGStktKGHK1t/lQvbHzgfTE2M5xa6yxVjs3YsNwZMCsZi2gBo2gBLSgjAKtDHNa2YErsA0fxoIU36Xdaj0oq6HVAoHyFgeqpOnooMxAOzZKaKTRXBeLL7FWd9PKcx1TCJIaHIEqwy01SkoKsrGt0GPbivGPSC6Nc1ZyAnw6P43VgQboEDSnQvGGKmM47UzT0qHtBjPoDhtXPN9iCjj9EdQ771Kc45iry8FUf0X3YQnleVfr8Xz3gf5YK7uJ7humqlRufSjXfGn5dDqdfgEAAP//AwDbxUFEJQQAAA==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRUwW7cIBT8FYuzcQBjbHyLNo26Stus2lVb9fYMzwmKg1eA00bR/nuFd6s0p6oXhJ6Zx7yZwS/EwyOSnlweDu+e0KdISpLcWhJMKMoUZfWe6Z61fc0rJgTjXP8gJXE3+Ex60kpjuNFIa1RIpWUNHerRUGtRc8YtE43MPeEukv6FgKssPjmD1Ry/Yohu9qQn35y38898N7jKTPNiqzBPuPUxgTeZzKft5oZ+uNztb3enUxFjBlfOkp6MUkpgWtKaQ0dlMwwUGjXS2nA0nCvFRHuCOZ8weJiqaB9e77dz8phMLypRV4wKTY4lsZAgUx4g4v75kFmsEl3lermW123/Qp4wkF6Uf8Q8tbswk7t4jMPiJntxWhPEh7iuI5g0h2dSkkOYDxiSw1WfyxjxcZie9xAfrk9n8ja++4VmSWg38+IT6YmqSUlWfaYJkpt9caa4mRz6tH5MwfnozL9aZWVuvxS7CdI4h8c3dnw5qbz9D5E/grl3HovtFekJ4yhs3SEdBVdUdhYoNLWmStVqRG50KzgpyWb2yfllXmKx9QnvwjoS6ck1TBFP/C6DuXcJTVpCnvO7yrHahdkuJhWvVnJWsapmLIOWdFhS8RmtC2gS5iH2YTn3+/oWIpRYQZslBPSp2EG6L95DvCc90dAZDho0gDJmxIbhyCwDxVqLyiq0UtjWSi2tkpoZJWHg0kLDhzFXSEkwJ6dYw8rHViq0DbVSCSqZkBTqbqRK2ZZJI0GP2dxXHYvbKePAdEyiranG0VKpOVAt65rauoFWqLFtxfiXJOc8cJYFtvh0enYrA2Vth1ZxKiRvqNSa0043LR3abtCD6rAxmfMNBo/TX0J9dCbMcR5TcU5I8Ua6z4vPv45iTctP5+mv1aOr2TxgKLLH4Hx+KWdbj8fj8TcAAAD//wMAk61HJIEEAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUTW/jNhCG/4rAs6hQFEWJuqVOFzWy2Rgbd1v0NiJHDhGZNCgq2yDwf19QdhBnFz30Joz4zsczL/lKHOyRdOT6cPj9GV2cSE6iXUKccUmZpKzaMtWxphOskKKquGT/kJzYW3whHWmE1qVWSCuUSIVhNe2rQVNjUJWsNIzXIuWE3US6VwK2MPhsNRZ++oZhst6RjvxlnfHfU22whR79bIrgR1y7KYLTqZkv69Ut/Xy92d5vTqcmnJK4sIZ0hMm6kbrmVBuFVNRS0haloYKV2pQN9Iqpk8y6iMHBWEzm6b2+8dFh1B0veFUwyhU55sRAhNRyDxNuXw6piwXRTYrnS3j57F7JMwbS8fwN5indlR7t1X7qZzuaq9HvdtbtVt4NdjcHiKlwTg7BHzBEiwuc36yD8PLZ73YpH/kE44QkJ1sMe+tgPP24wQHmMT74OSxkJvP0X2dIR2COnuRkITmOS9nsPMxqtOjiL9qLwvcP2WaEOPiw/7CkhxP79f9Afwf60TrM1jdJUyI3VYt04KWkojVAoa4UlbKSA5ZaNbwkOVl5F62b/Txlaxdxd6b2ob/roB9tRB3nkGb6WyazbYI3s47Z+4JLVrCiYiyJ5niYY/YVjQ2oI6YhtmE+5/tJwiVfRJ/siL/gWc0hoIvZBuJj9gdMj6QjClpdggIFILUesGY4MMNAssagNBKN4KYxQgkjhWJaCuhLYaAu+yFFSE4wmSxbfF0L0DAAUlNJSYVmDYWWM2q4qnXbt2D64QPc7H5MOtAtE2gqqnAwVKgSqBJVRU1VQ8Pl0DR8uOB0NkTJEvVLE/45oTl76cvJ2m+zG3w+3eOlT2lMi0aWlIuypkKpkraqbmjftL3qZYu1TpOtvJv8G8hvGHo/2ZgekTvr7B7Gn4+8b+YWg8PxYjt3Vgc/+SFmZ1tmH/b1dXbpFcsWi363jv67GOPG6ycMWTIWWHexzOPxePwBAAD//wMATqNAzAwFAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACoxUTW/jNhD9KwLPpkJKFCUa6MFwdlEjm42ReNuiN4ozjInIokFRzgaL/PeCsr12tj30Jozm4703b/iD9HqHZE4W+/2nA/ZxIDMS3RQqWCEpk5SVG6bmrJ4LlqtK8FI2f5MZcXf4RuakFsZwo5CWKJEKYBVtS2soACrOOLCiEqmnfh7I/AfRLgc8OIO5H/7AMDjfkzn50/XgX9Ns7XLT+RHy4Dtc9UPUvUlgvq6Wd/TLYr15WB+zBhxSce6AzAmTVS1NVVADCqmopKQNSqCCcQO81q1i6ljm+oih110+wMtlPvjYYzTzIi/KnNFCkfcZAR11gtzqATdv+4Rikug2xWdTePqc/yAHDGRezM5iHtvdmM7d7IZ2dB3cRB2eMdqgd/jqwwsedEdmZB/8HkN0OGnz8JRdIHGWs7yQBWNkRu612boes9Vt9tAlwto0TCCUVKEFKhTXVImypFBWui6krevCkhm5w9Bjd9X13pngB29jdpI8+zBn6fvo+tGPQ7bqIz4HHY91n3U3IJmR9dh2btg+ooa3jX8c079+7BKX5RgC9jFb67jNftfDlsyJ0o3hWmmltTTGYsXQMmBashpQgkQQBdQglAApFDNS6JYL0BVvbYqQGXkY436MZ/2/X4HYBLfbIVwQbCaN152O1ofdCrCPzrq0mnPGZKium1hlp57LzmEfP4icHMWxgLJBagsuqWhAU12VikpZSovcqLrgR8Gsex5/6sSsBVHaqmlkq1rOsLB1I1htWwbGlkZB1WJd1KxusFGGsbYSvGmVYYC8EpDYBQ+jib9aoZwW9Dj26TqzVaL96nr6XYqLIuvgoze+uxD+176Wfrf3g4uJuT0t9duA975Pf0+X/7F44eMlhukCsunoFGt5Ky3QAkqggitGNXBGoQKsoKhlrRLkW29eMGTJWtr10zbObnp4yhbBbF1EE8eQJv810Tku8vP5WC5K5F8/bZY+4GK/n52ivx2SPMdm59V/eFG+DSl964d4RflE7Qk7ewZ2ZSTAw/GRcikoARoEyWkheEWFUpw2qqppWzetamWDlbkYNXtEcAFNnPptwpimnZT9L0cuQnRWmziks/nizWSkkzNPKb+CvFrbz+rj8KvVnUx06sRZMuvT8cmcvPO/Xsz39/f3fwAAAP//AwBL4gnFIgYAAA==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSU227cNhCGX0XgtSjzfNCdYbeo66ZexIu06B3FGdlCtNKCojYNjH33gNoNEveud8JA/xy++YdvZAoHJC25PR5/OeGUF1KTPGwhwYShzFAm98y3zLaKNVo774z8h9RkeMSvpCVWxcijRyrRIFXANO1kHykAes44MKFVyRleFtK+kTA0gKchYjMvnzAtwzyRlvw1TDB/KbXD0MRxXqFJ84gP05LDFEszfz7cPdI/bnf7p93lrwWXIm4GIC1hRlsTtaARPFKljaEODVDFeARuQ+eZv8iGKWOawtgs8PlHfZjzhDm2ohGyYVR4cq4JhBxKy11YcP/1WLrYEN2XeL2Ft8/2jZwwkVbU32Fe0t3EcbjJ83HEE47HkBZMN3E+HMIEpCbHNB8x5QE3LNuk4xjyME/VtdjdOOCUSU2enqvdGHI/p8M7Vs8XBA//g8AJU0daIpmWxlpUUsrgTScYgjXRGNHFwGzfCeQRmfbKem4Zl14wL7WxzkJgPpKavIxzF8bfl42fF6xzwKwwAhV6oYzxkaF02GuLDIIxnXHRg3RWKAdOBh8C9x3a6E0sBvkQ4uswYfVwX6bhKEA6pL3ghioHgQYtPTVGmh559FZwUpO7ecrDtM7rUj1MGV/Sxo+05NcwLnghd5vi65Ax5jUVqH+bUmyXZlhjrn44gLOGNZKxIlrzcc3VR4QhYcxY8O7Tes33H4kwYhPdrSnhlKtdyK/Vb2F5LVSCizz4MqqJsUfNsGfAgmEW0IBBUAIsKK/AKM+iUaHjCoLmXV8ipCZYDFdtHu8tOGRBUs1YpAoDo05xT5V2PWjGRQB4x7F6GosuRMcUgqQee6DK80C9kpKC1MEK01sr+p+QXM3HWQEMeLpc69aBAXAIhlOhuKbKe06d15Z21nW+Mw51LD0/Yppw/AnUhyGmeZn7XF29W71D93GdyotTbT7+Mkz0321H93P8jKkqOw7DVA7sutZzTQ4YljXhYXuw2jeyK9dV7bd3S7hGeiZr8pxDyuvxGpa6Uc7r8/l8/gYAAP//AwBRUmUl9QQAAA==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUTW/cRgyG/4owZ4083x+6GXaLLtzUi3jRBr2NhlQsRCstRqNNA2P/ezHaLRL3lptAiOQ7D1/yjUzhiKQl96fTL2ec8kJqkoctJJgwlBnK5IH5ltlWscYwY7jzf5OaDE/4jbTEqhh59EglGqQKmKad7CMFQM8ZBya0KjXD54W0byQMDeB5iNjMy5+YlmGeSEv+GiaYv5beYWjiOK/QpHnE3bTkMMUi5o/dwxP9/X5/eN5f/1pwKcnNAKQlzGhrohY0gkeqtDHUoQGqGI/Abeg889e0YcqYpjA2C3z53h/mPGGOrWiEbBgVnlxqAiGHIrkLCx6+nYqKDdFjiddbePts38gZE2lF/R/Ma7m7OA53y9qNeMbxFNKC6S7Ox2OYgNTklOYTpjzghuWMqZuXIReiMdrgHOfgglXagpNaSAuSIThmNXjwwSjTi6h1D53zVvUKBFdgUKnOkpps4MYx5GGeqpv2h3HAKZOaPL9U+zHkfk7Hd+hfrkR3PwG0yCYtkUxLYy0qKWXwphMMwZpojOhiYLbvBPKITHtlPbeMSy+Yl9pYZyEwH0lNPoT4OkxY7R5Ld44CpEPaC26ochBo0NJTY6TpkUdvBSc1eZinPEzrvC7Vbsr4OW3vJS35NYwLXl96n+LrkDHmNRUIn0wx4z7NsMZcfTcAZw1rJGMlac2nNVcfEYaEMWPBcUjrrd7/UoQRW9LDmhJOudqH/Fr9FpZX0hIfXOTBBx+CibFHzbBnwIJhFtCAQVACLCivwCjPolGh4wqC5l1fIqQmWPxWbRbnSoFzzFLJdEdVFxztugAUle95X4gqfMexeh5LXoiOKQRJPfZAleeBeiUlBamDFaa3VvQ/ILmZhbMCGPB8XdZNgQFwCIZTobimyntOndeWdtZ1vjMOdSyanzBNOP4A6sMQ07zMfa5uXqveofu4TuXgVJvvvg4T/Web0eMcv2CqyozDMJX9uo31UpMjhmVNeNzuVftG9mW5qsN2toRrpGeyJi85pLyebmGpG+W8vlwul38BAAD//wMAv7X+fPQEAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUQW/cNhCF/4rAsyiTEkWJuhnrBF24qRfJIi16G3FGMWGZWpCUE8PY/15Qu0Hq3nohiAHf8PGbJ70xD8/EBnZ7On14IZ8iK1lyW6kWteZCc9EchRlENyhZCSN6bdq/WcncPb2ygXXKWmkN8YY0cYWi5WMzWY5IRgqJom5V7gnfIhveGLgK6cVZqpb4lUJ0i2cD+9N5XL7nu8FVdl5WrMIy097HBN5mM3/sd/f899vD8eFwORUpZnHlkA1M6LbTtq25RUNctVrznjRyJaRF2cFohLnInE8UPMxVxKdf9+OSPCU71FXdVILXhp1LhpAgWx4h0vH1lF1siO5yvdzK23Z4Yy8U2FCXP2Fe2t3Y2d08x3F1M95c1gTxKW7rBDYt4ZWV7BSWE4XkaONzGyM9j/PrEeLTx8uZvI0ffpBdE+FuWX3Kw9GsZBufeYbkFl9cLe5mRz6xkj18KQ4zpGkJz+8If7mA2/8Pbp/APjpPxf4uayTV2PTEp1pqrnoEDm1juNaNnkha09WSlWy3+OT8uqyx2PtE38Lmkg3sI8yRLv5ug310iWxaQ7b+l85JOYQFV5uKX9ORohJVI0QWrem0puIzoQtkE+VHHMN67fcfSa3rTbRbQyCfigOkx+I3iI9sYAZ6K8GAAdDWTtQKmgQK0KJD0qgJVY0dKqNQKyOsVjBKhdDKccoVVjLKYSi2/GndKTGS5K0G4GrsJj5aMfHWdL1RBJOqp3cci4c568D2QhE23NCEXBkJ3Kim4di00NV66rpN9xPJdcRSZMBIL5cv6eIAsSfUktdKtlwZI3lv2o6PXT+aUffU2uz5noKn+V+gPjkblrhMqbgmpHiH7vPq89+g2NLy3Xn+Y5vR3WKfKBR5xuB8Dv91rOfz+fwPAAAA//8DAIvqMrtUBAAA

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRVTW/jNhD9KwKvtbT8kChRQA+p42yNNE4QG92itxE5itnIpEFR2U2D/PeCctIku+ihF4l6JGceH2eenoiDA5KWnB2Pqwd0cSQLEu0MccplTmVOxY6qltZtyQqqZCWr5k+yIPYSH0lL6lJrphXmAiXmpaFV3ole58agYpQZyqsyxYS7kbRPBGxh8MFqLPz4O4bRekda8sU647+m3GALPfjJFMEPuHZjBKcTmc16eZn/dnazu745rRpxTJsLa0hLqKxqqSuea6MwLysp8walyUvKtGE1dIqq0zbrIgYHQzGa+7f8xkeHUbe84KKgOVfkeUEMREiUOxhx93hMLGaJzhO+mOF52D6RBwyk5YtXMU/hPunBfjqM3WQH82l+kgU5Bn/EEC3OalxvszcSjBa04JJTShbkCvTeOszW59n1kI4IuqElGpEr7E1eKga5KoXIjaig5rKva96TBbnE4HB4F/XK6uBH38fsReTsQ57t2XLloBsw5biAYUSyIOtxG8EZGLzD1TfUUzzF2oUpTS+9i9ZNfhqztYt4F+Bl/nX/cgoBXcxuIO6zX2Hck5YoaDQDBQpAat1jRbGnhoKktUFpJJqSm9qUqjSyVFTLEjpWGqhY1yeELMgvScPtpDWO43u2qUqGYSaRvVzUcrDo4gcdU5kw5EY0mPecybxsDORQCZVLKWSPTKuas9c8Owh3GElL+qbrOqp1x0vFNHAFwvRUGNkrzusayl5UdcmlrGgN2tQ1Z6URNWoQvaANJwtyE7yZdPz+rsV8AzfB/4U6Jq1IS0RNgfPaMDBlUwnaNBxUVXZV00tpuh60VFphp/seRG1q7BrGhWS0Zo1Qsnmlv3J31uG5HY8DPL7L2xSyED9pgIb18KbqaflFgAN+9eF+c6rjYrPakQW5nVyyhGydauSrdfk3mVr6ahqi3e0DgkFz5Q3+WEiY+iWbW5R3otMaRF7XAvKyqkXeAYNcAAWtWc+rWapzr+8xZKnEwLrUVv8Gu95mZ0HvbUQdp5D4/THzuN5mNwPE3ofDByt5d7DvBSi4YDSlM/hwsqOZozSmQSNZzktW5aVSLG9UVedd3XSqkw1WOil2PcXjFLNbNDagjvOJX1rjAuwwBVxCxDsfkj9uVrvt+eUrneUe9f2POr0WyEv1MprKcHtyuPX/MLhVCD4s/ZR8vH3/tXa9z56ypT8c7YAh+zlbZFfjTOkzOgwwvIdWDzBMp356j746wYfdAY77GdjBeD8Ptub+Fkc/PGAYZ2CDcWvSHFtkm+kzxhl90+O0CKJ9wJ33g96DPeVYeoNnDobH0Z4i3cLf/kT+y7Gf32fjcfMS8Dru55Nlz8m9DwjjFPAw/9PaJ7J2DsOc83w6GdbaXdlhsCNq78xI2lKKQnBav1zVfy2reFOwiqvn5+fnfwAAAP//AwAe2YZzPwcAAA==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRTS2/cIBD+KxZn4wDG2PgWbVJ1laZZJau26g0z4yyKg1cY56Fo/3uFd6skvfWC0Ihv5nsMb8SbRyQtOd/vL5/Qx4nkJLqlJJhQlCnKyi3TLatbyQumy5JX4jfJibvCV9KSWlrLrUZaokIqgVW0K3tLAVBzxoGJSqae5n4i7RsxrgB8chaLcfqBYXKjJy356TyMz2m2cYUdxhmKMA649lM03iYy39erK/rtfLO92RxfTTglcOGAtISpqla2EtSCRiorpWiDCqhk3AKvTaeZPsKcjxi8GYoJHt7nwxg9RtuKQpQFo0KTQ07ARJMod2bC7es+sVgsukj1fCkv1/aNPGEgrcj/mnlsd2YHd/Y4dbMb4Ox4RjM9JJX7MO4xRIeLJ4vMYTDRjT47TVoNDn0kObm5yzaDif0YHj8ZdXfUv/4P+ds0/fIF7RwRVuPsY0pZkZxcG7tzHrP1RerGUUDZIO0FV1Q2YKipSk2VKlWP3OpacJKT1eij8/M4T9naR7wPC3/Ski9mmPDI/DzYnYto4xySqF8qrcImjDDbmL3bz1nBipKxBJrjfo7ZLYILaCMmedswn/r9AxFKLKDVHAL6mG1M3GVfzbQjLdGmsdxoo41R1vZYMewZMKNYDahAIUgBNUgtQUnNrJKm4xJMxbs+VUhOMKWdLQsmUKtai55aoSWVVc9op3RNe1tWsuF13WjxycfsZkg4YxsmEUqqsQcqNTdUy7KkUFamFqqva9F/sOQUPmfJYMCn41dZGCiABkFxKiSvqNSa00ZXNe3qptOdarCyifMVBo/DB6OunQ3jNPYxO+1O9sm629mn754te/TsPH1ZMroY7QOGLGVsnE/bfYr1cDgc/gAAAP//AwB2v0bKNQQAAA==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUTW/cRgyG/4owZ408X5oP3Qy7RQ039SI20qI3akjFQrTSYjTaNDD834vROkjcW28CIXJePnzJFzbDkVjHrk+nX84055XVLI97SAllubBc6CcROik65RobWum8/ZvVbLynb6xjzsQoYyCuyRI3KFre6yFyRApSSBSqNaUmfF5Z98JgbJDOY6RmWT9RWsdlZh37c5xx+VrehrGJ07Jhk5aJ7uY1wxyLmD/ubu7579eHp4fD5a+V1pLcjMg65sHbaAC56annRvSKgzaCezkMXrbGKxCXtHHOlGaYmhW//HgflzxTjp1qlG4EV4G91gwhQ5Hcw0pP305FxY7otsTrPbx/di/sTIl1qv4O81LuKk7j1br1E51pOkFaKV3F5XiEGVnNTmk5Ucoj7VjOlPplHXMhGqMD76VED860Dr1ulXaoBaEXrsWAAayxg4ptO2DvgzODQSUNWjKmd6xmO7hpgjwuc/Wm/WYaac6sZg+P1WGCPCzp+A7944Xo3f8AWmSzjmnRauscGa01BNsrQehstFb1EYQbekUykmiDcUE6IXVQIujWOu8QRIisZh8gPo8zVXe3rGNCkkLtiQ9KWm48AodWB26ttgPJGJySrGY3y5zHeVu2tbqbM31Oe7+sY7/CtNKl0+sUn8dMMW+pQPjLFjMe0oJbzNUPA0jRiEaL0tPDlk9brj4SjolipoLjKW1v9f6Toqzak262lGjO1QHyc/UbrM+sYwF8lBAgANgYB2oFDQIFWOGQLFpCo9ChCQatCSJaA700CK3shxJhNaPit2q3uNRWuwiKg5GSm6h67i0Al85q3WOMPbp3HKuHqeRB9MIQah5oQG6CBB6M1hx1C07ZwTk1/ITkzSxSFMBI58uy7gosoie0kisjW25CkNyH1vHe+T701lMbi+Z7SjNNP4H6MMa0rMuQqzevVe/QfdzmcnCq3Xdfx5n/s8/odolfKFVlxjDOZb/exvpasyPBuiU67veqe2GHslzV0362tGyEsG3NHjOkvJ2+h0MjbWhfX19f/wUAAP//AwCh5ahd9AQAAA==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUwW7jNhCGX0XgWVQoiqJE3VKnixrZbIyNuy16G5Ejh4hMGhSVbRD43ReUHcTZRQ+9CSPOzD/f/OQrcbBH0pHrw+H3Z3RxIjmJdglxxiVlkrJqy1RXso43RcMV56z5h+TE3uIL6UgjtC61QlqhRCoMq2lfDZoag6pkpWG8Fqkm7CbSvRKwhcFnq7Hw0zcMk/WOdOQv64z/nnqDLfToZ1MEP+LaTRGcTmK+rFe39PP1Znu/OZ2acErJhTWkIy20UgswVPTYU8F6TqESjLblMLRlLVoO7JRmXcTgYCwm8/Te3/joMOqOF7wqGOWKHHNiIEKS3MOE25dDUrEguknxfAkvn90recZAOp6/wTyVu9KjvdpP/WxHczX63c663cq7we7mADE1zskh+AOGaHGB85t1EF4++90u1SOfYJyQ5GSLYW8djKcfNzjAPMYHP4eFzGSe/usM6QjM0ZOcLCTHcWmbnYdZjRZd/CX3ovH9Q7YZIQ4+7D8s6eHEfv0/0N+BfrQOs/UN6QgrkZuqRTrwUlLRGqBQV4pKWckBS60aXpKcrLyL1s1+nrK1i7g7U/ug7zroRxtRxzmkmf6WyWyb4M2sY/a+4JIVrKhYUnI/x8Mcs69obEAdMQ2xDfO53k8pXPIl6ZMd8Rc8qzkEdDHbQHzM/oDpkXREQatLUKAApNYD1gwHZhhI1hiURqIR3DRGKGGkUExLAX0pDNRlP6QIyQkmk2WLr43UdTm0FW1YX1GhuKSgeqBYNaYyqGrZfISb3Y8pD3TLBJqKKhwMFaoEqkRVUVPV0HA5NA0fLjidDVGyRP3ShH9OaM5e+nKy9tvsBp9P93jRKY1p0ciSclHWVChV0lbVDe2btle9bLHWabKVd5N/A/kNQ+8nG9Mjcmed3cP485H3zdxicDhebOfO6uAnP8TsbMvsw76+zi69Ytli0e/W0X8XY9x4/YQhS8YC6y6WeTwejz8AAAD//wMABJlj+QwFAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUTW/kNgyG/4qhs+Xoy/rwLUhaNE23GWwGbdEbLdGJsR55IMuzXQTz3xfyTLBNb70ZhF+SeviSbyTCAUlHbo/Hn04Y80JqksctJJjQlGnK5J65jrNOmEYrq6Wxf5OajI/4jXTEKO+5d0glaqQqsJb2cvA0BHSc8cBEq0pOeFlI90ZgbAKeRo/NvPyBaRnnSDry5xjD/LXUhrHx07yGJs0TPsQlQ/Slmd8f7h7pb7e7/dPu8teCSxE3YyAdsWC1VxCo6rGnivWCglSMWj4MlrfKCmAX2RgzpghTs4QvP+qHOUfMvhONkA2jwpFzTQJkKC33sOD+27F0sSG6L/F6C2+f3Rs5YSKdqN9hXtLd+Gm8yfNxwhNOR0gLphs/Hw4QA6nJMc1HTHnEDcv20mmCPM6xuha7m0aMmdTk6bnaTZCHOR0+sHq+IHj4HwROmHrSEclaqY1BJaUEp3vBMBjttRa9B2aGXiD3yFqnjOOGcekEc7LVxpoAzHlSk5dp7mH6ddn4OcF6G5gRWqBCJ5TWzjOUFofWIAugda+td0FaI5QNVoID4K5H4532xSCfwL+OEauHe9IRxlEEaZEOgmuqbAAKrXRUa6kH5N4ZwUlN7uaYx7jO61I9xIwvaeNHOvIzTAteyN0m/zpm9HlNBepfuhTbpTmsPlc/HMBZwxrJCqOnNR/XXH3GMCb0GQvefVqv+f4jEVpsors1JYy52kF+rX6B5bVQAes5uPJU7f2ALcOBBQaamYA6aAxKBBOUU0Erx7xW0HMVoOX9UCKkJlgMV20ex4IU5EAtKk5VKxi1zGqqHfOSYVDKDR84Vk9T0YG3TGGQ1OEQqHIcqFNS0iBbMEIPxoiie0dyNR9nBXDA02Vbtw50CBaD5lQo3lLlHKfWtYb2xvau1xZbX3p+xBRx+heoT6NP8zIPubp6t/qA7vMay8WpNh9/HSP9Z5vR/ey/YKrKjGGMZcGuYz3X5ICwrAkP28Hq3siubFe13+6W5A1juq3Jc4aU1+N72DVcu/Z8Pp+/AwAA//8DANkq8Dj1BAAA

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSTwW7cOAyGX8XQ2XIkWZYt34JJFzvIthm0g+5ib7RIN0IceSDLaYtg3r2QZ4o2e9uLIBAi+f8fqVcW4JlYz25Pp3cvFNLCSpb8FlJCGS4MF/VR2F6KXnVVq422TfsvK5m/p++sZ612TjpLvCZDXKNo+FCPjiOSlUKiUI3ONeHLwvpXBr5CevGOqnn5THHxc2A9+9sHnL/m3uArN80rVnGeaB+WBMFlMR/2u3v+1+3h+HC4vFpoycmVR9azDjrjNCDXAw1ci0FxqLXgnRzHTja6UyAuaT4kigGmasGnX/1xToGS61Wl6kpwZdm5ZAgJsuQBFjp+P2UVG6K7HC+38HbtX9kLRdar8ifMS7kbN/mb52VY/YQ3lzPB8pRdnuJ8opg8bUw2m9MEyc+huHbaTZ5CYiV7+FQcJkjjHJ/fgPp08b//H/aPufu7b+TWRLib15BYz2TdsZK9B/foAxX7O9YzIUlh3REflTRcdwgcmtpyY2ozknS2VZKVbDeH5MM6r0uxD4m+xM0A69kfMC10kX4b3aNP5NIas6t/TN6FQ5xxdan4xV+KSlS1yCIf1nRaU/GR0EdyibK/Y1yv9f6ToozaknZrjBRScYD0WPwJyyPrmYXOSbBgAYxzIzWCRoECjGiRDBpCrbBFbTUabYUzGgapERo5jDnCSkZ53MW2YUPbDqMQLVfgGq4zHWix49hJa9DV1I1vORYPU84D1wlNWHNLI3JtJXCr65pj3UCrzNi2avwNyXX6UmTASC+Xv7IpMIgdoZFcadlwba3knW1aPrTdYAfTUeOy5nuKgabfQL33Ls7LPKbiujzFG3Qf15D/e7Et0lcf+LdtRneze6JY5BmDD3m9r2M9n8/nHwAAAP//AwD5p65GNgQAAA==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACoxUS2/bOBD+KwLPpkJS1IMC9mA4LWqkaYzE3V30RpHDmIgsGhTlNAj83xeU5NopetibMJrX9xi+o07uAdVoeTh8OkIXerRAwY4hRliBSYFJtiWipqRmVUrzSgia/0ALZO/gDdWo5EpRJQBnUADmmuS4yYzCWoOghGrCch57yuce1e9I2lTD0SpIXf83+N66DtXoH9tp9xpnS5uq1g069a6FddcH2am4zLf16g5/XW62D5spq4c+FqdWoxpVsioUlxrzBhrMScOwzDjBFTWmojmvmCRTme0C+E62aa9fLvO1Cx0EVbOUZSnBTKDTAmkZZFy5kT1s3w5xi5Gi2xhfjOHxs35HR/CoZoszmVO7G9Xam33fDLbVN0H6ZwjGyz28Ov8CR9miBTp4dwAfLIzcPDwll5UoSUnKCkbi4vdS7WwHyfo2eWgjYKkqwkFnWIDRmAsqseBZhnWWy5IVpiyZQQt0B76D9qrrvVXe9c6EZKY8+TBn5bpgu8ENfbLuAjx7Gaa6z7LtAS3QZmha2+8eQeq3rXsc4r9uaCOW1eA9dCHZyLBLvsh+h2okZKWoFFJIWShlICdgiCayIKWGQhegOdOl5oLrgguiCi4byrXMaWNiBC3QwxAOQzjz//Nqia23+z3oywbbkeNNK4Nxfr/W0AVrbJTmnDEaqm1HVMncc9Va6MIHklGNCAWmswqwYbTAvNISyzwTuCiywgBVomR0IszY5+EXT8QYzTOTV1XRiIYSYKasOClNQ7QymRI6b6BkJSkrqIQipMk5rRqhiAaacx3ReacHFX63QjYK9Dh08TqTdYT9ajv8s+AXRjbeBadcGwWzLTy99QH2f1Jt5fYH19sQ8ZtZ2u893Lsu/p3vf+ZsLl66cIlBvINkPD3FlWImp1jSTGGuhMSSEIEBKNECJMlVlPHWqRfwSTSYtN2oydlTD0/J0qudDaDC4OPkf0dQk5yfzydz4SP99mm7ch6Wh8Nijv51jCRNzc4G+PCufO9j+s714QryDO0JWnNe7MpOGo7TU2VjsNC6Al1QzDjNMReC4krkJW7KqhFNUcGEc7Jr8gjaelBh7Lf1Q5w2M/snXy59sEaq0Mfj+erUaKfZn3PK70teyfarehp+Jd1spbkTJdGyT9PDOTrof72bp9Pp9B8AAAD//wMAqlPlEigGAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUXW/cKhCG/4rFtXH4MgbfRZtWZ5XTZtWu2qp3GMYNioNXgNNG0f73CnurNFdH5wahMTO888yLX1Awj4B6dH06vXuCkBOqUfZriBEmMZGY8CPRPSU9U00nuOKafUc18rfwjHrUCWup1YA5SMDCkRYPfLTYOdCUUEdYK0pN8yOh/gUZ3zh48haaOX2BmPwcUI+++uDmn+Vu4xs7zYtr4jzBPqRsgi1iPu53t/jf68Px7rCdSpBKcuMd6pEySlphHBYDDFiQgWHDBcGKjqOirVDMkC3NhwwxmKlJ7uH1fjfnANn2rGG8IZhpdK6RM9kUyYNJcHw+FRUropsSr9fwuu1f0BNE1LP6D8yt3JWd/NVjGhY/uattzSY9pHUdjc1zfEY1OsX5BDF7WPlcpwSPw/R8NOnh/XambNO7X2CXDG43LyGjHlHeohqtgKbJZD+H6qJxN3kIef2Yow/J2/+qxVGN7j5Xh8nkcY6Pb+bxecO8/x+UPxh77wNU+xvUI0KBOa4Aj4xKLJQz2LRcYym5HIFa3TGKarSbQ/ZhmZdU7UOGH3FtCfXovZkSbPquo733GWxeYunzmyy+OsTZLTZXr7OkpCENJ0XJ3ZJPS64+gfMRbIbSxDEul3pf3qYwydak3RIjhFwdTL6v/jHpHvVIG2Wp0UYbI60doSUwEkeMJJ0D6SQ4wVznhBZOCk2sFGagwpmWDmOJoBpBsU61utV2rCVikJirocOiHThWrpXYqlFyqkZGSWHyyrG6m0qesYoIcBxrGB0WmhqsBefY8dZ0TI5dx8a/kFz8sBVz8LS9u1WBdE6BkxQzQVsstKZY6bbDQ6cGPUgFrS2abyEGmP4C9cHbOKd5zNXFIdUbdJ+WUP4d1eqWnz7gX+uMbmb7ALEqMzY+lKdyGev5fD7/BgAA//8DAG6oGh2CBAAA

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACoxUy27kNhD8FYHXiDJfokjdHNuLDBw/sDNIgtxaZMtmLFMDirJ3YfjfA2ns9WMRIBdBaJJd1dXV/UQi3CNpyfF+f/aAMU+kJDmsIcGEpkxTJnfMtpy1wlRNzWwt+N+kJOEcv5OWNMo57ixSiRqp8qymnewd9R4tZ9wzUaslJ9xMpH0iECqPD8FhNU5/YJrCGElL/gzRj48LNoTKDePsqzQOuIlThugWMpebk3P6+/H17ur6cGvCaXlcBU9aYsBop8BT1WFHFesEBakYNbzvDa+VEcAOz0LMmCIM1eTv3vD9mCNm14pKyIpRYclzSTxkWCh3MOHu+35hsUp0usTLNbz+tk/kARNpRfkq5iHdkRvC0f3UzWHwR+uXlGSfxj2mHHBV42pbvJHgrGKV0IItVC/A3YaIxea0uBqWEsEZptBLarH3VFkO1CopqZc1NEL3TSN6UpJzTBGHd1kvgkvjNPa5eBG5+ICzPT45i9ANuGB8gWFCUpLNtM0QPQxjxLNv6OZ8yLVL83J8MsYc4jzOU7GJGW8SvJy/vj+ZU8KYi2vIt8VvMN2SllgwjoMFC6Cd67Fm2DPPQLPGo/YavRK+8coqr5VlTivouPJQ865fIqQkvy4abmfncJre2KwmGYaVQ/HSp5MhYMwfZCQtYRyFlwZpL7imynigUEtLtZa6R+5sI/grzA7SDWbSkt50Xcec64Sy3IGwIH3PpNe9FaJpQPWybpTQumYNON80gisvG3Qge8mMICW5TqOfXf7cark24DqN/6DLi1SkJZrVtXHQdUIrbsAaVFwroy02VvXAlHQd8NpA13EGNXPWCAdcW1Cdr/sfKp3FmxDxNEz7Ab6/wzWVruQvDsDwHtSn618S3OPjmO4uDzauLs92pCRf57hshGKzWOQxRPpNLxN9MQ857G4Tgkd/MXr82Ue4jEuxTihzxmrtBXW6Bqp0banltaK175VBY503DSnJ6ejuMBWLwyDEZap+JLvaFsfJ3YaMLs9p4ffXyuNqW1wPkPsx3X/YJO8K+yxAJSRnS2c8Phy20cpRe2/Qa06F4jVV1nJqbN3QrjGd7bTB2i2KXc15P+fiK/qQ0OW14hcvrpgnt+jufhbj1QUvFuVs8dr2sMVWaf/XEnsuyT3CNCe8X7d1+0Q2MWJakU/nwyhu4kUYhjChG6OfSMuZZJU0jXxh+N/3rKxs3Zjn5+fnfwEAAP//AwCrQngFGwYAAA==

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,28 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.Data.SqlClient;
var connectionString = "Server=localhost;Database=PlotLine;User Id=PlotLineApp;Password=t6eb1cvd9bNB27czde#h9r;MultipleActiveResultSets=true;Encrypt=false;";
var scriptPath = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", "..", "PlotLine", "Sql", "026_TimelineConfigurationSettings.sql"));
var script = await File.ReadAllTextAsync(scriptPath);
var batches = Regex.Split(script, @"^\s*GO\s*$", RegexOptions.Multiline | RegexOptions.IgnoreCase);
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
var count = 0;
foreach (var batch in batches)
{
if (string.IsNullOrWhiteSpace(batch))
{
continue;
}
await using var command = new SqlCommand(batch, connection);
command.CommandTimeout = 120;
await command.ExecuteNonQueryAsync();
count++;
}
Console.WriteLine($"Applied {count} SQL batches.");

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\PlotLine\PlotLine.csproj" />
</ItemGroup>
</Project>

Binary file not shown.

View File

@ -8,78 +8,44 @@
".NETCoreApp,Version=v10.0": { ".NETCoreApp,Version=v10.0": {
"PlotLine/1.0.0": { "PlotLine/1.0.0": {
"dependencies": { "dependencies": {
"Dapper": "2.1.66", "Dapper": "2.1.79",
"Microsoft.Data.SqlClient": "6.1.3" "Microsoft.Data.SqlClient": "7.0.1"
}, },
"runtime": { "runtime": {
"PlotLine.dll": {} "PlotLine.dll": {}
} }
}, },
"Azure.Core/1.47.1": { "Dapper/2.1.79": {
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "8.0.0",
"System.ClientModel": "1.5.1",
"System.Memory.Data": "8.0.1"
},
"runtime": { "runtime": {
"lib/net8.0/Azure.Core.dll": { "lib/net10.0/Dapper.dll": {
"assemblyVersion": "1.47.1.0",
"fileVersion": "1.4700.125.36505"
}
}
},
"Azure.Identity/1.14.2": {
"dependencies": {
"Azure.Core": "1.47.1",
"Microsoft.Identity.Client": "4.73.1",
"Microsoft.Identity.Client.Extensions.Msal": "4.73.1"
},
"runtime": {
"lib/net8.0/Azure.Identity.dll": {
"assemblyVersion": "1.14.2.0",
"fileVersion": "1.1400.225.36004"
}
}
},
"Dapper/2.1.66": {
"runtime": {
"lib/net8.0/Dapper.dll": {
"assemblyVersion": "2.0.0.0", "assemblyVersion": "2.0.0.0",
"fileVersion": "2.1.66.48463" "fileVersion": "2.1.79.29349"
} }
} }
}, },
"Microsoft.Bcl.AsyncInterfaces/8.0.0": { "Microsoft.Bcl.Cryptography/9.0.13": {
"runtime": {
"lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"Microsoft.Bcl.Cryptography/9.0.4": {
"runtime": { "runtime": {
"lib/net9.0/Microsoft.Bcl.Cryptography.dll": { "lib/net9.0/Microsoft.Bcl.Cryptography.dll": {
"assemblyVersion": "9.0.0.4", "assemblyVersion": "9.0.0.13",
"fileVersion": "9.0.425.16305" "fileVersion": "9.0.1326.6317"
} }
} }
}, },
"Microsoft.Data.SqlClient/6.1.3": { "Microsoft.Data.SqlClient/7.0.1": {
"dependencies": { "dependencies": {
"Azure.Core": "1.47.1", "Microsoft.Bcl.Cryptography": "9.0.13",
"Azure.Identity": "1.14.2", "Microsoft.Data.SqlClient.Extensions.Abstractions": "1.0.0",
"Microsoft.Bcl.Cryptography": "9.0.4", "Microsoft.Data.SqlClient.Internal.Logging": "1.0.0",
"Microsoft.Data.SqlClient.SNI.runtime": "6.0.2", "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2",
"Microsoft.IdentityModel.JsonWebTokens": "7.7.1", "Microsoft.IdentityModel.JsonWebTokens": "8.16.0",
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1", "Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.16.0",
"Microsoft.SqlServer.Server": "1.0.0", "Microsoft.SqlServer.Server": "1.0.0",
"System.Configuration.ConfigurationManager": "9.0.4" "System.Configuration.ConfigurationManager": "9.0.13"
}, },
"runtime": { "runtime": {
"lib/net9.0/Microsoft.Data.SqlClient.dll": { "lib/net9.0/Microsoft.Data.SqlClient.dll": {
"assemblyVersion": "6.0.0.0", "assemblyVersion": "7.0.0.0",
"fileVersion": "6.13.25316.3" "fileVersion": "7.0.1.26114"
} }
}, },
"resources": { "resources": {
@ -127,14 +93,33 @@
"runtimes/unix/lib/net9.0/Microsoft.Data.SqlClient.dll": { "runtimes/unix/lib/net9.0/Microsoft.Data.SqlClient.dll": {
"rid": "unix", "rid": "unix",
"assetType": "runtime", "assetType": "runtime",
"assemblyVersion": "6.0.0.0", "assemblyVersion": "7.0.0.0",
"fileVersion": "6.13.25316.3" "fileVersion": "7.0.1.26114"
}, },
"runtimes/win/lib/net9.0/Microsoft.Data.SqlClient.dll": { "runtimes/win/lib/net9.0/Microsoft.Data.SqlClient.dll": {
"rid": "win", "rid": "win",
"assetType": "runtime", "assetType": "runtime",
"assemblyVersion": "6.0.0.0", "assemblyVersion": "7.0.0.0",
"fileVersion": "6.13.25316.3" "fileVersion": "7.0.1.26114"
}
}
},
"Microsoft.Data.SqlClient.Extensions.Abstractions/1.0.0": {
"dependencies": {
"Microsoft.Data.SqlClient.Internal.Logging": "1.0.0"
},
"runtime": {
"lib/netstandard2.0/Microsoft.Data.SqlClient.Extensions.Abstractions.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.26076"
}
}
},
"Microsoft.Data.SqlClient.Internal.Logging/1.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.Data.SqlClient.Internal.Logging.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.26076"
} }
} }
}, },
@ -157,90 +142,67 @@
} }
} }
}, },
"Microsoft.Identity.Client/4.73.1": { "Microsoft.IdentityModel.Abstractions/8.16.0": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "7.7.1"
},
"runtime": { "runtime": {
"lib/net8.0/Microsoft.Identity.Client.dll": { "lib/net10.0/Microsoft.IdentityModel.Abstractions.dll": {
"assemblyVersion": "4.73.1.0", "assemblyVersion": "8.16.0.0",
"fileVersion": "4.73.1.0" "fileVersion": "8.16.0.26043"
} }
} }
}, },
"Microsoft.Identity.Client.Extensions.Msal/4.73.1": { "Microsoft.IdentityModel.JsonWebTokens/8.16.0": {
"dependencies": { "dependencies": {
"Microsoft.Identity.Client": "4.73.1", "Microsoft.IdentityModel.Tokens": "8.16.0"
"System.Security.Cryptography.ProtectedData": "9.0.4"
}, },
"runtime": { "runtime": {
"lib/net8.0/Microsoft.Identity.Client.Extensions.Msal.dll": { "lib/net10.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
"assemblyVersion": "4.73.1.0", "assemblyVersion": "8.16.0.0",
"fileVersion": "4.73.1.0" "fileVersion": "8.16.0.26043"
} }
} }
}, },
"Microsoft.IdentityModel.Abstractions/7.7.1": { "Microsoft.IdentityModel.Logging/8.16.0": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "8.16.0"
},
"runtime": { "runtime": {
"lib/net8.0/Microsoft.IdentityModel.Abstractions.dll": { "lib/net10.0/Microsoft.IdentityModel.Logging.dll": {
"assemblyVersion": "7.7.1.0", "assemblyVersion": "8.16.0.0",
"fileVersion": "7.7.1.50719" "fileVersion": "8.16.0.26043"
} }
} }
}, },
"Microsoft.IdentityModel.JsonWebTokens/7.7.1": { "Microsoft.IdentityModel.Protocols/8.16.0": {
"dependencies": { "dependencies": {
"Microsoft.IdentityModel.Tokens": "7.7.1" "Microsoft.IdentityModel.Tokens": "8.16.0"
}, },
"runtime": { "runtime": {
"lib/net8.0/Microsoft.IdentityModel.JsonWebTokens.dll": { "lib/net10.0/Microsoft.IdentityModel.Protocols.dll": {
"assemblyVersion": "7.7.1.0", "assemblyVersion": "8.16.0.0",
"fileVersion": "7.7.1.50719" "fileVersion": "8.16.0.26043"
} }
} }
}, },
"Microsoft.IdentityModel.Logging/7.7.1": { "Microsoft.IdentityModel.Protocols.OpenIdConnect/8.16.0": {
"dependencies": { "dependencies": {
"Microsoft.IdentityModel.Abstractions": "7.7.1" "Microsoft.IdentityModel.Protocols": "8.16.0",
"System.IdentityModel.Tokens.Jwt": "8.16.0"
}, },
"runtime": { "runtime": {
"lib/net8.0/Microsoft.IdentityModel.Logging.dll": { "lib/net10.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll": {
"assemblyVersion": "7.7.1.0", "assemblyVersion": "8.16.0.0",
"fileVersion": "7.7.1.50719" "fileVersion": "8.16.0.26043"
} }
} }
}, },
"Microsoft.IdentityModel.Protocols/7.7.1": { "Microsoft.IdentityModel.Tokens/8.16.0": {
"dependencies": { "dependencies": {
"Microsoft.IdentityModel.Tokens": "7.7.1" "Microsoft.IdentityModel.Logging": "8.16.0"
}, },
"runtime": { "runtime": {
"lib/net8.0/Microsoft.IdentityModel.Protocols.dll": { "lib/net10.0/Microsoft.IdentityModel.Tokens.dll": {
"assemblyVersion": "7.7.1.0", "assemblyVersion": "8.16.0.0",
"fileVersion": "7.7.1.50719" "fileVersion": "8.16.0.26043"
}
}
},
"Microsoft.IdentityModel.Protocols.OpenIdConnect/7.7.1": {
"dependencies": {
"Microsoft.IdentityModel.Protocols": "7.7.1",
"System.IdentityModel.Tokens.Jwt": "7.7.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll": {
"assemblyVersion": "7.7.1.0",
"fileVersion": "7.7.1.50719"
}
}
},
"Microsoft.IdentityModel.Tokens/7.7.1": {
"dependencies": {
"Microsoft.IdentityModel.Logging": "7.7.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Tokens.dll": {
"assemblyVersion": "7.7.1.0",
"fileVersion": "7.7.1.50719"
} }
} }
}, },
@ -252,53 +214,34 @@
} }
} }
}, },
"System.ClientModel/1.5.1": { "System.Configuration.ConfigurationManager/9.0.13": {
"dependencies": { "dependencies": {
"System.Memory.Data": "8.0.1" "System.Security.Cryptography.ProtectedData": "9.0.13"
},
"runtime": {
"lib/net8.0/System.ClientModel.dll": {
"assemblyVersion": "1.5.1.0",
"fileVersion": "1.500.125.36405"
}
}
},
"System.Configuration.ConfigurationManager/9.0.4": {
"dependencies": {
"System.Security.Cryptography.ProtectedData": "9.0.4"
}, },
"runtime": { "runtime": {
"lib/net9.0/System.Configuration.ConfigurationManager.dll": { "lib/net9.0/System.Configuration.ConfigurationManager.dll": {
"assemblyVersion": "9.0.0.0", "assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.425.16305" "fileVersion": "9.0.1326.6317"
} }
} }
}, },
"System.IdentityModel.Tokens.Jwt/7.7.1": { "System.IdentityModel.Tokens.Jwt/8.16.0": {
"dependencies": { "dependencies": {
"Microsoft.IdentityModel.JsonWebTokens": "7.7.1", "Microsoft.IdentityModel.JsonWebTokens": "8.16.0",
"Microsoft.IdentityModel.Tokens": "7.7.1" "Microsoft.IdentityModel.Tokens": "8.16.0"
}, },
"runtime": { "runtime": {
"lib/net8.0/System.IdentityModel.Tokens.Jwt.dll": { "lib/net10.0/System.IdentityModel.Tokens.Jwt.dll": {
"assemblyVersion": "7.7.1.0", "assemblyVersion": "8.16.0.0",
"fileVersion": "7.7.1.50719" "fileVersion": "8.16.0.26043"
} }
} }
}, },
"System.Memory.Data/8.0.1": { "System.Security.Cryptography.ProtectedData/9.0.13": {
"runtime": {
"lib/net8.0/System.Memory.Data.dll": {
"assemblyVersion": "8.0.0.1",
"fileVersion": "8.0.1024.46610"
}
}
},
"System.Security.Cryptography.ProtectedData/9.0.4": {
"runtime": { "runtime": {
"lib/net9.0/System.Security.Cryptography.ProtectedData.dll": { "lib/net9.0/System.Security.Cryptography.ProtectedData.dll": {
"assemblyVersion": "9.0.0.0", "assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.425.16305" "fileVersion": "9.0.1326.6317"
} }
} }
} }
@ -310,47 +253,40 @@
"serviceable": false, "serviceable": false,
"sha512": "" "sha512": ""
}, },
"Azure.Core/1.47.1": { "Dapper/2.1.79": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-oPcncSsDHuxB8SC522z47xbp2+ttkcKv2YZ90KXhRKN0YQd2+7l1UURT9EBzUNEXtkLZUOAB5xbByMTrYRh3yA==", "sha512": "sha512-8YijbzgTfmqmQOnVNorYM6K++pxqnW3nJ4aC1sRHzxUA2CcuoJ9gsTem3kgBnPRMc38zZHl4Esb6hAezXIEEuw==",
"path": "azure.core/1.47.1", "path": "dapper/2.1.79",
"hashPath": "azure.core.1.47.1.nupkg.sha512" "hashPath": "dapper.2.1.79.nupkg.sha512"
}, },
"Azure.Identity/1.14.2": { "Microsoft.Bcl.Cryptography/9.0.13": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-YhNMwOTwT+I2wIcJKSdP0ADyB2aK+JaYWZxO8LSRDm5w77LFr0ykR9xmt2ZV5T1gaI7xU6iNFIh/yW1dAlpddQ==", "sha512": "sha512-5T+bH3Lb1nEe8Hf/ixMxLmhlrx5wRi53wv7OhVwG2F1ZviW1ejFRS1NHur3uqPpJRGtkQwUchtY6zhVK2R+v+w==",
"path": "azure.identity/1.14.2", "path": "microsoft.bcl.cryptography/9.0.13",
"hashPath": "azure.identity.1.14.2.nupkg.sha512" "hashPath": "microsoft.bcl.cryptography.9.0.13.nupkg.sha512"
}, },
"Dapper/2.1.66": { "Microsoft.Data.SqlClient/7.0.1": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-/q77jUgDOS+bzkmk3Vy9SiWMaetTw+NOoPAV0xPBsGVAyljd5S6P+4RUW7R3ZUGGr9lDRyPKgAMj2UAOwvqZYw==", "sha512": "sha512-9jZFXAJ2ThNYK7lhj2RhH7klXVNaWSvZpQncq3bPIOjmHBrdjwgeO4c8wucUVxQwFT8rAA13Z2F2jzoYR7ICDw==",
"path": "dapper/2.1.66", "path": "microsoft.data.sqlclient/7.0.1",
"hashPath": "dapper.2.1.66.nupkg.sha512" "hashPath": "microsoft.data.sqlclient.7.0.1.nupkg.sha512"
}, },
"Microsoft.Bcl.AsyncInterfaces/8.0.0": { "Microsoft.Data.SqlClient.Extensions.Abstractions/1.0.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==", "sha512": "sha512-rlnxc0KfwDSbE8ZHntFnl8SCgOa9QtJZblMv2zXLhRwl1Je7fsdsVzxSjzzC4JMsfAK+jXJWyezRB8SxUY4BdA==",
"path": "microsoft.bcl.asyncinterfaces/8.0.0", "path": "microsoft.data.sqlclient.extensions.abstractions/1.0.0",
"hashPath": "microsoft.bcl.asyncinterfaces.8.0.0.nupkg.sha512" "hashPath": "microsoft.data.sqlclient.extensions.abstractions.1.0.0.nupkg.sha512"
}, },
"Microsoft.Bcl.Cryptography/9.0.4": { "Microsoft.Data.SqlClient.Internal.Logging/1.0.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-YgZYAWzyNuPVtPq6WNm0bqOWNjYaWgl5mBWTGZyNoXitYBUYSp6iUB9AwK0V1mo793qRJUXz2t6UZrWITZSvuQ==", "sha512": "sha512-Kue/7CF8KNT9zozfr30C94dMZVZml3atqWZvQemSXvTau76tRdypzeKiBKXadqgbOME0UiQIyVTNo5WxCRNVNg==",
"path": "microsoft.bcl.cryptography/9.0.4", "path": "microsoft.data.sqlclient.internal.logging/1.0.0",
"hashPath": "microsoft.bcl.cryptography.9.0.4.nupkg.sha512" "hashPath": "microsoft.data.sqlclient.internal.logging.1.0.0.nupkg.sha512"
},
"Microsoft.Data.SqlClient/6.1.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ys/z8Tx8074CDU20EilNvBRJuJdwKSthpHkzUpt3JghnjB6GjbZusoOcCtNbhPCCWsEJqN8bxaT7HnS3UZuUDQ==",
"path": "microsoft.data.sqlclient/6.1.3",
"hashPath": "microsoft.data.sqlclient.6.1.3.nupkg.sha512"
}, },
"Microsoft.Data.SqlClient.SNI.runtime/6.0.2": { "Microsoft.Data.SqlClient.SNI.runtime/6.0.2": {
"type": "package", "type": "package",
@ -359,61 +295,47 @@
"path": "microsoft.data.sqlclient.sni.runtime/6.0.2", "path": "microsoft.data.sqlclient.sni.runtime/6.0.2",
"hashPath": "microsoft.data.sqlclient.sni.runtime.6.0.2.nupkg.sha512" "hashPath": "microsoft.data.sqlclient.sni.runtime.6.0.2.nupkg.sha512"
}, },
"Microsoft.Identity.Client/4.73.1": { "Microsoft.IdentityModel.Abstractions/8.16.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-NnDLS8QwYqO5ZZecL2oioi1LUqjh5Ewk4bMLzbgiXJbQmZhDLtKwLxL3DpGMlQAJ2G4KgEnvGPKa+OOgffeJbw==", "sha512": "sha512-gSxKLWRZzBpIsEoeUPkxfywNCCvRvl7hkq146XHPk5vOQc9izSf1I+uL1vh4y2U19QPxd9Z8K/8AdWyxYz2lSg==",
"path": "microsoft.identity.client/4.73.1", "path": "microsoft.identitymodel.abstractions/8.16.0",
"hashPath": "microsoft.identity.client.4.73.1.nupkg.sha512" "hashPath": "microsoft.identitymodel.abstractions.8.16.0.nupkg.sha512"
}, },
"Microsoft.Identity.Client.Extensions.Msal/4.73.1": { "Microsoft.IdentityModel.JsonWebTokens/8.16.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-xDztAiV2F0wI0W8FLKv5cbaBefyLD6JVaAsvgSN7bjWNCzGYzHbcOEIP5s4TJXUpQzMfUyBsFl1mC6Zmgpz0PQ==", "sha512": "sha512-prBU72cIP4V8E9fhN+o/YdskTsLeIcnKPbhZf0X6mD7fdxoZqnS/NdEkSr+9Zp+2q7OZBOMfNBKGbTbhXODO4w==",
"path": "microsoft.identity.client.extensions.msal/4.73.1", "path": "microsoft.identitymodel.jsonwebtokens/8.16.0",
"hashPath": "microsoft.identity.client.extensions.msal.4.73.1.nupkg.sha512" "hashPath": "microsoft.identitymodel.jsonwebtokens.8.16.0.nupkg.sha512"
}, },
"Microsoft.IdentityModel.Abstractions/7.7.1": { "Microsoft.IdentityModel.Logging/8.16.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-S7sHg6gLg7oFqNGLwN1qSbJDI+QcRRj8SuJ1jHyCmKSipnF6ZQL+tFV2NzVfGj/xmGT9TykQdQiBN+p5Idl4TA==", "sha512": "sha512-MTzXmETkNQPACR7/XCXM1OGM6oU9RkyibqeJRtO9Ndew2LnGjMf9Atqj2VSf4XC27X0FQycUAlzxxEgQMWn2xQ==",
"path": "microsoft.identitymodel.abstractions/7.7.1", "path": "microsoft.identitymodel.logging/8.16.0",
"hashPath": "microsoft.identitymodel.abstractions.7.7.1.nupkg.sha512" "hashPath": "microsoft.identitymodel.logging.8.16.0.nupkg.sha512"
}, },
"Microsoft.IdentityModel.JsonWebTokens/7.7.1": { "Microsoft.IdentityModel.Protocols/8.16.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-3Izi75UCUssvo8LPx3OVnEeZay58qaFicrtSnbtUt7q8qQi0gy46gh4V8VUTkMVMKXV6VMyjBVmeNNgeCUJuIw==", "sha512": "sha512-UFrU7d46UTsPQTa2HIEIpB9H1uJe1BW9FLw5uhEJ2ZuKdur8bcUA/bO5caq5dlBt5gNJeRIB3QQXYNs5fCQCZA==",
"path": "microsoft.identitymodel.jsonwebtokens/7.7.1", "path": "microsoft.identitymodel.protocols/8.16.0",
"hashPath": "microsoft.identitymodel.jsonwebtokens.7.7.1.nupkg.sha512" "hashPath": "microsoft.identitymodel.protocols.8.16.0.nupkg.sha512"
}, },
"Microsoft.IdentityModel.Logging/7.7.1": { "Microsoft.IdentityModel.Protocols.OpenIdConnect/8.16.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-BZNgSq/o8gsKExdYoBKPR65fdsxW0cTF8PsdqB8y011AGUJJW300S/ZIsEUD0+sOmGc003Gwv3FYbjrVjvsLNQ==", "sha512": "sha512-h4yVXyJsEBBX5lg2G5ftMsi5JzcNEGAzrNphA6DQ6eOd8P0s+cDCOyPwVTYLePZvJL5unbPvYIvzrbTXzFjXnQ==",
"path": "microsoft.identitymodel.logging/7.7.1", "path": "microsoft.identitymodel.protocols.openidconnect/8.16.0",
"hashPath": "microsoft.identitymodel.logging.7.7.1.nupkg.sha512" "hashPath": "microsoft.identitymodel.protocols.openidconnect.8.16.0.nupkg.sha512"
}, },
"Microsoft.IdentityModel.Protocols/7.7.1": { "Microsoft.IdentityModel.Tokens/8.16.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-h+fHHBGokepmCX+QZXJk4Ij8OApCb2n2ktoDkNX5CXteXsOxTHMNgjPGpAwdJMFvAL7TtGarUnk3o97NmBq2QQ==", "sha512": "sha512-rtViGJcGsN7WcfUNErwNeQgjuU5cJNl6FDQsfi9TncwO+Epzn0FTfBsg3YuFW1Q0Ch/KPxaVdjLw3/+5Z5ceFQ==",
"path": "microsoft.identitymodel.protocols/7.7.1", "path": "microsoft.identitymodel.tokens/8.16.0",
"hashPath": "microsoft.identitymodel.protocols.7.7.1.nupkg.sha512" "hashPath": "microsoft.identitymodel.tokens.8.16.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Protocols.OpenIdConnect/7.7.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-yT2Hdj8LpPbcT9C9KlLVxXl09C8zjFaVSaApdOwuecMuoV4s6Sof/mnTDz/+F/lILPIBvrWugR9CC7iRVZgbfQ==",
"path": "microsoft.identitymodel.protocols.openidconnect/7.7.1",
"hashPath": "microsoft.identitymodel.protocols.openidconnect.7.7.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Tokens/7.7.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-fQ0VVCba75lknUHGldi3iTKAYUQqbzp1Un8+d9cm9nON0Gs8NAkXddNg8iaUB0qi/ybtAmNWizTR4avdkCJ9pQ==",
"path": "microsoft.identitymodel.tokens/7.7.1",
"hashPath": "microsoft.identitymodel.tokens.7.7.1.nupkg.sha512"
}, },
"Microsoft.SqlServer.Server/1.0.0": { "Microsoft.SqlServer.Server/1.0.0": {
"type": "package", "type": "package",
@ -422,40 +344,26 @@
"path": "microsoft.sqlserver.server/1.0.0", "path": "microsoft.sqlserver.server/1.0.0",
"hashPath": "microsoft.sqlserver.server.1.0.0.nupkg.sha512" "hashPath": "microsoft.sqlserver.server.1.0.0.nupkg.sha512"
}, },
"System.ClientModel/1.5.1": { "System.Configuration.ConfigurationManager/9.0.13": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-k2jKSO0X45IqhVOT9iQB4xralNN9foRQsRvXBTyRpAVxyzCJlG895T9qYrQWbcJ6OQXxOouJQ37x5nZH5XKK+A==", "sha512": "sha512-GbBrJq9S/gYpHzm7Pxx6Y5tDyfSfyxW6tlP5oiKJV38uf19Wp+GIIAnWfyL1zmNiz1+EjwVapw2WkBFvvqKQzg==",
"path": "system.clientmodel/1.5.1", "path": "system.configuration.configurationmanager/9.0.13",
"hashPath": "system.clientmodel.1.5.1.nupkg.sha512" "hashPath": "system.configuration.configurationmanager.9.0.13.nupkg.sha512"
}, },
"System.Configuration.ConfigurationManager/9.0.4": { "System.IdentityModel.Tokens.Jwt/8.16.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-dvjqKp+2LpGid6phzrdrS/2mmEPxFl3jE1+L7614q4ZChKbLJCpHXg6sBILlCCED1t//EE+un/UdAetzIMpqnw==", "sha512": "sha512-rrs2u7DRMXQG2yh0oVyF/vLwosfRv20Ld2iEpYcKwQWXHjfV+gFXNQsQ9p008kR9Ou4pxBs68Q6/9zC8Gi1wjg==",
"path": "system.configuration.configurationmanager/9.0.4", "path": "system.identitymodel.tokens.jwt/8.16.0",
"hashPath": "system.configuration.configurationmanager.9.0.4.nupkg.sha512" "hashPath": "system.identitymodel.tokens.jwt.8.16.0.nupkg.sha512"
}, },
"System.IdentityModel.Tokens.Jwt/7.7.1": { "System.Security.Cryptography.ProtectedData/9.0.13": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-rQkO1YbAjLwnDJSMpRhRtrc6XwIcEOcUvoEcge+evurpzSZM3UNK+MZfD3sKyTlYsvknZ6eJjSBfnmXqwOsT9Q==", "sha512": "sha512-t8S9IDpjJKsLpLkeBdW8cWtcPyYqrGu93Dej1RO6WwuL/lkFSqWlan3rMJfortqz1mRIh+sys2AFsSA6jWJ3Jg==",
"path": "system.identitymodel.tokens.jwt/7.7.1", "path": "system.security.cryptography.protecteddata/9.0.13",
"hashPath": "system.identitymodel.tokens.jwt.7.7.1.nupkg.sha512" "hashPath": "system.security.cryptography.protecteddata.9.0.13.nupkg.sha512"
},
"System.Memory.Data/8.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BVYuec3jV23EMRDeR7Dr1/qhx7369dZzJ9IWy2xylvb4YfXsrUxspWc4UWYid/tj4zZK58uGZqn2WQiaDMhmAg==",
"path": "system.memory.data/8.0.1",
"hashPath": "system.memory.data.8.0.1.nupkg.sha512"
},
"System.Security.Cryptography.ProtectedData/9.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-o94k2RKuAce3GeDMlUvIXlhVa1kWpJw95E6C9LwW0KlG0nj5+SgCiIxJ2Eroqb9sLtG1mEMbFttZIBZ13EJPvQ==",
"path": "system.security.cryptography.protecteddata/9.0.4",
"hashPath": "system.security.cryptography.protecteddata.9.0.4.nupkg.sha512"
} }
} }
} }

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,6 +18,54 @@ public sealed class TimelineController(ITimelineService timeline) : Controller
return model is null ? NotFound() : View(model); return model is null ? NotFound() : View(model);
} }
public async Task<IActionResult> Settings(int projectId)
{
var model = await timeline.GetSettingsAsync(projectId);
return model is null ? NotFound() : View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Settings(TimelineSettingsViewModel model)
{
if (model.ShowMetricShape && !model.SelectedMetricTypeIDs.Any())
{
ModelState.AddModelError(nameof(model.SelectedMetricTypeIDs), "Select at least one metric or disable Metric Shape.");
}
if (!ModelState.IsValid)
{
var current = await timeline.GetSettingsAsync(model.ProjectID);
if (current is null)
{
return NotFound();
}
current.ShowSceneCards = model.ShowSceneCards;
current.ShowMetricShape = model.ShowMetricShape;
current.ShowPlotLines = model.ShowPlotLines;
current.ShowStoryAssets = model.ShowStoryAssets;
current.ShowCharacterAppearances = model.ShowCharacterAppearances;
current.ShowWarnings = model.ShowWarnings;
current.SelectedMetricTypeIDs = model.SelectedMetricTypeIDs;
current.MetricOptions = current.MetricOptions
.Select(x => new TimelineMetricSettingOptionViewModel
{
MetricTypeID = x.MetricTypeID,
MetricName = x.MetricName,
Description = x.Description,
SortOrder = x.SortOrder,
IsSelected = model.SelectedMetricTypeIDs.Contains(x.MetricTypeID)
})
.ToList();
return View(current);
}
await timeline.SaveSettingsAsync(model);
TempData["TimelineSettingsMessage"] = "Timeline settings saved.";
return RedirectToAction(nameof(Settings), new { projectId = model.ProjectID });
}
[HttpPost] [HttpPost]
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public async Task<IActionResult> SavePreset(TimelinePresetSaveViewModel model) public async Task<IActionResult> SavePreset(TimelinePresetSaveViewModel model)

View File

@ -51,7 +51,7 @@ public interface ILookupRepository
public interface ITimelineRepository public interface ITimelineRepository
{ {
Task<TimelineData> GetByProjectAsync(int projectId, int? bookId); Task<TimelineData> GetByProjectAsync(int projectId, int? bookId, bool includeMetrics, IEnumerable<int> metricTypeIds, bool includePlotLines);
} }
public interface ITimelinePresetRepository public interface ITimelinePresetRepository
@ -62,6 +62,14 @@ public interface ITimelinePresetRepository
Task ArchiveAsync(int timelineViewPresetId); Task ArchiveAsync(int timelineViewPresetId);
} }
public interface ITimelineSettingsRepository
{
Task<ProjectTimelineSettings?> GetAsync(int projectId);
Task<IReadOnlyList<SceneMetricType>> ListMetricTypesAsync(int projectId);
Task<IReadOnlyList<ProjectTimelineMetricSetting>> ListMetricSettingsAsync(int projectId);
Task SaveAsync(ProjectTimelineSettings settings, IEnumerable<int> metricTypeIds);
}
public interface IPlotRepository public interface IPlotRepository
{ {
Task<PlotLookupData> GetLookupsAsync(); Task<PlotLookupData> GetLookupsAsync();
@ -1353,12 +1361,20 @@ public sealed class LookupRepository(ISqlConnectionFactory connectionFactory) :
public sealed class TimelineRepository(ISqlConnectionFactory connectionFactory) : ITimelineRepository public sealed class TimelineRepository(ISqlConnectionFactory connectionFactory) : ITimelineRepository
{ {
public async Task<TimelineData> GetByProjectAsync(int projectId, int? bookId) public async Task<TimelineData> GetByProjectAsync(int projectId, int? bookId, bool includeMetrics, IEnumerable<int> metricTypeIds, bool includePlotLines)
{ {
using var connection = connectionFactory.CreateConnection(); using var connection = connectionFactory.CreateConnection();
var selectedMetricIds = string.Join(',', metricTypeIds.Where(id => id > 0).Distinct());
using var result = await connection.QueryMultipleAsync( using var result = await connection.QueryMultipleAsync(
"dbo.Timeline_GetByProject", "dbo.Timeline_GetByProject",
new { ProjectID = projectId, BookID = bookId }, new
{
ProjectID = projectId,
BookID = bookId,
IncludeMetrics = includeMetrics,
SelectedMetricTypeIDs = selectedMetricIds,
IncludePlotLines = includePlotLines
},
commandType: CommandType.StoredProcedure); commandType: CommandType.StoredProcedure);
var project = await result.ReadSingleOrDefaultAsync<Project>(); var project = await result.ReadSingleOrDefaultAsync<Project>();
@ -1386,6 +1402,57 @@ public sealed class TimelineRepository(ISqlConnectionFactory connectionFactory)
} }
} }
public sealed class TimelineSettingsRepository(ISqlConnectionFactory connectionFactory) : ITimelineSettingsRepository
{
public async Task<ProjectTimelineSettings?> GetAsync(int projectId)
{
using var connection = connectionFactory.CreateConnection();
return await connection.QuerySingleOrDefaultAsync<ProjectTimelineSettings>(
"dbo.ProjectTimelineSettings_Get",
new { ProjectID = projectId },
commandType: CommandType.StoredProcedure);
}
public async Task<IReadOnlyList<SceneMetricType>> ListMetricTypesAsync(int projectId)
{
using var connection = connectionFactory.CreateConnection();
var rows = await connection.QueryAsync<SceneMetricType>(
"dbo.ProjectTimelineSettings_MetricTypes",
new { ProjectID = projectId },
commandType: CommandType.StoredProcedure);
return rows.ToList();
}
public async Task<IReadOnlyList<ProjectTimelineMetricSetting>> ListMetricSettingsAsync(int projectId)
{
using var connection = connectionFactory.CreateConnection();
var rows = await connection.QueryAsync<ProjectTimelineMetricSetting>(
"dbo.ProjectTimelineMetricSettings_List",
new { ProjectID = projectId },
commandType: CommandType.StoredProcedure);
return rows.ToList();
}
public async Task SaveAsync(ProjectTimelineSettings settings, IEnumerable<int> metricTypeIds)
{
using var connection = connectionFactory.CreateConnection();
await connection.ExecuteAsync(
"dbo.ProjectTimelineSettings_Save",
new
{
settings.ProjectID,
settings.ShowSceneCards,
settings.ShowMetricShape,
settings.ShowPlotLines,
settings.ShowStoryAssets,
settings.ShowCharacterAppearances,
settings.ShowWarnings,
MetricTypeIDs = string.Join(',', metricTypeIds.Where(id => id > 0).Distinct())
},
commandType: CommandType.StoredProcedure);
}
}
public sealed class TimelinePresetRepository(ISqlConnectionFactory connectionFactory) : ITimelinePresetRepository public sealed class TimelinePresetRepository(ISqlConnectionFactory connectionFactory) : ITimelinePresetRepository
{ {
public async Task<IReadOnlyList<TimelineViewPreset>> ListAsync(int projectId, int? bookId) public async Task<IReadOnlyList<TimelineViewPreset>> ListAsync(int projectId, int? bookId)

View File

@ -183,6 +183,28 @@ public sealed class TimelineViewPreset
public bool IsArchived { get; set; } public bool IsArchived { get; set; }
} }
public sealed class ProjectTimelineSettings
{
public int ProjectTimelineSettingsID { get; set; }
public int ProjectID { get; set; }
public bool ShowSceneCards { get; set; } = true;
public bool ShowMetricShape { get; set; } = true;
public bool ShowPlotLines { get; set; } = true;
public bool ShowStoryAssets { get; set; } = true;
public bool ShowCharacterAppearances { get; set; } = true;
public bool ShowWarnings { get; set; } = true;
public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; }
}
public sealed class ProjectTimelineMetricSetting
{
public int ProjectID { get; set; }
public int MetricTypeID { get; set; }
public string MetricName { get; set; } = string.Empty;
public int SortOrder { get; set; }
}
public sealed class PlotLineType public sealed class PlotLineType
{ {
public int PlotLineTypeID { get; set; } public int PlotLineTypeID { get; set; }

View File

@ -25,6 +25,7 @@ public class Program
builder.Services.AddScoped<ILookupRepository, LookupRepository>(); builder.Services.AddScoped<ILookupRepository, LookupRepository>();
builder.Services.AddScoped<ITimelineRepository, TimelineRepository>(); builder.Services.AddScoped<ITimelineRepository, TimelineRepository>();
builder.Services.AddScoped<ITimelinePresetRepository, TimelinePresetRepository>(); builder.Services.AddScoped<ITimelinePresetRepository, TimelinePresetRepository>();
builder.Services.AddScoped<ITimelineSettingsRepository, TimelineSettingsRepository>();
builder.Services.AddScoped<IPlotRepository, PlotRepository>(); builder.Services.AddScoped<IPlotRepository, PlotRepository>();
builder.Services.AddScoped<IAssetRepository, AssetRepository>(); builder.Services.AddScoped<IAssetRepository, AssetRepository>();
builder.Services.AddScoped<ICharacterRepository, CharacterRepository>(); builder.Services.AddScoped<ICharacterRepository, CharacterRepository>();

View File

@ -136,6 +136,8 @@ public interface ICharacterService
public interface ITimelineService public interface ITimelineService
{ {
Task<TimelineViewModel?> GetAsync(TimelineFilterViewModel filter); Task<TimelineViewModel?> GetAsync(TimelineFilterViewModel filter);
Task<TimelineSettingsViewModel?> GetSettingsAsync(int projectId);
Task SaveSettingsAsync(TimelineSettingsViewModel model);
Task<int> SavePresetAsync(TimelinePresetSaveViewModel model); Task<int> SavePresetAsync(TimelinePresetSaveViewModel model);
Task<TimelineViewPreset?> GetPresetAsync(int timelineViewPresetId); Task<TimelineViewPreset?> GetPresetAsync(int timelineViewPresetId);
Task ArchivePresetAsync(int timelineViewPresetId); Task ArchivePresetAsync(int timelineViewPresetId);
@ -874,6 +876,8 @@ public sealed class SceneService(
public sealed class TimelineService( public sealed class TimelineService(
ITimelineRepository timelineRepository, ITimelineRepository timelineRepository,
ITimelinePresetRepository presets, ITimelinePresetRepository presets,
ITimelineSettingsRepository timelineSettings,
IProjectRepository projects,
IBookRepository books, IBookRepository books,
ISceneService scenes, ISceneService scenes,
IAssetRepository assets, IAssetRepository assets,
@ -885,14 +889,32 @@ public sealed class TimelineService(
ISceneDependencyRepository sceneDependencies, ISceneDependencyRepository sceneDependencies,
ILogger<TimelineService> logger) : ITimelineService ILogger<TimelineService> logger) : ITimelineService
{ {
private static readonly string[] DefaultGraphMetrics = ["Overall Intensity", "Tension", "Emotional Weight", "Action"];
public async Task<TimelineViewModel?> GetAsync(TimelineFilterViewModel filter) public async Task<TimelineViewModel?> GetAsync(TimelineFilterViewModel filter)
{ {
var projectId = filter.ProjectID; var projectId = filter.ProjectID;
var bookId = filter.BookID; var bookId = filter.BookID;
var selectedSceneId = filter.SelectedSceneID; var selectedSceneId = filter.SelectedSceneID;
var timeline = await TimeTimelineLoadAsync("dbo.Timeline_GetByProject", () => timelineRepository.GetByProjectAsync(projectId, bookId), projectId, bookId); var settings = await TimeTimelineLoadAsync("dbo.ProjectTimelineSettings_Get", () => timelineSettings.GetAsync(projectId), projectId, bookId);
if (settings is null)
{
return null;
}
var selectedMetricIds = (await TimeTimelineLoadAsync("dbo.ProjectTimelineMetricSettings_List", () => timelineSettings.ListMetricSettingsAsync(projectId), projectId, bookId))
.OrderBy(x => x.SortOrder)
.Select(x => x.MetricTypeID)
.ToList();
var needsPlotTimelineData = settings.ShowPlotLines || filter.PlotLineID.HasValue || filter.PlotThreadID.HasValue || filter.FocusType is "plotline" or "plotthread";
var needsMetricTimelineData = settings.ShowMetricShape && selectedMetricIds.Any();
var needsAssetTimelineData = settings.ShowStoryAssets || filter.StoryAssetID.HasValue || filter.FocusType == "asset";
var needsCharacterTimelineData = settings.ShowCharacterAppearances || filter.CharacterID.HasValue || filter.FocusType == "character";
var needsWarnings = settings.ShowWarnings || filter.WarningSeverityID.HasValue || filter.WarningTypeID.HasValue || filter.ShowWarningsOnly;
var timeline = await TimeTimelineLoadAsync(
"dbo.Timeline_GetByProject",
() => timelineRepository.GetByProjectAsync(projectId, bookId, needsMetricTimelineData, selectedMetricIds, needsPlotTimelineData),
projectId,
bookId);
if (timeline.Project is null) if (timeline.Project is null)
{ {
return null; return null;
@ -913,7 +935,9 @@ public sealed class TimelineService(
var scenesByChapter = timeline.Scenes.GroupBy(x => x.ChapterID).ToDictionary(x => x.Key, x => x.ToList()); var scenesByChapter = timeline.Scenes.GroupBy(x => x.ChapterID).ToDictionary(x => x.Key, x => x.ToList());
var purposeLabelsByScene = timeline.PurposeLabels.GroupBy(x => x.SceneID).ToDictionary(x => x.Key, x => x.OrderBy(p => p.SortOrder).ToList()); var purposeLabelsByScene = timeline.PurposeLabels.GroupBy(x => x.SceneID).ToDictionary(x => x.Key, x => x.OrderBy(p => p.SortOrder).ToList());
var orderedScenes = timeline.Scenes.ToList(); var orderedScenes = timeline.Scenes.ToList();
var warningCounts = (await TimeTimelineLoadAsync("dbo.ContinuityWarning_SceneCounts", () => warnings.GetSceneCountsAsync(projectId, bookId), projectId, bookId)).ToDictionary(x => x.SceneID, x => x.WarningCount); var warningCounts = needsWarnings
? (await TimeTimelineLoadAsync("dbo.ContinuityWarning_SceneCounts", () => warnings.GetSceneCountsAsync(projectId, bookId), projectId, bookId)).ToDictionary(x => x.SceneID, x => x.WarningCount)
: new Dictionary<int, int>();
var dependencyCounts = (await TimeTimelineLoadAsync("dbo.SceneDependency_Counts", () => sceneDependencies.GetCountsAsync(projectId, bookId), projectId, bookId)).ToDictionary(x => x.SceneID, x => x.DependencyCount); var dependencyCounts = (await TimeTimelineLoadAsync("dbo.SceneDependency_Counts", () => sceneDependencies.GetCountsAsync(projectId, bookId), projectId, bookId)).ToDictionary(x => x.SceneID, x => x.DependencyCount);
foreach (var scene in orderedScenes) foreach (var scene in orderedScenes)
@ -923,8 +947,12 @@ public sealed class TimelineService(
scene.DependencyCount = dependencyCounts.GetValueOrDefault(scene.SceneID); scene.DependencyCount = dependencyCounts.GetValueOrDefault(scene.SceneID);
} }
var assetTimeline = await TimeTimelineLoadAsync("dbo.AssetTimeline_GetByProject", () => assets.GetTimelineAsync(projectId, bookId), projectId, bookId); (IReadOnlyList<StoryAsset> Assets, IReadOnlyList<AssetEvent> Events) assetTimeline = needsAssetTimelineData
var characterTimeline = await TimeTimelineLoadAsync("dbo.CharacterTimeline_GetByProject", () => characters.GetTimelineAsync(projectId, bookId), projectId, bookId); ? await TimeTimelineLoadAsync("dbo.AssetTimeline_GetByProject", () => assets.GetTimelineAsync(projectId, bookId), projectId, bookId)
: ([], []);
(IReadOnlyList<Character> Characters, IReadOnlyList<SceneCharacter> Appearances) characterTimeline = needsCharacterTimelineData
? await TimeTimelineLoadAsync("dbo.CharacterTimeline_GetByProject", () => characters.GetTimelineAsync(projectId, bookId), projectId, bookId)
: ([], []);
var scenePovLabels = characterTimeline.Appearances var scenePovLabels = characterTimeline.Appearances
.Where(x => x.RoleInSceneTypeName?.Contains("POV", StringComparison.OrdinalIgnoreCase) == true) .Where(x => x.RoleInSceneTypeName?.Contains("POV", StringComparison.OrdinalIgnoreCase) == true)
.GroupBy(x => x.SceneID) .GroupBy(x => x.SceneID)
@ -951,6 +979,7 @@ public sealed class TimelineService(
return new TimelineViewModel return new TimelineViewModel
{ {
Project = timeline.Project, Project = timeline.Project,
Settings = settings,
SelectedBookID = bookId, SelectedBookID = bookId,
SelectedSceneID = selectedScene?.SceneID, SelectedSceneID = selectedScene?.SceneID,
SelectedScene = selectedScene, SelectedScene = selectedScene,
@ -991,10 +1020,10 @@ public sealed class TimelineService(
.ToList() .ToList()
}).ToList(), }).ToList(),
OrderedScenes = orderedScenes, OrderedScenes = orderedScenes,
MetricGraphs = BuildMetricGraphs(timeline, orderedScenes), MetricGraphs = settings.ShowMetricShape ? BuildMetricGraphs(timeline, orderedScenes) : [],
PlotLanes = BuildPlotLanes(timeline, orderedScenes), PlotLanes = settings.ShowPlotLines ? BuildPlotLanes(timeline, orderedScenes) : [],
AssetLanes = BuildAssetLanes(assetTimeline.Assets, assetTimeline.Events, orderedScenes), AssetLanes = settings.ShowStoryAssets ? BuildAssetLanes(assetTimeline.Assets, assetTimeline.Events, orderedScenes) : [],
CharacterLanes = BuildCharacterLanes(characterTimeline.Characters, characterTimeline.Appearances, orderedScenes), CharacterLanes = settings.ShowCharacterAppearances ? BuildCharacterLanes(characterTimeline.Characters, characterTimeline.Appearances, orderedScenes) : [],
MatchingSceneIDs = matchingSceneIds, MatchingSceneIDs = matchingSceneIds,
FocusSceneIDs = focusSceneIds, FocusSceneIDs = focusSceneIds,
ScenePovLabels = scenePovLabels, ScenePovLabels = scenePovLabels,
@ -1006,6 +1035,63 @@ public sealed class TimelineService(
public Task ArchivePresetAsync(int timelineViewPresetId) => presets.ArchiveAsync(timelineViewPresetId); public Task ArchivePresetAsync(int timelineViewPresetId) => presets.ArchiveAsync(timelineViewPresetId);
public async Task<TimelineSettingsViewModel?> GetSettingsAsync(int projectId)
{
var project = await projects.GetAsync(projectId);
if (project is null)
{
return null;
}
var settings = await timelineSettings.GetAsync(projectId) ?? new ProjectTimelineSettings { ProjectID = projectId };
var metricTypes = await timelineSettings.ListMetricTypesAsync(projectId);
var selectedMetricIds = (await timelineSettings.ListMetricSettingsAsync(projectId)).Select(x => x.MetricTypeID).ToHashSet();
return new TimelineSettingsViewModel
{
ProjectID = project.ProjectID,
ProjectName = project.ProjectName,
ShowSceneCards = settings.ShowSceneCards,
ShowMetricShape = settings.ShowMetricShape,
ShowPlotLines = settings.ShowPlotLines,
ShowStoryAssets = settings.ShowStoryAssets,
ShowCharacterAppearances = settings.ShowCharacterAppearances,
ShowWarnings = settings.ShowWarnings,
SelectedMetricTypeIDs = selectedMetricIds.ToList(),
MetricOptions = metricTypes
.OrderBy(x => x.SortOrder)
.ThenBy(x => x.MetricName)
.Select(x => new TimelineMetricSettingOptionViewModel
{
MetricTypeID = x.MetricTypeID,
MetricName = x.MetricName,
Description = x.Description,
SortOrder = x.SortOrder,
IsSelected = selectedMetricIds.Contains(x.MetricTypeID)
})
.ToList()
};
}
public async Task SaveSettingsAsync(TimelineSettingsViewModel model)
{
if (model.ShowMetricShape && !model.SelectedMetricTypeIDs.Any())
{
throw new InvalidOperationException("Select at least one metric or disable Metric Shape.");
}
await timelineSettings.SaveAsync(new ProjectTimelineSettings
{
ProjectID = model.ProjectID,
ShowSceneCards = model.ShowSceneCards,
ShowMetricShape = model.ShowMetricShape,
ShowPlotLines = model.ShowPlotLines,
ShowStoryAssets = model.ShowStoryAssets,
ShowCharacterAppearances = model.ShowCharacterAppearances,
ShowWarnings = model.ShowWarnings
}, model.SelectedMetricTypeIDs);
}
private async Task<T> TimeTimelineLoadAsync<T>(string operationName, Func<Task<T>> operation, int projectId, int? bookId) private async Task<T> TimeTimelineLoadAsync<T>(string operationName, Func<Task<T>> operation, int projectId, int? bookId)
{ {
var stopwatch = Stopwatch.StartNew(); var stopwatch = Stopwatch.StartNew();
@ -1280,7 +1366,6 @@ public sealed class TimelineService(
.ToDictionary(x => x.Key, x => x.ToDictionary(point => point.SceneID)); .ToDictionary(x => x.Key, x => x.ToDictionary(point => point.SceneID));
return timeline.MetricTypes return timeline.MetricTypes
.Where(metric => DefaultGraphMetrics.Contains(metric.MetricName))
.OrderBy(metric => metric.SortOrder) .OrderBy(metric => metric.SortOrder)
.Select(metric => new MetricGraphViewModel .Select(metric => new MetricGraphViewModel
{ {

View File

@ -0,0 +1,271 @@
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
IF OBJECT_ID(N'dbo.ProjectTimelineSettings', N'U') IS NULL
BEGIN
CREATE TABLE dbo.ProjectTimelineSettings
(
ProjectTimelineSettingsID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_ProjectTimelineSettings PRIMARY KEY,
ProjectID int NOT NULL,
ShowSceneCards bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowSceneCards DEFAULT 1,
ShowMetricShape bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowMetricShape DEFAULT 1,
ShowPlotLines bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowPlotLines DEFAULT 1,
ShowStoryAssets bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowStoryAssets DEFAULT 1,
ShowCharacterAppearances bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowCharacterAppearances DEFAULT 1,
ShowWarnings bit NOT NULL CONSTRAINT DF_ProjectTimelineSettings_ShowWarnings DEFAULT 1,
CreatedDate datetime2(0) NOT NULL CONSTRAINT DF_ProjectTimelineSettings_CreatedDate DEFAULT SYSUTCDATETIME(),
UpdatedDate datetime2(0) NOT NULL CONSTRAINT DF_ProjectTimelineSettings_UpdatedDate DEFAULT SYSUTCDATETIME(),
CONSTRAINT UQ_ProjectTimelineSettings_ProjectID UNIQUE(ProjectID),
CONSTRAINT FK_ProjectTimelineSettings_Projects FOREIGN KEY(ProjectID) REFERENCES dbo.Projects(ProjectID)
);
END;
GO
IF OBJECT_ID(N'dbo.ProjectTimelineMetricSettings', N'U') IS NULL
BEGIN
CREATE TABLE dbo.ProjectTimelineMetricSettings
(
ProjectID int NOT NULL,
MetricTypeID int NOT NULL,
SortOrder int NOT NULL,
CreatedDate datetime2(0) NOT NULL CONSTRAINT DF_ProjectTimelineMetricSettings_CreatedDate DEFAULT SYSUTCDATETIME(),
CONSTRAINT PK_ProjectTimelineMetricSettings PRIMARY KEY(ProjectID, MetricTypeID),
CONSTRAINT FK_ProjectTimelineMetricSettings_Projects FOREIGN KEY(ProjectID) REFERENCES dbo.Projects(ProjectID),
CONSTRAINT FK_ProjectTimelineMetricSettings_SceneMetricTypes FOREIGN KEY(MetricTypeID) REFERENCES dbo.SceneMetricTypes(MetricTypeID)
);
END;
GO
CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_EnsureDefaults
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM dbo.Projects WHERE ProjectID = @ProjectID AND IsArchived = 0)
RETURN;
IF NOT EXISTS (SELECT 1 FROM dbo.ProjectTimelineSettings WHERE ProjectID = @ProjectID)
BEGIN
INSERT dbo.ProjectTimelineSettings
(ProjectID, ShowSceneCards, ShowMetricShape, ShowPlotLines, ShowStoryAssets, ShowCharacterAppearances, ShowWarnings)
VALUES
(@ProjectID, 1, 1, 1, 1, 1, 1);
END;
IF NOT EXISTS (SELECT 1 FROM dbo.ProjectTimelineMetricSettings WHERE ProjectID = @ProjectID)
BEGIN
INSERT dbo.ProjectTimelineMetricSettings (ProjectID, MetricTypeID, SortOrder)
SELECT @ProjectID, mt.MetricTypeID, mt.SortOrder
FROM dbo.SceneMetricTypes mt
WHERE mt.IsActive = 1
AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
AND mt.MetricName IN (N'Overall Intensity', N'Tension', N'Emotional Weight', N'Action');
END;
END;
GO
CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_Get
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
EXEC dbo.ProjectTimelineSettings_EnsureDefaults @ProjectID = @ProjectID;
SELECT ProjectTimelineSettingsID, ProjectID, ShowSceneCards, ShowMetricShape, ShowPlotLines,
ShowStoryAssets, ShowCharacterAppearances, ShowWarnings, CreatedDate, UpdatedDate
FROM dbo.ProjectTimelineSettings
WHERE ProjectID = @ProjectID;
END;
GO
CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_MetricTypes
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
SELECT MetricTypeID, ProjectID, MetricName, Description, MinValue, MaxValue, DefaultValue, SortOrder, IsActive
FROM dbo.SceneMetricTypes
WHERE IsActive = 1 AND (ProjectID IS NULL OR ProjectID = @ProjectID)
ORDER BY SortOrder, MetricName;
END;
GO
CREATE OR ALTER PROCEDURE dbo.ProjectTimelineMetricSettings_List
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
EXEC dbo.ProjectTimelineSettings_EnsureDefaults @ProjectID = @ProjectID;
SELECT ptms.ProjectID, ptms.MetricTypeID, mt.MetricName, mt.SortOrder
FROM dbo.ProjectTimelineMetricSettings ptms
INNER JOIN dbo.SceneMetricTypes mt ON mt.MetricTypeID = ptms.MetricTypeID
WHERE ptms.ProjectID = @ProjectID
AND mt.IsActive = 1
AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
ORDER BY ptms.SortOrder, mt.SortOrder, mt.MetricName;
END;
GO
CREATE OR ALTER PROCEDURE dbo.ProjectTimelineSettings_Save
@ProjectID int,
@ShowSceneCards bit,
@ShowMetricShape bit,
@ShowPlotLines bit,
@ShowStoryAssets bit,
@ShowCharacterAppearances bit,
@ShowWarnings bit,
@MetricTypeIDs nvarchar(max) = NULL
AS
BEGIN
SET NOCOUNT ON;
EXEC dbo.ProjectTimelineSettings_EnsureDefaults @ProjectID = @ProjectID;
UPDATE dbo.ProjectTimelineSettings
SET ShowSceneCards = @ShowSceneCards,
ShowMetricShape = @ShowMetricShape,
ShowPlotLines = @ShowPlotLines,
ShowStoryAssets = @ShowStoryAssets,
ShowCharacterAppearances = @ShowCharacterAppearances,
ShowWarnings = @ShowWarnings,
UpdatedDate = SYSUTCDATETIME()
WHERE ProjectID = @ProjectID;
DELETE FROM dbo.ProjectTimelineMetricSettings
WHERE ProjectID = @ProjectID;
IF @MetricTypeIDs IS NOT NULL AND LTRIM(RTRIM(@MetricTypeIDs)) <> N''
BEGIN
INSERT dbo.ProjectTimelineMetricSettings (ProjectID, MetricTypeID, SortOrder)
SELECT @ProjectID, mt.MetricTypeID, mt.SortOrder
FROM dbo.SceneMetricTypes mt
INNER JOIN
(
SELECT DISTINCT TRY_CONVERT(int, value) AS MetricTypeID
FROM string_split(@MetricTypeIDs, N',')
WHERE TRY_CONVERT(int, value) IS NOT NULL
) selected ON selected.MetricTypeID = mt.MetricTypeID
WHERE mt.IsActive = 1 AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID);
END;
END;
GO
CREATE OR ALTER PROCEDURE dbo.Timeline_GetByProject
@ProjectID int,
@BookID int = NULL,
@IncludeMetrics bit = 1,
@SelectedMetricTypeIDs nvarchar(max) = NULL,
@IncludePlotLines bit = 1
AS
BEGIN
SET NOCOUNT ON;
DECLARE @MetricSelection TABLE (MetricTypeID int NOT NULL PRIMARY KEY);
INSERT @MetricSelection (MetricTypeID)
SELECT DISTINCT TRY_CONVERT(int, value)
FROM string_split(COALESCE(@SelectedMetricTypeIDs, N''), N',')
WHERE TRY_CONVERT(int, value) IS NOT NULL;
SELECT ProjectID, ProjectName, Description, CreatedDate, UpdatedDate, IsArchived
FROM dbo.Projects
WHERE ProjectID = @ProjectID AND IsArchived = 0;
SELECT BookID, ProjectID, BookTitle, BookNumber, Description, SortOrder, CreatedDate, UpdatedDate, IsArchived
FROM dbo.Books
WHERE ProjectID = @ProjectID AND IsArchived = 0 AND (@BookID IS NULL OR BookID = @BookID)
ORDER BY SortOrder, BookNumber;
SELECT c.ChapterID, c.BookID, c.ChapterNumber, c.ChapterTitle, c.POVCharacterID, c.Summary, c.SortOrder,
c.RevisionStatusID, rs.StatusName AS RevisionStatusName, c.CreatedDate, c.UpdatedDate, c.IsArchived
FROM dbo.Chapters c
INNER JOIN dbo.Books b ON b.BookID = c.BookID
INNER JOIN dbo.RevisionStatuses rs ON rs.RevisionStatusID = c.RevisionStatusID
WHERE b.ProjectID = @ProjectID AND c.IsArchived = 0 AND b.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID)
ORDER BY b.SortOrder, c.SortOrder;
SELECT s.SceneID, s.ChapterID, s.SceneNumber, s.SceneTitle, s.Summary, s.POVCharacterID, s.PrimaryLocationID,
location.LocationName AS PrimaryLocationName, location.LocationPath AS PrimaryLocationPath,
s.SortOrder, s.TimeModeID, tm.TimeModeName, s.StartDateTime, s.EndDateTime, s.DurationAmount, s.DurationUnitID,
du.DurationUnitName, s.RelativeTimeText, s.TimeConfidenceID, tc.TimeConfidenceName, s.ScenePurposeNotes,
s.SceneOutcomeNotes, s.RevisionStatusID, rs.StatusName AS RevisionStatusName, s.CreatedDate, s.UpdatedDate, s.IsArchived
FROM dbo.Scenes s
INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
INNER JOIN dbo.Books b ON b.BookID = c.BookID
INNER JOIN dbo.TimeModes tm ON tm.TimeModeID = s.TimeModeID
INNER JOIN dbo.TimeConfidences tc ON tc.TimeConfidenceID = s.TimeConfidenceID
INNER JOIN dbo.RevisionStatuses rs ON rs.RevisionStatusID = s.RevisionStatusID
LEFT JOIN dbo.DurationUnits du ON du.DurationUnitID = s.DurationUnitID
LEFT JOIN dbo.LocationPaths location ON location.LocationID = s.PrimaryLocationID
WHERE b.ProjectID = @ProjectID AND s.IsArchived = 0 AND c.IsArchived = 0 AND b.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID)
ORDER BY b.SortOrder, c.SortOrder, s.SortOrder;
SELECT sp.SceneID, spt.ScenePurposeTypeID, spt.PurposeName, spt.SortOrder
FROM dbo.ScenePurposes sp
INNER JOIN dbo.ScenePurposeTypes spt ON spt.ScenePurposeTypeID = sp.ScenePurposeTypeID
INNER JOIN dbo.Scenes s ON s.SceneID = sp.SceneID
INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
INNER JOIN dbo.Books b ON b.BookID = c.BookID
WHERE b.ProjectID = @ProjectID AND (@BookID IS NULL OR b.BookID = @BookID)
ORDER BY spt.SortOrder;
SELECT MetricTypeID, ProjectID, MetricName, Description, MinValue, MaxValue, DefaultValue, SortOrder, IsActive
FROM dbo.SceneMetricTypes
WHERE @IncludeMetrics = 1
AND IsActive = 1
AND (ProjectID IS NULL OR ProjectID = @ProjectID)
AND (NOT EXISTS (SELECT 1 FROM @MetricSelection) OR MetricTypeID IN (SELECT MetricTypeID FROM @MetricSelection))
ORDER BY SortOrder;
SELECT s.SceneID, mt.MetricTypeID, mt.MetricName, COALESCE(smv.Value, mt.DefaultValue) AS Value, smv.Notes
FROM dbo.Scenes s
INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
INNER JOIN dbo.Books b ON b.BookID = c.BookID
INNER JOIN dbo.SceneMetricTypes mt ON mt.IsActive = 1 AND (mt.ProjectID IS NULL OR mt.ProjectID = @ProjectID)
LEFT JOIN dbo.SceneMetricValues smv ON smv.SceneID = s.SceneID AND smv.MetricTypeID = mt.MetricTypeID
WHERE @IncludeMetrics = 1
AND b.ProjectID = @ProjectID
AND s.IsArchived = 0
AND c.IsArchived = 0
AND b.IsArchived = 0
AND (@BookID IS NULL OR b.BookID = @BookID)
AND (NOT EXISTS (SELECT 1 FROM @MetricSelection) OR mt.MetricTypeID IN (SELECT MetricTypeID FROM @MetricSelection))
ORDER BY b.SortOrder, c.SortOrder, s.SortOrder, mt.SortOrder;
SELECT pl.PlotLineID, pl.ProjectID, pl.BookID, b.BookTitle, pl.PlotLineName, pl.PlotLineTypeID, plt.TypeName AS PlotLineTypeName,
pl.Description, pl.ParentPlotLineID, parent.PlotLineName AS ParentPlotLineName, pl.SortOrder, pl.Colour, pl.IsMainPlot, pl.IsVisibleOnTimeline,
pl.CreatedDate, pl.UpdatedDate, pl.IsArchived
FROM dbo.PlotLines pl
INNER JOIN dbo.PlotLineTypes plt ON plt.PlotLineTypeID = pl.PlotLineTypeID
LEFT JOIN dbo.Books b ON b.BookID = pl.BookID
LEFT JOIN dbo.PlotLines parent ON parent.PlotLineID = pl.ParentPlotLineID
WHERE @IncludePlotLines = 1
AND pl.ProjectID = @ProjectID
AND pl.IsArchived = 0
AND pl.IsVisibleOnTimeline = 1
AND (@BookID IS NULL OR pl.BookID IS NULL OR pl.BookID = @BookID)
ORDER BY pl.SortOrder, pl.PlotLineName;
SELECT te.ThreadEventID, te.PlotThreadID, pt.ThreadTitle, pt.PlotLineID, pl.PlotLineName, pl.Colour, te.SceneID, te.EventTypeID,
tet.TypeName AS EventTypeName, tet.MarkerText, te.EventTitle, te.EventDescription, te.CreatedDate, te.UpdatedDate
FROM dbo.ThreadEvents te
INNER JOIN dbo.PlotThreads pt ON pt.PlotThreadID = te.PlotThreadID
INNER JOIN dbo.PlotLines pl ON pl.PlotLineID = pt.PlotLineID
INNER JOIN dbo.ThreadEventTypes tet ON tet.ThreadEventTypeID = te.EventTypeID
INNER JOIN dbo.Scenes s ON s.SceneID = te.SceneID
INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
INNER JOIN dbo.Books b ON b.BookID = c.BookID
WHERE @IncludePlotLines = 1
AND b.ProjectID = @ProjectID
AND pl.IsArchived = 0
AND pt.IsArchived = 0
AND (@BookID IS NULL OR b.BookID = @BookID)
ORDER BY pl.SortOrder, pt.ThreadTitle, b.SortOrder, c.SortOrder, s.SortOrder;
END;
GO

View File

@ -374,6 +374,7 @@ public sealed class Phase1AcceptanceViewModel
public sealed class TimelineViewModel public sealed class TimelineViewModel
{ {
public Project Project { get; set; } = new(); public Project Project { get; set; } = new();
public ProjectTimelineSettings Settings { get; set; } = new();
public int? SelectedBookID { get; set; } public int? SelectedBookID { get; set; }
public int? SelectedSceneID { get; set; } public int? SelectedSceneID { get; set; }
public SceneEditViewModel? SelectedScene { get; set; } public SceneEditViewModel? SelectedScene { get; set; }
@ -415,6 +416,29 @@ public sealed class TimelineViewModel
public ContinuityValidationSummary? LastValidationSummary { get; set; } public ContinuityValidationSummary? LastValidationSummary { get; set; }
} }
public sealed class TimelineSettingsViewModel
{
public int ProjectID { get; set; }
public string ProjectName { get; set; } = string.Empty;
public bool ShowSceneCards { get; set; } = true;
public bool ShowMetricShape { get; set; } = true;
public bool ShowPlotLines { get; set; } = true;
public bool ShowStoryAssets { get; set; } = true;
public bool ShowCharacterAppearances { get; set; } = true;
public bool ShowWarnings { get; set; } = true;
public List<int> SelectedMetricTypeIDs { get; set; } = [];
public IReadOnlyList<TimelineMetricSettingOptionViewModel> MetricOptions { get; set; } = [];
}
public sealed class TimelineMetricSettingOptionViewModel
{
public int MetricTypeID { get; set; }
public string MetricName { get; set; } = string.Empty;
public string? Description { get; set; }
public int SortOrder { get; set; }
public bool IsSelected { get; set; }
}
public sealed class StoryBibleViewModel public sealed class StoryBibleViewModel
{ {
public Project Project { get; set; } = new(); public Project Project { get; set; } = new();

View File

@ -15,6 +15,7 @@
</div> </div>
<nav class="context-nav" aria-label="Project navigation"> <nav class="context-nav" aria-label="Project navigation">
<a asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Timeline</a> <a asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Timeline</a>
<a asp-controller="Timeline" asp-action="Settings" asp-route-projectId="@Model.Project.ProjectID">Timeline Settings</a>
<a asp-controller="Scenarios" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Scenarios</a> <a asp-controller="Scenarios" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Scenarios</a>
<a asp-controller="Writer" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Writer Workspace</a> <a asp-controller="Writer" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Writer Workspace</a>
<a asp-controller="StoryBible" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Story Bible</a> <a asp-controller="StoryBible" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Story Bible</a>
@ -42,6 +43,7 @@
<div class="button-row"> <div class="button-row">
<a class="btn btn-outline-secondary" asp-action="Edit" asp-route-id="@Model.Project.ProjectID">Edit project</a> <a class="btn btn-outline-secondary" asp-action="Edit" asp-route-id="@Model.Project.ProjectID">Edit project</a>
<a class="btn btn-outline-primary" asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Timeline</a> <a class="btn btn-outline-primary" asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Timeline</a>
<a class="btn btn-outline-secondary" asp-controller="Timeline" asp-action="Settings" asp-route-projectId="@Model.Project.ProjectID">Timeline Settings</a>
<a class="btn btn-outline-primary" asp-controller="Scenarios" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Scenarios</a> <a class="btn btn-outline-primary" asp-controller="Scenarios" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Scenarios</a>
<a class="btn btn-outline-primary" asp-controller="Writer" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Writer Workspace</a> <a class="btn btn-outline-primary" asp-controller="Writer" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Writer Workspace</a>
<a class="btn btn-outline-primary" asp-controller="StoryBible" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Story Bible</a> <a class="btn btn-outline-primary" asp-controller="StoryBible" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Story Bible</a>

View File

@ -116,6 +116,7 @@
<nav class="context-nav" aria-label="Workspace navigation"> <nav class="context-nav" aria-label="Workspace navigation">
<a asp-controller="Projects" asp-action="Details" asp-route-id="@Model.Project.ProjectID">Project</a> <a asp-controller="Projects" asp-action="Details" asp-route-id="@Model.Project.ProjectID">Project</a>
<a asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Timeline</a> <a asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Timeline</a>
<a asp-controller="Timeline" asp-action="Settings" asp-route-projectId="@Model.Project.ProjectID">Timeline Settings</a>
<a asp-controller="Scenarios" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Scenarios</a> <a asp-controller="Scenarios" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Scenarios</a>
<a asp-controller="Analytics" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Story health</a> <a asp-controller="Analytics" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Story health</a>
<a asp-controller="Warnings" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Warnings</a> <a asp-controller="Warnings" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Warnings</a>
@ -155,6 +156,7 @@
} }
<a class="btn btn-outline-secondary" asp-controller="Warnings" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Warnings</a> <a class="btn btn-outline-secondary" asp-controller="Warnings" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Warnings</a>
<a class="btn btn-outline-secondary" asp-controller="Analytics" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Story health</a> <a class="btn btn-outline-secondary" asp-controller="Analytics" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Story health</a>
<a class="btn btn-outline-secondary" asp-controller="Timeline" asp-action="Settings" asp-route-projectId="@Model.Project.ProjectID">Timeline Settings</a>
<a class="btn btn-outline-primary" asp-controller="Scenarios" asp-action="Create" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Create Scenario</a> <a class="btn btn-outline-primary" asp-controller="Scenarios" asp-action="Create" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Create Scenario</a>
<a class="btn btn-outline-secondary" asp-controller="Archives" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Archived Items</a> <a class="btn btn-outline-secondary" asp-controller="Archives" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Archived Items</a>
</div> </div>
@ -280,13 +282,12 @@
<option value="scene-detail">Scene Detail</option> <option value="scene-detail">Scene Detail</option>
</select> </select>
</label> </label>
<label><input type="checkbox" data-timeline-toggle="scene-cards" checked /> Scene cards</label> @if (Model.Settings.ShowSceneCards) { <label><input type="checkbox" data-timeline-toggle="scene-cards" checked /> Scene cards</label> }
<label><input type="checkbox" data-timeline-toggle="plot-lines" checked /> Plot lines</label> @if (Model.Settings.ShowPlotLines) { <label><input type="checkbox" data-timeline-toggle="plot-lines" checked /> Plot lines</label> }
<label><input type="checkbox" data-timeline-toggle="assets" checked /> Story assets</label> @if (Model.Settings.ShowStoryAssets) { <label><input type="checkbox" data-timeline-toggle="assets" checked /> Story assets</label> }
<label><input type="checkbox" data-timeline-toggle="characters" checked /> Characters</label> @if (Model.Settings.ShowCharacterAppearances) { <label><input type="checkbox" data-timeline-toggle="characters" checked /> Characters</label> }
<label><input type="checkbox" data-timeline-toggle="locations" checked /> Locations</label> @if (Model.Settings.ShowWarnings) { <label><input type="checkbox" data-timeline-toggle="warnings" checked /> Warnings</label> }
<label><input type="checkbox" data-timeline-toggle="warnings" checked /> Warnings</label> @if (Model.Settings.ShowMetricShape) { <label><input type="checkbox" data-timeline-toggle="metrics" checked /> Metrics</label> }
<label><input type="checkbox" data-timeline-toggle="metrics" checked /> Metrics</label>
</div> </div>
</details> </details>
@ -575,6 +576,8 @@ else
<div class="workspace-layout timeline-filtered-root @(hasSelectedScene ? "inspector-drawer-open" : "inspector-drawer-closed")" data-timeline-root> <div class="workspace-layout timeline-filtered-root @(hasSelectedScene ? "inspector-drawer-open" : "inspector-drawer-closed")" data-timeline-root>
<main class="timeline-workspace"> <main class="timeline-workspace">
<section class="timeline-shell workspace-timeline" data-timeline-section="scene-cards" style="--scene-count:@timelineColumns.Count"> <section class="timeline-shell workspace-timeline" data-timeline-section="scene-cards" style="--scene-count:@timelineColumns.Count">
@if (Model.Settings.ShowSceneCards)
{
<div class="timeline-section-header" data-collapse-target="scene-cards"> <div class="timeline-section-header" data-collapse-target="scene-cards">
<button type="button" data-collapse-toggle="scene-cards">Scene Cards</button> <button type="button" data-collapse-toggle="scene-cards">Scene Cards</button>
<span>@Model.OrderedScenes.Count scene@(Model.OrderedScenes.Count == 1 ? "" : "s")</span> <span>@Model.OrderedScenes.Count scene@(Model.OrderedScenes.Count == 1 ? "" : "s")</span>
@ -659,13 +662,16 @@ else
<span class="scene-pov-label">@povLabel</span> <span class="scene-pov-label">@povLabel</span>
<div class="scene-badge-row"> <div class="scene-badge-row">
<span class="status-pill">@scene.RevisionStatusName</span> <span class="status-pill">@scene.RevisionStatusName</span>
@if (scene.WarningCount > 0) @if (Model.Settings.ShowWarnings)
{ {
<span class="warning-placeholder active" data-warning-marker>@scene.WarningCount warning@(scene.WarningCount == 1 ? "" : "s")</span> if (scene.WarningCount > 0)
} {
else <span class="warning-placeholder active" data-warning-marker>@scene.WarningCount warning@(scene.WarningCount == 1 ? "" : "s")</span>
{ }
<span class="warning-placeholder">Warnings 0</span> else
{
<span class="warning-placeholder">Warnings 0</span>
}
} }
@if (scene.DependencyCount > 0) @if (scene.DependencyCount > 0)
{ {
@ -704,6 +710,9 @@ else
</div> </div>
</div> </div>
</div> </div>
}
@if (Model.Settings.ShowMetricShape)
{
<div class="metric-timeline-board" data-timeline-section="metrics" style="--scene-count:@timelineColumns.Count"> <div class="metric-timeline-board" data-timeline-section="metrics" style="--scene-count:@timelineColumns.Count">
<div class="lane-board-heading metric-lane-board-heading"> <div class="lane-board-heading metric-lane-board-heading">
<button type="button" data-collapse-toggle="metrics">Metric Shape</button> <button type="button" data-collapse-toggle="metrics">Metric Shape</button>
@ -777,9 +786,12 @@ else
} }
</div> </div>
</div> </div>
@if (Model.PlotLanes.Any() && Model.OrderedScenes.Any()) }
@if (Model.Settings.ShowPlotLines)
{ {
<div class="plot-lane-board" data-timeline-section="plot-lines" style="--scene-count:@timelineColumns.Count"> if (Model.PlotLanes.Any() && Model.OrderedScenes.Any())
{
<div class="plot-lane-board" data-timeline-section="plot-lines" style="--scene-count:@timelineColumns.Count">
<div class="lane-board-heading plot-lane-board-heading"> <div class="lane-board-heading plot-lane-board-heading">
<button type="button" data-collapse-toggle="plot-lines">Plot line lanes</button> <button type="button" data-collapse-toggle="plot-lines">Plot line lanes</button>
<small>Thread event markers by scene</small> <small>Thread event markers by scene</small>
@ -838,17 +850,20 @@ else
</div> </div>
} }
</div> </div>
</div> </div>
}
else
{
<div class="future-lane-placeholder">
Add visible plot lines and thread events to see narrative lanes here.
</div>
}
} }
else @if (Model.Settings.ShowStoryAssets)
{ {
<div class="future-lane-placeholder"> if (Model.AssetLanes.Any() && Model.OrderedScenes.Any())
Add visible plot lines and thread events to see narrative lanes here. {
</div> <div class="asset-lane-board" data-timeline-section="assets" style="--scene-count:@timelineColumns.Count">
}
@if (Model.AssetLanes.Any() && Model.OrderedScenes.Any())
{
<div class="asset-lane-board" data-timeline-section="assets" style="--scene-count:@timelineColumns.Count">
<div class="lane-board-heading asset-lane-board-heading"> <div class="lane-board-heading asset-lane-board-heading">
<button type="button" data-collapse-toggle="assets">Story asset lanes</button> <button type="button" data-collapse-toggle="assets">Story asset lanes</button>
<small>Asset event markers by scene</small> <small>Asset event markers by scene</small>
@ -902,17 +917,20 @@ else
</div> </div>
} }
</div> </div>
</div> </div>
}
else
{
<div class="future-lane-placeholder">
Add story assets and asset events to see asset lanes here.
</div>
}
} }
else @if (Model.Settings.ShowCharacterAppearances)
{ {
<div class="future-lane-placeholder"> if (Model.CharacterLanes.Any() && Model.OrderedScenes.Any())
Add story assets and asset events to see asset lanes here. {
</div> <div class="character-lane-board" data-timeline-section="characters" style="--scene-count:@timelineColumns.Count">
}
@if (Model.CharacterLanes.Any() && Model.OrderedScenes.Any())
{
<div class="character-lane-board" data-timeline-section="characters" style="--scene-count:@timelineColumns.Count">
<div class="lane-board-heading character-lane-board-heading"> <div class="lane-board-heading character-lane-board-heading">
<button type="button" data-collapse-toggle="characters">Character appearances</button> <button type="button" data-collapse-toggle="characters">Character appearances</button>
<small>All project characters, grouped by role and activity</small> <small>All project characters, grouped by role and activity</small>
@ -971,13 +989,14 @@ else
</div> </div>
} }
</div> </div>
</div> </div>
} }
else else
{ {
<div class="future-lane-placeholder"> <div class="future-lane-placeholder">
Add characters to scenes to see character appearance lanes here. Add characters to scenes to see character appearance lanes here.
</div> </div>
}
} }
</section> </section>
</main> </main>

View File

@ -0,0 +1,130 @@
@model TimelineSettingsViewModel
@{
ViewData["Title"] = "Timeline Settings";
}
<nav class="breadcrumb-trail" aria-label="Breadcrumb">
<a asp-controller="Projects" asp-action="Index">Projects</a>
<a asp-controller="Projects" asp-action="Details" asp-route-id="@Model.ProjectID">@Model.ProjectName</a>
<a asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.ProjectID">Timeline</a>
<span>Timeline Settings</span>
</nav>
<section class="context-header">
<div class="context-title">
<span class="eyebrow">Display configuration</span>
<strong>@Model.ProjectName</strong>
</div>
<nav class="context-nav" aria-label="Timeline settings navigation">
<a asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.ProjectID">Open timeline</a>
<a asp-controller="Projects" asp-action="Details" asp-route-id="@Model.ProjectID">Project</a>
</nav>
</section>
<div class="page-heading compact">
<div>
<p class="eyebrow">Timeline Settings</p>
<h1>Configure timeline display</h1>
<p class="lead-text">Choose which workspace sections PlotLine loads and renders for this project. Filters and saved views still work separately.</p>
</div>
</div>
@if (TempData["TimelineSettingsMessage"] is string message)
{
<div class="alert alert-info">@message</div>
}
<form asp-action="Settings" method="post" class="timeline-settings-form">
<input type="hidden" asp-for="ProjectID" />
<input type="hidden" asp-for="ProjectName" />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<section class="story-bible-section timeline-settings-section">
<div class="story-bible-section-heading">
<div>
<p class="eyebrow">Sections</p>
<h2>Workspace sections</h2>
</div>
</div>
<div class="timeline-settings-grid">
<label class="timeline-setting-card">
<input asp-for="ShowSceneCards" />
<span>
<strong>Scene Cards</strong>
<small>Shows books, chapters and scene cards in narrative order.</small>
</span>
</label>
<label class="timeline-setting-card">
<input asp-for="ShowMetricShape" />
<span>
<strong>Metric Shape</strong>
<small>Shows emotional and pacing metrics beneath the scene timeline.</small>
</span>
</label>
<label class="timeline-setting-card">
<input asp-for="ShowPlotLines" />
<span>
<strong>Plot Lines</strong>
<small>Shows plot thread activity across the scene timeline.</small>
</span>
</label>
<label class="timeline-setting-card">
<input asp-for="ShowStoryAssets" />
<span>
<strong>Story Assets</strong>
<small>Shows clues, objects, evidence and state changes by scene.</small>
</span>
</label>
<label class="timeline-setting-card">
<input asp-for="ShowCharacterAppearances" />
<span>
<strong>Character Appearances</strong>
<small>Shows which characters appear in each scene.</small>
</span>
</label>
<label class="timeline-setting-card">
<input asp-for="ShowWarnings" />
<span>
<strong>Warning Indicators</strong>
<small>Shows continuity warning counts and warning-focused timeline cues.</small>
</span>
</label>
</div>
</section>
<section class="story-bible-section timeline-settings-section">
<div class="story-bible-section-heading">
<div>
<p class="eyebrow">Metric Shape</p>
<h2>Timeline metrics</h2>
</div>
<span class="soft-count">@Model.MetricOptions.Count metrics</span>
</div>
<p class="muted">These metrics appear on the timeline graph only. Story Health can continue using the full metric set.</p>
<span asp-validation-for="SelectedMetricTypeIDs" class="text-danger"></span>
<div class="timeline-settings-grid timeline-metric-settings-grid">
@foreach (var metric in Model.MetricOptions)
{
<label class="timeline-setting-card metric-setting-card">
<input type="checkbox" name="SelectedMetricTypeIDs" value="@metric.MetricTypeID" checked="@metric.IsSelected" />
<span>
<strong>@metric.MetricName</strong>
@if (!string.IsNullOrWhiteSpace(metric.Description))
{
<small>@metric.Description</small>
}
</span>
</label>
}
</div>
</section>
<div class="button-row">
<button class="btn btn-primary" type="submit">Save settings</button>
<a class="btn btn-outline-secondary" asp-action="Index" asp-route-projectId="@Model.ProjectID">Back to timeline</a>
</div>
</form>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

View File

@ -870,6 +870,62 @@ a:focus-visible {
background: rgba(122, 77, 44, 0.1); background: rgba(122, 77, 44, 0.1);
} }
.timeline-settings-form {
display: grid;
gap: 1rem;
max-width: 1180px;
}
.timeline-settings-section {
display: grid;
gap: 0.85rem;
}
.timeline-settings-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 0.75rem;
}
.timeline-setting-card {
display: grid;
grid-template-columns: auto minmax(0, 1fr);
gap: 0.72rem;
align-items: start;
min-height: 92px;
border: 1px solid rgba(84, 68, 48, 0.13);
border-radius: var(--plotline-radius-sm);
padding: 0.85rem;
background: rgba(255, 253, 248, 0.82);
box-shadow: var(--plotline-shadow-subtle);
cursor: pointer;
}
.timeline-setting-card input {
margin-top: 0.25rem;
accent-color: var(--plotline-secondary);
}
.timeline-setting-card strong,
.timeline-setting-card small {
display: block;
}
.timeline-setting-card strong {
color: #211915;
}
.timeline-setting-card small {
margin-top: 0.25rem;
color: var(--plotline-text-muted);
line-height: 1.4;
}
.timeline-setting-card:has(input:checked) {
border-color: rgba(49, 95, 103, 0.25);
background: linear-gradient(135deg, rgba(223, 236, 239, 0.52), rgba(255, 253, 248, 0.92));
}
.plotline-confirm-modal .modal-title { .plotline-confirm-modal .modal-title {
font-family: Georgia, "Times New Roman", serif; font-family: Georgia, "Times New Roman", serif;
} }