add update node

This commit is contained in:
Владимир Фёдоров 2025-12-07 03:41:45 +07:00
parent 2192bf4e77
commit 49c415d4b9
13 changed files with 538 additions and 236 deletions

View File

@ -83,6 +83,13 @@ service EveningDetective {
get: "/graph"
};
}
rpc UpdateNode(UpdateNodeReq) returns (UpdateNodeRsp) {
option (google.api.http) = {
put: "/graph/nodes",
body: "*"
};
}
}
message PingReq {}
@ -189,24 +196,32 @@ message DownloadTeamsQrCodesFileRsp {
message GetGraphReq {}
message GetGraphRsp {
repeated Node nodes = 1;
repeated GraphNode nodes = 1;
repeated Edge edges = 2;
int32 countNodes = 3;
int32 countEdges = 4;
message Node {
int32 id = 1;
string label = 2;
string name = 3;
string text = 4;
repeated Application applications = 5;
}
message Edge {
int32 from = 1;
int32 to = 2;
string arrows = 3;
}
message Application {
string name = 1;
}
}
message UpdateNodeReq {
GraphNode node = 1;
}
message UpdateNodeRsp {}
message GraphNode {
int32 id = 1;
string label = 2;
string name = 3;
string text = 4;
repeated GraphApplication applications = 5;
}
message GraphApplication {
string name = 1;
}

View File

@ -128,7 +128,7 @@ func main() {
func cors(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PATCH, DELETE")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization, ResponseType, X-Id, X-Password")
if r.Method == "OPTIONS" {
return

View File

@ -1 +1 @@
:root{--vt-c-white: #ffffff;--vt-c-white-soft: #f8f8f8;--vt-c-white-mute: #f2f2f2;--vt-c-black: #181818;--vt-c-black-soft: #222222;--vt-c-black-mute: #282828;--vt-c-indigo: #2c3e50;--vt-c-divider-light-1: rgba(60, 60, 60, .29);--vt-c-divider-light-2: rgba(60, 60, 60, .12);--vt-c-divider-dark-1: rgba(84, 84, 84, .65);--vt-c-divider-dark-2: rgba(84, 84, 84, .48);--vt-c-text-light-1: var(--vt-c-indigo);--vt-c-text-light-2: rgba(60, 60, 60, .66);--vt-c-text-dark-1: var(--vt-c-white);--vt-c-text-dark-2: rgba(235, 235, 235, .64);--main-color: rgba(34, 50, 60, 1);--second-color: rgb(97, 74, 22);--main-back-color: rgba(240, 240, 240, 1);--main-back-item-color: rgba(254, 254, 254, 1)}:root{--color-background: var(--vt-c-white);--color-background-soft: var(--vt-c-white-soft);--color-background-mute: var(--vt-c-white-mute);--color-border: var(--vt-c-divider-light-2);--color-border-hover: var(--vt-c-divider-light-1);--color-heading: var(--vt-c-text-light-1);--color-text: var(--vt-c-text-light-1);--section-gap: 160px}*,*:before,*:after{box-sizing:border-box;margin:0;font-weight:400}body{min-height:100dvh;color:var(--color-text);background:var(--main-back-color);transition:color .5s,background-color .5s;line-height:1.6;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:15px;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.input-custom{width:100%;box-sizing:border-box;margin-bottom:15px}.button-custom{margin-left:auto;background-color:var(--main-color);font-weight:600;color:#fff}.button-custom-inline{margin:10px;background-color:var(--main-color);font-weight:600;color:#fff;padding:6px 8px;border:1px solid #ddd;border-radius:15px;font-size:14px}.button-custom:hover,.button-custom-inline:hover{background-color:var(--second-color)}.input-custom,.button-custom{padding:12px 16px;border:1px solid #ddd;border-radius:15px;font-size:16px}.button-container{display:flex}.center-message{display:flex;justify-content:center;align-items:center;height:calc(100dvh - 100px);text-align:center}.qr[data-v-666b8d35]{position:absolute;top:130px;right:30px;text-align:center;width:120px}.header-block[data-v-5b6894ef]{background-color:var(--main-color);font-size:large;color:#fff;vertical-align:middle;padding:10px 0 10px 16px;font-weight:700}.buttons-block[data-v-27835e5c]{padding-top:5px}.button-menu[data-v-27835e5c]{margin:5px 10px 5px 0}table[data-v-27835e5c]{width:700px;border-collapse:collapse;margin:30px auto;border:1px solid #444444}th[data-v-27835e5c],td[data-v-27835e5c]{padding:12px;text-align:left}th[data-v-27835e5c]{background-color:var(--main-color);color:#fff;font-weight:700}tr[data-v-27835e5c]:nth-child(odd){background-color:#efefef}tr[data-v-27835e5c]:nth-child(2n){background-color:#fff}tr[data-v-27835e5c]:hover{background-color:#cfcfcf}.time[data-v-27835e5c]{white-space:nowrap}.team-name[data-v-27835e5c]{font-weight:600}.link-button[data-v-27835e5c]{display:inline;border:none;background:none;padding:0;margin:0;font:inherit;cursor:pointer;color:var(--main-color);text-decoration:underline;font-weight:600;-webkit-appearance:none;-moz-appearance:none;appearance:none;line-height:inherit;text-align:left}.link-button[data-v-27835e5c]:hover{color:var(--second-color);text-decoration:none}.link-button[data-v-27835e5c]:active{color:#036}.link-button[data-v-27835e5c]:focus{outline:none;text-decoration:none;box-shadow:0 0 0 2px #0066cc4d}.form-block[data-v-27835e5c]{width:700px;margin:0 auto}a[data-v-27835e5c]{color:var(--second-color);text-decoration:none;transition:all .2s ease;cursor:pointer}a[data-v-27835e5c]:hover{text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:3px}a[data-v-27835e5c]:focus-visible{outline:2px solid #3182ce;outline-offset:2px;border-radius:2px}a[disabled][data-v-27835e5c]{color:#a0aec0;pointer-events:none;cursor:not-allowed}.button-container[data-v-27835e5c]{margin-bottom:30px}.cell-center[data-v-27835e5c]{text-align:center}.graph-container[data-v-22fb1d18]{width:100%;height:calc(100vh - 50px);border:1px solid #e0e0e0;border-radius:8px}.nodes-container[data-v-22fb1d18]{position:fixed;left:5px;top:55px;height:calc(100vh - 100px);padding:10px 20px}.edit-node-container[data-v-22fb1d18]{position:fixed;right:5px;top:55px;height:calc(100vh - 100px);padding:10px 20px;max-width:300px}.node-select-button[data-v-22fb1d18]{color:#373737}.node-select-button[data-v-22fb1d18]:hover{font-weight:700;cursor:pointer}.selected-node[data-v-22fb1d18]{font-weight:700;color:#960000;cursor:pointer}
:root{--vt-c-white: #ffffff;--vt-c-white-soft: #f8f8f8;--vt-c-white-mute: #f2f2f2;--vt-c-black: #181818;--vt-c-black-soft: #222222;--vt-c-black-mute: #282828;--vt-c-indigo: #2c3e50;--vt-c-divider-light-1: rgba(60, 60, 60, .29);--vt-c-divider-light-2: rgba(60, 60, 60, .12);--vt-c-divider-dark-1: rgba(84, 84, 84, .65);--vt-c-divider-dark-2: rgba(84, 84, 84, .48);--vt-c-text-light-1: var(--vt-c-indigo);--vt-c-text-light-2: rgba(60, 60, 60, .66);--vt-c-text-dark-1: var(--vt-c-white);--vt-c-text-dark-2: rgba(235, 235, 235, .64);--main-color: rgba(34, 50, 60, 1);--second-color: rgb(97, 74, 22);--main-back-color: rgba(240, 240, 240, 1);--main-back-item-color: rgba(254, 254, 254, 1)}:root{--color-background: var(--vt-c-white);--color-background-soft: var(--vt-c-white-soft);--color-background-mute: var(--vt-c-white-mute);--color-border: var(--vt-c-divider-light-2);--color-border-hover: var(--vt-c-divider-light-1);--color-heading: var(--vt-c-text-light-1);--color-text: var(--vt-c-text-light-1);--section-gap: 160px}*,*:before,*:after{box-sizing:border-box;margin:0;font-weight:400}body{min-height:100dvh;color:var(--color-text);background:var(--main-back-color);transition:color .5s,background-color .5s;line-height:1.6;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:15px;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.input-custom{width:100%;box-sizing:border-box;margin-bottom:15px}.button-custom{margin-left:auto;background-color:var(--main-color);font-weight:600;color:#fff}.button-custom-inline{margin:10px;background-color:var(--main-color);font-weight:600;color:#fff;padding:6px 8px;border:1px solid #ddd;border-radius:15px;font-size:14px}.button-custom:hover,.button-custom-inline:hover{background-color:var(--second-color)}.input-custom,.button-custom{padding:12px 16px;border:1px solid #ddd;border-radius:15px;font-size:16px}.button-container{display:flex}.center-message{display:flex;justify-content:center;align-items:center;height:calc(100dvh - 100px);text-align:center}.qr[data-v-666b8d35]{position:absolute;top:130px;right:30px;text-align:center;width:120px}.header-block[data-v-5b6894ef]{background-color:var(--main-color);font-size:large;color:#fff;vertical-align:middle;padding:10px 0 10px 16px;font-weight:700}.buttons-block[data-v-27835e5c]{padding-top:5px}.button-menu[data-v-27835e5c]{margin:5px 10px 5px 0}table[data-v-27835e5c]{width:700px;border-collapse:collapse;margin:30px auto;border:1px solid #444444}th[data-v-27835e5c],td[data-v-27835e5c]{padding:12px;text-align:left}th[data-v-27835e5c]{background-color:var(--main-color);color:#fff;font-weight:700}tr[data-v-27835e5c]:nth-child(odd){background-color:#efefef}tr[data-v-27835e5c]:nth-child(2n){background-color:#fff}tr[data-v-27835e5c]:hover{background-color:#cfcfcf}.time[data-v-27835e5c]{white-space:nowrap}.team-name[data-v-27835e5c]{font-weight:600}.link-button[data-v-27835e5c]{display:inline;border:none;background:none;padding:0;margin:0;font:inherit;cursor:pointer;color:var(--main-color);text-decoration:underline;font-weight:600;-webkit-appearance:none;-moz-appearance:none;appearance:none;line-height:inherit;text-align:left}.link-button[data-v-27835e5c]:hover{color:var(--second-color);text-decoration:none}.link-button[data-v-27835e5c]:active{color:#036}.link-button[data-v-27835e5c]:focus{outline:none;text-decoration:none;box-shadow:0 0 0 2px #0066cc4d}.form-block[data-v-27835e5c]{width:700px;margin:0 auto}a[data-v-27835e5c]{color:var(--second-color);text-decoration:none;transition:all .2s ease;cursor:pointer}a[data-v-27835e5c]:hover{text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:3px}a[data-v-27835e5c]:focus-visible{outline:2px solid #3182ce;outline-offset:2px;border-radius:2px}a[disabled][data-v-27835e5c]{color:#a0aec0;pointer-events:none;cursor:not-allowed}.button-container[data-v-27835e5c]{margin-bottom:30px}.cell-center[data-v-27835e5c]{text-align:center}.graph-container[data-v-06ee41bb]{width:100%;height:calc(100vh - 50px);border:1px solid #e0e0e0;border-radius:8px}.nodes-container[data-v-06ee41bb]{position:fixed;left:5px;top:55px;height:calc(100vh - 100px);padding:10px 20px}.edit-node-container[data-v-06ee41bb]{position:fixed;right:5px;top:55px;height:calc(100vh - 100px);padding:10px 20px;min-width:350px;max-width:400px}.node-select-button[data-v-06ee41bb]{color:#373737}.node-select-button[data-v-06ee41bb]:hover{font-weight:700;cursor:pointer}.selected-node[data-v-06ee41bb]{font-weight:700;color:#960000;cursor:pointer}.node-text-edit-field[data-v-06ee41bb]{padding:7px;margin:5px 0;width:100%}.node-edit-save-button[data-v-06ee41bb]{padding:3px 7px;margin:5px;background-color:#fff;border-radius:7px;border:1px solid #373737}.node-edit-save-button[data-v-06ee41bb]:hover{background-color:#ddd;cursor:pointer}.hr[data-v-06ee41bb]{margin:10px 0}

View File

@ -5,8 +5,8 @@
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ВД Админка</title>
<script type="module" crossorigin src="/assets/index-C6nQe7QU.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DQOm-aLN.css">
<script type="module" crossorigin src="/assets/index-DY0mDz-m.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-1rBZ50JZ.css">
</head>
<body>
<div id="app"></div>

View File

@ -44,7 +44,7 @@
{
"code": "М",
"name": "Медпункт",
"text": "Небольшое побелено-голубое здание в тени сосен. Внутри приемная с выцветшими плакатами про “чистые руки” и “опасность клещей”, изолятор с двумя койками за занавеской, а дальше общий душ и туалет. На столе стоят 3 кружки из-под чая. Печенье “Юбилейное” в открытой пачке. Медицинская карта с последней записью: “22:30 23.08.99 Волкова С. (отряд “Орлы”) жалобы на температуру и тошноту. Диагноз: пищевое отравление?” В мусорном ведре вы замечаете упаковку от таблетки, 3 пакетика чая и использованный презерватив. Слабый аромат духов дешевый, сладкий, явно не медицинский."
"text": "Небольшое побелено-голубое здание в тени сосен. Внутри приемная с выцветшими плакатами про “чистые руки” и “опасность клещей”, изолятор с двумя койками за занавеской, а дальше общий душ и туалет. На столе стоят 3 кружки из-под чая. Печенье “Юбилейное” в открытой пачке. Медицинская карта с последней записью: “22:30 23.08.99 Волкова С. (отряд “Орлы”)([O-4]) жалобы на температуру и тошноту. Диагноз: пищевое отравление?” В мусорном ведре вы замечаете упаковку от таблетки, 3 пакетика чая и использованный презерватив. Слабый аромат духов дешевый, сладкий, явно не медицинский."
},
{
"code": "O-1",
@ -54,17 +54,17 @@
{
"code": "O-2",
"name": "Отряд 2",
"text": "Тени от сосен за окном рисуют на стенах полосатые узоры. Зайдя внутрь здания, вы замечаете одного из вожатых — Кирилла. Заведя разговор о произошедшем, вы по секрету узнаете, что его напарница Даша бегает на свиданки с вожатым первого отряда Максимом. Больше ничего необычного вы не заметили."
"text": "Тени от сосен за окном рисуют на стенах полосатые узоры. Зайдя внутрь здания, вы замечаете одного из вожатых — Кирилла([КЛ]). Заведя разговор о произошедшем, вы по секрету узнаете, что его напарница Даша([ДО]) бегает на свиданки с вожатым первого отряда Максимом([МК]). Больше ничего необычного вы не заметили."
},
{
"code": "O-3",
"name": "Отряд 3",
"text": "Приближаясь, Вы осматриваете кирпичное здание с нарисованным сбоку здания мультяшным героем. Переводя взгляд в окно, вы видите детей, разбившихся на группки: кто-то рисует, кто-то бегает, а кто-то просто сидит в сторонке. \n«Вы тоже за тем, что пропало?» — раздаётся голос за спиной. Обернувшись, вы видите мальчика лет 12 с слишком взрослым взглядом. «Лёха говорит, что если что — искать надо в лисах. Только он не договорил... что именно.» Он нервно оглядывается и исчезает за углом, оставив вас с новой загадкой и ощущением, что за вами уже наблюдают."
"text": "Приближаясь, Вы осматриваете кирпичное здание с нарисованным сбоку здания мультяшным героем. Переводя взгляд в окно, вы видите детей, разбившихся на группки: кто-то рисует, кто-то бегает, а кто-то просто сидит в сторонке. \n«Вы тоже за тем, что пропало?» — раздаётся голос за спиной. Обернувшись, вы видите мальчика лет 12 с слишком взрослым взглядом. «Лёха говорит, что если что — искать надо в лисах([О-2]). Только он не договорил... что именно.» Он нервно оглядывается и исчезает за углом, оставив вас с новой загадкой и ощущением, что за вами уже наблюдают."
},
{
"code": "O-4",
"name": "Отряд 4",
"text": "У входа в отряд вы видите десятки пар обуви, аккуратно выставленных в ряд. Среди них вы сразу замечаете кроссовки с характерным зигзагообразным протектором, слегка запачканные грязью и... чем-то тёмным у носка. «Это Катины!» — оживляется девочка с косичками, тыча пальцем в обувь. — «Она их всегда носит, даже когда дождь!»"
"text": "У входа в отряд вы видите десятки пар обуви, аккуратно выставленных в ряд. Среди них вы сразу замечаете кроссовки с характерным зигзагообразным протектором, слегка запачканные грязью и... чем-то тёмным у носка. «Это Катины!»([КС]) — оживляется девочка с косичками, тыча пальцем в обувь. — «Она их всегда носит, даже когда дождь!»"
},
{
"code": "П",
@ -79,7 +79,7 @@
{
"code": "С-2",
"name": "Стадион",
"text": "На стадионе вы встречаете детей 3 и 4 отрядов. Вы интересуетесь, почему они не собирают вещи. Вам рассказывают, что их вожатые самые классные на земле, они приучили их к спорту — каждое утро они даже бегали с Катей вокруг стадиона и водонапорной вышки. Но сегодня последний день и Катя почему-то отправила их играть в волейбол, а бегать запретила."
"text": "На стадионе вы встречаете детей 3([О-3]) и 4([О-4]) отрядов. Вы интересуетесь, почему они не собирают вещи. Вам рассказывают, что их вожатые самые классные на земле, они приучили их к спорту — каждое утро они даже бегали с Катей([КС]) вокруг стадиона и водонапорной вышки. Но сегодня последний день и Катя почему-то отправила их играть в волейбол, а бегать запретила."
},
{
"code": "Т",
@ -95,12 +95,12 @@
{
"code": "МК",
"name": "Макс Крутов",
"text": "Перед вами парень в рваных джинсах и черной футболке, похожий на музыканта. Говорит, что был в душе вчера во время дискотеки: «Тёма был на дискотеке, а наши все вчера на медляках отжигали. Ну, я и решил помыться. Пока в душ шёл у администрации у Лехи сигарету и стрельнул. Поговорили немного, о чем я вам не могу сказать. Потом мы заметили за туалетом какие-то шорохи, Леха решил проверить, сказал, что за одно и обход сделает, якобы лишним не будет, ответственный наш» — Пока он это рассказывал мимо проходил директор — «Смотрите наш броненосец пиджак скинул, а я думал это его кожа!»."
"text": "Перед вами парень в рваных джинсах и черной футболке, похожий на музыканта. Говорит, что был в душе вчера во время дискотеки: «Тёма([АК]) был на дискотеке, а наши все вчера на медляках отжигали. Ну, я и решил помыться. Пока в душ шёл у администрации у Лехи сигарету и стрельнул. Поговорили немного, о чем я вам не могу сказать. Потом мы заметили за туалетом какие-то шорохи, Леха решил проверить, сказал, что за одно и обход сделает, якобы лишним не будет, ответственный наш» — Пока он это рассказывал мимо проходил директор — «Смотрите наш броненосец пиджак скинул, а я думал это его кожа!»."
},
{
"code": "АК",
"name": "Артём Ковалёв",
"text": "«Я следил за детьми в клубе, даже драку девочек разнял — ребята утром подслушали ссору Лехи с Алиной и поддерживали разные стороны, как видите очень яро. Макс отпросился в душ, с парнями вчера спортом был занят весь день»."
"text": "«Я следил за детьми в клубе, даже драку девочек разнял — ребята утром подслушали ссору Лехи с Алиной([АЗ]) и поддерживали разные стороны, как видите очень яро. Макс([МК]) отпросился в душ, с парнями вчера спортом был занят весь день»."
},
{
"code": "ДО",
@ -146,12 +146,12 @@
{
"code": "СС",
"name": "Сергей Смирнов",
"text": "Вы подошли к мужчине среднего роста в спортивном костюме: «Вечером телевизор смотрел, музыка долбила спать не давала. Петрович([ВПБ]) заходил, мы досмотрели “музыкальный ринг” да и побёг он. На дискотеки я не ходок, да и Лёха сказал помощь не нужна. За день набегался, дел много и не только своих, там помоги, сям помоги, никто ничего не может, вот и помогаю. Устаю, возраст как никак. Петрович попросил, вчера помочь с вывозом мусора, с тех пор в коморке и сидел. Лёху видел последний раз в воскресенье, он сказал зарядку не проводить пущай дети поспят»."
"text": "Вы подошли к мужчине среднего роста в спортивном костюме: «Вечером телевизор смотрел, музыка долбила спать не давала. Петрович([ВПБ]) заходил, мы досмотрели “музыкальный ринг” да и побёг он. На дискотеки я не ходок, да и Лёха сказал помощь не нужна. За день набегался, дел много и не только своих, там помоги, сям помоги, никто ничего не может, вот и помогаю. Устаю, возраст как никак. Петрович попросил, вчера помочь с вывозом мусора, с тех пор в коморке([К-3]) и сидел. Лёху видел последний раз в воскресенье, он сказал зарядку не проводить пущай дети поспят»."
},
{
"code": "ВПБ",
"name": "Виктор Петрович Белов",
"text": "«У меня свой режим: завтрак в 9 утра, вынос мусора в 9 вечера, в 11 вечера обход. Всю дискотеку Лёха сидел в администрации, как с концерта пришел, так и не выходил. В пол десятого я до клуба отходил проверить все ли спокойно во время дискотеки, проверил все и за клубом, площадь посмотрел — минут 30 заняло. Фонари давно у клуба не работают, пришлось с фонариком везде лазить. Тело обнаружил уже на обходе — очень перепугался и сразу в администрацию побежал».",
"text": "«У меня свой режим: завтрак в 9 утра, вынос мусора в 9 вечера, в 11 вечера обход. Всю дискотеку Лёха сидел в администрации([А]), как с концерта пришел, так и не выходил. В пол десятого я до клуба([К-1]) отходил проверить все ли спокойно во время дискотеки, проверил все и за клубом, площадь посмотрел — минут 30 заняло. Фонари давно у клуба не работают, пришлось с фонариком везде лазить. Тело обнаружил уже на обходе — очень перепугался и сразу в администрацию побежал».",
"applications": [{ "name": "Карта лагеря" }]
}
]

View File

@ -67,3 +67,7 @@ func (s *Server) DownloadTeamsQrCodesFile(ctx context.Context, req *proto.Downlo
func (s *Server) GetGraph(ctx context.Context, req *proto.GetGraphReq) (*proto.GetGraphRsp, error) {
return s.services.GetGraph(ctx, req)
}
func (s *Server) UpdateNode(ctx context.Context, req *proto.UpdateNodeReq) (*proto.UpdateNodeRsp, error) {
return s.services.UpdateNode(ctx, req)
}

View File

@ -187,7 +187,7 @@ func (s *Services) AddTeams(ctx context.Context, req *proto.AddTeamsReq) (*proto
}
func (s *Services) DownloadTeamsQrCodesFile(ctx context.Context, req *proto.DownloadTeamsQrCodesFileReq) (*proto.DownloadTeamsQrCodesFileRsp, error) {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
defer cancel()
teams, err := s.repository.GetTeams(ctx)
if err != nil {
@ -200,20 +200,43 @@ func (s *Services) DownloadTeamsQrCodesFile(ctx context.Context, req *proto.Down
return &proto.DownloadTeamsQrCodesFileRsp{Result: b}, nil
}
func (s *Services) UpdateNode(ctx context.Context, req *proto.UpdateNodeReq) (*proto.UpdateNodeRsp, error) {
applications := make([]*story_service.GraphApplication, 0, len(req.Node.Applications))
for _, application := range req.Node.Applications {
applications = append(
applications,
&story_service.GraphApplication{
Name: application.Name,
},
)
}
node := &story_service.GraphNode{
ID: req.Node.Id,
Label: req.Node.Label,
Name: req.Node.Name,
Text: req.Node.Text,
Applications: applications,
}
if err := s.storyService.UpdatePlace(node); err != nil {
return nil, err
}
return &proto.UpdateNodeRsp{}, nil
}
func (s *Services) GetGraph(ctx context.Context, req *proto.GetGraphReq) (*proto.GetGraphRsp, error) {
graph := s.storyService.GetGraph(ctx)
nodes := make([]*proto.GetGraphRsp_Node, 0, len(graph.Nodes))
nodes := make([]*proto.GraphNode, 0, len(graph.Nodes))
for _, node := range graph.Nodes {
applications := make([]*proto.GetGraphRsp_Application, 0, len(node.Applications))
applications := make([]*proto.GraphApplication, 0, len(node.Applications))
for _, application := range node.Applications {
applications = append(
applications,
&proto.GetGraphRsp_Application{
&proto.GraphApplication{
Name: application.Name,
},
)
}
nodes = append(nodes, &proto.GetGraphRsp_Node{
nodes = append(nodes, &proto.GraphNode{
Id: node.ID,
Label: node.Label,
Name: node.Name,

View File

@ -11,23 +11,24 @@ import (
)
type StoryService struct {
story *Story
filepath string
story *Story
}
func NewStoryService(filepath string) (*StoryService, error) {
s := &StoryService{}
if err := s.Load(filepath); err != nil {
s := &StoryService{filepath: filepath}
if err := s.Load(); err != nil {
return nil, err
}
return s, nil
}
func (s *StoryService) Load(filepath string) error {
data, err := os.ReadFile(filepath)
func (s *StoryService) Load() error {
data, err := os.ReadFile(s.filepath)
if err != nil {
return fmt.Errorf("story file %s not found", filepath)
return fmt.Errorf("story file %s not found", s.filepath)
}
log.Printf("load story from: %s", filepath)
log.Printf("load story from: %s", s.filepath)
story := &Story{}
if err := json.Unmarshal(data, story); err != nil {
return err
@ -36,19 +37,26 @@ func (s *StoryService) Load(filepath string) error {
return nil
}
func (s *StoryService) Save(filepath string) error {
func (s *StoryService) Save() error {
story := s.story
data, err := json.Marshal(story)
if err != nil {
return err
}
if err := os.WriteFile(filepath, data, 0x777); err != nil {
if err := os.WriteFile(s.filepath, data, 0x777); err != nil {
return err
}
log.Printf("save story to: %s", filepath)
log.Printf("save story to: %s", s.filepath)
return nil
}
func (s *StoryService) Update() error {
if err := s.Save(); err != nil {
return err
}
return s.Load()
}
func (s *StoryService) GetPlace(code string) *Place {
if strings.HasPrefix(code, "[") || strings.HasSuffix(code, "]") {
return &Place{
@ -77,6 +85,22 @@ func (s *StoryService) GetPlace(code string) *Place {
}
}
func (s *StoryService) UpdatePlace(node *GraphNode) error {
for i := range s.story.Places {
if s.story.Places[i].Code == node.Label {
s.story.Places[i] = &Place{
Code: s.story.Places[i].Code,
Name: node.Name,
Text: node.Text,
Applications: s.story.Places[i].Applications,
}
break
}
}
s.Update()
return nil
}
func (s *StoryService) GetGraph(ctx context.Context) *Graph {
m := make(map[string]int32, len(s.story.Places))
nodes := make([]*GraphNode, 0, len(s.story.Places))

View File

@ -1288,7 +1288,7 @@ func (*GetGraphReq) Descriptor() ([]byte, []int) {
type GetGraphRsp struct {
state protoimpl.MessageState `protogen:"open.v1"`
Nodes []*GetGraphRsp_Node `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
Nodes []*GraphNode `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
Edges []*GetGraphRsp_Edge `protobuf:"bytes,2,rep,name=edges,proto3" json:"edges,omitempty"`
CountNodes int32 `protobuf:"varint,3,opt,name=countNodes,proto3" json:"countNodes,omitempty"`
CountEdges int32 `protobuf:"varint,4,opt,name=countEdges,proto3" json:"countEdges,omitempty"`
@ -1326,7 +1326,7 @@ func (*GetGraphRsp) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{28}
}
func (x *GetGraphRsp) GetNodes() []*GetGraphRsp_Node {
func (x *GetGraphRsp) GetNodes() []*GraphNode {
if x != nil {
return x.Nodes
}
@ -1354,31 +1354,27 @@ func (x *GetGraphRsp) GetCountEdges() int32 {
return 0
}
type GetGraphRsp_Node struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"`
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
Text string `protobuf:"bytes,4,opt,name=text,proto3" json:"text,omitempty"`
Applications []*GetGraphRsp_Application `protobuf:"bytes,5,rep,name=applications,proto3" json:"applications,omitempty"`
type UpdateNodeReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Node *GraphNode `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetGraphRsp_Node) Reset() {
*x = GetGraphRsp_Node{}
func (x *UpdateNodeReq) Reset() {
*x = UpdateNodeReq{}
mi := &file_main_proto_msgTypes[29]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetGraphRsp_Node) String() string {
func (x *UpdateNodeReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetGraphRsp_Node) ProtoMessage() {}
func (*UpdateNodeReq) ProtoMessage() {}
func (x *GetGraphRsp_Node) ProtoReflect() protoreflect.Message {
func (x *UpdateNodeReq) ProtoReflect() protoreflect.Message {
mi := &file_main_proto_msgTypes[29]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -1390,46 +1386,174 @@ func (x *GetGraphRsp_Node) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
// Deprecated: Use GetGraphRsp_Node.ProtoReflect.Descriptor instead.
func (*GetGraphRsp_Node) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{28, 0}
// Deprecated: Use UpdateNodeReq.ProtoReflect.Descriptor instead.
func (*UpdateNodeReq) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{29}
}
func (x *GetGraphRsp_Node) GetId() int32 {
func (x *UpdateNodeReq) GetNode() *GraphNode {
if x != nil {
return x.Node
}
return nil
}
type UpdateNodeRsp struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UpdateNodeRsp) Reset() {
*x = UpdateNodeRsp{}
mi := &file_main_proto_msgTypes[30]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UpdateNodeRsp) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UpdateNodeRsp) ProtoMessage() {}
func (x *UpdateNodeRsp) ProtoReflect() protoreflect.Message {
mi := &file_main_proto_msgTypes[30]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UpdateNodeRsp.ProtoReflect.Descriptor instead.
func (*UpdateNodeRsp) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{30}
}
type GraphNode struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"`
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
Text string `protobuf:"bytes,4,opt,name=text,proto3" json:"text,omitempty"`
Applications []*GraphApplication `protobuf:"bytes,5,rep,name=applications,proto3" json:"applications,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GraphNode) Reset() {
*x = GraphNode{}
mi := &file_main_proto_msgTypes[31]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GraphNode) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GraphNode) ProtoMessage() {}
func (x *GraphNode) ProtoReflect() protoreflect.Message {
mi := &file_main_proto_msgTypes[31]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GraphNode.ProtoReflect.Descriptor instead.
func (*GraphNode) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{31}
}
func (x *GraphNode) GetId() int32 {
if x != nil {
return x.Id
}
return 0
}
func (x *GetGraphRsp_Node) GetLabel() string {
func (x *GraphNode) GetLabel() string {
if x != nil {
return x.Label
}
return ""
}
func (x *GetGraphRsp_Node) GetName() string {
func (x *GraphNode) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *GetGraphRsp_Node) GetText() string {
func (x *GraphNode) GetText() string {
if x != nil {
return x.Text
}
return ""
}
func (x *GetGraphRsp_Node) GetApplications() []*GetGraphRsp_Application {
func (x *GraphNode) GetApplications() []*GraphApplication {
if x != nil {
return x.Applications
}
return nil
}
type GraphApplication struct {
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GraphApplication) Reset() {
*x = GraphApplication{}
mi := &file_main_proto_msgTypes[32]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GraphApplication) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GraphApplication) ProtoMessage() {}
func (x *GraphApplication) ProtoReflect() protoreflect.Message {
mi := &file_main_proto_msgTypes[32]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GraphApplication.ProtoReflect.Descriptor instead.
func (*GraphApplication) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{32}
}
func (x *GraphApplication) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type GetGraphRsp_Edge struct {
state protoimpl.MessageState `protogen:"open.v1"`
From int32 `protobuf:"varint,1,opt,name=from,proto3" json:"from,omitempty"`
@ -1441,7 +1565,7 @@ type GetGraphRsp_Edge struct {
func (x *GetGraphRsp_Edge) Reset() {
*x = GetGraphRsp_Edge{}
mi := &file_main_proto_msgTypes[30]
mi := &file_main_proto_msgTypes[33]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1453,7 +1577,7 @@ func (x *GetGraphRsp_Edge) String() string {
func (*GetGraphRsp_Edge) ProtoMessage() {}
func (x *GetGraphRsp_Edge) ProtoReflect() protoreflect.Message {
mi := &file_main_proto_msgTypes[30]
mi := &file_main_proto_msgTypes[33]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1466,7 +1590,7 @@ func (x *GetGraphRsp_Edge) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetGraphRsp_Edge.ProtoReflect.Descriptor instead.
func (*GetGraphRsp_Edge) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{28, 1}
return file_main_proto_rawDescGZIP(), []int{28, 0}
}
func (x *GetGraphRsp_Edge) GetFrom() int32 {
@ -1490,50 +1614,6 @@ func (x *GetGraphRsp_Edge) GetArrows() string {
return ""
}
type GetGraphRsp_Application struct {
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetGraphRsp_Application) Reset() {
*x = GetGraphRsp_Application{}
mi := &file_main_proto_msgTypes[31]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetGraphRsp_Application) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetGraphRsp_Application) ProtoMessage() {}
func (x *GetGraphRsp_Application) ProtoReflect() protoreflect.Message {
mi := &file_main_proto_msgTypes[31]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetGraphRsp_Application.ProtoReflect.Descriptor instead.
func (*GetGraphRsp_Application) Descriptor() ([]byte, []int) {
return file_main_proto_rawDescGZIP(), []int{28, 2}
}
func (x *GetGraphRsp_Application) GetName() string {
if x != nil {
return x.Name
}
return ""
}
var File_main_proto protoreflect.FileDescriptor
const file_main_proto_rawDesc = "" +
@ -1603,29 +1683,31 @@ const file_main_proto_rawDesc = "" +
"\x1bDownloadTeamsQrCodesFileReq\"5\n" +
"\x1bDownloadTeamsQrCodesFileRsp\x12\x16\n" +
"\x06result\x18\x01 \x01(\fR\x06result\"\r\n" +
"\vGetGraphReq\"\xe3\x03\n" +
"\vGetGraphRsp\x12?\n" +
"\x05nodes\x18\x01 \x03(\v2).crabs.evening_detective.GetGraphRsp.NodeR\x05nodes\x12?\n" +
"\vGetGraphReq\"\x8c\x02\n" +
"\vGetGraphRsp\x128\n" +
"\x05nodes\x18\x01 \x03(\v2\".crabs.evening_detective.GraphNodeR\x05nodes\x12?\n" +
"\x05edges\x18\x02 \x03(\v2).crabs.evening_detective.GetGraphRsp.EdgeR\x05edges\x12\x1e\n" +
"\n" +
"countNodes\x18\x03 \x01(\x05R\n" +
"countNodes\x12\x1e\n" +
"\n" +
"countEdges\x18\x04 \x01(\x05R\n" +
"countEdges\x1a\xaa\x01\n" +
"\x04Node\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x05R\x02id\x12\x14\n" +
"\x05label\x18\x02 \x01(\tR\x05label\x12\x12\n" +
"\x04name\x18\x03 \x01(\tR\x04name\x12\x12\n" +
"\x04text\x18\x04 \x01(\tR\x04text\x12T\n" +
"\fapplications\x18\x05 \x03(\v20.crabs.evening_detective.GetGraphRsp.ApplicationR\fapplications\x1aB\n" +
"countEdges\x1aB\n" +
"\x04Edge\x12\x12\n" +
"\x04from\x18\x01 \x01(\x05R\x04from\x12\x0e\n" +
"\x02to\x18\x02 \x01(\x05R\x02to\x12\x16\n" +
"\x06arrows\x18\x03 \x01(\tR\x06arrows\x1a!\n" +
"\vApplication\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name2\xed\n" +
"\n" +
"\x06arrows\x18\x03 \x01(\tR\x06arrows\"G\n" +
"\rUpdateNodeReq\x126\n" +
"\x04node\x18\x01 \x01(\v2\".crabs.evening_detective.GraphNodeR\x04node\"\x0f\n" +
"\rUpdateNodeRsp\"\xa8\x01\n" +
"\tGraphNode\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x05R\x02id\x12\x14\n" +
"\x05label\x18\x02 \x01(\tR\x05label\x12\x12\n" +
"\x04name\x18\x03 \x01(\tR\x04name\x12\x12\n" +
"\x04text\x18\x04 \x01(\tR\x04text\x12M\n" +
"\fapplications\x18\x05 \x03(\v2).crabs.evening_detective.GraphApplicationR\fapplications\"&\n" +
"\x10GraphApplication\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name2\xe4\v\n" +
"\x10EveningDetective\x12Y\n" +
"\x04Ping\x12 .crabs.evening_detective.PingReq\x1a .crabs.evening_detective.PingRsp\"\r\x82\xd3\xe4\x93\x02\a\x12\x05/ping\x12i\n" +
"\bAddTeams\x12$.crabs.evening_detective.AddTeamsReq\x1a$.crabs.evening_detective.AddTeamsRsp\"\x11\x82\xd3\xe4\x93\x02\v:\x01*\"\x06/teams\x12f\n" +
@ -1640,7 +1722,9 @@ const file_main_proto_rawDesc = "" +
"\x10GiveApplications\x12,.crabs.evening_detective.GiveApplicationsReq\x1a,.crabs.evening_detective.GiveApplicationsRsp\"'\x82\xd3\xe4\x93\x02!:\x01*\"\x1c/teams/{teamId}/applications\x12\x9a\x01\n" +
"\x18DownloadTeamsQrCodesFile\x124.crabs.evening_detective.DownloadTeamsQrCodesFileReq\x1a4.crabs.evening_detective.DownloadTeamsQrCodesFileRsp\"\x12\x82\xd3\xe4\x93\x02\f\x12\n" +
"/teams/pdf\x12f\n" +
"\bGetGraph\x12$.crabs.evening_detective.GetGraphReq\x1a$.crabs.evening_detective.GetGraphRsp\"\x0e\x82\xd3\xe4\x93\x02\b\x12\x06/graphB\vZ\tpkg/protob\x06proto3"
"\bGetGraph\x12$.crabs.evening_detective.GetGraphReq\x1a$.crabs.evening_detective.GetGraphRsp\"\x0e\x82\xd3\xe4\x93\x02\b\x12\x06/graph\x12u\n" +
"\n" +
"UpdateNode\x12&.crabs.evening_detective.UpdateNodeReq\x1a&.crabs.evening_detective.UpdateNodeRsp\"\x17\x82\xd3\xe4\x93\x02\x11:\x01*\x1a\f/graph/nodesB\vZ\tpkg/protob\x06proto3"
var (
file_main_proto_rawDescOnce sync.Once
@ -1654,7 +1738,7 @@ func file_main_proto_rawDescGZIP() []byte {
return file_main_proto_rawDescData
}
var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 32)
var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 34)
var file_main_proto_goTypes = []any{
(*PingReq)(nil), // 0: crabs.evening_detective.PingReq
(*PingRsp)(nil), // 1: crabs.evening_detective.PingRsp
@ -1685,9 +1769,11 @@ var file_main_proto_goTypes = []any{
(*DownloadTeamsQrCodesFileRsp)(nil), // 26: crabs.evening_detective.DownloadTeamsQrCodesFileRsp
(*GetGraphReq)(nil), // 27: crabs.evening_detective.GetGraphReq
(*GetGraphRsp)(nil), // 28: crabs.evening_detective.GetGraphRsp
(*GetGraphRsp_Node)(nil), // 29: crabs.evening_detective.GetGraphRsp.Node
(*GetGraphRsp_Edge)(nil), // 30: crabs.evening_detective.GetGraphRsp.Edge
(*GetGraphRsp_Application)(nil), // 31: crabs.evening_detective.GetGraphRsp.Application
(*UpdateNodeReq)(nil), // 29: crabs.evening_detective.UpdateNodeReq
(*UpdateNodeRsp)(nil), // 30: crabs.evening_detective.UpdateNodeRsp
(*GraphNode)(nil), // 31: crabs.evening_detective.GraphNode
(*GraphApplication)(nil), // 32: crabs.evening_detective.GraphApplication
(*GetGraphRsp_Edge)(nil), // 33: crabs.evening_detective.GetGraphRsp.Edge
}
var file_main_proto_depIdxs = []int32{
3, // 0: crabs.evening_detective.AddTeamsReq.teams:type_name -> crabs.evening_detective.Team
@ -1697,38 +1783,41 @@ var file_main_proto_depIdxs = []int32{
16, // 4: crabs.evening_detective.GetTeamRsp.actions:type_name -> crabs.evening_detective.Action
11, // 5: crabs.evening_detective.Action.applications:type_name -> crabs.evening_detective.Application
11, // 6: crabs.evening_detective.GiveApplicationsReq.applications:type_name -> crabs.evening_detective.Application
29, // 7: crabs.evening_detective.GetGraphRsp.nodes:type_name -> crabs.evening_detective.GetGraphRsp.Node
30, // 8: crabs.evening_detective.GetGraphRsp.edges:type_name -> crabs.evening_detective.GetGraphRsp.Edge
31, // 9: crabs.evening_detective.GetGraphRsp.Node.applications:type_name -> crabs.evening_detective.GetGraphRsp.Application
0, // 10: crabs.evening_detective.EveningDetective.Ping:input_type -> crabs.evening_detective.PingReq
2, // 11: crabs.evening_detective.EveningDetective.AddTeams:input_type -> crabs.evening_detective.AddTeamsReq
6, // 12: crabs.evening_detective.EveningDetective.GetTeams:input_type -> crabs.evening_detective.GetTeamsReq
8, // 13: crabs.evening_detective.EveningDetective.GetTeamsCSV:input_type -> crabs.evening_detective.GetTeamsCSVReq
12, // 14: crabs.evening_detective.EveningDetective.GetTeam:input_type -> crabs.evening_detective.GetTeamReq
14, // 15: crabs.evening_detective.EveningDetective.AddAction:input_type -> crabs.evening_detective.AddActionReq
17, // 16: crabs.evening_detective.EveningDetective.GetGame:input_type -> crabs.evening_detective.GetGameReq
19, // 17: crabs.evening_detective.EveningDetective.GameStart:input_type -> crabs.evening_detective.GameStartReq
21, // 18: crabs.evening_detective.EveningDetective.GameStop:input_type -> crabs.evening_detective.GameStopReq
23, // 19: crabs.evening_detective.EveningDetective.GiveApplications:input_type -> crabs.evening_detective.GiveApplicationsReq
25, // 20: crabs.evening_detective.EveningDetective.DownloadTeamsQrCodesFile:input_type -> crabs.evening_detective.DownloadTeamsQrCodesFileReq
27, // 21: crabs.evening_detective.EveningDetective.GetGraph:input_type -> crabs.evening_detective.GetGraphReq
1, // 22: crabs.evening_detective.EveningDetective.Ping:output_type -> crabs.evening_detective.PingRsp
4, // 23: crabs.evening_detective.EveningDetective.AddTeams:output_type -> crabs.evening_detective.AddTeamsRsp
7, // 24: crabs.evening_detective.EveningDetective.GetTeams:output_type -> crabs.evening_detective.GetTeamsRsp
9, // 25: crabs.evening_detective.EveningDetective.GetTeamsCSV:output_type -> crabs.evening_detective.GetTeamsCSVRsp
13, // 26: crabs.evening_detective.EveningDetective.GetTeam:output_type -> crabs.evening_detective.GetTeamRsp
15, // 27: crabs.evening_detective.EveningDetective.AddAction:output_type -> crabs.evening_detective.AddActionRsp
18, // 28: crabs.evening_detective.EveningDetective.GetGame:output_type -> crabs.evening_detective.GetGameRsp
20, // 29: crabs.evening_detective.EveningDetective.GameStart:output_type -> crabs.evening_detective.GameStartRsp
22, // 30: crabs.evening_detective.EveningDetective.GameStop:output_type -> crabs.evening_detective.GameStopRsp
24, // 31: crabs.evening_detective.EveningDetective.GiveApplications:output_type -> crabs.evening_detective.GiveApplicationsRsp
26, // 32: crabs.evening_detective.EveningDetective.DownloadTeamsQrCodesFile:output_type -> crabs.evening_detective.DownloadTeamsQrCodesFileRsp
28, // 33: crabs.evening_detective.EveningDetective.GetGraph:output_type -> crabs.evening_detective.GetGraphRsp
22, // [22:34] is the sub-list for method output_type
10, // [10:22] is the sub-list for method input_type
10, // [10:10] is the sub-list for extension type_name
10, // [10:10] is the sub-list for extension extendee
0, // [0:10] is the sub-list for field type_name
31, // 7: crabs.evening_detective.GetGraphRsp.nodes:type_name -> crabs.evening_detective.GraphNode
33, // 8: crabs.evening_detective.GetGraphRsp.edges:type_name -> crabs.evening_detective.GetGraphRsp.Edge
31, // 9: crabs.evening_detective.UpdateNodeReq.node:type_name -> crabs.evening_detective.GraphNode
32, // 10: crabs.evening_detective.GraphNode.applications:type_name -> crabs.evening_detective.GraphApplication
0, // 11: crabs.evening_detective.EveningDetective.Ping:input_type -> crabs.evening_detective.PingReq
2, // 12: crabs.evening_detective.EveningDetective.AddTeams:input_type -> crabs.evening_detective.AddTeamsReq
6, // 13: crabs.evening_detective.EveningDetective.GetTeams:input_type -> crabs.evening_detective.GetTeamsReq
8, // 14: crabs.evening_detective.EveningDetective.GetTeamsCSV:input_type -> crabs.evening_detective.GetTeamsCSVReq
12, // 15: crabs.evening_detective.EveningDetective.GetTeam:input_type -> crabs.evening_detective.GetTeamReq
14, // 16: crabs.evening_detective.EveningDetective.AddAction:input_type -> crabs.evening_detective.AddActionReq
17, // 17: crabs.evening_detective.EveningDetective.GetGame:input_type -> crabs.evening_detective.GetGameReq
19, // 18: crabs.evening_detective.EveningDetective.GameStart:input_type -> crabs.evening_detective.GameStartReq
21, // 19: crabs.evening_detective.EveningDetective.GameStop:input_type -> crabs.evening_detective.GameStopReq
23, // 20: crabs.evening_detective.EveningDetective.GiveApplications:input_type -> crabs.evening_detective.GiveApplicationsReq
25, // 21: crabs.evening_detective.EveningDetective.DownloadTeamsQrCodesFile:input_type -> crabs.evening_detective.DownloadTeamsQrCodesFileReq
27, // 22: crabs.evening_detective.EveningDetective.GetGraph:input_type -> crabs.evening_detective.GetGraphReq
29, // 23: crabs.evening_detective.EveningDetective.UpdateNode:input_type -> crabs.evening_detective.UpdateNodeReq
1, // 24: crabs.evening_detective.EveningDetective.Ping:output_type -> crabs.evening_detective.PingRsp
4, // 25: crabs.evening_detective.EveningDetective.AddTeams:output_type -> crabs.evening_detective.AddTeamsRsp
7, // 26: crabs.evening_detective.EveningDetective.GetTeams:output_type -> crabs.evening_detective.GetTeamsRsp
9, // 27: crabs.evening_detective.EveningDetective.GetTeamsCSV:output_type -> crabs.evening_detective.GetTeamsCSVRsp
13, // 28: crabs.evening_detective.EveningDetective.GetTeam:output_type -> crabs.evening_detective.GetTeamRsp
15, // 29: crabs.evening_detective.EveningDetective.AddAction:output_type -> crabs.evening_detective.AddActionRsp
18, // 30: crabs.evening_detective.EveningDetective.GetGame:output_type -> crabs.evening_detective.GetGameRsp
20, // 31: crabs.evening_detective.EveningDetective.GameStart:output_type -> crabs.evening_detective.GameStartRsp
22, // 32: crabs.evening_detective.EveningDetective.GameStop:output_type -> crabs.evening_detective.GameStopRsp
24, // 33: crabs.evening_detective.EveningDetective.GiveApplications:output_type -> crabs.evening_detective.GiveApplicationsRsp
26, // 34: crabs.evening_detective.EveningDetective.DownloadTeamsQrCodesFile:output_type -> crabs.evening_detective.DownloadTeamsQrCodesFileRsp
28, // 35: crabs.evening_detective.EveningDetective.GetGraph:output_type -> crabs.evening_detective.GetGraphRsp
30, // 36: crabs.evening_detective.EveningDetective.UpdateNode:output_type -> crabs.evening_detective.UpdateNodeRsp
24, // [24:37] is the sub-list for method output_type
11, // [11:24] is the sub-list for method input_type
11, // [11:11] is the sub-list for extension type_name
11, // [11:11] is the sub-list for extension extendee
0, // [0:11] is the sub-list for field type_name
}
func init() { file_main_proto_init() }
@ -1742,7 +1831,7 @@ func file_main_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_main_proto_rawDesc), len(file_main_proto_rawDesc)),
NumEnums: 0,
NumMessages: 32,
NumMessages: 34,
NumExtensions: 0,
NumServices: 1,
},

View File

@ -335,6 +335,33 @@ func local_request_EveningDetective_GetGraph_0(ctx context.Context, marshaler ru
return msg, metadata, err
}
func request_EveningDetective_UpdateNode_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq UpdateNodeReq
metadata runtime.ServerMetadata
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.UpdateNode(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_EveningDetective_UpdateNode_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq UpdateNodeReq
metadata runtime.ServerMetadata
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.UpdateNode(ctx, &protoReq)
return msg, metadata, err
}
// RegisterEveningDetectiveHandlerServer registers the http handlers for service EveningDetective to "mux".
// UnaryRPC :call EveningDetectiveServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@ -581,6 +608,26 @@ func RegisterEveningDetectiveHandlerServer(ctx context.Context, mux *runtime.Ser
}
forward_EveningDetective_GetGraph_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPut, pattern_EveningDetective_UpdateNode_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/crabs.evening_detective.EveningDetective/UpdateNode", runtime.WithHTTPPathPattern("/graph/nodes"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_EveningDetective_UpdateNode_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_EveningDetective_UpdateNode_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -825,6 +872,23 @@ func RegisterEveningDetectiveHandlerClient(ctx context.Context, mux *runtime.Ser
}
forward_EveningDetective_GetGraph_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPut, pattern_EveningDetective_UpdateNode_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/crabs.evening_detective.EveningDetective/UpdateNode", runtime.WithHTTPPathPattern("/graph/nodes"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_EveningDetective_UpdateNode_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_EveningDetective_UpdateNode_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@ -841,6 +905,7 @@ var (
pattern_EveningDetective_GiveApplications_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2}, []string{"teams", "teamId", "applications"}, ""))
pattern_EveningDetective_DownloadTeamsQrCodesFile_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"teams", "pdf"}, ""))
pattern_EveningDetective_GetGraph_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"graph"}, ""))
pattern_EveningDetective_UpdateNode_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"graph", "nodes"}, ""))
)
var (
@ -856,4 +921,5 @@ var (
forward_EveningDetective_GiveApplications_0 = runtime.ForwardResponseMessage
forward_EveningDetective_DownloadTeamsQrCodesFile_0 = runtime.ForwardResponseMessage
forward_EveningDetective_GetGraph_0 = runtime.ForwardResponseMessage
forward_EveningDetective_UpdateNode_0 = runtime.ForwardResponseMessage
)

View File

@ -141,6 +141,38 @@
]
}
},
"/graph/nodes": {
"put": {
"operationId": "EveningDetective_UpdateNode",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/evening_detectiveUpdateNodeRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/evening_detectiveUpdateNodeReq"
}
}
],
"tags": [
"EveningDetective"
]
}
},
"/ping": {
"get": {
"operationId": "EveningDetective_Ping",
@ -348,45 +380,6 @@
}
}
},
"GetGraphRspNode": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int32"
},
"label": {
"type": "string"
},
"name": {
"type": "string"
},
"text": {
"type": "string"
},
"applications": {
"type": "array",
"items": {
"$ref": "#/definitions/evening_detectiveGetGraphRspApplication"
}
}
}
},
"crabsevening_detectiveApplication": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "int64"
},
"name": {
"type": "string"
},
"state": {
"type": "string"
}
}
},
"evening_detectiveAction": {
"type": "object",
"properties": {
@ -406,7 +399,7 @@
"applications": {
"type": "array",
"items": {
"$ref": "#/definitions/crabsevening_detectiveApplication"
"$ref": "#/definitions/evening_detectiveApplication"
}
}
}
@ -444,6 +437,21 @@
}
}
},
"evening_detectiveApplication": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "int64"
},
"name": {
"type": "string"
},
"state": {
"type": "string"
}
}
},
"evening_detectiveDownloadTeamsQrCodesFileRsp": {
"type": "object",
"properties": {
@ -491,7 +499,7 @@
"nodes": {
"type": "array",
"items": {
"$ref": "#/definitions/GetGraphRspNode"
"$ref": "#/definitions/evening_detectiveGraphNode"
}
},
"edges": {
@ -510,14 +518,6 @@
}
}
},
"evening_detectiveGetGraphRspApplication": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"evening_detectiveGetTeamRsp": {
"type": "object",
"properties": {
@ -561,7 +561,7 @@
"applications": {
"type": "array",
"items": {
"$ref": "#/definitions/crabsevening_detectiveApplication"
"$ref": "#/definitions/evening_detectiveApplication"
}
}
}
@ -569,6 +569,38 @@
"evening_detectiveGiveApplicationsRsp": {
"type": "object"
},
"evening_detectiveGraphApplication": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"evening_detectiveGraphNode": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int32"
},
"label": {
"type": "string"
},
"name": {
"type": "string"
},
"text": {
"type": "string"
},
"applications": {
"type": "array",
"items": {
"$ref": "#/definitions/evening_detectiveGraphApplication"
}
}
}
},
"evening_detectivePingRsp": {
"type": "object"
},
@ -603,7 +635,7 @@
"applications": {
"type": "array",
"items": {
"$ref": "#/definitions/crabsevening_detectiveApplication"
"$ref": "#/definitions/evening_detectiveApplication"
}
}
}
@ -623,6 +655,17 @@
}
}
},
"evening_detectiveUpdateNodeReq": {
"type": "object",
"properties": {
"node": {
"$ref": "#/definitions/evening_detectiveGraphNode"
}
}
},
"evening_detectiveUpdateNodeRsp": {
"type": "object"
},
"protobufAny": {
"type": "object",
"properties": {

View File

@ -31,6 +31,7 @@ const (
EveningDetective_GiveApplications_FullMethodName = "/crabs.evening_detective.EveningDetective/GiveApplications"
EveningDetective_DownloadTeamsQrCodesFile_FullMethodName = "/crabs.evening_detective.EveningDetective/DownloadTeamsQrCodesFile"
EveningDetective_GetGraph_FullMethodName = "/crabs.evening_detective.EveningDetective/GetGraph"
EveningDetective_UpdateNode_FullMethodName = "/crabs.evening_detective.EveningDetective/UpdateNode"
)
// EveningDetectiveClient is the client API for EveningDetective service.
@ -49,6 +50,7 @@ type EveningDetectiveClient interface {
GiveApplications(ctx context.Context, in *GiveApplicationsReq, opts ...grpc.CallOption) (*GiveApplicationsRsp, error)
DownloadTeamsQrCodesFile(ctx context.Context, in *DownloadTeamsQrCodesFileReq, opts ...grpc.CallOption) (*DownloadTeamsQrCodesFileRsp, error)
GetGraph(ctx context.Context, in *GetGraphReq, opts ...grpc.CallOption) (*GetGraphRsp, error)
UpdateNode(ctx context.Context, in *UpdateNodeReq, opts ...grpc.CallOption) (*UpdateNodeRsp, error)
}
type eveningDetectiveClient struct {
@ -179,6 +181,16 @@ func (c *eveningDetectiveClient) GetGraph(ctx context.Context, in *GetGraphReq,
return out, nil
}
func (c *eveningDetectiveClient) UpdateNode(ctx context.Context, in *UpdateNodeReq, opts ...grpc.CallOption) (*UpdateNodeRsp, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UpdateNodeRsp)
err := c.cc.Invoke(ctx, EveningDetective_UpdateNode_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// EveningDetectiveServer is the server API for EveningDetective service.
// All implementations must embed UnimplementedEveningDetectiveServer
// for forward compatibility.
@ -195,6 +207,7 @@ type EveningDetectiveServer interface {
GiveApplications(context.Context, *GiveApplicationsReq) (*GiveApplicationsRsp, error)
DownloadTeamsQrCodesFile(context.Context, *DownloadTeamsQrCodesFileReq) (*DownloadTeamsQrCodesFileRsp, error)
GetGraph(context.Context, *GetGraphReq) (*GetGraphRsp, error)
UpdateNode(context.Context, *UpdateNodeReq) (*UpdateNodeRsp, error)
mustEmbedUnimplementedEveningDetectiveServer()
}
@ -241,6 +254,9 @@ func (UnimplementedEveningDetectiveServer) DownloadTeamsQrCodesFile(context.Cont
func (UnimplementedEveningDetectiveServer) GetGraph(context.Context, *GetGraphReq) (*GetGraphRsp, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetGraph not implemented")
}
func (UnimplementedEveningDetectiveServer) UpdateNode(context.Context, *UpdateNodeReq) (*UpdateNodeRsp, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateNode not implemented")
}
func (UnimplementedEveningDetectiveServer) mustEmbedUnimplementedEveningDetectiveServer() {}
func (UnimplementedEveningDetectiveServer) testEmbeddedByValue() {}
@ -478,6 +494,24 @@ func _EveningDetective_GetGraph_Handler(srv interface{}, ctx context.Context, de
return interceptor(ctx, in, info, handler)
}
func _EveningDetective_UpdateNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateNodeReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(EveningDetectiveServer).UpdateNode(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: EveningDetective_UpdateNode_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EveningDetectiveServer).UpdateNode(ctx, req.(*UpdateNodeReq))
}
return interceptor(ctx, in, info, handler)
}
// EveningDetective_ServiceDesc is the grpc.ServiceDesc for EveningDetective service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@ -533,6 +567,10 @@ var EveningDetective_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetGraph",
Handler: _EveningDetective_GetGraph_Handler,
},
{
MethodName: "UpdateNode",
Handler: _EveningDetective_UpdateNode_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "main.proto",