mirror of https://github.com/01-edu/public.git
lee
4 years ago
5 changed files with 102 additions and 492 deletions
@ -1,119 +1,37 @@ |
|||||||
<!DOCTYPE html> |
|
||||||
<html> |
<html> |
||||||
<head> |
<head> |
||||||
<title>Graphql Doc</title> |
<title>Simple GraphiQL Example</title> |
||||||
<meta charset="utf-8"> |
<link href="https://unpkg.com/graphiql/graphiql.min.css" rel="stylesheet" /> |
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |
</head> |
||||||
<style> |
<body style="margin: 0;"> |
||||||
|
<div id="graphiql" style="height: 100vh;"></div> |
||||||
:root { |
|
||||||
--color: hsl(0, 0%, 65%); |
<script |
||||||
} |
crossorigin |
||||||
|
src="https://unpkg.com/react/umd/react.production.min.js" |
||||||
* { |
></script> |
||||||
box-sizing: border-box; |
<script |
||||||
} |
crossorigin |
||||||
|
src="https://unpkg.com/react-dom/umd/react-dom.production.min.js" |
||||||
body { |
></script> |
||||||
background: hsl(0, 0%, 16%); |
<script |
||||||
font-family: sans-serif; |
crossorigin |
||||||
letter-spacing: 1.5px; |
src="https://unpkg.com/graphiql/graphiql.min.js" |
||||||
display: flex; |
></script> |
||||||
flex-wrap: wrap; |
|
||||||
justify-content: center; |
<script> |
||||||
align-content: center; |
const graphQLFetcher = graphQLParams => |
||||||
width: inherit; |
fetch(`https://${location.hostname}/api/graphql-engine/v1/graphql`, { |
||||||
height: inherit; |
method: 'post', |
||||||
padding: 5rem; |
headers: { 'Content-Type': 'application/json' }, |
||||||
font-size: 12px; |
body: JSON.stringify(graphQLParams), |
||||||
} |
}) |
||||||
|
.then(response => response.json()) |
||||||
input { |
.catch(() => response.text()); |
||||||
border: none; |
ReactDOM.render( |
||||||
position: absolute; |
React.createElement(GraphiQL, { fetcher: graphQLFetcher }), |
||||||
margin: 6px 24px 8px 15px; |
document.getElementById('graphiql'), |
||||||
background: rgba(255, 255, 255, 0); |
); |
||||||
border-bottom: 1px solid var(--color); |
</script> |
||||||
outline: none; |
</body> |
||||||
} |
|
||||||
|
|
||||||
.docExplorerWrap { |
|
||||||
position: inherit; |
|
||||||
width: 80%; |
|
||||||
height: 100%; |
|
||||||
top: 50%; |
|
||||||
left: 50%; |
|
||||||
background-color: hsl(0, 1%, 35%); |
|
||||||
} |
|
||||||
|
|
||||||
.doc-title, .doc-explore-content { |
|
||||||
padding: 10px; |
|
||||||
margin: 10px; |
|
||||||
align-content: center; |
|
||||||
border-bottom: 1px solid var(--color); |
|
||||||
} |
|
||||||
|
|
||||||
.doc-title { |
|
||||||
display: flex; |
|
||||||
} |
|
||||||
|
|
||||||
.back { |
|
||||||
width: 50px; |
|
||||||
height: 50px; |
|
||||||
} |
|
||||||
|
|
||||||
h3, h4, li { |
|
||||||
font-weight: 300; |
|
||||||
width: 100%; |
|
||||||
margin: 15px; |
|
||||||
} |
|
||||||
|
|
||||||
h3 { |
|
||||||
font-size: 1.25rem; |
|
||||||
} |
|
||||||
|
|
||||||
h4 { |
|
||||||
font-size: 0.8rem; |
|
||||||
white-space: pre; |
|
||||||
} |
|
||||||
|
|
||||||
b { |
|
||||||
padding: 4px; |
|
||||||
border-bottom: 1px solid var(--color); |
|
||||||
} |
|
||||||
|
|
||||||
a { |
|
||||||
color:lightcoral; |
|
||||||
} |
|
||||||
|
|
||||||
a:hover { |
|
||||||
text-decoration: underline; |
|
||||||
cursor: pointer; |
|
||||||
} |
|
||||||
|
|
||||||
img { |
|
||||||
cursor: pointer; |
|
||||||
width: 30px; |
|
||||||
height: 30px; |
|
||||||
} |
|
||||||
|
|
||||||
</style> |
|
||||||
</head> |
|
||||||
<body> |
|
||||||
<script type="module" src="./lib/schema.js"></script> |
|
||||||
<div class="docExplorerWrap"> |
|
||||||
<div class="doc-title"><h3 class="title">Schema Documentation</h3></div> |
|
||||||
<div class="doc-explore-content"> |
|
||||||
<label class="search-box"> |
|
||||||
<img src="https://cdn1.iconfinder.com/data/icons/thin-ui-1/100/Noun_Project_100Icon_1px_grid_thin_ic_cookie-512.png"> |
|
||||||
<input class="search" type="text" placeholder="Search Schema..."> |
|
||||||
</label> |
|
||||||
<div class="doc-type-description"> <h4 class="comment">A Graphql schema provides a root type for each kind of operation</h4><!-- description of... --></div> |
|
||||||
<br> |
|
||||||
<div class="doc-category"><h4><b class="doc-type">ROOT TYPES</b></h4></div> |
|
||||||
<br> |
|
||||||
<div class="display-doc"></h4></div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</body> |
|
||||||
</html> |
</html> |
@ -1,163 +0,0 @@ |
|||||||
const backImg = |
|
||||||
'https://cdn1.iconfinder.com/data/icons/thin-ui-1/100/Noun_Project_100Icon_1px_grid_thin_ic_arrow_left_simple-512.png' |
|
||||||
const body = document.body |
|
||||||
const docDisplay = document.querySelector('.display-doc') |
|
||||||
const exist = () => document.querySelector('.back') |
|
||||||
const removeComments = (obj) => |
|
||||||
Object.fromEntries(obj.filter((v) => v[0] !== 'comment')) |
|
||||||
|
|
||||||
const getData = async (pathToFile) => { |
|
||||||
const data = await fetch(pathToFile) |
|
||||||
.then((data) => data.json()) |
|
||||||
.catch(console.log) |
|
||||||
return data |
|
||||||
} |
|
||||||
|
|
||||||
const generateLinks = (k, v) => { |
|
||||||
const h4 = document.createElement('h4') |
|
||||||
const a = document.createElement('a') |
|
||||||
a.innerText = v |
|
||||||
h4.innerHTML = k |
|
||||||
h4.appendChild(a) |
|
||||||
docDisplay.appendChild(h4) |
|
||||||
return a |
|
||||||
} |
|
||||||
|
|
||||||
const generateAllQueries = (data) => { |
|
||||||
const docTitle = document.querySelector('.doc-title') |
|
||||||
docDisplay.innerHTML = '' |
|
||||||
const back = backArrow() |
|
||||||
docTitle.appendChild(back) |
|
||||||
for (let obj of data.types) { |
|
||||||
for (const [k, _] of Object.entries(removeComments(Object.entries(obj)))) { |
|
||||||
generateContent(k, obj) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const loadRootTypes = async () => { |
|
||||||
const data = await getData('./lib/schema.json') |
|
||||||
for (let v of data.root_types) { |
|
||||||
const h4 = document.createElement('h4') |
|
||||||
const a = document.createElement('a') |
|
||||||
a.addEventListener('click', (event) => changeContent(event, data)) |
|
||||||
|
|
||||||
for (const [k, value] of Object.entries(v)) { |
|
||||||
a.innerText = value |
|
||||||
h4.innerHTML = `${k}: ` |
|
||||||
h4.appendChild(a) |
|
||||||
docDisplay.appendChild(h4) |
|
||||||
} |
|
||||||
} |
|
||||||
const a = generateLinks('all: ', 'all_available_queries') |
|
||||||
a.addEventListener('click', () => generateAllQueries(data)) |
|
||||||
} |
|
||||||
|
|
||||||
const generateContent = (t, data) => { |
|
||||||
docDisplay.innerHTML += `type ${t.toUpperCase()} {` |
|
||||||
for (const [k, v] of Object.entries(data[t])) { |
|
||||||
generateLinks(` ${k}: `, v) |
|
||||||
} |
|
||||||
docDisplay.innerHTML += `}<br><br>` |
|
||||||
if (t === 'query') { |
|
||||||
for (let v of document.getElementsByTagName('a')) { |
|
||||||
v.addEventListener('click', (e) => changeContent(e, data)) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const backArrow = () => { |
|
||||||
const title = document.querySelector('.title') |
|
||||||
const typeDescription = document.querySelector('.comment') |
|
||||||
const contType = document.querySelector('.doc-type') |
|
||||||
const origType = contType.innerText |
|
||||||
const origTitle = title.innerText |
|
||||||
const origTypeDescription = typeDescription.innerText |
|
||||||
const back = document.createElement('img') |
|
||||||
back.className = 'back' |
|
||||||
back.src = backImg |
|
||||||
|
|
||||||
back.addEventListener('click', () => { |
|
||||||
back.remove() |
|
||||||
docDisplay.innerHTML = '' |
|
||||||
title.innerText = origTitle |
|
||||||
contType.innerText = origType |
|
||||||
typeDescription.innerText = origTypeDescription |
|
||||||
loadRootTypes() |
|
||||||
}) |
|
||||||
return back |
|
||||||
} |
|
||||||
|
|
||||||
const allArgs = (data) => { |
|
||||||
for (const [k, v] of Object.entries(data.arguments)) { |
|
||||||
docDisplay.innerHTML += `<hr><h4><b>${k}</b>: <a>(${v.description})</a> // ${v.comment}</h4>Expressions:<br>` |
|
||||||
for (const exp of v.expressions) { |
|
||||||
docDisplay.innerHTML += `<h4>${exp}</h4>` |
|
||||||
} |
|
||||||
docDisplay.innerHTML += `<a>Example: </a><h4>${v.example}</h4><br><br>` |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const changeContent = ({ target }, data) => { |
|
||||||
const title = document.querySelector('.title') |
|
||||||
const typeDescription = document.querySelector('.comment') |
|
||||||
const contType = document.querySelector('.doc-type') |
|
||||||
const docTitle = document.querySelector('.doc-title') |
|
||||||
|
|
||||||
const t = target.innerText |
|
||||||
const back = backArrow() |
|
||||||
|
|
||||||
title.innerText = t.toUpperCase() |
|
||||||
contType.innerText = `${t.toUpperCase()} fields` |
|
||||||
docDisplay.innerHTML = '' |
|
||||||
if (/\[\w*\!\]\!/g.test(t)) { |
|
||||||
const b = t.replace(/\[|\]|\!/g, '') |
|
||||||
const obj = data.types.filter((v) => v[b])[0] |
|
||||||
typeDescription.innerText = obj.comment |
|
||||||
generateContent(b, obj) |
|
||||||
} else if (t === 'arguments') { |
|
||||||
allArgs(data) |
|
||||||
!exist() && docTitle.appendChild(back) |
|
||||||
} else { |
|
||||||
generateContent(t, data) |
|
||||||
!exist() && docTitle.appendChild(back) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
loadRootTypes() |
|
||||||
|
|
||||||
/* search */ |
|
||||||
const updateResult = (dataToSearch, { target }) => { |
|
||||||
docDisplay.innerHTML = '' |
|
||||||
|
|
||||||
dataToSearch.search.map((type) => |
|
||||||
target.value.split(' ').map((w) => { |
|
||||||
if (type.toLowerCase().indexOf(w.toLowerCase()) !== -1) { |
|
||||||
docDisplay.innerHTML += `<li><a class="query-result">${type}</a></li>` |
|
||||||
document |
|
||||||
.querySelectorAll('.query-result') |
|
||||||
.forEach((ele) => |
|
||||||
ele.addEventListener('click', (e) => changeContent(e, dataToSearch)) |
|
||||||
) |
|
||||||
} |
|
||||||
}) |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
const initSearch = async () => { |
|
||||||
const data = await getData('./lib/schema.json') |
|
||||||
const input = document.querySelector('.search') |
|
||||||
|
|
||||||
input.addEventListener('focus', () => { |
|
||||||
const bg = document.querySelector('.back') |
|
||||||
if (!bg) { |
|
||||||
const back = backArrow() |
|
||||||
document.querySelector('.doc-title').appendChild(back) |
|
||||||
} |
|
||||||
docDisplay.innerHTML = '' |
|
||||||
}) |
|
||||||
input.oninput = (e) => updateResult(data, e) |
|
||||||
} |
|
||||||
|
|
||||||
initSearch() |
|
||||||
/*--------------*/ |
|
@ -1,136 +0,0 @@ |
|||||||
{ |
|
||||||
"search": [ |
|
||||||
"[user!]!", |
|
||||||
"[object!]!", |
|
||||||
"[transaction!]!", |
|
||||||
"[progress_view!]!", |
|
||||||
"[result!]!", |
|
||||||
"query", |
|
||||||
"arguments" |
|
||||||
], |
|
||||||
"root_types": [{ "query": "query" }, { "arguments": "arguments" }], |
|
||||||
"query": { |
|
||||||
"user": "[user!]!", |
|
||||||
"object": "[object!]!", |
|
||||||
"transaction": "[transaction!]!", |
|
||||||
"progress_view": "[progress_view!]!", |
|
||||||
"result": "[result!]!" |
|
||||||
}, |
|
||||||
"types": [ |
|
||||||
{ |
|
||||||
"user": { |
|
||||||
"id": "ID!", |
|
||||||
"attrs": "Jsonb!", |
|
||||||
"createdAt": "String!", |
|
||||||
"discordDMChannelId": "String!", |
|
||||||
"discordId": "String!", |
|
||||||
"discordLogin": "String!", |
|
||||||
"githubId": "String!", |
|
||||||
"githubLogin": "String!", |
|
||||||
"profile": "Jsonb!", |
|
||||||
"updatedAt": "String!" |
|
||||||
}, |
|
||||||
"comment": "Fetch data from the table: \"user\"\nThis table will have information about the user" |
|
||||||
}, |
|
||||||
{ |
|
||||||
"object": { |
|
||||||
"id": "ID!", |
|
||||||
"attrs": "Jsonb!", |
|
||||||
"authorId": "String!", |
|
||||||
"childrenAttrs": "String!", |
|
||||||
"createdAt": "String!", |
|
||||||
"externalRelationUrl": "String!", |
|
||||||
"name": "String!", |
|
||||||
"type": "String!", |
|
||||||
"status": "String!", |
|
||||||
"updatedAt": "String!" |
|
||||||
}, |
|
||||||
"comment": "Fetch data from the table: \"object\"\nThis table will give you information about all objects (exercises/projects)" |
|
||||||
}, |
|
||||||
{ |
|
||||||
"transaction": { |
|
||||||
"id": "ID!", |
|
||||||
"attrs": "Jsonb!", |
|
||||||
"amount": "Int!", |
|
||||||
"createdAt": "String!", |
|
||||||
"type": "String!", |
|
||||||
"userId": "Int!" |
|
||||||
}, |
|
||||||
"comment": "Fetch data from the table: \"transaction\"\nThis table will give you access to XP and audits ratio" |
|
||||||
}, |
|
||||||
{ |
|
||||||
"progress_view": { |
|
||||||
"id": "ID!", |
|
||||||
"attrs": "Jsonb!", |
|
||||||
"bestResultId": "Int!", |
|
||||||
"createdAt": "String!", |
|
||||||
"eventId": "Int!", |
|
||||||
"groupId": "Int!", |
|
||||||
"objectId": "Int!", |
|
||||||
"updatedAt": "String!", |
|
||||||
"userId": "Int!" |
|
||||||
}, |
|
||||||
"comment": "Fetch data from the table: \"progress\"\nBoth progress and result table will give you the student progression" |
|
||||||
}, |
|
||||||
{ |
|
||||||
"result": { |
|
||||||
"id": "ID!", |
|
||||||
"progressId": "Int!", |
|
||||||
"attrs": "Jsonb!", |
|
||||||
"createdAt": "String!", |
|
||||||
"grade": "Int!", |
|
||||||
"updatedAt": "String!" |
|
||||||
}, |
|
||||||
"comment": "Fetch data from the table: \"result\"\nBoth progress and result table will give you the student progression" |
|
||||||
} |
|
||||||
], |
|
||||||
"arguments": { |
|
||||||
"where": { |
|
||||||
"description": "bool_exp", |
|
||||||
"expressions": [ |
|
||||||
"_eq (equal)", |
|
||||||
"_gt (grater then)", |
|
||||||
"_gte (grater then equal)", |
|
||||||
"_in (in)", |
|
||||||
"_is_null (boolean)", |
|
||||||
"_lt (lower then)", |
|
||||||
"_lte (lower then equal)", |
|
||||||
"_neq (not equal)", |
|
||||||
"_nin (not in)" |
|
||||||
], |
|
||||||
"example": "user(where: {id: { _eq: x } }){\n id \n}", |
|
||||||
"comment": "filter the rows returned" |
|
||||||
}, |
|
||||||
"order_by": { |
|
||||||
"description": "[order_by!]", |
|
||||||
"expressions": [ |
|
||||||
"asc (ascending)", |
|
||||||
"asc_nulls_first", |
|
||||||
"asc_nulls_last", |
|
||||||
"desc (descending)", |
|
||||||
"desc_nulls_first", |
|
||||||
"asc_nulls_last" |
|
||||||
], |
|
||||||
"example": "user(order_by: {id: desc }){\n id \n}", |
|
||||||
"comment": "sort the rows by one or more columns" |
|
||||||
}, |
|
||||||
"limit": { |
|
||||||
"description": "Int", |
|
||||||
"expressions": ["Int"], |
|
||||||
"example": "user(limit: 1 ){\n id \n}", |
|
||||||
"comment": "limit the number of rows returned" |
|
||||||
}, |
|
||||||
"distinct_on": { |
|
||||||
"description": "column name", |
|
||||||
"expressions": ["column name"], |
|
||||||
"example": "object(distinct_on: name, where: { name:{ _eq:\"forum\" } }){\n name \n}", |
|
||||||
"comment": "distinct select on columns" |
|
||||||
}, |
|
||||||
"offset": { |
|
||||||
"description": "int", |
|
||||||
"expressions": ["Int"], |
|
||||||
"example": "object(distinct_on: name, where: { name:{ _eq:\"forum\" } }){\n name\n }", |
|
||||||
"comment": "skip the first n rows by one or more columns" |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue