Drag and drop

This commit is contained in:
Nick Beckley 2026-06-03 13:42:01 +01:00
parent 5b189fa9bb
commit b96e295f53
52 changed files with 838 additions and 174 deletions

View File

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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

@ -1,5 +0,0 @@
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==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRTTW/UMBD9K5HP69R2HCfOrdqCWBXoClaAuE08E2o1dVaOU0DV/nfk7CIoNy6WNfKbeR/jZxbgkVjHro/HV08U0sw2LPm1pIQyXBguqoNUnWg6pUrRVE1jm69sw/wt/WQda7Rz0lniFRniGkXN+2pwHJGsFBKFqnXuCd9m1j0z8CXSk3dUTvMnirOfAuvYZx9w+p5ngy/dOC1YxmmkXZgTBJfJvN9tb/nb6/3hbn9+NdOcwaVH1rG2r6zswXLqXc+1bomDdooPvR5AtAJFk0mAL31IFAOM5YwPf+bjlAIl16lSVaXgyrLThiEkyJR7mOnw85hZrBbd5PpmLa/X7pk9UWSd2vw289zuyo3+6nHuFz/i1flMMD9klcc4HSkmT6snq8xxhOSnUFwmbUdPIbENu/tY7EdIwxQfXxj18ax/9x/yD3n6qx/klkS4nZaQWMeklmzD3oG794GK3Q3rmJCksGqJD0oarlsEDnVluTGVGUg626iM2U4h+bBMy1zsQqJvcRXAOvYaxpnO1K+ju/eJXFpiVvXFZB77OOHiUvHHfylKUVZCZNCSjksqPhD6SC5R1neIy6XfPxBl1AraLjFSSMUe0n3xBuZ71jELrZNgwQIY5waqBQ0CBRjRIBk0hFphg9pqNNoKZzT0UiPUsh9yhW0Y5biLdcN05SoLBnjfC+C6R+J9IxzXUhlraiNq4174WNyNGQeuFZqw4pYG5NpK4FZXFceqhkaZoWnU8Jcll/SlyAYjPZ3/ysrAILaERnKlZc21tZK3tm5437S97U1LtcucbykGGv8y6p13cZqnIRWX5SleWPdhCfm/F+siffeB/1gzupncA8UiZww+5PW+xHo6nU6/AAAA//8DAByDI8o2BAAA

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSTwW7cOAyGX8XQ2XIkWZYt34LJLjpIuxm0QVv0Rot0R6gjD2Q5bRHMuy/kmSLt3vYm/BLJjz+pFxbgiVjPbk+nv54ppIWVLPlNUkIZLgwX9aNUvWh7pSrRmrpT8gsrmb+nn6xnrXZOOku8JkNco2j4UI+OI5KVQqJQjc454evC+hcGvkJ69o6qeflIcfFzYD375APO33Nt8JWb5hWrOE+0D0uC4DLMP/vdPX97e3h8OFxeLbTk4Moj61k31FYOYDkNbuBad8RBO8XHQY8gOoGizRDgKx8SxQBTteC31/o4p0DJ9apSdSW4suxcMoQEGXmAhR5/njLFZtFd1stN3o79C3umyHpV/jLzku7GTf7GzU9PEPBm9MEvR1ayU5xPFJOnzY6tw2mC5OdQXIvsJk8hsZI9fCgOE6Rxjk9/ePTh0vr+f3T+DtzRByr2d6xnQpLCuiM+Kmm47hA4NLXlxtRmJOlsqyQr2W4OyYd1XpdiHxJ9jRsl69nfMC104buN7ugTubTGjP7Z5GL0w6fdjFkQrGSHOOPqUvFqtxSVqGqRLx/WdFpT8Z7QR3KJck+Pcb2m/0+IMmoL2q0xUkjFAdKxeAPLkfXMQuckWLAAxrmRGkGjQAFGtEgGDaFW2KK2Go22whkNg9QIjRzGrGTuPN1iW6hmEOBsp7mzznHdWOTWAXA3CNs2Cgx0GfHV1uJhynHgOqEJa25pRK6tBG51XXOsG2iVGdtWjb9Zcp24FNlvpOfL19gIDGJHaCRXWjZcWyt5Z5uWD2032MF01LjMfE8x0PSbUe+8i/Myj6m4Lkzxh3Xv15C/d7Etz3cf+I9tZHez+0axyCMHH/I2X6d8Pp/P/wIAAP//AwBVXz3zJQQAAA==

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUTW/cNhCG/4rAsyjzm6Juht2iCzf1Il60QW8UZxQL0VILito0MPa/F9Rukbi33ISBZvjOM+/MG4n+iKQj96fTL2eMeSE1yeMWEkwYygxl8sBFx9qOs0YwI1vp/iY1GZ/wG+mIVSHw4JBKNEgVME17OQQKgI4zDkxoVWr6zwvp3ogfG8DzGLCZlz8xLeMcSUf+GiPMX8vbfmzCNK/QpHnCXVyyj6GI+WP38ER/v98fnvfXvxZcSnIzAulI0NKjVkAd2J4qDj3tVdtTBlI63jKPwl7TxpgxRT81C3z5/j7MOWIOnWiEbBgVjlxqAj77Irn3Cx6+nYqKDdFjiddbePvs3sgZE+lE/R/Ma7m7MI13y9pPeMbp5NOC6S7Mx6OPQGpySvMJUx5xw3LG1M/LmAvREKxvW86h9VZpC63UQlqQDKFlVoMD540ygwhaD9C3zqpBgeAKDCrVl0Y3cNPk8zjH6qb9YRoxZlKT55dqP/k8zOn4Dv3LlejuJ4AW2aQjkmlprEUlpfTO9IIhWBOMEX3wzA69QB6Qaaes45Zx6QRzUhvbWvDMBVKTDz68jhGr3SPpCOMoQLZIB8ENVS146rV01BhpBuTBWcFJTR7mmMe4zutS7WLGz2nrl3TkVz8teO30PoXXMWPIayoQPplixn2aYQ25+m4AzhrWSMZK0ppPa64+IowJQ8aC45DWW73/pQgjtqSHNSWMudr7/Fr95pdX0hHn28C98857E8KAmuHAgHnDLKABg6AEWFBOgVGOBaN8zxV4zfuhREhNsPit2izOJfYtd5YiV5wq2w60N5ZTjm5AXfYS/TuO1fNU8nxomUKQ1OEAVDnuqVNSUpDaW2EGa8XwA5KbWTgrgAHP12XdFBiAFsFwKhTXVDnHaeu0pb1te9ebFnUomp8wRZx+APVhDGle5iFXN69V79B9XGM5ONXmu69jpP9sM3qcwxdMVZmxH2PZr9tYLzU5ol/WhMftXnVvZF+WqzpsZ0vwRiuha/KSfcrr6RaWtpFOqcvlcvkXAAD//wMAUD50S/QEAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUTW/cNhCG/4rAsyjzS6Som2G3qOumXsSLtOiN5IxsIVpqQVGbBsb+94DaDRL31psw0DszfOadeSPRHZD05PZ4/OWEMS+kJnncQoIJTZmmTO656FnXc9ZwI5VQ8h9Sk/ERv5KeGBUCDxapRI1UAWupl0OgAGg548BEq0pO97KQ/o24sQE8jQGbefmEaRnnSHry1xhh/lJqu7EJ07xCk+YJH+KSXQylmT8f7h7pH7e7/dPu8teCSxE3I5CehFY6bBVQC8ZTxcFTrzpPGUhpecccCnORjTFjim5qFvj8oz7MOWIOvWiEbBgVlpxrAi670rJ3C+6/HksXG6L7Eq+38PbZv5ETJtKL+jvMS7qbMI03eT5OeMLp6NKC6SbMh4OLQGpyTPMRUx5xw7K9dJpcHudYXYvdTSPGTGry9FztJpeHOR3esXq+IHj4HwROmDzpiWSt1MagklI6q71gCEYHrYUPjpnBC+QBWWuVsdwwLq1gVrbadAYcs4HU5GWavZt+XzZ+VjDfATNCC1RohdLaBoayw6E1yMBp7XUXLMjOCNVBJ511jluPJlgdikE+uPA6Rqwe7klPGEcBskM6CK6p6sBR10pLtZZ6QB6sEZzU5G6OeYzrvC7VQ8z4kjZ+pCe/umnBC7nbFF7HjCGvqUD9W5diuzTDGnL1wwGcNayRjBXRmo9rrj4ijAlDxoJ3n9Zrvv9IhBab6G5NCWOudi6/Vr+55bVQcV3gzpan6hAGbBkODJjTzABq0AhKgAFlFWhlWdDKea7AtdwPJUJqgsVw1eZxLblnMgzUc2sKE6RedoyCYq0QXniv2TuO1dNUdC50TCFIanEAqix31CopKcjWGaEHY8TwE5Kr+TgrgAFPl229dADQIWhOheItVdZy2tnWUG86b73usA2l50dMEaefQH0YQ5qXecjV1bvVO3Qf11guTrX5+MsY6b/bjO7n8BlTVWbsxlgW7DrWc00O6JY14WE7WP0b2ZXtqvbb3RK8aZVoa/KcXcrr8RqWppFWqfP5fP4GAAD//wMAdisCNPUEAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACoxUS2/bOBD+KwLPpkJSFCUK2IPhtFgjTWMk7u5ibxQ5jInIokFRToMi/31BWa6dooe9CaN5fY/hD9SrPaAGLQ+HT0fo44AWKLopxAgTmAhMii1lDakbSvKy4qSS9F+0QO4O3lCDKq411RJwAQIwN6TEbWE1NgYkJdQQVvLUUz0PqPmBlMsNHJ2G3A9/QRic71GD/na98a9ptnK57vxo8uA7WPdDVL1Oy3xdr+7wl+Vm+7A5ZQ0wpOLcGdQgXRYKSm6wNFWLOTUtbnndYmKKQtKaKGDVqcz1EUKvunwwL5f5xsceom5YzoqcYCbR+wIZFVVauVUDbN8OaYuJotsUX0zh6bP5gY4QUMMWZzJP7W505272Qzu6ztxEFZ4h2qD28OrDCxxVhxboEPwBQnQwcfPwlF1WoiQnOROMELRA90rvXA/Z+jZ76BJgpWvCwRRYgjWYS6qw5EWBTVGqiglbVcyiBbqD0EN31fXe6eAHb2M2U559mLPyfXT96MchW/cRnoOKp7rPqhsALdBmbDs37B5BmbetfxzTv37sEpbVGAL0MduouMv+VMMONUiqWlMllVRKaG2hJGCJIUqQyoAwAgxnpjJcciO4JFpw1VJuVElbmyJogR7GeBjjmf/vV0tsg9vvwVw22E4cbzoVrQ/7tYE+OuuSNOeMyVBdN6HK5p6rzkEfP5CMGkQoMFPUgC2jAvPaKKzKQmIhCmGBalkxeiLMuufxJ0/EWsMLW9a1aGVLCTBb1ZxUtiVG20JLU7ZQsYpUNdRSE9KWnNat1MQALblJ6II3o46/WqGYBHoc+3Sd2TrBfnU9/i74hZFN8NFr3yXBXAdPb0OE/e9UW/n9wQ8uJvx2lvbbAPe+T3/n+585m4uXPl5ikO4gm06PSQaFMC0ubCEwL1qLaysFVpyyumZlIblGC3Tr9QuELBlMuX7S5Oyph6dsGfTORdBxDGnyPxOok5yfzydz4SP/+mm78gGWh8Nijv5xTCSdmp0N8OFd+Tak9J0f4hXkGdoTdPa82JWdDBxPT5VLQWFMDUZQzDgtMZeS4lqWFW6rupWtqKHUF7tmj2BcAB2nftswpmkzs7/z5TJEZ5WOQzqeL15Pdpr9Oaf8uuSVbD+rT8OvpJutNHeiJFn26fRwTg76X+/m+/v7+38AAAD//wMAvph9rCgGAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpSUXW/jKBSG/4rFtXEBY2x81013tFGn02ianV3tHYbjFNWBCHBnqyr/fYSTqumM9mLvrGPe8/GcF16RU3tAPbo+HH5/BpciKlGyS4gRJjARmNRbynrS9ZRUrOas5fQfVCJ7Cy+oRy3XmmoJuAYBmBvS4KEeNTYGJCXUENbwnFPtIupfkbKVgWerofLxG4RovUM9+ss647/n2spWevKzqYKfYO1iUk7nZr6sV7f48/Vme785nYoQs7iyBvVIN7WChhssTTtgTs2AB94NmJi6lrQjClh7klmXIDg1VdE8vdc3PjlIumcVqyuCmUTHEhmVVG55UBG2L4fcxYLoJsfLJbx89q/oGQLqWfkG85TuSk/2ah+H2U7mavK7nXW7lXej3c1BpVy4RIfgDxCShQXOb9ap8PLZ73Y5H/qkpgioRFsIe+vUdPpxA6Oap/Tg57CQiebpv86gHqk5eVSiheQ0LWWL8zCryYJLv2gvCt8/FJtJpdGH/YclPZzYr/8H+julH62DYn2DekQoMFN3gEdGBeadUVg1tcRC1GIEqmXLKCrRyrtk3eznWKxdgt2Z2of+roN+tAl0mkOe6W+RzbYJ3sw6Fe8LpqQiVU1IFs3pMKfiKxgbQCfIQ2zDfM73k4QJtog+2Ql+wbOaQwCXio1Kj8UfKj6iHknVaaqkkkoJrUdoCIzEECVIa0AYAYYz0xouuRFcEi24Gig3qqHDmCOoRJBNViy+HnQzjGJguIaxxVxojgcpNVZCt11HJe2o+AC3uJ+yTumOcDA1ljAazCVVWPK6xqZuVMvE2LZsvOB0NgQlmfqlCf+MYM5e+nKy9tvsBp5P93jpUxjTgREUM04bzKWkuJNNi4e2G+QgOmh0nmzlXfRvIL9BGHy0KT8id9bZvZp+PvK+mVsIDqaL7dxZHXz0YyrOtiw+7Ovr7PIrViwW/W4d/ncxxo3XTxCKbCxl3cUyj8fj8QcAAAD//wMA8IdRlQwFAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACoxU227cNhD9FYGvFRXeRJF6c20HXaSOjeyiLfo2JEc2a5laUJSTwPC/F9LauaJAXwRhSM45c+bMPJEED0h6cnY8Xj5iKjOpSYlbSDChKdOUyQMXPTM95w23nCvb/U1qEt/hZ9KTTnnPvUUqUSNVgbXUycHTENByxgMTrVpzwu1M+icCsQn4GD020/wH5jlOifTkz5jC9HHFhtj4cVpCk6cRd2kukPxK5v3u/B39/ezmcH1zujXjvD5uYiA98a0EbFWgNnSOKh4cdco4yoKUlhsGKLrTs5gK5gRjM4f7r/hhKgmL70UjZMOosOS5JgEKrJQdzHj4fFxZbBJdrPF6C2+//RN5xEx6Ub+KeUr3xo/xzcPsljiGN9uX1OSYpyPmEnFT43pffSXBWcMaoQVjpCZX4O9iwmp3UV2Pa4ngDVMYJLU4BKosB2qVlDTIFjqhh64TA6nJO8wJx2+yXkWfp3kaSvUicvUdzv7s/DKBG3HFeAvjjKQmu3lfIAUYp4SXn9Av5ZTrkJf1+HxKJaZlWuZqlwreZng5f31/vuSMqVQ3UO6q32C+Iz2xYDwHCxZAez9gy3BggYFmXUAdNAYlQheUVUEry7xW4LgK0HI3rBFSk19XDfeL9zjPX9lsJhnHjUP10qfzMWIq38lIesI4iiAN0kFwTZUJQKGVlmot9YDc207wV5gD5FsspCeDcc4x751QlnsQFmQYmAx6sEJ0HahBtp0SWresAx+6TnAVZIce5CCZEaQmN3kKiy8/tlpuDbjJ0z/oyyoV6YlmbWs8OCe04gasQcW1MtpiZ9UATEnvgLcGnOMMWuatER64tqBcaIcvKl2m25jwIs7HET5/g2sa3chfPIDhA6gfrr/N8IAfp3z//mTj5v3lgdTkw5LWjVDtVot8jIl+0utEXy1jiYe7jBAwXE0Bf/YRruNSnSaUW9SiU7RToqXKDJYacIy2zPFWGtcalKQmF5O/x1ytDoOY1qn6kux6X51lfxcL+rLkld9fG4/rfXUzQhmm/PDdJvmmsB8FaITkbO1MwMfTNto46hAMBs2pULylylpOjW076jrjrNMGW78qdr2U41KqDxhiRl+2il+8uGGe36G//1mMVxe8WJSz1Wv70xbbpP1fS+y5Jg8I85LxYdvW/RPZpYR5Q75YTqO4S1dxHOOMfkphJr3VurGGiReC/3WNMy6ajmn7/Pz8/C8AAAD//wMAfy8DGxoGAAA=

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRUTW/bOhD8KwLPpsIvUaJugdPiGXltjNZoi94o7qoholAGSaUNAv/3grKLNKeHdyGIFWc5OzPUCwn2EUlPro/Hd08YciIbkv1aEkxoyjRl8sBFz7qe85p3bcNa/p1siL/FZ9KTVjnHnUEqUSNVwBo6yNFRADSccWCiUaWn/ZFI/0KsrwGfvMN6Tl8wJj8H0pOvPsD8s9xtfe2meYE6zhPuQso2uELm4257S/+93h/u9udTCVMB1x5IT1wjLTYKqIF2oIrDQAfVDZSBlIZ3zKJozzAfMsZgpzrBw+v9MOeA2fWiFrJmVBhy2hCw2RbKg014eD4WFqtEN6W+Wcvrtn8hTxhJLzZ/xDy3u3KTv3pMw+InuDqv2aaHtK6jdXmOz2RDjnE+YsweV32uU8LHYXo+2PTw/nymbNO7X+iWjLCdl5BJT7gsA60CTZPNfg7VheN28hjy+jFHH5J3/9VLkg25+1ztJ5vHOT6+8ePzWebd/1D5g3X3PmC1uyE9YRwFyA7pKLimqgNLbSMN1VrqEbkzreBkQ7ZzyD4s85KqXcj4I64jkZ68t1PCM7/r6O59RpeXWOb8pkuu9nGGxeXq1UvOalZLxgpoycclV58QfESXsQxxiMul35e3EKHFCtouMWLI1d7m++ofm+5JT4ztHLfGGmu1cyM2DEcGzGrWAmrQCEpAC8oo0Mowp5UduALb8GEsFbIhWKJTrWmV3WAGJQU1IJEqaxvaoRkoDlpjiy1XvBB51bG6mwrOuo4pBEkNjkCV4ZYaJSUF2dhW6LFtxfiXJJc8cFYEBnw6v7uVgQboEDSnQvGGKmM47UzT0qEt1HSHjSucbzEGnP4S6oN3cU7zmKtLQqo30n1aQvl3VGtafvpAf60e3czuAWNVPLY+lKdysfV0Op1+AwAA//8DAIAUdzaCBAAA

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRTwW7cNhD9FWHOokxSFCXqZqxTdOEmXiSLtOiN4oxiwjK1oCgngbH/HlC7QeLeeiGIAd/Me28eXyHYZ4Iebk+ndy8U0gIlJL+VJJeacc14fRSy510vRCU6U0vV/Qsl+Hv6Dj20yjnhDLGaNDGFvGFDPTqGSEZwgVw2Kve0XxboX8H6CunFO6rm5TPFxc8BevjbB5y/5tnWV26aV6ziPNE+LMkGl8l82O/u2V+3h+PD4fJqoSWDK4/Qg2tqS41CZrAdmBI4sEF1A+NY10Z03JJsLzAfEsVgp2rBp1/zcU6BkutlJeuKM2ngXALaZDPlwS50/H7KLDaL7nK93MrbtX+FF4rQy/KnmZd2N27yN8/LsPoJby5nsstTVnmK84li8rR5ssmcJpv8HIrrpN3kKSQo4eFTcZhsGuf4/MaoTxf9+/8h/5inv/tGbk2Eu3kNCXoQikMJ76179IGK/R30wAVJrDtioxSaqQ4ts01tmNa1Hkk400oBJezmkHxY53Up9iHRl7gJgB7+sNNCF+q30T36RC6tMav6R+csHOKMq0vFL/8Fr3hV88zkYU2nNRUfCX0klyjrO8b12u8/EKnlBtqtMVJIxcGmx+JPuzxCD8Z2TlhjjbXauZEaTiNHbjVvkTRqQiWxRWUUamW408oOQqFtxDDmCpRAed3FljDsmsE41zBRY8uUVpYNshFMkhxpGFEM9Vsfi4cp46zruCKsmaERmTLCMqPqmmHd2FbqsW3l+Jsl1+0Lng1Gern8lY2BRuwItWBSiYYpYwTrTNOyoe0GM+iOGpc531MMNP1m1Hvv4rzMYyqu4SneWPdxDfm/F1uQvvrAvm07upvdE8Ui79j6kON9Xev5fD7/AAAA//8DAFPJlSU2BAAA

