diff options
Diffstat (limited to 'views')
-rw-r--r-- | views/dashboard.php | 20 | ||||
-rw-r--r-- | views/index.php | 19 | ||||
-rw-r--r-- | views/new-bookmark.php | 10 | ||||
-rw-r--r-- | views/new-post.php | 40 | ||||
-rw-r--r-- | views/review.php | 257 |
5 files changed, 318 insertions, 28 deletions
diff --git a/views/dashboard.php b/views/dashboard.php index a20a44b..59cd41e 100644 --- a/views/dashboard.php +++ b/views/dashboard.php @@ -2,21 +2,23 @@ <?= partial('partials/header') ?> <ul class="post-type-icons"> - <li><a href="/editor"><img src="/images/quill.svg" width="60"></a></li> - <li><a href="/new"><img src="/images/note.svg" width="60"></a></li> - <li><a href="/event"><img src="/images/calendar.svg" width="60"></a></li> - <li><a href="/bookmark"><img src="/images/bookmark.svg" width="60"></a></li> - <li><a href="/favorite"><img src="/images/star.svg" width="60"></a></li> - <li><a href="/repost"><img src="/images/repost.svg" width="60"></a></li> - <li><a href="/itinerary"><img src="/images/plane.svg" width="60"></a></li> - <li><a href="/email"><img src="/images/email.svg" width="60"></a></li> + <li><a href="/editor">📄</a></li> + <li><a href="/new">✏️</a></li> + <li><a href="/event">📅</a></li> + <li><a href="/bookmark">🔖</a></li> + <li><a href="/favorite">👍</a></li> + <li><a href="/repost">♺</a></li> + <li><a href="/itinerary">✈️</a></li> + <li><a href="/review">⭐️</a></li> + <li><a href="/email">✉️</a></li> </ul> </div> <style type="text/css"> .post-type-icons { - margin-top: 1em; + margin-top: 0; list-style-type: none; + font-size: 42pt; } .post-type-icons li { float: left; diff --git a/views/index.php b/views/index.php index 3ed34c2..4e1ffb4 100644 --- a/views/index.php +++ b/views/index.php @@ -5,14 +5,19 @@ <p class="tagline">Quill is a simple app for posting text notes to your website.</p> - <p>To use Quill, sign in with your domain. Your website will need to support <a href="http://indiewebcamp.com/micropub">Micropub</a> for creating new posts.</p> + <? if(session('me')): ?> + <p>You're already signed in!<p> + <p><a href="/dashboard" class="btn btn-primary">Continue</a></p> + <? else: ?> + <p>To use Quill, sign in with your domain. Your website will need to support <a href="https://indieweb.org/micropub">Micropub</a> for creating new posts.</p> - <form action="/auth/start" method="get" class="form-inline"> - <input type="url" name="me" placeholder="http://example.com" value="" class="form-control"> - <input type="submit" value="Sign In" class="btn btn-primary"> - <input type="hidden" name="client_id" value="https://quill.p3k.io"> - <input type="hidden" name="redirect_uri" value="https://quill.p3k.io/auth/callback"> - </form> + <form action="/auth/start" method="get" class="form-inline"> + <input type="url" name="me" placeholder="https://example.com" value="" class="form-control" onchange="auto_prefix_url_field(this)" autofocus> + <input type="submit" value="Sign In" class="btn btn-primary"> + <input type="hidden" name="client_id" value="https://quill.p3k.io"> + <input type="hidden" name="redirect_uri" value="https://quill.p3k.io/auth/callback"> + </form> + <? endif; ?> </div> diff --git a/views/new-bookmark.php b/views/new-bookmark.php index 417c86d..1ac208c 100644 --- a/views/new-bookmark.php +++ b/views/new-bookmark.php @@ -13,27 +13,27 @@ <form role="form" style="margin-top: 20px;" id="note_form"> <div class="form-group"> - <label for="note_bookmark"><code>bookmark-of</code></label> + <label for="note_bookmark">Bookmark URL (<code>bookmark-of</code>)</label> <input type="text" id="note_bookmark" value="<?= $this->bookmark_url ?>" class="form-control"> </div> <div class="form-group"> - <label for="note_name"><code>name</code></label> + <label for="note_name">Name (<code>name</code>)</label> <input type="text" id="note_name" value="<?= $this->bookmark_name ?>" class="form-control"> </div> <div class="form-group"> - <label for="note_content"><code>content</code> (optional)</label> + <label for="note_content">Content (<code>content</code>, optional)</label> <textarea id="note_content" value="" class="form-control" style="height: 5em;"><?= $this->bookmark_content ?></textarea> </div> <div class="form-group"> - <label for="note_category"><code>category</code> (optional, comma-separated list of tags)</label> + <label for="note_category">Tags (<code>category</code>, optional, comma-separated list of tags)</label> <input type="text" id="note_category" value="<?= $this->bookmark_tags ?>" class="form-control" placeholder="e.g. web, personal"> </div> <div class="form-group"> - <label for="note_syndicate-to"><code>syndicate-to</code> <a href="javascript:reload_syndications()">(refresh)</a></label> + <label for="note_syndicate-to">Syndicate (<code>syndicate-to</code>) <a href="javascript:reload_syndications()">refresh</a></label> <div id="syndication-container"> <?php if($this->syndication_targets) { diff --git a/views/new-post.php b/views/new-post.php index 0d79767..21571ec 100644 --- a/views/new-post.php +++ b/views/new-post.php @@ -27,6 +27,8 @@ <div class="form-group"> <label for="note_photo"><code>photo</code></label> <input type="file" name="note_photo" id="note_photo" accept="image/*"> + <a href="javascript:switchToManualPhotoURL();" id="note_manual_photo">enter photo url</a> + <a href="javascript:addPhotoURL();" class="hidden" id="add_photo">add photo</a> <br> <div id="photo_preview_container" class="hidden"> <img src="" id="photo_preview" style="max-width: 300px; max-height: 300px;"> @@ -180,11 +182,30 @@ function restoreNoteState() { } function replacePhotoWithPhotoURL(url) { - $("#note_photo").after('<input type="url" name="note_photo_url" id="note_photo_url" value="" class="form-control">'); - $("#note_photo_url").val(url); + $("#note_photo").after('<input type="url" name="note_photo_url[]" value="" class="note_photo_url form-control">'); + $(".note_photo_url").val(url); $("#note_photo").remove(); $("#photo_preview").attr("src", url); $("#photo_preview_container").removeClass("hidden"); + $("#note_manual_photo").addClass("hidden"); +} + +function switchToManualPhotoURL() { + $("#note_photo").after('<input type="url" name="note_photo_url[]" value="" class="note_photo_url form-control">'); + $("#note_photo").remove(); + $("#note_photo_url").change(function(){ + $("#photo_preview").attr("src", $(this).val()); + $("#photo_preview_container").removeClass("hidden"); + }); + $("#note_manual_photo").addClass("hidden"); + $("#add_photo").removeClass("hidden"); +} + +function addPhotoURL() { + $(".note_photo_url:last").after('<input type="url" name="note_photo_url[]" value="" class="note_photo_url form-control" style="margin-top:2px;">'); + if($(".note_photo_url").length == 4) { + $("#add_photo").remove(); + } } $(function(){ @@ -193,7 +214,7 @@ $(function(){ var hasMediaEndpoint = <?= $this->media_endpoint ? 'true' : 'false' ?>; - $("#note_content, #note_category, #note_in_reply_to, #note_slug").on('keyup change', function(e){ + $("#note_content, #note_category, #note_in_reply_to, #note_slug, #note_photo_url").on('keyup change', function(e){ saveNoteState(); }) @@ -233,8 +254,10 @@ $(function(){ }); $("#remove_photo").on("click", function(){ $("#note_photo").val(""); + $(".note_photo_url").val(""); $("#photo_preview").attr("src", "" ); $("#photo_preview_container").addClass("hidden"); + saveNoteState(); }); $("#note_content").on('change keyup', function(e){ @@ -307,8 +330,12 @@ $(function(){ // Add either the photo as a file, or the photo URL depending on whether the user has a media endpoint if(document.getElementById("note_photo") && document.getElementById("note_photo").files[0]) { formData.append("photo", document.getElementById("note_photo").files[0]); - } else if($("#note_photo_url").val()) { - formData.append("photo", $("#note_photo_url").val()); + } else if($(".note_photo_url").val()) { + $(".note_photo_url").each(function(){ + if($(this).val()) { + formData.append("photo[]", $(this).val()); + } + }); } // Need to append a placeholder field because if the file size max is hit, $_POST will @@ -316,12 +343,11 @@ $(function(){ // This will be stripped by Quill before it's sent to the Micropub endpoint formData.append("null","null"); - var request = new XMLHttpRequest(); request.open("POST", "/micropub/multipart"); request.onreadystatechange = function() { if(request.readyState == XMLHttpRequest.DONE) { - console.log(request.responseText); + // console.log(request.responseText); try { var response = JSON.parse(request.responseText); localforage.removeItem('current-note'); diff --git a/views/review.php b/views/review.php new file mode 100644 index 0000000..dacc797 --- /dev/null +++ b/views/review.php @@ -0,0 +1,257 @@ +<div class="narrow"> + <?= partial('partials/header') ?> + + <div style="clear: both;"> + <div class="alert alert-success hidden" id="post_success"><strong>Success! Your post should be on your website now!</strong><br><a href="" id="post_href">View your post</a></div> + <div class="alert alert-danger hidden" id="post_error"><strong>There was a problem saving your post. Your endpoint did not return a Location header.</strong><br>See <a href="/creating-a-micropub-endpoint">Creating a Micropub Endpoint</a> for more information.</div> + </div> + + <form role="form" style="margin-top: 20px;" id="note_form"> + + <h2>Product</h2> + + <div class="row"> + <div class="col-xs-6"> + <div class="form-group"> + <label>Name</label> + <input type="text" class="form-control" id="item_name" placeholder="" value=""> + </div> + </div> + <div class="col-xs-6"> + <div class="form-group"> + <label>URL</label> + <input type="url" class="form-control" id="item_url" placeholder="" value=""> + </div> + </div> + </div> + + <h2>Review</h2> + + <div class="rating-stars"> + <a href="" data-rating="1"></a><a href="" data-rating="2"></a><a href="" data-rating="3"></a><a href="" data-rating="4"></a><a href="" data-rating="5"></a> + <span class="description">It's okay</span> + </div> + + <div class="row review-content hidden"> + <div class="col-xs-12"> + <div class="form-group"> + <textarea id="review_content" value="" class="form-control" style="height: 4em;" placeholder="Write your review here"></textarea> + <div id="review-html-note"> + <input type="checkbox" id="review_is_html" value="1"> Post as HTML + </div> + </div> + </div> + </div> + + <div class="row review-summary hidden"> + <div class="col-xs-12"> + <div class="form-group"> + <input id="review_summary" value="" class="form-control" placeholder="Review summary"> + </div> + </div> + </div> + + <div class="row review-save hidden"> + <div class="col-xs-12"> + <div style="float: right; margin-top: 6px;"> + <button class="btn btn-success" id="btn_post">Post Review</button> + </div> + </div> + </div> + + </form> + +</div> +<style type="text/css"> +.alert { + margin-top: 1em; +} +.rating-stars { + display: flex; + flex-direction: row; + align-items: center; +} +.rating-stars .description { + display: none; + font-weight: bold; + margin-left: 20px; +} +.rating-stars .description.visible { + display: inline-block; +} +.rating-stars a { + display: inline-block; + width: 64px; + height: 64px; + background-repeat: no-repeat; + background-image: url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4IgogICB3aWR0aD0iNjRweCIgaGVpZ2h0PSI2NHB4IiB2aWV3Qm94PSIwIDAgNjQgNjQiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDY0IDY0IiB4bWw6c3BhY2U9InByZXNlcnZlIj48cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9IiNBN0E5QUMiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludHM9IjMxLjg2Niw2LjYxOCA0MC4wOSwyMy4yODEgNTguNDc5LDI1Ljk1MyA0NS4xNzIsMzguOTIzIDQ4LjMxMyw1Ny4yMzkgMzEuODY2LDQ4LjU5MiAxNS40MTgsNTcuMjM5IDE4LjU2LDM4LjkyMyA1LjI1MywyNS45NTMgMjMuNjQyLDIzLjI4MSAiLz48L3N2Zz4="); + +} +.rating-stars a.hover { + background-image: url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeD0iMHB4IiB5PSIwcHgiCiAgIHdpZHRoPSI2NHB4IiBoZWlnaHQ9IjY0cHgiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgNjQgNjQiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwb2x5Z29uIGZpbGw9IiM1MUFFQ0QiIHN0cm9rZT0iIzUxQUVDRCIgc3Ryb2tlLXdpZHRoPSI0IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50cz0iMzEuODY2LDYuNjE4IDQwLjA5LDIzLjI4MSA1OC40NzksMjUuOTUzIDQ1LjE3MiwzOC45MjMgNDguMzEzLDU3LjIzOSAzMS44NjYsNDguNTkyIDE1LjQxOCw1Ny4yMzkgMTguNTYsMzguOTIzIDUuMjUzLDI1Ljk1MyAyMy42NDIsMjMuMjgxICIvPjwvc3ZnPgo="); +} +.rating-stars a.selected { + background-image: url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4IgogICB3aWR0aD0iNjRweCIgaGVpZ2h0PSI2NHB4IiB2aWV3Qm94PSIwIDAgNjQgNjQiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDY0IDY0IiB4bWw6c3BhY2U9InByZXNlcnZlIj48cG9seWdvbiBmaWxsPSIjRkVDMjBGIiBzdHJva2U9IiNGRUMyMEYiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludHM9IjMxLjg2Niw2LjYxOCA0MC4wOSwyMy4yODEgNTguNDc5LDI1Ljk1MyA0NS4xNzIsMzguOTIzIDQ4LjMxMyw1Ny4yMzkgMzEuODY2LDQ4LjU5MiAxNS40MTgsNTcuMjM5IDE4LjU2LDM4LjkyMyA1LjI1MywyNS45NTMgMjMuNjQyLDIzLjI4MSAiLz48L3N2Zz4="); +} + +.review-content { + margin-top: 1em; +} +#review-html-note { + font-size: 12px; + text-align: right; +} + +</style> +<script> +var selectedRating = 0; +var userSelectedHTML = null; + +function isHTML(str) { + var doc = new DOMParser().parseFromString(str, "text/html"); + return Array.from(doc.body.childNodes).some(node => node.nodeType === 1); +} + +function isTouchDevice() { + return 'ontouchstart' in document.documentElement; +} + +function setSaveButtonState() { + if(selectedRating > 0 && $("#item_name").val() != "" && $("#item_url").val() != "") { + $(".review-save").removeClass("hidden"); + } else { + $(".review-save").addClass("hidden"); + } +} + +$(function(){ + + $(".rating-stars a").on("mouseover",function(){ + // Disable hover effects on touch devices + if(isTouchDevice()) { return; } + + $(this).addClass("hover"); + var to = intval($(this).data("rating")); + $(".rating-stars a").removeClass("selected"); + for(var i=1; i<=to; i++) { + $(".rating-stars a[data-rating="+i+"]").addClass("hover").removeClass("selected"); + } + var description; + switch(to) { + case 1: + description = "I hate it"; break; + case 2: + description = "I don't like it"; break; + case 3: + description = "It's okay"; break; + case 4: + description = "I like it"; break; + case 5: + description = "I love it!"; break; + } + $(".rating-stars .description").text(description); + $(".rating-stars span").addClass("visible"); + }); + $(".rating-stars a").on("mouseout",function(){ + $(this).removeClass("hover"); + }); + $(".rating-stars").on("mouseout",function(){ + $(".rating-stars span").removeClass("visible"); + $(".rating-stars a").removeClass("hover"); + if(selectedRating) { + for(var i=1; i<=selectedRating; i++) { + $(".rating-stars a[data-rating="+i+"]").addClass("selected") + } + } + }); + $(".rating-stars a").on("click",function(){ + selectedRating = intval($(this).data("rating")); + $(".rating-stars a").removeClass("hover").removeClass("selected"); + for(var i=1; i<=selectedRating; i++) { + $(".rating-stars a[data-rating="+i+"]").addClass("selected") + } + $(".review-content").removeClass("hidden"); + setSaveButtonState(); + return false; + }); + + $("#review_is_html").on("click", function(){ + if($(this).attr("checked") == "checked") { + userSelectedHTML = 1; + } else { + userSelectedHTML = -1; + } + }); + $("#review_content").on("keyup", function(){ + if(userSelectedHTML == null) { + if(isHTML($(this).val())) { + $("#review_is_html").attr("checked", "checked"); + } else { + $("#review_is_html").removeAttr("checked"); + } + } + if($(this).val() != "") { + $(".review-summary").removeClass("hidden"); + } else { + $(".review-summary").addClass("hidden"); + } + + var scrollHeight = document.getElementById("review_content").scrollHeight; + var currentHeight = parseInt($("#review_content").css("height")); + if(Math.abs(scrollHeight - currentHeight) > 20) { + $("#review_content").css("height", (scrollHeight+30)+"px"); + } + }); + + $("#item_name").on("keyup", setSaveButtonState); + $("#item_url").on("keyup", setSaveButtonState); + + $("#btn_post").click(function(){ + $("#btn_post").addClass("loading disabled").text("Working..."); + + var review = { + item: [{ + type: "h-product", + properties: { + name: [$("#item_name").val()], + url: [$("#item_url").val()] + } + }], + rating: [selectedRating], + }; + if($("#review_content").val() != "") { + if($("#review_is_html").attr("checked") == "checked") { + review["content"] = [{html: $("#review_content").val()}]; + } else { + review["content"] = [$("#review_content").val()]; + } + } + if($("#review_summary").val() != "") { + review["summary"] = [$("#review_summary").val()]; + } + + $.post("/micropub/postjson", { + data: JSON.stringify({ + "type": "h-review", + "properties": review + }) + }, function(response){ + $("#btn_post").removeClass("loading disabled").text("Post Review"); + + if(response.location != false) { + $("#post_success").removeClass('hidden'); + $("#post_error").addClass('hidden'); + $("#post_href").attr("href", response.location); + $("#note_form").addClass("hidden"); + } else { + $("#post_success").addClass('hidden'); + $("#post_error").removeClass('hidden'); + } + + }); + return false; + + }); + +}); +</script> |