Phase 1P
This commit is contained in:
parent
30845f05cd
commit
8f56934dd8
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSU227cNhCGX0Xg9VLmSTzozrBb1HXTLGKjLXpHcYa2EC21oKhNA2PfPaB2i8S9650w0D+Hb/7hG0n+gKQnt8fjTydMZSE7UsYtJJjQlGnK+DNnvZQ9t63uDBNC/012ZHzEr6QnRoXAg0MqUSNVwDo6yBgoADrOODDRqZrTvyykfyN+bAFPY8B2Xv7AvIxzIj35c0wwf6m1/diGaV6hzfOED2kpPoXazO8Pd4/0t9v988f95a8FlypuRyA9iTrGTmpNbScsVcwaOoho6DAohUoxGzm/yMZUMCc/tQt8/l4f5pKwhF60QraMCkfOOwK++Nry4Bd8/nqsXWyI7mt8t4W3z/6NnDCTXuz+hXlJdxOm8abMxwlPOB19XjDfhPlw8AnIjhzzfMRcRtywbJNOky/jnJprsbtpxFTIjnx8avaTL3HOh3esni4IHv4HgRPmoTYI6AHBerColJMySofaCG+t1aDc4Dkz0oKxAyDnbhARTZBBdBGCgrrQl2ke/PTrsvFzgg0WmBFaoEInlNYuMJQWY2eQgdd60DY4kNYIZcFK77znbkATnA413wcfXseEzcM96QnjKEBapFFwTZUFT30nHdVa6og8OCPqNHdzKmNa53VpHlLBl7zxIz352U8LXsjd5vA6FgxlzRXqX7oW2+cZ1lCa7w7grGWtZKyK1nJcS/MJYcwYCla8z3m95vuPRGixie7WnDGVZu/La/OLX14rFW8D966OqkOI2DGMDJjXzABq0AhKgAHlFGjlWNDKD1yB7/gQa4TsCFbDNZvHuZYQ3RBp6LSmSntBrdNIBaDq9NBxofg7js3Hqep8sEwhSOowAlWOe+qUlBRk543Q0RgRf0ByNR9nNRng6XKtWwcawCJoToXiHVXOcWpdZ+hg7OAGbbELtedHzAmnH0B9GEOelzmW5urd5h26T2uqL06z+fjLmOg/247u5/AZc1N37MdUD+y61vOOHNAva8bD9mD1b2Rfr6t53t4tYdrOcb4jT8Xnsh6vYa3artPqfD6fvwEAAP//AwAyyd9e9QQAAA==
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUXW/bNhSG/4rAa1EhKYoSdZc5K2akbdzGa4fdUeShQ0QhDYpKFwT+7wNlB7Fb7GJ3whHf8/Gcl3xFXj0B6tH1fv/7M/g0oRIlt4QYYQITgQndUtLXdU9lxQQRrZB/oxK5W3hBPWq51lRLwDUIwNyQBg+11dgYkJRQQ1jDc061m1D/ipSrDDw7DVWYvkGcXPCoR9+dN+FHrq1cpccwmyqGEdZ+Ssrr3Mzn9eoWf7zebO82x1MTTFlcOYN6ZIW1TS0E7hrWYU66Fg/MtngYOAfOSWcpPcqcTxC9GqvJPL7XNyF5SLpnFasrgplEhxIZlVRueVATbF/2uYsF0U2Ol0t4+exf0TNE1LPyDeYx3ZUe3dXTNMxuNFdj2O2c362Ct243R5Vy4RLtY9hDTA4WOL85r+LLx7Db5XzogxonQCXaQnxyXo3HHzdg1Tym+zDHhcxkHv/rDOqRmlNAJVpIjuNStjgNsxod+PSL9qzw3X2xGVWyIT5dLOn+yH79P9B/UvrBeSjWN6hHhAIzdQfYMiow74zCqqklFqIWFqiWLcuaVfDJ+TnMU7H2CXYnahf9XUf94BLoNMc8018im20Tg5l1Kt4XTElFqpqQLJrTfk7FVzAugk6Qh9jG+ZTvJwkTbBF9cCP8gmc1xwg+FRuVHoo/1PSAeiRVp6mSSioltLbQELDEECVIa0AYAYYz0xouuRFcEi24Gig3qqGDzRFUIsgmKxZfQwbUDRoTagfMBwVYUc4wpQOta8qoge4CbnE3Zp3SHeFgaizBGswlVVjyusamblTLhG1bZs84bY+GoCRTPzfhnxOYk5c+H639NruB5+M9XvoUxnRgBMWM0wZzKSnuZNPioe0GOYgOGp0nWwU/hTeQ3yAOYXIpPyJfZgfZiRcH3vdyC9HDeLabT07HMAWbipMpi4ttfZ19fsOKxaA/nMf/LLa4CfoRYpFtpZw/W+XhcDj8CwAA//8DAEHbGBYKBQAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxUTW/bOBD9KwLPpkJSFPUB7MFwWqyRpjESd3exN4ocxkRk0qAop0GR/76gLNdO0cPehNF8vHnvDX8gJ/eAWrQ8HD4dwcUBLVC0U4gRJjARmNAtJW1RtLTJeVUwRot/0QLZO3hDLaq4UlQ1gAsQgLkmJe4Ko7DW0FBCNWElTz3l84DaH0jaXMPRKsj98BeEwXqHWvS3ddq/ptnS5qr3o86D72HthiidSmC+rld3+Mtys33YnLIGGFJxbjVqkRHGlIUQuC5ZjTmpK9wxU+Gu4xw4J7Wh9FRmXYTgZJ8P+uUyX/voIKqW5azICWYNel8gLaNMkDs5wPbtkFBMFN2m+GIKT5/tD3SEgFq2OJN5anejenuzH7rR9vomyvAM0QS5h1cfXuAoe7RAh+APEKKFiZuHp+wCiZKc5EwwQtAC3Uu1sw6y9W320KeFpaoJB13gBozGvKESN7wosC5KWTFhqooZtEB3EBz0V13vrQp+8CZmM+XZhzkr76J1ox+HbO0iPAcZT3WfZT8AWqDN2PV22D2C1G9b/zimf27s0y6rMQRwMdvIuMv+lMMOtaiRtaKykY2UQikDJQFDNJGCVBqEFqA505XmDdeCN0QJLjvKtSxpZ1IELdDDGA9jPPP//QrENtj9HvQFwXbieNPLaHzYrzW4aI1N0pwzJkP1/bRVNvdc9RZc/EAyahGhwHRRAzaMCsxrLbEsiwYLUQgDVDUVS45aeWfs8/iTJ2KM5oUp61p0TUcJMFPVnFSmI1qZQjW67KBiFalqqBtFSFdyWneNIhpoyXXaLng9qvirFYpJoMfRpevM1mntV+vwd8EvjGyCj175Pglme3h6GyLsf6fayu8PfrAx7W9mab8NcO9d+jvf/8zZXLz08RKDdAfZdHpV09GqqAtMea0wp5zgDiRg01W16CQpjGRogW69eoGQJYNJ6yZNzp56eMqWQe1sBBXHkCb/My11kvPz+WQufORfP21XPsDycFjM0T+OiaRTs7MBPrwr34aUvvND2iKG8cpHT9CbM64rN2k4nl4qm4JC6xq0oJhxWmLeNBTXTVnhrqq7phM1lOri1uwRtA2g4tRve5o2E/s7Wy5DtEaqOKTb+eLV5KbZnnPKryCvVPtZfRp+pdzspLkTJcmxT6d3czLQ/3o239/f3/8DAAD//wMAbueSACcGAAA=
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUUW/kJhDHv4rF8+IDjDH4LUpadZVes7qL2qovqzEMWRoHbzHO9RTtdz/h3SiX3lPf7NH8h5kf/+GFRHhC0pOr4/GnZ4x5JhuSwxoSTCjKFGX8nrO+aXrBaiV4K1TzF9mQcItfSU86aS23BmmDCql0rKVD4y11Dg1n3DHRylITHmbSvxAItcPnYLGe5t8xzWGKpCd/hOimL+VsCLUdp8XVaRpxG+cM0ZZmftte39Jfr3b3d7tz1oxzEdfBkZ545X3bKEV1KzSVTHd0EL6jwyAlSsm05/wsCzFjijDWs3t8O99NOWK2vahFUzMqDDltiIMMpeUBZrz/eixdrIhuSnyzhtfP/oU8YyK92LzCPJf7YMfwIS2RbMgxTUdMOeDKYB1rHCGHKVaXytdjwJjPqX+jzft1LqFtZ9xgUMrOOgRsG2eZE5I1qN3APZfSNmi0ZUbyllnPtADvRavB6wHJhtx9rnYjZD+lp3egP5/5bf8Hvo9gDyFitb0hPWEchWs0Ui+4olI7oNA2hirVKI/cmk4UzfUUc4jLtMzVNmZ8SOvUpCc/wzhf+rtK9hAy2rykguJPVQwzwhLtYX9Mkw8j7sO8d+hhGXPp96LdpcktNldvF8lZzeqGsVJ4ycclV5/QhYQ2Yxn0Pi2XM/8jEUqsouslJYy52kE+VL/AfCA9MaAtBwMGQFnrsWXomWOgWOdQOYVOCtc5aaRT0jCrJAxcOmj54EuEbAgW31TrlQLnjbGaU+OlotILoKbVgg5M2qHpwBgQ71hXd+Oqs5pJdA016B2VhgM1smmoa1rohPJdJ3yx+PG4z2dLvTqpGNV9R+viOM74j5gT/rPgfIZ14b1fznKHz+fNXcdQzml0ilMheUulMZxq03Z06PRgBqWxtWXwW0wRx+9ofww2TfPkc3WxYvWO/6clltenWm35JUT672qGm8k+YqqKmSDEsmwX/5w25AlhXhI+rY9X/0KOYB/hoYziMWG0uLfTEvO6n7N7fP3jb6v2QyY7nU6nbwAAAP//AwCS5D12GwUAAA==
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRUXW/cKBT9KxbPxuHL2PgtmrTaUbabUTvqrvYNw6VBcWAEOG0UzX9f4ZlVm6fVviB0zbmce87BbyjoZ0ATuj2dPrxAKBm1qPitxAiTmEhM6JGSifOJkY4MsidU/o1a5O/hFU1oEMZQowBzkICFJT2euTPYWlCUUEtYL2pP/S2j6Q1p31l48Qa6mL9Cyj4GNKE/fbDxe71b+84scbVdigvsQy46mErmj/3uHv9+ezg+HC6nMuQK7rxFE3LSuZ5LiceejViQccAzcwOeZyFACDI6Si8wHwqkoJcu26ef99tYAhQzsY7xjmCm0LlFVhddKc86w/H1VFlsEt3VeruVt+30hl4goYm1/4p5aXdjFn/znOfVL/bmshadn/K2Om1KTK+oRacUT5CKh02f25zheV5ejzo/fbycqdv84QeYtYDdxTUUNCHKe9SiTaBl0cXH0Fw57hYPoWwfS/Ihe/NfvThq0cOX5rDo4mJ6fufHl4vM+/+h8idtHn2AZn+HJkQoMMtHwI5RicVoNdY9V1hKLh1QowZWMbsYig9rXHOzDwW+pW0kNKGPeslw4XebzKMvYMqa6px/yZqrQ4p2NaX56SUlHek4IRW0ltNams9gfQJToA5xTOu139f3ECbZBtqtKUEozUGXx+Y3nR/RhJQeDdVKK62lMQ56Ao5YoiUZLEgrwQpmByuUsFIoYqTQMxVW93R2tYJaBDU6zZbWQTDKBykwJUZjocYeK8MUZvMsCFdumPn4TsfmYak4bUYiwHKswFksFNVYCc6x5b0emHTDwNwvklzzQEkV2MLL5d1tDKS1I1hJMRO0x0IpikfVD3gexlnNcoTeVM73kAIsvwj1yZsUc3SluSakeSfd5zXUf0ezpeW7D/jH5tFdNE+Qmuqx9qE+laut5/P5/A8AAAD//wMAG9hLKYIEAAA=
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRTTW/UMBD9K5HP69R2HMfOrdqCWBXoClaAuDmeMbWaOivHKaBq/ztydhGUGxfLGvnNvI/xM4n2EUlPro/HV08Y80w2JIe1JJhQlCnK+IGzvml6wWrWGcl185VsSLjFn6QnnXSOO4O0QYVUAmvp0HhHAdBwxoGJVpae9ttM+mdiQw34FBzW0/wJ0xymSHryOUSYvpfZNtRunBao0zTiLs7ZRlfIvN9tb+nb6/3hbn9+NeNcwHUA0hOvvG8bpahuhaaS6Y4Ownd0GKREKZn2nJ9hIWZM0Y71DA9/5sOUI2bXi1o0NaPCkNOGgM22UB7sjIefx8Jiteim1Ddreb32z+QJE+nF5reZ53ZXbgxXj/OwhBGuzme280NReUzTEVMOuHqyyhxHm8MUq8uk7RgwZrIhdx+r/Wizn9LjC6M+nvXv/kP+oUx/9QPdkhG20xIz6QlvNNmQd9bdh4jV7ob0hHEU0GikXnBFpQZLbdsYqlSjPHJnOlHabaeYQ1ymZa52MeO3tAogPXltxxnP1K+Tuw8ZXV5SUfVFlV3YpwkWl6s//nNWs7phrICWfFxy9QEhJHQZi75DWi79/oEIJVbQdkkJY672Nt9Xb+x8T3pirHbcGmusVc55bBl6Bswq1gEqUAhSQAfSSFDSMKekHbgE2/LBlwrZECxxV+uGWSs19y3QwXtBZQOcGq49VUwyrTvmwbz0sbobV5zTTCI01KAHKg231MimodC0thPKd53wf1lySZ+zYjDg0/mvrAwUgEZQnArJWyqN4VSbtqNDpwczKI2tK5xvMUUc/zLqXXBpmiefq8vyVC+s+7DE8t+rdZG+h0h/rBndTO4BU1UytiGW9b7EejqdTr8AAAD//wMAMdT3xzYEAAA=
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxU227cNhD9FYGvFRXeRJF6c20HXaSOjeyiLfo2Ikc2a5laUJSTwPC/F9TauaJAXwRhSM45c+bMPJEID0h6cnY8Xj5izAupSQ5bSDChKdOU8QNnvZS9YA0zQlut/iY1Ce/wM+lJp5zjziKVqJEqz1o6yNFR79Fyxj0TrSo54XYh/ROB0Hh8DA6befkD0xLmSHryZ4h+/liwITRumlffpHnCXVwyRFfIvN+dv6O/n90crm9OtxZcyuMmeNKTUY9jK7WmphWGKmY6Ooixo8OgFCrFzMj56VmIGVOEqVn8/Vd8P+eI2fWiEbJhVFjyXBMPGQrlARY8fD4WFptEFyVeb+Htt38ij5hIL+pXMU/p3rgpvHlYhjVM/s32JTU5pvmIKQfc1LjeV19JcNawRmjBGKnJFbi7ELHaXVTXUykRnGEKvaQWR0+V5UCtkpJ62UIn9Nh1YiQ1eYcp4vRN1qvg0rzMY65eRK6+w9mfnV9GGCYsGG9hWpDUZLfsM0QP0xzx8hO6NZ9yHdJajs/nmENc53WpdjHjbYKX89f352tKGHN1A/mu+g2WO9ITC8ZxsGABtHMjtgxH5hlo1nnUXqNXwndeWeW1ssxpBQNXHlo+jCVCavJr0XC/OofL8pXNZpJp2jhUL306nwLG/J2MpCeMo/DSIB0F11QZDxRaaanWUo/Ine0Ef4U5QLrFXKxlhmFgzg1CWe5AWJB+ZNLr0QrRdaBG2XZKaN2yDpzvOsGVlx06kKNkRpCa3KTZry7/2Gq5NeAmzf+gy0Uq0hPN2tY4GAahFTdgDSquldEWO6tGYEq6AXhrYBg4g5Y5a4QDri2owbfjF5Uu422IeBGW4wSfv8E1jW7kLw7A8BHUD9ffJnjAj3O6f3+ycfP+8kBq8mGNZSNUu2KRjyHST7pM9NU65XC4Swge/dXs8WcfYRmXaptQN9gRteVUm5ZTpUegRrZIbWfkgNJrhyXpxezuMVXFYRBimaovya731VlydyGjy2sq/P7aeFzvq5sJ8jinh+82yTeF/ShAIyRnpTMeH0/baOOovTfoNadC8ZYqazk1tu3o0JnBDtpg64pi12s+rrn6gD4kdHmr+MWLG+b5Hbr7n8V4dcGLRTkrXtufttgm7f9aYs81eUBY1oQP27bun8guRkwb8sV6GsVdvArTFBZ0c/QL6Y3kje20fSH4n9fatuk6K56fn5//BQAA//8DAPehEukZBgAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUTW/cNhCG/4rAsyjzS/zQzbBbdOGmXsSLNuiN4gxjIVppQVGbBsb+94LaLRL3lpsw0My888w7fCOTPyLpyP3p9MsZp7yQmuRhCwkmNGWaMn7grJOyU6qR0mlnxN+kJsMTfiMdMSoEHhxSiRqpAtbSXsZAAdBxxoGJVpWa/vNCujfihwbwPARs5uVPTMswT6Qjfw0TzF9Lbz80YZxXaNI84m5asp9CEfPH7uGJ/n6/Pzzvr38tuJTkZgDSEa4VF7wHGnmIVDkhqXVaU40SgnbBeQ/XtGHKmCY/Ngt8+d4f5jxhDp1ohGwYFY5cagI++yK59wsevp2Kig3RY4nXW3j77N7IGRPpRP0fzGu5uzAOd8vaj3jG8eTTgukuzMejn4qWU5pPmPKAG5Yzpn5ehlyIhmC8tZyD9Ua1BqxshTQgGYJlpgUHzmulowhtG6G3zqioQHAFGpXqDanJBm4cfR7mqbppfxgHnDKpyfNLtR99jnM6vkP/ciW6+wmgRXaZF9ADgvVgUSknZZQOtRHeWqtBud5zZqQFY3tAzl0vIpogg2gjBAXFHx98eB0mrHaPpCOMowBpkUbBNVUWPPWtdFRrqSPy4IzgpCYP85SHaZ3XpdpNGT+nbV7SkV/9uOB10vsUXoeMIa+pQPikS7N9mmENufpuAM4a1kjGStKaT2uuPiIMCUPGguOQ1lu9/6UILbakhzUlnHK19/m1+s0vr6QjrTaiVUwF30qOIkQnWGTMOilACQxGAxohQq+UizLKNvQ+9MbGHkH2pkyIxW/VZnEJrQTDDGXQAlXCeGq5c1S5FpmyPUbQ7zhWz2PJ88EyhSCpwwhUOe6pU1JSkK03QkdjRPwByc0snJX2gOfrsW4KNIBF0JwKxVuqnOPUutbQ3tje9dpiGxypyROmCccfQH0YQpqXOebq5rXqHbqP61QenGrz3ddhov9sO3qcwxdMVdmxH6ZyX7e1XmpyRL+sCY/be9W9kX05ruqwPVvCNpwrXZOX7FNeT7ewdI2RQl0ul8u/AAAA//8DANzcjJX0BAAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRUTW/cNhT8KwLPS5lfokTd3HWDLpzETrxNit4o8nFNWCYXFOXUMPzfC2rX8G6CHnoTqDdv3psZ8gUF/QioR5f7/e9PEPKEVij75YgRJjGRmNAtJT3nvRB1J6WglPyNVshfwzPqUSuMoUYB5iABC0saPHBnsLWgKKGWsEaUnno3of4FaV9bePIG6jh9gzT5GFCPvvtg44/CrX1txjjbOsURNmHKOpgyzOfN+hp/vLzd3tweqiaYCrj2FvWISkEZHSx21DgsFOO4U1JiCdwaqYzS2h5gPmRIQY/1ZB/e+W3MAbLpWc14TTBT6HWFrM66jDzoCbbP+zLFItFVOV8tx8tn/4KeIKGerd7EPLS7MKO/eJyG2Y/2Yoy7nQ+7dQzO7+akcyFeoX2Ke0jZwyLObz7o9Pwx7nalH/qgxwnQCm0hPfqgx8OPK3B6HvNdnNOizGQf/qsG9UjPOaIVWpQcx4W2Oi6zHj2E/Av2hPjmrroddXYxPZ6ZdHfQfvM/pP+kzb0PUG2uUI8IBWZ5B9gxKrHorMa64QpLyaUDalTLKFqhdQzZhznOU7UJGXZH1c7mu0zm3mcweU5lp79kCdttinY2uXo3mJKa1JyQAprzfs7VV7A+gclQltim+djvJwiTbAF98CP8Is96TglCrm51vq/+0NM96lEjW9YIIoxuOAVmnGLEEdIpzqxgYFppoWXMDEIoxx1vzKDN0HZuAMuHtqwNJWTVkmtonOycpFi2ncCCcIYHRzm2rVWtsta2Q3MmbnUzFpw2HRFgOVbgLBaKaqwE59jyRrdMurZl7kSn7SEQlBT60xD+OYE9ZunzIdpvu1t4OtzjZU5pbQdWUswEbbBQiuJONS0e2m5Qg+ygMepg6BTfhPwGaYiTz+UR+TJ7KEk8K3j35RpSgPHEm0/epDhFl6tjKKszt77Oobxh1RLQHz7gf5ZYXEXzAKkqsdI+nFj5+vr6+i8AAAD//wMA0bGPpgoFAAA=
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUTW/cNhCG/4rA81Lml/ihm2G3qOumWcRGW/Q2Ioe2EC21oKhNA2P/e0DtFol7600Y6J0ZPvPOvJEEByQ9uT0efzphKgvZkTJuIcGEpkxTxp8566XslWolU9IJ9jfZkfERv5KeGOU99w6pRI1UBdbRQUZPQ0DHGQ9MdKrmhJeF9G8ExjbgafTYzssfmJdxTqQnf44pzF9qbRhbP81raPM84UNaCiRfm/n94e6R/na7f/64v/y14FLF7RhIT7hWXPAh0Mh9pMoJSa3TmmqUwWvnHUC4yMZUMCeY2iV8/l4/zCVh8b1ohWwZFY6cdyRAgdryAAs+fz3WLjZE9zW+28LbZ/9GTphJL3b/wryku/HTeFPm44QnnI6QF8w3fj4cINVejnk+Yi4jbli2l04TlHFOzbXY3TRiKmRHPj41+wlKnPPhHaunC4KH/0HghHmoDQaEgMFCsKiUkzJKh9oIsNbqoNwAnBlpg7FDQM7dICIaL73oYvAq1IG+TPMA06/Lxs8JNtjAjNACFTqhtHaeobQYO4MsgNaDtt4FaY1QNlgJDoC7AY132td8H8C/jgmbh3vSE8ZRBGmRRsE1VTYAhU46qrXUEbl3RnCyI3dzKmNa53VpHlLBl7zxIz35GaYFL+Rus38dC/qy5gr1L12L7fMcVl+a7w7grGWtZKyK1nJcS/MJw5jRF6x4n/N6zfcfidBiE92tOWMqzR7Ka/MLLK+kJ502olNMeegkR+GjEywyZp0UQQn0Rgc0QvhBKRdllJ0fwA/GxgGDHEx9IVbDNZvHQYFTAwTqFTCqBHYUGNeUu6i7LqIG9p5j83HadN4yhUFShzFQ5ThQp6SkQXZghI7GiPgDkqv5OKvlA54u27p1oEOwGDSnQvGOKuc4ta4zdDB2cIO22HlHduQRc8LpB1AfRp/nZY6luXq3eYfu05rqxWk2H38ZE/1nm9H97D9jbuqMYUx1wa5jPe/IAWFZMx62g9W/kX3druZ5u1vCtpwrvSNPBXJZj9ewdK2RQp3P5/M3AAAA//8DAEQ8Blv1BAAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxU227cNhD9FYGvFRXeRIp6c20HXaSOjeyiLfo2JEc2a5laUJSTwPC/F9LauaJAXwRhyJlzeObMPJEED0h6cnY8Xj5iKjOpSYlbSDChKdOU8QNnvZS9ahttOmG5+ZvUJL7Dz6QnRnnPvUUqUSNVgbXUycHTENByxgMTrVprwu1M+icCsQn4GD020/wH5jlOifTkz5jC9HHFhtj4cVpCk6cRd2kukPxK5v3u/B39/ezmcH1zujXjvCY3MZCecK244C7QgfuBKisk7azWVKMMXltvAcIpLaaCOcHYzOH+K36YSsLie9EI2TAqLHmuSYACK2UHMx4+H1cWm0QXa7zewttv/0QeMZNe1K9insq98WN88zC7JY7hzfYlNTnm6Yi5RNzUuN5XX0lw1rBGaMEYqckV+LuYsNpdVNfj+kTwHVMYJLU4BKosB2qVlDTIFozQgzFiIDV5hznh+E3Vq+jzNE9DqV5Err7D2Z+dXyZwI64Yb2GckdRkN+8LpADjlPDyE/qlnGod8rIen0+pxLRMy1ztUsHbDC/nr/nnS86YSnUD5a76DeY70pNWG9Eqpjy0kqPwgxVsYKyzUgQl0Bsd0AjhnVJ2kINsvQPvTDc4DNIZTmry66rhfvEe5/krm80k47hxqF76dD5GTOU7GUlPGEcRZId0EFxT1QWg0EpLtZZ6QO6tEV9gDpBvsZCeDJ1zjnnvhLLcg7Agw8Bk0IMVwhhQg2yNElq3zIAPxgiugjToQQ6SdYLU5CZPYfHlx1bLrQE3efoHfVmlIj3RrG07D84JrXgHtkPFteq0RWPVAExJ74C3HTjHGbTM20544NqCcqEd7Cv9y3QbE17E+TjC529wu0Y38hcP0PEB1A/X32Z4wI9Tvn9/snHz/vJAavJhSetGqHarRT7GRD/pdaKvlrHEw11GCBiupoA/+wjXcam2CTXMtuC0pO2gJVUDN9SBZNSABoZaCGCO1ORi8veYq9VhENM6VV+KXe+rs+zvYkFflrzy+2vjcb2vbkYow5Qfvtsk3zzsRwEaITlbOxPw8bSNNo46hA6D5lQo3lJlLaedbQ11pnPW6Q5bvyp2vZTjUqoPGGJGX7YXv3hxwzy/Q3//sxivLnixKGer1/anLbZJ+7+W2HNNHhDmJePDtq37J7JLCfOGfLGcRnGXruI4xhn9lMJM+k7wRgshXwj+5zUlG6Vs9/z8/PwvAAAA//8DADP4f00ZBgAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRUy27cOBD8FaHPosyXKFE3Y5xgB96sB8kgG+RGka2YsEwNSMqJYfjfF9TMwvFpsReCoFjd1VVFvUAwjwgDXJ9OH54w5AQ1ZL8dccoVoYpQdmR0EGKQbaM6xgTrvkMN/hafYYBOWsusRiJQIZGOtmQUkyXOoWaUOcpbWWqaHwmGFzC+cfjkLTZL+oox+SXAAH/74JafpbfxjZ2X1TVxmXEfUjbBFjJ/7Xe35M/rw/HucL6VMBVw4x0MwJRknI2OTMxORGouSK+VIgqFs0pbbYw7w3zIGIOZm+Qe3vq7JQfMduANFw0lXMNrDc5kUyiPJuHx+VRYbBLdlPN6O962wws8YYSB1/+KeS53ZWd/9ZjG1c/u6rxmkx7Stk7G5iU+Qw2nuJwwZo+bPtcp4eM4Px9Nevh4vlO26cMvtGtGt1vWkMvEooUaNoHm2WS/hOrCcTd7DHn7mKMPydv/qiWghrsv1WE2eVri4zs/vpxl3v8PlT8Ze+8DVvsbGIAy5E70SCbOFJG9M8S0QhOlhJqQWd1xBjXslpB9WJc1VfuQ8UfcRoIBPpo54ZnfdbT3PqPNayxzflMlV4e4uNXm6s1LRhvaCEoLaM2nNVef0fmINmMZ4hjXS72v7yFc8Q20W2PEkKuDyffVHybdwwCt6ngrqbSmFQy5nTSnE6W9FtxJjrZTDjvO7SilnsQkWjsaO3b9NKITY1cmxBKdaktrL0Y3Wm1IK7QjUlBO+l51BC3VveiZQlksedOxupsLztieSnSCaJwckZoZoqUQxInWdFxNXcen3yS55IHR0t7h0/ndbQyUcz06xQiXrCVSa0Z63XZk7PpRj6rH1mqo4RZjwPk3oT55G5e0TLm6JKR6J93nNZR/R7Wl5acP5Nfm0c1iHzBWxWPjQ3kqF1tfX19f/wEAAP//AwD694M2ggQAAA==
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxUyW7jOBD9FYFnU+GmFZiD4XRjjHQ6RuKeGcyNSzEmIosGRSUdBPn3AWU5dhp9mJtQquXVe6/4hnq5B9Si5eHw5Rn6OKAFim4KMcJKTEpM6JaSlvNWFDmpalKV7F+0QO4GXlGLKqE11Q1gDiVgYUiBFbcaGwMNJdQQVojUUz4OqH1D0uUGnp2G3A9/QRic71GL/na98S9ptnS57vxo8uA7WPdDlL1OYL6vVzf423KzvdscswYYUnHuDGoRLQVlVBlsqbZYNIzjuilLXAI3umx0I6U5lrk+Quhllw/m6Tzf+NhD1C3LGc8JZg16XyAjo0yQlRxg+3pIKCaKrlN8MYWnz/YNPUNALVucyDy2u9Kdu9oPanSduYoyPEK0Qe7hxYcneJYdWqBD8AcI0cHEzd1DdoZESU5yVjJC0ALdSr1zPWTr6+yuSwtLXRMBhuMGrMGioRI3gnNseCErVtqqYhYt0A2EHrqLrrdOBz94G7OZ8uzTnJXvo+tHPw7Zuo/wGGQ81n2V3QBogTaj6tywuwdpXrf+fkz/+rFLu6zGEKCP2UbGXfanHHaoRUVZsUIQoWXBKTBtG0YsIXXDmREMdFUaqBjTSojGcssLraRWVW0VGK4qihboboyHMZ74/3kBYhvcfg/mjGA7cbzpZLQ+7NcG+uisS9KcMiZDdd20VTb3XHUO+viJZNQiQoEZXgO2jJZY1EZiWfAGlyUvLVDdVCyhW/neusfxgydirRHcFnVdqkZRAsxWtSCVVcRoy3VjCgUVq0hVQ91oQlQhaK0aTQzQQiSTboI3o46/WoFPAt2PfbrObJ3WfnE9/lmKMyOb4KPXvkuCuQ4eXocI+9+ptvL7gx9cTPvbWdofA9z6Pv2d73/mbC5e+niOQbqDbDo9QutCCEWxqlWBRWUKrIxKN2SJpFaQknO0QNdeP0HIksGk6ydNTp66e8iWQe9cBB3HkCb/My11lPPr6WTOfOTfv2xXPsDycFjM0T+eE0nHZicDfHpXfgwpfeeHtEUM44WPHqCzJ1wXbjLwfHypXAqWxtRgSoqZoAUWTUNx3RQVVlWtGlXWUOjmw63ZPRgXQMep3/Y4bSb2d7Zchuis1HFIt/PN68lNsz3nlF9BXqj2UX0cfqHc7KS5EyXJsQ/Hd3My0P96Nt/f39//AwAA//8DADQAEnAnBgAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRTS2/UMBD+K5HPcepXHDu3agtiVaCrsgLEzY8JtZo6K8fpQ9X+d+TsogI3LpY18jfzPcavKJoHQD26PBzePULMM6pRDmuJESYxkZjQPSU9571oG9kJSbT8gWoUruEF9agTzlGnAXOQgIUnLbZ8cNh70JRQT1grSk/zc0b9KzKh8fAYHDTT/BXSHKaIevQtRD89ldkmNG6cFt+kaYRtnLOJrpD5vN1c44+Xu/3N7vRqhrmAm+BRj6gUlFHr8UDdgIVmHCstJZbAvZPaaWP8CRZihhTN2Mz+/m2+n3KE7HrWMN4QzDQ61sibbApla2bYvxwKi9Wiq1Kv1/J67V/RIyTUs/q3mad2F24MFw+zXcLoL05nNvN9UXlI0wFSDrB6ssocR5PDFKvzpM0YIGZUo5sv1W40eZjSw19GfTnp3/6H/H2Z/u4Z3JLBb6Yl5oLlCtXok3F3IUK1vUI9IhSY5wrwwKjEQnmDTcs1lpLLAajTHaOoRpsp5hCXaZmrbczwM60CUI/em3GGE/XL5O5CBpeXVFR9l2UXdmnyi8vVm/+UNKThhBTQkg9Lrm7BhwQuQ9G3T8u53z8QJtkK2iwpQczVzuS76oOZ71CPWtmxVhDhTMspMDdoRgZClObMCwaukx46xpwVQg984K2zxtlODRY8t11RCCXuat0wq6yyzigMjA1YUK+w9lRh3jLBtQXlbaH45mN1MxaccYoI8BxrGDwWmhqsBefY89Z0TA5dx4Y/LDmnT0kZ7+Hx9FdWBtJ7BV5SzARtsdCaYqXbDttOWW2lgtZpVKNrSBHGP4z6FFya5mnI1Xl5qr+su11i+e/VukhPIeLnNaOryd1DqkrGJsSy3udYj8fj8RcAAAD//wMAYDGxDjYEAAA=
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUTW/cNhCG/4rAs6jwS5Som2G36MJNvUiMtuhlQQ2HXtYypVKU08DY/x5Iu4bj5tSbNOA7Hw/f4QuJ9glJR66m6adnjHkmJclhCwkmNGWaMn7PWSdlp3QlhOGNaf4iJQm3+JV0pFEAHAxSiRqpcqymvfRAnUPDGXdM1GrNaR9m0r0QGyqHzwGwGuffMc1hjKQjf4Toxi9rbRsqGMbFVWkccBfnbCOszfy2u76lv17t7+/251Mzzqu4Co50hGvFBe8d9Rw8VUZI2hqtqUbpQBsw1rqzLMSMKdqhmt3jW3035ogZOlEJWTEqDDmVxNls15Z7O+P912ntYkN0s8bLLbx9di/kGRPpRPkK85zuAwzhQ1oiKcmUxglTDrgx2MYaBpvDGItL5ushYMzno38j5MM2l2ihMa43qFQDDi3W0gFzQjGJreu550qBRNMCM4rXDDxrhfVe1K31bY+kJHefi/1gsx/T0zvQn8/8dv8D30cLxxCx2N2QjjCOwskWqRdcU9U6S20tDdVaao8cTCM4Kcn1GHOIy7jMxS5mfEjb1KQjP9thvvR3leAYMkJe0oriT70aZrBLhONhSqMPAx7CfHDo7TJk0hF/0e7T6BbIxdtFclaxSjK2Jl7ytOTiE7qQEDKug96n5VLzPxKhxSa6XlLCmIu9zcfiFzsfSUdq3YhaMQW2lhwFeCOYZ6w1UjglEBrtsBECeqWMl17W0Fvom9b36GTfrBRw9U2xXallvbTgDXWt9lS5VlNbO0elbrzpWb9e9TvWxd2w6aBlCp2kBr2jynBLjZKSOlnbRmjfNMKvFp+mQz5b6tVJq1Hdd7QujuOM/4g54T8LzmdYF96H5Sx3+Hze3G0M7VyLTnMqFK+pMobT1tQN7Zu2N71usQZDSnKLKeLwHe2PAdI4jz4XFysW7/h/WuL6+hSbLb+ESP/dzHAzwiOmYjWTDXFdtot/TiV5QjsvCZ+2x6t7IZOFR/uwjuIxYQQ8wLjEvO3n7B5f//jbqv1wkp1Op9M3AAAA//8DAEDxRpkbBQAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRTXW/UMBD8K5Gf49RfceK8VVcQpwI90QoQb4695ixS++Q4pVV1/x05d6gtb7xZK8/s7MzuMwr6HtCALg+Hdw8Q8oxqlP1aYoRJTCQm9I6SgYuB8aYTnWS9+IFq5K/hCQ2oE8ZQowBzkICFJS0euTPYWlCUUEtYKwqn/jmj4Rlp31h48AaaOH+FNPsY0IC++WDj79Jb+8ZMcbFNihNsw5x1MEXM5+3mGn+83N3d7E6/ZpgLuPEWDYhKQRkdLXbUOCwU47hXUmIJ3BqpjNLanmA+ZEhBT81sf730tzEHyGZgDeMNwUyhY42szrpIHvUMd0+HomK16KrU67W8Podn9AAJDaz+a+aJ7sJM/sLE+3sd7IXzwc97VKNDigdI2cNqxzrhNOnsY6jOTTaTh5BRjW5uq92ks4vp/o1Ht6fRt/8x+Sdt9j5Atb1CAyIUmOU9YMeoxKK3GuuWKywllw6oUR2jqEabGLIPS1zmahsy/EyrSjSg93qa4aTvMpm9z2Dykor077JkDY8+b6ItBVyIdinaxeTqxW9KGtJwQgrJkg9Lrr6A9QlMhjLUXVrO/P9AmGQraLOkBCFXO5331Qc979GAWtmxVhBhdMspMOMUI46QXnFmBQPTSQsdY2YUQjnueGtGbcaudyNYPnZFKJR4q3WjBG1BqI5gSjXFQlCLR2dHPBrRgRRC9oa/8bW6mQpOm54IsBwrcBYLRTVWgnNseas7Jl3XMffKknPklJT2Fh5Ot7EqkNb2YCXFTNAWC6Uo7lXb4bHrRzXKHlqjUI2uIQWYXhn1yZsU5+hydd6Y6o11X5ZQ7rtat+e3D/hxzewqml+QqpK59qGs8znm4/F4/AMAAP//AwBbRwxXJgQAAA==
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRUTW/bOBT8KwLPosIvUaJuWWeLNdI2buNtF3ujyCeHiEIaFJVuEPi/Lyg7iN1iD3sTqDdv3psZ8hV5/QSoQ9f7/e/P4NOESpTccsQIk5hITOiWko6LjotK1aJumfwblcjdwgvqUCOMoUYB5iABC0tq3PPBYGtBUUItYbXIPfVuQt0r0q6y8OwMVGH6BnFywaMOfXfehh+ZW7vKjGG2VQwjrP2UtDd5mM/r1S3+eL3Z3m2OVRNMGVw5izpEWMsk1TWGVrRYSAZYi7bGmtp2kIY3qrVHmPMJotdjNdnHd34bkodkOlYxXhHMFDqUyOqk88i9nmD7ss9TLBLd5PNyOV4+u1f0DBF1rHwT89juyozu6mnqZzfaqzHsds7vVsEPbjdHnTJxifYx7CEmB4s4vzmv48vHsNvlfuiDHidAJdpCfHJej8cfNzDoeUz3YY6LMpN9/K8a1CE9p4BKtCg5jgttcVpmNTrw6RfsGfHdfbEZdRpCfLow6f6o/fp/SP9JmwfnoVjfZAwFZnkLeGBUYtFajXXNFZaSywGoUQ2jqESr4JPzc5inYu0T7E6qXcx3Hc2DS2DSHPNOf8kctk0MdjapeDeYkopUnJAMmtN+TsVXsC6CSZCX2Mb51O8nCJNsAX1wI/wiz2qOEXwqNjo9FH/o6QF1qJYNqwURRtecAjODYmQgpFWcWcHANNJCw5jphVADH3htem36ph16sLxv8tqQQ1YsuW6bnnLW11jZAbBg1OC25g1WhA4EgNZCX4pb3I0Zp01LBFiOFQwWC0U1VoJzbHmtGyaHpmHDmU7bYyAoyfTnIfxzAnvK0udjtN92t/B8vMfLnNLaFqykmAlaY6EUxa2qG9w3ba962UJt1NHQKbwJ+Q1iHyaX8iPyZXaQk3hR8O7LLUQP45k3n5yJYQpDKk6hLC7c+jr7/IYVS0B/OI//WWJxE8wjxCLHSjt/ZuXhcDj8CwAA//8DAGAI+UoKBQAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSU227cNhCGX0Xg9VLm+aA7w25R102ziI226B3FGdlCtNSCojYNjH33gNotEveud8JA/xy++YdvJIUDko7cHo8/nTCVhexIGbeQYMJQZijjz5x1UnVStdJrzZ39m+zI+IhfSUesipFHj1SiQaqAadrLIVIA9JxxYEKrmjO8LKR7I2FsAU9jxHZe/sC8jHMiHflzTDB/qbXD2MZpXqHN84QPaSkhxdrM7w93j/S32/3zx/3lrwWXKm5HIB1hwgnDg6bolKPKCKRBOU0DBzeYKK13cJGNqWBOYWoX+Py9PswlYYmdaIVsGRWenHcEQgm15T4s+Pz1WLvYEN3X+G4Lb5/dGzlhJp3Y/Qvzku4mTuNNmY8TnnA6hrxgvonz4RBS7eWY5yPmMuKGZZt0mkIZ59Rci91NI6ZCduTjU7OfQhnmfHjH6umC4OF/EDhh7muDgAEQXACHSnkpB+nRWBGccwaU7wNnVjqwrgfk3PdiQBtlFHqAqKAu9GWa+zD9umz8vGC9A2aFEajQC2WMjwylw0FbZBCM6Y2LHqSzQjlwMvgQuO/RRm9izfchxNcxYfNwX6fhKEA6pIPghioHgQYtPTVGmgF59FZwsiN3cypjWud1aR5SwZe88SMd+TlMC17I3eb4OhaMZc0V6l+mFtvnGdZYmu8O4KxlrWSsitZyXEvzCWHMGAtWvM95veb7j0QYsYnu1pwxlWYfymvzS1heSUe0sUIrpmLQkqOIgxdsYMx5KUAJjNYAWiFir5Qf5CB17EPsrRt6BNnbOiFWwzWbxwNoqFug3EpDlWKW9gw0BSkE9zZoJcU7js3HadNFxxSCpB4HoMrzQL2SkoLUwQozWCuGH5BczcdZLQ94ulzr1oEBcAiGU6G4psp7Tp3XlvbW9b43DnX0ZEceMSecfgD1YYx5XuahNFfvNu/QfVpTfXGazcdfxkT/2XZ0P8fPmJu64zCmemDXtZ535IBhWTMetgereyP7el3N8/ZuCdUyy/WOPJWQy3q8hqVtjeL+fD6fvwEAAP//AwAL3gdL9QQAAA==
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUTW/cNhCG/4rA81Lm94duht2ihpt6ERtt0BvFGcZCtNKCojYNjP3vBbVbJO4tN2GgmXnnmXf4RqZwQNKR2+PxlxNOZSE7UoYtJJgwlBnK+AtnnVSdVK2Smisv/yY7MjziN9IRq2Lk0SOVaJAqYJr2MkUKgJ4zDkxoVWuGzwvp3kgYWsDTELGdlz8xL8M8kY78NUwwf629w9DGcV6hzfOID9NSwhSrmD8e7h7p77f7l6f95a8Fl5rcDkA6woQThgdN0SlHlRFIg3KaBg4umSitd3BJG6aCeQpju8CX7/1hLhOW2IlWyJZR4cl5RyCUUCX3YcGXb8eqYkN0X+O7Lbx9dm/khJl0YvcfzEu5mzgON8vaj3jC8RjygvkmzodDmKqWY56PmMuAG5YT5n5ehlKJxmiDc5yDC1ZpC05qIS1IhuCY1eDBB6NMElHrBL3zViUFgiswqFRvyY5s4MYxlGGemqv2u3HAqZAdeXpu9mMoac6Hd+ifL0QffgJolV3nBQyA4AI4VMpLmaRHY0VwzhlQvg+cWenAuh6Qc9+LhDbKKHSCqKD640OIr8OEzcN97c5RgHRIk+CGKgeBBi09NUaahDx6KzjZkbt5KsO0zuvSPEwFP+dtXtKRX8O44GXS2xxfh4KxrLlC+GRqs32eYY2l+W4AzlrWSsZq0lqOa2k+IgwZY8GK4yWv13r/SxFGbEl3a844lWYfymvzW1heSUe0sUIrpmLQkqOIyQuWGHNeClACozWAVojYK+WTTFLHPsTeutQjyN7WCbH6rdkszrkLyUdHpWOCKsk1dazXNCaRvHEKjO7fcWyexpoXomMKQVKPCajyPFCvpKQgdbDCJGtF+gHJ1Syc1faAp8uxbgoMgEMwnArFNVXec+q8trS3rve9caijJzvyiHnC8QdQH4aY52VOpbl6rXmH7uM61Qen2Xz3dZjoP9uO7uf4BXNTdxyGqd7Xda3nHTlgWNaMh+296t7Ivh5X87I9W0K1zHK9I88l5LIer2FpW6O4P5/P538BAAD//wMAXUY/gfQEAAA=
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxUTW/bOBD9KwLPokKRlEQa2IPhtFgjTWMk7u5ibxQ5jInIokFRSYMg/31BWY6dooe9CaP5ePPeG76hXu0BLdDycPjyDH0cUI6im0KU0BqTGpNyW5IF4wtWFSWvqobKf1GO3A28ogVquNalloAZ1IC5IRVumdXYGJAlKQ2hFU891eOAFm9IucLAs9NQ+OEvCIPzPVqgv11v/EuarVyhOz+aIvgO1v0QVa8TmO/r1Q3+ttxs7zbHrAGGVFw4gxaIUEHrUlUYBBeY1xSw4qLCqjTC1po1UphjmesjhF51xWCezvONjz1EvaAFZQXBVKL3HBkVVYLcqgG2r4eEYqLoOsXzKTx9Lt7QMwS0oPmJzGO7K925q/3Qjq4zV1GFR4g2qD28+PAEz6pDOToEf4AQHUzc3D1kZ0glKUhBa0oIytGt0jvXQ7a+zu66tLDSgnAwDEuwBnNZKiw5Y9iwSjW0tk1DLcrRDYQeuouut04HP3gbs5ny7NOcle+j60c/Dtm6j/AYVDzWfVXdAChHm7Ht3LC7B2Vet/5+TP/6sUu7rMYQoI/ZRsVd9qcadmiBqrqhFSdcq4qVQLWVlFhChGTUcAq6qQ00lOqWc2mZZZVulW4bYVswrG1KlKO7MR7GeOL/5wWIbXD7PZgzgu3E8aZT0fqwXxvoo7MuSXPKmAzVddNW2dxz1Tno4yeSk6NKoIYJwJaWNebCKKwqJnFds9pCqWVDE7qV7617HD94ItYazmwlRN3KtiRAbSM4aWxLjLZMS1O10NCGNAKE1IS0FS9FKzUxUFY8mXQTvBl1/NUKbBLofuzTdWbrtPaL6/HPmp8Z2QQfvfZdEsx18PA6RNj/TrWV3x/84GLa387S/hjg1vfp73z/M2dz8dLHcwzSHWTT6cmqrbWgFeYiOVFzi6UFiQ0YyTTRpCUM5eja6ycIWTKYcv2kyclTdw/ZMuidi6DjGNLkf6aljnJ+PZ3MmY/i+5ftygdYHg75HP3jOZF0bHYywKd35ceQ0nd+SFvEMF746AE6e8J14SYDz8eXyqVgbYwAU5eY8rLCXMoSC1k1uG1EK9taQKXlh1uzezAugI5Tv+1x2kzs72y5DNFZpeOQbueb15ObZnvOKb+CvFDto/o4/EK52Ulzp5Ikxz4c383JQP/r2Xx/f3//DwAA//8DACepZYcnBgAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRUTW/cNhD9KwLPoswv8UM3Y52gCzf1IlmkRW8UOYoJy9SCpJwYxv73gtotEp+KXghiyDfz5s0j31C0z4AGdHs6fXiBWDJqUQlbiBEmMZGY0CMlAxcD7zslBFHa/I1aFO7hFQ1ICeeoM4A5SMDCkx6PfHLYezCUUE9YL2pO+y2j4Q3Z0Hl4CQ66JX+FlMMS0YD+DNEv32ttGzo3L6vv0jLDPuZio6tk/tjv7vHvt4fjw+FyK0Ou4C54NCDCNJPU9hi00FhIBtgK3WNLvZ6k48pof4GFWCBFO3fZP/2s75cSobiBdYx3BDODzi3ytthKebQZjq+nymKT6K7G2y28bYc39AIJDaz9V8xLuhs3h5vnPK5h9jeXtdj8lLd1sq4s6RW16JSWE6QSYNPnNmd4HufXo81PHy936jZ/+AFuLeB3yxoLGhDlPWrRJtA82xKW2Fw57uYAsWyHJYWYg/uvXBy16OFLc5htmZb0/G4eXy4y7/+Hyp+sewwRmv1dxVBgnmvAE6MSC+0ttj03WEouJ6DOKEZRi3ZLLCGuy5qbfSzwLW0toQF9tHOGC7/b5B5DAVfWVPv8S1ZfHdLiV1ean7OkpCMdJ6SC1nJaS/MZfEjgCtQmjmm95vv6HsIk20C7NSWIpTnY8tj8ZvMjGlAvFesFEc72nAJzk2FkIkQbzrxg4JT0oBhzoxBm4hPv3WjdqPQ0guejqh1CtU6zuZV7TaRmEybKeSy0NXgcqcKCKuJ7KrkY3+vYPMwVZ50mAjzHBiaPhaEWG8E59ry3islJKTb9IsnVD5TU8h5eLu9uYyC91+AlxUzQHgtjKNamV3hUejSj1NA7g1p0DynC/ItQn4JLS16m0lwd0ryT7vMa69/RbG75HiL+sc3obnFPkJo6YxtifSrXsZ7P5/M/AAAA//8DAKDmvtCCBAAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxU227cNhD9FYGvFRXeRenNtR10kTo2sou26NuQHNqsZWohUU4Cw/9eSGvnigJ9EQRyOOfMmTPzRDI8IOnJ2fF4+Yi5zKQmJW1HgglDmaGMHzjrpeqlblotmBH8b1KT9A4/k560ynvuO6QSDVIVmKZORk9DwI4zHpjQas0JtzPpnwikJuBj8tiM8x84zWnMpCd/phzGjys2pMYP4xKaaRxwl+cC2a9k3u/O39Hfz24O1zenqBnn9XGTAukJE1YYDpqiVZYqI5CCspoCDzYaL9vOhtOzlAtOGYZmDvdf8cNYMhbfi0bIhlHRkeeaBCiwUnYw4+HzcWWxSXSxntfb8fbbP5FHnEgv6lcxT+ne+CG9eZjdkobwZvuSmhyn8YhTSbipcb2vvpLgrGGNMIIxUpMr8HcpY7W7qK6HtUTwlikMknYYA1UdB9opKWmQGlphYtuKSGryDqeMwzdZr5KfxnmMpXoRufoOZ392fpnBDbhivIVhRlKT3bwvkAMMY8bLT+iXcsp1mJb1+nzMJeVlXOZqlwveTvBy//r+fJkmzKW6gXJX/QbzHemJNq3QiikPWnIUPnaCRcZsJ0VQAn1rArZCeKdUF2WU2jvwrrXRYZCu5aQmv64a7hfvcZ6/stlMMgwbh+qlT+dDwly+k3F1CUcRpEUaBTdU2QAUtOyoMdJE5L5rxReYA0y3WEhPonXOMe+dUB33IDqQITIZTOyEaFtQUepWCWM0a8GHthVcBdmiBxkls4LU5GYaw+LLj62WWwNupvEf9GWVivTEMK2tB+eEUdxCZ1Fxo6zpsO1UBKakd8C1Bec4A818Z4UHbjpQLujYvdK/zLcp40WajwN8/gbXNqaRv3gAyyOoH8LfTvCAH8fp/v3Jxs37ywOpyYclrxuh2q0W+Zgy/WTWib5ahpIOdxNCwHA1BvzZR7iOS7VNqLNMaS0k5SpGqkIbqRNoqHSOgXeOn1p8Mfp7nKrVYZDyOlVfkl3vq7PJ36WCvizTyu+vjcf1vroZoMRxevhuk3xT2I8CNEJytnYm4ONpG20cTQgWg+FUKK6p6jpObadb6lrrOmcsar8qdr2U41KqDxjShL5sFb94ccM8v0N//7MYry54sShna7370xbbpP1fS+y5Jg8I8zLhw7at+yeyyxmnDfliOY3iLl+lYUgz+jGHmfSW6UbKVr8Q/M8wYRothX5+fn7+FwAA//8DAOIV/fMZBgAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRTy27cOBD8FYFnUeZbpG7GOIsdeBMPkkF2sTeKbMaEZWpAUU4CY/49oGaCxHvbC0E0WF1d1cVXlOwzoAHdnk7vXiCVBbWoxK3ECFOYKEzokZKBi4HLrhe9ZtL8i1oU7+E7GlAvnKPOAOagAAtPJB55cNh7MJRQT5gUtaf9sqDhFdnYeXiJDrp5+Qx5iXNCA/o7Jj9/rdw2dm6aV9/leYJ9WopNrg7zYb+7x3/dHo4Ph8urBZYK7qJHAyJMM0WtxKCFxkIxwFZoiS31OijHe6P9BRZTgZzs1C3+6Re/n0uC4gbWMd4RzAw6t8jbYuvIo13g+P1Up9gsuqv1ditv1+EVvUBGA2t/mnlpd+OmePO8jGuc/M3lLHZ5qipPeT5BLhE2TzaZ02RLnFNzZdpNEVJBLXr41BwmW8Kcn98Y9emif/8/5B8r+7tv4NYCfjevqaABUa5Ri95b9xgTNPu72o4C81wDDowqLLS32EpusFJcBaDO9IyiFu3mVGJa53Vp9qnAl7wJQAP6w04LXEa/ze4xFnBlzVXVP6pm4ZBnv7rS/PKfko50nJAKWstpLc1H8DGDK1D1HfN67fcfCFNsA+3WnCGV5mDLY/OnXR7RgKTqmRREOCs5BeaCYSQQog1nXjBwvfLQM+ZGIUzggUs3Wjf2Oozg+dhXhVDX3WwJG0kIVmmFrZIKC9pLPAYtcBDaa80dU3x842PzMFWcdZoI8BwbCB4LQy02gnPsubQ9U6HvWfjNkuv2Kan0Hl4uf2WbQHmvwSuKmaASC2Mo1kb2eOz1aEalQTqDWnQPOcH0m1Hvo8vzMofSXMPTvLHu45rqf2+2IH2NCX/bdnQ3uyfITd2xjanG+7rW8/l8/gEAAP//AwCsEOr4NgQAAA==
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUy27cNhSGX0XgWlR4E0VqZ9gtOnBTDxKjLboZUOShh7VMqRTlNDDm3QNqxnDcrLqTiPOfy8f/8AVF8wSoR1fz/NMzxLygGuWwHTHCJCYSE3pPSc9Fz2XDlBRSdX+hGoVb+Ip61AlrqdWAOUjAwpEWD9xb7BxoSqgjrBUlp3lYUP+CTGgcPAcLzbT8DmkJU0Q9+iNEN30ptU1o7DitrknTCLu4ZBNtaea33fUt/vVqf3+3P0ctsBRxExzqEWGKSWpaDEooLCQDbIRqsaFOeWl5p5U7y0LMkKIZm8U9vtV3U46Qbc8axhuCmUanGjmTTWl5MAvcf51LFxuim3Jeb8fbZ/+CniGhntWvMM/pPtgxfEhrRDWa0zRDygE2BttY42hymGJ1yXw9Boj5HPo32HzY5mLKdtoNGoTorAMDLXeWOCYIB+UG6qkQloNWlmhBW2I9Ucx4z1plvBoA1ejuc7UfTfZTenoH+vOZ3+5/4Pto7DFEqHY3RUOBOa4Ae0YlFsoZbFqusZRceqBWd4yiGl1PMYe4TutS7WKGh7RNjXr0sxmXS39XyR5DBpvXVFD8KYthRrNGezzMafJhhENYDg68WceMeuQv2n2a3Gpz9XaRlDSk4YSUxGue11x9AhcS2Axl0Pu0Xmr+R8Ik20TXa0oQc7U3+Vj9YpYj6lErO9YKIqxpOQVmvWbEE6I0Z04wsJ100DFmByG05563djB26JQfwPGhKxSg+KbarpRqaRVXFvuOdFh46bBmrsXMU8U5HbiQ7TvW1d1YdMYqIsBxrME7LDQ1WAvOseOt6Zj0Xcd8sfg8H/LZUq9OKkZ139G6OI4S+iPmBP+ssJxhXXgf1rPcwfN5c7cxpHMKnKSYCdpioTXFSrcdHjo16EEqaK1GNbqFFGH8jvbHYNO0TD5XFytW7/h/WmN5farNll9CxP9uZriZ7COkqpjJhFiW7eKfU42ewCxrgqft8epf0Gzso3koo3hIEC0c7LTGvO3n4h5f/+jbqv0QSU6n0+kbAAAA//8DAO62JwsbBQAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRTy27UMBT9lcjrOPUrjp1dNQUxKtARrQCxc+wbxiK1R45TWlXz78iZQW3ZsYuucs49j+tnFMw9oB5dHg7vHiDkGdUo+3XECJOYSEzoHSU9F72QDSWaKkZ/oBr5a3hCPeqEtdRqwBwkYOFIiwc+WuwcaEqoI6wVhdP8nFH/jIxvHDx4C02cv0KafQyoR998cPF32W18Y6e4uCbFCbZhzibYIubzdnONP17u7m52p79mmAu48Q71iDDFJDUtBiUUFpIBNkK12FCnRml5p5U7wXzIkIKZmtn9etnvYg6Qbc8axhuCmUbHGjmTTZE8mBnung5FxRrRVZnX63j97J/RAyTUs/pvmCe6Czv5Cxvv701wF6MPft6jGh1SPEDKHtY4VofTZLKPoTov2UweQkY1urmtdpPJY0z3bzK6PVnf/ofzT8bufYBqe1UwFJjjCvDIqMRCOYNNyzWWkssRqNUdo6hGmxiyD0tc5mobMvxMq0rUo/dmmuGk7zLZvc9g85KK9O+ydA2PPm+iKwNciHYpusXm6iVvShrScEIKyZIPS66+gPMJbIZi6i4tZ/5/IEyyFbRZUoKQq53J++qDmfeoR63sWCuIsKblFJgdNSMjIUpz5gQD20kHHWN2EEKPfOStHYwdOjUO4PjQFaFQ6q3Wi5JaDm4kHDPCOixIK7EajMGiZUzygTNGi9WXXKubqeCMVUSA41jD6LDQ1GAtOMeOt6Zjcuw6Nr6K5Fw5JWW9g4fT2zgpcE6BkxQzQVsstKZY6bbDQ6cGPUgFrdWoRteQAkyvgvrkbYpzHHN1vpjqTXRfllDed7Vez28f8OPa2VW0vyBVpXPjQznnc83H4/H4BwAA//8DAKOT5R4mBAAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUTW/cNhCG/4rAsyjzS/zQzbBb1HVTL+JFWvRGcka2EK20oKhNA2P/e0DtBol7600Y6J0ZPvPOvJHJH5B05PZ4/OWEU15ITfKwhQQTmjJNGd9z1knVtappW90qxv4hNRke8SvpiFEx8uiQStRIFbCWBtlHCoCOMw5MtKrk9C8L6d6IHxrA0xCxmZdPmJZhnkhH/hommL+U2n5o4jiv0KR5xIdpyX6KpZk/H+4e6R+3u/3T7vLXgksRNwOQjlirFbOcU9lyoKo1gTrTBxqtNFq7IKMQF9kwZUyTH5sFPv+oD3OeMMdONEI2jApHzjUBn31pOfgF91+PpYsN0X2J11t4++zeyAkT6UT9HeYl3U0ch5s8H0c84Xj0acF0E+fDwU9AanJM8xFTHnDDsr10HH0e5qm6FrsbB5wyqcnTc7Ubfe7ndHjH6vmC4OF/EDhhCqVBQA8I1oNFpZyUvXSojfDWWg3KBc+ZkRaMDYCcuyB6NFFG0fYQFZSBvoxz8OPvy8bPCRYsMCO0QIVOKK1dZCgt9q1BBl7roG10IK0RyoKV3nnPXUATnY4l3wcfX4cJq4d70hHGUYC0SHvBNVUWPPWtdFRrqXvk0RnBSU3u5ikP0zqvS/UwZXxJGz/SkV/9uOCF3G2Kr0PGmNdUoP6tS7FdmmGNufrhAM4a1kjGimjNxzVXHxGGhDFjwbtP6zXffyRCi010t6aEU652Pr9Wv/nllXSk1Ua0iqnoW8lRxN4J1jNmnRSgBEajAY0QMSjletnLNgYfg7F9QJDBlBdiMVy1eVxhrwG4oD4yS5XqA/VRAkXjuYkxBAz9O47V01h0PlqmECR12ANVjnvqlJQUZOuN0L0xoui+I7maj7NSHvB02datAw1gETSnQvGWKuc4ta41NBgbXNAW2+hITR4xTTj+BOrDENO8zH2urt6t3qH7uE7l4lSbj78ME/13m9H9HD9jqsqM/TCVBbuO9VyTA/plTXjYDlb3RnZlu6r9drckb1Rra/Kcfcrr8RpVomklU+fz+fwNAAD//wMAh8LN9fQEAAA=
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSU227cNhCGX0XgtSjzfNCdYbfowk29iBdt0DuKM4qFaKUFRW0aGPvuBbVbJO5d7oSB/jl88w/fyBSOSFpyfzr9csYpL6QmedhCgglDmaGMHzhrpWq1agxjwjn3N6nJ8ITfSEusipFHj1SiQaqAadrJPlIA9JxxYEKrkjN8Xkj7RsLQAJ6HiM28/IlpGeaJtOSvYYL5a6kdhiaO8wpNmkfcTUsOUyzN/LF7eKK/3+8Pz/vrXwsuRdwMQFrinFHMcU6l5kCVth31tu9odNIa4zsZhbjKhiljmsLYLPDle32Y84Q5tqIRsmFUeHKpCYQcSstdWPDw7VS62BA9lni9hbfP9o2cMZFW1P/BvKa7i+Nwt6zdiGccTyEtmO7ifDyGCUhNTmk+YcoDbljOmLp5GXIhGqMNznEOLlilLTiphbQgGYJjVoMHH4wyvYha99A5b1WvQHAFBpXqLKnJBm4cQx7mqbr1/jAOOGVSk+eXaj+G3M/p+A79y5Xo7ieAlrbLvIABEFwAh0p5KXvp0VgRnHMGlO8CZ1Y6sK4D5Nx3okcbZRS6h6ig+ONDiK/DhNXukbSEcRQgHdJecEOVg0CDlp4aI02PPHorOKnJwzzlYVrndal2U8bPaZuXtOTXMC54nfQ+xdchY8xrKhA+mVJsn2ZYY66+G4CzhjWSsSJa82nN1UeEIWHMWHAc0nrL9z+JMGITPawp4ZSrfciv1W9heSUt0cYKrZiKQUuOIvZesJ4x56UAJTBaA2iFiJ1Svpe91LELsbOu7xBkZ8uEWPxWbRaPDgClclR2UlGlhaVeR0m9dRBCFCYw945j9TwWXYiOKQRJPfZAleeBeiUlBamDFaa3VvQ/ILmZhbNSHvB8PdatAwPgEAynQnFNlfecOq8t7azrfGcc6uhJTZ4wTTj+AOrDENO8zH2ubl6r3qH7uE7lwak2330dJvrPtqPHOX7BVJUdh2Eq93Vb66UmRwzLmvC4vVftG9mX46oO27MleaO0q8lLDimvp1tUiUZLpi6Xy+VfAAAA//8DAHpkYp/zBAAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRTS2/cNhD+KwLPosw3Rd2MdYou3MSLZJEWvfExignL1IKinATG/veA2g2c9NYLQQz4zXyP4StK9hnQgG5Pp3cvkMqCWlTiVmKEKUwUJvRIycDFIGVnJDGG039Ri+I9fEcD0sJ76g1gDgqwCERix0ePQwBDCQ2ESVF72i8LGl6RjV2Al+ihm5fPkJc4JzSgv2MK89c628bOT/MaujxPsE9LsclXMh/2u3v81+3h+HC4vFpgqeAuBjSgvleC9JRiLmnAQmqHjR4d9j3XShnHPWMXWEwFcrJTt4Snt/lhLgmKH1jHeEcwM+jcomCLrZSdXeD4/VRZbBbd1Xq7lbfr8IpeIKOBtT/NvLS78VO8eV7cGqdwczmLXZ6qylOeT5BLhM2TTeY02RLn1Fwn7aYIqaAWPXxqDpMt45yffzPq00X//n/IP9bp776BXwuE3bymggZEeY9a9N76x5ig2d+hAREKLPAe8MiowqIPFlvJDVaKqxGoN5pR1KLdnEpM67wuzT4V+JI3AWhAf9hpgQv12+wfYwFf1lxV/aPqLhzyHFZfmjf/KelIxwmpoLWc1tJ8hBAz+AJV3zGv137/gTDFNtBuzRlSaQ62PDZ/2uURDUgqzaQgwlvJKTA/GkZGQnrDWRAMvFYBNGPeCWFGPnLpnfVO96ODwJ2uCqHG3Wwbprx1wjqFvegdFk5T7HqisCCSUzdqzmQl8uZj8zBVnPU9ERA4NjAGLAy12AjOceDSaqZGrdn4iyXX9Cmp4wO8XP7KhUEIPQRFMRNUYmEMxb2RGjvdO+NUD9Ib1KJ7yAmmX4x6H32el3kszXV5mt+s+7im+t+bbZG+xoS/bRndzf4JclMztjHV9b7Gej6fzz8AAAD//wMAV+GhYTYEAAA=
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRUTW/bOBT8KwLPosIvUaJuWWeLNdI2buNtF3ujyCeHiEIaFJVuEPi/Lyg7iN1iD3sTqDdv3psZ8hV5/QSoQ9f7/e/P4NOESpTccsQIk5hITOiWko6Lrq4rWgvVCPU3KpG7hRfUoUYYQ40CzEECFpbUuOeDwdaCooRawmqRe+rdhLpXpF1l4dkZqML0DeLkgkcd+u68DT8yt3aVGcNsqxhGWPspaW/yMJ/Xq1v88XqzvdscqyaYMrhyFnWobaUgLaWY19RiUTc9Vs3QY9PyRkrVc8PYEeZ8guj1WE328Z3fhuQhmY5VjFcEM4UOJbI66TxyryfYvuzzFItEN/m8XI6Xz+4VPUNEHSvfxDy2uzKju3qa+tmN9moMu53zu1Xwg9vNUadMXKJ9DHuIycEizm/O6/jyMex2uR/6oMcJUIm2EJ+c1+Pxxw0Meh7TfZjjosxkH/+rBnVIzymgEi1KjuNCW5yWWY0OfPoFe0Z8d19sRp2GEJ8uTLo/ar/+H9J/0ubBeSjWN6hDhAKzvAU8MCqxaK3GuuYKS8nlANSohlFUolXwyfk5zFOx9gl2J9Uu5ruO5sElMGmOeae/ZA7bJgY7m1S8G0xJRSpOSAbNaT+n4itYF8EkyEts43zq9xOESbaAPrgRfpFnNccIPhUbnR6KP/T0gDpUy4bVggija06BmUExMhDSKs6sYGAaaaFhzPRCqIEPvDa9Nn3TDj1Y3jd5bcghK5ZcKwKDaIXFfc0sFoPUuK2BY9X3TAxWKt2YC3GLuzHjtGmJAMuxgsFioajGSnCOLa91w+TQNGw402l7DAQlmf48hH9OYE9Z+nyM9tvuFp6P93iZU1rbgpUUM0FrLJSiuFV1g/um7VUvW6iNOho6hTchv0Hsw+RSfkS+zA5yEi8K3n25hehhPPPmkzMxTGFIxSmUxYVbX2ef37BiCegP5/E/SyxugnmEWORYaefPrDwcDod/AQAA//8DAM8mzccKBQAA
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxU227cNhD9FYGvFRXeL3pzbQddpI6N7KIt+sbLyGYtUwuKchIY/vdCWjtXFOiLIAw5cw7PnJknlN0DoB6dHY+Xj5DrjFpU0xZihClMFCb0QEnPRS9lZ6WgjKu/UYvSO/iMeqRFCDRYwBwUYBGJxJ4PAccIlhIaCZNireluZ9Q/IZe6CI8pQDfNf0CZ05RRj/5MOU4fV2yXujBOS+zKNMIuz9XlsJJ5vzt/h38/uzlc35xuzTCvyV2KqEfGKEEMpZhLGrGQ2mOrB4+D4Vop63lg7JSWcoWS3djN8f4rfpxqhhp61jHeEcwsem5RdNWtlL2b4fD5uLLYJLpY4+0W3n77J/QIBfWsfRXzVO5NGNObh9kvaYxvti9q0bFMRyg1wabG9b75SoKSjnRMMUJQi65cuEsZmt1Fcz2uT3TBEAGRYwtDxMJSh63gHEcunWZq0JoNqEXvoGQYv6l6lUKZ5mmozYvIzXc4+7Pzy+z8CCvGWzfOgFq0m/fV5ejGKcPlJwhLPdU6lGU9Pp9yTXmZlrnZ5Qq3xb2cv+afL6VArs2Nq3fNb26+Qz2SSjMpiAhOcgosDJaRgRBjOYuCQdAqgmYseCHswAcug3fBazN4iNxrilr066rhfgkB5vkrm80k47hxaF76dD4myPU7GVGPCAUWuQE8MKqwMNFhJ7nFSnE1AA1Wsy8wB1duoaIeDcZ7T0LwTFgaHLOOx4HwqAbLmNZODFxqwZSSRLsQtWZURK4hOD5wYlbb3ZQpLqH+2Gq+NeCmTP9AqKtUqEeKSGmC854pQY2zBgRVwigL2orBEcGDd1Qa5z0lTpJgDQuOKuuEj3Kwr/Qv823KcJHm4+g+f4NrOtXxX4Jzhg5O/HD9bXEP8HEq9+9PNu7eXx5Qiz4sed0IzW61yMeU8Se1TvTVMtZ0uCvgIsSrKcLPPoJ1XJptQgX1joHUONigsVDUY++9w4MdgjCGaEk1atHFFO6hNKvDXMrrVH0pdr1vzkq4SxVCXcrK76+Nx/W+uRldHaby8N0m+eZhPwrQMU7J2pkIj6dttHFUMRqIimImqMTCWoqNlRp7bbz1yoAMq2LXSz0utfkAMRUIdXvxixc3zPM7CPc/i/HqgheLUrJ6bX/aYpu0/2uJPbfoAdy8FHjYtnX/hHY5Q9mQL5bTKO7yVRrHNEOYcpxRbyjpKJHiheB/XuOsE5qy5+fn538BAAD//wMAY5toPBkGAAA=
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRUTW/cNhD9KwLPosxviboZ6wRduKkXySIteuPHKCYsUwuScmIY+98LardIfCp6IYgh38ybN498Q9E8AxrR7en04QViyahFJWwhRpjCRGFCj5SMXIxSdloMjA7kb9SicA+vaES9cI46DZiDAiw8kdjyyWHvQVNCPWFS1JzmW0bjGzKh8/ASHHRL/gophyWiEf0Zol++19omdG5eVt+lZYZ9zMVEV8n8sd/d499vD8eHw+VWhlzBXfBoRMOgBBkoxVxSj4XsLdb9ZLEbeK+UttwxdoGFWCBFM3fZP/2s75cSobiRdYx3BDONzi3ypphK2ZoMx9dTZbFJdFfj7RbetuMbeoGERtb+K+Yl3Y2bw81ztmuY/c1lLSY/5W2djCtLekUtOqXlBKkE2PS5zRme7fx6NPnp4+VO3eYPP8CtBfxuWWNBI6JcohZtAs2zKWGJzZXjbg4Qy3ZYUog5uP/KxVGLHr40h9mUaUnP7+bx5SLz/n+o/Mm4xxCh2d+hEREKzPMB8MSowmLwBhvJNVaKqwmo0z2jqEW7JZYQ12XNzT4W+Ja2ltCIPpo5w4XfbXKPoYAra6p9/qWqrw5p8asrzc9ZUtKRjhNSQWs5raX5DD4kcAVqE8e0XvN9fQ9him2g3ZoSxNIcTHlsfjP5EY1Iqp5JQYQzklNgbtKMTIQMmjMvGLheeegZc1YIPfGJS2eNs/0wWfDc9rVDqNZpNrdao+XAnMYwTYAFEIEHazS2Wg5eSQqyd+90bB7mijNuIAI8xxomj4WmBmvBOfZcmp6pqe/Z9IskVz9QUst7eLm8u42B8n4AryhmgkostKZ40LLHth+stmoA6TRq0T2kCPMvQn0KLi15mUpzdUjzTrrPa6x/R7O55XuI+Mc2o7vFPUFq6oxNiPWpXMd6Pp/P/wAAAP//AwAaq/UgggQAAA==
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxUyW7jOBD9FYFnU+GijQLmYDjdGCOdTpC4ZwZz41KMiciiQVFOB0H+fUBZjp1GH+YmlGp59d4rvqFe7gC1aLnffzlAHwe0QNFNIUZYhUmFCd1Q0vKiLcucV7RpBP0XLZC7gVfUorrQmmoBmEMFuDCkxIpbjY0BQQk1hJVF6imfBtS+IelyAwenIffDXxAG53vUor9db/xLmi1drjs/mjz4Dtb9EGWvE5jv69UN/ra839zdH7MGGFJx7gxqUdNUBWkoxbykBhdlrbCorcK64XVVCcU1Y8cy10cIvezywTyf5xsfe4i6ZTnjOcFMoPcFMjLKBFnJATav+4Rioug6xRdTePps39ABAmrZ4kTmsd2V7tzVblCj68xVlOEJog1yBy8+PMNBdmiB9sHvIUQHEzd3j9kZEiU5yVnFCEELdCv11vWQra+zuy4tLHVDCjAcC7AGF4JKLArOseGlrFll65pZtEA3EHroLrreOh384G3MZsqzT3NWvo+uH/04ZOs+wlOQ8Vj3VXYDoAW6H1Xnhu0DSPO68Q9j+tePXdplNYYAfczuZdxmf8phi1pUVjUrC1JoWXIKTFvBiCWkEZyZgoGuKwM1Y1oVhbDc8lIrqVXdWAWGq5qiBbob436MJ/5/XoDYBLfbgTkj2Ewc33cyWh92awN9dNYlaU4Zk6G6btoqm3uuOgd9/EQyahGhwAxvAFtGK1w0RmJZcoGrilcWqBY1S+hWvrfuafzgiVhrCm7LpqmUUJQAs3VTkNoqYrTlWphSQc1qUjfQCE2IKgvaKKGJAVoWJm0XvBl1/NUKfBLoYezTdWbrtPaL6/HPqjgzch989Np3STDXwePrEGH3O9VWfrf3g4tpfztL+2OAW9+nv/P9z5zNxUsfzzFId5BNpweyVpYyiUlDLS5UbbCsuMK8IrVoqpoJlZx47fUzhCwZTLp+0uTkqbvHbBn01kXQcQxp8j/TUkc5v55O5sxH/v3LZuUDLPf7xRz945BIOjY7GeDTu/JjSOlbP6QtYhgvfPQInT3hunCTgcPxpXIpWBnTgKkoZgUtcSEExY0oa6zqRglVNVBq8eHW7AGMC6Dj1G9znDYT+ztbLkN0Vuo4pNv55vXkptmec8qvIC9U+6g+Dr9QbnbS3ImS5NjH47s5Geh/PZvv7+/v/wEAAP//AwDMb2aaJwYAAA==
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUy27cNhSGX0XgWlR4FUntDLtFB27qQWK0RTcDijz0sJYplaKcBsa8eyDNGI6bVXcScf5z+fgfvqBknwB16GqafnqGVGZUoxK3I0ZYi0mLCb2npOOik20jNOfc6L9QjeItfEUdUsI56gxgDi1g4YnEPQ8Oew+GEuoJk2LNaR9m1L0gGxsPz9FBM86/Q57jmFCH/ojJj1/W2jY2bhgX3+RxgF2ai01ubea33fUt/vVqf3+3P0fNMK/iJnrUIa1bQTSlmEvqsZCqx0aFHjvNVduanjvGzrKYCuRkh2b2j2/1/VgSFNexhvGGYGbQqUbeFru23NsZ7r9Oaxcbopv1vN6Ot8/uBT1DRh2rX2Ge031wQ/yQl4RqNOVxglwibAy2sYbBljim6pL5eoiQyjn0b3DlsM3FtFPG9waEUM6DBcm9I54JwkH7ngYqhONgtCNGUElcIJrZEJjUNugeUI3uPlf7wZYw5qd3oD+f+e3+B76P1h1jgmp3gzpEKDDPNeDAaIuF9hZbyQ1uW94GoM4oRlGNrsdUYlrGZa52qcBD3qZGHfrZDvOlv6vsjrGAK0teUfzZroYZ7JLc8TDlMcQBDnE+eAh2GQrqULho93n0iyvV20VS0pCGE7ImXsq0lOoT+JjBFVgHvc/LpeZ/JKxlm+h6yRlSqfa2HKtf7HxEHZKtYlIQ4azkFJgLhpFAiDacecHAqdaDYsz1QpjAA5eut65XOvTgea9WCrD6ptquVFrbu+AVFhIIFlz22EoqMKNWGcW4IRzesa7uhlVnnSYCPMcGgsfCUIuN4Bx7Lq1ibVCKhdXi03QoZ0u9Omk1qv+O1sVxlNAfMWf4Z4H5DOvC+7Cc5R6ez5u7jdF6r8G3FDNBJRbGUKyNVLhXujd9q0E6g2p0CznB8B3tj9HlcR5DqS5WrN7x/7Sk9fWpNlt+iQn/u5nhZnSPkKvVTDamddku/jnV6AnsvGR42h6v7gVN1j3ah3WUABmSg4Mbl1S2/Zz94+sffVu1HyLJ6XQ6fQMAAP//AwB7Idn4GwUAAA==
|
||||
@ -1,5 +0,0 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRTXW/UMBD8K5Gf49RfseO8VVcQpwI90QoQb4694SxS++Q4pVV1/x05d6gtb7xZK8/s7MzuMwrmHlCPLg+Hdw8Q8oxqlP1aYoRJTCQm9I6Snrc9UY0gTDIqf6Aa+Wt4Qj1SwlpqNWAOErBwpMUDHy12DjQl1BHWisJpfs6of0bGNw4evIUmzl8hzT4G1KNvPrj4u/Q2vrFTXFyT4gTbMGcTbBHzebu5xh8vd3c3u9OvGeYCbrxDPeo6KUhHKeYtdVi0asBajQO2HVdS6oFbxk4wHzKkYKZmdr9e+ruYA2Tbs4bxhmCm0bFGzmRTJA9mhrunQ1GxWnRV6vVaXp/9M3qAhHpW/zXzRHdhJ39h4/29Ce5i9MHPe1SjQ4oHSNnDasc64TSZ7GOozk02k4eQUY1ubqvdZPIY0/0bj25Po2//Y/JPxu59gGp7hXpEKDDHO8AjoxKLzhlsWq6xlFyOQK1WjKIabWLIPixxmattyPAzrSpRj96baYaTvstk9z6DzUsq0r/LkjU8+ryJrhRwIdql6Babqxe/KWlIwwkpJEs+LLn6As4nsBnKUHdpOfP/A2GSraDNkhKEXO1M3lcfzLxHPWqlYq0gwpqWU2B21IyMhHSaMycYWCUdKMbsIIQe+chbOxg7qG4cwPFBFaFQ4q3WjWKckZZriTvFHRZcO2xIS/HIneNaM6Fp98bX6mYqOGM7IsBxrGF0WGhqsBacY8dbo5gclWLjK0vOkVNS2jt4ON3GqkA614GTFDNBWyy0prjTrcKD6gY9yA5aq1GNriEFmF4Z9cnbFOc45uq8MdUb674sodx3tW7Pbx/w45rZVbS/IFUlc+NDWedzzMfj8fgHAAD//wMAG25qdSYEAAA=
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUTW/cNhCG/4rAsyjzS6Som2G3qOumXsSLtOiN5IxsIVpqQVGbBsb+94DaDRL31psw0Dsfz7zDNxLdAUlPbo/HX04Y80JqksctJJjQlGnK+J7zXvCes4ZJLUUr/yE1GR/xK+mJUSHwYJFK1EgVsJZ6OQQKgJYzDky0quR0Lwvp34gbG8DTGLCZl0+YlnGOpCd/jRHmL6W2G5swzSs0aZ7wIS7ZxVCa+fPh7pH+cbvbP+0ufy24FHEzAukJ81xxi4x6azVVEgztDHd0QPBdGLTWwVxkY8yYopuaBT7/qA9zjphDLxohG0aFJeeagMuutOzdgvuvx9LFhui+xOstvH32b+SEifSi/g7zku4mTONNno8TnnA6urRgugnz4eAikJoc03zElEfcsGyTTpPL4xyra7G7acSYSU2enqvd5PIwp8M7Vs8XBA//g8AJkyc9kayV2hhUUkpntRcMweigtfDBMTN4gTwga60ylhvGpRXMylabzoBjNpCavEyzd9Pvy8bPCuY7YEZogQqtUFrbwFB2OLQGGTitve6CBdkZoTropLPOcevRBKtDMcgHF17HiNXDfZmGowDZIR0E11R14KhrpaVaSz0gD9YITmpyN8c8xnVel+ohZnxJGz/Sk1/dtOCF3G0Kr2PGkNdUoP6tS7FdmmENufrhgOLtRjJWRGs+rrn6iDAmDBkL3n1ar/n+IxFabKK7NSWMudq5/Fr95pbXQsV1gTtbRtUhDNgyHBgwp5kB1KARlAADyirQyrKglfNcgWu5H0qE1ASL4arN485yJQZsKUJrqOqCoz4AUPSSMZTetvCeY/U0bbrQMYUgqcUBqLLcUaukpCBbZ4QejBHDT0iu5uOsAAY8Xa5160ADdAiaU6F4S5W1nHa2NdSbzluvO2xD6fkRU8TpJ1AfxpDmZR5ydfVu9Q7dxzWWF6fafPxljPTfbUf3c/iMqSo7dmMsB3Zd67kmB3TLmvCwPVj9G9mV66r227slTMNlJ2vynF3K6/EalraxUprz+Xz+BgAA//8DABTuqPX1BAAA
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxUS2/bOBD+KwLPpkJKFCUK2IPhtFgjTWMk7u5ibxQ5jInIpEFRToMi/31BWa6dooe9CaN5fY/hD+TkHlCLlofDpyO4OKAFinYKFaTgmHBM6JbStqAtJTlrOKVV+S9aIHsHb6hFNVOKKgG4BA6YaVLhrjQKaw2CEqpJUbHUUz4PqP2BpM01HK2C3A9/QRisd6hFf1un/WuaLW2uej/qPPge1m6I0qm0zNf16g5/WW62D5tT1gBDKs6tRi0iHWVUAMGdEByzUte4qanEBnTXKMM5V/WpzLoIwck+H/TLZb720UFUbZEXZU5wIdD7AmkZZVq5kwNs3w5pi4mi2xRfTOHps/2BjhBQWyzOZJ7a3aje3uyHbrS9vokyPEM0Qe7h1YcXOMoeLdAh+AOEaGHi5uEpu6xESU7ygheEoAW6l2pnHWTr2+yhT4ClaggDXWIBRmMmqMSClSXWZSXrgpu6LgxaoDsIDvqrrvdWBT94E7OZ8uzDnJV30brRj0O2dhGeg4ynus+yHwAt0GbsejvsHkHqt61/HNM/N/YJy2oMAVzMNjLusj/lsEMtErJRVAoppORKGagIGKKJ5KTWwDUHzQpdayaY5kwQxZnsKNOyop1JEbRAD2M8jPHM//erJbbB7vegLxtsJ443vYzGh/1ag4vW2CTNOWMyVN9PqLK556q34OIHkpOjKBS6bACbgnLMGi2xrEqBOS+5AapEXdATYcY+jz95IsZoVpqqaXgnOkqgMHXDSG06opUpldBVB3VRk7qBRihCuorRphOKaKAV0wld8HpU8VcrlJNAj6NL15mtE+xX6/B3zi6MbIKPXvk+CWZ7eHobIux/p9rK7w9+sDHhN7O03wa49y79ne9/5mwuXvp4iUG6g2w6PUEqTXklMFXQYcaMxp2uOyxEaaQBU/A6obr16gVClgwmrZs0OXvq4SlbBrWzEVQcQ5r8zwTqJOfn88lc+Mi/ftqufIDl4bCYo38cE0mnZmcDfHhXvg0pfeeHeAV5hvYEvTkvdmUnDcfTU2VTkGvdgOYUF4xWmAlBcSOqGnd104mON1Cpi12zR9A2gIpTv20Y07SZ2d/5chmiNVLFIR3PF68mO83+nFN+XfJKtp/Vp+FX0s1WmjtRkiz7dHo4Jwf9r3fz/f39/T8AAAD//wMAnt4S3SgGAAA=
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUTW/cNhCG/4rAsyjzS6Som2G36MJNvYgXbdDbiDOKhWilBUVtGhj73wtqt0jcW27CQDPzzjMv541NcCTWsvvT6ZczTWlhJUvDFlJCWS4sF/IgZatkK0UlnLFCqr9ZyYYn+sZa5kwIMnjimixxg6Lmne4DRyQvhUShapNrwueFtW8MhgrpPASq5uVPisswT6xlfw0Tzl9zbxiqMM4rVnEeaTctCaaQxfyxe3jiv9/vD8/7618LLTm5GpC1THTSSE+Cd95bbjQ63jgJvCfsmtBba4O7pg1TojjBWC345Xt/nNNEKbSqUroSXHl2KRlCgiy5g4UO305ZxYboMcfLLbx9tm/sTJG1qvwP5rXcXRiHu2XtRjrTeIK4ULwL8/EIE7KSneJ8opgG2rCcKXbzMqRMNAQHTSMlNuBM7bDRtdIOtSBshKvRowdrbK9CXffYNd6Z3qCSBi0Z0+VBN3DjCGmYp+Km/WEcaEqsZM8vxX6E1M/x+A79y5Xo7ieAZtmsZVrU2jpHRmsN3nZKEDobrFVdAOH6TpEMJGpvnJdOSO2V8Lq2rnEIwgdWsg8QXoeJit1j7i5JoW6I90pabhoEDrX23Fpte5LBOyVZyR7mKQ3TOq9LsZsSfY7bvKxlv8K40HXS+xheh0QhrTFD+GSzGfdxxjWk4rsBsrUrLUROWtNpTcVHwiFSSJRxHOJ6q/e/FGXVlvSwxkhTKvaQXovfYHllLfPQBAkePIANoadaUC9QgBUOyaIlNAodGm/QGi+CNdBJg1DLrs8RVjLKfis2i4faUm2U5x30PTekDIcAxI1H4YPoXK3oHcfiecx5EBphCDX31CM3XgL3RmuOuganbO+c6n9AcjOLFBkw0vn6WDcFFrEhtJIrI2tuvJe88bXjnWs639mG6pA1P1GcaPwB1IchxHmZ+1TcvFa8Q/dxnfLBKTbffR0m/s+2o8c5fKFY5B3DMOX3dVvrpWRHgmWNdNzuVfvG9vlxFYftbClXSd3okr0kiGk93cLaV15rd7lcLv8CAAD//wMAfUhktfQEAAA=
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRTwW7bOBD9FYFnUSEpihJ1C5xd1Ei7MdqgXextxBnVRBXKoKi0ReB/X1B20aa33ohHvpk37w1fWIAnYj27PZ3+eqaQFlay5DdICWW4MFzIRyl7JXvZVJ2sO6Hq/1jJ/D19Zz1rtXPSWeI1GeIaRcOHenQckawUEoVqdK4JnxfWvzDwFdKzd1TNy0eKi58D69knH3D+mnuDr9w0r1jFeaJ9WBIEl8X8s9/d87e3h8eHw+XVQksmVx5Zz8QgtbQk+GCt4brGlnetBD4SDp0bjTGuvdB8SBQDTNWCX372xzkFSq5XlaorwZVl55IhJMiSB1jo8fspq9gsust4ucHbsX9hzxRZr8ofZl7K3bjJ37j56QkC3ow++OXISnaK84li8rTZsU04TZD8HIprk93kKSRWsocPxWGCNM7x6ZVHHy6j7/9g8nfgjj5Qsb/LHEkK6474qKThukPg0NSWG1ObkaSzrZKsZLs5JB/WeV2KfUj0OW4qWc/+hmmhi77b6I4+kUtrzNL/NTlr+ubTbsYMCFayQ5xxdan4abcUlahqkS8f1nRaU/Ge0EdyifJMj3G9lv+NoozaSLs1RgqpOEA6Fm9gObKeWeicBAsWwDg3UiNoFCjAiBbJoCHUClvUVqPRVjijYZAaoZHDmJGsO6dbXBYKGzsMI/EOFHFtleEWB8tNLRAGQLSDe2Vr8TBlHrhOaMKaWxqRayuBW13XHOsGWmXGtlXjL5ZcE5ci+430fPkamwKD2BEayZWWDdfWSt7ZpuVD2w12MB01Lmu+pxho+sWod97FeZnHVFwXpnhl3fs15O9dbMvz1Qf+bYvsbnZfKBY5cvAhb/M15fP5fP4fAAD//wMAHpFmlyUEAAA=
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRTTW/cNhD9KwLPokxSFCXqZqxTdOEmXiSLtOhtxBnFhGVqQVFOAmP/e0DtBk5664UgBnwz72P4ygI8E+vZ7en07oVCWljJkt9KSijDheFCHqXslexlU3VSKqmbf1nJ/D19Zz1rtXPSWeI1GeIaRcOHenQckawUEoVqdO4JXxbWvzLwFdKLd1TNy2eKi58D69nfPuD8Nc8GX7lpXrGK80T7sCQILpP5sN/d879uD8eHw+XVQksGVx5Zz8QgtbQk+GCt4brGlnetBD4SDp0bjTGuvcB8SBQDTNWCT2/zcU6BkutVpepKcGXZuWQICTLlARY6fj9lFptFd7lebuXt2r+yF4qsV+VPMy/tbtzkb56XYfUT3lzOBMtTVnmK84li8rR5ssmcJkh+DsV10m7yFBIr2cOn4jBBGuf4/JtRny769/9D/jFPf/eN3JoId/MaEuuZrC0r2Xtwjz5Qsb/L7SQprDvio5KG6w6BQ1NbbkxtRpLOtkqyku3mkHxY53Up9iHRl7gJYD37A6aFLtRvo3v0iVxaY1b1j8m7cIgzri4Vb/5LUYmqFiKD1nRaU/GR0EdyibK+Y1yv/f4DUUZtoN0aI4VUHCA9Fn/C8sh6ZqFzEixYAOPcSI2gUaAAI1okg4ZQK2xRW41GW+GMhkFqhEYOY66wklGOu9g2TCoYYFSSkxoF1w0MfOiM5LUgRa4ZZNdmIm8+Fg9TxoHrhCasuaURubYSuNV1zbFuoFVmbFs1/mLJNX0pssFIL5e/sjEwiB2hkVxp2XBtreSdbVo+tN1gB9NR4zLne4qBpl+Meu9dnJd5TMV1eYrfrPu4hvzfi22RvvrAv20Z3c3uiWKRMwYf8npfYz2fz+cfAAAA//8DAHg1vGQ2BAAA
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxUy27kNhD8FYHXiDJfokTdHNuLDBw/sDNIgtyaZMtmLFMDirJ3YfjfA2ns9WMRIBdBaJJd1dXV/UQi3CPpyPF+f/aAMU+kJDmsIcGEpkxTxnecd4J3vK5aLo3R8m9SknCO30lHGuUcdwapRI1UeVZTK3tHvUfDGfdM1GrJCTcT6Z4IhMrjQ3BYjdMfmKYwRtKRP0P04+OCDaFywzj7Ko0DbuKUIbqFzOXm5Jz+fny9u7o+3JpwWh5XwZOOMMsVN8ioNUZTJX1D24YD7dHb1vVaa9ccnoWYMUUYqsnfveH7MUfMrhOVkBWjwpDnknjIsFC2MOHu+35hsUp0usTLNbz+dk/kARPpRPkq5iHdkRvC0f1k5zD4o/VLSrJP4x5TDriqcbUt3khwVrFKaMEYKckFuNsQsdicFlfDUiK4lin0khrsPVWGAzVKSuplDY3QfdOInpTkHFPE4V3Wi+DSOI19Ll5ELj7gbI9PziLYAReMLzBMSEqymbYZoodhjHj2Dd2cD7l2aV6OT8aYQ5zHeSo2MeNNgpfz1/cnc0oYc3EN+bb4DaZb0hEDreNgwABo53qsGfbMM9Cs8ai9Rq+Eb7wyymtlmNMKLFceam77JUJK8uui4XZ2Dqfpjc1qkmFYORQvfToZAsb8QcbFJRyFly3SXnBNVeuBQi0N1VrqHrkzjeCvMDtIN5hJR/rWWsucs0IZ7kAYkL5n0uveCNE0oHpZN0poXbMGnG8awZWXDTqQvWStICW5TqOfXf7cark24DqN/6DLi1SkI5rVdevAWqEVb8G0qLhWrTbYGNUDU9JZ4HUL1nIGNXOmFQ64NqCsr/sfKp3FmxDxNEz7Ab6/w20rXclfHEDLe1Cfrn9JcI+PY7q7PNi4ujzbkZJ8neOyEYrNYpHHEOk3vUz0xTzksLtNCB79xejxZx/hMi7FOqHcIlimLLVaaKq4kdSwHqljgjGrFce2JSU5Hd0dpmJxGIS4TNWPZFfb4ji525DR5Tkt/P5aeVxti+sBcj+m+w+b5F1hnwWohORs6YzHh8M2Wjlq71v0mlOheE2VMZy2pm6obVprrG6xdotiV3Pez7n4ij4kdHmt+MWLK+bJLbq7n8V4dcGLRTlbvLY9bLFV2v+1xJ5Lco8wzQnv123dPZFNjJhW5NP5MIqbeBGGIUzoxugn0tUNbyuhpXph+N/3GlHx2vDn5+fnfwEAAP//AwCXJBKUGwYAAA==
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRU0W7cKBT9FYtn4wDG2PgtmrTaUbabUTvqrvYNc68bFAdGgNNG0fz7Cs+s2jyt9gWha87l3HMOfiPePCMZye3p9OEFfU6kJtltJcGEokxRxo+cj4KPvGsGNgyKib9JTdw9vpKR9NJabjXSFhVSCayjUztbCoCaMw5MdLL0NN8SGd+IcQ3gi7PYhPQVY3LBk5H86TyE7+Vu4xq7hBWaGBbc+5SNt4XMH/vdPf399nB8OFxOJUwF3DggI2ETl1wjo5PWisoWejr03NAZYRrsrJSy/QXmfMbozdIkePp5P4TsMdtRNKJtGBWanGsCJptCeTIJj6+nwmKT6K7U6628bcc38oKRjKL+V8xLuxu7uJvnNK1ugZvLmk16Sts6G5tDfCU1OcVwwpgdbvrcpoTP0/J6NOnp4+VM2aYPP9CuGWEXVp/JSHirSE02gZbFZBd8deW4Wxz6vH3M0fnk7H/1aklNHr5Uh8XkOcTnd358uci8/x8qfzL20Xms9ncFw1FAOyCdBVdUDmCo6VpNlWrVjNzqXnBSk13w2fk1rKna+4zf4jYSGclHsyS88LuN9tFltHmNZc6/VMnVIQZYba5+eslZw5qWsQJa82nN1WcEF9FmLEMc43rt9/U9RCixgXZrjOhzdTD5sfrNpEcyEm0Gy4022hhl7Ywdw5kBM4r1gAoUghTQg9QSlNTMKmkmLsF0fJpLhdQES3SqLa0aejPA0NOug45K0fd0kJ2iknM7Gd2ynsM7HauHpeCMHZhEaKnGGajU3FAt25ZC25leqLnvxfyLJNc8cFYEBny5vLuNgQIYEBSnQvKOSq05HXTX06kfJj2pATtbON9j9Lj8ItQnZ2NIYc7VNSHVO+k+r778O6otLd+dpz82j+6CfcJYFY+N8+WpXG09n8/nfwAAAP//AwDwEAjXggQAAA==
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSU227cNhCGX0Xg9VLm+aA7w25R102ziI226B3JGdlCtNKCojYNjH33gNotEveud8JA/xy++YdvZAoHJB25PR5/OuFUFrIjZdhCgglDmaGMP3PeCd4J23KhBWPyb7IjwyN+JR2xKiWePFKJBqkCpmmUfaIA6DnjwIRWNWd4WUj3RsLQAp6GhO28/IF5GeaJdOTPYYL5S60dhjaN8wptnkd8mJYSplSb+f3h7pH+drt//ri//LXgUsXtAKQj2qXeRB2ot0JThQ6ogxio1lwxLrVXhl9kw1QwT2FsF/j8vT7MZcKSOtEK2TIqPDnvCIQSassxLPj89Vi72BDd1/huC2+f3Rs5YSad2P0L85LuJo3DTZmPI55wPIa8YL5J8+EQJiA7cszzEXMZcMOyTTqOoQzz1FyL3Y0DToXsyMenZj+G0s/58I7V0wXBw/8gcMIca4OAARBcAIdKeSl76dFYEZxzBpSPgTMrHVgXATn3UfRok0xC95AU1IW+jHMM46/Lxs8LFh0wK4xAhV4oY3xiKB322iKDYEw0LnmQzgrlwMngQ+A+ok3epJrvQ0ivw4TNwz3pCOMoQDqkveCGKgeBBi09NUaaHnnyVtRp7uapDNM6r0vzMBV8yRs/0pGfw7jghdxtTq9DwVTWXKH+ZWqxfZ5hTaX57gDOWtZKxqpoLce1NJ8QhoypYMX7nNdrvv9IhBGb6G7NGafS7EN5bX4Jy2vdibFCK6ZS0JKjSL0XrGfMeSlACUzWAFohUlTK97KXOsWQonV9RJDR1gmxGq7ZPC41GsVUT9EKRhVoTb0TjDIAlXw0BhK849h8HKsuJMcUgqQee6DK80C9kpKC1MEK01sr+h+QXM3HWS0PeLpc69aBAXAIhlOhuKbKe06d15ZG66KPxqFOnuzII+YJxx9AfRhSnpe5L83Vu807dJ/Wqb44zebjL8NE/9l2dD+nz5ibuuMwTPXArms978gBw7JmPGwPVvdG9vW6muft3RK29ZKJHXkqIZf1eA1r31rh9fl8Pn8DAAD//wMAJXTPRPUEAAA=
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSU227cNhCGX0Xg9VLm+aA7w25Rw029iI026B3FGcZCtNKCojYNjH33gtotEvcud8JA/xy++YdvZAoHJB25PR5/OeFUFrIjZdhCgglDmaGMv3DeCd4J23IjnXH+b7IjwyN+Ix2xKkYePVKJBqkCpmkvU6QA6DnjwIRWNWf4vJDujYShBTwNEdt5+RPzMswT6chfwwTz11o7DG0c5xXaPI/4MC0lTLE288fD3SP9/Xb/8rS//LXgUsXtAKQj2sVkeh2ot0JThQ6ogz5QrbliXGqvDL/IhqlgnsLYLvDle32Yy4QldqIVsmVUeHLeEQgl1Jb7sODLt2PtYkN0X+O7Lbx9dm/khJl0YvcfzEu6mzgON8vaj3jC8RjygvkmzodDmIDsyDHPR8xlwA3LCXM/L0OpRGO0wTnOwQWrtAUntZAWJENwzGrw4INRJomodYLeeauSAsEVGFSqt2RHNnDjGMowT82197txwKmQHXl6bvZjKGnOh3fony9EH34CaG27zgsYAMEFcKiUlzJJj8aK4JwzoHwfOLPSgXU9IOe+FwltlFHoBFFB9ceHEF+HCZuHe9IRxlGAdEiT4IYqB4EGLT01RpqEPHoravW7eSrDtM7r0jxMBT/nbV7SkV/DuOBl0tscX4eCsay5QvhkarF9nmGNpfluAM5a1krGqmgtx7U0HxGGjLFgxfGS12u+/0mEEZvobs0Zp9LsQ3ltfgvLa2VorNCKqRi05Chi8oIlxpyXApTAaA2gFSL2Svkkk9SxD7G3LvUIsrd1Qqx+azaLW6GSs8lRC32iikdOe+0DxeCs9MaEqOw7js3TWHUhOqYQJPWYgCrPA/VKSgpSBytMslakH5BczcJZLQ94uhzr1oEBcAiGU6G4psp7Tp3XlvbW9b43DnX0ZEceMU84/gDqwxDzvMypNFevNe/QfVyn+uA0m+++DhP9Z9vR/Ry/YG7qjsMw1fu6rvW8IwcMy5rxsL1X3RvZ1+NqXrZnS9jWSyZ25LmEXNbjNax9a4XX5/P5/C8AAAD//wMAcuMez/QEAAA=
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUXW/bNhiF/4rAa1PhlyhRd5mzYkbaJm28dtgdRb50iCikQVHpgiD/faDsIHaLXexOoHjej+cc6QUF/QioR5f7/e9PEPKEVij75YgRJjGRmNAtpT2jPWtr2QrVSvU3WiF/Dc+oR60whhoFmIMELCxp8MCdwdaCooRawhpRaurdhPoXpH1t4ckbqOP0DdLkY0A9+u6DjT9Kb+1rM8bZ1imOsAlT1sGUYT5v1tf44+Xt9ub2cGuCqYhrb1GPms44OTQaq5Y1WEBncWcHjZuGCkJ5o4SkB5kPGVLQYz3Zh/f+NuYA2fSsZrwmmCn0ukJWZ11GHvQE2+d9mWJBdFXOV8vx8ti/oCdIqGerN5iHchdm9BeP0zD70V6McbfzYbeOwfndnHQujVdon+IeUvawwPnNB52eP8bdrtRDH/Q4AVqhLaRHH/R4eHEFTs9jvotzWshM9uG/7qAe6TlHtEILyXFc2lbHZdajh5B/0Z40vrmrbkedXUyPZybdHdhv/gf6T9rc+wDV5gr1iFBglneAHaMSi85qrBuusJRcOqBGtaxo1jFkH+Y4T9UmZNgdqZ3Nd5nMvc9g8pzKTn/JErbbFO1scvVuMCU1qTkhRTTn/Zyrr2B9ApOhLLFN87HeTxIm2SL64Ef4Bc96TglCrm51vq/+0NN9wSFb1ggijG44BWacYsQR0inOrGBgWmmhZcwMQijHHW/MoM3Qdm4Ay4e2rA0lZNWSa+DSAucEUyscFppYPAAD3DlrXNMRRR07g1vdjEWnTUcEWI4VOIuFohorwTm2vNEtk65tmTvhtD0EgpLS/jSEf05gj1n6fIj22+4Wng7f8TKntLYDKylmgjZYKEVxp5oWD203qEF20Bh1MHSKbyC/QRri5HP5iXyZPZQknl149+UaUoDxxJtP3qQ4RZerYyirM7e+zqH8w6oloD98wP8ssbiK5gFSVWKlfTix8vX19fVfAAAA//8DAItNHA8KBQAA
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxUTW/bOBD9KwLPpkJSlEQa2IPhtFgjTWMk7u5ibxQ5jInIokFRToPA/31BWY6dooe9CaP5ePPeG76jTu0AzdFiv/9ygC72aIaiG0OMsAqTChO6oXTO6JzVuZBlUVXiXzRD7g7e0BzVXGuqJeACKsDckBI3hdXYGJCUUENYyVNP9dyj+TtSLjdwcBpy3/8FoXe+Q3P0t+uMf02zlct16weTB9/Cquuj6nQC8321vMPfFuvNw/qU1UOfinNn0ByVQtuqKRWWNSsxB2GwMI3CZUk5oUUpeUVPZa6LEDrV5r15ucw3PnYQ9ZzlrMgJZhIdZ8ioqBLkRvWwedsnFCNFtyk+G8Pj5/wdHSCgOZudyTy1u9Gtu9n1zeBacxNVeIZog9rBqw8vcFAtmqF98HsI0cHIzcNTdoFESU5yVjFC0AzdK711HWSr2+yhTQsrLQgHU2AJ1mAuqcKSFwU2RalqVtm6ZhbN0B2EDtqrrvdOB997G7OJ8uzTnKXvousGP/TZqovwHFQ81X1VbQ9ohtZD07p++wjKvG3845D+dUObdlkOIUAXs7WK2+xP1W+TLlXNSk64VmVBgWkrGbGECFkwwxnoujJQM6YbzqUtbFHqRummFrYBUzR10uxhiPshnvn/eQViE9xuB+aCYDNyvG5VtD7sVga66KxL0pwzRkO17bhVNvVctg66+IlkNEeEAjOFAGwZrTAXRmFVFhJXVVFZoFrWLKFb+s665+GDJ2Kt4YUthaga2VACzNaCk9o2xGhbaGnKBmpWk1qAkJqQpuRUNFITA7TkJm0XvBl0/NUKxSjQ49Cl68xWae1X1+GfFb8wsg4+eu3bJJhr4emtj7D7nWpLv9v73sW0v52k/dHDve/S3+n+J86m4oWPlxikO8jG0wNVc8NAYqaAYy4KwELSGlsJohCNJpKmrW69foGQJYMp142anD318JQtgt66CDoOIU3+Z1zqJOfX88lc+Mi/f9ksfYDFfj+bon8cEkmnZmcDfHpXfvQpfev7tEUMw5WPnqC1Z1xXbjJwOL1ULgUrYwSYimLGaYm5lBQLWda4qUUjm0pAqeWHW7NHMC6AjmO/zWnaROzvbLkI0VmlY59u55vXo5sme04pv4K8Uu2j+jT8SrnJSVMnSpJjn07v5mig//VsHo/H438AAAD//wMAmj/F9ScGAAA=
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACoxU227cNhT8FYGvXcq8i9SbazvownVsZBdt0TdeDm3WMrWQKCeB4X8vqLUTO0GBvggCL2eGM3POE8r2AVCPTg+Hi0fIZUYbVNK6xAhTmChM6J7SntGe6VZqaYTq/kYblC7hK+pRJ7yn3gDmoACLQCR2PHocAhhKaCBMilrT3s6of0I2tQEek4d2nP+AaU5jRj36M+Uwfq7YNrV+GJfQTuMA2zwXm30l83F7dol/P73ZX98cT80w18ttCqhHUvuonLTYdExiATpgHZzFUlJBKK+c6fFaygWmbId2Dvff8cNYMhTfs5bxlmBm0PMGBVtspezsDPuvh8pilei8rm/W5fW3f0KPMKGebV7FPJY78UM6eZjdkoZwsn7RBh2m8QBTSbCqcb1rvpOgpCUtU4wQtEFX1t+lDM32vLke6hOt10RA4NhADFgYarERnOPApe2Yil3HItqgS5gyDG+qXiU/jfMYS/MicvMOZ3d6dpGtG6BifLDDDGiDtvOu2BzsMGa4+AJ+Kcda+2mp22djLikv4zI321zgdrIv+6/3z5ZpglyaG1vumt/sfFctUh2TgghvJafAfDSMREK04SwIBr5TATrGvBPCRB659M561+noIHDXVft+rRruFu9hnr+zWUMyDCuH5sWnsyFBLu9kRD0iFFjgGnBkVGGhg8VWcoOV4ioC9aZj32D2drqFgnoUtXOOeO+YMNRbZiwPkfCgomGs66yIXHaCKSVJZ33oOkZF4B14yyMnmqENupnGsPjyo9V8NeBmGv8BX6pUqEeKSKm9dY4pQbU1GgRVQisDnRHREsG9s1Rq6xwlVhJvNPOWKmOFCzKaV/oX+TZlOE/zYbBf3+DqVrX8F2+tptGKH45/mOwDfB6n+4/HGLcfL/Zogz4tuU6EZlsj8jll/EXVjr5ahpL2dxPYAOFqDPBzjqC2S7N2qI9dpz2NuNqLhRAKGwMex+i0JoZpQyub89Hfw9TUhNmUa1d9K3a9a04nf5cK+LJMld9fK4/rXXMz2BLH6eHdJHnzsB8FaBmnpDoT4PE4jVaOKgQNQVHMBJVYGEOxNrLDrtPOOKVB+srxeimHpTSfIKQJfFlf/JLFFfPsDvz9z2K8puAlopTUrO2OU2yV9n8NsecNegA7LxM8rNO6f0LbnGFakc+XYytu81UahjSDH3OYUW8YbZUW9IXgfx4TspUdYc/Pz8//AgAA//8DAPtdxY4ZBgAA
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRTy27bMBD8FYFnU+Fbom6B06JG2sZIjLbojSKXNRGFMigqDwT+94KyizS99UIQC87uzOzwFUXzAKhDl4fDh0eIeUIrlMNSYoQpTBQmdEdpx2jH2lq2nHBNf6IVCtfwgjrUCGup1YA5KMDCEYl77i12DjQl1BEmRelpfk2oe0Um1A4eg4V6nL5BmsIYUYe+h+jGpzLbhNoO4+zqNA6wiVM20RYyXzfra/z5cru72Z5eTTAVcB0c6pBsrVe9NFg3TGIBrcOt6w2WkgpCudRC0RMsxAwpmqGe3P3bfDfmCNl2rGa8JphpdFwhZ7IplHszwe7lUFgsFl2V+mopL9fuFT1CQh1b/THz1O7CDuHiYernMLiL05nNdF9UHtJ4gJQDLJ4sMofB5DDG6jxpPQSIGa3QzV21HUz2Y3p4Z9TdSf/mP+TvyvQPz2DnDG49zjGjDlFB0Ap9MXYfIlSbK9QhQoE53gL2jCosWmewkVxjpbjyQK1uWGm3HmMOcR7nqdrEDL/SIgB16KMZJjhRv0x2HzLYPKei6ocqWdim0c02V2/+U1KTmpPC5GbOhzlXt+BCApuh6Nul+dzvHwhTbAGt55Qg5mpr8r76ZKZ9MUU1TAoirJGcArNeM+IJaTVnTjCwjXLQMGZ7IbTnnkvbG9s3re/B8b4pCqGsu1oSpjWR0ivARDqCBeceG9oy3GhtGy+4U4y/87G6GQrO2JYIcBxr8A4LTQ3WgnPsuDQNU75pmP/LkvP2KSnjHTye/srCQDnXglMUM0ElFlpT3GrZ4L5pe92rFqTVaIWuIUUY/jLqS7BpnEafq3N4qnfW3c6x/PdqCdJTiPh52dHVaO8hVWXHJsQS7/Naj8fj8TcAAAD//wMA9x2TBjYEAAA=
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpRUTW/cNhD9KwLPosxvkboZ6wRduKkXySIteqPIUUxYphYk5cQw9r8X1G6R+FT0QhBDvpk3bx75hqJ9BjSg29PpwwvEklGLSthCjDCFicKEHikdGB2Y7qSmhDHyN2pRuIdXNKBeOEedAcxBARaeSDzyyWHvwVBCPWFS1Jz2W0bDG7Kh8/ASHHRL/gophyWiAf0Zol++19o2dG5eVt+lZYZ9zMVGV8n8sd/d499vD8eHw+VWhlzBXfBoQFK7SY3SYtMziQVoj7UfLZaSCkK5NELRCyzEAinaucv+6Wd9v5QIxQ2sY7wjmBl0bpG3xVbKo81wfD1VFptEdzXebuFtO7yhF0hoYO2/Yl7S3bg53DzncQ2zv7msxeanvK2TdWVJr6hFp7ScIJUAmz63OcPzOL8ebX76eLlTt/nDD3BrAb9b1ljQgCjvUYs2gebZlrDE5spxNweIZTssKcQc3H/l4qhFD1+aw2zLtKTnd/P4cpF5/z9U/mTdY4jQ7O/QgAgF5rkGPDGqsNDeYiu5wUpxNQF1pmcVs1tiCXFd1tzsY4FvaWsJDeijnTNc+N0m9xgKuLKm2udfqvrqkBa/utL8nCUlHek4IRW0ltNams/gQwJXoDZxTOs139f3EKbYBtqtKUEszcGWx+Y3mx9r56pnUhDhrOQUmJsMIxMh2nDmBQPXKw89Y24Uwkx84tKN1o29nkbwfOxrh1Ct02xu9caB11RizX2PhdISa6MI9saDFUqNxKl3OjYPc8VZp4kAz7GByWNhqMVGcI49l7Znaup7Nv0iydUPlNTyHl4u725joLzX4BXFTFCJhTEUayN7PPZ6NKPSIJ1BLbqHFGH+RahPwaUlL1Nprg5p3kn3eY3172g2t3wPEf/YZnS3uCdITZ2xDbE+letYz+fz+R8AAAD//wMAWwyKLoIEAAA=
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSUX2/kJhTFv4rF8+DlrwG/RUmrjtJtRrtRW/VlhOGSoXHwFONsV9F89xWeibLpPvXNRpzLPT/O5QUl+wSoR1fH40/PkMqMNqjEdYkR1mHSYULvKe0Z7ZlpiVJKM/MX2qB4C19Rj5RwjjoDmEMHWHgi8cCDw96DoYR6wqSoNe3DjPoXZGPr4Tk6aKf5d8hznBLq0R8x+elLPdvG1o3T4ts8jbBNc7HJ1WZ+217f4l+vdvd3u/OuGeYqbqNHPZLahW6QFhvFJBagPdZ+sFhKKgjl0oiOnmUxFcjJju3sH9/O91NJUFzPWsZbgplBpw3yttja8mBnuP96rF2siG7q+mZdXj/7F/QMGfVs8wrzXO6DG+OHvCS0Qcc8HSGXCCuD1dY42hKn1FwqX48RUjlv/Rtc2a++mHbK+MGAEMp5sCC5d8QzQThoP9BAhXAcjHbECCqJC0QzGwKT2gY9ANqgu8/NbrQlTPnpHejPZ37b/4Hvo3WHmKDZ3qAeEQrMcw04MNphob3FVnKDu453AagzilXN9ZRKTMu0zM02FXjIq2vUo5/tOF/6u8ruEAu4suSK4s+uBma0S3KH/TFPIY6wj/PeQ7DLWFCPwkW7y5NfXGneLpKSlrSckFp4KcelNJ/AxwyuQDV6n5fLmf+RsI6touslZ0il2dlyaH6x86HS6RSTgghnJafAXDCMBEK04cwLBk51HhRjbhDCBB64dIN1g9JhAM8HVSlAzU2zXmlQnWKaARaSCSwEMGys0tgpbZTojBwG8451czdWnXWaCPAcGwgeC0MtNoJz7Lm0inVBKRZqxI/HfTlH6jVJNaj+O1qXxFFCf8Sc4Z8F5jOsC+/9cpZ7eD5P7mqj816D7yhmgkosjKFYG6nwoPRghk6DdNXGLeQE43e0P0aXp3kKpblEsXnH/9OS6uvTrLH8EhP+dw3DzeQeITc1TDamOmyX/Jw26AnsvGR4Wh+v/gUdrXu0D9VKgAzJwd5NSyrrfM7+8fWPvo3aDzvJ6XQ6fQMAAP//AwDsbjNRGwUAAA==
|
||||
@ -0,0 +1,5 @@
|
||||
https://dc.services.visualstudio.com/v2/track
|
||||
Content-Type:application/x-json-stream
|
||||
Content-Encoding:gzip
|
||||
|
||||
H4sIAAAAAAAACpSTy27bMBBFf0Xg2lT4lqhd4LSokaYxmqAtuqPIUUxEIQ2KygOB/72g7CJJd90JA92ZO+cOX1EwD4A6dL7ff3qEkCe0QtkvJUaYwkRhQm8p7RjteFMTwbhm7DdaIX8JL6hDjbCWWg2YgwIsHJG454PFzoGmhDrCpCg9zd2EuldkfO3g0Vuo4/QD0uRjQB366YOLT2W28bUd4+zqFEfYhCmbYIuZb5v1Jf56vr293h7/mmAq4to71CHZ2kH10mDdMIkFtA63rjdYSioI5VILRY8yHzKkYMZ6cvdv813MAbLtWM14TTDT6LBCzmRTLPdmgtuXfXGxILoo9dVSXj67V/QICXVs9Rfmsd2ZHf2ZjQ8PJrizwQc/7dAK7VPcQ8oeFhzLhuNoso+hOg1Zjx5CRit0fVNtR5OHmB4+MLo5rr75j82vjN35ANXmAnWIUGCOt4AHRhUWrTPYSK6xUlwNQK1uWNGsY8g+zHGeqk3IcJcWl6hDn804wdHfebI7n8HmORXrv1TJGp59XkdXCrg02qboZpurN96U1KTmhJQmc97PufoOziewGcpSt2k+9f9HwhRbROs5JQi52pq8q76YaVdIqIZJQYQ1klNgdtCMDIS0mjMnGNhGOWgYs70QeuADl7Y3tm/aoQfH+6YYhRJvtVyUEsISwhs88MZgQbjEpqUcG0GVsj21vbQfuFbXY9EZ2xIBjmMNg8NCU4O14Bw7Lk3D1NA0bHiH5BQ5JWW8g8fj2zg6cK4FpyhmgkostKa41bLBfdP2ulctSKvRCl1CCjC+A3XlbYpTHHJ1upjqA7rvcyjvu1qu58kH/LxkdhHtPaSqZG58KOd8ivlwOBz+AAAA//8DAL8FuWgmBAAA
|
||||
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
@ -4,7 +4,13 @@ using PlotLine.ViewModels;
|
||||
|
||||
namespace PlotLine.Controllers;
|
||||
|
||||
public sealed class ScenesController(ISceneService scenes, IPlotService plots, IAssetService assets, ICharacterService characters, ILocationService locations) : Controller
|
||||
public sealed class ScenesController(
|
||||
ISceneService scenes,
|
||||
IPlotService plots,
|
||||
IAssetService assets,
|
||||
ICharacterService characters,
|
||||
ILocationService locations,
|
||||
IWriterWorkspaceService writerWorkspace) : Controller
|
||||
{
|
||||
public async Task<IActionResult> Create(int chapterId)
|
||||
{
|
||||
@ -272,6 +278,80 @@ public sealed class ScenesController(ISceneService scenes, IPlotService plots, I
|
||||
return RedirectForScene(model.SceneID, model.ReturnProjectID, model.ReturnBookID);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> SaveWorkflow(SceneWorkflowEditViewModel model)
|
||||
{
|
||||
await writerWorkspace.SaveSceneWorkflowAsync(model);
|
||||
return RedirectForScene(model.SceneID, model.ReturnProjectID, model.ReturnBookID);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> SaveNote(SceneNoteEditViewModel model)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(model.NoteText))
|
||||
{
|
||||
TempData["WriterWorkspaceError"] = "Enter note text before saving.";
|
||||
return RedirectForScene(model.SceneID, model.ReturnProjectID, model.ReturnBookID);
|
||||
}
|
||||
|
||||
await writerWorkspace.SaveNoteAsync(model);
|
||||
return RedirectForScene(model.SceneID, model.ReturnProjectID, model.ReturnBookID);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> DeleteNote(int id, int sceneId, int? projectId, int? bookId)
|
||||
{
|
||||
await writerWorkspace.DeleteNoteAsync(id);
|
||||
return RedirectForScene(sceneId, projectId, bookId);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> SaveChecklistItem(SceneChecklistItemEditViewModel model)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(model.ItemText))
|
||||
{
|
||||
TempData["WriterWorkspaceError"] = "Enter checklist text before saving.";
|
||||
return RedirectForScene(model.SceneID, model.ReturnProjectID, model.ReturnBookID);
|
||||
}
|
||||
|
||||
await writerWorkspace.SaveChecklistItemAsync(model);
|
||||
return RedirectForScene(model.SceneID, model.ReturnProjectID, model.ReturnBookID);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> DeleteChecklistItem(int id, int sceneId, int? projectId, int? bookId)
|
||||
{
|
||||
await writerWorkspace.DeleteChecklistItemAsync(id);
|
||||
return RedirectForScene(sceneId, projectId, bookId);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> SaveAttachment(SceneAttachmentEditViewModel model)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(model.Title))
|
||||
{
|
||||
TempData["WriterWorkspaceError"] = "Enter an attachment title before saving.";
|
||||
return RedirectForScene(model.SceneID, model.ReturnProjectID, model.ReturnBookID);
|
||||
}
|
||||
|
||||
await writerWorkspace.SaveAttachmentAsync(model);
|
||||
return RedirectForScene(model.SceneID, model.ReturnProjectID, model.ReturnBookID);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> DeleteAttachment(int id, int sceneId, int? projectId, int? bookId)
|
||||
{
|
||||
await writerWorkspace.DeleteAttachmentAsync(id);
|
||||
return RedirectForScene(sceneId, projectId, bookId);
|
||||
}
|
||||
|
||||
private IActionResult RedirectForScene(int sceneId, int? projectId, int? bookId)
|
||||
{
|
||||
if (projectId.HasValue)
|
||||
|
||||
28
PlotLine/Controllers/WriterController.cs
Normal file
28
PlotLine/Controllers/WriterController.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using PlotLine.Services;
|
||||
using PlotLine.ViewModels;
|
||||
|
||||
namespace PlotLine.Controllers;
|
||||
|
||||
public sealed class WriterController(IWriterWorkspaceService writerWorkspace) : Controller
|
||||
{
|
||||
public async Task<IActionResult> Index(int? projectId)
|
||||
{
|
||||
var model = await writerWorkspace.GetDashboardAsync(projectId);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Chapter(int id)
|
||||
{
|
||||
var model = await writerWorkspace.GetChapterWorkflowAsync(id);
|
||||
return model is null ? NotFound() : View(model);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> SaveChapterGoal(ChapterGoalEditViewModel model)
|
||||
{
|
||||
await writerWorkspace.SaveChapterGoalAsync(model);
|
||||
return RedirectToAction(nameof(Chapter), new { id = model.ChapterID });
|
||||
}
|
||||
}
|
||||
@ -190,6 +190,28 @@ public interface IStoryBibleRepository
|
||||
Task<IReadOnlyList<StoryBibleSearchResult>> SearchAsync(int projectId, string? query);
|
||||
}
|
||||
|
||||
public interface IWriterWorkspaceRepository
|
||||
{
|
||||
Task<IReadOnlyList<SceneNoteType>> ListNoteTypesAsync();
|
||||
Task<IReadOnlyList<SceneAttachmentType>> ListAttachmentTypesAsync();
|
||||
Task<SceneWorkflow> GetWorkflowAsync(int sceneId);
|
||||
Task SaveWorkflowAsync(SceneWorkflow workflow);
|
||||
Task<IReadOnlyList<SceneNote>> ListNotesAsync(int sceneId);
|
||||
Task<int> SaveNoteAsync(SceneNote note);
|
||||
Task DeleteNoteAsync(int sceneNoteId);
|
||||
Task<IReadOnlyList<SceneChecklistItem>> ListChecklistItemsAsync(int sceneId);
|
||||
Task<int> SaveChecklistItemAsync(SceneChecklistItem item);
|
||||
Task DeleteChecklistItemAsync(int sceneChecklistItemId);
|
||||
Task<IReadOnlyList<SceneAttachment>> ListAttachmentsAsync(int sceneId);
|
||||
Task<int> SaveAttachmentAsync(SceneAttachment attachment);
|
||||
Task DeleteAttachmentAsync(int sceneAttachmentId);
|
||||
Task<ChapterGoal> GetChapterGoalAsync(int chapterId);
|
||||
Task SaveChapterGoalAsync(ChapterGoal goal);
|
||||
Task<IReadOnlyList<ChapterWorkflowScene>> GetChapterWorkflowAsync(int chapterId);
|
||||
Task<IReadOnlyList<WriterDashboardScene>> GetWriterDashboardScenesAsync(int? projectId, string queue);
|
||||
Task<IReadOnlyList<StoryBibleAttentionItem>> GetWriterDashboardRemindersAsync(int? projectId);
|
||||
}
|
||||
|
||||
public sealed class TimelineData
|
||||
{
|
||||
public Project? Project { get; init; }
|
||||
@ -561,6 +583,154 @@ public sealed class StoryBibleRepository(ISqlConnectionFactory connectionFactory
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class WriterWorkspaceRepository(ISqlConnectionFactory connectionFactory) : IWriterWorkspaceRepository
|
||||
{
|
||||
public async Task<IReadOnlyList<SceneNoteType>> ListNoteTypesAsync()
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
var rows = await connection.QueryAsync<SceneNoteType>("dbo.SceneNoteType_List", commandType: CommandType.StoredProcedure);
|
||||
return rows.ToList();
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<SceneAttachmentType>> ListAttachmentTypesAsync()
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
var rows = await connection.QueryAsync<SceneAttachmentType>("dbo.SceneAttachmentType_List", commandType: CommandType.StoredProcedure);
|
||||
return rows.ToList();
|
||||
}
|
||||
|
||||
public async Task<SceneWorkflow> GetWorkflowAsync(int sceneId)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
return await connection.QuerySingleAsync<SceneWorkflow>("dbo.SceneWorkflow_Get", new { SceneID = sceneId }, commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task SaveWorkflowAsync(SceneWorkflow workflow)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
await connection.ExecuteAsync(
|
||||
"dbo.SceneWorkflow_Save",
|
||||
new
|
||||
{
|
||||
workflow.SceneID,
|
||||
workflow.DraftStatus,
|
||||
workflow.EstimatedWordCount,
|
||||
workflow.ActualWordCount,
|
||||
workflow.DraftedDate,
|
||||
workflow.LastWorkedOn,
|
||||
workflow.ReadyForDraft,
|
||||
workflow.ReadyForRevision,
|
||||
workflow.ReadyForPolish,
|
||||
workflow.IsBlocked,
|
||||
workflow.BlockedReason,
|
||||
workflow.Priority
|
||||
},
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<SceneNote>> ListNotesAsync(int sceneId)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
var rows = await connection.QueryAsync<SceneNote>("dbo.SceneNote_ListByScene", new { SceneID = sceneId }, commandType: CommandType.StoredProcedure);
|
||||
return rows.ToList();
|
||||
}
|
||||
|
||||
public async Task<int> SaveNoteAsync(SceneNote note)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
return await connection.QuerySingleAsync<int>(
|
||||
"dbo.SceneNote_Save",
|
||||
new { note.SceneNoteID, note.SceneID, note.SceneNoteTypeID, note.NoteTitle, note.NoteText, note.SortOrder, note.IsPinned, note.IsResolved },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task DeleteNoteAsync(int sceneNoteId)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
await connection.ExecuteAsync("dbo.SceneNote_Delete", new { SceneNoteID = sceneNoteId }, commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<SceneChecklistItem>> ListChecklistItemsAsync(int sceneId)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
var rows = await connection.QueryAsync<SceneChecklistItem>("dbo.SceneChecklist_ListByScene", new { SceneID = sceneId }, commandType: CommandType.StoredProcedure);
|
||||
return rows.ToList();
|
||||
}
|
||||
|
||||
public async Task<int> SaveChecklistItemAsync(SceneChecklistItem item)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
return await connection.QuerySingleAsync<int>(
|
||||
"dbo.SceneChecklist_Save",
|
||||
new { item.SceneChecklistItemID, item.SceneID, item.ItemText, item.IsCompleted, item.SortOrder },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task DeleteChecklistItemAsync(int sceneChecklistItemId)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
await connection.ExecuteAsync("dbo.SceneChecklist_Delete", new { SceneChecklistItemID = sceneChecklistItemId }, commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<SceneAttachment>> ListAttachmentsAsync(int sceneId)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
var rows = await connection.QueryAsync<SceneAttachment>("dbo.SceneAttachment_ListByScene", new { SceneID = sceneId }, commandType: CommandType.StoredProcedure);
|
||||
return rows.ToList();
|
||||
}
|
||||
|
||||
public async Task<int> SaveAttachmentAsync(SceneAttachment attachment)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
return await connection.QuerySingleAsync<int>(
|
||||
"dbo.SceneAttachment_Save",
|
||||
new { attachment.SceneAttachmentID, attachment.SceneID, attachment.SceneAttachmentTypeID, attachment.Title, attachment.FilePath, attachment.ExternalUrl, attachment.Notes },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task DeleteAttachmentAsync(int sceneAttachmentId)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
await connection.ExecuteAsync("dbo.SceneAttachment_Delete", new { SceneAttachmentID = sceneAttachmentId }, commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task<ChapterGoal> GetChapterGoalAsync(int chapterId)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
return await connection.QuerySingleAsync<ChapterGoal>("dbo.ChapterGoal_Get", new { ChapterID = chapterId }, commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task SaveChapterGoalAsync(ChapterGoal goal)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
await connection.ExecuteAsync(
|
||||
"dbo.ChapterGoal_Save",
|
||||
new { goal.ChapterID, goal.GoalSummary, goal.EmotionalGoal, goal.ReaderTakeaway, goal.MustInclude, goal.RisksOrConcerns },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<ChapterWorkflowScene>> GetChapterWorkflowAsync(int chapterId)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
var rows = await connection.QueryAsync<ChapterWorkflowScene>("dbo.ChapterWorkflow_Summary", new { ChapterID = chapterId }, commandType: CommandType.StoredProcedure);
|
||||
return rows.ToList();
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<WriterDashboardScene>> GetWriterDashboardScenesAsync(int? projectId, string queue)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
var rows = await connection.QueryAsync<WriterDashboardScene>("dbo.WriterDashboard_Scenes", new { ProjectID = projectId, Queue = queue }, commandType: CommandType.StoredProcedure);
|
||||
return rows.ToList();
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<StoryBibleAttentionItem>> GetWriterDashboardRemindersAsync(int? projectId)
|
||||
{
|
||||
using var connection = connectionFactory.CreateConnection();
|
||||
var rows = await connection.QueryAsync<StoryBibleAttentionItem>("dbo.WriterDashboard_Reminders", new { ProjectID = projectId }, commandType: CommandType.StoredProcedure);
|
||||
return rows.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SceneDependencyRepository(ISqlConnectionFactory connectionFactory) : ISceneDependencyRepository
|
||||
{
|
||||
public async Task<SceneDependencyLookupData> GetLookupsAsync()
|
||||
|
||||
@ -1147,6 +1147,135 @@ public sealed class StoryBibleSearchResult
|
||||
public int? SceneID { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SceneNoteType
|
||||
{
|
||||
public int SceneNoteTypeID { get; set; }
|
||||
public string TypeName { get; set; } = string.Empty;
|
||||
public int SortOrder { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SceneNote
|
||||
{
|
||||
public int SceneNoteID { get; set; }
|
||||
public int SceneID { get; set; }
|
||||
public int SceneNoteTypeID { get; set; }
|
||||
public string TypeName { get; set; } = string.Empty;
|
||||
public string? NoteTitle { get; set; }
|
||||
public string NoteText { get; set; } = string.Empty;
|
||||
public int? SortOrder { get; set; }
|
||||
public bool IsPinned { get; set; }
|
||||
public bool IsResolved { get; set; }
|
||||
public DateTime CreatedDate { get; set; }
|
||||
public DateTime UpdatedDate { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ChapterGoal
|
||||
{
|
||||
public int ChapterGoalID { get; set; }
|
||||
public int ChapterID { get; set; }
|
||||
public string? GoalSummary { get; set; }
|
||||
public string? EmotionalGoal { get; set; }
|
||||
public string? ReaderTakeaway { get; set; }
|
||||
public string? MustInclude { get; set; }
|
||||
public string? RisksOrConcerns { get; set; }
|
||||
public DateTime CreatedDate { get; set; }
|
||||
public DateTime UpdatedDate { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SceneWorkflow
|
||||
{
|
||||
public int SceneWorkflowID { get; set; }
|
||||
public int SceneID { get; set; }
|
||||
public string DraftStatus { get; set; } = "Planned";
|
||||
public int? EstimatedWordCount { get; set; }
|
||||
public int? ActualWordCount { get; set; }
|
||||
public DateTime? DraftedDate { get; set; }
|
||||
public DateTime? LastWorkedOn { get; set; }
|
||||
public bool ReadyForDraft { get; set; }
|
||||
public bool ReadyForRevision { get; set; }
|
||||
public bool ReadyForPolish { get; set; }
|
||||
public bool IsBlocked { get; set; }
|
||||
public string? BlockedReason { get; set; }
|
||||
public int? Priority { get; set; }
|
||||
public DateTime CreatedDate { get; set; }
|
||||
public DateTime UpdatedDate { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SceneChecklistItem
|
||||
{
|
||||
public int SceneChecklistItemID { get; set; }
|
||||
public int SceneID { get; set; }
|
||||
public string ItemText { get; set; } = string.Empty;
|
||||
public bool IsCompleted { get; set; }
|
||||
public int? SortOrder { get; set; }
|
||||
public DateTime CreatedDate { get; set; }
|
||||
public DateTime UpdatedDate { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SceneAttachmentType
|
||||
{
|
||||
public int SceneAttachmentTypeID { get; set; }
|
||||
public string TypeName { get; set; } = string.Empty;
|
||||
public int SortOrder { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SceneAttachment
|
||||
{
|
||||
public int SceneAttachmentID { get; set; }
|
||||
public int SceneID { get; set; }
|
||||
public int SceneAttachmentTypeID { get; set; }
|
||||
public string TypeName { get; set; } = string.Empty;
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public string? FilePath { get; set; }
|
||||
public string? ExternalUrl { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
public DateTime CreatedDate { get; set; }
|
||||
public DateTime UpdatedDate { get; set; }
|
||||
}
|
||||
|
||||
public sealed class WriterDashboardScene
|
||||
{
|
||||
public int ProjectID { get; set; }
|
||||
public string ProjectName { get; set; } = string.Empty;
|
||||
public int BookID { get; set; }
|
||||
public string BookTitle { get; set; } = string.Empty;
|
||||
public int ChapterID { get; set; }
|
||||
public decimal ChapterNumber { get; set; }
|
||||
public string ChapterTitle { get; set; } = string.Empty;
|
||||
public int SceneID { get; set; }
|
||||
public decimal SceneNumber { get; set; }
|
||||
public string SceneTitle { get; set; } = string.Empty;
|
||||
public string? Summary { get; set; }
|
||||
public string DraftStatus { get; set; } = "Planned";
|
||||
public int? Priority { get; set; }
|
||||
public bool IsBlocked { get; set; }
|
||||
public string? BlockedReason { get; set; }
|
||||
public int WarningCount { get; set; }
|
||||
public int RemainingChecklistCount { get; set; }
|
||||
public int UnresolvedNoteCount { get; set; }
|
||||
public string? ImportantThreads { get; set; }
|
||||
public string? PinnedNotes { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ChapterWorkflowScene
|
||||
{
|
||||
public int SceneID { get; set; }
|
||||
public decimal SceneNumber { get; set; }
|
||||
public string SceneTitle { get; set; } = string.Empty;
|
||||
public string DraftStatus { get; set; } = "Planned";
|
||||
public int? Priority { get; set; }
|
||||
public bool ReadyForDraft { get; set; }
|
||||
public bool ReadyForRevision { get; set; }
|
||||
public bool ReadyForPolish { get; set; }
|
||||
public bool IsBlocked { get; set; }
|
||||
public string? BlockedReason { get; set; }
|
||||
public int WarningCount { get; set; }
|
||||
public int RemainingChecklistCount { get; set; }
|
||||
public int UnresolvedNoteCount { get; set; }
|
||||
}
|
||||
|
||||
public sealed class AnalyticsBusyScene
|
||||
{
|
||||
public int SceneID { get; set; }
|
||||
|
||||
@ -33,6 +33,7 @@ public class Program
|
||||
builder.Services.AddScoped<ISceneDependencyRepository, SceneDependencyRepository>();
|
||||
builder.Services.AddScoped<IAnalyticsRepository, AnalyticsRepository>();
|
||||
builder.Services.AddScoped<IStoryBibleRepository, StoryBibleRepository>();
|
||||
builder.Services.AddScoped<IWriterWorkspaceRepository, WriterWorkspaceRepository>();
|
||||
builder.Services.AddScoped<IProjectService, ProjectService>();
|
||||
builder.Services.AddScoped<IBookService, BookService>();
|
||||
builder.Services.AddScoped<IChapterService, ChapterService>();
|
||||
@ -45,6 +46,7 @@ public class Program
|
||||
builder.Services.AddScoped<IContinuityValidationService, ContinuityValidationService>();
|
||||
builder.Services.AddScoped<IAnalyticsService, AnalyticsService>();
|
||||
builder.Services.AddScoped<IStoryBibleService, StoryBibleService>();
|
||||
builder.Services.AddScoped<IWriterWorkspaceService, WriterWorkspaceService>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
|
||||
@ -150,6 +150,20 @@ public interface IStoryBibleService
|
||||
Task<StoryBibleViewModel?> GetAsync(int projectId, string? query);
|
||||
}
|
||||
|
||||
public interface IWriterWorkspaceService
|
||||
{
|
||||
Task<WriterDashboardViewModel> GetDashboardAsync(int? projectId);
|
||||
Task<ChapterWorkflowViewModel?> GetChapterWorkflowAsync(int chapterId);
|
||||
Task SaveChapterGoalAsync(ChapterGoalEditViewModel model);
|
||||
Task SaveSceneWorkflowAsync(SceneWorkflowEditViewModel model);
|
||||
Task<int> SaveNoteAsync(SceneNoteEditViewModel model);
|
||||
Task DeleteNoteAsync(int sceneNoteId);
|
||||
Task<int> SaveChecklistItemAsync(SceneChecklistItemEditViewModel model);
|
||||
Task DeleteChecklistItemAsync(int sceneChecklistItemId);
|
||||
Task<int> SaveAttachmentAsync(SceneAttachmentEditViewModel model);
|
||||
Task DeleteAttachmentAsync(int sceneAttachmentId);
|
||||
}
|
||||
|
||||
public sealed class ProjectService(IProjectRepository projects, IBookRepository books) : IProjectService
|
||||
{
|
||||
public Task<IReadOnlyList<Project>> ListAsync() => projects.ListAsync();
|
||||
@ -376,7 +390,8 @@ public sealed class SceneService(
|
||||
ICharacterRepository characters,
|
||||
ILocationRepository locations,
|
||||
IWarningRepository warnings,
|
||||
ISceneDependencyRepository sceneDependencies) : ISceneService
|
||||
ISceneDependencyRepository sceneDependencies,
|
||||
IWriterWorkspaceRepository writerWorkspace) : ISceneService
|
||||
{
|
||||
public async Task<SceneEditViewModel?> GetCreateAsync(int chapterId)
|
||||
{
|
||||
@ -552,6 +567,17 @@ public sealed class SceneService(
|
||||
model.DependenciesNeedingThisScene = sceneDependencyRows.Where(x => x.SourceSceneID == model.SceneID).ToList();
|
||||
model.CharacterKnowledge = model.SceneID == 0 ? [] : await characters.ListKnowledgeBySceneAsync(model.SceneID);
|
||||
model.RelationshipEvents = model.SceneID == 0 ? [] : await characters.ListRelationshipEventsBySceneAsync(model.SceneID);
|
||||
var noteTypes = await writerWorkspace.ListNoteTypesAsync();
|
||||
var attachmentTypes = await writerWorkspace.ListAttachmentTypesAsync();
|
||||
model.Workflow = model.SceneID == 0 ? new SceneWorkflow() : await writerWorkspace.GetWorkflowAsync(model.SceneID);
|
||||
model.Notes = model.SceneID == 0 ? [] : await writerWorkspace.ListNotesAsync(model.SceneID);
|
||||
model.ChecklistItems = model.SceneID == 0 ? [] : await writerWorkspace.ListChecklistItemsAsync(model.SceneID);
|
||||
model.Attachments = model.SceneID == 0 ? [] : await writerWorkspace.ListAttachmentsAsync(model.SceneID);
|
||||
model.SceneNoteTypeOptions = ChapterService.ToSelectList(noteTypes, x => x.SceneNoteTypeID, x => x.TypeName);
|
||||
model.SceneAttachmentTypeOptions = ChapterService.ToSelectList(attachmentTypes, x => x.SceneAttachmentTypeID, x => x.TypeName);
|
||||
model.DraftStatusOptions = DraftStatuses()
|
||||
.Select(x => new SelectListItem(x, x, string.Equals(x, model.Workflow.DraftStatus, StringComparison.OrdinalIgnoreCase)))
|
||||
.ToList();
|
||||
model.PlotLineOptions = ToOptionalSelectList(plotLines, x => x.PlotLineID, x => x.PlotLineName);
|
||||
model.PlotThreadOptions = ToOptionalSelectList(plotThreads, x => x.PlotThreadID, x => $"{x.PlotLineName}: {x.ThreadTitle}");
|
||||
model.ThreadTypeOptions = ToOptionalSelectList(plotLookups.ThreadTypes, x => x.ThreadTypeID, x => x.TypeName);
|
||||
@ -656,6 +682,30 @@ public sealed class SceneService(
|
||||
?? dependencyLookups.DependencyTypes.FirstOrDefault()?.SceneDependencyTypeID
|
||||
?? 0
|
||||
};
|
||||
model.NewNote = new SceneNoteEditViewModel
|
||||
{
|
||||
SceneID = model.SceneID,
|
||||
ReturnProjectID = model.ReturnProjectID,
|
||||
ReturnBookID = model.ReturnBookID,
|
||||
SceneNoteTypeID = noteTypes.FirstOrDefault(x => x.TypeName == "Drafting Note")?.SceneNoteTypeID
|
||||
?? noteTypes.FirstOrDefault()?.SceneNoteTypeID
|
||||
?? 0
|
||||
};
|
||||
model.NewChecklistItem = new SceneChecklistItemEditViewModel
|
||||
{
|
||||
SceneID = model.SceneID,
|
||||
ReturnProjectID = model.ReturnProjectID,
|
||||
ReturnBookID = model.ReturnBookID
|
||||
};
|
||||
model.NewAttachment = new SceneAttachmentEditViewModel
|
||||
{
|
||||
SceneID = model.SceneID,
|
||||
ReturnProjectID = model.ReturnProjectID,
|
||||
ReturnBookID = model.ReturnBookID,
|
||||
SceneAttachmentTypeID = attachmentTypes.FirstOrDefault(x => x.TypeName == "Link")?.SceneAttachmentTypeID
|
||||
?? attachmentTypes.FirstOrDefault()?.SceneAttachmentTypeID
|
||||
?? 0
|
||||
};
|
||||
model.MoveRequest = new SceneMoveRequestViewModel
|
||||
{
|
||||
SceneID = model.SceneID,
|
||||
@ -667,6 +717,18 @@ public sealed class SceneService(
|
||||
return model;
|
||||
}
|
||||
|
||||
internal static IReadOnlyList<string> DraftStatuses() =>
|
||||
[
|
||||
"Planned",
|
||||
"Ready To Draft",
|
||||
"Drafting",
|
||||
"Drafted",
|
||||
"Revising",
|
||||
"Polishing",
|
||||
"Complete",
|
||||
"On Hold"
|
||||
];
|
||||
|
||||
private static IReadOnlyList<SelectListItem> ToOptionalSelectList<T>(IEnumerable<T> rows, Func<T, int> value, Func<T, string> text)
|
||||
=> rows.Select(x => new SelectListItem(text(x), value(x).ToString())).ToList();
|
||||
|
||||
@ -1726,6 +1788,112 @@ public sealed class StoryBibleService(IProjectRepository projects, IStoryBibleRe
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class WriterWorkspaceService(
|
||||
IProjectRepository projects,
|
||||
IBookRepository books,
|
||||
IChapterRepository chapters,
|
||||
IWriterWorkspaceRepository writerWorkspace) : IWriterWorkspaceService
|
||||
{
|
||||
public async Task<WriterDashboardViewModel> GetDashboardAsync(int? projectId)
|
||||
{
|
||||
var projectRows = await projects.ListAsync();
|
||||
return new WriterDashboardViewModel
|
||||
{
|
||||
ProjectID = projectId,
|
||||
ProjectOptions = projectRows.Select(x => new SelectListItem(x.ProjectName, x.ProjectID.ToString(), x.ProjectID == projectId)).ToList(),
|
||||
ContinueWriting = await writerWorkspace.GetWriterDashboardScenesAsync(projectId, "ContinueWriting"),
|
||||
NeedsAttention = await writerWorkspace.GetWriterDashboardScenesAsync(projectId, "NeedsAttention"),
|
||||
RevisionQueue = await writerWorkspace.GetWriterDashboardScenesAsync(projectId, "RevisionQueue"),
|
||||
PolishingQueue = await writerWorkspace.GetWriterDashboardScenesAsync(projectId, "PolishingQueue"),
|
||||
StoryHealthReminders = await writerWorkspace.GetWriterDashboardRemindersAsync(projectId)
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<ChapterWorkflowViewModel?> GetChapterWorkflowAsync(int chapterId)
|
||||
{
|
||||
var chapter = await chapters.GetAsync(chapterId);
|
||||
var book = chapter is null ? null : await books.GetAsync(chapter.BookID);
|
||||
var project = book is null ? null : await projects.GetAsync(book.ProjectID);
|
||||
if (chapter is null || book is null || project is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ChapterWorkflowViewModel
|
||||
{
|
||||
Project = project,
|
||||
Book = book,
|
||||
Chapter = chapter,
|
||||
Goal = await writerWorkspace.GetChapterGoalAsync(chapterId),
|
||||
Scenes = await writerWorkspace.GetChapterWorkflowAsync(chapterId)
|
||||
};
|
||||
}
|
||||
|
||||
public Task SaveChapterGoalAsync(ChapterGoalEditViewModel model) => writerWorkspace.SaveChapterGoalAsync(new ChapterGoal
|
||||
{
|
||||
ChapterID = model.ChapterID,
|
||||
GoalSummary = model.GoalSummary,
|
||||
EmotionalGoal = model.EmotionalGoal,
|
||||
ReaderTakeaway = model.ReaderTakeaway,
|
||||
MustInclude = model.MustInclude,
|
||||
RisksOrConcerns = model.RisksOrConcerns
|
||||
});
|
||||
|
||||
public Task SaveSceneWorkflowAsync(SceneWorkflowEditViewModel model) => writerWorkspace.SaveWorkflowAsync(new SceneWorkflow
|
||||
{
|
||||
SceneID = model.SceneID,
|
||||
DraftStatus = model.DraftStatus,
|
||||
EstimatedWordCount = model.EstimatedWordCount,
|
||||
ActualWordCount = model.ActualWordCount,
|
||||
DraftedDate = model.DraftedDate,
|
||||
LastWorkedOn = model.LastWorkedOn,
|
||||
ReadyForDraft = model.ReadyForDraft,
|
||||
ReadyForRevision = model.ReadyForRevision,
|
||||
ReadyForPolish = model.ReadyForPolish,
|
||||
IsBlocked = model.IsBlocked,
|
||||
BlockedReason = model.BlockedReason,
|
||||
Priority = model.Priority
|
||||
});
|
||||
|
||||
public Task<int> SaveNoteAsync(SceneNoteEditViewModel model) => writerWorkspace.SaveNoteAsync(new SceneNote
|
||||
{
|
||||
SceneNoteID = model.SceneNoteID,
|
||||
SceneID = model.SceneID,
|
||||
SceneNoteTypeID = model.SceneNoteTypeID,
|
||||
NoteTitle = model.NoteTitle,
|
||||
NoteText = model.NoteText,
|
||||
SortOrder = model.SortOrder,
|
||||
IsPinned = model.IsPinned,
|
||||
IsResolved = model.IsResolved
|
||||
});
|
||||
|
||||
public Task DeleteNoteAsync(int sceneNoteId) => writerWorkspace.DeleteNoteAsync(sceneNoteId);
|
||||
|
||||
public Task<int> SaveChecklistItemAsync(SceneChecklistItemEditViewModel model) => writerWorkspace.SaveChecklistItemAsync(new SceneChecklistItem
|
||||
{
|
||||
SceneChecklistItemID = model.SceneChecklistItemID,
|
||||
SceneID = model.SceneID,
|
||||
ItemText = model.ItemText,
|
||||
IsCompleted = model.IsCompleted,
|
||||
SortOrder = model.SortOrder
|
||||
});
|
||||
|
||||
public Task DeleteChecklistItemAsync(int sceneChecklistItemId) => writerWorkspace.DeleteChecklistItemAsync(sceneChecklistItemId);
|
||||
|
||||
public Task<int> SaveAttachmentAsync(SceneAttachmentEditViewModel model) => writerWorkspace.SaveAttachmentAsync(new SceneAttachment
|
||||
{
|
||||
SceneAttachmentID = model.SceneAttachmentID,
|
||||
SceneID = model.SceneID,
|
||||
SceneAttachmentTypeID = model.SceneAttachmentTypeID,
|
||||
Title = model.Title,
|
||||
FilePath = model.FilePath,
|
||||
ExternalUrl = model.ExternalUrl,
|
||||
Notes = model.Notes
|
||||
});
|
||||
|
||||
public Task DeleteAttachmentAsync(int sceneAttachmentId) => writerWorkspace.DeleteAttachmentAsync(sceneAttachmentId);
|
||||
}
|
||||
|
||||
public sealed class AssetService(IProjectRepository projects, IAssetRepository assets, ILocationRepository locations) : IAssetService
|
||||
{
|
||||
public async Task<StoryAssetListViewModel?> GetAssetsAsync(int projectId)
|
||||
|
||||
714
PlotLine/Sql/015_Phase1P_WriterWorkspace.sql
Normal file
714
PlotLine/Sql/015_Phase1P_WriterWorkspace.sql
Normal file
@ -0,0 +1,714 @@
|
||||
SET ANSI_NULLS ON;
|
||||
GO
|
||||
SET QUOTED_IDENTIFIER ON;
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.SceneNoteTypes', N'U') IS NULL
|
||||
BEGIN
|
||||
CREATE TABLE dbo.SceneNoteTypes
|
||||
(
|
||||
SceneNoteTypeID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_SceneNoteTypes PRIMARY KEY,
|
||||
TypeName nvarchar(100) NOT NULL,
|
||||
SortOrder int NOT NULL,
|
||||
IsActive bit NOT NULL CONSTRAINT DF_SceneNoteTypes_IsActive DEFAULT 1,
|
||||
CONSTRAINT UQ_SceneNoteTypes_TypeName UNIQUE (TypeName)
|
||||
);
|
||||
END;
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.SceneNotes', N'U') IS NULL
|
||||
BEGIN
|
||||
CREATE TABLE dbo.SceneNotes
|
||||
(
|
||||
SceneNoteID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_SceneNotes PRIMARY KEY,
|
||||
SceneID int NOT NULL,
|
||||
SceneNoteTypeID int NOT NULL,
|
||||
NoteTitle nvarchar(200) NULL,
|
||||
NoteText nvarchar(max) NOT NULL,
|
||||
SortOrder int NULL,
|
||||
IsPinned bit NOT NULL CONSTRAINT DF_SceneNotes_IsPinned DEFAULT 0,
|
||||
IsResolved bit NOT NULL CONSTRAINT DF_SceneNotes_IsResolved DEFAULT 0,
|
||||
CreatedDate datetime2 NOT NULL CONSTRAINT DF_SceneNotes_CreatedDate DEFAULT SYSUTCDATETIME(),
|
||||
UpdatedDate datetime2 NOT NULL CONSTRAINT DF_SceneNotes_UpdatedDate DEFAULT SYSUTCDATETIME(),
|
||||
CONSTRAINT FK_SceneNotes_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID),
|
||||
CONSTRAINT FK_SceneNotes_Types FOREIGN KEY (SceneNoteTypeID) REFERENCES dbo.SceneNoteTypes(SceneNoteTypeID)
|
||||
);
|
||||
END;
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.ChapterGoals', N'U') IS NULL
|
||||
BEGIN
|
||||
CREATE TABLE dbo.ChapterGoals
|
||||
(
|
||||
ChapterGoalID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_ChapterGoals PRIMARY KEY,
|
||||
ChapterID int NOT NULL,
|
||||
GoalSummary nvarchar(max) NULL,
|
||||
EmotionalGoal nvarchar(max) NULL,
|
||||
ReaderTakeaway nvarchar(max) NULL,
|
||||
MustInclude nvarchar(max) NULL,
|
||||
RisksOrConcerns nvarchar(max) NULL,
|
||||
CreatedDate datetime2 NOT NULL CONSTRAINT DF_ChapterGoals_CreatedDate DEFAULT SYSUTCDATETIME(),
|
||||
UpdatedDate datetime2 NOT NULL CONSTRAINT DF_ChapterGoals_UpdatedDate DEFAULT SYSUTCDATETIME(),
|
||||
CONSTRAINT FK_ChapterGoals_Chapters FOREIGN KEY (ChapterID) REFERENCES dbo.Chapters(ChapterID),
|
||||
CONSTRAINT UQ_ChapterGoals_ChapterID UNIQUE (ChapterID)
|
||||
);
|
||||
END;
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.SceneWorkflow', N'U') IS NULL
|
||||
BEGIN
|
||||
CREATE TABLE dbo.SceneWorkflow
|
||||
(
|
||||
SceneWorkflowID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_SceneWorkflow PRIMARY KEY,
|
||||
SceneID int NOT NULL,
|
||||
DraftStatus nvarchar(50) NOT NULL CONSTRAINT DF_SceneWorkflow_DraftStatus DEFAULT N'Planned',
|
||||
EstimatedWordCount int NULL,
|
||||
ActualWordCount int NULL,
|
||||
DraftedDate date NULL,
|
||||
LastWorkedOn date NULL,
|
||||
ReadyForDraft bit NOT NULL CONSTRAINT DF_SceneWorkflow_ReadyForDraft DEFAULT 0,
|
||||
ReadyForRevision bit NOT NULL CONSTRAINT DF_SceneWorkflow_ReadyForRevision DEFAULT 0,
|
||||
ReadyForPolish bit NOT NULL CONSTRAINT DF_SceneWorkflow_ReadyForPolish DEFAULT 0,
|
||||
IsBlocked bit NOT NULL CONSTRAINT DF_SceneWorkflow_IsBlocked DEFAULT 0,
|
||||
BlockedReason nvarchar(max) NULL,
|
||||
Priority int NULL,
|
||||
CreatedDate datetime2 NOT NULL CONSTRAINT DF_SceneWorkflow_CreatedDate DEFAULT SYSUTCDATETIME(),
|
||||
UpdatedDate datetime2 NOT NULL CONSTRAINT DF_SceneWorkflow_UpdatedDate DEFAULT SYSUTCDATETIME(),
|
||||
CONSTRAINT FK_SceneWorkflow_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID),
|
||||
CONSTRAINT UQ_SceneWorkflow_SceneID UNIQUE (SceneID),
|
||||
CONSTRAINT CK_SceneWorkflow_DraftStatus CHECK (DraftStatus IN (N'Planned', N'Ready To Draft', N'Drafting', N'Drafted', N'Revising', N'Polishing', N'Complete', N'On Hold')),
|
||||
CONSTRAINT CK_SceneWorkflow_Priority CHECK (Priority IS NULL OR Priority BETWEEN 1 AND 10),
|
||||
CONSTRAINT CK_SceneWorkflow_WordCounts CHECK ((EstimatedWordCount IS NULL OR EstimatedWordCount >= 0) AND (ActualWordCount IS NULL OR ActualWordCount >= 0))
|
||||
);
|
||||
END;
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.SceneChecklistItems', N'U') IS NULL
|
||||
BEGIN
|
||||
CREATE TABLE dbo.SceneChecklistItems
|
||||
(
|
||||
SceneChecklistItemID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_SceneChecklistItems PRIMARY KEY,
|
||||
SceneID int NOT NULL,
|
||||
ItemText nvarchar(300) NOT NULL,
|
||||
IsCompleted bit NOT NULL CONSTRAINT DF_SceneChecklistItems_IsCompleted DEFAULT 0,
|
||||
SortOrder int NULL,
|
||||
CreatedDate datetime2 NOT NULL CONSTRAINT DF_SceneChecklistItems_CreatedDate DEFAULT SYSUTCDATETIME(),
|
||||
UpdatedDate datetime2 NOT NULL CONSTRAINT DF_SceneChecklistItems_UpdatedDate DEFAULT SYSUTCDATETIME(),
|
||||
CONSTRAINT FK_SceneChecklistItems_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID)
|
||||
);
|
||||
END;
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.SceneAttachmentTypes', N'U') IS NULL
|
||||
BEGIN
|
||||
CREATE TABLE dbo.SceneAttachmentTypes
|
||||
(
|
||||
SceneAttachmentTypeID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_SceneAttachmentTypes PRIMARY KEY,
|
||||
TypeName nvarchar(100) NOT NULL,
|
||||
SortOrder int NOT NULL,
|
||||
IsActive bit NOT NULL CONSTRAINT DF_SceneAttachmentTypes_IsActive DEFAULT 1,
|
||||
CONSTRAINT UQ_SceneAttachmentTypes_TypeName UNIQUE (TypeName)
|
||||
);
|
||||
END;
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.SceneAttachments', N'U') IS NULL
|
||||
BEGIN
|
||||
CREATE TABLE dbo.SceneAttachments
|
||||
(
|
||||
SceneAttachmentID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_SceneAttachments PRIMARY KEY,
|
||||
SceneID int NOT NULL,
|
||||
SceneAttachmentTypeID int NOT NULL,
|
||||
Title nvarchar(200) NOT NULL,
|
||||
FilePath nvarchar(500) NULL,
|
||||
ExternalUrl nvarchar(1000) NULL,
|
||||
Notes nvarchar(max) NULL,
|
||||
CreatedDate datetime2 NOT NULL CONSTRAINT DF_SceneAttachments_CreatedDate DEFAULT SYSUTCDATETIME(),
|
||||
UpdatedDate datetime2 NOT NULL CONSTRAINT DF_SceneAttachments_UpdatedDate DEFAULT SYSUTCDATETIME(),
|
||||
CONSTRAINT FK_SceneAttachments_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID),
|
||||
CONSTRAINT FK_SceneAttachments_Types FOREIGN KEY (SceneAttachmentTypeID) REFERENCES dbo.SceneAttachmentTypes(SceneAttachmentTypeID)
|
||||
);
|
||||
END;
|
||||
GO
|
||||
|
||||
MERGE dbo.SceneNoteTypes AS target
|
||||
USING (VALUES
|
||||
(N'Drafting Note', 10), (N'Revision Note', 20), (N'Continuity Note', 30), (N'Research Note', 40),
|
||||
(N'Emotional Intent', 50), (N'Dialogue Note', 60), (N'Sensory Note', 70), (N'Timeline Note', 80),
|
||||
(N'Plot Reminder', 90), (N'Character Reminder', 100), (N'TODO', 110)
|
||||
) AS source (TypeName, SortOrder)
|
||||
ON target.TypeName = source.TypeName
|
||||
WHEN MATCHED THEN UPDATE SET SortOrder = source.SortOrder, IsActive = 1
|
||||
WHEN NOT MATCHED THEN INSERT (TypeName, SortOrder, IsActive) VALUES (source.TypeName, source.SortOrder, 1);
|
||||
GO
|
||||
|
||||
MERGE dbo.SceneAttachmentTypes AS target
|
||||
USING (VALUES
|
||||
(N'Image', 10), (N'Link', 20), (N'Research Reference', 30), (N'Historical Reference', 40),
|
||||
(N'Character Reference', 50), (N'Location Reference', 60), (N'Continuity Reference', 70), (N'General File', 80)
|
||||
) AS source (TypeName, SortOrder)
|
||||
ON target.TypeName = source.TypeName
|
||||
WHEN MATCHED THEN UPDATE SET SortOrder = source.SortOrder, IsActive = 1
|
||||
WHEN NOT MATCHED THEN INSERT (TypeName, SortOrder, IsActive) VALUES (source.TypeName, source.SortOrder, 1);
|
||||
GO
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_SceneNotes_SceneID' AND object_id = OBJECT_ID(N'dbo.SceneNotes'))
|
||||
CREATE INDEX IX_SceneNotes_SceneID ON dbo.SceneNotes(SceneID, IsResolved, IsPinned, SortOrder);
|
||||
GO
|
||||
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_SceneChecklistItems_SceneID' AND object_id = OBJECT_ID(N'dbo.SceneChecklistItems'))
|
||||
CREATE INDEX IX_SceneChecklistItems_SceneID ON dbo.SceneChecklistItems(SceneID, IsCompleted, SortOrder);
|
||||
GO
|
||||
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_SceneAttachments_SceneID' AND object_id = OBJECT_ID(N'dbo.SceneAttachments'))
|
||||
CREATE INDEX IX_SceneAttachments_SceneID ON dbo.SceneAttachments(SceneID, SceneAttachmentTypeID);
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneNoteType_List
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SELECT SceneNoteTypeID, TypeName, SortOrder, IsActive
|
||||
FROM dbo.SceneNoteTypes
|
||||
WHERE IsActive = 1
|
||||
ORDER BY SortOrder, TypeName;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneAttachmentType_List
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SELECT SceneAttachmentTypeID, TypeName, SortOrder, IsActive
|
||||
FROM dbo.SceneAttachmentTypes
|
||||
WHERE IsActive = 1
|
||||
ORDER BY SortOrder, TypeName;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneWorkflow_Get
|
||||
@SceneID int
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM dbo.SceneWorkflow WHERE SceneID = @SceneID)
|
||||
BEGIN
|
||||
INSERT dbo.SceneWorkflow (SceneID)
|
||||
VALUES (@SceneID);
|
||||
END;
|
||||
|
||||
IF NOT EXISTS (SELECT 1 FROM dbo.SceneChecklistItems WHERE SceneID = @SceneID)
|
||||
BEGIN
|
||||
INSERT dbo.SceneChecklistItems (SceneID, ItemText, SortOrder)
|
||||
VALUES
|
||||
(@SceneID, N'Purpose clear', 10),
|
||||
(@SceneID, N'Emotional payoff clear', 20),
|
||||
(@SceneID, N'Continuity checked', 30),
|
||||
(@SceneID, N'POV consistent', 40),
|
||||
(@SceneID, N'Dialogue pass complete', 50),
|
||||
(@SceneID, N'Sensory detail pass complete', 60),
|
||||
(@SceneID, N'Character motivation clear', 70),
|
||||
(@SceneID, N'Ending hook strong', 80);
|
||||
END;
|
||||
|
||||
SELECT SceneWorkflowID, SceneID, DraftStatus, EstimatedWordCount, ActualWordCount, DraftedDate, LastWorkedOn,
|
||||
ReadyForDraft, ReadyForRevision, ReadyForPolish, IsBlocked, BlockedReason, Priority, CreatedDate, UpdatedDate
|
||||
FROM dbo.SceneWorkflow
|
||||
WHERE SceneID = @SceneID;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneWorkflow_Save
|
||||
@SceneID int,
|
||||
@DraftStatus nvarchar(50),
|
||||
@EstimatedWordCount int = NULL,
|
||||
@ActualWordCount int = NULL,
|
||||
@DraftedDate date = NULL,
|
||||
@LastWorkedOn date = NULL,
|
||||
@ReadyForDraft bit = 0,
|
||||
@ReadyForRevision bit = 0,
|
||||
@ReadyForPolish bit = 0,
|
||||
@IsBlocked bit = 0,
|
||||
@BlockedReason nvarchar(max) = NULL,
|
||||
@Priority int = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
IF EXISTS (SELECT 1 FROM dbo.SceneWorkflow WHERE SceneID = @SceneID)
|
||||
BEGIN
|
||||
UPDATE dbo.SceneWorkflow
|
||||
SET DraftStatus = @DraftStatus,
|
||||
EstimatedWordCount = @EstimatedWordCount,
|
||||
ActualWordCount = @ActualWordCount,
|
||||
DraftedDate = @DraftedDate,
|
||||
LastWorkedOn = @LastWorkedOn,
|
||||
ReadyForDraft = @ReadyForDraft,
|
||||
ReadyForRevision = @ReadyForRevision,
|
||||
ReadyForPolish = @ReadyForPolish,
|
||||
IsBlocked = @IsBlocked,
|
||||
BlockedReason = @BlockedReason,
|
||||
Priority = @Priority,
|
||||
UpdatedDate = SYSUTCDATETIME()
|
||||
WHERE SceneID = @SceneID;
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
INSERT dbo.SceneWorkflow (SceneID, DraftStatus, EstimatedWordCount, ActualWordCount, DraftedDate, LastWorkedOn, ReadyForDraft, ReadyForRevision, ReadyForPolish, IsBlocked, BlockedReason, Priority)
|
||||
VALUES (@SceneID, @DraftStatus, @EstimatedWordCount, @ActualWordCount, @DraftedDate, @LastWorkedOn, @ReadyForDraft, @ReadyForRevision, @ReadyForPolish, @IsBlocked, @BlockedReason, @Priority);
|
||||
END;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneNote_ListByScene
|
||||
@SceneID int
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SELECT n.SceneNoteID, n.SceneID, n.SceneNoteTypeID, nt.TypeName, n.NoteTitle, n.NoteText, n.SortOrder,
|
||||
n.IsPinned, n.IsResolved, n.CreatedDate, n.UpdatedDate
|
||||
FROM dbo.SceneNotes n
|
||||
INNER JOIN dbo.SceneNoteTypes nt ON nt.SceneNoteTypeID = n.SceneNoteTypeID
|
||||
WHERE n.SceneID = @SceneID
|
||||
ORDER BY n.IsPinned DESC, n.IsResolved, ISNULL(n.SortOrder, 9999), n.UpdatedDate DESC;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneNote_Save
|
||||
@SceneNoteID int = 0,
|
||||
@SceneID int,
|
||||
@SceneNoteTypeID int,
|
||||
@NoteTitle nvarchar(200) = NULL,
|
||||
@NoteText nvarchar(max),
|
||||
@SortOrder int = NULL,
|
||||
@IsPinned bit = 0,
|
||||
@IsResolved bit = 0
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
IF @SceneNoteID IS NULL OR @SceneNoteID = 0
|
||||
BEGIN
|
||||
INSERT dbo.SceneNotes (SceneID, SceneNoteTypeID, NoteTitle, NoteText, SortOrder, IsPinned, IsResolved)
|
||||
VALUES (@SceneID, @SceneNoteTypeID, @NoteTitle, @NoteText, @SortOrder, @IsPinned, @IsResolved);
|
||||
SET @SceneNoteID = CAST(SCOPE_IDENTITY() AS int);
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
UPDATE dbo.SceneNotes
|
||||
SET SceneNoteTypeID = @SceneNoteTypeID,
|
||||
NoteTitle = @NoteTitle,
|
||||
NoteText = @NoteText,
|
||||
SortOrder = @SortOrder,
|
||||
IsPinned = @IsPinned,
|
||||
IsResolved = @IsResolved,
|
||||
UpdatedDate = SYSUTCDATETIME()
|
||||
WHERE SceneNoteID = @SceneNoteID;
|
||||
END;
|
||||
|
||||
SELECT @SceneNoteID;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneNote_Delete
|
||||
@SceneNoteID int
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DELETE dbo.SceneNotes WHERE SceneNoteID = @SceneNoteID;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneChecklist_ListByScene
|
||||
@SceneID int
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SELECT SceneChecklistItemID, SceneID, ItemText, IsCompleted, SortOrder, CreatedDate, UpdatedDate
|
||||
FROM dbo.SceneChecklistItems
|
||||
WHERE SceneID = @SceneID
|
||||
ORDER BY IsCompleted, ISNULL(SortOrder, 9999), SceneChecklistItemID;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneChecklist_Save
|
||||
@SceneChecklistItemID int = 0,
|
||||
@SceneID int,
|
||||
@ItemText nvarchar(300),
|
||||
@IsCompleted bit = 0,
|
||||
@SortOrder int = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
IF @SceneChecklistItemID IS NULL OR @SceneChecklistItemID = 0
|
||||
BEGIN
|
||||
INSERT dbo.SceneChecklistItems (SceneID, ItemText, IsCompleted, SortOrder)
|
||||
VALUES (@SceneID, @ItemText, @IsCompleted, @SortOrder);
|
||||
SET @SceneChecklistItemID = CAST(SCOPE_IDENTITY() AS int);
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
UPDATE dbo.SceneChecklistItems
|
||||
SET ItemText = @ItemText, IsCompleted = @IsCompleted, SortOrder = @SortOrder, UpdatedDate = SYSUTCDATETIME()
|
||||
WHERE SceneChecklistItemID = @SceneChecklistItemID;
|
||||
END;
|
||||
|
||||
SELECT @SceneChecklistItemID;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneChecklist_Delete
|
||||
@SceneChecklistItemID int
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DELETE dbo.SceneChecklistItems WHERE SceneChecklistItemID = @SceneChecklistItemID;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneAttachment_ListByScene
|
||||
@SceneID int
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SELECT a.SceneAttachmentID, a.SceneID, a.SceneAttachmentTypeID, at.TypeName, a.Title, a.FilePath, a.ExternalUrl, a.Notes, a.CreatedDate, a.UpdatedDate
|
||||
FROM dbo.SceneAttachments a
|
||||
INNER JOIN dbo.SceneAttachmentTypes at ON at.SceneAttachmentTypeID = a.SceneAttachmentTypeID
|
||||
WHERE a.SceneID = @SceneID
|
||||
ORDER BY a.UpdatedDate DESC, a.SceneAttachmentID DESC;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneAttachment_Save
|
||||
@SceneAttachmentID int = 0,
|
||||
@SceneID int,
|
||||
@SceneAttachmentTypeID int,
|
||||
@Title nvarchar(200),
|
||||
@FilePath nvarchar(500) = NULL,
|
||||
@ExternalUrl nvarchar(1000) = NULL,
|
||||
@Notes nvarchar(max) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
IF @SceneAttachmentID IS NULL OR @SceneAttachmentID = 0
|
||||
BEGIN
|
||||
INSERT dbo.SceneAttachments (SceneID, SceneAttachmentTypeID, Title, FilePath, ExternalUrl, Notes)
|
||||
VALUES (@SceneID, @SceneAttachmentTypeID, @Title, @FilePath, @ExternalUrl, @Notes);
|
||||
SET @SceneAttachmentID = CAST(SCOPE_IDENTITY() AS int);
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
UPDATE dbo.SceneAttachments
|
||||
SET SceneAttachmentTypeID = @SceneAttachmentTypeID,
|
||||
Title = @Title,
|
||||
FilePath = @FilePath,
|
||||
ExternalUrl = @ExternalUrl,
|
||||
Notes = @Notes,
|
||||
UpdatedDate = SYSUTCDATETIME()
|
||||
WHERE SceneAttachmentID = @SceneAttachmentID;
|
||||
END;
|
||||
|
||||
SELECT @SceneAttachmentID;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SceneAttachment_Delete
|
||||
@SceneAttachmentID int
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
DELETE dbo.SceneAttachments WHERE SceneAttachmentID = @SceneAttachmentID;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.ChapterGoal_Get
|
||||
@ChapterID int
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
IF NOT EXISTS (SELECT 1 FROM dbo.ChapterGoals WHERE ChapterID = @ChapterID)
|
||||
BEGIN
|
||||
INSERT dbo.ChapterGoals (ChapterID) VALUES (@ChapterID);
|
||||
END;
|
||||
|
||||
SELECT ChapterGoalID, ChapterID, GoalSummary, EmotionalGoal, ReaderTakeaway, MustInclude, RisksOrConcerns, CreatedDate, UpdatedDate
|
||||
FROM dbo.ChapterGoals
|
||||
WHERE ChapterID = @ChapterID;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.ChapterGoal_Save
|
||||
@ChapterID int,
|
||||
@GoalSummary nvarchar(max) = NULL,
|
||||
@EmotionalGoal nvarchar(max) = NULL,
|
||||
@ReaderTakeaway nvarchar(max) = NULL,
|
||||
@MustInclude nvarchar(max) = NULL,
|
||||
@RisksOrConcerns nvarchar(max) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
IF EXISTS (SELECT 1 FROM dbo.ChapterGoals WHERE ChapterID = @ChapterID)
|
||||
BEGIN
|
||||
UPDATE dbo.ChapterGoals
|
||||
SET GoalSummary = @GoalSummary,
|
||||
EmotionalGoal = @EmotionalGoal,
|
||||
ReaderTakeaway = @ReaderTakeaway,
|
||||
MustInclude = @MustInclude,
|
||||
RisksOrConcerns = @RisksOrConcerns,
|
||||
UpdatedDate = SYSUTCDATETIME()
|
||||
WHERE ChapterID = @ChapterID;
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
INSERT dbo.ChapterGoals (ChapterID, GoalSummary, EmotionalGoal, ReaderTakeaway, MustInclude, RisksOrConcerns)
|
||||
VALUES (@ChapterID, @GoalSummary, @EmotionalGoal, @ReaderTakeaway, @MustInclude, @RisksOrConcerns);
|
||||
END;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.ChapterWorkflow_Summary
|
||||
@ChapterID int
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
SELECT s.SceneID, s.SceneNumber, s.SceneTitle,
|
||||
COALESCE(sw.DraftStatus, N'Planned') AS DraftStatus,
|
||||
sw.Priority,
|
||||
COALESCE(sw.ReadyForDraft, 0) AS ReadyForDraft,
|
||||
COALESCE(sw.ReadyForRevision, 0) AS ReadyForRevision,
|
||||
COALESCE(sw.ReadyForPolish, 0) AS ReadyForPolish,
|
||||
COALESCE(sw.IsBlocked, 0) AS IsBlocked,
|
||||
sw.BlockedReason,
|
||||
ISNULL(warnings.WarningCount, 0) AS WarningCount,
|
||||
ISNULL(checklist.RemainingChecklistCount, 0) AS RemainingChecklistCount,
|
||||
ISNULL(notes.UnresolvedNoteCount, 0) AS UnresolvedNoteCount
|
||||
FROM dbo.Scenes s
|
||||
LEFT JOIN dbo.SceneWorkflow sw ON sw.SceneID = s.SceneID
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT COUNT(*) AS WarningCount
|
||||
FROM dbo.ContinuityWarnings cw
|
||||
WHERE cw.SceneID = s.SceneID AND cw.IsDismissed = 0
|
||||
) warnings
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT COUNT(*) AS RemainingChecklistCount
|
||||
FROM dbo.SceneChecklistItems sci
|
||||
WHERE sci.SceneID = s.SceneID AND sci.IsCompleted = 0
|
||||
) checklist
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT COUNT(*) AS UnresolvedNoteCount
|
||||
FROM dbo.SceneNotes sn
|
||||
WHERE sn.SceneID = s.SceneID AND sn.IsResolved = 0
|
||||
) notes
|
||||
WHERE s.ChapterID = @ChapterID AND s.IsArchived = 0
|
||||
ORDER BY s.SortOrder, s.SceneID;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.WriterDashboard_Scenes
|
||||
@ProjectID int = NULL,
|
||||
@Queue nvarchar(50)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
WITH SceneBase AS
|
||||
(
|
||||
SELECT p.ProjectID, p.ProjectName, b.BookID, b.BookTitle, c.ChapterID, c.ChapterNumber, c.ChapterTitle,
|
||||
s.SceneID, s.SceneNumber, s.SceneTitle, s.Summary,
|
||||
COALESCE(sw.DraftStatus, N'Planned') AS DraftStatus,
|
||||
sw.Priority,
|
||||
COALESCE(sw.IsBlocked, 0) AS IsBlocked,
|
||||
sw.BlockedReason,
|
||||
COALESCE(sw.ReadyForDraft, 0) AS ReadyForDraft,
|
||||
COALESCE(sw.ReadyForRevision, 0) AS ReadyForRevision,
|
||||
COALESCE(sw.ReadyForPolish, 0) AS ReadyForPolish,
|
||||
b.SortOrder AS BookSortOrder,
|
||||
c.SortOrder AS ChapterSortOrder,
|
||||
s.SortOrder AS SceneSortOrder
|
||||
FROM dbo.Projects p
|
||||
INNER JOIN dbo.Books b ON b.ProjectID = p.ProjectID AND b.IsArchived = 0
|
||||
INNER JOIN dbo.Chapters c ON c.BookID = b.BookID AND c.IsArchived = 0
|
||||
INNER JOIN dbo.Scenes s ON s.ChapterID = c.ChapterID AND s.IsArchived = 0
|
||||
LEFT JOIN dbo.SceneWorkflow sw ON sw.SceneID = s.SceneID
|
||||
WHERE p.IsArchived = 0 AND (@ProjectID IS NULL OR p.ProjectID = @ProjectID)
|
||||
)
|
||||
SELECT TOP (40) sb.ProjectID, sb.ProjectName, sb.BookID, sb.BookTitle, sb.ChapterID, sb.ChapterNumber, sb.ChapterTitle,
|
||||
sb.SceneID, sb.SceneNumber, sb.SceneTitle, sb.Summary, sb.DraftStatus, sb.Priority, sb.IsBlocked, sb.BlockedReason,
|
||||
ISNULL(warnings.WarningCount, 0) AS WarningCount,
|
||||
ISNULL(checklist.RemainingChecklistCount, 0) AS RemainingChecklistCount,
|
||||
ISNULL(notes.UnresolvedNoteCount, 0) AS UnresolvedNoteCount,
|
||||
threads.ImportantThreads,
|
||||
pinned.PinnedNotes
|
||||
FROM SceneBase sb
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT COUNT(*) AS WarningCount
|
||||
FROM dbo.ContinuityWarnings cw
|
||||
WHERE cw.SceneID = sb.SceneID AND cw.IsDismissed = 0
|
||||
) warnings
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT COUNT(*) AS RemainingChecklistCount
|
||||
FROM dbo.SceneChecklistItems sci
|
||||
WHERE sci.SceneID = sb.SceneID AND sci.IsCompleted = 0
|
||||
) checklist
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT COUNT(*) AS UnresolvedNoteCount
|
||||
FROM dbo.SceneNotes sn
|
||||
INNER JOIN dbo.SceneNoteTypes snt ON snt.SceneNoteTypeID = sn.SceneNoteTypeID
|
||||
WHERE sn.SceneID = sb.SceneID AND sn.IsResolved = 0
|
||||
AND (@Queue <> N'NeedsAttention' OR snt.TypeName IN (N'TODO', N'Continuity Note'))
|
||||
) notes
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT STRING_AGG(CONVERT(nvarchar(max), pt.ThreadTitle), N', ') AS ImportantThreads
|
||||
FROM
|
||||
(
|
||||
SELECT DISTINCT TOP (5) pt.ThreadTitle, pt.Importance
|
||||
FROM dbo.ThreadEvents te
|
||||
INNER JOIN dbo.PlotThreads pt ON pt.PlotThreadID = te.PlotThreadID
|
||||
WHERE te.SceneID = sb.SceneID
|
||||
ORDER BY pt.Importance DESC, pt.ThreadTitle
|
||||
) pt
|
||||
) threads
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT STRING_AGG(CONVERT(nvarchar(max), COALESCE(sn.NoteTitle, sn.NoteText)), N' | ') AS PinnedNotes
|
||||
FROM dbo.SceneNotes sn
|
||||
WHERE sn.SceneID = sb.SceneID AND sn.IsPinned = 1 AND sn.IsResolved = 0
|
||||
) pinned
|
||||
WHERE
|
||||
(@Queue = N'ContinueWriting' AND (sb.DraftStatus IN (N'Ready To Draft', N'Drafting') OR sb.ReadyForDraft = 1 OR ISNULL(sb.Priority, 0) >= 8))
|
||||
OR (@Queue = N'NeedsAttention' AND (sb.IsBlocked = 1 OR ISNULL(warnings.WarningCount, 0) > 0 OR ISNULL(notes.UnresolvedNoteCount, 0) > 0))
|
||||
OR (@Queue = N'RevisionQueue' AND (sb.DraftStatus IN (N'Drafted', N'Revising') OR sb.ReadyForRevision = 1))
|
||||
OR (@Queue = N'PolishingQueue' AND (sb.DraftStatus = N'Polishing' OR sb.ReadyForPolish = 1))
|
||||
ORDER BY ISNULL(sb.Priority, 0) DESC, sb.BookSortOrder, sb.ChapterSortOrder, sb.SceneSortOrder, sb.SceneID;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.WriterDashboard_Reminders
|
||||
@ProjectID int = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
SELECT TOP (60) N'Chapter Goal' AS Category, N'Info' AS SeverityName,
|
||||
CONCAT(N'Chapter ', c.ChapterNumber, N' needs intent') AS Title,
|
||||
N'Goal summary is empty.' AS Detail,
|
||||
CAST(NULL AS int) AS SceneID, c.ChapterID AS EntityID, N'Chapter' AS EntityType
|
||||
FROM dbo.Chapters c
|
||||
INNER JOIN dbo.Books b ON b.BookID = c.BookID AND b.IsArchived = 0
|
||||
LEFT JOIN dbo.ChapterGoals cg ON cg.ChapterID = c.ChapterID
|
||||
WHERE c.IsArchived = 0 AND (@ProjectID IS NULL OR b.ProjectID = @ProjectID)
|
||||
AND NULLIF(LTRIM(RTRIM(cg.GoalSummary)), N'') IS NULL
|
||||
UNION ALL
|
||||
SELECT N'Plot Thread', N'Info', pt.ThreadTitle,
|
||||
CONCAT(N'Unresolved thread in ', pl.PlotLineName, N'.'),
|
||||
CAST(NULL AS int), pt.PlotThreadID, N'PlotThread'
|
||||
FROM dbo.PlotThreads pt
|
||||
INNER JOIN dbo.ThreadStatuses ts ON ts.ThreadStatusID = pt.ThreadStatusID
|
||||
INNER JOIN dbo.PlotLines pl ON pl.PlotLineID = pt.PlotLineID AND pl.IsArchived = 0
|
||||
WHERE pt.IsArchived = 0 AND ts.IsOpenStatus = 1 AND (@ProjectID IS NULL OR pl.ProjectID = @ProjectID)
|
||||
UNION ALL
|
||||
SELECT N'Writer Note', N'Warning', COALESCE(sn.NoteTitle, s.SceneTitle),
|
||||
sn.NoteText, s.SceneID, sn.SceneNoteID, N'SceneNote'
|
||||
FROM dbo.SceneNotes sn
|
||||
INNER JOIN dbo.SceneNoteTypes snt ON snt.SceneNoteTypeID = sn.SceneNoteTypeID
|
||||
INNER JOIN dbo.Scenes s ON s.SceneID = sn.SceneID AND s.IsArchived = 0
|
||||
INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID AND c.IsArchived = 0
|
||||
INNER JOIN dbo.Books b ON b.BookID = c.BookID AND b.IsArchived = 0
|
||||
WHERE sn.IsResolved = 0 AND snt.TypeName IN (N'TODO', N'Continuity Note', N'Revision Note') AND (@ProjectID IS NULL OR b.ProjectID = @ProjectID);
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.StoryBible_Search
|
||||
@ProjectID int,
|
||||
@Query nvarchar(200) = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
IF NULLIF(LTRIM(RTRIM(@Query)), N'') IS NULL
|
||||
RETURN;
|
||||
|
||||
DECLARE @Term nvarchar(204) = N'%' + LTRIM(RTRIM(@Query)) + N'%';
|
||||
|
||||
SELECT N'Character' AS ResultType, ch.CharacterID AS EntityID, ch.CharacterName AS Title,
|
||||
ch.DefaultDescription AS Detail, CAST(NULL AS int) AS SceneID
|
||||
FROM dbo.Characters ch
|
||||
WHERE ch.ProjectID = @ProjectID AND ch.IsArchived = 0
|
||||
AND (ch.CharacterName LIKE @Term OR ch.ShortName LIKE @Term OR ch.DefaultDescription LIKE @Term)
|
||||
UNION ALL
|
||||
SELECT N'Scene', s.SceneID, CONCAT(N'Scene ', s.SceneNumber, N': ', s.SceneTitle),
|
||||
s.Summary, s.SceneID
|
||||
FROM dbo.Scenes s
|
||||
INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID AND c.IsArchived = 0
|
||||
INNER JOIN dbo.Books b ON b.BookID = c.BookID AND b.ProjectID = @ProjectID AND b.IsArchived = 0
|
||||
WHERE s.IsArchived = 0 AND (s.SceneTitle LIKE @Term OR s.Summary LIKE @Term OR s.ScenePurposeNotes LIKE @Term OR s.SceneOutcomeNotes LIKE @Term)
|
||||
UNION ALL
|
||||
SELECT N'Plot Thread', pt.PlotThreadID, pt.ThreadTitle, pt.Summary, CAST(NULL AS int)
|
||||
FROM dbo.PlotThreads pt
|
||||
INNER JOIN dbo.PlotLines pl ON pl.PlotLineID = pt.PlotLineID AND pl.ProjectID = @ProjectID AND pl.IsArchived = 0
|
||||
WHERE pt.IsArchived = 0 AND (pt.ThreadTitle LIKE @Term OR pt.Summary LIKE @Term)
|
||||
UNION ALL
|
||||
SELECT N'Story Asset', sa.StoryAssetID, sa.AssetName, sa.Description, CAST(NULL AS int)
|
||||
FROM dbo.StoryAssets sa
|
||||
WHERE sa.ProjectID = @ProjectID AND sa.IsArchived = 0 AND (sa.AssetName LIKE @Term OR sa.Description LIKE @Term)
|
||||
UNION ALL
|
||||
SELECT N'Location', lp.LocationID, lp.LocationPath, lp.Description, CAST(NULL AS int)
|
||||
FROM dbo.LocationPaths lp
|
||||
WHERE lp.ProjectID = @ProjectID AND (lp.LocationName LIKE @Term OR lp.LocationPath LIKE @Term OR lp.Description LIKE @Term)
|
||||
UNION ALL
|
||||
SELECT N'Relationship', cr.CharacterRelationshipID, CONCAT(ca.CharacterName, N' - ', cb.CharacterName),
|
||||
CONCAT(rt.TypeName, N'. ', ISNULL(cr.Notes, N'')), CAST(NULL AS int)
|
||||
FROM dbo.CharacterRelationships cr
|
||||
INNER JOIN dbo.Characters ca ON ca.CharacterID = cr.CharacterAID
|
||||
INNER JOIN dbo.Characters cb ON cb.CharacterID = cr.CharacterBID
|
||||
INNER JOIN dbo.RelationshipTypes rt ON rt.RelationshipTypeID = cr.RelationshipTypeID
|
||||
WHERE cr.ProjectID = @ProjectID AND cr.IsArchived = 0
|
||||
AND (ca.CharacterName LIKE @Term OR cb.CharacterName LIKE @Term OR rt.TypeName LIKE @Term OR cr.Notes LIKE @Term)
|
||||
UNION ALL
|
||||
SELECT N'Warning', cw.ContinuityWarningID, cw.Message, cw.Details, cw.SceneID
|
||||
FROM dbo.ContinuityWarnings cw
|
||||
WHERE cw.ProjectID = @ProjectID AND cw.IsDismissed = 0
|
||||
AND (cw.Message LIKE @Term OR cw.Details LIKE @Term OR cw.EntityType LIKE @Term)
|
||||
UNION ALL
|
||||
SELECT N'Scene Note', sn.SceneNoteID, COALESCE(sn.NoteTitle, CONCAT(snt.TypeName, N' for ', s.SceneTitle)),
|
||||
sn.NoteText, sn.SceneID
|
||||
FROM dbo.SceneNotes sn
|
||||
INNER JOIN dbo.SceneNoteTypes snt ON snt.SceneNoteTypeID = sn.SceneNoteTypeID
|
||||
INNER JOIN dbo.Scenes s ON s.SceneID = sn.SceneID AND s.IsArchived = 0
|
||||
INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID AND c.IsArchived = 0
|
||||
INNER JOIN dbo.Books b ON b.BookID = c.BookID AND b.ProjectID = @ProjectID AND b.IsArchived = 0
|
||||
WHERE sn.NoteTitle LIKE @Term OR sn.NoteText LIKE @Term OR snt.TypeName LIKE @Term
|
||||
UNION ALL
|
||||
SELECT N'Chapter Goal', cg.ChapterGoalID, CONCAT(N'Chapter ', c.ChapterNumber, N': ', c.ChapterTitle),
|
||||
CONCAT(ISNULL(cg.GoalSummary, N''), N' ', ISNULL(cg.EmotionalGoal, N''), N' ', ISNULL(cg.ReaderTakeaway, N''), N' ', ISNULL(cg.MustInclude, N''), N' ', ISNULL(cg.RisksOrConcerns, N'')),
|
||||
CAST(NULL AS int)
|
||||
FROM dbo.ChapterGoals cg
|
||||
INNER JOIN dbo.Chapters c ON c.ChapterID = cg.ChapterID AND c.IsArchived = 0
|
||||
INNER JOIN dbo.Books b ON b.BookID = c.BookID AND b.ProjectID = @ProjectID AND b.IsArchived = 0
|
||||
WHERE cg.GoalSummary LIKE @Term OR cg.EmotionalGoal LIKE @Term OR cg.ReaderTakeaway LIKE @Term OR cg.MustInclude LIKE @Term OR cg.RisksOrConcerns LIKE @Term
|
||||
UNION ALL
|
||||
SELECT N'Attachment', sa.SceneAttachmentID, sa.Title,
|
||||
CONCAT(ISNULL(sa.ExternalUrl, N''), N' ', ISNULL(sa.FilePath, N''), N' ', ISNULL(sa.Notes, N'')), sa.SceneID
|
||||
FROM dbo.SceneAttachments sa
|
||||
INNER JOIN dbo.Scenes s ON s.SceneID = sa.SceneID AND s.IsArchived = 0
|
||||
INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID AND c.IsArchived = 0
|
||||
INNER JOIN dbo.Books b ON b.BookID = c.BookID AND b.ProjectID = @ProjectID AND b.IsArchived = 0
|
||||
WHERE sa.Title LIKE @Term OR sa.ExternalUrl LIKE @Term OR sa.FilePath LIKE @Term OR sa.Notes LIKE @Term
|
||||
UNION ALL
|
||||
SELECT N'Workflow', sw.SceneWorkflowID, CONCAT(N'Workflow: ', s.SceneTitle),
|
||||
sw.BlockedReason, s.SceneID
|
||||
FROM dbo.SceneWorkflow sw
|
||||
INNER JOIN dbo.Scenes s ON s.SceneID = sw.SceneID AND s.IsArchived = 0
|
||||
INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID AND c.IsArchived = 0
|
||||
INNER JOIN dbo.Books b ON b.BookID = c.BookID AND b.ProjectID = @ProjectID AND b.IsArchived = 0
|
||||
WHERE sw.BlockedReason LIKE @Term OR sw.DraftStatus LIKE @Term
|
||||
ORDER BY ResultType, Title;
|
||||
END;
|
||||
GO
|
||||
39
PlotLine/Sql/016_FixCharacterTimelineAppearanceLabels.sql
Normal file
39
PlotLine/Sql/016_FixCharacterTimelineAppearanceLabels.sql
Normal file
@ -0,0 +1,39 @@
|
||||
SET ANSI_NULLS ON;
|
||||
GO
|
||||
SET QUOTED_IDENTIFIER ON;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.CharacterTimeline_GetByProject
|
||||
@ProjectID int,
|
||||
@BookID int = NULL
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
SELECT TOP (12) CharacterID, ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID,
|
||||
Height, EyeColour, DefaultDescription, CreatedDate, UpdatedDate, IsArchived
|
||||
FROM dbo.Characters
|
||||
WHERE ProjectID = @ProjectID AND IsArchived = 0
|
||||
ORDER BY 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, ch.ChapterNumber, b.BookTitle,
|
||||
sc.CreatedDate, sc.UpdatedDate
|
||||
FROM dbo.SceneCharacters sc
|
||||
INNER JOIN dbo.Characters c ON c.CharacterID = sc.CharacterID
|
||||
INNER JOIN dbo.Scenes s ON s.SceneID = sc.SceneID
|
||||
INNER JOIN dbo.Chapters ch ON ch.ChapterID = s.ChapterID
|
||||
INNER JOIN dbo.Books b ON b.BookID = ch.BookID
|
||||
LEFT JOIN dbo.CharacterRoleInSceneTypes role ON role.CharacterRoleInSceneTypeID = sc.RoleInSceneTypeID
|
||||
LEFT JOIN dbo.PresenceTypes presence ON presence.PresenceTypeID = sc.PresenceTypeID
|
||||
LEFT JOIN dbo.LocationPaths location ON location.LocationID = sc.LocationID
|
||||
LEFT JOIN dbo.LocationPaths entry ON entry.LocationID = sc.EntryLocationID
|
||||
LEFT JOIN dbo.LocationPaths exitLocation ON exitLocation.LocationID = sc.ExitLocationID
|
||||
WHERE c.ProjectID = @ProjectID AND c.IsArchived = 0 AND s.IsArchived = 0 AND ch.IsArchived = 0 AND b.IsArchived = 0
|
||||
AND (@BookID IS NULL OR b.BookID = @BookID)
|
||||
ORDER BY b.SortOrder, ch.SortOrder, s.SortOrder, c.CharacterName;
|
||||
END;
|
||||
GO
|
||||
@ -170,6 +170,16 @@ public sealed class SceneEditViewModel
|
||||
public IReadOnlyList<SceneDependency> DependenciesNeedingThisScene { get; set; } = [];
|
||||
public SceneDependencyCreateViewModel NewDependency { get; set; } = new();
|
||||
public SceneMoveRequestViewModel MoveRequest { get; set; } = new();
|
||||
public SceneWorkflow Workflow { get; set; } = new();
|
||||
public IReadOnlyList<SceneNote> Notes { get; set; } = [];
|
||||
public IReadOnlyList<SceneChecklistItem> ChecklistItems { get; set; } = [];
|
||||
public IReadOnlyList<SceneAttachment> Attachments { get; set; } = [];
|
||||
public SceneNoteEditViewModel NewNote { get; set; } = new();
|
||||
public SceneChecklistItemEditViewModel NewChecklistItem { get; set; } = new();
|
||||
public SceneAttachmentEditViewModel NewAttachment { get; set; } = new();
|
||||
public IReadOnlyList<SelectListItem> SceneNoteTypeOptions { get; set; } = [];
|
||||
public IReadOnlyList<SelectListItem> SceneAttachmentTypeOptions { get; set; } = [];
|
||||
public IReadOnlyList<SelectListItem> DraftStatusOptions { get; set; } = [];
|
||||
|
||||
public int? ReturnProjectID { get; set; }
|
||||
public int? ReturnBookID { get; set; }
|
||||
@ -185,6 +195,93 @@ public sealed class SceneEditViewModel
|
||||
public IReadOnlyList<ScenePurposeType> ScenePurposeTypes { get; set; } = [];
|
||||
}
|
||||
|
||||
public sealed class SceneWorkflowEditViewModel
|
||||
{
|
||||
public int SceneID { get; set; }
|
||||
public int? ReturnProjectID { get; set; }
|
||||
public int? ReturnBookID { get; set; }
|
||||
public string DraftStatus { get; set; } = "Planned";
|
||||
public int? EstimatedWordCount { get; set; }
|
||||
public int? ActualWordCount { get; set; }
|
||||
public DateTime? DraftedDate { get; set; }
|
||||
public DateTime? LastWorkedOn { get; set; }
|
||||
public bool ReadyForDraft { get; set; }
|
||||
public bool ReadyForRevision { get; set; }
|
||||
public bool ReadyForPolish { get; set; }
|
||||
public bool IsBlocked { get; set; }
|
||||
public string? BlockedReason { get; set; }
|
||||
public int? Priority { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SceneNoteEditViewModel
|
||||
{
|
||||
public int SceneNoteID { get; set; }
|
||||
public int SceneID { get; set; }
|
||||
public int? ReturnProjectID { get; set; }
|
||||
public int? ReturnBookID { get; set; }
|
||||
public int SceneNoteTypeID { get; set; }
|
||||
public string? NoteTitle { get; set; }
|
||||
public string NoteText { get; set; } = string.Empty;
|
||||
public int? SortOrder { get; set; }
|
||||
public bool IsPinned { get; set; }
|
||||
public bool IsResolved { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SceneChecklistItemEditViewModel
|
||||
{
|
||||
public int SceneChecklistItemID { get; set; }
|
||||
public int SceneID { get; set; }
|
||||
public int? ReturnProjectID { get; set; }
|
||||
public int? ReturnBookID { get; set; }
|
||||
public string ItemText { get; set; } = string.Empty;
|
||||
public bool IsCompleted { get; set; }
|
||||
public int? SortOrder { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SceneAttachmentEditViewModel
|
||||
{
|
||||
public int SceneAttachmentID { get; set; }
|
||||
public int SceneID { get; set; }
|
||||
public int? ReturnProjectID { get; set; }
|
||||
public int? ReturnBookID { get; set; }
|
||||
public int SceneAttachmentTypeID { get; set; }
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public string? FilePath { get; set; }
|
||||
public string? ExternalUrl { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ChapterGoalEditViewModel
|
||||
{
|
||||
public int ChapterGoalID { get; set; }
|
||||
public int ChapterID { get; set; }
|
||||
public string? GoalSummary { get; set; }
|
||||
public string? EmotionalGoal { get; set; }
|
||||
public string? ReaderTakeaway { get; set; }
|
||||
public string? MustInclude { get; set; }
|
||||
public string? RisksOrConcerns { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ChapterWorkflowViewModel
|
||||
{
|
||||
public Project Project { get; set; } = new();
|
||||
public Book Book { get; set; } = new();
|
||||
public Chapter Chapter { get; set; } = new();
|
||||
public ChapterGoal Goal { get; set; } = new();
|
||||
public IReadOnlyList<ChapterWorkflowScene> Scenes { get; set; } = [];
|
||||
}
|
||||
|
||||
public sealed class WriterDashboardViewModel
|
||||
{
|
||||
public int? ProjectID { get; set; }
|
||||
public IReadOnlyList<SelectListItem> ProjectOptions { get; set; } = [];
|
||||
public IReadOnlyList<WriterDashboardScene> ContinueWriting { get; set; } = [];
|
||||
public IReadOnlyList<WriterDashboardScene> NeedsAttention { get; set; } = [];
|
||||
public IReadOnlyList<WriterDashboardScene> RevisionQueue { get; set; } = [];
|
||||
public IReadOnlyList<WriterDashboardScene> PolishingQueue { get; set; } = [];
|
||||
public IReadOnlyList<StoryBibleAttentionItem> StoryHealthReminders { get; set; } = [];
|
||||
}
|
||||
|
||||
public sealed class TimelineViewModel
|
||||
{
|
||||
public Project Project { get; set; } = new();
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
</div>
|
||||
<nav class="context-nav" aria-label="Chapter navigation">
|
||||
<a asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.Book.BookID">Timeline</a>
|
||||
<a asp-controller="Writer" asp-action="Chapter" asp-route-id="@Model.Chapter.ChapterID">Chapter workflow</a>
|
||||
<a asp-controller="Analytics" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.Book.BookID" asp-route-startChapterNumber="@Model.Chapter.ChapterNumber" asp-route-endChapterNumber="@Model.Chapter.ChapterNumber">Story health</a>
|
||||
<a asp-controller="Warnings" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.Book.BookID">Warnings</a>
|
||||
<a asp-controller="Characters" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Characters</a>
|
||||
@ -40,6 +41,7 @@
|
||||
<div class="button-row">
|
||||
<a class="btn btn-outline-secondary" asp-action="Edit" asp-route-id="@Model.Chapter.ChapterID">Edit chapter</a>
|
||||
<a class="btn btn-outline-primary" asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.Book.BookID">Timeline</a>
|
||||
<a class="btn btn-outline-primary" asp-controller="Writer" asp-action="Chapter" asp-route-id="@Model.Chapter.ChapterID">Chapter workflow</a>
|
||||
<a class="btn btn-primary" asp-controller="Scenes" asp-action="Create" asp-route-chapterId="@Model.Chapter.ChapterID">Add scene</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
</div>
|
||||
<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="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="Analytics" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Story health</a>
|
||||
<a asp-controller="Warnings" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Warnings</a>
|
||||
@ -37,6 +38,7 @@
|
||||
<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-primary" asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Timeline</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="PlotLines" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Plot lines</a>
|
||||
<a class="btn btn-outline-primary" asp-controller="PlotThreads" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID">Plot threads</a>
|
||||
|
||||
@ -63,6 +63,10 @@
|
||||
<a href="#inspector-timing">Time</a>
|
||||
<a href="#inspector-purpose">Purpose</a>
|
||||
<a href="#inspector-metrics">Metrics</a>
|
||||
<a href="#inspector-writer">Writer</a>
|
||||
<a href="#inspector-notes">Notes</a>
|
||||
<a href="#inspector-checklist">Checklist</a>
|
||||
<a href="#inspector-attachments">Attachments</a>
|
||||
<a href="#inspector-warnings">Warnings</a>
|
||||
<a href="#inspector-dependencies">Dependencies</a>
|
||||
<a href="#inspector-move">Move</a>
|
||||
@ -220,6 +224,223 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@if (TempData["WriterWorkspaceError"] is string writerWorkspaceError)
|
||||
{
|
||||
<div class="alert alert-warning">@writerWorkspaceError</div>
|
||||
}
|
||||
|
||||
<section class="inspector-section writer-workspace-section" data-section-title="Writer Workspace" data-section-id="inspector-writer">
|
||||
<div class="inspector-section-heading">
|
||||
<h3>Writer Workspace</h3>
|
||||
<a class="btn btn-outline-secondary btn-sm" asp-controller="Writer" asp-action="Chapter" asp-route-id="@Model.ChapterID">Chapter workflow</a>
|
||||
</div>
|
||||
<form asp-controller="Scenes" asp-action="SaveWorkflow" method="post" class="writer-workspace-form">
|
||||
<input type="hidden" name="SceneID" value="@Model.SceneID" />
|
||||
<input type="hidden" name="ReturnProjectID" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="ReturnBookID" value="@Model.ReturnBookID" />
|
||||
<div class="row g-2">
|
||||
<div class="col-sm-6">
|
||||
<label class="form-label" for="DraftStatus">Draft status</label>
|
||||
<select class="form-select form-select-sm" id="DraftStatus" name="DraftStatus" asp-items="Model.DraftStatusOptions"></select>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="form-label" for="Priority">Priority</label>
|
||||
<input class="form-control form-control-sm" id="Priority" name="Priority" type="number" min="1" max="10" value="@Model.Workflow.Priority" />
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="form-label" for="EstimatedWordCount">Estimated words</label>
|
||||
<input class="form-control form-control-sm" id="EstimatedWordCount" name="EstimatedWordCount" type="number" min="0" value="@Model.Workflow.EstimatedWordCount" />
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="form-label" for="ActualWordCount">Actual words</label>
|
||||
<input class="form-control form-control-sm" id="ActualWordCount" name="ActualWordCount" type="number" min="0" value="@Model.Workflow.ActualWordCount" />
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="form-label" for="DraftedDate">Drafted date</label>
|
||||
<input class="form-control form-control-sm" id="DraftedDate" name="DraftedDate" type="date" value="@Model.Workflow.DraftedDate?.ToString("yyyy-MM-dd")" />
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="form-label" for="LastWorkedOn">Last worked on</label>
|
||||
<input class="form-control form-control-sm" id="LastWorkedOn" name="LastWorkedOn" type="date" value="@Model.Workflow.LastWorkedOn?.ToString("yyyy-MM-dd")" />
|
||||
</div>
|
||||
<div class="col-12 writer-checkbox-grid">
|
||||
<label><input type="checkbox" name="ReadyForDraft" value="true" checked="@Model.Workflow.ReadyForDraft" /> Ready for draft</label>
|
||||
<label><input type="checkbox" name="ReadyForRevision" value="true" checked="@Model.Workflow.ReadyForRevision" /> Ready for revision</label>
|
||||
<label><input type="checkbox" name="ReadyForPolish" value="true" checked="@Model.Workflow.ReadyForPolish" /> Ready for polish</label>
|
||||
<label><input type="checkbox" name="IsBlocked" value="true" checked="@Model.Workflow.IsBlocked" /> Blocked</label>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label" for="BlockedReason">Blocked reason</label>
|
||||
<input class="form-control form-control-sm" id="BlockedReason" name="BlockedReason" value="@Model.Workflow.BlockedReason" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="button-row compact-buttons mt-2">
|
||||
<button class="btn btn-primary btn-sm" type="submit">Save workflow</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="inspector-section writer-notes-section" data-section-title="Scene Notes" data-section-id="inspector-notes">
|
||||
<h3>Scene Notes</h3>
|
||||
@if (!Model.Notes.Any())
|
||||
{
|
||||
<p class="muted">No working notes yet.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="writer-note-list">
|
||||
@foreach (var note in Model.Notes)
|
||||
{
|
||||
<details class="writer-mini-card" @(note.IsPinned ? "open" : "")>
|
||||
<summary>
|
||||
<span class="status-pill">@note.TypeName</span>
|
||||
<strong>@(string.IsNullOrWhiteSpace(note.NoteTitle) ? note.NoteText : note.NoteTitle)</strong>
|
||||
@if (note.IsPinned) { <span class="badge text-bg-light">Pinned</span> }
|
||||
@if (note.IsResolved) { <span class="badge text-bg-success">Resolved</span> }
|
||||
</summary>
|
||||
<form asp-controller="Scenes" asp-action="SaveNote" method="post" class="writer-edit-form">
|
||||
<input type="hidden" name="SceneNoteID" value="@note.SceneNoteID" />
|
||||
<input type="hidden" name="SceneID" value="@Model.SceneID" />
|
||||
<input type="hidden" name="ReturnProjectID" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="ReturnBookID" value="@Model.ReturnBookID" />
|
||||
<select class="form-select form-select-sm" name="SceneNoteTypeID">
|
||||
@foreach (var option in Model.SceneNoteTypeOptions)
|
||||
{
|
||||
<option value="@option.Value" selected="@(option.Value == note.SceneNoteTypeID.ToString())">@option.Text</option>
|
||||
}
|
||||
</select>
|
||||
<input class="form-control form-control-sm" name="NoteTitle" value="@note.NoteTitle" placeholder="Title" />
|
||||
<textarea class="form-control form-control-sm" name="NoteText" rows="3">@note.NoteText</textarea>
|
||||
<div class="writer-checkbox-grid">
|
||||
<label><input type="checkbox" name="IsPinned" value="true" checked="@note.IsPinned" /> Pinned</label>
|
||||
<label><input type="checkbox" name="IsResolved" value="true" checked="@note.IsResolved" /> Resolved</label>
|
||||
</div>
|
||||
<div class="button-row compact-buttons">
|
||||
<button class="btn btn-primary btn-sm" type="submit">Save note</button>
|
||||
</div>
|
||||
</form>
|
||||
<form asp-controller="Scenes" asp-action="DeleteNote" method="post" class="mt-1">
|
||||
<input type="hidden" name="id" value="@note.SceneNoteID" />
|
||||
<input type="hidden" name="sceneId" value="@Model.SceneID" />
|
||||
<input type="hidden" name="projectId" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="bookId" value="@Model.ReturnBookID" />
|
||||
<button class="btn btn-outline-danger btn-sm" type="submit">Remove note</button>
|
||||
</form>
|
||||
</details>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<form asp-controller="Scenes" asp-action="SaveNote" method="post" class="writer-add-form">
|
||||
<input type="hidden" name="SceneID" value="@Model.SceneID" />
|
||||
<input type="hidden" name="ReturnProjectID" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="ReturnBookID" value="@Model.ReturnBookID" />
|
||||
<select class="form-select form-select-sm" name="SceneNoteTypeID" asp-items="Model.SceneNoteTypeOptions"></select>
|
||||
<input class="form-control form-control-sm" name="NoteTitle" placeholder="Optional title" />
|
||||
<textarea class="form-control form-control-sm" name="NoteText" rows="3" placeholder="Add a drafting, revision, research, or TODO note"></textarea>
|
||||
<div class="writer-checkbox-grid">
|
||||
<label><input type="checkbox" name="IsPinned" value="true" /> Pin note</label>
|
||||
</div>
|
||||
<button class="btn btn-outline-primary btn-sm" type="submit">Add note</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="inspector-section writer-checklist-section" data-section-title="Scene Checklist" data-section-id="inspector-checklist">
|
||||
<h3>Scene Checklist</h3>
|
||||
<div class="writer-checklist">
|
||||
@foreach (var item in Model.ChecklistItems)
|
||||
{
|
||||
<form asp-controller="Scenes" asp-action="SaveChecklistItem" method="post" class="writer-checklist-row">
|
||||
<input type="hidden" name="SceneChecklistItemID" value="@item.SceneChecklistItemID" />
|
||||
<input type="hidden" name="SceneID" value="@Model.SceneID" />
|
||||
<input type="hidden" name="ReturnProjectID" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="ReturnBookID" value="@Model.ReturnBookID" />
|
||||
<input type="checkbox" name="IsCompleted" value="true" checked="@item.IsCompleted" />
|
||||
<input class="form-control form-control-sm" name="ItemText" value="@item.ItemText" />
|
||||
<button class="btn btn-outline-primary btn-sm" type="submit">Save</button>
|
||||
</form>
|
||||
<form asp-controller="Scenes" asp-action="DeleteChecklistItem" method="post" class="writer-remove-inline">
|
||||
<input type="hidden" name="id" value="@item.SceneChecklistItemID" />
|
||||
<input type="hidden" name="sceneId" value="@Model.SceneID" />
|
||||
<input type="hidden" name="projectId" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="bookId" value="@Model.ReturnBookID" />
|
||||
<button class="btn btn-outline-danger btn-sm" type="submit">Remove</button>
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
<form asp-controller="Scenes" asp-action="SaveChecklistItem" method="post" class="writer-add-form writer-add-inline">
|
||||
<input type="hidden" name="SceneID" value="@Model.SceneID" />
|
||||
<input type="hidden" name="ReturnProjectID" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="ReturnBookID" value="@Model.ReturnBookID" />
|
||||
<input class="form-control form-control-sm" name="ItemText" placeholder="Add checklist item" />
|
||||
<button class="btn btn-outline-primary btn-sm" type="submit">Add item</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="inspector-section writer-attachments-section" data-section-title="Attachments / Research" data-section-id="inspector-attachments">
|
||||
<h3>Attachments / Research</h3>
|
||||
@if (!Model.Attachments.Any())
|
||||
{
|
||||
<p class="muted">No scene references yet.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="writer-note-list">
|
||||
@foreach (var attachment in Model.Attachments)
|
||||
{
|
||||
<details class="writer-mini-card">
|
||||
<summary>
|
||||
<span class="status-pill">@attachment.TypeName</span>
|
||||
<strong>@attachment.Title</strong>
|
||||
</summary>
|
||||
<form asp-controller="Scenes" asp-action="SaveAttachment" method="post" class="writer-edit-form">
|
||||
<input type="hidden" name="SceneAttachmentID" value="@attachment.SceneAttachmentID" />
|
||||
<input type="hidden" name="SceneID" value="@Model.SceneID" />
|
||||
<input type="hidden" name="ReturnProjectID" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="ReturnBookID" value="@Model.ReturnBookID" />
|
||||
<select class="form-select form-select-sm" name="SceneAttachmentTypeID">
|
||||
@foreach (var option in Model.SceneAttachmentTypeOptions)
|
||||
{
|
||||
<option value="@option.Value" selected="@(option.Value == attachment.SceneAttachmentTypeID.ToString())">@option.Text</option>
|
||||
}
|
||||
</select>
|
||||
<input class="form-control form-control-sm" name="Title" value="@attachment.Title" />
|
||||
<input class="form-control form-control-sm" name="ExternalUrl" value="@attachment.ExternalUrl" placeholder="External URL" />
|
||||
<input class="form-control form-control-sm" name="FilePath" value="@attachment.FilePath" placeholder="File path" />
|
||||
<textarea class="form-control form-control-sm" name="Notes" rows="2">@attachment.Notes</textarea>
|
||||
<button class="btn btn-primary btn-sm" type="submit">Save attachment</button>
|
||||
</form>
|
||||
<form asp-controller="Scenes" asp-action="DeleteAttachment" method="post" class="mt-1">
|
||||
<input type="hidden" name="id" value="@attachment.SceneAttachmentID" />
|
||||
<input type="hidden" name="sceneId" value="@Model.SceneID" />
|
||||
<input type="hidden" name="projectId" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="bookId" value="@Model.ReturnBookID" />
|
||||
<button class="btn btn-outline-danger btn-sm" type="submit">Remove attachment</button>
|
||||
</form>
|
||||
@if (!string.IsNullOrWhiteSpace(attachment.ExternalUrl))
|
||||
{
|
||||
<a href="@attachment.ExternalUrl" target="_blank" rel="noopener">Open link</a>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(attachment.FilePath))
|
||||
{
|
||||
<p class="muted">@attachment.FilePath</p>
|
||||
}
|
||||
</details>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<form asp-controller="Scenes" asp-action="SaveAttachment" method="post" class="writer-add-form">
|
||||
<input type="hidden" name="SceneID" value="@Model.SceneID" />
|
||||
<input type="hidden" name="ReturnProjectID" value="@Model.ReturnProjectID" />
|
||||
<input type="hidden" name="ReturnBookID" value="@Model.ReturnBookID" />
|
||||
<select class="form-select form-select-sm" name="SceneAttachmentTypeID" asp-items="Model.SceneAttachmentTypeOptions"></select>
|
||||
<input class="form-control form-control-sm" name="Title" placeholder="Reference title" />
|
||||
<input class="form-control form-control-sm" name="ExternalUrl" placeholder="External URL" />
|
||||
<input class="form-control form-control-sm" name="FilePath" placeholder="File path" />
|
||||
<textarea class="form-control form-control-sm" name="Notes" rows="2" placeholder="Why this reference matters"></textarea>
|
||||
<button class="btn btn-outline-primary btn-sm" type="submit">Add attachment</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="inspector-section warning-inspector-section" data-section-title="Continuity Warnings" data-section-id="inspector-warnings">
|
||||
<div class="inspector-section-heading">
|
||||
<h3>Continuity Warnings</h3>
|
||||
|
||||
@ -23,6 +23,9 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Projects" asp-action="Index">Projects</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Writer" asp-action="Index">Writer Workspace</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">About</a>
|
||||
</li>
|
||||
|
||||
100
PlotLine/Views/Writer/Chapter.cshtml
Normal file
100
PlotLine/Views/Writer/Chapter.cshtml
Normal file
@ -0,0 +1,100 @@
|
||||
@model ChapterWorkflowViewModel
|
||||
@{
|
||||
ViewData["Title"] = $"Chapter Workflow - {Model.Chapter.ChapterTitle}";
|
||||
var blockedCount = Model.Scenes.Count(x => x.IsBlocked);
|
||||
var readyDraftCount = Model.Scenes.Count(x => x.ReadyForDraft);
|
||||
var readyRevisionCount = Model.Scenes.Count(x => x.ReadyForRevision);
|
||||
var readyPolishCount = Model.Scenes.Count(x => x.ReadyForPolish);
|
||||
}
|
||||
|
||||
<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.Project.ProjectID">@Model.Project.ProjectName</a>
|
||||
<a asp-controller="Books" asp-action="Details" asp-route-id="@Model.Book.BookID">@Model.Book.BookTitle</a>
|
||||
<a asp-controller="Chapters" asp-action="Details" asp-route-id="@Model.Chapter.ChapterID">Chapter @Model.Chapter.ChapterNumber</a>
|
||||
<span>Workflow</span>
|
||||
</nav>
|
||||
|
||||
<div class="page-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Chapter workflow</p>
|
||||
<h1>Chapter @Model.Chapter.ChapterNumber: @Model.Chapter.ChapterTitle</h1>
|
||||
<p class="lead-text">Chapter intent, readiness, blockers, notes, and checklist progress.</p>
|
||||
</div>
|
||||
<div class="button-row">
|
||||
<a class="btn btn-outline-primary" asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.Book.BookID">Open timeline</a>
|
||||
<a class="btn btn-outline-secondary" asp-controller="Warnings" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.Book.BookID">Warnings</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="story-bible-section">
|
||||
<div class="story-bible-grid story-bible-grid-compact">
|
||||
<article class="story-bible-card"><h3>Ready to draft</h3><strong class="writer-kpi">@readyDraftCount</strong></article>
|
||||
<article class="story-bible-card"><h3>Ready to revise</h3><strong class="writer-kpi">@readyRevisionCount</strong></article>
|
||||
<article class="story-bible-card"><h3>Ready to polish</h3><strong class="writer-kpi">@readyPolishCount</strong></article>
|
||||
<article class="story-bible-card"><h3>Blocked</h3><strong class="writer-kpi">@blockedCount</strong></article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="story-bible-section">
|
||||
<div class="story-bible-section-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Intent</p>
|
||||
<h2>Chapter Goals</h2>
|
||||
</div>
|
||||
</div>
|
||||
<form asp-action="SaveChapterGoal" method="post" class="story-bible-card chapter-goal-form">
|
||||
<input type="hidden" name="ChapterGoalID" value="@Model.Goal.ChapterGoalID" />
|
||||
<input type="hidden" name="ChapterID" value="@Model.Chapter.ChapterID" />
|
||||
<label class="form-label">Goal summary</label>
|
||||
<textarea class="form-control" name="GoalSummary" rows="3">@Model.Goal.GoalSummary</textarea>
|
||||
<label class="form-label">Emotional goal</label>
|
||||
<input class="form-control" name="EmotionalGoal" value="@Model.Goal.EmotionalGoal" />
|
||||
<label class="form-label">Reader takeaway</label>
|
||||
<textarea class="form-control" name="ReaderTakeaway" rows="2">@Model.Goal.ReaderTakeaway</textarea>
|
||||
<label class="form-label">Must include</label>
|
||||
<textarea class="form-control" name="MustInclude" rows="3">@Model.Goal.MustInclude</textarea>
|
||||
<label class="form-label">Risks or concerns</label>
|
||||
<textarea class="form-control" name="RisksOrConcerns" rows="3">@Model.Goal.RisksOrConcerns</textarea>
|
||||
<button class="btn btn-primary mt-2" type="submit">Save chapter goals</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="story-bible-section">
|
||||
<div class="story-bible-section-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Scenes</p>
|
||||
<h2>Workflow Summary</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="writer-queue-list">
|
||||
@foreach (var scene in Model.Scenes)
|
||||
{
|
||||
<article class="writer-queue-card">
|
||||
<div class="writer-queue-title">
|
||||
<h3>Scene @scene.SceneNumber: @scene.SceneTitle</h3>
|
||||
<span class="status-pill">@scene.DraftStatus</span>
|
||||
</div>
|
||||
<div class="story-bible-meta">
|
||||
@if (scene.Priority.HasValue) { <span>Priority @scene.Priority</span> }
|
||||
<span>@scene.WarningCount warnings</span>
|
||||
<span>@scene.RemainingChecklistCount checklist remaining</span>
|
||||
<span>@scene.UnresolvedNoteCount open notes</span>
|
||||
@if (scene.ReadyForDraft) { <span>Ready for draft</span> }
|
||||
@if (scene.ReadyForRevision) { <span>Ready for revision</span> }
|
||||
@if (scene.ReadyForPolish) { <span>Ready for polish</span> }
|
||||
@if (scene.IsBlocked) { <span>Blocked</span> }
|
||||
</div>
|
||||
@if (!string.IsNullOrWhiteSpace(scene.BlockedReason))
|
||||
{
|
||||
<p class="muted">@scene.BlockedReason</p>
|
||||
}
|
||||
<div class="story-bible-actions">
|
||||
<a asp-controller="Scenes" asp-action="Edit" asp-route-id="@scene.SceneID">Open scene</a>
|
||||
<a asp-controller="Timeline" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.Book.BookID" asp-route-selectedSceneId="@scene.SceneID">Timeline</a>
|
||||
<a asp-controller="Warnings" asp-action="Index" asp-route-projectId="@Model.Project.ProjectID" asp-route-bookId="@Model.Book.BookID" asp-route-sceneId="@scene.SceneID">Warnings</a>
|
||||
</div>
|
||||
</article>
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
91
PlotLine/Views/Writer/Index.cshtml
Normal file
91
PlotLine/Views/Writer/Index.cshtml
Normal file
@ -0,0 +1,91 @@
|
||||
@model WriterDashboardViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Writer Workspace";
|
||||
}
|
||||
|
||||
<div class="page-heading writer-dashboard-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Today view</p>
|
||||
<h1>Writer Workspace</h1>
|
||||
<p class="lead-text">A practical control room for drafting, revision, polish, and story readiness.</p>
|
||||
</div>
|
||||
<form asp-action="Index" method="get" class="story-bible-search">
|
||||
<select class="form-select" name="projectId" asp-items="Model.ProjectOptions">
|
||||
<option value="">All projects</option>
|
||||
</select>
|
||||
<button class="btn btn-primary" type="submit">Focus</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="writer-dashboard-grid">
|
||||
<section class="writer-dashboard-panel">
|
||||
<div class="story-bible-section-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Write Next</p>
|
||||
<h2>Continue Writing</h2>
|
||||
</div>
|
||||
<span class="soft-count">@Model.ContinueWriting.Count scenes</span>
|
||||
</div>
|
||||
<partial name="_WriterSceneQueue" model="Model.ContinueWriting" />
|
||||
</section>
|
||||
|
||||
<section class="writer-dashboard-panel">
|
||||
<div class="story-bible-section-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Practical blockers</p>
|
||||
<h2>Needs Attention</h2>
|
||||
</div>
|
||||
<span class="soft-count">@Model.NeedsAttention.Count scenes</span>
|
||||
</div>
|
||||
<partial name="_WriterSceneQueue" model="Model.NeedsAttention" />
|
||||
</section>
|
||||
|
||||
<section class="writer-dashboard-panel">
|
||||
<div class="story-bible-section-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Revision</p>
|
||||
<h2>Revision Queue</h2>
|
||||
</div>
|
||||
<span class="soft-count">@Model.RevisionQueue.Count scenes</span>
|
||||
</div>
|
||||
<partial name="_WriterSceneQueue" model="Model.RevisionQueue" />
|
||||
</section>
|
||||
|
||||
<section class="writer-dashboard-panel">
|
||||
<div class="story-bible-section-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Final pass</p>
|
||||
<h2>Polishing Queue</h2>
|
||||
</div>
|
||||
<span class="soft-count">@Model.PolishingQueue.Count scenes</span>
|
||||
</div>
|
||||
<partial name="_WriterSceneQueue" model="Model.PolishingQueue" />
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="story-bible-section">
|
||||
<div class="story-bible-section-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Story health</p>
|
||||
<h2>Reminders</h2>
|
||||
</div>
|
||||
<span class="soft-count">@Model.StoryHealthReminders.Count items</span>
|
||||
</div>
|
||||
<div class="attention-list">
|
||||
@foreach (var reminder in Model.StoryHealthReminders)
|
||||
{
|
||||
<article>
|
||||
<span class="badge text-bg-light">@reminder.Category</span>
|
||||
<strong>@reminder.Title</strong>
|
||||
@if (!string.IsNullOrWhiteSpace(reminder.Detail))
|
||||
{
|
||||
<p>@reminder.Detail</p>
|
||||
}
|
||||
@if (reminder.SceneID.HasValue)
|
||||
{
|
||||
<a asp-controller="Scenes" asp-action="Edit" asp-route-id="@reminder.SceneID">Open scene</a>
|
||||
}
|
||||
</article>
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
51
PlotLine/Views/Writer/_WriterSceneQueue.cshtml
Normal file
51
PlotLine/Views/Writer/_WriterSceneQueue.cshtml
Normal file
@ -0,0 +1,51 @@
|
||||
@model IReadOnlyList<WriterDashboardScene>
|
||||
|
||||
@if (!Model.Any())
|
||||
{
|
||||
<p class="muted">Nothing in this queue.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="writer-queue-list">
|
||||
@foreach (var scene in Model)
|
||||
{
|
||||
<article class="writer-queue-card">
|
||||
<div class="writer-queue-title">
|
||||
<div>
|
||||
<span class="eyebrow">@scene.BookTitle / Chapter @scene.ChapterNumber</span>
|
||||
<h3>Scene @scene.SceneNumber: @scene.SceneTitle</h3>
|
||||
</div>
|
||||
<span class="status-pill">@scene.DraftStatus</span>
|
||||
</div>
|
||||
@if (!string.IsNullOrWhiteSpace(scene.Summary))
|
||||
{
|
||||
<p>@scene.Summary</p>
|
||||
}
|
||||
<div class="story-bible-meta">
|
||||
@if (scene.Priority.HasValue) { <span>Priority @scene.Priority</span> }
|
||||
<span>@scene.WarningCount warnings</span>
|
||||
<span>@scene.RemainingChecklistCount checklist remaining</span>
|
||||
<span>@scene.UnresolvedNoteCount open notes</span>
|
||||
@if (scene.IsBlocked) { <span>Blocked</span> }
|
||||
</div>
|
||||
@if (!string.IsNullOrWhiteSpace(scene.ImportantThreads))
|
||||
{
|
||||
<p class="muted"><strong>Important:</strong> @scene.ImportantThreads</p>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(scene.PinnedNotes))
|
||||
{
|
||||
<p class="muted"><strong>Notes:</strong> @scene.PinnedNotes</p>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(scene.BlockedReason))
|
||||
{
|
||||
<p class="muted"><strong>Blocked:</strong> @scene.BlockedReason</p>
|
||||
}
|
||||
<div class="story-bible-actions">
|
||||
<a asp-controller="Scenes" asp-action="Edit" asp-route-id="@scene.SceneID">Open scene</a>
|
||||
<a asp-controller="Timeline" asp-action="Index" asp-route-projectId="@scene.ProjectID" asp-route-bookId="@scene.BookID" asp-route-selectedSceneId="@scene.SceneID">Timeline</a>
|
||||
<a asp-controller="Warnings" asp-action="Index" asp-route-projectId="@scene.ProjectID" asp-route-bookId="@scene.BookID" asp-route-sceneId="@scene.SceneID">Warnings</a>
|
||||
</div>
|
||||
</article>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@ -2594,6 +2594,121 @@ body.dragging-location [data-drag-type="location"] {
|
||||
color: var(--plotline-muted);
|
||||
}
|
||||
|
||||
.writer-workspace-form,
|
||||
.writer-add-form,
|
||||
.writer-edit-form,
|
||||
.chapter-goal-form {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.writer-checkbox-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px 14px;
|
||||
}
|
||||
|
||||
.writer-checkbox-grid label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: var(--plotline-muted);
|
||||
font-size: 0.86rem;
|
||||
font-weight: 650;
|
||||
}
|
||||
|
||||
.writer-note-list,
|
||||
.writer-queue-list {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.writer-mini-card {
|
||||
border: 1px solid var(--plotline-line);
|
||||
border-radius: 12px;
|
||||
padding: 10px;
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
}
|
||||
|
||||
.writer-mini-card summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.writer-mini-card summary strong {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.writer-checklist {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.writer-checklist-row,
|
||||
.writer-add-inline {
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.writer-remove-inline {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
margin: -2px 0 4px;
|
||||
}
|
||||
|
||||
.writer-dashboard-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
margin-bottom: 26px;
|
||||
}
|
||||
|
||||
.writer-dashboard-panel {
|
||||
border: 1px solid var(--plotline-line);
|
||||
border-radius: 14px;
|
||||
padding: 14px;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
box-shadow: 0 14px 34px rgba(36, 32, 26, 0.05);
|
||||
}
|
||||
|
||||
.writer-queue-card {
|
||||
border: 1px solid var(--plotline-line);
|
||||
border-radius: 12px;
|
||||
padding: 12px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.writer-queue-card h3 {
|
||||
margin: 0;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.writer-queue-card p {
|
||||
margin: 8px 0 0;
|
||||
color: var(--plotline-muted);
|
||||
}
|
||||
|
||||
.writer-queue-title {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.writer-kpi {
|
||||
display: block;
|
||||
color: var(--plotline-accent);
|
||||
font-size: 2.2rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.plotline-shell {
|
||||
padding-left: 14px;
|
||||
@ -2625,6 +2740,15 @@ body.dragging-location [data-drag-type="location"] {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.writer-dashboard-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.writer-checklist-row,
|
||||
.writer-add-inline {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.attention-list p {
|
||||
grid-column: auto;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user