DEV: Chat service object initial implementation (#19814)
This is a combined work of Martin Brennan, Loïc Guitaut, and Joffrey Jaffeux. --- This commit implements a base service object when working in chat. The documentation is available at https://discourse.github.io/discourse/chat/backend/Chat/Service.html Generating documentation has been made as part of this commit with a bigger goal in mind of generally making it easier to dive into the chat project. Working with services generally involves 3 parts: - The service object itself, which is a series of steps where few of them are specialized (model, transaction, policy) ```ruby class UpdateAge include Chat::Service::Base model :user, :fetch_user policy :can_see_user contract step :update_age class Contract attribute :age, :integer end def fetch_user(user_id:, **) User.find_by(id: user_id) end def can_see_user(guardian:, **) guardian.can_see_user(user) end def update_age(age:, **) user.update!(age: age) end end ``` - The `with_service` controller helper, handling success and failure of the service within a service and making easy to return proper response to it from the controller ```ruby def update with_service(UpdateAge) do on_success { render_serialized(result.user, BasicUserSerializer, root: "user") } end end ``` - Rspec matchers and steps inspector, improving the dev experience while creating specs for a service ```ruby RSpec.describe(UpdateAge) do subject(:result) do described_class.call(guardian: guardian, user_id: user.id, age: age) end fab!(:user) { Fabricate(:user) } fab!(:current_user) { Fabricate(:admin) } let(:guardian) { Guardian.new(current_user) } let(:age) { 1 } it { expect(user.reload.age).to eq(age) } end ``` Note in case of unexpected failure in your spec, the output will give all the relevant information: ``` 1) UpdateAge when no channel_id is given is expected to fail to find a model named 'user' Failure/Error: it { is_expected.to fail_to_find_a_model(:user) } Expected model 'foo' (key: 'result.model.user') was not found in the result object. [1/4] [model] 'user' ❌ [2/4] [policy] 'can_see_user' [3/4] [contract] 'default' [4/4] [step] 'update_age' /Users/joffreyjaffeux/Code/pr-discourse/plugins/chat/app/services/update_age.rb:32:in `fetch_user': missing keyword: :user_id (ArgumentError) from /Users/joffreyjaffeux/Code/pr-discourse/plugins/chat/app/services/base.rb:202:in `instance_exec' from /Users/joffreyjaffeux/Code/pr-discourse/plugins/chat/app/services/base.rb:202:in `call' from /Users/joffreyjaffeux/Code/pr-discourse/plugins/chat/app/services/base.rb:219:in `call' from /Users/joffreyjaffeux/Code/pr-discourse/plugins/chat/app/services/base.rb:417:in `block in run!' from /Users/joffreyjaffeux/Code/pr-discourse/plugins/chat/app/services/base.rb:417:in `each' from /Users/joffreyjaffeux/Code/pr-discourse/plugins/chat/app/services/base.rb:417:in `run!' from /Users/joffreyjaffeux/Code/pr-discourse/plugins/chat/app/services/base.rb:411:in `run' from <internal:kernel>:90:in `tap' from /Users/joffreyjaffeux/Code/pr-discourse/plugins/chat/app/services/base.rb:302:in `call' from /Users/joffreyjaffeux/Code/pr-discourse/plugins/chat/spec/services/update_age_spec.rb:15:in `block (3 levels) in <main>' ```
This commit is contained in:
parent
81a4d75f06
commit
60ad836313
|
@ -12,3 +12,4 @@ node_modules/
|
|||
spec/
|
||||
dist/
|
||||
tmp/
|
||||
documentation/
|
||||
|
|
|
@ -7,7 +7,7 @@ on:
|
|||
- main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
@ -40,7 +40,6 @@ jobs:
|
|||
gem install bundler --conservative -v $(awk '/BUNDLED WITH/ { getline; gsub(/ /,""); print $0 }' Gemfile.lock)
|
||||
bundle config --local path vendor/bundle
|
||||
bundle config --local deployment true
|
||||
bundle config --local without development
|
||||
bundle install --jobs 4
|
||||
bundle clean
|
||||
|
||||
|
@ -60,17 +59,23 @@ jobs:
|
|||
- name: Yarn install
|
||||
run: yarn install
|
||||
|
||||
- name: Check Chat documentation
|
||||
- name: Check documentation
|
||||
run: |
|
||||
LOAD_PLUGINS=1 bin/rake chat:doc
|
||||
LOAD_PLUGINS=1 bin/rake documentation
|
||||
|
||||
if [ ! -z "$(git status --porcelain plugins/chat/docs/)" ]; then
|
||||
echo "Chat documentation is not up to date. To resolve, run:"
|
||||
echo " LOAD_PLUGINS=1 bin/rake chat:doc"
|
||||
if [ ! -z "$(git status --porcelain documentation/)" ]; then
|
||||
echo "Documentation is not up to date. To resolve, run:"
|
||||
echo " LOAD_PLUGINS=1 bin/rake documentation"
|
||||
echo
|
||||
echo "Or manually apply the diff printed below:"
|
||||
echo "---------------------------------------------"
|
||||
git -c color.ui=always diff plugins/chat/docs/
|
||||
git -c color.ui=always diff documentation/
|
||||
exit 1
|
||||
fi
|
||||
timeout-minutes: 30
|
||||
|
||||
- name: Deploy documentation to github pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./documentation
|
||||
|
|
14
.jsdoc
14
.jsdoc
|
@ -3,5 +3,19 @@
|
|||
{
|
||||
"source": {
|
||||
"excludePattern": ""
|
||||
},
|
||||
"templates": {
|
||||
"default": {
|
||||
"includeDate": false
|
||||
}
|
||||
},
|
||||
"opts": {
|
||||
"template": "./node_modules/tidy-jsdoc",
|
||||
"prism-theme": "prism-custom",
|
||||
"encoding": "utf8",
|
||||
"recurse": true
|
||||
},
|
||||
"metadata": {
|
||||
"title": "Discourse"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ plugins/**/assets/stylesheets/vendor/
|
|||
plugins/**/assets/javascripts/vendor/
|
||||
plugins/**/config/locales/**/*.yml
|
||||
plugins/**/config/*.yml
|
||||
documentation/
|
||||
package.json
|
||||
config/locales/**/*.yml
|
||||
!config/locales/**/*.en*.yml
|
||||
|
|
1
Gemfile
1
Gemfile
|
@ -180,6 +180,7 @@ group :development do
|
|||
gem "better_errors", platform: :mri, require: !!ENV["BETTER_ERRORS"]
|
||||
gem "binding_of_caller"
|
||||
gem "yaml-lint"
|
||||
gem "yard"
|
||||
end
|
||||
|
||||
if ENV["ALLOW_DEV_POPULATE"] == "1"
|
||||
|
|
|
@ -516,6 +516,8 @@ GEM
|
|||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
yaml-lint (0.1.2)
|
||||
yard (0.9.28)
|
||||
webrick (~> 1.7.0)
|
||||
zeitwerk (2.6.7)
|
||||
|
||||
PLATFORMS
|
||||
|
@ -663,6 +665,7 @@ DEPENDENCIES
|
|||
webrick
|
||||
xorcist
|
||||
yaml-lint
|
||||
yard
|
||||
|
||||
BUNDLED WITH
|
||||
2.4.4
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="960" height="375" viewBox="0 0 960 375" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M960 163.361C960 76.4166 861.5 2.37168e-05 574 0C286.5 -2.37168e-05 0 76.4166 0 163.361C0 250.306 124 385 415.5 373.5C707 362 960 250.306 960 163.361Z" fill="#FBF5AF"/>
|
||||
</svg>
|
After Width: | Height: | Size: 325 B |
|
@ -0,0 +1,6 @@
|
|||
<svg width="1867" height="475" viewBox="0 0 1867 475" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1865.6 220.428C1856.87 332.048 1771.2 390.61 1665.99 404.379C1563.03 417.858 1471.85 319.945 1480.58 208.325C1489.3 96.7051 1591.56 4.34115 1697.59 0.168844C1828.53 -4.98699 1874.33 108.807 1865.6 220.428Z" fill="#FBF5AF"/>
|
||||
<path d="M1464.63 416.562C1464.23 416.562 1463.83 416.594 1463.42 416.659C1458.84 417.393 1454.7 421.929 1455.71 428.253C1456.72 434.575 1462.62 438.145 1467.25 437.407C1469.45 437.053 1471.1 435.907 1472.15 433.993C1473.3 431.918 1473.65 429.03 1473.14 425.867C1472.64 422.761 1471.34 420.134 1469.46 418.463C1468.05 417.209 1466.4 416.562 1464.63 416.562ZM1465.91 444.071C1457.94 444.071 1450.59 437.774 1449.23 429.29C1447.75 419.993 1453.52 411.598 1462.38 410.179C1466.57 409.514 1470.62 410.714 1473.82 413.561C1476.83 416.233 1478.89 420.237 1479.62 424.827C1480.37 429.495 1479.77 433.758 1477.9 437.154C1475.88 440.829 1472.47 443.217 1468.29 443.883C1467.49 444.011 1466.7 444.071 1465.91 444.071" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M344 323.966C344 353.644 324.906 366.211 293.64 366.211C262.374 366.211 223 321.874 223 292.194C223 262.514 272.175 254 303.441 254C334.707 254 344 294.286 344 323.966Z" fill="#0CA64E"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M396.325 444.694C396.653 458.473 386.913 467.649 370.18 473.648C356.257 478.638 342.267 465.392 336.512 453.65C330.052 440.465 344.903 425.749 369.376 421.378C383.936 418.778 395.973 429.909 396.325 444.694Z" fill="#E84A51"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 97 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 7.2 KiB |
|
@ -0,0 +1,118 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
Module: Chat
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "Chat";
|
||||
relpath = '';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="_index.html">Index (C)</a> »
|
||||
|
||||
|
||||
<span class="title">Chat</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><h1>Module: Chat
|
||||
|
||||
|
||||
|
||||
</h1>
|
||||
<div class="box_info">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Defined in:</dt>
|
||||
<dd>plugins/chat/app/services/base.rb<span class="defines">,<br />
|
||||
plugins/chat/app/services/update_user_last_read.rb,<br /> plugins/chat/app/services/trash_channel.rb,<br /> plugins/chat/app/services/update_channel.rb,<br /> plugins/chat/app/services/update_channel_status.rb</span>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<h2>Defined Under Namespace</h2>
|
||||
<p class="children">
|
||||
|
||||
|
||||
<strong class="modules">Modules:</strong> <span class='object_link'><a href="Chat/Service.html" title="Chat::Service (module)">Service</a></span>
|
||||
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,120 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
Module: Chat::Service
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="../css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="../css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "Chat::Service";
|
||||
relpath = '../';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="../class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="../_index.html">Index (S)</a> »
|
||||
<span class='title'><span class='object_link'><a href="../Chat.html" title="Chat (module)">Chat</a></span></span>
|
||||
»
|
||||
<span class="title">Service</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="../class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><h1>Module: Chat::Service
|
||||
|
||||
|
||||
|
||||
</h1>
|
||||
<div class="box_info">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Defined in:</dt>
|
||||
<dd>plugins/chat/app/services/base.rb<span class="defines">,<br />
|
||||
plugins/chat/app/services/update_user_last_read.rb,<br /> plugins/chat/app/services/trash_channel.rb,<br /> plugins/chat/app/services/update_channel.rb,<br /> plugins/chat/app/services/update_channel_status.rb</span>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<h2>Defined Under Namespace</h2>
|
||||
<p class="children">
|
||||
|
||||
|
||||
<strong class="modules">Modules:</strong> <span class='object_link'><a href="Service/Base.html" title="Chat::Service::Base (module)">Base</a></span>
|
||||
|
||||
|
||||
|
||||
<strong class="classes">Classes:</strong> <span class='object_link'><a href="Service/TrashChannel.html" title="Chat::Service::TrashChannel (class)">TrashChannel</a></span>, <span class='object_link'><a href="Service/UpdateChannel.html" title="Chat::Service::UpdateChannel (class)">UpdateChannel</a></span>, <span class='object_link'><a href="Service/UpdateChannelStatus.html" title="Chat::Service::UpdateChannelStatus (class)">UpdateChannelStatus</a></span>, <span class='object_link'><a href="Service/UpdateUserLastRead.html" title="Chat::Service::UpdateUserLastRead (class)">UpdateUserLastRead</a></span>
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,723 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
Module: Chat::Service::Base
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="../../css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="../../css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "Chat::Service::Base";
|
||||
relpath = '../../';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="../../class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="../../_index.html">Index (B)</a> »
|
||||
<span class='title'><span class='object_link'><a href="../../Chat.html" title="Chat (module)">Chat</a></span></span> » <span class='title'><span class='object_link'><a href="../Service.html" title="Chat::Service (module)">Service</a></span></span>
|
||||
»
|
||||
<span class="title">Base</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="../../class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><h1>Module: Chat::Service::Base
|
||||
|
||||
|
||||
|
||||
</h1>
|
||||
<div class="box_info">
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Extended by:</dt>
|
||||
<dd>ActiveSupport::Concern</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Included in:</dt>
|
||||
<dd><span class='object_link'><a href="TrashChannel.html" title="Chat::Service::TrashChannel (class)">TrashChannel</a></span>, <span class='object_link'><a href="UpdateChannel.html" title="Chat::Service::UpdateChannel (class)">UpdateChannel</a></span>, <span class='object_link'><a href="UpdateChannelStatus.html" title="Chat::Service::UpdateChannelStatus (class)">UpdateChannelStatus</a></span>, <span class='object_link'><a href="UpdateUserLastRead.html" title="Chat::Service::UpdateUserLastRead (class)">UpdateUserLastRead</a></span></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Defined in:</dt>
|
||||
<dd>plugins/chat/app/services/base.rb</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<h2>Overview</h2><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Module to be included to provide steps DSL to any class. This allows to create easy to understand services as the whole service cycle is visible simply by reading the beginning of its class.</p>
|
||||
|
||||
<p>Steps are executed in the order they’re defined. They will use their name to execute the corresponding method defined in the service class.</p>
|
||||
|
||||
<p>Currently, there are 5 types of steps:</p>
|
||||
<ul><li>
|
||||
<p><tt>model(name = :model)</tt>: used to instantiate a model (either by building it or fetching it from the DB). If a falsy value is returned, then the step will fail. Otherwise the resulting object will be assigned in <code>context[name]</code> (<code>context[:model]</code> by default).</p>
|
||||
</li><li>
|
||||
<p><tt>policy(name = :default)</tt>: used to perform a check on the state of the system. Typically used to run guardians. If a falsy value is returned, the step will fail.</p>
|
||||
</li><li>
|
||||
<p><tt>contract(name = :default)</tt>: used to validate the input parameters, typically provided by a user calling an endpoint. A special embedded <code>Contract</code> class has to be defined to holds the validations. If the validations fail, the step will fail. Otherwise, the resulting contract will be available in <tt><a href=":"contract.default"">context</a></tt>.</p>
|
||||
</li><li>
|
||||
<p><tt>step(name)</tt>: used to run small snippets of arbitrary code. The step doesn’t care about its return value, so to mark the service as failed, #fail! has to be called explicitly.</p>
|
||||
</li><li>
|
||||
<p><code>transaction</code>: used to wrap other steps inside a DB transaction.</p>
|
||||
</li></ul>
|
||||
|
||||
<p>The methods defined on the service are automatically provided with the whole context passed as keyword arguments. This allows to define in a very explicit way what dependencies are used by the method. If for whatever reason a key isn’t found in the current context, then Ruby will raise an exception when the method is called.</p>
|
||||
|
||||
<p>Regarding contract classes, they have automatically ActiveModel modules included so all the ActiveModel API is available.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<p class="example_title"><div class='inline'>
|
||||
<p>An example from the <span class='object_link'><a href="TrashChannel.html" title="Chat::Service::TrashChannel (class)">TrashChannel</a></span> service</p>
|
||||
</div></p>
|
||||
|
||||
<pre class="example code"><code><span class='kw'>class</span> <span class='const'><span class='object_link'><a href="TrashChannel.html" title="Chat::Service::TrashChannel (class)">TrashChannel</a></span></span>
|
||||
<span class='id identifier rubyid_include'>include</span> <span class='const'>Base</span>
|
||||
|
||||
<span class='id identifier rubyid_model'>model</span> <span class='symbol'>:channel</span><span class='comma'>,</span> <span class='symbol'>:fetch_channel</span>
|
||||
<span class='id identifier rubyid_policy'>policy</span> <span class='symbol'>:invalid_access</span>
|
||||
<span class='id identifier rubyid_transaction'>transaction</span> <span class='kw'>do</span>
|
||||
<span class='id identifier rubyid_step'>step</span> <span class='symbol'>:prevents_slug_collision</span>
|
||||
<span class='id identifier rubyid_step'>step</span> <span class='symbol'>:soft_delete_channel</span>
|
||||
<span class='id identifier rubyid_step'>step</span> <span class='symbol'>:log_channel_deletion</span>
|
||||
<span class='kw'>end</span>
|
||||
<span class='id identifier rubyid_step'>step</span> <span class='symbol'>:enqueue_delete_channel_relations_job</span>
|
||||
|
||||
<span class='id identifier rubyid_private'>private</span>
|
||||
|
||||
<span class='kw'>def</span> <span class='id identifier rubyid_fetch_channel'>fetch_channel</span><span class='lparen'>(</span><span class='label'>channel_id:</span><span class='comma'>,</span> <span class='op'>**</span><span class='rparen'>)</span>
|
||||
<span class='const'>ChatChannel</span><span class='period'>.</span><span class='id identifier rubyid_find_by'>find_by</span><span class='lparen'>(</span><span class='label'>id:</span> <span class='id identifier rubyid_channel_id'>channel_id</span><span class='rparen'>)</span>
|
||||
<span class='kw'>end</span>
|
||||
|
||||
<span class='kw'>def</span> <span class='id identifier rubyid_invalid_access'>invalid_access</span><span class='lparen'>(</span><span class='label'>guardian:</span><span class='comma'>,</span> <span class='label'>channel:</span><span class='comma'>,</span> <span class='op'>**</span><span class='rparen'>)</span>
|
||||
<span class='id identifier rubyid_guardian'>guardian</span><span class='period'>.</span><span class='id identifier rubyid_can_preview_chat_channel?'>can_preview_chat_channel?</span><span class='lparen'>(</span><span class='id identifier rubyid_channel'>channel</span><span class='rparen'>)</span> <span class='op'>&&</span> <span class='id identifier rubyid_guardian'>guardian</span><span class='period'>.</span><span class='id identifier rubyid_can_delete_chat_channel?'>can_delete_chat_channel?</span>
|
||||
<span class='kw'>end</span>
|
||||
|
||||
<span class='kw'>def</span> <span class='id identifier rubyid_prevents_slug_collision'>prevents_slug_collision</span><span class='lparen'>(</span><span class='label'>channel:</span><span class='comma'>,</span> <span class='op'>**</span><span class='rparen'>)</span>
|
||||
<span class='id identifier rubyid_…'>…</span>
|
||||
<span class='kw'>end</span>
|
||||
|
||||
<span class='kw'>def</span> <span class='id identifier rubyid_soft_delete_channel'>soft_delete_channel</span><span class='lparen'>(</span><span class='label'>guardian:</span><span class='comma'>,</span> <span class='label'>channel:</span><span class='comma'>,</span> <span class='op'>**</span><span class='rparen'>)</span>
|
||||
<span class='id identifier rubyid_…'>…</span>
|
||||
<span class='kw'>end</span>
|
||||
|
||||
<span class='kw'>def</span> <span class='id identifier rubyid_log_channel_deletion'>log_channel_deletion</span><span class='lparen'>(</span><span class='label'>guardian:</span><span class='comma'>,</span> <span class='label'>channel:</span><span class='comma'>,</span> <span class='op'>**</span><span class='rparen'>)</span>
|
||||
<span class='id identifier rubyid_…'>…</span>
|
||||
<span class='kw'>end</span>
|
||||
|
||||
<span class='kw'>def</span> <span class='id identifier rubyid_enqueue_delete_channel_relations_job'>enqueue_delete_channel_relations_job</span><span class='lparen'>(</span><span class='label'>channel:</span><span class='comma'>,</span> <span class='op'>**</span><span class='rparen'>)</span>
|
||||
<span class='id identifier rubyid_…'>…</span>
|
||||
<span class='kw'>end</span>
|
||||
<span class='kw'>end</span></code></pre>
|
||||
|
||||
|
||||
<p class="example_title"><div class='inline'>
|
||||
<p>An example from the <span class='object_link'><a href="UpdateChannelStatus.html" title="Chat::Service::UpdateChannelStatus (class)">UpdateChannelStatus</a></span> service which uses a contract</p>
|
||||
</div></p>
|
||||
|
||||
<pre class="example code"><code><span class='kw'>class</span> <span class='const'><span class='object_link'><a href="UpdateChannelStatus.html" title="Chat::Service::UpdateChannelStatus (class)">UpdateChannelStatus</a></span></span>
|
||||
<span class='id identifier rubyid_include'>include</span> <span class='const'>Base</span>
|
||||
|
||||
<span class='id identifier rubyid_model'>model</span> <span class='symbol'>:channel</span><span class='comma'>,</span> <span class='symbol'>:fetch_channel</span>
|
||||
<span class='id identifier rubyid_contract'>contract</span>
|
||||
<span class='id identifier rubyid_policy'>policy</span> <span class='symbol'>:check_channel_permission</span>
|
||||
<span class='id identifier rubyid_step'>step</span> <span class='symbol'>:change_status</span>
|
||||
|
||||
<span class='kw'>class</span> <span class='const'>Contract</span>
|
||||
<span class='id identifier rubyid_attribute'>attribute</span> <span class='symbol'>:status</span>
|
||||
<span class='id identifier rubyid_validates'>validates</span> <span class='symbol'>:status</span><span class='comma'>,</span> <span class='label'>inclusion:</span> <span class='lbrace'>{</span> <span class='label'>in:</span> <span class='const'>ChatChannel</span><span class='period'>.</span><span class='id identifier rubyid_editable_statuses'>editable_statuses</span><span class='period'>.</span><span class='id identifier rubyid_keys'>keys</span> <span class='rbrace'>}</span>
|
||||
<span class='kw'>end</span>
|
||||
|
||||
<span class='id identifier rubyid_…'>…</span>
|
||||
<span class='kw'>end</span></code></pre>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div><h2>Defined Under Namespace</h2>
|
||||
<p class="children">
|
||||
|
||||
|
||||
|
||||
|
||||
<strong class="classes">Classes:</strong> <span class='object_link'><a href="Base/Context.html" title="Chat::Service::Base::Context (class)">Context</a></span>, <span class='object_link'><a href="Base/Failure.html" title="Chat::Service::Base::Failure (class)">Failure</a></span>
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
Class Method Summary
|
||||
<small><a href="#" class="summary_toggle">collapse</a></small>
|
||||
</h2>
|
||||
|
||||
<ul class="summary">
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#contract-class_method" title="contract (class method)">.<strong>contract</strong>(name = :default, class_name: self::Contract, use_default_values_from: nil) ⇒ Object </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'>
|
||||
<p>Checks the validity of the input parameters.</p>
|
||||
</div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#model-class_method" title="model (class method)">.<strong>model</strong>(name = :model, step_name = :"fetch_#{name}") ⇒ Object </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'>
|
||||
<p>Evaluates arbitrary code to build or fetch a model (typically from the DB).</p>
|
||||
</div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#policy-class_method" title="policy (class method)">.<strong>policy</strong>(name = :default) ⇒ Object </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'>
|
||||
<p>Performs checks related to the state of the system.</p>
|
||||
</div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#step-class_method" title="step (class method)">.<strong>step</strong>(name) ⇒ Object </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'>
|
||||
<p>Runs arbitrary code.</p>
|
||||
</div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#transaction-class_method" title="transaction (class method)">.<strong>transaction</strong>(&block) ⇒ Object </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'>
|
||||
<p>Runs steps inside a DB transaction.</p>
|
||||
</div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div id="class_method_details" class="method_details_list">
|
||||
<h2>Class Method Details</h2>
|
||||
|
||||
|
||||
<div class="method_details first">
|
||||
<h3 class="signature first" id="contract-class_method">
|
||||
|
||||
.<strong>contract</strong>(name = :default, class_name: self::Contract, use_default_values_from: nil) ⇒ <tt>Object</tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Checks the validity of the input parameters. Implements ActiveModel::Validations and ActiveModel::Attributes.</p>
|
||||
|
||||
<p>It stores the resulting contract in <tt>context [“contract.default”]</tt> by default (can be customized by providing the <code>name</code> argument).</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<pre class="example code"><code><span class='id identifier rubyid_contract'>contract</span>
|
||||
|
||||
<span class='kw'>class</span> <span class='const'>Contract</span>
|
||||
<span class='id identifier rubyid_attribute'>attribute</span> <span class='symbol'>:name</span>
|
||||
<span class='id identifier rubyid_validates'>validates</span> <span class='symbol'>:name</span><span class='comma'>,</span> <span class='label'>presence:</span> <span class='kw'>true</span>
|
||||
<span class='kw'>end</span></code></pre>
|
||||
|
||||
</div>
|
||||
<p class="tag_title">Parameters:</p>
|
||||
<ul class="param">
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>name</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Symbol</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt>:default</tt>)</em>
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>name for this contract</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>class_name</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Class</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt>self::Contract</tt>)</em>
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>a class defining the contract</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>use_default_values_from</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Symbol</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt>nil</tt>)</em>
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>name of the model to get default values from</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method_details ">
|
||||
<h3 class="signature " id="model-class_method">
|
||||
|
||||
.<strong>model</strong>(name = :model, step_name = :"fetch_#{name}") ⇒ <tt>Object</tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Evaluates arbitrary code to build or fetch a model (typically from the DB). If the step returns a falsy value, then the step will fail.</p>
|
||||
|
||||
<p>It stores the resulting model in <code>context[:model]</code> by default (can be customized by providing the <code>name</code> argument).</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<pre class="example code"><code><span class='id identifier rubyid_model'>model</span> <span class='symbol'>:channel</span><span class='comma'>,</span> <span class='symbol'>:fetch_channel</span>
|
||||
|
||||
<span class='id identifier rubyid_private'>private</span>
|
||||
|
||||
<span class='kw'>def</span> <span class='id identifier rubyid_fetch_channel'>fetch_channel</span><span class='lparen'>(</span><span class='label'>channel_id:</span><span class='comma'>,</span> <span class='op'>**</span><span class='rparen'>)</span>
|
||||
<span class='const'>ChatChannel</span><span class='period'>.</span><span class='id identifier rubyid_find_by'>find_by</span><span class='lparen'>(</span><span class='label'>id:</span> <span class='id identifier rubyid_channel_id'>channel_id</span><span class='rparen'>)</span>
|
||||
<span class='kw'>end</span></code></pre>
|
||||
|
||||
</div>
|
||||
<p class="tag_title">Parameters:</p>
|
||||
<ul class="param">
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>name</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Symbol</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt>:model</tt>)</em>
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>name of the model</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>step_name</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Symbol</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt>:"fetch_#{name}"</tt>)</em>
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>name of the method to call for this step</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method_details ">
|
||||
<h3 class="signature " id="policy-class_method">
|
||||
|
||||
.<strong>policy</strong>(name = :default) ⇒ <tt>Object</tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Performs checks related to the state of the system. If the step doesn’t return a truthy value, then the policy will fail.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<pre class="example code"><code><span class='id identifier rubyid_policy'>policy</span> <span class='symbol'>:no_direct_message_channel</span>
|
||||
|
||||
<span class='id identifier rubyid_private'>private</span>
|
||||
|
||||
<span class='kw'>def</span> <span class='id identifier rubyid_no_direct_message_channel'>no_direct_message_channel</span><span class='lparen'>(</span><span class='label'>channel:</span><span class='comma'>,</span> <span class='op'>**</span><span class='rparen'>)</span>
|
||||
<span class='op'>!</span><span class='id identifier rubyid_channel'>channel</span><span class='period'>.</span><span class='id identifier rubyid_direct_message_channel?'>direct_message_channel?</span>
|
||||
<span class='kw'>end</span></code></pre>
|
||||
|
||||
</div>
|
||||
<p class="tag_title">Parameters:</p>
|
||||
<ul class="param">
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>name</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Symbol</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt>:default</tt>)</em>
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>name for this policy</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method_details ">
|
||||
<h3 class="signature " id="step-class_method">
|
||||
|
||||
.<strong>step</strong>(name) ⇒ <tt>Object</tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Runs arbitrary code. To mark a step as failed, a call to #fail! needs to be made explicitly.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<pre class="example code"><code><span class='id identifier rubyid_step'>step</span> <span class='symbol'>:update_channel</span>
|
||||
|
||||
<span class='id identifier rubyid_private'>private</span>
|
||||
|
||||
<span class='kw'>def</span> <span class='id identifier rubyid_update_channel'>update_channel</span><span class='lparen'>(</span><span class='label'>channel:</span><span class='comma'>,</span> <span class='label'>params_to_edit:</span><span class='comma'>,</span> <span class='op'>**</span><span class='rparen'>)</span>
|
||||
<span class='id identifier rubyid_channel'>channel</span><span class='period'>.</span><span class='id identifier rubyid_update!'>update!</span><span class='lparen'>(</span><span class='id identifier rubyid_params_to_edit'>params_to_edit</span><span class='rparen'>)</span>
|
||||
<span class='kw'>end</span></code></pre>
|
||||
|
||||
|
||||
<p class="example_title"><div class='inline'>
|
||||
<p>using #fail! in a step</p>
|
||||
</div></p>
|
||||
|
||||
<pre class="example code"><code><span class='id identifier rubyid_step'>step</span> <span class='symbol'>:save_channel</span>
|
||||
|
||||
<span class='id identifier rubyid_private'>private</span>
|
||||
|
||||
<span class='kw'>def</span> <span class='id identifier rubyid_save_channel'>save_channel</span><span class='lparen'>(</span><span class='label'>channel:</span><span class='comma'>,</span> <span class='op'>**</span><span class='rparen'>)</span>
|
||||
<span class='id identifier rubyid_fail!'>fail!</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>something went wrong</span><span class='tstring_end'>"</span></span><span class='rparen'>)</span> <span class='kw'>unless</span> <span class='id identifier rubyid_channel'>channel</span><span class='period'>.</span><span class='id identifier rubyid_save'>save</span>
|
||||
<span class='kw'>end</span></code></pre>
|
||||
|
||||
</div>
|
||||
<p class="tag_title">Parameters:</p>
|
||||
<ul class="param">
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>name</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Symbol</tt>)</span>
|
||||
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>the name of this step</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method_details ">
|
||||
<h3 class="signature " id="transaction-class_method">
|
||||
|
||||
.<strong>transaction</strong>(&block) ⇒ <tt>Object</tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Runs steps inside a DB transaction.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<pre class="example code"><code><span class='id identifier rubyid_transaction'>transaction</span> <span class='kw'>do</span>
|
||||
<span class='id identifier rubyid_step'>step</span> <span class='symbol'>:prevents_slug_collision</span>
|
||||
<span class='id identifier rubyid_step'>step</span> <span class='symbol'>:soft_delete_channel</span>
|
||||
<span class='id identifier rubyid_step'>step</span> <span class='symbol'>:log_channel_deletion</span>
|
||||
<span class='kw'>end</span></code></pre>
|
||||
|
||||
</div>
|
||||
<p class="tag_title">Parameters:</p>
|
||||
<ul class="param">
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>block</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Proc</tt>)</span>
|
||||
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>a block containing steps to be run inside a transaction</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,485 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
Class: Chat::Service::Base::Context
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="../../../css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "Chat::Service::Base::Context";
|
||||
relpath = '../../../';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../../js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../../js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="../../../class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="../../../_index.html">Index (C)</a> »
|
||||
<span class='title'><span class='object_link'><a href="../../../Chat.html" title="Chat (module)">Chat</a></span></span> » <span class='title'><span class='object_link'><a href="../../Service.html" title="Chat::Service (module)">Service</a></span></span> » <span class='title'><span class='object_link'><a href="../Base.html" title="Chat::Service::Base (module)">Base</a></span></span>
|
||||
»
|
||||
<span class="title">Context</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="../../../class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><h1>Class: Chat::Service::Base::Context
|
||||
|
||||
|
||||
|
||||
</h1>
|
||||
<div class="box_info">
|
||||
|
||||
<dl>
|
||||
<dt>Inherits:</dt>
|
||||
<dd>
|
||||
<span class="inheritName">OpenStruct</span>
|
||||
|
||||
<ul class="fullTree">
|
||||
<li>Object</li>
|
||||
|
||||
<li class="next">OpenStruct</li>
|
||||
|
||||
<li class="next">Chat::Service::Base::Context</li>
|
||||
|
||||
</ul>
|
||||
<a href="#" class="inheritanceTree">show all</a>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Defined in:</dt>
|
||||
<dd>plugins/chat/app/services/base.rb</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<h2>Overview</h2><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Simple structure to hold the context of the service during its whole lifecycle.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
Instance Method Summary
|
||||
<small><a href="#" class="summary_toggle">collapse</a></small>
|
||||
</h2>
|
||||
|
||||
<ul class="summary">
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#fail-instance_method" title="#fail (instance method)">#<strong>fail</strong>(context = {}) ⇒ Context </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'>
|
||||
<p>Marks the context as failed without raising an exception.</p>
|
||||
</div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#fail!-instance_method" title="#fail! (instance method)">#<strong>fail!</strong>(context = {}) ⇒ Context </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'>
|
||||
<p>Marks the context as failed.</p>
|
||||
</div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#failure%3F-instance_method" title="#failure? (instance method)">#<strong>failure?</strong> ⇒ Boolean </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'>
|
||||
<p>Returns <code>true</code> if the context is set as failed.</p>
|
||||
</div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#success%3F-instance_method" title="#success? (instance method)">#<strong>success?</strong> ⇒ Boolean </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'>
|
||||
<p>Returns <code>true</code> if the conext is set as successful (default).</p>
|
||||
</div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div id="instance_method_details" class="method_details_list">
|
||||
<h2>Instance Method Details</h2>
|
||||
|
||||
|
||||
<div class="method_details first">
|
||||
<h3 class="signature first" id="fail-instance_method">
|
||||
|
||||
#<strong>fail</strong>(context = {}) ⇒ <tt><span class='object_link'><a href="" title="Chat::Service::Base::Context (class)">Context</a></span></tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Marks the context as failed without raising an exception.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<pre class="example code"><code><span class='id identifier rubyid_context'>context</span><span class='period'>.</span><span class='id identifier rubyid_fail'>fail</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>failure</span><span class='label_end'>":</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>something went wrong</span><span class='tstring_end'>"</span></span><span class='rparen'>)</span></code></pre>
|
||||
|
||||
</div>
|
||||
<p class="tag_title">Parameters:</p>
|
||||
<ul class="param">
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>context</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Hash</tt>, <tt><span class='object_link'><a href="" title="Chat::Service::Base::Context (class)">Context</a></span></tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt>{}</tt>)</em>
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>the context to merge into the current one</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p class="tag_title">Returns:</p>
|
||||
<ul class="return">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
<span class='type'>(<tt><span class='object_link'><a href="" title="Chat::Service::Base::Context (class)">Context</a></span></tt>)</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method_details ">
|
||||
<h3 class="signature " id="fail!-instance_method">
|
||||
|
||||
#<strong>fail!</strong>(context = {}) ⇒ <tt><span class='object_link'><a href="" title="Chat::Service::Base::Context (class)">Context</a></span></tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Marks the context as failed.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<pre class="example code"><code><span class='id identifier rubyid_context'>context</span><span class='period'>.</span><span class='id identifier rubyid_fail!'>fail!</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>failure</span><span class='label_end'>":</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>something went wrong</span><span class='tstring_end'>"</span></span><span class='rparen'>)</span></code></pre>
|
||||
|
||||
</div>
|
||||
<p class="tag_title">Parameters:</p>
|
||||
<ul class="param">
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>context</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Hash</tt>, <tt><span class='object_link'><a href="" title="Chat::Service::Base::Context (class)">Context</a></span></tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt>{}</tt>)</em>
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>the context to merge into the current one</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p class="tag_title">Returns:</p>
|
||||
<ul class="return">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
<span class='type'>(<tt><span class='object_link'><a href="" title="Chat::Service::Base::Context (class)">Context</a></span></tt>)</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<p class="tag_title">Raises:</p>
|
||||
<ul class="raise">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
<span class='type'>(<tt><span class='object_link'><a href="Failure.html" title="Chat::Service::Base::Failure (class)">Failure</a></span></tt>)</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method_details ">
|
||||
<h3 class="signature " id="failure?-instance_method">
|
||||
|
||||
#<strong>failure?</strong> ⇒ <tt>Boolean</tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Returns <code>true</code> if the context is set as failed</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<p class="tag_title">Returns:</p>
|
||||
<ul class="return">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Boolean</tt>)</span>
|
||||
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>returns <code>true</code> if the context is set as failed</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p class="tag_title">See Also:</p>
|
||||
<ul class="see">
|
||||
|
||||
<li><span class='object_link'><a href="#fail!-instance_method" title="Chat::Service::Base::Context#fail! (method)">#fail!</a></span></li>
|
||||
|
||||
<li><span class='object_link'><a href="#fail-instance_method" title="Chat::Service::Base::Context#fail (method)">#fail</a></span></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="method_details ">
|
||||
<h3 class="signature " id="success?-instance_method">
|
||||
|
||||
#<strong>success?</strong> ⇒ <tt>Boolean</tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Returns <code>true</code> if the conext is set as successful (default)</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<p class="tag_title">Returns:</p>
|
||||
<ul class="return">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Boolean</tt>)</span>
|
||||
|
||||
|
||||
|
||||
—
|
||||
<div class='inline'>
|
||||
<p>returns <code>true</code> if the conext is set as successful (default)</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,209 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
Exception: Chat::Service::Base::Failure
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="../../../css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="../../../css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "Chat::Service::Base::Failure";
|
||||
relpath = '../../../';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../../js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../../js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="../../../class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="../../../_index.html">Index (F)</a> »
|
||||
<span class='title'><span class='object_link'><a href="../../../Chat.html" title="Chat (module)">Chat</a></span></span> » <span class='title'><span class='object_link'><a href="../../Service.html" title="Chat::Service (module)">Service</a></span></span> » <span class='title'><span class='object_link'><a href="../Base.html" title="Chat::Service::Base (module)">Base</a></span></span>
|
||||
»
|
||||
<span class="title">Failure</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="../../../class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><h1>Exception: Chat::Service::Base::Failure
|
||||
|
||||
|
||||
|
||||
</h1>
|
||||
<div class="box_info">
|
||||
|
||||
<dl>
|
||||
<dt>Inherits:</dt>
|
||||
<dd>
|
||||
<span class="inheritName">StandardError</span>
|
||||
|
||||
<ul class="fullTree">
|
||||
<li>Object</li>
|
||||
|
||||
<li class="next">StandardError</li>
|
||||
|
||||
<li class="next">Chat::Service::Base::Failure</li>
|
||||
|
||||
</ul>
|
||||
<a href="#" class="inheritanceTree">show all</a>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Defined in:</dt>
|
||||
<dd>plugins/chat/app/services/base.rb</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<h2>Overview</h2><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>The only exception that can be raised by a service.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h2>Instance Attribute Summary <small><a href="#" class="summary_toggle">collapse</a></small></h2>
|
||||
<ul class="summary">
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#context-instance_method" title="#context (instance method)">#<strong>context</strong> ⇒ Context </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="note title readonly">readonly</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'></div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div id="instance_attr_details" class="attr_details">
|
||||
<h2>Instance Attribute Details</h2>
|
||||
|
||||
|
||||
<span id=""></span>
|
||||
<div class="method_details first">
|
||||
<h3 class="signature first" id="context-instance_method">
|
||||
|
||||
#<strong>context</strong> ⇒ <tt><span class='object_link'><a href="Context.html" title="Chat::Service::Base::Context (class)">Context</a></span></tt> <span class="extras">(readonly)</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<p class="tag_title">Returns:</p>
|
||||
<ul class="return">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
<span class='type'>(<tt><span class='object_link'><a href="Context.html" title="Chat::Service::Base::Context (class)">Context</a></span></tt>)</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,277 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
Class: Chat::Service::TrashChannel
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="../../css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="../../css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "Chat::Service::TrashChannel";
|
||||
relpath = '../../';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="../../class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="../../_index.html">Index (T)</a> »
|
||||
<span class='title'><span class='object_link'><a href="../../Chat.html" title="Chat (module)">Chat</a></span></span> » <span class='title'><span class='object_link'><a href="../Service.html" title="Chat::Service (module)">Service</a></span></span>
|
||||
»
|
||||
<span class="title">TrashChannel</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="../../class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><h1>Class: Chat::Service::TrashChannel
|
||||
|
||||
|
||||
|
||||
</h1>
|
||||
<div class="box_info">
|
||||
|
||||
<dl>
|
||||
<dt>Inherits:</dt>
|
||||
<dd>
|
||||
<span class="inheritName">Object</span>
|
||||
|
||||
<ul class="fullTree">
|
||||
<li>Object</li>
|
||||
|
||||
<li class="next">Chat::Service::TrashChannel</li>
|
||||
|
||||
</ul>
|
||||
<a href="#" class="inheritanceTree">show all</a>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Includes:</dt>
|
||||
<dd><span class='object_link'><a href="Base.html" title="Chat::Service::Base (module)">Base</a></span></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Defined in:</dt>
|
||||
<dd>plugins/chat/app/services/trash_channel.rb</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<h2>Overview</h2><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Service responsible for trashing a chat channel. Note the slug is modified to prevent collisions.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<pre class="example code"><code><span class='const'><span class='object_link'><a href="../../Chat.html" title="Chat (module)">Chat</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="../Service.html" title="Chat::Service (module)">Service</a></span></span><span class='op'>::</span><span class='const'>TrashChannel</span><span class='period'>.</span><span class='id identifier rubyid_call'><span class='object_link'><a href="#call-instance_method" title="Chat::Service::TrashChannel#call (method)">call</a></span></span><span class='lparen'>(</span><span class='label'>channel_id:</span> <span class='int'>2</span><span class='comma'>,</span> <span class='label'>guardian:</span> <span class='id identifier rubyid_guardian'>guardian</span><span class='rparen'>)</span></code></pre>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<h2>
|
||||
Constant Summary
|
||||
<small><a href="#" class="constants_summary_toggle">collapse</a></small>
|
||||
</h2>
|
||||
|
||||
<dl class="constants">
|
||||
|
||||
<dt id="DELETE_CHANNEL_LOG_KEY-constant" class="">DELETE_CHANNEL_LOG_KEY =
|
||||
|
||||
</dt>
|
||||
<dd><pre class="code"><span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>chat_channel_delete</span><span class='tstring_end'>"</span></span></pre></dd>
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
Instance Method Summary
|
||||
<small><a href="#" class="summary_toggle">collapse</a></small>
|
||||
</h2>
|
||||
|
||||
<ul class="summary">
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#call-instance_method" title="#call (instance method)">#<strong>call</strong>(channel_id: , guardian: ) ⇒ Chat::Service::Base::Context </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'></div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="inherited">Methods included from <span class='object_link'><a href="Base.html" title="Chat::Service::Base (module)">Base</a></span></h3>
|
||||
<p class="inherited"><span class='object_link'><a href="Base.html#contract-class_method" title="Chat::Service::Base.contract (method)">contract</a></span>, <span class='object_link'><a href="Base.html#model-class_method" title="Chat::Service::Base.model (method)">model</a></span>, <span class='object_link'><a href="Base.html#policy-class_method" title="Chat::Service::Base.policy (method)">policy</a></span>, <span class='object_link'><a href="Base.html#step-class_method" title="Chat::Service::Base.step (method)">step</a></span>, <span class='object_link'><a href="Base.html#transaction-class_method" title="Chat::Service::Base.transaction (method)">transaction</a></span></p>
|
||||
|
||||
|
||||
|
||||
<div id="instance_method_details" class="method_details_list">
|
||||
<h2>Instance Method Details</h2>
|
||||
|
||||
|
||||
<div class="method_details first">
|
||||
<h3 class="signature first" id="call-instance_method">
|
||||
|
||||
#<strong>call</strong>(channel_id: , guardian: ) ⇒ <tt><span class='object_link'><a href="Base/Context.html" title="Chat::Service::Base::Context (class)">Chat::Service::Base::Context</a></span></tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
<p class="tag_title">Parameters:</p>
|
||||
<ul class="param">
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>channel_id</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Integer</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt></tt>)</em>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>guardian</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Guardian</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt></tt>)</em>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p class="tag_title">Returns:</p>
|
||||
<ul class="return">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
<span class='type'>(<tt><span class='object_link'><a href="Base/Context.html" title="Chat::Service::Base::Context (class)">Chat::Service::Base::Context</a></span></tt>)</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,346 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
Class: Chat::Service::UpdateChannel
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="../../css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="../../css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "Chat::Service::UpdateChannel";
|
||||
relpath = '../../';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="../../class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="../../_index.html">Index (U)</a> »
|
||||
<span class='title'><span class='object_link'><a href="../../Chat.html" title="Chat (module)">Chat</a></span></span> » <span class='title'><span class='object_link'><a href="../Service.html" title="Chat::Service (module)">Service</a></span></span>
|
||||
»
|
||||
<span class="title">UpdateChannel</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="../../class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><h1>Class: Chat::Service::UpdateChannel
|
||||
|
||||
|
||||
|
||||
</h1>
|
||||
<div class="box_info">
|
||||
|
||||
<dl>
|
||||
<dt>Inherits:</dt>
|
||||
<dd>
|
||||
<span class="inheritName">Object</span>
|
||||
|
||||
<ul class="fullTree">
|
||||
<li>Object</li>
|
||||
|
||||
<li class="next">Chat::Service::UpdateChannel</li>
|
||||
|
||||
</ul>
|
||||
<a href="#" class="inheritanceTree">show all</a>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Includes:</dt>
|
||||
<dd><span class='object_link'><a href="Base.html" title="Chat::Service::Base (module)">Base</a></span></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Defined in:</dt>
|
||||
<dd>plugins/chat/app/services/update_channel.rb</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<h2>Overview</h2><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Service responsible for updating a chat channel’s name, slug, and description.</p>
|
||||
|
||||
<p>For a CategoryChannel, the settings for auto_join_users and allow_channel_wide_mentions are also editable.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<pre class="example code"><code><span class='const'><span class='object_link'><a href="../../Chat.html" title="Chat (module)">Chat</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="../Service.html" title="Chat::Service (module)">Service</a></span></span><span class='op'>::</span><span class='const'>UpdateChannel</span><span class='period'>.</span><span class='id identifier rubyid_call'><span class='object_link'><a href="#call-instance_method" title="Chat::Service::UpdateChannel#call (method)">call</a></span></span><span class='lparen'>(</span>
|
||||
<span class='label'>channel_id:</span> <span class='int'>2</span><span class='comma'>,</span>
|
||||
<span class='label'>guardian:</span> <span class='id identifier rubyid_guardian'>guardian</span><span class='comma'>,</span>
|
||||
<span class='label'>name:</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>SuperChannel</span><span class='tstring_end'>"</span></span><span class='comma'>,</span>
|
||||
<span class='label'>description:</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>This is the best channel</span><span class='tstring_end'>"</span></span><span class='comma'>,</span>
|
||||
<span class='label'>slug:</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>super-channel</span><span class='tstring_end'>"</span></span><span class='comma'>,</span>
|
||||
<span class='rparen'>)</span></code></pre>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
Instance Method Summary
|
||||
<small><a href="#" class="summary_toggle">collapse</a></small>
|
||||
</h2>
|
||||
|
||||
<ul class="summary">
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#call-instance_method" title="#call (instance method)">#<strong>call</strong>(channel_id: , guardian: , **params_to_edit) ⇒ Chat::Service::Base::Context </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'></div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="inherited">Methods included from <span class='object_link'><a href="Base.html" title="Chat::Service::Base (module)">Base</a></span></h3>
|
||||
<p class="inherited"><span class='object_link'><a href="Base.html#contract-class_method" title="Chat::Service::Base.contract (method)">contract</a></span>, <span class='object_link'><a href="Base.html#model-class_method" title="Chat::Service::Base.model (method)">model</a></span>, <span class='object_link'><a href="Base.html#policy-class_method" title="Chat::Service::Base.policy (method)">policy</a></span>, <span class='object_link'><a href="Base.html#step-class_method" title="Chat::Service::Base.step (method)">step</a></span>, <span class='object_link'><a href="Base.html#transaction-class_method" title="Chat::Service::Base.transaction (method)">transaction</a></span></p>
|
||||
|
||||
|
||||
|
||||
<div id="instance_method_details" class="method_details_list">
|
||||
<h2>Instance Method Details</h2>
|
||||
|
||||
|
||||
<div class="method_details first">
|
||||
<h3 class="signature first" id="call-instance_method">
|
||||
|
||||
#<strong>call</strong>(channel_id: , guardian: , **params_to_edit) ⇒ <tt><span class='object_link'><a href="Base/Context.html" title="Chat::Service::Base::Context (class)">Chat::Service::Base::Context</a></span></tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
<p class="tag_title">Parameters:</p>
|
||||
<ul class="param">
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>channel_id</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Integer</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt></tt>)</em>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>guardian</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Guardian</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt></tt>)</em>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>params_to_edit</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Hash</tt>)</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<p class="tag_title">Options Hash (<tt>**params_to_edit</tt>):</p>
|
||||
<ul class="option">
|
||||
|
||||
<li>
|
||||
<span class="name">name</span>
|
||||
<span class="type">(<tt>String</tt>, <tt>nil</tt>)</span>
|
||||
<span class="default">
|
||||
|
||||
</span>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<span class="name">description</span>
|
||||
<span class="type">(<tt>String</tt>, <tt>nil</tt>)</span>
|
||||
<span class="default">
|
||||
|
||||
</span>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<span class="name">slug</span>
|
||||
<span class="type">(<tt>String</tt>, <tt>nil</tt>)</span>
|
||||
<span class="default">
|
||||
|
||||
</span>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<span class="name">auto_join_users</span>
|
||||
<span class="type">(<tt>Boolean</tt>)</span>
|
||||
<span class="default">
|
||||
|
||||
</span>
|
||||
|
||||
— <div class='inline'>
|
||||
<p>Only valid for CategoryChannel. Whether active users with permission to see the category should automatically join the channel.</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<span class="name">allow_channel_wide_mentions</span>
|
||||
<span class="type">(<tt>Boolean</tt>)</span>
|
||||
<span class="default">
|
||||
|
||||
</span>
|
||||
|
||||
— <div class='inline'>
|
||||
<p>Allow the use of @here and @all in the channel.</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<p class="tag_title">Returns:</p>
|
||||
<ul class="return">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
<span class='type'>(<tt><span class='object_link'><a href="Base/Context.html" title="Chat::Service::Base::Context (class)">Chat::Service::Base::Context</a></span></tt>)</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,274 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
Class: Chat::Service::UpdateChannelStatus
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="../../css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="../../css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "Chat::Service::UpdateChannelStatus";
|
||||
relpath = '../../';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="../../class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="../../_index.html">Index (U)</a> »
|
||||
<span class='title'><span class='object_link'><a href="../../Chat.html" title="Chat (module)">Chat</a></span></span> » <span class='title'><span class='object_link'><a href="../Service.html" title="Chat::Service (module)">Service</a></span></span>
|
||||
»
|
||||
<span class="title">UpdateChannelStatus</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="../../class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><h1>Class: Chat::Service::UpdateChannelStatus
|
||||
|
||||
|
||||
|
||||
</h1>
|
||||
<div class="box_info">
|
||||
|
||||
<dl>
|
||||
<dt>Inherits:</dt>
|
||||
<dd>
|
||||
<span class="inheritName">Object</span>
|
||||
|
||||
<ul class="fullTree">
|
||||
<li>Object</li>
|
||||
|
||||
<li class="next">Chat::Service::UpdateChannelStatus</li>
|
||||
|
||||
</ul>
|
||||
<a href="#" class="inheritanceTree">show all</a>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Includes:</dt>
|
||||
<dd><span class='object_link'><a href="Base.html" title="Chat::Service::Base (module)">Base</a></span></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Defined in:</dt>
|
||||
<dd>plugins/chat/app/services/update_channel_status.rb</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<h2>Overview</h2><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Service responsible for updating a chat channel status.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<pre class="example code"><code><span class='const'><span class='object_link'><a href="../../Chat.html" title="Chat (module)">Chat</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="../Service.html" title="Chat::Service (module)">Service</a></span></span><span class='op'>::</span><span class='const'>UpdateChannelStatus</span><span class='period'>.</span><span class='id identifier rubyid_call'><span class='object_link'><a href="#call-instance_method" title="Chat::Service::UpdateChannelStatus#call (method)">call</a></span></span><span class='lparen'>(</span><span class='label'>channel_id:</span> <span class='int'>2</span><span class='comma'>,</span> <span class='label'>guardian:</span> <span class='id identifier rubyid_guardian'>guardian</span><span class='comma'>,</span> <span class='label'>status:</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>open</span><span class='tstring_end'>"</span></span><span class='rparen'>)</span></code></pre>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
Instance Method Summary
|
||||
<small><a href="#" class="summary_toggle">collapse</a></small>
|
||||
</h2>
|
||||
|
||||
<ul class="summary">
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#call-instance_method" title="#call (instance method)">#<strong>call</strong>(channel_id: , guardian: , status: ) ⇒ Chat::Service::Base::Context </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'></div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="inherited">Methods included from <span class='object_link'><a href="Base.html" title="Chat::Service::Base (module)">Base</a></span></h3>
|
||||
<p class="inherited"><span class='object_link'><a href="Base.html#contract-class_method" title="Chat::Service::Base.contract (method)">contract</a></span>, <span class='object_link'><a href="Base.html#model-class_method" title="Chat::Service::Base.model (method)">model</a></span>, <span class='object_link'><a href="Base.html#policy-class_method" title="Chat::Service::Base.policy (method)">policy</a></span>, <span class='object_link'><a href="Base.html#step-class_method" title="Chat::Service::Base.step (method)">step</a></span>, <span class='object_link'><a href="Base.html#transaction-class_method" title="Chat::Service::Base.transaction (method)">transaction</a></span></p>
|
||||
|
||||
|
||||
|
||||
<div id="instance_method_details" class="method_details_list">
|
||||
<h2>Instance Method Details</h2>
|
||||
|
||||
|
||||
<div class="method_details first">
|
||||
<h3 class="signature first" id="call-instance_method">
|
||||
|
||||
#<strong>call</strong>(channel_id: , guardian: , status: ) ⇒ <tt><span class='object_link'><a href="Base/Context.html" title="Chat::Service::Base::Context (class)">Chat::Service::Base::Context</a></span></tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
<p class="tag_title">Parameters:</p>
|
||||
<ul class="param">
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>channel_id</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Integer</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt></tt>)</em>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>guardian</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Guardian</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt></tt>)</em>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>status</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>String</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt></tt>)</em>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p class="tag_title">Returns:</p>
|
||||
<ul class="return">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
<span class='type'>(<tt><span class='object_link'><a href="Base/Context.html" title="Chat::Service::Base::Context (class)">Chat::Service::Base::Context</a></span></tt>)</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,274 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
Class: Chat::Service::UpdateUserLastRead
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="../../css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="../../css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "Chat::Service::UpdateUserLastRead";
|
||||
relpath = '../../';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="../../js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="../../class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="../../_index.html">Index (U)</a> »
|
||||
<span class='title'><span class='object_link'><a href="../../Chat.html" title="Chat (module)">Chat</a></span></span> » <span class='title'><span class='object_link'><a href="../Service.html" title="Chat::Service (module)">Service</a></span></span>
|
||||
»
|
||||
<span class="title">UpdateUserLastRead</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="../../class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><h1>Class: Chat::Service::UpdateUserLastRead
|
||||
|
||||
|
||||
|
||||
</h1>
|
||||
<div class="box_info">
|
||||
|
||||
<dl>
|
||||
<dt>Inherits:</dt>
|
||||
<dd>
|
||||
<span class="inheritName">Object</span>
|
||||
|
||||
<ul class="fullTree">
|
||||
<li>Object</li>
|
||||
|
||||
<li class="next">Chat::Service::UpdateUserLastRead</li>
|
||||
|
||||
</ul>
|
||||
<a href="#" class="inheritanceTree">show all</a>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Includes:</dt>
|
||||
<dd><span class='object_link'><a href="Base.html" title="Chat::Service::Base (module)">Base</a></span></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Defined in:</dt>
|
||||
<dd>plugins/chat/app/services/update_user_last_read.rb</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<h2>Overview</h2><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
<p>Service responsible for updating the last read message id of a membership.</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
|
||||
<div class="examples">
|
||||
<p class="tag_title">Examples:</p>
|
||||
|
||||
|
||||
<pre class="example code"><code><span class='const'><span class='object_link'><a href="../../Chat.html" title="Chat (module)">Chat</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="../Service.html" title="Chat::Service (module)">Service</a></span></span><span class='op'>::</span><span class='const'>UpdateUserLastRead</span><span class='period'>.</span><span class='id identifier rubyid_call'><span class='object_link'><a href="#call-instance_method" title="Chat::Service::UpdateUserLastRead#call (method)">call</a></span></span><span class='lparen'>(</span><span class='label'>user_id:</span> <span class='int'>1</span><span class='comma'>,</span> <span class='label'>channel_id:</span> <span class='int'>2</span><span class='comma'>,</span> <span class='label'>guardian:</span> <span class='id identifier rubyid_guardian'>guardian</span><span class='rparen'>)</span></code></pre>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
Instance Method Summary
|
||||
<small><a href="#" class="summary_toggle">collapse</a></small>
|
||||
</h2>
|
||||
|
||||
<ul class="summary">
|
||||
|
||||
<li class="public ">
|
||||
<span class="summary_signature">
|
||||
|
||||
<a href="#call-instance_method" title="#call (instance method)">#<strong>call</strong>(user_id: , channel_id: , guardian: ) ⇒ Chat::Service::Base::Context </a>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="summary_desc"><div class='inline'></div></span>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="inherited">Methods included from <span class='object_link'><a href="Base.html" title="Chat::Service::Base (module)">Base</a></span></h3>
|
||||
<p class="inherited"><span class='object_link'><a href="Base.html#contract-class_method" title="Chat::Service::Base.contract (method)">contract</a></span>, <span class='object_link'><a href="Base.html#model-class_method" title="Chat::Service::Base.model (method)">model</a></span>, <span class='object_link'><a href="Base.html#policy-class_method" title="Chat::Service::Base.policy (method)">policy</a></span>, <span class='object_link'><a href="Base.html#step-class_method" title="Chat::Service::Base.step (method)">step</a></span>, <span class='object_link'><a href="Base.html#transaction-class_method" title="Chat::Service::Base.transaction (method)">transaction</a></span></p>
|
||||
|
||||
|
||||
|
||||
<div id="instance_method_details" class="method_details_list">
|
||||
<h2>Instance Method Details</h2>
|
||||
|
||||
|
||||
<div class="method_details first">
|
||||
<h3 class="signature first" id="call-instance_method">
|
||||
|
||||
#<strong>call</strong>(user_id: , channel_id: , guardian: ) ⇒ <tt><span class='object_link'><a href="Base/Context.html" title="Chat::Service::Base::Context (class)">Chat::Service::Base::Context</a></span></tt>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</h3><div class="docstring">
|
||||
<div class="discussion">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
<p class="tag_title">Parameters:</p>
|
||||
<ul class="param">
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>user_id</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Integer</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt></tt>)</em>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>channel_id</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Integer</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt></tt>)</em>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
<span class='name'>guardian</span>
|
||||
|
||||
|
||||
<span class='type'>(<tt>Guardian</tt>)</span>
|
||||
|
||||
|
||||
<em class="default">(defaults to: <tt></tt>)</em>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p class="tag_title">Returns:</p>
|
||||
<ul class="return">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
<span class='type'>(<tt><span class='object_link'><a href="Base/Context.html" title="Chat::Service::Base::Context (class)">Chat::Service::Base::Context</a></span></tt>)</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,204 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = null;
|
||||
relpath = '';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><h1 class="noborder title">Documentation by YARD 0.9.28</h1>
|
||||
<div id="listing">
|
||||
<h1 class="alphaindex">Alphabetic Index</h1>
|
||||
|
||||
<h2>File Listing</h2>
|
||||
<ul id="files" class="index_inline_list">
|
||||
|
||||
|
||||
<li class="r1"><a href="index.html" title="README">README</a></li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="clear"></div>
|
||||
<h2>Namespace Listing A-Z</h2>
|
||||
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td valign='top' width="33%">
|
||||
|
||||
|
||||
<ul id="alpha_B" class="alpha">
|
||||
<li class="letter">B</li>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<span class='object_link'><a href="Chat/Service/Base.html" title="Chat::Service::Base (module)">Base</a></span>
|
||||
|
||||
<small>(Chat::Service)</small>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
|
||||
<ul id="alpha_C" class="alpha">
|
||||
<li class="letter">C</li>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<span class='object_link'><a href="Chat.html" title="Chat (module)">Chat</a></span>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<span class='object_link'><a href="Chat/Service/Base/Context.html" title="Chat::Service::Base::Context (class)">Context</a></span>
|
||||
|
||||
<small>(Chat::Service::Base)</small>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
|
||||
<ul id="alpha_F" class="alpha">
|
||||
<li class="letter">F</li>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<span class='object_link'><a href="Chat/Service/Base/Failure.html" title="Chat::Service::Base::Failure (class)">Failure</a></span>
|
||||
|
||||
<small>(Chat::Service::Base)</small>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
|
||||
<ul id="alpha_S" class="alpha">
|
||||
<li class="letter">S</li>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<span class='object_link'><a href="Chat/Service.html" title="Chat::Service (module)">Service</a></span>
|
||||
|
||||
<small>(Chat)</small>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
|
||||
<ul id="alpha_T" class="alpha">
|
||||
<li class="letter">T</li>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<span class='object_link'><a href="Chat/Service/TrashChannel.html" title="Chat::Service::TrashChannel (class)">TrashChannel</a></span>
|
||||
|
||||
<small>(Chat::Service)</small>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
|
||||
<ul id="alpha_U" class="alpha">
|
||||
<li class="letter">U</li>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<span class='object_link'><a href="Chat/Service/UpdateChannel.html" title="Chat::Service::UpdateChannel (class)">UpdateChannel</a></span>
|
||||
|
||||
<small>(Chat::Service)</small>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<span class='object_link'><a href="Chat/Service/UpdateChannelStatus.html" title="Chat::Service::UpdateChannelStatus (class)">UpdateChannelStatus</a></span>
|
||||
|
||||
<small>(Chat::Service)</small>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<span class='object_link'><a href="Chat/Service/UpdateUserLastRead.html" title="Chat::Service::UpdateUserLastRead (class)">UpdateUserLastRead</a></span>
|
||||
|
||||
<small>(Chat::Service)</small>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,51 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" />
|
||||
|
||||
<link rel="stylesheet" href="css/common.css" type="text/css" media="screen" />
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
|
||||
|
||||
|
||||
<title>Class List</title>
|
||||
<base id="base_target" target="_parent" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<div class="fixed_header">
|
||||
<h1 id="full_list_header">Class List</h1>
|
||||
<div id="full_list_nav">
|
||||
|
||||
<span><a target="_self" href="class_list.html">
|
||||
Classes
|
||||
</a></span>
|
||||
|
||||
<span><a target="_self" href="method_list.html">
|
||||
Methods
|
||||
</a></span>
|
||||
|
||||
<span><a target="_self" href="file_list.html">
|
||||
Files
|
||||
</a></span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">Search: <input type="text" /></div>
|
||||
</div>
|
||||
|
||||
<ul id="full_list" class="class">
|
||||
<li id="object_" class="odd"><div class="item" style="padding-left:30px"><span class='object_link'><a href="top-level-namespace.html" title="Top Level Namespace (root)">Top Level Namespace</a></span></div></li>
|
||||
<li id='object_Chat' class='even'><div class='item' style='padding-left:30px'><a class='toggle'></a> <span class='object_link'><a href="Chat.html" title="Chat (module)">Chat</a></span><small class='search_info'>Top Level Namespace</small></div><ul><li id='object_Chat::Service' class='collapsed odd'><div class='item' style='padding-left:45px'><a class='toggle'></a> <span class='object_link'><a href="Chat/Service.html" title="Chat::Service (module)">Service</a></span><small class='search_info'>Chat</small></div><ul><li id='object_Chat::Service::Base' class='collapsed'><div class='item' style='padding-left:60px'><a class='toggle'></a> <span class='object_link'><a href="Chat/Service/Base.html" title="Chat::Service::Base (module)">Base</a></span><small class='search_info'>Chat::Service</small></div><ul><li id='object_Chat::Service::Base::Context' class='collapsed'><div class='item' style='padding-left:75px'><span class='object_link'><a href="Chat/Service/Base/Context.html" title="Chat::Service::Base::Context (class)">Context</a></span> < OpenStruct<small class='search_info'>Chat::Service::Base</small></div></li><li id='object_Chat::Service::Base::Failure' class='collapsed'><div class='item' style='padding-left:75px'><span class='object_link'><a href="Chat/Service/Base/Failure.html" title="Chat::Service::Base::Failure (class)">Failure</a></span> < StandardError<small class='search_info'>Chat::Service::Base</small></div></li></ul></li><li id='object_Chat::Service::TrashChannel' class='collapsed'><div class='item' style='padding-left:60px'><span class='object_link'><a href="Chat/Service/TrashChannel.html" title="Chat::Service::TrashChannel (class)">TrashChannel</a></span> < Object<small class='search_info'>Chat::Service</small></div></li><li id='object_Chat::Service::UpdateChannel' class='collapsed'><div class='item' style='padding-left:60px'><span class='object_link'><a href="Chat/Service/UpdateChannel.html" title="Chat::Service::UpdateChannel (class)">UpdateChannel</a></span> < Object<small class='search_info'>Chat::Service</small></div></li><li id='object_Chat::Service::UpdateChannelStatus' class='collapsed'><div class='item' style='padding-left:60px'><span class='object_link'><a href="Chat/Service/UpdateChannelStatus.html" title="Chat::Service::UpdateChannelStatus (class)">UpdateChannelStatus</a></span> < Object<small class='search_info'>Chat::Service</small></div></li><li id='object_Chat::Service::UpdateUserLastRead' class='collapsed'><div class='item' style='padding-left:60px'><span class='object_link'><a href="Chat/Service/UpdateUserLastRead.html" title="Chat::Service::UpdateUserLastRead (class)">UpdateUserLastRead</a></span> < Object<small class='search_info'>Chat::Service</small></div></li></ul></li></ul></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
/* Override this file with custom rules */
|
|
@ -0,0 +1,58 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
height: 101%;
|
||||
overflow-x: hidden;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
h1 { padding: 12px 10px; padding-bottom: 0; margin: 0; font-size: 1.4em; }
|
||||
.clear { clear: both; }
|
||||
.fixed_header { position: fixed; background: #fff; width: 100%; padding-bottom: 10px; margin-top: 0; top: 0; z-index: 9999; height: 70px; }
|
||||
#search { position: absolute; right: 5px; top: 9px; padding-left: 24px; }
|
||||
#content.insearch #search, #content.insearch #noresults { background: url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAAPr6+pKSkoiIiO7u7sjIyNjY2J6engAAAI6OjsbGxjIyMlJSUuzs7KamppSUlPLy8oKCghwcHLKysqSkpJqamvT09Pj4+KioqM7OzkRERAwMDGBgYN7e3ujo6Ly8vCoqKjY2NkZGRtTU1MTExDw8PE5OTj4+PkhISNDQ0MrKylpaWrS0tOrq6nBwcKysrLi4uLq6ul5eXlxcXGJiYoaGhuDg4H5+fvz8/KKiohgYGCwsLFZWVgQEBFBQUMzMzDg4OFhYWBoaGvDw8NbW1pycnOLi4ubm5kBAQKqqqiQkJCAgIK6urnJyckpKSjQ0NGpqatLS0sDAwCYmJnx8fEJCQlRUVAoKCggICLCwsOTk5ExMTPb29ra2tmZmZmhoaNzc3KCgoBISEiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCAAAACwAAAAAEAAQAAAHaIAAgoMgIiYlg4kACxIaACEJCSiKggYMCRselwkpghGJBJEcFgsjJyoAGBmfggcNEx0flBiKDhQFlIoCCA+5lAORFb4AJIihCRbDxQAFChAXw9HSqb60iREZ1omqrIPdJCTe0SWI09GBACH5BAkIAAAALAAAAAAQABAAAAdrgACCgwc0NTeDiYozCQkvOTo9GTmDKy8aFy+NOBA7CTswgywJDTIuEjYFIY0JNYMtKTEFiRU8Pjwygy4ws4owPyCKwsMAJSTEgiQlgsbIAMrO0dKDGMTViREZ14kYGRGK38nHguHEJcvTyIEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDAggPg4iJAAMJCRUAJRIqiRGCBI0WQEEJJkWDERkYAAUKEBc4Po1GiKKJHkJDNEeKig4URLS0ICImJZAkuQAhjSi/wQyNKcGDCyMnk8u5rYrTgqDVghgZlYjcACTA1sslvtHRgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCQARAtOUoQRGRiFD0kJUYWZhUhKT1OLhR8wBaaFBzQ1NwAlkIszCQkvsbOHL7Y4q4IuEjaqq0ZQD5+GEEsJTDCMmIUhtgk1lo6QFUwJVDKLiYJNUd6/hoEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4uen4ICCA+IkIsDCQkVACWmhwSpFqAABQoQF6ALTkWFnYMrVlhWvIKTlSAiJiVVPqlGhJkhqShHV1lCW4cMqSkAR1ofiwsjJyqGgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCSMhREZGIYYGY2ElYebi56fhyWQniSKAKKfpaCLFlAPhl0gXYNGEwkhGYREUywag1wJwSkHNDU3D0kJYIMZQwk8MjPBLx9eXwuETVEyAC/BOKsuEjYFhoEAIfkECQgAAAAsAAAAABAAEAAAB2eAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4ueICImip6CIQkJKJ4kigynKaqKCyMnKqSEK05StgAGQRxPYZaENqccFgIID4KXmQBhXFkzDgOnFYLNgltaSAAEpxa7BQoQF4aBACH5BAkIAAAALAAAAAAQABAAAAdogACCg4SFggJiPUqCJSWGgkZjCUwZACQkgxGEXAmdT4UYGZqCGWQ+IjKGGIUwPzGPhAc0NTewhDOdL7Ykji+dOLuOLhI2BbaFETICx4MlQitdqoUsCQ2vhKGjglNfU0SWmILaj43M5oEAOwAAAAAAAAAAAA==) no-repeat center left; }
|
||||
#full_list { padding: 0; list-style: none; margin-left: 0; margin-top: 80px; font-size: 1.1em; }
|
||||
#full_list ul { padding: 0; }
|
||||
#full_list li { padding: 0; margin: 0; list-style: none; }
|
||||
#full_list li .item { padding: 5px 5px 5px 12px; }
|
||||
#noresults { padding: 7px 12px; background: #fff; }
|
||||
#content.insearch #noresults { margin-left: 7px; }
|
||||
li.collapsed ul { display: none; }
|
||||
li a.toggle { cursor: default; position: relative; left: -5px; top: 4px; text-indent: -999px; width: 10px; height: 9px; margin-left: -10px; display: block; float: left; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdEVYdENyZWF0aW9uIFRpbWUAMy8xNC8wOeNZPpQAAAE2SURBVDiNrZTBccIwEEXfelIAHUA6CZ24BGaWO+FuzZAK4k6gg5QAdGAq+Bxs2Yqx7BzyL7Llp/VfzZeQhCTc/ezuGzKKnKSzpCxXJM8fwNXda3df5RZETlIt6YUzSQDs93sl8w3wBZxCCE10GM1OcWbWjB2mWgEH4Mfdyxm3PSepBHibgQE2wLe7r4HjEidpnXMYdQPKEMJcsZ4zs2POYQOcaPfwMVOo58zsAdMt18BuoVDPxUJRacELbXv3hUIX2vYmOUvi8C8ydz/ThjXrqKqqLbDIAdsCKBd+Wo7GWa7o9qzOQHVVVXeAbs+yHHCH4aTsaCOQqunmUy1yBUAXkdMIfMlgF5EXLo2OpV/c/Up7jG4hhHcYLgWzAZXUc2b2ixsfvc/RmNNfOXD3Q/oeL9axJE1yT9IOoUu6MGUkAAAAAElFTkSuQmCC) no-repeat bottom left; }
|
||||
li.collapsed a.toggle { opacity: 0.5; cursor: default; background-position: top left; }
|
||||
li { color: #888; cursor: pointer; }
|
||||
li.deprecated { text-decoration: line-through; font-style: italic; }
|
||||
li.odd { background: #f0f0f0; }
|
||||
li.even { background: #fafafa; }
|
||||
.item:hover { background: #ddd; }
|
||||
li small:before { content: "("; }
|
||||
li small:after { content: ")"; }
|
||||
li small.search_info { display: none; }
|
||||
a, a:visited { text-decoration: none; color: #05a; }
|
||||
li.clicked > .item { background: #05a; color: #ccc; }
|
||||
li.clicked > .item a, li.clicked > .item a:visited { color: #eee; }
|
||||
li.clicked > .item a.toggle { opacity: 0.5; background-position: bottom right; }
|
||||
li.collapsed.clicked a.toggle { background-position: top right; }
|
||||
#search input { border: 1px solid #bbb; border-radius: 3px; }
|
||||
#full_list_nav { margin-left: 10px; font-size: 0.9em; display: block; color: #aaa; }
|
||||
#full_list_nav a, #nav a:visited { color: #358; }
|
||||
#full_list_nav a:hover { background: transparent; color: #5af; }
|
||||
#full_list_nav span:after { content: ' | '; }
|
||||
#full_list_nav span:last-child:after { content: ''; }
|
||||
|
||||
#content h1 { margin-top: 0; }
|
||||
li { white-space: nowrap; cursor: normal; }
|
||||
li small { display: block; font-size: 0.8em; }
|
||||
li small:before { content: ""; }
|
||||
li small:after { content: ""; }
|
||||
li small.search_info { display: none; }
|
||||
#search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #888; padding-left: 0; padding-right: 24px; }
|
||||
#content.insearch #search { background-position: center right; }
|
||||
#search input { width: 110px; }
|
||||
|
||||
#full_list.insearch ul { display: block; }
|
||||
#full_list.insearch .item { display: none; }
|
||||
#full_list.insearch .found { display: block; padding-left: 11px !important; }
|
||||
#full_list.insearch li a.toggle { display: none; }
|
||||
#full_list.insearch li small.search_info { display: block; }
|
|
@ -0,0 +1,497 @@
|
|||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
}
|
||||
|
||||
#nav {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
border-right: 1px dotted #eee;
|
||||
overflow: auto;
|
||||
}
|
||||
.nav_wrap {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 20%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
flex-shrink: 0;
|
||||
-webkit-flex-shrink: 0;
|
||||
-ms-flex: 1 0;
|
||||
}
|
||||
#resizer {
|
||||
position: absolute;
|
||||
right: -5px;
|
||||
top: 0;
|
||||
width: 10px;
|
||||
height: 100%;
|
||||
cursor: col-resize;
|
||||
z-index: 9999;
|
||||
}
|
||||
#main {
|
||||
flex: 5 1;
|
||||
-webkit-flex: 5 1;
|
||||
-ms-flex: 5 1;
|
||||
outline: none;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
padding: 1.2em;
|
||||
padding-top: 0.2em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (max-width: 920px) {
|
||||
.nav_wrap { width: 100%; top: 0; right: 0; overflow: visible; position: absolute; }
|
||||
#resizer { display: none; }
|
||||
#nav {
|
||||
z-index: 9999;
|
||||
background: #fff;
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
right: 12px;
|
||||
width: 500px;
|
||||
max-width: 80%;
|
||||
height: 80%;
|
||||
overflow-y: scroll;
|
||||
border: 1px solid #999;
|
||||
border-collapse: collapse;
|
||||
box-shadow: -7px 5px 25px #aaa;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 920px) {
|
||||
body { height: 100%; overflow: hidden; }
|
||||
#main { height: 100%; overflow: auto; }
|
||||
#search { display: none; }
|
||||
}
|
||||
|
||||
#main img { max-width: 100%; }
|
||||
h1 { font-size: 25px; margin: 1em 0 0.5em; padding-top: 4px; border-top: 1px dotted #d5d5d5; }
|
||||
h1.noborder { border-top: 0px; margin-top: 0; padding-top: 4px; }
|
||||
h1.title { margin-bottom: 10px; }
|
||||
h1.alphaindex { margin-top: 0; font-size: 22px; }
|
||||
h2 {
|
||||
padding: 0;
|
||||
padding-bottom: 3px;
|
||||
border-bottom: 1px #aaa solid;
|
||||
font-size: 1.4em;
|
||||
margin: 1.8em 0 0.5em;
|
||||
position: relative;
|
||||
}
|
||||
h2 small { font-weight: normal; font-size: 0.7em; display: inline; position: absolute; right: 0; }
|
||||
h2 small a {
|
||||
display: block;
|
||||
height: 20px;
|
||||
border: 1px solid #aaa;
|
||||
border-bottom: 0;
|
||||
border-top-left-radius: 5px;
|
||||
background: #f8f8f8;
|
||||
position: relative;
|
||||
padding: 2px 7px;
|
||||
}
|
||||
.clear { clear: both; }
|
||||
.inline { display: inline; }
|
||||
.inline p:first-child { display: inline; }
|
||||
.docstring, .tags, #filecontents { font-size: 15px; line-height: 1.5145em; }
|
||||
.docstring p > code, .docstring p > tt, .tags p > code, .tags p > tt {
|
||||
color: #c7254e; background: #f9f2f4; padding: 2px 4px; font-size: 1em;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.docstring h1, .docstring h2, .docstring h3, .docstring h4 { padding: 0; border: 0; border-bottom: 1px dotted #bbb; }
|
||||
.docstring h1 { font-size: 1.2em; }
|
||||
.docstring h2 { font-size: 1.1em; }
|
||||
.docstring h3, .docstring h4 { font-size: 1em; border-bottom: 0; padding-top: 10px; }
|
||||
.summary_desc .object_link a, .docstring .object_link a {
|
||||
font-family: monospace; font-size: 1.05em;
|
||||
color: #05a; background: #EDF4FA; padding: 2px 4px; font-size: 1em;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.rdoc-term { padding-right: 25px; font-weight: bold; }
|
||||
.rdoc-list p { margin: 0; padding: 0; margin-bottom: 4px; }
|
||||
.summary_desc pre.code .object_link a, .docstring pre.code .object_link a {
|
||||
padding: 0px; background: inherit; color: inherit; border-radius: inherit;
|
||||
}
|
||||
|
||||
/* style for <table> */
|
||||
#filecontents table, .docstring table { border-collapse: collapse; }
|
||||
#filecontents table th, #filecontents table td,
|
||||
.docstring table th, .docstring table td { border: 1px solid #ccc; padding: 8px; padding-right: 17px; }
|
||||
#filecontents table tr:nth-child(odd),
|
||||
.docstring table tr:nth-child(odd) { background: #eee; }
|
||||
#filecontents table tr:nth-child(even),
|
||||
.docstring table tr:nth-child(even) { background: #fff; }
|
||||
#filecontents table th, .docstring table th { background: #fff; }
|
||||
|
||||
/* style for <ul> */
|
||||
#filecontents li > p, .docstring li > p { margin: 0px; }
|
||||
#filecontents ul, .docstring ul { padding-left: 20px; }
|
||||
/* style for <dl> */
|
||||
#filecontents dl, .docstring dl { border: 1px solid #ccc; }
|
||||
#filecontents dt, .docstring dt { background: #ddd; font-weight: bold; padding: 3px 5px; }
|
||||
#filecontents dd, .docstring dd { padding: 5px 0px; margin-left: 18px; }
|
||||
#filecontents dd > p, .docstring dd > p { margin: 0px; }
|
||||
|
||||
.note {
|
||||
color: #222;
|
||||
margin: 20px 0;
|
||||
padding: 10px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 3px;
|
||||
display: block;
|
||||
}
|
||||
.docstring .note {
|
||||
border-left-color: #ccc;
|
||||
border-left-width: 5px;
|
||||
}
|
||||
.note.todo { background: #ffffc5; border-color: #ececaa; }
|
||||
.note.returns_void { background: #efefef; }
|
||||
.note.deprecated { background: #ffe5e5; border-color: #e9dada; }
|
||||
.note.title.deprecated { background: #ffe5e5; border-color: #e9dada; }
|
||||
.note.private { background: #ffffc5; border-color: #ececaa; }
|
||||
.note.title { padding: 3px 6px; font-size: 0.9em; font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; display: inline; }
|
||||
.summary_signature + .note.title { margin-left: 7px; }
|
||||
h1 .note.title { font-size: 0.5em; font-weight: normal; padding: 3px 5px; position: relative; top: -3px; text-transform: capitalize; }
|
||||
.note.title { background: #efefef; }
|
||||
.note.title.constructor { color: #fff; background: #6a98d6; border-color: #6689d6; }
|
||||
.note.title.writeonly { color: #fff; background: #45a638; border-color: #2da31d; }
|
||||
.note.title.readonly { color: #fff; background: #6a98d6; border-color: #6689d6; }
|
||||
.note.title.private { background: #d5d5d5; border-color: #c5c5c5; }
|
||||
.note.title.not_defined_here { background: transparent; border: none; font-style: italic; }
|
||||
.discussion .note { margin-top: 6px; }
|
||||
.discussion .note:first-child { margin-top: 0; }
|
||||
|
||||
h3.inherited {
|
||||
font-style: italic;
|
||||
font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif;
|
||||
font-weight: normal;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 3px;
|
||||
font-size: 13px;
|
||||
}
|
||||
p.inherited {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.box_info dl {
|
||||
margin: 0;
|
||||
border: 0;
|
||||
width: 100%;
|
||||
font-size: 1em;
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
}
|
||||
.box_info dl dt {
|
||||
flex-shrink: 0;
|
||||
-webkit-flex-shrink: 1;
|
||||
-ms-flex-shrink: 1;
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
border: 1px solid #aaa;
|
||||
border-width: 1px 0px 0px 1px;
|
||||
padding: 6px 0;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.box_info dl dd {
|
||||
flex-grow: 1;
|
||||
-webkit-flex-grow: 1;
|
||||
-ms-flex: 1;
|
||||
max-width: 420px;
|
||||
padding: 6px 0;
|
||||
padding-right: 20px;
|
||||
border: 1px solid #aaa;
|
||||
border-width: 1px 1px 0 0;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.box_info dl:last-child > * {
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
.box_info dl:nth-child(odd) > * { background: #eee; }
|
||||
.box_info dl:nth-child(even) > * { background: #fff; }
|
||||
.box_info dl > * { margin: 0; }
|
||||
|
||||
ul.toplevel { list-style: none; padding-left: 0; font-size: 1.1em; }
|
||||
.index_inline_list { padding-left: 0; font-size: 1.1em; }
|
||||
|
||||
.index_inline_list li {
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
padding: 0 12px;
|
||||
line-height: 30px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
dl.constants { margin-left: 10px; }
|
||||
dl.constants dt { font-weight: bold; font-size: 1.1em; margin-bottom: 5px; }
|
||||
dl.constants.compact dt { display: inline-block; font-weight: normal }
|
||||
dl.constants dd { width: 75%; white-space: pre; font-family: monospace; margin-bottom: 18px; }
|
||||
dl.constants .docstring .note:first-child { margin-top: 5px; }
|
||||
|
||||
.summary_desc {
|
||||
margin-left: 32px;
|
||||
display: block;
|
||||
font-family: sans-serif;
|
||||
font-size: 1.1em;
|
||||
margin-top: 8px;
|
||||
line-height: 1.5145em;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
.summary_desc tt { font-size: 0.9em; }
|
||||
dl.constants .note { padding: 2px 6px; padding-right: 12px; margin-top: 6px; }
|
||||
dl.constants .docstring { margin-left: 32px; font-size: 0.9em; font-weight: normal; }
|
||||
dl.constants .tags { padding-left: 32px; font-size: 0.9em; line-height: 0.8em; }
|
||||
dl.constants .discussion *:first-child { margin-top: 0; }
|
||||
dl.constants .discussion *:last-child { margin-bottom: 0; }
|
||||
|
||||
.method_details { border-top: 1px dotted #ccc; margin-top: 25px; padding-top: 0; }
|
||||
.method_details.first { border: 0; margin-top: 5px; }
|
||||
.method_details.first h3.signature { margin-top: 1em; }
|
||||
p.signature, h3.signature {
|
||||
font-size: 1.1em; font-weight: normal; font-family: Monaco, Consolas, Courier, monospace;
|
||||
padding: 6px 10px; margin-top: 1em;
|
||||
background: #E8F4FF; border: 1px solid #d8d8e5; border-radius: 5px;
|
||||
}
|
||||
p.signature tt,
|
||||
h3.signature tt { font-family: Monaco, Consolas, Courier, monospace; }
|
||||
p.signature .overload,
|
||||
h3.signature .overload { display: block; }
|
||||
p.signature .extras,
|
||||
h3.signature .extras { font-weight: normal; font-family: sans-serif; color: #444; font-size: 1em; }
|
||||
p.signature .not_defined_here,
|
||||
h3.signature .not_defined_here,
|
||||
p.signature .aliases,
|
||||
h3.signature .aliases { display: block; font-weight: normal; font-size: 0.9em; font-family: sans-serif; margin-top: 0px; color: #555; }
|
||||
p.signature .aliases .names,
|
||||
h3.signature .aliases .names { font-family: Monaco, Consolas, Courier, monospace; font-weight: bold; color: #000; font-size: 1.2em; }
|
||||
|
||||
.tags .tag_title { font-size: 1.05em; margin-bottom: 0; font-weight: bold; }
|
||||
.tags .tag_title tt { color: initial; padding: initial; background: initial; }
|
||||
.tags ul { margin-top: 5px; padding-left: 30px; list-style: square; }
|
||||
.tags ul li { margin-bottom: 3px; }
|
||||
.tags ul .name { font-family: monospace; font-weight: bold; }
|
||||
.tags ul .note { padding: 3px 6px; }
|
||||
.tags { margin-bottom: 12px; }
|
||||
|
||||
.tags .examples .tag_title { margin-bottom: 10px; font-weight: bold; }
|
||||
.tags .examples .inline p { padding: 0; margin: 0; font-weight: bold; font-size: 1em; }
|
||||
.tags .examples .inline p:before { content: "▸"; font-size: 1em; margin-right: 5px; }
|
||||
|
||||
.tags .overload .overload_item { list-style: none; margin-bottom: 25px; }
|
||||
.tags .overload .overload_item .signature {
|
||||
padding: 2px 8px;
|
||||
background: #F1F8FF; border: 1px solid #d8d8e5; border-radius: 3px;
|
||||
}
|
||||
.tags .overload .signature { margin-left: -15px; font-family: monospace; display: block; font-size: 1.1em; }
|
||||
.tags .overload .docstring { margin-top: 15px; }
|
||||
|
||||
.defines { display: none; }
|
||||
|
||||
#method_missing_details .notice.this { position: relative; top: -8px; color: #888; padding: 0; margin: 0; }
|
||||
|
||||
.showSource { font-size: 0.9em; }
|
||||
.showSource a, .showSource a:visited { text-decoration: none; color: #666; }
|
||||
|
||||
#content a, #content a:visited { text-decoration: none; color: #05a; }
|
||||
#content a:hover { background: #ffffa5; }
|
||||
|
||||
ul.summary {
|
||||
list-style: none;
|
||||
font-family: monospace;
|
||||
font-size: 1em;
|
||||
line-height: 1.5em;
|
||||
padding-left: 0px;
|
||||
}
|
||||
ul.summary a, ul.summary a:visited {
|
||||
text-decoration: none; font-size: 1.1em;
|
||||
}
|
||||
ul.summary li { margin-bottom: 5px; }
|
||||
.summary_signature { padding: 4px 8px; background: #f8f8f8; border: 1px solid #f0f0f0; border-radius: 5px; }
|
||||
.summary_signature:hover { background: #CFEBFF; border-color: #A4CCDA; cursor: pointer; }
|
||||
.summary_signature.deprecated { background: #ffe5e5; border-color: #e9dada; }
|
||||
ul.summary.compact li { display: inline-block; margin: 0px 5px 0px 0px; line-height: 2.6em;}
|
||||
ul.summary.compact .summary_signature { padding: 5px 7px; padding-right: 4px; }
|
||||
#content .summary_signature:hover a,
|
||||
#content .summary_signature:hover a:visited {
|
||||
background: transparent;
|
||||
color: #049;
|
||||
}
|
||||
|
||||
p.inherited a { font-family: monospace; font-size: 0.9em; }
|
||||
p.inherited { word-spacing: 5px; font-size: 1.2em; }
|
||||
|
||||
p.children { font-size: 1.2em; }
|
||||
p.children a { font-size: 0.9em; }
|
||||
p.children strong { font-size: 0.8em; }
|
||||
p.children strong.modules { padding-left: 5px; }
|
||||
|
||||
ul.fullTree { display: none; padding-left: 0; list-style: none; margin-left: 0; margin-bottom: 10px; }
|
||||
ul.fullTree ul { margin-left: 0; padding-left: 0; list-style: none; }
|
||||
ul.fullTree li { text-align: center; padding-top: 18px; padding-bottom: 12px; background: url(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAHtJREFUeNqMzrEJAkEURdGzuhgZbSoYWcAWoBVsB4JgZAGmphsZCZYzTQgWNCYrDN9RvMmHx+X916SUBFbo8CzD1idXrLErw1mQttgXtyrOcQ/Ny5p4Qh+2XqLYYazsPWNTiuMkRxa4vcV+evuNAUOLIx5+c2hyzv7hNQC67Q+/HHmlEwAAAABJRU5ErkJggg==) no-repeat top center; }
|
||||
ul.fullTree li:first-child { padding-top: 0; background: transparent; }
|
||||
ul.fullTree li:last-child { padding-bottom: 0; }
|
||||
.showAll ul.fullTree { display: block; }
|
||||
.showAll .inheritName { display: none; }
|
||||
|
||||
#search { position: absolute; right: 12px; top: 0px; z-index: 9000; }
|
||||
#search a {
|
||||
display: block; float: left;
|
||||
padding: 4px 8px; text-decoration: none; color: #05a; fill: #05a;
|
||||
border: 1px solid #d8d8e5;
|
||||
border-bottom-left-radius: 3px; border-bottom-right-radius: 3px;
|
||||
background: #F1F8FF;
|
||||
box-shadow: -1px 1px 3px #ddd;
|
||||
}
|
||||
#search a:hover { background: #f5faff; color: #06b; fill: #06b; }
|
||||
#search a.active {
|
||||
background: #568; padding-bottom: 20px; color: #fff; fill: #fff;
|
||||
border: 1px solid #457;
|
||||
border-top-left-radius: 5px; border-top-right-radius: 5px;
|
||||
}
|
||||
#search a.inactive { color: #999; fill: #999; }
|
||||
.inheritanceTree, .toggleDefines {
|
||||
float: right;
|
||||
border-left: 1px solid #aaa;
|
||||
position: absolute; top: 0; right: 0;
|
||||
height: 100%;
|
||||
background: #f6f6f6;
|
||||
padding: 5px;
|
||||
min-width: 55px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#menu { font-size: 1.3em; color: #bbb; }
|
||||
#menu .title, #menu a { font-size: 0.7em; }
|
||||
#menu .title a { font-size: 1em; }
|
||||
#menu .title { color: #555; }
|
||||
#menu a, #menu a:visited { color: #333; text-decoration: none; border-bottom: 1px dotted #bbd; }
|
||||
#menu a:hover { color: #05a; }
|
||||
|
||||
#footer { margin-top: 15px; border-top: 1px solid #ccc; text-align: center; padding: 7px 0; color: #999; }
|
||||
#footer a, #footer a:visited { color: #444; text-decoration: none; border-bottom: 1px dotted #bbd; }
|
||||
#footer a:hover { color: #05a; }
|
||||
|
||||
#listing ul.alpha { font-size: 1.1em; }
|
||||
#listing ul.alpha { margin: 0; padding: 0; padding-bottom: 10px; list-style: none; }
|
||||
#listing ul.alpha li.letter { font-size: 1.4em; padding-bottom: 10px; }
|
||||
#listing ul.alpha ul { margin: 0; padding-left: 15px; }
|
||||
#listing ul small { color: #666; font-size: 0.7em; }
|
||||
|
||||
li.r1 { background: #f0f0f0; }
|
||||
li.r2 { background: #fafafa; }
|
||||
|
||||
#content ul.summary li.deprecated .summary_signature a,
|
||||
#content ul.summary li.deprecated .summary_signature a:visited { text-decoration: line-through; font-style: italic; }
|
||||
|
||||
#toc {
|
||||
position: relative;
|
||||
float: right;
|
||||
overflow-x: auto;
|
||||
right: -3px;
|
||||
margin-left: 20px;
|
||||
margin-bottom: 20px;
|
||||
padding: 20px; padding-right: 30px;
|
||||
max-width: 300px;
|
||||
z-index: 5000;
|
||||
background: #fefefe;
|
||||
border: 1px solid #ddd;
|
||||
box-shadow: -2px 2px 6px #bbb;
|
||||
}
|
||||
#toc .title { margin: 0; }
|
||||
#toc ol { padding-left: 1.8em; }
|
||||
#toc li { font-size: 1.1em; line-height: 1.7em; }
|
||||
#toc > ol > li { font-size: 1.1em; font-weight: bold; }
|
||||
#toc ol > li > ol { font-size: 0.9em; }
|
||||
#toc ol ol > li > ol { padding-left: 2.3em; }
|
||||
#toc ol + li { margin-top: 0.3em; }
|
||||
#toc.hidden { padding: 10px; background: #fefefe; box-shadow: none; }
|
||||
#toc.hidden:hover { background: #fafafa; }
|
||||
#filecontents h1 + #toc.nofloat { margin-top: 0; }
|
||||
@media (max-width: 560px) {
|
||||
#toc {
|
||||
margin-left: 0;
|
||||
margin-top: 16px;
|
||||
float: none;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* syntax highlighting */
|
||||
.source_code { display: none; padding: 3px 8px; border-left: 8px solid #ddd; margin-top: 5px; }
|
||||
#filecontents pre.code, .docstring pre.code, .source_code pre { font-family: monospace; }
|
||||
#filecontents pre.code, .docstring pre.code { display: block; }
|
||||
.source_code .lines { padding-right: 12px; color: #555; text-align: right; }
|
||||
#filecontents pre.code, .docstring pre.code,
|
||||
.tags pre.example {
|
||||
padding: 9px 14px;
|
||||
margin-top: 4px;
|
||||
border: 1px solid #e1e1e8;
|
||||
background: #f7f7f9;
|
||||
border-radius: 4px;
|
||||
font-size: 1em;
|
||||
overflow-x: auto;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
pre.code { color: #000; tab-size: 2; }
|
||||
pre.code .info.file { color: #555; }
|
||||
pre.code .val { color: #036A07; }
|
||||
pre.code .tstring_content,
|
||||
pre.code .heredoc_beg, pre.code .heredoc_end,
|
||||
pre.code .qwords_beg, pre.code .qwords_end, pre.code .qwords_sep,
|
||||
pre.code .words_beg, pre.code .words_end, pre.code .words_sep,
|
||||
pre.code .qsymbols_beg, pre.code .qsymbols_end, pre.code .qsymbols_sep,
|
||||
pre.code .symbols_beg, pre.code .symbols_end, pre.code .symbols_sep,
|
||||
pre.code .tstring, pre.code .dstring { color: #036A07; }
|
||||
pre.code .fid, pre.code .rubyid_new, pre.code .rubyid_to_s,
|
||||
pre.code .rubyid_to_sym, pre.code .rubyid_to_f,
|
||||
pre.code .dot + pre.code .id,
|
||||
pre.code .rubyid_to_i pre.code .rubyid_each { color: #0085FF; }
|
||||
pre.code .comment { color: #0066FF; }
|
||||
pre.code .const, pre.code .constant { color: #585CF6; }
|
||||
pre.code .label,
|
||||
pre.code .symbol { color: #C5060B; }
|
||||
pre.code .kw,
|
||||
pre.code .rubyid_require,
|
||||
pre.code .rubyid_extend,
|
||||
pre.code .rubyid_include { color: #0000FF; }
|
||||
pre.code .ivar { color: #318495; }
|
||||
pre.code .gvar,
|
||||
pre.code .rubyid_backref,
|
||||
pre.code .rubyid_nth_ref { color: #6D79DE; }
|
||||
pre.code .regexp, .dregexp { color: #036A07; }
|
||||
pre.code a { border-bottom: 1px dotted #bbf; }
|
||||
/* inline code */
|
||||
*:not(pre) > code {
|
||||
padding: 1px 3px 1px 3px;
|
||||
border: 1px solid #E1E1E8;
|
||||
background: #F7F7F9;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Color fix for links */
|
||||
#content .summary_desc pre.code .id > .object_link a, /* identifier */
|
||||
#content .docstring pre.code .id > .object_link a { color: #0085FF; }
|
||||
#content .summary_desc pre.code .const > .object_link a, /* constant */
|
||||
#content .docstring pre.code .const > .object_link a { color: #585CF6; }
|
|
@ -0,0 +1,81 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
File: README
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "README";
|
||||
relpath = '';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="file_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="_index.html">Index</a> »
|
||||
<span class="title">File: README</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><div id='filecontents'>
|
||||
<p>This plugin is still in active development and may change frequently</p>
|
||||
|
||||
<h2 id="label-Documentation">Documentation</h2>
|
||||
|
||||
<p>The Discourse Chat plugin adds chat functionality to your Discourse so it can natively support both long-form and short-form communication needs of your online community.</p>
|
||||
|
||||
<p>For user documentation, see <a href="https://meta.discourse.org/t/discourse-chat/230881">Discourse Chat</a>.</p>
|
||||
|
||||
<p>For developer documentation, see <a href="https://discourse.github.io/discourse/">Discourse Documentation</a>.</p>
|
||||
</div></div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" />
|
||||
|
||||
<link rel="stylesheet" href="css/common.css" type="text/css" media="screen" />
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
|
||||
|
||||
|
||||
<title>File List</title>
|
||||
<base id="base_target" target="_parent" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<div class="fixed_header">
|
||||
<h1 id="full_list_header">File List</h1>
|
||||
<div id="full_list_nav">
|
||||
|
||||
<span><a target="_self" href="class_list.html">
|
||||
Classes
|
||||
</a></span>
|
||||
|
||||
<span><a target="_self" href="method_list.html">
|
||||
Methods
|
||||
</a></span>
|
||||
|
||||
<span><a target="_self" href="file_list.html">
|
||||
Files
|
||||
</a></span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">Search: <input type="text" /></div>
|
||||
</div>
|
||||
|
||||
<ul id="full_list" class="file">
|
||||
|
||||
|
||||
<li id="object_README" class="odd">
|
||||
<div class="item"><span class="object_link"><a href="index.html" title="README">README</a></span></div>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Documentation by YARD 0.9.28</title>
|
||||
</head>
|
||||
<script type="text/javascript">
|
||||
var match = unescape(window.location.hash).match(/^#!(.+)/);
|
||||
var name = match ? match[1] : 'index.html';
|
||||
name = name.replace(/^(\w+):\/\//, '').replace(/^\/\//, '');
|
||||
window.top.location = name;
|
||||
</script>
|
||||
<noscript>
|
||||
<h1>Oops!</h1>
|
||||
<h2>YARD requires JavaScript!</h2>
|
||||
</noscript>
|
||||
</html>
|
|
@ -0,0 +1,81 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
File: README
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "README";
|
||||
relpath = '';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="_index.html">Index</a> »
|
||||
<span class="title">File: README</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><div id='filecontents'>
|
||||
<p>This plugin is still in active development and may change frequently</p>
|
||||
|
||||
<h2 id="label-Documentation">Documentation</h2>
|
||||
|
||||
<p>The Discourse Chat plugin adds chat functionality to your Discourse so it can natively support both long-form and short-form communication needs of your online community.</p>
|
||||
|
||||
<p>For user documentation, see <a href="https://meta.discourse.org/t/discourse-chat/230881">Discourse Chat</a>.</p>
|
||||
|
||||
<p>For developer documentation, see <a href="https://discourse.github.io/discourse/">Discourse Documentation</a>.</p>
|
||||
</div></div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,314 @@
|
|||
(function() {
|
||||
|
||||
var localStorage = {}, sessionStorage = {};
|
||||
try { localStorage = window.localStorage; } catch (e) { }
|
||||
try { sessionStorage = window.sessionStorage; } catch (e) { }
|
||||
|
||||
function createSourceLinks() {
|
||||
$('.method_details_list .source_code').
|
||||
before("<span class='showSource'>[<a href='#' class='toggleSource'>View source</a>]</span>");
|
||||
$('.toggleSource').toggle(function() {
|
||||
$(this).parent().nextAll('.source_code').slideDown(100);
|
||||
$(this).text("Hide source");
|
||||
},
|
||||
function() {
|
||||
$(this).parent().nextAll('.source_code').slideUp(100);
|
||||
$(this).text("View source");
|
||||
});
|
||||
}
|
||||
|
||||
function createDefineLinks() {
|
||||
var tHeight = 0;
|
||||
$('.defines').after(" <a href='#' class='toggleDefines'>more...</a>");
|
||||
$('.toggleDefines').toggle(function() {
|
||||
tHeight = $(this).parent().prev().height();
|
||||
$(this).prev().css('display', 'inline');
|
||||
$(this).parent().prev().height($(this).parent().height());
|
||||
$(this).text("(less)");
|
||||
},
|
||||
function() {
|
||||
$(this).prev().hide();
|
||||
$(this).parent().prev().height(tHeight);
|
||||
$(this).text("more...");
|
||||
});
|
||||
}
|
||||
|
||||
function createFullTreeLinks() {
|
||||
var tHeight = 0;
|
||||
$('.inheritanceTree').toggle(function() {
|
||||
tHeight = $(this).parent().prev().height();
|
||||
$(this).parent().toggleClass('showAll');
|
||||
$(this).text("(hide)");
|
||||
$(this).parent().prev().height($(this).parent().height());
|
||||
},
|
||||
function() {
|
||||
$(this).parent().toggleClass('showAll');
|
||||
$(this).parent().prev().height(tHeight);
|
||||
$(this).text("show all");
|
||||
});
|
||||
}
|
||||
|
||||
function searchFrameButtons() {
|
||||
$('.full_list_link').click(function() {
|
||||
toggleSearchFrame(this, $(this).attr('href'));
|
||||
return false;
|
||||
});
|
||||
window.addEventListener('message', function(e) {
|
||||
if (e.data === 'navEscape') {
|
||||
$('#nav').slideUp(100);
|
||||
$('#search a').removeClass('active inactive');
|
||||
$(window).focus();
|
||||
}
|
||||
});
|
||||
|
||||
$(window).resize(function() {
|
||||
if ($('#search:visible').length === 0) {
|
||||
$('#nav').removeAttr('style');
|
||||
$('#search a').removeClass('active inactive');
|
||||
$(window).focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function toggleSearchFrame(id, link) {
|
||||
var frame = $('#nav');
|
||||
$('#search a').removeClass('active').addClass('inactive');
|
||||
if (frame.attr('src') === link && frame.css('display') !== "none") {
|
||||
frame.slideUp(100);
|
||||
$('#search a').removeClass('active inactive');
|
||||
}
|
||||
else {
|
||||
$(id).addClass('active').removeClass('inactive');
|
||||
if (frame.attr('src') !== link) frame.attr('src', link);
|
||||
frame.slideDown(100);
|
||||
}
|
||||
}
|
||||
|
||||
function linkSummaries() {
|
||||
$('.summary_signature').click(function() {
|
||||
document.location = $(this).find('a').attr('href');
|
||||
});
|
||||
}
|
||||
|
||||
function summaryToggle() {
|
||||
$('.summary_toggle').click(function(e) {
|
||||
e.preventDefault();
|
||||
localStorage.summaryCollapsed = $(this).text();
|
||||
$('.summary_toggle').each(function() {
|
||||
$(this).text($(this).text() == "collapse" ? "expand" : "collapse");
|
||||
var next = $(this).parent().parent().nextAll('ul.summary').first();
|
||||
if (next.hasClass('compact')) {
|
||||
next.toggle();
|
||||
next.nextAll('ul.summary').first().toggle();
|
||||
}
|
||||
else if (next.hasClass('summary')) {
|
||||
var list = $('<ul class="summary compact" />');
|
||||
list.html(next.html());
|
||||
list.find('.summary_desc, .note').remove();
|
||||
list.find('a').each(function() {
|
||||
$(this).html($(this).find('strong').html());
|
||||
$(this).parent().html($(this)[0].outerHTML);
|
||||
});
|
||||
next.before(list);
|
||||
next.toggle();
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
if (localStorage.summaryCollapsed == "collapse") {
|
||||
$('.summary_toggle').first().click();
|
||||
} else { localStorage.summaryCollapsed = "expand"; }
|
||||
}
|
||||
|
||||
function constantSummaryToggle() {
|
||||
$('.constants_summary_toggle').click(function(e) {
|
||||
e.preventDefault();
|
||||
localStorage.summaryCollapsed = $(this).text();
|
||||
$('.constants_summary_toggle').each(function() {
|
||||
$(this).text($(this).text() == "collapse" ? "expand" : "collapse");
|
||||
var next = $(this).parent().parent().nextAll('dl.constants').first();
|
||||
if (next.hasClass('compact')) {
|
||||
next.toggle();
|
||||
next.nextAll('dl.constants').first().toggle();
|
||||
}
|
||||
else if (next.hasClass('constants')) {
|
||||
var list = $('<dl class="constants compact" />');
|
||||
list.html(next.html());
|
||||
list.find('dt').each(function() {
|
||||
$(this).addClass('summary_signature');
|
||||
$(this).text( $(this).text().split('=')[0]);
|
||||
if ($(this).has(".deprecated").length) {
|
||||
$(this).addClass('deprecated');
|
||||
};
|
||||
});
|
||||
// Add the value of the constant as "Tooltip" to the summary object
|
||||
list.find('pre.code').each(function() {
|
||||
console.log($(this).parent());
|
||||
var dt_element = $(this).parent().prev();
|
||||
var tooltip = $(this).text();
|
||||
if (dt_element.hasClass("deprecated")) {
|
||||
tooltip = 'Deprecated. ' + tooltip;
|
||||
};
|
||||
dt_element.attr('title', tooltip);
|
||||
});
|
||||
list.find('.docstring, .tags, dd').remove();
|
||||
next.before(list);
|
||||
next.toggle();
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
if (localStorage.summaryCollapsed == "collapse") {
|
||||
$('.constants_summary_toggle').first().click();
|
||||
} else { localStorage.summaryCollapsed = "expand"; }
|
||||
}
|
||||
|
||||
function generateTOC() {
|
||||
if ($('#filecontents').length === 0) return;
|
||||
var _toc = $('<ol class="top"></ol>');
|
||||
var show = false;
|
||||
var toc = _toc;
|
||||
var counter = 0;
|
||||
var tags = ['h2', 'h3', 'h4', 'h5', 'h6'];
|
||||
var i;
|
||||
var curli;
|
||||
if ($('#filecontents h1').length > 1) tags.unshift('h1');
|
||||
for (i = 0; i < tags.length; i++) { tags[i] = '#filecontents ' + tags[i]; }
|
||||
var lastTag = parseInt(tags[0][1], 10);
|
||||
$(tags.join(', ')).each(function() {
|
||||
if ($(this).parents('.method_details .docstring').length != 0) return;
|
||||
if (this.id == "filecontents") return;
|
||||
show = true;
|
||||
var thisTag = parseInt(this.tagName[1], 10);
|
||||
if (this.id.length === 0) {
|
||||
var proposedId = $(this).attr('toc-id');
|
||||
if (typeof(proposedId) != "undefined") this.id = proposedId;
|
||||
else {
|
||||
var proposedId = $(this).text().replace(/[^a-z0-9-]/ig, '_');
|
||||
if ($('#' + proposedId).length > 0) { proposedId += counter; counter++; }
|
||||
this.id = proposedId;
|
||||
}
|
||||
}
|
||||
if (thisTag > lastTag) {
|
||||
for (i = 0; i < thisTag - lastTag; i++) {
|
||||
if ( typeof(curli) == "undefined" ) {
|
||||
curli = $('<li/>');
|
||||
toc.append(curli);
|
||||
}
|
||||
toc = $('<ol/>');
|
||||
curli.append(toc);
|
||||
curli = undefined;
|
||||
}
|
||||
}
|
||||
if (thisTag < lastTag) {
|
||||
for (i = 0; i < lastTag - thisTag; i++) {
|
||||
toc = toc.parent();
|
||||
toc = toc.parent();
|
||||
}
|
||||
}
|
||||
var title = $(this).attr('toc-title');
|
||||
if (typeof(title) == "undefined") title = $(this).text();
|
||||
curli =$('<li><a href="#' + this.id + '">' + title + '</a></li>');
|
||||
toc.append(curli);
|
||||
lastTag = thisTag;
|
||||
});
|
||||
if (!show) return;
|
||||
html = '<div id="toc"><p class="title hide_toc"><a href="#"><strong>Table of Contents</strong></a></p></div>';
|
||||
$('#content').prepend(html);
|
||||
$('#toc').append(_toc);
|
||||
$('#toc .hide_toc').toggle(function() {
|
||||
$('#toc .top').slideUp('fast');
|
||||
$('#toc').toggleClass('hidden');
|
||||
$('#toc .title small').toggle();
|
||||
}, function() {
|
||||
$('#toc .top').slideDown('fast');
|
||||
$('#toc').toggleClass('hidden');
|
||||
$('#toc .title small').toggle();
|
||||
});
|
||||
}
|
||||
|
||||
function navResizeFn(e) {
|
||||
if (e.which !== 1) {
|
||||
navResizeFnStop();
|
||||
return;
|
||||
}
|
||||
|
||||
sessionStorage.navWidth = e.pageX.toString();
|
||||
$('.nav_wrap').css('width', e.pageX);
|
||||
$('.nav_wrap').css('-ms-flex', 'inherit');
|
||||
}
|
||||
|
||||
function navResizeFnStop() {
|
||||
$(window).unbind('mousemove', navResizeFn);
|
||||
window.removeEventListener('message', navMessageFn, false);
|
||||
}
|
||||
|
||||
function navMessageFn(e) {
|
||||
if (e.data.action === 'mousemove') navResizeFn(e.data.event);
|
||||
if (e.data.action === 'mouseup') navResizeFnStop();
|
||||
}
|
||||
|
||||
function navResizer() {
|
||||
$('#resizer').mousedown(function(e) {
|
||||
e.preventDefault();
|
||||
$(window).mousemove(navResizeFn);
|
||||
window.addEventListener('message', navMessageFn, false);
|
||||
});
|
||||
$(window).mouseup(navResizeFnStop);
|
||||
|
||||
if (sessionStorage.navWidth) {
|
||||
navResizeFn({which: 1, pageX: parseInt(sessionStorage.navWidth, 10)});
|
||||
}
|
||||
}
|
||||
|
||||
function navExpander() {
|
||||
var done = false, timer = setTimeout(postMessage, 500);
|
||||
function postMessage() {
|
||||
if (done) return;
|
||||
clearTimeout(timer);
|
||||
var opts = { action: 'expand', path: pathId };
|
||||
document.getElementById('nav').contentWindow.postMessage(opts, '*');
|
||||
done = true;
|
||||
}
|
||||
|
||||
window.addEventListener('message', function(event) {
|
||||
if (event.data === 'navReady') postMessage();
|
||||
return false;
|
||||
}, false);
|
||||
}
|
||||
|
||||
function mainFocus() {
|
||||
var hash = window.location.hash;
|
||||
if (hash !== '' && $(hash)[0]) {
|
||||
$(hash)[0].scrollIntoView();
|
||||
}
|
||||
|
||||
setTimeout(function() { $('#main').focus(); }, 10);
|
||||
}
|
||||
|
||||
function navigationChange() {
|
||||
// This works around the broken anchor navigation with the YARD template.
|
||||
window.onpopstate = function() {
|
||||
var hash = window.location.hash;
|
||||
if (hash !== '' && $(hash)[0]) {
|
||||
$(hash)[0].scrollIntoView();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
navResizer();
|
||||
navExpander();
|
||||
createSourceLinks();
|
||||
createDefineLinks();
|
||||
createFullTreeLinks();
|
||||
searchFrameButtons();
|
||||
linkSummaries();
|
||||
summaryToggle();
|
||||
constantSummaryToggle();
|
||||
generateTOC();
|
||||
mainFocus();
|
||||
navigationChange();
|
||||
});
|
||||
|
||||
})();
|
|
@ -0,0 +1,216 @@
|
|||
(function() {
|
||||
|
||||
var $clicked = $(null);
|
||||
var searchTimeout = null;
|
||||
var searchCache = [];
|
||||
var caseSensitiveMatch = false;
|
||||
var ignoreKeyCodeMin = 8;
|
||||
var ignoreKeyCodeMax = 46;
|
||||
var commandKey = 91;
|
||||
|
||||
RegExp.escape = function(text) {
|
||||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
}
|
||||
|
||||
function escapeShortcut() {
|
||||
$(document).keydown(function(evt) {
|
||||
if (evt.which == 27) {
|
||||
window.parent.postMessage('navEscape', '*');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function navResizer() {
|
||||
$(window).mousemove(function(e) {
|
||||
window.parent.postMessage({
|
||||
action: 'mousemove', event: {pageX: e.pageX, which: e.which}
|
||||
}, '*');
|
||||
}).mouseup(function(e) {
|
||||
window.parent.postMessage({action: 'mouseup'}, '*');
|
||||
});
|
||||
window.parent.postMessage("navReady", "*");
|
||||
}
|
||||
|
||||
function clearSearchTimeout() {
|
||||
clearTimeout(searchTimeout);
|
||||
searchTimeout = null;
|
||||
}
|
||||
|
||||
function enableLinks() {
|
||||
// load the target page in the parent window
|
||||
$('#full_list li').on('click', function(evt) {
|
||||
$('#full_list li').removeClass('clicked');
|
||||
$clicked = $(this);
|
||||
$clicked.addClass('clicked');
|
||||
evt.stopPropagation();
|
||||
|
||||
if (evt.target.tagName === 'A') return true;
|
||||
|
||||
var elem = $clicked.find('> .item .object_link a')[0];
|
||||
var e = evt.originalEvent;
|
||||
var newEvent = new MouseEvent(evt.originalEvent.type);
|
||||
newEvent.initMouseEvent(e.type, e.canBubble, e.cancelable, e.view, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
|
||||
elem.dispatchEvent(newEvent);
|
||||
evt.preventDefault();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function enableToggles() {
|
||||
// show/hide nested classes on toggle click
|
||||
$('#full_list a.toggle').on('click', function(evt) {
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
$(this).parent().parent().toggleClass('collapsed');
|
||||
highlight();
|
||||
});
|
||||
}
|
||||
|
||||
function populateSearchCache() {
|
||||
$('#full_list li .item').each(function() {
|
||||
var $node = $(this);
|
||||
var $link = $node.find('.object_link a');
|
||||
if ($link.length > 0) {
|
||||
searchCache.push({
|
||||
node: $node,
|
||||
link: $link,
|
||||
name: $link.text(),
|
||||
fullName: $link.attr('title').split(' ')[0]
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function enableSearch() {
|
||||
$('#search input').keyup(function(event) {
|
||||
if (ignoredKeyPress(event)) return;
|
||||
if (this.value === "") {
|
||||
clearSearch();
|
||||
} else {
|
||||
performSearch(this.value);
|
||||
}
|
||||
});
|
||||
|
||||
$('#full_list').after("<div id='noresults' style='display:none'></div>");
|
||||
}
|
||||
|
||||
function ignoredKeyPress(event) {
|
||||
if (
|
||||
(event.keyCode > ignoreKeyCodeMin && event.keyCode < ignoreKeyCodeMax) ||
|
||||
(event.keyCode == commandKey)
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function clearSearch() {
|
||||
clearSearchTimeout();
|
||||
$('#full_list .found').removeClass('found').each(function() {
|
||||
var $link = $(this).find('.object_link a');
|
||||
$link.text($link.text());
|
||||
});
|
||||
$('#full_list, #content').removeClass('insearch');
|
||||
$clicked.parents().removeClass('collapsed');
|
||||
highlight();
|
||||
}
|
||||
|
||||
function performSearch(searchString) {
|
||||
clearSearchTimeout();
|
||||
$('#full_list, #content').addClass('insearch');
|
||||
$('#noresults').text('').hide();
|
||||
partialSearch(searchString, 0);
|
||||
}
|
||||
|
||||
function partialSearch(searchString, offset) {
|
||||
var lastRowClass = '';
|
||||
var i = null;
|
||||
for (i = offset; i < Math.min(offset + 50, searchCache.length); i++) {
|
||||
var item = searchCache[i];
|
||||
var searchName = (searchString.indexOf('::') != -1 ? item.fullName : item.name);
|
||||
var matchString = buildMatchString(searchString);
|
||||
var matchRegexp = new RegExp(matchString, caseSensitiveMatch ? "" : "i");
|
||||
if (searchName.match(matchRegexp) == null) {
|
||||
item.node.removeClass('found');
|
||||
item.link.text(item.link.text());
|
||||
}
|
||||
else {
|
||||
item.node.addClass('found');
|
||||
item.node.removeClass(lastRowClass).addClass(lastRowClass == 'r1' ? 'r2' : 'r1');
|
||||
lastRowClass = item.node.hasClass('r1') ? 'r1' : 'r2';
|
||||
item.link.html(item.name.replace(matchRegexp, "<strong>$&</strong>"));
|
||||
}
|
||||
}
|
||||
if(i == searchCache.length) {
|
||||
searchDone();
|
||||
} else {
|
||||
searchTimeout = setTimeout(function() {
|
||||
partialSearch(searchString, i);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function searchDone() {
|
||||
searchTimeout = null;
|
||||
highlight();
|
||||
if ($('#full_list li:visible').size() === 0) {
|
||||
$('#noresults').text('No results were found.').hide().fadeIn();
|
||||
} else {
|
||||
$('#noresults').text('').hide();
|
||||
}
|
||||
$('#content').removeClass('insearch');
|
||||
}
|
||||
|
||||
function buildMatchString(searchString, event) {
|
||||
caseSensitiveMatch = searchString.match(/[A-Z]/) != null;
|
||||
var regexSearchString = RegExp.escape(searchString);
|
||||
if (caseSensitiveMatch) {
|
||||
regexSearchString += "|" +
|
||||
$.map(searchString.split(''), function(e) { return RegExp.escape(e); }).
|
||||
join('.+?');
|
||||
}
|
||||
return regexSearchString;
|
||||
}
|
||||
|
||||
function highlight() {
|
||||
$('#full_list li:visible').each(function(n) {
|
||||
$(this).removeClass('even odd').addClass(n % 2 == 0 ? 'odd' : 'even');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands the tree to the target element and its immediate
|
||||
* children.
|
||||
*/
|
||||
function expandTo(path) {
|
||||
var $target = $(document.getElementById('object_' + path));
|
||||
$target.addClass('clicked');
|
||||
$target.removeClass('collapsed');
|
||||
$target.parentsUntil('#full_list', 'li').removeClass('collapsed');
|
||||
if($target[0]) {
|
||||
window.scrollTo(window.scrollX, $target.offset().top - 250);
|
||||
highlight();
|
||||
}
|
||||
}
|
||||
|
||||
function windowEvents(event) {
|
||||
var msg = event.data;
|
||||
if (msg.action === "expand") {
|
||||
expandTo(msg.path);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
window.addEventListener("message", windowEvents, false);
|
||||
|
||||
$(document).ready(function() {
|
||||
escapeShortcut();
|
||||
navResizer();
|
||||
enableLinks();
|
||||
enableToggles();
|
||||
populateSearchCache();
|
||||
enableSearch();
|
||||
});
|
||||
|
||||
})();
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,163 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" />
|
||||
|
||||
<link rel="stylesheet" href="css/common.css" type="text/css" media="screen" />
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
|
||||
|
||||
|
||||
<title>Method List</title>
|
||||
<base id="base_target" target="_parent" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<div class="fixed_header">
|
||||
<h1 id="full_list_header">Method List</h1>
|
||||
<div id="full_list_nav">
|
||||
|
||||
<span><a target="_self" href="class_list.html">
|
||||
Classes
|
||||
</a></span>
|
||||
|
||||
<span><a target="_self" href="method_list.html">
|
||||
Methods
|
||||
</a></span>
|
||||
|
||||
<span><a target="_self" href="file_list.html">
|
||||
Files
|
||||
</a></span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">Search: <input type="text" /></div>
|
||||
</div>
|
||||
|
||||
<ul id="full_list" class="method">
|
||||
|
||||
|
||||
<li class="odd ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/Base.html#contract-class_method" title="Chat::Service::Base.contract (method)">contract</a></span>
|
||||
<small>Chat::Service::Base</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="even ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/Base.html#model-class_method" title="Chat::Service::Base.model (method)">model</a></span>
|
||||
<small>Chat::Service::Base</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="odd ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/Base.html#policy-class_method" title="Chat::Service::Base.policy (method)">policy</a></span>
|
||||
<small>Chat::Service::Base</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="even ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/Base.html#step-class_method" title="Chat::Service::Base.step (method)">step</a></span>
|
||||
<small>Chat::Service::Base</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="odd ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/Base.html#transaction-class_method" title="Chat::Service::Base.transaction (method)">transaction</a></span>
|
||||
<small>Chat::Service::Base</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="even ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/Base/Context.html#fail-instance_method" title="Chat::Service::Base::Context#fail (method)">#fail</a></span>
|
||||
<small>Chat::Service::Base::Context</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="odd ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/Base/Context.html#fail!-instance_method" title="Chat::Service::Base::Context#fail! (method)">#fail!</a></span>
|
||||
<small>Chat::Service::Base::Context</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="even ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/Base/Context.html#failure%3F-instance_method" title="Chat::Service::Base::Context#failure? (method)">#failure?</a></span>
|
||||
<small>Chat::Service::Base::Context</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="odd ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/Base/Context.html#success%3F-instance_method" title="Chat::Service::Base::Context#success? (method)">#success?</a></span>
|
||||
<small>Chat::Service::Base::Context</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="even ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/Base/Failure.html#context-instance_method" title="Chat::Service::Base::Failure#context (method)">#context</a></span>
|
||||
<small>Chat::Service::Base::Failure</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="odd ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/TrashChannel.html#call-instance_method" title="Chat::Service::TrashChannel#call (method)">#call</a></span>
|
||||
<small>Chat::Service::TrashChannel</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="even ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/UpdateChannel.html#call-instance_method" title="Chat::Service::UpdateChannel#call (method)">#call</a></span>
|
||||
<small>Chat::Service::UpdateChannel</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="odd ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/UpdateChannelStatus.html#call-instance_method" title="Chat::Service::UpdateChannelStatus#call (method)">#call</a></span>
|
||||
<small>Chat::Service::UpdateChannelStatus</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="even ">
|
||||
<div class="item">
|
||||
<span class='object_link'><a href="Chat/Service/UpdateUserLastRead.html#call-instance_method" title="Chat::Service::UpdateUserLastRead#call (method)">#call</a></span>
|
||||
<small>Chat::Service::UpdateUserLastRead</small>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,111 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>
|
||||
Top Level Namespace
|
||||
|
||||
— Documentation by YARD 0.9.28
|
||||
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
pathId = "";
|
||||
relpath = '';
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav_wrap">
|
||||
<iframe id="nav" src="class_list.html?1"></iframe>
|
||||
<div id="resizer"></div>
|
||||
</div>
|
||||
|
||||
<div id="main" tabindex="-1">
|
||||
<div id="header">
|
||||
<div id="menu">
|
||||
|
||||
<a href="_index.html">Index</a> »
|
||||
|
||||
|
||||
<span class="title">Top Level Namespace</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="search">
|
||||
|
||||
<a class="full_list_link" id="class_list_link"
|
||||
href="class_list.html">
|
||||
|
||||
<svg width="24" height="24">
|
||||
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
||||
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="content"><h1>Top Level Namespace
|
||||
|
||||
|
||||
|
||||
</h1>
|
||||
<div class="box_info">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<h2>Defined Under Namespace</h2>
|
||||
<p class="children">
|
||||
|
||||
|
||||
<strong class="modules">Modules:</strong> <span class='object_link'><a href="Chat.html" title="Chat (module)">Chat</a></span>
|
||||
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
0.9.28.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,372 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Discourse: Global</title>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/vendor/prism-custom.css">
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/styles.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="layout-header">
|
||||
|
||||
<h1>
|
||||
<a href="./index.html">
|
||||
Discourse
|
||||
</a>
|
||||
</h1>
|
||||
<nav class="layout-nav">
|
||||
<ul><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="PluginApi.html">PluginApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#decorateChatMessage">decorateChatMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#registerChatComposerButton">registerChatComposerButton</a></span></li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="module.exports.html">exports</a></span></li></ul><ul><li class="nav-heading">Modules</li><li class="nav-heading"><span class="nav-item-type type-module" title="module">M</span><span class="nav-item-name is-module"><a href="module-ChatApi.html">ChatApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#categoryPermissions">categoryPermissions</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channel">channel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channels">channels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannel">createChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannelArchive">createChannelArchive</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#destroyChannel">destroyChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#followChannel">followChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listChannelMemberships">listChannelMemberships</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listCurrentUserChannels">listCurrentUserChannels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#moveChannelMessages">moveChannelMessages</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#sendMessage">sendMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#unfollowChannel">unfollowChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannel">updateChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannelStatus">updateChannelStatus</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateCurrentUserChannelNotificationsSettings">updateCurrentUserChannelNotificationsSettings</a></span></li></ul><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#load">load</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#loadMore">loadMore</a></span></li>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
||||
<main class="layout-main ">
|
||||
<div class="container">
|
||||
<p class="page-kind"></p>
|
||||
<h1 class="page-title">Global</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
|
||||
<header class="not-class">
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- <h2></h2> -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subtitle">Methods</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<article class="method">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="method-type">
|
||||
|
||||
</div>
|
||||
|
||||
<h4 class="method-name" id="load">load<span class="signature">()</span><span class="return-type-signature"> → {Promise}</span>
|
||||
</h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="method-description">
|
||||
|
||||
Loads first batch of results
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h4 class="method-heading">Returns</h4>
|
||||
<ul>
|
||||
|
||||
<li class="method-returns">
|
||||
|
||||
<code>Promise</code>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="method-heading">Source</h4>
|
||||
<ul>
|
||||
<li class="method-source">
|
||||
<a href="lib_collection.js.html">lib/collection.js</a><a href="lib_collection.js.html#source.51">, line 51</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<article class="method">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="method-type">
|
||||
|
||||
</div>
|
||||
|
||||
<h4 class="method-name" id="loadMore">loadMore<span class="signature">()</span><span class="return-type-signature"> → {Promise}</span>
|
||||
</h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="method-description">
|
||||
|
||||
Attempts to load more results
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h4 class="method-heading">Returns</h4>
|
||||
<ul>
|
||||
|
||||
<li class="method-returns">
|
||||
|
||||
<code>Promise</code>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="method-heading">Source</h4>
|
||||
<ul>
|
||||
<li class="method-source">
|
||||
<a href="lib_collection.js.html">lib/collection.js</a><a href="lib_collection.js.html#source.81">, line 81</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="layout-footer">
|
||||
<div class="container">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.0</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="scripts/prism.dev.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,80 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Discourse: </title>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/vendor/prism-custom.css">
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/styles.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="layout-header">
|
||||
|
||||
<h1>
|
||||
<a href="./index.html">
|
||||
Discourse
|
||||
</a>
|
||||
</h1>
|
||||
<nav class="layout-nav">
|
||||
<ul><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="PluginApi.html">PluginApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#decorateChatMessage">decorateChatMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#registerChatComposerButton">registerChatComposerButton</a></span></li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="module.exports.html">exports</a></span></li></ul><ul><li class="nav-heading">Modules</li><li class="nav-heading"><span class="nav-item-type type-module" title="module">M</span><span class="nav-item-name is-module"><a href="module-ChatApi.html">ChatApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#categoryPermissions">categoryPermissions</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channel">channel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channels">channels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannel">createChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannelArchive">createChannelArchive</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#destroyChannel">destroyChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#followChannel">followChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listChannelMemberships">listChannelMemberships</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listCurrentUserChannels">listCurrentUserChannels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#moveChannelMessages">moveChannelMessages</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#sendMessage">sendMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#unfollowChannel">unfollowChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannel">updateChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannelStatus">updateChannelStatus</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateCurrentUserChannelNotificationsSettings">updateCurrentUserChannelNotificationsSettings</a></span></li></ul><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#load">load</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#loadMore">loadMore</a></span></li>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
||||
<main class="layout-main ">
|
||||
<div class="container">
|
||||
<p class="page-kind"></p>
|
||||
<h1 class="page-title"></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3> </h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section class="readme">
|
||||
<article><p>This plugin is still in active development and may change frequently</p>
|
||||
<h2>Documentation</h2>
|
||||
<p>The Discourse Chat plugin adds chat functionality to your Discourse so it can natively support both long-form and short-form communication needs of your online community.</p>
|
||||
<p>For user documentation, see <a href="https://meta.discourse.org/t/discourse-chat/230881">Discourse Chat</a>.</p>
|
||||
<p>For developer documentation, see <a href="https://discourse.github.io/discourse/">Discourse Documentation</a>.</p></article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="layout-footer">
|
||||
<div class="container">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.0</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="scripts/prism.dev.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,178 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Discourse: lib/collection.js</title>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/vendor/prism-custom.css">
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/styles.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="layout-header">
|
||||
|
||||
<h1>
|
||||
<a href="./index.html">
|
||||
Discourse
|
||||
</a>
|
||||
</h1>
|
||||
<nav class="layout-nav">
|
||||
<ul><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="PluginApi.html">PluginApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#decorateChatMessage">decorateChatMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#registerChatComposerButton">registerChatComposerButton</a></span></li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="module.exports.html">exports</a></span></li></ul><ul><li class="nav-heading">Modules</li><li class="nav-heading"><span class="nav-item-type type-module" title="module">M</span><span class="nav-item-name is-module"><a href="module-ChatApi.html">ChatApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#categoryPermissions">categoryPermissions</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channel">channel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channels">channels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannel">createChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannelArchive">createChannelArchive</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#destroyChannel">destroyChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#followChannel">followChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listChannelMemberships">listChannelMemberships</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listCurrentUserChannels">listCurrentUserChannels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#moveChannelMessages">moveChannelMessages</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#sendMessage">sendMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#unfollowChannel">unfollowChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannel">updateChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannelStatus">updateChannelStatus</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateCurrentUserChannelNotificationsSettings">updateCurrentUserChannelNotificationsSettings</a></span></li></ul><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#load">load</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#loadMore">loadMore</a></span></li>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
||||
<main class="layout-main layout-content--source">
|
||||
<div class="container">
|
||||
<p class="page-kind">source</p>
|
||||
<h1 class="page-title">lib/collection.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre id="source" class="source-page line-numbers"><code class="language-js">import { ajax } from "discourse/lib/ajax";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
import { Promise } from "rsvp";
|
||||
|
||||
/**
|
||||
* Handles a paginated API response.
|
||||
*/
|
||||
export default class Collection {
|
||||
@tracked items = [];
|
||||
@tracked meta = {};
|
||||
@tracked loading = false;
|
||||
|
||||
constructor(resourceURL, handler) {
|
||||
this._resourceURL = resourceURL;
|
||||
this._handler = handler;
|
||||
this._fetchedAll = false;
|
||||
}
|
||||
|
||||
get loadMoreURL() {
|
||||
return this.meta.load_more_url;
|
||||
}
|
||||
|
||||
get totalRows() {
|
||||
return this.meta.total_rows;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this.items.length;
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols
|
||||
[Symbol.iterator]() {
|
||||
let index = 0;
|
||||
|
||||
return {
|
||||
next: () => {
|
||||
if (index < this.items.length) {
|
||||
return { value: this.items[index++], done: false };
|
||||
} else {
|
||||
return { done: true };
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads first batch of results
|
||||
* @returns {Promise}
|
||||
*/
|
||||
@bind
|
||||
load(params = {}) {
|
||||
this._fetchedAll = false;
|
||||
|
||||
if (this.loading) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
|
||||
const filteredQueryParams = Object.entries(params).filter(
|
||||
([, v]) => v !== undefined
|
||||
);
|
||||
const queryString = new URLSearchParams(filteredQueryParams).toString();
|
||||
|
||||
const endpoint = this._resourceURL + (queryString ? `?${queryString}` : "");
|
||||
return this.#fetch(endpoint)
|
||||
.then((result) => {
|
||||
this.items = this._handler(result);
|
||||
this.meta = result.meta;
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to load more results
|
||||
* @returns {Promise}
|
||||
*/
|
||||
@bind
|
||||
loadMore() {
|
||||
let promise = Promise.resolve();
|
||||
|
||||
if (this.loading) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
if (
|
||||
this._fetchedAll ||
|
||||
(this.totalRows && this.items.length >= this.totalRows)
|
||||
) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
|
||||
if (this.loadMoreURL) {
|
||||
promise = this.#fetch(this.loadMoreURL).then((result) => {
|
||||
const newItems = this._handler(result);
|
||||
|
||||
if (newItems.length) {
|
||||
this.items = this.items.concat(newItems);
|
||||
} else {
|
||||
this._fetchedAll = true;
|
||||
}
|
||||
this.meta = result.meta;
|
||||
});
|
||||
}
|
||||
|
||||
return promise.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
#fetch(url) {
|
||||
return ajax(url, { type: "GET" });
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="layout-footer">
|
||||
<div class="container">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.0</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="scripts/prism.dev.js"></script>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,198 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Discourse: exports</title>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/vendor/prism-custom.css">
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/styles.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="layout-header">
|
||||
|
||||
<h1>
|
||||
<a href="./index.html">
|
||||
Discourse
|
||||
</a>
|
||||
</h1>
|
||||
<nav class="layout-nav">
|
||||
<ul><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="PluginApi.html">PluginApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#decorateChatMessage">decorateChatMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#registerChatComposerButton">registerChatComposerButton</a></span></li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="module.exports.html">exports</a></span></li></ul><ul><li class="nav-heading">Modules</li><li class="nav-heading"><span class="nav-item-type type-module" title="module">M</span><span class="nav-item-name is-module"><a href="module-ChatApi.html">ChatApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#categoryPermissions">categoryPermissions</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channel">channel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channels">channels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannel">createChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannelArchive">createChannelArchive</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#destroyChannel">destroyChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#followChannel">followChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listChannelMemberships">listChannelMemberships</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listCurrentUserChannels">listCurrentUserChannels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#moveChannelMessages">moveChannelMessages</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#sendMessage">sendMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#unfollowChannel">unfollowChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannel">updateChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannelStatus">updateChannelStatus</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateCurrentUserChannelNotificationsSettings">updateCurrentUserChannelNotificationsSettings</a></span></li></ul><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#load">load</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#loadMore">loadMore</a></span></li>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
||||
<main class="layout-main ">
|
||||
<div class="container">
|
||||
<p class="page-kind">Class</p>
|
||||
<h1 class="page-title">exports</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
|
||||
<header class="class">
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- <h2>exports</h2> -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="class-description">Handles a paginated API response.</div>
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subtitle">Constructor</h3>
|
||||
|
||||
|
||||
<div class="method-type">
|
||||
|
||||
</div>
|
||||
|
||||
<h4 class="method-name" id="exports">new exports<span class="signature">()</span><span class="return-type-signature"></span>
|
||||
</h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="method-heading">Source</h4>
|
||||
<ul>
|
||||
<li class="method-source">
|
||||
<a href="lib_collection.js.html">lib/collection.js</a><a href="lib_collection.js.html#source.9">, line 9</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="layout-footer">
|
||||
<div class="container">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.0</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="scripts/prism.dev.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,156 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Discourse: pre-initializers/chat-plugin-api.js</title>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/vendor/prism-custom.css">
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/styles.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="layout-header">
|
||||
|
||||
<h1>
|
||||
<a href="./index.html">
|
||||
Discourse
|
||||
</a>
|
||||
</h1>
|
||||
<nav class="layout-nav">
|
||||
<ul><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="PluginApi.html">PluginApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#decorateChatMessage">decorateChatMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#registerChatComposerButton">registerChatComposerButton</a></span></li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="module.exports.html">exports</a></span></li></ul><ul><li class="nav-heading">Modules</li><li class="nav-heading"><span class="nav-item-type type-module" title="module">M</span><span class="nav-item-name is-module"><a href="module-ChatApi.html">ChatApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#categoryPermissions">categoryPermissions</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channel">channel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channels">channels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannel">createChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannelArchive">createChannelArchive</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#destroyChannel">destroyChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#followChannel">followChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listChannelMemberships">listChannelMemberships</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listCurrentUserChannels">listCurrentUserChannels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#moveChannelMessages">moveChannelMessages</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#sendMessage">sendMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#unfollowChannel">unfollowChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannel">updateChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannelStatus">updateChannelStatus</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateCurrentUserChannelNotificationsSettings">updateCurrentUserChannelNotificationsSettings</a></span></li></ul><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#load">load</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#loadMore">loadMore</a></span></li>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
||||
<main class="layout-main layout-content--source">
|
||||
<div class="container">
|
||||
<p class="page-kind">source</p>
|
||||
<h1 class="page-title">pre-initializers/chat-plugin-api.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre id="source" class="source-page line-numbers"><code class="language-js">import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import {
|
||||
addChatMessageDecorator,
|
||||
resetChatMessageDecorators,
|
||||
} from "discourse/plugins/chat/discourse/components/chat-message";
|
||||
import { registerChatComposerButton } from "discourse/plugins/chat/discourse/lib/chat-composer-buttons";
|
||||
|
||||
/**
|
||||
* Class exposing the javascript API available to plugins and themes.
|
||||
* @class PluginApi
|
||||
*/
|
||||
|
||||
/**
|
||||
* Callback used to decorate a chat message
|
||||
*
|
||||
* @callback PluginApi~decorateChatMessageCallback
|
||||
* @param {ChatMessage} chatMessage - model
|
||||
* @param {HTMLElement} messageContainer - DOM node
|
||||
* @param {ChatChannel} chatChannel - model
|
||||
*/
|
||||
|
||||
/**
|
||||
* Decorate a chat message
|
||||
*
|
||||
* @memberof PluginApi
|
||||
* @instance
|
||||
* @function decorateChatMessage
|
||||
* @param {PluginApi~decorateChatMessageCallback} decorator
|
||||
* @example
|
||||
*
|
||||
* api.decorateChatMessage((chatMessage, messageContainer) => {
|
||||
* messageContainer.dataset.foo = chatMessage.id;
|
||||
* });
|
||||
*/
|
||||
|
||||
/**
|
||||
* Register a button in the chat composer
|
||||
*
|
||||
* @memberof PluginApi
|
||||
* @instance
|
||||
* @function registerChatComposerButton
|
||||
* @param {Object} options
|
||||
* @param {number} options.id - The id of the button
|
||||
* @param {function} options.action - An action name or an anonymous function called when the button is pressed, eg: "onFooClicked" or `() => { console.log("clicked") }`
|
||||
* @param {string} options.icon - A valid font awesome icon name, eg: "far fa-image"
|
||||
* @param {string} options.label - Text displayed on the button, a translatable key, eg: "foo.bar"
|
||||
* @param {string} options.translatedLabel - Text displayed on the button, a string, eg: "Add gifs"
|
||||
* @param {string} [options.position] - Can be "inline" or "dropdown", defaults to "inline"
|
||||
* @param {string} [options.title] - Title attribute of the button, a translatable key, eg: "foo.bar"
|
||||
* @param {string} [options.translatedTitle] - Title attribute of the button, a string, eg: "Add gifs"
|
||||
* @param {string} [options.ariaLabel] - aria-label attribute of the button, a translatable key, eg: "foo.bar"
|
||||
* @param {string} [options.translatedAriaLabel] - aria-label attribute of the button, a string, eg: "Add gifs"
|
||||
* @param {string} [options.classNames] - Additional names to add to the button’s class attribute, eg: ["foo", "bar"]
|
||||
* @param {boolean} [options.displayed] - Hide or show the button
|
||||
* @param {boolean} [options.disabled] - Sets the disabled attribute on the button
|
||||
* @param {number} [options.priority] - An integer defining the order of the buttons, higher comes first, eg: `700`
|
||||
* @param {Array.<string>} [options.dependentKeys] - List of property names which should trigger a refresh of the buttons when changed, eg: `["foo.bar", "bar.baz"]`
|
||||
* @example
|
||||
*
|
||||
* api.registerChatComposerButton({
|
||||
* id: "foo",
|
||||
* displayed() {
|
||||
* return this.site.mobileView && this.canAttachUploads;
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: "chat-plugin-api",
|
||||
after: "inject-discourse-objects",
|
||||
|
||||
initialize() {
|
||||
withPluginApi("1.2.0", (api) => {
|
||||
const apiPrototype = Object.getPrototypeOf(api);
|
||||
|
||||
if (!apiPrototype.hasOwnProperty("decorateChatMessage")) {
|
||||
Object.defineProperty(apiPrototype, "decorateChatMessage", {
|
||||
value(decorator) {
|
||||
addChatMessageDecorator(decorator);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!apiPrototype.hasOwnProperty("registerChatComposerButton")) {
|
||||
Object.defineProperty(apiPrototype, "registerChatComposerButton", {
|
||||
value(button) {
|
||||
registerChatComposerButton(button);
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
teardown() {
|
||||
resetChatMessageDecorators();
|
||||
},
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="layout-footer">
|
||||
<div class="container">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.0</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="scripts/prism.dev.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,57 @@
|
|||
(function() {
|
||||
|
||||
if (typeof self === 'undefined' || !self.Prism || !self.document) {
|
||||
return;
|
||||
}
|
||||
|
||||
Prism.hooks.add('complete', function (env) {
|
||||
if (!env.code) {
|
||||
return;
|
||||
}
|
||||
|
||||
// works only for <code> wrapped inside <pre> (not inline)
|
||||
var pre = env.element.parentNode;
|
||||
var clsReg = /\s*\bline-numbers\b\s*/;
|
||||
if (
|
||||
!pre || !/pre/i.test(pre.nodeName) ||
|
||||
// Abort only if nor the <pre> nor the <code> have the class
|
||||
(!clsReg.test(pre.className) && !clsReg.test(env.element.className))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (env.element.querySelector(".line-numbers-rows")) {
|
||||
// Abort if line numbers already exists
|
||||
return;
|
||||
}
|
||||
|
||||
if (clsReg.test(env.element.className)) {
|
||||
// Remove the class "line-numbers" from the <code>
|
||||
env.element.className = env.element.className.replace(clsReg, '');
|
||||
}
|
||||
if (!clsReg.test(pre.className)) {
|
||||
// Add the class "line-numbers" to the <pre>
|
||||
pre.className += ' line-numbers';
|
||||
}
|
||||
|
||||
var match = env.code.match(/\n(?!$)/g);
|
||||
var linesNum = match ? match.length + 1 : 1;
|
||||
var lineNumbersWrapper;
|
||||
|
||||
var lines = new Array(linesNum + 1);
|
||||
lines = lines.join('<span></span>');
|
||||
|
||||
lineNumbersWrapper = document.createElement('span');
|
||||
lineNumbersWrapper.setAttribute('aria-hidden', 'true');
|
||||
lineNumbersWrapper.className = 'line-numbers-rows';
|
||||
lineNumbersWrapper.innerHTML = lines;
|
||||
|
||||
if (pre.hasAttribute('data-start')) {
|
||||
pre.style.counterReset = 'linenumber ' + (parseInt(pre.getAttribute('data-start'), 10) - 1);
|
||||
}
|
||||
|
||||
env.element.appendChild(lineNumbersWrapper);
|
||||
|
||||
});
|
||||
|
||||
}());
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,325 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Discourse: services/chat-api.js</title>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/vendor/prism-custom.css">
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="styles/styles.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="layout-header">
|
||||
|
||||
<h1>
|
||||
<a href="./index.html">
|
||||
Discourse
|
||||
</a>
|
||||
</h1>
|
||||
<nav class="layout-nav">
|
||||
<ul><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="PluginApi.html">PluginApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#decorateChatMessage">decorateChatMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="PluginApi.html#registerChatComposerButton">registerChatComposerButton</a></span></li><li class="nav-heading"><span class="nav-item-type type-class" title="class">C</span><span class="nav-item-name is-class"><a href="module.exports.html">exports</a></span></li></ul><ul><li class="nav-heading">Modules</li><li class="nav-heading"><span class="nav-item-type type-module" title="module">M</span><span class="nav-item-name is-module"><a href="module-ChatApi.html">ChatApi</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#categoryPermissions">categoryPermissions</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channel">channel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#channels">channels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannel">createChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#createChannelArchive">createChannelArchive</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#destroyChannel">destroyChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#followChannel">followChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listChannelMemberships">listChannelMemberships</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#listCurrentUserChannels">listCurrentUserChannels</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#moveChannelMessages">moveChannelMessages</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#sendMessage">sendMessage</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#unfollowChannel">unfollowChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannel">updateChannel</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateChannelStatus">updateChannelStatus</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="module-ChatApi.html#updateCurrentUserChannelNotificationsSettings">updateCurrentUserChannelNotificationsSettings</a></span></li></ul><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#load">load</a></span></li><li class="nav-item"><span class="nav-item-type type-function" title="function">F</span><span class="nav-item-name is-function"><a href="global.html#loadMore">loadMore</a></span></li>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
||||
<main class="layout-main layout-content--source">
|
||||
<div class="container">
|
||||
<p class="page-kind">source</p>
|
||||
<h1 class="page-title">services/chat-api.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre id="source" class="source-page line-numbers"><code class="language-js">import Service, { inject as service } from "@ember/service";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import UserChatChannelMembership from "discourse/plugins/chat/discourse/models/user-chat-channel-membership";
|
||||
import Collection from "../lib/collection";
|
||||
|
||||
/**
|
||||
* Chat API service. Provides methods to interact with the chat API.
|
||||
*
|
||||
* @module ChatApi
|
||||
* @implements {@ember/service}
|
||||
*/
|
||||
export default class ChatApi extends Service {
|
||||
@service chatChannelsManager;
|
||||
|
||||
/**
|
||||
* Get a channel by its ID.
|
||||
* @param {number} channelId - The ID of the channel.
|
||||
* @returns {Promise}
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* this.chatApi.channel(1).then(channel => { ... })
|
||||
*/
|
||||
channel(channelId) {
|
||||
return this.#getRequest(`/channels/${channelId}`).then((result) =>
|
||||
this.chatChannelsManager.store(result.channel)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all accessible category channels of the current user.
|
||||
* @returns {Collection}
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* this.chatApi.channels.then(channels => { ... })
|
||||
*/
|
||||
channels() {
|
||||
return new Collection(`${this.#basePath}/channels`, (response) => {
|
||||
return response.channels.map((channel) =>
|
||||
this.chatChannelsManager.store(channel)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves messages from one channel to another.
|
||||
* @param {number} channelId - The ID of the original channel.
|
||||
* @param {object} data - Params of the move.
|
||||
* @param {Array.<number>} data.message_ids - IDs of the moved messages.
|
||||
* @param {number} data.destination_channel_id - ID of the channel where the messages are moved to.
|
||||
* @returns {Promise}
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* this.chatApi
|
||||
* .moveChannelMessages(1, {
|
||||
* message_ids: [2, 3],
|
||||
* destination_channel_id: 4,
|
||||
* }).then(() => { ... })
|
||||
*/
|
||||
moveChannelMessages(channelId, data = {}) {
|
||||
return this.#postRequest(`/channels/${channelId}/messages/moves`, {
|
||||
move: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a channel.
|
||||
* @param {number} channelId - The ID of the channel.
|
||||
* @returns {Promise}
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* this.chatApi.destroyChannel(1).then(() => { ... })
|
||||
*/
|
||||
destroyChannel(channelId) {
|
||||
return this.#deleteRequest(`/channels/${channelId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a channel.
|
||||
* @param {object} data - Params of the channel.
|
||||
* @param {string} data.name - The name of the channel.
|
||||
* @param {string} data.chatable_id - The category of the channel.
|
||||
* @param {string} data.description - The description of the channel.
|
||||
* @param {boolean} [data.auto_join_users] - Should users join this channel automatically.
|
||||
* @returns {Promise}
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* this.chatApi
|
||||
* .createChannel({ name: "foo", chatable_id: 1, description "bar" })
|
||||
* .then((channel) => { ... })
|
||||
*/
|
||||
createChannel(data = {}) {
|
||||
return this.#postRequest("/channels", { channel: data }).then((response) =>
|
||||
this.chatChannelsManager.store(response.channel)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists chat permissions for a category.
|
||||
* @param {number} categoryId - ID of the category.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
categoryPermissions(categoryId) {
|
||||
return this.#getRequest(`/category-chatables/${categoryId}/permissions`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message.
|
||||
* @param {number} channelId - ID of the channel.
|
||||
* @param {object} data - Params of the message.
|
||||
* @param {string} data.message - The raw content of the message in markdown.
|
||||
* @param {string} data.cooked - The cooked content of the message.
|
||||
* @param {number} [data.in_reply_to_id] - The ID of the replied-to message.
|
||||
* @param {number} [data.staged_id] - The staged ID of the message before it was persisted.
|
||||
* @param {Array.<number>} [data.upload_ids] - Array of upload ids linked to the message.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
sendMessage(channelId, data = {}) {
|
||||
return ajax(`/chat/${channelId}`, {
|
||||
ignoreUnsent: false,
|
||||
type: "POST",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a channel archive.
|
||||
* @param {number} channelId - The ID of the channel.
|
||||
* @param {object} data - Params of the archive.
|
||||
* @param {string} data.selection - "new_topic" or "existing_topic".
|
||||
* @param {string} [data.title] - Title of the topic when creating a new topic.
|
||||
* @param {string} [data.category_id] - ID of the category used when creating a new topic.
|
||||
* @param {Array.<string>} [data.tags] - tags used when creating a new topic.
|
||||
* @param {string} [data.topic_id] - ID of the topic when using an existing topic.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
createChannelArchive(channelId, data = {}) {
|
||||
return this.#postRequest(`/channels/${channelId}/archives`, {
|
||||
archive: data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a channel.
|
||||
* @param {number} channelId - The ID of the channel.
|
||||
* @param {object} data - Params of the archive.
|
||||
* @param {string} [data.description] - Description of the channel.
|
||||
* @param {string} [data.name] - Name of the channel.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
updateChannel(channelId, data = {}) {
|
||||
return this.#putRequest(`/channels/${channelId}`, { channel: data });
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the status of a channel.
|
||||
* @param {number} channelId - The ID of the channel.
|
||||
* @param {string} status - The new status, can be "open" or "closed".
|
||||
* @returns {Promise}
|
||||
*/
|
||||
updateChannelStatus(channelId, status) {
|
||||
return this.#putRequest(`/channels/${channelId}/status`, { status });
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists members of a channel.
|
||||
* @param {number} channelId - The ID of the channel.
|
||||
* @returns {Collection}
|
||||
*/
|
||||
listChannelMemberships(channelId) {
|
||||
return new Collection(
|
||||
`${this.#basePath}/channels/${channelId}/memberships`,
|
||||
(response) => {
|
||||
return response.memberships.map((membership) =>
|
||||
UserChatChannelMembership.create(membership)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists public and direct message channels of the current user.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
listCurrentUserChannels() {
|
||||
return this.#getRequest("/channels/me").then((result) => {
|
||||
return (result?.channels || []).map((channel) =>
|
||||
this.chatChannelsManager.store(channel)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes current user follow a channel.
|
||||
* @param {number} channelId - The ID of the channel.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
followChannel(channelId) {
|
||||
return this.#postRequest(`/channels/${channelId}/memberships/me`).then(
|
||||
(result) => UserChatChannelMembership.create(result.membership)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes current user unfollow a channel.
|
||||
* @param {number} channelId - The ID of the channel.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
unfollowChannel(channelId) {
|
||||
return this.#deleteRequest(`/channels/${channelId}/memberships/me`).then(
|
||||
(result) => UserChatChannelMembership.create(result.membership)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update notifications settings of current user for a channel.
|
||||
* @param {number} channelId - The ID of the channel.
|
||||
* @param {object} data - The settings to modify.
|
||||
* @param {boolean} [data.muted] - Mutes the channel.
|
||||
* @param {string} [data.desktop_notification_level] - Notifications level on desktop: never, mention or always.
|
||||
* @param {string} [data.mobile_notification_level] - Notifications level on mobile: never, mention or always.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
updateCurrentUserChannelNotificationsSettings(channelId, data = {}) {
|
||||
return this.#putRequest(
|
||||
`/channels/${channelId}/notifications-settings/me`,
|
||||
{ notifications_settings: data }
|
||||
);
|
||||
}
|
||||
|
||||
get #basePath() {
|
||||
return "/chat/api";
|
||||
}
|
||||
|
||||
#getRequest(endpoint, data = {}) {
|
||||
return ajax(`${this.#basePath}${endpoint}`, {
|
||||
type: "GET",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
#putRequest(endpoint, data = {}) {
|
||||
return ajax(`${this.#basePath}${endpoint}`, {
|
||||
type: "PUT",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
#postRequest(endpoint, data = {}) {
|
||||
return ajax(`${this.#basePath}${endpoint}`, {
|
||||
type: "POST",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
#deleteRequest(endpoint, data = {}) {
|
||||
return ajax(`${this.#basePath}${endpoint}`, {
|
||||
type: "DELETE",
|
||||
data,
|
||||
});
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="layout-footer">
|
||||
<div class="container">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.0</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="scripts/prism.dev.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,498 @@
|
|||
:root {
|
||||
--primary-color: #0664a8;
|
||||
--secondary-color: #107e7d;
|
||||
--link-color: var(--primary-color);
|
||||
--link-hover-color: var(--primary-color);
|
||||
--border-color: #eee;
|
||||
--code-color: #666;
|
||||
--code-attention-color: #ca2d00;
|
||||
--text-color: #4a4a4a;
|
||||
--light-font-color: #999;
|
||||
--supporting-color: #7097b5;
|
||||
--heading-color: var(--text-color);
|
||||
--subheading-color: var(--secondary-color);
|
||||
--heading-background: #f7f7f7;
|
||||
--code-bg-color: #f8f8f8;
|
||||
--nav-title-color: var(--primary-color);
|
||||
--nav-title-align: center;
|
||||
--nav-title-size: 1rem;
|
||||
--nav-title-margin-bottom: 1.5em;
|
||||
--nav-title-font-weight: 600;
|
||||
--nav-list-margin-left: 2em;
|
||||
--nav-bg-color: #fff;
|
||||
--nav-heading-display: block;
|
||||
--nav-heading-color: #aaa;
|
||||
--nav-link-color: #666;
|
||||
--nav-text-color: #aaa;
|
||||
--nav-type-class-color: #fff;
|
||||
--nav-type-class-bg: #FF8C00;
|
||||
--nav-type-member-color: #39b739;
|
||||
--nav-type-member-bg: #d5efd5;
|
||||
--nav-type-function-color: #549ab9;
|
||||
--nav-type-function-bg: #e1f6ff;
|
||||
--nav-type-namespace-color: #eb6420;
|
||||
--nav-type-namespace-bg: #fad8c7;
|
||||
--nav-type-typedef-color: #964cb1;
|
||||
--nav-type-typedef-bg: #f2e4f7;
|
||||
--nav-type-module-color: #964cb1;
|
||||
--nav-type-module-bg: #f2e4f7;
|
||||
--nav-type-event-color: #948b34;
|
||||
--nav-type-event-bg: #fff6a6;
|
||||
--max-content-width: 900px;
|
||||
--nav-width: 320px;
|
||||
--padding-unit: 30px;
|
||||
--layout-footer-color: #aaa;
|
||||
--member-name-signature-display: none;
|
||||
--base-font-size: 16px;
|
||||
--base-line-height: 1.7;
|
||||
--body-font: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
--code-font: Consolas, Monaco, "Andale Mono", monospace;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--body-font);
|
||||
font-size: var(--base-font-size);
|
||||
line-height: var(--base-line-height);
|
||||
color: var(--text-color);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--link-color);
|
||||
}
|
||||
a:hover, a:active {
|
||||
text-decoration: underline;
|
||||
color: var(--link-hover-color);
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
img + p {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
tt, code, kbd, samp {
|
||||
font-family: var(--code-font);
|
||||
}
|
||||
|
||||
code {
|
||||
display: inline-block;
|
||||
background-color: var(--code-bg-color);
|
||||
padding: 2px 6px 0px;
|
||||
border-radius: 3px;
|
||||
color: var(--code-attention-color);
|
||||
}
|
||||
|
||||
.prettyprint.source code:not([class*=language-]) {
|
||||
display: block;
|
||||
padding: 20px;
|
||||
overflow: scroll;
|
||||
color: var(--code-color);
|
||||
}
|
||||
|
||||
.layout-main,
|
||||
.layout-footer {
|
||||
margin-left: var(--nav-width);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: var(--max-content-width);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.layout-main {
|
||||
margin-top: var(--padding-unit);
|
||||
margin-bottom: var(--padding-unit);
|
||||
padding: 0 var(--padding-unit);
|
||||
}
|
||||
|
||||
.layout-header {
|
||||
background: var(--nav-bg-color);
|
||||
border-right: 1px solid var(--border-color);
|
||||
position: fixed;
|
||||
padding: 0 var(--padding-unit);
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: var(--nav-width);
|
||||
height: 100%;
|
||||
overflow: scroll;
|
||||
}
|
||||
.layout-header h1 {
|
||||
display: block;
|
||||
margin-bottom: var(--nav-title-margin-bottom);
|
||||
font-size: var(--nav-title-size);
|
||||
font-weight: var(--nav-title-font-weight);
|
||||
text-align: var(--nav-title-align);
|
||||
}
|
||||
.layout-header h1 a:link, .layout-header h1 a:visited {
|
||||
color: var(--nav-title-color);
|
||||
}
|
||||
.layout-header img {
|
||||
max-width: 120px;
|
||||
display: block;
|
||||
margin: 1em auto;
|
||||
}
|
||||
|
||||
.layout-nav {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.layout-nav ul {
|
||||
margin: 0 0 var(--nav-list-margin-left);
|
||||
padding: 0;
|
||||
}
|
||||
.layout-nav li {
|
||||
list-style-type: none;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
.layout-nav li.nav-heading:first-child {
|
||||
display: var(--nav-heading-display);
|
||||
margin-left: 0;
|
||||
margin-bottom: 1em;
|
||||
text-transform: uppercase;
|
||||
color: var(--nav-heading-color);
|
||||
font-size: 0.85em;
|
||||
}
|
||||
.layout-nav a {
|
||||
color: var(--nav-link-color);
|
||||
}
|
||||
.layout-nav a:link, .layout-nav a a:visited {
|
||||
color: var(--nav-link-color);
|
||||
}
|
||||
|
||||
.layout-content--source {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.nav-heading {
|
||||
margin-top: 1em;
|
||||
font-weight: 500;
|
||||
}
|
||||
.nav-heading a {
|
||||
color: var(--nav-link-color);
|
||||
}
|
||||
.nav-heading a:link, .nav-heading a:visited {
|
||||
color: var(--nav-link-color);
|
||||
}
|
||||
.nav-heading .nav-item-type {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.nav-item-type {
|
||||
display: inline-block;
|
||||
font-size: 0.9em;
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
line-height: 1.2em;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
border-radius: 0.2em;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
.nav-item-type.type-class {
|
||||
color: var(--nav-type-class-color);
|
||||
background: var(--nav-type-class-bg);
|
||||
}
|
||||
.nav-item-type.type-typedef {
|
||||
color: var(--nav-type-typedef-color);
|
||||
background: var(--nav-type-typedef-bg);
|
||||
}
|
||||
.nav-item-type.type-function {
|
||||
color: var(--nav-type-function-color);
|
||||
background: var(--nav-type-function-bg);
|
||||
}
|
||||
.nav-item-type.type-namespace {
|
||||
color: var(--nav-type-namespace-color);
|
||||
background: var(--nav-type-namespace-bg);
|
||||
}
|
||||
.nav-item-type.type-member {
|
||||
color: var(--nav-type-member-color);
|
||||
background: var(--nav-type-member-bg);
|
||||
}
|
||||
.nav-item-type.type-module {
|
||||
color: var(--nav-type-module-color);
|
||||
background: var(--nav-type-module-bg);
|
||||
}
|
||||
.nav-item-type.type-event {
|
||||
color: var(--nav-type-event-color);
|
||||
background: var(--nav-type-event-bg);
|
||||
}
|
||||
|
||||
.nav-item-name.is-function:after {
|
||||
display: inline;
|
||||
content: "()";
|
||||
color: var(--nav-link-color);
|
||||
opacity: 0.75;
|
||||
}
|
||||
.nav-item-name.is-class {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.layout-footer {
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
font-size: 0.8em;
|
||||
text-align: center;
|
||||
color: var(--layout-footer-color);
|
||||
}
|
||||
.layout-footer a {
|
||||
color: var(--light-font-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
color: var(--heading-color);
|
||||
}
|
||||
|
||||
h5 {
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
font-size: 1em;
|
||||
}
|
||||
h5 + .code-caption {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.page-kind {
|
||||
margin: 0 0 -0.5em;
|
||||
font-weight: 400;
|
||||
color: var(--light-font-color);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-weight: 600;
|
||||
font-size: 1.5em;
|
||||
color: var(--subheading-color);
|
||||
margin: 1em 0;
|
||||
padding: 0.4em 0;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
.subtitle + .event, .subtitle + .member, .subtitle + .method {
|
||||
border-top: none;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.method-type + .method-name {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.event-name,
|
||||
.member-name,
|
||||
.method-name,
|
||||
.type-definition-name {
|
||||
margin: 1em 0;
|
||||
font-size: 1.4rem;
|
||||
font-family: var(--code-font);
|
||||
font-weight: 600;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.event-name .signature-attributes,
|
||||
.member-name .signature-attributes,
|
||||
.method-name .signature-attributes,
|
||||
.type-definition-name .signature-attributes {
|
||||
display: inline-block;
|
||||
margin-left: 0.25em;
|
||||
font-size: 60%;
|
||||
color: #999;
|
||||
font-style: italic;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.type-signature {
|
||||
display: inline-block;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.member-name .type-signature {
|
||||
display: var(--member-name-signature-display);
|
||||
}
|
||||
|
||||
.type-signature,
|
||||
.return-type-signature {
|
||||
color: #aaa;
|
||||
font-weight: 400;
|
||||
}
|
||||
.type-signature a:link, .type-signature a:visited,
|
||||
.return-type-signature a:link,
|
||||
.return-type-signature a:visited {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
table {
|
||||
margin-top: 1rem;
|
||||
width: auto;
|
||||
min-width: 400px;
|
||||
max-width: 100%;
|
||||
border-top: 1px solid var(--border-color);
|
||||
border-right: 1px solid var(--border-color);
|
||||
}
|
||||
table th, table h4 {
|
||||
font-weight: 500;
|
||||
}
|
||||
table th,
|
||||
table td {
|
||||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
table th,
|
||||
table td {
|
||||
border-left: 1px solid var(--border-color);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
table p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.readme h2 {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
margin: 1em 0;
|
||||
padding-bottom: 0.5rem;
|
||||
color: var(--subheading-color);
|
||||
}
|
||||
.readme h2 + h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.readme h3 {
|
||||
margin: 2rem 0 1rem 0;
|
||||
}
|
||||
|
||||
article.event, article.member, article.method {
|
||||
padding: 1em 0 1em;
|
||||
margin: 1em 0;
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.method-type-signature:not(:empty) {
|
||||
display: inline-block;
|
||||
background: #ecf0f1;
|
||||
color: #627475;
|
||||
padding: 0.25em 0.5em 0.35em;
|
||||
font-weight: 300;
|
||||
font-size: 0.8rem;
|
||||
margin: 0 0.75em 0 0;
|
||||
}
|
||||
|
||||
.method-heading {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
li.method-returns,
|
||||
.method-params li {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.method-source a:link, .method-source a:visited {
|
||||
color: var(--light-font-color);
|
||||
}
|
||||
|
||||
.method-returns p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.event-description,
|
||||
.method-description {
|
||||
margin: 0 0 2em;
|
||||
}
|
||||
|
||||
.param-type code,
|
||||
.method-returns code {
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.param-name {
|
||||
font-weight: 600;
|
||||
display: inline-block;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.param-type,
|
||||
.param-default,
|
||||
.param-attributes {
|
||||
font-family: var(--code-font);
|
||||
}
|
||||
|
||||
.param-default::before {
|
||||
display: inline-block;
|
||||
content: "Default:";
|
||||
font-family: var(--body-font);
|
||||
}
|
||||
|
||||
.param-attributes {
|
||||
color: var(--light-font-color);
|
||||
}
|
||||
|
||||
.param-description p:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.param-properties {
|
||||
font-weight: 500;
|
||||
margin: 1em 0 0;
|
||||
}
|
||||
|
||||
.param-types,
|
||||
.property-types {
|
||||
display: inline-block;
|
||||
margin: 0 0.5em 0 0.25em;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.param-attr,
|
||||
.property-attr {
|
||||
display: inline-block;
|
||||
padding: 0.2em 0.5em;
|
||||
border: 1px solid #eee;
|
||||
color: #aaa;
|
||||
font-weight: 300;
|
||||
font-size: 0.8em;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.properties-table p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
pre[class*=language-] {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
code[class*=language-],
|
||||
pre[class*=language-] {
|
||||
text-shadow: none;
|
||||
border: none;
|
||||
}
|
||||
code[class*=language-].source-page,
|
||||
pre[class*=language-].source-page {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.line-numbers .line-numbers-rows {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.source-page {
|
||||
font-size: 14px;
|
||||
}
|
||||
.source-page code {
|
||||
z-index: 1;
|
||||
}
|
||||
.source-page .line-height.temporary {
|
||||
z-index: 0;
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/* PrismJS 1.17.1
|
||||
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+http */
|
||||
/**
|
||||
* 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;
|
||||
font-size: 1em;
|
||||
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: #f6f8fa;
|
||||
}
|
||||
|
||||
/* 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: #9a6e3a;
|
||||
background: hsla(0, 0%, 100%, .5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.class-name {
|
||||
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;
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="shortcut icon" href="assets/favicon.ico">
|
||||
<link rel="icon" href="assets/favicon.png">
|
||||
<link rel="apple-touch-icon" href="assets/favicon.png">
|
||||
<meta content="en" name="language">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||
<meta name="robots" content="noindex,nofollow,noarchive">
|
||||
<title>Discourse documentation | Discourse - Civilized Discussion</title>
|
||||
<style>
|
||||
body { background: white; }
|
||||
|
||||
* , *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Rubik", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #111;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
h1 a, h1 a:visited {
|
||||
background-image: url(assets/highlight.png);
|
||||
background-size: contain;
|
||||
background-position: bottom;
|
||||
background-repeat: no-repeat;
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a, a:visited {
|
||||
color: rgb(14, 118, 178);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
.site-header-navigation__container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 0 auto;
|
||||
padding: 0 2em;
|
||||
}
|
||||
|
||||
.content-header {
|
||||
text-align: center;
|
||||
margin-bottom: 5em;
|
||||
}
|
||||
|
||||
.content {
|
||||
background-image: url(assets/blobs.svg);
|
||||
background-position: top center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: 600px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.content__wrapper {
|
||||
padding: 0 2em;
|
||||
}
|
||||
|
||||
.projects-list {
|
||||
padding: 2em;
|
||||
border-radius: 15px;
|
||||
position: relative;
|
||||
background-image: url(assets/blob-wide-yellow3.svg);
|
||||
background-position: top center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
min-height: 400px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.projects-list__item {
|
||||
list-style: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header role="banner" class="site-header-navigation">
|
||||
<div class="site-header-navigation__container">
|
||||
<div class="site-header-navigation__logo">
|
||||
<a href="https://discourse.github.io/discourse">
|
||||
<svg width="385" height="104" viewBox="0 0 300 40">
|
||||
<use xlink:href="assets/logo.svg#logo-large"></use>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<header class="content-header">
|
||||
<div class="content__wrapper">
|
||||
<h1><a href="https://www.discourse.org">Discourse</a> projects documentation</h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="content">
|
||||
<div class="content__wrapper">
|
||||
<ul class="projects-list">
|
||||
<li class="projects-list__item">
|
||||
<h4>Chat</h4>
|
||||
<p>
|
||||
<a href="chat/backend/index.html">Backend</a>
|
||||
<span> - </span>
|
||||
<a href="chat/frontend/index.html">Frontend</a>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Order was not deterministic for identic method names defined with @!method
|
||||
# so we sort the list on path instead
|
||||
def generate_method_list
|
||||
@items =
|
||||
prune_method_listing(Registry.all(:method), false)
|
||||
.reject { |m| m.name.to_s =~ /=$/ && m.is_attribute? }
|
||||
.sort_by { |m| m.path }
|
||||
@list_title = "Method List"
|
||||
@list_type = "method"
|
||||
generate_list_contents
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
<%# Removes date and ruby version to avoid differences in CI check %>
|
||||
<div id="footer">
|
||||
Generated by
|
||||
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
||||
<%= YARD::VERSION %>.
|
||||
</div>
|
|
@ -0,0 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
def source
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "fileutils"
|
||||
|
||||
task "documentation" do
|
||||
generate_chat_documentation
|
||||
end
|
||||
|
||||
def generate_chat_documentation
|
||||
destination = File.join(Rails.root, "documentation/chat/frontend/")
|
||||
config = File.join(Rails.root, ".jsdoc")
|
||||
files = %w[
|
||||
plugins/chat/assets/javascripts/discourse/lib/collection.js
|
||||
plugins/chat/assets/javascripts/discourse/pre-initializers/chat-plugin-api.js
|
||||
plugins/chat/assets/javascripts/discourse/services/chat-api.js
|
||||
]
|
||||
`yarn --silent jsdoc --readme plugins/chat/README.md -c #{config} #{files.join(" ")} -d #{destination}`
|
||||
|
||||
# unecessary files
|
||||
%w[
|
||||
documentation/chat/frontend/scripts/prism.min.js
|
||||
documentation/chat/frontend/scripts/prism.js
|
||||
documentation/chat/frontend/styles/vendor/prism-default.css
|
||||
documentation/chat/frontend/styles/vendor/prism-okaidia.css
|
||||
documentation/chat/frontend/styles/vendor/prism-tomorrow-night.css
|
||||
].each { |file| FileUtils.rm(file) }
|
||||
|
||||
require "open3"
|
||||
require "yard"
|
||||
YARD::Templates::Engine.register_template_path(
|
||||
File.join(Rails.root, "documentation", "yard-custom-template"),
|
||||
)
|
||||
files = %w[
|
||||
plugins/chat/app/services/base.rb
|
||||
plugins/chat/app/services/update_user_last_read.rb
|
||||
plugins/chat/app/services/trash_channel.rb
|
||||
plugins/chat/app/services/update_channel.rb
|
||||
plugins/chat/app/services/update_channel_status.rb
|
||||
]
|
||||
cmd =
|
||||
"bundle exec yardoc -p documentation/yard-custom-template -t default -r plugins/chat/README.md --output-dir documentation/chat/backend #{files.join(" ")}"
|
||||
Open3.popen3(cmd) { |_, stderr| puts stderr.read }
|
||||
end
|
|
@ -31,9 +31,10 @@
|
|||
"chrome-launcher": "^0.15.1",
|
||||
"chrome-remote-interface": "^0.31.3",
|
||||
"eslint-config-discourse": "^3.3.0",
|
||||
"jsdoc-to-markdown": "^8.0.0",
|
||||
"jsdoc": "^4.0.0",
|
||||
"lefthook": "^1.2.0",
|
||||
"puppeteer-core": "^13.7.0"
|
||||
"puppeteer-core": "^13.7.0",
|
||||
"tidy-jsdoc": "^1.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "yarn --cwd app/assets/javascripts/discourse $(node -e 'if(JSON.parse(process.env.npm_config_argv).original.includes(`--frozen-lockfile`)){console.log(`--frozen-lockfile`)}')"
|
||||
|
|
|
@ -1,54 +1,9 @@
|
|||
:warning: This plugin is still in active development and may change frequently
|
||||
This plugin is still in active development and may change frequently
|
||||
|
||||
## Documentation
|
||||
|
||||
The Discourse Chat plugin adds chat functionality to your Discourse so it can natively support both long-form and short-form communication needs of your online community.
|
||||
|
||||
For documentation, see [Discourse Chat](https://meta.discourse.org/t/discourse-chat/230881)
|
||||
For user documentation, see [Discourse Chat](https://meta.discourse.org/t/discourse-chat/230881).
|
||||
|
||||
## Plugin API
|
||||
|
||||
### registerChatComposerButton
|
||||
|
||||
#### Usage
|
||||
|
||||
```javascript
|
||||
api.registerChatComposerButton({ id: "foo", ... });
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
Every option accepts a `value` or a `function`, when passing a function `this` will be the `chat-composer` component instance. Example of an option using a function:
|
||||
|
||||
```javascript
|
||||
api.registerChatComposerButton({
|
||||
id: "foo",
|
||||
displayed() {
|
||||
return this.site.mobileView && this.canAttachUploads;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
##### Required
|
||||
|
||||
- `id` unique, used to identify your button, eg: "gifs"
|
||||
- `action` callback when the button is pressed, can be an action name or an anonymous function, eg: "onFooClicked" or `() => { console.log("clicked") }`
|
||||
|
||||
A button requires at least an icon or a label:
|
||||
|
||||
- `icon`, eg: "times"
|
||||
- `label`, text displayed on the button, a translatable key, eg: "foo.bar"
|
||||
- `translatedLabel`, text displayed on the button, a string, eg: "Add gifs"
|
||||
|
||||
##### Optional
|
||||
|
||||
- `position`, can be "inline" or "dropdown", defaults to "inline"
|
||||
- `title`, title attribute of the button, a translatable key, eg: "foo.bar"
|
||||
- `translatedTitle`, title attribute of the button, a string, eg: "Add gifs"
|
||||
- `ariaLabel`, aria-label attribute of the button, a translatable key, eg: "foo.bar"
|
||||
- `translatedAriaLabel`, aria-label attribute of the button, a string, eg: "Add gifs"
|
||||
- `classNames`, additional names to add to the button’s class attribute, eg: ["foo", "bar"]
|
||||
- `displayed`, hide/or show the button, expects a boolean
|
||||
- `disabled`, sets the disabled attribute on the button, expects a boolean
|
||||
- `priority`, an integer defining the order of the buttons, higher comes first, eg: `700`
|
||||
- `dependentKeys`, list of property names which should trigger a refresh of the buttons when changed, eg: `["foo.bar", "bar.baz"]`
|
||||
For developer documentation, see [Discourse Documentation](https://discourse.github.io/discourse/).
|
||||
|
|
|
@ -29,37 +29,9 @@ class Chat::Api::ChatChannelsController < Chat::Api
|
|||
end
|
||||
|
||||
def destroy
|
||||
confirmation = params.require(:channel).require(:name_confirmation)&.downcase
|
||||
guardian.ensure_can_delete_chat_channel!
|
||||
|
||||
if channel_from_params.title(current_user).downcase != confirmation
|
||||
raise Discourse::InvalidParameters.new(:name_confirmation)
|
||||
with_service Chat::Service::TrashChannel do
|
||||
on_model_not_found(:channel) { raise ActiveRecord::RecordNotFound }
|
||||
end
|
||||
|
||||
begin
|
||||
ChatChannel.transaction do
|
||||
channel_from_params.update!(
|
||||
slug:
|
||||
"#{Time.now.strftime("%Y%m%d-%H%M")}-#{channel_from_params.slug}-deleted".truncate(
|
||||
SiteSetting.max_topic_title_length,
|
||||
omission: "",
|
||||
),
|
||||
)
|
||||
channel_from_params.trash!(current_user)
|
||||
StaffActionLogger.new(current_user).log_custom(
|
||||
"chat_channel_delete",
|
||||
{
|
||||
chat_channel_id: channel_from_params.id,
|
||||
chat_channel_name: channel_from_params.title(current_user),
|
||||
},
|
||||
)
|
||||
end
|
||||
rescue ActiveRecord::Rollback
|
||||
return render_json_error(I18n.t("chat.errors.delete_channel_failed"))
|
||||
end
|
||||
|
||||
Jobs.enqueue(:chat_channel_delete, { chat_channel_id: channel_from_params.id })
|
||||
render json: success_json
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -118,38 +90,26 @@ class Chat::Api::ChatChannelsController < Chat::Api
|
|||
end
|
||||
|
||||
def update
|
||||
guardian.ensure_can_edit_chat_channel!
|
||||
|
||||
if channel_from_params.direct_message_channel?
|
||||
raise Discourse::InvalidParameters.new(
|
||||
I18n.t("chat.errors.cant_update_direct_message_channel"),
|
||||
)
|
||||
end
|
||||
|
||||
params_to_edit = editable_params(params, channel_from_params)
|
||||
params_to_edit.each { |k, v| params_to_edit[k] = nil if params_to_edit[k].blank? }
|
||||
|
||||
if ActiveRecord::Type::Boolean.new.deserialize(params_to_edit[:auto_join_users])
|
||||
auto_join_limiter(channel_from_params).performed!
|
||||
end
|
||||
|
||||
channel_from_params.update!(params_to_edit)
|
||||
|
||||
ChatPublisher.publish_chat_channel_edit(channel_from_params, current_user)
|
||||
|
||||
if channel_from_params.category_channel? && channel_from_params.auto_join_users
|
||||
Chat::ChatChannelMembershipManager.new(
|
||||
channel_from_params,
|
||||
).enforce_automatic_channel_memberships
|
||||
end
|
||||
|
||||
with_service(Chat::Service::UpdateChannel, **params_to_edit) do
|
||||
on_success do
|
||||
render_serialized(
|
||||
channel_from_params,
|
||||
result.channel,
|
||||
ChatChannelSerializer,
|
||||
root: "channel",
|
||||
membership: channel_from_params.membership_for(current_user),
|
||||
membership: result.channel.membership_for(current_user),
|
||||
)
|
||||
end
|
||||
on_model_not_found(:channel) { raise ActiveRecord::RecordNotFound }
|
||||
on_failed_policy(:check_channel_permission) { raise Discourse::InvalidAccess }
|
||||
on_failed_policy(:no_direct_message_channel) { raise Discourse::InvalidAccess }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -2,17 +2,10 @@
|
|||
|
||||
class Chat::Api::ChatChannelsStatusController < Chat::Api::ChatChannelsController
|
||||
def update
|
||||
status = params.require(:status)
|
||||
|
||||
# we only want to use this endpoint for open/closed status changes,
|
||||
# the others are more "special" and are handled by the archive endpoint
|
||||
if !ChatChannel.statuses.keys.include?(status) || status == "read_only" || status == "archive"
|
||||
raise Discourse::InvalidParameters
|
||||
end
|
||||
|
||||
guardian.ensure_can_change_channel_status!(channel_from_params, status.to_sym)
|
||||
channel_from_params.public_send("#{status}!", current_user)
|
||||
|
||||
render_serialized(channel_from_params, ChatChannelSerializer, root: "channel")
|
||||
with_service(Chat::Service::UpdateChannelStatus) do
|
||||
on_success { render_serialized(result.channel, ChatChannelSerializer, root: "channel") }
|
||||
on_model_not_found(:channel) { raise ActiveRecord::RecordNotFound }
|
||||
on_failed_policy(:check_channel_permission) { raise Discourse::InvalidAccess }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,8 @@ class Chat::Api < Chat::ChatBaseController
|
|||
before_action :ensure_logged_in
|
||||
before_action :ensure_can_chat
|
||||
|
||||
include Chat::WithServiceHelper
|
||||
|
||||
private
|
||||
|
||||
def ensure_can_chat
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
module Chat
|
||||
module WithServiceHelper
|
||||
def result
|
||||
@_result
|
||||
end
|
||||
|
||||
def with_service(service, default_actions: true, **dependencies, &block)
|
||||
controller = self
|
||||
merged_block =
|
||||
proc do
|
||||
instance_eval(&controller.default_actions_for_service) if default_actions
|
||||
instance_eval(&(block || proc {}))
|
||||
end
|
||||
Chat::Endpoint.call(service, controller, **dependencies, &merged_block)
|
||||
end
|
||||
|
||||
def run_service(service, dependencies)
|
||||
@_result = service.call(params.to_unsafe_h.merge(guardian: guardian, **dependencies.to_h))
|
||||
end
|
||||
|
||||
def default_actions_for_service
|
||||
proc do
|
||||
on_success { render(json: success_json) }
|
||||
on_failure { render(json: failed_json, status: 422) }
|
||||
on_failed_policy(:invalid_access) { raise Discourse::InvalidAccess }
|
||||
on_failed_contract do
|
||||
render(
|
||||
json:
|
||||
failed_json.merge(errors: result[:"result.contract.default"].errors.full_messages),
|
||||
status: 400,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -36,6 +36,10 @@ class ChatChannel < ActiveRecord::Base
|
|||
delegate :empty?, to: :chat_messages, prefix: true
|
||||
|
||||
class << self
|
||||
def editable_statuses
|
||||
statuses.filter { |k, _| !%w[read_only archived].include?(k) }
|
||||
end
|
||||
|
||||
def public_channel_chatable_types
|
||||
["Category"]
|
||||
end
|
||||
|
|
|
@ -0,0 +1,427 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Chat
|
||||
module Service
|
||||
# Module to be included to provide steps DSL to any class. This allows to
|
||||
# create easy to understand services as the whole service cycle is visible
|
||||
# simply by reading the beginning of its class.
|
||||
#
|
||||
# Steps are executed in the order they’re defined. They will use their name
|
||||
# to execute the corresponding method defined in the service class.
|
||||
#
|
||||
# Currently, there are 5 types of steps:
|
||||
#
|
||||
# * +model(name = :model)+: used to instantiate a model (either by building
|
||||
# it or fetching it from the DB). If a falsy value is returned, then the
|
||||
# step will fail. Otherwise the resulting object will be assigned in
|
||||
# +context[name]+ (+context[:model]+ by default).
|
||||
# * +policy(name = :default)+: used to perform a check on the state of the
|
||||
# system. Typically used to run guardians. If a falsy value is returned,
|
||||
# the step will fail.
|
||||
# * +contract(name = :default)+: used to validate the input parameters,
|
||||
# typically provided by a user calling an endpoint. A special embedded
|
||||
# +Contract+ class has to be defined to holds the validations. If the
|
||||
# validations fail, the step will fail. Otherwise, the resulting contract
|
||||
# will be available in +context[:contract]+.
|
||||
# * +step(name)+: used to run small snippets of arbitrary code. The step
|
||||
# doesn’t care about its return value, so to mark the service as failed,
|
||||
# {#fail!} has to be called explicitly.
|
||||
# * +transaction+: used to wrap other steps inside a DB transaction.
|
||||
#
|
||||
# The methods defined on the service are automatically provided with
|
||||
# the whole context passed as keyword arguments. This allows to define in a
|
||||
# very explicit way what dependencies are used by the method. If for
|
||||
# whatever reason a key isn’t found in the current context, then Ruby will
|
||||
# raise an exception when the method is called.
|
||||
#
|
||||
# Regarding contract classes, they have automatically {ActiveModel} modules
|
||||
# included so all the {ActiveModel} API is available.
|
||||
#
|
||||
# @example An example from the {TrashChannel} service
|
||||
# class TrashChannel
|
||||
# include Base
|
||||
#
|
||||
# model :channel, :fetch_channel
|
||||
# policy :invalid_access
|
||||
# transaction do
|
||||
# step :prevents_slug_collision
|
||||
# step :soft_delete_channel
|
||||
# step :log_channel_deletion
|
||||
# end
|
||||
# step :enqueue_delete_channel_relations_job
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def fetch_channel(channel_id:, **)
|
||||
# ChatChannel.find_by(id: channel_id)
|
||||
# end
|
||||
#
|
||||
# def invalid_access(guardian:, channel:, **)
|
||||
# guardian.can_preview_chat_channel?(channel) && guardian.can_delete_chat_channel?
|
||||
# end
|
||||
#
|
||||
# def prevents_slug_collision(channel:, **)
|
||||
# …
|
||||
# end
|
||||
#
|
||||
# def soft_delete_channel(guardian:, channel:, **)
|
||||
# …
|
||||
# end
|
||||
#
|
||||
# def log_channel_deletion(guardian:, channel:, **)
|
||||
# …
|
||||
# end
|
||||
#
|
||||
# def enqueue_delete_channel_relations_job(channel:, **)
|
||||
# …
|
||||
# end
|
||||
# end
|
||||
# @example An example from the {UpdateChannelStatus} service which uses a contract
|
||||
# class UpdateChannelStatus
|
||||
# include Base
|
||||
#
|
||||
# model :channel, :fetch_channel
|
||||
# contract
|
||||
# policy :check_channel_permission
|
||||
# step :change_status
|
||||
#
|
||||
# class Contract
|
||||
# attribute :status
|
||||
# validates :status, inclusion: { in: ChatChannel.editable_statuses.keys }
|
||||
# end
|
||||
#
|
||||
# …
|
||||
# end
|
||||
module Base
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# The only exception that can be raised by a service.
|
||||
class Failure < StandardError
|
||||
# @return [Context]
|
||||
attr_reader :context
|
||||
|
||||
# @!visibility private
|
||||
def initialize(context = nil)
|
||||
@context = context
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
# Simple structure to hold the context of the service during its whole lifecycle.
|
||||
class Context < OpenStruct
|
||||
# @return [Boolean] returns +true+ if the conext is set as successful (default)
|
||||
def success?
|
||||
!failure?
|
||||
end
|
||||
|
||||
# @return [Boolean] returns +true+ if the context is set as failed
|
||||
# @see #fail!
|
||||
# @see #fail
|
||||
def failure?
|
||||
@failure || false
|
||||
end
|
||||
|
||||
# Marks the context as failed.
|
||||
# @param context [Hash, Context] the context to merge into the current one
|
||||
# @example
|
||||
# context.fail!("failure": "something went wrong")
|
||||
# @return [Context]
|
||||
def fail!(context = {})
|
||||
fail(context)
|
||||
raise Failure, self
|
||||
end
|
||||
|
||||
# Marks the context as failed without raising an exception.
|
||||
# @param context [Hash, Context] the context to merge into the current one
|
||||
# @example
|
||||
# context.fail("failure": "something went wrong")
|
||||
# @return [Context]
|
||||
def fail(context = {})
|
||||
merge(context)
|
||||
@failure = true
|
||||
self
|
||||
end
|
||||
|
||||
# Merges the given context into the current one.
|
||||
# @!visibility private
|
||||
def merge(other_context = {})
|
||||
other_context.each { |key, value| self[key.to_sym] = value }
|
||||
self
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.build(context = {})
|
||||
self === context ? context : new(context)
|
||||
end
|
||||
end
|
||||
|
||||
# Internal module to define available steps as DSL
|
||||
# @!visibility private
|
||||
module StepsHelpers
|
||||
def model(name = :model, step_name = :"fetch_#{name}")
|
||||
steps << ModelStep.new(name, step_name)
|
||||
end
|
||||
|
||||
def contract(name = :default, class_name: self::Contract, default_values_from: nil)
|
||||
steps << ContractStep.new(
|
||||
name,
|
||||
class_name: class_name,
|
||||
default_values_from: default_values_from,
|
||||
)
|
||||
end
|
||||
|
||||
def policy(name = :default)
|
||||
steps << PolicyStep.new(name)
|
||||
end
|
||||
|
||||
def step(name)
|
||||
steps << Step.new(name)
|
||||
end
|
||||
|
||||
def transaction(&block)
|
||||
steps << TransactionStep.new(&block)
|
||||
end
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
class Step
|
||||
attr_reader :name, :method_name, :class_name
|
||||
|
||||
def initialize(name, method_name = name, class_name: nil)
|
||||
@name = name
|
||||
@method_name = method_name
|
||||
@class_name = class_name
|
||||
end
|
||||
|
||||
def call(instance, context)
|
||||
method = instance.method(method_name)
|
||||
args = {}
|
||||
args = context.to_h unless method.arity.zero?
|
||||
context[result_key] = Context.build
|
||||
instance.instance_exec(**args, &method)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def type
|
||||
self.class.name.split("::").last.downcase.sub(/^(\w+)step$/, "\\1")
|
||||
end
|
||||
|
||||
def result_key
|
||||
"result.#{type}.#{name}"
|
||||
end
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
class ModelStep < Step
|
||||
def call(instance, context)
|
||||
context[name] = super
|
||||
raise ArgumentError, "Model not found" unless context[name]
|
||||
rescue ArgumentError => exception
|
||||
context[result_key].fail(exception: exception)
|
||||
context.fail!
|
||||
end
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
class PolicyStep < Step
|
||||
def call(instance, context)
|
||||
unless super
|
||||
context[result_key].fail
|
||||
context.fail!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
class ContractStep < Step
|
||||
attr_reader :default_values_from
|
||||
|
||||
def initialize(name, method_name = name, class_name: nil, default_values_from: nil)
|
||||
super(name, method_name, class_name: class_name)
|
||||
@default_values_from = default_values_from
|
||||
end
|
||||
|
||||
def call(instance, context)
|
||||
attributes = class_name.attribute_names.map(&:to_sym)
|
||||
default_values = {}
|
||||
default_values = context[default_values_from].slice(*attributes) if default_values_from
|
||||
contract = class_name.new(default_values.merge(context.to_h.slice(*attributes)))
|
||||
context[contract_name] = contract
|
||||
context[result_key] = Context.build
|
||||
unless contract.valid?
|
||||
context[result_key].fail(errors: contract.errors)
|
||||
context.fail!
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def contract_name
|
||||
return :contract if name.to_sym == :default
|
||||
:"#{name}_contract"
|
||||
end
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
class TransactionStep < Step
|
||||
include StepsHelpers
|
||||
|
||||
attr_reader :steps
|
||||
|
||||
def initialize(&block)
|
||||
@steps = []
|
||||
instance_exec(&block)
|
||||
end
|
||||
|
||||
def call(instance, context)
|
||||
ActiveRecord::Base.transaction { steps.each { |step| step.call(instance, context) } }
|
||||
end
|
||||
end
|
||||
|
||||
included do
|
||||
# The global context which is available from any step.
|
||||
attr_reader :context
|
||||
|
||||
# @!visibility private
|
||||
# Internal class used to setup the base contract of the service.
|
||||
self::Contract =
|
||||
Class.new do
|
||||
include ActiveModel::API
|
||||
include ActiveModel::Attributes
|
||||
include ActiveModel::AttributeMethods
|
||||
include ActiveModel::Validations::Callbacks
|
||||
end
|
||||
end
|
||||
|
||||
class_methods do
|
||||
include StepsHelpers
|
||||
|
||||
def call(context = {})
|
||||
new(context).tap(&:run).context
|
||||
end
|
||||
|
||||
def call!(context = {})
|
||||
new(context).tap(&:run!).context
|
||||
end
|
||||
|
||||
def steps
|
||||
@steps ||= []
|
||||
end
|
||||
end
|
||||
|
||||
# @!scope class
|
||||
# @!method model(name = :model, step_name = :"fetch_#{name}")
|
||||
# @param name [Symbol] name of the model
|
||||
# @param step_name [Symbol] name of the method to call for this step
|
||||
# Evaluates arbitrary code to build or fetch a model (typically from the
|
||||
# DB). If the step returns a falsy value, then the step will fail.
|
||||
#
|
||||
# It stores the resulting model in +context[:model]+ by default (can be
|
||||
# customized by providing the +name+ argument).
|
||||
#
|
||||
# @example
|
||||
# model :channel, :fetch_channel
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def fetch_channel(channel_id:, **)
|
||||
# ChatChannel.find_by(id: channel_id)
|
||||
# end
|
||||
|
||||
# @!scope class
|
||||
# @!method policy(name = :default)
|
||||
# @param name [Symbol] name for this policy
|
||||
# Performs checks related to the state of the system. If the
|
||||
# step doesn’t return a truthy value, then the policy will fail.
|
||||
#
|
||||
# @example
|
||||
# policy :no_direct_message_channel
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def no_direct_message_channel(channel:, **)
|
||||
# !channel.direct_message_channel?
|
||||
# end
|
||||
|
||||
# @!scope class
|
||||
# @!method contract(name = :default, class_name: self::Contract, default_values_from: nil)
|
||||
# @param name [Symbol] name for this contract
|
||||
# @param class_name [Class] a class defining the contract
|
||||
# @param default_values_from [Symbol] name of the model to get default values from
|
||||
# Checks the validity of the input parameters.
|
||||
# Implements ActiveModel::Validations and ActiveModel::Attributes.
|
||||
#
|
||||
# It stores the resulting contract in +context[:contract]+ by default
|
||||
# (can be customized by providing the +name+ argument).
|
||||
#
|
||||
# @example
|
||||
# contract
|
||||
#
|
||||
# class Contract
|
||||
# attribute :name
|
||||
# validates :name, presence: true
|
||||
# end
|
||||
|
||||
# @!scope class
|
||||
# @!method step(name)
|
||||
# @param name [Symbol] the name of this step
|
||||
# Runs arbitrary code. To mark a step as failed, a call to {#fail!} needs
|
||||
# to be made explicitly.
|
||||
#
|
||||
# @example
|
||||
# step :update_channel
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def update_channel(channel:, params_to_edit:, **)
|
||||
# channel.update!(params_to_edit)
|
||||
# end
|
||||
# @example using {#fail!} in a step
|
||||
# step :save_channel
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def save_channel(channel:, **)
|
||||
# fail!("something went wrong") unless channel.save
|
||||
# end
|
||||
|
||||
# @!scope class
|
||||
# @!method transaction(&block)
|
||||
# @param block [Proc] a block containing steps to be run inside a transaction
|
||||
# Runs steps inside a DB transaction.
|
||||
#
|
||||
# @example
|
||||
# transaction do
|
||||
# step :prevents_slug_collision
|
||||
# step :soft_delete_channel
|
||||
# step :log_channel_deletion
|
||||
# end
|
||||
|
||||
# @!visibility private
|
||||
def initialize(initial_context = {})
|
||||
@initial_context = initial_context.with_indifferent_access
|
||||
@context = Context.build(initial_context.merge(__steps__: self.class.steps))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def run
|
||||
run!
|
||||
rescue Failure => exception
|
||||
raise if context.object_id != exception.context.object_id
|
||||
end
|
||||
|
||||
def run!
|
||||
self.class.steps.each { |step| step.call(self, context) }
|
||||
end
|
||||
|
||||
def fail!(message)
|
||||
step_name = caller_locations(1, 1)[0].label
|
||||
context["result.step.#{step_name}"].fail(error: message)
|
||||
context.fail!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,66 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Chat
|
||||
module Service
|
||||
# Service responsible for trashing a chat channel.
|
||||
# Note the slug is modified to prevent collisions.
|
||||
#
|
||||
# @example
|
||||
# Chat::Service::TrashChannel.call(channel_id: 2, guardian: guardian)
|
||||
#
|
||||
class TrashChannel
|
||||
include Base
|
||||
|
||||
# @!method call(channel_id:, guardian:)
|
||||
# @param [Integer] channel_id
|
||||
# @param [Guardian] guardian
|
||||
# @return [Chat::Service::Base::Context]
|
||||
|
||||
DELETE_CHANNEL_LOG_KEY = "chat_channel_delete"
|
||||
|
||||
model :channel, :fetch_channel
|
||||
policy :invalid_access
|
||||
transaction do
|
||||
step :prevents_slug_collision
|
||||
step :soft_delete_channel
|
||||
step :log_channel_deletion
|
||||
end
|
||||
step :enqueue_delete_channel_relations_job
|
||||
|
||||
private
|
||||
|
||||
def fetch_channel(channel_id:, **)
|
||||
ChatChannel.find_by(id: channel_id)
|
||||
end
|
||||
|
||||
def invalid_access(guardian:, channel:, **)
|
||||
guardian.can_preview_chat_channel?(channel) && guardian.can_delete_chat_channel?
|
||||
end
|
||||
|
||||
def prevents_slug_collision(channel:, **)
|
||||
channel.update!(
|
||||
slug:
|
||||
"#{Time.current.strftime("%Y%m%d-%H%M")}-#{channel.slug}-deleted".truncate(
|
||||
SiteSetting.max_topic_title_length,
|
||||
omission: "",
|
||||
),
|
||||
)
|
||||
end
|
||||
|
||||
def soft_delete_channel(guardian:, channel:, **)
|
||||
channel.trash!(guardian.user)
|
||||
end
|
||||
|
||||
def log_channel_deletion(guardian:, channel:, **)
|
||||
StaffActionLogger.new(guardian.user).log_custom(
|
||||
DELETE_CHANNEL_LOG_KEY,
|
||||
{ chat_channel_id: channel.id, chat_channel_name: channel.title(guardian.user) },
|
||||
)
|
||||
end
|
||||
|
||||
def enqueue_delete_channel_relations_job(channel:, **)
|
||||
Jobs.enqueue(:chat_channel_delete, chat_channel_id: channel.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,88 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Chat
|
||||
module Service
|
||||
# Service responsible for updating a chat channel's name, slug, and description.
|
||||
#
|
||||
# For a CategoryChannel, the settings for auto_join_users and allow_channel_wide_mentions
|
||||
# are also editable.
|
||||
#
|
||||
# @example
|
||||
# Chat::Service::UpdateChannel.call(
|
||||
# channel_id: 2,
|
||||
# guardian: guardian,
|
||||
# name: "SuperChannel",
|
||||
# description: "This is the best channel",
|
||||
# slug: "super-channel",
|
||||
# )
|
||||
#
|
||||
class UpdateChannel
|
||||
include Base
|
||||
|
||||
# @!method call(channel_id:, guardian:, **params_to_edit)
|
||||
# @param [Integer] channel_id
|
||||
# @param [Guardian] guardian
|
||||
# @param [Hash] params_to_edit
|
||||
# @option params_to_edit [String,nil] name
|
||||
# @option params_to_edit [String,nil] description
|
||||
# @option params_to_edit [String,nil] slug
|
||||
# @option params_to_edit [Boolean] auto_join_users Only valid for {CategoryChannel}. Whether active users
|
||||
# with permission to see the category should automatically join the channel.
|
||||
# @option params_to_edit [Boolean] allow_channel_wide_mentions Allow the use of @here and @all in the channel.
|
||||
# @return [Chat::Service::Base::Context]
|
||||
|
||||
model :channel, :fetch_channel
|
||||
policy :no_direct_message_channel
|
||||
policy :check_channel_permission
|
||||
contract default_values_from: :channel
|
||||
step :update_channel
|
||||
step :publish_channel_update
|
||||
step :auto_join_users_if_needed
|
||||
|
||||
# @!visibility private
|
||||
class Contract
|
||||
attribute :name, :string
|
||||
attribute :description, :string
|
||||
attribute :slug, :string
|
||||
attribute :auto_join_users, :boolean, default: false
|
||||
attribute :allow_channel_wide_mentions, :boolean, default: true
|
||||
|
||||
before_validation do
|
||||
assign_attributes(
|
||||
attributes
|
||||
.symbolize_keys
|
||||
.slice(:name, :description, :slug)
|
||||
.transform_values(&:presence),
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_channel(channel_id:, **)
|
||||
ChatChannel.find_by(id: channel_id)
|
||||
end
|
||||
|
||||
def no_direct_message_channel(channel:, **)
|
||||
!channel.direct_message_channel?
|
||||
end
|
||||
|
||||
def check_channel_permission(guardian:, channel:, **)
|
||||
guardian.can_preview_chat_channel?(channel) && guardian.can_edit_chat_channel?
|
||||
end
|
||||
|
||||
def update_channel(channel:, contract:, **)
|
||||
channel.update!(contract.attributes)
|
||||
end
|
||||
|
||||
def publish_channel_update(channel:, guardian:, **)
|
||||
ChatPublisher.publish_chat_channel_edit(channel, guardian.user)
|
||||
end
|
||||
|
||||
def auto_join_users_if_needed(channel:, **)
|
||||
return unless channel.auto_join_users?
|
||||
Chat::ChatChannelMembershipManager.new(channel).enforce_automatic_channel_memberships
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,46 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Chat
|
||||
module Service
|
||||
# Service responsible for updating a chat channel status.
|
||||
#
|
||||
# @example
|
||||
# Chat::Service::UpdateChannelStatus.call(channel_id: 2, guardian: guardian, status: "open")
|
||||
#
|
||||
class UpdateChannelStatus
|
||||
include Base
|
||||
|
||||
# @!method call(channel_id:, guardian:, status:)
|
||||
# @param [Integer] channel_id
|
||||
# @param [Guardian] guardian
|
||||
# @param [String] status
|
||||
# @return [Chat::Service::Base::Context]
|
||||
|
||||
model :channel, :fetch_channel
|
||||
contract
|
||||
policy :check_channel_permission
|
||||
step :change_status
|
||||
|
||||
# @!visibility private
|
||||
class Contract
|
||||
attribute :status
|
||||
validates :status, inclusion: { in: ChatChannel.editable_statuses.keys }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_channel(channel_id:, **)
|
||||
ChatChannel.find_by(id: channel_id)
|
||||
end
|
||||
|
||||
def check_channel_permission(guardian:, channel:, status:, **)
|
||||
guardian.can_preview_chat_channel?(channel) &&
|
||||
guardian.can_change_channel_status?(channel, status.to_sym)
|
||||
end
|
||||
|
||||
def change_status(channel:, status:, guardian:, **)
|
||||
channel.public_send("#{status}!", guardian.user)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,79 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Chat
|
||||
module Service
|
||||
# Service responsible for updating the last read message id of a membership.
|
||||
#
|
||||
# @example
|
||||
# Chat::Service::UpdateUserLastRead.call(user_id: 1, channel_id: 2, message_id: 3, guardian: guardian)
|
||||
#
|
||||
class UpdateUserLastRead
|
||||
include Base
|
||||
|
||||
# @!method call(user_id:, channel_id:, message_id:, guardian:)
|
||||
# @param [Integer] user_id
|
||||
# @param [Integer] channel_id
|
||||
# @param [Integer] message_id
|
||||
# @param [Guardian] guardian
|
||||
# @return [Chat::Service::Base::Context]
|
||||
|
||||
model :membership, :fetch_active_membership
|
||||
policy :invalid_access
|
||||
contract
|
||||
policy :ensure_message_id_recency
|
||||
policy :ensure_message_exists
|
||||
step :update_last_read_message_id
|
||||
step :mark_associated_mentions_as_read
|
||||
step :publish_new_last_read_to_clients
|
||||
|
||||
# @!visibility private
|
||||
class Contract
|
||||
attribute :message_id, :integer
|
||||
attribute :user_id, :integer
|
||||
attribute :channel_id, :integer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_active_membership(user_id:, channel_id:, **)
|
||||
UserChatChannelMembership.includes(:user, :chat_channel).find_by(
|
||||
user_id: user_id,
|
||||
chat_channel_id: channel_id,
|
||||
following: true,
|
||||
)
|
||||
end
|
||||
|
||||
def invalid_access(guardian:, membership:, **)
|
||||
guardian.can_join_chat_channel?(membership.chat_channel)
|
||||
end
|
||||
|
||||
def ensure_message_id_recency(message_id:, membership:, **)
|
||||
!membership.last_read_message_id || message_id >= membership.last_read_message_id
|
||||
end
|
||||
|
||||
def ensure_message_exists(channel_id:, message_id:, **)
|
||||
ChatMessage.with_deleted.exists?(chat_channel_id: channel_id, id: message_id)
|
||||
end
|
||||
|
||||
def update_last_read_message_id(message_id:, membership:, **)
|
||||
membership.update!(last_read_message_id: message_id)
|
||||
end
|
||||
|
||||
def mark_associated_mentions_as_read(membership:, message_id:, **)
|
||||
Notification
|
||||
.where(notification_type: Notification.types[:chat_mention])
|
||||
.where(user: membership.user)
|
||||
.where(read: false)
|
||||
.joins("INNER JOIN chat_mentions ON chat_mentions.notification_id = notifications.id")
|
||||
.joins("INNER JOIN chat_messages ON chat_mentions.chat_message_id = chat_messages.id")
|
||||
.where("chat_messages.id <= ?", message_id)
|
||||
.where("chat_messages.chat_channel_id = ?", membership.chat_channel.id)
|
||||
.update_all(read: true)
|
||||
end
|
||||
|
||||
def publish_new_last_read_to_clients(guardian:, channel_id:, message_id:, **)
|
||||
ChatPublisher.publish_user_tracking_state(guardian.user, channel_id, message_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +1,3 @@
|
|||
/** @module Collection */
|
||||
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
|
@ -7,19 +5,12 @@ import { Promise } from "rsvp";
|
|||
|
||||
/**
|
||||
* Handles a paginated API response.
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
export default class Collection {
|
||||
@tracked items = [];
|
||||
@tracked meta = {};
|
||||
@tracked loading = false;
|
||||
|
||||
/**
|
||||
* Create a Collection instance
|
||||
* @param {string} resourceURL - the API endpoint to call
|
||||
* @param {callback} handler - anonymous function used to handle the response
|
||||
*/
|
||||
constructor(resourceURL, handler) {
|
||||
this._resourceURL = resourceURL;
|
||||
this._handler = handler;
|
||||
|
|
|
@ -5,6 +5,66 @@ import {
|
|||
} from "discourse/plugins/chat/discourse/components/chat-message";
|
||||
import { registerChatComposerButton } from "discourse/plugins/chat/discourse/lib/chat-composer-buttons";
|
||||
|
||||
/**
|
||||
* Class exposing the javascript API available to plugins and themes.
|
||||
* @class PluginApi
|
||||
*/
|
||||
|
||||
/**
|
||||
* Callback used to decorate a chat message
|
||||
*
|
||||
* @callback PluginApi~decorateChatMessageCallback
|
||||
* @param {ChatMessage} chatMessage - model
|
||||
* @param {HTMLElement} messageContainer - DOM node
|
||||
* @param {ChatChannel} chatChannel - model
|
||||
*/
|
||||
|
||||
/**
|
||||
* Decorate a chat message
|
||||
*
|
||||
* @memberof PluginApi
|
||||
* @instance
|
||||
* @function decorateChatMessage
|
||||
* @param {PluginApi~decorateChatMessageCallback} decorator
|
||||
* @example
|
||||
*
|
||||
* api.decorateChatMessage((chatMessage, messageContainer) => {
|
||||
* messageContainer.dataset.foo = chatMessage.id;
|
||||
* });
|
||||
*/
|
||||
|
||||
/**
|
||||
* Register a button in the chat composer
|
||||
*
|
||||
* @memberof PluginApi
|
||||
* @instance
|
||||
* @function registerChatComposerButton
|
||||
* @param {Object} options
|
||||
* @param {number} options.id - The id of the button
|
||||
* @param {function} options.action - An action name or an anonymous function called when the button is pressed, eg: "onFooClicked" or `() => { console.log("clicked") }`
|
||||
* @param {string} options.icon - A valid font awesome icon name, eg: "far fa-image"
|
||||
* @param {string} options.label - Text displayed on the button, a translatable key, eg: "foo.bar"
|
||||
* @param {string} options.translatedLabel - Text displayed on the button, a string, eg: "Add gifs"
|
||||
* @param {string} [options.position] - Can be "inline" or "dropdown", defaults to "inline"
|
||||
* @param {string} [options.title] - Title attribute of the button, a translatable key, eg: "foo.bar"
|
||||
* @param {string} [options.translatedTitle] - Title attribute of the button, a string, eg: "Add gifs"
|
||||
* @param {string} [options.ariaLabel] - aria-label attribute of the button, a translatable key, eg: "foo.bar"
|
||||
* @param {string} [options.translatedAriaLabel] - aria-label attribute of the button, a string, eg: "Add gifs"
|
||||
* @param {string} [options.classNames] - Additional names to add to the button’s class attribute, eg: ["foo", "bar"]
|
||||
* @param {boolean} [options.displayed] - Hide or show the button
|
||||
* @param {boolean} [options.disabled] - Sets the disabled attribute on the button
|
||||
* @param {number} [options.priority] - An integer defining the order of the buttons, higher comes first, eg: `700`
|
||||
* @param {Array.<string>} [options.dependentKeys] - List of property names which should trigger a refresh of the buttons when changed, eg: `["foo.bar", "bar.baz"]`
|
||||
* @example
|
||||
*
|
||||
* api.registerChatComposerButton({
|
||||
* id: "foo",
|
||||
* displayed() {
|
||||
* return this.site.mobileView && this.canAttachUploads;
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: "chat-plugin-api",
|
||||
after: "inject-discourse-objects",
|
||||
|
|
|
@ -14,7 +14,8 @@ export default function withChatChannel(extendedClass) {
|
|||
this.controllerFor("chat-channel").set("targetMessageId", null);
|
||||
this.chat.activeChannel = model;
|
||||
|
||||
let { messageId } = this.paramsFor(this.routeName);
|
||||
let { messageId, channelTitle } = this.paramsFor(this.routeName);
|
||||
|
||||
// messageId query param backwards-compatibility
|
||||
if (messageId) {
|
||||
this.router.replaceWith(
|
||||
|
@ -24,7 +25,6 @@ export default function withChatChannel(extendedClass) {
|
|||
);
|
||||
}
|
||||
|
||||
const { channelTitle } = this.paramsFor("chat.channel");
|
||||
if (channelTitle && channelTitle !== model.slugifiedTitle) {
|
||||
const nearMessageParams = this.paramsFor("chat.channel.near-message");
|
||||
if (nearMessageParams.messageId) {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/** @module ChatApi */
|
||||
|
||||
import Service, { inject as service } from "@ember/service";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import UserChatChannelMembership from "discourse/plugins/chat/discourse/models/user-chat-channel-membership";
|
||||
|
@ -8,7 +6,7 @@ import Collection from "../lib/collection";
|
|||
/**
|
||||
* Chat API service. Provides methods to interact with the chat API.
|
||||
*
|
||||
* @class
|
||||
* @module ChatApi
|
||||
* @implements {@ember/service}
|
||||
*/
|
||||
export default class ChatApi extends Service {
|
||||
|
@ -31,7 +29,7 @@ export default class ChatApi extends Service {
|
|||
|
||||
/**
|
||||
* List all accessible category channels of the current user.
|
||||
* @returns {module:Collection}
|
||||
* @returns {Collection}
|
||||
*
|
||||
* @example
|
||||
*
|
||||
|
@ -70,17 +68,14 @@ export default class ChatApi extends Service {
|
|||
/**
|
||||
* Destroys a channel.
|
||||
* @param {number} channelId - The ID of the channel.
|
||||
* @param {string} channelName - The name of the channel to be destroyed, used as confirmation.
|
||||
* @returns {Promise}
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* this.chatApi.destroyChannel(1, "foo").then(() => { ... })
|
||||
* this.chatApi.destroyChannel(1).then(() => { ... })
|
||||
*/
|
||||
destroyChannel(channelId, channelName) {
|
||||
return this.#deleteRequest(`/channels/${channelId}`, {
|
||||
channel: { name_confirmation: channelName },
|
||||
});
|
||||
destroyChannel(channelId) {
|
||||
return this.#deleteRequest(`/channels/${channelId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -174,7 +169,7 @@ export default class ChatApi extends Service {
|
|||
/**
|
||||
* Lists members of a channel.
|
||||
* @param {number} channelId - The ID of the channel.
|
||||
* @returns {module:Collection}
|
||||
* @returns {Collection}
|
||||
*/
|
||||
listChannelMemberships(channelId) {
|
||||
return new Collection(
|
||||
|
|
|
@ -1,352 +0,0 @@
|
|||
## Modules
|
||||
|
||||
<dl>
|
||||
<dt><a href="#module_Collection">Collection</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#module_ChatApi">ChatApi</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
<a name="module_Collection"></a>
|
||||
|
||||
## Collection
|
||||
|
||||
* [Collection](#module_Collection)
|
||||
* [module.exports](#exp_module_Collection--module.exports) ⏏
|
||||
* [new module.exports(resourceURL, handler)](#new_module_Collection--module.exports_new)
|
||||
* [.load()](#module_Collection--module.exports+load) ⇒ <code>Promise</code>
|
||||
* [.loadMore()](#module_Collection--module.exports+loadMore) ⇒ <code>Promise</code>
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
<a name="exp_module_Collection--module.exports"></a>
|
||||
|
||||
### module.exports ⏏
|
||||
Handles a paginated API response.
|
||||
|
||||
**Kind**: Exported class
|
||||
|
||||
* * *
|
||||
|
||||
<a name="new_module_Collection--module.exports_new"></a>
|
||||
|
||||
#### new module.exports(resourceURL, handler)
|
||||
Create a Collection instance
|
||||
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| resourceURL | <code>string</code> | the API endpoint to call |
|
||||
| handler | <code>callback</code> | anonymous function used to handle the response |
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_Collection--module.exports+load"></a>
|
||||
|
||||
#### module.exports.load() ⇒ <code>Promise</code>
|
||||
Loads first batch of results
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_Collection--module.exports)
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_Collection--module.exports+loadMore"></a>
|
||||
|
||||
#### module.exports.loadMore() ⇒ <code>Promise</code>
|
||||
Attempts to load more results
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_Collection--module.exports)
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi"></a>
|
||||
|
||||
## ChatApi
|
||||
|
||||
* [ChatApi](#module_ChatApi)
|
||||
* [module.exports](#exp_module_ChatApi--module.exports) ⏏
|
||||
* [.channel(channelId)](#module_ChatApi--module.exports+channel) ⇒ <code>Promise</code>
|
||||
* [.channels()](#module_ChatApi--module.exports+channels) ⇒ [<code>module.exports</code>](#exp_module_Collection--module.exports)
|
||||
* [.moveChannelMessages(channelId, data)](#module_ChatApi--module.exports+moveChannelMessages) ⇒ <code>Promise</code>
|
||||
* [.destroyChannel(channelId, channelName)](#module_ChatApi--module.exports+destroyChannel) ⇒ <code>Promise</code>
|
||||
* [.createChannel(data)](#module_ChatApi--module.exports+createChannel) ⇒ <code>Promise</code>
|
||||
* [.categoryPermissions(categoryId)](#module_ChatApi--module.exports+categoryPermissions) ⇒ <code>Promise</code>
|
||||
* [.sendMessage(channelId, data)](#module_ChatApi--module.exports+sendMessage) ⇒ <code>Promise</code>
|
||||
* [.createChannelArchive(channelId, data)](#module_ChatApi--module.exports+createChannelArchive) ⇒ <code>Promise</code>
|
||||
* [.updateChannel(channelId, data)](#module_ChatApi--module.exports+updateChannel) ⇒ <code>Promise</code>
|
||||
* [.updateChannelStatus(channelId, status)](#module_ChatApi--module.exports+updateChannelStatus) ⇒ <code>Promise</code>
|
||||
* [.listChannelMemberships(channelId)](#module_ChatApi--module.exports+listChannelMemberships) ⇒ [<code>module.exports</code>](#exp_module_Collection--module.exports)
|
||||
* [.listCurrentUserChannels()](#module_ChatApi--module.exports+listCurrentUserChannels) ⇒ <code>Promise</code>
|
||||
* [.followChannel(channelId)](#module_ChatApi--module.exports+followChannel) ⇒ <code>Promise</code>
|
||||
* [.unfollowChannel(channelId)](#module_ChatApi--module.exports+unfollowChannel) ⇒ <code>Promise</code>
|
||||
* [.updateCurrentUserChannelNotificationsSettings(channelId, data)](#module_ChatApi--module.exports+updateCurrentUserChannelNotificationsSettings) ⇒ <code>Promise</code>
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
<a name="exp_module_ChatApi--module.exports"></a>
|
||||
|
||||
### module.exports ⏏
|
||||
Chat API service. Provides methods to interact with the chat API.
|
||||
|
||||
**Kind**: Exported class
|
||||
**Implements**: <code>{@ember/service}</code>
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+channel"></a>
|
||||
|
||||
#### module.exports.channel(channelId) ⇒ <code>Promise</code>
|
||||
Get a channel by its ID.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| channelId | <code>number</code> | The ID of the channel. |
|
||||
|
||||
**Example**
|
||||
```js
|
||||
this.chatApi.channel(1).then(channel => { ... })
|
||||
```
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+channels"></a>
|
||||
|
||||
#### module.exports.channels() ⇒ [<code>module.exports</code>](#exp_module_Collection--module.exports)
|
||||
List all accessible category channels of the current user.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
**Example**
|
||||
```js
|
||||
this.chatApi.channels.then(channels => { ... })
|
||||
```
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+moveChannelMessages"></a>
|
||||
|
||||
#### module.exports.moveChannelMessages(channelId, data) ⇒ <code>Promise</code>
|
||||
Moves messages from one channel to another.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| channelId | <code>number</code> | The ID of the original channel. |
|
||||
| data | <code>object</code> | Params of the move. |
|
||||
| data.message_ids | <code>Array.<number></code> | IDs of the moved messages. |
|
||||
| data.destination_channel_id | <code>number</code> | ID of the channel where the messages are moved to. |
|
||||
|
||||
**Example**
|
||||
```js
|
||||
this.chatApi
|
||||
.moveChannelMessages(1, {
|
||||
message_ids: [2, 3],
|
||||
destination_channel_id: 4,
|
||||
}).then(() => { ... })
|
||||
```
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+destroyChannel"></a>
|
||||
|
||||
#### module.exports.destroyChannel(channelId, channelName) ⇒ <code>Promise</code>
|
||||
Destroys a channel.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| channelId | <code>number</code> | The ID of the channel. |
|
||||
| channelName | <code>string</code> | The name of the channel to be destroyed, used as confirmation. |
|
||||
|
||||
**Example**
|
||||
```js
|
||||
this.chatApi.destroyChannel(1, "foo").then(() => { ... })
|
||||
```
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+createChannel"></a>
|
||||
|
||||
#### module.exports.createChannel(data) ⇒ <code>Promise</code>
|
||||
Creates a channel.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| data | <code>object</code> | Params of the channel. |
|
||||
| data.name | <code>string</code> | The name of the channel. |
|
||||
| data.chatable_id | <code>string</code> | The category of the channel. |
|
||||
| data.description | <code>string</code> | The description of the channel. |
|
||||
| [data.auto_join_users] | <code>boolean</code> | Should users join this channel automatically. |
|
||||
|
||||
**Example**
|
||||
```js
|
||||
this.chatApi
|
||||
.createChannel({ name: "foo", chatable_id: 1, description "bar" })
|
||||
.then((channel) => { ... })
|
||||
```
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+categoryPermissions"></a>
|
||||
|
||||
#### module.exports.categoryPermissions(categoryId) ⇒ <code>Promise</code>
|
||||
Lists chat permissions for a category.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| categoryId | <code>number</code> | ID of the category. |
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+sendMessage"></a>
|
||||
|
||||
#### module.exports.sendMessage(channelId, data) ⇒ <code>Promise</code>
|
||||
Sends a message.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| channelId | <code>number</code> | ID of the channel. |
|
||||
| data | <code>object</code> | Params of the message. |
|
||||
| data.message | <code>string</code> | The raw content of the message in markdown. |
|
||||
| data.cooked | <code>string</code> | The cooked content of the message. |
|
||||
| [data.in_reply_to_id] | <code>number</code> | The ID of the replied-to message. |
|
||||
| [data.staged_id] | <code>number</code> | The staged ID of the message before it was persisted. |
|
||||
| [data.upload_ids] | <code>Array.<number></code> | Array of upload ids linked to the message. |
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+createChannelArchive"></a>
|
||||
|
||||
#### module.exports.createChannelArchive(channelId, data) ⇒ <code>Promise</code>
|
||||
Creates a channel archive.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| channelId | <code>number</code> | The ID of the channel. |
|
||||
| data | <code>object</code> | Params of the archive. |
|
||||
| data.selection | <code>string</code> | "new_topic" or "existing_topic". |
|
||||
| [data.title] | <code>string</code> | Title of the topic when creating a new topic. |
|
||||
| [data.category_id] | <code>string</code> | ID of the category used when creating a new topic. |
|
||||
| [data.tags] | <code>Array.<string></code> | tags used when creating a new topic. |
|
||||
| [data.topic_id] | <code>string</code> | ID of the topic when using an existing topic. |
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+updateChannel"></a>
|
||||
|
||||
#### module.exports.updateChannel(channelId, data) ⇒ <code>Promise</code>
|
||||
Updates a channel.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| channelId | <code>number</code> | The ID of the channel. |
|
||||
| data | <code>object</code> | Params of the archive. |
|
||||
| [data.description] | <code>string</code> | Description of the channel. |
|
||||
| [data.name] | <code>string</code> | Name of the channel. |
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+updateChannelStatus"></a>
|
||||
|
||||
#### module.exports.updateChannelStatus(channelId, status) ⇒ <code>Promise</code>
|
||||
Updates the status of a channel.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| channelId | <code>number</code> | The ID of the channel. |
|
||||
| status | <code>string</code> | The new status, can be "open" or "closed". |
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+listChannelMemberships"></a>
|
||||
|
||||
#### module.exports.listChannelMemberships(channelId) ⇒ [<code>module.exports</code>](#exp_module_Collection--module.exports)
|
||||
Lists members of a channel.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| channelId | <code>number</code> | The ID of the channel. |
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+listCurrentUserChannels"></a>
|
||||
|
||||
#### module.exports.listCurrentUserChannels() ⇒ <code>Promise</code>
|
||||
Lists public and direct message channels of the current user.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+followChannel"></a>
|
||||
|
||||
#### module.exports.followChannel(channelId) ⇒ <code>Promise</code>
|
||||
Makes current user follow a channel.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| channelId | <code>number</code> | The ID of the channel. |
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+unfollowChannel"></a>
|
||||
|
||||
#### module.exports.unfollowChannel(channelId) ⇒ <code>Promise</code>
|
||||
Makes current user unfollow a channel.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| channelId | <code>number</code> | The ID of the channel. |
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
<a name="module_ChatApi--module.exports+updateCurrentUserChannelNotificationsSettings"></a>
|
||||
|
||||
#### module.exports.updateCurrentUserChannelNotificationsSettings(channelId, data) ⇒ <code>Promise</code>
|
||||
Update notifications settings of current user for a channel.
|
||||
|
||||
**Kind**: instance method of [<code>module.exports</code>](#exp_module_ChatApi--module.exports)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| channelId | <code>number</code> | The ID of the channel. |
|
||||
| data | <code>object</code> | The settings to modify. |
|
||||
| [data.muted] | <code>boolean</code> | Mutes the channel. |
|
||||
| [data.desktop_notification_level] | <code>string</code> | Notifications level on desktop: never, mention or always. |
|
||||
| [data.mobile_notification_level] | <code>string</code> | Notifications level on mobile: never, mention or always. |
|
||||
|
||||
|
||||
* * *
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
# frozen_string_literal: true
|
||||
#
|
||||
# = Chat::Endpoint
|
||||
#
|
||||
# This class is to be used via its helper +with_service+ in a controller. Its
|
||||
# main purpose is to ease how actions can be run upon a service completion.
|
||||
# Since a service will likely return the same kind of things over and over,
|
||||
# this allows us to not have to repeat the same boilerplate code in every
|
||||
# controller.
|
||||
#
|
||||
# There are several available actions and we can add new ones very easily:
|
||||
#
|
||||
# * +on_success+: will execute the provided block if the service succeeds
|
||||
# * +on_failure+: will execute the provided block if the service fails
|
||||
# * +on_failed_policy(name)+: will execute the provided block if the policy
|
||||
# named `name` fails
|
||||
# * +on_failed_contract(name)+: will execute the provided block if the contract
|
||||
# named `name` fails
|
||||
# * +on_model_not_found(name)+: will execute the provided block if the service
|
||||
# fails and its model is not present
|
||||
#
|
||||
# @example
|
||||
# # in a controller
|
||||
# def create
|
||||
# with_service MyService do
|
||||
# on_success do
|
||||
# flash[:notice] = "Success!"
|
||||
# redirect_to a_path
|
||||
# end
|
||||
# on_failed_policy(:a_named_policy) { redirect_to root_path }
|
||||
# on_failure { render :new }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# The actions will be evaluated in the order they appear. So even if the
|
||||
# service will ultimately fail with a failed policy, in this example only the
|
||||
# +on_failed_policy+ action will be executed and not the +on_failure+ one.
|
||||
# The only exception to this being +on_failure+ as it will always be executed
|
||||
# last.
|
||||
#
|
||||
class Chat::Endpoint
|
||||
# @!visibility private
|
||||
NULL_RESULT = OpenStruct.new(failure?: false)
|
||||
# @!visibility private
|
||||
AVAILABLE_ACTIONS = {
|
||||
on_success: -> { result.success? },
|
||||
on_failure: -> { result.failure? },
|
||||
on_failed_policy: ->(name = "default") { failure_for?("result.policy.#{name}") },
|
||||
on_failed_contract: ->(name = "default") { failure_for?("result.contract.#{name}") },
|
||||
on_model_not_found: ->(name = "model") { failure_for?("result.model.#{name}") },
|
||||
}.with_indifferent_access.freeze
|
||||
|
||||
# @!visibility private
|
||||
attr_reader :service, :controller, :dependencies
|
||||
|
||||
delegate :result, to: :controller
|
||||
|
||||
# @!visibility private
|
||||
def initialize(service, controller, **dependencies)
|
||||
@service = service
|
||||
@controller = controller
|
||||
@dependencies = dependencies
|
||||
@actions = {}
|
||||
end
|
||||
|
||||
# @param service [Class] a class including {Chat::Service::Base}
|
||||
# @param block [Proc] a block containing the steps to match on
|
||||
# @return [void]
|
||||
def self.call(service, controller, **dependencies, &block)
|
||||
new(service, controller, **dependencies).call(&block)
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
def call(&block)
|
||||
instance_eval(&block)
|
||||
controller.run_service(service, dependencies)
|
||||
# Always have `on_failure` as the last action
|
||||
(
|
||||
actions
|
||||
.except(:on_failure)
|
||||
.merge(actions.slice(:on_failure))
|
||||
.detect { |name, (condition, _)| condition.call } || [-> {}]
|
||||
).flatten.last.call
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :actions
|
||||
|
||||
def failure_for?(key)
|
||||
(controller.result[key] || NULL_RESULT).failure?
|
||||
end
|
||||
|
||||
def add_action(name, *args, &block)
|
||||
actions[[name, *args].join("_").to_sym] = [
|
||||
-> { instance_exec(*args, &AVAILABLE_ACTIONS[name]) },
|
||||
-> { controller.instance_eval(&block) },
|
||||
]
|
||||
end
|
||||
|
||||
def method_missing(method_name, *args, &block)
|
||||
return super unless AVAILABLE_ACTIONS[method_name]
|
||||
add_action(method_name, *args, &block)
|
||||
end
|
||||
|
||||
def respond_to_missing?(method_name, include_private = false)
|
||||
AVAILABLE_ACTIONS[method_name] || super
|
||||
end
|
||||
end
|
|
@ -61,6 +61,7 @@ module Chat::GuardianExtensions
|
|||
return false if chat_channel.status.to_sym == target_status.to_sym
|
||||
return false if !is_staff?
|
||||
|
||||
# FIXME: This logic shouldn't be handled in guardian
|
||||
case target_status
|
||||
when :closed
|
||||
chat_channel.open?
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Chat
|
||||
# = Chat::StepsInspector
|
||||
#
|
||||
# This class takes a {Chat::Service::Base::Context} object and inspects it.
|
||||
# It will output a list of steps and what is their known state.
|
||||
class StepsInspector
|
||||
# @!visibility private
|
||||
class Step
|
||||
attr_reader :step, :result, :nesting_level
|
||||
|
||||
delegate :name, to: :step
|
||||
delegate :failure?, :success?, :error, to: :step_result, allow_nil: true
|
||||
|
||||
def self.for(step, result, nesting_level: 0)
|
||||
class_name =
|
||||
"#{module_parent_name}::#{step.class.name.split("::").last.sub(/^(\w+)Step$/, "\\1")}"
|
||||
class_name.constantize.new(step, result, nesting_level: nesting_level)
|
||||
end
|
||||
|
||||
def initialize(step, result, nesting_level: 0)
|
||||
@step = step
|
||||
@result = result
|
||||
@nesting_level = nesting_level
|
||||
end
|
||||
|
||||
def type
|
||||
self.class.name.split("::").last.downcase
|
||||
end
|
||||
|
||||
def emoji
|
||||
return "❌" if failure?
|
||||
return "✅" if success?
|
||||
""
|
||||
end
|
||||
|
||||
def steps
|
||||
[self]
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#{" " * nesting_level}[#{type}] '#{name}' #{emoji}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def step_result
|
||||
result["result.#{type}.#{name}"]
|
||||
end
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
class Model < Step
|
||||
def error
|
||||
step_result.exception.full_message
|
||||
end
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
class Contract < Step
|
||||
def error
|
||||
step_result.errors.inspect
|
||||
end
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
class Policy < Step
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
class Transaction < Step
|
||||
def steps
|
||||
[self, *step.steps.map { Step.for(_1, result, nesting_level: nesting_level + 1).steps }]
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#{" " * nesting_level}[#{type}]"
|
||||
end
|
||||
|
||||
def step_result
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :steps, :result
|
||||
|
||||
def initialize(result)
|
||||
@steps = result.__steps__.map { Step.for(_1, result).steps }.flatten
|
||||
@result = result
|
||||
end
|
||||
|
||||
# Inspect the provided result object.
|
||||
# Example output:
|
||||
# [1/4] [model] 'channel' ✅
|
||||
# [2/4] [contract] 'default' ✅
|
||||
# [3/4] [policy] 'check_channel_permission' ❌
|
||||
# [4/4] [step] 'change_status'
|
||||
# @return [String] the steps of the result object with their state
|
||||
def inspect
|
||||
steps
|
||||
.map
|
||||
.with_index { |step, index| "[#{index + 1}/#{steps.size}] #{step.inspect}" }
|
||||
.join("\n")
|
||||
end
|
||||
|
||||
# @return [String, nil] the first available error, if any.
|
||||
def error
|
||||
steps.detect(&:failure?)&.error
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,13 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
task "chat:doc" do
|
||||
destination = File.join(Rails.root, "plugins/chat/docs/FRONTEND.md")
|
||||
config = File.join(Rails.root, ".jsdoc")
|
||||
|
||||
files = %w[
|
||||
plugins/chat/assets/javascripts/discourse/lib/collection.js
|
||||
plugins/chat/assets/javascripts/discourse/services/chat-api.js
|
||||
]
|
||||
|
||||
`yarn --silent jsdoc2md --separators -c #{config} -f #{files.join(" ")} > #{destination}`
|
||||
end
|
|
@ -91,6 +91,7 @@ require_relative "app/core_ext/plugin_instance.rb"
|
|||
GlobalSetting.add_default(:allow_unsecure_chat_uploads, false)
|
||||
|
||||
after_initialize do
|
||||
# Namespace for classes and modules parts of chat plugin
|
||||
module ::Chat
|
||||
PLUGIN_NAME = "chat"
|
||||
HAS_CHAT_ENABLED = "has_chat_enabled"
|
||||
|
@ -119,6 +120,7 @@ after_initialize do
|
|||
"../app/controllers/admin/admin_incoming_chat_webhooks_controller.rb",
|
||||
__FILE__,
|
||||
)
|
||||
load File.expand_path("../app/helpers/with_service_helper.rb", __FILE__)
|
||||
load File.expand_path("../app/controllers/chat_base_controller.rb", __FILE__)
|
||||
load File.expand_path("../app/controllers/chat_controller.rb", __FILE__)
|
||||
load File.expand_path("../app/controllers/emojis_controller.rb", __FILE__)
|
||||
|
@ -163,6 +165,7 @@ after_initialize do
|
|||
load File.expand_path("../app/serializers/admin_chat_index_serializer.rb", __FILE__)
|
||||
load File.expand_path("../app/serializers/user_chat_message_bookmark_serializer.rb", __FILE__)
|
||||
load File.expand_path("../app/serializers/reviewable_chat_message_serializer.rb", __FILE__)
|
||||
load File.expand_path("../app/services/base.rb", __FILE__)
|
||||
load File.expand_path("../lib/chat_channel_fetcher.rb", __FILE__)
|
||||
load File.expand_path("../lib/chat_channel_hashtag_data_source.rb", __FILE__)
|
||||
load File.expand_path("../lib/chat_mailer.rb", __FILE__)
|
||||
|
@ -191,6 +194,8 @@ after_initialize do
|
|||
load File.expand_path("../lib/slack_compatibility.rb", __FILE__)
|
||||
load File.expand_path("../lib/post_notification_handler.rb", __FILE__)
|
||||
load File.expand_path("../lib/secure_uploads_compatibility.rb", __FILE__)
|
||||
load File.expand_path("../lib/endpoint.rb", __FILE__)
|
||||
load File.expand_path("../lib/steps_inspector.rb", __FILE__)
|
||||
load File.expand_path("../app/jobs/regular/auto_manage_channel_memberships.rb", __FILE__)
|
||||
load File.expand_path("../app/jobs/regular/auto_join_channel_batch.rb", __FILE__)
|
||||
load File.expand_path("../app/jobs/regular/process_chat_message.rb", __FILE__)
|
||||
|
@ -207,7 +212,11 @@ after_initialize do
|
|||
load File.expand_path("../app/jobs/scheduled/auto_join_users.rb", __FILE__)
|
||||
load File.expand_path("../app/jobs/scheduled/chat_periodical_updates.rb", __FILE__)
|
||||
load File.expand_path("../app/services/chat_publisher.rb", __FILE__)
|
||||
load File.expand_path("../app/services/trash_channel.rb", __FILE__)
|
||||
load File.expand_path("../app/services/update_channel.rb", __FILE__)
|
||||
load File.expand_path("../app/services/update_channel_status.rb", __FILE__)
|
||||
load File.expand_path("../app/services/chat_message_destroyer.rb", __FILE__)
|
||||
load File.expand_path("../app/services/update_user_last_read.rb", __FILE__)
|
||||
load File.expand_path("../app/controllers/api_controller.rb", __FILE__)
|
||||
load File.expand_path("../app/controllers/api/chat_channels_controller.rb", __FILE__)
|
||||
load File.expand_path("../app/controllers/api/chat_current_user_channels_controller.rb", __FILE__)
|
||||
|
|
|
@ -59,9 +59,50 @@ Fabricator(:chat_message) do
|
|||
end
|
||||
|
||||
Fabricator(:chat_mention) do
|
||||
chat_message { Fabricate(:chat_message) }
|
||||
transient read: false
|
||||
transient high_priority: true
|
||||
transient identifier: :direct_mentions
|
||||
|
||||
user { Fabricate(:user) }
|
||||
notification { Fabricate(:notification) }
|
||||
chat_message { Fabricate(:chat_message) }
|
||||
notification do |attrs|
|
||||
# All this setup should be in a service we could just call here
|
||||
# At the moment the logic is all split in a job
|
||||
channel = attrs[:chat_message].chat_channel
|
||||
|
||||
payload = {
|
||||
is_direct_message_channel: channel.direct_message_channel?,
|
||||
mentioned_by_username: attrs[:chat_message].user.username,
|
||||
chat_channel_id: channel.id,
|
||||
chat_message_id: attrs[:chat_message].id,
|
||||
}
|
||||
|
||||
if channel.direct_message_channel?
|
||||
payload[:chat_channel_title] = channel.title(membership.user)
|
||||
payload[:chat_channel_slug] = channel.slug
|
||||
end
|
||||
|
||||
unless attrs[:identifier] == :direct_mentions
|
||||
case attrs[:identifier]
|
||||
when :here_mentions
|
||||
payload[:identifier] = "here"
|
||||
when :global_mentions
|
||||
payload[:identifier] = "all"
|
||||
else
|
||||
payload[:identifier] = attrs[:identifier] if attrs[:identifier]
|
||||
payload[:is_group_mention] = true
|
||||
end
|
||||
end
|
||||
|
||||
Fabricate(
|
||||
:notification,
|
||||
notification_type: Notification.types[:chat_mention],
|
||||
user: attrs[:user],
|
||||
data: payload.to_json,
|
||||
read: attrs[:read],
|
||||
high_priority: attrs[:high_priority],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
Fabricator(:chat_message_reaction) do
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe Chat::Endpoint do
|
||||
class SuccessService
|
||||
include Chat::Service::Base
|
||||
end
|
||||
|
||||
class FailureService
|
||||
include Chat::Service::Base
|
||||
|
||||
step :fail_step
|
||||
|
||||
def fail_step
|
||||
fail!("error")
|
||||
end
|
||||
end
|
||||
|
||||
class FailedPolicyService
|
||||
include Chat::Service::Base
|
||||
|
||||
policy :test
|
||||
|
||||
def test
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
class SuccessPolicyService
|
||||
include Chat::Service::Base
|
||||
|
||||
policy :test
|
||||
|
||||
def test
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
class FailedContractService
|
||||
include Chat::Service::Base
|
||||
|
||||
class Contract
|
||||
attribute :test
|
||||
validates :test, presence: true
|
||||
end
|
||||
|
||||
contract
|
||||
end
|
||||
|
||||
class SuccessContractService
|
||||
include Chat::Service::Base
|
||||
|
||||
contract
|
||||
end
|
||||
|
||||
class FailureWithModelService
|
||||
include Chat::Service::Base
|
||||
|
||||
model :fake_model, :fetch_fake_model
|
||||
|
||||
private
|
||||
|
||||
def fetch_fake_model
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
class SuccessWithModelService
|
||||
include Chat::Service::Base
|
||||
|
||||
model :fake_model, :fetch_fake_model
|
||||
|
||||
private
|
||||
|
||||
def fetch_fake_model
|
||||
:model_found
|
||||
end
|
||||
end
|
||||
|
||||
describe ".call(service, &block)" do
|
||||
subject(:endpoint) { described_class.call(service, controller, &actions_block) }
|
||||
|
||||
let(:result) { controller.result }
|
||||
let(:actions_block) { controller.instance_eval(actions) }
|
||||
let(:service) { SuccessService }
|
||||
let(:actions) { "proc {}" }
|
||||
let(:controller) do
|
||||
Class
|
||||
.new(Chat::Api) do
|
||||
def request
|
||||
OpenStruct.new
|
||||
end
|
||||
|
||||
def params
|
||||
ActionController::Parameters.new
|
||||
end
|
||||
|
||||
def guardian
|
||||
end
|
||||
end
|
||||
.new
|
||||
end
|
||||
|
||||
it "runs the provided service in the context of a controller" do
|
||||
endpoint
|
||||
expect(result).to be_a Chat::Service::Base::Context
|
||||
expect(result).to be_a_success
|
||||
end
|
||||
|
||||
context "when using the on_success action" do
|
||||
let(:actions) { <<-BLOCK }
|
||||
proc do
|
||||
on_success { :success }
|
||||
end
|
||||
BLOCK
|
||||
|
||||
context "when the service succeeds" do
|
||||
it "runs the provided block" do
|
||||
expect(endpoint).to eq :success
|
||||
end
|
||||
end
|
||||
|
||||
context "when the service does not succeed" do
|
||||
let(:service) { FailureService }
|
||||
|
||||
it "does not run the provided block" do
|
||||
expect(endpoint).not_to eq :success
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when using the on_failure action" do
|
||||
let(:actions) { <<-BLOCK }
|
||||
proc do
|
||||
on_failure { :fail }
|
||||
end
|
||||
BLOCK
|
||||
|
||||
context "when the service fails" do
|
||||
let(:service) { FailureService }
|
||||
|
||||
it "runs the provided block" do
|
||||
expect(endpoint).to eq :fail
|
||||
end
|
||||
end
|
||||
|
||||
context "when the service does not fail" do
|
||||
let(:service) { SuccessService }
|
||||
|
||||
it "does not run the provided block" do
|
||||
expect(endpoint).not_to eq :fail
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when using the on_failed_policy action" do
|
||||
let(:actions) { <<-BLOCK }
|
||||
proc do
|
||||
on_failed_policy(:test) { :policy_failure }
|
||||
end
|
||||
BLOCK
|
||||
|
||||
context "when the service policy fails" do
|
||||
let(:service) { FailedPolicyService }
|
||||
|
||||
it "runs the provided block" do
|
||||
expect(endpoint).to eq :policy_failure
|
||||
end
|
||||
end
|
||||
|
||||
context "when the service policy does not fail" do
|
||||
let(:service) { SuccessPolicyService }
|
||||
|
||||
it "does not run the provided block" do
|
||||
expect(endpoint).not_to eq :policy_failure
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when using the on_failed_contract action" do
|
||||
let(:actions) { <<-BLOCK }
|
||||
proc do
|
||||
on_failed_contract { :contract_failure }
|
||||
end
|
||||
BLOCK
|
||||
|
||||
context "when the service contract fails" do
|
||||
let(:service) { FailedContractService }
|
||||
|
||||
it "runs the provided block" do
|
||||
expect(endpoint).to eq :contract_failure
|
||||
end
|
||||
end
|
||||
|
||||
context "when the service contract does not fail" do
|
||||
let(:service) { SuccessContractService }
|
||||
|
||||
it "does not run the provided block" do
|
||||
expect(endpoint).not_to eq :contract_failure
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when using the on_model_not_found action" do
|
||||
let(:actions) { <<-BLOCK }
|
||||
->(*) do
|
||||
on_model_not_found(:fake_model) { :no_model }
|
||||
end
|
||||
BLOCK
|
||||
|
||||
context "when the service failed without a model" do
|
||||
let(:service) { FailureWithModelService }
|
||||
|
||||
it "runs the provided block" do
|
||||
expect(endpoint).to eq :no_model
|
||||
end
|
||||
end
|
||||
|
||||
context "when the service does not fail with a model" do
|
||||
let(:service) { SuccessWithModelService }
|
||||
|
||||
it "does not run the provided block" do
|
||||
expect(endpoint).not_to eq :no_model
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when using several actions together" do
|
||||
let(:service) { FailureService }
|
||||
let(:actions) { <<-BLOCK }
|
||||
proc do
|
||||
on_success { :success }
|
||||
on_failure { :failure }
|
||||
on_failed_policy { :policy_failure }
|
||||
end
|
||||
BLOCK
|
||||
|
||||
it "runs the first matching action" do
|
||||
expect(endpoint).to eq :failure
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,175 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe Chat::StepsInspector do
|
||||
class DummyService
|
||||
include Chat::Service::Base
|
||||
|
||||
model :model
|
||||
policy :policy
|
||||
contract
|
||||
transaction do
|
||||
step :in_transaction_step_1
|
||||
step :in_transaction_step_2
|
||||
end
|
||||
step :final_step
|
||||
|
||||
class Contract
|
||||
attribute :parameter
|
||||
|
||||
validates :parameter, presence: true
|
||||
end
|
||||
end
|
||||
|
||||
subject(:inspector) { described_class.new(result) }
|
||||
|
||||
let(:parameter) { "present" }
|
||||
let(:result) { DummyService.call(parameter: parameter) }
|
||||
|
||||
before do
|
||||
class DummyService
|
||||
%i[fetch_model policy in_transaction_step_1 in_transaction_step_2 final_step].each do |name|
|
||||
define_method(name) { true }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#inspect" do
|
||||
subject(:output) { inspector.inspect }
|
||||
|
||||
context "when service runs without error" do
|
||||
it "outputs all the steps of the service" do
|
||||
expect(output).to eq <<~OUTPUT.chomp
|
||||
[1/7] [model] 'model' ✅
|
||||
[2/7] [policy] 'policy' ✅
|
||||
[3/7] [contract] 'default' ✅
|
||||
[4/7] [transaction]
|
||||
[5/7] [step] 'in_transaction_step_1' ✅
|
||||
[6/7] [step] 'in_transaction_step_2' ✅
|
||||
[7/7] [step] 'final_step' ✅
|
||||
OUTPUT
|
||||
end
|
||||
end
|
||||
|
||||
context "when the model step is failing" do
|
||||
before do
|
||||
class DummyService
|
||||
def fetch_model
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "shows the failing step" do
|
||||
expect(output).to eq <<~OUTPUT.chomp
|
||||
[1/7] [model] 'model' ❌
|
||||
[2/7] [policy] 'policy'
|
||||
[3/7] [contract] 'default'
|
||||
[4/7] [transaction]
|
||||
[5/7] [step] 'in_transaction_step_1'
|
||||
[6/7] [step] 'in_transaction_step_2'
|
||||
[7/7] [step] 'final_step'
|
||||
OUTPUT
|
||||
end
|
||||
end
|
||||
|
||||
context "when the policy step is failing" do
|
||||
before do
|
||||
class DummyService
|
||||
def policy
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "shows the failing step" do
|
||||
expect(output).to eq <<~OUTPUT.chomp
|
||||
[1/7] [model] 'model' ✅
|
||||
[2/7] [policy] 'policy' ❌
|
||||
[3/7] [contract] 'default'
|
||||
[4/7] [transaction]
|
||||
[5/7] [step] 'in_transaction_step_1'
|
||||
[6/7] [step] 'in_transaction_step_2'
|
||||
[7/7] [step] 'final_step'
|
||||
OUTPUT
|
||||
end
|
||||
end
|
||||
|
||||
context "when the contract step is failing" do
|
||||
let(:parameter) { nil }
|
||||
|
||||
it "shows the failing step" do
|
||||
expect(output).to eq <<~OUTPUT.chomp
|
||||
[1/7] [model] 'model' ✅
|
||||
[2/7] [policy] 'policy' ✅
|
||||
[3/7] [contract] 'default' ❌
|
||||
[4/7] [transaction]
|
||||
[5/7] [step] 'in_transaction_step_1'
|
||||
[6/7] [step] 'in_transaction_step_2'
|
||||
[7/7] [step] 'final_step'
|
||||
OUTPUT
|
||||
end
|
||||
end
|
||||
|
||||
context "when a common step is failing" do
|
||||
before do
|
||||
class DummyService
|
||||
def in_transaction_step_2
|
||||
fail!("step error")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "shows the failing step" do
|
||||
expect(output).to eq <<~OUTPUT.chomp
|
||||
[1/7] [model] 'model' ✅
|
||||
[2/7] [policy] 'policy' ✅
|
||||
[3/7] [contract] 'default' ✅
|
||||
[4/7] [transaction]
|
||||
[5/7] [step] 'in_transaction_step_1' ✅
|
||||
[6/7] [step] 'in_transaction_step_2' ❌
|
||||
[7/7] [step] 'final_step'
|
||||
OUTPUT
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#error" do
|
||||
subject(:error) { inspector.error }
|
||||
|
||||
context "when there are no errors" do
|
||||
it "returns nothing" do
|
||||
expect(error).to be_blank
|
||||
end
|
||||
end
|
||||
|
||||
context "when the model step is failing" do
|
||||
before do
|
||||
class DummyService
|
||||
def fetch_model
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "returns an error related to the model" do
|
||||
expect(error).to match(/Model not found/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when the contract step is failing" do
|
||||
let(:parameter) { nil }
|
||||
|
||||
it "returns an error related to the contract" do
|
||||
expect(error).to match(/ActiveModel::Error attribute=parameter, type=blank, options={}/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when a common step is failing" do
|
||||
before { result["result.step.final_step"].fail(error: "my error") }
|
||||
|
||||
it "returns an error related to the step" do
|
||||
expect(error).to eq("my error")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -22,4 +22,7 @@ module ChatSystemHelpers
|
|||
end
|
||||
end
|
||||
|
||||
RSpec.configure { |config| config.include ChatSystemHelpers, type: :system }
|
||||
RSpec.configure do |config|
|
||||
config.include ChatSystemHelpers, type: :system
|
||||
config.include Chat::ServiceMatchers
|
||||
end
|
||||
|
|
|
@ -170,12 +170,7 @@ RSpec.describe Chat::Api::ChatChannelsController do
|
|||
before { sign_in(current_user) }
|
||||
|
||||
it "returns an error" do
|
||||
delete "/chat/api/channels/#{channel_1.id}",
|
||||
params: {
|
||||
channel: {
|
||||
name_confirmation: channel_1.title(current_user),
|
||||
},
|
||||
}
|
||||
delete "/chat/api/channels/#{channel_1.id}"
|
||||
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
@ -190,38 +185,15 @@ RSpec.describe Chat::Api::ChatChannelsController do
|
|||
before { channel_1.destroy! }
|
||||
|
||||
it "returns an error" do
|
||||
delete "/chat/api/channels/#{channel_1.id}",
|
||||
params: {
|
||||
channel: {
|
||||
name_confirmation: channel_1.title(current_user),
|
||||
},
|
||||
}
|
||||
delete "/chat/api/channels/#{channel_1.id}"
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
end
|
||||
|
||||
context "when the confirmation doesn’t match the channel name" do
|
||||
it "returns an error" do
|
||||
delete "/chat/api/channels/#{channel_1.id}",
|
||||
params: {
|
||||
channel: {
|
||||
name_confirmation: channel_1.title(current_user) + "foo",
|
||||
},
|
||||
}
|
||||
|
||||
expect(response.status).to eq(400)
|
||||
end
|
||||
end
|
||||
|
||||
context "with valid params" do
|
||||
it "properly destroys the channel" do
|
||||
delete "/chat/api/channels/#{channel_1.id}",
|
||||
params: {
|
||||
channel: {
|
||||
name_confirmation: channel_1.title(current_user),
|
||||
},
|
||||
}
|
||||
delete "/chat/api/channels/#{channel_1.id}"
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
expect(channel_1.reload.trashed?).to eq(true)
|
||||
|
@ -243,14 +215,7 @@ RSpec.describe Chat::Api::ChatChannelsController do
|
|||
freeze_time(DateTime.parse("2022-07-08 09:30:00"))
|
||||
old_slug = channel_1.slug
|
||||
|
||||
delete(
|
||||
"/chat/api/channels/#{channel_1.id}",
|
||||
params: {
|
||||
channel: {
|
||||
name_confirmation: channel_1.title(current_user),
|
||||
},
|
||||
},
|
||||
)
|
||||
delete "/chat/api/channels/#{channel_1.id}"
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
expect(channel_1.reload.slug).to eq(
|
||||
|
@ -371,7 +336,13 @@ RSpec.describe Chat::Api::ChatChannelsController do
|
|||
before { sign_in(Fabricate(:user)) }
|
||||
|
||||
it "returns a 403" do
|
||||
put "/chat/api/channels/#{channel.id}"
|
||||
put "/chat/api/channels/#{channel.id}",
|
||||
params: {
|
||||
channel: {
|
||||
name: "joffrey",
|
||||
description: "cat owner",
|
||||
},
|
||||
}
|
||||
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
@ -400,7 +371,7 @@ RSpec.describe Chat::Api::ChatChannelsController do
|
|||
it "nullifies the field and doesn’t store an empty string" do
|
||||
put "/chat/api/channels/#{channel.id}", params: { channel: { name: " " } }
|
||||
|
||||
expect(channel.reload.name).to be_nil
|
||||
expect(channel.reload.name).to eq(nil)
|
||||
end
|
||||
|
||||
it "doesn’t nullify the description" do
|
||||
|
@ -421,7 +392,7 @@ RSpec.describe Chat::Api::ChatChannelsController do
|
|||
it "nullifies the field and doesn’t store an empty string" do
|
||||
put "/chat/api/channels/#{channel.id}", params: { channel: { description: " " } }
|
||||
|
||||
expect(channel.reload.description).to be_nil
|
||||
expect(channel.reload.description).to eq(nil)
|
||||
end
|
||||
|
||||
it "doesn’t nullify the name" do
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe(Chat::Service::TrashChannel) do
|
||||
subject(:result) { described_class.call(guardian: guardian) }
|
||||
|
||||
let(:guardian) { Guardian.new(current_user) }
|
||||
|
||||
context "when channel_id is not provided" do
|
||||
fab!(:current_user) { Fabricate(:admin) }
|
||||
|
||||
it { is_expected.to fail_to_find_a_model(:channel) }
|
||||
end
|
||||
|
||||
context "when channel_id is provided" do
|
||||
subject(:result) { described_class.call(channel_id: channel.id, guardian: guardian) }
|
||||
|
||||
fab!(:channel) { Fabricate(:chat_channel) }
|
||||
|
||||
context "when user is not allowed to perform the action" do
|
||||
fab!(:current_user) { Fabricate(:user) }
|
||||
|
||||
it { is_expected.to fail_a_policy(:invalid_access) }
|
||||
end
|
||||
|
||||
context "when user is allowed to perform the action" do
|
||||
fab!(:current_user) { Fabricate(:admin) }
|
||||
|
||||
it "sets the service result as successful" do
|
||||
expect(result).to be_a_success
|
||||
end
|
||||
|
||||
it "trashes the channel" do
|
||||
expect(result[:channel]).to be_trashed
|
||||
end
|
||||
|
||||
it "logs the action" do
|
||||
expect { result }.to change { UserHistory.count }.by(1)
|
||||
expect(UserHistory.last).to have_attributes(
|
||||
custom_type: "chat_channel_delete",
|
||||
details:
|
||||
"chat_channel_id: #{result[:channel].id}\nchat_channel_name: #{result[:channel].title(guardian.user)}",
|
||||
)
|
||||
end
|
||||
|
||||
it "changes the slug to prevent colisions" do
|
||||
expect(result[:channel].slug).to include("deleted")
|
||||
end
|
||||
|
||||
it "queues a job to delete channel relations" do
|
||||
expect { result }.to change(Jobs::ChatChannelDelete.jobs, :size).by(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,107 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe Chat::Service::UpdateChannel do
|
||||
subject(:result) { described_class.call(guardian: guardian, channel_id: channel.id, **params) }
|
||||
|
||||
fab!(:channel) { Fabricate(:chat_channel) }
|
||||
fab!(:current_user) { Fabricate(:admin) }
|
||||
|
||||
let(:guardian) { Guardian.new(current_user) }
|
||||
let(:params) do
|
||||
{
|
||||
name: "cool channel",
|
||||
description: "a channel description",
|
||||
slug: "snail",
|
||||
allow_channel_wide_mentions: true,
|
||||
auto_join_users: false,
|
||||
}
|
||||
end
|
||||
|
||||
context "when the user cannot edit the channel" do
|
||||
fab!(:current_user) { Fabricate(:user) }
|
||||
|
||||
it { is_expected.to fail_a_policy(:check_channel_permission) }
|
||||
end
|
||||
|
||||
context "when the user tries to edit a DM channel" do
|
||||
fab!(:channel) { Fabricate(:direct_message_channel, users: [current_user, Fabricate(:user)]) }
|
||||
|
||||
it { is_expected.to fail_a_policy(:no_direct_message_channel) }
|
||||
end
|
||||
|
||||
context "when channel is a category one" do
|
||||
context "when a valid user provides valid params" do
|
||||
let(:message) do
|
||||
MessageBus.track_publish(ChatPublisher::CHANNEL_EDITS_MESSAGE_BUS_CHANNEL) { result }.first
|
||||
end
|
||||
|
||||
it "sets the service result as successful" do
|
||||
expect(result).to be_a_success
|
||||
end
|
||||
|
||||
it "updates the channel accordingly" do
|
||||
result
|
||||
expect(channel.reload).to have_attributes(
|
||||
name: "cool channel",
|
||||
slug: "snail",
|
||||
description: "a channel description",
|
||||
allow_channel_wide_mentions: true,
|
||||
auto_join_users: false,
|
||||
)
|
||||
end
|
||||
|
||||
it "publishes a MessageBus message" do
|
||||
expect(message.data).to eq(
|
||||
{
|
||||
chat_channel_id: channel.id,
|
||||
name: "cool channel",
|
||||
description: "a channel description",
|
||||
slug: "snail",
|
||||
},
|
||||
)
|
||||
end
|
||||
|
||||
context "when the name is blank" do
|
||||
before { params[:name] = "" }
|
||||
|
||||
it "nils out the name" do
|
||||
result
|
||||
expect(channel.reload.name).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "when the description is blank" do
|
||||
before do
|
||||
channel.update!(description: "something")
|
||||
params[:description] = ""
|
||||
end
|
||||
|
||||
it "nils out the description" do
|
||||
result
|
||||
expect(channel.reload.description).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "when auto_join_users is set to 'true'" do
|
||||
before do
|
||||
channel.update!(auto_join_users: false)
|
||||
params[:auto_join_users] = true
|
||||
end
|
||||
|
||||
it "updates the model accordingly" do
|
||||
result
|
||||
expect(channel.reload).to have_attributes(auto_join_users: true)
|
||||
end
|
||||
|
||||
it "auto joins users" do
|
||||
expect_enqueued_with(
|
||||
job: :auto_manage_channel_memberships,
|
||||
args: {
|
||||
chat_channel_id: channel.id,
|
||||
},
|
||||
) { result }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,54 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe(Chat::Service::UpdateChannelStatus) do
|
||||
subject(:result) do
|
||||
described_class.call(guardian: guardian, channel_id: channel.id, status: status)
|
||||
end
|
||||
|
||||
fab!(:channel) { Fabricate(:chat_channel) }
|
||||
fab!(:current_user) { Fabricate(:admin) }
|
||||
|
||||
let(:guardian) { Guardian.new(current_user) }
|
||||
let(:status) { "open" }
|
||||
|
||||
context "when no channel_id is given" do
|
||||
subject(:result) { described_class.call(guardian: guardian, status: status) }
|
||||
|
||||
it { is_expected.to fail_to_find_a_model(:channel) }
|
||||
end
|
||||
|
||||
context "when user is not allowed to change channel status" do
|
||||
fab!(:current_user) { Fabricate(:user) }
|
||||
|
||||
it { is_expected.to fail_a_policy(:check_channel_permission) }
|
||||
end
|
||||
|
||||
context "when status is not allowed" do
|
||||
(ChatChannel.statuses.keys - ChatChannel.editable_statuses.keys).each do |na_status|
|
||||
context "when status is '#{na_status}'" do
|
||||
let(:status) { na_status }
|
||||
|
||||
it { is_expected.to fail_a_contract }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when new status is the same than the existing one" do
|
||||
let(:status) { channel.status }
|
||||
|
||||
it { is_expected.to fail_a_policy(:check_channel_permission) }
|
||||
end
|
||||
|
||||
context "when status is allowed" do
|
||||
let(:status) { "closed" }
|
||||
|
||||
it "sets the service result as successful" do
|
||||
expect(result).to be_a_success
|
||||
end
|
||||
|
||||
it "changes the status" do
|
||||
result
|
||||
expect(channel.reload).to be_closed
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,118 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe(Chat::Service::UpdateUserLastRead) do
|
||||
subject(:result) { described_class.call(params) }
|
||||
|
||||
fab!(:current_user) { Fabricate(:user) }
|
||||
fab!(:channel) { Fabricate(:chat_channel) }
|
||||
fab!(:membership) do
|
||||
Fabricate(:user_chat_channel_membership, user: current_user, chat_channel: channel)
|
||||
end
|
||||
fab!(:message_1) { Fabricate(:chat_message, chat_channel: membership.chat_channel) }
|
||||
|
||||
let(:guardian) { Guardian.new(current_user) }
|
||||
let(:params) do
|
||||
{
|
||||
guardian: guardian,
|
||||
user_id: current_user.id,
|
||||
channel_id: channel.id,
|
||||
message_id: message_1.id,
|
||||
}
|
||||
end
|
||||
|
||||
context "when channel_id is not provided" do
|
||||
before { params.delete(:channel_id) }
|
||||
|
||||
it { is_expected.to fail_to_find_a_model(:membership) }
|
||||
end
|
||||
|
||||
context "when user_id is not provided" do
|
||||
before { params.delete(:user_id) }
|
||||
|
||||
it { is_expected.to fail_to_find_a_model(:membership) }
|
||||
end
|
||||
|
||||
context "when user has no membership" do
|
||||
before { membership.destroy! }
|
||||
|
||||
it { is_expected.to fail_to_find_a_model(:membership) }
|
||||
end
|
||||
|
||||
context "when user can’t access the channel" do
|
||||
fab!(:membership) do
|
||||
Fabricate(
|
||||
:user_chat_channel_membership,
|
||||
user: current_user,
|
||||
chat_channel: Fabricate(:private_category_channel),
|
||||
)
|
||||
end
|
||||
|
||||
before { params[:channel_id] = membership.chat_channel.id }
|
||||
|
||||
it { is_expected.to fail_a_policy(:invalid_access) }
|
||||
end
|
||||
|
||||
context "when message_id is older than membership's last_read_message_id" do
|
||||
before do
|
||||
params[:message_id] = -2
|
||||
membership.update!(last_read_message_id: -1)
|
||||
end
|
||||
|
||||
it { is_expected.to fail_a_policy(:ensure_message_id_recency) }
|
||||
end
|
||||
|
||||
context "when message doesn’t exist" do
|
||||
before do
|
||||
params[:message_id] = 2
|
||||
membership.update!(last_read_message_id: 1)
|
||||
end
|
||||
|
||||
it { is_expected.to fail_a_policy(:ensure_message_exists) }
|
||||
end
|
||||
|
||||
context "when params are valid" do
|
||||
before { Jobs.run_immediately! }
|
||||
|
||||
it "sets the service result as successful" do
|
||||
expect(result).to be_a_success
|
||||
end
|
||||
|
||||
it "updates the last_read message id" do
|
||||
expect { result }.to change { membership.reload.last_read_message_id }.to(message_1.id)
|
||||
end
|
||||
|
||||
it "marks existing notifications related to the message as read" do
|
||||
expect {
|
||||
notification =
|
||||
Fabricate(
|
||||
:notification,
|
||||
notification_type: Notification.types[:chat_mention],
|
||||
user: current_user,
|
||||
)
|
||||
|
||||
# FIXME: we need a better way to create proper chat mention
|
||||
ChatMention.create!(notification: notification, user: current_user, chat_message: message_1)
|
||||
}.to change {
|
||||
Notification.where(
|
||||
notification_type: Notification.types[:chat_mention],
|
||||
user: current_user,
|
||||
read: false,
|
||||
).count
|
||||
}.by(1)
|
||||
|
||||
expect { result }.to change {
|
||||
Notification.where(
|
||||
notification_type: Notification.types[:chat_mention],
|
||||
user: current_user,
|
||||
read: false,
|
||||
).count
|
||||
}.by(-1)
|
||||
end
|
||||
|
||||
it "publishes new last read to clients" do
|
||||
messages = MessageBus.track_publish { result }
|
||||
|
||||
expect(messages.map(&:channel)).to include("/chat/user-tracking-state/#{current_user.id}")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,135 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Chat
|
||||
module ServiceMatchers
|
||||
class FailStep
|
||||
attr_reader :name, :result
|
||||
|
||||
def initialize(name)
|
||||
@name = name
|
||||
end
|
||||
|
||||
def matches?(result)
|
||||
@result = result
|
||||
step_exists? && step_failed? && service_failed?
|
||||
end
|
||||
|
||||
def failure_message
|
||||
message =
|
||||
if !step_exists?
|
||||
"Expected #{type} '#{name}' (key: '#{step}') was not found in the result object."
|
||||
elsif !step_failed?
|
||||
"Expected #{type} '#{name}' (key: '#{step}') to fail but it succeeded."
|
||||
else
|
||||
"expected the service to fail but it succeeded."
|
||||
end
|
||||
error_message_with_inspection(message)
|
||||
end
|
||||
|
||||
def failure_message_when_negated
|
||||
message = "Expected #{type} '#{name}' (key: '#{step}') to succeed but it failed."
|
||||
error_message_with_inspection(message)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def step_exists?
|
||||
result[step].present?
|
||||
end
|
||||
|
||||
def step_failed?
|
||||
result[step].failure?
|
||||
end
|
||||
|
||||
def service_failed?
|
||||
result.failure?
|
||||
end
|
||||
|
||||
def type
|
||||
"step"
|
||||
end
|
||||
|
||||
def error_message_with_inspection(message)
|
||||
inspector = StepsInspector.new(result)
|
||||
"#{message}\n\n#{inspector.inspect}\n\n#{inspector.error}"
|
||||
end
|
||||
end
|
||||
|
||||
class FailContract < FailStep
|
||||
attr_reader :error_message
|
||||
|
||||
def step
|
||||
"result.contract.#{name}"
|
||||
end
|
||||
|
||||
def type
|
||||
"contract"
|
||||
end
|
||||
|
||||
def matches?(service)
|
||||
super && has_error?
|
||||
end
|
||||
|
||||
def has_error?
|
||||
result[step].errors.present?
|
||||
end
|
||||
|
||||
def failure_message
|
||||
return "expected contract '#{step}' to have errors" unless has_error?
|
||||
super
|
||||
end
|
||||
|
||||
def description
|
||||
"fail a contract named '#{name}'"
|
||||
end
|
||||
end
|
||||
|
||||
class FailPolicy < FailStep
|
||||
def type
|
||||
"policy"
|
||||
end
|
||||
|
||||
def step
|
||||
"result.policy.#{name}"
|
||||
end
|
||||
|
||||
def description
|
||||
"fail a policy named '#{name}'"
|
||||
end
|
||||
end
|
||||
|
||||
class FailToFindModel < FailStep
|
||||
def type
|
||||
"model"
|
||||
end
|
||||
|
||||
def step
|
||||
"result.model.#{name}"
|
||||
end
|
||||
|
||||
def description
|
||||
"fail to find a model named '#{name}'"
|
||||
end
|
||||
end
|
||||
|
||||
def fail_a_policy(name)
|
||||
FailPolicy.new(name)
|
||||
end
|
||||
|
||||
def fail_a_contract(name = "default")
|
||||
FailContract.new(name)
|
||||
end
|
||||
|
||||
def fail_to_find_a_model(name = "model")
|
||||
FailToFindModel.new(name)
|
||||
end
|
||||
|
||||
def inspect_steps(result)
|
||||
inspector = Chat::StepsInspector.new(result)
|
||||
puts "Steps:"
|
||||
puts inspector.inspect
|
||||
puts "\nFirst error:"
|
||||
puts inspector.error
|
||||
end
|
||||
end
|
||||
end
|
428
yarn.lock
428
yarn.lock
|
@ -567,13 +567,6 @@ ajv@^6.10.0, ajv@^6.12.4:
|
|||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-escape-sequences@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz#2483c8773f50dd9174dd9557e92b1718f1816097"
|
||||
integrity sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==
|
||||
dependencies:
|
||||
array-back "^3.0.1"
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||
|
@ -604,40 +597,6 @@ aria-query@^5.0.0:
|
|||
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.0.0.tgz#210c21aaf469613ee8c9a62c7f86525e058db52c"
|
||||
integrity sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==
|
||||
|
||||
array-back@^1.0.2, array-back@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b"
|
||||
integrity sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==
|
||||
dependencies:
|
||||
typical "^2.6.0"
|
||||
|
||||
array-back@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022"
|
||||
integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==
|
||||
dependencies:
|
||||
typical "^2.6.1"
|
||||
|
||||
array-back@^3.0.1, array-back@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0"
|
||||
integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==
|
||||
|
||||
array-back@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e"
|
||||
integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==
|
||||
|
||||
array-back@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/array-back/-/array-back-5.0.0.tgz#e196609edcec48376236d163958df76e659a0d36"
|
||||
integrity sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==
|
||||
|
||||
array-back@^6.2.2:
|
||||
version "6.2.2"
|
||||
resolved "https://registry.yarnpkg.com/array-back/-/array-back-6.2.2.tgz#f567d99e9af88a6d3d2f9dfcc21db6f9ba9fd157"
|
||||
integrity sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==
|
||||
|
||||
array-union@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
|
||||
|
@ -725,15 +684,6 @@ buffer@^5.2.1, buffer@^5.5.0:
|
|||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
cache-point@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cache-point/-/cache-point-2.0.0.tgz#91e03c38da9cfba9d95ac6a34d24cfe6eff8920f"
|
||||
integrity sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==
|
||||
dependencies:
|
||||
array-back "^4.0.1"
|
||||
fs-then-native "^2.0.0"
|
||||
mkdirp2 "^1.0.4"
|
||||
|
||||
callsites@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
|
@ -832,14 +782,6 @@ clone@^1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
||||
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
|
||||
|
||||
collect-all@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/collect-all/-/collect-all-1.0.4.tgz#50cd7119ac24b8e12a661f0f8c3aa0ea7222ddfc"
|
||||
integrity sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==
|
||||
dependencies:
|
||||
stream-connect "^1.0.2"
|
||||
stream-via "^1.0.4"
|
||||
|
||||
color-convert@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||
|
@ -869,37 +811,6 @@ colors@^1.4.0:
|
|||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
||||
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
|
||||
|
||||
command-line-args@^5.0.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e"
|
||||
integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==
|
||||
dependencies:
|
||||
array-back "^3.1.0"
|
||||
find-replace "^3.0.0"
|
||||
lodash.camelcase "^4.3.0"
|
||||
typical "^4.0.0"
|
||||
|
||||
command-line-tool@^0.8.0:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/command-line-tool/-/command-line-tool-0.8.0.tgz#b00290ef1dfc11cc731dd1f43a92cfa5f21e715b"
|
||||
integrity sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==
|
||||
dependencies:
|
||||
ansi-escape-sequences "^4.0.0"
|
||||
array-back "^2.0.0"
|
||||
command-line-args "^5.0.0"
|
||||
command-line-usage "^4.1.0"
|
||||
typical "^2.6.1"
|
||||
|
||||
command-line-usage@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-4.1.0.tgz#a6b3b2e2703b4dcf8bd46ae19e118a9a52972882"
|
||||
integrity sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==
|
||||
dependencies:
|
||||
ansi-escape-sequences "^4.0.0"
|
||||
array-back "^2.0.0"
|
||||
table-layout "^0.4.2"
|
||||
typical "^2.6.1"
|
||||
|
||||
commander@2.11.x:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
|
||||
|
@ -915,23 +826,11 @@ commander@^8.3.0:
|
|||
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
||||
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
|
||||
|
||||
common-sequence@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/common-sequence/-/common-sequence-2.0.2.tgz#accc76bdc5876a1fcd92b73484d4285fff99d838"
|
||||
integrity sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
config-master@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/config-master/-/config-master-3.1.0.tgz#667663590505a283bf26a484d68489d74c5485da"
|
||||
integrity sha512-n7LBL1zBzYdTpF1mx5DNcZnZn05CWIdsdvtPL4MosvqbBUK3Rq6VWEtGUuF3Y0s9/CIhMejezqlSkP6TnCJ/9g==
|
||||
dependencies:
|
||||
walk-back "^2.0.1"
|
||||
|
||||
convert-source-map@^1.7.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
|
||||
|
@ -992,11 +891,6 @@ debug@^2.6.8:
|
|||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
deep-extend@~0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
|
||||
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
|
||||
|
||||
deep-is@^0.1.3:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
|
||||
|
@ -1026,24 +920,6 @@ dir-glob@^3.0.1:
|
|||
dependencies:
|
||||
path-type "^4.0.0"
|
||||
|
||||
dmd@^6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dmd/-/dmd-6.2.0.tgz#d267a9fb1ce62b74edca8bf5bcbd3b8e08574fe7"
|
||||
integrity sha512-uXWxLF1H7TkUAuoHK59/h/ts5cKavm2LnhrIgJWisip4BVzPoXavlwyoprFFn2CzcahKYgvkfaebS6oxzgflkg==
|
||||
dependencies:
|
||||
array-back "^6.2.2"
|
||||
cache-point "^2.0.0"
|
||||
common-sequence "^2.0.2"
|
||||
file-set "^4.0.2"
|
||||
handlebars "^4.7.7"
|
||||
marked "^4.2.3"
|
||||
object-get "^2.1.1"
|
||||
reduce-flatten "^3.0.1"
|
||||
reduce-unique "^2.0.1"
|
||||
reduce-without "^1.0.1"
|
||||
test-value "^3.0.0"
|
||||
walk-back "^5.1.0"
|
||||
|
||||
doctrine@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
|
||||
|
@ -1416,14 +1292,6 @@ file-entry-cache@^6.0.1:
|
|||
dependencies:
|
||||
flat-cache "^3.0.4"
|
||||
|
||||
file-set@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/file-set/-/file-set-4.0.2.tgz#8d67c92a864202c2085ac9f03f1c9909c7e27030"
|
||||
integrity sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==
|
||||
dependencies:
|
||||
array-back "^5.0.0"
|
||||
glob "^7.1.6"
|
||||
|
||||
fill-range@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||
|
@ -1431,13 +1299,6 @@ fill-range@^7.0.1:
|
|||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
find-replace@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38"
|
||||
integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==
|
||||
dependencies:
|
||||
array-back "^3.0.1"
|
||||
|
||||
find-up@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
|
||||
|
@ -1490,11 +1351,6 @@ fs-extra@^9.1.0:
|
|||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
fs-then-native@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-then-native/-/fs-then-native-2.0.0.tgz#19a124d94d90c22c8e045f2e8dd6ebea36d48c67"
|
||||
integrity sha512-X712jAOaWXkemQCAmWeg5rOT2i+KOpWz1Z/txk/cW0qlOu2oQ9H61vc5w3X/iyuUEfq/OyaFJ78/cZAQD1/bgA==
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
|
@ -1567,7 +1423,7 @@ glob-stream@^7.0.0:
|
|||
to-absolute-glob "^2.0.2"
|
||||
unique-stream "^2.3.1"
|
||||
|
||||
glob@^7.1.3, glob@^7.1.6, glob@^7.2.0:
|
||||
glob@^7.1.3, glob@^7.2.0:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
|
@ -1619,18 +1475,6 @@ graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
|
|||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
|
||||
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
|
||||
|
||||
handlebars@^4.7.7:
|
||||
version "4.7.7"
|
||||
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
|
||||
integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==
|
||||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
neo-async "^2.6.0"
|
||||
source-map "^0.6.1"
|
||||
wordwrap "^1.0.0"
|
||||
optionalDependencies:
|
||||
uglify-js "^3.1.4"
|
||||
|
||||
has-flag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
|
@ -1692,6 +1536,11 @@ inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
|
|||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
inherits@2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
|
||||
|
||||
is-absolute@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576"
|
||||
|
@ -1804,45 +1653,26 @@ js2xmlparser@^4.0.2:
|
|||
dependencies:
|
||||
xmlcreate "^2.0.4"
|
||||
|
||||
jsdoc-api@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsdoc-api/-/jsdoc-api-8.0.0.tgz#4b2c25ff60f91b80da51b6cd33943acc7b2cab74"
|
||||
integrity sha512-Rnhor0suB1Ds1abjmFkFfKeD+kSMRN9oHMTMZoJVUrmtCGDwXty+sWMA9sa4xbe4UyxuPjhC7tavZ40mDKK6QQ==
|
||||
jsdoc@^3.6.3:
|
||||
version "3.6.11"
|
||||
resolved "https://registry.yarnpkg.com/jsdoc/-/jsdoc-3.6.11.tgz#8bbb5747e6f579f141a5238cbad4e95e004458ce"
|
||||
integrity sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==
|
||||
dependencies:
|
||||
array-back "^6.2.2"
|
||||
cache-point "^2.0.0"
|
||||
collect-all "^1.0.4"
|
||||
file-set "^4.0.2"
|
||||
fs-then-native "^2.0.0"
|
||||
jsdoc "^4.0.0"
|
||||
object-to-spawn-args "^2.0.1"
|
||||
temp-path "^1.0.0"
|
||||
walk-back "^5.1.0"
|
||||
|
||||
jsdoc-parse@^6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jsdoc-parse/-/jsdoc-parse-6.2.0.tgz#2b71d3925acfc4badc72526f2470766e0561f6b5"
|
||||
integrity sha512-Afu1fQBEb7QHt6QWX/6eUWvYHJofB90Fjx7FuJYF7mnG9z5BkAIpms1wsnvYLytfmqpEENHs/fax9p8gvMj7dw==
|
||||
dependencies:
|
||||
array-back "^6.2.2"
|
||||
lodash.omit "^4.5.0"
|
||||
lodash.pick "^4.4.0"
|
||||
reduce-extract "^1.0.0"
|
||||
sort-array "^4.1.5"
|
||||
test-value "^3.0.0"
|
||||
|
||||
jsdoc-to-markdown@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsdoc-to-markdown/-/jsdoc-to-markdown-8.0.0.tgz#27f32ed200d3b84dbf22a49beed485790f93b3ce"
|
||||
integrity sha512-2FQvYkg491+FP6s15eFlgSSWs69CvQrpbABGYBtvAvGWy/lWo8IKKToarT283w59rQFrpcjHl3YdhHCa3l7gXg==
|
||||
dependencies:
|
||||
array-back "^6.2.2"
|
||||
command-line-tool "^0.8.0"
|
||||
config-master "^3.1.0"
|
||||
dmd "^6.2.0"
|
||||
jsdoc-api "^8.0.0"
|
||||
jsdoc-parse "^6.2.0"
|
||||
walk-back "^5.1.0"
|
||||
"@babel/parser" "^7.9.4"
|
||||
"@types/markdown-it" "^12.2.3"
|
||||
bluebird "^3.7.2"
|
||||
catharsis "^0.9.0"
|
||||
escape-string-regexp "^2.0.0"
|
||||
js2xmlparser "^4.0.2"
|
||||
klaw "^3.0.0"
|
||||
markdown-it "^12.3.2"
|
||||
markdown-it-anchor "^8.4.1"
|
||||
marked "^4.0.10"
|
||||
mkdirp "^1.0.4"
|
||||
requizzle "^0.2.3"
|
||||
strip-json-comments "^3.1.0"
|
||||
taffydb "2.6.2"
|
||||
underscore "~1.13.2"
|
||||
|
||||
jsdoc@^4.0.0:
|
||||
version "4.0.0"
|
||||
|
@ -1999,11 +1829,6 @@ locate-path@^7.1.0:
|
|||
dependencies:
|
||||
p-locate "^6.0.0"
|
||||
|
||||
lodash.camelcase@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
|
||||
integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==
|
||||
|
||||
lodash.kebabcase@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"
|
||||
|
@ -2014,21 +1839,6 @@ lodash.merge@^4.6.2:
|
|||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
lodash.omit@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60"
|
||||
integrity sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==
|
||||
|
||||
lodash.padend@^4.6.1:
|
||||
version "4.6.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e"
|
||||
integrity sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw==
|
||||
|
||||
lodash.pick@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
|
||||
integrity sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==
|
||||
|
||||
lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
|
@ -2070,7 +1880,7 @@ markdown-it@^12.3.2:
|
|||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.5"
|
||||
|
||||
marked@^4.0.10, marked@^4.2.3:
|
||||
marked@^4.0.10:
|
||||
version "4.2.5"
|
||||
resolved "https://registry.yarnpkg.com/marked/-/marked-4.2.5.tgz#979813dfc1252cc123a79b71b095759a32f42a5d"
|
||||
integrity sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ==
|
||||
|
@ -2115,21 +1925,11 @@ minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
|
|||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
|
||||
integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
|
||||
|
||||
mkdirp-classic@^0.5.2:
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
||||
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
||||
|
||||
mkdirp2@^1.0.4:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp2/-/mkdirp2-1.0.5.tgz#68bbe61defefafce4b48948608ec0bac942512c2"
|
||||
integrity sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==
|
||||
|
||||
mkdirp@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
|
@ -2162,11 +1962,6 @@ natural-compare@^1.4.0:
|
|||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||
|
||||
neo-async@^2.6.0:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||
|
||||
no-case@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
|
||||
|
@ -2187,16 +1982,6 @@ node-releases@^2.0.5:
|
|||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666"
|
||||
integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==
|
||||
|
||||
object-get@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-get/-/object-get-2.1.1.tgz#1dad63baf6d94df184d1c58756cc9be55b174dac"
|
||||
integrity sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==
|
||||
|
||||
object-to-spawn-args@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz#cf8b8e3c9b3589137a469cac90391f44870144a5"
|
||||
integrity sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==
|
||||
|
||||
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
|
@ -2452,35 +2237,6 @@ readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
|
|||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
reduce-extract@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/reduce-extract/-/reduce-extract-1.0.0.tgz#67f2385beda65061b5f5f4312662e8b080ca1525"
|
||||
integrity sha512-QF8vjWx3wnRSL5uFMyCjDeDc5EBMiryoT9tz94VvgjKfzecHAVnqmXAwQDcr7X4JmLc2cjkjFGCVzhMqDjgR9g==
|
||||
dependencies:
|
||||
test-value "^1.0.1"
|
||||
|
||||
reduce-flatten@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-1.0.1.tgz#258c78efd153ddf93cb561237f61184f3696e327"
|
||||
integrity sha512-j5WfFJfc9CoXv/WbwVLHq74i/hdTUpy+iNC534LxczMRP67vJeK3V9JOdnL0N1cIRbn9mYhE2yVjvvKXDxvNXQ==
|
||||
|
||||
reduce-flatten@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-3.0.1.tgz#3db6b48ced1f4dbe4f4f5e31e422aa9ff0cd21ba"
|
||||
integrity sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==
|
||||
|
||||
reduce-unique@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/reduce-unique/-/reduce-unique-2.0.1.tgz#fb34b90e89297c1e08d75dcf17e9a6443ea71081"
|
||||
integrity sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==
|
||||
|
||||
reduce-without@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/reduce-without/-/reduce-without-1.0.1.tgz#68ad0ead11855c9a37d4e8256c15bbf87972fc8c"
|
||||
integrity sha512-zQv5y/cf85sxvdrKPlfcRzlDn/OqKFThNimYmsS3flmkioKvkUGn2Qg9cJVoQiEvdxFGLE0MQER/9fZ9sUqdxg==
|
||||
dependencies:
|
||||
test-value "^2.0.0"
|
||||
|
||||
regexpp@^3.0.0, regexpp@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
|
||||
|
@ -2619,47 +2375,22 @@ snake-case@^3.0.3:
|
|||
dot-case "^3.0.4"
|
||||
tslib "^2.0.3"
|
||||
|
||||
sort-array@^4.1.5:
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/sort-array/-/sort-array-4.1.5.tgz#64b92aaba222aec606786f4df28ae4e3e3e68313"
|
||||
integrity sha512-Ya4peoS1fgFN42RN1REk2FgdNOeLIEMKFGJvs7VTP3OklF8+kl2SkpVliZ4tk/PurWsrWRsdNdU+tgyOBkB9sA==
|
||||
dependencies:
|
||||
array-back "^5.0.0"
|
||||
typical "^6.0.1"
|
||||
|
||||
source-map-js@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
|
||||
source-map@^0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
squoosh@discourse/squoosh#dc9649d:
|
||||
version "2.0.0"
|
||||
resolved "https://codeload.github.com/discourse/squoosh/tar.gz/dc9649d0a4d396d1251c22291b17d99f1716da44"
|
||||
dependencies:
|
||||
wasm-feature-detect "^1.2.11"
|
||||
|
||||
stream-connect@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/stream-connect/-/stream-connect-1.0.2.tgz#18bc81f2edb35b8b5d9a8009200a985314428a97"
|
||||
integrity sha512-68Kl+79cE0RGKemKkhxTSg8+6AGrqBt+cbZAXevg2iJ6Y3zX4JhA/sZeGzLpxW9cXhmqAcE7KnJCisUmIUfnFQ==
|
||||
dependencies:
|
||||
array-back "^1.0.2"
|
||||
|
||||
stream-shift@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
|
||||
integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
|
||||
|
||||
stream-via@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/stream-via/-/stream-via-1.0.4.tgz#8dccbb0ac909328eb8bc8e2a4bd3934afdaf606c"
|
||||
integrity sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
|
@ -2714,16 +2445,15 @@ supports-preserve-symlinks-flag@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
table-layout@^0.4.2:
|
||||
version "0.4.5"
|
||||
resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-0.4.5.tgz#d906de6a25fa09c0c90d1d08ecd833ecedcb7378"
|
||||
integrity sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==
|
||||
dependencies:
|
||||
array-back "^2.0.0"
|
||||
deep-extend "~0.6.0"
|
||||
lodash.padend "^4.6.1"
|
||||
typical "^2.6.1"
|
||||
wordwrapjs "^3.0.0"
|
||||
taffydb@2.6.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268"
|
||||
integrity sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==
|
||||
|
||||
taffydb@^2.7.3:
|
||||
version "2.7.3"
|
||||
resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.7.3.tgz#2ad37169629498fca5bc84243096d3cde0ec3a34"
|
||||
integrity sha512-GQ3gtYFSOAxSMN/apGtDKKkbJf+8izz5YfbGqIsUc7AMiQOapARZ76dhilRY2h39cynYxBFdafQo5HUL5vgkrg==
|
||||
|
||||
tar-fs@2.1.1:
|
||||
version "2.1.1"
|
||||
|
@ -2746,35 +2476,6 @@ tar-stream@^2.1.4:
|
|||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
temp-path@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/temp-path/-/temp-path-1.0.0.tgz#24b1543973ab442896d9ad367dd9cbdbfafe918b"
|
||||
integrity sha512-TvmyH7kC6ZVTYkqCODjJIbgvu0FKiwQpZ4D1aknE7xpcDf/qEOB8KZEK5ef2pfbVoiBhNWs3yx4y+ESMtNYmlg==
|
||||
|
||||
test-value@^1.0.1:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/test-value/-/test-value-1.1.0.tgz#a09136f72ec043d27c893707c2b159bfad7de93f"
|
||||
integrity sha512-wrsbRo7qP+2Je8x8DsK8ovCGyxe3sYfQwOraIY/09A2gFXU9DYKiTF14W4ki/01AEh56kMzAmlj9CaHGDDUBJA==
|
||||
dependencies:
|
||||
array-back "^1.0.2"
|
||||
typical "^2.4.2"
|
||||
|
||||
test-value@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291"
|
||||
integrity sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w==
|
||||
dependencies:
|
||||
array-back "^1.0.3"
|
||||
typical "^2.6.0"
|
||||
|
||||
test-value@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/test-value/-/test-value-3.0.0.tgz#9168c062fab11a86b8d444dd968bb4b73851ce92"
|
||||
integrity sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==
|
||||
dependencies:
|
||||
array-back "^2.0.0"
|
||||
typical "^2.6.1"
|
||||
|
||||
text-table@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||
|
@ -2801,6 +2502,15 @@ through@^2.3.8:
|
|||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
||||
|
||||
tidy-jsdoc@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/tidy-jsdoc/-/tidy-jsdoc-1.4.1.tgz#609289afb4094c4b4cb4367cbce746f940232edd"
|
||||
integrity sha512-FpH1oL6fEMMO0qPPAjoV8peAriwTjdys92TMsfMufrDERDGfmg2w90ieqOQ4RGDH7yuvDTqxR7a0W1Mfun8fzA==
|
||||
dependencies:
|
||||
jsdoc "^3.6.3"
|
||||
taffydb "^2.7.3"
|
||||
util "^0.10.3"
|
||||
|
||||
tmp@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
|
||||
|
@ -2855,31 +2565,11 @@ type-fest@^0.20.2:
|
|||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
|
||||
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
|
||||
|
||||
typical@^2.4.2, typical@^2.6.0, typical@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d"
|
||||
integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg==
|
||||
|
||||
typical@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4"
|
||||
integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==
|
||||
|
||||
typical@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/typical/-/typical-6.0.1.tgz#89bd1a6aa5e5e96fa907fb6b7579223bff558a06"
|
||||
integrity sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==
|
||||
|
||||
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.17.4"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c"
|
||||
integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==
|
||||
|
||||
unbzip2-stream@1.4.3:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7"
|
||||
|
@ -2936,21 +2626,18 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
util@^0.10.3:
|
||||
version "0.10.4"
|
||||
resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901"
|
||||
integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==
|
||||
dependencies:
|
||||
inherits "2.0.3"
|
||||
|
||||
v8-compile-cache@^2.0.3, v8-compile-cache@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
|
||||
|
||||
walk-back@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/walk-back/-/walk-back-2.0.1.tgz#554e2a9d874fac47a8cb006bf44c2f0c4998a0a4"
|
||||
integrity sha512-Nb6GvBR8UWX1D+Le+xUq0+Q1kFmRBIWVrfLnQAOmcpEzA9oAxwJ9gIr36t9TWYfzvWRvuMtjHiVsJYEkXWaTAQ==
|
||||
|
||||
walk-back@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/walk-back/-/walk-back-5.1.0.tgz#486d6f29e67f56ab89b952d987028bbb1a4e956c"
|
||||
integrity sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==
|
||||
|
||||
wasm-feature-detect@^1.2.11:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/wasm-feature-detect/-/wasm-feature-detect-1.3.0.tgz#fb3fc5dd4a1ba950a429be843daad67fe048bc42"
|
||||
|
@ -2988,19 +2675,6 @@ word-wrap@^1.2.3:
|
|||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
||||
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
|
||||
|
||||
wordwrap@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
|
||||
integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
|
||||
|
||||
wordwrapjs@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-3.0.0.tgz#c94c372894cadc6feb1a66bff64e1d9af92c5d1e"
|
||||
integrity sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==
|
||||
dependencies:
|
||||
reduce-flatten "^1.0.1"
|
||||
typical "^2.6.1"
|
||||
|
||||
workbox-cacheable-response@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-4.3.1.tgz#f53e079179c095a3f19e5313b284975c91428c91"
|
||||
|
|
Loading…
Reference in New Issue