View File

@ -0,0 +1,5 @@
https://dc.services.visualstudio.com/v2/track
Content-Type:application/x-json-stream
Content-Encoding:gzip
H4sIAAAAAAAACpRTy27cOBD8FYFnUeZLlKibMd5FBk7Wg8RIFnuj2K0MEZkcUJSTwJh/X1AzQeLcciOKrO7qquYLCfYJyUBuT6e/njHkhdQk+w0STGjKNGXykYuB9QPnDTe87aX8j9TE3+N3MpBOOcedQSpRI1XAWjrKyVEANJxxYKJVpab9vJDhhVjfAD57h01cPmJafAxkIJ98gPi19La+cXNcoUlxxn1Ysg2uiPlnv7unb28Pjw+Hy6sFl0JuPJCBuFZabBVQA91IFYeRjqofKQMpDe+ZRdFdaD5kTMHOzQJffvaHmANmN4hGyIZRYci5JmCzLZJHu+Dj91NRsVl0V/B6g7fj8EKeMZFB1D/MvJS7cbO/cfHpyQa4mXzwy5HU5JTiCVP2uNmxTTjPNvsYqmuT3ewxZFKThw/VYbZ5iunplUcfLqPv/2Dyd9YdfcBqf0cGwjgKkD3SSXBNVQ+W2lYaqrXUE3JnOsFJTXYxZB/WuC7VPmT8nDaVZCB/23nBi77b5I4+o8trKtL/1SVr/ObzLkIBGKnJIUVYXa5+2s1ZwxrJyuXDmk9rrt4j+IQuY5npMa3X8r9RhBYbabemhCFXB5uP1Ru7HMlAjO0dt8Yaa7VzE7YMJwbMatYBatAISkAHyijQyjCnlR25AtvycSpI0V3SrbaFGpXU3eSAWpAjVc6NdGRtT7FTLWMgrOzGV7ZWD3PhWdczhSCpwQmoMtxSo6SkIFvbCT11nZh+seSaOGfFb8Dny9fYFGiAHkFzKhRvqTKG0960HR27fjSj7rF1RfM9poDzL0a98y7FJU65ui5M9cq692so37valuerD/TbFtlddF8wVSVy60PZ5mvK5/P5/D8AAAD//wMAsOqwDyUEAAA=

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

