Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4ee4ff9d03 | ||
|
c61dbfea14 |
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -23,6 +23,3 @@ erd.pdf
|
||||||
config/database.yml
|
config/database.yml
|
||||||
.env
|
.env
|
||||||
.env*
|
.env*
|
||||||
|
|
||||||
lolcommit.yml
|
|
||||||
*.swp
|
|
||||||
|
|
26
Gemfile
26
Gemfile
|
@ -1,5 +1,6 @@
|
||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
|
|
||||||
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
||||||
gem 'rails', '4.2.1'
|
gem 'rails', '4.2.1'
|
||||||
# Use sqlite3 as the database for Active Record
|
# Use sqlite3 as the database for Active Record
|
||||||
|
@ -15,7 +16,6 @@ gem 'coffee-rails', '~> 4.1.0'
|
||||||
|
|
||||||
# Use jquery as the JavaScript library
|
# Use jquery as the JavaScript library
|
||||||
gem 'jquery-rails'
|
gem 'jquery-rails'
|
||||||
gem 'jquery-ui-rails'
|
|
||||||
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
|
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
|
||||||
gem 'turbolinks'
|
gem 'turbolinks'
|
||||||
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
|
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
|
||||||
|
@ -24,7 +24,7 @@ gem 'jbuilder', '~> 2.0'
|
||||||
# bundle exec rake doc:rails generates the API under doc/api.
|
# bundle exec rake doc:rails generates the API under doc/api.
|
||||||
group :doc do
|
group :doc do
|
||||||
gem 'sdoc', '~> 0.4.0'
|
gem 'sdoc', '~> 0.4.0'
|
||||||
gem 'rails-erd'
|
gem 'erd'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Use ActiveModel has_secure_password
|
# Use ActiveModel has_secure_password
|
||||||
|
@ -50,25 +50,19 @@ end
|
||||||
|
|
||||||
# Web Server
|
# Web Server
|
||||||
gem 'puma'
|
gem 'puma'
|
||||||
# Environnement .env
|
|
||||||
gem 'dotenv-rails'
|
|
||||||
# Database
|
# Database
|
||||||
gem 'pg'
|
gem 'pg'
|
||||||
|
|
||||||
# Users
|
|
||||||
gem 'devise'
|
|
||||||
# Upload
|
# Upload
|
||||||
gem 'carrierwave'
|
gem 'carrierwave'
|
||||||
# Commentable items
|
# Environnement .env
|
||||||
gem 'acts_as_commentable'
|
gem 'dotenv-rails'
|
||||||
|
# Users
|
||||||
# HTML Templating
|
gem 'devise'
|
||||||
gem 'slim-rails'
|
|
||||||
# Bootstrap
|
|
||||||
gem "twitter-bootstrap-rails"
|
|
||||||
# Pagination
|
# Pagination
|
||||||
gem 'will_paginate'
|
gem 'will_paginate'
|
||||||
|
# Bootstrap
|
||||||
|
gem 'bootstrap-sass'
|
||||||
# Bootstrap for pagination
|
# Bootstrap for pagination
|
||||||
gem 'bootstrap-will_paginate'
|
gem 'bootstrap-will_paginate'
|
||||||
# Autocomplete for ids
|
# HTML Templating
|
||||||
gem 'rails-jquery-autocomplete'
|
gem 'slim-rails'
|
||||||
|
|
58
Gemfile.lock
58
Gemfile.lock
|
@ -36,11 +36,16 @@ GEM
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
thread_safe (~> 0.3, >= 0.3.4)
|
thread_safe (~> 0.3, >= 0.3.4)
|
||||||
tzinfo (~> 1.1)
|
tzinfo (~> 1.1)
|
||||||
acts_as_commentable (4.0.2)
|
arel (6.0.0)
|
||||||
arel (6.0.3)
|
autoprefixer-rails (5.2.0.1)
|
||||||
|
execjs
|
||||||
|
json
|
||||||
bcrypt (3.1.10)
|
bcrypt (3.1.10)
|
||||||
binding_of_caller (0.7.2)
|
binding_of_caller (0.7.2)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
|
bootstrap-sass (3.3.5)
|
||||||
|
autoprefixer-rails (>= 5.0.0.1)
|
||||||
|
sass (>= 3.2.19)
|
||||||
bootstrap-will_paginate (0.0.10)
|
bootstrap-will_paginate (0.0.10)
|
||||||
will_paginate
|
will_paginate
|
||||||
builder (3.2.2)
|
builder (3.2.2)
|
||||||
|
@ -69,24 +74,24 @@ GEM
|
||||||
responders
|
responders
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
dotenv (2.0.2)
|
dotenv (2.0.1)
|
||||||
dotenv-rails (2.0.2)
|
dotenv-rails (2.0.1)
|
||||||
dotenv (= 2.0.2)
|
dotenv (= 2.0.1)
|
||||||
railties (~> 4.0)
|
erd (0.3.2)
|
||||||
|
nokogiri
|
||||||
|
rails-erd (>= 0.4.5)
|
||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
execjs (2.5.2)
|
execjs (2.5.2)
|
||||||
globalid (0.3.6)
|
globalid (0.3.5)
|
||||||
activesupport (>= 4.1.0)
|
activesupport (>= 4.1.0)
|
||||||
i18n (0.7.0)
|
i18n (0.7.0)
|
||||||
jbuilder (2.3.1)
|
jbuilder (2.3.0)
|
||||||
activesupport (>= 3.0.0, < 5)
|
activesupport (>= 3.0.0, < 5)
|
||||||
multi_json (~> 1.2)
|
multi_json (~> 1.2)
|
||||||
jquery-rails (4.0.4)
|
jquery-rails (4.0.4)
|
||||||
rails-dom-testing (~> 1.0)
|
rails-dom-testing (~> 1.0)
|
||||||
railties (>= 4.2.0)
|
railties (>= 4.2.0)
|
||||||
thor (>= 0.14, < 2.0)
|
thor (>= 0.14, < 2.0)
|
||||||
jquery-ui-rails (5.0.5)
|
|
||||||
railties (>= 3.2.16)
|
|
||||||
json (1.8.3)
|
json (1.8.3)
|
||||||
loofah (2.0.2)
|
loofah (2.0.2)
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.5.9)
|
||||||
|
@ -95,8 +100,8 @@ GEM
|
||||||
method_source (0.8.2)
|
method_source (0.8.2)
|
||||||
mime-types (2.6.1)
|
mime-types (2.6.1)
|
||||||
mini_portile (0.6.2)
|
mini_portile (0.6.2)
|
||||||
minitest (5.8.0)
|
minitest (5.7.0)
|
||||||
multi_json (1.11.2)
|
multi_json (1.11.1)
|
||||||
nokogiri (1.6.6.2)
|
nokogiri (1.6.6.2)
|
||||||
mini_portile (~> 0.6.0)
|
mini_portile (~> 0.6.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
|
@ -105,8 +110,9 @@ GEM
|
||||||
coderay (~> 1.1.0)
|
coderay (~> 1.1.0)
|
||||||
method_source (~> 0.8.1)
|
method_source (~> 0.8.1)
|
||||||
slop (~> 3.4)
|
slop (~> 3.4)
|
||||||
puma (2.12.3)
|
puma (2.11.3)
|
||||||
rack (1.6.4)
|
rack (>= 1.1, < 2.0)
|
||||||
|
rack (1.6.2)
|
||||||
rack-test (0.6.3)
|
rack-test (0.6.3)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
rails (4.2.1)
|
rails (4.2.1)
|
||||||
|
@ -126,15 +132,13 @@ GEM
|
||||||
activesupport (>= 4.2.0.beta, < 5.0)
|
activesupport (>= 4.2.0.beta, < 5.0)
|
||||||
nokogiri (~> 1.6.0)
|
nokogiri (~> 1.6.0)
|
||||||
rails-deprecated_sanitizer (>= 1.0.1)
|
rails-deprecated_sanitizer (>= 1.0.1)
|
||||||
rails-erd (1.4.2)
|
rails-erd (1.4.0)
|
||||||
activerecord (>= 3.2)
|
activerecord (>= 3.2)
|
||||||
activesupport (>= 3.2)
|
activesupport (>= 3.2)
|
||||||
choice (~> 0.2.0)
|
choice (~> 0.2.0)
|
||||||
ruby-graphviz (~> 1.2)
|
ruby-graphviz (~> 1.2)
|
||||||
rails-html-sanitizer (1.0.2)
|
rails-html-sanitizer (1.0.2)
|
||||||
loofah (~> 2.0)
|
loofah (~> 2.0)
|
||||||
rails-jquery-autocomplete (1.0.3)
|
|
||||||
rails (>= 3.2)
|
|
||||||
railties (4.2.1)
|
railties (4.2.1)
|
||||||
actionpack (= 4.2.1)
|
actionpack (= 4.2.1)
|
||||||
activesupport (= 4.2.1)
|
activesupport (= 4.2.1)
|
||||||
|
@ -145,7 +149,7 @@ GEM
|
||||||
responders (2.1.0)
|
responders (2.1.0)
|
||||||
railties (>= 4.2.0, < 5)
|
railties (>= 4.2.0, < 5)
|
||||||
ruby-graphviz (1.2.2)
|
ruby-graphviz (1.2.2)
|
||||||
sass (3.4.16)
|
sass (3.4.14)
|
||||||
sass-rails (5.0.3)
|
sass-rails (5.0.3)
|
||||||
railties (>= 4.0.0, < 5.0)
|
railties (>= 4.0.0, < 5.0)
|
||||||
sass (~> 3.1)
|
sass (~> 3.1)
|
||||||
|
@ -168,7 +172,7 @@ GEM
|
||||||
spring (1.3.6)
|
spring (1.3.6)
|
||||||
sprockets (3.2.0)
|
sprockets (3.2.0)
|
||||||
rack (~> 1.0)
|
rack (~> 1.0)
|
||||||
sprockets-rails (2.3.2)
|
sprockets-rails (2.3.1)
|
||||||
actionpack (>= 3.0)
|
actionpack (>= 3.0)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
sprockets (>= 2.8, < 4.0)
|
sprockets (>= 2.8, < 4.0)
|
||||||
|
@ -178,11 +182,6 @@ GEM
|
||||||
tilt (1.4.1)
|
tilt (1.4.1)
|
||||||
turbolinks (2.5.3)
|
turbolinks (2.5.3)
|
||||||
coffee-rails
|
coffee-rails
|
||||||
twitter-bootstrap-rails (3.2.0)
|
|
||||||
actionpack (~> 4.1)
|
|
||||||
execjs (~> 2.2)
|
|
||||||
rails (~> 4.1)
|
|
||||||
railties (~> 4.1)
|
|
||||||
tzinfo (1.2.2)
|
tzinfo (1.2.2)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
uglifier (2.7.1)
|
uglifier (2.7.1)
|
||||||
|
@ -190,7 +189,7 @@ GEM
|
||||||
json (>= 1.8.0)
|
json (>= 1.8.0)
|
||||||
warden (1.2.3)
|
warden (1.2.3)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
web-console (2.2.1)
|
web-console (2.1.3)
|
||||||
activemodel (>= 4.0)
|
activemodel (>= 4.0)
|
||||||
binding_of_caller (>= 0.7.2)
|
binding_of_caller (>= 0.7.2)
|
||||||
railties (>= 4.0)
|
railties (>= 4.0)
|
||||||
|
@ -201,31 +200,28 @@ PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
acts_as_commentable
|
bootstrap-sass
|
||||||
bootstrap-will_paginate
|
bootstrap-will_paginate
|
||||||
byebug
|
byebug
|
||||||
carrierwave
|
carrierwave
|
||||||
coffee-rails (~> 4.1.0)
|
coffee-rails (~> 4.1.0)
|
||||||
devise
|
devise
|
||||||
dotenv-rails
|
dotenv-rails
|
||||||
|
erd
|
||||||
jbuilder (~> 2.0)
|
jbuilder (~> 2.0)
|
||||||
jquery-rails
|
jquery-rails
|
||||||
jquery-ui-rails
|
|
||||||
pg
|
pg
|
||||||
pry
|
pry
|
||||||
puma
|
puma
|
||||||
rails (= 4.2.1)
|
rails (= 4.2.1)
|
||||||
rails-erd
|
|
||||||
rails-jquery-autocomplete
|
|
||||||
sass-rails (~> 5.0)
|
sass-rails (~> 5.0)
|
||||||
sdoc (~> 0.4.0)
|
sdoc (~> 0.4.0)
|
||||||
slim-rails
|
slim-rails
|
||||||
spring
|
spring
|
||||||
turbolinks
|
turbolinks
|
||||||
twitter-bootstrap-rails
|
|
||||||
uglifier (>= 1.3.0)
|
uglifier (>= 1.3.0)
|
||||||
web-console (~> 2.0)
|
web-console (~> 2.0)
|
||||||
will_paginate
|
will_paginate
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.11.2
|
1.10.3
|
||||||
|
|
675
License
675
License
|
@ -1,675 +0,0 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
|
||||||
software and other kinds of works.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
|
||||||
to take away your freedom to share and change the works. By contrast,
|
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
|
||||||
share and change all versions of a program--to make sure it remains free
|
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
|
||||||
GNU General Public License for most of our software; it applies also to
|
|
||||||
any other work released this way by its authors. You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
|
||||||
or can get the source code. And you must show them these terms so they
|
|
||||||
know their rights.
|
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
|
||||||
that there is no warranty for this free software. For both users' and
|
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
|
||||||
changed, so that their problems will not be attributed erroneously to
|
|
||||||
authors of previous versions.
|
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run
|
|
||||||
modified versions of the software inside them, although the manufacturer
|
|
||||||
can do so. This is fundamentally incompatible with the aim of
|
|
||||||
protecting users' freedom to change the software. The systematic
|
|
||||||
pattern of such abuse occurs in the area of products for individuals to
|
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we
|
|
||||||
have designed this version of the GPL to prohibit the practice for those
|
|
||||||
products. If such problems arise substantially in other domains, we
|
|
||||||
stand ready to extend this provision to those domains in future versions
|
|
||||||
of the GPL, as needed to protect the freedom of users.
|
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents.
|
|
||||||
States should not allow patents to restrict development and use of
|
|
||||||
software on general-purpose computers, but in those that do, we wish to
|
|
||||||
avoid the special danger that patents applied to a free program could
|
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that
|
|
||||||
patents cannot be used to render the program non-free.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the special requirements of the GNU Affero General Public License,
|
|
||||||
section 13, concerning interaction through a network will apply to the
|
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
{one line to give the program's name and a brief idea of what it does.}
|
|
||||||
Copyright (C) 2015 {name of author}
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
|
||||||
notice like this when it starts in an interactive mode:
|
|
||||||
|
|
||||||
MorningPeak Copyright (C) 2015 Arthur Poulet
|
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
|
||||||
<http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
||||||
|
|
138
README.md
138
README.md
|
@ -1,133 +1,51 @@
|
||||||
# Project Presentation
|
# Installation
|
||||||
|
|
||||||
_Morning Peak is a modern and OpenSource Web Application.
|
## Requirements
|
||||||
It has been designed to manage clients, bills, and issues for little and medium compagnies._
|
|
||||||
|
|
||||||
<img att="Dashboard Mobile view" src="http://imgur.com/bnYHYJ6l.png" width="200" />
|
- First install ruby 2 or greater. It is not advised to do the following commands as ``root``.
|
||||||
<img alt="Dashboard Desktop view" src="http://i.imgur.com/oxE9LR1.png" width="500" />
|
- Then, be sure you have postgresql installed, and started.
|
||||||
|
|
||||||
There is a lot of CRM on the web. Some of them are web application. Some of them are open source. Some of them are modern.
|
## Initialization
|
||||||
But, I __never see any of them grouping the 3__. It is why I started to develop this application.
|
|
||||||
To improve my skills, my knowledges, and to use it.
|
|
||||||
|
|
||||||
I want a simple application, that I __understand__, and that I __need__. By __simple__, I mean:
|
|
||||||
|
|
||||||
- No tasks, no reports, no chat. I want an application to do ONE thing, manage my clients, and it must do it clearly, and good.
|
|
||||||
- A pluggable application, with many __REST API__. Because tasks and reports are usefull.
|
|
||||||
- Generic items. I prefere __ONE kind of Bills + Tags__ than __4 ou 5 kinds of Bills__ (for example).
|
|
||||||
|
|
||||||
<img alt="Tickets Desktop view" src="http://i.imgur.com/e004zBZ.png" width="500" />
|
|
||||||
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
1. [Installation](#1-installation)
|
|
||||||
1. [Requirements](#11-requirements)
|
|
||||||
2. [Initialization](#12-initialization)
|
|
||||||
3. [Configuration](#13-configuration)
|
|
||||||
4. [First start](#14-first-start)
|
|
||||||
2. [Contributions](#2-contributions)
|
|
||||||
1. [Contributors](#21-contributors)
|
|
||||||
2. [How to contribute](#22-how-to-contribute-)
|
|
||||||
3. [License](#23-license)
|
|
||||||
3. [Architecture](#3-architecture)
|
|
||||||
1. [Modelisation](#31-modelisation)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 1. Installation
|
|
||||||
|
|
||||||
## 1.1. Requirements
|
|
||||||
- Ruby 2.0 or greater.
|
|
||||||
- Postgresql server 9 or greater running with creditentials.
|
|
||||||
|
|
||||||
## 1.2. Initialization
|
|
||||||
Start by pasting this script in your shell:
|
|
||||||
```bash
|
```bash
|
||||||
cd MorningPeak/
|
cd Appli/
|
||||||
gem install bundler
|
gem install bundler
|
||||||
bundle install
|
bundle install
|
||||||
cp config/database.yml.example config/database.yml
|
cp config/database.yml.example config/database.yml
|
||||||
edit config/database.yml # Configure your database connection first
|
edit config/database.yml # Configure your database connection first
|
||||||
rake db:create
|
rake db:create # create the db
|
||||||
rake db:migrate
|
rake db:migrate # migrate the db
|
||||||
rake db:seed # will generate default data. Not on production ;)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 1.3. Configuration
|
you can try with an first example of dataset :
|
||||||
- You can create a file ``.env`` to save your locals cvars without pollute your global env.
|
|
||||||
- You can also create ``.env.production`` etc. for environement specifics cvars
|
```
|
||||||
- A ``.env`` file looks like:
|
rake db:seed
|
||||||
```text
|
|
||||||
COMPANY: "Yolo production"
|
|
||||||
LOCALE: fr
|
|
||||||
...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- The application's specifics cvars are :
|
## Running
|
||||||
- COMPANY
|
|
||||||
|
You can run the server by :
|
||||||
|
|
||||||
## 1.4. First start
|
|
||||||
When you done with the configuration of the database (editing ``config/database.yml``),
|
|
||||||
you can run the server by the following command :
|
|
||||||
```
|
```
|
||||||
rails s # "-b 0.0.0.0 -p 80" to test on internet :)
|
rails s
|
||||||
```
|
```
|
||||||
|
|
||||||
The server will be accessible via [localhost:3000](http://localhost:3000)
|
The server will be accessible via [localhost](http://localhost:3000)
|
||||||
|
|
||||||
Default creditentials are generated in the seed:
|
# Organisation MVC
|
||||||
|
|
||||||
```text
|
Guide documentation : [visit](http://guides.rubyonrails.org/)
|
||||||
user> login: user@client.com , password: user2015
|
|
||||||
```
|
|
||||||
|
|
||||||
```text
|
The RoR Project works with some main parts :
|
||||||
admin> login: admin@admin.admin , password: wir2015
|
|
||||||
```
|
|
||||||
|
|
||||||
Checkout for [rails minidoc](RailsMinidoc.md) for a resume of rails.
|
- __/config/routes.rb__ : the routing. The url accessible from http://... will call a Controller.method
|
||||||
|
- __/app/controllers/*__ : the controllers. they act from the parameters from the calling url
|
||||||
|
- __/app/models/*__ : the modelisation of the database
|
||||||
|
- __/app/views/*/*__ : the views rendered after the controller
|
||||||
|
- __/db/migrate/*__ : the migrations. They represents the state of the databases
|
||||||
|
- __/app/assets/__ : all stylesheets css, javascript, images
|
||||||
|
|
||||||
|
# Contributors
|
||||||
|
|
||||||
# 2. Contributions
|
- poulet_a (as lead)
|
||||||
|
|
||||||
## 2.1. Contributors
|
|
||||||
- __Arthur Poulet__ : main developper, upstream (poulet_a)
|
|
||||||
<img alt="Look at this cute face" src="https://pbs.twimg.com/media/CJ_ErJ2W8AAdev3.jpg" width="200" height="150" />
|
|
||||||
|
|
||||||
## 2.2. How to contribute ?
|
|
||||||
You can contribute to this project by Merge Request on the gitlab repository [here](https://gitlab.com/poulet_a/MorningPeak).
|
|
||||||
The best pratices are to create short commits, and short Merge Requests. Respect the git commit nomage convention as possible with:
|
|
||||||
|
|
||||||
- title
|
|
||||||
- description
|
|
||||||
- concerned issues with "#id"
|
|
||||||
|
|
||||||
We accept any kind of work : translations, bug fix, additionnal features, optimizations, documentation, etc.
|
|
||||||
|
|
||||||
Don't be afraid !
|
|
||||||
|
|
||||||
## 2.3. License
|
|
||||||
|
|
||||||
see the license in the ``License`` file.
|
|
||||||
|
|
||||||
It is under:
|
|
||||||
|
|
||||||
```text
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
```
|
|
||||||
|
|
||||||
# 3. Architecture
|
|
||||||
|
|
||||||
## 3.1 Modelisation
|
|
||||||
|
|
||||||
### Creation and belongs
|
|
||||||
- User has a Client (which is created when the user is created)
|
|
||||||
- Client has many Contacts and Bills
|
|
||||||
- User/Admin has many Tickets and Comments
|
|
||||||
|
|
||||||
### Permissions
|
|
||||||
- Admin can Comment, Read, Edit, Delete, and Create everything
|
|
||||||
- User can open Ticket, Anwser and Close them.
|
|
||||||
- User can Read every Bills wich is associated to him
|
|
||||||
- User can not read his client informations (like notes, ...)
|
|
||||||
|
|
28
README.rdoc
Normal file
28
README.rdoc
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
== README
|
||||||
|
|
||||||
|
This README would normally document whatever steps are necessary to get the
|
||||||
|
application up and running.
|
||||||
|
|
||||||
|
Things you may want to cover:
|
||||||
|
|
||||||
|
* Ruby version
|
||||||
|
|
||||||
|
* System dependencies
|
||||||
|
|
||||||
|
* Configuration
|
||||||
|
|
||||||
|
* Database creation
|
||||||
|
|
||||||
|
* Database initialization
|
||||||
|
|
||||||
|
* How to run the test suite
|
||||||
|
|
||||||
|
* Services (job queues, cache servers, search engines, etc.)
|
||||||
|
|
||||||
|
* Deployment instructions
|
||||||
|
|
||||||
|
* ...
|
||||||
|
|
||||||
|
|
||||||
|
Please feel free to use a different markup language if you do not plan to run
|
||||||
|
<tt>rake doc:app</tt>.
|
|
@ -1,22 +0,0 @@
|
||||||
# Rails minidoc
|
|
||||||
|
|
||||||
Guide documentation : [visit](http://guides.rubyonrails.org/)
|
|
||||||
|
|
||||||
The RoR Project works with some main parts :
|
|
||||||
|
|
||||||
- __/config/routes.rb__ : the routing. The url accessible from http://... will call a Controller.method
|
|
||||||
- __/app/controllers/*__ : the controllers. they are the mind using the parameters and choosing the render to use
|
|
||||||
- __/app/models/*__ : the modelisation of the database
|
|
||||||
- __/app/views/*/*__ : the views rendered after the controller
|
|
||||||
- __/db/migrate/*__ : the migrations. They represents the state of the databases
|
|
||||||
- __/app/assets/__ : all stylesheets css, javascript, images
|
|
||||||
|
|
||||||
## Create a new table, upgrade, etc.
|
|
||||||
|
|
||||||
### Create a table
|
|
||||||
|
|
||||||
Creating a new table = Create a new migration. Use the command like ``rails generate Table data1:string data2:integer`` etc.
|
|
||||||
|
|
||||||
### Change an existing table
|
|
||||||
|
|
||||||
Each changement on the database needs a migration. ``rails g migration``.
|
|
Binary file not shown.
Before Width: | Height: | Size: 21 KiB |
Binary file not shown.
Before Width: | Height: | Size: 36 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
Before Width: | Height: | Size: 52 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.4 KiB |
|
@ -12,8 +12,5 @@
|
||||||
//
|
//
|
||||||
//= require jquery
|
//= require jquery
|
||||||
//= require jquery_ujs
|
//= require jquery_ujs
|
||||||
//= require jquery-ui
|
//= require turbolinks
|
||||||
//= require twitter/bootstrap
|
|
||||||
//= require jquery-ui/autocomplete
|
|
||||||
//= require autocomplete-rails
|
|
||||||
//= require_tree .
|
//= require_tree .
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
jQuery ->
|
|
||||||
$("a[rel~=popover], .has-popover").popover()
|
|
||||||
$("a[rel~=tooltip], .has-tooltip").tooltip()
|
|
|
@ -1,11 +0,0 @@
|
||||||
commentableLoadComments = (base_url) ->
|
|
||||||
$.get(base_url + "/comments/about").done (e) ->
|
|
||||||
$("#comments").html(e)
|
|
||||||
|
|
||||||
$(document).ready ->
|
|
||||||
url = window.location.pathname
|
|
||||||
commentableLoadComments(url)
|
|
||||||
$(document).on "ajax:success", "#new_comment", (e, data, status, xhr) ->
|
|
||||||
commentableLoadComments(url)
|
|
||||||
$(document).on "ajax:complete", ".remove-comment", (e, data, status, xhr) ->
|
|
||||||
commentableLoadComments(url)
|
|
|
@ -1,10 +1,3 @@
|
||||||
# Place all the behaviors and hooks related to the matching controller here.
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
# All this logic will automatically be available in application.js.
|
# All this logic will automatically be available in application.js.
|
||||||
# You can use CoffeeScript in this file: http://coffeescript.org/
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
updateViewAtWhenClick = () ->
|
|
||||||
$('.contact-link-view_at').bind('ajax:success', (event, data, status, xhr) ->
|
|
||||||
this.parentElement.children[7].textContent = data["view_at"]
|
|
||||||
)
|
|
||||||
|
|
||||||
$ ->
|
|
||||||
updateViewAtWhenClick()
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
$ ->
|
|
||||||
# $("#contact_view_at").datepicker()
|
|
||||||
$(".form-date").datepicker({ dateFormat: 'yy-mm-dd' })
|
|
|
@ -1,17 +0,0 @@
|
||||||
/*
|
|
||||||
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
||||||
* listed below.
|
|
||||||
*
|
|
||||||
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
||||||
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
|
||||||
*
|
|
||||||
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
||||||
* compiled file so the styles you add here take precedence over styles defined in any styles
|
|
||||||
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
|
||||||
* file per style scope.
|
|
||||||
*
|
|
||||||
*= require jquery-ui
|
|
||||||
*= require_tree .
|
|
||||||
*= require_self
|
|
||||||
*= require "dashboard"
|
|
||||||
*/
|
|
2
app/assets/stylesheets/application.css.sass
Normal file
2
app/assets/stylesheets/application.css.sass
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
@import 'bootstrap-sprockets'
|
||||||
|
@import 'bootstrap'
|
|
@ -1,7 +0,0 @@
|
||||||
/*
|
|
||||||
=require twitter-bootstrap-static/bootstrap
|
|
||||||
|
|
||||||
Use Font Awesome icons (default)
|
|
||||||
To use Glyphicons sprites instead of Font Awesome, replace with "require twitter-bootstrap-static/sprites"
|
|
||||||
=require twitter-bootstrap-static/fontawesome
|
|
||||||
*/
|
|
|
@ -1,105 +0,0 @@
|
||||||
/*
|
|
||||||
* Base structure
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Move down content because we have a fixed navbar that is 50px tall */
|
|
||||||
body {
|
|
||||||
padding-top: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Global add-ons
|
|
||||||
*/
|
|
||||||
|
|
||||||
.sub-header {
|
|
||||||
padding-bottom: 10px;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Top navigation
|
|
||||||
* Hide default border to remove 1px line.
|
|
||||||
*/
|
|
||||||
.navbar-fixed-top {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sidebar
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Hide for mobile, show later */
|
|
||||||
.sidebar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.sidebar {
|
|
||||||
position: fixed;
|
|
||||||
top: 51px;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
display: block;
|
|
||||||
padding: 20px;
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
border-right: 1px solid #eee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sidebar navigation */
|
|
||||||
.nav-sidebar {
|
|
||||||
margin-right: -21px; /* 20px padding + 1px border */
|
|
||||||
margin-bottom: 20px;
|
|
||||||
margin-left: -20px;
|
|
||||||
}
|
|
||||||
.nav-sidebar > li > a {
|
|
||||||
padding-right: 20px;
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
.nav-sidebar > .active > a,
|
|
||||||
.nav-sidebar > .active > a:hover,
|
|
||||||
.nav-sidebar > .active > a:focus {
|
|
||||||
color: #fff;
|
|
||||||
background-color: #428bca;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Main content
|
|
||||||
*/
|
|
||||||
|
|
||||||
.main {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.main {
|
|
||||||
padding-right: 40px;
|
|
||||||
padding-left: 40px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.main .page-header {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Placeholder dashboard ideas
|
|
||||||
*/
|
|
||||||
|
|
||||||
.placeholders {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.placeholders h4 {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
.placeholder {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
.placeholder img {
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
|
@ -18,16 +18,16 @@ pre {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a { */
|
a {
|
||||||
/* color: #000; */
|
color: #000;
|
||||||
/* &:visited { */
|
&:visited {
|
||||||
/* color: #666; */
|
color: #666;
|
||||||
/* } */
|
}
|
||||||
/* &:hover { */
|
&:hover {
|
||||||
/* color: #fff; */
|
color: #fff;
|
||||||
/* background-color: #000; */
|
background-color: #000;
|
||||||
/* } */
|
}
|
||||||
/* } */
|
}
|
||||||
|
|
||||||
div {
|
div {
|
||||||
&.field, &.actions {
|
&.field, &.actions {
|
||||||
|
@ -35,9 +35,9 @@ div {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #notice { */
|
#notice {
|
||||||
/* color: green; */
|
color: green;
|
||||||
/* } */
|
}
|
||||||
|
|
||||||
.field_with_errors {
|
.field_with_errors {
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
|
|
|
@ -1,8 +1,3 @@
|
||||||
.ticket-description {
|
// Place all the styles related to the tickets controller here.
|
||||||
border: 1px dashed black;
|
// They will automatically be included in application.css.
|
||||||
padding: 10px;
|
// You can use Sass (SCSS) here: http://sass-lang.com/
|
||||||
}
|
|
||||||
|
|
||||||
.ticket-creator {
|
|
||||||
color: #d9534f;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
# Prevent CSRF attacks by raising an exception.
|
# Prevent CSRF attacks by raising an exception.
|
||||||
# For APIs, you may want to use :null_session instead.
|
# For APIs, you may want to use :null_session instead.
|
||||||
|
|
||||||
protect_from_forgery with: :exception
|
protect_from_forgery with: :exception
|
||||||
|
|
||||||
# before_action :authenticate_user!
|
# before_action :authenticate_user!
|
||||||
# before_action :authenticate_admin!
|
# before_action :authenticate_admin!
|
||||||
|
|
||||||
|
# def admin_page!
|
||||||
|
# redirect_to root_url, notice: 'You must be admin to access to this page' if current_user.nil? or not current_user.admin?
|
||||||
|
# end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
class BillsController < ApplicationController
|
class BillsController < ApplicationController
|
||||||
include CommentableForm
|
|
||||||
|
|
||||||
autocomplete :client, :name
|
|
||||||
|
|
||||||
before_action :set_bill, only: [:show, :edit, :update, :destroy]
|
before_action :set_bill, only: [:show, :edit, :update, :destroy]
|
||||||
before_action :authenticate_admin!
|
before_action :authenticate_admin!
|
||||||
|
|
||||||
|
@ -15,7 +11,6 @@ class BillsController < ApplicationController
|
||||||
# GET /bills/1
|
# GET /bills/1
|
||||||
# GET /bills/1.json
|
# GET /bills/1.json
|
||||||
def show
|
def show
|
||||||
prepare_comment_for @bill
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /bills/new
|
# GET /bills/new
|
||||||
|
|
|
@ -1,25 +1,21 @@
|
||||||
class ClientTicketsController < ApplicationController
|
class ClientTicketsController < ApplicationController
|
||||||
include CommentableForm
|
|
||||||
|
|
||||||
before_action :set_ticket, only: [:show, :edit, :update, :destroy]
|
before_action :set_ticket, only: [:show, :edit, :update, :destroy]
|
||||||
before_action :set_ticket_custom_route, only: [:close, :open, :respond]
|
before_action :set_ticket_custom_route, only: [:close, :open, :respond]
|
||||||
before_action :looks_ticket, only: [:show, :edit, :update, :close, :open]
|
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
|
||||||
# GET /tickets
|
# GET /tickets
|
||||||
# GET /tickets.json
|
# GET /tickets.json
|
||||||
def index
|
def index
|
||||||
@tickets = current_user.tickets.order('state DESC')
|
@tickets = current_user.tickets.heads.order('state DESC')
|
||||||
end
|
end
|
||||||
|
|
||||||
def close
|
def close
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @ticket.close
|
if @ticket.close
|
||||||
@ticket.update(admin_view_at: Time.now) # add comment ?
|
format.html { redirect_to tickets_url, notice: 'Ticket was successfully closed.' }
|
||||||
format.html { redirect_to client_ticket_url(@ticket), notice: 'Ticket was successfully closed.' }
|
|
||||||
format.json { render :show, status: :ok, location: client_tickets_url(@ticket) }
|
format.json { render :show, status: :ok, location: client_tickets_url(@ticket) }
|
||||||
else
|
else
|
||||||
format.html { redirect_to client_ticket_url(@ticket), alert: 'The ticket is already close' }
|
format.html { render :index }
|
||||||
format.json { render json: @ticket.errors, status: :unprocessable_entity }
|
format.json { render json: @ticket.errors, status: :unprocessable_entity }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -28,20 +24,33 @@ class ClientTicketsController < ApplicationController
|
||||||
def open
|
def open
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @ticket.open
|
if @ticket.open
|
||||||
@ticket.update(admin_view_at: nil) # add comment ?
|
format.html { redirect_to tickets_url, notice: 'Ticket was successfully reopened.' }
|
||||||
format.html { redirect_to client_ticket_url(@ticket), notice: 'Ticket was successfully reopened.' }
|
|
||||||
format.json { render :show, status: :ok, location: client_tickets_url(@ticket) }
|
format.json { render :show, status: :ok, location: client_tickets_url(@ticket) }
|
||||||
else
|
else
|
||||||
format.html { redirect_to client_ticket_url(@ticket), alert: 'The ticket is already open' }
|
format.html { render :index }
|
||||||
format.json { render json: @ticket.errors, status: :unprocessable_entity }
|
format.json { render json: @ticket.errors, status: :unprocessable_entity }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def respond
|
||||||
|
session[:user_ticket_respond_parent_id] = @ticket.id
|
||||||
|
@ticket = Ticket.new(ticket_id: @ticket.head.id,
|
||||||
|
creator: current_user,
|
||||||
|
title: @ticket.title)
|
||||||
|
if @ticket.close? or @ticket.head.close?
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to tickets_url }
|
||||||
|
format.json { render json: {ticket: 'the ticket is closed'}, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
render :new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# GET /tickets/1
|
# GET /tickets/1
|
||||||
# GET /tickets/1.json
|
# GET /tickets/1.json
|
||||||
def show
|
def show
|
||||||
prepare_comment_for @ticket
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /tickets/new
|
# GET /tickets/new
|
||||||
|
@ -57,11 +66,13 @@ class ClientTicketsController < ApplicationController
|
||||||
# POST /tickets.json
|
# POST /tickets.json
|
||||||
def create
|
def create
|
||||||
@ticket = Ticket.new(ticket_params)
|
@ticket = Ticket.new(ticket_params)
|
||||||
|
@ticket.ticket_id = session[:user_ticket_respond_parent_id]
|
||||||
@ticket.creator = current_user
|
@ticket.creator = current_user
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @ticket.save
|
if @ticket.save
|
||||||
format.html { redirect_to client_ticket_url(@ticket), notice: 'Ticket was successfully created.' }
|
@ticket.close_head if @ticket.close?
|
||||||
|
format.html { redirect_to @ticket, notice: 'Ticket was successfully created.' }
|
||||||
format.json { render :show, status: :created, location: client_tickets_url(@ticket) }
|
format.json { render :show, status: :created, location: client_tickets_url(@ticket) }
|
||||||
else
|
else
|
||||||
format.html { render :new }
|
format.html { render :new }
|
||||||
|
@ -75,6 +86,7 @@ class ClientTicketsController < ApplicationController
|
||||||
def update
|
def update
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @ticket.update(ticket_params)
|
if @ticket.update(ticket_params)
|
||||||
|
@ticket.close_head if @ticket.close?
|
||||||
format.html { redirect_to @ticket, notice: 'Ticket was successfully updated.' }
|
format.html { redirect_to @ticket, notice: 'Ticket was successfully updated.' }
|
||||||
format.json { render :show, status: :ok, location: client_tickets_url(@ticket) }
|
format.json { render :show, status: :ok, location: client_tickets_url(@ticket) }
|
||||||
else
|
else
|
||||||
|
@ -97,11 +109,11 @@ class ClientTicketsController < ApplicationController
|
||||||
private
|
private
|
||||||
# Use callbacks to share common setup or constraints between actions.
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
def set_ticket
|
def set_ticket
|
||||||
@ticket = Ticket.find_by(id: params[:id], creator: current_user)
|
@ticket = Ticket.find(params[:id])
|
||||||
|
@ticket = nil if not @ticket.creator == current_user and not @ticket.head.creator == current_user
|
||||||
@ticket
|
@ticket
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: remove
|
|
||||||
def set_ticket_custom_route
|
def set_ticket_custom_route
|
||||||
params[:id] = params[:client_ticket_id]
|
params[:id] = params[:client_ticket_id]
|
||||||
set_ticket
|
set_ticket
|
||||||
|
@ -112,8 +124,4 @@ class ClientTicketsController < ApplicationController
|
||||||
params.require(:ticket).permit(:title, :description, :state)
|
params.require(:ticket).permit(:title, :description, :state)
|
||||||
end
|
end
|
||||||
|
|
||||||
def looks_ticket
|
|
||||||
@ticket.set_view_by('User')
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
class ClientsController < ApplicationController
|
class ClientsController < ApplicationController
|
||||||
include CommentableForm
|
|
||||||
|
|
||||||
autocomplete :contact, :name
|
|
||||||
|
|
||||||
before_action :authenticate_admin!
|
|
||||||
before_action :set_client, only: [:show, :edit, :update, :destroy]
|
before_action :set_client, only: [:show, :edit, :update, :destroy]
|
||||||
|
before_action :authenticate_admin!
|
||||||
|
|
||||||
# GET /clients
|
# GET /clients
|
||||||
# GET /clients.json
|
# GET /clients.json
|
||||||
|
@ -15,7 +11,6 @@ class ClientsController < ApplicationController
|
||||||
# GET /clients/1
|
# GET /clients/1
|
||||||
# GET /clients/1.json
|
# GET /clients/1.json
|
||||||
def show
|
def show
|
||||||
prepare_comment_for @client
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /clients/new
|
# GET /clients/new
|
||||||
|
|
|
@ -1,117 +0,0 @@
|
||||||
class CommentsController < ApplicationController
|
|
||||||
before_action :set_comment, only: [:show, :edit, :update, :destroy]
|
|
||||||
before_action :set_commentable, only: [:index, :about, :show, :create]
|
|
||||||
before_action :set_commentable_client, only: [:about_client, :show, :create]
|
|
||||||
|
|
||||||
# GET /comments
|
|
||||||
# GET /comments.json
|
|
||||||
def index
|
|
||||||
@comments = Comment.where(commentable: @commentable) if @commentable
|
|
||||||
@comments ||= Comment.where('0=1')
|
|
||||||
end
|
|
||||||
|
|
||||||
def about
|
|
||||||
index()
|
|
||||||
@comment = Comment.new
|
|
||||||
@comment.commentable = @commentable
|
|
||||||
render :about, layout: false
|
|
||||||
end
|
|
||||||
def about_client
|
|
||||||
index()
|
|
||||||
@comment = Comment.new
|
|
||||||
@comment.commentable = @commentable
|
|
||||||
render :about_client, layout: false
|
|
||||||
end
|
|
||||||
|
|
||||||
# GET /comments/1
|
|
||||||
# GET /comments/1.json
|
|
||||||
def show
|
|
||||||
binding.pry
|
|
||||||
render status: :forbidden unless admin_signed_in? or (user_signed_in? and @comment.commentable.is_a? Ticket and @comment.commentable.creator == current_user)
|
|
||||||
end
|
|
||||||
|
|
||||||
# GET /comments/new
|
|
||||||
def new
|
|
||||||
@comment = Comment.new
|
|
||||||
@comment.commentable = @commentable
|
|
||||||
render status: :forbidden unless admin_signed_in? or (user_signed_in? and @comment.commentable.is_a? Ticket and @comment.commentable.creator == current_user)
|
|
||||||
end
|
|
||||||
|
|
||||||
# GET /comments/1/edit
|
|
||||||
def edit
|
|
||||||
render status: :forbidden unless admin_signed_in? or (user_signed_in? and @comment.commentable.is_a? Ticket and @comment.commentable.creator == current_user)
|
|
||||||
end
|
|
||||||
|
|
||||||
# POST /comments
|
|
||||||
# POST /comments.json
|
|
||||||
def create
|
|
||||||
@comment = Comment.new(comment_params)
|
|
||||||
@comment.creator = (current_admin || current_user)
|
|
||||||
render status: :forbidden unless admin_signed_in? or (user_signed_in? and @comment.commentable.is_a? Ticket and @comment.commentable.creator == current_user)
|
|
||||||
|
|
||||||
respond_to do |format|
|
|
||||||
if @comment.save
|
|
||||||
format.html { redirect_to @comment, notice: 'Comment was successfully created.' }
|
|
||||||
format.json { render :show, status: :created, location: @comment }
|
|
||||||
else
|
|
||||||
format.html { render :new }
|
|
||||||
format.json { render json: @comment.errors, status: :unprocessable_entity }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# PATCH/PUT /comments/1
|
|
||||||
# PATCH/PUT /comments/1.json
|
|
||||||
def update
|
|
||||||
render status: :forbidden unless admin_signed_in?
|
|
||||||
respond_to do |format|
|
|
||||||
if @comment.update(comment_params)
|
|
||||||
format.html { redirect_to @comment, notice: 'Comment was successfully updated.' }
|
|
||||||
format.json { render :show, status: :ok, location: @comment }
|
|
||||||
else
|
|
||||||
format.html { render :edit }
|
|
||||||
format.json { render json: @comment.errors, status: :unprocessable_entity }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# DELETE /comments/1
|
|
||||||
# DELETE /comments/1.json
|
|
||||||
def destroy
|
|
||||||
render status: :forbidden unless admin_signed_in?
|
|
||||||
@comment.destroy
|
|
||||||
respond_to do |format|
|
|
||||||
format.html { redirect_to comments_url, notice: 'Comment was successfully destroyed.' }
|
|
||||||
format.json { head :no_content }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
# Use callbacks to share common setup or constraints between actions.
|
|
||||||
def set_comment
|
|
||||||
@comment = Comment.find(params[:id])
|
|
||||||
end
|
|
||||||
|
|
||||||
# Never trust parameters from the scary internet, only allow the white list through.
|
|
||||||
def comment_params
|
|
||||||
params.require(:comment).permit(:title, :comment, :commentable_id, :commentable_type,
|
|
||||||
#:creator_id, :creator_type,
|
|
||||||
:role)
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_commentable
|
|
||||||
return unless admin_signed_in?
|
|
||||||
@commentable ||= Client.find_by_id(params[:client_id])
|
|
||||||
@commentable ||= Contact.find_by_id(params[:contact_id])
|
|
||||||
@commentable ||= Bill.find_by_id(params[:bill_id])
|
|
||||||
@commentable ||= Ticket.find_by_id(params[:ticket_id])
|
|
||||||
@commentable_by = 'Admin'
|
|
||||||
end
|
|
||||||
def set_commentable_client
|
|
||||||
return unless user_signed_in?
|
|
||||||
if @commentable.nil?
|
|
||||||
@commentable ||= Ticket.find_by(id: params[:client_ticket_id], creator: current_user)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
module CommentableForm
|
|
||||||
|
|
||||||
def prepare_comment_for(commentable)
|
|
||||||
@comment = Comment.new
|
|
||||||
@comment.commentable = commentable
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,17 +1,7 @@
|
||||||
class ContactsController < ApplicationController
|
class ContactsController < ApplicationController
|
||||||
include CommentableForm
|
before_action :set_contact, only: [:show, :edit, :update, :destroy]
|
||||||
|
|
||||||
autocomplete :client, :name
|
|
||||||
|
|
||||||
before_action :set_contact, only: [:show, :edit, :update, :destroy, :view]
|
|
||||||
before_action :authenticate_admin!
|
before_action :authenticate_admin!
|
||||||
|
|
||||||
# PATCH /view/1
|
|
||||||
def view
|
|
||||||
@contact.update(view_at: Time.now)
|
|
||||||
render json: @contact, status: :ok
|
|
||||||
end
|
|
||||||
|
|
||||||
# GET /contacts
|
# GET /contacts
|
||||||
# GET /contacts.json
|
# GET /contacts.json
|
||||||
def index
|
def index
|
||||||
|
@ -21,7 +11,6 @@ class ContactsController < ApplicationController
|
||||||
# GET /contacts/1
|
# GET /contacts/1
|
||||||
# GET /contacts/1.json
|
# GET /contacts/1.json
|
||||||
def show
|
def show
|
||||||
prepare_comment_for @contact
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /contacts/new
|
# GET /contacts/new
|
||||||
|
@ -81,6 +70,6 @@ class ContactsController < ApplicationController
|
||||||
|
|
||||||
# Never trust parameters from the scary internet, only allow the white list through.
|
# Never trust parameters from the scary internet, only allow the white list through.
|
||||||
def contact_params
|
def contact_params
|
||||||
params.require(:contact).permit(:client_id, :name, :phone, :email, :note, :region, :department, :postal_code, :address)
|
params.require(:contact).permit(:client_id, :name, :phone, :email, :last_contact, :note, :region, :department, :postal_code, :address)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,37 +1,6 @@
|
||||||
class HomeController < ApplicationController
|
class HomeController < ApplicationController
|
||||||
before_action :authenticate_admin!, only: [:admin_dashboard, :export]
|
|
||||||
before_action :authenticate_user!, only: [:user_dashboard]
|
|
||||||
|
|
||||||
def user_dashboard
|
def index
|
||||||
@retard_bills = current_user.bills.retard.count
|
|
||||||
@advanced_bills = current_user.bills.advanced.count
|
|
||||||
@next_bills = current_user.bills.next.count
|
|
||||||
@old_bills = current_user.bills.old.count
|
|
||||||
@bills_count = current_user.bills.count
|
|
||||||
@ticket_closed = current_user.tickets.close.count
|
|
||||||
@ticket_opened = current_user.tickets.open.count
|
|
||||||
@ticket_waiting = current_user.tickets_unview.count
|
|
||||||
end
|
|
||||||
|
|
||||||
def admin_dashboard
|
|
||||||
@clients_count = Client.count
|
|
||||||
@contacts_count = Contact.count
|
|
||||||
@no_client_contacts_count = (Client.all.pluck(:id) - Contact.all.pluck(:client_id).uniq).size
|
|
||||||
@retard_bills = Bill.retard.count
|
|
||||||
@advanced_bills = Bill.advanced.count
|
|
||||||
@next_bills = Bill.next.count
|
|
||||||
@old_bills = Bill.old.count
|
|
||||||
@bills_count = Bill.count
|
|
||||||
@ticket_closed = Ticket.close.count
|
|
||||||
@ticket_opened = Ticket.open.count
|
|
||||||
@ticket_waiting = current_admin.tickets_unview.count
|
|
||||||
end
|
|
||||||
|
|
||||||
def export
|
|
||||||
redirect_to "/admins/export.json" if params[:format] != "json"
|
|
||||||
@clients = Client.all
|
|
||||||
@contacts = Contact.all
|
|
||||||
@bills = Bill.all
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,25 +1,21 @@
|
||||||
class TicketsController < ApplicationController
|
class TicketsController < ApplicationController
|
||||||
include CommentableForm
|
|
||||||
|
|
||||||
before_action :set_ticket, only: [:show, :edit, :update, :destroy]
|
before_action :set_ticket, only: [:show, :edit, :update, :destroy]
|
||||||
before_action :set_ticket_custom_route, only: [:close, :open]
|
before_action :set_ticket_custom_route, only: [:close, :open, :respond]
|
||||||
before_action :looks_ticket, only: [:show, :edit, :update, :close, :open]
|
|
||||||
before_action :authenticate_admin!
|
before_action :authenticate_admin!
|
||||||
|
|
||||||
# GET /tickets
|
# GET /tickets
|
||||||
# GET /tickets.json
|
# GET /tickets.json
|
||||||
def index
|
def index
|
||||||
@tickets = Ticket.order('state DESC')
|
@tickets = Ticket.heads.order('state DESC')
|
||||||
end
|
end
|
||||||
|
|
||||||
def close
|
def close
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @ticket.close
|
if @ticket.close
|
||||||
@ticket.update(admin_view_at: Time.now) # add comment ?
|
format.html { redirect_to tickets_url, notice: 'Ticket was successfully closed.' }
|
||||||
format.html { redirect_to ticket_url(@ticket), notice: 'Ticket was successfully closed.' }
|
|
||||||
format.json { render :show, status: :ok, location: @ticket }
|
format.json { render :show, status: :ok, location: @ticket }
|
||||||
else
|
else
|
||||||
format.html { redirect_to ticket_url(@ticket), alert: 'The ticket is already close' }
|
format.html { render :index }
|
||||||
format.json { render json: @ticket.errors, status: :unprocessable_entity }
|
format.json { render json: @ticket.errors, status: :unprocessable_entity }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -28,20 +24,32 @@ class TicketsController < ApplicationController
|
||||||
def open
|
def open
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @ticket.open
|
if @ticket.open
|
||||||
@ticket.update(creator_view_at: nil) # add comment ?
|
format.html { redirect_to tickets_url, notice: 'Ticket was successfully reopened.' }
|
||||||
format.html { redirect_to ticket_url(@ticket), notice: 'Ticket was successfully reopened.' }
|
|
||||||
format.json { render :show, status: :ok, location: @ticket }
|
format.json { render :show, status: :ok, location: @ticket }
|
||||||
else
|
else
|
||||||
format.html { redirect_to ticket_url(@ticket), alert: 'The ticket is already open' }
|
format.html { render :index }
|
||||||
format.json { render json: @ticket.errors, status: :unprocessable_entity }
|
format.json { render json: @ticket.errors, status: :unprocessable_entity }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def respond
|
||||||
|
@ticket = Ticket.new(ticket_id: @ticket.head.id,
|
||||||
|
creator: current_admin,
|
||||||
|
title: @ticket.title)
|
||||||
|
if @ticket.close? or @ticket.head.close?
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to tickets_url }
|
||||||
|
format.json { render json: {ticket: 'the ticket is closed'}, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
render :new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# GET /tickets/1
|
# GET /tickets/1
|
||||||
# GET /tickets/1.json
|
# GET /tickets/1.json
|
||||||
def show
|
def show
|
||||||
prepare_comment_for @ticket
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /tickets/new
|
# GET /tickets/new
|
||||||
|
@ -76,6 +84,7 @@ class TicketsController < ApplicationController
|
||||||
def update
|
def update
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @ticket.update(ticket_params)
|
if @ticket.update(ticket_params)
|
||||||
|
@ticket.close_head if @ticket.close?
|
||||||
format.html { redirect_to @ticket, notice: 'Ticket was successfully updated.' }
|
format.html { redirect_to @ticket, notice: 'Ticket was successfully updated.' }
|
||||||
format.json { render :show, status: :ok, location: @ticket }
|
format.json { render :show, status: :ok, location: @ticket }
|
||||||
else
|
else
|
||||||
|
@ -107,11 +116,7 @@ class TicketsController < ApplicationController
|
||||||
|
|
||||||
# Never trust parameters from the scary internet, only allow the white list through.
|
# Never trust parameters from the scary internet, only allow the white list through.
|
||||||
def ticket_params
|
def ticket_params
|
||||||
params.require(:ticket).permit(:title, :description, :state)
|
params.require(:ticket).permit(:ticket_id, :title, :description, :state)
|
||||||
end
|
|
||||||
|
|
||||||
def looks_ticket
|
|
||||||
@ticket.set_view_by('Admin')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module ApplicationHelper
|
module ApplicationHelper
|
||||||
|
|
||||||
def application_title
|
def application_title
|
||||||
['MorningPeak', ENV['COMPANY'], 'CRM'].compact.join(' ')
|
['Appli', ENV['COMPANY'], 'client gestion'].join(' ')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,2 @@
|
||||||
module BillsHelper
|
module BillsHelper
|
||||||
|
|
||||||
def user_bills_count_due
|
|
||||||
return nil if not user_signed_in?
|
|
||||||
return (current_user.bills.next + current_user.bills.retard).count
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
module CommentsHelper
|
|
||||||
end
|
|
|
@ -1,8 +1,2 @@
|
||||||
module TicketClientsHelper
|
module TicketClientsHelper
|
||||||
|
|
||||||
def user_tickets_unview_count
|
|
||||||
return nil if not user_signed_in?
|
|
||||||
return current_user.tickets_unview.count
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,39 +8,4 @@ module TicketsHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def admin_tickets_unview_count
|
|
||||||
return if not admin_signed_in?
|
|
||||||
return current_admin.tickets_unview.count
|
|
||||||
end
|
|
||||||
|
|
||||||
def brize text
|
|
||||||
texts = text.split("\n")
|
|
||||||
texts.join(tag(:br))
|
|
||||||
end
|
|
||||||
|
|
||||||
def imagize text, uris
|
|
||||||
uris.each do |uri|
|
|
||||||
text.gsub!(uri, "<a href='#{uri}'><img src='#{uri}' alt='#{uri}'/></a>")
|
|
||||||
end
|
|
||||||
text
|
|
||||||
end
|
|
||||||
|
|
||||||
def linkize text, uris
|
|
||||||
uris.each do |uri|
|
|
||||||
text.gsub!(uri, "<a href='#{uri}'>#{uri}</a>")
|
|
||||||
end
|
|
||||||
text
|
|
||||||
end
|
|
||||||
|
|
||||||
def descriptionize text
|
|
||||||
uris = URI.extract(text)
|
|
||||||
imgs = uris.select{|e| e.match(/\.(jpg|png|jpeg|gif)\Z/)}
|
|
||||||
links = uris - imgs
|
|
||||||
text = raw text
|
|
||||||
text = brize text
|
|
||||||
text = imagize text, imgs
|
|
||||||
text = linkize text, links
|
|
||||||
text.html_safe
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,10 +9,5 @@ class Admin < ActiveRecord::Base
|
||||||
#:validatable
|
#:validatable
|
||||||
|
|
||||||
has_many :tickets, as: :creator
|
has_many :tickets, as: :creator
|
||||||
has_many :comments, as: :creator
|
|
||||||
|
|
||||||
def tickets_unview
|
|
||||||
Ticket.all.where(admin_view_at: nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,14 +1,5 @@
|
||||||
class Bill < ActiveRecord::Base
|
class Bill < ActiveRecord::Base
|
||||||
acts_as_commentable
|
|
||||||
belongs_to :client
|
belongs_to :client
|
||||||
|
|
||||||
validates :due_date, presence: true
|
|
||||||
|
|
||||||
delegate :name, to: :client, prefix: true
|
delegate :name, to: :client, prefix: true
|
||||||
|
|
||||||
scope :retard, -> {where("due_date <= '#{Date.today}'").where(paid: false)}
|
|
||||||
scope :advanced, -> {where("due_date > '#{Date.today}'").where(paid: true)}
|
|
||||||
scope :next, -> {where("due_date > '#{Date.today}'").where(paid: false)}
|
|
||||||
scope :old, -> {where("due_date <= '#{Date.today}'").where(paid: true)}
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
class Client < ActiveRecord::Base
|
class Client < ActiveRecord::Base
|
||||||
acts_as_commentable
|
|
||||||
|
|
||||||
has_many :contacts
|
has_many :contacts
|
||||||
has_many :bills
|
has_many :bills
|
||||||
has_many :tickets, through: :user
|
has_many :tickets, through: :user
|
||||||
|
@ -10,7 +8,7 @@ class Client < ActiveRecord::Base
|
||||||
delegate :name, to: :contact, allow_nil: true, prefix: true
|
delegate :name, to: :contact, allow_nil: true, prefix: true
|
||||||
|
|
||||||
def last_contact
|
def last_contact
|
||||||
contacts.where('view_at IS NOT NULL').pluck(:view_at).max || "never"
|
contacts.pluck('last_contact').max || "never"
|
||||||
end
|
end
|
||||||
|
|
||||||
def bills_retard
|
def bills_retard
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
class Comment < ActiveRecord::Base
|
|
||||||
include ActsAsCommentable::Comment
|
|
||||||
|
|
||||||
belongs_to :commentable, :polymorphic => true
|
|
||||||
|
|
||||||
default_scope -> { order('created_at DESC') }
|
|
||||||
|
|
||||||
# NOTE: install the acts_as_votable plugin if you
|
|
||||||
# want user to vote on the quality of comments.
|
|
||||||
#acts_as_voteable
|
|
||||||
|
|
||||||
# NOTE: Comments belong to a creator
|
|
||||||
belongs_to :creator, polymorphic: true
|
|
||||||
|
|
||||||
def thread(commentable=:self)
|
|
||||||
commentable = self.commentable if commentable == :self
|
|
||||||
if commentable.nil?
|
|
||||||
[]
|
|
||||||
else
|
|
||||||
Comment.where(commentable: commentable)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
after_create :update_view_date_for_ticket
|
|
||||||
def update_view_date_for_ticket
|
|
||||||
if commentable.is_a? Ticket
|
|
||||||
commentable.updated_by(creator.class.to_s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,5 +1,4 @@
|
||||||
class Contact < ActiveRecord::Base
|
class Contact < ActiveRecord::Base
|
||||||
acts_as_commentable
|
|
||||||
belongs_to :client
|
belongs_to :client
|
||||||
|
|
||||||
delegate :name, to: :client, prefix: true
|
delegate :name, to: :client, prefix: true
|
||||||
|
|
|
@ -1,83 +1,58 @@
|
||||||
# coding: utf-8
|
|
||||||
class Ticket < ActiveRecord::Base
|
class Ticket < ActiveRecord::Base
|
||||||
acts_as_commentable
|
|
||||||
|
|
||||||
# WARNING ! IT REVERSE LAST / FIRST
|
|
||||||
default_scope { order('created_at DESC') }
|
|
||||||
|
|
||||||
OPEN = 'open'
|
OPEN = 'open'
|
||||||
CLOSE = 'close'
|
CLOSE = 'close'
|
||||||
|
|
||||||
CREATORS = ['Admin', 'User']
|
CREATORS = ['Admin', 'User']
|
||||||
|
|
||||||
validates :state, inclusion: {in: [OPEN, CLOSE]}
|
|
||||||
# validates :creator, inclusion: {in: CREATORS}
|
|
||||||
validates :title, length: {in: 7..124}
|
|
||||||
validates :description, length: {minimum: 12}
|
|
||||||
|
|
||||||
belongs_to :creator, polymorphic: true
|
belongs_to :creator, polymorphic: true
|
||||||
delegate :name, to: :creator, prefix: true
|
delegate :name, to: :creator, prefix: true
|
||||||
|
|
||||||
scope :open, -> { where(state: OPEN) }
|
belongs_to :ticket
|
||||||
scope :close, -> { where(state: CLOSE) }
|
has_many :tickets
|
||||||
|
|
||||||
|
scope :heads, -> { where(ticket_id: nil) }
|
||||||
|
scope :open, -> { heads.where(state: OPEN) }
|
||||||
|
scope :close, -> { heads.where(state: CLOSE) }
|
||||||
|
|
||||||
before_save :check_creator
|
before_save :check_creator
|
||||||
def check_creator
|
def check_creator
|
||||||
return true if CREATORS.include? creator_type
|
return true if CREATORS.include? creator_type
|
||||||
errors[:base] << "#{creator_type} is not in the list of the possible creators list"
|
errors.add "#{creator_type} is not in the list of the possible creators list"
|
||||||
raise ActiveRecord::RecordInvalid.new(self)
|
raise ActiveRecord::RecordInvalid.new(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
after_create :set_view_init
|
def last_response
|
||||||
def set_view_init
|
head.tickets.last
|
||||||
set_view_by(creator_type)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_view_by(viewer_type)
|
def head
|
||||||
if creator_type == 'Admin'
|
return self if not ticket
|
||||||
if viewer_type == 'Admin'
|
return ticket.head
|
||||||
update(admin_view_at: Time.now, creator_view_at: Time.now)
|
|
||||||
end
|
|
||||||
elsif creator_type == 'User'
|
|
||||||
if viewer_type == 'User'
|
|
||||||
update(creator_view_at: Time.now)
|
|
||||||
elsif viewer_type == 'Admin'
|
|
||||||
update(admin_view_at: Time.now)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_unview_by(viewer_type)
|
|
||||||
if creator_type == 'Admin'
|
|
||||||
return # ... ?
|
|
||||||
elsif creator_type == 'User'
|
|
||||||
if viewer_type == 'User'
|
|
||||||
update(admin_view_at: nil)
|
|
||||||
elsif viewer_type == 'Admin'
|
|
||||||
update(creator_view_at: nil)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def updated_by(viewer_type)
|
|
||||||
set_view_by(viewer_type)
|
|
||||||
set_unview_by(viewer_type)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def close
|
def close
|
||||||
if close?
|
if close?
|
||||||
errors[:base] << "Already close"
|
errors.add "Already close"
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
update(state: Ticket::CLOSE)
|
head.update(state: Ticket::CLOSE) && update(state: Ticket::CLOSE)
|
||||||
|
end
|
||||||
|
|
||||||
|
def close_head
|
||||||
|
if head.close?
|
||||||
|
errors.add "Already close"
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
head.update(state: Ticket::CLOSE)
|
||||||
end
|
end
|
||||||
|
|
||||||
def open
|
def open
|
||||||
if open?
|
if open?
|
||||||
errors[:base] << "Already open"
|
errors.add "Already open"
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
update(state: Ticket::OPEN)
|
head.update(state: Ticket::OPEN) && update(state: Ticket::OPEN)
|
||||||
end
|
end
|
||||||
|
|
||||||
def open?
|
def open?
|
||||||
|
@ -88,8 +63,4 @@ class Ticket < ActiveRecord::Base
|
||||||
state == CLOSE
|
state == CLOSE
|
||||||
end
|
end
|
||||||
|
|
||||||
def short_description
|
|
||||||
description.to_s.first(100)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,19 +10,12 @@ class User < ActiveRecord::Base
|
||||||
has_one :client
|
has_one :client
|
||||||
delegate :name, to: :client
|
delegate :name, to: :client
|
||||||
has_many :tickets, as: :creator
|
has_many :tickets, as: :creator
|
||||||
has_many :comments, as: :creator
|
|
||||||
has_many :contacts, through: :client
|
has_many :contacts, through: :client
|
||||||
has_many :bills, through: :client
|
has_many :bills, through: :client
|
||||||
|
|
||||||
after_create :create_client
|
after_create :create_client
|
||||||
def create_client
|
def create_client
|
||||||
if self.client_id.nil?
|
update(client: Client.create(name: email.gsub(/@.+/, '')))
|
||||||
update_attributes(client: Client.create(name: email.tr('@.-_', ' ')))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def tickets_unview
|
|
||||||
tickets.where(creator_view_at: nil)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,38 +6,25 @@
|
||||||
- @bill.errors.full_messages.each do |message|
|
- @bill.errors.full_messages.each do |message|
|
||||||
li = message
|
li = message
|
||||||
|
|
||||||
.form-horizontal
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.autocomplete_field :client, autocomplete_client_name_bills_path, :id_element => '#bill_client_id', class: "form-control", placeholder: "Client Name"
|
= f.label :client_id
|
||||||
= f.label :client_id, class: "sr-only"
|
= f.text_field :client_id
|
||||||
= f.text_field :client_id, class: "form-control sr-only", placeholder: "#{t('.client_id')}"
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :title, class: "sr-only"
|
= f.label :title
|
||||||
= f.text_field :title, class: "form-control", placeholder: "#{t('.title')}"
|
= f.text_field :title
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :description, class: "sr-only"
|
= f.label :description
|
||||||
= f.text_area :description, class: "form-control", placeholder: "#{t('.description')}"
|
= f.text_area :description
|
||||||
.form-inline
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :amount, class: "sr-only"
|
= f.label :amount
|
||||||
= f.number_field :amount, class: "form-control", placeholder: "#{t('.amount')}"
|
= f.number_field :amount
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label t('.is_paid')
|
= f.label :paid
|
||||||
br
|
= f.check_box :paid
|
||||||
= f.check_box :paid, class: "form-control", placeholder: "#{t('.is_paid')}"
|
|
||||||
.form-inline
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :emission_date, class: "sr-only"
|
= f.label :emission_date
|
||||||
= f.text_field :emission_date, class: "form-control form-date", placeholder: "#{t('.e_date')}"
|
= f.date_select :emission_date
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :due_date, class: "sr-only"
|
= f.label :due_date
|
||||||
= f.text_field :due_date, class: "form-control form-date", placeholder: "#{t('.d_date')}"
|
= f.date_select :due_date
|
||||||
|
.actions = f.submit
|
||||||
.actions = f.submit class: "btn btn-success"
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
h1.page-header = t(".page.title")
|
h1 Editing bill
|
||||||
|
|
||||||
== render 'form'
|
== render 'form'
|
||||||
|
|
||||||
= link_to t("show"), @bill, class: 'btn btn-sm btn-default'
|
= link_to 'Show', @bill, class: 'btn btn-sm btn-default'
|
||||||
= link_to t("back"), bills_path, class: 'btn btn-sm btn-default'
|
= link_to 'Back', bills_path, class: 'btn btn-sm btn-default'
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
h1.page-header = t(".page.title")
|
h1 Listing bills
|
||||||
|
|
||||||
table.table.table-condensed
|
table.table.table-condensed.table-striped
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
th = t(".id")
|
td ID
|
||||||
th = t(".client")
|
th Client
|
||||||
th = t(".title")
|
th Title
|
||||||
th = t(".description")
|
th Description
|
||||||
th = t(".amount")
|
th Amount
|
||||||
th = t(".paid")
|
th Paid
|
||||||
th = t(".e_date")
|
th Emission date
|
||||||
th = t(".d_date")
|
th Due date
|
||||||
th
|
th
|
||||||
th
|
th
|
||||||
th
|
th
|
||||||
|
@ -32,10 +32,10 @@ table.table.table-condensed
|
||||||
td.bg-danger = distance_of_time_in_words_to_now(bill.due_date) + " - " + bill.due_date.to_s(:long)
|
td.bg-danger = distance_of_time_in_words_to_now(bill.due_date) + " - " + bill.due_date.to_s(:long)
|
||||||
- else
|
- else
|
||||||
td.bg-info = distance_of_time_in_words_to_now(bill.due_date).to_s + " - " + bill.due_date.to_s(:long)
|
td.bg-info = distance_of_time_in_words_to_now(bill.due_date).to_s + " - " + bill.due_date.to_s(:long)
|
||||||
td = link_to t('show'), bill
|
td = link_to '', bill, class: 'glyphicon glyphicon-eye-open'
|
||||||
td = link_to t('edit'), edit_bill_path(bill)
|
td = link_to '', edit_bill_path(bill), class: 'glyphicon glyphicon-pencil'
|
||||||
td = link_to t('destroy'), bill, data: {:confirm => 'Are you sure?'}, :method => :delete
|
td = link_to '', bill, data: {:confirm => 'Are you sure?'}, :method => :delete, class: 'glyphicon glyphicon-remove-sign'
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
||||||
= link_to t("new"), new_bill_path, class: 'btn btn-sm btn-default'
|
= link_to 'New Bill', new_bill_path, class: 'btn btn-sm btn-default'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
h1.page-header = t(".page.title")
|
h1 New bill
|
||||||
|
|
||||||
== render 'form'
|
== render 'form'
|
||||||
|
|
||||||
= link_to t("back"), bills_path
|
= link_to 'Back', bills_path
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
h1.page-header = "#{t('.page.title')}: #{@bill.title}"
|
p#notice = notice
|
||||||
|
|
||||||
p
|
p
|
||||||
strong = t ".client"
|
strong Client:
|
||||||
= link_to @bill.client.name, @bill.client
|
= link_to @bill.client.name, @bill.client
|
||||||
p
|
p
|
||||||
strong = t ".title"
|
strong Title:
|
||||||
= @bill.title
|
= @bill.title
|
||||||
p
|
p
|
||||||
strong = t ".description"
|
strong Description:
|
||||||
= @bill.description
|
= @bill.description
|
||||||
p
|
p
|
||||||
strong = t ".amount"
|
strong Amount:
|
||||||
= @bill.amount
|
= @bill.amount
|
||||||
p
|
p
|
||||||
strong = t ".is_paid"
|
strong Paid:
|
||||||
= @bill.paid
|
= @bill.paid
|
||||||
p
|
p
|
||||||
strong = t ".e_date"
|
strong Emission date:
|
||||||
= @bill.emission_date
|
= @bill.emission_date
|
||||||
p
|
p
|
||||||
strong = t ".d_date"
|
strong Due date:
|
||||||
- if @bill.due_date < Date.today
|
- if @bill.due_date < Date.today
|
||||||
- if @bill.paid
|
- if @bill.paid
|
||||||
.bg-success = distance_of_time_in_words_to_now(@bill.due_date) + " - " + @bill.due_date.to_s(:long)
|
.bg-success = distance_of_time_in_words_to_now(@bill.due_date) + " - " + @bill.due_date.to_s(:long)
|
||||||
|
@ -28,10 +28,5 @@ p
|
||||||
- else
|
- else
|
||||||
.bg-info = distance_of_time_in_words_to_now(@bill.due_date) + " - " + @bill.due_date.to_s(:long)
|
.bg-info = distance_of_time_in_words_to_now(@bill.due_date) + " - " + @bill.due_date.to_s(:long)
|
||||||
|
|
||||||
= link_to t('edit'), edit_bill_path(@bill), class: 'btn btn-sm btn-default'
|
= link_to 'Edit', edit_bill_path(@bill), class: 'btn btn-sm btn-default'
|
||||||
= link_to t('back'), bills_path, class: 'btn btn-sm btn-default'
|
= link_to 'Back', bills_path, class: 'btn btn-sm btn-default'
|
||||||
|
|
||||||
#comments.container-fluid
|
|
||||||
h2.page-header Comments
|
|
||||||
= render partial: "/comments/about", locals: {commentable: @bill}
|
|
||||||
= render partial: "/comments/form"
|
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
h1.page-header = t '.page.title'
|
h1 Listing bills
|
||||||
|
|
||||||
table.table.table-condensed
|
table.table.table-condensed.table-striped
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
th ID
|
td ID
|
||||||
th = t '.title'
|
th Title
|
||||||
th = t '.description'
|
th Description
|
||||||
th = t '.amount'
|
th Amount
|
||||||
th = t '.paid'
|
th Paid
|
||||||
th = t '.emission_date'
|
th Emission date
|
||||||
th = t '.due_date'
|
th Due date
|
||||||
th
|
th
|
||||||
th
|
th
|
||||||
th
|
th
|
||||||
|
@ -30,6 +30,6 @@ table.table.table-condensed
|
||||||
td.bg-danger = distance_of_time_in_words_to_now(bill.due_date) + " - " + bill.due_date.to_s(:long)
|
td.bg-danger = distance_of_time_in_words_to_now(bill.due_date) + " - " + bill.due_date.to_s(:long)
|
||||||
- else
|
- else
|
||||||
td.bg-info = distance_of_time_in_words_to_now(bill.due_date).to_s + " - " + bill.due_date.to_s(:long)
|
td.bg-info = distance_of_time_in_words_to_now(bill.due_date).to_s + " - " + bill.due_date.to_s(:long)
|
||||||
td = link_to t('show'), client_bill_url(bill)
|
td = link_to '', bill, class: 'glyphicon glyphicon-eye-open'
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
h1.page-header = t '.page.title'
|
p#notice = notice
|
||||||
|
|
||||||
p
|
p
|
||||||
strong = t ".title"
|
strong Title:
|
||||||
= @bill.title
|
= @bill.title
|
||||||
p
|
p
|
||||||
strong = t ".description"
|
strong Description:
|
||||||
= @bill.description
|
= @bill.description
|
||||||
p
|
p
|
||||||
strong = t ".amount"
|
strong Amount:
|
||||||
= @bill.amount
|
= @bill.amount
|
||||||
p
|
p
|
||||||
strong = t ".paid"
|
strong Paid:
|
||||||
= @bill.paid
|
= @bill.paid
|
||||||
p
|
p
|
||||||
strong = t ".emission_date"
|
strong Emission date:
|
||||||
= @bill.emission_date
|
= @bill.emission_date
|
||||||
p
|
p
|
||||||
strong = t ".due_date"
|
strong Due date:
|
||||||
- if @bill.due_date < Date.today
|
- if @bill.due_date < Date.today
|
||||||
- if @bill.paid
|
- if @bill.paid
|
||||||
.bg-success = distance_of_time_in_words_to_now(@bill.due_date) + " - " + @bill.due_date.to_s(:long)
|
.bg-success = distance_of_time_in_words_to_now(@bill.due_date) + " - " + @bill.due_date.to_s(:long)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
= form_for @ticket, url: @ticket.id ? client_ticket_path(@ticket) : client_tickets_path do |f|
|
= form_for @ticket, url: client_tickets_path do |f|
|
||||||
- if @ticket.errors.any?
|
- if @ticket.errors.any?
|
||||||
#error_explanation
|
#error_explanation
|
||||||
h2 = "#{pluralize(@ticket.errors.count, "error")} prohibited this ticket from being saved:"
|
h2 = "#{pluralize(@ticket.errors.count, "error")} prohibited this ticket from being saved:"
|
||||||
|
@ -6,18 +6,13 @@
|
||||||
- @ticket.errors.full_messages.each do |message|
|
- @ticket.errors.full_messages.each do |message|
|
||||||
li = message
|
li = message
|
||||||
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :title, class: "sr-only"
|
= f.label :title
|
||||||
= f.text_field :title, class: "form-control", placeholder: "#{t('.title')}"
|
= f.text_field :title
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :description, class: "sr-only"
|
= f.label :description
|
||||||
= f.text_area :description, class: "form-control", size: "100x8", placeholder: "#{t('.description')}"
|
= f.text_area :description
|
||||||
/ display the choice to close only if 'respond to'
|
|
||||||
- if @head
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label t('.state')
|
= f.label :state
|
||||||
= f.select :state, ["open", "close"], {}, class: "form-control"
|
= f.text_field :state
|
||||||
.actions = f.submit class: "btn btn-default"
|
.actions = f.submit
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
h1.page-header = t(".page.title")
|
h1 Editing ticket
|
||||||
|
|
||||||
== render 'form'
|
== render 'form'
|
||||||
|
|
||||||
= link_to t('show'), client_ticket_path(@ticket), class: 'btn btn-sm btn-default'
|
= link_to 'Show', client_ticket_path(@ticket), class: 'btn btn-sm btn-default'
|
||||||
= link_to t('back'), client_tickets_path, class: 'btn btn-sm btn-default'
|
= link_to 'Back', client_tickets_path, class: 'btn btn-sm btn-default'
|
||||||
|
|
|
@ -1,37 +1,42 @@
|
||||||
h1.page-header = t ".page.title"
|
h1 Listing tickets
|
||||||
|
|
||||||
table.table.table-condensed
|
table.table.table-condensed.table-striped
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
th ID
|
td ID
|
||||||
th = t ".title"
|
th Creator
|
||||||
th = t ".description"
|
th Title
|
||||||
th = t ".state"
|
th Description
|
||||||
th = t ".last_update"
|
th State
|
||||||
th = t ".last_response"
|
th Last update
|
||||||
|
th Last response
|
||||||
|
th
|
||||||
th
|
th
|
||||||
th
|
th
|
||||||
th
|
th
|
||||||
|
|
||||||
tbody
|
tbody
|
||||||
- @tickets.each do |ticket|
|
- @tickets.each do |ticket|
|
||||||
tr class="#{ticket.creator_view_at.nil? ? 'bg-warning' : ''}"
|
tr
|
||||||
td = link_to("##{ticket.id}", client_ticket_path(ticket))
|
td = link_to("##{ticket.id}", client_ticket_path(ticket))
|
||||||
|
td = link_to_creator(ticket)
|
||||||
td = link_to ticket.title, client_ticket_path(ticket)
|
td = link_to ticket.title, client_ticket_path(ticket)
|
||||||
td = ticket.short_description
|
td = ticket.description
|
||||||
- if ticket.state == Ticket::CLOSE
|
- if ticket.state == Ticket::CLOSE
|
||||||
td.bg-danger = t ".states.close"
|
td.bg-danger = ticket.state
|
||||||
- else
|
- else
|
||||||
td.bg-success = t ".states.open"
|
td.bg-success = ticket.state
|
||||||
td = ticket.updated_at.to_s(:long)
|
td = ticket.updated_at.to_s(:long)
|
||||||
td = ticket.comments.empty? ? "never" : distance_of_time_in_words_to_now(ticket.comments.first.updated_at)
|
td = ticket.last_response ? distance_of_time_in_words_to_now(ticket.last_response.updated_at) : "never"
|
||||||
td = link_to (t "show"), ticket
|
td = link_to '', ticket, class: 'glyphicon glyphicon-eye-open'
|
||||||
td = link_to (t "edit"), edit_client_ticket_path(ticket)
|
td = link_to '', edit_client_ticket_path(ticket), class: 'glyphicon glyphicon-pencil'
|
||||||
|
/ td = link_to '', ticket, data: {:confirm => 'Are you sure?'}, :method => :delete, class: 'glyphicon glyphicon-remove-sign'
|
||||||
|
td = link_to '', ticket_respond_path(ticket), class: 'glyphicon glyphicon-comment' if ticket.open?
|
||||||
- if ticket.open?
|
- if ticket.open?
|
||||||
td = link_to (t "close"), client_ticket_close_path(ticket), data: {:confirm => 'Are you sure?'}, :method => :patch
|
td = link_to '', client_ticket_close_path(ticket), data: {:confirm => 'Are you sure to CLOSE this ticket?'}, method: :patch, class: 'glyphicon glyphicon-ok-circle'
|
||||||
- elsif ticket.close?
|
- elsif ticket.close?
|
||||||
td = link_to (t "reopen"), client_ticket_open_path(ticket), data: {:confirm => 'Are you sure?'}, :method => :patch
|
td = link_to '', client_ticket_open_path(ticket), data: {:confirm => 'Are you sure to REOPEN this ticket?'}, method: :patch, class: 'glyphicon glyphicon-remove-circle'
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
||||||
= link_to (t "new"), new_client_ticket_path, class: 'btn btn-sm btn-default'
|
= link_to 'New Ticket', new_client_ticket_path, class: 'btn btn-sm btn-default'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
h1 = @head ? t("client_tickets.response.page.title") : t(".page.title")
|
h1 New ticket
|
||||||
|
|
||||||
== render 'form'
|
== render 'form'
|
||||||
|
|
||||||
= link_to t('back'), client_tickets_path, class: 'btn btn-sm btn-default'
|
= link_to 'Back', client_tickets_path
|
||||||
|
|
|
@ -1,44 +1,62 @@
|
||||||
h1.page-header = "Ticket: #{@ticket.title}"
|
p#notice = notice
|
||||||
|
|
||||||
p
|
p
|
||||||
strong
|
strong
|
||||||
| Id: #
|
| Id: #
|
||||||
= @ticket.id
|
= @ticket.id
|
||||||
p
|
p
|
||||||
strong = t ".title"
|
strong Réponse à:
|
||||||
|:
|
= link_to @ticket.head.title, client_ticket_path(@ticket.head)
|
||||||
= link_to @ticket.title, client_ticket_path(@ticket)
|
|
||||||
|
|
||||||
p
|
p
|
||||||
strong = t ".state"
|
strong State:
|
||||||
|:
|
- if @ticket.head.state == Ticket::CLOSE
|
||||||
- if @ticket.state == Ticket::CLOSE
|
td.bg-danger = @ticket.head.state
|
||||||
td.bg-danger = t ".states.close"
|
|
||||||
- else
|
- else
|
||||||
td.bg-success = t ".states.open"
|
td.bg-success = @ticket.head.state
|
||||||
|
|
||||||
p
|
p
|
||||||
strong = t ".creator"
|
strong Creator:
|
||||||
|:
|
= link_to_creator @ticket
|
||||||
span.ticket-creator = link_to_creator @ticket
|
|
||||||
p
|
p
|
||||||
strong = t ".title"
|
strong Title:
|
||||||
|:
|
|
||||||
= @ticket.title
|
= @ticket.title
|
||||||
p
|
p
|
||||||
strong = t ".description"
|
strong Description:
|
||||||
|:
|
= @ticket.description
|
||||||
.container-fluid.ticket-description
|
p
|
||||||
= descriptionize @ticket.description
|
strong State:
|
||||||
|
= @ticket.state
|
||||||
|
|
||||||
== render partial: "/comments/thread", locals: {commentable: @ticket, type: 'user'}
|
table.table.table-condensed.table-striped
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th Creator
|
||||||
|
th Title
|
||||||
|
th Description
|
||||||
|
th Last update
|
||||||
|
th
|
||||||
|
th
|
||||||
|
/ th
|
||||||
|
|
||||||
|
tbody
|
||||||
|
- @ticket.tickets.each do |ticket|
|
||||||
|
tr
|
||||||
|
td = link_to_creator(ticket)
|
||||||
|
td = link_to ticket.title, client_ticket_path(ticket)
|
||||||
|
td = ticket.description
|
||||||
|
- if ticket.state == Ticket::CLOSE
|
||||||
|
td.bg-danger = ticket.state
|
||||||
|
- else
|
||||||
|
td.bg-success = ticket.state
|
||||||
|
td = ticket.updated_at.to_s(:long)
|
||||||
|
td = link_to 'Show', client_ticket_path(ticket)
|
||||||
|
td = link_to 'Edit', edit_client_ticket_path(ticket)
|
||||||
|
/ td = link_to 'Destroy', client_ticket_path(ticket), data: {:confirm => 'Are you sure?'}, :method => :delete
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
||||||
- if @ticket.open?
|
|
||||||
= link_to (t 'close'), client_ticket_close_path(@ticket), method: :patch, class: 'btn btn-sm btn-success'
|
|
||||||
- else
|
|
||||||
= link_to (t 'reopen'), client_ticket_open_path(@ticket), method: :patch, class: 'btn btn-sm btn-danger'
|
|
||||||
= link_to (t 'edit'), edit_client_ticket_path(@ticket), class: 'btn btn-sm btn-default'
|
|
||||||
= link_to (t 'back'), client_tickets_path, class: 'btn btn-sm btn-default'
|
|
||||||
|
|
||||||
|
= link_to 'Respond', client_ticket_respond_path(@ticket), class: 'btn btn-sm btn-default'
|
||||||
|
= link_to 'Edit', edit_client_ticket_path(@ticket), class: 'btn btn-sm btn-default'
|
||||||
|
= link_to 'Back', client_tickets_path, class: 'btn btn-sm btn-default'
|
||||||
|
|
|
@ -6,31 +6,22 @@
|
||||||
- @client.errors.full_messages.each do |message|
|
- @client.errors.full_messages.each do |message|
|
||||||
li = message
|
li = message
|
||||||
|
|
||||||
.form-horizontal
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :name, class: "sr-only"
|
= f.label :name
|
||||||
= f.text_field :name, class: "form-control", placeholder: "Name"
|
= f.text_field :name
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :url, class: "sr-only"
|
= f.label :url
|
||||||
= f.text_field :url, class: "form-control", placeholder: "URL"
|
= f.text_field :url
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :activity, class: "sr-only"
|
= f.label :activity
|
||||||
= f.text_field :activity, class: "form-control", placeholder: "Activity"
|
= f.text_field :activity
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :contact_reasons, class: "sr-only"
|
= f.label :contact_reasons
|
||||||
= f.text_area :contact_reasons, class: "form-control", placeholder: "Contact reasons"
|
= f.text_area :contact_reasons
|
||||||
.form-horizontal
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :user_id, class: "sr-only"
|
= f.label :user_id
|
||||||
= f.text_field :user_id, class: "form-control", placeholder: "User ID"
|
= f.text_field :user_id
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.autocomplete_field :contact, autocomplete_contact_name_clients_path, :id_element => '#client_contact_id', class: "form-control", placeholder: "Main Contact Name"
|
= f.label :contact_id
|
||||||
= f.label :contact_id, class: "sr-only"
|
= f.text_field :contact_id
|
||||||
= f.text_field :contact_id, class: "form-control sr-only", placeholder: "Main Contact ID"
|
.actions = f.submit
|
||||||
.actions = f.submit class: "btn btn-success"
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
h1.page-header Editing client
|
h1 Editing client
|
||||||
|
|
||||||
== render 'form'
|
== render 'form'
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
h1.page-header Listing clients
|
h1 Listing clients
|
||||||
|
|
||||||
table.table.table-condensed
|
table.table.table-condensed.table-striped
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
td ID
|
td ID
|
||||||
|
@ -32,9 +32,9 @@ table.table.table-condensed
|
||||||
td = client.retard
|
td = client.retard
|
||||||
td = client.weight
|
td = client.weight
|
||||||
td = client.next
|
td = client.next
|
||||||
td = link_to 'Show', client
|
td = link_to '', client, class: 'glyphicon glyphicon-eye-open'
|
||||||
td = link_to 'Edit', edit_client_path(client)
|
td = link_to '', edit_client_path(client), class: 'glyphicon glyphicon-pencil'
|
||||||
td = link_to 'Destroy', client, data: {:confirm => 'Are you sure?'}, :method => :delete
|
td = link_to '', client, data: {:confirm => 'Are you sure?'}, :method => :delete, class: 'glyphicon glyphicon-remove-sign'
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
h1.page-header New client
|
h1 New client
|
||||||
|
|
||||||
== render 'form'
|
== render 'form'
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
h1.page-header Show Client
|
p#notice = notice
|
||||||
|
|
||||||
p
|
p
|
||||||
strong Name:
|
strong Name:
|
||||||
|
@ -29,9 +29,8 @@ p
|
||||||
= link_to 'Edit', edit_client_path(@client), class: 'btn btn-sm btn-default'
|
= link_to 'Edit', edit_client_path(@client), class: 'btn btn-sm btn-default'
|
||||||
= link_to 'Back', clients_path, class: 'btn btn-sm btn-default'
|
= link_to 'Back', clients_path, class: 'btn btn-sm btn-default'
|
||||||
|
|
||||||
#contacts.container-fluid
|
table.table.table-condensed
|
||||||
h2 Contacts list
|
caption Contacts list
|
||||||
table.table.table-condensed
|
|
||||||
tr
|
tr
|
||||||
th Name
|
th Name
|
||||||
th Phone
|
th Phone
|
||||||
|
@ -42,9 +41,7 @@ p
|
||||||
td = contact.phone
|
td = contact.phone
|
||||||
td = contact.email
|
td = contact.email
|
||||||
|
|
||||||
#bills.container-fluid
|
table.table.table-condensed
|
||||||
h2 Bills list
|
|
||||||
table.table.table-condensed
|
|
||||||
caption = "Retarded Due Bills list #{@client.bills_retard.pluck(:amount).sum} €"
|
caption = "Retarded Due Bills list #{@client.bills_retard.pluck(:amount).sum} €"
|
||||||
tr
|
tr
|
||||||
th Title
|
th Title
|
||||||
|
@ -56,7 +53,7 @@ p
|
||||||
td.bg-danger = bill.amount
|
td.bg-danger = bill.amount
|
||||||
td.bg-danger = bill.due_date
|
td.bg-danger = bill.due_date
|
||||||
|
|
||||||
table.table.table-condensed
|
table.table.table-condensed
|
||||||
caption = "Next Bills list #{@client.bills_next.pluck(:amount).sum} €"
|
caption = "Next Bills list #{@client.bills_next.pluck(:amount).sum} €"
|
||||||
tr
|
tr
|
||||||
th Title
|
th Title
|
||||||
|
@ -68,7 +65,7 @@ p
|
||||||
td.bg-info = bill.amount
|
td.bg-info = bill.amount
|
||||||
td.bg-info = bill.due_date
|
td.bg-info = bill.due_date
|
||||||
|
|
||||||
table.table.table-condensed
|
table.table.table-condensed
|
||||||
caption = "Old Bills list #{@client.bills_old.pluck(:amount).sum} €"
|
caption = "Old Bills list #{@client.bills_old.pluck(:amount).sum} €"
|
||||||
tr
|
tr
|
||||||
th Title
|
th Title
|
||||||
|
@ -79,8 +76,3 @@ p
|
||||||
td.bg-success = link_to bill.title, bill
|
td.bg-success = link_to bill.title, bill
|
||||||
td.bg-success = bill.amount
|
td.bg-success = bill.amount
|
||||||
td.bg-success = bill.due_date
|
td.bg-success = bill.due_date
|
||||||
|
|
||||||
#comments.container-fluid
|
|
||||||
h2.page-header Comments
|
|
||||||
= render partial: "/comments/about", locals: {commentable: @client}
|
|
||||||
= render partial: "/comments/form"
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
table.table.table-condensed
|
|
||||||
tr
|
|
||||||
th Creator
|
|
||||||
th Title
|
|
||||||
th Content
|
|
||||||
th
|
|
||||||
- commentable.comments.each do |c|
|
|
||||||
tr
|
|
||||||
td = c.creator_type
|
|
||||||
td = c.title
|
|
||||||
td = descriptionize c.comment
|
|
||||||
td
|
|
||||||
= link_to "/comments/#{c.id}.json", remote: true, data: {:confirm => 'Are you sure?'}, method: :delete, class: "close remove-comment", type: "button", "aria-label" => "Close" do
|
|
||||||
span aria-hidden="true" ×
|
|
|
@ -1,10 +0,0 @@
|
||||||
table.table.table-condensed
|
|
||||||
tr
|
|
||||||
th Creator
|
|
||||||
th Title
|
|
||||||
th Content
|
|
||||||
- commentable.comments.each do |c|
|
|
||||||
tr
|
|
||||||
td = c.creator_type
|
|
||||||
td = c.title
|
|
||||||
td = descriptionize c.comment
|
|
|
@ -1,36 +0,0 @@
|
||||||
= form_for @comment, format: :json, remote: true do |f|
|
|
||||||
- if @comment.errors.any?
|
|
||||||
#error_explanation
|
|
||||||
h2 = "#{pluralize(@comment.errors.count, "error")} prohibited this comment from being saved:"
|
|
||||||
ul
|
|
||||||
- @comment.errors.full_messages.each do |message|
|
|
||||||
li = message
|
|
||||||
|
|
||||||
.form-horizontal
|
|
||||||
.form-group
|
|
||||||
.field
|
|
||||||
= f.label :title, class: "sr-only"
|
|
||||||
= f.text_field :title, class: "form-control", placeholder: "Title"
|
|
||||||
.form-group
|
|
||||||
.field
|
|
||||||
= f.label :comment, class: "sr-only"
|
|
||||||
= f.text_area :comment, class: "form-control", placeholder: "Content"
|
|
||||||
.form-inline
|
|
||||||
.field
|
|
||||||
= f.label :commentable_id, class: "form-control", class: "sr-only hidden"
|
|
||||||
= f.number_field :commentable_id, class: "form-control hidden", placeholder: "Commentable ID"
|
|
||||||
.field
|
|
||||||
= f.label :commentable_type, class: "sr-only hidden"
|
|
||||||
= f.text_field :commentable_type, class: "form-control hidden", placeholder: "Commentable Type"
|
|
||||||
.form-inline
|
|
||||||
.field
|
|
||||||
= f.label :creator_id, class: "sr-only"
|
|
||||||
= f.number_field :creator_id, class: "form-control hidden", placeholder: "Creator ID"
|
|
||||||
.field
|
|
||||||
= f.label :creator_type, class: "sr-only hidden"
|
|
||||||
= f.text_field :creator_type, class: "form-control hidden", placeholder: "Creator Type"
|
|
||||||
.form-inline
|
|
||||||
.field
|
|
||||||
= f.label :role, class: "sr-only hidden"
|
|
||||||
= f.text_field :role, class: "form-control hidden", placeholder: "Role"
|
|
||||||
.actions = f.submit class: "btn btn-success action-comment"
|
|
|
@ -1,4 +0,0 @@
|
||||||
#comments.container-fluid
|
|
||||||
h2.page-header Comments
|
|
||||||
= render partial: "/comments/form"
|
|
||||||
= render partial: "/comments/about#{type == 'user' ? '_client' : '' }", locals: {commentable: commentable}
|
|
|
@ -1 +0,0 @@
|
||||||
== render partial: 'thread', locals: {commentable: @commentable, type: 'admin'}
|
|
|
@ -1 +0,0 @@
|
||||||
== render partial: 'thread', locals: {commentable: @commentable, type: 'user'}
|
|
|
@ -1,7 +0,0 @@
|
||||||
h1.page-header Editing comment
|
|
||||||
|
|
||||||
== render 'form'
|
|
||||||
|
|
||||||
= link_to t('show'), @comment
|
|
||||||
'|
|
|
||||||
= link_to t('back'), comments_path
|
|
|
@ -1,33 +0,0 @@
|
||||||
h1 Listing comments
|
|
||||||
|
|
||||||
table.table.table-condensed
|
|
||||||
thead
|
|
||||||
tr
|
|
||||||
th Title
|
|
||||||
th Comment
|
|
||||||
th Commentable
|
|
||||||
th Commentable type
|
|
||||||
th Creator ID
|
|
||||||
th Creator Type
|
|
||||||
th Role
|
|
||||||
th
|
|
||||||
th
|
|
||||||
th
|
|
||||||
|
|
||||||
tbody
|
|
||||||
- @comments.each do |comment|
|
|
||||||
tr
|
|
||||||
td = comment.title
|
|
||||||
td = comment.comment
|
|
||||||
td = comment.commentable_id
|
|
||||||
td = comment.commentable_type
|
|
||||||
td = comment.creator_id
|
|
||||||
td = comment.creator_type
|
|
||||||
td = comment.role
|
|
||||||
td = link_to t('show'), comment
|
|
||||||
td = link_to t('edit'), edit_comment_path(comment)
|
|
||||||
td = link_to t('destroy'), comment, data: {:confirm => 'Are you sure?'}, :method => :delete
|
|
||||||
|
|
||||||
br
|
|
||||||
|
|
||||||
= link_to t('new'), new_comment_path
|
|
|
@ -1,4 +0,0 @@
|
||||||
json.array!(@comments) do |comment|
|
|
||||||
json.extract! comment, :id, :title, :comment, :commentable_id, :commentable_type, :creator_id, :creator_type, :role
|
|
||||||
json.url comment_url(comment, format: :json)
|
|
||||||
end
|
|
|
@ -1,5 +0,0 @@
|
||||||
h1.page-header New comment
|
|
||||||
|
|
||||||
== render 'form'
|
|
||||||
|
|
||||||
= link_to t('back'), comments_path
|
|
|
@ -1,27 +0,0 @@
|
||||||
p#notice = notice
|
|
||||||
|
|
||||||
p
|
|
||||||
strong Title:
|
|
||||||
= @comment.title
|
|
||||||
p
|
|
||||||
strong Comment:
|
|
||||||
= @comment.comment
|
|
||||||
p
|
|
||||||
strong Commentable:
|
|
||||||
= @comment.commentable_id
|
|
||||||
p
|
|
||||||
strong Commentable type:
|
|
||||||
= @comment.commentable_type
|
|
||||||
p
|
|
||||||
strong Creator id:
|
|
||||||
= @comment.creator_id
|
|
||||||
p
|
|
||||||
strong Creator type:
|
|
||||||
= @comment.creator_type
|
|
||||||
p
|
|
||||||
strong Role:
|
|
||||||
= @comment.role
|
|
||||||
|
|
||||||
= link_to t('edit'), edit_comment_path(@comment)
|
|
||||||
'|
|
|
||||||
= link_to t('back'), comments_path
|
|
|
@ -1 +0,0 @@
|
||||||
json.extract! @comment, :id, :title, :comment, :commentable_id, :commentable_type, :creator_id, :creator_type, :role, :created_at, :updated_at
|
|
|
@ -6,49 +6,34 @@
|
||||||
- @contact.errors.full_messages.each do |message|
|
- @contact.errors.full_messages.each do |message|
|
||||||
li = message
|
li = message
|
||||||
|
|
||||||
.form-horizontal
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.autocomplete_field :client, autocomplete_client_name_contacts_path, :id_element => '#contact_client_id', class: "form-control", placeholder: "Client Name"
|
= f.label :client_id
|
||||||
= f.label :client_id, class: "sr-only"
|
= f.text_field :client_id
|
||||||
= f.text_field :client_id, class: "form-control sr-only", placeholder: "Client ID"
|
|
||||||
.form-inline
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :name, class: "sr-only"
|
= f.label :name
|
||||||
= f.text_field :name, class: "form-control", placeholder: "Name"
|
= f.text_field :name
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :phone, class: "sr-only"
|
= f.label :phone
|
||||||
= f.text_field :phone, class: "form-control", placeholder: "Phone"
|
= f.text_field :phone
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :email, class: "sr-only"
|
= f.label :email
|
||||||
= f.text_field :email, class: "form-control", placeholder: "Email"
|
= f.text_field :email
|
||||||
.form-inline
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :region, class: "sr-only"
|
= f.label :last_contact
|
||||||
= f.text_field :region, class: "form-control", placeholder: "Region"
|
= f.date_select :last_contact
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :department, class: "sr-only"
|
= f.label :note
|
||||||
= f.text_field :department, class: "form-control", placeholder: "Department"
|
= f.text_area :note
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :postal_code, class: "sr-only"
|
= f.label :region
|
||||||
= f.text_field :postal_code, class: "form-control", placeholder: "Postal Code"
|
= f.text_field :region
|
||||||
.form-horizontal
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :address, class: "sr-only"
|
= f.label :department
|
||||||
= f.text_area :address, class: "form-control", placeholder: "Address"
|
= f.text_field :department
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :note, class: "sr-only"
|
= f.label :postal_code
|
||||||
= f.text_area :note, class: "form-control", placeholder: "Note"
|
= f.text_field :postal_code
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :view_at, class: "sr-only"
|
= f.label :address
|
||||||
= f.text_field :view_at, class: "form-control form-date", placeholder: "View at"
|
= f.text_area :address
|
||||||
.actions = f.submit class: "btn btn-success"
|
.actions = f.submit
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
h1.page-header Editing contact
|
h1 Editing contact
|
||||||
|
|
||||||
== render 'form'
|
== render 'form'
|
||||||
|
|
||||||
= link_to 'Show', @contact
|
= link_to 'Show', @contact
|
||||||
'|
|
'|
|
||||||
= link_to 'Back', contacts_path
|
= link_to 'Back', contacts_path
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
h1.page-header Listing contacts
|
h1 Listing contacts
|
||||||
|
|
||||||
table.table.table-condensed.
|
table.table.table-condensed.table-striped
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
td ID
|
td ID
|
||||||
|
@ -8,10 +8,12 @@ table.table.table-condensed.
|
||||||
th Name
|
th Name
|
||||||
th Phone
|
th Phone
|
||||||
th Email
|
th Email
|
||||||
|
th Last contact
|
||||||
th Note
|
th Note
|
||||||
|
th Region
|
||||||
|
th Department
|
||||||
th Postal code
|
th Postal code
|
||||||
th Last view
|
th Address
|
||||||
th
|
|
||||||
th
|
th
|
||||||
th
|
th
|
||||||
th
|
th
|
||||||
|
@ -24,15 +26,15 @@ table.table.table-condensed.
|
||||||
td = link_to contact.name, contact
|
td = link_to contact.name, contact
|
||||||
td = contact.phone
|
td = contact.phone
|
||||||
td = contact.email
|
td = contact.email
|
||||||
|
td = contact.last_contact
|
||||||
td = contact.note
|
td = contact.note
|
||||||
|
td = contact.region
|
||||||
|
td = contact.department
|
||||||
td = contact.postal_code
|
td = contact.postal_code
|
||||||
td.contact-value-view_at
|
td = contact.address
|
||||||
= contact.view_at
|
td = link_to '', contact, class: 'glyphicon glyphicon-eye-open'
|
||||||
td.contact-link-view_at
|
td = link_to '', edit_contact_path(contact), class: 'glyphicon glyphicon-pencil'
|
||||||
= link_to 'View today!', view_contact_path(contact), method: :patch, remote: true
|
td = link_to '', contact, data: {:confirm => 'Are you sure?'}, :method => :delete, class: 'glyphicon glyphicon-remove-sign'
|
||||||
td = link_to 'Show', contact
|
|
||||||
td = link_to 'Edit', edit_contact_path(contact)
|
|
||||||
td = link_to 'Destroy', contact, data: {:confirm => 'Are you sure?'}, :method => :delete
|
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
json.array!(@contacts) do |contact|
|
json.array!(@contacts) do |contact|
|
||||||
json.extract! contact, :id, :client_id, :name, :phone, :email, :view_at, :note, :region, :department, :postal_code, :address
|
json.extract! contact, :id, :client_id, :name, :phone, :email, :last_contact, :note, :region, :department, :postal_code, :address
|
||||||
json.url contact_url(contact, format: :json)
|
json.url contact_url(contact, format: :json)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
h1.page-header New contact
|
h1 New contact
|
||||||
|
|
||||||
== render 'form'
|
== render 'form'
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
h1.page-header Show contact
|
p#notice = notice
|
||||||
|
|
||||||
p
|
p
|
||||||
strong Client:
|
strong Client:
|
||||||
|
@ -13,8 +13,8 @@ p
|
||||||
strong Email:
|
strong Email:
|
||||||
= @contact.email
|
= @contact.email
|
||||||
p
|
p
|
||||||
strong View at:
|
strong Last contact:
|
||||||
= @contact.view_at
|
= @contact.last_contact
|
||||||
p
|
p
|
||||||
strong Note:
|
strong Note:
|
||||||
= @contact.note
|
= @contact.note
|
||||||
|
@ -33,8 +33,3 @@ p
|
||||||
|
|
||||||
= link_to 'Edit', edit_contact_path(@contact), class: 'btn btn-sm btn-default'
|
= link_to 'Edit', edit_contact_path(@contact), class: 'btn btn-sm btn-default'
|
||||||
= link_to 'Back', contacts_path, class: 'btn btn-sm btn-default'
|
= link_to 'Back', contacts_path, class: 'btn btn-sm btn-default'
|
||||||
|
|
||||||
#comments.container-fluid
|
|
||||||
h2.page-header Comments
|
|
||||||
= render partial: "/comments/about", locals: {commentable: @contact}
|
|
||||||
= render partial: "/comments/form"
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
json.extract! @contact, :id, :client_id, :name, :phone, :email, :view_at, :note, :region, :department, :postal_code, :address, :created_at, :updated_at
|
json.extract! @contact, :id, :client_id, :name, :phone, :email, :last_contact, :note, :region, :department, :postal_code, :address, :created_at, :updated_at
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
h1.page-header = t ".title"
|
|
||||||
|
|
||||||
.row.placeholders
|
|
||||||
.col-xs-6.col-sm-2.placeholder
|
|
||||||
= link_to clients_url do
|
|
||||||
= image_tag "icone_client.png", alt: "image clients", class: "img-responsive", size: "128x128"
|
|
||||||
h4 Clients
|
|
||||||
span.text-muted = "Count: #{@clients_count}"
|
|
||||||
br
|
|
||||||
|
|
||||||
.col-xs-6.col-sm-2.placeholder
|
|
||||||
= link_to contacts_url do
|
|
||||||
= image_tag "icone_contact.png", alt: "image contact", class: "img-responsive", size: "128x128"
|
|
||||||
h4 Contacts
|
|
||||||
span.text-muted = "Count: #{@contacts_count}"
|
|
||||||
br
|
|
||||||
span.text-muted = "Client with no contacts: #{@no_client_contacts_count}"
|
|
||||||
br
|
|
||||||
|
|
||||||
.col-xs-6.col-sm-2.placeholder
|
|
||||||
= link_to bills_url do
|
|
||||||
= image_tag "icone_bill.png", alt: "image bills", class: "img-responsive", size: "128x128"
|
|
||||||
h4 Bills
|
|
||||||
span.text-muted = "Retard bills: #{@retard_bills}"
|
|
||||||
br
|
|
||||||
span.text-muted = "Advanced bills: #{@advanced_bills}"
|
|
||||||
br
|
|
||||||
span.text-muted = "Next bills: #{@retard_bills}"
|
|
||||||
br
|
|
||||||
span.text-muted = "Old bills: #{@old_bills}"
|
|
||||||
br
|
|
||||||
span.text-muted = "Total Bills: #{@bills_count}"
|
|
||||||
br
|
|
||||||
|
|
||||||
.col-xs-6.col-sm-2.placeholder
|
|
||||||
= link_to tickets_url do
|
|
||||||
= image_tag "icone_ticket.png", alt: "image tickets", class: "img-responsive", size: "128x128"
|
|
||||||
h4 Tickets
|
|
||||||
span.text-muted = "Closed tickets: #{@ticket_closed}"
|
|
||||||
br
|
|
||||||
span.text-muted = "Opened tickets: #{@ticket_opened}"
|
|
||||||
br
|
|
||||||
span.text-muted = "Waiting tickets: #{@ticket_waiting}"
|
|
||||||
br
|
|
||||||
|
|
||||||
.col-xs-6.col-sm-2.placeholder
|
|
||||||
= link_to admins_export_url do
|
|
||||||
= image_tag "icone_export.png", alt: "image export", class: "img-responsive", size: "128x128"
|
|
||||||
h4
|
|
||||||
abbr[title="This option only export the clients, contacts, and bills, without comments etc. If you want to export the complete database, use the native feature of your ORDBMS."] Export
|
|
||||||
span.text-muted = "Clients: #{@clients_count}"
|
|
||||||
br
|
|
||||||
span.text-muted = "Contacts: #{@contacts_count}"
|
|
||||||
br
|
|
||||||
span.text-muted = "Bills: #{@bills_count}"
|
|
||||||
br
|
|
||||||
|
|
||||||
/ here, add a wonderful statistic graph with js
|
|
|
@ -1,3 +0,0 @@
|
||||||
json.clients(@clients)
|
|
||||||
json.contacts(@contacts)
|
|
||||||
json.bills(@bills)
|
|
|
@ -1,53 +0,0 @@
|
||||||
h1.page-header Help
|
|
||||||
|
|
||||||
- if user_signed_in?
|
|
||||||
.panel.panel-primary
|
|
||||||
.panel-heading
|
|
||||||
.panel-title Client
|
|
||||||
.panel-body
|
|
||||||
p
|
|
||||||
| Wecome to the Morning Peak CRM.
|
|
||||||
| This is an open source web application, designed for you, client of a provider, and your creditor.
|
|
||||||
| The application is compatible on Desktop, Tablet, and Mobiles.
|
|
||||||
h3 On Desktop
|
|
||||||
p
|
|
||||||
| With a large screen, you will be able to use the left sidebar panel. It allowes you to access to your
|
|
||||||
| dashboard (click on 'User'). You have also a link to the bills you due to your provider, and a links to the tickets,
|
|
||||||
| used to make easier the contact and conversation with him.
|
|
||||||
h3 On Tablet and Mobile
|
|
||||||
p
|
|
||||||
| With Tablets and Mobiles, you cannot see the sidebar panel. Instead, you will have an access to your dashboard,
|
|
||||||
| by using the square button on the top right.
|
|
||||||
br
|
|
||||||
| On the dashboard, you will see how many Bills you have (due, passed, ...) and the same for your tickets.
|
|
||||||
|
|
||||||
- if admin_signed_in?
|
|
||||||
.panel.panel-danger
|
|
||||||
.panel-heading
|
|
||||||
.panel-title Admin
|
|
||||||
.panel-body
|
|
||||||
p
|
|
||||||
| You can access to the list of your clients, the contacts for each clients,
|
|
||||||
| the bills your clients due to you and also the tickets to communicate with them.
|
|
||||||
|
|
||||||
- if not user_signed_in? and not admin_signed_in?
|
|
||||||
.panel.panel-primary
|
|
||||||
.panel-heading
|
|
||||||
.panel-title Connection
|
|
||||||
.panel-body
|
|
||||||
p
|
|
||||||
| To use this application, you have to sign in as a Client or Administrator with your créditentials.
|
|
||||||
br
|
|
||||||
= link_to "Sign in as User", new_user_session_path
|
|
||||||
br
|
|
||||||
| If you are an administrator, use this link instead
|
|
||||||
br
|
|
||||||
= link_to "Sign in as Admin", new_admin_session_path
|
|
||||||
br
|
|
||||||
|
|
||||||
p
|
|
||||||
| You can also contact the administrator, via the
|
|
||||||
= link_to "developpers on the website", "https://gitlab.com/poulet_a/MorningPeak/issues"
|
|
||||||
br
|
|
||||||
| Please, don't forget to be explicit and to write carefully.
|
|
||||||
| It the request is too much broad, then it will not be handled.
|
|
|
@ -3,18 +3,22 @@
|
||||||
.space-client.col-xs-4
|
.space-client.col-xs-4
|
||||||
.panel.panel-success
|
.panel.panel-success
|
||||||
.panel-heading
|
.panel-heading
|
||||||
h3 = t "home.user_dashboard.title"
|
h3
|
||||||
|
| Client
|
||||||
|
.glyphicon.glyphicon-log-in
|
||||||
.panel-body
|
.panel-body
|
||||||
- if user_signed_in?
|
- if user_signed_in?
|
||||||
= link_to t(".links.logout"), destroy_user_session_path, method: :delete
|
= link_to "Log out", destroy_user_session_path, method: :delete
|
||||||
- else
|
- else
|
||||||
= link_to t(".links.login"), new_user_session_path
|
= link_to "Log in", new_user_session_path
|
||||||
.space-admin.col-xs-4
|
.space-admin.col-xs-4
|
||||||
.panel.panel-danger
|
.panel.panel-danger
|
||||||
.panel-heading
|
.panel-heading
|
||||||
h3 = t("home.admin_dashboard.title")
|
h3
|
||||||
|
| Administration
|
||||||
|
.glyphicon.glyphicon-log-in
|
||||||
.panel-body
|
.panel-body
|
||||||
- if admin_signed_in?
|
- if admin_signed_in?
|
||||||
= link_to t(".links.logout"), destroy_admin_session_path, method: :delete
|
= link_to "Log out", destroy_admin_session_path, method: :delete
|
||||||
- else
|
- else
|
||||||
= link_to t(".links.login"), new_admin_session_path
|
= link_to "Log in", new_admin_session_path
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
h1.page-header = t ".title"
|
|
||||||
|
|
||||||
.row.placeholders
|
|
||||||
.col-xs-6.col-sm-3.placeholder
|
|
||||||
= link_to client_bills_url do
|
|
||||||
= image_tag "icone_bill.png", alt: "image bills", class: "img-responsive", size: "128x128"
|
|
||||||
h4 = t "home.dashboard.bills"
|
|
||||||
span.text-muted = "#{t 'home.dashboard.retard_bills'}: #{@retard_bills}"
|
|
||||||
br
|
|
||||||
span.text-muted = "#{t 'home.dashboard.advanced_bills'}: #{@advanced_bills}"
|
|
||||||
br
|
|
||||||
span.text-muted = "#{t 'home.dashboard.next_bills'}: #{@retard_bills}"
|
|
||||||
br
|
|
||||||
span.text-muted = "#{t 'home.dashboard.old_bills'}: #{@old_bills}"
|
|
||||||
br
|
|
||||||
span.text-muted = "#{t 'home.dashboard.total_bills'}: #{@bills_count}"
|
|
||||||
br
|
|
||||||
|
|
||||||
.col-xs-6.col-sm-3.placeholder
|
|
||||||
= link_to client_tickets_url do
|
|
||||||
= image_tag "icone_ticket.png", alt: "image tickets", class: "img-responsive", size: "128x128"
|
|
||||||
h4 = t "home.dashboard.tickets"
|
|
||||||
span.text-muted = "#{t 'home.dashboard.closed_tickets'}: #{@ticket_closed}"
|
|
||||||
br
|
|
||||||
span.text-muted = "#{t 'home.dashboard.opened_tickets'}: #{@ticket_opened}"
|
|
||||||
br
|
|
||||||
span.text-muted = "#{t 'home.dashboard.waiting_tickets'}: #{@ticket_waiting}"
|
|
||||||
br
|
|
|
@ -1,11 +0,0 @@
|
||||||
#infos
|
|
||||||
- if alert
|
|
||||||
#alert.alert.bg-danger
|
|
||||||
span.glyphicon.glyphicon-exclamation-sign aria-hidden="true"
|
|
||||||
span.sr-only Error:
|
|
||||||
= " #{alert}"
|
|
||||||
- if notice
|
|
||||||
#notice.alert.bg-warning
|
|
||||||
span.glyphicon.glyphicon-info-sign aria-hidden="true"
|
|
||||||
span.sr-only Error:
|
|
||||||
= " #{notice}"
|
|
|
@ -1,22 +0,0 @@
|
||||||
nav.navbar.navbar-inverse.navbar-fixed-top
|
|
||||||
.container-fluid
|
|
||||||
#navbar-title.navbar-header
|
|
||||||
button.navbar-toggle.collapsed[type="button" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"]
|
|
||||||
span.sr-only Toggle navigation
|
|
||||||
span.icon-bar
|
|
||||||
span.icon-bar
|
|
||||||
span.icon-bar
|
|
||||||
.navbar-brand
|
|
||||||
= link_to application_title, root_url
|
|
||||||
|
|
||||||
#navbar.navbar-collapse.collapse
|
|
||||||
ul.nav.navbar-nav.navbar-right
|
|
||||||
- if user_signed_in?
|
|
||||||
li = link_to t(".user_dashboard"), users_dashboard_url
|
|
||||||
- if admin_signed_in?
|
|
||||||
li = link_to t(".admin_dashboard"), admins_dashboard_url
|
|
||||||
- if user_signed_in?
|
|
||||||
li = link_to "#{current_user.name} #{t '.logout'}", destroy_user_session_path, method: :delete
|
|
||||||
- if admin_signed_in?
|
|
||||||
li = link_to "#{current_admin.email} #{t '.logout'}", destroy_admin_session_path, method: :delete
|
|
||||||
li = link_to "Help", help_url
|
|
|
@ -1,30 +0,0 @@
|
||||||
.col-sm-3.col-md-2.sidebar
|
|
||||||
/ User side
|
|
||||||
- if user_signed_in?
|
|
||||||
ul.nav.nav-sidebar
|
|
||||||
li.active
|
|
||||||
= link_to users_dashboard_url do
|
|
||||||
= t ".user.user"
|
|
||||||
span.sr-only (current)
|
|
||||||
li = link_to client_bills_url do
|
|
||||||
= t ".user.bills_due"
|
|
||||||
.badge = user_bills_count_due
|
|
||||||
li = link_to client_tickets_url do
|
|
||||||
= t ".user.tickets"
|
|
||||||
.badge = user_tickets_unview_count
|
|
||||||
|
|
||||||
/ Admin side
|
|
||||||
- if admin_signed_in?
|
|
||||||
- if user_signed_in?
|
|
||||||
br
|
|
||||||
ul.nav.nav-sidebar
|
|
||||||
li.active
|
|
||||||
= link_to admins_dashboard_url do
|
|
||||||
= t(".admin.admin")
|
|
||||||
span.sr-only (current)
|
|
||||||
li = link_to t(".admin.clients"), clients_url
|
|
||||||
li = link_to t(".admin.contacts"), contacts_url
|
|
||||||
li = link_to t( ".admin.bills"), bills_url
|
|
||||||
li = link_to tickets_url do
|
|
||||||
= t ".admin.tickets"
|
|
||||||
.badge = admin_tickets_unview_count
|
|
|
@ -2,21 +2,32 @@ doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title = application_title
|
title = application_title
|
||||||
meta charset="utf-8"
|
|
||||||
meta name="viewport" content="width=device-width, initial-scale=1"
|
|
||||||
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
|
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
|
||||||
= javascript_include_tag 'application', 'data-turbolinks-track' => true
|
= javascript_include_tag 'application', 'data-turbolinks-track' => true
|
||||||
= csrf_meta_tags
|
= csrf_meta_tags
|
||||||
|
|
||||||
body
|
body
|
||||||
= render partial: "/layouts/navbar"
|
nav.navbar.navbar-default
|
||||||
|
|
||||||
.container-fluid
|
.container-fluid
|
||||||
.row
|
.navbar-header
|
||||||
= render partial: "/layouts/sidebar"
|
.navbar-brand = link_to application_title, root_url
|
||||||
|
|
||||||
#main.main.col-sm-9.col-sm-offset-3.col-md-10.col-md-offset-2.main
|
.navbar-collapse.collapse
|
||||||
|
- if user_signed_in?
|
||||||
|
.nav.navbar-nav.navbar-left
|
||||||
|
| #{current_user.name}
|
||||||
|
= link_to " bills ", client_bills_url, class: 'btn btn-lg btn-success narbar-btn'
|
||||||
|
= link_to " tickets ", client_tickets_url, class: 'btn btn-lg btn-warning narbar-btn glyphicon glyphicon-envelope'
|
||||||
|
= link_to "", destroy_user_session_path, method: :delete, class: 'btn btn-lg btn-default narbar-btn glyphicon glyphicon-log-out'
|
||||||
|
- if admin_signed_in?
|
||||||
|
.nav.navbar-nav.navbar-right
|
||||||
|
| #{current_admin.email}
|
||||||
|
= link_to " clients ", clients_url, class: 'btn btn-lg btn-primary narbar-btn glyphicon glyphicon-user'
|
||||||
|
= link_to " contact ", contacts_url, class: 'btn btn-lg btn-info narbar-btn glyphicon glyphicon-duplicate'
|
||||||
|
= link_to " bills ", bills_url, class: 'btn btn-lg btn-success narbar-btn glyphicon glyphicon-eur'
|
||||||
|
= link_to " tickets", tickets_url, class: 'btn btn-lg btn-warning narbar-btn glyphicon-envelope'
|
||||||
|
= link_to "", destroy_admin_session_path, method: :delete, class: 'btn btn-lg btn-default narbar-btn glyphicon glyphicon-log-out'
|
||||||
|
|
||||||
= render partial: "/layouts/infos"
|
.yield
|
||||||
#yield.yield
|
.container-fluid
|
||||||
= yield
|
= yield
|
||||||
|
|
|
@ -6,25 +6,22 @@
|
||||||
- @ticket.errors.full_messages.each do |message|
|
- @ticket.errors.full_messages.each do |message|
|
||||||
li = message
|
li = message
|
||||||
|
|
||||||
.form-horizontal
|
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :creator_type, class: "sr-only"
|
= f.label :ticket_id
|
||||||
= f.text_field :creator_type, class: "form-control", placeholder: "Creator type"
|
= f.text_field :ticket_id
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :creator_id, class: "sr-only"
|
= f.label :creator_type
|
||||||
= f.text_field :creator_id, class: "form-control", placeholder: "Creator ID"
|
= f.text_field :creator_type
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :title, class: "sr-only"
|
= f.label :creator_id
|
||||||
= f.text_field :title, class: "form-control", placeholder: "Title"
|
= f.text_field :creator_id
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :description, class: "sr-only"
|
= f.label :title
|
||||||
= f.text_area :description, class: "form-control", placeholder: "Description"
|
= f.text_field :title
|
||||||
.form-group
|
|
||||||
.field
|
.field
|
||||||
= f.label :state, class: "sr-only"
|
= f.label :description
|
||||||
= f.select :state, ["open", "close"], {}, class: "form-control"
|
= f.text_area :description
|
||||||
.actions = f.submit class: "btn btn-success"
|
.field
|
||||||
|
= f.label :state
|
||||||
|
= f.text_field :state
|
||||||
|
.actions = f.submit
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
h1.page-header Editing ticket
|
h1 Editing ticket
|
||||||
|
|
||||||
== render 'form'
|
== render 'form'
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
h1 Listing tickets
|
h1 Listing tickets
|
||||||
|
|
||||||
table.table.table-condensed.
|
table.table.table-condensed.table-striped
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
td ID
|
td ID
|
||||||
|
@ -14,27 +14,29 @@ table.table.table-condensed.
|
||||||
th
|
th
|
||||||
th
|
th
|
||||||
th
|
th
|
||||||
|
th
|
||||||
|
|
||||||
tbody
|
tbody
|
||||||
- @tickets.each do |ticket|
|
- @tickets.each do |ticket|
|
||||||
tr class="#{ticket.admin_view_at.nil? ? 'bg-warning' : ''}"
|
tr
|
||||||
td = link_to("##{ticket.id}", ticket)
|
td = link_to("##{ticket.id}", ticket)
|
||||||
td = link_to_creator(ticket)
|
td = link_to_creator(ticket)
|
||||||
td = link_to ticket.title, ticket
|
td = link_to ticket.title, ticket
|
||||||
td = ticket.short_description
|
td = ticket.description
|
||||||
- if ticket.state == Ticket::CLOSE
|
- if ticket.state == Ticket::CLOSE
|
||||||
td.bg-danger = ticket.state
|
td.bg-danger = ticket.state
|
||||||
- else
|
- else
|
||||||
td.bg-success = ticket.state
|
td.bg-success = ticket.state
|
||||||
td = ticket.updated_at.to_s(:long)
|
td = ticket.updated_at.to_s(:long)
|
||||||
td = ticket.comments.empty? ? "never" : distance_of_time_in_words_to_now(ticket.comments.first.updated_at)
|
td = ticket.last_response ? distance_of_time_in_words_to_now(ticket.last_response.updated_at) : "never"
|
||||||
td = link_to 'Show', ticket
|
td = link_to '', ticket, class: 'glyphicon glyphicon-eye-open'
|
||||||
td = link_to 'Edit', edit_ticket_path(ticket)
|
td = link_to '', edit_ticket_path(ticket), class: 'glyphicon glyphicon-pencil'
|
||||||
td = link_to 'Destroy', ticket, data: {:confirm => 'Are you sure?'}, :method => :delete
|
td = link_to '', ticket, data: {:confirm => 'Are you sure to REMOVE this ticket?'}, :method => :delete, class: 'glyphicon glyphicon-remove-sign'
|
||||||
|
td = link_to '', ticket_respond_path(ticket), class: 'glyphicon glyphicon-comment' if ticket.open?
|
||||||
- if ticket.open?
|
- if ticket.open?
|
||||||
td = link_to 'Close', ticket_close_path(ticket), data: {:confirm => 'Are you sure?'}, :method => :patch
|
td = link_to '', ticket_close_path(ticket), data: {:confirm => 'Are you sure to CLOSE this ticket?'}, method: :patch, class: 'glyphicon glyphicon-ok-circle'
|
||||||
- elsif ticket.close?
|
- elsif ticket.close?
|
||||||
td = link_to 'Reopen', ticket_open_path(ticket), data: {:confirm => 'Are you sure?'}, :method => :patch
|
td = link_to '', ticket_open_path(ticket), data: {:confirm => 'Are you sure to REOPEN this ticket?'}, method: :patch, class: 'glyphicon glyphicon-remove-circle'
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
json.array!(@tickets) do |ticket|
|
json.array!(@tickets) do |ticket|
|
||||||
json.extract! ticket, :id, :title, :description, :state
|
json.extract! ticket, :id, :client_id, :bill_id, :title, :description, :state
|
||||||
json.url ticket_url(ticket, format: :json)
|
json.url ticket_url(ticket, format: :json)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
h1.page-header New ticket
|
h1 New ticket
|
||||||
|
|
||||||
== render 'form'
|
== render 'form'
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
h1.page-header = "Show ticket: #{@ticket.title}"
|
p#notice = notice
|
||||||
|
|
||||||
p
|
p
|
||||||
strong
|
strong
|
||||||
| Id: #
|
| Id: #
|
||||||
= @ticket.id
|
= @ticket.id
|
||||||
|
p
|
||||||
|
strong Réponse à:
|
||||||
|
= link_to @ticket.head.title, @ticket.head
|
||||||
|
|
||||||
p
|
p
|
||||||
strong State:
|
strong State:
|
||||||
- if @ticket.state == Ticket::CLOSE
|
- if @ticket.head.state == Ticket::CLOSE
|
||||||
td.bg-danger = @ticket.state
|
td.bg-danger = @ticket.head.state
|
||||||
- else
|
- else
|
||||||
td.bg-success = @ticket.state
|
td.bg-success = @ticket.head.state
|
||||||
|
|
||||||
p
|
p
|
||||||
strong Creator:
|
strong Creator:
|
||||||
|
@ -20,19 +23,40 @@ p
|
||||||
= @ticket.title
|
= @ticket.title
|
||||||
p
|
p
|
||||||
strong Description:
|
strong Description:
|
||||||
.container-fluid.ticket-description
|
= @ticket.description
|
||||||
= descriptionize @ticket.description
|
|
||||||
p
|
p
|
||||||
strong State:
|
strong State:
|
||||||
= @ticket.state
|
= @ticket.state
|
||||||
|
|
||||||
|
table.table.table-condensed.table-striped
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th Creator
|
||||||
|
th Title
|
||||||
|
th Description
|
||||||
|
th Last update
|
||||||
|
th
|
||||||
|
th
|
||||||
|
th
|
||||||
|
|
||||||
|
tbody
|
||||||
|
- @ticket.tickets.each do |ticket|
|
||||||
|
tr
|
||||||
|
td = link_to_creator(ticket)
|
||||||
|
td = link_to ticket.title, ticket
|
||||||
|
td = ticket.description
|
||||||
|
- if ticket.state == Ticket::CLOSE
|
||||||
|
td.bg-danger = ticket.state
|
||||||
|
- else
|
||||||
|
td.bg-success = ticket.state
|
||||||
|
td = ticket.updated_at.to_s(:long)
|
||||||
|
td = link_to 'Show', ticket
|
||||||
|
td = link_to 'Edit', edit_ticket_path(ticket)
|
||||||
|
td = link_to 'Destroy', ticket, data: {:confirm => 'Are you sure?'}, :method => :delete
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
||||||
- if @ticket.open?
|
|
||||||
= link_to 'Close', ticket_close_path(@ticket), method: :patch, class: 'btn btn-sm btn-success'
|
= link_to 'Respond', ticket_respond_path(@ticket), class: 'btn btn-sm btn-default'
|
||||||
- else
|
|
||||||
= link_to 'Reopen', ticket_open_path(@ticket), method: :patch, class: 'btn btn-sm btn-danger'
|
|
||||||
= link_to 'Edit', edit_ticket_path(@ticket), class: 'btn btn-sm btn-default'
|
= link_to 'Edit', edit_ticket_path(@ticket), class: 'btn btn-sm btn-default'
|
||||||
= link_to 'Back', tickets_path, class: 'btn btn-sm btn-default'
|
= link_to 'Back', tickets_path, class: 'btn btn-sm btn-default'
|
||||||
|
|
||||||
== render partial: "/comments/thread", locals: {commentable: @ticket, type: 'admin'}
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
json.extract! @ticket, :id, :title, :description, :state, :created_at, :updated_at
|
json.extract! @ticket, :id, :client_id, :bill_id, :title, :description, :state, :created_at, :updated_at
|
||||||
|
|
|
@ -6,7 +6,7 @@ require 'rails/all'
|
||||||
# you've limited to :test, :development, or :production.
|
# you've limited to :test, :development, or :production.
|
||||||
Bundler.require(*Rails.groups)
|
Bundler.require(*Rails.groups)
|
||||||
|
|
||||||
module MorningPeak
|
module WebImmo
|
||||||
class Application < Rails::Application
|
class Application < Rails::Application
|
||||||
# Settings in config/environments/* take precedence over those specified here.
|
# Settings in config/environments/* take precedence over those specified here.
|
||||||
# Application configuration should go into files in config/initializers
|
# Application configuration should go into files in config/initializers
|
||||||
|
|
|
@ -1,14 +1,46 @@
|
||||||
default: &default
|
development:
|
||||||
adapter: postgresql
|
adapter: postgresql
|
||||||
|
host: localhost
|
||||||
username: root
|
username: root
|
||||||
|
database: appli_dev
|
||||||
password: toor
|
password: toor
|
||||||
|
|
||||||
development:
|
|
||||||
<<: *default
|
|
||||||
host: localhost
|
|
||||||
database: webimmo_dev
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
<<: *default
|
adapter: postgresql
|
||||||
host: localhost
|
host: localhost
|
||||||
database: webimmo_test
|
username: root
|
||||||
|
database: appli_test
|
||||||
|
password: toor
|
||||||
|
|
||||||
|
production:
|
||||||
|
adapter: postgresql
|
||||||
|
host: localhost
|
||||||
|
username: root
|
||||||
|
database: appli_prod
|
||||||
|
password: toor
|
||||||
|
|
||||||
|
# # SQLite version 3.x
|
||||||
|
# # gem install sqlite3
|
||||||
|
# #
|
||||||
|
# # Ensure the SQLite 3 gem is defined in your Gemfile
|
||||||
|
# # gem 'sqlite3'
|
||||||
|
# #
|
||||||
|
# default: &default
|
||||||
|
# adapter: sqlite3
|
||||||
|
# pool: 5
|
||||||
|
# timeout: 5000
|
||||||
|
|
||||||
|
# development:
|
||||||
|
# <<: *default
|
||||||
|
# database: db/development.sqlite3
|
||||||
|
|
||||||
|
# # Warning: The database defined as "test" will be erased and
|
||||||
|
# # re-generated from your development database when you run "rake".
|
||||||
|
# # Do not set this db to the same as development or production.
|
||||||
|
# test:
|
||||||
|
# <<: *default
|
||||||
|
# database: db/test.sqlite3
|
||||||
|
|
||||||
|
# production:
|
||||||
|
# <<: *default
|
||||||
|
# database: db/production.sqlite3
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
# Be sure to restart your server when you modify this file.
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
Rails.application.config.session_store :cookie_store, key: '_MorningPeak_session'
|
Rails.application.config.session_store :cookie_store, key: '_WebImmo_session'
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
fr:
|
|
||||||
bills:
|
|
||||||
form:
|
|
||||||
client_id: ID du Client
|
|
||||||
title: Titre
|
|
||||||
description: Détail
|
|
||||||
amount: Montant
|
|
||||||
is_paid: Payé ?
|
|
||||||
e_date: "Date d'emission"
|
|
||||||
d_date: "Date d'échéance"
|
|
||||||
edit:
|
|
||||||
page:
|
|
||||||
title: Éditer une facture
|
|
||||||
new:
|
|
||||||
page:
|
|
||||||
title: Nouvelle facture
|
|
||||||
index:
|
|
||||||
page:
|
|
||||||
title: Liste des factures
|
|
||||||
id: ID
|
|
||||||
client: Client
|
|
||||||
Title: Titre
|
|
||||||
description: Detail
|
|
||||||
amount: Montant
|
|
||||||
is_paid: Payé ?
|
|
||||||
e_date: "Date d'emission"
|
|
||||||
d_date: "Date d'échéance"
|
|
||||||
show:
|
|
||||||
page:
|
|
||||||
title: Facture
|
|
||||||
id: ID
|
|
||||||
client: Client
|
|
||||||
Title: Titre
|
|
||||||
description: Detail
|
|
||||||
amount: Montant
|
|
||||||
is_paid: Payé ?
|
|
||||||
e_date: "Date d'emission"
|
|
||||||
d_date: "Date d'échéance"
|
|
||||||
|
|
||||||
en:
|
|
||||||
bills:
|
|
||||||
form:
|
|
||||||
client_id: Client ID
|
|
||||||
title: Title
|
|
||||||
description: Description
|
|
||||||
amount: Amount
|
|
||||||
is_paid: Paid ?
|
|
||||||
e_date: Emission date
|
|
||||||
d_date: Due date
|
|
||||||
edit:
|
|
||||||
page:
|
|
||||||
title: Edit a Bill
|
|
||||||
new:
|
|
||||||
page:
|
|
||||||
title: New Bill
|
|
||||||
index:
|
|
||||||
page:
|
|
||||||
title: Listing Bills
|
|
||||||
id: ID
|
|
||||||
client: Client
|
|
||||||
title: Title
|
|
||||||
description: Description
|
|
||||||
amount: Amount
|
|
||||||
is_paid: Paid ?
|
|
||||||
e_date: Emission date
|
|
||||||
d_date: Due date
|
|
||||||
show:
|
|
||||||
page:
|
|
||||||
title: Bill
|
|
||||||
id: ID
|
|
||||||
client: Client
|
|
||||||
title: Title
|
|
||||||
description: Description
|
|
||||||
amount: Amount
|
|
||||||
is_paid: Paid ?
|
|
||||||
e_date: Emission date
|
|
||||||
d_date: Due date
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user