Added verify step
This commit is contained in:
parent
7ea256f85b
commit
0f0aff81f4
@ -754,6 +754,14 @@ html {
|
|||||||
--tw-contain-style: ;
|
--tw-contain-style: ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (hover:hover) {
|
||||||
|
.table tr.hover:hover,
|
||||||
|
.table tr.hover:nth-child(even):hover {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
@ -818,6 +826,57 @@ html {
|
|||||||
content: var(--tw-content);
|
content: var(--tw-content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-radius: var(--rounded-box, 1rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:focus {
|
||||||
|
outline: 2px solid transparent;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card figure {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.image-full {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.image-full:before {
|
||||||
|
position: relative;
|
||||||
|
content: "";
|
||||||
|
z-index: 10;
|
||||||
|
border-radius: var(--rounded-box, 1rem);
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.image-full:before,
|
||||||
|
.card.image-full > * {
|
||||||
|
grid-column-start: 1;
|
||||||
|
grid-row-start: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.image-full > figure img {
|
||||||
|
height: 100%;
|
||||||
|
-o-object-fit: cover;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.image-full > .card-body {
|
||||||
|
position: relative;
|
||||||
|
z-index: 20;
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown {
|
.dropdown {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -1137,6 +1196,39 @@ html {
|
|||||||
min-width: 4rem;
|
min-width: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: var(--rounded-box, 1rem);
|
||||||
|
text-align: left;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table :where(.table-pin-rows thead tr) {
|
||||||
|
position: sticky;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 1;
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
.table :where(.table-pin-rows tfoot tr) {
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0px;
|
||||||
|
z-index: 1;
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
.table :where(.table-pin-cols tr th) {
|
||||||
|
position: sticky;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));
|
||||||
|
}
|
||||||
|
|
||||||
.btm-nav > *.disabled,
|
.btm-nav > *.disabled,
|
||||||
.btm-nav > *[disabled] {
|
.btm-nav > *[disabled] {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@ -1271,6 +1363,53 @@ html {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card :where(figure:first-child) {
|
||||||
|
overflow: hidden;
|
||||||
|
border-start-start-radius: inherit;
|
||||||
|
border-start-end-radius: inherit;
|
||||||
|
border-end-start-radius: unset;
|
||||||
|
border-end-end-radius: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card :where(figure:last-child) {
|
||||||
|
overflow: hidden;
|
||||||
|
border-start-start-radius: unset;
|
||||||
|
border-start-end-radius: unset;
|
||||||
|
border-end-start-radius: inherit;
|
||||||
|
border-end-end-radius: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:focus-visible {
|
||||||
|
outline: 2px solid currentColor;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.bordered {
|
||||||
|
border-width: 1px;
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.compact .card-body {
|
||||||
|
padding: 1rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 1.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.image-full :where(figure) {
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes checkmark {
|
@keyframes checkmark {
|
||||||
0% {
|
0% {
|
||||||
background-position-y: 5px;
|
background-position-y: 5px;
|
||||||
@ -1643,6 +1782,45 @@ html {
|
|||||||
color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)));
|
color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table:where([dir="rtl"], [dir="rtl"] *) {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table :where(th, td) {
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
padding-bottom: 0.75rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tr.active,
|
||||||
|
.table tr.active:nth-child(even),
|
||||||
|
.table-zebra tbody tr:nth-child(even) {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
.table :where(thead tr, tbody tr:not(:last-child), tbody tr:first-child:last-child) {
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-bottom-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
.table :where(thead, tfoot) {
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--fallback-bc,oklch(var(--bc)/0.6));
|
||||||
|
}
|
||||||
|
|
||||||
|
.table :where(tfoot) {
|
||||||
|
border-top-width: 1px;
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-top-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes toast-pop {
|
@keyframes toast-pop {
|
||||||
0% {
|
0% {
|
||||||
transform: scale(0.9);
|
transform: scale(0.9);
|
||||||
@ -1737,6 +1915,14 @@ html {
|
|||||||
grid-template-rows: repeat(1, minmax(0, 1fr));
|
grid-template-rows: repeat(1, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-compact .card-title {
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-normal .card-title {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.join.join-vertical > :where(*:not(:first-child)) {
|
.join.join-vertical > :where(*:not(:first-child)) {
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
@ -1809,8 +1995,12 @@ html {
|
|||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mt-16 {
|
.mb-1 {
|
||||||
margin-top: 4rem;
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-5 {
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mt-5 {
|
.mt-5 {
|
||||||
@ -1821,6 +2011,10 @@ html {
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
.contents {
|
.contents {
|
||||||
display: contents;
|
display: contents;
|
||||||
}
|
}
|
||||||
@ -1830,6 +2024,10 @@ html {
|
|||||||
height: 2rem;
|
height: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-\[30rem\] {
|
||||||
|
height: 30rem;
|
||||||
|
}
|
||||||
|
|
||||||
.h-full {
|
.h-full {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
@ -1847,6 +2045,10 @@ html {
|
|||||||
min-height: 4rem;
|
min-height: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-96 {
|
||||||
|
width: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
.w-full {
|
.w-full {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@ -1867,6 +2069,10 @@ html {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-wrap {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
.flex-nowrap {
|
.flex-nowrap {
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
}
|
}
|
||||||
@ -1891,6 +2097,14 @@ html {
|
|||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gap-5 {
|
||||||
|
gap: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overflow-auto {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.overflow-y-auto {
|
.overflow-y-auto {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
@ -1900,6 +2114,10 @@ html {
|
|||||||
background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));
|
background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p-5 {
|
||||||
|
padding: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.px-2 {
|
.px-2 {
|
||||||
padding-left: 0.5rem;
|
padding-left: 0.5rem;
|
||||||
padding-right: 0.5rem;
|
padding-right: 0.5rem;
|
||||||
@ -1920,8 +2138,8 @@ html {
|
|||||||
padding-bottom: 2.5rem;
|
padding-bottom: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pb-36 {
|
.pb-10 {
|
||||||
padding-bottom: 9rem;
|
padding-bottom: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-xl {
|
.text-xl {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::util::model::member::{Member, MembersMigration};
|
||||||
use dioxus::prelude::{dioxus_elements::FileEngine, *};
|
use dioxus::prelude::{dioxus_elements::FileEngine, *};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -17,12 +18,13 @@ enum Steps {
|
|||||||
#[component]
|
#[component]
|
||||||
pub fn Migration() -> Element {
|
pub fn Migration() -> Element {
|
||||||
let step = use_signal(|| Steps::Upload);
|
let step = use_signal(|| Steps::Upload);
|
||||||
|
let members_migration = use_signal(|| MembersMigration::new());
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
div {
|
div {
|
||||||
class: "flex flex-col items-center justify-center h-full py-10",
|
class: "flex flex-col items-center justify-center py-10",
|
||||||
ul {
|
ul {
|
||||||
class: "steps pb-36",
|
class: "steps pb-10",
|
||||||
li { class: "step step-primary", "Uploaden" },
|
li { class: "step step-primary", "Uploaden" },
|
||||||
li {
|
li {
|
||||||
class: "step",
|
class: "step",
|
||||||
@ -32,16 +34,16 @@ pub fn Migration() -> Element {
|
|||||||
li { class: "step", "Klaar" },
|
li { class: "step", "Klaar" },
|
||||||
},
|
},
|
||||||
match *step.read() {
|
match *step.read() {
|
||||||
Steps::Upload => rsx! { Upload { step: step } },
|
Steps::Upload => rsx! { Upload { step: step, members_migration: members_migration } },
|
||||||
Steps::Verify => rsx! { Verify {} },
|
Steps::Verify => rsx! { Verify { members_migration: members_migration} },
|
||||||
Steps::Done => rsx! { Verify {} },
|
Steps::Done => rsx! { Verify { members_migration: members_migration } },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn Upload(step: Signal<Steps>) -> Element {
|
fn Upload(step: Signal<Steps>, members_migration: Signal<MembersMigration>) -> Element {
|
||||||
let mut file_uploaded = use_signal(|| None);
|
let mut file_uploaded = use_signal(|| None);
|
||||||
|
|
||||||
let mut loading = use_signal(|| false);
|
let mut loading = use_signal(|| false);
|
||||||
@ -69,23 +71,25 @@ fn Upload(step: Signal<Steps>) -> Element {
|
|||||||
Some(file) => {
|
Some(file) => {
|
||||||
loading.set(true);
|
loading.set(true);
|
||||||
|
|
||||||
if let Ok(_response) = upload_members_list(file.contents.clone()).await {
|
if let Ok(response) = upload_members_list(file.contents.clone()).await {
|
||||||
tracing::info!("Done");
|
members_migration.set(response);
|
||||||
step.set(Steps::Verify);
|
step.set(Steps::Verify);
|
||||||
|
loading.set(false);
|
||||||
}
|
}
|
||||||
loading.set(false);
|
loading.set(false);
|
||||||
}
|
}
|
||||||
None => tracing::info!("File doesn't exists"),
|
None => tracing::info!("File doesn't exists"),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
form {
|
form {
|
||||||
class: "flex flex-col items-center w-full h-full max-w-md mx-auto px-2",
|
class: "flex flex-col items-center w-full h-full max-w-md mx-auto px-2",
|
||||||
onsubmit: sumbit,
|
onsubmit: sumbit,
|
||||||
h2 { class: "text-xl", "Selecteer het ledenbestand" },
|
h2 { class: "text-xl mb-5", "Selecteer de ledenlijst" },
|
||||||
input {
|
input {
|
||||||
r#type: "file",
|
r#type: "file",
|
||||||
class: "file-input file-input-bordered w-full mt-16",
|
class: "file-input file-input-bordered w-full",
|
||||||
accept: ".csv",
|
accept: ".csv",
|
||||||
multiple: false,
|
multiple: false,
|
||||||
autocomplete: "off",
|
autocomplete: "off",
|
||||||
@ -99,32 +103,81 @@ fn Upload(step: Signal<Steps>) -> Element {
|
|||||||
}
|
}
|
||||||
"Uploaden"
|
"Uploaden"
|
||||||
}
|
}
|
||||||
"{file_uploaded.read().is_none()}"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn Verify() -> Element {
|
fn Verify(members_migration: Signal<MembersMigration>) -> Element {
|
||||||
|
let mut loading = use_signal(|| false);
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
div {
|
div {
|
||||||
class: "flex flex-col items-center w-full h-full max-w-md mx-auto px-2",
|
class: "flex flex-col items-center justify-center w-full mx-auto px-2",
|
||||||
h2 { class: "text-xl", "Controleer de actie" },
|
h2 { class: "text-xl mb-5", "Controleer de verandering" },
|
||||||
|
div {
|
||||||
|
class: "flex flex-wrap gap-5",
|
||||||
|
div {
|
||||||
|
class: "card bg-base-200 p-5",
|
||||||
|
h2 { class: "card-title mb-1", "Toevoegen" }
|
||||||
|
MembersTable { members: members_migration.read().inserted.clone() }
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
class: "card bg-base-200 p-5",
|
||||||
|
h2 { class: "card-title mb-1", "Verwijderen" }
|
||||||
|
MembersTable { members: members_migration.read().removed.clone() }
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
class: "card bg-base-200 p-5",
|
||||||
|
h2 { class: "card-title mb-1", "Updaten" }
|
||||||
|
MembersTable { members: members_migration.read().updated.clone() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
class: "btn btn-primary btn-wide mt-5",
|
||||||
|
disabled: loading(),
|
||||||
|
if loading() {
|
||||||
|
span { class: "loading loading-spinner" }
|
||||||
|
}
|
||||||
|
"Toepassen"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn MembersTable(members: Vec<Member>) -> Element {
|
||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
class: "h-[30rem] w-96 overflow-auto font-normal",
|
||||||
|
table {
|
||||||
|
class: "table table-pin-rows",
|
||||||
|
thead {
|
||||||
|
tr {
|
||||||
|
th { "Relatiecode" }
|
||||||
|
th { "Naam" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tbody {
|
||||||
|
for member in members {
|
||||||
|
tr {
|
||||||
|
th { "{member.id}" }
|
||||||
|
th { "{member.name.full}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[server]
|
#[server]
|
||||||
async fn upload_members_list(input: String) -> Result<String, ServerFnError> {
|
async fn upload_members_list(input: String) -> Result<MembersMigration, ServerFnError> {
|
||||||
use crate::util::model::member::Member;
|
match Member::migrate_proposal(input).await {
|
||||||
|
Ok(r) => Ok(r),
|
||||||
tracing::info!("Getting members...");
|
Err(err) => Err(ServerFnError::new(err.to_string())),
|
||||||
|
}
|
||||||
let result = Member::migrate_proposal(input).await;
|
|
||||||
|
|
||||||
tracing::info!("{:?}", result);
|
|
||||||
|
|
||||||
Ok("Whoo".to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[server]
|
#[server]
|
||||||
|
@ -1,2 +1 @@
|
|||||||
#[cfg(feature = "server")]
|
|
||||||
pub mod member;
|
pub mod member;
|
||||||
|
@ -1,24 +1,32 @@
|
|||||||
#[cfg(feature = "server")]
|
#[cfg(feature = "server")]
|
||||||
use crate::util::surrealdb::DB;
|
use crate::util::surrealdb::DB;
|
||||||
use serde::Deserialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
|
#[cfg(feature = "server")]
|
||||||
mod migration;
|
mod migration;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
|
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)]
|
||||||
pub struct Member {
|
pub struct Member {
|
||||||
id: String,
|
pub id: String,
|
||||||
name: Name,
|
pub name: Name,
|
||||||
hours: BTreeSet<String>,
|
pub hours: BTreeSet<String>,
|
||||||
groups: BTreeSet<String>,
|
pub groups: BTreeSet<String>,
|
||||||
diploma: Option<String>,
|
pub diploma: Option<String>,
|
||||||
registration_token: Option<String>,
|
pub registration_token: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
|
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)]
|
||||||
pub struct Name {
|
pub struct Name {
|
||||||
first: String,
|
pub first: String,
|
||||||
full: String,
|
pub full: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
|
||||||
|
pub struct MembersMigration {
|
||||||
|
pub inserted: Vec<Member>,
|
||||||
|
pub updated: Vec<Member>,
|
||||||
|
pub removed: Vec<Member>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "server")]
|
#[cfg(feature = "server")]
|
||||||
@ -31,3 +39,13 @@ impl Member {
|
|||||||
Ok(members)
|
Ok(members)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MembersMigration {
|
||||||
|
pub fn new() -> MembersMigration {
|
||||||
|
MembersMigration {
|
||||||
|
inserted: vec![],
|
||||||
|
updated: vec![],
|
||||||
|
removed: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use crate::util::surrealdb::DB;
|
use super::{Member, MembersMigration};
|
||||||
|
|
||||||
use super::Member;
|
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
use std::collections::{BTreeSet, HashMap};
|
||||||
|
|
||||||
// Create a store for saving information when migrating to a new members list
|
// Create a store for saving information when migrating to a new members list
|
||||||
static MEMBERS_STORE: Lazy<MembersStore> = Lazy::new(|| MembersStore::new());
|
static MEMBERS_STORE: Lazy<MembersStore> = Lazy::new(|| MembersStore::new());
|
||||||
@ -129,11 +127,10 @@ fn rows_to_members(rows: Vec<Row>) -> Vec<Member> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compare the new members list with the current
|
// Compare the new members list with the current
|
||||||
// (inserted, updated, removed)
|
|
||||||
fn combine_members_lists(
|
fn combine_members_lists(
|
||||||
new_members_list: Vec<Member>,
|
new_members_list: Vec<Member>,
|
||||||
current_members_list: Vec<Member>,
|
current_members_list: Vec<Member>,
|
||||||
) -> (Vec<Member>, Vec<Member>, Vec<Member>) {
|
) -> MembersMigration {
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"Current: {}, New: {}",
|
"Current: {}, New: {}",
|
||||||
current_members_list.len(),
|
current_members_list.len(),
|
||||||
@ -183,13 +180,17 @@ fn combine_members_lists(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(inserted_members, updated_members, removed_members)
|
MembersMigration {
|
||||||
|
inserted: inserted_members,
|
||||||
|
updated: updated_members,
|
||||||
|
removed: removed_members,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Member {
|
impl Member {
|
||||||
pub async fn migrate_proposal(
|
pub async fn migrate_proposal(
|
||||||
csv: String,
|
csv: String,
|
||||||
) -> Result<(Vec<Member>, Vec<Member>, Vec<Member>), Box<dyn std::error::Error>> {
|
) -> Result<MembersMigration, Box<dyn std::error::Error>> {
|
||||||
let rows = csv_to_rows(csv)?;
|
let rows = csv_to_rows(csv)?;
|
||||||
|
|
||||||
let new_members = rows_to_members(rows);
|
let new_members = rows_to_members(rows);
|
||||||
|
Loading…
Reference in New Issue
Block a user