diff --git a/app/assets/javascripts/tags.js b/app/assets/javascripts/tags.js index bbcfd70226335067e45d8a100e219a0f4422e47c..30d5a75b98444c2d9619e3179625d7ad57461227 100644 --- a/app/assets/javascripts/tags.js +++ b/app/assets/javascripts/tags.js @@ -24,17 +24,34 @@ $(() => { $('.js-tag-select').each((i, el) => { const $tgt = $(el); + let $this; const useIds = $tgt.attr('data-use-ids') === 'true'; $tgt.select2({ tags: $tgt.attr('data-create') !== 'false', ajax: { url: '/tags', data: function (params) { - return Object.assign(params, { tag_set: $(this).data('tag-set') }); + $this = $(this); + // (for the tour) + if ($this.data('tag-set') == "-1") { + return Object.assign(params, { tag_set: "1" }); + } + return Object.assign(params, { tag_set: $this.data('tag-set') }); }, headers: { 'Accept': 'application/json' }, delay: 100, processResults: data => { + // (for the tour) + if ($this.data('tag-set') == "-1") { + return { + results: [ + { id: 1, text: "hot-red-firebreather", desc: "Very cute dragon" }, + { id: 2, text: "training", desc: "How to train a dragon" }, + { id: 3, text: "behavior", desc: "How a dragon behaves" }, + { id: 4, text: "sapphire-blue-waterspouter", desc: "Other cute dragon" } + ] + } + } return {results: data.map(t => ({id: useIds ? t.id : t.name, text: t.name, desc: t.excerpt}))}; }, }, diff --git a/app/assets/javascripts/tour.js b/app/assets/javascripts/tour.js new file mode 100644 index 0000000000000000000000000000000000000000..a37ab99a74125033acf4adb81c8278074c3e3b1b --- /dev/null +++ b/app/assets/javascripts/tour.js @@ -0,0 +1,52 @@ +const tour = { + firstAnswer: function () { + $(".js-good-answer").removeClass("hide"); + $(".js-answer-counter").text("1 answer"); + $(".step-1").addClass("hide"); + $(".step-2").removeClass("hide"); + }, + firstAnswerUpvote: function (self) { + $(self).addClass("is-active"); + $(".step-3").addClass("hide"); + $(".step-4").removeClass("hide"); + $(".js-good-answer .js-upvote-count").text("+1"); + $(".js-good-answer .js-upvote-count").text("+1"); + window.setTimeout(() => { + tour.secondAnswer(); + }, 4000); + }, + secondAnswer: function () { + $(".js-bad-answer").removeClass("hide"); + $(".js-answer-counter").text("2 answers"); + $(".step-4").addClass("hide"); + $(".step-5").removeClass("hide"); + }, + secondAnswerFlag: function () { + $(".step-5").addClass("hide"); + $(".step-6").removeClass("hide"); + $(".tour-flag-success").removeClass("hide"); + $(".js-flag-box").addClass("hide"); + + window.setTimeout(() => { + $(".js-answer-counter").text("1 answer"); + $(".js-bad-answer").addClass("deleted-content"); + }, 4000); + window.setTimeout(() => { + $(".js-bad-answer").addClass("hide"); + }, 6000); + } +} + +$(() => { + if ($(".js-tour-trigger-qa-page").length) { + window.setTimeout(() => { + tour.firstAnswer(); + }, 8000); + } + + $("[data-step-from][data-step-to]").click((e) => { + $this = $(e.target); + $($this.attr("data-step-from")).toggleClass("hide"); + $($this.attr("data-step-to")).toggleClass("hide"); + }); +}); \ No newline at end of file diff --git a/app/assets/stylesheets/tour.scss b/app/assets/stylesheets/tour.scss new file mode 100644 index 0000000000000000000000000000000000000000..221eb76e5d7f449050a200920788b41c1eeebfda --- /dev/null +++ b/app/assets/stylesheets/tour.scss @@ -0,0 +1,16 @@ +.codidactyl { + width: 80px; + padding: 2rem; + margin-top: 1rem; +} +.codidactyl + .is-flexible { width: 0; } + +.codidactyl-sticky { + position: sticky; + top: 0.5rem; + padding: 1rem; +} + +.codidactyl-small { + max-height: 1em; +} \ No newline at end of file diff --git a/app/controllers/tour_controller.rb b/app/controllers/tour_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..b7101473dfa66aade9a2fe6ed23568341b9aa56b --- /dev/null +++ b/app/controllers/tour_controller.rb @@ -0,0 +1,17 @@ +class TourController < ApplicationController + layout 'without_sidebar' + + def index; end + + def question1; end + + def question2; end + + def question3; end + + def more + @communities = Community.all + end + + def end; end +end diff --git a/app/helpers/tour_helper.rb b/app/helpers/tour_helper.rb new file mode 100644 index 0000000000000000000000000000000000000000..681d157d6414e35f2ef9a3e83ee754540f8579bd --- /dev/null +++ b/app/helpers/tour_helper.rb @@ -0,0 +1,2 @@ +module TourHelper +end diff --git a/app/models/user.rb b/app/models/user.rb index 3ed44d6518d7873ece81628e9aaec435a7672501..f80e49436d58366f760baba8958bcf8f12e59287 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -32,6 +32,8 @@ class User < ApplicationRecord delegate :reputation, :reputation=, to: :community_user + after_create :send_welcome_tour_message + def self.list_includes includes(:posts, :avatar_attachment) end @@ -70,7 +72,7 @@ class User < ApplicationRecord end def unread_count - notifications.where(is_read: false).count + notifications.unscoped.where(user: self, is_read: false).count end def questions @@ -185,5 +187,12 @@ class User < ApplicationRecord request.headers['CF-Connecting-IP'] || request.ip end + def send_welcome_tour_message + return if id == -1 + + create_notification('👋 Welcome to ' + SiteSetting['SiteName'] + '! Take our tour to find out ' \ + 'how this site works.', '/tour') + end + # rubocop:enable Naming/PredicateName end diff --git a/app/views/tour/end.html.erb b/app/views/tour/end.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..ed53964c52382df6bbee996015a27bc546f08bba --- /dev/null +++ b/app/views/tour/end.html.erb @@ -0,0 +1,16 @@ +<div class="grid"> + <div class="grid--cell codidactyl"> + <img src="/assets/codidactyl.png" alt="Codidactyl"> + </div> + <div class="grid--cell is-flexible"> + <div class="widget"> + <div class="widget--body"> + <h1>Congratulations!</h1> + <p>You have successfully completed my tutorial. Now you're ready to dive into this community. Go and learn together.</p> + </div> + <div class="widget--footer step-1-footer"> + <a href="/" class="button is-filled">End tutorial</a> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/app/views/tour/index.html.erb b/app/views/tour/index.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..5e76f9b6280a5ce3fc309c225fe5c15bb9f9f36c --- /dev/null +++ b/app/views/tour/index.html.erb @@ -0,0 +1,17 @@ +<div class="grid"> + <div class="grid--cell codidactyl"> + <img src="/assets/codidactyl.png" alt="Codidactyl"> + </div> + <div class="grid--cell is-flexible"> + <div class="widget"> + <div class="widget--body"> + <p>Hi!</p> + <p>I'm your friendly neighbourhood <a href="https://en.wikipedia.org/wiki/Pterodactylus">Codidactyl</a> and I'd like to introduce you to this website. Don't worry: It doesn't take long and you can abort at any time.</p> + </div> + <div class="widget--footer"> + <a href="/tour/q" class="button is-filled">Let's go</a> + <a href="/" class="button">No, thanks</a> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/app/views/tour/more.html.erb b/app/views/tour/more.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..3a6709830dcbffae4178453d9d31a644eadefeb6 --- /dev/null +++ b/app/views/tour/more.html.erb @@ -0,0 +1,155 @@ +<div class="grid step-1" id="1"> + <div class="grid--cell codidactyl"> + <img src="/assets/codidactyl.png" alt="Codidactyl"> + </div> + <div class="grid--cell is-flexible"> + <div class="widget"> + <div class="widget--body"> + <p>Yay!</p> + <p>You have successfully learned the basics of using our Q&A site. However, there are some more things you should know, which differentiate us from other communities.</p> + </div> + <div class="widget--footer step-1-footer"> + <a href="#2" data-step-from=".step-1-footer" data-step-to=".step-2" class="button is-filled">Next</a> + </div> + </div> + </div> +</div> + +<div class="grid step-2 hide" id="2"> + <div class="grid--cell codidactyl"> + <img src="/assets/codidactyl.png" alt="Codidactyl"> + </div> + <div class="grid--cell is-flexible"> + <div class="widget"> + <div class="widget--body"> + <p>First, there is more than just pure questions and answers. We have multiple categories (which you can navigate through in the top bar), which structure content. The categories are for different purposes. Click each category to see its description, or click the "Categories" link at the top to see all of them. Here are the current descriptions for this site:</p> + + <table class="table"> + <tr> + <th>Category</th> + <th>Description</th> + </tr> + <% @header_categories.each do |cat| %> + <% next unless (current_user&.trust_level || 0) >= (cat.min_view_trust_level || -1) %> + <tr> + <td class="h-fw-bold"><%= cat.name %></td> + <td><%= raw(sanitize(render_markdown(cat.short_wiki), scrubber: scrubber)) %></td> + </tr> + <% end %> + </table> + <p>We also have more post types than questions and answers.</p> + <p>Their usage depends on the category, but it's possible to write</p> + <ul> + <li>questions (with answers, can be voted and commented on) and</li> + <li>articles (without answers, can be voted and commented on).</li> + </ul> + </div> + <div class="widget--footer step-2-footer"> + <a href="#3" data-step-from=".step-2-footer" data-step-to=".step-3" class="button is-filled">Next</a> + </div> + </div> + </div> +</div> + +<div class="grid step-3 hide" id="3"> + <div class="grid--cell codidactyl"> + <img src="/assets/codidactyl.png" alt="Codidactyl"> + </div> + <div class="grid--cell is-flexible"> + <div class="widget"> + <div class="widget--body"> + <p>Another thing: this site is community-run.</p> + <p>There is no for-profit company behind it, and the organization providing the platform won't interfere with community business.</p> + <p>This means that all community-governance issues need to be decided in the local meta category. This is a special category, which isn't about the topic of the current site but about the community. There is also a global Meta community on <a href="https://meta.codidact.com">meta.codidact.com</a>, where network-wide issues are resolved.</p> + <p>If you want a new feature or if you find a bug, you can (and should) suggest/report it in the local meta category or on Codidact Meta.</p> + </div> + <div class="widget--footer step-3-footer"> + <a href="#4" data-step-from=".step-3-footer" data-step-to=".step-4" class="button is-filled">Next</a> + </div> + </div> + </div> +</div> + +<div class="grid step-4 hide" id="4"> + <div class="grid--cell codidactyl"> + <img src="/assets/codidactyl.png" alt="Codidactyl"> + </div> + <div class="grid--cell is-flexible"> + <div class="widget"> + <div class="widget--body"> + <p>Did you know that there are other communities, too? You can check them out on <a href="https://codidact.com">codidact.com</a> and decide if you want to join them:</p> + <div class="grid community-list"> + <% @communities.each do |c| %> + <% settings = SiteSetting.for_community_id(c.id) %> + <% logo_setting = settings.find_by(name: 'SiteLogoPath') %> + <div class="grid--cell is-4 is-6-md is-12-sm"> + <div class="widget"> + <div class="widget--header is-complex"> + <div class="has-text-align-center has-font-weight-bold has-font-size-display"> + <%= link_to "//" + c.host, class: "dashboard-full-center" do %> + <% if !logo_setting.nil? %> + <img src="<%= logo_setting&.typed %>" alt="<%= c.name %>"> + <% else %> + <%= c.name %> + <% end %> + <% end %> + </div> + </div> + </div> + </div> + <% end %> + </div> + </div> + <div class="widget--footer step-4-footer"> + <a href="#5" data-step-from=".step-4-footer" data-step-to=".step-5" class="button is-filled">Next</a> + </div> + </div> + </div> +</div> + +<div class="grid step-5 hide" id="5"> + <div class="grid--cell codidactyl"> + <img src="/assets/codidactyl.png" alt="Codidactyl"> + </div> + <div class="grid--cell is-flexible"> + <div class="widget"> + <div class="widget--body"> + <% if !current_user.nil? %> + <p>By the way, we have generated a user profile for you, which is publicly visible to other users.</p> + <p>It's currently mostly blank, but you can <a href="/users/edit/profile">personalize it</a> if you want.</a></p> + <% else %> + <p>By the way. When this here looks interesting, why don't you <a href="/users/sign_up">sign up</a> and create an account to join our communities?</p> + <% end %> + </div> + <div class="widget--footer step-5-footer"> + <a href="#5" data-step-from=".step-5-footer" data-step-to=".step-6" class="button is-filled">Next</a> + </div> + </div> + </div> +</div> + +<div class="grid step-6 hide" id="6"> + <div class="grid--cell codidactyl"> + <img src="/assets/codidactyl.png" alt="Codidactyl"> + </div> + <div class="grid--cell is-flexible"> + <div class="widget"> + <div class="widget--body"> + <p>Great. You are almost finished.</p> + <p>Looking for more information? Here are some more places to find help:</p> + <ol> + <li>The <a href="/help"><strong>help center</strong></a> contains useful help and policy documents, which explain how the site works.</li> + <li>The local <strong>meta category</strong></a> is the right place to ask questions about this community and its rules. It can also be used for support questions or community-specific bugs or feature requests.</li> + <li><a href="https://meta.codidact.com"><strong>Codidact Meta</strong></a> is where network-wide governance questions are considered and where support questions, bug reports, and feature requests can be posted.</li> + </ol> + <% chat = SiteSetting['ChatLink'] %> + <% if chat.present? %> + <p>You might also want to <a href="<%= chat %>">join our community chat</a> and chat with other community members.</p> + <% end %> + </div> + <div class="widget--footer step-6-footer"> + <a href="/tour/end" class="button is-filled">Next</a> + </div> + </div> + </div> +</div> diff --git a/app/views/tour/question1.html.erb b/app/views/tour/question1.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..2b66c1cbaaea785cb591a3e077e45b33fa6c3b02 --- /dev/null +++ b/app/views/tour/question1.html.erb @@ -0,0 +1,16 @@ +<div class="grid"> + <div class="grid--cell codidactyl"> + <img src="/assets/codidactyl.png" alt="Codidactyl"> + </div> + <div class="grid--cell is-flexible"> + <div class="widget"> + <div class="widget--body"> + <p>Great.</p> + <p>This is a Q&A site, so everything starts with a question. Let's try to ask one to see, how it works.</p> + </div> + <div class="widget--footer"> + <a href="/tour/ask" class="button is-filled">New question</a> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/app/views/tour/question2.html.erb b/app/views/tour/question2.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..2314116a57e8919e371d6e962a34bb19cd968c48 --- /dev/null +++ b/app/views/tour/question2.html.erb @@ -0,0 +1,256 @@ +<%= render 'posts/markdown_script' %> + +<div class="grid step-0"> + <div class="grid--cell codidactyl"> + <img src="/assets/codidactyl.png" alt="Codidactyl"> + </div> + <div class="grid--cell is-flexible"> + <div class="widget"> + <div class="widget--body"> + <p>This is the "ask question" form. You can find it by looking at the category bar (the labels below the header that say things like "Q&A" and "Meta") and clicking on the "Ask Question" button. (In some categories this button might say something different, like "Create Challenge".)</p> + <p>I will put some hints into the sidebar. Please study them carefully and build your first question.</p> + </div> + <div class="widget--footer"> + <button class="button is-filled" data-step-from=".step-0" data-step-to=".step-1">Get started</button> + </div> + </div> + </div> +</div> + +<hr> + +<div class="grid"> + <div class="grid--cell is-8"> + <h1>New Post in Q&A</h1> + <div class="notice is-info"> + <%= raw(sanitize(render_markdown(SiteSetting['AskingGuidance']), scrubber: scrubber)) %> + </div> + <div class="form-group"> + <label for="tour-post-body" class="form-element">Body</label> + <div class="widget"> + <%= render 'shared/markdown_tools' %> + <textarea class="form-element post-field js-post-field widget--body h-b-0 h-m-0" rows=15 placeholder="Start typing your post..." id="tour-post-body"></textarea> + <%= render 'posts/mdhint' %> + </div> + </div> + + <div class="post-preview"></div> + + <div class="form-group"> + <label for="tour-post-title" class="form-element">Summarize your post with a title:</label> + <input id="tour-post-title" class="form-element"> + </div> + + <div class="form-group"> + <label class="form-element" for="post_tags_cache">Tags (at least one):</label> + <input name="post[tags_cache][]" type="hidden" value="" /><select multiple="multiple" class="form-element js-tag-select" data-tag-set="-1" name="post[tags_cache][]" id="post_tags_cache"><option value=""></option></select> + </div> + + </div> + <div class="grid--cell is-4"> + <div class="codidactyl-hints codidactyl-sticky"> + <div class="widget step-1 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>Let's imagine you have a question about dragons.</p> + <p>If you'd really had a question about dragons, you'd need to check first whether it's <a href="/help/faq">on-topic for this site</a>, but I checked this for you now already. 😉</p> + </div> + <div class="widget--footer"> + <button class="button" disabled>Back</button> + <button class="button is-filled" data-step-from=".step-1" data-step-to=".step-2">Next</button> + </div> + </div> + <div class="widget step-2 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p><strong>Step 1: Question body</strong></p> + <p>Every question starts with a body, which is a full explanation of your question including additional information needed to answer it.</p> + <p>I'll guide you through writing a good question body.</p> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-1" data-step-to=".step-2">Back</button> + <button class="button is-filled" data-step-from=".step-2" data-step-to=".step-3">Next</button> + </div> + </div> + <div class="widget step-3 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>You should start your question body with a short summary of your problem. For example, in our case, this could be:</p> +<blockquote class="h-ff-code">My dragon Martha has constantly been chasing my sheep around, and I'd like to get her to stop this behavior.</blockquote> + <p>Why don't you write (or copy) that into the body form?</p> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-2" data-step-to=".step-3">Back</button> + <button class="button is-filled" data-step-from=".step-3" data-step-to=".step-4">Next</button> + </div> + </div> + <div class="widget step-4 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>Next you should add some more detailed information about your specific issue. What exactly has happened? What went wrong? If you have error messages, add them here too.</p> + <p>Other users should be able to understand your problems and ideally be able to reproduce the issue.</p> + <p>This is how the explanation could look for your dragon Martha.</p> +<blockquote class="h-ff-code">Martha is a Hot Red Firebreather, and is five and a half feet long at about a year old (still pretty young, since dragons are only fully grown at three). I've had her for about three months now. She's generally very well-behaved - never breathing fire inside the house and not fighting with my neighbor's old Sapphire Blue Waterspouter. However, every time she sees my (solitary) sheep, she chases him around and bothers him, and it's really not good for the sheep.</blockquote> + <p>Formatting tip: Add a blank line to start a new paragraph.</p> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-3" data-step-to=".step-4">Back</button> + <button class="button is-filled" data-step-from=".step-4" data-step-to=".step-5">Next</button> + </div> + </div> + <div class="widget step-5 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>Awesome.</p> + <p>When you ask a question, we generally expect you to have done some research and to have tried to solve the issue by yourself.</p> + <p>Add a short summary of your prior efforts and how they failed. Help the community help you by sharing what you already know, so they know where to start and they don't waste time suggesting things you've already tried.</p> + <p>This is how it could look for your dragon question:</p> +<blockquote class="h-ff-code">I've asked around and done some research, and the folks at the Dwarven Library told me that I could paint my sheep blue to prevent this from happening. However, I'm not looking to do anything to the sheep - just for training the dragon.</blockquote> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-4" data-step-to=".step-5">Back</button> + <button class="button is-filled" data-step-from=".step-5" data-step-to=".step-6">Next</button> + </div> + </div> + <div class="widget step-6 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>Now you're almost finished.</p> + <p>In some cases, you might want to add some restrictions, what you definitely do not want to do. This helps answerers focus on what you really need.</p> + <p>For example, you might not want to tickle the dragon:</p> +<blockquote class="h-ff-code">I do not want to use any training methods that involve pain or restricting the dragon in any way, and I'm not looking to do anything to the sheep. I'm pretty experienced in training dragons, but I've never had to deal with this situation before.</blockquote> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-5" data-step-to=".step-6">Back</button> + <button class="button is-filled" data-step-from=".step-6" data-step-to=".step-7">Next</button> + </div> + </div> + <div class="widget step-7 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>That's it.</p> + <p>You have written your first question body. You can see a preview of how it will look below the text input.</p> + <p>You might want to improve the formatting of the post. We use <a href="/help/formatting">Markdown</a> for that. You can also use the buttons at the top of the post editor. Each button has a tooltip.</p> + <p>Use <strong>**bold**</strong>, <em>*italics*</em> or <code>`code`</code> formatting and two newlines for new paragraphs. For lists, just use numbers (1., 2., 3.) or bullet points (* or -).</p> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-6" data-step-to=".step-7">Back</button> + <button class="button is-filled" data-step-from=".step-7" data-step-to=".step-8">Next</button> + </div> + </div> + <div class="widget step-8 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p><strong>Step 2: Question title</strong></p> + <p>After writing the question body, summarize your question in a title. This summary will be shown to other users looking for posts to answer, so make it clear and specific.</p> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-7" data-step-to=".step-8">Back</button> + <button class="button is-filled" data-step-from=".step-8" data-step-to=".step-9">Next</button> + </div> + </div> + <div class="widget step-9 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>Good question titles include neither too much nor too little information. They don't have to tell everything your question includes, but they shouldn't be just a general summary of the related topics (that's what tags are for, to which we'll come a bit later). The title can, but doesn't have to be, a question.</p> + <p>For example, the title "Dragon vs Sheep" is not good for our current question and neither is "Stop cute one year old dragon from eating my sheep without painting them blue or restraining the dragon". Instead, use something like this:</p> + <blockquote class="h-ff-code">How do I teach my dragon not to chase my sheep around?</blockquote> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-8" data-step-to=".step-9">Back</button> + <button class="button is-filled" data-step-from=".step-9" data-step-to=".step-10">Next</button> + </div> + </div> + <div class="widget step-10 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p><strong>Step 3: Question tags</strong></p> + <p>Tags categorize posts. They're shown alongside the title, which helps people browsing the list of questions, and they can also be searched for, helping people who are experts in particular topics find questions to answer (like yours).</p> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-9" data-step-to=".step-10">Back</button> + <button class="button is-filled" data-step-from=".step-10" data-step-to=".step-11">Next</button> + </div> + </div> + <div class="widget step-11 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>You should add at least two to three tags to your question. Good tags are about a topical area of your post, rather than some meta-information (experience level, "urgent", ...). Tags are alphanumerical and use dashes (-) to separate multiple words.</p> + <p>Many tags should already exist, but if you need a new one, you can create them, too.</p> + <p>For your dragon question, you might want to use these tags:</p> + <p> + <span class="badge is-tag">hot-red-firebreather</span> + <span class="badge is-tag">training</span> + <span class="badge is-tag">behavior</span> + </p> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-10" data-step-to=".step-11">Back</button> + <button class="button is-filled" data-step-from=".step-11" data-step-to=".step-12">Next</button> + </div> + </div> + <div class="widget step-12 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>Fantastic!</p> + <p>Your first question is almost complete. Just check through everything once again to make sure that there are no spelling errors and that everything looks okay. Try to imagine that you don't already know about Martha and your sheep as you review your question. Is the question clear and complete?</p> + <p>Don't worry. You'll be able to edit your question after submission, too.</p> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-11" data-step-to=".step-12">Back</button> + <button class="button is-filled" data-step-from=".step-12" data-step-to=".step-13">Next</button> + </div> + </div> + <div class="widget step-13 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>Ready?</p> + <p>Let's go. You can now submit your question, so that other users can answer it.</p> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-12" data-step-to=".step-13">Back</button> + <a href="/tour/qa" class="button is-filled">Post question</a> + </div> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/app/views/tour/question3.html.erb b/app/views/tour/question3.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..e38b689a9b0e61c9f9e44c4161f004556cf01947 --- /dev/null +++ b/app/views/tour/question3.html.erb @@ -0,0 +1,391 @@ +<%= render 'posts/markdown_script' %> + +<div class="grid step-0"> + <div class="grid--cell codidactyl"> + <img src="/assets/codidactyl.png" alt="Codidactyl"> + </div> + <div class="grid--cell is-flexible"> + <div class="widget"> + <div class="widget--body"> + <p>Hey! Your question has been posted. Isn't that exciting?</p> + <p>Now you have to wait for answers to come in. If other users have questions regarding your post, they can ask + them in comments.</p> + </div> + </div> + </div> +</div> + +<hr> + +<div class="grid"> + <div class="grid--cell is-8"> + <div class="post"> + <h1 + class="post--title has-border-top-width-4 has-border-top-style-solid has-border-color-primary-400 has-padding-2"> + How do I teach my dragon not to chase my sheep around? + <span class="badge is-tag is-filled is-muted"><i class="fas fa-question"></i> <span>Question</span></span> + </h1> + + <div class="post--container grid is-nowrap"> + <div class="grid--cell"> + <div class="post--votes has-text-align-center" title="0.5"> + <button class="tour-vote-button button is-icon-only-button" aria-label="Upvote"> + <svg width="2em" height="1.33em" viewbox="0 0 100 50"> + <path d="M50,0 L100,50 L0,50 Z" fill="currentColor" /> + </svg> + </button> + <div class="score has-font-size-subheading js-upvote-count"> + +0 + </div> + <div class="score has-font-size-subheading js-downvote-count"> + −0 + </div> + <button class="tour-vote-button button is-icon-only-button " aria-label="Downvote"> + <svg width="2em" height="1.33em" viewbox="0 0 100 50"> + <path d="M0,0 L100,0 L50,50 Z" fill="currentColor" /> + </svg> + </button> + </div> + </div> + + <div class="grid--cell is-flexible has-padding-2"> + <div class="post--body"> + <p>My dragon Martha has constantly been chasing my sheep around, and I'd like to get her to stop this + behavior.</p> + <p>Martha is a Hot Red Firebreather, and is five and a half feet long at about a year old (still pretty + young, since dragons are only fully grown at three). I've had her for about three months now. She's + generally very well-behaved - never breathing fire inside the house and not fighting with my neighbor's + old Sapphire Blue Waterspouter. However, every time she sees my (solitary) sheep, she chases him around + and bothers him, and it's really not good for the sheep.</p> + <p>I've asked around and done some research, and the folks at the Dwarven Library told me that I could paint + my sheep blue to prevent this from happening. However, I'm not looking to do anything to the sheep - just + for training the dragon.</p> + <p>I do not want to use any training methods that involve pain or restricting the dragon in any way, and I'm + not looking to do anything to the sheep. I'm pretty experienced in training dragons, but I've never had to + deal with this situation before.</p> + + <div class="post--meta has-margin-bottom-4"> + <div class="post--author has-float-right has-color-tertiary"> + <div title="2020-07-10T09:32:35Z">just now</div> + <div> + <img alt="user avatar" src="<%= current_user.nil? ? avatar_url(User.find(-1)) : avatar_url(current_user) %>" height="32" width="32" + class="has-float-left" /> + <div class="has-padding-1 has-float-left"> + <a href="#"><%= current_user&.username || "user31415" %></a> <span + class="badge is-user-trust-level is-muted"><%= current_user&.reputation || 1 %></span> + </div> + <div class="has-clear-clear"></div> + </div> + </div> + <div class="post--tags has-padding-2"> + <a class="badge is-tag " href="#">hot-red-firebreather</a> + <a class="badge is-tag " href="#">training</a> + <a class="badge is-tag " href="#">behavior</a> + </div> + </div> + <div class="has-clear-clear"></div> + + + <div class="post--actions"> + <div class="tools"> + <a class="tools--item" href="#"> + <i class="fa fa-link"></i> + Permalink + </a> <a class="tools--item" href="#"> + <i class="fa fa-history"></i> + History + </a> <a class="tools--item" href="#"> + <i class="fa fa-pencil-alt"></i> + Edit + </a> <a href="#" class="flag-dialog-link tools--item"> + <i class="fa fa-flag"></i> + Flag + </a> + </div> + </div> + + <div class="post--comments has-padding-4"> + <h4 class="has-margin-0"> + 0 comments + <span class="has-color-tertiary-500"></span> + </h4> + <div class="post--comments-container"> + </div> + + <div class="post--comments-links has-margin-top-1"> + <a href="#!">Add a comment</a> + </div> + </div> + </div> + </div> + </div> + </div> + + <h2 class="js-answer-counter">0 answers</h2> + + <div class="post hide js-good-answer" id="good-answer"> + <div class="post--container grid is-nowrap"> + <div class="grid--cell"> + <div class="post--votes has-text-align-center" title="0.5"> + <button class="tour-vote-button button is-icon-only-button" onclick="tour.firstAnswerUpvote(this);" aria-label="Upvote"> + <svg width="2em" height="1.33em" viewbox="0 0 100 50"> + <path d="M50,0 L100,50 L0,50 Z" fill="currentColor" /> + </svg> + </button> + <div class="score has-font-size-subheading js-upvote-count"> + +0 + </div> + <div class="score has-font-size-subheading js-downvote-count"> + −0 + </div> + <button class="tour-vote-button button is-icon-only-button " aria-label="Downvote"> + <svg width="2em" height="1.33em" viewbox="0 0 100 50"> + <path d="M0,0 L100,0 L50,50 Z" fill="currentColor" /> + </svg> + </button> + </div> + </div> + + <div class="grid--cell is-flexible has-padding-2"> + <div class="post--body"> + <p><strong>Music.</strong></p> + <p>It is well known, that dragons are quite sensitive to music. If you play the right music, it can calm your dragon down and it won't be chasing your sheep around anymore.</p> + <p>As you likely don't want Martha to sleep all day, you'll need to play the music only around the sheep. You could put a music player on their back for example.</p> + <p>The music won't affect the sheep much if at all, because they are less sensitive to it than dragons. However, you must <em>not play aggressive music</em>, because it can also make the dragon more aggressive, which is probably the last you want.</p> + <p>I have a dragon-calming playlist, you might want to <a href="#">check it out</a>.</p> + + <div class="post--meta has-margin-bottom-4"> + <div class="post--author has-float-right has-color-tertiary"> + <div title="2020-07-10T09:32:35Z">just now</div> + <div> + <img alt="user avatar" src="/assets/tour-clippy.png" height="32" width="32" + class="has-float-left" /> + <div class="has-padding-1 has-float-left"> + <a href="#">paper_clip</a> <span + class="badge is-user-trust-level is-muted">5013</span> + </div> + <div class="has-clear-clear"></div> + </div> + </div> + </div> + <div class="has-clear-clear"></div> + + + <div class="post--actions"> + <div class="tools"> + <a class="tools--item" href="#"> + <i class="fa fa-link"></i> + Permalink + </a> <a class="tools--item" href="#"> + <i class="fa fa-history"></i> + History + </a> <a href="#" class="flag-dialog-link tools--item"> + <i class="fa fa-flag"></i> + Flag + </a> + </div> + </div> + + <div class="post--comments has-padding-4"> + <h4 class="has-margin-0"> + 0 comments + <span class="has-color-tertiary-500"></span> + </h4> + <div class="post--comments-container"> + </div> + + <div class="post--comments-links has-margin-top-1"> + <a href="#!">Add a comment</a> + </div> + </div> + </div> + </div> + </div> + </div> + <div class="post hide js-bad-answer" id="bad-answer"> + <div class="post--container grid is-nowrap"> + <div class="grid--cell"> + <div class="post--votes has-text-align-center" title="0.5"> + <button class="tour-vote-button button is-icon-only-button" aria-label="Upvote"> + <svg width="2em" height="1.33em" viewbox="0 0 100 50"> + <path d="M50,0 L100,50 L0,50 Z" fill="currentColor" /> + </svg> + </button> + <div class="score has-font-size-subheading js-upvote-count"> + +0 + </div> + <div class="score has-font-size-subheading js-downvote-count"> + −0 + </div> + <button class="tour-vote-button button is-icon-only-button " aria-label="Downvote"> + <svg width="2em" height="1.33em" viewbox="0 0 100 50"> + <path d="M0,0 L100,0 L50,50 Z" fill="currentColor" /> + </svg> + </button> + </div> + </div> + + <div class="grid--cell is-flexible has-padding-2"> + <div class="post--body"> + <p>Well... that's your fault of keeping both a dragon and sheep. How stupid...</p> + + <div class="post--meta has-margin-bottom-4"> + <div class="post--author has-float-right has-color-tertiary"> + <div title="2020-07-10T09:32:35Z">just now</div> + <div> + <img alt="user avatar" src="/assets/tour-evil.png" height="32" width="32" + class="has-float-left" /> + <div class="has-padding-1 has-float-left"> + <a href="#">nas_tea</a> <span + class="badge is-user-trust-level is-muted">15</span> + </div> + <div class="has-clear-clear"></div> + </div> + </div> + </div> + <div class="has-clear-clear"></div> + + + <div class="post--actions"> + <div class="tools"> + <a class="tools--item" href="#"> + <i class="fa fa-link"></i> + Permalink + </a> <a class="tools--item" href="#"> + <i class="fa fa-history"></i> + History + </a> <a href="#!" class="flag-dialog-link tools--item"> + <i class="fa fa-flag"></i> + Flag + </a> + </div> + </div> + + + <div class="post--action-dialog js-flag-box"> + <div class="widget"> + <div class="widget--body"> + <label class="form-element" for="flag-bad-post"> + Why does this post require moderator attention? + </label> + <input class="form-element js-flag-comment" id="flag-bad-post> + </div> + <div class="widget--footer"> + <button class="js-tour-flag-link button is-filled is-muted" onclick="tour.secondAnswerFlag(this);"> + Flag for moderator attention + </button> + </div> + </div> + </div> + + <div class="tour-flag-success hide"> + <div class="notice is-success"> + <button class="button is-close-button" data-dismiss=".tour-flag-success" data-dismiss-soft>×</button> + <p>Thanks for your report. We'll look into it.</p> + </div> + </div> + + <div class="post--comments has-padding-4"> + <h4 class="has-margin-0"> + 0 comments + <span class="has-color-tertiary-500"></span> + </h4> + <div class="post--comments-container"> + </div> + + <div class="post--comments-links has-margin-top-1"> + <a href="#">Add a comment</a> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + <div class="grid--cell is-4"> + <div class="codidactyl-hints codidactyl-sticky"> + <div class="widget step-1"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>This is your post. We are currently waiting for other people to see and answer it.</p> + </div> + </div> + + <div class="widget step-2 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>Ooh. Nice. There is an answer to your question.</p> + <p>Read through it and consider whether it helps you solve your problem. Try out the solution if it's practical.</p> + </div> + <div class="widget--footer"> + <button class="button is-filled" data-step-from=".step-2" data-step-to=".step-3">Next</button> + </div> + </div> + + <div class="widget step-3 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>This answer looks helpful.</p> + <p>To show other users reading this answer, that you found it helpful (and also as a way to say "thanks" to the answerer), you can <em>upvote</em> it.</p> + <p>Voting also helps good content be more visible. Good answers are promoted to the top, while bad ones sink to the bottom. Please help curate the community by voting responsibly.</p> + <p>Do so by clicking the <svg class="h-c-tertiary-400" width="2em" height="1.33em" viewbox="0 0 100 50"> + <path d="M50,0 L100,50 L0,50 Z" fill="currentColor" /> + </svg> icon next to the post.</p> + </div> + <div class="widget--footer"> + <button class="button" data-step-from=".step-2" data-step-to=".step-3">Back</button> + </div> + </div> + + <div class="widget step-4 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>Thanks.</p> + <p>Let's wait for other answers, which might produce different solutions.</p> + </div> + </div> + + <div class="widget step-5 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>Oh. A second answer.</p> + <p>Unfortunately, it doesn't seem to be nice. It isn't helpful to the question and quite snarky.</p> + <p>We expect users to stay civil and to follow our minimal <a href="/policy/code-of-conduct">code of conduct</a>.</p> + <p>This answer should therefore be deleted. <em>Flag</em> it, so that one of our moderators can see and handle it.</p> + </div> + </div> + + <div class="widget step-6 hide"> + <div class="widget--header"> + <img src="/assets/codidactyl.png" alt="" class="codidactyl-small"> + Codidactyl's Hints + </div> + <div class="widget--body"> + <p>Thanks for flagging it.</p> + <p>A moderator will look at it and will likely remove the answer.</p> + <p>Flagging is important to help maintain the site. If you see something rude, flag it. Inappropriate content will get deleted, but somebody has to know about it first -- so flag to let moderators know. If you see anything else that doesn't look quite right, flag it and let us know about it.</p> + </div> + <div class="widget--footer"> + <a href="/tour/more" class="button is-filled">Find out more</a> + </div> + </div> + </div> + </div> +</div> + +<div class="js-tour-trigger-qa-page hide"></div> diff --git a/config/routes.rb b/config/routes.rb index 451a0cbe3167a822cf48c3d2d33f576be2e711a0..530976cc7a90ef3f071f1ac1114c493d092d3d98 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -226,6 +226,15 @@ Rails.application.routes.draw do get 'category/:id.png', to: 'advertisement#specific_category', as: :specific_category_ads end + scope 'tour' do + root to: 'tour#index', as: :tour + get 'q', to: 'tour#question1', as: :tour_q1 + get 'ask', to: 'tour#question2', as: :tour_q2 + get 'qa', to: 'tour#question3', as: :tour_q3 + get 'more', to: 'tour#more', as: :tour_more + get 'end', to: 'tour#end', as: :tour_end + end + get '403', to: 'errors#forbidden' get '404', to: 'errors#not_found' get '409', to: 'errors#conflict' diff --git a/public/assets/codidactyl.png b/public/assets/codidactyl.png new file mode 100644 index 0000000000000000000000000000000000000000..8a158fe6f08e6d09b7b83d41e7554a704dedc18a Binary files /dev/null and b/public/assets/codidactyl.png differ diff --git a/public/assets/tour-clippy.png b/public/assets/tour-clippy.png new file mode 100644 index 0000000000000000000000000000000000000000..f857cbedf2f0380b26968025d0a3fe1d88448106 Binary files /dev/null and b/public/assets/tour-clippy.png differ diff --git a/public/assets/tour-evil.png b/public/assets/tour-evil.png new file mode 100644 index 0000000000000000000000000000000000000000..25c5e3db1b973293f4ce1cacbe0f692e4bf20e83 Binary files /dev/null and b/public/assets/tour-evil.png differ diff --git a/test/controllers/tour_controller_test.rb b/test/controllers/tour_controller_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..32d5ac93be463b45f29be54c60275f9d4f566a57 --- /dev/null +++ b/test/controllers/tour_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class TourControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end