@ -107,7 +107,7 @@ public sealed class TimelineController(ITimelineService timeline) : Controller
{
TempData["TimelineDragMessage"] = $"Scene moved. Validation found {summary.WarningCount} warning{(summary.WarningCount == 1 ? "" : "s")}.";
}
return RedirectToAction(nameof(Index), new { projectId = model.ProjectID, bookId = model.BookID, selectedSceneId = model.SceneID });
return RedirectToAction(nameof(Index), new { projectId = model.ProjectID, bookId = model.BookID, selectedSceneId = model.ReturnSelectedSceneID });
}
[HttpPost]

View File

@ -321,7 +321,8 @@ public sealed class LocationRepository(ISqlConnectionFactory connectionFactory)
location.ParentLocationID,
location.LocationName,
location.LocationTypeID,
location.Description
location.Description,
location.ShowInQuickAddBar
},
commandType: CommandType.StoredProcedure);
}
@ -1696,7 +1697,8 @@ public sealed class AssetRepository(ISqlConnectionFactory connectionFactory) : I
asset.Importance,
asset.CurrentStateID,
asset.CurrentLocationID,
asset.IsResolved
asset.IsResolved,
asset.ShowInQuickAddBar
},
commandType: CommandType.StoredProcedure);
}
@ -1884,6 +1886,7 @@ public sealed class CharacterRepository(ISqlConnectionFactory connectionFactory)
character.Height,
character.EyeColour,
character.CharacterImportance,
character.ShowInQuickAddBar,
character.DefaultDescription
},
commandType: CommandType.StoredProcedure);

View File

@ -353,6 +353,7 @@ public sealed class StoryAsset
public string? CurrentLocationName { get; set; }
public string? CurrentLocationPath { get; set; }
public bool IsResolved { get; set; }
public bool ShowInQuickAddBar { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; }
public bool IsArchived { get; set; }
@ -490,6 +491,7 @@ public sealed class Character
public string? Height { get; set; }
public string? EyeColour { get; set; }
public int? CharacterImportance { get; set; }
public bool ShowInQuickAddBar { get; set; }
public string? DefaultDescription { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; }
@ -704,6 +706,7 @@ public sealed class LocationItem
public string? Description { get; set; }
public string LocationPath { get; set; } = string.Empty;
public int Depth { get; set; }
public bool ShowInQuickAddBar { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; }
public bool IsArchived { get; set; }

View File

