-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/wizard #127
base: master
Are you sure you want to change the base?
Feature/wizard #127
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
import React, { useState, useEffect } from "react"; | ||
import { useForm } from "react-hook-form"; | ||
import ReactMarkdown from 'react-markdown' | ||
import { Card, CardHeader, CardBody, CardFooter, FormGroup, FormText, Input, Label, Pagination, PaginationItem, PaginationLink } from "reactstrap"; | ||
|
||
|
||
export function Wizard({ | ||
name, wizardPages | ||
}) { | ||
|
||
const [rows, setRows] = useState(); | ||
const [page, setPage] = useState(1); | ||
const [totalCount, setTotalCount] = useState(0); //TODO: calculate | ||
const [progressStep, setProgressStep] = useState(20); | ||
const [pageTitle, setPageTitle] = useState(""); | ||
const { register, handleSubmit, setValue, getValues, errors, reset } = useForm(); | ||
|
||
useEffect(() => { | ||
setTotalCount(wizardPages.length); | ||
}, []); | ||
|
||
useEffect(() => { | ||
getRows(); | ||
setPageTitle(wizardPages[page - 1].title ? wizardPages[page - 1].title : page - 1); // pagination counts index from 1, not 0 | ||
}, [page]); | ||
|
||
const getRows = () => { | ||
var view = [] | ||
if (wizardPages != undefined) { | ||
var pageView = wizardPages[page - 1] | ||
if (pageView.rows != undefined) { | ||
pageView.rows.forEach(row => { | ||
if (row.type == "markdown") { | ||
view.push( | ||
<ReactMarkdown> | ||
{row.contents} | ||
</ReactMarkdown> | ||
) | ||
} else if (row.type == "object") { | ||
var line = row.properties | ||
Object.keys(line).map((key, idx) => { | ||
view.push(<InputStringItem | ||
key={line[key].$id} | ||
id={line[key].$id} | ||
label={line[key].title} | ||
description={line[key].description} | ||
placeholder={line[key].default} | ||
description={line[key].description} | ||
register={register} | ||
/>) | ||
}) | ||
}; | ||
}); | ||
}; | ||
setRows(view) | ||
}; | ||
}; | ||
|
||
|
||
return ( | ||
<Card className="height-100"> | ||
<CardHeader> | ||
{pageTitle} | ||
</CardHeader> | ||
|
||
<CardBody className="table-responsive"> | ||
{rows} | ||
</CardBody> | ||
<CardFooter> | ||
<ListPagination | ||
page={page} | ||
pageTitle={pageTitle} | ||
onPageChange={setPage} | ||
max={totalCount} | ||
progressStep={progressStep} | ||
/> | ||
{/* Here should be some progress indicator */} | ||
</CardFooter> | ||
</Card> | ||
); | ||
} | ||
|
||
|
||
|
||
|
||
function ListPagination(props) { | ||
|
||
const slots = Math.min(5, props.max); | ||
|
||
var start = props.page - Math.floor(slots / 2); | ||
var end = props.page + Math.floor(slots / 2); | ||
|
||
if (start < 1) { | ||
start = 1; | ||
end = Math.min(slots, props.max); | ||
} | ||
|
||
else if (end > props.max) { | ||
start = Math.max(props.max - slots + 1, 1); | ||
end = props.max; | ||
} | ||
|
||
let pages = []; | ||
var i; | ||
for (i = start; i <= end; i++) { | ||
pages.push(i); | ||
} | ||
|
||
return ( | ||
<Pagination> | ||
<PaginationItem> | ||
<PaginationLink | ||
previous | ||
disabled={props.pages <= 1} | ||
onClick={(e) => props.onPageChange(Math.max(1, props.page - 1))} | ||
> | ||
</PaginationLink> | ||
</PaginationItem> | ||
|
||
{pages.map((i, x) => | ||
<PaginationItem key={x} active={(i) == props.page}> | ||
<PaginationLink | ||
onClick={(e) => { | ||
props.onPageChange(i); | ||
}} | ||
> | ||
{i} | ||
</PaginationLink> | ||
</PaginationItem> | ||
)} | ||
|
||
<PaginationItem> | ||
<PaginationLink | ||
next | ||
disabled={props.page >= props.max} | ||
onClick={(e) => { | ||
props.onPageChange(props.page + 1) | ||
}} | ||
> | ||
</PaginationLink> | ||
</PaginationItem> | ||
</Pagination> | ||
); | ||
} | ||
|
||
|
||
// TODO: Different types of Item to cover formats such as "number", "boolean", checkbox, radiobox | ||
export function InputStringItem(props) { | ||
return ( | ||
<FormGroup> | ||
<Label for={props.id}> | ||
{props.label} | ||
</Label> | ||
<Input | ||
type="text" | ||
name={props.id} | ||
id={props.id} | ||
placeholder={props.placeholder} | ||
innerRef={props.register()} | ||
/> | ||
<FormText color="muted"> | ||
{props.description} | ||
</FormText> | ||
</FormGroup> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import React from 'react'; | ||
|
||
import { Wizard } from './Wizard'; | ||
import { Container } from 'reactstrap'; | ||
|
||
import json from './mock-data.json'; | ||
|
||
const WizardContainer = (props) => { | ||
console.log(json) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @titkov49 Here is some forgotten console.log |
||
|
||
return ( | ||
<Container> | ||
<Wizard className="m-2 card-editor" | ||
app={props.App} | ||
name={json.name} | ||
wizardPages={json.wizardPages} | ||
/> | ||
</Container> | ||
) | ||
} | ||
|
||
export default WizardContainer; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import Module from 'asab-webui/abc/Module'; | ||
import WizardContainer from './WizardContainer'; | ||
|
||
export default class WizardModule extends Module { | ||
constructor (app) { | ||
super(app, "WizardModule"); | ||
|
||
console.log("WizardModule: ", this); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @titkov49 Here is some forgotten console.log |
||
|
||
this.Router.addRoute({ | ||
path: "/wizard/", | ||
exact: true, | ||
name: "Wizard", | ||
component: WizardContainer | ||
}) | ||
|
||
this.Navigation.addItem({ | ||
name: "Wizard", | ||
icon: "cil-gem", | ||
url: "/wizard/" | ||
}) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @titkov49 Do we need mocked data in the |
||
"name": "Wizard Name", | ||
"wizardPages": [ | ||
{ | ||
"title": "a 1", | ||
"rows": | ||
[ | ||
{ | ||
"type": "markdown", | ||
"contents": "# headline \n ## second line \n normal text \n\n second line of normal text" | ||
}, | ||
{ | ||
"$id": "some_id", | ||
"type": "object", | ||
"description": "description", | ||
"examples": [ | ||
{ | ||
"servers": "lm1:12181,lm2:22181,lm3:32181", | ||
"path": "/lmio" | ||
} | ||
], | ||
"required": [ | ||
"servers", | ||
"path" | ||
], | ||
"properties": { | ||
"servers": { | ||
"$id": "#/properties/asab%3Azookeeper/properties/servers", | ||
"type": "text", | ||
"title": "The servers schema", | ||
"description": "An explanation about the purpose of this instance.", | ||
"default": "", | ||
"examples": [ | ||
"lm1:12181,lm2:22181,lm3:32181" | ||
] | ||
}, | ||
"path": { | ||
"$id": "#/properties/asab%3Azookeeper/properties/path", | ||
"type": "text", | ||
"title": "The path schema", | ||
"description": "An explanation about the purpose of this instance.", | ||
"default": "", | ||
"examples": [ | ||
"/lmio" | ||
] | ||
} | ||
} | ||
}, | ||
{ | ||
"type": "markdown", | ||
"contents": "## headline 2" | ||
} | ||
] | ||
}, | ||
{ | ||
"title": "b 2", | ||
"rows": | ||
[ | ||
{ | ||
"type": "markdown", | ||
"contents": "# headline \n ## second line \n normal text \n\n second line of normal text" | ||
}, | ||
{ | ||
"type": "markdown", | ||
"contents": "## headline 2" | ||
}, | ||
{ | ||
"type": "markdown", | ||
"contents": "### headline 3" | ||
}, | ||
{ | ||
"type": "markdown", | ||
"contents": "#### headline 4" | ||
}, | ||
{ | ||
"$id": "some_id2", | ||
"type": "object", | ||
"description": "description", | ||
"examples": [ | ||
{ | ||
"servers": "lm1:12181,lm2:22181,lm3:32181", | ||
"path": "/lmio" | ||
} | ||
], | ||
"required": [ | ||
"servers", | ||
"path" | ||
], | ||
"properties": { | ||
"servers2": { | ||
"$id": "#/properties/asab%3Azookeeper/properties/servers2", | ||
"type": "string", | ||
"title": "The servers schema2", | ||
"description": "An explanation about the purpose of servers2.", | ||
"default": "", | ||
"examples": [ | ||
"lm1:12181,lm2:22181,lm3:32181" | ||
] | ||
}, | ||
"path2": { | ||
"$id": "#/properties/asab%3Azookeeper/properties/path2", | ||
"type": "string", | ||
"title": "The path schema2", | ||
"description": "An explanation about the purpose of path2.", | ||
"default": "some default value", | ||
"examples": [ | ||
"/lmio" | ||
] | ||
} | ||
} | ||
}, | ||
{ | ||
"type": "markdown", | ||
"contents": "last markdown under input" | ||
} | ||
] | ||
} | ||
] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@titkov49 Why do you need to define Config, Navigation and Router in here? Also, I think it should be without
?
. Also, be patient with the indentation on line 6 and 7