Add current project
This commit is contained in:
parent
61df06fa4e
commit
44f29bf758
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.vscode/
|
||||||
|
lib/
|
||||||
|
info.php
|
18
README.md
18
README.md
|
@ -1 +1,17 @@
|
||||||
SnippetManager
|
# Snippet Manager
|
||||||
|
|
||||||
|
An instance of this site is hosted at [snippets.neilbrommer.com](https://snippets.neilbrommer.com)
|
||||||
|
|
||||||
|
A tool for keeping pieces of useful code and programming resources.
|
||||||
|
|
||||||
|
Includes a RESTful API and a web client.
|
||||||
|
|
||||||
|
There is currently no login system; all data is public.
|
||||||
|
|
||||||
|
## Libraries
|
||||||
|
|
||||||
|
[JQuery](https://jquery.com/)
|
||||||
|
|
||||||
|
[Popper.js](https://popper.js.org/)
|
||||||
|
|
||||||
|
[Bootstrap](https://getbootstrap.com/)
|
||||||
|
|
55
css/multiTable.css
Normal file
55
css/multiTable.css
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
.navbar {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
padding-bottom: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
tab-size: 4;
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
background-color: rgb(245, 245, 245);
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.langList {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addSection {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.snippetBody {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.requiredField {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#successAlert {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
padding-top: 7px;
|
||||||
|
padding-bottom: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.langSelect {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tablesImg {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resultsContainer {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
background-color: rgb(245, 245, 245);
|
||||||
|
max-height: 600px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
139
css/prism.css
Normal file
139
css/prism.css
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+abap+actionscript+ada+apacheconf+apl+applescript+c+asciidoc+aspnet+autohotkey+autoit+bash+basic+batch+bison+brainfuck+bro+cpp+csharp+arduino+coffeescript+ruby+css-extras+d+dart+django+diff+docker+eiffel+elixir+erlang+fsharp+flow+fortran+gherkin+git+glsl+go+graphql+groovy+haml+handlebars+haskell+haxe+http+icon+inform7+ini+j+java+jolie+json+julia+keyman+kotlin+latex+less+livescript+lolcode+lua+makefile+markdown+matlab+mel+mizar+monkey+n4js+nasm+nginx+nim+nix+nsis+objectivec+ocaml+opencl+oz+parigp+parser+pascal+perl+php+php-extras+powershell+processing+prolog+properties+protobuf+pug+puppet+pure+python+q+qore+r+jsx+renpy+reason+rest+rip+roboconf+crystal+rust+sas+sass+scss+scala+scheme+smalltalk+smarty+sql+stylus+swift+tcl+textile+twig+typescript+vbnet+verilog+vhdl+vim+wiki+xojo+yaml */
|
||||||
|
/**
|
||||||
|
* prism.js default theme for JavaScript, CSS and HTML
|
||||||
|
* Based on dabblet (http://dabblet.com)
|
||||||
|
* @author Lea Verou
|
||||||
|
*/
|
||||||
|
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
color: black;
|
||||||
|
background: none;
|
||||||
|
text-shadow: 0 1px white;
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||||
|
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||||
|
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
pre[class*="language-"] {
|
||||||
|
padding: 1em;
|
||||||
|
margin: .5em 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre) > code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
background: #f5f2f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
:not(pre) > code[class*="language-"] {
|
||||||
|
padding: .1em;
|
||||||
|
border-radius: .3em;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.comment,
|
||||||
|
.token.prolog,
|
||||||
|
.token.doctype,
|
||||||
|
.token.cdata {
|
||||||
|
color: slategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.punctuation {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.namespace {
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.property,
|
||||||
|
.token.tag,
|
||||||
|
.token.boolean,
|
||||||
|
.token.number,
|
||||||
|
.token.constant,
|
||||||
|
.token.symbol,
|
||||||
|
.token.deleted {
|
||||||
|
color: #905;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.selector,
|
||||||
|
.token.attr-name,
|
||||||
|
.token.string,
|
||||||
|
.token.char,
|
||||||
|
.token.builtin,
|
||||||
|
.token.inserted {
|
||||||
|
color: #690;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.operator,
|
||||||
|
.token.entity,
|
||||||
|
.token.url,
|
||||||
|
.language-css .token.string,
|
||||||
|
.style .token.string {
|
||||||
|
color: #a67f59;
|
||||||
|
background: hsla(0, 0%, 100%, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.atrule,
|
||||||
|
.token.attr-value,
|
||||||
|
.token.keyword {
|
||||||
|
color: #07a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.function {
|
||||||
|
color: #DD4A68;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.regex,
|
||||||
|
.token.important,
|
||||||
|
.token.variable {
|
||||||
|
color: #e90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.important,
|
||||||
|
.token.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.token.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
|
13
dbTools.php
Normal file
13
dbTools.php
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
function buildPDO() {
|
||||||
|
include_once "info.php";
|
||||||
|
|
||||||
|
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
|
||||||
|
$opt = [
|
||||||
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||||
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||||
|
PDO::ATTR_EMULATE_PREPARES => false,
|
||||||
|
];
|
||||||
|
return new PDO($dsn, $user, $pass, $opt);
|
||||||
|
}
|
||||||
|
?>
|
413
documentation.html
Normal file
413
documentation.html
Normal file
|
@ -0,0 +1,413 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="A new tab page">
|
||||||
|
<meta name="author" content="Neil Brommer">
|
||||||
|
<link rel="icon" href="favicon.ico">
|
||||||
|
|
||||||
|
<title>Documentation - Multi-Table Service</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="lib/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles -->
|
||||||
|
<link href="css/multiTable.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="wrapper" class="container">
|
||||||
|
<nav class="navbar rounded navbar-expand-md navbar-dark bg-dark mb-4">
|
||||||
|
<a class="navbar-brand" href="#">Snippets</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse"
|
||||||
|
aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||||
|
<ul class="navbar-nav mr-auto">
|
||||||
|
<li>
|
||||||
|
<a class="nav-link" href="index.html">Web Client</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="nav-link active" href="documentation.html">API</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<form class="form-inline mt-2 mt-md-0">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<h1>About</h1>
|
||||||
|
<p>
|
||||||
|
This app keeps a set of code snippets and programming resources categorized by language/library.
|
||||||
|
Each snippet or resource can be associated with multiple languages and vice versa.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Features I plan to add to the backend:</p>
|
||||||
|
<ul>
|
||||||
|
<li>A login system</li>
|
||||||
|
<li>Add a column for snippets to indicate the language the snippet is written in</li>
|
||||||
|
<li>Search</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Features I plan to add to the web client:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Syntax highlighting via <a href="http://prismjs.com/" target="_blamk">Prism</a></li>
|
||||||
|
<li>When a single language is selected, show all related snippets and resources</li>
|
||||||
|
<li>Deep linking</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>Tables</h1>
|
||||||
|
<p>There are three main tables:</p>
|
||||||
|
<ul>
|
||||||
|
<li>language</li>
|
||||||
|
<li>snippet</li>
|
||||||
|
<li>resource</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>And three tables used to link these tables together:</p>
|
||||||
|
<ul>
|
||||||
|
<li>langLang</li>
|
||||||
|
<li>langSnippet</li>
|
||||||
|
<li>langResource</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<img id="tablesImg" src="tables.png" class="img-fluid rounded my-3 p-2 border">
|
||||||
|
|
||||||
|
<p>Each of the three main tables has a corresponding API endpoint (off of the base URL webdev.neilbrommer.com/multiTable/):</p>
|
||||||
|
<ul>
|
||||||
|
<li>lang.php</li>
|
||||||
|
<li>snippet.php</li>
|
||||||
|
<li>resource.php</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1>API</h1>
|
||||||
|
<p>
|
||||||
|
Each of the endpoints is off of the base URL of <u>https://webdev.neilbrommer.com/multiTable/</u>.
|
||||||
|
SSL is required.
|
||||||
|
</p>
|
||||||
|
<p>Arguments that are <u>underlined</u> are optional.</p>
|
||||||
|
|
||||||
|
<h3 class="mt-5">lang.php</h3>
|
||||||
|
<p>For managing the list of languages.</p>
|
||||||
|
|
||||||
|
<div class="row border mb-4 rounded">
|
||||||
|
<form id="languageForm" class="py-3 col-md-4">
|
||||||
|
<p>webdev.neilbrommer.com<wbr>/multiTable<wbr>/lang.php</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<select id="languageType" class="custom-select">
|
||||||
|
<option value="GET" selected>GET</option>
|
||||||
|
<option value="POST">POST</option>
|
||||||
|
<option value="PUT">PUT</option>
|
||||||
|
<option value="DELETE">DELETE</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="languageLangID">langID</label>
|
||||||
|
<input id="languageLangID" type="number" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="languageLangName">langName</label>
|
||||||
|
<input id="languageLangName" type="text" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="languageLangDesc">langDescription</label>
|
||||||
|
<input id="languageLangDesc" type="text" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="languageAssocLang">associatedLang</label>
|
||||||
|
<input id="languageAssocLang" type="number" class="form-control">
|
||||||
|
</div>
|
||||||
|
<button id="languageSubmit" type="submit" class="btn btn-primary">Submit</button>
|
||||||
|
</form>
|
||||||
|
<pre class="col-md-8 p-1 resultsContainer"><code id="languageResults">Results will appear here</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>GET</dt>
|
||||||
|
<dd>
|
||||||
|
<p>
|
||||||
|
Each of these returns a JSON object with <code>langID</code>, <code>langName</code>, <code>langDescription</code>,
|
||||||
|
a list of related <code>languages</code>, a list of <code>snippets</code>, and a list of <code>resources</code>.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
No arguments: returns all language entries.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>langID</code> (number): returns the specified language.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>POST</dt>
|
||||||
|
<p>Returns the <code>langID</code> of the new entry.</p>
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>langName</code> (string), <u><code>langDescription</code></u> (string), <u><code>associatedLang</code></u>
|
||||||
|
(number): Creates a new language with the specified information. <code>associatedLang</code> is the
|
||||||
|
<code>langID</code> of the language you want to link to the one being created. More languages can be linked later
|
||||||
|
via <code>PUT</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>PUT</dt>
|
||||||
|
<p>Returns no data.</p>
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>langID</code> (number), <u><code>langName</code></u> (string), <u><code>langDescription</code></u>
|
||||||
|
(string), <u><code>associatedLang</code></u> (number): Modifies any provided fields for the language
|
||||||
|
specified by the <code>langID</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>DELETE</dt>
|
||||||
|
<p>Returns no data.</p>
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>langID</code> (number): Deletes the specified language entry, including all connections to snippets,
|
||||||
|
resources, and other languages.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>langID</code> (number), <code>associatedLang</code> (number): Removes the connection between the two
|
||||||
|
specified languages.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<h3 class="mt-5">snippet.php</h3>
|
||||||
|
<p>For managing the list of snippets.</p>
|
||||||
|
|
||||||
|
<div class="row border mb-4 rounded">
|
||||||
|
<form id="snippetForm" class="py-3 col-md-4">
|
||||||
|
<p class="wrapping">webdev.neilbrommer.com<wbr>/multiTable<wbr>/snippet.php</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<select id="snippetType" class="custom-select">
|
||||||
|
<option value="GET" selected>GET</option>
|
||||||
|
<option value="POST">POST</option>
|
||||||
|
<option value="PUT">PUT</option>
|
||||||
|
<option value="DELETE">DELETE</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="snippetSnippetID">snippetID</label>
|
||||||
|
<input id="snippetSnippetID" type="number" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="snippetSnippetName">snippetName</label>
|
||||||
|
<input id="snippetSnippetName" type="text" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="snippetSnippetDesc">snippetDescription</label>
|
||||||
|
<input id="snippetSnippetDesc" type="text" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="snippetSnippetBody">snippet</label>
|
||||||
|
<textarea id="snippetSnippetBody" class="form-control"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="snippetLangID">langID</label>
|
||||||
|
<input id="snippetLangID" type="number" class="form-control">
|
||||||
|
</div>
|
||||||
|
<button id="snippetSubmit" type="submit" class="btn btn-primary">Submit</button>
|
||||||
|
</form>
|
||||||
|
<pre class="col-md-8 p-1 resultsContainer"><code id="snippetResults">Results will appear here</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>GET</dt>
|
||||||
|
<dd>
|
||||||
|
<p>
|
||||||
|
Each of these returns a JSON object with <code>snippetID</code>, <code>snippetName</code>,
|
||||||
|
<code>snippetDescription</code>, <code>snippet</code>, and a list of related <code>languages</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
No arguments: Returns a list of all snippets.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>snippetID</code> (number): Returns the entry for the specified language.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>langID</code> (number): Returns a list of snippets related to the given language.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>POST</dt>
|
||||||
|
<dd>
|
||||||
|
<p>Returns the <code>snippetID</code> of the new snippet.</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>snippetName</code> (string), <u><code>langID</code></u> (number),
|
||||||
|
<u><code>snippetDescription</code></u> (string), <u><code>snippet</code></u> (string):
|
||||||
|
Creates a new snippet with the given values.
|
||||||
|
|
||||||
|
Only one language can be associated with a snippet at creation. More can be added later via
|
||||||
|
<code>PUT</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>PUT</dt>
|
||||||
|
<dd>
|
||||||
|
<p>Returns nothing</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>snippetID</code> (number), <u><code>langID</code></u> (number),
|
||||||
|
<u><code>snippetName</code></u> (string), <u><code>snippetDescription</code></u> (string),
|
||||||
|
<u><code>snippet</code></u> (string): Modifies the specified information.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>DELETE</dt>
|
||||||
|
<dd>
|
||||||
|
<p>Returns nothing</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>snippetID</code> (number): Deletes the entry for the specified snippet.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>snippetID</code> (number), <code>langID</code> (number): Removes the connection between
|
||||||
|
the specified snippet and language.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<h3 class="mt-5">resource.php</h3>
|
||||||
|
<p>For managing the list of resources.</p>
|
||||||
|
<p>
|
||||||
|
The API for resource.php is nearly identical to the one for snippet.php with <code>resourceLink</code>
|
||||||
|
in place of <code>snippet</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="row border mb-4 rounded">
|
||||||
|
<form id="resourceForm" class="py-3 col-md-4">
|
||||||
|
<p class="wrapping">webdev.neilbrommer.com<wbr>/multiTable<wbr>/resource.php</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<select id="resourceType" class="custom-select">
|
||||||
|
<option value="GET" selected>GET</option>
|
||||||
|
<option value="POST">POST</option>
|
||||||
|
<option value="PUT">PUT</option>
|
||||||
|
<option value="DELETE">DELETE</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="resourceResourceID">resourceID</label>
|
||||||
|
<input id="resourceResourceID" type="number" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="resourceResourceName">resourceName</label>
|
||||||
|
<input id="resourceResourceName" type="text" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="resourceResourceDesc">resourceDescription</label>
|
||||||
|
<input id="resourceResourceDesc" type="text" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="resourceResourceLink">resourceLink</label>
|
||||||
|
<input id="resourceResourceLink" type="url" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="resourceLangID">langID</label>
|
||||||
|
<input id="resourceLangID" type="number" class="form-control">
|
||||||
|
</div>
|
||||||
|
<button id="resourceSubmit" type="submit" class="btn btn-primary">Submit</button>
|
||||||
|
</form>
|
||||||
|
<pre class="col-md-8 p-1 resultsContainer"><code id="resourceResults">Results will appear here</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>GET</dt>
|
||||||
|
<dd>
|
||||||
|
<p>
|
||||||
|
Returns JSON encoded resources with a <code>resourceID</code>, a <code>resourceName</code>, a
|
||||||
|
<code>resourceDescription</code>, a <code>resourceLink</code>, and a list of related
|
||||||
|
<code>languages</code>.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
No arguments: Returns a list of all resource entries.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>langID</code> (number): Returns a list of resources related to the specified language.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>resourceID</code> (number): Returns the specified resource entry.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>POST</dt>
|
||||||
|
<dd>
|
||||||
|
<p>
|
||||||
|
Returns the <code>resourceID</code> of the newly created resource.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>resourceName</code> (string), <u><code>langID</code></u> (number),
|
||||||
|
<u><code>resourceDescription</code></u> (string), and <u><code>resourceLink</code></u> (string):
|
||||||
|
Creates a resource with the given information.
|
||||||
|
|
||||||
|
Only one language can be associated at creation. More can be added via <code>PUT</code>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>PUT</dt>
|
||||||
|
<dd>
|
||||||
|
<p>Returns nothing.</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>resourceID</code> (number), <u><code>resourceName</code></u> (string),
|
||||||
|
<u><code>langID</code></u> (number), <u><code>resourceDescription</code></u> (string), and
|
||||||
|
<u><code>resourceLink</code></u> (string): Modifies the specified data for the specified
|
||||||
|
resource.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>DELETE</dt>
|
||||||
|
<dd>
|
||||||
|
<p>Returns nothing.</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>resourceID</code> (number): Deletes the specified resource.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>resourceID</code> (number), <code>langID</code> (number): Removes the connection between
|
||||||
|
the specified resource and language.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="lib/jquery/jquery-3.2.1.min.js"></script>
|
||||||
|
<script src="lib/popper/popper.js"></script>
|
||||||
|
<script src="lib/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
|
||||||
|
<!-- custom JavaScript -->
|
||||||
|
<script src="js/docs.js"></script>
|
||||||
|
</body>
|
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
362
index.html
Normal file
362
index.html
Normal file
|
@ -0,0 +1,362 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="A new tab page">
|
||||||
|
<meta name="author" content="Neil Brommer">
|
||||||
|
<link rel="icon" href="favicon.ico">
|
||||||
|
|
||||||
|
<title>Multi-Table Service</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="lib/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles -->
|
||||||
|
<link href="css/multiTable.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="wrapper" class="container">
|
||||||
|
<nav class="navbar rounded navbar-expand-md navbar-dark bg-dark mb-4">
|
||||||
|
<a class="navbar-brand" href="#">Snippets</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse"
|
||||||
|
aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||||
|
<ul class="navbar-nav mr-auto">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a id="langLink" class="nav-link active" href="#">Languages</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a id="snippetLink" class="nav-link" href="#">Snippets</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a id="resourceLink" class="nav-link" href="#">Resources</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="nav-link" href="documentation.html">API</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<form class="form-inline mt-2 mt-md-0">
|
||||||
|
<button class="btn btn-primary ml-sm-2" type="button" data-toggle="modal" data-target="#addModal">Add</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div id="successAlert" class="alert alert-success"></div>
|
||||||
|
|
||||||
|
<div id="mainList">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="addModal" class="modal fade" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Add Item</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<ul class="nav nav-tabs" id="tabContent">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a id="addLangTab" class="nav-link active" href="#addLang" data-toggle="tab">Language</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a id="addSnippetTab" class="nav-link" href="#addSnippet" data-toggle="tab">Snippet</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a id="addResourceTab" class="nav-link" href="#addResource" data-toggle="tab">Resource</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="tab-content">
|
||||||
|
<div id="addLang" class="addSection tab-pane fade show active">
|
||||||
|
<form id="formAddLang">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="txtLangName">Name</label>
|
||||||
|
<input id="txtLangName" type="text" class="form-control addField" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="selectLangLangs">Languages</label>
|
||||||
|
<button type="button" class="btn btn-info btn-sm float-right clearLangSelect">Clear</button>
|
||||||
|
<select id="selectLangLangs" class="custom-select langSelect" multiple size="9"></select>
|
||||||
|
<small class="form-text text-muted">Hold Ctrl to select multiple</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="txtLangDesc">Description</label>
|
||||||
|
<textarea id="txtLangDesc" class="form-control addField"></textarea>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="addSnippet" class="addSection tab-pane fade">
|
||||||
|
<form id="formAddSnippet">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="txtSnippetName">Name</label>
|
||||||
|
<input id="txtSnippetName" type="text" class="form-control addField" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="selectSnippetLangs">Languages</label>
|
||||||
|
<button type="button" class="btn btn-info btn-sm float-right clearLangSelect">Clear</button>
|
||||||
|
<select id="selectSnippetLangs" class="custom-select langSelect" multiple size="9"></select>
|
||||||
|
<small class="form-text text-muted">Hold Ctrl to select multiple</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="txtSnippetDesc">Description</label>
|
||||||
|
<textarea id="txtSnippetDesc" class="form-control addField"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="txtSnippetBody">Snippet</label>
|
||||||
|
<textarea id="txtSnippetBody" class="form-control addField snippetBody" rows="10" wrap="off"></textarea>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="addResource" class="addSection tab-pane fade">
|
||||||
|
<form id="formAddResource">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="txtResourceName">Name</label>
|
||||||
|
<input id="txtResourceName" type="text" class="form-control addField" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="selectResourceLangs">Languages</label>
|
||||||
|
<button type="button" class="btn btn-info btn-sm float-right clearLangSelect">Clear</button>
|
||||||
|
<select id="selectResourceLangs" class="custom-select langSelect" multiple size="9"></select>
|
||||||
|
<small class="form-text text-muted">Hold Ctrl to select multiple</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="txtResourceDesc">Description</label>
|
||||||
|
<textarea id="txtResourceDesc" class="form-control addField"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="txtResourceLink">Link</label>
|
||||||
|
<input id="txtResourceLink" type="url" class="form-control addField">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="btnAddItem" type="button" class="btn btn-primary">Add</button>
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="editLangModal" class="modal fade" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Edit Language</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="formEditLang">
|
||||||
|
<input id="editLangID" type="hidden">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" id="editLangNameChk" class="custom-control-input editChk" data-for="#txtEditLangName">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">Name</span>
|
||||||
|
</label>
|
||||||
|
<input id="txtEditLangName" type="text" class="form-control editField" disabled>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" id="editLangLangsChk" class="custom-control-input editChk" data-for="#selectEditLangLangs">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">Languages</span>
|
||||||
|
</label>
|
||||||
|
<button type="button" class="btn btn-info btn-sm float-right clearLangSelect">Clear</button>
|
||||||
|
<select id="selectEditLangLangs" class="custom-select editField langSelect" multiple size="9" disabled></select>
|
||||||
|
<small class="form-text text-muted">Hold Ctrl to select multiple</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" id="editLangDescChk" class="custom-control-input editChk" data-for="#txtEditLangDesc">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">Description</span>
|
||||||
|
</label>
|
||||||
|
<textarea id="txtEditLangDesc" class="form-control editField" disabled></textarea>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="btnSaveLang" type="button" class="btn btn-primary">Save</button>
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="editSnippetModal" class="modal fade" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Edit Snippet</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="formEditSnippet">
|
||||||
|
<input id="editSnippetID" type="hidden">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" id="editSnippetNameChk" class="custom-control-input editChk" data-for="#txtEditSnippetName">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">Name</span>
|
||||||
|
</label>
|
||||||
|
<input id="txtEditSnippetName" type="text" class="form-control editField" disabled>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" id="editSnippetLangsChk" class="custom-control-input editChk" data-for="#selectEditSnippetLangs">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">Languages</span>
|
||||||
|
</label>
|
||||||
|
<button type="button" class="btn btn-info btn-sm float-right clearLangSelect">Clear</button>
|
||||||
|
<select id="selectEditSnippetLangs" class="custom-select editField langSelect" multiple size="9" disabled></select>
|
||||||
|
<small class="form-text text-muted">Hold Ctrl to select multiple</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" id="editSnippetDescChk" class="custom-control-input editChk" data-for="#txtEditSnippetDesc">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">Description</span>
|
||||||
|
</label>
|
||||||
|
<textarea id="txtEditSnippetDesc" class="form-control editField" disabled></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" id="editSnippetBodyChk" class="custom-control-input editChk" data-for="#txtEditSnippetBody">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">Snippet</span>
|
||||||
|
</label>
|
||||||
|
<textarea id="txtEditSnippetBody" class="form-control snippetBody editField" rows="10" wrap="off" disabled></textarea>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="btnSaveSnippet" type="button" class="btn btn-primary">Save</button>
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="editResourceModal" class="modal fade" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Edit Resource</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="formEditResource">
|
||||||
|
<input id="editResourceID" type="hidden">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" id="editResourceNameChk" class="custom-control-input editChk" data-for="#txtEditResourceName">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">Name</span>
|
||||||
|
</label>
|
||||||
|
<input id="txtEditResourceName" type="text" class="form-control editField" disabled>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" id="editResourceLangsChk" class="custom-control-input editChk" data-for="#selectEditResourceLangs">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">Languages</span>
|
||||||
|
</label>
|
||||||
|
<button type="button" class="btn btn-info btn-sm float-right clearLangSelect">Clear</button>
|
||||||
|
<select id="selectEditResourceLangs" class="custom-select editField langSelect" multiple size="9" disabled></select>
|
||||||
|
<small class="form-text text-muted">Hold Ctrl to select multiple</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" id="editResourceDescChk" class="custom-control-input editChk" data-for="#txtEditResourceDesc">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">Description</span>
|
||||||
|
</label>
|
||||||
|
<textarea id="txtEditResourceDesc" class="form-control editField" disabled></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input type="checkbox" id="editResourceLinkChk" class="custom-control-input editChk" data-for="#txtEditResourceLink">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">Link</span>
|
||||||
|
</label>
|
||||||
|
<input id="txtEditResourceLink" type="url" class="form-control editField" disabled>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="btnSaveResource" type="button" class="btn btn-primary">Save</button>
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="confirmDeleteModal" class="modal fade" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Confirm Delete</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p id="deleteText">Are you sure?</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="btnConfirmDelete" type="button" class="btn btn-danger">Delete</button>
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="errorModal" class="modal fade" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header text-white bg-danger">
|
||||||
|
<h5 class="modal-title">Error</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p id="errorText">ERROR</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="lib/jquery/jquery-3.2.1.min.js"></script>
|
||||||
|
<script src="lib/popper/popper.js"></script>
|
||||||
|
<script src="lib/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="js/main.js"></script>
|
||||||
|
|
||||||
|
</body>
|
174
js/docs.js
Normal file
174
js/docs.js
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
$(document).ready(function () {
|
||||||
|
$("#languageForm").submit(languageSubmit);
|
||||||
|
$("#snippetForm").submit(snippetSubmit);
|
||||||
|
$("#resourceForm").submit(resourceSubmit);
|
||||||
|
});
|
||||||
|
|
||||||
|
function languageSubmit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var type = $("#languageType").val();
|
||||||
|
var data = {};
|
||||||
|
|
||||||
|
if (type == "GET" || type == "DELETE") {
|
||||||
|
var langID = $("#languageLangID").val();
|
||||||
|
var assoc = $("#languageAssocLang").val();
|
||||||
|
|
||||||
|
if (langID != "")
|
||||||
|
data['langID'] = langID;
|
||||||
|
if (assoc != "")
|
||||||
|
data['associatedLang'] = assoc;
|
||||||
|
} else if (type == "POST") {
|
||||||
|
var langName = $("#languageLangName").val();
|
||||||
|
var langDesc = $("#languageLangDesc").val();
|
||||||
|
var assoc = $("#languageAssocLang").val();
|
||||||
|
|
||||||
|
if (langName != "")
|
||||||
|
data['langName'] = langName;
|
||||||
|
if (langDesc != "")
|
||||||
|
data['langDescription'] = langDesc;
|
||||||
|
if (assoc != "")
|
||||||
|
data['associatedLang'] = assoc;
|
||||||
|
} else { // PUT
|
||||||
|
var langID = $("#languageLangID").val();
|
||||||
|
var langName = $("#languageLangName").val();
|
||||||
|
var langDesc = $("#languageLangDesc").val();
|
||||||
|
var assoc = $("#languageAssocLang").val();
|
||||||
|
|
||||||
|
if (langID != "")
|
||||||
|
data['langID'] = langID;
|
||||||
|
if (langName != "")
|
||||||
|
data['langName'] = langName;
|
||||||
|
if (langDesc != "")
|
||||||
|
data['langDescription'] = langDesc;
|
||||||
|
if (assoc != "")
|
||||||
|
data['associatedLang'] = assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeRequest(type, "lang.php", data, $("#languageResults"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function snippetSubmit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var type = $("#snippetType").val();
|
||||||
|
var data = {};
|
||||||
|
|
||||||
|
if (type == "GET" || type == "DELETE") {
|
||||||
|
var snippetID = $("#snippetSnippetID").val();
|
||||||
|
var assoc = $("#snippetLangID").val();
|
||||||
|
|
||||||
|
if (snippetID != "")
|
||||||
|
data['snippetID'] = snippetID;
|
||||||
|
if (assoc != "")
|
||||||
|
data['langID'] = assoc;
|
||||||
|
} else if (type == "POST") {
|
||||||
|
var snippetName = $("#snippetSnippetName").val();
|
||||||
|
var snippetDesc = $("#snippetSnippetDesc").val();
|
||||||
|
var body = $("#snippetSnippetBody").val();
|
||||||
|
var assoc = $("#snippetLangID").val();
|
||||||
|
|
||||||
|
if (snippetName != "")
|
||||||
|
data['snippetName'] = snippetName;
|
||||||
|
if (snippetDesc != "")
|
||||||
|
data['snippetDescription'] = snippetDesc;
|
||||||
|
if (body != "")
|
||||||
|
data['snippet'] = body;
|
||||||
|
if (assoc != "")
|
||||||
|
data['langID'] = assoc;
|
||||||
|
} else { // PUT
|
||||||
|
var snippetID = $("#snippetSnippetID").val();
|
||||||
|
var snippetName = $("#snippetSnippetName").val();
|
||||||
|
var snippetDesc = $("#snippetSnippetDesc").val();
|
||||||
|
var body = $("#snippetSnippetBody").val();
|
||||||
|
var assoc = $("#snippetLangID").val();
|
||||||
|
|
||||||
|
if (snippetID != "")
|
||||||
|
data['snippetID'] = snippetID;
|
||||||
|
if (snippetName != "")
|
||||||
|
data['snippetName'] = snippetName;
|
||||||
|
if (snippetDesc != "")
|
||||||
|
data['snippetDescription'] = snippetDesc;
|
||||||
|
if (body != "")
|
||||||
|
data['snippet'] = body;
|
||||||
|
if (assoc != "")
|
||||||
|
data['langID'] = assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeRequest(type, "snippet.php", data, $("#snippetResults"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function resourceSubmit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var type = $("#resourceType").val();
|
||||||
|
var data = {};
|
||||||
|
|
||||||
|
if (type == "GET" || type == "DELETE") {
|
||||||
|
var resourceID = $("#resourceResourceID").val();
|
||||||
|
var assoc = $("#resourceLangID").val();
|
||||||
|
|
||||||
|
if (resourceID != "")
|
||||||
|
data['resourceID'] = resourceID;
|
||||||
|
if (assoc != "")
|
||||||
|
data['langID'] = assoc;
|
||||||
|
} else if (type == "POST") {
|
||||||
|
var resourceName = $("#resourceResourceName").val();
|
||||||
|
var resourceDesc = $("#resourceResourceDesc").val();
|
||||||
|
var link = $("#resourceResourceLink").val();
|
||||||
|
var assoc = $("#resourceLangID").val();
|
||||||
|
|
||||||
|
if (resourceName != "")
|
||||||
|
data['resourceName'] = resourceName;
|
||||||
|
if (resourceDesc != "")
|
||||||
|
data['resourceDescription'] = resourceDesc;
|
||||||
|
if (link != "")
|
||||||
|
data['resourceLink'] = link;
|
||||||
|
if (assoc != "")
|
||||||
|
data['langID'] = assoc;
|
||||||
|
} else { // PUT
|
||||||
|
var resourceID = $("#resourceResourceID").val();
|
||||||
|
var resourceName = $("#resourceResourceName").val();
|
||||||
|
var resourceDesc = $("#resourceResourceDesc").val();
|
||||||
|
var link = $("#resourceResourceLink").val();
|
||||||
|
var assoc = $("#resourceLangID").val();
|
||||||
|
|
||||||
|
if (resourceID != "")
|
||||||
|
data['resourceID'] = resourceID;
|
||||||
|
if (resourceName != "")
|
||||||
|
data['resourceName'] = resourceName;
|
||||||
|
if (resourceDesc != "")
|
||||||
|
data['resourceDescription'] = resourceDesc;
|
||||||
|
if (link != "")
|
||||||
|
data['resourceLink'] = link;
|
||||||
|
if (assoc != "")
|
||||||
|
data['langID'] = assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
makeRequest(type, "resource.php", data, $("#resourceResults"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeRequest(type, endpoint, data, resultsSection) {
|
||||||
|
$.ajax({
|
||||||
|
url: endpoint,
|
||||||
|
type: type,
|
||||||
|
data: data,
|
||||||
|
success: function (res, status, xhr) { insertSuccess(res, xhr, resultsSection); },
|
||||||
|
error: function (xhr, status, err) { insertError(xhr, resultsSection); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertSuccess(results, xhr, resultsSection) {
|
||||||
|
var str = xhr.getAllResponseHeaders() + "\r\nStatus Code: " + xhr.status + " " + xhr.statusText;
|
||||||
|
if (results != null) {
|
||||||
|
if (typeof results === 'string' || results instanceof String)
|
||||||
|
str += "\r\n\r\n" + results;
|
||||||
|
else
|
||||||
|
str += "\r\n\r\n" + JSON.stringify(results, null, 4);
|
||||||
|
}
|
||||||
|
resultsSection.text(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertError(xhr, resultsSection) {
|
||||||
|
var str = xhr.getAllResponseHeaders() + "\r\nStatus Code: " + xhr.status + " " + xhr.statusText;
|
||||||
|
if (xhr.responseText != null)
|
||||||
|
str += "\r\n\r\n" + xhr.responseText;
|
||||||
|
resultsSection.text(str);
|
||||||
|
}
|
739
js/main.js
Normal file
739
js/main.js
Normal file
|
@ -0,0 +1,739 @@
|
||||||
|
var selectList = [];
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
loadLangs();
|
||||||
|
|
||||||
|
$("#langLink").click(function (evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
loadLangs();
|
||||||
|
});
|
||||||
|
$("#snippetLink").click(function (evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
loadSnippets();
|
||||||
|
});
|
||||||
|
$("#resourceLink").click(function (evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
loadResources();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#addModal").on("show.bs.modal", function (e) {
|
||||||
|
$("#addLangTab").tab("show");
|
||||||
|
$(".addField").val("");
|
||||||
|
buildLangSelect();
|
||||||
|
});
|
||||||
|
$("#editLangModal").on("shown.bs.modal", function (e) { $(".langSelect").val(selectList); });
|
||||||
|
$("#editSnippetModal").on("shown.bs.modal", function (e) { $(".langSelect").val(selectList); });
|
||||||
|
$("#editResourceModal").on("shown.bs.modal", function (e) { $(".langSelect").val(selectList); });
|
||||||
|
$("#addModal").on("shown.bs.modal", function (e) { $("#txtLangName").focus(); });
|
||||||
|
$("#addLangTab").on("shown.bs.tab", function (e) { $("#txtLangName").focus(); });
|
||||||
|
$("#addSnippetTab").on("shown.bs.tab", function (e) { $("#txtSnippetName").focus(); });
|
||||||
|
$("#addResourceTab").on("shown.bs.tab", function (e) { $("#txtResourceName").focus(); });
|
||||||
|
|
||||||
|
$("#btnAddItem").click(addNewItem);
|
||||||
|
$("#btnSaveLang").click(saveLang);
|
||||||
|
$("#btnSaveSnippet").click(saveSnippet);
|
||||||
|
$("#btnSaveResource").click(saveResource);
|
||||||
|
$(".clearLangSelect").click(function () { $(".langSelect").val([]); });
|
||||||
|
|
||||||
|
$(".editChk").change(checkBoxChange);
|
||||||
|
});
|
||||||
|
|
||||||
|
function buildLangSelect() {
|
||||||
|
$.ajax({
|
||||||
|
url: "lang.php",
|
||||||
|
type: "GET",
|
||||||
|
success: addSelectLangs,
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSelectLangs(langList) {
|
||||||
|
var selectors = $(".langSelect");
|
||||||
|
selectors.empty();
|
||||||
|
for (var i = 0; i < langList.length; i++) {
|
||||||
|
var cur = langList[i];
|
||||||
|
$("<option>").val(cur.langID).text(cur.langName).appendTo(selectors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkBoxChange() {
|
||||||
|
var me = $(this);
|
||||||
|
$(me.data("for")).attr("disabled", !me.prop("checked"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNewItem() {
|
||||||
|
if ($("#addLangTab").hasClass("active")) {
|
||||||
|
if ($("#formAddLang")[0].checkValidity()) {
|
||||||
|
var data = {};
|
||||||
|
data['langName'] = $("#txtLangName").val().trim();
|
||||||
|
|
||||||
|
if ($("#txtLangDesc").val().trim() != "") {
|
||||||
|
data['langDescription'] = $("#txtLangDesc").val().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
var langs = $("#selectLangLangs").val();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "lang.php",
|
||||||
|
type: "POST",
|
||||||
|
data: data,
|
||||||
|
success: function (res) { addLangLangs(res, data['langName'], langs); },
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if ($("#addSnippetTab").hasClass("active")) {
|
||||||
|
if ($("#formAddSnippet")[0].checkValidity()) {
|
||||||
|
var data = {};
|
||||||
|
data['snippetName'] = $("#txtSnippetName").val().trim();
|
||||||
|
if ($("#txtSnippetDesc").val().trim() != "") {
|
||||||
|
data['snippetDescription'] = $("#txtSnippetDesc").val().trim();
|
||||||
|
}
|
||||||
|
if ($("#txtSnippetBody").val().trim() != "") {
|
||||||
|
data['snippet'] = $("#txtSnippetBody").val().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
var langs = $("#selectSnippetLangs").val();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "snippet.php",
|
||||||
|
type: "POST",
|
||||||
|
data: data,
|
||||||
|
success: function (res) { addSnippetLangs(res, data['snippetName'], langs) },
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($("#formAddResource")[0].checkValidity()) {
|
||||||
|
var data = {};
|
||||||
|
data['resourceName'] = $("#txtResourceName").val().trim();
|
||||||
|
if ($("#txtResourceDesc").val().trim() != "") {
|
||||||
|
data['resourceDescription'] = $("#txtResourceDesc").val().trim();
|
||||||
|
}
|
||||||
|
if ($("#txtResourceLink").val().trim() != "") {
|
||||||
|
data['resourceLink'] = $("#txtResourceLink").val().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
var langs = $("#selectResourceLangs").val();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "resource.php",
|
||||||
|
type: "POST",
|
||||||
|
data: data,
|
||||||
|
success: function (res) { addResourceLangs(res, data['resourceName'], langs); },
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addLangLangs(langID, langName, langIDList) {
|
||||||
|
if (langIDList != null) {
|
||||||
|
for (var i = 0; i < langIDList.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: "lang.php",
|
||||||
|
type: "PUT",
|
||||||
|
data: {langID: langID, associatedLang: langIDList[i]},
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
successAlert("Successfully Added language: " + langName, "lang");
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSnippetLangs(snippetID, snippetName, langIDList) {
|
||||||
|
if (langIDList != null) {
|
||||||
|
for (var i = 0; i < langIDList.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: "snippet.php",
|
||||||
|
type: "PUT",
|
||||||
|
data: {snippetID: snippetID, langID: langIDList[i]},
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
successAlert("Successfully Added snippet: " + snippetName, "snippet");
|
||||||
|
}
|
||||||
|
|
||||||
|
function addResourceLangs(resourceID, resourceName, langIDList) {
|
||||||
|
if (langIDList != null) {
|
||||||
|
for (var i = 0; i < langIDList.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: "resource.php",
|
||||||
|
type: "PUT",
|
||||||
|
data: {resourceID: resourceID, langID: langIDList[i]},
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
successAlert("Successfully Added resource: " + resourceName, "resource");
|
||||||
|
}
|
||||||
|
|
||||||
|
function successAlert(text, type) {
|
||||||
|
var alert = $("#successAlert");
|
||||||
|
|
||||||
|
if (alert.attr("display") == "none") {
|
||||||
|
alert.slideUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
alert.text(text).slideDown().delay(5000).slideUp();
|
||||||
|
|
||||||
|
if (type.toLowerCase() == "lang")
|
||||||
|
loadLangs();
|
||||||
|
else if (type.toLowerCase() == "snippet")
|
||||||
|
loadSnippets();
|
||||||
|
else if (type.toLowerCase() == "resource")
|
||||||
|
loadResources();
|
||||||
|
|
||||||
|
$(".modal").modal('hide');
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadResources() {
|
||||||
|
$("#langLink").removeClass("active");
|
||||||
|
$("#snippetLink").removeClass("active");
|
||||||
|
$("#resourceLink").addClass("active");
|
||||||
|
$("#mainList").empty();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "resource.php",
|
||||||
|
type: "GET",
|
||||||
|
success: addResourceList,
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addResourceList(resourceList) {
|
||||||
|
var mainList = $("#mainList");
|
||||||
|
for (var i = 0; i < resourceList.length; i++) {
|
||||||
|
$("<div>").attr({ "id": "resource-" + resourceList[i].resourceID }).appendTo(mainList);
|
||||||
|
$.ajax({
|
||||||
|
url: "resource.php?resourceID=" + resourceList[i].resourceID,
|
||||||
|
type: "GET",
|
||||||
|
success: addResource,
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addResource(resource) {
|
||||||
|
var link = $('<a>').attr({
|
||||||
|
"id": "resource-" + resource.resourceID + "-link",
|
||||||
|
"href": resource.resourceLink,
|
||||||
|
"target": "_blank"
|
||||||
|
}).text(resource.resourceLink);
|
||||||
|
buildCard("resource", resource.resourceID, resource.resourceName, resource.languages, resource.resourceDescription, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showResource(resourceID) {
|
||||||
|
deselectNav();
|
||||||
|
$("#mainList").empty();
|
||||||
|
|
||||||
|
$("<div>").attr("id", "resource-" + resourceID).appendTo($("#mainList"));
|
||||||
|
$.ajax({
|
||||||
|
url: "resource.php?resourceID=" + resourceID,
|
||||||
|
type: "GET",
|
||||||
|
success: function (result) { addResource(result); },
|
||||||
|
error: function (result) { displayError(result); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadSnippets() {
|
||||||
|
$("#langLink").removeClass("active");
|
||||||
|
$("#snippetLink").addClass("active");
|
||||||
|
$("#resourceLink").removeClass("active");
|
||||||
|
$("#mainList").empty();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "snippet.php",
|
||||||
|
type: "GET",
|
||||||
|
success: function (result) { addSnippets(result) },
|
||||||
|
error: function (result) { displayError(result) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSnippets(snippetList) {
|
||||||
|
var mainList = $("#mainList");
|
||||||
|
for (var i = 0; i < snippetList.length; i++) {
|
||||||
|
// add thesse so that everything is loaded in order regardless of async
|
||||||
|
$("<div>").attr({ "id": "snippet-" + snippetList[i].snippetID }).appendTo(mainList);
|
||||||
|
$.ajax({
|
||||||
|
url: "snippet.php?snippetID=" + snippetList[i].snippetID,
|
||||||
|
type: "GET",
|
||||||
|
success: function (result) { addSnippet(result) },
|
||||||
|
error: function (result) { displayError(result) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSnippet(snippet) {
|
||||||
|
var code = $('<pre><code>').attr("id", "snippet-" + snippet.snippetID + "-body").text(snippet.snippet);
|
||||||
|
buildCard("snippet", snippet.snippetID, snippet.snippetName, snippet.languages, snippet.snippetDescription, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSnippet(snippetID) {
|
||||||
|
deselectNav();
|
||||||
|
$("#mainList").empty();
|
||||||
|
$("<div>").attr("id", "snippet-" + snippetID).appendTo($("#mainList"));
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "snippet.php?snippetID=" + snippetID,
|
||||||
|
type: "GET",
|
||||||
|
success: function (result) { addSnippet(result); },
|
||||||
|
error: function (result) { displayError(result); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showLang(langID) {
|
||||||
|
deselectNav();
|
||||||
|
$("#mainList").empty();
|
||||||
|
|
||||||
|
$("<div>").attr("id", "lang-" + langID).appendTo($("#mainList"));
|
||||||
|
$.ajax({
|
||||||
|
url: "lang.php?langID=" + langID,
|
||||||
|
type: "GET",
|
||||||
|
success: function (result) { addLang(result) },
|
||||||
|
error: function (result) { displayError(result) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadLangs() {
|
||||||
|
$("#langLink").addClass("active");
|
||||||
|
$("#snippetLink").removeClass("active");
|
||||||
|
$("#resourceLink").removeClass("active");
|
||||||
|
$("#mainList").empty();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "lang.php",
|
||||||
|
type: "GET",
|
||||||
|
success: function (result) { addLangs(result) },
|
||||||
|
error: function (result) { displayError(result) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addLangs(langList) {
|
||||||
|
var mainList = $("#mainList");
|
||||||
|
for (var i = 0; i < langList.length; i++) {
|
||||||
|
$("<div>").attr({ "id": "lang-" + langList[i].langID }).appendTo(mainList);
|
||||||
|
$.ajax({
|
||||||
|
url: "lang.php?langID=" + langList[i].langID,
|
||||||
|
type: "GET",
|
||||||
|
success: function (result) { addLang(result) },
|
||||||
|
error: function (result) { displayError(result) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addLang(lang) {
|
||||||
|
var body = $('<div>');
|
||||||
|
|
||||||
|
// build list of snippet links
|
||||||
|
if (lang.snippets.length != 0) {
|
||||||
|
$('<hr>').appendTo(body);
|
||||||
|
$('<span>').addClass("card-text text-muted mr-3").text("Snippets:").appendTo(body);
|
||||||
|
|
||||||
|
var snippets = lang.snippets;
|
||||||
|
for (var i = 0; i < snippets.length; i++) {
|
||||||
|
var cur = snippets[i];
|
||||||
|
var snippetID = cur.snippetID;
|
||||||
|
$("<a>").attr({
|
||||||
|
"id": "snippet-" + snippetID,
|
||||||
|
"class": "card-link",
|
||||||
|
"href": "#",
|
||||||
|
"data-snippetID": snippetID,
|
||||||
|
"onClick": "handleSnippetClicked(event, " + snippetID + ")"
|
||||||
|
}).text(cur.snippetName).appendTo(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//build list of resource links
|
||||||
|
if (lang.resources.length != 0) {
|
||||||
|
$('<hr>').appendTo(body);
|
||||||
|
$('<span>').addClass("card-text text-muted mr-3").text("Resources:").appendTo(body);
|
||||||
|
|
||||||
|
var resources = lang.resources;
|
||||||
|
for (var i = 0; i < resources.length; i++) {
|
||||||
|
var cur = resources[i];
|
||||||
|
var resourceID = cur.resourceID;
|
||||||
|
$("<a>").attr({
|
||||||
|
"id": "resource-" + resourceID,
|
||||||
|
"class": "card-link",
|
||||||
|
"href": "#",
|
||||||
|
"data-resourceID": resourceID,
|
||||||
|
"onclick": "handleResourceClicked(event, " + resourceID + ")"
|
||||||
|
}).text(cur.resourceName).appendTo(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildCard("lang", lang.langID, lang.langName, lang.languages, lang.langDescription, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildCard(type, id, name, languageList, DescriptionText, body) {
|
||||||
|
var card = $('<div>').addClass("card mb-3").attr("id", type + "-" + id + "-card");
|
||||||
|
var header = $('<div>').addClass("card-header").appendTo(card);
|
||||||
|
$('<h3>').attr("id", type + "-" + id + "-name").addClass("d-inline").text(name).appendTo(header);
|
||||||
|
$('<span>').attr("id", type + "-" + id + "-id").addClass("text-muted ml-3").text("#" + id).appendTo(header);
|
||||||
|
|
||||||
|
$("<button>").attr({
|
||||||
|
"type": "button",
|
||||||
|
"class": "btn btn-danger float-right",
|
||||||
|
"data-id": id,
|
||||||
|
"data-type": type
|
||||||
|
}).text("Delete").click(deleteClicked).appendTo(header);
|
||||||
|
|
||||||
|
$("<button>").attr({
|
||||||
|
"type": "button",
|
||||||
|
"class": "btn btn-info float-right mr-2",
|
||||||
|
"data-id": id,
|
||||||
|
"data-type": type
|
||||||
|
}).text("Edit").click(editClicked).appendTo(header);
|
||||||
|
|
||||||
|
var cardBody = $('<div>').addClass("card-body").appendTo(card);
|
||||||
|
var langList = $("<div>").addClass("langList").appendTo(cardBody);
|
||||||
|
|
||||||
|
var langString = [];
|
||||||
|
if (languageList != null && languageList.length > 0) {
|
||||||
|
for (var i = 0; i < languageList.length; i++) {
|
||||||
|
var cur = languageList[i];
|
||||||
|
langString[i] = cur.langID;
|
||||||
|
$("<a>").attr({
|
||||||
|
"class": "card-link",
|
||||||
|
"href": "#",
|
||||||
|
"onClick": "handleLangClicked(event, " + cur.langID + ")"
|
||||||
|
}).text(cur.langName).appendTo(langList);
|
||||||
|
}
|
||||||
|
card.attr("data-langs", JSON.stringify(langString));
|
||||||
|
} else {
|
||||||
|
card.attr("data-langs", "[]");
|
||||||
|
}
|
||||||
|
|
||||||
|
$('<p>').attr("id", type + "-" + id + "-description").addClass("card-text").text(DescriptionText).appendTo(cardBody);
|
||||||
|
cardBody.append(body);
|
||||||
|
|
||||||
|
card.append(cardBody);
|
||||||
|
card.appendTo($("#" + type + "-" + id));
|
||||||
|
}
|
||||||
|
|
||||||
|
function editClicked() {
|
||||||
|
var button = $(this);
|
||||||
|
var type = button.data("type");
|
||||||
|
var id = button.data("id");
|
||||||
|
|
||||||
|
$(".editChk").prop("checked", false);
|
||||||
|
$(".editField").prop("disabled", true);
|
||||||
|
|
||||||
|
if (type == "lang")
|
||||||
|
initEditLang(id);
|
||||||
|
else if (type == "snippet")
|
||||||
|
initEditSnippet(id);
|
||||||
|
else
|
||||||
|
initEditResource(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initEditLang(langID) {
|
||||||
|
$("#editLangID").val(langID);
|
||||||
|
$("#txtEditLangName").val($("#lang-" + langID + "-name").text());
|
||||||
|
$("#txtEditLangDesc").val($("#lang-" + langID + "-description").text());
|
||||||
|
|
||||||
|
buildLangSelect();
|
||||||
|
selectList = $("#lang-" + langID + "-card").data("langs");
|
||||||
|
|
||||||
|
$("#editLangModal").modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
function initEditSnippet(snippetID) {
|
||||||
|
$("#editSnippetID").val(snippetID);
|
||||||
|
$("#txtEditSnippetName").val($("#snippet-" + snippetID + "-name").text());
|
||||||
|
$("#txtEditSnippetDesc").val($("#snippet-" + snippetID + "-description").text());
|
||||||
|
$("#txtEditSnippetBody").val($("#snippet-" + snippetID + "-body").text());
|
||||||
|
|
||||||
|
buildLangSelect();
|
||||||
|
selectList = $("#snippet-" + snippetID + "-card").data("langs");
|
||||||
|
|
||||||
|
$("#editSnippetModal").modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
function initEditResource(resourceID) {
|
||||||
|
$("#editResourceID").val(resourceID);
|
||||||
|
$("#txtEditResourceName").val($("#resource-" + resourceID + "-name").text());
|
||||||
|
$("#txtEditResourceDesc").val($("#resource-" + resourceID + "-description").text());
|
||||||
|
$("#txtEditResourceLink").val($("#resource-" + resourceID + "-link").text());
|
||||||
|
|
||||||
|
buildLangSelect();
|
||||||
|
selectList = $("#resource-" + resourceID + "-card").data("langs");
|
||||||
|
|
||||||
|
$("#editResourceModal").modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveLang() {
|
||||||
|
var changeName = $("#editLangNameChk").prop("checked");
|
||||||
|
var changeLang = $("#editLangLangsChk").prop("checked");
|
||||||
|
var changeDesc = $("#editLangDescChk").prop("checked");
|
||||||
|
|
||||||
|
if (!changeName && !changeDesc && !changeLang)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var langID = $("#editLangID").val();
|
||||||
|
var langName = $("#txtEditLangName").val().trim();
|
||||||
|
var data = {};
|
||||||
|
data['langID'] = langID;
|
||||||
|
|
||||||
|
if (changeName && langName == "") {
|
||||||
|
displayError({responseText: "Name cannot be empty"});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeName && langName != "")
|
||||||
|
data['langName'] = langName;
|
||||||
|
if (changeDesc)
|
||||||
|
data['langDescription'] = $("#txtEditLangDesc").val();
|
||||||
|
|
||||||
|
if (changeName || changeDesc) {
|
||||||
|
$.ajax({
|
||||||
|
url: "lang.php",
|
||||||
|
type: "PUT",
|
||||||
|
data: data,
|
||||||
|
success: function () { successAlert("Successfully saved language: " + langName, "lang") },
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeLang) {
|
||||||
|
var curLangsList = $("#lang-" + langID + "-card").data("langs");
|
||||||
|
var newLangsList = $("#selectEditLangLangs").val().map(function (item) {
|
||||||
|
return parseInt(item, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
var langsToAdd = inANotInB(newLangsList, curLangsList);
|
||||||
|
var langsToDelete = inANotInB(curLangsList, newLangsList);
|
||||||
|
|
||||||
|
addLangsLang(langID, langName, langsToAdd, langsToDelete != 0);
|
||||||
|
deleteLangsLang(langID, langName, langsToDelete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addLangsLang(langID, langName, langList, forceUpdate) {
|
||||||
|
for (var i = 0; i < langList.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: "lang.php",
|
||||||
|
type: "PUT",
|
||||||
|
data: {langID: langID, associatedLang: langList[i]},
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forceUpdate || langList.length != 0)
|
||||||
|
successAlert("Successfully saved language: " + langName, "lang")
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteLangsLang(langID, langName, langList) {
|
||||||
|
for (var i = 0; i < langList.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: "lang.php",
|
||||||
|
type: "DELETE",
|
||||||
|
data: {langID: langID, associatedLang: langList[i]},
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveSnippet() {
|
||||||
|
var changeName = $("#editSnippetNameChk").prop("checked");
|
||||||
|
var changeLang = $("#editSnippetLangsChk").prop("checked");
|
||||||
|
var changeDesc = $("#editSnippetDescChk").prop("checked");
|
||||||
|
var changeBody = $("#editSnippetBodyChk").prop("checked");
|
||||||
|
|
||||||
|
if (!changeName && !changeLang && !changeDesc && !changeBody)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var snippetID = $("#editSnippetID").val();
|
||||||
|
var snippetName = $("#txtEditSnippetName").val().trim();
|
||||||
|
var data = {};
|
||||||
|
data['snippetID'] = snippetID;
|
||||||
|
|
||||||
|
if (changeName && snippetName == "") {
|
||||||
|
displayError({responseText: "Name cannot be empty"});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeName)
|
||||||
|
data['snippetName'] = snippetName;
|
||||||
|
if (changeDesc)
|
||||||
|
data['snippetDescription'] = $("#txtEditSnippetDesc").val().trim();
|
||||||
|
if (changeBody)
|
||||||
|
data['snippet'] = $("#txtEditSnippetBody").val().trim();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "snippet.php",
|
||||||
|
type: "PUT",
|
||||||
|
data: data,
|
||||||
|
success: function () { successAlert("Successfully saved snippet: " + snippetName, "snippet"); },
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (changeLang) {
|
||||||
|
var curLangsList = $("#snippet-" + snippetID + "-card").data("langs");
|
||||||
|
var newLangsList = $("#selectEditSnippetLangs").val().map(function (item) {
|
||||||
|
return parseInt(item, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
var langsToAdd = inANotInB(newLangsList, curLangsList);
|
||||||
|
addLangsSnippet(snippetID, langsToAdd);
|
||||||
|
|
||||||
|
var langsToDelete = inANotInB(curLangsList, newLangsList);
|
||||||
|
deleteLangsSnippet(snippetID, langsToDelete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addLangsSnippet(snippetID, langList) {
|
||||||
|
for (var i = 0; i < langList.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: "snippet.php",
|
||||||
|
type: "PUT",
|
||||||
|
data: {snippetID: snippetID, langID: langList[i]},
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteLangsSnippet(snippetID, langList) {
|
||||||
|
for (var i = 0; i < langList.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: "snippet.php",
|
||||||
|
type: "DELETE",
|
||||||
|
data: {snippetID: snippetID, langID: langList[i]},
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveResource() {
|
||||||
|
var changeName = $("#editResourceNameChk").prop("checked");
|
||||||
|
var changeLang = $("#editResourceLangsChk").prop("checked");
|
||||||
|
var changeDesc = $("#editResourceDescChk").prop("checked");
|
||||||
|
var changeLink = $("#editResourceLinkChk").prop("checked");
|
||||||
|
|
||||||
|
if (!changeName && !changeLang && !changeDesc && !changeLink)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var resourceID = $("#editResourceID").val();
|
||||||
|
var resourceName = $("#txtEditResourceName").val().trim();
|
||||||
|
var data = {};
|
||||||
|
data['resourceID'] = resourceID;
|
||||||
|
|
||||||
|
if (changeName && resourceName == "") {
|
||||||
|
displayError({responseText: "Name cannot be empty"});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeName)
|
||||||
|
data['resourceName'] = resourceName;
|
||||||
|
if (changeDesc)
|
||||||
|
data['resourceDescription'] = $("#txtEditResourceDesc").val().trim();
|
||||||
|
if (changeLink)
|
||||||
|
data['resourceLink'] = $("#txtEditResourceLink").val().trim();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "resource.php",
|
||||||
|
type: "PUT",
|
||||||
|
data: data,
|
||||||
|
success: function () { successAlert("Successfully saved resource: " + resourceName, "resource"); },
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
|
||||||
|
if (changeLang) {
|
||||||
|
var curLangsList = $("#resource-" + resourceID + "-card").data("langs");
|
||||||
|
var newLangsList = $("#selectEditResourceLangs").val().map(function (item) {
|
||||||
|
return parseInt(item, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
var langsToAdd = inANotInB(newLangsList, curLangsList);
|
||||||
|
addLangsResource(resourceID, langsToAdd);
|
||||||
|
|
||||||
|
var langsToDelete = inANotInB(curLangsList, newLangsList);
|
||||||
|
deleteLangsResource(resourceID, langsToDelete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addLangsResource(resourceID, langList) {
|
||||||
|
for (var i = 0; i < langList.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: "resource.php",
|
||||||
|
type: "PUT",
|
||||||
|
data: {resourceID: resourceID, langID: langList[i]},
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteLangsResource(resourceID, langList) {
|
||||||
|
for (var i = 0; i < langList.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: "resource.php",
|
||||||
|
type: "DELETE",
|
||||||
|
data: {resourceID: resourceID, langID: langList[i]},
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteClicked() {
|
||||||
|
var button = $(this);
|
||||||
|
var type = button.data("type");
|
||||||
|
var id = button.data("id");
|
||||||
|
|
||||||
|
$("#btnConfirmDelete").off('click').click(function () { deleteItem(type, id); });
|
||||||
|
$("#confirmDeleteModal").modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteItem(type, id) {
|
||||||
|
var data = {};
|
||||||
|
data[type + "ID"] = id;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: type + ".php",
|
||||||
|
type: "DELETE",
|
||||||
|
data: data,
|
||||||
|
success: function (res) { successAlert("Item successfully deleted", type); },
|
||||||
|
error: displayError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSnippetClicked(evt, snippetID) {
|
||||||
|
evt.preventDefault();
|
||||||
|
showSnippet(snippetID);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleResourceClicked(evt, resourceID) {
|
||||||
|
evt.preventDefault();
|
||||||
|
showResource(resourceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleLangClicked(evt, langID) {
|
||||||
|
// TODO: show related snippets and resources
|
||||||
|
evt.preventDefault();
|
||||||
|
showLang(langID);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deselectNav() {
|
||||||
|
$("#langLink").removeClass("active");
|
||||||
|
$("#snippetLink").removeClass("active");
|
||||||
|
$("#resourceLink").removeClass("active");
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayError(error, str) {
|
||||||
|
console.log(error);
|
||||||
|
$("#errorText").text(error.responseText);
|
||||||
|
$("#errorModal").modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
function inANotInB(a, b) {
|
||||||
|
var list = [];
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
if (b.indexOf(a[i]) == -1)
|
||||||
|
list.push(a[i]);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
284
lang.php
Normal file
284
lang.php
Normal file
|
@ -0,0 +1,284 @@
|
||||||
|
<?php
|
||||||
|
// table language: langID, langName, langDescription
|
||||||
|
// table langLang: langID, associatedLang
|
||||||
|
include_once "dbTools.php";
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] == 'GET') {
|
||||||
|
$pdo = buildPDO();
|
||||||
|
|
||||||
|
if (isset(($_GET['langID'])) && isset($_GET['associatedLang'])) {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("Both langID and associatedLang are specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_GET['langID'])) {
|
||||||
|
$id = $_GET['langID'];
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM language WHERE langID=?;");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$lang = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (count($lang) <= 0) {
|
||||||
|
http_response_code(404);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("No such language");
|
||||||
|
}
|
||||||
|
|
||||||
|
$lang = buildLangList($pdo, $lang);
|
||||||
|
$lang = buildSnippetList($pdo, $lang);
|
||||||
|
$lang = buildResourceList($pdo, $lang);
|
||||||
|
|
||||||
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
echo json_encode($lang[0]);
|
||||||
|
} elseif (isset($_GET['associatedLang'])) {
|
||||||
|
$assoc = $_GET['associatedLang'];
|
||||||
|
if ($assoc == '') {
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("associatedLang is given, but empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("SELECT langID, langName, langDescription FROM language NATURAL JOIN langLang Where associatedLang=?;");
|
||||||
|
$stmt->execute([$assoc]);
|
||||||
|
$langList = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$langList = buildLangList($pdo, $langList);
|
||||||
|
$langList = buildSnippetList($pdo, $langList);
|
||||||
|
$langList = buildResourceList($pdo, $langList);
|
||||||
|
|
||||||
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
echo json_encode($langList);
|
||||||
|
} else {
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM language ORDER BY langID;");
|
||||||
|
$stmt->execute();
|
||||||
|
$langList = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$langList = buildLangList($pdo, $langList);
|
||||||
|
$langList = buildSnippetList($pdo, $langList);
|
||||||
|
$langList = buildResourceList($pdo, $langList);
|
||||||
|
|
||||||
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
echo json_encode($langList);
|
||||||
|
}
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] == 'POST') {
|
||||||
|
if (!isset($_POST['langName']) || trim($_POST['langName']) == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("A name is required");
|
||||||
|
}
|
||||||
|
$name = trim($_POST['langName']);
|
||||||
|
|
||||||
|
$pdo = buildPDO();
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM language WHERE langName=?;");
|
||||||
|
$stmt->execute([$name]);
|
||||||
|
if ($stmt->rowCount() > 0) {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("A language with the given name already exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
$desc = '';
|
||||||
|
if (isset($_POST['langDescription'])) {
|
||||||
|
$desc = trim($_POST['langDescription']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$assoc = null;
|
||||||
|
if (isset($_POST['associatedLang'])) {
|
||||||
|
$assoc = trim($_POST['associatedLang']);
|
||||||
|
if ($assoc == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("Associated language is given, but empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO language VALUES (NULL, ?, ?);");
|
||||||
|
$stmt->execute([$name, $desc]);
|
||||||
|
$newID = $pdo->lastInsertId();
|
||||||
|
|
||||||
|
if (isset($assoc)) {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO langLang VALUES (?, ?);");
|
||||||
|
$stmt->execute([$newID, $assoc]);
|
||||||
|
$stmt->execute([$assoc, $newID]); // make it two way
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response_code(201);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
echo $newID;
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] == 'PUT') {
|
||||||
|
$pdo = buildPDO();
|
||||||
|
|
||||||
|
// send request as url encoded form
|
||||||
|
$_PUT = array();
|
||||||
|
parse_str(file_get_contents("php://input"), $_PUT);
|
||||||
|
|
||||||
|
if (!isset($_PUT['langID']) || trim($_PUT['langID']) === '') {
|
||||||
|
http_response_code(422);
|
||||||
|
die("A langID is required");
|
||||||
|
}
|
||||||
|
$id = trim($_PUT['langID']);
|
||||||
|
|
||||||
|
$name = null;
|
||||||
|
if (isset($_PUT['langName']) && trim($_PUT['langName']) != '') {
|
||||||
|
$name = trim($_PUT['langName']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo = buildPDO();
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM language WHERE langName=?;");
|
||||||
|
$stmt->execute([$name]);
|
||||||
|
if ($stmt->rowCount() > 0) {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("A language with the given name already exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
$desc = null;
|
||||||
|
if (isset($_PUT['langDescription'])) {
|
||||||
|
$desc = trim($_PUT['langDescription']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$assoc = null;
|
||||||
|
if (isset($_PUT['associatedLang'])) {
|
||||||
|
$assoc = trim($_PUT['associatedLang']);
|
||||||
|
if ($assoc == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("Associated language is given, but empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($name) && isset($desc)) {
|
||||||
|
$stmt = $pdo->prepare("UPDATE language SET langName=?, langDescription=? WHERE langID=?;");
|
||||||
|
$stmt->execute([$name, $desc, $id]);
|
||||||
|
} elseif (isset($name)) {
|
||||||
|
$stmt = $pdo->prepare("UPDATE language SET langName=? WHERE langID=?;");
|
||||||
|
$stmt->execute([$name, $id]);
|
||||||
|
} elseif (isset($desc)) {
|
||||||
|
$stmt = $pdo->prepare("UPDATE language SET langDescription=? WHERE langID=?;");
|
||||||
|
$stmt->execute([$desc, $id]);
|
||||||
|
} elseif (!isset($assoc)) {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("Nothing given to update");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($assoc)) {
|
||||||
|
$stmt = $pdo->prepare("Select * FROM langLang WHERE langID=? AND associatedLang=?;");
|
||||||
|
$stmt->execute([$id, $assoc]);
|
||||||
|
|
||||||
|
if ($stmt->rowCount() > 0) {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("The given langID-langID connection already exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO langLang VALUES (?, ?);");
|
||||||
|
$stmt->execute([$id, $assoc]);
|
||||||
|
$stmt->execute([$assoc, $id]); // make it two way
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response_code(200);
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] == 'DELETE') {
|
||||||
|
// send request as url encoded form
|
||||||
|
$_DELETE = array();
|
||||||
|
parse_str(file_get_contents("php://input"), $_DELETE);
|
||||||
|
|
||||||
|
if (!isset($_DELETE['langID']) || trim($_DELETE['langID']) == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("A langID is required");
|
||||||
|
}
|
||||||
|
$id = trim($_DELETE['langID']);
|
||||||
|
|
||||||
|
$pdo = buildPDO();
|
||||||
|
|
||||||
|
if (isset($_DELETE['associatedLang'])) {
|
||||||
|
$assoc = trim($_DELETE['associatedLang']);
|
||||||
|
if ($assoc == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("Associated language is given, but empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM langLang WHERE langID=? AND associatedLang=?;");
|
||||||
|
$stmt->execute([$id, $assoc]);
|
||||||
|
$stmt->execute([$assoc, $id]);
|
||||||
|
|
||||||
|
if ($stmt->rowCount() == 0) {
|
||||||
|
http_response_code(404);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("No such item");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM language WHERE langID=?;");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
|
||||||
|
if ($stmt->rowCount() == 0) {
|
||||||
|
http_response_code(404);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("No such item");
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM langSnippet WHERE langID=?;");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM langResource WHERE langID=?;");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response_code(204);
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] == 'OPTIONS') {
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
echo "Allow: GET,POST,PUT,DELETE";
|
||||||
|
} else {
|
||||||
|
http_response_code(405);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildLangList($pdo, $langList)
|
||||||
|
{
|
||||||
|
for ($i = 0; $i < count($langList); $i++) {
|
||||||
|
$id = $langList[$i]['langID'];
|
||||||
|
|
||||||
|
$langList[$i]['languages'] = array();
|
||||||
|
$stmt = $pdo->prepare("SELECT langID, langName FROM langLang NATURAL JOIN language WHERE associatedLang=?");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$newList = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
for ($j = 0; $j < count($newList); $j++) {
|
||||||
|
$langList[$i]['languages'][$j] = $newList[$j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $langList;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSnippetList($pdo, $langList)
|
||||||
|
{
|
||||||
|
for ($j = 0; $j < count($langList); $j++) {
|
||||||
|
$id = $langList[$j]['langID'];
|
||||||
|
|
||||||
|
$langList[$j]['snippets'] = array();
|
||||||
|
$stmt = $pdo->prepare("SELECT snippetID, snippetName FROM langSnippet NATURAL JOIN snippet WHERE langID=?;");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$snippetList = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
for ($i = 0; $i < count($snippetList); $i++) {
|
||||||
|
$langList[$j]['snippets'][$i] = $snippetList[$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $langList;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildResourceList($pdo, $langList)
|
||||||
|
{
|
||||||
|
for ($j = 0; $j < count($langList); $j++) {
|
||||||
|
$id = $langList[$j]['langID'];
|
||||||
|
|
||||||
|
$langList[$j]['resources'] = array();
|
||||||
|
$stmt = $pdo->prepare("SELECT resourceID, resourceName FROM langResource NATURAL JOIN resource WHERE langID=?;");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$resourceList = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
for ($i = 0; $i < count($resourceList); $i++) {
|
||||||
|
$langList[$j]['resources'][$i] = $resourceList[$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $langList;
|
||||||
|
}
|
238
resource.php
Normal file
238
resource.php
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
<?php
|
||||||
|
// resourceID, resourceName, resourceDescription, resourceLink
|
||||||
|
// intermediary table that relates resourceIDs to langIDs
|
||||||
|
// using an intermediary allows for each snippet to be related to many languages
|
||||||
|
|
||||||
|
include_once "dbTools.php";
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] == 'GET') {
|
||||||
|
$pdo = buildPDO();
|
||||||
|
|
||||||
|
if (isset($_GET['resourseID']) && isset($_GET['langID'])) {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("Both resourceID and langID are specified. Only one can be given");
|
||||||
|
} else if (isset($_GET['resourceID'])) {
|
||||||
|
if (trim($_GET['resourceID']) == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("Empty resourceID");
|
||||||
|
}
|
||||||
|
|
||||||
|
$resourceID = $_GET['resourceID'];
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM resource WHERE resourceID=?;");
|
||||||
|
$stmt->execute([$resourceID]);
|
||||||
|
$resources = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (count($resources) <= 0) {
|
||||||
|
http_response_code(404);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("No such resource");
|
||||||
|
}
|
||||||
|
|
||||||
|
$resources = buildLangList($pdo, $resources);
|
||||||
|
|
||||||
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
echo json_encode($resources[0]);
|
||||||
|
} elseif (isset($_GET['langID'])) {
|
||||||
|
if (trim($_GET['langID']) == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("Empty langID");
|
||||||
|
}
|
||||||
|
|
||||||
|
$langID = $_GET['langID'];
|
||||||
|
$stmt = $pdo->prepare("SELECT DISTINCT resourceID, resourceName, resourceDescription, resourceLink FROM resource NATURAL JOIN langResource WHERE langID=? ORDER BY resourceID;");
|
||||||
|
$stmt->execute([$langID]);
|
||||||
|
$resources = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$resources = buildLangList($pdo, $resources);
|
||||||
|
|
||||||
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
echo json_encode($resources);
|
||||||
|
} else {
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM resource ORDER BY resourceID;");
|
||||||
|
$stmt->execute();
|
||||||
|
$resources = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$resources = buildLangList($pdo, $resources);
|
||||||
|
|
||||||
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
echo json_encode($resources);
|
||||||
|
}
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] == 'POST') {
|
||||||
|
$pdo = buildPDO();
|
||||||
|
|
||||||
|
if (!isset($_POST['resourceName']) || trim($_POST['resourceName']) == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("A resourceName is required");
|
||||||
|
}
|
||||||
|
$name = $_POST['resourceName'];
|
||||||
|
|
||||||
|
$desc = '';
|
||||||
|
if (isset($_POST['resourceDescription'])) {
|
||||||
|
$desc = trim($_POST['resourceDescription']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$link = '';
|
||||||
|
if (isset($_POST['resourceLink'])) {
|
||||||
|
$link = trim($_POST['resourceLink']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$langID = NULL;
|
||||||
|
if (isset($_POST['langID'])) {
|
||||||
|
$langID = $_POST['langID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO resource (resourceID, resourceName, resourceDescription, resourceLink) VALUES (NULL, ?, ?, ?);");
|
||||||
|
$stmt->execute([$name, $desc, $link]);
|
||||||
|
$resourceID = $pdo->lastInsertId();
|
||||||
|
|
||||||
|
if (isset($langID)) {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO langResource (resourceID, langID) VALUES (?, ?);");
|
||||||
|
$stmt->execute([$resourceID, $langID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response_code(201);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
echo $resourceID;
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] == 'PUT') {
|
||||||
|
$pdo = buildPDO();
|
||||||
|
|
||||||
|
// send request as url encoded form
|
||||||
|
$_PUT = array();
|
||||||
|
parse_str(file_get_contents("php://input"), $_PUT);
|
||||||
|
|
||||||
|
if (!isset($_PUT['resourceID']) && trim($_PUT['resourceID']) == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("resourceID is required");
|
||||||
|
}
|
||||||
|
$resourceID = trim($_PUT['resourceID']);
|
||||||
|
|
||||||
|
$name = null;
|
||||||
|
if (isset($_PUT['resourceName'])) {
|
||||||
|
$name = trim($_PUT['resourceName']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$desc = null;
|
||||||
|
if (isset($_PUT['resourceDescription'])) {
|
||||||
|
$desc = trim($_PUT['resourceDescription']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$link = null;
|
||||||
|
if (isset($_PUT['resourceLink'])) {
|
||||||
|
$link = trim($_PUT['resourceLink']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$langID = null;
|
||||||
|
if (isset($_PUT['langID'])) {
|
||||||
|
$langID = trim($_PUT['langID']);
|
||||||
|
}
|
||||||
|
if (isset($langID) && $langID == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("langID is empty");
|
||||||
|
}
|
||||||
|
if (isset($langID)) {
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM langResource WHERE resourceID=? AND langID=?;");
|
||||||
|
$stmt->execute([$resourceID, $langID]);
|
||||||
|
if ($stmt->rowCount() > 0) {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("The given resourceID-langID connection already exists");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($name)) {
|
||||||
|
$stmt = $pdo->prepare("UPDATE resource SET resourceName=? WHERE resourceID=?;");
|
||||||
|
$stmt->execute([$name, $resourceID]);
|
||||||
|
}
|
||||||
|
if (isset($desc)) {
|
||||||
|
$stmt = $pdo->prepare("UPDATE resource SET resourceDescription=? WHERE resourceID=?;");
|
||||||
|
$stmt->execute([$desc, $resourceID]);
|
||||||
|
}
|
||||||
|
if (isset($link)) {
|
||||||
|
$stmt = $pdo->prepare("UPDATE resource SET resourceLink=? WHERE resourceID=?;");
|
||||||
|
$stmt->execute([$link, $resourceID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($langID)) {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO langResource (resourceID, langID) VALUES (?, ?);");
|
||||||
|
$stmt->execute([$resourceID, $langID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response_code(204);
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] == 'DELETE') {
|
||||||
|
$pdo = buildPDO();
|
||||||
|
|
||||||
|
// send request as url encoded form
|
||||||
|
$_DELETE = array();
|
||||||
|
parse_str(file_get_contents("php://input"), $_DELETE);
|
||||||
|
|
||||||
|
// can delete either the snippet itself or an association with a lang
|
||||||
|
if (!isset($_DELETE['resourceID']) || trim($_DELETE['resourceID'])== '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("snippetID is required");
|
||||||
|
}
|
||||||
|
$resourceID = trim($_DELETE['resourceID']);
|
||||||
|
|
||||||
|
$langID = null;
|
||||||
|
if (isset($_DELETE['langID'])) {
|
||||||
|
$langID = trim($_DELETE['langID']);
|
||||||
|
}
|
||||||
|
if (isset($langID) && $langID == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("langId is given, but empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = null;
|
||||||
|
if (isset($langID)) {
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM langResource WHERE resourceID=? AND langID=?;");
|
||||||
|
$stmt->execute([$resourceID, $langID]);
|
||||||
|
$rows = $stmt->rowCount();
|
||||||
|
} else {
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM resource WHERE resourceID=?;");
|
||||||
|
$stmt->execute([$resourceID]);
|
||||||
|
$rows = $stmt->rowCount();
|
||||||
|
if ($rows > 0) {
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM langResource WHERE resourceID=?;");
|
||||||
|
$stmt->execute([$resourceID]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($rows == 0) {
|
||||||
|
http_response_code(404);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("No such item");
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response_code(204);
|
||||||
|
} else if ($_SERVER["REQUEST_METHOD"] == 'OPTIONS') {
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
echo "Allow: GET,POST,PUT,DELETE";
|
||||||
|
} else {
|
||||||
|
http_response_code(405);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildLangList($pdo, $resources) {
|
||||||
|
for ($j = 0; $j < count($resources); $j++) {
|
||||||
|
$resourceID = $resources[$j]['resourceID'];
|
||||||
|
|
||||||
|
$resources[$j]['languages'] = array();
|
||||||
|
$stmt = $pdo->prepare("SELECT langID, langName FROM langResource NATURAL JOIN language WHERE resourceID=? ORDER BY langID;");
|
||||||
|
$stmt->execute([$resourceID]);
|
||||||
|
$langList = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
for ($i = 0; $i < count($langList); $i++) {
|
||||||
|
$resources[$j]['languages'][$i] = $langList[$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $resources;
|
||||||
|
}
|
||||||
|
?>
|
250
snippet.php
Normal file
250
snippet.php
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
<?php
|
||||||
|
// table snippet: snippetID, snippetName, snippetDescription, snippet
|
||||||
|
// table langSnippet: intermediary table that relates snippetIDs to langIDs
|
||||||
|
// using an intermediary allows for each snippet to be related to many languages
|
||||||
|
|
||||||
|
include_once "dbTools.php";
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] == 'GET') {
|
||||||
|
$pdo = buildPDO();
|
||||||
|
|
||||||
|
if (isset($_GET['snippetID']) && isset($_GET['langID'])) {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("Both snippetID and langID are specified. Only one can be given");
|
||||||
|
} else if (isset($_GET['snippetID'])) {
|
||||||
|
if (trim($_GET['snippetID']) == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("Empty snippetID");
|
||||||
|
}
|
||||||
|
|
||||||
|
$snippetID = $_GET['snippetID'];
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM snippet WHERE snippetID=? ORDER BY snippetID;");
|
||||||
|
$stmt->execute([$snippetID]);
|
||||||
|
$snippets = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (count($snippets) <= 0) {
|
||||||
|
http_response_code(404);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("No such snippet");
|
||||||
|
}
|
||||||
|
|
||||||
|
$snippets = buildLangList($pdo, $snippets);
|
||||||
|
|
||||||
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
echo json_encode($snippets[0]);
|
||||||
|
} elseif (isset($_GET['langID'])) {
|
||||||
|
if (trim($_GET['langID']) == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("Empty langID");
|
||||||
|
}
|
||||||
|
|
||||||
|
$langID = $_GET['langID'];
|
||||||
|
$stmt = $pdo->prepare("SELECT DISTINCT snippetID, snippetName, snippetDescription, snippet FROM snippet NATURAL JOIN langSnippet WHERE langID=? ORDER BY snippetID;");
|
||||||
|
$stmt->execute([$langID]);
|
||||||
|
$snippets = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (count($snippets) <= 0) {
|
||||||
|
http_response_code(404);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("No snippets for the given langID");
|
||||||
|
}
|
||||||
|
|
||||||
|
$snippets = buildLangList($pdo, $snippets);
|
||||||
|
|
||||||
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
echo json_encode($snippets);
|
||||||
|
} else {
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM snippet ORDER BY snippetID;");
|
||||||
|
$stmt->execute();
|
||||||
|
$snippets = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$snippets = buildLangList($pdo, $snippets);
|
||||||
|
|
||||||
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
echo json_encode($snippets);
|
||||||
|
}
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] == 'POST') {
|
||||||
|
$pdo = buildPDO();
|
||||||
|
|
||||||
|
if (!isset($_POST['snippetName']) || trim($_POST['snippetName']) == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("A snippet name is required");
|
||||||
|
}
|
||||||
|
$name = trim($_POST['snippetName']);
|
||||||
|
|
||||||
|
$desc = '';
|
||||||
|
if (isset($_POST['snippetDescription'])) {
|
||||||
|
$desc = trim($_POST['snippetDescription']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$snippet = '';
|
||||||
|
if (isset($_POST['snippet'])) {
|
||||||
|
$snippet = trim($_POST['snippet']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$langID = NULL;
|
||||||
|
if (isset($_POST['langID'])) {
|
||||||
|
$langID = $_POST['langID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO snippet (snippetID, snippetName, snippetDescription, snippet) VALUES (NULL, ?, ?, ?);");
|
||||||
|
$stmt->execute([$name, $desc, $snippet]);
|
||||||
|
$snippetID = $pdo->lastInsertId();
|
||||||
|
|
||||||
|
if (isset($langID)) {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO langSnippet (snippetID, langID) VALUES (?, ?);");
|
||||||
|
$stmt->execute([$snippetID, $langID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response_code(201);
|
||||||
|
header("Content-type: application/json; charset=utf-8");
|
||||||
|
echo $snippetID;
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] == 'PUT') {
|
||||||
|
$pdo = buildPDO();
|
||||||
|
|
||||||
|
// send request as url encoded form
|
||||||
|
$_PUT = array();
|
||||||
|
parse_str(file_get_contents("php://input"), $_PUT);
|
||||||
|
|
||||||
|
if (!isset($_PUT['snippetID']) || trim($_PUT['snippetID']) == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("snippetID is required");
|
||||||
|
}
|
||||||
|
$snippetID = trim($_PUT['snippetID']);
|
||||||
|
|
||||||
|
$name = null;
|
||||||
|
if (isset($_PUT['snippetName'])) {
|
||||||
|
$name = trim($_PUT['snippetName']);
|
||||||
|
}
|
||||||
|
if (isset($name) && $name == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("snippetName cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
$desc = null;
|
||||||
|
if (isset($_PUT['snippetDescription'])) {
|
||||||
|
$desc = trim($_PUT['snippetDescription']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = null;
|
||||||
|
if (isset($_PUT['snippet'])) {
|
||||||
|
$body = trim($_PUT['snippet']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$langID = null;
|
||||||
|
if (isset($_PUT['langID'])) {
|
||||||
|
$langID = trim($_PUT['langID']);
|
||||||
|
}
|
||||||
|
if (isset($langID) && $langID == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("langID is empty");
|
||||||
|
}
|
||||||
|
if (isset($langID)) {
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM langSnippet WHERE snippetID=? AND langID=?;");
|
||||||
|
$stmt->execute([$snippetID, $langID]);
|
||||||
|
if ($stmt->rowCount() > 0) {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("The given snippetID-langID connection already exists");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($name)) {
|
||||||
|
$stmt = $pdo->prepare("UPDATE snippet SET snippetName=? WHERE snippetID=?;");
|
||||||
|
$stmt->execute([$name, $snippetID]);
|
||||||
|
}
|
||||||
|
if (isset($desc)) {
|
||||||
|
$stmt = $pdo->prepare("UPDATE snippet SET snippetDescription=? WHERE snippetID=?;");
|
||||||
|
$stmt->execute([$desc, $snippetID]);
|
||||||
|
}
|
||||||
|
if (isset($body)) {
|
||||||
|
$stmt = $pdo->prepare("UPDATE snippet SET snippet=? WHERE snippetID=?;");
|
||||||
|
$stmt->execute([$body, $snippetID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($langID)) {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO langSnippet (snippetID, langID) VALUES (?, ?);");
|
||||||
|
$stmt->execute([$snippetID, $langID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response_code(204);
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] == 'DELETE') {
|
||||||
|
$pdo = buildPDO();
|
||||||
|
|
||||||
|
// send request as url encoded form
|
||||||
|
$_DELETE = array();
|
||||||
|
parse_str(file_get_contents("php://input"), $_DELETE);
|
||||||
|
|
||||||
|
// can delete either the snippet itself or an association with a lang
|
||||||
|
if (!isset($_DELETE['snippetID']) || trim($_DELETE['snippetID'])== '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("snippetID is required");
|
||||||
|
}
|
||||||
|
$snippetID = trim($_DELETE['snippetID']);
|
||||||
|
|
||||||
|
$langID = null;
|
||||||
|
if (isset($_DELETE['langID'])) {
|
||||||
|
$langID = trim($_DELETE['langID']);
|
||||||
|
}
|
||||||
|
if (isset($langID) && $langID == '') {
|
||||||
|
http_response_code(422);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("langId is given, but empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = null;
|
||||||
|
if (isset($langID)) {
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM langSnippet WHERE snippetID=? AND langID=?;");
|
||||||
|
$stmt->execute([$snippetID, $langID]);
|
||||||
|
$rows = $stmt->rowCount();
|
||||||
|
} else {
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM snippet WHERE snippetID=?;");
|
||||||
|
$stmt->execute([$snippetID]);
|
||||||
|
$rows = $stmt->rowCount();
|
||||||
|
if ($rows > 0) {
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM langSnippet WHERE snippetID=?;");
|
||||||
|
$stmt->execute([$snippetID]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($rows == 0) {
|
||||||
|
http_response_code(404);
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
die("No such item");
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response_code(204);
|
||||||
|
} else if ($_SERVER["REQUEST_METHOD"] == 'OPTIONS') {
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
echo "Allow: GET,POST,PUT,DELETE";
|
||||||
|
} else {
|
||||||
|
http_response_code(405);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildLangList($pdo, $snippets) {
|
||||||
|
for ($j = 0; $j < count($snippets); $j++) {
|
||||||
|
$snippetID = $snippets[$j]['snippetID'];
|
||||||
|
|
||||||
|
$snippets[$j]['languages'] = array();
|
||||||
|
$stmt = $pdo->prepare("SELECT langID, langName FROM langSnippet NATURAL JOIN language WHERE snippetID=? ORDER BY langID;");
|
||||||
|
$stmt->execute([$snippetID]);
|
||||||
|
$langList = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
for ($i = 0; $i < count($langList); $i++) {
|
||||||
|
$snippets[$j]['languages'][$i] = $langList[$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $snippets;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
BIN
tables.png
Normal file
BIN
tables.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 77 KiB |
1
tables.xml
Normal file
1
tables.xml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<mxfile userAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/7.6.6 Chrome/58.0.3029.110 Electron/1.7.5 Safari/537.36" version="7.6.6" editor="www.draw.io" type="device"><diagram id="d667a6e1-8b29-6e91-a70b-4ec352606e5d" name="Page-1">7Vzfc6soFP5r8ridCGqSx3vb3h8z3Z07tzO7dx9tpAlbIy4hTbJ//aKCiUAam6LSpHkpHhXwnO+DA5zTAbxebL7SKJv/TmKUDMAw3gzgzQAAb+gD/ieXbEtJGAjBjOJYPLQT3OP/kHxTSFc4Rsvag4yQhOGsLpySNEVTVpNFlJJ1/bFHktRbzaIZ0gT30yjRpX/hmM1l77zJ7sY3hGdz0XToi44/RNOnGSWrVLQ3APCx+JW3F5GsSzy/nEcxWe+J4O0AXlNCWFlabK5RkutWqq1878uBu1W/KUpZkxeEWZ6jZCU+PYnS2SpXT9k/tpU6WTJKnip18J5+Xs8xQ/dZNM2fWHMkcNmcLRJ+5fFilOBZystT3hdEuUDvnOjvM6IMbfZEorNfEVkgRrf8EXHXD4XiBLA8eb3eN5OQzfcsVAkjAY1ZVfdOPbwgNGTWFtS0tUxxliHmprLAsK4sOO5SWb6mLIqWZADChLfyeZlFKS/P8vKKcqUIOa91/5abih2BPhUbaIqVynsk/JP21RX+uyLyxm/LYpj9xB/wQLbZ3ZS6zpl/L/FcWaOs85A15lGWF+mcLB5Wy9yumn3yCsQI7434dYYo5t+c20K+92Mn6oUno7o5gW8wJzCZE1gwZ9iiOX9yxinsugB7VrNxL/YcGeypqHnv+1Eaf8odFn55+3MRpdtC5xFlmhRtMPsl3+Llv3l5WNTAO/hr/6K4cxVU1rsmCaFFy3BY/PidwkdBsawveSgay3WMuRv0kh0EovaHIt7fGWI1jwLFNQ9Lt1XjoZKiJGL4ue6ZmQwk2vhBcEEbSe5AAUOg2Lj8HvHWvqukVASVijy1olILWkUFXqoPbwShSUsQOgwHCa4SNsfh5TVFCNQREjiGEE/xKeHkRIQApSKgVmQPIXKh1ANEauNPCRfzCNQUIkCHSOgYRALFkw7giRAJlYp8tSKLEJHzZocQkUDw1LHi8PjSCCL+O4DIWLHs6FSIKBVBtSJ7EIGehohcn/fiMiUp0lyFGmTMnscoqONJ1MMlX3Del+L5fxBjW+FHRitGuIhQNiczkkbJHSGZaOQw2hohxzOMLrAhdBojoqlrKDtj3dcX2xDfb5o6+rxfOFvmVpEuf0xWDwm6reQLrjCce+besNEyoJf9jfqgDAxufmurcDC2xJ0rEGijpSPcMThv/XFH33yzyp0/okXjZfJZsMfze6XPxBZ9Rs7Sx+C19EcffTvWKn0OUqcUx/hZFb2t2Ru0nFKcMUzSI01zca31c+SyuvLslstQX1icxOXaqsExN9Kw09Ufl9s6ATjG5XOkDhz3SR3fEnVUL3LoEHVCnTqgN+q0edpyYcsvqB6zdEqcoa7UVxHHDW6MXOKG6eTKFjcubnmlRqp0yw5bG3vK6sqlaWXsEnXGLVLnY2nVJ4/Vff1uV1bQEo8dXllNdB77vfHYdPJug1NUBOJcmIsY9LrHCH1bs6CzW/RSn06wR3amNfZ0PRO+6LRezhQY9ru7GLTjy7rEYpnj4ASLTXEj75nFH/5sLXa91/1OGNohs8NHBXIV6gaZQctkvsPp00W5tBM1FLDbjR1rLq2r+zpviRi2T5+2gk4u8LgAwDpxKj50Q5x2dlJcmncM4Sb9EaflcJML444H1U3ITp220dlPOobwjqYB5va502aC53siziNv6M/BkTSBV2xjTCZXY7j7+T1OR9BS9LCyDnJpOjKEffRHqbbCPt7jvr5lWo1epFW3M5XfZnjP3UtnsYqVnUmk1uxosPbhGAYl5RWajNlaIrXfViZ1gwQ245GPzGEbmDLYlEHteErbobA43RpdpbBBZZ/fPzURVo190TJq7aWw+abIi5ZBcjQR33DScDYgCSYKSE7Oc1QqajHPMWgjz7HL86NX48YUVBF25GzJxi9+/WJhBtaG5E7dKflf26yuUlzmjfR3euGNbPyDN2/nTdAlb/jl7j/2ldPT7t8iwtv/AQ==</diagram></mxfile>
|
Loading…
Reference in a new issue