@ -994,14 +994,28 @@ public sealed class TimelineService(
PlotLineOptions = plotLines.Select(x => new SelectListItem(x.PlotLineName, x.PlotLineID.ToString(), x.PlotLineID == filter.PlotLineID)).ToList(),
PlotThreadOptions = plotThreads.Select(x => new SelectListItem(x.ThreadTitle, x.PlotThreadID.ToString(), x.PlotThreadID == filter.PlotThreadID)).ToList(),
AssetOptions = allAssets.Select(x => new SelectListItem(x.AssetName, x.StoryAssetID.ToString(), x.StoryAssetID == filter.StoryAssetID)).ToList(),
QuickAddAssets = allAssets
.Where(x => x.ShowInQuickAddBar)
.OrderByDescending(x => x.Importance)
.ThenBy(x => x.AssetName)
.ToList(),
AssetEventTypeOptions = ChapterService.ToSelectList(assetLookupData.AssetEventTypes, x => x.AssetEventTypeID, x => x.TypeName),
AssetStateOptions = assetLookupData.AssetStates.Select(x => new SelectListItem(x.StateName, x.AssetStateID.ToString())).ToList(),
AssetDependencyTypeOptions = ChapterService.ToSelectList(assetLookupData.AssetDependencyTypes, x => x.AssetDependencyTypeID, x => x.TypeName),
CharacterOptions = allCharacters.Select(x => new SelectListItem(x.CharacterName, x.CharacterID.ToString(), x.CharacterID == filter.CharacterID)).ToList(),
QuickAddCharacters = allCharacters
.Where(x => x.ShowInQuickAddBar)
.OrderByDescending(x => x.CharacterImportance ?? 0)
.ThenBy(x => x.CharacterName)
.ToList(),
CharacterRoleOptions = characterLookupData.RoleTypes.Select(x => new SelectListItem(x.TypeName, x.CharacterRoleInSceneTypeID.ToString())).ToList(),
PresenceTypeOptions = characterLookupData.PresenceTypes.Select(x => new SelectListItem(x.TypeName, x.PresenceTypeID.ToString())).ToList(),
PovCharacterOptions = allCharacters.Select(x => new SelectListItem(x.CharacterName, x.CharacterID.ToString(), x.CharacterID == filter.POVCharacterID)).ToList(),
LocationOptions = allLocations.Select(x => new SelectListItem(x.LocationPath, x.LocationID.ToString(), x.LocationID == filter.LocationID)).ToList(),
QuickAddLocations = allLocations
.Where(x => x.ShowInQuickAddBar)
.OrderBy(x => x.LocationPath)
.ToList(),
LocationRelationshipTypeOptions = ChapterService.ToSelectList(locationLookupData.RelationshipTypes, x => x.LocationRelationshipTypeID, x => x.TypeName),
WarningSeverityOptions = warningLookups.Severities.Select(x => new SelectListItem(x.SeverityName, x.WarningSeverityID.ToString(), x.WarningSeverityID == filter.WarningSeverityID)).ToList(),
WarningTypeOptions = warningLookups.WarningTypes.Select(x => new SelectListItem(x.TypeName, x.WarningTypeID.ToString(), x.WarningTypeID == filter.WarningTypeID)).ToList(),
@ -1118,7 +1132,27 @@ public sealed class TimelineService(
return null;
}
await scenes.MoveRelativeAsync(model.SceneID, model.AnchorSceneID, model.Position == "Before" ? "Before" : "After");
if (model.AnchorSceneID > 0)
{
await scenes.MoveRelativeAsync(model.SceneID, model.AnchorSceneID, model.Position == "Before" ? "Before" : "After");
}
else if (model.TargetChapterID.HasValue)
{
await scenes.MoveToChapterAsync(new SceneMoveRequestViewModel
{
SceneID = model.SceneID,
TargetChapterID = model.TargetChapterID.Value,
Position = "End",
RenumberScenes = true,
ReturnProjectID = model.ProjectID,
ReturnBookID = model.BookID
});
}
else
{
return null;
}
await warnings.FinaliseSceneDependencyWarningsAsync(model.ProjectID, model.BookID);
return model.BookID.HasValue
? await warnings.ValidateBookAsync(model.BookID.Value)
@ -2709,6 +2743,7 @@ public sealed class AssetService(IProjectRepository projects, IAssetRepository a
CurrentStateID = asset.CurrentStateID,
CurrentLocationID = asset.CurrentLocationID,
IsResolved = asset.IsResolved,
ShowInQuickAddBar = asset.ShowInQuickAddBar,
Project = project
}, lookupData);
}
@ -2761,7 +2796,8 @@ public sealed class AssetService(IProjectRepository projects, IAssetRepository a
Importance = model.Importance,
CurrentStateID = model.CurrentStateID,
CurrentLocationID = model.CurrentLocationID,
IsResolved = model.IsResolved
IsResolved = model.IsResolved,
ShowInQuickAddBar = model.ShowInQuickAddBar
});
public Task ArchiveAssetAsync(int storyAssetId) => assets.ArchiveAssetAsync(storyAssetId);
@ -2893,6 +2929,7 @@ public sealed class LocationService(IProjectRepository projects, ILocationReposi
LocationName = location.LocationName,
LocationTypeID = location.LocationTypeID,
Description = location.Description,
ShowInQuickAddBar = location.ShowInQuickAddBar,
Project = await projects.GetAsync(location.ProjectID)
});
}
@ -2942,7 +2979,8 @@ public sealed class LocationService(IProjectRepository projects, ILocationReposi
ParentLocationID = model.ParentLocationID == model.LocationID ? null : model.ParentLocationID,
LocationName = model.LocationName,
LocationTypeID = model.LocationTypeID,
Description = model.Description
Description = model.Description,
ShowInQuickAddBar = model.ShowInQuickAddBar
});
public Task ArchiveAsync(int locationId) => locations.ArchiveAsync(locationId);
@ -3027,6 +3065,7 @@ public sealed class CharacterService(IProjectRepository projects, ICharacterRepo
Height = character.Height,
EyeColour = character.EyeColour,
CharacterImportance = character.CharacterImportance,
ShowInQuickAddBar = character.ShowInQuickAddBar,
DefaultDescription = character.DefaultDescription,
Project = await projects.GetAsync(character.ProjectID)
};
@ -3071,6 +3110,7 @@ public sealed class CharacterService(IProjectRepository projects, ICharacterRepo
Height = model.Height,
EyeColour = model.EyeColour,
CharacterImportance = model.CharacterImportance,
ShowInQuickAddBar = model.ShowInQuickAddBar,
DefaultDescription = model.DefaultDescription
});

View File

