Add bulma css
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
100f7c8ad6
commit
05d77329ab
|
@ -103,7 +103,7 @@ module Backend
|
||||||
|
|
||||||
@[GraphQL::Field]
|
@[GraphQL::Field]
|
||||||
# Starts assignment job of mentors to students
|
# Starts assignment job of mentors to students
|
||||||
def assign_students(context : Context) : Bool?
|
def start_assignment(context : Context) : Bool?
|
||||||
context.admin!
|
context.admin!
|
||||||
|
|
||||||
Worker::Jobs::AssignStudentsJob.new.enqueue
|
Worker::Jobs::AssignStudentsJob.new.enqueue
|
||||||
|
|
|
@ -54,115 +54,8 @@ module Backend
|
||||||
teachers = Db::Teacher.query
|
teachers = Db::Teacher.query
|
||||||
.where do
|
.where do
|
||||||
raw("EXISTS (SELECT 1 FROM teacher_votes WHERE teacher_id = teachers.id)") &
|
raw("EXISTS (SELECT 1 FROM teacher_votes WHERE teacher_id = teachers.id)") &
|
||||||
(max_students > 0)
|
max_students > 0
|
||||||
end
|
end
|
||||||
.with_teacher_votes
|
|
||||||
.to_a
|
|
||||||
vote_index = Hash.zip(teachers.map(&.id), [0] * teachers.size)
|
|
||||||
teacher_votes : Hash(Int32, Array(TeacherVote)) = Hash.zip(
|
|
||||||
teachers.map(&.id),
|
|
||||||
teachers.map do |t|
|
|
||||||
t.teacher_votes.map do |tv|
|
|
||||||
vote_index[t.id] += 1
|
|
||||||
|
|
||||||
{
|
|
||||||
student: tv.vote.student.id,
|
|
||||||
priority: tv.priority,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
teachers.sort_by! { |t| vote_index[t.id] }
|
|
||||||
|
|
||||||
students = Db::Student.query
|
|
||||||
.with_vote(&.with_teacher_votes(&.order_by(priority: :asc)))
|
|
||||||
.to_a
|
|
||||||
student_ids = students.map(&.id)
|
|
||||||
votes = Hash.zip(
|
|
||||||
student_ids,
|
|
||||||
students.map do |s|
|
|
||||||
s.vote.not_nil!.teacher_votes
|
|
||||||
.to_a
|
|
||||||
.select { |tv| teacher_votes.has_key?(tv.teacher.id) }
|
|
||||||
.map do |tv|
|
|
||||||
{
|
|
||||||
teacher: tv.teacher.id,
|
|
||||||
teacher_max_students: tv.teacher.max_students,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
best_assignment = {
|
|
||||||
assignment: {} of Int32 => Assignment,
|
|
||||||
score: Float32::INFINITY,
|
|
||||||
}
|
|
||||||
|
|
||||||
Backend.config.assignment_possibility_count.times.each do
|
|
||||||
assignment = {} of Int32 => Assignment
|
|
||||||
assignment_count = Hash.zip(teachers.map(&.id), [0] * teachers.size)
|
|
||||||
# teachers.each do |t|
|
|
||||||
# queue = Deque.new(teacher_votes[t.id].shuffle)
|
|
||||||
|
|
||||||
# count = 1
|
|
||||||
# while count < t.max_students
|
|
||||||
# break unless x = queue.shift?
|
|
||||||
# tv = x.not_nil!
|
|
||||||
|
|
||||||
# if assignment[tv[:student]]?.nil? || assignment[tv[:student]][:priority] <= tv[:priority]
|
|
||||||
# assignment[tv[:student]] = {teacher: t.id, priority: tv[:priority]}
|
|
||||||
# count += 1
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
votes.to_a.shuffle.each do |s, tvs|
|
|
||||||
tvs.each_with_index do |tv, i|
|
|
||||||
if assignment[s]?.nil?
|
|
||||||
assignment_count[tv[:teacher]] += 1
|
|
||||||
assignment[s] = {teacher: tv[:teacher], priority: i}
|
|
||||||
elsif assignment_count[tv[:teacher]] < tv[:teacher_max_students]
|
|
||||||
assignment_count[assignment[s][:teacher]] -= 1
|
|
||||||
assignment_count[tv[:teacher]] += 1
|
|
||||||
assignment[s] = {teacher: tv[:teacher], priority: i}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
pp! assignment, assignment_count
|
|
||||||
|
|
||||||
score = 0_f32
|
|
||||||
# positivity = 0
|
|
||||||
# assignment.each do |s, a|
|
|
||||||
# ratio = (vote_sizes[s] - a[:priority]) / vote_sizes[s]
|
|
||||||
# score += 2 ** ratio
|
|
||||||
# positivity += ratio > 0.5 ? 1 : -1
|
|
||||||
# end
|
|
||||||
assignment.each do |s, a|
|
|
||||||
size = votes[s].size
|
|
||||||
p! a[:priority], (votes[s].size - a[:priority]) / size
|
|
||||||
# score += 1 if ((votes[s].size - a[:priority]) / size) >= 0.5
|
|
||||||
score += a[:priority]
|
|
||||||
end
|
|
||||||
|
|
||||||
# full_score = score ** positivity
|
|
||||||
if score < best_assignment[:score]
|
|
||||||
best_assignment = {
|
|
||||||
assignment: assignment,
|
|
||||||
score: score,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
pp! best_assignment
|
|
||||||
|
|
||||||
str = String.build do |str|
|
|
||||||
str << "===========================\n"
|
|
||||||
best_assignment[:assignment].each do |s, a|
|
|
||||||
str << "#{Db::Student.query.find!(s).user.username} : #{Db::Teacher.query.find!(a[:teacher]).user.username} (#{a[:priority]} / #{votes[s].size})\n"
|
|
||||||
end
|
|
||||||
str << "===========================\n"
|
|
||||||
end
|
|
||||||
print str
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,6 @@ FROM lukemathwalker/cargo-chef:latest-rust-1.65.0 as chef
|
||||||
WORKDIR /usr/src/frontend
|
WORKDIR /usr/src/frontend
|
||||||
|
|
||||||
FROM chef as planner
|
FROM chef as planner
|
||||||
WORKDIR /usr/src/frontend
|
|
||||||
RUN mkdir src && touch src/main.rs
|
RUN mkdir src && touch src/main.rs
|
||||||
COPY ./Cargo.toml .
|
COPY ./Cargo.toml .
|
||||||
RUN cargo chef prepare --recipe-path recipe.json
|
RUN cargo chef prepare --recipe-path recipe.json
|
||||||
|
@ -11,10 +10,10 @@ FROM chef as builder
|
||||||
WORKDIR /usr/local/bin
|
WORKDIR /usr/local/bin
|
||||||
ARG TRUNK_VERSION="v0.16.0"
|
ARG TRUNK_VERSION="v0.16.0"
|
||||||
RUN wget -qO- https://github.com/thedodd/trunk/releases/download/${TRUNK_VERSION}/trunk-x86_64-unknown-linux-gnu.tar.gz | tar -xzf-
|
RUN wget -qO- https://github.com/thedodd/trunk/releases/download/${TRUNK_VERSION}/trunk-x86_64-unknown-linux-gnu.tar.gz | tar -xzf-
|
||||||
WORKDIR /usr/src/frontend
|
|
||||||
RUN rustup target add wasm32-unknown-unknown
|
RUN rustup target add wasm32-unknown-unknown
|
||||||
COPY ./.cargo ./.cargo
|
WORKDIR /usr/src/frontend
|
||||||
COPY --from=planner /usr/src/frontend/recipe.json .
|
COPY --from=planner /usr/src/frontend/recipe.json .
|
||||||
|
COPY ./.cargo ./.cargo
|
||||||
RUN cargo chef cook --release --recipe-path recipe.json
|
RUN cargo chef cook --release --recipe-path recipe.json
|
||||||
COPY ./index.html .
|
COPY ./index.html .
|
||||||
COPY ./graphql ./graphql
|
COPY ./graphql ./graphql
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
mutation Login($username: String!, $password: String!) {
|
mutation Login($username: String!, $password: String!) {
|
||||||
login(username: $username, password: $password) {
|
login(username: $username, password: $password) {
|
||||||
token
|
token
|
||||||
|
user {
|
||||||
|
admin
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
mutation StartAssignment {
|
||||||
|
startAssignment
|
||||||
|
}
|
|
@ -86,7 +86,6 @@ type LoginPayload {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
assignStudents: Boolean
|
|
||||||
createUser(checkLdap: Boolean! = true, input: UserCreateInput!): User
|
createUser(checkLdap: Boolean! = true, input: UserCreateInput!): User
|
||||||
createVote(input: VoteCreateInput!): Vote
|
createVote(input: VoteCreateInput!): Vote
|
||||||
deleteUser(id: Int!): Int
|
deleteUser(id: Int!): Int
|
||||||
|
@ -94,6 +93,7 @@ type Mutation {
|
||||||
logout: UUID
|
logout: UUID
|
||||||
registerTeacher(input: TeacherInput!): Teacher
|
registerTeacher(input: TeacherInput!): Teacher
|
||||||
revokeToken(token: UUID!): UUID!
|
revokeToken(token: UUID!): UUID!
|
||||||
|
startAssignment: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
input TeacherInput {
|
input TeacherInput {
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.4/css/bulma.min.css"
|
||||||
|
integrity="sha512-HqxHUkJM0SYcbvxUw5P60SzdOTy/QVwA1JJrvaXJv4q7lmbDZCmZaqz01UPOaQveoxfYRv1tHozWGPMcuTBuvQ=="
|
||||||
|
crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -3,6 +3,12 @@ events {
|
||||||
}
|
}
|
||||||
|
|
||||||
http {
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
tcp_nopush on;
|
||||||
|
|
||||||
server_tokens off;
|
server_tokens off;
|
||||||
more_clear_headers Server;
|
more_clear_headers Server;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use yew_agent::{Bridge, Bridged};
|
||||||
use yew_router::prelude::*;
|
use yew_router::prelude::*;
|
||||||
|
|
||||||
use crate::agents;
|
use crate::agents;
|
||||||
use crate::cookie_names;
|
use crate::cookies;
|
||||||
use crate::routes;
|
use crate::routes;
|
||||||
|
|
||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
|
@ -38,7 +38,7 @@ impl Component for LoggedInHandler {
|
||||||
Msg::LoggedIn(x) => {
|
Msg::LoggedIn(x) => {
|
||||||
if self.logged_in && !x {
|
if self.logged_in && !x {
|
||||||
log::info!("Global logout!");
|
log::info!("Global logout!");
|
||||||
wasm_cookies::delete(cookie_names::TOKEN);
|
cookies::logout_clear();
|
||||||
ctx.link().history().unwrap().push(routes::Route::Login);
|
ctx.link().history().unwrap().push(routes::Route::Login);
|
||||||
}
|
}
|
||||||
self.logged_in = x;
|
self.logged_in = x;
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
use const_format::concatcp;
|
|
||||||
|
|
||||||
pub const BASE: &str = "mentorenwahl_";
|
|
||||||
pub const TOKEN: &str = concatcp!(BASE, "token");
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
use const_format::concatcp;
|
||||||
|
|
||||||
|
const BASE: &str = "mentorenwahl_";
|
||||||
|
|
||||||
|
pub const TOKEN: &str = concatcp!(BASE, "token");
|
||||||
|
pub const ADMIN: &str = concatcp!(BASE, "admin");
|
||||||
|
|
||||||
|
pub const DELETE_ON_LOGOUT: [&str; 2] = [TOKEN, ADMIN];
|
||||||
|
|
||||||
|
pub fn logout_clear() {
|
||||||
|
for x in DELETE_ON_LOGOUT {
|
||||||
|
wasm_cookies::delete(x);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,4 +2,5 @@ pub mod login;
|
||||||
pub mod logout;
|
pub mod logout;
|
||||||
pub mod register_teacher;
|
pub mod register_teacher;
|
||||||
pub mod revoke_token;
|
pub mod revoke_token;
|
||||||
|
pub mod start_assignment;
|
||||||
pub mod vote;
|
pub mod vote;
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
use graphql_client::GraphQLQuery;
|
||||||
|
|
||||||
|
#[derive(GraphQLQuery)]
|
||||||
|
#[graphql(
|
||||||
|
schema_path = "graphql/schema.graphql",
|
||||||
|
query_path = "graphql/mutations/start_assignment.graphql",
|
||||||
|
response_derives = "Debug",
|
||||||
|
skip_serializing_none
|
||||||
|
)]
|
||||||
|
pub struct StartAssignment;
|
|
@ -1,6 +1,6 @@
|
||||||
pub mod agents;
|
pub mod agents;
|
||||||
pub mod components;
|
pub mod components;
|
||||||
pub mod cookie_names;
|
pub mod cookies;
|
||||||
pub mod graphql;
|
pub mod graphql;
|
||||||
pub mod layouts;
|
pub mod layouts;
|
||||||
pub mod routes;
|
pub mod routes;
|
||||||
|
|
|
@ -33,6 +33,7 @@ impl Component for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
wasm_logger::init(wasm_logger::Config::default());
|
wasm_logger::init(wasm_logger::Config::default());
|
||||||
|
|
||||||
yew::start_app::<App>();
|
yew::start_app::<App>();
|
||||||
|
|
|
@ -5,7 +5,7 @@ use yew_router::prelude::*;
|
||||||
use yew_side_effect::title::Title;
|
use yew_side_effect::title::Title;
|
||||||
|
|
||||||
use crate::components;
|
use crate::components;
|
||||||
use crate::cookie_names;
|
use crate::cookies;
|
||||||
use crate::graphql;
|
use crate::graphql;
|
||||||
use crate::routes;
|
use crate::routes;
|
||||||
|
|
||||||
|
@ -50,13 +50,24 @@ impl Component for Login {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if response.errors.is_some() {
|
if response.errors.is_some() {
|
||||||
wasm_cookies::delete(cookie_names::TOKEN);
|
cookies::logout_clear();
|
||||||
} else {
|
} else {
|
||||||
|
let data = response.data.unwrap().login.unwrap();
|
||||||
|
|
||||||
wasm_cookies::set(
|
wasm_cookies::set(
|
||||||
cookie_names::TOKEN,
|
cookies::TOKEN,
|
||||||
&response.data.unwrap().login.unwrap().token,
|
&data.token,
|
||||||
&wasm_cookies::CookieOptions::default(),
|
&wasm_cookies::CookieOptions::default(),
|
||||||
)
|
);
|
||||||
|
if data.user.admin {
|
||||||
|
wasm_cookies::set(
|
||||||
|
cookies::ADMIN,
|
||||||
|
"1",
|
||||||
|
&wasm_cookies::CookieOptions::default(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
wasm_cookies::delete(cookies::ADMIN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Msg::Login(components::graphql_errors::convert(response.errors))
|
Msg::Login(components::graphql_errors::convert(response.errors))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
use yew_router::prelude::*;
|
use yew_router::prelude::*;
|
||||||
|
|
||||||
use crate::cookie_names;
|
use crate::cookies;
|
||||||
use crate::layouts;
|
use crate::layouts;
|
||||||
|
|
||||||
pub mod home;
|
pub mod home;
|
||||||
|
@ -24,12 +24,12 @@ pub enum Route {
|
||||||
|
|
||||||
pub fn switch(routes: &Route) -> Html {
|
pub fn switch(routes: &Route) -> Html {
|
||||||
let token = {
|
let token = {
|
||||||
let tmp = wasm_cookies::get(cookie_names::TOKEN);
|
let tmp = wasm_cookies::get(cookies::TOKEN);
|
||||||
if let Some(x) = tmp {
|
if let Some(x) = tmp {
|
||||||
if let Ok(y) = x {
|
if let Ok(y) = x {
|
||||||
Some(y)
|
Some(y)
|
||||||
} else {
|
} else {
|
||||||
wasm_cookies::delete(cookie_names::TOKEN);
|
wasm_cookies::delete(cookies::TOKEN);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -37,6 +37,20 @@ pub fn switch(routes: &Route) -> Html {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let logged_in = token.is_some();
|
let logged_in = token.is_some();
|
||||||
|
let admin = {
|
||||||
|
let tmp = wasm_cookies::get(cookies::ADMIN);
|
||||||
|
if let Some(x) = tmp {
|
||||||
|
if let Ok(_) = x {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
wasm_cookies::delete(cookies::ADMIN);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
log::debug!("admin = {:?}", admin);
|
||||||
|
|
||||||
match routes {
|
match routes {
|
||||||
Route::Home => {
|
Route::Home => {
|
||||||
|
@ -52,7 +66,7 @@ pub fn switch(routes: &Route) -> Html {
|
||||||
html! {
|
html! {
|
||||||
<layouts::logged_in::LoggedIn {logged_in}>
|
<layouts::logged_in::LoggedIn {logged_in}>
|
||||||
<layouts::main::Main token={token.to_owned()} {logged_in}>
|
<layouts::main::Main token={token.to_owned()} {logged_in}>
|
||||||
<settings::Settings {token} />
|
<settings::Settings {token} {admin} />
|
||||||
</layouts::main::Main>
|
</layouts::main::Main>
|
||||||
</layouts::logged_in::LoggedIn>
|
</layouts::logged_in::LoggedIn>
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
use graphql_client::reqwest::post_graphql;
|
||||||
|
use yew::prelude::*;
|
||||||
|
|
||||||
|
use crate::components;
|
||||||
|
use crate::graphql;
|
||||||
|
|
||||||
|
pub enum Msg {
|
||||||
|
StartAssignment,
|
||||||
|
StartAssignmentDone(Option<Vec<String>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Properties, PartialEq, Eq)]
|
||||||
|
pub struct AssignmentsProps {
|
||||||
|
pub token: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Assignments {
|
||||||
|
errors: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Assignments {
|
||||||
|
type Message = Msg;
|
||||||
|
type Properties = AssignmentsProps;
|
||||||
|
|
||||||
|
fn create(_ctx: &Context<Self>) -> Self {
|
||||||
|
Self { errors: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
||||||
|
match msg {
|
||||||
|
Msg::StartAssignment => {
|
||||||
|
let client = graphql::client(Some(&ctx.props().token)).unwrap();
|
||||||
|
ctx.link().send_future(async move {
|
||||||
|
let response =
|
||||||
|
post_graphql::<graphql::mutations::start_assignment::StartAssignment, _>(
|
||||||
|
&client,
|
||||||
|
graphql::URL.as_str(),
|
||||||
|
graphql::mutations::start_assignment::start_assignment::Variables,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Msg::StartAssignmentDone(components::graphql_errors::convert(response.errors))
|
||||||
|
});
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
Msg::StartAssignmentDone(errors) => {
|
||||||
|
self.errors = errors;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
||||||
|
html! {
|
||||||
|
<fieldset>
|
||||||
|
<legend>{ "Zuweisungen" }</legend>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>{ "Aktion" }</th>
|
||||||
|
<th>{ "Optionen" }</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{ "Zuweisung starten" }</td>
|
||||||
|
<td>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<button onclick={ctx.link().callback(|_| Msg::StartAssignment)}>
|
||||||
|
{ "Ausführen" }
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<components::graphql_errors::GraphQLErrors errors={self.errors.to_owned()} />
|
||||||
|
</fieldset>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,13 @@
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
use yew_side_effect::title::Title;
|
use yew_side_effect::title::Title;
|
||||||
|
|
||||||
|
pub mod assignments;
|
||||||
pub mod tokens;
|
pub mod tokens;
|
||||||
|
|
||||||
#[derive(Properties, PartialEq, Eq)]
|
#[derive(Properties, PartialEq, Eq)]
|
||||||
pub struct SettingsProps {
|
pub struct SettingsProps {
|
||||||
pub token: Option<String>,
|
pub token: Option<String>,
|
||||||
|
pub admin: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Settings;
|
pub struct Settings;
|
||||||
|
@ -25,6 +27,11 @@ impl Component for Settings {
|
||||||
<section>
|
<section>
|
||||||
<tokens::Tokens token={ctx.props().token.as_ref().unwrap().to_owned()} />
|
<tokens::Tokens token={ctx.props().token.as_ref().unwrap().to_owned()} />
|
||||||
</section>
|
</section>
|
||||||
|
if ctx.props().admin {
|
||||||
|
<section>
|
||||||
|
<assignments::Assignments token={ctx.props().token.as_ref().unwrap().to_owned()} />
|
||||||
|
</section>
|
||||||
|
}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl Component for Tokens {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
true
|
false
|
||||||
}
|
}
|
||||||
Msg::RevokeDone { errors, id } => {
|
Msg::RevokeDone { errors, id } => {
|
||||||
self.errors = errors;
|
self.errors = errors;
|
||||||
|
@ -122,7 +122,7 @@ impl Component for Tokens {
|
||||||
}) }
|
}) }
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<components::graphql_errors::GraphQLErrors errors={self.errors.clone()} />
|
<components::graphql_errors::GraphQLErrors errors={self.errors.to_owned()} />
|
||||||
}
|
}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue