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