@ -0,0 +1,424 @@
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
IF COL_LENGTH(N'dbo.Characters', N'ShowInQuickAddBar') IS NULL
BEGIN
ALTER TABLE dbo.Characters
ADD ShowInQuickAddBar bit NOT NULL
CONSTRAINT DF_Characters_ShowInQuickAddBar DEFAULT 0 WITH VALUES;
END;
GO
IF COL_LENGTH(N'dbo.StoryAssets', N'ShowInQuickAddBar') IS NULL
BEGIN
ALTER TABLE dbo.StoryAssets
ADD ShowInQuickAddBar bit NOT NULL
CONSTRAINT DF_StoryAssets_ShowInQuickAddBar DEFAULT 0 WITH VALUES;
END;
GO
IF COL_LENGTH(N'dbo.Locations', N'ShowInQuickAddBar') IS NULL
BEGIN
ALTER TABLE dbo.Locations
ADD ShowInQuickAddBar bit NOT NULL
CONSTRAINT DF_Locations_ShowInQuickAddBar DEFAULT 0 WITH VALUES;
END;
GO
UPDATE dbo.Characters
SET ShowInQuickAddBar = 1
WHERE ShowInQuickAddBar = 0 AND ISNULL(CharacterImportance, 0) >= 6;
GO
UPDATE dbo.StoryAssets
SET ShowInQuickAddBar = 1
WHERE ShowInQuickAddBar = 0 AND (Importance >= 5 OR IsResolved = 0);
GO
WITH RankedCharacters AS
(
SELECT CharacterID,
ROW_NUMBER() OVER (PARTITION BY ProjectID ORDER BY ISNULL(CharacterImportance, 0) DESC, CharacterName) AS RowNumber,
SUM(CASE WHEN ShowInQuickAddBar = 1 THEN 1 ELSE 0 END) OVER (PARTITION BY ProjectID) AS FlaggedCount
FROM dbo.Characters
WHERE IsArchived = 0
)
UPDATE c
SET ShowInQuickAddBar = 1
FROM dbo.Characters c
INNER JOIN RankedCharacters rc ON rc.CharacterID = c.CharacterID
WHERE rc.FlaggedCount = 0 AND rc.RowNumber <= 10;
GO
WITH RankedAssets AS
(
SELECT StoryAssetID,
ROW_NUMBER() OVER (PARTITION BY ProjectID ORDER BY Importance DESC, AssetName) AS RowNumber,
SUM(CASE WHEN ShowInQuickAddBar = 1 THEN 1 ELSE 0 END) OVER (PARTITION BY ProjectID) AS FlaggedCount
FROM dbo.StoryAssets
WHERE IsArchived = 0
)
UPDATE sa
SET ShowInQuickAddBar = 1
FROM dbo.StoryAssets sa
INNER JOIN RankedAssets ra ON ra.StoryAssetID = sa.StoryAssetID
WHERE ra.FlaggedCount = 0 AND ra.RowNumber <= 10;
GO
WITH RankedLocations AS
(
SELECT lp.LocationID,
ROW_NUMBER() OVER (PARTITION BY lp.ProjectID ORDER BY lp.SortPath) AS RowNumber,
SUM(CASE WHEN l.ShowInQuickAddBar = 1 THEN 1 ELSE 0 END) OVER (PARTITION BY lp.ProjectID) AS FlaggedCount
FROM dbo.LocationPaths lp
INNER JOIN dbo.Locations l ON l.LocationID = lp.LocationID
)
UPDATE l
SET ShowInQuickAddBar = 1
FROM dbo.Locations l
INNER JOIN RankedLocations rl ON rl.LocationID = l.LocationID
WHERE rl.FlaggedCount = 0 AND rl.RowNumber <= 10;
GO
CREATE OR ALTER PROCEDURE dbo.Character_ListByProject
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
SELECT CharacterID, ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID,
Height, EyeColour, CharacterImportance, ShowInQuickAddBar, DefaultDescription, CreatedDate, UpdatedDate, IsArchived
FROM dbo.Characters
WHERE ProjectID = @ProjectID AND IsArchived = 0
ORDER BY CharacterName;
END;
GO
CREATE OR ALTER PROCEDURE dbo.Character_Get
@CharacterID int
AS
BEGIN
SET NOCOUNT ON;
SELECT CharacterID, ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID,
Height, EyeColour, CharacterImportance, ShowInQuickAddBar, DefaultDescription, CreatedDate, UpdatedDate, IsArchived
FROM dbo.Characters
WHERE CharacterID = @CharacterID AND IsArchived = 0;
END;
GO
CREATE OR ALTER PROCEDURE dbo.Character_Save
@CharacterID int = NULL,
@ProjectID int,
@CharacterName nvarchar(200),
@ShortName nvarchar(100) = NULL,
@Sex nvarchar(50) = NULL,
@BirthDate date = NULL,
@AgeAtSeriesStart int = NULL,
@AgeReferenceSceneID int = NULL,
@Height nvarchar(50) = NULL,
@EyeColour nvarchar(50) = NULL,
@CharacterImportance int = NULL,
@ShowInQuickAddBar bit = 0,
@DefaultDescription nvarchar(max) = NULL
AS
BEGIN
SET NOCOUNT ON;
IF @CharacterID IS NULL OR @CharacterID = 0
BEGIN
INSERT dbo.Characters (ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID, Height, EyeColour, CharacterImportance, ShowInQuickAddBar, DefaultDescription)
VALUES (@ProjectID, @CharacterName, @ShortName, @Sex, @BirthDate, @AgeAtSeriesStart, @AgeReferenceSceneID, @Height, @EyeColour, @CharacterImportance, @ShowInQuickAddBar, @DefaultDescription);
SET @CharacterID = CAST(SCOPE_IDENTITY() AS int);
END
ELSE
BEGIN
UPDATE dbo.Characters
SET CharacterName = @CharacterName, ShortName = @ShortName, Sex = @Sex, BirthDate = @BirthDate,
AgeAtSeriesStart = @AgeAtSeriesStart, AgeReferenceSceneID = @AgeReferenceSceneID,
Height = @Height, EyeColour = @EyeColour, CharacterImportance = @CharacterImportance,
ShowInQuickAddBar = @ShowInQuickAddBar, DefaultDescription = @DefaultDescription,
UpdatedDate = SYSUTCDATETIME()
WHERE CharacterID = @CharacterID;
END
SELECT @CharacterID;
END;
GO
CREATE OR ALTER PROCEDURE dbo.CharacterTimeline_GetByProject
@ProjectID int,
@BookID int = NULL
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #TimelineScenes
(
SceneID int NOT NULL PRIMARY KEY,
SceneNumber decimal(9,2) NOT NULL,
SceneTitle nvarchar(200) NOT NULL,
ChapterNumber decimal(9,2) NOT NULL,
BookTitle nvarchar(200) NOT NULL,
BookSortOrder int NOT NULL,
ChapterSortOrder int NOT NULL,
SceneSortOrder int NOT NULL
);
INSERT #TimelineScenes (SceneID, SceneNumber, SceneTitle, ChapterNumber, BookTitle, BookSortOrder, ChapterSortOrder, SceneSortOrder)
SELECT s.SceneID, s.SceneNumber, s.SceneTitle, ch.ChapterNumber, b.BookTitle, b.SortOrder, ch.SortOrder, s.SortOrder
FROM dbo.Books b
INNER JOIN dbo.Chapters ch ON ch.BookID = b.BookID
INNER JOIN dbo.Scenes s ON s.ChapterID = ch.ChapterID
WHERE b.ProjectID = @ProjectID
AND b.IsArchived = 0
AND ch.IsArchived = 0
AND s.IsArchived = 0
AND (@BookID IS NULL OR b.BookID = @BookID);
CREATE TABLE #TimelineCharacters
(
CharacterID int NOT NULL PRIMARY KEY,
ProjectID int NOT NULL,
CharacterName nvarchar(200) NOT NULL,
ShortName nvarchar(100) NULL,
Sex nvarchar(50) NULL,
BirthDate date NULL,
AgeAtSeriesStart int NULL,
AgeReferenceSceneID int NULL,
Height nvarchar(50) NULL,
EyeColour nvarchar(50) NULL,
CharacterImportance int NULL,
ShowInQuickAddBar bit NOT NULL,
DefaultDescription nvarchar(max) NULL,
CreatedDate datetime2 NOT NULL,
UpdatedDate datetime2 NOT NULL,
IsArchived bit NOT NULL
);
INSERT #TimelineCharacters (CharacterID, ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID, Height, EyeColour, CharacterImportance, ShowInQuickAddBar, DefaultDescription, CreatedDate, UpdatedDate, IsArchived)
SELECT CharacterID, ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID,
Height, EyeColour, CharacterImportance, ShowInQuickAddBar, DefaultDescription, CreatedDate, UpdatedDate, IsArchived
FROM dbo.Characters
WHERE ProjectID = @ProjectID AND IsArchived = 0;
CREATE TABLE #ProjectLocationPaths
(
LocationID int NOT NULL PRIMARY KEY,
LocationName nvarchar(200) NOT NULL,
LocationPath nvarchar(max) NOT NULL
);
;WITH ProjectLocationTree AS
(
SELECT LocationID, LocationName, CAST(LocationName AS nvarchar(max)) AS LocationPath
FROM dbo.Locations
WHERE ProjectID = @ProjectID AND ParentLocationID IS NULL AND IsArchived = 0
UNION ALL
SELECT child.LocationID, child.LocationName, CAST(parent.LocationPath + N' > ' + child.LocationName AS nvarchar(max)) AS LocationPath
FROM dbo.Locations child
INNER JOIN ProjectLocationTree parent ON parent.LocationID = child.ParentLocationID
WHERE child.ProjectID = @ProjectID AND child.IsArchived = 0
)
INSERT #ProjectLocationPaths (LocationID, LocationName, LocationPath)
SELECT LocationID, LocationName, LocationPath
FROM ProjectLocationTree;
SELECT CharacterID, ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID,
Height, EyeColour, CharacterImportance, ShowInQuickAddBar, DefaultDescription, CreatedDate, UpdatedDate, IsArchived
FROM #TimelineCharacters
ORDER BY ISNULL(CharacterImportance, 0) DESC, CharacterName;
SELECT sc.SceneCharacterID, sc.SceneID, sc.CharacterID, c.ProjectID, c.CharacterName, c.ShortName, c.BirthDate, c.AgeAtSeriesStart,
sc.RoleInSceneTypeID, role.TypeName AS RoleInSceneTypeName, sc.PresenceTypeID, presence.TypeName AS PresenceTypeName,
sc.LocationID, location.LocationName, location.LocationPath, sc.EntryLocationID, entry.LocationName AS EntryLocationName,
sc.ExitLocationID, exitLocation.LocationName AS ExitLocationName, sc.AppearanceNotes, sc.OutfitDescription,
sc.PhysicalCondition, sc.EmotionalState, sc.KnowledgeNotes, s.SceneNumber, s.SceneTitle, s.ChapterNumber, s.BookTitle,
sc.CreatedDate, sc.UpdatedDate
FROM #TimelineScenes s
INNER JOIN dbo.SceneCharacters sc ON sc.SceneID = s.SceneID
INNER JOIN #TimelineCharacters c ON c.CharacterID = sc.CharacterID
LEFT JOIN dbo.CharacterRoleInSceneTypes role ON role.CharacterRoleInSceneTypeID = sc.RoleInSceneTypeID
LEFT JOIN dbo.PresenceTypes presence ON presence.PresenceTypeID = sc.PresenceTypeID
LEFT JOIN #ProjectLocationPaths location ON location.LocationID = sc.LocationID
LEFT JOIN #ProjectLocationPaths entry ON entry.LocationID = sc.EntryLocationID
LEFT JOIN #ProjectLocationPaths exitLocation ON exitLocation.LocationID = sc.ExitLocationID
ORDER BY s.BookSortOrder, s.ChapterSortOrder, s.SceneSortOrder, c.CharacterName;
END;
GO
CREATE OR ALTER VIEW dbo.LocationPaths
AS
WITH LocationTree AS
(
SELECT LocationID, ProjectID, ParentLocationID, LocationName, LocationTypeID, Description, ShowInQuickAddBar,
CAST(LocationName AS nvarchar(max)) AS LocationPath,
CAST(RIGHT('000000' + CAST(LocationID AS varchar(6)), 6) AS nvarchar(max)) AS SortPath,
0 AS Depth
FROM dbo.Locations
WHERE ParentLocationID IS NULL AND IsArchived = 0
UNION ALL
SELECT child.LocationID, child.ProjectID, child.ParentLocationID, child.LocationName, child.LocationTypeID, child.Description, child.ShowInQuickAddBar,
CAST(parent.LocationPath + N' > ' + child.LocationName AS nvarchar(max)),
CAST(parent.SortPath + N'.' + RIGHT('000000' + CAST(child.LocationID AS varchar(6)), 6) AS nvarchar(max)),
parent.Depth + 1
FROM dbo.Locations child
INNER JOIN LocationTree parent ON parent.LocationID = child.ParentLocationID
WHERE child.IsArchived = 0
)
SELECT LocationID, ProjectID, ParentLocationID, LocationName, LocationTypeID, Description, ShowInQuickAddBar, LocationPath, SortPath, Depth
FROM LocationTree;
GO
CREATE OR ALTER PROCEDURE dbo.Location_ListByProject
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
SELECT lp.LocationID, lp.ProjectID, lp.ParentLocationID, lp.LocationName, lp.LocationTypeID, lt.TypeName AS LocationTypeName,
lp.Description, lp.ShowInQuickAddBar, lp.LocationPath, lp.Depth, l.CreatedDate, l.UpdatedDate, l.IsArchived
FROM dbo.LocationPaths lp
INNER JOIN dbo.Locations l ON l.LocationID = lp.LocationID
LEFT JOIN dbo.LocationTypes lt ON lt.LocationTypeID = lp.LocationTypeID
WHERE lp.ProjectID = @ProjectID
ORDER BY lp.SortPath;
END;
GO
CREATE OR ALTER PROCEDURE dbo.Location_Get
@LocationID int
AS
BEGIN
SET NOCOUNT ON;
SELECT lp.LocationID, lp.ProjectID, lp.ParentLocationID, parent.LocationName AS ParentLocationName,
lp.LocationName, lp.LocationTypeID, lt.TypeName AS LocationTypeName, lp.Description, lp.ShowInQuickAddBar, lp.LocationPath, lp.Depth,
l.CreatedDate, l.UpdatedDate, l.IsArchived
FROM dbo.LocationPaths lp
INNER JOIN dbo.Locations l ON l.LocationID = lp.LocationID
LEFT JOIN dbo.Locations parent ON parent.LocationID = lp.ParentLocationID
LEFT JOIN dbo.LocationTypes lt ON lt.LocationTypeID = lp.LocationTypeID
WHERE lp.LocationID = @LocationID;
END;
GO
CREATE OR ALTER PROCEDURE dbo.Location_Save
@LocationID int = NULL,
@ProjectID int,
@ParentLocationID int = NULL,
@LocationName nvarchar(200),
@LocationTypeID int = NULL,
@Description nvarchar(max) = NULL,
@ShowInQuickAddBar bit = 0
AS
BEGIN
SET NOCOUNT ON;
IF @LocationID IS NULL OR @LocationID = 0
BEGIN
INSERT dbo.Locations (ProjectID, ParentLocationID, LocationName, LocationTypeID, Description, ShowInQuickAddBar)
VALUES (@ProjectID, @ParentLocationID, @LocationName, @LocationTypeID, @Description, @ShowInQuickAddBar);
SET @LocationID = CAST(SCOPE_IDENTITY() AS int);
END
ELSE
BEGIN
UPDATE dbo.Locations
SET ParentLocationID = @ParentLocationID, LocationName = @LocationName, LocationTypeID = @LocationTypeID,
Description = @Description, ShowInQuickAddBar = @ShowInQuickAddBar, UpdatedDate = SYSUTCDATETIME()
WHERE LocationID = @LocationID;
END
SELECT @LocationID;
END;
GO
CREATE OR ALTER PROCEDURE dbo.StoryAsset_Save
@StoryAssetID int = NULL, @ProjectID int, @AssetName nvarchar(200), @AssetKindID int, @Description nvarchar(max) = NULL,
@Importance int, @CurrentStateID int = NULL, @CurrentLocationID int = NULL, @IsResolved bit, @ShowInQuickAddBar bit = 0
AS
BEGIN
SET NOCOUNT ON;
IF @StoryAssetID IS NULL OR @StoryAssetID = 0
BEGIN
INSERT dbo.StoryAssets (ProjectID, AssetName, AssetKindID, Description, Importance, CurrentStateID, CurrentLocationID, IsResolved, ShowInQuickAddBar)
VALUES (@ProjectID, @AssetName, @AssetKindID, @Description, @Importance, @CurrentStateID, @CurrentLocationID, @IsResolved, @ShowInQuickAddBar);
SET @StoryAssetID = CAST(SCOPE_IDENTITY() AS int);
END
ELSE
BEGIN
UPDATE dbo.StoryAssets
SET AssetName = @AssetName, AssetKindID = @AssetKindID, Description = @Description, Importance = @Importance,
CurrentStateID = @CurrentStateID, CurrentLocationID = @CurrentLocationID, IsResolved = @IsResolved,
ShowInQuickAddBar = @ShowInQuickAddBar, UpdatedDate = SYSUTCDATETIME()
WHERE StoryAssetID = @StoryAssetID;
END
SELECT @StoryAssetID;
END;
GO
CREATE OR ALTER PROCEDURE dbo.StoryAsset_ListByProject
@ProjectID int
AS
BEGIN
SET NOCOUNT ON;
SELECT sa.StoryAssetID, sa.ProjectID, sa.AssetName, sa.AssetKindID, ak.KindName, sa.Description, sa.Importance,
sa.CurrentStateID, ast.StateName AS CurrentStateName, sa.CurrentLocationID,
location.LocationName AS CurrentLocationName, location.LocationPath AS CurrentLocationPath,
sa.IsResolved, sa.ShowInQuickAddBar, sa.CreatedDate, sa.UpdatedDate, sa.IsArchived
FROM dbo.StoryAssets sa
INNER JOIN dbo.AssetKinds ak ON ak.AssetKindID = sa.AssetKindID
LEFT JOIN dbo.AssetStates ast ON ast.AssetStateID = sa.CurrentStateID
LEFT JOIN dbo.LocationPaths location ON location.LocationID = sa.CurrentLocationID
WHERE sa.ProjectID = @ProjectID AND sa.IsArchived = 0
ORDER BY sa.Importance DESC, sa.AssetName;
END;
GO
CREATE OR ALTER PROCEDURE dbo.StoryAsset_Get
@StoryAssetID int
AS
BEGIN
SET NOCOUNT ON;
SELECT sa.StoryAssetID, sa.ProjectID, sa.AssetName, sa.AssetKindID, ak.KindName, sa.Description, sa.Importance,
sa.CurrentStateID, ast.StateName AS CurrentStateName, sa.CurrentLocationID,
location.LocationName AS CurrentLocationName, location.LocationPath AS CurrentLocationPath,
sa.IsResolved, sa.ShowInQuickAddBar, sa.CreatedDate, sa.UpdatedDate, sa.IsArchived
FROM dbo.StoryAssets sa
INNER JOIN dbo.AssetKinds ak ON ak.AssetKindID = sa.AssetKindID
LEFT JOIN dbo.AssetStates ast ON ast.AssetStateID = sa.CurrentStateID
LEFT JOIN dbo.LocationPaths location ON location.LocationID = sa.CurrentLocationID
WHERE sa.StoryAssetID = @StoryAssetID AND sa.IsArchived = 0;
END;
GO
CREATE OR ALTER PROCEDURE dbo.AssetTimeline_GetByProject
@ProjectID int,
@BookID int = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT sa.StoryAssetID, sa.ProjectID, sa.AssetName, sa.AssetKindID, ak.KindName, sa.Description, sa.Importance,
sa.CurrentStateID, ast.StateName AS CurrentStateName, sa.CurrentLocationID,
location.LocationName AS CurrentLocationName, location.LocationPath AS CurrentLocationPath,
sa.IsResolved, sa.ShowInQuickAddBar, sa.CreatedDate, sa.UpdatedDate, sa.IsArchived
FROM dbo.StoryAssets sa
INNER JOIN dbo.AssetKinds ak ON ak.AssetKindID = sa.AssetKindID
LEFT JOIN dbo.AssetStates ast ON ast.AssetStateID = sa.CurrentStateID
LEFT JOIN dbo.LocationPaths location ON location.LocationID = sa.CurrentLocationID
WHERE sa.ProjectID = @ProjectID AND sa.IsArchived = 0 AND (sa.Importance >= 5 OR sa.IsResolved = 0)
ORDER BY sa.Importance DESC, sa.AssetName;
SELECT ae.AssetEventID, ae.StoryAssetID, sa.ProjectID, sa.AssetName, sa.AssetKindID, ak.KindName,
ae.SceneID, ae.AssetEventTypeID, aet.TypeName AS AssetEventTypeName, aet.MarkerText,
ae.FromStateID, fs.StateName AS FromStateName, ae.ToStateID, ts.StateName AS ToStateName,
ae.EventTitle, ae.EventDescription, ae.CreatedDate, ae.UpdatedDate
FROM dbo.AssetEvents ae
INNER JOIN dbo.StoryAssets sa ON sa.StoryAssetID = ae.StoryAssetID
INNER JOIN dbo.AssetKinds ak ON ak.AssetKindID = sa.AssetKindID
INNER JOIN dbo.AssetEventTypes aet ON aet.AssetEventTypeID = ae.AssetEventTypeID
INNER JOIN dbo.Scenes s ON s.SceneID = ae.SceneID
INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID
INNER JOIN dbo.Books b ON b.BookID = c.BookID
LEFT JOIN dbo.AssetStates fs ON fs.AssetStateID = ae.FromStateID
LEFT JOIN dbo.AssetStates ts ON ts.AssetStateID = ae.ToStateID
WHERE sa.ProjectID = @ProjectID AND sa.IsArchived = 0 AND (@BookID IS NULL OR b.BookID = @BookID)
ORDER BY b.SortOrder, c.SortOrder, s.SortOrder, sa.AssetName;
END;
GO

