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