View File

@ -390,14 +390,17 @@ public sealed class TimelineViewModel
public IReadOnlyList<SelectListItem> PlotLineOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> PlotThreadOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> AssetOptions { get; set; } = [];
public IReadOnlyList<StoryAsset> QuickAddAssets { get; set; } = [];
public IReadOnlyList<SelectListItem> AssetEventTypeOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> AssetStateOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> AssetDependencyTypeOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> CharacterOptions { get; set; } = [];
public IReadOnlyList<Character> QuickAddCharacters { get; set; } = [];
public IReadOnlyList<SelectListItem> CharacterRoleOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> PresenceTypeOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> PovCharacterOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> LocationOptions { get; set; } = [];
public IReadOnlyList<LocationItem> QuickAddLocations { get; set; } = [];
public IReadOnlyList<SelectListItem> LocationRelationshipTypeOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> WarningSeverityOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> WarningTypeOptions { get; set; } = [];
@ -502,7 +505,9 @@ public sealed class TimelineSceneDropMoveViewModel
public int? BookID { get; set; }
public int SceneID { get; set; }
public int AnchorSceneID { get; set; }
public int? TargetChapterID { get; set; }
public string Position { get; set; } = "After";
public int? ReturnSelectedSceneID { get; set; }
}
public sealed class TimelineSceneCharacterDropViewModel
@ -747,6 +752,9 @@ public sealed class StoryAssetEditViewModel
[Display(Name = "Resolved")]
public bool IsResolved { get; set; }
[Display(Name = "Show in Quick Add Bar")]
public bool ShowInQuickAddBar { get; set; }
public Project? Project { get; set; }
public IReadOnlyList<SelectListItem> AssetKindOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> AssetStateOptions { get; set; } = [];
@ -865,6 +873,9 @@ public sealed class CharacterEditViewModel
[Display(Name = "Story importance")]
public int? CharacterImportance { get; set; }
[Display(Name = "Show in Quick Add Bar")]
public bool ShowInQuickAddBar { get; set; }
[Display(Name = "Default description")]
public string? DefaultDescription { get; set; }
@ -1000,6 +1011,8 @@ public sealed class LocationEditViewModel
public int? LocationTypeID { get; set; }
public string? Description { get; set; }
[Display(Name = "Show in Quick Add Bar")]
public bool ShowInQuickAddBar { get; set; }
public Project? Project { get; set; }
public IReadOnlyList<SelectListItem> ParentLocationOptions { get; set; } = [];
public IReadOnlyList<SelectListItem> LocationTypeOptions { get; set; } = [];

View File

@ -49,6 +49,13 @@
<select asp-for="CharacterImportance" asp-items="Model.ImportanceOptions" class="form-select"></select>
<div class="form-text">Controls timeline grouping for major, secondary/supporting, and minor characters.</div>
</div>
<div class="col-md-6 d-flex align-items-end">
<div class="form-check mb-2">
<input asp-for="ShowInQuickAddBar" class="form-check-input" />
<label asp-for="ShowInQuickAddBar" class="form-check-label"></label>
<div class="form-text">Makes this item available as a draggable shortcut on the Timeline page.</div>
</div>
</div>
<div class="col-12">
<label asp-for="DefaultDescription" class="form-label"></label>
<textarea asp-for="DefaultDescription" class="form-control" rows="5"></textarea>

View File

@ -32,6 +32,13 @@
<option value="">Top level</option>
</select>
</div>
<div class="col-12">
<div class="form-check">
<input asp-for="ShowInQuickAddBar" class="form-check-input" />
<label asp-for="ShowInQuickAddBar" class="form-check-label"></label>
<div class="form-text">Makes this item available as a draggable shortcut on the Timeline page.</div>
</div>
</div>
<div class="col-12">
<label asp-for="Description" class="form-label"></label>
<textarea asp-for="Description" class="form-control" rows="5"></textarea>

View File

@ -52,6 +52,13 @@
<label asp-for="IsResolved" class="form-check-label"></label>
</div>
</div>
<div class="col-md-4 d-flex align-items-end">
<div class="form-check mb-2">
<input asp-for="ShowInQuickAddBar" class="form-check-input" />
<label asp-for="ShowInQuickAddBar" class="form-check-label"></label>
<div class="form-text">Makes this item available as a draggable shortcut on the Timeline page.</div>
</div>
</div>
<div class="col-12">
<label asp-for="Description" class="form-label"></label>
<textarea asp-for="Description" class="form-control" rows="5"></textarea>

View File

@ -423,17 +423,21 @@
<details class="timeline-drag-palette" data-drag-palette>
<summary>Drag Sources</summary>
<div class="drag-chip-group">
@foreach (var character in Model.CharacterOptions.Take(10))
@if (!Model.QuickAddCharacters.Any() && !Model.QuickAddAssets.Any() && !Model.QuickAddLocations.Any())
{
<span class="drag-chip character" draggable="true" data-drag-type="character" data-drag-id="@character.Value" data-drag-label="@character.Text">@character.Text</span>
<span class="muted">No Quick Add items yet. Tick “Show in Quick Add Bar” on characters, story assets or locations to add shortcuts here.</span>
}
@foreach (var asset in Model.AssetOptions.Take(10))
@foreach (var character in Model.QuickAddCharacters)
{
<span class="drag-chip asset" draggable="true" data-drag-type="asset" data-drag-id="@asset.Value" data-drag-label="@asset.Text">@asset.Text</span>
<span class="drag-chip character" draggable="true" data-drag-type="character" data-drag-id="@character.CharacterID" data-drag-label="@character.CharacterName">@character.CharacterName</span>
}
@foreach (var location in Model.LocationOptions.Take(10))
@foreach (var asset in Model.QuickAddAssets)
{
<span class="drag-chip location" draggable="true" data-drag-type="location" data-drag-id="@location.Value" data-drag-label="@location.Text">@location.Text</span>
<span class="drag-chip asset" draggable="true" data-drag-type="asset" data-drag-id="@asset.StoryAssetID" data-drag-label="@asset.AssetName">@asset.AssetName</span>
}
@foreach (var location in Model.QuickAddLocations)
{
<span class="drag-chip location" draggable="true" data-drag-type="location" data-drag-id="@location.LocationID" data-drag-label="@location.LocationName" title="@location.LocationPath">@location.LocationName</span>
}
</div>
</details>
@ -470,23 +474,6 @@
</div>
<p class="muted" data-drag-panel-summary></p>
<form asp-controller="Timeline" asp-action="DropMoveScene" method="post" class="drag-drop-form d-none" data-drag-form="scene">
<input type="hidden" name="ProjectID" value="@Model.Project.ProjectID" />
<input type="hidden" name="BookID" value="@Model.SelectedBookID" />
<input type="hidden" name="SceneID" />
<input type="hidden" name="AnchorSceneID" />
<input type="hidden" name="Position" />
<div class="focused-validation-summary">
<span>After moving, PlotLine will run continuity validation.</span>
<span>Existing links, events, metrics, purposes, characters, assets, warnings and dependencies stay attached to the same SceneID.</span>
</div>
<div class="button-row mt-2">
<button class="btn btn-primary btn-sm" type="submit">Move Scene</button>
<button class="btn btn-outline-secondary btn-sm" type="button" data-drag-cancel>Cancel</button>
<a class="btn btn-outline-secondary btn-sm" asp-controller="Warnings" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.SelectedBookID">Review Warnings</a>
</div>
</form>
<form asp-controller="Timeline" asp-action="DropCharacter" method="post" class="drag-drop-form d-none" data-drag-form="character">
<input type="hidden" name="SceneID" />
<input type="hidden" name="CharacterID" />
@ -564,6 +551,40 @@
</form>
</section>
<div class="modal fade plotline-modal" id="sceneMoveModal" tabindex="-1" aria-labelledby="sceneMoveModalTitle" aria-hidden="true" data-scene-move-modal>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content plotline-confirm-modal scene-move-modal-content">
<form asp-controller="Timeline" asp-action="DropMoveScene" method="post" data-drag-form="scene">
<div class="modal-header">
<div>
<p class="eyebrow mb-1">Scene move</p>
<h2 class="modal-title" id="sceneMoveModalTitle" data-scene-move-title>Move Scene?</h2>
</div>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cancel move"></button>
</div>
<div class="modal-body">
<input type="hidden" name="ProjectID" value="@Model.Project.ProjectID" />
<input type="hidden" name="BookID" value="@Model.SelectedBookID" />
<input type="hidden" name="SceneID" />
<input type="hidden" name="AnchorSceneID" />
<input type="hidden" name="TargetChapterID" />
<input type="hidden" name="Position" />
<input type="hidden" name="ReturnSelectedSceneID" value="@Model.SelectedSceneID" />
<p class="scene-move-summary" data-scene-move-summary></p>
<div class="focused-validation-summary">
<span>After moving, PlotLine will run continuity validation.</span>
<span>Existing links, events, metrics, purposes, characters, assets, warnings and dependencies stay attached to the same SceneID.</span>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="submit" data-scene-move-submit>Move Scene</button>
<button class="btn btn-outline-secondary" type="button" data-bs-dismiss="modal">Cancel</button>
</div>
</form>
</div>
</div>
</div>
@if (!Model.Books.Any())
{
<section class="empty-panel">
@ -613,15 +634,22 @@ else
{
@foreach (var chapter in book.Chapters)
{
<div class="timeline-chapter" style="--chapter-scene-count:@ChapterSceneColumns(chapter)">
<div class="timeline-chapter"
style="--chapter-scene-count:@ChapterSceneColumns(chapter)"
data-chapter-drop-target="true"
data-chapter-id="@chapter.Chapter.ChapterID"
data-chapter-label="Chapter @chapter.Chapter.ChapterNumber: @chapter.Chapter.ChapterTitle">
<div class="timeline-chapter-title">
<span>Chapter @chapter.Chapter.ChapterNumber</span>
<strong>@chapter.Chapter.ChapterTitle</strong>
</div>
<div class="timeline-scenes">
<div class="timeline-scenes"
data-chapter-drop-target="true"
data-chapter-id="@chapter.Chapter.ChapterID"
data-chapter-label="Chapter @chapter.Chapter.ChapterNumber: @chapter.Chapter.ChapterTitle">
@if (!chapter.Scenes.Any())
{
<div class="timeline-empty-scene timeline-placeholder-scene is-placeholder">No scenes</div>
<div class="timeline-empty-scene timeline-placeholder-scene is-placeholder" data-empty-chapter-drop-target="true">Drop a scene here</div>
}
else
{

View File

@ -2159,6 +2159,9 @@ body.timeline-inspector-resizing {
display: flex;
flex-wrap: wrap;
gap: 6px;
max-height: 104px;
overflow: auto;
padding-right: 4px;
}
.drag-chip {
@ -2198,6 +2201,26 @@ body.timeline-inspector-resizing {
outline-offset: 2px;
}
.timeline-chapter.chapter-drop-active,
.timeline-scenes.drop-chapter-end {
background: rgba(47, 111, 99, 0.06);
}
.timeline-scenes.drop-chapter-end::after {
content: "Drop scene at end of chapter";
display: flex;
align-items: center;
justify-content: center;
min-width: var(--timeline-scene-width);
min-height: 74px;
border: 2px dashed rgba(197, 139, 43, 0.48);
border-radius: 12px;
color: #7a5527;
background: rgba(255, 248, 232, 0.82);
font-size: 0.8rem;
font-weight: 900;
}
.timeline-scene-card.drop-before {
box-shadow: inset 5px 0 0 #c58b2b, 0 12px 26px rgba(197, 139, 43, 0.16);
}
@ -2230,6 +2253,54 @@ body.timeline-inspector-resizing {
padding-top: 10px;
}
.scene-move-modal-content {
border: 1px solid rgba(47, 111, 99, 0.18);
border-radius: 14px;
background: var(--plotline-surface);
color: var(--plotline-ink);
box-shadow: 0 24px 70px rgba(55, 48, 39, 0.22);
}
.scene-move-modal-content .modal-header,
.scene-move-modal-content .modal-footer {
border-color: var(--plotline-line);
}
.scene-move-modal-content .modal-title {
margin: 0;
color: var(--plotline-ink);
font-size: 1.2rem;
font-weight: 900;
}
.scene-move-summary {
margin: 0 0 12px;
color: var(--plotline-ink);
font-size: 1rem;
font-weight: 800;
}
[data-theme="dark"] .scene-move-modal-content {
background: #201f22;
color: #f4eadc;
border-color: rgba(244, 234, 220, 0.16);
box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55);
}
[data-theme="dark"] .scene-move-modal-content .modal-title,
[data-theme="dark"] .scene-move-summary {
color: #f4eadc;
}
[data-theme="dark"] .scene-move-modal-content .modal-header,
[data-theme="dark"] .scene-move-modal-content .modal-footer {
border-color: rgba(244, 234, 220, 0.14);
}
[data-theme="dark"] .scene-move-modal-content .btn-close {
filter: invert(1) grayscale(100%);
}
.plain-preview {
border: 1px solid rgba(197, 139, 43, 0.28);
border-radius: 8px;
@ -2610,6 +2681,7 @@ body.dragging-location [data-drag-type="location"] {
body.dragging-character .timeline-scene-card,
body.dragging-asset .timeline-scene-card,
body.dragging-scene .timeline-scene-card,
body.dragging-scene .timeline-scenes[data-chapter-drop-target],
body.dragging-asset [data-asset-drop-target],
body.dragging-location [data-drag-type="location"] {
outline: 1px dashed rgba(47, 111, 99, 0.22);

View File

@ -949,11 +949,20 @@
return;
}
const forms = new Map([...panel.querySelectorAll("[data-drag-form]")].map((form) => [form.dataset.dragForm, form]));
const forms = new Map([...document.querySelectorAll("[data-drag-form]")].map((form) => [form.dataset.dragForm, form]));
const title = panel.querySelector("[data-drag-panel-title]");
const kicker = panel.querySelector("[data-drag-panel-kicker]");
const summary = panel.querySelector("[data-drag-panel-summary]");
const sceneMoveModalElement = document.querySelector("[data-scene-move-modal]");
const sceneMoveModal = sceneMoveModalElement && window.bootstrap?.Modal
? window.bootstrap.Modal.getOrCreateInstance(sceneMoveModalElement)
: null;
const sceneMoveTitle = sceneMoveModalElement?.querySelector("[data-scene-move-title]");
const sceneMoveSummary = sceneMoveModalElement?.querySelector("[data-scene-move-summary]");
const sceneMoveSubmit = sceneMoveModalElement?.querySelector("[data-scene-move-submit]");
const scrollKey = "plotline.timeline.scroll";
let currentDrag = null;
let suppressSceneClickUntil = 0;
const setValue = (form, name, value) => {
const field = form?.querySelector(`[name='${CSS.escape(name)}']`);
@ -963,8 +972,41 @@
};
const selectText = (select) => select?.selectedOptions?.[0]?.textContent?.trim() || "";
const quoteScene = (label) => `\u201c${label || "this scene"}\u201d`;
const buildSceneMoveSummary = (payload, sourceChapter, targetChapter, position, anchorLabel) => {
if (sourceChapter && targetChapter && sourceChapter === targetChapter) {
return `Move ${quoteScene(payload.label)} to this new position within ${targetChapter}?`;
}
if (sourceChapter && targetChapter) {
return `Move ${quoteScene(payload.label)} from ${sourceChapter} to ${targetChapter}?`;
}
return `Move ${quoteScene(payload.label)} ${position.toLowerCase()} ${anchorLabel}?`;
};
const showForm = (key, heading, body, actionLabel) => {
if (key === "scene") {
panel.classList.add("d-none");
panel.querySelectorAll("[data-drag-form]").forEach((form) => form.classList.add("d-none"));
forms.get("scene")?.classList.remove("d-none");
if (sceneMoveTitle) {
sceneMoveTitle.textContent = heading;
}
if (sceneMoveSummary) {
sceneMoveSummary.textContent = body;
}
if (sceneMoveSubmit) {
sceneMoveSubmit.classList.toggle("d-none", heading.toLowerCase().startsWith("cannot") || heading.toLowerCase().startsWith("scene already"));
}
if (sceneMoveModal) {
sceneMoveModal.show();
} else {
panel.classList.remove("d-none");
}
return;
}
forms.forEach((form, formKey) => form.classList.toggle("d-none", formKey !== key));
panel.classList.remove("d-none");
title.textContent = heading;
@ -978,6 +1020,37 @@
forms.forEach((form) => form.classList.add("d-none"));
};
const clearDropHighlights = () => {
document
.querySelectorAll(".drop-target-active, .drop-before, .drop-after, .chapter-drop-active, .drop-chapter-end")
.forEach((target) => target.classList.remove("drop-target-active", "drop-before", "drop-after", "chapter-drop-active", "drop-chapter-end"));
};
const saveTimelineScroll = () => {
const workspace = root?.querySelector(".timeline-shell");
try {
sessionStorage.setItem(scrollKey, JSON.stringify({ left: workspace?.scrollLeft || 0, top: window.scrollY || 0 }));
} catch {
// Scroll restoration is a convenience; blocked storage should not stop the move.
}
};
try {
const storedScroll = JSON.parse(sessionStorage.getItem(scrollKey) || "null");
if (storedScroll) {
sessionStorage.removeItem(scrollKey);
requestAnimationFrame(() => {
const workspace = root?.querySelector(".timeline-shell");
if (workspace) {
workspace.scrollLeft = storedScroll.left || 0;
}
window.scrollTo({ top: storedScroll.top || 0 });
});
}
} catch {
sessionStorage.removeItem(scrollKey);
}
const readPayload = (event) => {
try {
const payload = JSON.parse(event.dataTransfer.getData("application/json") || "{}");
@ -1007,19 +1080,26 @@
item.classList.remove("is-dragging");
document.body.classList.remove("drag-active", "dragging-scene", "dragging-character", "dragging-asset", "dragging-location");
currentDrag = null;
document.querySelectorAll(".drop-target-active, .drop-before, .drop-after").forEach((target) => {
target.classList.remove("drop-target-active", "drop-before", "drop-after");
});
clearDropHighlights();
});
});
panel.querySelectorAll("[data-drag-cancel]").forEach((button) => button.addEventListener("click", hidePanel));
forms.get("scene")?.addEventListener("submit", saveTimelineScroll);
root?.querySelectorAll(".timeline-scene-card[data-scene-id]").forEach((card) => {
card.addEventListener("click", (event) => {
if (Date.now() < suppressSceneClickUntil) {
event.preventDefault();
event.stopPropagation();
}
});
card.addEventListener("dragover", (event) => {
const payload = readPayload(event);
if (["scene", "character", "asset"].includes(payload.type)) {
event.preventDefault();
event.stopPropagation();
event.dataTransfer.dropEffect = payload.type === "scene" ? "move" : "copy";
card.classList.add("drop-target-active");
card.classList.toggle("drop-before", payload.type === "scene" && event.offsetX < card.clientWidth / 2);
@ -1036,6 +1116,8 @@
}
event.preventDefault();
event.stopPropagation();
suppressSceneClickUntil = Date.now() + 800;
card.classList.remove("drop-target-active", "drop-before", "drop-after");
const sceneId = card.dataset.sceneId;
@ -1047,10 +1129,14 @@
const form = forms.get("scene");
const position = event.offsetX < card.clientWidth / 2 ? "Before" : "After";
const sourceCard = root.querySelector(`.timeline-scene-card[data-scene-id='${CSS.escape(payload.id)}']`);
const sourceChapter = sourceCard?.dataset.chapterLabel || "";
const targetChapter = card.dataset.chapterLabel || "";
setValue(form, "SceneID", payload.id);
setValue(form, "AnchorSceneID", sceneId);
setValue(form, "TargetChapterID", "");
setValue(form, "Position", position);
showForm("scene", "Move scene?", `Move ${payload.label} ${position.toLowerCase()} ${card.dataset.dragLabel}.`, "Scene move");
showForm("scene", "Move Scene?", buildSceneMoveSummary(payload, sourceChapter, targetChapter, position, card.dataset.dragLabel), "Scene move");
return;
}
@ -1070,6 +1156,65 @@
});
});
root?.querySelectorAll(".timeline-scenes[data-chapter-drop-target]").forEach((chapterBody) => {
const chapter = chapterBody.closest("[data-chapter-drop-target]");
const chapterId = chapterBody.dataset.chapterId || chapter?.dataset.chapterId;
const chapterLabel = chapterBody.dataset.chapterLabel || chapter?.dataset.chapterLabel || "this chapter";
chapterBody.addEventListener("dragover", (event) => {
const payload = readPayload(event);
if (payload.type !== "scene" || !chapterId) {
return;
}
if (event.target.closest(".timeline-scene-card[data-scene-id]")) {
return;
}
event.preventDefault();
event.dataTransfer.dropEffect = "move";
chapterBody.classList.add("drop-target-active", "drop-chapter-end");
chapter?.classList.add("chapter-drop-active");
});
chapterBody.addEventListener("dragleave", (event) => {
if (chapterBody.contains(event.relatedTarget)) {
return;
}
chapterBody.classList.remove("drop-target-active", "drop-chapter-end");
chapter?.classList.remove("chapter-drop-active");
});
chapterBody.addEventListener("drop", (event) => {
const payload = readPayload(event);
if (payload.type !== "scene" || !chapterId) {
return;
}
if (event.target.closest(".timeline-scene-card[data-scene-id]")) {
return;
}
event.preventDefault();
event.stopPropagation();
suppressSceneClickUntil = Date.now() + 800;
clearDropHighlights();
const sourceCard = root.querySelector(`.timeline-scene-card[data-scene-id='${CSS.escape(payload.id)}']`);
if (sourceCard?.dataset.chapterId === chapterId && chapterBody.lastElementChild?.dataset?.sceneId === payload.id) {
showForm("scene", "Scene already here", `${payload.label} is already at the end of ${chapterLabel}.`, "Scene move");
return;
}
const form = forms.get("scene");
setValue(form, "SceneID", payload.id);
setValue(form, "AnchorSceneID", "");
setValue(form, "TargetChapterID", chapterId);
setValue(form, "Position", "End");
showForm("scene", "Move Scene?", buildSceneMoveSummary(payload, sourceCard?.dataset.chapterLabel || "", chapterLabel, "After", chapterLabel), "Scene move");
});
});
const assetDependencyForm = forms.get("asset-dependency");
const updateAssetPreview = () => {
const source = assetDependencyForm?.dataset.sourceLabel || "Source asset";