Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d58fd6434f | ||
|
|
0f9733c890 | ||
|
|
14643d3cf4 | ||
|
|
d49f837b2e | ||
|
|
cb19d235c6 | ||
|
|
d41d1d8a34 | ||
|
|
b6d9c7816c | ||
|
|
7345d065b8 | ||
|
|
3211e8607d | ||
|
|
be3e0fa2c2 | ||
|
|
41d24fe134 | ||
|
|
e9f7141f65 | ||
|
|
d7e60e1e23 | ||
|
|
1ed6410380 | ||
|
|
42783f8886 | ||
|
|
80054e8aa9 | ||
|
|
7be4f10441 | ||
|
|
a0a8b57992 | ||
|
|
e8ee0862ef | ||
|
|
1b006b83ad | ||
|
|
71527eab2b | ||
|
|
1576c57241 | ||
|
|
187d602c91 | ||
|
|
e88cd2d880 | ||
|
|
4baea3e63f | ||
|
|
eeed7ad847 | ||
|
|
9f27939471 | ||
|
|
5e61291703 | ||
|
|
59174b40ff | ||
|
|
359c768041 | ||
|
|
a64861ce63 | ||
|
|
115d50f793 | ||
|
|
e4b5856338 | ||
|
|
a8cbfb1ec0 | ||
|
|
c4bb20fd12 | ||
|
|
5eba524bfc | ||
|
|
0ba46039a2 | ||
|
|
340df9ce16 | ||
|
|
eaa15d2905 | ||
|
|
29413c0e52 | ||
|
|
347e79610e | ||
|
|
c084792d32 | ||
|
|
d77e636e53 | ||
|
|
4729252c63 | ||
|
|
6cbb82a927 | ||
|
|
bba9030f14 | ||
|
|
7cf6dbbe38 | ||
|
|
00993e7fe1 | ||
|
|
0fb92efbf3 | ||
|
|
2856da6888 | ||
|
|
c01a6dc9e9 | ||
|
|
845c96cd48 | ||
|
|
094d18be46 | ||
|
|
c6937fd184 | ||
|
|
430744a324 | ||
|
|
98c1589a1a | ||
|
|
d81bb8c893 | ||
|
|
21b774143b | ||
|
|
3925adc3f2 | ||
|
|
371f5e23c3 | ||
|
|
825fda5544 | ||
|
|
6ede5c1559 | ||
|
|
1ff90dacde | ||
|
|
2654b684df | ||
|
|
d424395d85 | ||
|
|
54810b3458 | ||
|
|
1cf66ad6c0 | ||
|
|
6dc334ca51 | ||
|
|
f9b4ead6be | ||
|
|
3bf6703929 | ||
|
|
ec657b9dcb | ||
|
|
4ffd048b2a | ||
|
|
6af19670da | ||
|
|
721e375d76 |
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,3 +1,7 @@
|
||||
test-results/
|
||||
tmp/
|
||||
routes/
|
||||
/none
|
||||
/src
|
||||
pkg
|
||||
bin2
|
||||
@@ -7,7 +11,6 @@ bin/release
|
||||
bin/test.sh
|
||||
bin/tmp
|
||||
bin/test
|
||||
bin/src
|
||||
public/upload
|
||||
app/routes/routes.go
|
||||
app/tmp/main.go
|
||||
@@ -15,5 +18,11 @@ app/tmp/main.go
|
||||
.settings
|
||||
.project
|
||||
public/config.codekit
|
||||
files
|
||||
files/
|
||||
/node_modules
|
||||
.idea
|
||||
*.iml
|
||||
target/
|
||||
package/leanote.tar.gz
|
||||
package/leanote/
|
||||
leanote.log
|
||||
17
.project
17
.project
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>leanote-public</name>
|
||||
<comment>leanote, your own cloud note!</comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.googlecode.goclipse.goBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>goclipse.goNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
28
.travis.yml
28
.travis.yml
@@ -1,29 +1,41 @@
|
||||
language: go
|
||||
go: 1.4
|
||||
go: 1.15
|
||||
|
||||
services:
|
||||
- mongodb # 2.4.12
|
||||
|
||||
install:
|
||||
- go version
|
||||
- export PATH=$PATH:$HOME/gopath/bin
|
||||
- go get -v github.com/leanote/leanote/app
|
||||
# - go get -v github.com/leanote/leanote/app
|
||||
- go get -u github.com/revel/cmd/revel
|
||||
- ls $GOPATH/src/github.com/revel/
|
||||
# - ls $GOPATH/src/github.com/revel/
|
||||
# - go get github.com/revel/moudle/revel
|
||||
# - go install github.com/revel/cmd/revel
|
||||
- revel version
|
||||
- pwd
|
||||
- ls
|
||||
|
||||
script:
|
||||
- wget https://github.com/leanote/leanote/archive/refs/heads/master.zip
|
||||
- unzip master.zip
|
||||
- mv leanote-master leanote
|
||||
- cd leanote
|
||||
|
||||
- mongo --version
|
||||
- mongorestore -h localhost -d leanote --directoryperdb ./mongodb_backup/leanote_install_data/
|
||||
- mongorestore -h localhost -d leanote --dir ./mongodb_backup/leanote_install_data/
|
||||
|
||||
- cd ./sh
|
||||
# - cd $GOPATH/src/github.com/leanote/leanote/sh
|
||||
- sh run.sh &
|
||||
|
||||
# gen tmp/main.go, routes/routes.go
|
||||
- go run app/cmd/main.go
|
||||
#- go run app/cmd/main.go
|
||||
# build
|
||||
- go build -o leanote github.com/leanote/leanote/app/tmp
|
||||
#- go build -o leanote github.com/leanote/leanote/app/tmp
|
||||
# run with port 9000
|
||||
- ./leanote -importPath=github.com/leanote/leanote -runMode=dev -port=9000 &
|
||||
#- ./leanote -importPath=github.com/leanote/leanote -runMode=dev -port=9000 &
|
||||
|
||||
- sleep 10s;
|
||||
# test
|
||||
- curl http://localhost:9000
|
||||
@@ -32,4 +44,4 @@ script:
|
||||
- curl http://localhost:9000/demo
|
||||
|
||||
# - revel build github.com/leanote/leanote tmp
|
||||
# OK
|
||||
# OK
|
||||
|
||||
359
LICENSE
359
LICENSE
@@ -1,359 +0,0 @@
|
||||
LEANOTE - NOT JUST A NOTEPAD!
|
||||
|
||||
Copyright 2014-2015 by the contributors
|
||||
|
||||
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 2 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.
|
||||
|
||||
Leanote is licensed under the GPL v2.
|
||||
|
||||
life(life@leanote.com, lifephp@gmail.com)
|
||||
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) 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
|
||||
this service 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 make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. 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.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
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
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the 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 a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE 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.
|
||||
|
||||
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
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
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 2 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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision 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, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This 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.
|
||||
13
README.md
13
README.md
@@ -31,7 +31,7 @@ We have been using the popular note-taking software/service `Evernote` as our kn
|
||||
|
||||
* A more powerful editor: `Evernote`'s editor lacks the functionalities of **document navigation**, **syntax based code rendering** (as a programmer, syntax highlighted code rendering is a necessity), **image resizing** and so forth.
|
||||
* Everybody loves *markdown*, however `Evernote` simply wouldn't add it despite of years' of requests from users. So we will do the favor and bring a *markdown* enabled editor to you, guess what, it is also rendered in real-time!
|
||||
* If you a developer and miss the `Vim` or `Emacs` ways of writing, we offer you the choice of `Vim` and `Emacs` editting modes. Equipped with *markdown* syntax for text formatting, you will never need to touch your mouse while writing.
|
||||
* If you a developer and miss the `Vim` or `Emacs` ways of writing, we offer you the choice of `Vim` and `Emacs` editing modes. Equipped with *markdown* syntax for text formatting, you will never need to touch your mouse while writing.
|
||||
* We love managing knowledge and thoughts as much as sharing them, so everybody has their own note account (`Evernote`, `Onenote`, `Google doc`, `Wiz note` etc.) and social media account (`Facebook`, `Wordpress`, blogs, etc.). But why can’t those two be one? Leanote makes this first step to bridge the private note-taking and public knowledge sharing seamlessly.
|
||||
* A complete and all-platform (sorry Windows phone) covering software suite: that includes Leanote Web & Server (this repository), [Desktop app](https://github.com/leanote/desktop-app), [iOS](https://github.com/leanote/leanote-ios), [Android](https://github.com/leanote/leanote-android). And they are all open source!
|
||||
* ......
|
||||
@@ -50,7 +50,7 @@ More information about how to install Leanote please see:
|
||||
* [Windows](https://github.com/leanote/leanote/wiki/leanote-source-installation-on-Windows-(En))
|
||||
* [Mac and Linux](https://github.com/leanote/leanote/wiki/leanote-binary-installation-on-Mac-and-Linux-(En))
|
||||
* Leanote source installation tutorial:
|
||||
* [Windows](https://github.com/leanote/leanote/wiki/leanote-source-installation-on-Windows-(En))
|
||||
<!-- * [Windows](https://github.com/leanote/leanote/wiki/leanote-source-installation-on-Windows-(En)) -->
|
||||
* [Mac and Linux](https://github.com/leanote/leanote/wiki/Leanote-source-installation-on-Mac-and-Linux-(En))
|
||||
|
||||
## 4. Documentation
|
||||
@@ -66,7 +66,7 @@ If you are a developer yourself and feel like to build on top of Leanote, please
|
||||
## 6. Contributions
|
||||
|
||||
Like or dislike Leanote, please leave your comments and suggestions to help us improve it.
|
||||
If you encounter any issue, we suggest you first do a search in the issues section to see whether a solution already exists, or open up a new one otherwise.
|
||||
If you encounter any issue, we suggest you first search the issues section to see whether a solution already exists, or open up a new one otherwise.
|
||||
|
||||
We’d like to acknowledge the contributions made by our [developers and contributors](https://github.com/leanote/leanote/graphs/contributors) to
|
||||
this project. Leanote won’t exist without your hard work. Your help is much appreciated.
|
||||
@@ -81,12 +81,12 @@ If you find any problems or have any good ideas, feature requests, please submit
|
||||
## 8. Donation
|
||||
|
||||
If you like our product, consider supporting us via [donate us](http://leanote.org/#donate).
|
||||
We acknowledge the donations make by all the [donators](http://leanote.leanote.com/post/leanote-donation-list).
|
||||
We acknowledge the donations made by all the [donators](http://leanote.leanote.com/post/leanote-donation-list).
|
||||
|
||||
## 9. Related projects
|
||||
|
||||
* [Leanote Desktop App](https://github.com/leanote/desktop-app), [Download](http://app.leanote.com)
|
||||
* [Leanote iOS](https://github.com/leanote/leanote-ios), [Download From App Store](https://itunes.apple.com/en/app/leanote/id1022302858?mt=8)
|
||||
* [Leanote iOS](https://github.com/leanote/leanote-ios), [Download From App Store](https://itunes.apple.com/app/leanote/id1022302858)
|
||||
* [Leanote Android](https://github.com/leanote/leanote-android), development phase
|
||||
|
||||
You are welcome to join us.
|
||||
@@ -145,7 +145,7 @@ Leanote云笔记产品包括: Leanote Web & Server(即本仓库), 桌面客户
|
||||
* [Windows](https://github.com/leanote/leanote/wiki/Leanote%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B---Windows)
|
||||
* [Mac, Linux](https://github.com/leanote/leanote/wiki/leanote%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
||||
* Leanote源码详细安装教程:
|
||||
* [Windows](https://github.com/leanote/leanote/wiki/Leanote-%E6%BA%90%E7%A0%81%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B----Windows)
|
||||
<!-- * [Windows](https://github.com/leanote/leanote/wiki/Leanote-%E6%BA%90%E7%A0%81%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B----Windows) -->
|
||||
* [Mac, Linux](https://github.com/leanote/leanote/wiki/leanote%E5%BC%80%E5%8F%91%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
||||
|
||||
## 4. 相关文档
|
||||
@@ -186,4 +186,3 @@ Leanote还有很多问题, 如果你喜欢它, 欢迎加入我们一起完善Lea
|
||||
* [Leanote 社区](http://bbs.leanote.com)
|
||||
* [QQ群](http://leanote.leanote.com/post/Leanote-groups)
|
||||
* [Leanote Google Group](https://groups.google.com/forum/#!forum/leanote)
|
||||
|
||||
|
||||
9
app/cmd/README.md
Normal file
9
app/cmd/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
全部代码来自https://github.com/revel/cmd
|
||||
|
||||
因为要改parse2, 所以改只要一点点代码
|
||||
harness/
|
||||
build.go 只要gensource, 其它的先return
|
||||
main.go 改动很小
|
||||
build.go 改动很小
|
||||
parser2/
|
||||
source_processors.go 改了 fsWalk 过滤掉 public, files, build 等文件夹
|
||||
270
app/cmd/build.go
Normal file
270
app/cmd/build.go
Normal file
@@ -0,0 +1,270 @@
|
||||
// Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
|
||||
// Revel Framework source code and usage is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"fmt"
|
||||
"github.com/leanote/leanote/app/cmd/harness" // 只改了这个
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
var cmdBuild = &Command{
|
||||
UsageLine: "revel build [-r [run mode]] [import path] [target path] ",
|
||||
Short: "build a Revel application (e.g. for deployment)",
|
||||
Long: `
|
||||
Build the Revel web application named by the given import path.
|
||||
This allows it to be deployed and run on a machine that lacks a Go installation.
|
||||
|
||||
For example:
|
||||
|
||||
revel build github.com/revel/examples/chat /tmp/chat
|
||||
|
||||
`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdBuild.RunWith = buildApp
|
||||
cmdBuild.UpdateConfig = updateBuildConfig
|
||||
}
|
||||
|
||||
// The update config updates the configuration command so that it can run
|
||||
func updateBuildConfig(c *model.CommandConfig, args []string) bool {
|
||||
c.Index = model.BUILD
|
||||
if c.Build.TargetPath == "" {
|
||||
c.Build.TargetPath = "target"
|
||||
}
|
||||
if len(args) == 0 && c.Build.ImportPath != "" {
|
||||
return true
|
||||
}
|
||||
// If arguments were passed in then there must be two
|
||||
if len(args) < 2 {
|
||||
fmt.Fprintf(os.Stderr, "%s\n%s", cmdBuild.UsageLine, cmdBuild.Long)
|
||||
return false
|
||||
}
|
||||
|
||||
c.Build.ImportPath = args[0]
|
||||
c.Build.TargetPath = args[1]
|
||||
if len(args) > 2 {
|
||||
c.Build.Mode = args[2]
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// The main entry point to build application from command line
|
||||
func buildApp(c *model.CommandConfig) (err error) {
|
||||
|
||||
appImportPath, destPath, mode := c.ImportPath, c.Build.TargetPath, DefaultRunMode
|
||||
if len(c.Build.Mode) > 0 {
|
||||
mode = c.Build.Mode
|
||||
}
|
||||
|
||||
// Convert target to absolute path
|
||||
c.Build.TargetPath, _ = filepath.Abs(destPath)
|
||||
c.Build.Mode = mode
|
||||
c.Build.ImportPath = appImportPath
|
||||
|
||||
revel_paths, err := model.NewRevelPaths(mode, appImportPath, c.AppPath, model.NewWrappedRevelCallback(nil, c.PackageResolver))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = buildSafetyCheck(destPath); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure the application can be built, this generates the main file
|
||||
app, err := harness.Build(c, revel_paths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Copy files
|
||||
// Included are:
|
||||
// - run scripts
|
||||
// - binary
|
||||
// - revel
|
||||
// - app
|
||||
|
||||
return // 改了这里
|
||||
|
||||
packageFolders, err := buildCopyFiles(c, app, revel_paths)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = buildCopyModules(c, revel_paths, packageFolders, app)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = buildWriteScripts(c, app)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Copy the files to the target
|
||||
func buildCopyFiles(c *model.CommandConfig, app *harness.App, revel_paths *model.RevelContainer) (packageFolders []string, err error) {
|
||||
appImportPath, destPath := c.ImportPath, c.Build.TargetPath
|
||||
|
||||
// Revel and the app are in a directory structure mirroring import path
|
||||
srcPath := filepath.Join(destPath, "src")
|
||||
destBinaryPath := filepath.Join(destPath, filepath.Base(app.BinaryPath))
|
||||
tmpRevelPath := filepath.Join(srcPath, filepath.FromSlash(model.RevelImportPath))
|
||||
if err = utils.CopyFile(destBinaryPath, filepath.Join(revel_paths.BasePath, app.BinaryPath)); err != nil {
|
||||
return
|
||||
}
|
||||
utils.MustChmod(destBinaryPath, 0755)
|
||||
|
||||
// Copy the templates from the revel
|
||||
if err = utils.CopyDir(filepath.Join(tmpRevelPath, "conf"), filepath.Join(revel_paths.RevelPath, "conf"), nil); err != nil {
|
||||
return
|
||||
}
|
||||
if err = utils.CopyDir(filepath.Join(tmpRevelPath, "templates"), filepath.Join(revel_paths.RevelPath, "templates"), nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Get the folders to be packaged
|
||||
packageFolders = strings.Split(revel_paths.Config.StringDefault("package.folders", "conf,public,app/views"), ",")
|
||||
for i, p := range packageFolders {
|
||||
// Clean spaces, reformat slash to filesystem
|
||||
packageFolders[i] = filepath.FromSlash(strings.TrimSpace(p))
|
||||
}
|
||||
|
||||
if c.Build.CopySource {
|
||||
err = utils.CopyDir(filepath.Join(srcPath, filepath.FromSlash(appImportPath)), revel_paths.BasePath, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
for _, folder := range packageFolders {
|
||||
err = utils.CopyDir(
|
||||
filepath.Join(srcPath, filepath.FromSlash(appImportPath), folder),
|
||||
filepath.Join(revel_paths.BasePath, folder),
|
||||
nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Based on the section copy over the build modules
|
||||
func buildCopyModules(c *model.CommandConfig, revel_paths *model.RevelContainer, packageFolders []string, app *harness.App) (err error) {
|
||||
destPath := filepath.Join(c.Build.TargetPath, "src")
|
||||
// Find all the modules used and copy them over.
|
||||
config := revel_paths.Config.Raw()
|
||||
|
||||
// We should only copy over the section of options what the build is targeted for
|
||||
// We will default to prod
|
||||
moduleImportList := []string{}
|
||||
for _, section := range config.Sections() {
|
||||
// If the runmode is defined we will only import modules defined for that run mode
|
||||
if c.Build.Mode != "" && c.Build.Mode != section {
|
||||
continue
|
||||
}
|
||||
options, _ := config.SectionOptions(section)
|
||||
for _, key := range options {
|
||||
if !strings.HasPrefix(key, "module.") {
|
||||
continue
|
||||
}
|
||||
moduleImportPath, _ := config.String(section, key)
|
||||
if moduleImportPath == "" {
|
||||
continue
|
||||
}
|
||||
moduleImportList = append(moduleImportList, moduleImportPath)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the the paths for each of the modules
|
||||
for _, importPath := range moduleImportList {
|
||||
fsPath := app.PackagePathMap[importPath]
|
||||
utils.Logger.Info("Copy files ", "to", filepath.Join(destPath, importPath), "from", fsPath)
|
||||
if c.Build.CopySource {
|
||||
err = utils.CopyDir(filepath.Join(destPath, importPath), fsPath, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
for _, folder := range packageFolders {
|
||||
err = utils.CopyDir(
|
||||
filepath.Join(destPath, importPath, folder),
|
||||
filepath.Join(fsPath, folder),
|
||||
nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Write the run scripts for the build
|
||||
func buildWriteScripts(c *model.CommandConfig, app *harness.App) (err error) {
|
||||
tmplData := map[string]interface{}{
|
||||
"BinName": filepath.Base(app.BinaryPath),
|
||||
"ImportPath": c.Build.ImportPath,
|
||||
"Mode": c.Build.Mode,
|
||||
}
|
||||
|
||||
err = utils.GenerateTemplate(
|
||||
filepath.Join(c.Build.TargetPath, "run.sh"),
|
||||
PACKAGE_RUN_SH,
|
||||
tmplData,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
utils.MustChmod(filepath.Join(c.Build.TargetPath, "run.sh"), 0755)
|
||||
err = utils.GenerateTemplate(
|
||||
filepath.Join(c.Build.TargetPath, "run.bat"),
|
||||
PACKAGE_RUN_BAT,
|
||||
tmplData,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Your application has been built in:", c.Build.TargetPath)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Checks to see if the target folder exists and can be created
|
||||
func buildSafetyCheck(destPath string) error {
|
||||
|
||||
// First, verify that it is either already empty or looks like a previous
|
||||
// build (to avoid clobbering anything)
|
||||
if utils.Exists(destPath) && !utils.Empty(destPath) && !utils.Exists(filepath.Join(destPath, "run.sh")) {
|
||||
return utils.NewBuildError("Abort: %s exists and does not look like a build directory.", "path", destPath)
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(destPath); err != nil && !os.IsNotExist(err) {
|
||||
return utils.NewBuildIfError(err, "Remove all error", "path", destPath)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(destPath, 0777); err != nil {
|
||||
return utils.NewBuildIfError(err, "MkDir all error", "path", destPath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const PACKAGE_RUN_SH = `#!/bin/sh
|
||||
|
||||
SCRIPTPATH=$(cd "$(dirname "$0")"; pwd)
|
||||
"$SCRIPTPATH/{{.BinName}}" -importPath {{.ImportPath}} -srcPath "$SCRIPTPATH/src" -runMode {{.Mode}}
|
||||
`
|
||||
const PACKAGE_RUN_BAT = `@echo off
|
||||
|
||||
{{.BinName}} -importPath {{.ImportPath}} -srcPath "%CD%\src" -runMode {{.Mode}}
|
||||
`
|
||||
4
app/cmd/gen_tmp.sh
Normal file
4
app/cmd/gen_tmp.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
SCRIPTPATH=$(cd "$(dirname "$0")"; pwd)
|
||||
cd $SCRIPTPATH
|
||||
go run . build -v ../../ ./tmptmp
|
||||
rm -rf ./tmptmp
|
||||
219
app/cmd/harness/app.go
Normal file
219
app/cmd/harness/app.go
Normal file
@@ -0,0 +1,219 @@
|
||||
// Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
|
||||
// Revel Framework source code and usage is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
"sync"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// App contains the configuration for running a Revel app. (Not for the app itself)
|
||||
// Its only purpose is constructing the command to execute.
|
||||
type App struct {
|
||||
BinaryPath string // Path to the app executable
|
||||
Port int // Port to pass as a command line argument.
|
||||
cmd AppCmd // The last cmd returned.
|
||||
PackagePathMap map[string]string // Package to directory path map
|
||||
Paths *model.RevelContainer
|
||||
}
|
||||
|
||||
// NewApp returns app instance with binary path in it
|
||||
func NewApp(binPath string, paths *model.RevelContainer, packagePathMap map[string]string) *App {
|
||||
return &App{BinaryPath: binPath, Paths: paths, Port: paths.HTTPPort, PackagePathMap:packagePathMap}
|
||||
}
|
||||
|
||||
// Cmd returns a command to run the app server using the current configuration.
|
||||
func (a *App) Cmd(runMode string) AppCmd {
|
||||
a.cmd = NewAppCmd(a.BinaryPath, a.Port, runMode, a.Paths)
|
||||
return a.cmd
|
||||
}
|
||||
|
||||
// Kill the last app command returned.
|
||||
func (a *App) Kill() {
|
||||
a.cmd.Kill()
|
||||
}
|
||||
|
||||
// AppCmd manages the running of a Revel app server.
|
||||
// It requires revel.Init to have been called previously.
|
||||
type AppCmd struct {
|
||||
*exec.Cmd
|
||||
}
|
||||
|
||||
// NewAppCmd returns the AppCmd with parameters initialized for running app
|
||||
func NewAppCmd(binPath string, port int, runMode string, paths *model.RevelContainer) AppCmd {
|
||||
cmd := exec.Command(binPath,
|
||||
fmt.Sprintf("-port=%d", port),
|
||||
fmt.Sprintf("-importPath=%s", paths.ImportPath),
|
||||
fmt.Sprintf("-runMode=%s", runMode))
|
||||
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
|
||||
return AppCmd{cmd}
|
||||
}
|
||||
|
||||
// Start the app server, and wait until it is ready to serve requests.
|
||||
func (cmd AppCmd) Start(c *model.CommandConfig) error {
|
||||
listeningWriter := &startupListeningWriter{os.Stdout, make(chan bool), c, &bytes.Buffer{}}
|
||||
cmd.Stdout = listeningWriter
|
||||
utils.CmdInit(cmd.Cmd, !c.Vendored, c.AppPath)
|
||||
utils.Logger.Info("Exec app:", "path", cmd.Path, "args", cmd.Args, "dir", cmd.Dir, "env", cmd.Env)
|
||||
if err := cmd.Cmd.Start(); err != nil {
|
||||
utils.Logger.Fatal("Error running:", "error", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case exitState := <-cmd.waitChan():
|
||||
fmt.Println("Startup failure view previous messages, \n Proxy is listening :", c.Run.Port)
|
||||
err := utils.NewError("", "Revel Run Error", "starting your application there was an exception. See terminal output, " + exitState, "")
|
||||
// TODO pretiffy command line output
|
||||
// err.MetaError = listeningWriter.getLastOutput()
|
||||
return err
|
||||
|
||||
case <-time.After(60 * time.Second):
|
||||
println("Revel proxy is listening, point your browser to :", c.Run.Port)
|
||||
utils.Logger.Error("Killing revel server process did not respond after wait timeout.", "processid", cmd.Process.Pid)
|
||||
cmd.Kill()
|
||||
return errors.New("revel/harness: app timed out")
|
||||
|
||||
case <-listeningWriter.notifyReady:
|
||||
println("Revel proxy is listening, point your browser to :", c.Run.Port)
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Run the app server inline. Never returns.
|
||||
func (cmd AppCmd) Run(c *model.CommandConfig) {
|
||||
utils.CmdInit(cmd.Cmd, !c.Vendored, c.AppPath)
|
||||
utils.Logger.Info("Exec app:", "path", cmd.Path, "args", cmd.Args)
|
||||
if err := cmd.Cmd.Run(); err != nil {
|
||||
utils.Logger.Fatal("Error running:", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Kill terminates the app server if it's running.
|
||||
func (cmd AppCmd) Kill() {
|
||||
|
||||
if cmd.Cmd != nil && (cmd.ProcessState == nil || !cmd.ProcessState.Exited()) {
|
||||
// Windows appears to send the kill to all threads, shutting down the
|
||||
// server before this can, this check will ensure the process is still running
|
||||
if _, err := os.FindProcess(int(cmd.Process.Pid)); err != nil {
|
||||
// Server has already exited
|
||||
utils.Logger.Info("Server not running revel server pid", "pid", cmd.Process.Pid)
|
||||
return
|
||||
}
|
||||
|
||||
// Wait for the shutdown channel
|
||||
waitMutex := &sync.WaitGroup{}
|
||||
waitMutex.Add(1)
|
||||
ch := make(chan bool, 1)
|
||||
go func() {
|
||||
waitMutex.Done()
|
||||
s, err := cmd.Process.Wait()
|
||||
defer func() {
|
||||
ch <- true
|
||||
}()
|
||||
if err != nil {
|
||||
utils.Logger.Info("Wait failed for process ", "error", err)
|
||||
}
|
||||
if s != nil {
|
||||
utils.Logger.Info("Revel App exited", "state", s.String())
|
||||
}
|
||||
}()
|
||||
// Wait for the channel to begin waiting
|
||||
waitMutex.Wait()
|
||||
|
||||
// Send an interrupt signal to allow for a graceful shutdown
|
||||
utils.Logger.Info("Killing revel server pid", "pid", cmd.Process.Pid)
|
||||
var err error
|
||||
if runtime.GOOS != "windows" {
|
||||
// os.Interrupt is not available on windows
|
||||
err = cmd.Process.Signal(os.Interrupt)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
utils.Logger.Info(
|
||||
"Revel app already exited.",
|
||||
"processid", cmd.Process.Pid, "error", err,
|
||||
"killerror", cmd.Process.Kill())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Use a timer to ensure that the process exits
|
||||
utils.Logger.Info("Waiting to exit")
|
||||
select {
|
||||
case <-ch:
|
||||
return
|
||||
case <-time.After(60 * time.Second):
|
||||
// Kill the process
|
||||
utils.Logger.Error(
|
||||
"Revel app failed to exit in 60 seconds - killing.",
|
||||
"processid", cmd.Process.Pid,
|
||||
"killerror", cmd.Process.Kill())
|
||||
}
|
||||
|
||||
utils.Logger.Info("Done Waiting to exit")
|
||||
}
|
||||
}
|
||||
|
||||
// Return a channel that is notified when Wait() returns.
|
||||
func (cmd AppCmd) waitChan() <-chan string {
|
||||
ch := make(chan string, 1)
|
||||
go func() {
|
||||
_ = cmd.Wait()
|
||||
state := cmd.ProcessState
|
||||
exitStatus := " unknown "
|
||||
if state != nil {
|
||||
exitStatus = state.String()
|
||||
}
|
||||
|
||||
ch <- exitStatus
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
// A io.Writer that copies to the destination, and listens for "Revel engine is listening on.."
|
||||
// in the stream. (Which tells us when the revel server has finished starting up)
|
||||
// This is super ghetto, but by far the simplest thing that should work.
|
||||
type startupListeningWriter struct {
|
||||
dest io.Writer
|
||||
notifyReady chan bool
|
||||
c *model.CommandConfig
|
||||
buffer *bytes.Buffer
|
||||
}
|
||||
|
||||
// Writes to this output stream
|
||||
func (w *startupListeningWriter) Write(p []byte) (int, error) {
|
||||
if w.notifyReady != nil && bytes.Contains(p, []byte("Revel engine is listening on")) {
|
||||
w.notifyReady <- true
|
||||
w.notifyReady = nil
|
||||
}
|
||||
if w.c.HistoricMode {
|
||||
if w.notifyReady != nil && bytes.Contains(p, []byte("Listening on")) {
|
||||
w.notifyReady <- true
|
||||
w.notifyReady = nil
|
||||
}
|
||||
}
|
||||
if w.notifyReady != nil {
|
||||
w.buffer.Write(p)
|
||||
}
|
||||
return w.dest.Write(p)
|
||||
}
|
||||
|
||||
// Returns the cleaned output from the response
|
||||
// TODO clean the response more
|
||||
func (w *startupListeningWriter) getLastOutput() string {
|
||||
return w.buffer.String()
|
||||
}
|
||||
|
||||
566
app/cmd/harness/build.go
Normal file
566
app/cmd/harness/build.go
Normal file
@@ -0,0 +1,566 @@
|
||||
// Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
|
||||
// Revel Framework source code and usage is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/build"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/leanote/leanote/app/cmd/parser2"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/parser"
|
||||
_ "github.com/revel/cmd/parser"
|
||||
"github.com/revel/cmd/utils"
|
||||
)
|
||||
|
||||
var importErrorPattern = regexp.MustCompile("cannot find package \"([^\"]+)\"")
|
||||
|
||||
type ByString []*model.TypeInfo
|
||||
|
||||
func (c ByString) Len() int {
|
||||
return len(c)
|
||||
}
|
||||
func (c ByString) Swap(i, j int) {
|
||||
c[i], c[j] = c[j], c[i]
|
||||
}
|
||||
func (c ByString) Less(i, j int) bool {
|
||||
return c[i].String() < c[j].String()
|
||||
}
|
||||
|
||||
// Build the app:
|
||||
// 1. Generate the the main.go file.
|
||||
// 2. Run the appropriate "go build" command.
|
||||
// Requires that revel.Init has been called previously.
|
||||
// Returns the path to the built binary, and an error if there was a problem building it.
|
||||
func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err error) {
|
||||
// First, clear the generated files (to avoid them messing with ProcessSource).
|
||||
cleanSource(paths, "tmp", "routes")
|
||||
|
||||
var sourceInfo *model.SourceInfo
|
||||
|
||||
if c.HistoricBuildMode {
|
||||
sourceInfo, err = parser.ProcessSource(paths)
|
||||
} else {
|
||||
sourceInfo, err = parser2.ProcessSource(paths)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Add the db.import to the import paths.
|
||||
if dbImportPath, found := paths.Config.String("db.import"); found {
|
||||
sourceInfo.InitImportPaths = append(sourceInfo.InitImportPaths, strings.Split(dbImportPath, ",")...)
|
||||
}
|
||||
|
||||
// Sort controllers so that file generation is reproducible
|
||||
controllers := sourceInfo.ControllerSpecs()
|
||||
sort.Stable(ByString(controllers))
|
||||
|
||||
// Generate two source files.
|
||||
templateArgs := map[string]interface{}{
|
||||
"ImportPath": paths.ImportPath,
|
||||
"Controllers": controllers,
|
||||
"ValidationKeys": sourceInfo.ValidationKeys,
|
||||
"ImportPaths": calcImportAliases(sourceInfo),
|
||||
"TestSuites": sourceInfo.TestSuites(),
|
||||
}
|
||||
|
||||
// Generate code for the main, run and routes file.
|
||||
// The run file allows external programs to launch and run the application
|
||||
// without being the main thread
|
||||
cleanSource(paths, "tmp", "routes")
|
||||
|
||||
if err = genSource(paths, "tmp", "main.go", RevelMainTemplate, templateArgs); err != nil {
|
||||
return
|
||||
}
|
||||
if err = genSource(paths, filepath.Join("tmp", "run"), "run.go", RevelRunTemplate, templateArgs); err != nil {
|
||||
return
|
||||
}
|
||||
if err = genSource(paths, "routes", "routes.go", RevelRoutesTemplate, templateArgs); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
utils.Logger.Warn("gen tmp/main.go, tmp/run/run.go, routes/routes.go success!!")
|
||||
|
||||
return // 改了这里
|
||||
|
||||
// Read build config.
|
||||
buildTags := paths.Config.StringDefault("build.tags", "")
|
||||
|
||||
// Build the user program (all code under app).
|
||||
// It relies on the user having "go" installed.
|
||||
goPath, err := exec.LookPath("go")
|
||||
if err != nil {
|
||||
utils.Logger.Fatal("Go executable not found in PATH.")
|
||||
}
|
||||
|
||||
// Binary path is a combination of target/app directory, app's import path and its name.
|
||||
binName := filepath.Join("target", "app", paths.ImportPath, filepath.Base(paths.BasePath))
|
||||
|
||||
// Change binary path for Windows build
|
||||
goos := runtime.GOOS
|
||||
if goosEnv := os.Getenv("GOOS"); goosEnv != "" {
|
||||
goos = goosEnv
|
||||
}
|
||||
if goos == "windows" {
|
||||
binName += ".exe"
|
||||
}
|
||||
|
||||
gotten := make(map[string]struct{})
|
||||
contains := func(s []string, e string) bool {
|
||||
for _, a := range s {
|
||||
if a == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if len(c.GoModFlags) > 0 {
|
||||
for _, gomod := range c.GoModFlags {
|
||||
goModCmd := exec.Command(goPath, append([]string{"mod"}, strings.Split(gomod, " ")...)...)
|
||||
utils.CmdInit(goModCmd, !c.Vendored, c.AppPath)
|
||||
output, err := goModCmd.CombinedOutput()
|
||||
utils.Logger.Info("Gomod applied ", "output", string(output))
|
||||
|
||||
// If the build succeeded, we're done.
|
||||
if err != nil {
|
||||
utils.Logger.Error("Gomod Failed continuing ", "error", err, "output", string(output))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
appVersion := getAppVersion(paths)
|
||||
if appVersion == "" {
|
||||
appVersion = "noVersionProvided"
|
||||
}
|
||||
|
||||
buildTime := time.Now().UTC().Format(time.RFC3339)
|
||||
versionLinkerFlags := fmt.Sprintf("-X '%s/app.AppVersion=%s' -X '%s/app.BuildTime=%s'",
|
||||
paths.ImportPath, appVersion, paths.ImportPath, buildTime)
|
||||
|
||||
// Append any build flags specified, they will override existing flags
|
||||
flags := []string{}
|
||||
if len(c.BuildFlags) == 0 {
|
||||
flags = []string{
|
||||
"build",
|
||||
"-ldflags", versionLinkerFlags,
|
||||
"-tags", buildTags,
|
||||
"-o", binName}
|
||||
} else {
|
||||
if !contains(c.BuildFlags, "build") {
|
||||
flags = []string{"build"}
|
||||
}
|
||||
if !contains(flags, "-ldflags") {
|
||||
ldflags := "-ldflags= " + versionLinkerFlags
|
||||
// Add user defined build flags
|
||||
for i := range c.BuildFlags {
|
||||
ldflags += " -X '" + c.BuildFlags[i] + "'"
|
||||
}
|
||||
flags = append(flags, ldflags)
|
||||
}
|
||||
if !contains(flags, "-tags") && buildTags != "" {
|
||||
flags = append(flags, "-tags", buildTags)
|
||||
}
|
||||
if !contains(flags, "-o") {
|
||||
flags = append(flags, "-o", binName)
|
||||
}
|
||||
}
|
||||
|
||||
// Note: It's not applicable for filepath.* usage
|
||||
flags = append(flags, path.Join(paths.ImportPath, "app", "tmp"))
|
||||
|
||||
buildCmd := exec.Command(goPath, flags...)
|
||||
if !c.Vendored {
|
||||
// This is Go main path
|
||||
gopath := c.GoPath
|
||||
for _, o := range paths.ModulePathMap {
|
||||
gopath += string(filepath.ListSeparator) + o.Path
|
||||
}
|
||||
|
||||
buildCmd.Env = append(os.Environ(),
|
||||
"GOPATH=" + gopath,
|
||||
)
|
||||
}
|
||||
utils.CmdInit(buildCmd, !c.Vendored, c.AppPath)
|
||||
|
||||
utils.Logger.Info("Exec:", "args", buildCmd.Args, "working dir", buildCmd.Dir)
|
||||
output, err := buildCmd.CombinedOutput()
|
||||
|
||||
// If the build succeeded, we're done.
|
||||
if err == nil {
|
||||
utils.Logger.Info("Build successful continuing")
|
||||
return NewApp(binName, paths, sourceInfo.PackageMap), nil
|
||||
}
|
||||
|
||||
// Since there was an error, capture the output in case we need to report it
|
||||
stOutput := string(output)
|
||||
utils.Logger.Infof("Got error on build of app %s", stOutput)
|
||||
|
||||
// See if it was an import error that we can go get.
|
||||
matches := importErrorPattern.FindAllStringSubmatch(stOutput, -1)
|
||||
utils.Logger.Info("Build failed checking for missing imports", "message", stOutput, "missing_imports", len(matches))
|
||||
if matches == nil {
|
||||
utils.Logger.Info("Build failed no missing imports", "message", stOutput)
|
||||
return nil, newCompileError(paths, output)
|
||||
}
|
||||
utils.Logger.Warn("Detected missing packages, importing them", "packages", len(matches))
|
||||
for _, match := range matches {
|
||||
// Ensure we haven't already tried to go get it.
|
||||
pkgName := match[1]
|
||||
utils.Logger.Info("Trying to import ", "package", pkgName)
|
||||
if _, alreadyTried := gotten[pkgName]; alreadyTried {
|
||||
utils.Logger.Error("Failed to import ", "package", pkgName)
|
||||
return nil, newCompileError(paths, output)
|
||||
}
|
||||
gotten[pkgName] = struct{}{}
|
||||
if err := c.PackageResolver(pkgName); err != nil {
|
||||
utils.Logger.Error("Unable to resolve package", "package", pkgName, "error", err)
|
||||
return nil, newCompileError(paths, []byte(err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
// Success getting the import, attempt to build again.
|
||||
}
|
||||
|
||||
// TODO remove this unreachable code and document it
|
||||
utils.Logger.Fatal("Not reachable")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Try to define a version string for the compiled app
|
||||
// The following is tried (first match returns):
|
||||
// - Read a version explicitly specified in the APP_VERSION environment
|
||||
// variable
|
||||
// - Read the output of "git describe" if the source is in a git repository
|
||||
// If no version can be determined, an empty string is returned.
|
||||
func getAppVersion(paths *model.RevelContainer) string {
|
||||
if version := os.Getenv("APP_VERSION"); version != "" {
|
||||
return version
|
||||
}
|
||||
|
||||
// Check for the git binary
|
||||
if gitPath, err := exec.LookPath("git"); err == nil {
|
||||
// Check for the .git directory
|
||||
gitDir := filepath.Join(paths.BasePath, ".git")
|
||||
info, err := os.Stat(gitDir)
|
||||
if (err != nil && os.IsNotExist(err)) || !info.IsDir() {
|
||||
return ""
|
||||
}
|
||||
gitCmd := exec.Command(gitPath, "--git-dir=" + gitDir, "--work-tree=" + paths.BasePath, "describe", "--always", "--dirty")
|
||||
utils.Logger.Info("Exec:", "args", gitCmd.Args)
|
||||
output, err := gitCmd.Output()
|
||||
|
||||
if err != nil {
|
||||
utils.Logger.Error("Cannot determine git repository version:", "error", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
return "git-" + strings.TrimSpace(string(output))
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func cleanSource(paths *model.RevelContainer, dirs ...string) {
|
||||
for _, dir := range dirs {
|
||||
cleanDir(paths, dir)
|
||||
}
|
||||
}
|
||||
|
||||
func cleanDir(paths *model.RevelContainer, dir string) {
|
||||
utils.Logger.Info("Cleaning dir ", "dir", dir)
|
||||
tmpPath := filepath.Join(paths.AppPath, dir)
|
||||
f, err := os.Open(tmpPath)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
utils.Logger.Error("Failed to clean dir:", "error", err)
|
||||
}
|
||||
} else {
|
||||
defer func() {
|
||||
_ = f.Close()
|
||||
}()
|
||||
|
||||
infos, err := f.Readdir(0)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
utils.Logger.Fatal("Failed to clean dir:", "error", err)
|
||||
}
|
||||
} else {
|
||||
for _, info := range infos {
|
||||
pathName := filepath.Join(tmpPath, info.Name())
|
||||
if info.IsDir() {
|
||||
err := os.RemoveAll(pathName)
|
||||
if err != nil {
|
||||
utils.Logger.Fatal("Failed to remove dir:", "error", err)
|
||||
}
|
||||
} else {
|
||||
err := os.Remove(pathName)
|
||||
if err != nil {
|
||||
utils.Logger.Fatal("Failed to remove file:", "error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// genSource renders the given template to produce source code, which it writes
|
||||
// to the given directory and file.
|
||||
func genSource(paths *model.RevelContainer, dir, filename, templateSource string, args map[string]interface{}) error {
|
||||
|
||||
return utils.GenerateTemplate(filepath.Join(paths.AppPath, dir, filename), templateSource, args)
|
||||
}
|
||||
|
||||
// Looks through all the method args and returns a set of unique import paths
|
||||
// that cover all the method arg types.
|
||||
// Additionally, assign package aliases when necessary to resolve ambiguity.
|
||||
func calcImportAliases(src *model.SourceInfo) map[string]string {
|
||||
aliases := make(map[string]string)
|
||||
typeArrays := [][]*model.TypeInfo{src.ControllerSpecs(), src.TestSuites()}
|
||||
for _, specs := range typeArrays {
|
||||
for _, spec := range specs {
|
||||
addAlias(aliases, spec.ImportPath, spec.PackageName)
|
||||
|
||||
for _, methSpec := range spec.MethodSpecs {
|
||||
for _, methArg := range methSpec.Args {
|
||||
if methArg.ImportPath == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
addAlias(aliases, methArg.ImportPath, methArg.TypeExpr.PkgName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the "InitImportPaths", with alias "_"
|
||||
for _, importPath := range src.InitImportPaths {
|
||||
if _, ok := aliases[importPath]; !ok {
|
||||
aliases[importPath] = "_"
|
||||
}
|
||||
}
|
||||
|
||||
return aliases
|
||||
}
|
||||
|
||||
// Adds an alias to the map of alias names
|
||||
func addAlias(aliases map[string]string, importPath, pkgName string) {
|
||||
alias, ok := aliases[importPath]
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
alias = makePackageAlias(aliases, pkgName)
|
||||
aliases[importPath] = alias
|
||||
}
|
||||
|
||||
// Generates a package alias
|
||||
func makePackageAlias(aliases map[string]string, pkgName string) string {
|
||||
i := 0
|
||||
alias := pkgName
|
||||
for containsValue(aliases, alias) || alias == "revel" {
|
||||
alias = fmt.Sprintf("%s%d", pkgName, i)
|
||||
i++
|
||||
}
|
||||
return alias
|
||||
}
|
||||
|
||||
// Returns true if this value is in the map
|
||||
func containsValue(m map[string]string, val string) bool {
|
||||
for _, v := range m {
|
||||
if v == val {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Parse the output of the "go build" command.
|
||||
// Return a detailed Error.
|
||||
func newCompileError(paths *model.RevelContainer, output []byte) *utils.SourceError {
|
||||
errorMatch := regexp.MustCompile(`(?m)^([^:#]+):(\d+):(\d+:)? (.*)$`).
|
||||
FindSubmatch(output)
|
||||
if errorMatch == nil {
|
||||
errorMatch = regexp.MustCompile(`(?m)^(.*?):(\d+):\s(.*?)$`).FindSubmatch(output)
|
||||
|
||||
if errorMatch == nil {
|
||||
utils.Logger.Error("Failed to parse build errors", "error", string(output))
|
||||
return &utils.SourceError{
|
||||
SourceType: "Go code",
|
||||
Title: "Go Compilation Error",
|
||||
Description: "See console for build error.",
|
||||
}
|
||||
}
|
||||
|
||||
errorMatch = append(errorMatch, errorMatch[3])
|
||||
|
||||
utils.Logger.Error("Build errors", "errors", string(output))
|
||||
}
|
||||
|
||||
findInPaths := func(relFilename string) string {
|
||||
// Extract the paths from the gopaths, and search for file there first
|
||||
gopaths := filepath.SplitList(build.Default.GOPATH)
|
||||
for _, gp := range gopaths {
|
||||
newPath := filepath.Join(gp, "src", paths.ImportPath, relFilename)
|
||||
println(newPath)
|
||||
if utils.Exists(newPath) {
|
||||
return newPath
|
||||
}
|
||||
}
|
||||
newPath, _ := filepath.Abs(relFilename)
|
||||
utils.Logger.Warn("Could not find in GO path", "file", relFilename)
|
||||
return newPath
|
||||
}
|
||||
|
||||
|
||||
// Read the source for the offending file.
|
||||
var (
|
||||
relFilename = string(errorMatch[1]) // e.g. "src/revel/sample/app/controllers/app.go"
|
||||
absFilename = findInPaths(relFilename)
|
||||
line, _ = strconv.Atoi(string(errorMatch[2]))
|
||||
description = string(errorMatch[4])
|
||||
compileError = &utils.SourceError{
|
||||
SourceType: "Go code",
|
||||
Title: "Go Compilation Error",
|
||||
Path: relFilename,
|
||||
Description: description,
|
||||
Line: line,
|
||||
}
|
||||
)
|
||||
|
||||
errorLink := paths.Config.StringDefault("error.link", "")
|
||||
|
||||
if errorLink != "" {
|
||||
compileError.SetLink(errorLink)
|
||||
}
|
||||
|
||||
fileStr, err := utils.ReadLines(absFilename)
|
||||
if err != nil {
|
||||
compileError.MetaError = absFilename + ": " + err.Error()
|
||||
utils.Logger.Info("Unable to readlines " + compileError.MetaError, "error", err)
|
||||
return compileError
|
||||
}
|
||||
|
||||
compileError.SourceLines = fileStr
|
||||
return compileError
|
||||
}
|
||||
|
||||
// RevelMainTemplate template for app/tmp/run/run.go
|
||||
const RevelRunTemplate = `// GENERATED CODE - DO NOT EDIT
|
||||
// This file is the run file for Revel.
|
||||
// It registers all the controllers and provides details for the Revel server engine to
|
||||
// properly inject parameters directly into the action endpoints.
|
||||
package run
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"github.com/revel/revel"{{range $k, $v := $.ImportPaths}}
|
||||
{{$v}} "{{$k}}"{{end}}
|
||||
"github.com/revel/revel/testing"
|
||||
)
|
||||
|
||||
var (
|
||||
// So compiler won't complain if the generated code doesn't reference reflect package...
|
||||
_ = reflect.Invalid
|
||||
)
|
||||
|
||||
// Register and run the application
|
||||
func Run(port int) {
|
||||
Register()
|
||||
revel.Run(port)
|
||||
}
|
||||
|
||||
// Register all the controllers
|
||||
func Register() {
|
||||
revel.AppLog.Info("Running revel server")
|
||||
{{range $i, $c := .Controllers}}
|
||||
revel.RegisterController((*{{index $.ImportPaths .ImportPath}}.{{.StructName}})(nil),
|
||||
[]*revel.MethodType{
|
||||
{{range .MethodSpecs}}&revel.MethodType{
|
||||
Name: "{{.Name}}",
|
||||
Args: []*revel.MethodArg{ {{range .Args}}
|
||||
&revel.MethodArg{Name: "{{.Name}}", Type: reflect.TypeOf((*{{index $.ImportPaths .ImportPath | .TypeExpr.TypeName}})(nil)) },{{end}}
|
||||
},
|
||||
RenderArgNames: map[int][]string{ {{range .RenderCalls}}
|
||||
{{.Line}}: []string{ {{range .Names}}
|
||||
"{{.}}",{{end}}
|
||||
},{{end}}
|
||||
},
|
||||
},
|
||||
{{end}}
|
||||
})
|
||||
{{end}}
|
||||
revel.DefaultValidationKeys = map[string]map[int]string{ {{range $path, $lines := .ValidationKeys}}
|
||||
"{{$path}}": { {{range $line, $key := $lines}}
|
||||
{{$line}}: "{{$key}}",{{end}}
|
||||
},{{end}}
|
||||
}
|
||||
testing.TestSuites = []interface{}{ {{range .TestSuites}}
|
||||
(*{{index $.ImportPaths .ImportPath}}.{{.StructName}})(nil),{{end}}
|
||||
}
|
||||
}
|
||||
`
|
||||
const RevelMainTemplate = `// GENERATED CODE - DO NOT EDIT
|
||||
// This file is the main file for Revel.
|
||||
// It registers all the controllers and provides details for the Revel server engine to
|
||||
// properly inject parameters directly into the action endpoints.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"{{.ImportPath}}/app/tmp/run"
|
||||
"github.com/revel/revel"
|
||||
)
|
||||
|
||||
var (
|
||||
runMode *string = flag.String("runMode", "", "Run mode.")
|
||||
port *int = flag.Int("port", 0, "By default, read from app.conf")
|
||||
importPath *string = flag.String("importPath", "", "Go Import Path for the app.")
|
||||
srcPath *string = flag.String("srcPath", "", "Path to the source root.")
|
||||
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
revel.Init(*runMode, *importPath, *srcPath)
|
||||
run.Run(*port)
|
||||
}
|
||||
`
|
||||
|
||||
// RevelRoutesTemplate template for app/conf/routes
|
||||
const RevelRoutesTemplate = `// GENERATED CODE - DO NOT EDIT
|
||||
// This file provides a way of creating URL's based on all the actions
|
||||
// found in all the controllers.
|
||||
package routes
|
||||
|
||||
import "github.com/revel/revel"
|
||||
|
||||
{{range $i, $c := .Controllers}}
|
||||
type t{{.StructName}} struct {}
|
||||
var {{.StructName}} t{{.StructName}}
|
||||
|
||||
{{range .MethodSpecs}}
|
||||
func (_ t{{$c.StructName}}) {{.Name}}({{range .Args}}
|
||||
{{.Name}} {{if .ImportPath}}interface{}{{else}}{{.TypeExpr.TypeName ""}}{{end}},{{end}}
|
||||
) string {
|
||||
args := make(map[string]string)
|
||||
{{range .Args}}
|
||||
revel.Unbind(args, "{{.Name}}", {{.Name}}){{end}}
|
||||
return revel.MainRouter.Reverse("{{$c.StructName}}.{{.Name}}", args).URL
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
`
|
||||
411
app/cmd/harness/harness.go
Normal file
411
app/cmd/harness/harness.go
Normal file
@@ -0,0 +1,411 @@
|
||||
// Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
|
||||
// Revel Framework source code and usage is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package harness for a Revel Framework.
|
||||
//
|
||||
// It has a following responsibilities:
|
||||
// 1. Parse the user program, generating a main.go file that registers
|
||||
// controller classes and starts the user's server.
|
||||
// 2. Build and run the user program. Show compile errors.
|
||||
// 3. Monitor the user source and re-build / restart the program when necessary.
|
||||
//
|
||||
// Source files are generated in the app/tmp directory.
|
||||
package harness
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"time"
|
||||
"go/build"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"github.com/revel/cmd/watcher"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
var (
|
||||
doNotWatch = []string{"tmp", "views", "routes"}
|
||||
|
||||
lastRequestHadError int32
|
||||
)
|
||||
|
||||
// Harness reverse proxies requests to the application server.
|
||||
// It builds / runs / rebuilds / restarts the server when code is changed.
|
||||
type Harness struct {
|
||||
app *App // The application
|
||||
useProxy bool // True if proxy is in use
|
||||
serverHost string // The proxy server host
|
||||
port int // The proxy serber port
|
||||
proxy *httputil.ReverseProxy // The proxy
|
||||
watcher *watcher.Watcher // The file watched
|
||||
mutex *sync.Mutex // A mutex to prevent concurrent updates
|
||||
paths *model.RevelContainer // The Revel container
|
||||
config *model.CommandConfig // The configuration
|
||||
runMode string // The runmode the harness is running in
|
||||
isError bool // True if harness is in error state
|
||||
ranOnce bool // True app compiled once
|
||||
}
|
||||
|
||||
func (h *Harness) renderError(iw http.ResponseWriter, ir *http.Request, err error) {
|
||||
// Render error here
|
||||
// Grab the template from three places
|
||||
// 1) Application/views/errors
|
||||
// 2) revel_home/views/errors
|
||||
// 3) views/errors
|
||||
if err == nil {
|
||||
utils.Logger.Panic("Caller passed in a nil error")
|
||||
}
|
||||
templateSet := template.New("__root__")
|
||||
seekViewOnPath := func(view string) (path string) {
|
||||
path = filepath.Join(h.paths.ViewsPath, "errors", view)
|
||||
if !utils.Exists(path) {
|
||||
path = filepath.Join(h.paths.RevelPath, "templates", "errors", view)
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Unable to read template file", path)
|
||||
}
|
||||
_, err = templateSet.New("errors/" + view).Parse(string(data))
|
||||
if err != nil {
|
||||
utils.Logger.Error("Unable to parse template file", path)
|
||||
}
|
||||
return
|
||||
}
|
||||
target := []string{seekViewOnPath("500.html"), seekViewOnPath("500-dev.html")}
|
||||
if !utils.Exists(target[0]) {
|
||||
fmt.Fprintf(iw, "Target template not found not found %s<br />\n", target[0])
|
||||
fmt.Fprintf(iw, "An error ocurred %s", err.Error())
|
||||
return
|
||||
}
|
||||
var revelError *utils.SourceError
|
||||
switch e := err.(type) {
|
||||
case *utils.SourceError:
|
||||
revelError = e
|
||||
case error:
|
||||
revelError = &utils.SourceError{
|
||||
Title: "Server Error",
|
||||
Description: e.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
if revelError == nil {
|
||||
panic("no error provided")
|
||||
}
|
||||
viewArgs := map[string]interface{}{}
|
||||
viewArgs["RunMode"] = h.paths.RunMode
|
||||
viewArgs["DevMode"] = h.paths.DevMode
|
||||
viewArgs["Error"] = revelError
|
||||
|
||||
// Render the template from the file
|
||||
err = templateSet.ExecuteTemplate(iw, "errors/500.html", viewArgs)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to execute", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ServeHTTP handles all requests.
|
||||
// It checks for changes to app, rebuilds if necessary, and forwards the request.
|
||||
func (h *Harness) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// Don't rebuild the app for favicon requests.
|
||||
if lastRequestHadError > 0 && r.URL.Path == "/favicon.ico" {
|
||||
return
|
||||
}
|
||||
|
||||
// Flush any change events and rebuild app if necessary.
|
||||
// Render an error page if the rebuild / restart failed.
|
||||
err := h.watcher.Notify()
|
||||
if err != nil {
|
||||
// In a thread safe manner update the flag so that a request for
|
||||
// /favicon.ico does not trigger a rebuild
|
||||
atomic.CompareAndSwapInt32(&lastRequestHadError, 0, 1)
|
||||
h.renderError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
// In a thread safe manner update the flag so that a request for
|
||||
// /favicon.ico is allowed
|
||||
atomic.CompareAndSwapInt32(&lastRequestHadError, 1, 0)
|
||||
|
||||
// Reverse proxy the request.
|
||||
// (Need special code for websockets, courtesy of bradfitz)
|
||||
if strings.EqualFold(r.Header.Get("Upgrade"), "websocket") {
|
||||
h.proxyWebsocket(w, r, h.serverHost)
|
||||
} else {
|
||||
h.proxy.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// NewHarness method returns a reverse proxy that forwards requests
|
||||
// to the given port.
|
||||
func NewHarness(c *model.CommandConfig, paths *model.RevelContainer, runMode string, noProxy bool) *Harness {
|
||||
// Get a template loader to render errors.
|
||||
// Prefer the app's views/errors directory, and fall back to the stock error pages.
|
||||
//revel.MainTemplateLoader = revel.NewTemplateLoader(
|
||||
// []string{filepath.Join(revel.RevelPath, "templates")})
|
||||
//if err := revel.MainTemplateLoader.Refresh(); err != nil {
|
||||
// revel.RevelLog.Error("Template loader error", "error", err)
|
||||
//}
|
||||
|
||||
addr := paths.HTTPAddr
|
||||
port := paths.Config.IntDefault("harness.port", 0)
|
||||
scheme := "http"
|
||||
|
||||
if paths.HTTPSsl {
|
||||
scheme = "https"
|
||||
}
|
||||
|
||||
// If the server is running on the wildcard address, use "localhost"
|
||||
if addr == "" {
|
||||
utils.Logger.Warn("No http.addr specified in the app.conf listening on localhost interface only. " +
|
||||
"This will not allow external access to your application")
|
||||
addr = "localhost"
|
||||
}
|
||||
|
||||
if port == 0 {
|
||||
port = getFreePort()
|
||||
}
|
||||
|
||||
serverURL, _ := url.ParseRequestURI(fmt.Sprintf(scheme+"://%s:%d", addr, port))
|
||||
|
||||
serverHarness := &Harness{
|
||||
port: port,
|
||||
serverHost: serverURL.String()[len(scheme+"://"):],
|
||||
proxy: httputil.NewSingleHostReverseProxy(serverURL),
|
||||
mutex: &sync.Mutex{},
|
||||
paths: paths,
|
||||
useProxy: !noProxy,
|
||||
config: c,
|
||||
runMode: runMode,
|
||||
}
|
||||
|
||||
if paths.HTTPSsl {
|
||||
serverHarness.proxy.Transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
}
|
||||
return serverHarness
|
||||
}
|
||||
|
||||
// Refresh method rebuilds the Revel application and run it on the given port.
|
||||
// called by the watcher
|
||||
func (h *Harness) Refresh() (err *utils.SourceError) {
|
||||
t := time.Now();
|
||||
fmt.Println("Changed detected, recompiling")
|
||||
err = h.refresh()
|
||||
if err!=nil && !h.ranOnce && h.useProxy {
|
||||
addr := fmt.Sprintf("%s:%d", h.paths.HTTPAddr, h.paths.HTTPPort)
|
||||
|
||||
fmt.Printf("\nError compiling code, to view error details see proxy running on http://%s\n\n",addr)
|
||||
}
|
||||
|
||||
h.ranOnce = true
|
||||
fmt.Printf("\nTime to recompile %s\n",time.Now().Sub(t).String())
|
||||
return
|
||||
}
|
||||
|
||||
func (h *Harness) refresh() (err *utils.SourceError) {
|
||||
// Allow only one thread to rebuild the process
|
||||
// If multiple requests to rebuild are queued only the last one is executed on
|
||||
// So before a build is started we wait for a second to determine if
|
||||
// more requests for a build are triggered.
|
||||
// Once no more requests are triggered the build will be processed
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
|
||||
if h.app != nil {
|
||||
h.app.Kill()
|
||||
}
|
||||
|
||||
utils.Logger.Info("Rebuild Called")
|
||||
var newErr error
|
||||
h.app, newErr = Build(h.config, h.paths)
|
||||
if newErr != nil {
|
||||
utils.Logger.Error("Build detected an error", "error", newErr)
|
||||
if castErr, ok := newErr.(*utils.SourceError); ok {
|
||||
return castErr
|
||||
}
|
||||
err = &utils.SourceError{
|
||||
Title: "App failed to start up",
|
||||
Description: err.Error(),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if h.useProxy {
|
||||
h.app.Port = h.port
|
||||
runMode := h.runMode
|
||||
if !h.config.HistoricMode {
|
||||
// Recalulate run mode based on the config
|
||||
var paths []byte
|
||||
if len(h.app.PackagePathMap)>0 {
|
||||
paths, _ = json.Marshal(h.app.PackagePathMap)
|
||||
}
|
||||
runMode = fmt.Sprintf(`{"mode":"%s", "specialUseFlag":%v,"packagePathMap":%s}`, h.app.Paths.RunMode, h.config.Verbose, string(paths))
|
||||
|
||||
}
|
||||
if err2 := h.app.Cmd(runMode).Start(h.config); err2 != nil {
|
||||
utils.Logger.Error("Could not start application", "error", err2)
|
||||
if err,k :=err2.(*utils.SourceError);k {
|
||||
return err
|
||||
}
|
||||
return &utils.SourceError{
|
||||
Title: "App failed to start up",
|
||||
Description: err2.Error(),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
h.app = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// WatchDir method returns false to file matches with doNotWatch
|
||||
// otheriwse true
|
||||
func (h *Harness) WatchDir(info os.FileInfo) bool {
|
||||
return !utils.ContainsString(doNotWatch, info.Name())
|
||||
}
|
||||
|
||||
// WatchFile method returns true given filename HasSuffix of ".go"
|
||||
// otheriwse false - implements revel.DiscerningListener
|
||||
func (h *Harness) WatchFile(filename string) bool {
|
||||
return strings.HasSuffix(filename, ".go")
|
||||
}
|
||||
|
||||
// Run the harness, which listens for requests and proxies them to the app
|
||||
// server, which it runs and rebuilds as necessary.
|
||||
func (h *Harness) Run() {
|
||||
var paths []string
|
||||
if h.paths.Config.BoolDefault("watch.gopath", false) {
|
||||
gopaths := filepath.SplitList(build.Default.GOPATH)
|
||||
paths = append(paths, gopaths...)
|
||||
}
|
||||
paths = append(paths, h.paths.CodePaths...)
|
||||
h.watcher = watcher.NewWatcher(h.paths, false)
|
||||
h.watcher.Listen(h, paths...)
|
||||
go h.Refresh()
|
||||
// h.watcher.Notify()
|
||||
|
||||
if h.useProxy {
|
||||
go func() {
|
||||
// Check the port to start on a random port
|
||||
if h.paths.HTTPPort == 0 {
|
||||
h.paths.HTTPPort = getFreePort()
|
||||
}
|
||||
addr := fmt.Sprintf("%s:%d", h.paths.HTTPAddr, h.paths.HTTPPort)
|
||||
utils.Logger.Infof("Proxy server is listening on %s", addr)
|
||||
|
||||
|
||||
var err error
|
||||
if h.paths.HTTPSsl {
|
||||
err = http.ListenAndServeTLS(
|
||||
addr,
|
||||
h.paths.HTTPSslCert,
|
||||
h.paths.HTTPSslKey,
|
||||
h)
|
||||
} else {
|
||||
err = http.ListenAndServe(addr, h)
|
||||
}
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to start reverse proxy:", "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
// Make a new channel to listen for the interrupt event
|
||||
ch := make(chan os.Signal)
|
||||
signal.Notify(ch, os.Interrupt, os.Kill)
|
||||
<-ch
|
||||
// Kill the app and exit
|
||||
if h.app != nil {
|
||||
h.app.Kill()
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Find an unused port
|
||||
func getFreePort() (port int) {
|
||||
conn, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
utils.Logger.Fatal("Unable to fetch a freee port address", "error", err)
|
||||
}
|
||||
|
||||
port = conn.Addr().(*net.TCPAddr).Port
|
||||
err = conn.Close()
|
||||
if err != nil {
|
||||
utils.Logger.Fatal("Unable to close port", "error", err)
|
||||
}
|
||||
return port
|
||||
}
|
||||
|
||||
// proxyWebsocket copies data between websocket client and server until one side
|
||||
// closes the connection. (ReverseProxy doesn't work with websocket requests.)
|
||||
func (h *Harness) proxyWebsocket(w http.ResponseWriter, r *http.Request, host string) {
|
||||
var (
|
||||
d net.Conn
|
||||
err error
|
||||
)
|
||||
if h.paths.HTTPSsl {
|
||||
// since this proxy isn't used in production,
|
||||
// it's OK to set InsecureSkipVerify to true
|
||||
// no need to add another configuration option.
|
||||
d, err = tls.Dial("tcp", host, &tls.Config{InsecureSkipVerify: true})
|
||||
} else {
|
||||
d, err = net.Dial("tcp", host)
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(w, "Error contacting backend server.", 500)
|
||||
utils.Logger.Error("Error dialing websocket backend ", "host", host, "error", err)
|
||||
return
|
||||
}
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Not a hijacker?", 500)
|
||||
return
|
||||
}
|
||||
nc, _, err := hj.Hijack()
|
||||
if err != nil {
|
||||
utils.Logger.Error("Hijack error", "error", err)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err = nc.Close(); err != nil {
|
||||
utils.Logger.Error("Connection close error", "error", err)
|
||||
}
|
||||
if err = d.Close(); err != nil {
|
||||
utils.Logger.Error("Dial close error", "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
err = r.Write(d)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Error copying request to target", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
errc := make(chan error, 2)
|
||||
cp := func(dst io.Writer, src io.Reader) {
|
||||
_, err := io.Copy(dst, src)
|
||||
errc <- err
|
||||
}
|
||||
go cp(d, nc)
|
||||
go cp(nc, d)
|
||||
<-errc
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/revel/cmd/harness"
|
||||
"github.com/revel/revel"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// go run main.go
|
||||
// 生成routes.go, main.go
|
||||
revel.Init("", "github.com/leanote/leanote", "")
|
||||
_, err := harness.Build() // ok, err
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("Ok")
|
||||
// panicOnError(reverr, "Failed to build")
|
||||
}
|
||||
427
app/cmd/parser2/source_info_processor.go
Normal file
427
app/cmd/parser2/source_info_processor.go
Normal file
@@ -0,0 +1,427 @@
|
||||
package parser2
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/utils"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"github.com/revel/cmd/model"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"strings"
|
||||
"path/filepath"
|
||||
"github.com/revel/cmd/logger"
|
||||
)
|
||||
|
||||
type (
|
||||
SourceInfoProcessor struct {
|
||||
sourceProcessor *SourceProcessor
|
||||
}
|
||||
)
|
||||
|
||||
func NewSourceInfoProcessor(sourceProcessor *SourceProcessor) *SourceInfoProcessor {
|
||||
return &SourceInfoProcessor{sourceProcessor:sourceProcessor}
|
||||
}
|
||||
|
||||
func (s *SourceInfoProcessor) processPackage(p *packages.Package) (sourceInfo *model.SourceInfo) {
|
||||
sourceInfo = &model.SourceInfo{
|
||||
ValidationKeys: map[string]map[int]string{},
|
||||
}
|
||||
var (
|
||||
isController = strings.HasSuffix(p.PkgPath, "/controllers") ||
|
||||
strings.Contains(p.PkgPath, "/controllers/")
|
||||
isTest = strings.HasSuffix(p.PkgPath, "/tests") ||
|
||||
strings.Contains(p.PkgPath, "/tests/")
|
||||
methodMap = map[string][]*model.MethodSpec{}
|
||||
)
|
||||
localImportMap := map[string]string{}
|
||||
log := s.sourceProcessor.log.New("package", p.PkgPath)
|
||||
log.Info("Processing package")
|
||||
for _, tree := range p.Syntax {
|
||||
for _, decl := range tree.Decls {
|
||||
|
||||
s.sourceProcessor.packageMap[p.PkgPath] = filepath.Dir(p.Fset.Position(decl.Pos()).Filename)
|
||||
if !s.addImport(decl, p, localImportMap, log) {
|
||||
continue
|
||||
}
|
||||
spec, found := s.getStructTypeDecl(decl, p.Fset)
|
||||
//log.Info("Checking file","filename", p.Fset.Position(decl.Pos()).Filename,"found",found)
|
||||
if found {
|
||||
if isController || isTest {
|
||||
controllerSpec := s.getControllerSpec(spec, p, localImportMap)
|
||||
sourceInfo.StructSpecs = append(sourceInfo.StructSpecs, controllerSpec)
|
||||
}
|
||||
} else {
|
||||
// Not a type definition, this could be a method for a controller try to extract that
|
||||
// Func declaration?
|
||||
funcDecl, ok := decl.(*ast.FuncDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// This could be a controller action endpoint, check and add if needed
|
||||
if isController &&
|
||||
funcDecl.Recv != nil && // Must have a receiver
|
||||
funcDecl.Name.IsExported() && // be public
|
||||
funcDecl.Type.Results != nil && len(funcDecl.Type.Results.List) == 1 {
|
||||
// return one result
|
||||
if m, receiver := s.getControllerFunc(funcDecl, p, localImportMap); m != nil {
|
||||
methodMap[receiver] = append(methodMap[receiver], m)
|
||||
log.Info("Added method map to ", "receiver", receiver, "method", m.Name)
|
||||
}
|
||||
}
|
||||
// Check for validation
|
||||
if lineKeyMap := s.getValidation(funcDecl, p); len(lineKeyMap) > 1 {
|
||||
sourceInfo.ValidationKeys[p.PkgPath + "." + s.getFuncName(funcDecl)] = lineKeyMap
|
||||
}
|
||||
if funcDecl.Name.Name == "init" {
|
||||
sourceInfo.InitImportPaths = append(sourceInfo.InitImportPaths, p.PkgPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the method specs to the struct specs.
|
||||
for _, spec := range sourceInfo.StructSpecs {
|
||||
spec.MethodSpecs = methodMap[spec.StructName]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
// Scan app source code for calls to X.Y(), where X is of type *Validation.
|
||||
//
|
||||
// Recognize these scenarios:
|
||||
// - "Y" = "Validation" and is a member of the receiver.
|
||||
// (The common case for inline validation)
|
||||
// - "X" is passed in to the func as a parameter.
|
||||
// (For structs implementing Validated)
|
||||
//
|
||||
// The line number to which a validation call is attributed is that of the
|
||||
// surrounding ExprStmt. This is so that it matches what runtime.Callers()
|
||||
// reports.
|
||||
//
|
||||
// The end result is that we can set the default validation key for each call to
|
||||
// be the same as the local variable.
|
||||
func (s *SourceInfoProcessor) getValidation(funcDecl *ast.FuncDecl, p *packages.Package) (map[int]string) {
|
||||
var (
|
||||
lineKeys = make(map[int]string)
|
||||
|
||||
// Check the func parameters and the receiver's members for the *revel.Validation type.
|
||||
validationParam = s.getValidationParameter(funcDecl)
|
||||
)
|
||||
|
||||
ast.Inspect(funcDecl.Body, func(node ast.Node) bool {
|
||||
// e.g. c.Validation.Required(arg) or v.Required(arg)
|
||||
callExpr, ok := node.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
// e.g. c.Validation.Required or v.Required
|
||||
funcSelector, ok := callExpr.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
switch x := funcSelector.X.(type) {
|
||||
case *ast.SelectorExpr: // e.g. c.Validation
|
||||
if x.Sel.Name != "Validation" {
|
||||
return true
|
||||
}
|
||||
|
||||
case *ast.Ident: // e.g. v
|
||||
if validationParam == nil || x.Obj != validationParam {
|
||||
return true
|
||||
}
|
||||
|
||||
default:
|
||||
return true
|
||||
}
|
||||
|
||||
if len(callExpr.Args) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
// Given the validation expression, extract the key.
|
||||
key := callExpr.Args[0]
|
||||
switch expr := key.(type) {
|
||||
case *ast.BinaryExpr:
|
||||
// If the argument is a binary expression, take the first expression.
|
||||
// (e.g. c.Validation.Required(myName != ""))
|
||||
key = expr.X
|
||||
case *ast.UnaryExpr:
|
||||
// If the argument is a unary expression, drill in.
|
||||
// (e.g. c.Validation.Required(!myBool)
|
||||
key = expr.X
|
||||
case *ast.BasicLit:
|
||||
// If it's a literal, skip it.
|
||||
return true
|
||||
}
|
||||
|
||||
if typeExpr := model.NewTypeExprFromAst("", key); typeExpr.Valid {
|
||||
lineKeys[p.Fset.Position(callExpr.End()).Line] = typeExpr.TypeName("")
|
||||
} else {
|
||||
s.sourceProcessor.log.Error("Error: Failed to generate key for field validation. Make sure the field name is valid.", "file", p.PkgPath,
|
||||
"line", p.Fset.Position(callExpr.End()).Line, "function", funcDecl.Name.String())
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
return lineKeys
|
||||
|
||||
}
|
||||
// Check to see if there is a *revel.Validation as an argument.
|
||||
func (s *SourceInfoProcessor) getValidationParameter(funcDecl *ast.FuncDecl) *ast.Object {
|
||||
for _, field := range funcDecl.Type.Params.List {
|
||||
starExpr, ok := field.Type.(*ast.StarExpr) // e.g. *revel.Validation
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
selExpr, ok := starExpr.X.(*ast.SelectorExpr) // e.g. revel.Validation
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
xIdent, ok := selExpr.X.(*ast.Ident) // e.g. rev
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if selExpr.Sel.Name == "Validation" && s.sourceProcessor.importMap[xIdent.Name] == model.RevelImportPath {
|
||||
return field.Names[0].Obj
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (s *SourceInfoProcessor) getControllerFunc(funcDecl *ast.FuncDecl, p *packages.Package, localImportMap map[string]string) (method *model.MethodSpec, recvTypeName string) {
|
||||
selExpr, ok := funcDecl.Type.Results.List[0].Type.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if selExpr.Sel.Name != "Result" {
|
||||
return
|
||||
}
|
||||
if pkgIdent, ok := selExpr.X.(*ast.Ident); !ok || s.sourceProcessor.importMap[pkgIdent.Name] != model.RevelImportPath {
|
||||
return
|
||||
}
|
||||
method = &model.MethodSpec{
|
||||
Name: funcDecl.Name.Name,
|
||||
}
|
||||
|
||||
// Add a description of the arguments to the method.
|
||||
for _, field := range funcDecl.Type.Params.List {
|
||||
for _, name := range field.Names {
|
||||
var importPath string
|
||||
typeExpr := model.NewTypeExprFromAst(p.Name, field.Type)
|
||||
if !typeExpr.Valid {
|
||||
utils.Logger.Warn("Warn: Didn't understand argument '%s' of action %s. Ignoring.", name, s.getFuncName(funcDecl))
|
||||
return // We didn't understand one of the args. Ignore this action.
|
||||
}
|
||||
// Local object
|
||||
if typeExpr.PkgName == p.Name {
|
||||
importPath = p.PkgPath
|
||||
} else if typeExpr.PkgName != "" {
|
||||
var ok bool
|
||||
if importPath, ok = localImportMap[typeExpr.PkgName]; !ok {
|
||||
if importPath, ok = s.sourceProcessor.importMap[typeExpr.PkgName]; !ok {
|
||||
utils.Logger.Error("Unable to find import", "importMap", s.sourceProcessor.importMap, "localimport", localImportMap)
|
||||
utils.Logger.Fatalf("Failed to find import for arg of type: %s , %s", typeExpr.PkgName, typeExpr.TypeName(""))
|
||||
}
|
||||
}
|
||||
}
|
||||
method.Args = append(method.Args, &model.MethodArg{
|
||||
Name: name.Name,
|
||||
TypeExpr: typeExpr,
|
||||
ImportPath: importPath,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Add a description of the calls to Render from the method.
|
||||
// Inspect every node (e.g. always return true).
|
||||
method.RenderCalls = []*model.MethodCall{}
|
||||
ast.Inspect(funcDecl.Body, func(node ast.Node) bool {
|
||||
// Is it a function call?
|
||||
callExpr, ok := node.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
// Is it calling (*Controller).Render?
|
||||
selExpr, ok := callExpr.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
// The type of the receiver is not easily available, so just store every
|
||||
// call to any method called Render.
|
||||
if selExpr.Sel.Name != "Render" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Add this call's args to the renderArgs.
|
||||
pos := p.Fset.Position(callExpr.Lparen)
|
||||
methodCall := &model.MethodCall{
|
||||
Line: pos.Line,
|
||||
Names: []string{},
|
||||
}
|
||||
for _, arg := range callExpr.Args {
|
||||
argIdent, ok := arg.(*ast.Ident)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
methodCall.Names = append(methodCall.Names, argIdent.Name)
|
||||
}
|
||||
method.RenderCalls = append(method.RenderCalls, methodCall)
|
||||
return true
|
||||
})
|
||||
|
||||
var recvType = funcDecl.Recv.List[0].Type
|
||||
if recvStarType, ok := recvType.(*ast.StarExpr); ok {
|
||||
recvTypeName = recvStarType.X.(*ast.Ident).Name
|
||||
} else {
|
||||
recvTypeName = recvType.(*ast.Ident).Name
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *SourceInfoProcessor) getControllerSpec(spec *ast.TypeSpec, p *packages.Package, localImportMap map[string]string) (controllerSpec *model.TypeInfo) {
|
||||
structType := spec.Type.(*ast.StructType)
|
||||
|
||||
// At this point we know it's a type declaration for a struct.
|
||||
// Fill in the rest of the info by diving into the fields.
|
||||
// Add it provisionally to the Controller list -- it's later filtered using field info.
|
||||
controllerSpec = &model.TypeInfo{
|
||||
StructName: spec.Name.Name,
|
||||
ImportPath: p.PkgPath,
|
||||
PackageName: p.Name,
|
||||
}
|
||||
log := s.sourceProcessor.log.New("file", p.Fset.Position(spec.Pos()).Filename, "position", p.Fset.Position(spec.Pos()).Line)
|
||||
for _, field := range structType.Fields.List {
|
||||
// If field.Names is set, it's not an embedded type.
|
||||
if field.Names != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// A direct "sub-type" has an ast.Field as either:
|
||||
// Ident { "AppController" }
|
||||
// SelectorExpr { "rev", "Controller" }
|
||||
// Additionally, that can be wrapped by StarExprs.
|
||||
fieldType := field.Type
|
||||
pkgName, typeName := func() (string, string) {
|
||||
// Drill through any StarExprs.
|
||||
for {
|
||||
if starExpr, ok := fieldType.(*ast.StarExpr); ok {
|
||||
fieldType = starExpr.X
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// If the embedded type is in the same package, it's an Ident.
|
||||
if ident, ok := fieldType.(*ast.Ident); ok {
|
||||
return "", ident.Name
|
||||
}
|
||||
|
||||
if selectorExpr, ok := fieldType.(*ast.SelectorExpr); ok {
|
||||
if pkgIdent, ok := selectorExpr.X.(*ast.Ident); ok {
|
||||
return pkgIdent.Name, selectorExpr.Sel.Name
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}()
|
||||
|
||||
// If a typename wasn't found, skip it.
|
||||
if typeName == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find the import path for this type.
|
||||
// If it was referenced without a package name, use the current package import path.
|
||||
// Else, look up the package's import path by name.
|
||||
var importPath string
|
||||
if pkgName == "" {
|
||||
importPath = p.PkgPath
|
||||
} else {
|
||||
var ok bool
|
||||
if importPath, ok = localImportMap[pkgName]; !ok {
|
||||
log.Debug("Debug: Unusual, failed to find package locally ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin", )
|
||||
if importPath, ok = s.sourceProcessor.importMap[pkgName]; !ok {
|
||||
log.Error("Error: Failed to find import path for ", "package", pkgName, "type", typeName, "map", s.sourceProcessor.importMap, "usedin", )
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
controllerSpec.EmbeddedTypes = append(controllerSpec.EmbeddedTypes, &model.EmbeddedTypeName{
|
||||
ImportPath: importPath,
|
||||
StructName: typeName,
|
||||
})
|
||||
}
|
||||
s.sourceProcessor.log.Info("Added controller spec", "name", controllerSpec.StructName, "package", controllerSpec.ImportPath)
|
||||
return
|
||||
}
|
||||
func (s *SourceInfoProcessor) getStructTypeDecl(decl ast.Decl, fset *token.FileSet) (spec *ast.TypeSpec, found bool) {
|
||||
genDecl, ok := decl.(*ast.GenDecl)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if genDecl.Tok != token.TYPE {
|
||||
return
|
||||
}
|
||||
|
||||
if len(genDecl.Specs) == 0 {
|
||||
utils.Logger.Warn("Warn: Surprising: %s:%d Decl contains no specifications", fset.Position(decl.Pos()).Filename, fset.Position(decl.Pos()).Line)
|
||||
return
|
||||
}
|
||||
|
||||
spec = genDecl.Specs[0].(*ast.TypeSpec)
|
||||
_, found = spec.Type.(*ast.StructType)
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
func (s *SourceInfoProcessor) getFuncName(funcDecl *ast.FuncDecl) string {
|
||||
prefix := ""
|
||||
if funcDecl.Recv != nil {
|
||||
recvType := funcDecl.Recv.List[0].Type
|
||||
if recvStarType, ok := recvType.(*ast.StarExpr); ok {
|
||||
prefix = "(*" + recvStarType.X.(*ast.Ident).Name + ")"
|
||||
} else {
|
||||
prefix = recvType.(*ast.Ident).Name
|
||||
}
|
||||
prefix += "."
|
||||
}
|
||||
return prefix + funcDecl.Name.Name
|
||||
}
|
||||
func (s *SourceInfoProcessor) addImport(decl ast.Decl, p *packages.Package, localImportMap map[string]string, log logger.MultiLogger) (shouldContinue bool) {
|
||||
shouldContinue = true
|
||||
genDecl, ok := decl.(*ast.GenDecl)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if genDecl.Tok == token.IMPORT {
|
||||
shouldContinue = false
|
||||
for _, spec := range genDecl.Specs {
|
||||
importSpec := spec.(*ast.ImportSpec)
|
||||
//fmt.Printf("*** import specification %#v\n", importSpec)
|
||||
var pkgAlias string
|
||||
if importSpec.Name != nil {
|
||||
pkgAlias = importSpec.Name.Name
|
||||
if pkgAlias == "_" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\""
|
||||
fullPath := quotedPath[1 : len(quotedPath) - 1] // Remove the quotes
|
||||
if pkgAlias == "" {
|
||||
pkgAlias = fullPath
|
||||
if index := strings.LastIndex(pkgAlias, "/"); index > 0 {
|
||||
pkgAlias = pkgAlias[index + 1:]
|
||||
}
|
||||
}
|
||||
localImportMap[pkgAlias] = fullPath
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
310
app/cmd/parser2/source_processor.go
Normal file
310
app/cmd/parser2/source_processor.go
Normal file
@@ -0,0 +1,310 @@
|
||||
package parser2
|
||||
|
||||
import (
|
||||
"github.com/revel/cmd/logger"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/scanner"
|
||||
"go/token"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
SourceProcessor struct {
|
||||
revelContainer *model.RevelContainer
|
||||
log logger.MultiLogger
|
||||
packageList []*packages.Package
|
||||
importMap map[string]string
|
||||
packageMap map[string]string
|
||||
sourceInfoProcessor *SourceInfoProcessor
|
||||
sourceInfo *model.SourceInfo
|
||||
}
|
||||
)
|
||||
|
||||
func ProcessSource(revelContainer *model.RevelContainer) (sourceInfo *model.SourceInfo, compileError error) {
|
||||
utils.Logger.Info("ProcessSource")
|
||||
processor := NewSourceProcessor(revelContainer)
|
||||
compileError = processor.parse()
|
||||
sourceInfo = processor.sourceInfo
|
||||
if compileError == nil {
|
||||
processor.log.Infof("From parsers : Structures:%d InitImports:%d ValidationKeys:%d %v", len(sourceInfo.StructSpecs), len(sourceInfo.InitImportPaths), len(sourceInfo.ValidationKeys), sourceInfo.PackageMap)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func NewSourceProcessor(revelContainer *model.RevelContainer) *SourceProcessor {
|
||||
s := &SourceProcessor{revelContainer:revelContainer, log:utils.Logger.New("parser", "SourceProcessor")}
|
||||
s.sourceInfoProcessor = NewSourceInfoProcessor(s)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *SourceProcessor) parse() (compileError error) {
|
||||
print("Parsing packages, (may require download if not cached)...")
|
||||
if compileError = s.addPackages(); compileError != nil {
|
||||
return
|
||||
}
|
||||
println(" Completed")
|
||||
if compileError = s.addImportMap(); compileError != nil {
|
||||
return
|
||||
}
|
||||
if compileError = s.addSourceInfo(); compileError != nil {
|
||||
return
|
||||
}
|
||||
|
||||
s.sourceInfo.PackageMap = map[string]string{}
|
||||
getImportFromMap := func(packagePath string) string {
|
||||
for path := range s.packageMap {
|
||||
if strings.Index(path, packagePath) == 0 {
|
||||
fullPath := s.packageMap[path]
|
||||
return fullPath[:(len(fullPath) - len(path) + len(packagePath))]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
s.sourceInfo.PackageMap[model.RevelImportPath] = getImportFromMap(model.RevelImportPath)
|
||||
s.sourceInfo.PackageMap[s.revelContainer.ImportPath] = getImportFromMap(s.revelContainer.ImportPath)
|
||||
for _, module := range s.revelContainer.ModulePathMap {
|
||||
s.sourceInfo.PackageMap[module.ImportPath] = getImportFromMap(module.ImportPath)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 这两个方法来自util
|
||||
|
||||
// Shortcut to fsWalk
|
||||
func (s *SourceProcessor) Walk(root string, walkFn filepath.WalkFunc) error {
|
||||
return s.fsWalk(root, root, walkFn)
|
||||
}
|
||||
|
||||
// Walk the path tree using the function
|
||||
// Every file found will call the function
|
||||
func (s *SourceProcessor) fsWalk(fname string, linkName string, walkFn filepath.WalkFunc) error {
|
||||
fsWalkFunc := func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var name string
|
||||
name, err = filepath.Rel(fname, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path = filepath.Join(linkName, name)
|
||||
|
||||
// 改了这里
|
||||
if strings.Contains(path, "/leanote/public") ||
|
||||
strings.Contains(path, "/leanote/files") ||
|
||||
strings.Contains(path, "/leanote/doc") ||
|
||||
strings.Contains(path, "/leanote/logs") ||
|
||||
strings.Contains(path, "/leanote/build") ||
|
||||
strings.Contains(path, "/leanote/target") {
|
||||
s.log.Warn("public 或 files 不要处理", "path", path)
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
if err == nil && info.Mode() & os.ModeSymlink == os.ModeSymlink {
|
||||
var symlinkPath string
|
||||
symlinkPath, err = filepath.EvalSymlinks(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// https://github.com/golang/go/blob/master/src/path/filepath/path.go#L392
|
||||
info, err = os.Lstat(symlinkPath)
|
||||
|
||||
if err != nil {
|
||||
return walkFn(path, info, err)
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return s.fsWalk(symlinkPath, path, walkFn)
|
||||
}
|
||||
}
|
||||
|
||||
return walkFn(path, info, err)
|
||||
}
|
||||
err := filepath.Walk(fname, fsWalkFunc)
|
||||
return err
|
||||
}
|
||||
|
||||
// Using the packages.Load function load all the packages and type specifications (forces compile).
|
||||
// this sets the SourceProcessor.packageList []*packages.Package
|
||||
func (s *SourceProcessor) addPackages() (err error) {
|
||||
allPackages := []string{model.RevelImportPath + "/..."}
|
||||
for _, module := range s.revelContainer.ModulePathMap {
|
||||
allPackages = append(allPackages, module.ImportPath + "/...") // +"/app/controllers/...")
|
||||
}
|
||||
s.log.Info("Reading packages", "packageList", allPackages)
|
||||
//allPackages = []string{s.revelContainer.ImportPath + "/..."} //+"/app/controllers/..."}
|
||||
|
||||
config := &packages.Config{
|
||||
// ode: packages.NeedSyntax | packages.NeedCompiledGoFiles,
|
||||
Mode:
|
||||
packages.NeedTypes | // For compile error
|
||||
packages.NeedDeps | // To load dependent files
|
||||
packages.NeedName | // Loads the full package name
|
||||
packages.NeedSyntax, // To load ast tree (for end points)
|
||||
//Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles |
|
||||
// packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile |
|
||||
// packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo |
|
||||
// packages.NeedTypesSizes,
|
||||
|
||||
//Mode: packages.NeedName | packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile | packages.NeedFiles |
|
||||
// packages.NeedCompiledGoFiles | packages.NeedTypesSizes |
|
||||
// packages.NeedSyntax | packages.NeedCompiledGoFiles ,
|
||||
//Mode: packages.NeedSyntax | packages.NeedCompiledGoFiles | packages.NeedName | packages.NeedFiles |
|
||||
// packages.LoadTypes | packages.NeedTypes | packages.NeedDeps, //, // |
|
||||
// packages.NeedTypes, // packages.LoadTypes | packages.NeedSyntax | packages.NeedTypesInfo,
|
||||
//packages.LoadSyntax | packages.NeedDeps,
|
||||
Dir:s.revelContainer.AppPath,
|
||||
}
|
||||
s.packageList, err = packages.Load(config, allPackages...)
|
||||
s.log.Info("Loaded modules ", "len results", len(s.packageList), "error", err)
|
||||
|
||||
// Now process the files in the aap source folder s.revelContainer.ImportPath + "/...",
|
||||
err = s.Walk(s.revelContainer.BasePath, s.processPath)
|
||||
s.log.Info("Loaded apps and modules ", "len results", len(s.packageList), "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
// This callback is used to build the packages for the "app" package. This allows us to
|
||||
// parse the source files without doing a full compile on them
|
||||
// This callback only processes folders, so any files passed to this will return a nil
|
||||
func (s *SourceProcessor) processPath(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
s.log.Error("Error scanning app source:", "error", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ignore files and folders not marked tmp (since those are generated)
|
||||
if !info.IsDir() || info.Name() == "tmp" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Real work for processing the folder
|
||||
pkgImportPath := s.revelContainer.ImportPath
|
||||
appPath := s.revelContainer.BasePath
|
||||
if appPath != path {
|
||||
pkgImportPath = s.revelContainer.ImportPath + "/" + filepath.ToSlash(path[len(appPath) + 1:])
|
||||
}
|
||||
s.log.Info("Processing source package folder", "package", pkgImportPath, "path", path)
|
||||
|
||||
// Parse files within the path.
|
||||
var pkgMap map[string]*ast.Package
|
||||
fset := token.NewFileSet()
|
||||
pkgMap, err = parser.ParseDir(
|
||||
fset,
|
||||
path,
|
||||
func(f os.FileInfo) bool {
|
||||
return !f.IsDir() && !strings.HasPrefix(f.Name(), ".") && strings.HasSuffix(f.Name(), ".go")
|
||||
},
|
||||
0)
|
||||
|
||||
if err != nil {
|
||||
if errList, ok := err.(scanner.ErrorList); ok {
|
||||
var pos = errList[0].Pos
|
||||
newError := &utils.SourceError{
|
||||
SourceType: ".go source",
|
||||
Title: "Go Compilation Error",
|
||||
Path: pos.Filename,
|
||||
Description: errList[0].Msg,
|
||||
Line: pos.Line,
|
||||
Column: pos.Column,
|
||||
SourceLines: utils.MustReadLines(pos.Filename),
|
||||
}
|
||||
|
||||
errorLink := s.revelContainer.Config.StringDefault("error.link", "")
|
||||
if errorLink != "" {
|
||||
newError.SetLink(errorLink)
|
||||
}
|
||||
return newError
|
||||
}
|
||||
|
||||
// This is exception, err already checked above. Here just a print
|
||||
ast.Print(nil, err)
|
||||
s.log.Fatal("Failed to parse dir", "error", err)
|
||||
}
|
||||
|
||||
// Skip "main" packages.
|
||||
delete(pkgMap, "main")
|
||||
|
||||
// Ignore packages that end with _test
|
||||
// These cannot be included in source code that is not generated specifically as a test
|
||||
for i := range pkgMap {
|
||||
if len(i) > 6 {
|
||||
if string(i[len(i) - 5:]) == "_test" {
|
||||
delete(pkgMap, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no code in this directory, skip it.
|
||||
if len(pkgMap) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// There should be only one package in this directory.
|
||||
if len(pkgMap) > 1 {
|
||||
for i := range pkgMap {
|
||||
println("Found duplicate packages in single directory ", i)
|
||||
}
|
||||
utils.Logger.Fatal("Most unexpected! Multiple packages in a single directory:", "packages", pkgMap)
|
||||
}
|
||||
|
||||
// At this point there is only one package in the pkgs map,
|
||||
p := &packages.Package{}
|
||||
p.PkgPath = pkgImportPath
|
||||
p.Fset = fset
|
||||
for _, pkg := range pkgMap {
|
||||
p.Name = pkg.Name
|
||||
s.log.Info("Found package", "pkg.Name", pkg.Name, "p.Name", p.PkgPath)
|
||||
for filename, astFile := range pkg.Files {
|
||||
p.Syntax = append(p.Syntax, astFile)
|
||||
p.GoFiles = append(p.GoFiles, filename)
|
||||
}
|
||||
}
|
||||
s.packageList = append(s.packageList, p)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// This function is used to populate a map so that we can lookup controller embedded types in order to determine
|
||||
// if a Struct inherits from from revel.Controller
|
||||
func (s *SourceProcessor) addImportMap() (err error) {
|
||||
s.importMap = map[string]string{}
|
||||
s.packageMap = map[string]string{}
|
||||
for _, p := range s.packageList {
|
||||
|
||||
if len(p.Errors) > 0 {
|
||||
// Generate a compile error
|
||||
for _, e := range p.Errors {
|
||||
s.log.Info("While reading packages encountered import error ignoring ", "PkgPath", p.PkgPath, "error", e)
|
||||
}
|
||||
}
|
||||
for _, tree := range p.Syntax {
|
||||
s.importMap[tree.Name.Name] = p.PkgPath
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *SourceProcessor) addSourceInfo() (err error) {
|
||||
for _, p := range s.packageList {
|
||||
if sourceInfo := s.sourceInfoProcessor.processPackage(p); sourceInfo != nil {
|
||||
if s.sourceInfo != nil {
|
||||
s.sourceInfo.Merge(sourceInfo)
|
||||
} else {
|
||||
s.sourceInfo = sourceInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
151
app/cmd/revel.go
Normal file
151
app/cmd/revel.go
Normal file
@@ -0,0 +1,151 @@
|
||||
// Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
|
||||
// Revel Framework source code and usage is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The command line tool for running Revel apps.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jessevdk/go-flags"
|
||||
|
||||
"github.com/agtorre/gocolorize"
|
||||
"github.com/revel/cmd/logger"
|
||||
"github.com/revel/cmd/model"
|
||||
"github.com/revel/cmd/utils"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
const (
|
||||
// RevelCmdImportPath Revel framework cmd tool import path
|
||||
RevelCmdImportPath = "github.com/revel/cmd"
|
||||
|
||||
// RevelCmdImportPath Revel framework cmd tool import path
|
||||
RevelSkeletonsImportPath = "github.com/revel/skeletons"
|
||||
|
||||
// DefaultRunMode for revel's application
|
||||
DefaultRunMode = "dev"
|
||||
)
|
||||
|
||||
// Command structure cribbed from the genius organization of the "go" command.
|
||||
type Command struct {
|
||||
UpdateConfig func(c *model.CommandConfig, args []string) bool
|
||||
RunWith func(c *model.CommandConfig) error
|
||||
UsageLine, Short, Long string
|
||||
}
|
||||
|
||||
// Name returns command name from usage line
|
||||
func (cmd *Command) Name() string {
|
||||
name := cmd.UsageLine
|
||||
i := strings.Index(name, " ")
|
||||
if i >= 0 {
|
||||
name = name[:i]
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// The commands
|
||||
var Commands = []*Command{
|
||||
nil, // Safety net, prevent missing index from running
|
||||
|
||||
// 只改了这个
|
||||
nil,
|
||||
nil,
|
||||
cmdBuild,
|
||||
}
|
||||
|
||||
func main() {
|
||||
if runtime.GOOS == "windows" {
|
||||
gocolorize.SetPlain(true)
|
||||
}
|
||||
c := &model.CommandConfig{}
|
||||
wd, _ := os.Getwd()
|
||||
|
||||
utils.InitLogger(wd, logger.LvlError)
|
||||
parser := flags.NewParser(c, flags.HelpFlag | flags.PassDoubleDash)
|
||||
if len(os.Args) < 2 {
|
||||
parser.WriteHelp(os.Stdout)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := ParseArgs(c, parser, os.Args[1:]); err != nil {
|
||||
fmt.Fprint(os.Stderr, err.Error() + "\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Switch based on the verbose flag
|
||||
if len(c.Verbose) > 1 {
|
||||
utils.InitLogger(wd, logger.LvlDebug)
|
||||
} else if len(c.Verbose) > 0 {
|
||||
utils.InitLogger(wd, logger.LvlInfo)
|
||||
} else {
|
||||
utils.InitLogger(wd, logger.LvlWarn)
|
||||
}
|
||||
|
||||
// Setup package resolver
|
||||
c.InitPackageResolver()
|
||||
|
||||
if err := c.UpdateImportPath(); err != nil {
|
||||
utils.Logger.Error(err.Error())
|
||||
parser.WriteHelp(os.Stdout)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
command := Commands[c.Index]
|
||||
println("Revel executing:", command.Short)
|
||||
|
||||
if err := command.RunWith(c); err != nil {
|
||||
utils.Logger.Error("Unable to execute", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the arguments passed into the model.CommandConfig
|
||||
func ParseArgs(c *model.CommandConfig, parser *flags.Parser, args []string) (err error) {
|
||||
var extraArgs []string
|
||||
if ini := flag.String("ini", "none", ""); *ini != "none" {
|
||||
if err = flags.NewIniParser(parser).ParseFile(*ini); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if extraArgs, err = parser.ParseArgs(args); err != nil {
|
||||
return
|
||||
} else {
|
||||
switch parser.Active.Name {
|
||||
case "new":
|
||||
c.Index = model.NEW
|
||||
case "run":
|
||||
c.Index = model.RUN
|
||||
case "build":
|
||||
c.Index = model.BUILD
|
||||
case "package":
|
||||
c.Index = model.PACKAGE
|
||||
case "clean":
|
||||
c.Index = model.CLEAN
|
||||
case "test":
|
||||
c.Index = model.TEST
|
||||
case "version":
|
||||
c.Index = model.VERSION
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !Commands[c.Index].UpdateConfig(c, extraArgs) {
|
||||
buffer := &bytes.Buffer{}
|
||||
parser.WriteHelp(buffer)
|
||||
err = fmt.Errorf("Invalid command line arguements %v\n%s", extraArgs, buffer.String())
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
@@ -23,11 +23,11 @@ func (c Album) Index() revel.Result {
|
||||
// all albums by userId
|
||||
func (c Album) GetAlbums() revel.Result {
|
||||
re := albumService.GetAlbums(c.GetUserId())
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
func (c Album) DeleteAlbum(albumId string) revel.Result {
|
||||
re, msg := albumService.DeleteAlbum(c.GetUserId(), albumId)
|
||||
return c.RenderJson(info.Re{Ok: re, Msg: msg})
|
||||
return c.RenderJSON(info.Re{Ok: re, Msg: msg})
|
||||
}
|
||||
|
||||
// add album
|
||||
@@ -40,13 +40,13 @@ func (c Album) AddAlbum(name string) revel.Result {
|
||||
re := albumService.AddAlbum(album)
|
||||
|
||||
if re {
|
||||
return c.RenderJson(album)
|
||||
return c.RenderJSON(album)
|
||||
} else {
|
||||
return c.RenderJson(false)
|
||||
return c.RenderJSON(false)
|
||||
}
|
||||
}
|
||||
|
||||
// update alnum name
|
||||
func (c Album) UpdateAlbum(albumId, name string) revel.Result {
|
||||
return c.RenderJson(albumService.UpdateAlbum(albumId, c.GetUserId(), name))
|
||||
return c.RenderJSON(albumService.UpdateAlbum(albumId, c.GetUserId(), name))
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ type Attach struct {
|
||||
// 上传附件
|
||||
func (c Attach) UploadAttach(noteId string) revel.Result {
|
||||
re := c.uploadAttach(noteId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
func (c Attach) uploadAttach(noteId string) (re info.Re) {
|
||||
var fileId = ""
|
||||
@@ -46,14 +46,17 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
|
||||
return re
|
||||
}
|
||||
|
||||
file, handel, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
return re
|
||||
}
|
||||
defer file.Close()
|
||||
var data []byte
|
||||
c.Params.Bind(&data, "file")
|
||||
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
// file, handel, err := c.Request.FormFile("file")
|
||||
// if err != nil {
|
||||
// return re
|
||||
// }
|
||||
// defer file.Close()
|
||||
|
||||
// data, err := ioutil.ReadAll(file)
|
||||
if data == nil || len(data) == 0 {
|
||||
return re
|
||||
}
|
||||
// > 5M?
|
||||
@@ -71,10 +74,13 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
|
||||
newGuid := NewGuid()
|
||||
filePath := "files/" + GetRandomFilePath(c.GetUserId(), newGuid) + "/attachs"
|
||||
dir := revel.BasePath + "/" + filePath
|
||||
err = os.MkdirAll(dir, 0755)
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
if err != nil {
|
||||
return re
|
||||
}
|
||||
|
||||
handel := c.Params.Files["file"][0]
|
||||
|
||||
// 生成新的文件名
|
||||
filename := handel.Filename
|
||||
_, ext := SplitFilename(filename) // .doc
|
||||
@@ -118,7 +124,7 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
|
||||
func (c Attach) DeleteAttach(attachId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Msg = attachService.DeleteAttach(attachId, c.GetUserId())
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// get all attachs by noteId
|
||||
@@ -126,7 +132,7 @@ func (c Attach) GetAttachs(noteId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = true
|
||||
re.List = attachService.ListAttachs(noteId, c.GetUserId())
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 下载附件
|
||||
|
||||
@@ -17,29 +17,29 @@ type Auth struct {
|
||||
//--------
|
||||
// 登录
|
||||
func (c Auth) Login(email, from string) revel.Result {
|
||||
c.RenderArgs["title"] = c.Message("login")
|
||||
c.RenderArgs["subTitle"] = c.Message("login")
|
||||
c.RenderArgs["email"] = email
|
||||
c.RenderArgs["from"] = from
|
||||
c.RenderArgs["openRegister"] = configService.IsOpenRegister()
|
||||
c.ViewArgs["title"] = c.Message("login")
|
||||
c.ViewArgs["subTitle"] = c.Message("login")
|
||||
c.ViewArgs["email"] = email
|
||||
c.ViewArgs["from"] = from
|
||||
c.ViewArgs["openRegister"] = configService.IsOpenRegister()
|
||||
|
||||
sessionId := c.Session.Id()
|
||||
sessionId := c.Session.ID()
|
||||
if sessionService.LoginTimesIsOver(sessionId) {
|
||||
c.RenderArgs["needCaptcha"] = true
|
||||
c.ViewArgs["needCaptcha"] = true
|
||||
}
|
||||
|
||||
c.SetLocale()
|
||||
|
||||
if c.Has("demo") {
|
||||
c.RenderArgs["demo"] = true
|
||||
c.RenderArgs["email"] = "demo@leanote.com"
|
||||
c.ViewArgs["demo"] = true
|
||||
c.ViewArgs["email"] = "demo@leanote.com"
|
||||
}
|
||||
return c.RenderTemplate("home/login.html")
|
||||
}
|
||||
|
||||
// 为了demo和register
|
||||
func (c Auth) doLogin(email, pwd string) revel.Result {
|
||||
sessionId := c.Session.Id()
|
||||
sessionId := c.Session.ID()
|
||||
var msg = ""
|
||||
|
||||
userInfo, err := authService.Login(email, pwd)
|
||||
@@ -49,13 +49,13 @@ func (c Auth) doLogin(email, pwd string) revel.Result {
|
||||
} else {
|
||||
c.SetSession(userInfo)
|
||||
sessionService.ClearLoginTimes(sessionId)
|
||||
return c.RenderJson(info.Re{Ok: true})
|
||||
return c.RenderJSON(info.Re{Ok: true})
|
||||
}
|
||||
|
||||
return c.RenderJson(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId), Msg: c.Message(msg)})
|
||||
return c.RenderJSON(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId), Msg: c.Message(msg)})
|
||||
}
|
||||
func (c Auth) DoLogin(email, pwd string, captcha string) revel.Result {
|
||||
sessionId := c.Session.Id()
|
||||
sessionId := c.Session.ID()
|
||||
var msg = ""
|
||||
|
||||
// > 5次需要验证码, 直到登录成功
|
||||
@@ -70,16 +70,16 @@ func (c Auth) DoLogin(email, pwd string, captcha string) revel.Result {
|
||||
} else {
|
||||
c.SetSession(userInfo)
|
||||
sessionService.ClearLoginTimes(sessionId)
|
||||
return c.RenderJson(info.Re{Ok: true})
|
||||
return c.RenderJSON(info.Re{Ok: true})
|
||||
}
|
||||
}
|
||||
|
||||
return c.RenderJson(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId), Msg: c.Message(msg)})
|
||||
return c.RenderJSON(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId), Msg: c.Message(msg)})
|
||||
}
|
||||
|
||||
// 注销
|
||||
func (c Auth) Logout() revel.Result {
|
||||
sessionId := c.Session.Id()
|
||||
sessionId := c.Session.ID()
|
||||
sessionService.Clear(sessionId)
|
||||
c.ClearSession()
|
||||
return c.Redirect("/login")
|
||||
@@ -92,7 +92,7 @@ func (c Auth) Demo() revel.Result {
|
||||
|
||||
userInfo, err := authService.Login(email, pwd)
|
||||
if err != nil {
|
||||
return c.RenderJson(info.Re{Ok: false})
|
||||
return c.RenderJSON(info.Re{Ok: false})
|
||||
} else {
|
||||
c.SetSession(userInfo)
|
||||
return c.Redirect("/note")
|
||||
@@ -107,11 +107,11 @@ func (c Auth) Register(from, iu string) revel.Result {
|
||||
return c.Redirect("/index")
|
||||
}
|
||||
c.SetLocale()
|
||||
c.RenderArgs["from"] = from
|
||||
c.RenderArgs["iu"] = iu
|
||||
c.ViewArgs["from"] = from
|
||||
c.ViewArgs["iu"] = iu
|
||||
|
||||
c.RenderArgs["title"] = c.Message("register")
|
||||
c.RenderArgs["subTitle"] = c.Message("register")
|
||||
c.ViewArgs["title"] = c.Message("register")
|
||||
c.ViewArgs["subTitle"] = c.Message("register")
|
||||
return c.RenderTemplate("home/register.html")
|
||||
}
|
||||
func (c Auth) DoRegister(email, pwd, iu string) revel.Result {
|
||||
@@ -145,22 +145,22 @@ func (c Auth) DoRegister(email, pwd, iu string) revel.Result {
|
||||
// 找回密码
|
||||
func (c Auth) FindPassword() revel.Result {
|
||||
c.SetLocale()
|
||||
c.RenderArgs["title"] = c.Message("findPassword")
|
||||
c.RenderArgs["subTitle"] = c.Message("findPassword")
|
||||
c.ViewArgs["title"] = c.Message("findPassword")
|
||||
c.ViewArgs["subTitle"] = c.Message("findPassword")
|
||||
return c.RenderTemplate("home/find_password.html")
|
||||
}
|
||||
func (c Auth) DoFindPassword(email string) revel.Result {
|
||||
pwdService.FindPwd(email)
|
||||
re := info.NewRe()
|
||||
re.Ok = true
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 点击链接后, 先验证之
|
||||
func (c Auth) FindPassword2(token string) revel.Result {
|
||||
c.SetLocale()
|
||||
c.RenderArgs["title"] = c.Message("findPassword")
|
||||
c.RenderArgs["subTitle"] = c.Message("findPassword")
|
||||
c.ViewArgs["title"] = c.Message("findPassword")
|
||||
c.ViewArgs["subTitle"] = c.Message("findPassword")
|
||||
if token == "" {
|
||||
return c.RenderTemplate("find_password2_timeout.html")
|
||||
}
|
||||
@@ -168,10 +168,10 @@ func (c Auth) FindPassword2(token string) revel.Result {
|
||||
if !ok {
|
||||
return c.RenderTemplate("home/find_password2_timeout.html")
|
||||
}
|
||||
c.RenderArgs["findPwd"] = findPwd
|
||||
c.ViewArgs["findPwd"] = findPwd
|
||||
|
||||
c.RenderArgs["title"] = c.Message("updatePassword")
|
||||
c.RenderArgs["subTitle"] = c.Message("updatePassword")
|
||||
c.ViewArgs["title"] = c.Message("updatePassword")
|
||||
c.ViewArgs["subTitle"] = c.Message("updatePassword")
|
||||
|
||||
return c.RenderTemplate("home/find_password2.html")
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func (c *BaseController) Message(message string, args ...interface{}) (value str
|
||||
|
||||
func (c BaseController) GetUserId() string {
|
||||
if userId, ok := c.Session["UserId"]; ok {
|
||||
return userId
|
||||
return userId.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -47,51 +47,30 @@ func (c BaseController) GetObjectUserId() bson.ObjectId {
|
||||
|
||||
func (c BaseController) GetEmail() string {
|
||||
if email, ok := c.Session["Email"]; ok {
|
||||
return email
|
||||
return email.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c BaseController) GetUsername() string {
|
||||
if email, ok := c.Session["Username"]; ok {
|
||||
return email
|
||||
return email.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 得到用户信息
|
||||
func (c BaseController) GetUserInfo() info.User {
|
||||
if userId, ok := c.Session["UserId"]; ok && userId != "" {
|
||||
userId := c.GetUserId()
|
||||
if userId != "" {
|
||||
return userService.GetUserInfo(userId)
|
||||
/*
|
||||
notebookWidth, _ := strconv.Atoi(c.Session["NotebookWidth"])
|
||||
noteListWidth, _ := strconv.Atoi(c.Session["NoteListWidth"])
|
||||
mdEditorWidth, _ := strconv.Atoi(c.Session["MdEditorWidth"])
|
||||
LogJ(c.Session)
|
||||
user := info.User{UserId: bson.ObjectIdHex(userId),
|
||||
Email: c.Session["Email"],
|
||||
Logo: c.Session["Logo"],
|
||||
Username: c.Session["Username"],
|
||||
UsernameRaw: c.Session["UsernameRaw"],
|
||||
Theme: c.Session["Theme"],
|
||||
NotebookWidth: notebookWidth,
|
||||
NoteListWidth: noteListWidth,
|
||||
MdEditorWidth: mdEditorWidth,
|
||||
}
|
||||
if c.Session["Verified"] == "1" {
|
||||
user.Verified = true
|
||||
}
|
||||
if c.Session["LeftIsMin"] == "1" {
|
||||
user.LeftIsMin = true
|
||||
}
|
||||
return user
|
||||
*/
|
||||
}
|
||||
return info.User{}
|
||||
}
|
||||
|
||||
func (c BaseController) GetUserAndBlogUrl() info.UserAndBlogUrl {
|
||||
if userId, ok := c.Session["UserId"]; ok && userId != "" {
|
||||
userId := c.GetUserId()
|
||||
if userId != "" {
|
||||
return userService.GetUserAndBlogUrl(userId)
|
||||
}
|
||||
return info.UserAndBlogUrl{}
|
||||
@@ -103,7 +82,7 @@ func (c BaseController) GetSession(key string) string {
|
||||
if !ok {
|
||||
v = ""
|
||||
}
|
||||
return v
|
||||
return v.(string)
|
||||
}
|
||||
func (c BaseController) SetSession(userInfo info.User) {
|
||||
if userInfo.UserId.Hex() != "" {
|
||||
@@ -180,7 +159,7 @@ func (c BaseController) GetTotalPage(page, count int) int {
|
||||
|
||||
//-------------
|
||||
func (c BaseController) E404() revel.Result {
|
||||
c.RenderArgs["title"] = "404"
|
||||
c.ViewArgs["title"] = "404"
|
||||
return c.NotFound("", nil)
|
||||
}
|
||||
|
||||
@@ -199,12 +178,12 @@ func (c BaseController) SetLocale() string {
|
||||
if !i18n.HasLang(locale) {
|
||||
lang = i18n.GetDefaultLang()
|
||||
}
|
||||
c.RenderArgs["locale"] = lang
|
||||
c.RenderArgs["siteUrl"] = configService.GetSiteUrl()
|
||||
c.ViewArgs["locale"] = lang
|
||||
c.ViewArgs["siteUrl"] = configService.GetSiteUrl()
|
||||
|
||||
c.RenderArgs["blogUrl"] = configService.GetBlogUrl()
|
||||
c.RenderArgs["leaUrl"] = configService.GetLeaUrl()
|
||||
c.RenderArgs["noteUrl"] = configService.GetNoteUrl()
|
||||
c.ViewArgs["blogUrl"] = configService.GetBlogUrl()
|
||||
c.ViewArgs["leaUrl"] = configService.GetLeaUrl()
|
||||
c.ViewArgs["noteUrl"] = configService.GetNoteUrl()
|
||||
|
||||
return lang
|
||||
}
|
||||
@@ -212,9 +191,9 @@ func (c BaseController) SetLocale() string {
|
||||
// 设置userInfo
|
||||
func (c BaseController) SetUserInfo() info.User {
|
||||
userInfo := c.GetUserInfo()
|
||||
c.RenderArgs["userInfo"] = userInfo
|
||||
c.ViewArgs["userInfo"] = userInfo
|
||||
if userInfo.Username == configService.GetAdminUsername() {
|
||||
c.RenderArgs["isAdmin"] = true
|
||||
c.ViewArgs["isAdmin"] = true
|
||||
}
|
||||
return userInfo
|
||||
}
|
||||
@@ -230,11 +209,11 @@ func (c BaseController) RenderTemplateStr(templatePath string) string {
|
||||
|
||||
tpl := &revel.RenderTemplateResult{
|
||||
Template: template,
|
||||
RenderArgs: c.RenderArgs, // 把args给它
|
||||
ViewArgs: c.ViewArgs, // 把args给它
|
||||
}
|
||||
|
||||
var buffer bytes.Buffer
|
||||
tpl.Template.Render(&buffer, c.RenderArgs)
|
||||
tpl.Template.Render(&buffer, c.ViewArgs)
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
@@ -263,5 +242,5 @@ func (c BaseController) RenderRe(re info.Re) revel.Result {
|
||||
if strings.HasPrefix(re.Msg, "???") {
|
||||
re.Msg = oldMsg
|
||||
}
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
// "encoding/json"
|
||||
"fmt"
|
||||
"github.com/leanote/leanote/app/info"
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
// . "github.com/leanote/leanote/app/lea"
|
||||
"github.com/leanote/leanote/app/lea/blog"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
// "github.com/leanote/leanote/app/types"
|
||||
@@ -49,8 +49,8 @@ $.bootstrapJsUrl
|
||||
|
||||
func (c Blog) render(templateName string, themePath string) revel.Result {
|
||||
isPreview := false
|
||||
if c.RenderArgs["isPreview"] != nil {
|
||||
themePath2 := c.RenderArgs["themePath"]
|
||||
if c.ViewArgs["isPreview"] != nil {
|
||||
themePath2 := c.ViewArgs["themePath"]
|
||||
if themePath2 == nil {
|
||||
return c.E404()
|
||||
}
|
||||
@@ -59,9 +59,9 @@ func (c Blog) render(templateName string, themePath string) revel.Result {
|
||||
c.setPreviewUrl()
|
||||
|
||||
// 因为common的themeInfo是从UserBlog.ThemeId来取的, 所以这里要fugai下
|
||||
c.RenderArgs["themeInfo"] = c.RenderArgs["themeInfoPreview"]
|
||||
c.ViewArgs["themeInfo"] = c.ViewArgs["themeInfoPreview"]
|
||||
}
|
||||
return blog.RenderTemplate(templateName, c.RenderArgs, revel.BasePath+"/"+themePath, isPreview)
|
||||
return blog.RenderTemplate(templateName, c.ViewArgs, revel.BasePath+"/"+themePath, isPreview)
|
||||
}
|
||||
|
||||
// 404
|
||||
@@ -77,7 +77,7 @@ func (c Blog) e404(themePath string) revel.Result {
|
||||
// life.leanote.com
|
||||
// lealife.com
|
||||
func (c Blog) domain() (ok bool, userBlog info.UserBlog) {
|
||||
host := c.Request.Request.Host // a.cc.com:9000
|
||||
host := c.Request.Host // a.cc.com:9000
|
||||
hostArr := strings.Split(host, ".")
|
||||
if strings.Contains(host, configService.GetDefaultDomain()) {
|
||||
// 有二级域名 a.leanoe.com 3个
|
||||
@@ -110,7 +110,7 @@ func (c Blog) setPreviewUrl() {
|
||||
if username != "" {
|
||||
userIdOrEmail = username
|
||||
}
|
||||
themeId := c.Session["themeId"]
|
||||
themeId := c.GetSession("themeId")
|
||||
theme := themeService.GetTheme(userId, themeId)
|
||||
|
||||
// siteUrl := configService.GetSiteUrl()
|
||||
@@ -125,19 +125,19 @@ func (c Blog) setPreviewUrl() {
|
||||
archiveUrl = blogUrl + "/archives/" + userIdOrEmail // blog.leanote.com/archive/userId
|
||||
tagsUrl = blogUrl + "/tags/" + userIdOrEmail // blog.leanote.com/archive/userId
|
||||
|
||||
c.RenderArgs["indexUrl"] = indexUrl
|
||||
c.RenderArgs["cateUrl"] = cateUrl
|
||||
c.RenderArgs["postUrl"] = postUrl
|
||||
c.RenderArgs["searchUrl"] = searchUrl
|
||||
c.RenderArgs["singleUrl"] = singleUrl // 单页
|
||||
c.RenderArgs["archiveUrl"] = archiveUrl
|
||||
c.RenderArgs["archivesUrl"] = archiveUrl // 别名
|
||||
c.RenderArgs["tagsUrl"] = tagsUrl
|
||||
c.RenderArgs["tagPostsUrl"] = blogUrl + "/tag/" + userIdOrEmail
|
||||
c.RenderArgs["tagUrl"] = c.RenderArgs["tagPostsUrl"]
|
||||
c.ViewArgs["indexUrl"] = indexUrl
|
||||
c.ViewArgs["cateUrl"] = cateUrl
|
||||
c.ViewArgs["postUrl"] = postUrl
|
||||
c.ViewArgs["searchUrl"] = searchUrl
|
||||
c.ViewArgs["singleUrl"] = singleUrl // 单页
|
||||
c.ViewArgs["archiveUrl"] = archiveUrl
|
||||
c.ViewArgs["archivesUrl"] = archiveUrl // 别名
|
||||
c.ViewArgs["tagsUrl"] = tagsUrl
|
||||
c.ViewArgs["tagPostsUrl"] = blogUrl + "/tag/" + userIdOrEmail
|
||||
c.ViewArgs["tagUrl"] = c.ViewArgs["tagPostsUrl"]
|
||||
|
||||
// themeBaseUrl 本theme的路径url, 可以加载js, css, images之类的
|
||||
c.RenderArgs["themeBaseUrl"] = "/" + theme.Path
|
||||
c.ViewArgs["themeBaseUrl"] = "/" + theme.Path
|
||||
}
|
||||
|
||||
// 各种地址设置
|
||||
@@ -152,36 +152,36 @@ func (c Blog) setUrl(userBlog info.UserBlog, userInfo info.User) {
|
||||
// 分类
|
||||
// 搜索
|
||||
// 查看
|
||||
c.RenderArgs["siteUrl"] = siteUrl
|
||||
c.RenderArgs["indexUrl"] = blogUrls.IndexUrl
|
||||
c.RenderArgs["cateUrl"] = blogUrls.CateUrl
|
||||
c.RenderArgs["postUrl"] = blogUrls.PostUrl
|
||||
c.RenderArgs["searchUrl"] = blogUrls.SearchUrl
|
||||
c.RenderArgs["singleUrl"] = blogUrls.SingleUrl // 单页
|
||||
c.RenderArgs["archiveUrl"] = blogUrls.ArchiveUrl
|
||||
c.RenderArgs["archivesUrl"] = blogUrls.ArchiveUrl // 别名
|
||||
c.RenderArgs["tagsUrl"] = blogUrls.TagsUrl
|
||||
c.RenderArgs["tagPostsUrl"] = blogUrls.TagPostsUrl
|
||||
c.RenderArgs["tagUrl"] = blogUrls.TagPostsUrl // 别名
|
||||
c.ViewArgs["siteUrl"] = siteUrl
|
||||
c.ViewArgs["indexUrl"] = blogUrls.IndexUrl
|
||||
c.ViewArgs["cateUrl"] = blogUrls.CateUrl
|
||||
c.ViewArgs["postUrl"] = blogUrls.PostUrl
|
||||
c.ViewArgs["searchUrl"] = blogUrls.SearchUrl
|
||||
c.ViewArgs["singleUrl"] = blogUrls.SingleUrl // 单页
|
||||
c.ViewArgs["archiveUrl"] = blogUrls.ArchiveUrl
|
||||
c.ViewArgs["archivesUrl"] = blogUrls.ArchiveUrl // 别名
|
||||
c.ViewArgs["tagsUrl"] = blogUrls.TagsUrl
|
||||
c.ViewArgs["tagPostsUrl"] = blogUrls.TagPostsUrl
|
||||
c.ViewArgs["tagUrl"] = blogUrls.TagPostsUrl // 别名
|
||||
|
||||
// themeBaseUrl 本theme的路径url, 可以加载js, css, images之类的
|
||||
c.RenderArgs["themeBaseUrl"] = "/" + userBlog.ThemePath
|
||||
c.ViewArgs["themeBaseUrl"] = "/" + userBlog.ThemePath
|
||||
|
||||
// 其它static js
|
||||
c.RenderArgs["jQueryUrl"] = "/js/jquery-1.9.0.min.js"
|
||||
c.ViewArgs["jQueryUrl"] = "/js/jquery-1.9.0.min.js"
|
||||
|
||||
c.RenderArgs["prettifyJsUrl"] = "/js/google-code-prettify/prettify.js"
|
||||
c.RenderArgs["prettifyCssUrl"] = "/js/google-code-prettify/prettify.css"
|
||||
c.ViewArgs["prettifyJsUrl"] = "/js/google-code-prettify/prettify.js"
|
||||
c.ViewArgs["prettifyCssUrl"] = "/js/google-code-prettify/prettify.css"
|
||||
|
||||
c.RenderArgs["blogCommonJsUrl"] = "/public/blog/js/common.js"
|
||||
c.ViewArgs["blogCommonJsUrl"] = "/public/blog/js/common.js"
|
||||
|
||||
c.RenderArgs["shareCommentCssUrl"] = "/public/blog/css/share_comment.css"
|
||||
c.RenderArgs["shareCommentJsUrl"] = "/public/blog/js/share_comment.js"
|
||||
c.ViewArgs["shareCommentCssUrl"] = "/public/blog/css/share_comment.css"
|
||||
c.ViewArgs["shareCommentJsUrl"] = "/public/blog/js/share_comment.js"
|
||||
|
||||
c.RenderArgs["fontAwesomeUrl"] = "/css/font-awesome-4.2.0/css/font-awesome.css"
|
||||
c.ViewArgs["fontAwesomeUrl"] = "/css/font-awesome-4.2.0/css/font-awesome.css"
|
||||
|
||||
c.RenderArgs["bootstrapCssUrl"] = "/css/bootstrap.css"
|
||||
c.RenderArgs["bootstrapJsUrl"] = "/js/bootstrap-min.js"
|
||||
c.ViewArgs["bootstrapCssUrl"] = "/css/bootstrap.css"
|
||||
c.ViewArgs["bootstrapJsUrl"] = "/js/bootstrap-min.js"
|
||||
}
|
||||
|
||||
// 笔记本分类
|
||||
@@ -265,8 +265,8 @@ func (c Blog) getCates(userBlog info.UserBlog) {
|
||||
}
|
||||
}
|
||||
|
||||
c.RenderArgs["cates"] = cates
|
||||
c.RenderArgs["catesTree"] = catesTree
|
||||
c.ViewArgs["cates"] = cates
|
||||
c.ViewArgs["catesTree"] = catesTree
|
||||
}
|
||||
|
||||
// 单页
|
||||
@@ -281,7 +281,7 @@ func (c Blog) getSingles(userId string) {
|
||||
singles2[i] = map[string]string{"title": page["Title"], "singleId": page["SingleId"]}
|
||||
}
|
||||
*/
|
||||
c.RenderArgs["singles"] = singles
|
||||
c.ViewArgs["singles"] = singles
|
||||
}
|
||||
|
||||
// $.blog = {userId, title, subTitle, desc, openComment, }
|
||||
@@ -300,11 +300,11 @@ func (c Blog) setBlog(userBlog info.UserBlog, userInfo info.User) {
|
||||
"SubDomain": userBlog.SubDomain,
|
||||
"Domain": userBlog.Domain,
|
||||
}
|
||||
c.RenderArgs["blogInfo"] = blogInfo
|
||||
c.ViewArgs["blogInfo"] = blogInfo
|
||||
}
|
||||
|
||||
func (c Blog) setPaging(pageInfo info.Page) {
|
||||
c.RenderArgs["paging"] = pageInfo
|
||||
c.ViewArgs["paging"] = pageInfo
|
||||
}
|
||||
|
||||
// 公共
|
||||
@@ -315,13 +315,13 @@ func (c Blog) blogCommon(userId string, userBlog info.UserBlog, userInfo info.Us
|
||||
return false, userBlog
|
||||
}
|
||||
}
|
||||
// c.RenderArgs["userInfo"] = userInfo
|
||||
// c.ViewArgs["userInfo"] = userInfo
|
||||
|
||||
// 最新笔记
|
||||
_, recentBlogs := blogService.ListBlogs(userId, "", 1, 5, userBlog.SortField, userBlog.IsAsc)
|
||||
c.RenderArgs["recentPosts"] = blogService.FixBlogs(recentBlogs)
|
||||
c.RenderArgs["latestPosts"] = c.RenderArgs["recentPosts"]
|
||||
c.RenderArgs["tags"] = blogService.GetBlogTags(userId)
|
||||
c.ViewArgs["recentPosts"] = blogService.FixBlogs(recentBlogs)
|
||||
c.ViewArgs["latestPosts"] = c.ViewArgs["recentPosts"]
|
||||
c.ViewArgs["tags"] = blogService.GetBlogTags(userId)
|
||||
|
||||
// 语言, url地址
|
||||
c.SetLocale()
|
||||
@@ -331,7 +331,7 @@ func (c Blog) blogCommon(userId string, userBlog info.UserBlog, userInfo info.Us
|
||||
userBlog = blogService.GetUserBlog(userId)
|
||||
}
|
||||
c.setBlog(userBlog, userInfo)
|
||||
// c.RenderArgs["userBlog"] = userBlog
|
||||
// c.ViewArgs["userBlog"] = userBlog
|
||||
|
||||
// 分类导航
|
||||
c.getCates(userBlog)
|
||||
@@ -342,12 +342,12 @@ func (c Blog) blogCommon(userId string, userBlog info.UserBlog, userInfo info.Us
|
||||
c.setUrl(userBlog, userInfo)
|
||||
|
||||
// 当前分类Id, 全设为""
|
||||
c.RenderArgs["curCateId"] = ""
|
||||
c.RenderArgs["curSingleId"] = ""
|
||||
c.ViewArgs["curCateId"] = ""
|
||||
c.ViewArgs["curSingleId"] = ""
|
||||
|
||||
// 得到主题信息
|
||||
themeInfo := themeService.GetThemeInfo(userBlog.ThemeId.Hex(), userBlog.Style)
|
||||
c.RenderArgs["themeInfo"] = themeInfo
|
||||
c.ViewArgs["themeInfo"] = themeInfo
|
||||
|
||||
// Log(">>")
|
||||
// Log(userBlog.Style)
|
||||
@@ -404,9 +404,9 @@ func (c Blog) Tags(userIdOrEmail string) (re revel.Result) {
|
||||
return c.e404(userBlog.ThemePath) // 404 TODO 使用用户的404
|
||||
}
|
||||
|
||||
c.RenderArgs["curIsTags"] = true
|
||||
c.ViewArgs["curIsTags"] = true
|
||||
tags := blogService.GetBlogTags(userId)
|
||||
c.RenderArgs["tags"] = tags
|
||||
c.ViewArgs["tags"] = tags
|
||||
return c.render("tags.html", userBlog.ThemePath)
|
||||
}
|
||||
|
||||
@@ -443,15 +443,15 @@ func (c Blog) Tag(userIdOrEmail, tag string) (re revel.Result) {
|
||||
tag = userIdOrEmail
|
||||
}
|
||||
|
||||
c.RenderArgs["curIsTagPosts"] = true
|
||||
c.RenderArgs["curTag"] = tag
|
||||
c.ViewArgs["curIsTagPosts"] = true
|
||||
c.ViewArgs["curTag"] = tag
|
||||
page := c.GetPage()
|
||||
pageInfo, blogs := blogService.SearchBlogByTags([]string{tag}, userId, page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc)
|
||||
c.setPaging(pageInfo)
|
||||
|
||||
c.RenderArgs["posts"] = blogService.FixBlogs(blogs)
|
||||
tagPostsUrl := c.RenderArgs["tagPostsUrl"].(string)
|
||||
c.RenderArgs["pagingBaseUrl"] = tagPostsUrl + "/" + tag
|
||||
c.ViewArgs["posts"] = blogService.FixBlogs(blogs)
|
||||
tagPostsUrl := c.ViewArgs["tagPostsUrl"].(string)
|
||||
c.ViewArgs["pagingBaseUrl"] = tagPostsUrl + "/" + tag
|
||||
|
||||
return c.render("tag_posts.html", userBlog.ThemePath)
|
||||
}
|
||||
@@ -490,16 +490,16 @@ func (c Blog) Archives(userIdOrEmail string, cateId string, year, month int) (re
|
||||
}
|
||||
|
||||
arcs := blogService.ListBlogsArchive(userId, notebookId, year, month, "PublicTime", false)
|
||||
c.RenderArgs["archives"] = arcs
|
||||
c.ViewArgs["archives"] = arcs
|
||||
|
||||
c.RenderArgs["curIsArchive"] = true
|
||||
c.ViewArgs["curIsArchive"] = true
|
||||
if notebookId != "" {
|
||||
notebook := notebookService.GetNotebookById(notebookId)
|
||||
c.RenderArgs["curCateTitle"] = notebook.Title
|
||||
c.RenderArgs["curCateId"] = notebookId
|
||||
c.ViewArgs["curCateTitle"] = notebook.Title
|
||||
c.ViewArgs["curCateId"] = notebookId
|
||||
}
|
||||
c.RenderArgs["curYear"] = year
|
||||
c.RenderArgs["curMonth"] = month
|
||||
c.ViewArgs["curYear"] = year
|
||||
c.ViewArgs["curMonth"] = month
|
||||
|
||||
return c.render("archive.html", userBlog.ThemePath)
|
||||
}
|
||||
@@ -541,15 +541,15 @@ func (c Blog) Cate(userIdOrEmail string, notebookId string) (re revel.Result) {
|
||||
page := c.GetPage()
|
||||
pageInfo, blogs := blogService.ListBlogs(userId, notebookId2, page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc)
|
||||
blogs2 := blogService.FixBlogs(blogs)
|
||||
c.RenderArgs["posts"] = blogs2
|
||||
c.ViewArgs["posts"] = blogs2
|
||||
|
||||
c.setPaging(pageInfo)
|
||||
|
||||
c.RenderArgs["curCateTitle"] = notebook.Title
|
||||
c.RenderArgs["curCateId"] = notebookId2
|
||||
cateUrl := c.RenderArgs["cateUrl"].(string)
|
||||
c.RenderArgs["pagingBaseUrl"] = cateUrl + "/" + notebookId
|
||||
c.RenderArgs["curIsCate"] = true
|
||||
c.ViewArgs["curCateTitle"] = notebook.Title
|
||||
c.ViewArgs["curCateId"] = notebookId2
|
||||
cateUrl := c.ViewArgs["cateUrl"].(string)
|
||||
c.ViewArgs["pagingBaseUrl"] = cateUrl + "/" + notebookId
|
||||
c.ViewArgs["curIsCate"] = true
|
||||
|
||||
return c.render("cate.html", userBlog.ThemePath)
|
||||
}
|
||||
@@ -594,12 +594,12 @@ func (c Blog) Index(userIdOrEmail string) (re revel.Result) {
|
||||
page := c.GetPage()
|
||||
pageInfo, blogs := blogService.ListBlogs(userId, "", page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc)
|
||||
blogs2 := blogService.FixBlogs(blogs)
|
||||
c.RenderArgs["posts"] = blogs2
|
||||
c.ViewArgs["posts"] = blogs2
|
||||
|
||||
c.setPaging(pageInfo)
|
||||
c.RenderArgs["pagingBaseUrl"] = c.RenderArgs["indexUrl"]
|
||||
c.ViewArgs["pagingBaseUrl"] = c.ViewArgs["indexUrl"]
|
||||
|
||||
c.RenderArgs["curIsIndex"] = true
|
||||
c.ViewArgs["curIsIndex"] = true
|
||||
|
||||
return c.render("index.html", userBlog.ThemePath)
|
||||
}
|
||||
@@ -609,7 +609,7 @@ func (c Blog) Post(userIdOrEmail, noteId string) (re revel.Result) {
|
||||
hasDomain, userBlog := c.domain()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
Log(err)
|
||||
// Log(err)
|
||||
re = c.e404(userBlog.ThemePath)
|
||||
}
|
||||
}()
|
||||
@@ -631,9 +631,9 @@ func (c Blog) Post(userIdOrEmail, noteId string) (re revel.Result) {
|
||||
}
|
||||
|
||||
post := blogService.FixBlog(blogInfo)
|
||||
c.RenderArgs["post"] = post
|
||||
// c.RenderArgs["userInfo"] = userInfo
|
||||
c.RenderArgs["curIsPost"] = true
|
||||
c.ViewArgs["post"] = post
|
||||
// c.ViewArgs["userInfo"] = userInfo
|
||||
c.ViewArgs["curIsPost"] = true
|
||||
|
||||
// 上一篇, 下一篇
|
||||
var baseTime interface{}
|
||||
@@ -649,10 +649,10 @@ func (c Blog) Post(userIdOrEmail, noteId string) (re revel.Result) {
|
||||
|
||||
prePost, nextPost := blogService.PreNextBlog(userId, userBlog.SortField, userBlog.IsAsc, post.NoteId, baseTime)
|
||||
if prePost.NoteId != "" {
|
||||
c.RenderArgs["prePost"] = prePost
|
||||
c.ViewArgs["prePost"] = prePost
|
||||
}
|
||||
if nextPost.NoteId != "" {
|
||||
c.RenderArgs["nextPost"] = nextPost
|
||||
c.ViewArgs["nextPost"] = nextPost
|
||||
}
|
||||
return c.render("post.html", userBlog.ThemePath)
|
||||
}
|
||||
@@ -682,7 +682,7 @@ func (c Blog) Single(userIdOrEmail, singleId string) (re revel.Result) {
|
||||
panic("")
|
||||
}
|
||||
|
||||
c.RenderArgs["single"] = map[string]interface{}{
|
||||
c.ViewArgs["single"] = map[string]interface{}{
|
||||
"SingleId": single.SingleId.Hex(),
|
||||
"Title": single.Title,
|
||||
"UrlTitle": single.UrlTitle,
|
||||
@@ -690,8 +690,8 @@ func (c Blog) Single(userIdOrEmail, singleId string) (re revel.Result) {
|
||||
"CreatedTime": single.CreatedTime,
|
||||
"UpdatedTime": single.UpdatedTime,
|
||||
}
|
||||
c.RenderArgs["curSingleId"] = single.SingleId.Hex()
|
||||
c.RenderArgs["curIsSingle"] = true
|
||||
c.ViewArgs["curSingleId"] = single.SingleId.Hex()
|
||||
c.ViewArgs["curIsSingle"] = true
|
||||
|
||||
return c.render("single.html", userBlog.ThemePath)
|
||||
}
|
||||
@@ -716,7 +716,7 @@ func (c Blog) Search(userIdOrEmail, keywords string) (re revel.Result) {
|
||||
} else {
|
||||
userInfo = userService.GetUserInfoByAny(userIdOrEmail)
|
||||
}
|
||||
// c.RenderArgs["userInfo"] = userInfo
|
||||
// c.ViewArgs["userInfo"] = userInfo
|
||||
userId = userInfo.UserId.Hex()
|
||||
var ok = false
|
||||
if ok, userBlog = c.blogCommon(userId, userBlog, userInfo); !ok {
|
||||
@@ -727,11 +727,11 @@ func (c Blog) Search(userIdOrEmail, keywords string) (re revel.Result) {
|
||||
pageInfo, blogs := blogService.SearchBlog(keywords, userId, page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc)
|
||||
c.setPaging(pageInfo)
|
||||
|
||||
c.RenderArgs["posts"] = blogService.FixBlogs(blogs)
|
||||
c.RenderArgs["keywords"] = keywords
|
||||
searchUrl, _ := c.RenderArgs["searchUrl"].(string)
|
||||
c.RenderArgs["pagingBaseUrl"] = searchUrl + "?keywords=" + keywords
|
||||
c.RenderArgs["curIsSearch"] = true
|
||||
c.ViewArgs["posts"] = blogService.FixBlogs(blogs)
|
||||
c.ViewArgs["keywords"] = keywords
|
||||
searchUrl, _ := c.ViewArgs["searchUrl"].(string)
|
||||
c.ViewArgs["pagingBaseUrl"] = searchUrl + "?keywords=" + keywords
|
||||
c.ViewArgs["curIsSearch"] = true
|
||||
|
||||
return c.render("search.html", userBlog.ThemePath)
|
||||
}
|
||||
@@ -741,7 +741,7 @@ func (c Blog) setRenderUserInfo(userInfo info.User) {
|
||||
if userInfo.Username == "" {
|
||||
userInfo.Username = userInfo.Email
|
||||
}
|
||||
c.RenderArgs["userInfo"] = userInfo
|
||||
c.ViewArgs["userInfo"] = userInfo
|
||||
}
|
||||
|
||||
//----------------
|
||||
@@ -753,7 +753,7 @@ func (c Blog) GetPostStat(noteId string) revel.Result {
|
||||
re.Ok = true
|
||||
statInfo := blogService.GetBlogStat(noteId)
|
||||
re.Item = statInfo
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// jsonP
|
||||
@@ -778,7 +778,7 @@ func (c Blog) GetLikes(noteId string, callback string) revel.Result {
|
||||
result["hasMoreLikedUser"] = hasMoreLikedUser
|
||||
|
||||
re.Item = result
|
||||
return c.RenderJsonP(callback, re)
|
||||
return c.RenderJSONP(callback, re)
|
||||
}
|
||||
func (c Blog) GetLikesAndComments(noteId, callback string) revel.Result {
|
||||
userId := c.GetUserId()
|
||||
@@ -806,13 +806,13 @@ func (c Blog) GetLikesAndComments(noteId, callback string) revel.Result {
|
||||
result["comments"] = comments
|
||||
result["commentUserInfo"] = commentUserInfo
|
||||
re.Item = result
|
||||
return c.RenderJsonP(callback, re)
|
||||
return c.RenderJSONP(callback, re)
|
||||
}
|
||||
|
||||
func (c Blog) IncReadNum(noteId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.IncReadNum(noteId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 点赞, 要用jsonp
|
||||
@@ -820,7 +820,7 @@ func (c Blog) LikePost(noteId string, callback string) revel.Result {
|
||||
re := info.NewRe()
|
||||
userId := c.GetUserId()
|
||||
re.Ok, re.Item = blogService.LikeBlog(noteId, userId)
|
||||
return c.RenderJsonP(callback, re)
|
||||
return c.RenderJSONP(callback, re)
|
||||
}
|
||||
func (c Blog) GetComments(noteId string, callback string) revel.Result {
|
||||
// 评论
|
||||
@@ -836,24 +836,24 @@ func (c Blog) GetComments(noteId string, callback string) revel.Result {
|
||||
re.Item = result
|
||||
|
||||
if callback != "" {
|
||||
return c.RenderJsonP(callback, result)
|
||||
return c.RenderJSONP(callback, result)
|
||||
}
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// jsonp
|
||||
func (c Blog) DeleteComment(noteId, commentId string, callback string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.DeleteComment(noteId, commentId, c.GetUserId())
|
||||
return c.RenderJsonP(callback, re)
|
||||
return c.RenderJSONP(callback, re)
|
||||
}
|
||||
|
||||
// jsonp
|
||||
func (c Blog) CommentPost(noteId, content, toCommentId string, callback string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Item = blogService.Comment(noteId, toCommentId, c.GetUserId(), content)
|
||||
return c.RenderJsonP(callback, re)
|
||||
return c.RenderJSONP(callback, re)
|
||||
}
|
||||
|
||||
// jsonp
|
||||
@@ -862,7 +862,7 @@ func (c Blog) LikeComment(commentId string, callback string) revel.Result {
|
||||
ok, isILikeIt, num := blogService.LikeComment(commentId, c.GetUserId())
|
||||
re.Ok = ok
|
||||
re.Item = bson.M{"IsILikeIt": isILikeIt, "Num": num}
|
||||
return c.RenderJsonP(callback, re)
|
||||
return c.RenderJSONP(callback, re)
|
||||
}
|
||||
|
||||
// 显示分类的最近博客, jsonp
|
||||
@@ -898,5 +898,5 @@ func (c Blog) ListCateLatest(notebookId, callback string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = true
|
||||
re.List = blogs
|
||||
return c.RenderJsonP(callback, re)
|
||||
return c.RenderJSONP(callback, re)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
// "path"
|
||||
// "strconv"
|
||||
"net/http"
|
||||
"io"
|
||||
)
|
||||
|
||||
// 验证码服务
|
||||
@@ -30,9 +31,10 @@ func (r Ca) Apply(req *revel.Request, resp *revel.Response) {
|
||||
func (c Captcha) Get() revel.Result {
|
||||
c.Response.ContentType = "image/png"
|
||||
image, str := captcha.Fetch()
|
||||
image.WriteTo(c.Response.Out)
|
||||
out := io.Writer(c.Response.GetWriter())
|
||||
image.WriteTo(out)
|
||||
|
||||
sessionId := c.Session["_ID"]
|
||||
sessionId := c.GetSession("_ID")
|
||||
// LogJ(c.Session)
|
||||
// Log("------")
|
||||
// Log(str)
|
||||
|
||||
@@ -24,9 +24,9 @@ type File struct {
|
||||
func (c File) UploadBlogLogo() revel.Result {
|
||||
re := c.uploadImage("blogLogo", "")
|
||||
|
||||
c.RenderArgs["fileUrlPath"] = re.Id
|
||||
c.RenderArgs["resultCode"] = re.Code
|
||||
c.RenderArgs["resultMsg"] = re.Msg
|
||||
c.ViewArgs["fileUrlPath"] = re.Id
|
||||
c.ViewArgs["resultCode"] = re.Code
|
||||
c.ViewArgs["resultMsg"] = re.Msg
|
||||
|
||||
return c.RenderTemplate("file/blog_logo.html")
|
||||
}
|
||||
@@ -54,16 +54,16 @@ func (c File) PasteImage(noteId string) revel.Result {
|
||||
}
|
||||
}
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 头像设置
|
||||
func (c File) UploadAvatar() revel.Result {
|
||||
re := c.uploadImage("logo", "")
|
||||
|
||||
c.RenderArgs["fileUrlPath"] = re.Id
|
||||
c.RenderArgs["resultCode"] = re.Code
|
||||
c.RenderArgs["resultMsg"] = re.Msg
|
||||
c.ViewArgs["fileUrlPath"] = re.Id
|
||||
c.ViewArgs["resultCode"] = re.Code
|
||||
c.ViewArgs["resultMsg"] = re.Msg
|
||||
|
||||
if re.Ok {
|
||||
re.Ok = userService.UpdateAvatar(c.GetUserId(), re.Id)
|
||||
@@ -72,13 +72,13 @@ func (c File) UploadAvatar() revel.Result {
|
||||
}
|
||||
}
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// leaui image plugin upload image
|
||||
func (c File) UploadImageLeaui(albumId string) revel.Result {
|
||||
re := c.uploadImage("", albumId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 上传图片, 公用方法
|
||||
@@ -97,11 +97,27 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
||||
re.Ok = Ok
|
||||
}()
|
||||
|
||||
file, handel, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
// file, handel, err := c.Request.FormFile("file")
|
||||
// if err != nil {
|
||||
// return re
|
||||
// }
|
||||
// defer file.Close()
|
||||
|
||||
var data []byte
|
||||
c.Params.Bind(&data, "file")
|
||||
handel := c.Params.Files["file"][0]
|
||||
if data == nil || len(data) == 0 {
|
||||
return re
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// file, handel, err := c.Request.FormFile("file")
|
||||
// if err != nil {
|
||||
// return re
|
||||
// }
|
||||
// defer file.Close()
|
||||
|
||||
// data, err := ioutil.ReadAll(file)
|
||||
|
||||
|
||||
// 生成上传路径
|
||||
newGuid := NewGuid()
|
||||
@@ -116,7 +132,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
||||
}
|
||||
|
||||
dir := revel.BasePath + "/" + fileUrlPath
|
||||
err = os.MkdirAll(dir, 0755)
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
if err != nil {
|
||||
return re
|
||||
}
|
||||
@@ -136,11 +152,11 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
||||
}
|
||||
|
||||
filename = newGuid + ext
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
LogJ(err)
|
||||
return re
|
||||
}
|
||||
// data, err := ioutil.ReadAll(file)
|
||||
// if err != nil {
|
||||
// LogJ(err)
|
||||
// return re
|
||||
// }
|
||||
|
||||
var maxFileSize float64
|
||||
if from == "logo" {
|
||||
@@ -201,19 +217,19 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
||||
// get all images by userId with page
|
||||
func (c File) GetImages(albumId, key string, page int) revel.Result {
|
||||
re := fileService.ListImagesWithPage(c.GetUserId(), albumId, key, page, 12)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c File) UpdateImageTitle(fileId, title string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = fileService.UpdateImageTitle(c.GetUserId(), fileId, title)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c File) DeleteImage(fileId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Msg = fileService.DeleteImage(c.GetUserId(), fileId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
//-----------
|
||||
@@ -235,7 +251,7 @@ func (c File) OutputImage(noteId, fileId string) revel.Result {
|
||||
func (c File) CopyImage(userId, fileId, toUserId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 复制外网的图片
|
||||
@@ -251,13 +267,13 @@ func (c File) CopyHttpImage(src string) revel.Result {
|
||||
dir := revel.BasePath + "/" + fileUrlPath
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
if err != nil {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
filesize, filename, _, ok := netutil.WriteUrl(src, dir)
|
||||
|
||||
if !ok {
|
||||
re.Msg = "copy error"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// File
|
||||
@@ -273,5 +289,5 @@ func (c File) CopyHttpImage(src string) revel.Result {
|
||||
// re.Item = fileInfo.Path
|
||||
re.Ok, re.Msg = fileService.AddImage(fileInfo, "", c.GetUserId(), true)
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ func (c Index) Default() revel.Result {
|
||||
// leanote展示页, 没有登录的, 或已登录明确要进该页的
|
||||
func (c Index) Index() revel.Result {
|
||||
c.SetUserInfo()
|
||||
c.RenderArgs["title"] = "leanote"
|
||||
c.RenderArgs["openRegister"] = configService.GlobalStringConfigs["openRegister"]
|
||||
c.ViewArgs["title"] = "leanote"
|
||||
c.ViewArgs["openRegister"] = configService.GlobalStringConfigs["openRegister"]
|
||||
c.SetLocale()
|
||||
|
||||
return c.RenderTemplate("home/index.html")
|
||||
@@ -40,5 +40,5 @@ func (c Index) Suggestion(addr, suggestion string) revel.Result {
|
||||
emailService.SendEmail("leanote@leanote.com", "建议", "UserId: "+c.GetUserId()+" <br /> Suggestions: "+suggestion)
|
||||
}()
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
@@ -12,5 +12,5 @@ type NoteContentHistory struct {
|
||||
func (c NoteContentHistory) ListHistories(noteId string) revel.Result {
|
||||
histories := noteContentHistoryService.ListHistories(noteId, c.GetUserId())
|
||||
|
||||
return c.RenderJson(histories)
|
||||
return c.RenderJSON(histories)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
"runtime"
|
||||
// "github.com/leanote/leanote/app/types"
|
||||
// "io/ioutil"
|
||||
"fmt"
|
||||
@@ -36,7 +37,7 @@ func (c Note) Index(noteId, online string) revel.Result {
|
||||
return c.Redirect("/login")
|
||||
}
|
||||
|
||||
c.RenderArgs["openRegister"] = configService.IsOpenRegister()
|
||||
c.ViewArgs["openRegister"] = configService.IsOpenRegister()
|
||||
|
||||
// 已登录了, 那么得到所有信息
|
||||
notebooks := notebookService.GetNotebooks(userId)
|
||||
@@ -58,16 +59,16 @@ func (c Note) Index(noteId, online string) revel.Result {
|
||||
noteContent = noteService.GetNoteContent(noteId, noteOwner)
|
||||
|
||||
hasRightNoteId = true
|
||||
c.RenderArgs["curNoteId"] = noteId
|
||||
c.RenderArgs["curNotebookId"] = note.NotebookId.Hex()
|
||||
c.ViewArgs["curNoteId"] = noteId
|
||||
c.ViewArgs["curNotebookId"] = note.NotebookId.Hex()
|
||||
|
||||
// 打开的是共享的笔记, 那么判断是否是共享给我的默认笔记
|
||||
if noteOwner != c.GetUserId() {
|
||||
if shareService.HasReadPerm(noteOwner, c.GetUserId(), noteId) {
|
||||
// 不要获取notebook下的笔记
|
||||
// 在前端下发请求
|
||||
c.RenderArgs["curSharedNoteNotebookId"] = note.NotebookId.Hex()
|
||||
c.RenderArgs["curSharedUserId"] = noteOwner
|
||||
c.ViewArgs["curSharedNoteNotebookId"] = note.NotebookId.Hex()
|
||||
c.ViewArgs["curSharedUserId"] = noteOwner
|
||||
// 没有读写权限
|
||||
} else {
|
||||
hasRightNoteId = false
|
||||
@@ -97,7 +98,7 @@ func (c Note) Index(noteId, online string) revel.Result {
|
||||
|
||||
// 得到最近的笔记
|
||||
_, latestNotes := noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false)
|
||||
c.RenderArgs["latestNotes"] = latestNotes
|
||||
c.ViewArgs["latestNotes"] = latestNotes
|
||||
}
|
||||
|
||||
// 没有传入笔记
|
||||
@@ -106,27 +107,27 @@ func (c Note) Index(noteId, online string) revel.Result {
|
||||
_, notes = noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false)
|
||||
if len(notes) > 0 {
|
||||
noteContent = noteService.GetNoteContent(notes[0].NoteId.Hex(), userId)
|
||||
c.RenderArgs["curNoteId"] = notes[0].NoteId.Hex()
|
||||
c.ViewArgs["curNoteId"] = notes[0].NoteId.Hex()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 当然, 还需要得到第一个notes的content
|
||||
//...
|
||||
c.RenderArgs["isAdmin"] = configService.GetAdminUsername() == userInfo.Username
|
||||
c.ViewArgs["isAdmin"] = configService.GetAdminUsername() == userInfo.Username
|
||||
|
||||
c.RenderArgs["userInfo"] = userInfo
|
||||
c.RenderArgs["notebooks"] = notebooks
|
||||
c.RenderArgs["shareNotebooks"] = shareNotebooks // note信息在notes列表中
|
||||
c.RenderArgs["sharedUserInfos"] = sharedUserInfos
|
||||
c.ViewArgs["userInfo"] = userInfo
|
||||
c.ViewArgs["notebooks"] = notebooks
|
||||
c.ViewArgs["shareNotebooks"] = shareNotebooks // note信息在notes列表中
|
||||
c.ViewArgs["sharedUserInfos"] = sharedUserInfos
|
||||
|
||||
c.RenderArgs["notes"] = notes
|
||||
c.RenderArgs["noteContentJson"] = noteContent
|
||||
c.RenderArgs["noteContent"] = noteContent.Content
|
||||
c.ViewArgs["notes"] = notes
|
||||
c.ViewArgs["noteContentJson"] = noteContent
|
||||
c.ViewArgs["noteContent"] = noteContent.Content
|
||||
|
||||
c.RenderArgs["tags"] = tagService.GetTags(c.GetUserId())
|
||||
c.ViewArgs["tags"] = tagService.GetTags(c.GetUserId())
|
||||
|
||||
c.RenderArgs["globalConfigs"] = configService.GetGlobalConfigForUser()
|
||||
c.ViewArgs["globalConfigs"] = configService.GetGlobalConfigForUser()
|
||||
|
||||
// return c.RenderTemplate("note/note.html")
|
||||
|
||||
@@ -142,18 +143,18 @@ func (c Note) Index(noteId, online string) revel.Result {
|
||||
// 否则, 转向登录页面
|
||||
func (c Note) ListNotes(notebookId string) revel.Result {
|
||||
_, notes := noteService.ListNotes(c.GetUserId(), notebookId, false, c.GetPage(), pageSize, defaultSortField, false, false)
|
||||
return c.RenderJson(notes)
|
||||
return c.RenderJSON(notes)
|
||||
}
|
||||
|
||||
// 得到trash
|
||||
func (c Note) ListTrashNotes() revel.Result {
|
||||
_, notes := noteService.ListNotes(c.GetUserId(), "", true, c.GetPage(), pageSize, defaultSortField, false, false)
|
||||
return c.RenderJson(notes)
|
||||
return c.RenderJSON(notes)
|
||||
}
|
||||
|
||||
// 得到note和内容
|
||||
func (c Note) GetNoteAndContent(noteId string) revel.Result {
|
||||
return c.RenderJson(noteService.GetNoteAndContent(noteId, c.GetUserId()))
|
||||
return c.RenderJSON(noteService.GetNoteAndContent(noteId, c.GetUserId()))
|
||||
}
|
||||
|
||||
func (c Note) GetNoteAndContentBySrc(src string) revel.Result {
|
||||
@@ -163,13 +164,13 @@ func (c Note) GetNoteAndContentBySrc(src string) revel.Result {
|
||||
ret.Ok = true
|
||||
ret.Item = noteAndContent
|
||||
}
|
||||
return c.RenderJson(ret)
|
||||
return c.RenderJSON(ret)
|
||||
}
|
||||
|
||||
// 得到内容
|
||||
func (c Note) GetNoteContent(noteId string) revel.Result {
|
||||
noteContent := noteService.GetNoteContent(noteId, c.GetUserId())
|
||||
return c.RenderJson(noteContent)
|
||||
return c.RenderJSON(noteContent)
|
||||
}
|
||||
|
||||
// 这里不能用json, 要用post
|
||||
@@ -201,7 +202,7 @@ func (c Note) UpdateNoteOrContent(noteOrContent info.NoteOrContent) revel.Result
|
||||
Abstract: noteOrContent.Abstract}
|
||||
|
||||
note = noteService.AddNoteAndContentForController(note, noteContent, c.GetUserId())
|
||||
return c.RenderJson(note)
|
||||
return c.RenderJSON(note)
|
||||
}
|
||||
|
||||
noteUpdate := bson.M{}
|
||||
@@ -233,22 +234,23 @@ func (c Note) UpdateNoteOrContent(noteOrContent info.NoteOrContent) revel.Result
|
||||
}
|
||||
|
||||
//-------------
|
||||
afterContentUsn := 0
|
||||
contentOk := false
|
||||
contentMsg := ""
|
||||
// afterContentUsn := 0
|
||||
// contentOk := false
|
||||
// contentMsg := ""
|
||||
if c.Has("Content") {
|
||||
// noteService.UpdateNoteContent(noteOrContent.UserId, c.GetUserId(),
|
||||
// noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract)
|
||||
contentOk, contentMsg, afterContentUsn = noteService.UpdateNoteContent(c.GetUserId(),
|
||||
// contentOk, contentMsg, afterContentUsn =
|
||||
noteService.UpdateNoteContent(c.GetUserId(),
|
||||
noteOrContent.NoteId, noteOrContent.Content, noteOrContent.Abstract,
|
||||
needUpdateNote, -1, time.Now())
|
||||
}
|
||||
|
||||
Log(afterContentUsn)
|
||||
Log(contentOk)
|
||||
Log(contentMsg)
|
||||
// Log("usn", "afterContentUsn", afterContentUsn + "")
|
||||
// Log(contentOk)
|
||||
// Log(contentMsg)
|
||||
|
||||
return c.RenderJson(true)
|
||||
return c.RenderJSON(true)
|
||||
}
|
||||
|
||||
// 删除note/ 删除别人共享给我的笔记
|
||||
@@ -258,19 +260,19 @@ func (c Note) DeleteNote(noteIds []string, isShared bool) revel.Result {
|
||||
for _, noteId := range noteIds {
|
||||
trashService.DeleteNote(noteId, c.GetUserId())
|
||||
}
|
||||
return c.RenderJson(true)
|
||||
return c.RenderJSON(true)
|
||||
}
|
||||
|
||||
for _, noteId := range noteIds {
|
||||
trashService.DeleteSharedNote(noteId, c.GetUserId())
|
||||
}
|
||||
|
||||
return c.RenderJson(true)
|
||||
return c.RenderJSON(true)
|
||||
}
|
||||
|
||||
// 删除trash, 已弃用, 用DeleteNote
|
||||
func (c Note) DeleteTrash(noteId string) revel.Result {
|
||||
return c.RenderJson(trashService.DeleteTrash(noteId, c.GetUserId()))
|
||||
return c.RenderJSON(trashService.DeleteTrash(noteId, c.GetUserId()))
|
||||
}
|
||||
|
||||
// 移动note
|
||||
@@ -279,7 +281,7 @@ func (c Note) MoveNote(noteIds []string, notebookId string) revel.Result {
|
||||
for _, noteId := range noteIds {
|
||||
noteService.MoveNote(noteId, notebookId, userId)
|
||||
}
|
||||
return c.RenderJson(true)
|
||||
return c.RenderJSON(true)
|
||||
}
|
||||
|
||||
// 复制note
|
||||
@@ -292,7 +294,7 @@ func (c Note) CopyNote(noteIds []string, notebookId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = true
|
||||
re.Item = copyNotes
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 复制别人共享的笔记给我
|
||||
@@ -305,7 +307,7 @@ func (c Note) CopySharedNote(noteIds []string, notebookId, fromUserId string) re
|
||||
re := info.NewRe()
|
||||
re.Ok = true
|
||||
re.Item = copyNotes
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
//------------
|
||||
@@ -313,13 +315,13 @@ func (c Note) CopySharedNote(noteIds []string, notebookId, fromUserId string) re
|
||||
// 通过title搜索
|
||||
func (c Note) SearchNote(key string) revel.Result {
|
||||
_, blogs := noteService.SearchNote(key, c.GetUserId(), c.GetPage(), pageSize, "UpdatedTime", false, false)
|
||||
return c.RenderJson(blogs)
|
||||
return c.RenderJSON(blogs)
|
||||
}
|
||||
|
||||
// 通过tags搜索
|
||||
func (c Note) SearchNoteByTags(tags []string) revel.Result {
|
||||
_, blogs := noteService.SearchNoteByTags(tags, c.GetUserId(), c.GetPage(), pageSize, "UpdatedTime", false)
|
||||
return c.RenderJson(blogs)
|
||||
return c.RenderJSON(blogs)
|
||||
}
|
||||
|
||||
// 生成PDF
|
||||
@@ -397,11 +399,11 @@ func (c Note) ToPdf(noteId, appKey string) revel.Result {
|
||||
} else {
|
||||
note.Tags = nil
|
||||
}
|
||||
c.RenderArgs["blog"] = note
|
||||
c.RenderArgs["content"] = contentStr
|
||||
c.RenderArgs["userInfo"] = userInfo
|
||||
c.ViewArgs["blog"] = note
|
||||
c.ViewArgs["content"] = contentStr
|
||||
c.ViewArgs["userInfo"] = userInfo
|
||||
userBlog := blogService.GetUserBlog(noteUserId)
|
||||
c.RenderArgs["userBlog"] = userBlog
|
||||
c.ViewArgs["userBlog"] = userBlog
|
||||
|
||||
return c.RenderTemplate("file/pdf.html")
|
||||
}
|
||||
@@ -446,7 +448,11 @@ func (c Note) ExportPdf(noteId string) revel.Result {
|
||||
binPath := configService.GetGlobalStringConfig("exportPdfBinPath")
|
||||
// 默认路径
|
||||
if binPath == "" {
|
||||
binPath = "/usr/local/bin/wkhtmltopdf"
|
||||
if runtime.GOOS == "windows" {
|
||||
binPath = `C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe`
|
||||
} else {
|
||||
binPath = "/usr/local/bin/wkhtmltopdf"
|
||||
}
|
||||
}
|
||||
|
||||
url := configService.GetSiteUrl() + "/note/toPdf?noteId=" + noteId + "&appKey=" + appKey
|
||||
@@ -456,13 +462,29 @@ func (c Note) ExportPdf(noteId string) revel.Result {
|
||||
// http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf_0.10.0_rc2-doc.html
|
||||
// wkhtmltopdf参数大全
|
||||
var cc string
|
||||
// var cc []string
|
||||
var ccWindows []string
|
||||
if note.IsMarkdown {
|
||||
cc = binPath + " --lowquality --window-status done \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\""
|
||||
// cc = []string{binPath, "--lowquality", "--window-status", "done", "\"" + url + "\"", "\"" + path + "\""}
|
||||
ccWindows = []string{"/C", binPath, "--lowquality", "--window-status", "done", url, path}
|
||||
} else {
|
||||
cc = binPath + " --lowquality \"" + url + "\" \"" + path + "\"" // \"" + cookieDomain + "\" \"" + cookieName + "\" \"" + cookieValue + "\""
|
||||
// cc = []string{binPath, "--lowquality", "\"" + url + "\"", "\"" + path + "\""}
|
||||
ccWindows = []string{"/C", binPath, "--lowquality", url, path}
|
||||
}
|
||||
|
||||
cmd := exec.Command("/bin/sh", "-c", cc)
|
||||
var cmd *exec.Cmd
|
||||
|
||||
// fmt.Println("-------1", runtime.GOOS, ccWindows)
|
||||
if runtime.GOOS == "windows" {
|
||||
fmt.Println(ccWindows)
|
||||
// cmd = exec.Command("cmd", ccWindows...)
|
||||
cmd = exec.Command(ccWindows[1], ccWindows[2:]...)
|
||||
} else {
|
||||
fmt.Println(cc)
|
||||
cmd = exec.Command("/bin/sh", "-c", cc)
|
||||
}
|
||||
_, err := cmd.Output()
|
||||
if err != nil {
|
||||
return c.RenderText("export pdf error. " + fmt.Sprintf("%v", err))
|
||||
@@ -488,5 +510,5 @@ func (c Note) SetNote2Blog(noteIds []string, isBlog, isTop bool) revel.Result {
|
||||
for _, noteId := range noteIds {
|
||||
noteService.ToBlog(c.GetUserId(), noteId, isBlog, isTop)
|
||||
}
|
||||
return c.RenderJson(true)
|
||||
return c.RenderJSON(true)
|
||||
}
|
||||
|
||||
@@ -14,18 +14,18 @@ type Notebook struct {
|
||||
}
|
||||
|
||||
func (c Notebook) Index(notebook info.Notebook, i int, name string) revel.Result {
|
||||
return c.RenderJson(notebook)
|
||||
return c.RenderJSON(notebook)
|
||||
}
|
||||
|
||||
// 得到用户的所有笔记本
|
||||
func (c Notebook) GetNotebooks() revel.Result {
|
||||
re := notebookService.GetNotebooks(c.GetUserId())
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c Notebook) DeleteNotebook(notebookId string) revel.Result {
|
||||
re, msg := notebookService.DeleteNotebook(c.GetUserId(), notebookId)
|
||||
return c.RenderJson(info.Re{Ok: re, Msg: msg})
|
||||
return c.RenderJSON(info.Re{Ok: re, Msg: msg})
|
||||
}
|
||||
|
||||
// 添加notebook
|
||||
@@ -41,21 +41,21 @@ func (c Notebook) AddNotebook(notebookId, title, parentNotebookId string) revel.
|
||||
re, notebook := notebookService.AddNotebook(notebook)
|
||||
|
||||
if re {
|
||||
return c.RenderJson(notebook)
|
||||
return c.RenderJSON(notebook)
|
||||
} else {
|
||||
return c.RenderJson(false)
|
||||
return c.RenderJSON(false)
|
||||
}
|
||||
}
|
||||
|
||||
// 修改标题
|
||||
func (c Notebook) UpdateNotebookTitle(notebookId, title string) revel.Result {
|
||||
return c.RenderJson(notebookService.UpdateNotebookTitle(notebookId, c.GetUserId(), title))
|
||||
return c.RenderJSON(notebookService.UpdateNotebookTitle(notebookId, c.GetUserId(), title))
|
||||
}
|
||||
|
||||
// 排序
|
||||
// 无用
|
||||
// func (c Notebook) SortNotebooks(notebookId2Seqs map[string]int) revel.Result {
|
||||
// return c.RenderJson(notebookService.SortNotebooks(c.GetUserId(), notebookId2Seqs))
|
||||
// return c.RenderJSON(notebookService.SortNotebooks(c.GetUserId(), notebookId2Seqs))
|
||||
// }
|
||||
|
||||
// 调整notebooks, 可能是排序, 可能是移动到其它笔记本下
|
||||
@@ -70,11 +70,11 @@ func (c Notebook) DragNotebooks(data string) revel.Result {
|
||||
info := DragNotebooksInfo{}
|
||||
json.Unmarshal([]byte(data), &info)
|
||||
|
||||
return c.RenderJson(notebookService.DragNotebooks(c.GetUserId(), info.CurNotebookId, info.ParentNotebookId, info.Siblings))
|
||||
return c.RenderJSON(notebookService.DragNotebooks(c.GetUserId(), info.CurNotebookId, info.ParentNotebookId, info.Siblings))
|
||||
}
|
||||
|
||||
// 设置notebook <-> blog
|
||||
func (c Notebook) SetNotebook2Blog(notebookId string, isBlog bool) revel.Result {
|
||||
re := notebookService.ToBlog(c.GetUserId(), notebookId, isBlog)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
@@ -25,17 +25,17 @@ func (c Preview) getPreviewThemeAbsolutePath(themeId string) bool {
|
||||
if themeId != "" {
|
||||
c.Session["themeId"] = themeId // 存到session中, 下次的url就不能带了, 待优化, 有时会取不到
|
||||
} else {
|
||||
themeId = c.Session["themeId"] // 直接从session中获取
|
||||
themeId = c.GetSession("themeId") // 直接从session中获取
|
||||
}
|
||||
if themeId == "" {
|
||||
return false
|
||||
}
|
||||
theme := themeService.GetTheme(c.GetUserId(), themeId)
|
||||
|
||||
c.RenderArgs["isPreview"] = true
|
||||
c.RenderArgs["themeId"] = themeId
|
||||
c.RenderArgs["themeInfoPreview"] = theme.Info
|
||||
c.RenderArgs["themePath"] = theme.Path
|
||||
c.ViewArgs["isPreview"] = true
|
||||
c.ViewArgs["themeId"] = themeId
|
||||
c.ViewArgs["themeInfoPreview"] = theme.Info
|
||||
c.ViewArgs["themePath"] = theme.Path
|
||||
if theme.Path == "" {
|
||||
return false
|
||||
}
|
||||
@@ -47,7 +47,7 @@ func (c Preview) Index(userIdOrEmail string, themeId string) revel.Result {
|
||||
return c.E404()
|
||||
}
|
||||
return c.Blog.Index(c.GetUserId())
|
||||
// return blog.RenderTemplate("index.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(themeId))
|
||||
// return blog.RenderTemplate("index.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(themeId))
|
||||
}
|
||||
|
||||
func (c Preview) Tag(userIdOrEmail, tag string) revel.Result {
|
||||
@@ -62,42 +62,42 @@ func (c Preview) Tags(userIdOrEmail string) revel.Result {
|
||||
}
|
||||
return c.Blog.Tags(c.GetUserId())
|
||||
// if tag == "" {
|
||||
// return blog.RenderTemplate("tags.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
// return blog.RenderTemplate("tags.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
// }
|
||||
// return blog.RenderTemplate("tag_posts.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
// return blog.RenderTemplate("tag_posts.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
}
|
||||
func (c Preview) Archives(userIdOrEmail string, notebookId string, year, month int) revel.Result {
|
||||
if !c.getPreviewThemeAbsolutePath("") {
|
||||
return c.E404()
|
||||
}
|
||||
return c.Blog.Archives(c.GetUserId(), notebookId, year, month)
|
||||
// return blog.RenderTemplate("archive.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
// return blog.RenderTemplate("archive.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
}
|
||||
func (c Preview) Cate(userIdOrEmail, notebookId string) revel.Result {
|
||||
if !c.getPreviewThemeAbsolutePath("") {
|
||||
return c.E404()
|
||||
}
|
||||
return c.Blog.Cate(userIdOrEmail, notebookId)
|
||||
// return blog.RenderTemplate("cate.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
// return blog.RenderTemplate("cate.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
}
|
||||
func (c Preview) Post(userIdOrEmail, noteId string) revel.Result {
|
||||
if !c.getPreviewThemeAbsolutePath("") {
|
||||
return c.E404()
|
||||
}
|
||||
return c.Blog.Post(userIdOrEmail, noteId)
|
||||
// return blog.RenderTemplate("view.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
// return blog.RenderTemplate("view.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
}
|
||||
func (c Preview) Single(userIdOrEmail, singleId string) revel.Result {
|
||||
if !c.getPreviewThemeAbsolutePath("") {
|
||||
return c.E404()
|
||||
}
|
||||
return c.Blog.Single(userIdOrEmail, singleId)
|
||||
// return blog.RenderTemplate("single.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
// return blog.RenderTemplate("single.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
}
|
||||
func (c Preview) Search(userIdOrEmail, keywords string) revel.Result {
|
||||
if !c.getPreviewThemeAbsolutePath("") {
|
||||
return c.E404()
|
||||
}
|
||||
return c.Blog.Search(c.GetUserId(), keywords)
|
||||
// return blog.RenderTemplate("search.html", c.RenderArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
// return blog.RenderTemplate("search.html", c.ViewArgs, c.getPreviewThemeAbsolutePath(""))
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func (c Share) AddShareNote(noteId string, emails []string, perm int) revel.Resu
|
||||
}
|
||||
}
|
||||
|
||||
return c.RenderJson(status)
|
||||
return c.RenderJSON(status)
|
||||
}
|
||||
|
||||
// 添加共享notebook
|
||||
@@ -53,7 +53,7 @@ func (c Share) AddShareNotebook(notebookId string, emails []string, perm int) re
|
||||
}
|
||||
}
|
||||
|
||||
return c.RenderJson(status)
|
||||
return c.RenderJSON(status)
|
||||
}
|
||||
|
||||
// 得到notes
|
||||
@@ -63,10 +63,10 @@ func (c Share) ListShareNotes(notebookId, userId string) revel.Result {
|
||||
var notes []info.ShareNoteWithPerm
|
||||
if notebookId == "" {
|
||||
notes = shareService.ListShareNotes(c.GetUserId(), userId, c.GetPage(), pageSize, defaultSortField, false)
|
||||
return c.RenderJson(notes)
|
||||
return c.RenderJSON(notes)
|
||||
} else {
|
||||
// 有notebookId的
|
||||
return c.RenderJson(shareService.ListShareNotesByNotebookId(notebookId, c.GetUserId(), userId, c.GetPage(), pageSize, defaultSortField, false))
|
||||
return c.RenderJSON(shareService.ListShareNotesByNotebookId(notebookId, c.GetUserId(), userId, c.GetPage(), pageSize, defaultSortField, false))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func (c Share) ListShareNotes(notebookId, userId string) revel.Result {
|
||||
// sharedUserId 是谁的笔记
|
||||
func (c Share) GetShareNoteContent(noteId, sharedUserId string) revel.Result {
|
||||
noteContent := shareService.GetShareNoteContent(noteId, c.GetUserId(), sharedUserId)
|
||||
return c.RenderJson(noteContent)
|
||||
return c.RenderJSON(noteContent)
|
||||
}
|
||||
|
||||
// 查看note的分享信息
|
||||
@@ -85,13 +85,13 @@ func (c Share) ListNoteShareUserInfo(noteId string) revel.Result {
|
||||
note := noteService.GetNote(noteId, c.GetUserId())
|
||||
|
||||
noteShareUserInfos := shareService.ListNoteShareUserInfo(noteId, c.GetUserId())
|
||||
c.RenderArgs["noteOrNotebookShareUserInfos"] = noteShareUserInfos
|
||||
c.ViewArgs["noteOrNotebookShareUserInfos"] = noteShareUserInfos
|
||||
|
||||
c.RenderArgs["noteOrNotebookShareGroupInfos"] = shareService.GetNoteShareGroups(noteId, c.GetUserId())
|
||||
c.ViewArgs["noteOrNotebookShareGroupInfos"] = shareService.GetNoteShareGroups(noteId, c.GetUserId())
|
||||
|
||||
c.RenderArgs["isNote"] = true
|
||||
c.RenderArgs["noteOrNotebookId"] = note.NoteId.Hex()
|
||||
c.RenderArgs["title"] = note.Title
|
||||
c.ViewArgs["isNote"] = true
|
||||
c.ViewArgs["noteOrNotebookId"] = note.NoteId.Hex()
|
||||
c.ViewArgs["title"] = note.Title
|
||||
|
||||
return c.RenderTemplate("share/note_notebook_share_user_infos.html")
|
||||
}
|
||||
@@ -99,14 +99,14 @@ func (c Share) ListNotebookShareUserInfo(notebookId string) revel.Result {
|
||||
notebook := notebookService.GetNotebook(notebookId, c.GetUserId())
|
||||
|
||||
notebookShareUserInfos := shareService.ListNotebookShareUserInfo(notebookId, c.GetUserId())
|
||||
c.RenderArgs["noteOrNotebookShareUserInfos"] = notebookShareUserInfos
|
||||
c.ViewArgs["noteOrNotebookShareUserInfos"] = notebookShareUserInfos
|
||||
|
||||
c.RenderArgs["noteOrNotebookShareGroupInfos"] = shareService.GetNotebookShareGroups(notebookId, c.GetUserId())
|
||||
LogJ(c.RenderArgs["noteOrNotebookShareGroupInfos"])
|
||||
c.ViewArgs["noteOrNotebookShareGroupInfos"] = shareService.GetNotebookShareGroups(notebookId, c.GetUserId())
|
||||
LogJ(c.ViewArgs["noteOrNotebookShareGroupInfos"])
|
||||
|
||||
c.RenderArgs["isNote"] = false
|
||||
c.RenderArgs["noteOrNotebookId"] = notebook.NotebookId.Hex()
|
||||
c.RenderArgs["title"] = notebook.Title
|
||||
c.ViewArgs["isNote"] = false
|
||||
c.ViewArgs["noteOrNotebookId"] = notebook.NotebookId.Hex()
|
||||
c.ViewArgs["title"] = notebook.Title
|
||||
|
||||
return c.RenderTemplate("share/note_notebook_share_user_infos.html")
|
||||
}
|
||||
@@ -114,38 +114,38 @@ func (c Share) ListNotebookShareUserInfo(notebookId string) revel.Result {
|
||||
//------------
|
||||
// 改变share note 权限
|
||||
func (c Share) UpdateShareNotePerm(noteId string, perm int, toUserId string) revel.Result {
|
||||
return c.RenderJson(shareService.UpdateShareNotePerm(noteId, perm, c.GetUserId(), toUserId))
|
||||
return c.RenderJSON(shareService.UpdateShareNotePerm(noteId, perm, c.GetUserId(), toUserId))
|
||||
}
|
||||
|
||||
// 改变share notebook 权限
|
||||
func (c Share) UpdateShareNotebookPerm(notebookId string, perm int, toUserId string) revel.Result {
|
||||
return c.RenderJson(shareService.UpdateShareNotebookPerm(notebookId, perm, c.GetUserId(), toUserId))
|
||||
return c.RenderJSON(shareService.UpdateShareNotebookPerm(notebookId, perm, c.GetUserId(), toUserId))
|
||||
}
|
||||
|
||||
//---------------
|
||||
// 删除share note
|
||||
func (c Share) DeleteShareNote(noteId string, toUserId string) revel.Result {
|
||||
return c.RenderJson(shareService.DeleteShareNote(noteId, c.GetUserId(), toUserId))
|
||||
return c.RenderJSON(shareService.DeleteShareNote(noteId, c.GetUserId(), toUserId))
|
||||
}
|
||||
|
||||
// 删除share notebook
|
||||
func (c Share) DeleteShareNotebook(notebookId string, toUserId string) revel.Result {
|
||||
return c.RenderJson(shareService.DeleteShareNotebook(notebookId, c.GetUserId(), toUserId))
|
||||
return c.RenderJSON(shareService.DeleteShareNotebook(notebookId, c.GetUserId(), toUserId))
|
||||
}
|
||||
|
||||
// 删除share note, 被共享方删除
|
||||
func (c Share) DeleteShareNoteBySharedUser(noteId string, fromUserId string) revel.Result {
|
||||
return c.RenderJson(shareService.DeleteShareNote(noteId, fromUserId, c.GetUserId()))
|
||||
return c.RenderJSON(shareService.DeleteShareNote(noteId, fromUserId, c.GetUserId()))
|
||||
}
|
||||
|
||||
// 删除share notebook, 被共享方删除
|
||||
func (c Share) DeleteShareNotebookBySharedUser(notebookId string, fromUserId string) revel.Result {
|
||||
return c.RenderJson(shareService.DeleteShareNotebook(notebookId, fromUserId, c.GetUserId()))
|
||||
return c.RenderJSON(shareService.DeleteShareNotebook(notebookId, fromUserId, c.GetUserId()))
|
||||
}
|
||||
|
||||
// 删除fromUserId分享给我的所有note, notebook
|
||||
func (c Share) DeleteUserShareNoteAndNotebook(fromUserId string) revel.Result {
|
||||
return c.RenderJson(shareService.DeleteUserShareNoteAndNotebook(fromUserId, c.GetUserId()))
|
||||
return c.RenderJSON(shareService.DeleteUserShareNoteAndNotebook(fromUserId, c.GetUserId()))
|
||||
}
|
||||
|
||||
//-------------
|
||||
@@ -155,14 +155,14 @@ func (c Share) DeleteUserShareNoteAndNotebook(fromUserId string) revel.Result {
|
||||
func (c Share) AddShareNoteGroup(noteId, groupId string, perm int) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = shareService.AddShareNoteGroup(c.GetUserId(), noteId, groupId, perm)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 删除
|
||||
func (c Share) DeleteShareNoteGroup(noteId, groupId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = shareService.DeleteShareNoteGroup(c.GetUserId(), noteId, groupId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 更新, 也是一样, 先删后加
|
||||
@@ -176,14 +176,14 @@ func (c Share) UpdateShareNoteGroupPerm(noteId, groupId string, perm int) revel.
|
||||
func (c Share) AddShareNotebookGroup(notebookId, groupId string, perm int) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = shareService.AddShareNotebookGroup(c.GetUserId(), notebookId, groupId, perm)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 删除
|
||||
func (c Share) DeleteShareNotebookGroup(notebookId, groupId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = shareService.DeleteShareNotebookGroup(c.GetUserId(), notebookId, groupId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 更新, 也是一样, 先删后加
|
||||
|
||||
@@ -18,7 +18,7 @@ func (c Tag) UpdateTag(tag string) revel.Result {
|
||||
ret := info.NewRe()
|
||||
ret.Ok = true
|
||||
ret.Item = tagService.AddOrUpdateTag(c.GetUserId(), tag)
|
||||
return c.RenderJson(ret)
|
||||
return c.RenderJSON(ret)
|
||||
}
|
||||
|
||||
// 删除标签
|
||||
@@ -26,5 +26,5 @@ func (c Tag) DeleteTag(tag string) revel.Result {
|
||||
ret := info.Re{}
|
||||
ret.Ok = true
|
||||
ret.Item = tagService.DeleteTag(c.GetUserId(), tag)
|
||||
return c.RenderJson(ret)
|
||||
return c.RenderJSON(ret)
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ type User struct {
|
||||
|
||||
func (c User) Account(tab int) revel.Result {
|
||||
userInfo := c.GetUserInfo()
|
||||
c.RenderArgs["userInfo"] = userInfo
|
||||
c.RenderArgs["tab"] = tab
|
||||
c.ViewArgs["userInfo"] = userInfo
|
||||
c.ViewArgs["tab"] = tab
|
||||
c.SetLocale()
|
||||
return c.RenderTemplate("user/account.html")
|
||||
}
|
||||
@@ -70,18 +70,18 @@ func (c User) UpdateTheme(theme string) revel.Result {
|
||||
if re.Ok {
|
||||
c.UpdateSession("Theme", theme)
|
||||
}
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 发送邀请链接
|
||||
func (c User) SendRegisterEmail(content, toEmail string) revel.Result {
|
||||
re := info.NewRe()
|
||||
if content == "" || !IsEmail(toEmail) {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
re.Ok = emailService.SendInviteEmail(c.GetUserInfo(), toEmail, content)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
@@ -90,7 +90,7 @@ func (c User) SendRegisterEmail(content, toEmail string) revel.Result {
|
||||
func (c User) ReSendActiveEmail() revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = emailService.RegisterSendActiveEmail(c.GetUserInfo(), c.GetEmail())
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 通过点击链接
|
||||
@@ -100,10 +100,10 @@ func (c User) UpdateEmail(token string) revel.Result {
|
||||
|
||||
ok, msg, email := userService.UpdateEmail(token)
|
||||
|
||||
c.RenderArgs["title"] = "验证邮箱"
|
||||
c.RenderArgs["ok"] = ok
|
||||
c.RenderArgs["msg"] = msg
|
||||
c.RenderArgs["email"] = email
|
||||
c.ViewArgs["title"] = "验证邮箱"
|
||||
c.ViewArgs["ok"] = ok
|
||||
c.ViewArgs["msg"] = msg
|
||||
c.ViewArgs["email"] = email
|
||||
|
||||
// 修改session
|
||||
if ok {
|
||||
@@ -124,10 +124,10 @@ func (c User) ActiveEmail(token string) revel.Result {
|
||||
c.UpdateSession("Verified", "1")
|
||||
}
|
||||
|
||||
c.RenderArgs["title"] = "验证邮箱"
|
||||
c.RenderArgs["ok"] = ok
|
||||
c.RenderArgs["msg"] = msg
|
||||
c.RenderArgs["email"] = email
|
||||
c.ViewArgs["title"] = "验证邮箱"
|
||||
c.ViewArgs["ok"] = ok
|
||||
c.ViewArgs["msg"] = msg
|
||||
c.ViewArgs["email"] = email
|
||||
|
||||
return c.RenderTemplate("user/active_email.html")
|
||||
}
|
||||
@@ -144,7 +144,7 @@ func (c User) UpdateColumnWidth(notebookWidth, noteListWidth, mdEditorWidth int)
|
||||
|
||||
LogJ(c.Session)
|
||||
}
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
func (c User) UpdateLeftIsMin(leftIsMin bool) revel.Result {
|
||||
re := info.NewRe()
|
||||
@@ -156,5 +156,5 @@ func (c User) UpdateLeftIsMin(leftIsMin bool) revel.Result {
|
||||
c.UpdateSession("LeftIsMin", "0")
|
||||
}
|
||||
}
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func (c AdminBaseController) getSorter(sorterField string, isAsc bool, okSorter
|
||||
} else {
|
||||
isAsc = false
|
||||
}
|
||||
c.RenderArgs["sorter"] = sorter
|
||||
c.ViewArgs["sorter"] = sorter
|
||||
return sorterField, isAsc
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,14 @@ func (c AdminBlog) Index(sorter, keywords string) revel.Result {
|
||||
pageNumber := c.GetPage()
|
||||
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "userId", "isRecommed", "createdTime"})
|
||||
pageInfo, blogs := blogService.ListAllBlogs("", "", keywords, false, pageNumber, userPageSize, sorterField, isAsc)
|
||||
c.RenderArgs["pageInfo"] = pageInfo
|
||||
c.RenderArgs["blogs"] = blogs
|
||||
c.RenderArgs["keywords"] = keywords
|
||||
c.ViewArgs["pageInfo"] = pageInfo
|
||||
c.ViewArgs["blogs"] = blogs
|
||||
c.ViewArgs["keywords"] = keywords
|
||||
return c.RenderTemplate("admin/blog/list.html")
|
||||
}
|
||||
|
||||
func (c AdminBlog) SetRecommend(noteId string, recommend bool) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.SetRecommend(noteId, recommend)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
@@ -14,23 +14,23 @@ type Admin struct {
|
||||
func (c Admin) Index() revel.Result {
|
||||
c.SetUserInfo()
|
||||
|
||||
c.RenderArgs["title"] = "leanote"
|
||||
c.ViewArgs["title"] = "leanote"
|
||||
c.SetLocale()
|
||||
|
||||
c.RenderArgs["countUser"] = userService.CountUser()
|
||||
c.RenderArgs["countNote"] = noteService.CountNote("")
|
||||
c.RenderArgs["countBlog"] = noteService.CountBlog("")
|
||||
c.ViewArgs["countUser"] = userService.CountUser()
|
||||
c.ViewArgs["countNote"] = noteService.CountNote("")
|
||||
c.ViewArgs["countBlog"] = noteService.CountBlog("")
|
||||
|
||||
return c.RenderTemplate("admin/index.html")
|
||||
}
|
||||
|
||||
// 模板
|
||||
func (c Admin) T(t string) revel.Result {
|
||||
c.RenderArgs["str"] = configService.GlobalStringConfigs
|
||||
c.RenderArgs["arr"] = configService.GlobalArrayConfigs
|
||||
c.RenderArgs["map"] = configService.GlobalMapConfigs
|
||||
c.RenderArgs["arrMap"] = configService.GlobalArrMapConfigs
|
||||
c.RenderArgs["version"] = configService.GetVersion()
|
||||
c.ViewArgs["str"] = configService.GlobalStringConfigs
|
||||
c.ViewArgs["arr"] = configService.GlobalArrayConfigs
|
||||
c.ViewArgs["map"] = configService.GlobalMapConfigs
|
||||
c.ViewArgs["arrMap"] = configService.GlobalArrMapConfigs
|
||||
c.ViewArgs["version"] = configService.GetVersion()
|
||||
return c.RenderTemplate("admin/" + t + ".html")
|
||||
}
|
||||
|
||||
|
||||
@@ -26,33 +26,33 @@ func (c AdminData) Index() revel.Result {
|
||||
backups2[j] = backups[i]
|
||||
j++
|
||||
}
|
||||
c.RenderArgs["backups"] = backups2
|
||||
c.ViewArgs["backups"] = backups2
|
||||
return c.RenderTemplate("admin/data/index.html")
|
||||
}
|
||||
|
||||
func (c AdminData) Backup() revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Msg = configService.Backup("")
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 还原
|
||||
func (c AdminData) Restore(createdTime string) revel.Result {
|
||||
re := info.Re{}
|
||||
re.Ok, re.Msg = configService.Restore(createdTime)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c AdminData) Delete(createdTime string) revel.Result {
|
||||
re := info.Re{}
|
||||
re.Ok, re.Msg = configService.DeleteBackup(createdTime)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
func (c AdminData) UpdateRemark(createdTime, remark string) revel.Result {
|
||||
re := info.Re{}
|
||||
re.Ok, re.Msg = configService.UpdateBackupRemark(createdTime, remark)
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
func (c AdminData) Download(createdTime string) revel.Result {
|
||||
backup, ok := configService.GetBackup(createdTime)
|
||||
|
||||
@@ -23,8 +23,8 @@ func (c AdminEmail) Email() revel.Result {
|
||||
func (c AdminEmail) Blog() revel.Result {
|
||||
recommendTags := configService.GetGlobalArrayConfig("recommendTags")
|
||||
newTags := configService.GetGlobalArrayConfig("newTags")
|
||||
c.RenderArgs["recommendTags"] = strings.Join(recommendTags, ",")
|
||||
c.RenderArgs["newTags"] = strings.Join(newTags, ",")
|
||||
c.ViewArgs["recommendTags"] = strings.Join(recommendTags, ",")
|
||||
c.ViewArgs["newTags"] = strings.Join(newTags, ",")
|
||||
return c.RenderTemplate("admin/setting/blog.html")
|
||||
}
|
||||
func (c AdminEmail) DoBlogTag(recommendTags, newTags string) revel.Result {
|
||||
@@ -33,14 +33,14 @@ func (c AdminEmail) DoBlogTag(recommendTags, newTags string) revel.Result {
|
||||
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "recommendTags", strings.Split(recommendTags, ","))
|
||||
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "newTags", strings.Split(newTags, ","))
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// demo
|
||||
// blog标签设置
|
||||
func (c AdminEmail) Demo() revel.Result {
|
||||
c.RenderArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername")
|
||||
c.RenderArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword")
|
||||
c.ViewArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername")
|
||||
c.ViewArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword")
|
||||
return c.RenderTemplate("admin/setting/demo.html")
|
||||
}
|
||||
func (c AdminEmail) DoDemo(demoUsername, demoPassword string) revel.Result {
|
||||
@@ -48,30 +48,30 @@ func (c AdminEmail) DoDemo(demoUsername, demoPassword string) revel.Result {
|
||||
|
||||
userInfo, err := authService.Login(demoUsername, demoPassword)
|
||||
if err != nil {
|
||||
return c.RenderJson(info.Re{Ok: false})
|
||||
return c.RenderJSON(info.Re{Ok: false})
|
||||
}
|
||||
if userInfo.UserId == "" {
|
||||
re.Msg = "The User is Not Exists"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUserId", userInfo.UserId.Hex())
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUsername", demoUsername)
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoPassword", demoPassword)
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// ToImage
|
||||
// 长微博的bin路径phantomJs
|
||||
func (c AdminEmail) ToImage() revel.Result {
|
||||
c.RenderArgs["toImageBinPath"] = configService.GetGlobalStringConfig("toImageBinPath")
|
||||
c.ViewArgs["toImageBinPath"] = configService.GetGlobalStringConfig("toImageBinPath")
|
||||
return c.RenderTemplate("admin/setting/toImage.html")
|
||||
}
|
||||
func (c AdminEmail) DoToImage(toImageBinPath string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "toImageBinPath", toImageBinPath)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c AdminEmail) Set(emailHost, emailPort, emailUsername, emailPassword, emailSSL string) revel.Result {
|
||||
@@ -82,7 +82,7 @@ func (c AdminEmail) Set(emailHost, emailPort, emailUsername, emailPassword, emai
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "emailPassword", emailPassword)
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "emailSSL", emailSSL)
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
func (c AdminEmail) Template() revel.Result {
|
||||
re := info.NewRe()
|
||||
@@ -108,7 +108,7 @@ func (c AdminEmail) Template() revel.Result {
|
||||
if !ok {
|
||||
re.Ok = false
|
||||
re.Msg = "Error key: " + key + "<br />" + msg
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
} else {
|
||||
configService.UpdateGlobalStringConfig(userId, key, v)
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func (c AdminEmail) Template() revel.Result {
|
||||
}
|
||||
|
||||
re.Ok = true
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 发送Email
|
||||
@@ -127,7 +127,7 @@ func (c AdminEmail) SendEmailToEmails(sendEmails, latestEmailSubject, latestEmai
|
||||
|
||||
if latestEmailSubject == "" || latestEmailBody == "" {
|
||||
re.Msg = "subject or body is blank"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
if saveAsOldEmail {
|
||||
@@ -140,7 +140,7 @@ func (c AdminEmail) SendEmailToEmails(sendEmails, latestEmailSubject, latestEmai
|
||||
emails := strings.Split(sendEmails, "\n")
|
||||
|
||||
re.Ok, re.Msg = emailService.SendEmailToEmails(emails, latestEmailSubject, latestEmailBody)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 发送Email
|
||||
@@ -151,7 +151,7 @@ func (c AdminEmail) SendToUsers2(emails, latestEmailSubject, latestEmailBody str
|
||||
|
||||
if latestEmailSubject == "" || latestEmailBody == "" {
|
||||
re.Msg = "subject or body is blank"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
if saveAsOldEmail {
|
||||
@@ -168,7 +168,7 @@ func (c AdminEmail) SendToUsers2(emails, latestEmailSubject, latestEmailBody str
|
||||
|
||||
re.Ok, re.Msg = emailService.SendEmailToUsers(users, latestEmailSubject, latestEmailBody)
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// send Email dialog
|
||||
@@ -176,9 +176,9 @@ func (c AdminEmail) SendEmailDialog(emails string) revel.Result {
|
||||
emailsArr := strings.Split(emails, ",")
|
||||
emailsNl := strings.Join(emailsArr, "\n")
|
||||
|
||||
c.RenderArgs["emailsNl"] = emailsNl
|
||||
c.RenderArgs["str"] = configService.GlobalStringConfigs
|
||||
c.RenderArgs["map"] = configService.GlobalMapConfigs
|
||||
c.ViewArgs["emailsNl"] = emailsNl
|
||||
c.ViewArgs["str"] = configService.GlobalStringConfigs
|
||||
c.ViewArgs["map"] = configService.GlobalMapConfigs
|
||||
|
||||
return c.RenderTemplate("admin/email/emailDialog.html")
|
||||
}
|
||||
@@ -190,7 +190,7 @@ func (c AdminEmail) SendToUsers(userFilterEmail, userFilterWhiteList, userFilter
|
||||
|
||||
if latestEmailSubject == "" || latestEmailBody == "" {
|
||||
re.Msg = "subject or body is blank"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
if saveAsOldEmail {
|
||||
@@ -204,33 +204,33 @@ func (c AdminEmail) SendToUsers(userFilterEmail, userFilterWhiteList, userFilter
|
||||
if users == nil || len(users) == 0 {
|
||||
re.Ok = false
|
||||
re.Msg = "no users"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
re.Ok, re.Msg = emailService.SendEmailToUsers(users, latestEmailSubject, latestEmailBody)
|
||||
if !re.Ok {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
re.Ok = true
|
||||
re.Msg = "users:" + strconv.Itoa(len(users))
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 删除emails
|
||||
func (c AdminEmail) DeleteEmails(ids string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = emailService.DeleteEmails(strings.Split(ids, ","))
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c AdminEmail) List(sorter, keywords string) revel.Result {
|
||||
pageNumber := c.GetPage()
|
||||
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"email", "ok", "subject", "createdTime"})
|
||||
pageInfo, emails := emailService.ListEmailLogs(pageNumber, userPageSize, sorterField, isAsc, keywords)
|
||||
c.RenderArgs["pageInfo"] = pageInfo
|
||||
c.RenderArgs["emails"] = emails
|
||||
c.RenderArgs["keywords"] = keywords
|
||||
c.ViewArgs["pageInfo"] = pageInfo
|
||||
c.ViewArgs["emails"] = emails
|
||||
c.ViewArgs["keywords"] = keywords
|
||||
return c.RenderTemplate("admin/email/list.html")
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ func (c AdminSetting) Email() revel.Result {
|
||||
func (c AdminSetting) Blog() revel.Result {
|
||||
recommendTags := configService.GetGlobalArrayConfig("recommendTags")
|
||||
newTags := configService.GetGlobalArrayConfig("newTags")
|
||||
c.RenderArgs["recommendTags"] = strings.Join(recommendTags, ",")
|
||||
c.RenderArgs["newTags"] = strings.Join(newTags, ",")
|
||||
c.ViewArgs["recommendTags"] = strings.Join(recommendTags, ",")
|
||||
c.ViewArgs["newTags"] = strings.Join(newTags, ",")
|
||||
return c.RenderTemplate("admin/setting/blog.html")
|
||||
}
|
||||
func (c AdminSetting) DoBlogTag(recommendTags, newTags string) revel.Result {
|
||||
@@ -33,7 +33,7 @@ func (c AdminSetting) DoBlogTag(recommendTags, newTags string) revel.Result {
|
||||
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "recommendTags", strings.Split(recommendTags, ","))
|
||||
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "newTags", strings.Split(newTags, ","))
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 共享设置
|
||||
@@ -43,14 +43,14 @@ func (c AdminSetting) ShareNote(registerSharedUserId string,
|
||||
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Msg = configService.UpdateShareNoteConfig(registerSharedUserId, registerSharedNotebookPerms, registerSharedNotePerms, registerSharedNotebookIds, registerSharedNoteIds, registerCopyNoteIds)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// demo
|
||||
// blog标签设置
|
||||
func (c AdminSetting) Demo() revel.Result {
|
||||
c.RenderArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername")
|
||||
c.RenderArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword")
|
||||
c.ViewArgs["demoUsername"] = configService.GetGlobalStringConfig("demoUsername")
|
||||
c.ViewArgs["demoPassword"] = configService.GetGlobalStringConfig("demoPassword")
|
||||
return c.RenderTemplate("admin/setting/demo.html")
|
||||
}
|
||||
func (c AdminSetting) DoDemo(demoUsername, demoPassword string) revel.Result {
|
||||
@@ -59,40 +59,40 @@ func (c AdminSetting) DoDemo(demoUsername, demoPassword string) revel.Result {
|
||||
userInfo, err := authService.Login(demoUsername, demoPassword)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return c.RenderJson(info.Re{Ok: false})
|
||||
return c.RenderJSON(info.Re{Ok: false})
|
||||
}
|
||||
if userInfo.UserId == "" {
|
||||
re.Msg = "The User is Not Exists"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUserId", userInfo.UserId.Hex())
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoUsername", demoUsername)
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "demoPassword", demoPassword)
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c AdminSetting) ExportPdf(path string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "exportPdfBinPath", path)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c AdminSetting) DoSiteUrl(siteUrl string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "siteUrl", siteUrl)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// SubDomain
|
||||
func (c AdminSetting) SubDomain() revel.Result {
|
||||
c.RenderArgs["str"] = configService.GlobalStringConfigs
|
||||
c.RenderArgs["arr"] = configService.GlobalArrayConfigs
|
||||
c.ViewArgs["str"] = configService.GlobalStringConfigs
|
||||
c.ViewArgs["arr"] = configService.GlobalArrayConfigs
|
||||
|
||||
c.RenderArgs["noteSubDomain"] = configService.GetGlobalStringConfig("noteSubDomain")
|
||||
c.RenderArgs["blogSubDomain"] = configService.GetGlobalStringConfig("blogSubDomain")
|
||||
c.RenderArgs["leaSubDomain"] = configService.GetGlobalStringConfig("leaSubDomain")
|
||||
c.ViewArgs["noteSubDomain"] = configService.GetGlobalStringConfig("noteSubDomain")
|
||||
c.ViewArgs["blogSubDomain"] = configService.GetGlobalStringConfig("blogSubDomain")
|
||||
c.ViewArgs["leaSubDomain"] = configService.GetGlobalStringConfig("leaSubDomain")
|
||||
|
||||
return c.RenderTemplate("admin/setting/subDomain.html")
|
||||
}
|
||||
@@ -106,13 +106,13 @@ func (c AdminSetting) DoSubDomain(noteSubDomain, blogSubDomain, leaSubDomain, bl
|
||||
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "blackSubDomains", strings.Split(blackSubDomains, ","))
|
||||
re.Ok = configService.UpdateGlobalArrayConfig(c.GetUserId(), "blackCustomDomains", strings.Split(blackCustomDomains, ","))
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c AdminSetting) OpenRegister(openRegister string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "openRegister", openRegister)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c AdminSetting) HomePage(homePage string) revel.Result {
|
||||
@@ -121,7 +121,7 @@ func (c AdminSetting) HomePage(homePage string) revel.Result {
|
||||
homePage = ""
|
||||
}
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "homePage", homePage)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c AdminSetting) Mongodb(mongodumpPath, mongorestorePath string) revel.Result {
|
||||
@@ -129,7 +129,7 @@ func (c AdminSetting) Mongodb(mongodumpPath, mongorestorePath string) revel.Resu
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongodumpPath", mongodumpPath)
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "mongorestorePath", mongorestorePath)
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c AdminSetting) UploadSize(uploadImageSize, uploadAvatarSize, uploadBlogLogoSize, uploadAttachSize float64) revel.Result {
|
||||
@@ -138,5 +138,5 @@ func (c AdminSetting) UploadSize(uploadImageSize, uploadAvatarSize, uploadBlogLo
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadAvatarSize", fmt.Sprintf("%v", uploadAvatarSize))
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadBlogLogoSize", fmt.Sprintf("%v", uploadBlogLogoSize))
|
||||
re.Ok = configService.UpdateGlobalStringConfig(c.GetUserId(), "uploadAttachSize", fmt.Sprintf("%v", uploadAttachSize))
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@ func (c AdminUpgrade) UpgradeBlog() revel.Result {
|
||||
func (c AdminUpgrade) UpgradeBetaToBeta2() revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Msg = upgradeService.UpgradeBetaToBeta2(c.GetUserId())
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c AdminUpgrade) UpgradeBeta3ToBeta4() revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Msg = upgradeService.Api(c.GetUserId())
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ var userPageSize = 10
|
||||
|
||||
func (c AdminUser) Index(sorter, keywords string, pageSize int) revel.Result {
|
||||
pageNumber := c.GetPage()
|
||||
if userPageSize == 0 {
|
||||
if pageSize == 0 {
|
||||
pageSize = userPageSize
|
||||
}
|
||||
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"email", "username", "verified", "createdTime", "accountType"})
|
||||
pageInfo, users := userService.ListUsers(pageNumber, pageSize, sorterField, isAsc, keywords)
|
||||
c.RenderArgs["pageInfo"] = pageInfo
|
||||
c.RenderArgs["users"] = users
|
||||
c.RenderArgs["keywords"] = keywords
|
||||
c.ViewArgs["pageInfo"] = pageInfo
|
||||
c.ViewArgs["users"] = users
|
||||
c.ViewArgs["keywords"] = keywords
|
||||
return c.RenderTemplate("admin/user/list.html")
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ func (c AdminUser) Register(email, pwd string) revel.Result {
|
||||
// 修改帐户
|
||||
func (c AdminUser) ResetPwd(userId string) revel.Result {
|
||||
userInfo := userService.GetUserInfo(userId)
|
||||
c.RenderArgs["userInfo"] = userInfo
|
||||
c.ViewArgs["userInfo"] = userInfo
|
||||
return c.RenderTemplate("admin/user/reset_pwd.html")
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
|
||||
|
||||
// 验证是否已登录
|
||||
// 必须是管理员
|
||||
if username, ok := c.Session["Username"]; ok && username == configService.GetAdminUsername() {
|
||||
if username, ok := c.Session["Username"]; ok && username.(string) == configService.GetAdminUsername() {
|
||||
return nil // 已登录
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
|
||||
if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
|
||||
re := info.NewRe()
|
||||
re.Msg = "NOTLOGIN"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
return c.Redirect("/login")
|
||||
|
||||
@@ -28,12 +28,12 @@ func (c ApiAuth) Login(email, pwd string) revel.Result {
|
||||
if err == nil {
|
||||
token := bson.NewObjectId().Hex()
|
||||
sessionService.SetUserId(token, userInfo.UserId.Hex())
|
||||
return c.RenderJson(info.AuthOk{Ok: true, Token: token, UserId: userInfo.UserId, Email: userInfo.Email, Username: userInfo.Username})
|
||||
return c.RenderJSON(info.AuthOk{Ok: true, Token: token, UserId: userInfo.UserId, Email: userInfo.Email, Username: userInfo.Username})
|
||||
} else {
|
||||
// 登录错误, 则错误次数++
|
||||
msg = "wrongUsernameOrPassword"
|
||||
}
|
||||
return c.RenderJson(info.ApiRe{Ok: false, Msg: c.Message(msg)})
|
||||
return c.RenderJSON(info.ApiRe{Ok: false, Msg: c.Message(msg)})
|
||||
}
|
||||
|
||||
// 注销
|
||||
@@ -43,7 +43,7 @@ func (c ApiAuth) Logout() revel.Result {
|
||||
sessionService.Clear(token)
|
||||
re := info.NewApiRe()
|
||||
re.Ok = true
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 注册
|
||||
@@ -53,17 +53,17 @@ func (c ApiAuth) Register(email, pwd string) revel.Result {
|
||||
re := info.NewApiRe()
|
||||
if !configService.IsOpenRegister() {
|
||||
re.Msg = "notOpenRegister" // 未开放注册
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
if re.Ok, re.Msg = Vd("email", email); !re.Ok {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 注册
|
||||
re.Ok, re.Msg = authService.Register(email, pwd, "")
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
@@ -23,18 +23,18 @@ type ApiBaseContrller struct {
|
||||
|
||||
// 得到token, 这个token是在AuthInterceptor设到Session中的
|
||||
func (c ApiBaseContrller) getToken() string {
|
||||
return c.Session["_token"]
|
||||
return c.GetSession("_token")
|
||||
}
|
||||
|
||||
// userId
|
||||
// _userId是在AuthInterceptor设置的
|
||||
func (c ApiBaseContrller) getUserId() string {
|
||||
return c.Session["_userId"]
|
||||
return c.GetSession("_userId")
|
||||
}
|
||||
|
||||
// 得到用户信息
|
||||
func (c ApiBaseContrller) getUserInfo() info.User {
|
||||
userId := c.Session["_userId"]
|
||||
userId := c.GetSession("_userId")
|
||||
if userId == "" {
|
||||
return info.User{}
|
||||
}
|
||||
@@ -53,16 +53,23 @@ func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg
|
||||
}
|
||||
*/
|
||||
|
||||
file, handel, err := c.Request.FormFile(name)
|
||||
if err != nil {
|
||||
var data []byte
|
||||
c.Params.Bind(&data, name)
|
||||
handel := c.Params.Files[name][0]
|
||||
if data == nil || len(data) == 0 {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// file, handel, err := c.Request.FormFile(name)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// defer file.Close()
|
||||
|
||||
// data, err := ioutil.ReadAll(file)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// > 5M?
|
||||
maxFileSize := configService.GetUploadSize("uploadAttachSize")
|
||||
if maxFileSize <= 0 {
|
||||
@@ -79,7 +86,7 @@ func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg
|
||||
filePath := "files/" + GetRandomFilePath(userId, newGuid) + "/attachs"
|
||||
|
||||
dir := revel.BasePath + "/" + filePath
|
||||
err = os.MkdirAll(dir, 0755)
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -122,11 +129,18 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok
|
||||
if isAttach {
|
||||
return c.uploadAttach(name, noteId)
|
||||
}
|
||||
file, handel, err := c.Request.FormFile(name)
|
||||
if err != nil {
|
||||
// file, handel, err := c.Request.FormFile(name)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// defer file.Close()
|
||||
|
||||
var data []byte
|
||||
c.Params.Bind(&data, name)
|
||||
handel := c.Params.Files[name][0]
|
||||
if data == nil || len(data) == 0 {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
newGuid := NewGuid()
|
||||
// 生成上传路径
|
||||
@@ -135,7 +149,7 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok
|
||||
fileUrlPath := "files/" + GetRandomFilePath(userId, newGuid) + "/images"
|
||||
|
||||
dir := revel.BasePath + "/" + fileUrlPath
|
||||
err = os.MkdirAll(dir, 0755)
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -148,10 +162,10 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok
|
||||
// }
|
||||
|
||||
filename = newGuid + ext
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// data, err := ioutil.ReadAll(file)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
|
||||
maxFileSize := configService.GetUploadSize("uploadImageSize")
|
||||
if maxFileSize <= 0 {
|
||||
|
||||
@@ -30,7 +30,7 @@ func (c ApiFile) CopyImage(userId, fileId, toUserId string) revel.Result {
|
||||
|
||||
re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId)
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// get all images by userId with page
|
||||
@@ -39,19 +39,19 @@ func (c ApiFile) GetImages(albumId, key string, page int) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = true
|
||||
re.Item = imagesPage
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c ApiFile) UpdateImageTitle(fileId, title string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = fileService.UpdateImageTitle(c.getUserId(), fileId, title)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c ApiFile) DeleteImage(fileId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Msg = fileService.DeleteImage(c.getUserId(), fileId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
@@ -52,7 +52,7 @@ func (c ApiNote) GetSyncNotes(afterUsn, maxEntry int) revel.Result {
|
||||
maxEntry = 100
|
||||
}
|
||||
notes := noteService.GetSyncNotes(c.getUserId(), afterUsn, maxEntry)
|
||||
return c.RenderJson(notes)
|
||||
return c.RenderJSON(notes)
|
||||
}
|
||||
|
||||
// 得到笔记本下的笔记
|
||||
@@ -61,17 +61,17 @@ func (c ApiNote) GetNotes(notebookId string) revel.Result {
|
||||
if notebookId != "" && !bson.IsObjectIdHex(notebookId) {
|
||||
re := info.NewApiRe()
|
||||
re.Msg = "notebookIdInvalid"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
_, notes := noteService.ListNotes(c.getUserId(), notebookId, false, c.GetPage(), pageSize, defaultSortField, false, false)
|
||||
return c.RenderJson(noteService.ToApiNotes(notes))
|
||||
return c.RenderJSON(noteService.ToApiNotes(notes))
|
||||
}
|
||||
|
||||
// 得到trash
|
||||
// [OK]
|
||||
func (c ApiNote) GetTrashNotes() revel.Result {
|
||||
_, notes := noteService.ListNotes(c.getUserId(), "", true, c.GetPage(), pageSize, defaultSortField, false, false)
|
||||
return c.RenderJson(noteService.ToApiNotes(notes))
|
||||
return c.RenderJSON(noteService.ToApiNotes(notes))
|
||||
|
||||
}
|
||||
|
||||
@@ -127,17 +127,17 @@ func (c ApiNote) GetNote(noteId string) revel.Result {
|
||||
if !bson.IsObjectIdHex(noteId) {
|
||||
re := info.NewApiRe()
|
||||
re.Msg = "noteIdInvalid"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
note := noteService.GetNote(noteId, c.getUserId())
|
||||
if note.NoteId == "" {
|
||||
re := info.NewApiRe()
|
||||
re.Msg = "notExists"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
apiNotes := noteService.ToApiNotes([]info.Note{note})
|
||||
return c.RenderJson(apiNotes[0])
|
||||
return c.RenderJSON(apiNotes[0])
|
||||
}
|
||||
|
||||
// 得到note和内容
|
||||
@@ -148,7 +148,7 @@ func (c ApiNote) GetNoteAndContent(noteId string) revel.Result {
|
||||
apiNotes := noteService.ToApiNotes([]info.Note{noteAndContent.Note})
|
||||
apiNote := apiNotes[0]
|
||||
apiNote.Content = noteService.FixContent(noteAndContent.Content, noteAndContent.IsMarkdown)
|
||||
return c.RenderJson(apiNote)
|
||||
return c.RenderJSON(apiNote)
|
||||
}
|
||||
|
||||
// content里的image, attach链接是
|
||||
@@ -178,7 +178,7 @@ func (c ApiNote) fixPostNotecontent(noteOrContent *info.ApiNote) {
|
||||
// "/api/file/getImage?fileId="+file.FileId, -1)
|
||||
} else {
|
||||
reg, _ := regexp.Compile(`https*://[^/]*?/api/file/getAttach\?fileId=`+file.LocalFileId)
|
||||
Log(reg)
|
||||
// Log(reg)
|
||||
noteOrContent.Content = reg.ReplaceAllString(noteOrContent.Content, `/api/file/getAttach?fileId=`+file.FileId)
|
||||
/*
|
||||
noteOrContent.Content = strings.Replace(noteOrContent.Content,
|
||||
@@ -207,7 +207,7 @@ func (c ApiNote) GetNoteContent(noteId string) revel.Result {
|
||||
Content: noteContent.Content,
|
||||
}
|
||||
|
||||
return c.RenderJson(apiNoteContent)
|
||||
return c.RenderJSON(apiNoteContent)
|
||||
}
|
||||
|
||||
// 添加笔记
|
||||
@@ -233,10 +233,10 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
|
||||
LogJ(file)
|
||||
}
|
||||
*/
|
||||
// return c.RenderJson(re)
|
||||
// return c.RenderJSON(re)
|
||||
if noteOrContent.NotebookId == "" || !bson.IsObjectIdHex(noteOrContent.NotebookId) {
|
||||
re.Msg = "notebookIdNotExists"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
noteId := bson.NewObjectId()
|
||||
@@ -259,7 +259,7 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
|
||||
}
|
||||
// 报不是图片的错误没关系, 证明客户端传来非图片的数据
|
||||
if msg != "notImage" {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
} else {
|
||||
// 建立映射
|
||||
@@ -271,7 +271,7 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +282,7 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
|
||||
// Log("Add")
|
||||
// LogJ(noteOrContent)
|
||||
|
||||
// return c.RenderJson(re)
|
||||
// return c.RenderJSON(re)
|
||||
|
||||
note := info.Note{UserId: userId,
|
||||
NoteId: noteId,
|
||||
@@ -318,7 +318,7 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
|
||||
|
||||
if note.NoteId == "" {
|
||||
re.Ok = false
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 添加需要返回的
|
||||
@@ -332,7 +332,7 @@ func (c ApiNote) AddNote(noteOrContent info.ApiNote) revel.Result {
|
||||
noteOrContent.Content = ""
|
||||
noteOrContent.Abstract = ""
|
||||
// apiNote := info.NoteToApiNote(note, noteOrContent.Files)
|
||||
return c.RenderJson(noteOrContent)
|
||||
return c.RenderJSON(noteOrContent)
|
||||
}
|
||||
|
||||
// 更新笔记
|
||||
@@ -347,12 +347,12 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
|
||||
|
||||
if noteOrContent.NoteId == "" {
|
||||
re.Msg = "noteIdNotExists"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
if noteOrContent.Usn <= 0 {
|
||||
re.Msg = "usnNotExists"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// Log("_____________")
|
||||
@@ -368,12 +368,12 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
|
||||
note := noteService.GetNote(noteId, userId)
|
||||
if note.NoteId == "" {
|
||||
re.Msg = "notExists"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
if note.Usn != noteOrContent.Usn {
|
||||
re.Msg = "conflict"
|
||||
Log("conflict")
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
Log("没有冲突")
|
||||
|
||||
@@ -402,14 +402,14 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
|
||||
} else {
|
||||
re.Msg = msg
|
||||
}
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
} else {
|
||||
// 建立映射
|
||||
file.FileId = fileId
|
||||
noteOrContent.Files[i] = file
|
||||
}
|
||||
} else {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -490,7 +490,7 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
|
||||
if !noteOk {
|
||||
re.Ok = false
|
||||
re.Msg = noteMsg
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,7 +528,7 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
|
||||
}
|
||||
|
||||
if !re.Ok {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
noteOrContent.Content = ""
|
||||
@@ -539,14 +539,14 @@ func (c ApiNote) UpdateNote(noteOrContent info.ApiNote) revel.Result {
|
||||
// LogJ(noteOrContent.Files)
|
||||
noteOrContent.UserId = c.getUserId()
|
||||
|
||||
return c.RenderJson(noteOrContent)
|
||||
return c.RenderJSON(noteOrContent)
|
||||
}
|
||||
|
||||
// 删除trash
|
||||
func (c ApiNote) DeleteTrash(noteId string, usn int) revel.Result {
|
||||
re := info.NewReUpdate()
|
||||
re.Ok, re.Msg, re.Usn = trashService.DeleteTrashApi(noteId, c.getUserId(), usn)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 得到历史列表
|
||||
@@ -558,7 +558,7 @@ func (c ApiNote) GetHistories(noteId string) revel.Result {
|
||||
re.Ok = true
|
||||
re.Item = histories
|
||||
}
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -569,13 +569,13 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result {
|
||||
userId := c.getUserId()
|
||||
if noteId == "" {
|
||||
re.Msg = "noteNotExists"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
note := noteService.GetNoteById(noteId)
|
||||
if note.NoteId == "" {
|
||||
re.Msg = "noteNotExists"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
noteUserId := note.UserId.Hex()
|
||||
@@ -584,7 +584,7 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result {
|
||||
// 是否是有权限协作的
|
||||
if !note.IsBlog && !shareService.HasReadPerm(noteUserId, userId, noteId) {
|
||||
re.Msg = "noteNotExists"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,7 +594,7 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result {
|
||||
dir := revel.BasePath + "/" + fileUrlPath
|
||||
if !MkdirAll(dir) {
|
||||
re.Msg = "noDir"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
filename := guid + ".pdf"
|
||||
path := dir + "/" + filename
|
||||
@@ -623,12 +623,12 @@ func (c ApiNote) ExportPdf(noteId string) revel.Result {
|
||||
_, err := cmd.Output()
|
||||
if err != nil {
|
||||
re.Msg = "sysError"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
re.Msg = "sysError"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
filenameReturn := note.Title
|
||||
|
||||
@@ -53,7 +53,7 @@ func (c ApiNotebook) GetSyncNotebooks(afterUsn, maxEntry int) revel.Result {
|
||||
maxEntry = 100
|
||||
}
|
||||
notebooks := notebookService.GeSyncNotebooks(c.getUserId(), afterUsn, maxEntry)
|
||||
return c.RenderJson(c.fixNotebooks(notebooks))
|
||||
return c.RenderJSON(c.fixNotebooks(notebooks))
|
||||
}
|
||||
|
||||
// 得到用户的所有笔记本
|
||||
@@ -61,7 +61,7 @@ func (c ApiNotebook) GetSyncNotebooks(afterUsn, maxEntry int) revel.Result {
|
||||
// info.SubNotebooks
|
||||
func (c ApiNotebook) GetNotebooks() revel.Result {
|
||||
notebooks := notebookService.GeSyncNotebooks(c.getUserId(), 0, 99999)
|
||||
return c.RenderJson(c.fixNotebooks(notebooks))
|
||||
return c.RenderJSON(c.fixNotebooks(notebooks))
|
||||
}
|
||||
|
||||
// 添加notebook
|
||||
@@ -77,9 +77,9 @@ func (c ApiNotebook) AddNotebook(title, parentNotebookId string, seq int) revel.
|
||||
re := info.NewRe()
|
||||
re.Ok, notebook = notebookService.AddNotebook(notebook)
|
||||
if !re.Ok {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
return c.RenderJson(c.fixNotebook(¬ebook))
|
||||
return c.RenderJSON(c.fixNotebook(¬ebook))
|
||||
}
|
||||
|
||||
// 修改笔记
|
||||
@@ -91,10 +91,10 @@ func (c ApiNotebook) UpdateNotebook(notebookId, title, parentNotebookId string,
|
||||
if !ok {
|
||||
re.Ok = false
|
||||
re.Msg = msg
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
LogJ(notebook)
|
||||
return c.RenderJson(c.fixNotebook(¬ebook))
|
||||
return c.RenderJSON(c.fixNotebook(¬ebook))
|
||||
}
|
||||
|
||||
// 删除笔记本
|
||||
@@ -102,5 +102,5 @@ func (c ApiNotebook) UpdateNotebook(notebookId, title, parentNotebookId string,
|
||||
func (c ApiNotebook) DeleteNotebook(notebookId string, usn int) revel.Result {
|
||||
re := info.NewApiRe()
|
||||
re.Ok, re.Msg = notebookService.DeleteNotebookForce(c.getUserId(), notebookId, usn)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func (c ApiTag) GetSyncTags(afterUsn, maxEntry int) revel.Result {
|
||||
maxEntry = 100
|
||||
}
|
||||
tags := tagService.GeSyncTags(c.getUserId(), afterUsn, maxEntry)
|
||||
return c.RenderJson(tags)
|
||||
return c.RenderJSON(tags)
|
||||
}
|
||||
|
||||
// 添加Tag
|
||||
@@ -44,7 +44,7 @@ func (c ApiTag) GetSyncTags(afterUsn, maxEntry int) revel.Result {
|
||||
*/
|
||||
func (c ApiTag) AddTag(tag string) revel.Result {
|
||||
ret := tagService.AddOrUpdateTag(c.getUserId(), tag)
|
||||
return c.RenderJson(ret)
|
||||
return c.RenderJSON(ret)
|
||||
}
|
||||
|
||||
// 删除标签
|
||||
@@ -52,5 +52,5 @@ func (c ApiTag) AddTag(tag string) revel.Result {
|
||||
func (c ApiTag) DeleteTag(tag string, usn int) revel.Result {
|
||||
re := info.NewReUpdate()
|
||||
re.Ok, re.Msg, re.Usn = tagService.DeleteTagApi(c.getUserId(), tag, usn)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func (c ApiUser) Info() revel.Result {
|
||||
|
||||
userInfo := c.getUserInfo()
|
||||
if userInfo.UserId == "" {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
apiUser := info.ApiUser{
|
||||
UserId: userInfo.UserId.Hex(),
|
||||
@@ -37,7 +37,7 @@ func (c ApiUser) Info() revel.Result {
|
||||
Logo: userInfo.Logo,
|
||||
Verified: userInfo.Verified,
|
||||
}
|
||||
return c.RenderJson(apiUser)
|
||||
return c.RenderJSON(apiUser)
|
||||
}
|
||||
|
||||
// 修改用户名
|
||||
@@ -46,15 +46,15 @@ func (c ApiUser) UpdateUsername(username string) revel.Result {
|
||||
re := info.NewApiRe()
|
||||
if c.GetUsername() == "demo" {
|
||||
re.Msg = "cannotUpdateDemo"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
if re.Ok, re.Msg = Vd("username", username); !re.Ok {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
re.Ok, re.Msg = userService.UpdateUsername(c.getUserId(), username)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 修改密码
|
||||
@@ -63,23 +63,23 @@ func (c ApiUser) UpdatePwd(oldPwd, pwd string) revel.Result {
|
||||
re := info.NewApiRe()
|
||||
if c.GetUsername() == "demo" {
|
||||
re.Msg = "cannotUpdateDemo"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
if re.Ok, re.Msg = Vd("password", oldPwd); !re.Ok {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
if re.Ok, re.Msg = Vd("password", pwd); !re.Ok {
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
re.Ok, re.Msg = userService.UpdatePwd(c.getUserId(), oldPwd, pwd)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 获得同步状态
|
||||
// [OK]
|
||||
func (c ApiUser) GetSyncState() revel.Result {
|
||||
ret := bson.M{"LastSyncUsn": userService.GetUsn(c.getUserId()), "LastSyncTime": time.Now().Unix()}
|
||||
return c.RenderJson(ret)
|
||||
return c.RenderJSON(ret)
|
||||
}
|
||||
|
||||
// 头像设置
|
||||
@@ -91,11 +91,11 @@ func (c ApiUser) UpdateLogo() revel.Result {
|
||||
|
||||
if ok {
|
||||
ok = userService.UpdateAvatar(c.getUserId(), url)
|
||||
return c.RenderJson(map[string]string{"Logo": url})
|
||||
return c.RenderJSON(map[string]string{"Logo": url})
|
||||
} else {
|
||||
re := info.NewApiRe()
|
||||
re.Msg = msg
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,16 +104,23 @@ func (c ApiUser) uploadImage() (ok bool, msg, url string) {
|
||||
var fileUrlPath = ""
|
||||
ok = false
|
||||
|
||||
file, handel, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
var data []byte
|
||||
c.Params.Bind(&data, "file")
|
||||
handel := c.Params.Files["file"][0]
|
||||
if data == nil || len(data) == 0 {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// file, handel, err := c.Request.FormFile("file")
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// defer file.Close()
|
||||
// 生成上传路径
|
||||
fileUrlPath = "public/upload/" + c.getUserId() + "/images/logo"
|
||||
|
||||
dir := revel.BasePath + "/" + fileUrlPath
|
||||
err = os.MkdirAll(dir, 0755)
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -129,11 +136,11 @@ func (c ApiUser) uploadImage() (ok bool, msg, url string) {
|
||||
}
|
||||
|
||||
filename = NewGuid() + ext
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
LogJ(err)
|
||||
return
|
||||
}
|
||||
// data, err := ioutil.ReadAll(file)
|
||||
// if err != nil {
|
||||
// LogJ(err)
|
||||
// return
|
||||
// }
|
||||
|
||||
// > 5M?
|
||||
if len(data) > 5*1024*1024 {
|
||||
|
||||
@@ -75,7 +75,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
|
||||
noToken := false
|
||||
if token == "" {
|
||||
// 若无, 则取sessionId
|
||||
token = c.Session.Id()
|
||||
token = c.Session.ID()
|
||||
noToken = true
|
||||
}
|
||||
c.Session["_token"] = token
|
||||
@@ -90,7 +90,10 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
|
||||
if noToken && userId == "" {
|
||||
// 从session中获取, api/file/getImage, api/file/getAttach, api/file/getAllAttach
|
||||
// 客户端
|
||||
userId, _ = c.Session["UserId"]
|
||||
userIdI, _ := c.Session["UserId"]
|
||||
if userIdI != nil {
|
||||
userId = userIdI.(string)
|
||||
}
|
||||
}
|
||||
c.Session["_userId"] = userId
|
||||
|
||||
@@ -106,7 +109,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
|
||||
// 没有登录, 返回错误的信息, 需要登录
|
||||
re := info.NewApiRe()
|
||||
re.Msg = "NOTLOGIN"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -103,7 +103,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
|
||||
if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
|
||||
re := info.NewRe()
|
||||
re.Msg = "NOTLOGIN"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
return c.Redirect("/login")
|
||||
|
||||
@@ -46,7 +46,7 @@ func (c MemberBaseController) getSorter(sorterField string, isAsc bool, okSorter
|
||||
} else {
|
||||
isAsc = false
|
||||
}
|
||||
c.RenderArgs["sorter"] = sorter
|
||||
c.ViewArgs["sorter"] = sorter
|
||||
return sorterField, isAsc
|
||||
}
|
||||
|
||||
|
||||
@@ -21,13 +21,13 @@ type MemberBlog struct {
|
||||
func (c MemberBlog) common() info.UserBlog {
|
||||
userId := c.GetUserId()
|
||||
userInfo := userService.GetUserInfo(userId)
|
||||
c.RenderArgs["userInfo"] = userInfo
|
||||
c.ViewArgs["userInfo"] = userInfo
|
||||
|
||||
// 得到博客设置信息
|
||||
c.RenderArgs["allowCustomDomain"] = configService.GetGlobalStringConfig("allowCustomDomain")
|
||||
c.ViewArgs["allowCustomDomain"] = configService.GetGlobalStringConfig("allowCustomDomain")
|
||||
|
||||
userBlog := blogService.GetUserBlog(userId)
|
||||
c.RenderArgs["userBlog"] = userBlog
|
||||
c.ViewArgs["userBlog"] = userBlog
|
||||
|
||||
c.SetUserInfo()
|
||||
c.SetLocale()
|
||||
@@ -62,7 +62,7 @@ func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string)
|
||||
} else {
|
||||
isAsc = false
|
||||
}
|
||||
c.RenderArgs["sorter"] = sorter
|
||||
c.ViewArgs["sorter"] = sorter
|
||||
return sorterField, isAsc
|
||||
}
|
||||
|
||||
@@ -72,18 +72,18 @@ var userPageSize = 15
|
||||
func (c MemberBlog) Index(sorter, keywords string) revel.Result {
|
||||
userId := c.GetUserId()
|
||||
userInfo := userService.GetUserInfo(userId)
|
||||
c.RenderArgs["userInfo"] = userInfo
|
||||
c.ViewArgs["userInfo"] = userInfo
|
||||
|
||||
c.RenderArgs["title"] = c.Message("Posts")
|
||||
c.ViewArgs["title"] = c.Message("Posts")
|
||||
pageNumber := c.GetPage()
|
||||
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "urlTitle", "updatedTime", "publicTime", "createdTime"})
|
||||
pageInfo, blogs := blogService.ListAllBlogs(c.GetUserId(), "", keywords, false, pageNumber, userPageSize, sorterField, isAsc)
|
||||
c.RenderArgs["pageInfo"] = pageInfo
|
||||
c.RenderArgs["blogs"] = blogs
|
||||
c.RenderArgs["keywords"] = keywords
|
||||
c.ViewArgs["pageInfo"] = pageInfo
|
||||
c.ViewArgs["blogs"] = blogs
|
||||
c.ViewArgs["keywords"] = keywords
|
||||
|
||||
userAndBlog := userService.GetUserAndBlog(c.GetUserId())
|
||||
c.RenderArgs["userAndBlog"] = userAndBlog
|
||||
c.ViewArgs["userAndBlog"] = userAndBlog
|
||||
|
||||
c.common()
|
||||
|
||||
@@ -94,48 +94,48 @@ func (c MemberBlog) Index(sorter, keywords string) revel.Result {
|
||||
func (c MemberBlog) UpdateBlogUrlTitle(noteId, urlTitle string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Item = blogService.UpateBlogUrlTitle(c.GetUserId(), noteId, urlTitle)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 修改笔记的urlTitle
|
||||
func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result {
|
||||
c.common()
|
||||
c.RenderArgs["title"] = c.Message("Update Post Abstract")
|
||||
c.ViewArgs["title"] = c.Message("Update Post Abstract")
|
||||
note := noteService.GetNoteAndContent(noteId, c.GetUserId())
|
||||
if !note.Note.IsBlog {
|
||||
return c.E404()
|
||||
}
|
||||
c.RenderArgs["note"] = note
|
||||
c.RenderArgs["noteId"] = noteId
|
||||
c.ViewArgs["note"] = note
|
||||
c.ViewArgs["noteId"] = noteId
|
||||
return c.RenderTemplate("member/blog/update_abstract.html")
|
||||
}
|
||||
func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.UpateBlogAbstract(c.GetUserId(), noteId, imgSrc, desc, abstract)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 基本信息设置
|
||||
func (c MemberBlog) Base() revel.Result {
|
||||
c.common()
|
||||
c.RenderArgs["title"] = c.Message("Blog Base Info")
|
||||
c.ViewArgs["title"] = c.Message("Blog Base Info")
|
||||
return c.RenderTemplate("member/blog/base.html")
|
||||
}
|
||||
func (c MemberBlog) Comment() revel.Result {
|
||||
c.common()
|
||||
c.RenderArgs["title"] = c.Message("Comment")
|
||||
c.ViewArgs["title"] = c.Message("Comment")
|
||||
return c.RenderTemplate("member/blog/comment.html")
|
||||
}
|
||||
|
||||
func (c MemberBlog) Paging() revel.Result {
|
||||
c.common()
|
||||
c.RenderArgs["title"] = c.Message("Paging")
|
||||
c.ViewArgs["title"] = c.Message("Paging")
|
||||
return c.RenderTemplate("member/blog/paging.html")
|
||||
}
|
||||
|
||||
func (c MemberBlog) Cate() revel.Result {
|
||||
userBlog := c.common()
|
||||
c.RenderArgs["title"] = c.Message("Category")
|
||||
c.ViewArgs["title"] = c.Message("Category")
|
||||
|
||||
notebooks := blogService.ListBlogNotebooks(c.GetUserId())
|
||||
notebooksMap := map[string]info.Notebook{}
|
||||
@@ -166,7 +166,7 @@ func (c MemberBlog) Cate() revel.Result {
|
||||
i++
|
||||
}
|
||||
}
|
||||
c.RenderArgs["notebooks"] = notebooks2
|
||||
c.ViewArgs["notebooks"] = notebooks2
|
||||
|
||||
return c.RenderTemplate("member/blog/cate.html")
|
||||
}
|
||||
@@ -175,54 +175,54 @@ func (c MemberBlog) Cate() revel.Result {
|
||||
func (c MemberBlog) UpateCateIds(cateIds []string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.UpateCateIds(c.GetUserId(), cateIds)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c MemberBlog) UpdateCateUrlTitle(cateId, urlTitle string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Item = blogService.UpateCateUrlTitle(c.GetUserId(), cateId, urlTitle)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 保存之, 包含增加与保存
|
||||
func (c MemberBlog) DoAddOrUpdateSingle(singleId, title, content string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.AddOrUpdateSingle(c.GetUserId(), singleId, title, content)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
func (c MemberBlog) AddOrUpdateSingle(singleId string) revel.Result {
|
||||
c.common()
|
||||
c.RenderArgs["title"] = c.Message("Add Single")
|
||||
c.RenderArgs["singleId"] = singleId
|
||||
c.ViewArgs["title"] = c.Message("Add Single")
|
||||
c.ViewArgs["singleId"] = singleId
|
||||
if singleId != "" {
|
||||
c.RenderArgs["title"] = c.Message("Update Single")
|
||||
c.RenderArgs["single"] = blogService.GetSingle(singleId)
|
||||
c.ViewArgs["title"] = c.Message("Update Single")
|
||||
c.ViewArgs["single"] = blogService.GetSingle(singleId)
|
||||
}
|
||||
return c.RenderTemplate("member/blog/add_single.html")
|
||||
}
|
||||
func (c MemberBlog) SortSingles(singleIds []string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.SortSingles(c.GetUserId(), singleIds)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c MemberBlog) DeleteSingle(singleId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.DeleteSingle(c.GetUserId(), singleId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 修改页面标题
|
||||
func (c MemberBlog) UpdateSingleUrlTitle(singleId, urlTitle string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Item = blogService.UpdateSingleUrlTitle(c.GetUserId(), singleId, urlTitle)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c MemberBlog) Single() revel.Result {
|
||||
c.common()
|
||||
c.RenderArgs["title"] = c.Message("Single")
|
||||
c.RenderArgs["singles"] = blogService.GetSingles(c.GetUserId())
|
||||
c.ViewArgs["title"] = c.Message("Single")
|
||||
c.ViewArgs["singles"] = blogService.GetSingles(c.GetUserId())
|
||||
|
||||
return c.RenderTemplate("member/blog/single.html")
|
||||
}
|
||||
@@ -231,12 +231,12 @@ func (c MemberBlog) Single() revel.Result {
|
||||
func (c MemberBlog) Theme() revel.Result {
|
||||
c.common()
|
||||
activeTheme, otherThemes := themeService.GetUserThemes(c.GetUserId())
|
||||
c.RenderArgs["activeTheme"] = activeTheme
|
||||
c.RenderArgs["otherThemes"] = otherThemes
|
||||
c.ViewArgs["activeTheme"] = activeTheme
|
||||
c.ViewArgs["otherThemes"] = otherThemes
|
||||
|
||||
c.RenderArgs["optionThemes"] = themeService.GetDefaultThemes()
|
||||
c.ViewArgs["optionThemes"] = themeService.GetDefaultThemes()
|
||||
|
||||
c.RenderArgs["title"] = c.Message("Theme")
|
||||
c.ViewArgs["title"] = c.Message("Theme")
|
||||
return c.RenderTemplate("member/blog/theme.html")
|
||||
}
|
||||
|
||||
@@ -253,11 +253,11 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
|
||||
}
|
||||
|
||||
c.common()
|
||||
c.RenderArgs["title"] = c.Message("Update Theme")
|
||||
c.RenderArgs["isNew"] = isNew
|
||||
c.ViewArgs["title"] = c.Message("Update Theme")
|
||||
c.ViewArgs["isNew"] = isNew
|
||||
|
||||
// 先复制之
|
||||
c.RenderArgs["themeId"] = themeId
|
||||
c.ViewArgs["themeId"] = themeId
|
||||
|
||||
// 得到脚本目录
|
||||
userId := c.GetUserId()
|
||||
@@ -266,7 +266,7 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
|
||||
if theme.ThemeId == "" {
|
||||
return c.E404()
|
||||
}
|
||||
c.RenderArgs["theme"] = theme
|
||||
c.ViewArgs["theme"] = theme
|
||||
|
||||
path := revel.BasePath + "/" + theme.Path
|
||||
|
||||
@@ -287,7 +287,7 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
|
||||
}
|
||||
}
|
||||
|
||||
c.RenderArgs["myTpls"] = myTpls
|
||||
c.ViewArgs["myTpls"] = myTpls
|
||||
|
||||
return c.RenderTemplate("member/blog/update_theme.html")
|
||||
}
|
||||
@@ -298,7 +298,7 @@ func (c MemberBlog) GetTplContent(themeId string, filename string) revel.Result
|
||||
re.Ok = true
|
||||
re.Item = themeService.GetTplContent(c.GetUserId(), themeId, filename)
|
||||
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
func (c MemberBlog) UpdateTplContent(themeId, filename, content string) revel.Result {
|
||||
re := info.NewRe()
|
||||
@@ -309,7 +309,7 @@ func (c MemberBlog) UpdateTplContent(themeId, filename, content string) revel.Re
|
||||
func (c MemberBlog) DeleteTpl(themeId, filename string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = themeService.DeleteTpl(c.GetUserId(), themeId, filename)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c MemberBlog) ListThemeImages(themeId string) revel.Result {
|
||||
@@ -320,22 +320,22 @@ func (c MemberBlog) ListThemeImages(themeId string) revel.Result {
|
||||
images := ListDir(path)
|
||||
re.List = images
|
||||
re.Ok = true
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c MemberBlog) DeleteThemeImage(themeId, filename string) revel.Result {
|
||||
re := info.NewRe()
|
||||
path := themeService.GetThemeAbsolutePath(c.GetUserId(), themeId) + "/images/" + filename
|
||||
re.Ok = DeleteFile(path)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 上传主题图片
|
||||
func (c MemberBlog) UploadThemeImage(themeId string) revel.Result {
|
||||
re := c.uploadImage(themeId)
|
||||
c.RenderArgs["fileUrlPath"] = re.Id
|
||||
c.RenderArgs["resultCode"] = re.Code
|
||||
c.RenderArgs["resultMsg"] = re.Msg
|
||||
c.ViewArgs["fileUrlPath"] = re.Id
|
||||
c.ViewArgs["resultCode"] = re.Code
|
||||
c.ViewArgs["resultMsg"] = re.Msg
|
||||
return c.RenderTemplate("file/blog_logo.html")
|
||||
}
|
||||
func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
|
||||
@@ -351,14 +351,21 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
|
||||
re.Ok = Ok
|
||||
}()
|
||||
|
||||
file, handel, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
var data []byte
|
||||
c.Params.Bind(&data, "file")
|
||||
handel := c.Params.Files["file"][0]
|
||||
if data == nil || len(data) == 0 {
|
||||
return re
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// file, handel, err := c.Request.FormFile("file")
|
||||
// if err != nil {
|
||||
// return re
|
||||
// }
|
||||
// defer file.Close()
|
||||
// 生成上传路径
|
||||
dir := themeService.GetThemeAbsolutePath(c.GetUserId(), themeId) + "/images"
|
||||
err = os.MkdirAll(dir, 0755)
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
if err != nil {
|
||||
return re
|
||||
}
|
||||
@@ -374,11 +381,11 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
|
||||
}
|
||||
|
||||
filename = filename
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
LogJ(err)
|
||||
return re
|
||||
}
|
||||
// data, err := ioutil.ReadAll(file)
|
||||
// if err != nil {
|
||||
// LogJ(err)
|
||||
// return re
|
||||
// }
|
||||
|
||||
// > 2M?
|
||||
if len(data) > 5*1024*1024 {
|
||||
@@ -405,21 +412,21 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
|
||||
func (c MemberBlog) ActiveTheme(themeId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = themeService.ActiveTheme(c.GetUserId(), themeId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 删除主题
|
||||
func (c MemberBlog) DeleteTheme(themeId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = themeService.DeleteTheme(c.GetUserId(), themeId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 管理员公开主题
|
||||
func (c MemberBlog) PublicTheme(themeId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = themeService.PublicTheme(c.GetUserId(), themeId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 导出
|
||||
@@ -441,20 +448,27 @@ func (c MemberBlog) ExportTheme(themeId string) revel.Result {
|
||||
func (c MemberBlog) ImportTheme() revel.Result {
|
||||
re := info.NewRe()
|
||||
|
||||
file, handel, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
re.Msg = fmt.Sprintf("%v", err)
|
||||
return c.RenderJson(re)
|
||||
var data []byte
|
||||
c.Params.Bind(&data, "file")
|
||||
handel := c.Params.Files["file"][0]
|
||||
if data == nil || len(data) == 0 {
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
// file, handel, err := c.Request.FormFile("file")
|
||||
// if err != nil {
|
||||
// re.Msg = fmt.Sprintf("%v", err)
|
||||
// return c.RenderJSON(re)
|
||||
// }
|
||||
|
||||
// defer file.Close()
|
||||
// 生成上传路径
|
||||
userId := c.GetUserId()
|
||||
dir := revel.BasePath + "/public/upload/" + userId + "/tmp"
|
||||
err = os.MkdirAll(dir, 0755)
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
if err != nil {
|
||||
re.Msg = fmt.Sprintf("%v", err)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
// 生成新的文件名
|
||||
filename := handel.Filename
|
||||
@@ -463,26 +477,26 @@ func (c MemberBlog) ImportTheme() revel.Result {
|
||||
_, ext = SplitFilename(filename)
|
||||
if ext != ".zip" {
|
||||
re.Msg = "Please upload zip file"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
filename = filename
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
// data, err := ioutil.ReadAll(file)
|
||||
// if err != nil {
|
||||
// return c.RenderJSON(re)
|
||||
// }
|
||||
|
||||
// > 10M?
|
||||
if len(data) > 10*1024*1024 {
|
||||
re.Msg = "File is big than 10M"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
toPath := dir + "/" + filename
|
||||
err = ioutil.WriteFile(toPath, data, 0777)
|
||||
if err != nil {
|
||||
re.Msg = fmt.Sprintf("%v", err)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 上传好后, 增加之
|
||||
@@ -494,7 +508,7 @@ func (c MemberBlog) ImportTheme() revel.Result {
|
||||
func (c MemberBlog) InstallTheme(themeId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = themeService.InstallTheme(c.GetUserId(), themeId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
// 新建主题
|
||||
@@ -508,17 +522,17 @@ func (c MemberBlog) NewTheme() revel.Result {
|
||||
func (c MemberBlog) SetUserBlogBase(userBlog info.UserBlogBase) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.UpdateUserBlogBase(c.GetUserId(), userBlog)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
func (c MemberBlog) SetUserBlogComment(userBlog info.UserBlogComment) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.UpdateUserBlogComment(c.GetUserId(), userBlog)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
func (c MemberBlog) SetUserBlogStyle(userBlog info.UserBlogStyle) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.UpdateUserBlogStyle(c.GetUserId(), userBlog)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c MemberBlog) SetUserBlogPaging(perPageSize int, sortField string, isAsc bool) revel.Result {
|
||||
|
||||
@@ -14,8 +14,8 @@ type MemberGroup struct {
|
||||
func (c MemberGroup) Index() revel.Result {
|
||||
c.SetUserInfo()
|
||||
c.SetLocale()
|
||||
c.RenderArgs["title"] = c.Message("My Group")
|
||||
c.RenderArgs["groups"] = groupService.GetGroupsAndUsers(c.GetUserId())
|
||||
c.ViewArgs["title"] = c.Message("My Group")
|
||||
c.ViewArgs["groups"] = groupService.GetGroupsAndUsers(c.GetUserId())
|
||||
return c.RenderTemplate("member/group/index.html")
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ func (c MemberGroup) Index() revel.Result {
|
||||
func (c MemberGroup) AddGroup(title string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Item = groupService.AddGroup(c.GetUserId(), title)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c MemberGroup) UpdateGroupTitle(groupId, title string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = groupService.UpdateGroupTitle(c.GetUserId(), groupId, title)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
func (c MemberGroup) DeleteGroup(groupId string) revel.Result {
|
||||
|
||||
@@ -13,10 +13,10 @@ type MemberIndex struct {
|
||||
// admin 主页
|
||||
func (c MemberIndex) Index() revel.Result {
|
||||
c.SetUserInfo()
|
||||
c.RenderArgs["title"] = c.Message("Leanote Member Center")
|
||||
c.ViewArgs["title"] = c.Message("Leanote Member Center")
|
||||
|
||||
c.RenderArgs["countNote"] = noteService.CountNote(c.GetUserId())
|
||||
c.RenderArgs["countBlog"] = noteService.CountBlog(c.GetUserId())
|
||||
c.ViewArgs["countNote"] = noteService.CountNote(c.GetUserId())
|
||||
c.ViewArgs["countBlog"] = noteService.CountBlog(c.GetUserId())
|
||||
|
||||
c.SetLocale()
|
||||
|
||||
@@ -25,10 +25,10 @@ func (c MemberIndex) Index() revel.Result {
|
||||
|
||||
// 模板
|
||||
func (c MemberIndex) T(t string) revel.Result {
|
||||
c.RenderArgs["str"] = configService.GlobalStringConfigs
|
||||
c.RenderArgs["arr"] = configService.GlobalArrayConfigs
|
||||
c.RenderArgs["map"] = configService.GlobalMapConfigs
|
||||
c.RenderArgs["arrMap"] = configService.GlobalArrMapConfigs
|
||||
c.ViewArgs["str"] = configService.GlobalStringConfigs
|
||||
c.ViewArgs["arr"] = configService.GlobalArrayConfigs
|
||||
c.ViewArgs["map"] = configService.GlobalMapConfigs
|
||||
c.ViewArgs["arrMap"] = configService.GlobalArrMapConfigs
|
||||
return c.RenderTemplate("admin/" + t + ".html")
|
||||
}
|
||||
|
||||
|
||||
@@ -13,28 +13,28 @@ type MemberUser struct {
|
||||
func (c MemberUser) Username() revel.Result {
|
||||
c.SetUserInfo()
|
||||
c.SetLocale()
|
||||
c.RenderArgs["title"] = c.Message("Username")
|
||||
c.ViewArgs["title"] = c.Message("Username")
|
||||
return c.RenderTemplate("member/user/username.html")
|
||||
}
|
||||
|
||||
func (c MemberUser) Email() revel.Result {
|
||||
c.SetUserInfo()
|
||||
c.SetLocale()
|
||||
c.RenderArgs["title"] = c.Message("Email")
|
||||
c.ViewArgs["title"] = c.Message("Email")
|
||||
return c.RenderTemplate("member/user/email.html")
|
||||
}
|
||||
|
||||
func (c MemberUser) Password() revel.Result {
|
||||
c.SetUserInfo()
|
||||
c.SetLocale()
|
||||
c.RenderArgs["title"] = c.Message("Password")
|
||||
c.ViewArgs["title"] = c.Message("Password")
|
||||
return c.RenderTemplate("member/user/password.html")
|
||||
}
|
||||
|
||||
func (c MemberUser) Avatar() revel.Result {
|
||||
c.SetUserInfo()
|
||||
c.SetLocale()
|
||||
c.RenderArgs["title"] = c.Message("Avatar")
|
||||
c.RenderArgs["globalConfigs"] = configService.GetGlobalConfigForUser()
|
||||
c.ViewArgs["title"] = c.Message("Avatar")
|
||||
c.ViewArgs["globalConfigs"] = configService.GetGlobalConfigForUser()
|
||||
return c.RenderTemplate("member/user/avatar.html")
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ func AuthInterceptor(c *revel.Controller) revel.Result {
|
||||
if c.Request.Header.Get("X-Requested-With") == "XMLHttpRequest" {
|
||||
re := info.NewRe()
|
||||
re.Msg = "NOTLOGIN"
|
||||
return c.RenderJson(re)
|
||||
return c.RenderJSON(re)
|
||||
}
|
||||
|
||||
return c.Redirect("/login")
|
||||
|
||||
@@ -76,6 +76,11 @@ func Init(url, dbname string) {
|
||||
// get dbname from urlEnv
|
||||
urls := strings.Split(url, "/")
|
||||
dbname = urls[len(urls)-1]
|
||||
|
||||
if strings.Contains(dbname, "?") {
|
||||
urls = strings.Split(dbname, "?")
|
||||
dbname = urls[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
if dbname == "" {
|
||||
|
||||
10
app/init.go
10
app/init.go
@@ -129,7 +129,7 @@ func init() {
|
||||
if tags == nil || len(tags) == 0 {
|
||||
return ""
|
||||
}
|
||||
locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string)
|
||||
locale, _ := renderArgs[revel.CurrentLocaleViewArg].(string)
|
||||
tagStr := ""
|
||||
lenTags := len(tags)
|
||||
|
||||
@@ -183,7 +183,7 @@ func init() {
|
||||
}
|
||||
|
||||
revel.TemplateFuncs["msg"] = func(renderArgs map[string]interface{}, message string, args ...interface{}) template.HTML {
|
||||
str, ok := renderArgs[revel.CurrentLocaleRenderArg].(string)
|
||||
str, ok := renderArgs[revel.CurrentLocaleViewArg].(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
@@ -192,7 +192,7 @@ func init() {
|
||||
|
||||
// 不用revel的msg
|
||||
revel.TemplateFuncs["leaMsg"] = func(renderArgs map[string]interface{}, key string) template.HTML {
|
||||
locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string)
|
||||
locale, _ := renderArgs[revel.CurrentLocaleViewArg].(string)
|
||||
str := i18n.Message(locale, key)
|
||||
if strings.HasPrefix(str, "???") {
|
||||
str = key
|
||||
@@ -205,7 +205,7 @@ func init() {
|
||||
if tags == nil || len(tags) == 0 {
|
||||
return ""
|
||||
}
|
||||
locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string)
|
||||
locale, _ := renderArgs[revel.CurrentLocaleViewArg].(string)
|
||||
tagStr := ""
|
||||
lenTags := len(tags)
|
||||
|
||||
@@ -307,7 +307,7 @@ func init() {
|
||||
|
||||
// http://stackoverflow.com/questions/14226416/go-lang-templates-always-quotes-a-string-and-removes-comments
|
||||
revel.TemplateFuncs["rawMsg"] = func(renderArgs map[string]interface{}, message string, args ...interface{}) template.JS {
|
||||
str, ok := renderArgs[revel.CurrentLocaleRenderArg].(string)
|
||||
str, ok := renderArgs[revel.CurrentLocaleViewArg].(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -6,21 +6,21 @@ import (
|
||||
"github.com/revel/revel"
|
||||
)
|
||||
|
||||
func Log(i ...interface{}) {
|
||||
revel.INFO.Println(i...)
|
||||
func Log(msg string, i ...interface{}) {
|
||||
revel.AppLog.Info(msg, i...)
|
||||
}
|
||||
|
||||
func LogW(i ...interface{}) {
|
||||
revel.WARN.Println(i...)
|
||||
func Logf(msg string, i ...interface{}) {
|
||||
revel.AppLog.Infof(msg, i...)
|
||||
}
|
||||
|
||||
func Log1(key, i interface{}) {
|
||||
revel.INFO.Println(key, i)
|
||||
func LogW(msg string, i ...interface{}) {
|
||||
revel.AppLog.Warn(msg, i...)
|
||||
}
|
||||
|
||||
func LogJ(i interface{}) {
|
||||
b, _ := json.MarshalIndent(i, "", " ")
|
||||
revel.INFO.Println(string(b))
|
||||
revel.AppLog.Info(string(b))
|
||||
}
|
||||
|
||||
// 为test用
|
||||
|
||||
@@ -79,7 +79,6 @@ func SendEmailOld(to, subject, body string) bool {
|
||||
err := smtp.SendMail(host+":"+port, auth, username, send_to, msg)
|
||||
|
||||
if err != nil {
|
||||
Log(err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -183,7 +183,6 @@ func PutFileStrContent(path, content string) bool {
|
||||
// Log(path)
|
||||
|
||||
if err1 != nil {
|
||||
Log(err1)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -400,9 +400,6 @@ func FixFilename(filename string) string {
|
||||
func IsValidTime(t time.Time) bool {
|
||||
if t.Year() > 20 {
|
||||
now := time.Now()
|
||||
Log("------")
|
||||
Log(t)
|
||||
Log(now)
|
||||
if t.Before(now) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ var CloneTemplate *template.Template
|
||||
type RenderTemplateResult struct {
|
||||
Template *template.Template
|
||||
PathContent map[string]string
|
||||
RenderArgs map[string]interface{}
|
||||
ViewArgs map[string]interface{}
|
||||
|
||||
IsPreview bool // 是否是预览
|
||||
CurBlogTpl *BlogTpl
|
||||
@@ -62,7 +62,7 @@ func parseTemplateError(err error) (templateName string, line int, description s
|
||||
return templateName, line, description
|
||||
}
|
||||
func (r *RenderTemplateResult) render(req *revel.Request, resp *revel.Response, wr io.Writer) {
|
||||
err := r.Template.Execute(wr, r.RenderArgs)
|
||||
err := r.Template.Execute(wr, r.ViewArgs)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func (r *RenderTemplateResult) render(req *revel.Request, resp *revel.Response,
|
||||
// 这里, 错误!!
|
||||
// 这里应该导向到本主题的错误页面
|
||||
resp.Status = 500
|
||||
ErrorResult{r.RenderArgs, compileError, r.IsPreview, r.CurBlogTpl}.Apply(req, resp)
|
||||
ErrorResult{r.ViewArgs, compileError, r.IsPreview, r.CurBlogTpl}.Apply(req, resp)
|
||||
}
|
||||
|
||||
func (r *RenderTemplateResult) Apply(req *revel.Request, resp *revel.Response) {
|
||||
@@ -104,7 +104,7 @@ func (r *RenderTemplateResult) Apply(req *revel.Request, resp *revel.Response) {
|
||||
chunked := revel.Config.BoolDefault("results.chunked", false)
|
||||
|
||||
// If it's a HEAD request, throw away the bytes.
|
||||
out := io.Writer(resp.Out)
|
||||
out := io.Writer(resp.GetWriter())
|
||||
if req.Method == "HEAD" {
|
||||
out = ioutil.Discard
|
||||
}
|
||||
@@ -162,7 +162,7 @@ func RenderTemplate(name string, args map[string]interface{}, basePath string, i
|
||||
r = &RenderTemplateResult{
|
||||
Template: t,
|
||||
PathContent: BlogTplObject.PathContent, // 为了显示错误
|
||||
RenderArgs: args, // 把args给它
|
||||
ViewArgs: args, // 把args给它
|
||||
}
|
||||
} else {
|
||||
// 复制一份
|
||||
@@ -202,7 +202,7 @@ func RenderTemplate(name string, args map[string]interface{}, basePath string, i
|
||||
r = &RenderTemplateResult{
|
||||
Template: t,
|
||||
PathContent: newBlogTplObject.PathContent, // 为了显示错误
|
||||
RenderArgs: args,
|
||||
ViewArgs: args,
|
||||
CurBlogTpl: newBlogTplObject,
|
||||
IsPreview: isPreview,
|
||||
}
|
||||
@@ -215,7 +215,7 @@ func RenderTemplate(name string, args map[string]interface{}, basePath string, i
|
||||
//
|
||||
|
||||
type ErrorResult struct {
|
||||
RenderArgs map[string]interface{}
|
||||
ViewArgs map[string]interface{}
|
||||
Error error
|
||||
IsPreview bool
|
||||
CurBlogTpl *BlogTpl
|
||||
@@ -280,18 +280,18 @@ func (r ErrorResult) Apply(req *revel.Request, resp *revel.Response) {
|
||||
panic("no error provided")
|
||||
}
|
||||
|
||||
if r.RenderArgs == nil {
|
||||
r.RenderArgs = make(map[string]interface{})
|
||||
if r.ViewArgs == nil {
|
||||
r.ViewArgs = make(map[string]interface{})
|
||||
}
|
||||
r.RenderArgs["Error"] = revelError
|
||||
r.RenderArgs["Router"] = revel.MainRouter
|
||||
r.ViewArgs["Error"] = revelError
|
||||
r.ViewArgs["Router"] = revel.MainRouter
|
||||
|
||||
// 不是preview就不要显示错误了
|
||||
if r.IsPreview {
|
||||
var b bytes.Buffer
|
||||
out := io.Writer(resp.Out)
|
||||
out := io.Writer(resp.GetWriter())
|
||||
// out = ioutil.Discard
|
||||
err = tmpl.Execute(&b, r.RenderArgs)
|
||||
err = tmpl.Execute(&b, r.ViewArgs)
|
||||
resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8")
|
||||
b.WriteTo(out)
|
||||
}
|
||||
|
||||
@@ -8,10 +8,11 @@ import (
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
)
|
||||
|
||||
const (
|
||||
CurrentLocaleRenderArg = "currentLocale" // The key for the current locale render arg value
|
||||
CurrentLocaleViewArg = "currentLocale" // The key for the current locale render arg value
|
||||
|
||||
messageFilesDirectory = "messages"
|
||||
messageFilePattern = `^\w+\.conf$`
|
||||
@@ -146,15 +147,15 @@ func loadMessageFile(locale string, path string, info os.FileInfo, osError error
|
||||
// If we have already parsed a message file for this locale, merge both
|
||||
if _, exists := messages[locale]; exists {
|
||||
messages[locale].Merge(config)
|
||||
revel.TRACE.Printf("Successfully merged messages for locale '%s'", locale)
|
||||
Logf("Successfully merged messages for locale '%s'", locale)
|
||||
} else {
|
||||
messages[locale] = config
|
||||
}
|
||||
|
||||
revel.TRACE.Println("Successfully loaded messages from file", info.Name())
|
||||
Logf("Successfully loaded messages from file", info.Name())
|
||||
}
|
||||
} else {
|
||||
revel.TRACE.Printf("Ignoring file %s because it did not have a valid extension", info.Name())
|
||||
Logf("Ignoring file %s because it did not have a valid extension", info.Name())
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -178,13 +179,13 @@ func init() {
|
||||
|
||||
func I18nFilter(c *revel.Controller, fc []revel.Filter) {
|
||||
if foundCookie, cookieValue := hasLocaleCookie(c.Request); foundCookie {
|
||||
revel.TRACE.Printf("Found locale cookie value: %s", cookieValue)
|
||||
// revel.TRACE.Printf("Found locale cookie value: %s", cookieValue)
|
||||
setCurrentLocaleControllerArguments(c, cookieValue)
|
||||
} else if foundHeader, headerValue := hasAcceptLanguageHeader(c.Request); foundHeader {
|
||||
revel.TRACE.Printf("Found Accept-Language header value: %s", headerValue)
|
||||
// revel.TRACE.Printf("Found Accept-Language header value: %s", headerValue)
|
||||
setCurrentLocaleControllerArguments(c, headerValue)
|
||||
} else {
|
||||
revel.TRACE.Println("Unable to find locale in cookie or header, using empty string")
|
||||
// revel.TRACE.Println("Unable to find locale in cookie or header, using empty string")
|
||||
setCurrentLocaleControllerArguments(c, "")
|
||||
}
|
||||
fc[0](c, fc[1:])
|
||||
@@ -193,7 +194,7 @@ func I18nFilter(c *revel.Controller, fc []revel.Filter) {
|
||||
// Set the current locale controller argument (CurrentLocaleControllerArg) with the given locale.
|
||||
func setCurrentLocaleControllerArguments(c *revel.Controller, locale string) {
|
||||
c.Request.Locale = locale
|
||||
c.RenderArgs[CurrentLocaleRenderArg] = locale
|
||||
c.ViewArgs[CurrentLocaleViewArg] = locale
|
||||
}
|
||||
|
||||
// Determine whether the given request has valid Accept-Language value.
|
||||
@@ -210,12 +211,12 @@ func hasAcceptLanguageHeader(request *revel.Request) (bool, string) {
|
||||
|
||||
// Determine whether the given request has a valid language cookie value.
|
||||
func hasLocaleCookie(request *revel.Request) (bool, string) {
|
||||
if request != nil && request.Cookies() != nil {
|
||||
if request != nil {
|
||||
name := revel.Config.StringDefault(localeCookieConfigKey, revel.CookiePrefix+"_LANG")
|
||||
if cookie, error := request.Cookie(name); error == nil {
|
||||
return true, cookie.Value
|
||||
return true, cookie.GetValue()
|
||||
} else {
|
||||
revel.TRACE.Printf("Unable to read locale cookie with name '%s': %s", name, error.Error())
|
||||
// revel.TRACE.Printf("Unable to read locale cookie with name '%s': %s", name, error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ func WriteUrl(url string, toPath string) (length int64, newFilename, path string
|
||||
func GetContent(url string) (content []byte, err error) {
|
||||
var resp *http.Response
|
||||
resp, err = http.Get(url)
|
||||
Log(err)
|
||||
if resp != nil && resp.Body != nil {
|
||||
defer resp.Body.Close()
|
||||
} else {
|
||||
@@ -65,7 +64,6 @@ func GetContent(url string) (content []byte, err error) {
|
||||
var buf []byte
|
||||
buf, err = ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
Log(err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package route
|
||||
import (
|
||||
"github.com/leanote/leanote/app/db"
|
||||
"github.com/revel/revel"
|
||||
// . "github.com/leanote/leanote/app/lea"
|
||||
// . "github.com/leanote/leanote/app/lea"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
@@ -14,15 +14,19 @@ var staticPrefix = []string{"/public", "/favicon.ico", "/css", "/js", "/images",
|
||||
|
||||
func RouterFilter(c *revel.Controller, fc []revel.Filter) {
|
||||
// 补全controller部分
|
||||
path := c.Request.Request.URL.Path
|
||||
path := c.Request.URL.Path
|
||||
|
||||
// Figure out the Controller/Action
|
||||
var route *revel.RouteMatch = revel.MainRouter.Route(c.Request.Request)
|
||||
// var route *revel.RouteMatch = revel.MainRouter.Route(c.Request.Request)
|
||||
route := revel.MainRouter.Route(c.Request)
|
||||
|
||||
if route == nil {
|
||||
c.Result = c.NotFound("No matching route found: " + c.Request.RequestURI)
|
||||
c.Result = c.NotFound("No matching route found: " + c.Request.GetRequestURI())
|
||||
return
|
||||
}
|
||||
|
||||
// Log("---------" + route.Action + " " + path)
|
||||
|
||||
// The route may want to explicitly return a 404.
|
||||
if route.Action == "404" {
|
||||
c.Result = c.NotFound("(intentionally)")
|
||||
@@ -47,14 +51,23 @@ func RouterFilter(c *revel.Controller, fc []revel.Filter) {
|
||||
// 检查mongodb 是否lost
|
||||
db.CheckMongoSessionLost()
|
||||
|
||||
// /api/file/getImage -> App\file (/api/file/getImage)
|
||||
// App\auth
|
||||
// App\note
|
||||
// static\static
|
||||
//
|
||||
// Log("---------" + route.ControllerName + " " + path)
|
||||
|
||||
// api设置
|
||||
// leanote.com/api/user/get => ApiUser::Get
|
||||
//* /api/login ApiAuth.Login, 这里的设置, 其实已经转成了ApiAuth了
|
||||
if strings.HasPrefix(path, "/api") && !strings.HasPrefix(route.ControllerName, "Api") {
|
||||
route.ControllerName = "Api" + route.ControllerName
|
||||
} else if strings.HasPrefix(path, "/member") && !strings.HasPrefix(route.ControllerName, "Member") {
|
||||
if strings.HasPrefix(path, "/api") && !strings.HasPrefix(route.ControllerName, "App\\api") {
|
||||
route.ControllerName = "App\\api" + strings.Split(route.ControllerName, "\\")[1]
|
||||
// route.ControllerName = "App\\apifile"
|
||||
} else if strings.HasPrefix(path, "/member") && !strings.HasPrefix(route.ControllerName, "App\\member") {
|
||||
// member设置
|
||||
route.ControllerName = "Member" + route.ControllerName
|
||||
// route.ControllerName = "App\\Member" + route.ControllerName
|
||||
route.ControllerName = "App\\member" + strings.Split(route.ControllerName, "\\")[1]
|
||||
}
|
||||
// end
|
||||
}
|
||||
@@ -78,7 +91,7 @@ func RouterFilter(c *revel.Controller, fc []revel.Filter) {
|
||||
arg := c.MethodType.Args[i]
|
||||
c.Params.Fixed.Set(arg.Name, value)
|
||||
} else {
|
||||
revel.WARN.Println("Too many parameters to", route.Action, "trying to add", value)
|
||||
// revel.WARN.Println("Too many parameters to", route.Action, "trying to add", value)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Compress and combine js files
|
||||
@@ -1,159 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
// "time"
|
||||
)
|
||||
|
||||
/*
|
||||
用golang exec 总是说找不到uglifyjs命令, 需要全部路径
|
||||
而且node, npm要在/usr/bin下, 已建ln
|
||||
*/
|
||||
|
||||
/*
|
||||
<script src="js/jquery-1.9.0.min.js"></script>
|
||||
|
||||
<!-- 以后将所有的js压缩合并成一个文件 -->
|
||||
<script src="js/jquery-cookie.js"></script>
|
||||
<script src="js/bootstrap.js"></script>
|
||||
<script type="text/javascript" src="tinymce/tinymce.js"></script>
|
||||
<script src="js/common.js"></script>
|
||||
<script src="js/app/note.js"></script>
|
||||
<script src="js/app/tag.js"></script>
|
||||
<script src="js/app/notebook.js"></script>
|
||||
<script src="js/app/share.js"></script>
|
||||
<script src="js/object_id.js"></script>
|
||||
<script type="text/javascript" src="js/ZeroClipboard/ZeroClipboard.js"></script>
|
||||
*/
|
||||
|
||||
//var jss = []string{"js/jquery-cookie", "js/bootstrap"}
|
||||
var jss = []string{"js/jquery-cookie", "js/bootstrap",
|
||||
"js/common", "js/app/note", "js/app/tag", "js/app/notebook", "js/app/share",
|
||||
"js/object_id", "js/ZeroClipboard/ZeroClipboard"}
|
||||
|
||||
var base1 = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/"
|
||||
var base = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/public/"
|
||||
var cmdPath = "/usr/local/bin/uglifyjs"
|
||||
|
||||
func cmdError(err error) {
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Fprintf(os.Stderr, "The command failed to perform: %s (Command: %s, Arguments: %s)", err, "", "")
|
||||
} else {
|
||||
fmt.Println("OK")
|
||||
}
|
||||
}
|
||||
|
||||
// filename没有扩展名
|
||||
func compressJs(filename string) {
|
||||
source := base + filename + ".js"
|
||||
to := base + filename + "-min.js"
|
||||
cmd := exec.Command(cmdPath, source, "-o", to)
|
||||
_, err := cmd.CombinedOutput()
|
||||
fmt.Println(source)
|
||||
cmdError(err)
|
||||
}
|
||||
|
||||
func combineJs() {
|
||||
// 生成一个总文件
|
||||
cmd := exec.Command("rm", base+"js/all.js")
|
||||
_, err := cmd.CombinedOutput()
|
||||
cmdError(err)
|
||||
|
||||
for _, js := range jss {
|
||||
to := base + js + "-min.js"
|
||||
fmt.Println(to)
|
||||
compressJs(js)
|
||||
|
||||
// 每个压缩后的文件放入之
|
||||
cmd2 := exec.Command("/bin/sh", "-c", "cat "+to+" >> "+base+"js/all.js")
|
||||
_, err := cmd2.CombinedOutput()
|
||||
cmdError(err)
|
||||
cmd2 = exec.Command("/bin/sh", "-c", "cat \n >> "+base+"js/all.js")
|
||||
_, err = cmd2.CombinedOutput()
|
||||
cmdError(err)
|
||||
}
|
||||
}
|
||||
|
||||
// 改note-dev->note
|
||||
func dev() {
|
||||
// 即替换note.js->note-min.js
|
||||
m := map[string]string{"tinymce.dev.js": "tinymce.min.js",
|
||||
"tinymce.js": "tinymce.min.js",
|
||||
"jquery.ztree.all-3.5.js": "jquery.ztree.all-3.5-min.js",
|
||||
"note.js": "note-min.js",
|
||||
"app.js": "app-min.js",
|
||||
"page.js": "page-min.js",
|
||||
"common.js": "common-min.js",
|
||||
"notebook.js": "notebook-min.js",
|
||||
"share.js": "share-min.js",
|
||||
"tag.js": "tag-min.js",
|
||||
"jquery.slimscroll.js": "jquery.slimscroll-min.js",
|
||||
"jquery.contextmenu.js": "jquery.contextmenu-min.js",
|
||||
"editor/editor.js": "editor/editor-min.js",
|
||||
"/public/mdeditor/editor/scrollLink.js": "/public/mdeditor/editor/scrollLink-min.js",
|
||||
"console.log(o);": "",
|
||||
}
|
||||
path := base1 + "/src/views/note/note-dev.html"
|
||||
target := base1 + "/src/views/note/note.html"
|
||||
|
||||
bs, _ := ioutil.ReadFile(path)
|
||||
content := string(bs)
|
||||
print(content)
|
||||
for key, value := range m {
|
||||
content = strings.Replace(content, key, value, -1)
|
||||
}
|
||||
|
||||
// var time = time.Now().Unix() % 1000
|
||||
|
||||
// content = strings.Replace(content, "-min.js", fmt.Sprintf("-min.js?r=%d", time), -1)
|
||||
// content = strings.Replace(content, "default{{end}}.css", fmt.Sprintf("default{{end}}.css?r=%d", time), 1)
|
||||
// content = strings.Replace(content, "writting-overwrite.css", fmt.Sprintf("writting-overwrite.css?r=%d", time), 1)
|
||||
|
||||
ioutil.WriteFile(target, []byte(content), os.ModeAppend)
|
||||
}
|
||||
|
||||
// 压缩js成一块
|
||||
func tinymce() {
|
||||
// cmdStr := "node_modules/jake/bin/cli.js minify bundle[themes:modern,plugins:table,paste,advlist,autolink,link,image,lists,charmap,hr,searchreplace,visualblocks,visualchars,code,nav,tabfocus,contextmenu,directionality,codemirror,codesyntax,textcolor,fullpage]"
|
||||
// cmd := exec.Command("/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master/node_modules/jake/bin/cli.js", "minify", "bundle[themes:modern,plugins:table,paste,advlist,autolink,link,image,lists,charmap,hr,searchreplace,visualblocks,visualchars,code,nav,tabfocus,contextmenu,directionality,codemirror,codesyntax,textcolor,fullpage]")
|
||||
cmd := exec.Command("/bin/sh", "-c", "grunt minify")
|
||||
cmd.Dir = base + "/tinymce_4.1.9"
|
||||
|
||||
fmt.Println("正在build tinymce")
|
||||
|
||||
// 必须要先删除
|
||||
cmd2 := exec.Command("/bin/sh", "-c", "rm "+cmd.Dir+"/js/tinymce/tinymce.dev.js")
|
||||
cmd2.CombinedOutput()
|
||||
cmd2 = exec.Command("/bin/sh", "-c", "rm "+cmd.Dir+"/js/tinymce/tinymce.jquery.dev.js")
|
||||
c, _ := cmd2.CombinedOutput()
|
||||
fmt.Println(string(c))
|
||||
|
||||
c, _ = cmd.CombinedOutput()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 压缩tinymce
|
||||
// tinymce()
|
||||
|
||||
dev()
|
||||
|
||||
// 其它零散的需要压缩的js
|
||||
otherJss := []string{"js/main", "js/app/page", "js/contextmenu/jquery.contextmenu",
|
||||
"js/jquery.ztree.all-3.5",
|
||||
"js/jQuery-slimScroll-1.3.0/jquery.slimscroll",
|
||||
}
|
||||
|
||||
for _, js := range otherJss {
|
||||
compressJs(js)
|
||||
}
|
||||
|
||||
// 先压缩后合并
|
||||
combineJs()
|
||||
|
||||
}
|
||||
@@ -606,5 +606,5 @@ func (this *ConfigService) HomePageIsAdminsBlog() bool {
|
||||
}
|
||||
|
||||
func (this *ConfigService) GetVersion() string {
|
||||
return "2.4"
|
||||
return "2.6.1"
|
||||
}
|
||||
|
||||
@@ -616,7 +616,7 @@ func (this *NoteService) UpdateNoteContent(updatedUserId, noteId, content, abstr
|
||||
return false, "conflict", 0
|
||||
}
|
||||
afterUsn = userService.IncrUsn(userId)
|
||||
db.UpdateByIdAndUserIdField(db.Notes, noteId, userId, "Usn", usn)
|
||||
db.UpdateByIdAndUserIdField(db.Notes, noteId, userId, "Usn", afterUsn)
|
||||
}
|
||||
|
||||
if db.UpdateByIdAndUserIdMap(db.NoteContents, noteId, userId, data) {
|
||||
@@ -1106,7 +1106,7 @@ func (this *NoteService) FixContent(content string, isMarkdown bool) string {
|
||||
reg2, _ = regexp.Compile("<a(?:[^>]+?)(" + eachPattern["src"] + `=['"]*` + baseUrlPattern + eachPattern["middle"] + `\?` + eachPattern["param"] + `=([a-z0-9A-Z]{24})["']*)[^>]*>`)
|
||||
}
|
||||
|
||||
Log(reg2)
|
||||
// Log(reg2)
|
||||
|
||||
content = reg.ReplaceAllStringFunc(content, func(str string) string {
|
||||
// str=这样的
|
||||
|
||||
@@ -360,8 +360,8 @@ func (this *NotebookService) DragNotebooks(userId string, curNotebookId string,
|
||||
func (this *NotebookService) ReCountNotebookNumberNotes(notebookId string) bool {
|
||||
notebookIdO := bson.ObjectIdHex(notebookId)
|
||||
count := db.Count(db.Notes, bson.M{"NotebookId": notebookIdO, "IsTrash": false, "IsDeleted": false})
|
||||
Log(count)
|
||||
Log(notebookId)
|
||||
// Log(count)
|
||||
// Log(notebookId)
|
||||
return db.UpdateByQField(db.Notebooks, bson.M{"_id": notebookIdO}, "NumberNotes", count)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package service
|
||||
import (
|
||||
"github.com/leanote/leanote/app/db"
|
||||
"github.com/leanote/leanote/app/info"
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
// . "github.com/leanote/leanote/app/lea"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
"time"
|
||||
// "strings"
|
||||
@@ -66,10 +66,10 @@ func (this *SessionService) GetCaptcha(sessionId string) string {
|
||||
}
|
||||
func (this *SessionService) SetCaptcha(sessionId, captcha string) bool {
|
||||
this.Get(sessionId)
|
||||
Log(sessionId)
|
||||
Log(captcha)
|
||||
// Log(sessionId)
|
||||
// Log(captcha)
|
||||
ok := this.Update(sessionId, "Captcha", captcha)
|
||||
Log(ok)
|
||||
// Log(ok)
|
||||
return ok
|
||||
}
|
||||
|
||||
|
||||
@@ -311,7 +311,7 @@ func (this *ThemeService) UpdateTplContent(userId, themeId, filename, content st
|
||||
basePath := this.GetThemeAbsolutePath(userId, themeId)
|
||||
path := basePath + "/" + filename
|
||||
if strings.Contains(filename, ".html") {
|
||||
Log(">>")
|
||||
// Log(">>")
|
||||
if ok, msg = this.ValidateTheme(basePath, filename, content); ok {
|
||||
// 模板
|
||||
if ok, msg = this.mustTpl(filename, content); ok {
|
||||
@@ -359,7 +359,7 @@ func (this *ThemeService) mustTpl(filename, content string) (ok bool, msg string
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
ok = false
|
||||
Log(err)
|
||||
// Log(err)
|
||||
msg = fmt.Sprintf("%v", err)
|
||||
}
|
||||
}()
|
||||
@@ -405,7 +405,7 @@ func (this *ThemeService) ExportTheme(userId, themeId string) (ok bool, path str
|
||||
theme := this.GetThemeById(themeId)
|
||||
// 打包
|
||||
// 验证路径, 别把整个项目打包了
|
||||
Log(theme.Path)
|
||||
// Log(theme.Path)
|
||||
if theme.Path == "" ||
|
||||
(!strings.HasPrefix(theme.Path, "public/upload") &&
|
||||
!strings.HasPrefix(theme.Path, "public/blog/themes")) ||
|
||||
@@ -417,12 +417,12 @@ func (this *ThemeService) ExportTheme(userId, themeId string) (ok bool, path str
|
||||
targetPath := revel.BasePath + "/public/upload/" + userId + "/tmp"
|
||||
err := os.MkdirAll(targetPath, 0755)
|
||||
if err != nil {
|
||||
Log(err)
|
||||
// Log(err)
|
||||
return
|
||||
}
|
||||
targetName := targetPath + "/" + theme.Name + ".zip"
|
||||
Log(sourcePath)
|
||||
Log(targetName)
|
||||
// Log(sourcePath)
|
||||
// Log(targetName)
|
||||
ok = archive.Zip(sourcePath, targetName)
|
||||
if !ok {
|
||||
return
|
||||
@@ -445,7 +445,7 @@ func (this *ThemeService) ImportTheme(userId, path string) (ok bool, msg string)
|
||||
}
|
||||
if ok, msg = archive.Unzip(path, targetPath); !ok {
|
||||
DeleteFile(targetPath)
|
||||
Log("oh no")
|
||||
// Log("oh no")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -558,8 +558,8 @@ func (this *ThemeService) InstallTheme(userId, themeId string) (ok bool) {
|
||||
// 验证主题是否全法, 存在循环引用?
|
||||
// filename, newContent 表示在修改模板时要判断模板修改时是否有错误
|
||||
func (this *ThemeService) ValidateTheme(path string, filename, newContent string) (ok bool, msg string) {
|
||||
Log("theme Path")
|
||||
Log(path)
|
||||
// Log("theme Path")
|
||||
// Log(path)
|
||||
// 建立一个有向图
|
||||
// 将该path下的所有文件提出, 得到文件的引用情况
|
||||
files := ListDir(path)
|
||||
@@ -613,9 +613,9 @@ func (this *ThemeService) ValidateTheme(path string, filename, newContent string
|
||||
for _, includes := range finds {
|
||||
include := includes[1]
|
||||
includeIndex, has := fileIndexMap[include]
|
||||
Log(includeIndex)
|
||||
Log("??")
|
||||
Log(has)
|
||||
// Log(includeIndex)
|
||||
// Log("??")
|
||||
// Log(has)
|
||||
if has {
|
||||
vector[thisIndex][includeIndex] = 1
|
||||
}
|
||||
|
||||
@@ -485,7 +485,7 @@ func (this *UserService) GetAllUserByFilter(userFilterEmail, userFilterWhiteList
|
||||
users := []info.User{}
|
||||
q := db.Users.Find(query)
|
||||
q.All(&users)
|
||||
Log(len(users))
|
||||
// Log(len(users))
|
||||
|
||||
return users
|
||||
}
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="col-sm-8">
|
||||
<form id="add_user_form">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label>Wkhtmltopdf Binary Path</label>
|
||||
<input type="text" class="form-control" placeholder="/usr/local/bin/wkhtmltopdf" name="path" value="{{.str.exportPdfBinPath}}">
|
||||
<input type="text" class="form-control" placeholder="/usr/local/bin/wkhtmltopdf or C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe" name="path" value="{{.str.exportPdfBinPath}}">
|
||||
Leanote use <a target="_blank" href="http://wkhtmltopdf.org">wkhtmltopdf</a> to export pdf. You should install it on your server.
|
||||
<br />
|
||||
Please input the path that wkhtmltopdf installed, e.g. <code>/usr/local/bin/wkhtmltopdf</code>
|
||||
Please input the path that wkhtmltopdf installed, e.g. <code>/usr/local/bin/wkhtmltopdf</code> on mac os/linux or <code>C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe</code> on windows.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ function log(o) {
|
||||
<a data-lang="zh-cn">简体中文</a>
|
||||
<a data-lang="zh-hk">繁体中文</a>
|
||||
<a data-lang="pt-pt">Português</a>
|
||||
<a data-lang="es-co">Spanish</a>
|
||||
</div>
|
||||
|
||||
<ul class="nav navbar-nav navbar-left">
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
name="sortField"
|
||||
value="">
|
||||
<option value="PublicTime" {{if eq $.userBlog.SortField "PublicTime"}}selected{{end}}>{{msg $ "publicTime"}}</option>
|
||||
<option value="CreatedTime" {{if eq $.userBlog.SortField "CreatedTimeTime"}}selected{{end}}>{{msg $ "createdTime"}}</option>
|
||||
<option value="CreatedTime" {{if eq $.userBlog.SortField "CreatedTime"}}selected{{end}}>{{msg $ "createdTime"}}</option>
|
||||
<option value="UpdatedTime" {{if eq $.userBlog.SortField "UpdatedTime"}}selected{{end}}>{{msg $ "updatedTime"}}</option>
|
||||
<option value="Title" {{if eq $.userBlog.SortField "Title"}}selected{{end}}>{{msg . "title"}}</option>
|
||||
</select>
|
||||
@@ -49,7 +49,7 @@
|
||||
{{template "member/footer.html" .}}
|
||||
<script>
|
||||
var urlPrefix = "{{.siteUrl}}";
|
||||
$(function() {
|
||||
$(function() {
|
||||
// domain
|
||||
$("#baseBtn").click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
152
bin/release.sh
152
bin/release.sh
@@ -1,152 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# release leanote
|
||||
|
||||
# 当前路径
|
||||
SP=$(cd "$(dirname "$0")"; pwd)
|
||||
|
||||
# tmp path to store leanote release files
|
||||
tmp="/Users/life/Desktop/leanote_release"
|
||||
|
||||
# version
|
||||
V="v2.4"
|
||||
|
||||
##=================================
|
||||
# 1. 先build 成 3个平台, 2种bit = 6种
|
||||
##=================================
|
||||
|
||||
# cd /Documents/Go/package2/src/github.com/leanote/leanote/bin
|
||||
# GOOS=darwin GOARCH=amd64 go build -o leanote-darwin-amd64 ../app/tmp
|
||||
|
||||
cd $SP
|
||||
|
||||
# $1 = darwin, linux
|
||||
# $2 = amd64
|
||||
function build()
|
||||
{
|
||||
echo build-$1-$2
|
||||
if [ $1 = "linux" -o $1 = "darwin" ]
|
||||
then
|
||||
suffix=""
|
||||
else
|
||||
suffix=".exe"
|
||||
fi
|
||||
|
||||
GOOS=$1 GOARCH=$2 go build -o leanote-$1-$2$suffix ../app/tmp
|
||||
}
|
||||
|
||||
build "linux" "386";
|
||||
build "linux" "amd64";
|
||||
build "linux" "arm";
|
||||
|
||||
build "windows" "386";
|
||||
build "windows" "amd64";
|
||||
|
||||
# build "darwin" "386";
|
||||
build "darwin" "amd64";
|
||||
|
||||
|
||||
##======================
|
||||
# 2. release目录准备工作
|
||||
##======================
|
||||
rm -rf $tmp/leanote
|
||||
mkdir -p $tmp/leanote/app
|
||||
mkdir -p $tmp/leanote/conf
|
||||
mkdir -p $tmp/leanote/bin
|
||||
|
||||
##==================
|
||||
# 3. 复制
|
||||
##==================
|
||||
|
||||
cd $SP
|
||||
cd ../
|
||||
|
||||
# bin
|
||||
cp -r ./bin/src $tmp/leanote/bin/
|
||||
cp ./bin/run.sh $tmp/leanote/bin/
|
||||
cp ./bin/run.bat $tmp/leanote/bin/
|
||||
|
||||
# views
|
||||
cp -r ./app/views $tmp/leanote/app
|
||||
# 可不要, 源码
|
||||
#cp -r ./app/service $tmp/leanote/app/service
|
||||
#cp -r ./app/controllers $tmp/leanote/app/controllers
|
||||
#cp -r ./app/db $tmp/leanote/app/db
|
||||
#cp -r ./app/info $tmp/leanote/app/info
|
||||
#cp -r ./app/lea $tmp/leanote/app/lea
|
||||
|
||||
# conf
|
||||
cp ./conf/app.conf $tmp/leanote/conf/app.conf
|
||||
cp ./conf/routes $tmp/leanote/conf/routes
|
||||
# 处理app.conf, 还原配置
|
||||
cat $tmp/leanote/conf/app.conf | sed 's/db.dbname=leanote.*#/db.dbname=leanote #/' > $tmp/leanote/conf/app.conf2 # 不能直接覆盖
|
||||
rm $tmp/leanote/conf/app.conf
|
||||
mv $tmp/leanote/conf/app.conf2 $tmp/leanote/conf/app.conf
|
||||
|
||||
# others
|
||||
cp -r ./messages ./public ./mongodb_backup $tmp/leanote/
|
||||
|
||||
# delete some files
|
||||
rm -r $tmp/leanote/public/tinymce/classes
|
||||
rm -r $tmp/leanote/public/upload
|
||||
mkdir $tmp/leanote/public/upload
|
||||
rm -r $tmp/leanote/public/.codekit-cache
|
||||
rm $tmp/leanote/public/.DS_Store
|
||||
rm $tmp/leanote/public/config.codekit
|
||||
|
||||
# make link
|
||||
# cd $tmp/leanote/bin
|
||||
# ln -s ../../../../ ./src/github.com/leanote/leanote
|
||||
|
||||
# archieve
|
||||
# << 'BLOCK
|
||||
|
||||
##===========
|
||||
# 4. 打包
|
||||
##===========
|
||||
# $1 = linux
|
||||
# $2 = 386, amd64
|
||||
|
||||
# 创建一个$V的目录存放之
|
||||
rm -rf $tmp/$V
|
||||
mkdir $tmp/$V
|
||||
|
||||
function tarRelease()
|
||||
{
|
||||
echo tar-$1-$2
|
||||
cd $SP
|
||||
cd ../
|
||||
rm $tmp/leanote/bin/leanote-* # 删除之前的bin文件
|
||||
rm $tmp/leanote/bin/run* # 删除之前的run.sh 或 run.bat
|
||||
|
||||
if [ $1 = "linux" -o $1 = "darwin" ]
|
||||
then
|
||||
suffix=""
|
||||
if [ $2 = "arm" ]
|
||||
then
|
||||
cp ./bin/run-arm.sh $tmp/leanote/bin/run.sh
|
||||
else
|
||||
cp ./bin/run-$1-$2.sh $tmp/leanote/bin/run.sh
|
||||
fi
|
||||
else
|
||||
cp ./bin/run.bat $tmp/leanote/bin/
|
||||
suffix=".exe"
|
||||
fi
|
||||
|
||||
cp ./bin/leanote-$1-$2$suffix $tmp/leanote/bin/
|
||||
cd $tmp
|
||||
tar -cf $tmp/$V/leanote-$1-$2-$V.bin.tar leanote
|
||||
gzip $tmp/$V/leanote-$1-$2-$V.bin.tar
|
||||
}
|
||||
|
||||
tarRelease "linux" "386";
|
||||
tarRelease "linux" "amd64";
|
||||
tarRelease "linux" "arm";
|
||||
|
||||
tarRelease "windows" "386";
|
||||
tarRelease "windows" "amd64";
|
||||
|
||||
# tarRelease "darwin" "386";
|
||||
tarRelease "darwin" "amd64";
|
||||
|
||||
# BLOCK'
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/bin/sh
|
||||
SCRIPTPATH=$(cd "$(dirname "$0")"; pwd)
|
||||
|
||||
# set link
|
||||
|
||||
path="$SCRIPTPATH/src/github.com/leanote"
|
||||
if [ ! -d "$path" ]; then
|
||||
mkdir -p "$path"
|
||||
fi
|
||||
rm -rf $SCRIPTPATH/src/github.com/leanote/leanote # 先删除
|
||||
ln -s ../../../../ $SCRIPTPATH/src/github.com/leanote/leanote
|
||||
|
||||
# set GOPATH
|
||||
export GOPATH=$SCRIPTPATH
|
||||
|
||||
script="$SCRIPTPATH/leanote-linux-arm"
|
||||
chmod 777 $script
|
||||
$script -importPath github.com/leanote/leanote
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/bin/sh
|
||||
SCRIPTPATH=$(cd "$(dirname "$0")"; pwd)
|
||||
|
||||
# set link
|
||||
|
||||
path="$SCRIPTPATH/src/github.com/leanote"
|
||||
if [ ! -d "$path" ]; then
|
||||
mkdir -p "$path"
|
||||
fi
|
||||
rm -rf $SCRIPTPATH/src/github.com/leanote/leanote # 先删除
|
||||
ln -s ../../../../ $SCRIPTPATH/src/github.com/leanote/leanote
|
||||
|
||||
# set GOPATH
|
||||
export GOPATH=$SCRIPTPATH
|
||||
|
||||
script="$SCRIPTPATH/leanote-darwin-amd64"
|
||||
chmod 777 $script
|
||||
$script -importPath github.com/leanote/leanote
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/bin/sh
|
||||
SCRIPTPATH=$(cd "$(dirname "$0")"; pwd)
|
||||
|
||||
# set link
|
||||
|
||||
path="$SCRIPTPATH/src/github.com/leanote"
|
||||
if [ ! -d "$path" ]; then
|
||||
mkdir -p "$path"
|
||||
fi
|
||||
rm -rf $SCRIPTPATH/src/github.com/leanote/leanote # 先删除
|
||||
ln -s ../../../../ $SCRIPTPATH/src/github.com/leanote/leanote
|
||||
|
||||
# set GOPATH
|
||||
export GOPATH=$SCRIPTPATH
|
||||
|
||||
script="$SCRIPTPATH/leanote-linux-386"
|
||||
chmod 777 $script
|
||||
$script -importPath github.com/leanote/leanote
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/bin/sh
|
||||
SCRIPTPATH=$(cd "$(dirname "$0")"; pwd)
|
||||
|
||||
# set link
|
||||
|
||||
path="$SCRIPTPATH/src/github.com/leanote"
|
||||
if [ ! -d "$path" ]; then
|
||||
mkdir -p "$path"
|
||||
fi
|
||||
rm -rf $SCRIPTPATH/src/github.com/leanote/leanote # 先删除
|
||||
ln -s ../../../../ $SCRIPTPATH/src/github.com/leanote/leanote
|
||||
|
||||
# set GOPATH
|
||||
export GOPATH=$SCRIPTPATH
|
||||
|
||||
script="$SCRIPTPATH/leanote-linux-amd64"
|
||||
chmod 777 $script
|
||||
$script -importPath github.com/leanote/leanote
|
||||
23
bin/run.bat
23
bin/run.bat
@@ -1,23 +0,0 @@
|
||||
@echo off
|
||||
|
||||
cd..
|
||||
set SCRIPTPATH=%cd%
|
||||
|
||||
: top src directory
|
||||
set path="%SCRIPTPATH%\bin\src\github.com\leanote"
|
||||
|
||||
if not exist "%path%" mkdir "%path%"
|
||||
|
||||
: create software link
|
||||
if exist "%path%\leanote" del /Q "%path%\leanote"
|
||||
mklink /D "%path%\leanote" %SCRIPTPATH%
|
||||
|
||||
: set GOPATH
|
||||
set GOPATH="%SCRIPTPATH%\bin"
|
||||
|
||||
: run
|
||||
if %processor_architecture%==x86 (
|
||||
"%SCRIPTPATH%\bin\leanote-windows-386.exe" -importPath github.com/leanote/leanote
|
||||
) else (
|
||||
"%SCRIPTPATH%\bin\leanote-windows-amd64.exe" -importPath github.com/leanote/leanote
|
||||
)
|
||||
@@ -1,545 +0,0 @@
|
||||
3dm=x-world/x-3dmf
|
||||
3dmf=x-world/x-3dmf
|
||||
7z=application/x-7z-compressed
|
||||
a=application/octet-stream
|
||||
aab=application/x-authorware-bin
|
||||
aam=application/x-authorware-map
|
||||
aas=application/x-authorware-seg
|
||||
abc=text/vndabc
|
||||
ace=application/x-ace-compressed
|
||||
acgi=text/html
|
||||
afl=video/animaflex
|
||||
ai=application/postscript
|
||||
aif=audio/aiff
|
||||
aifc=audio/aiff
|
||||
aiff=audio/aiff
|
||||
aim=application/x-aim
|
||||
aip=text/x-audiosoft-intra
|
||||
alz=application/x-alz-compressed
|
||||
ani=application/x-navi-animation
|
||||
aos=application/x-nokia-9000-communicator-add-on-software
|
||||
aps=application/mime
|
||||
arc=application/x-arc-compressed
|
||||
arj=application/arj
|
||||
art=image/x-jg
|
||||
asf=video/x-ms-asf
|
||||
asm=text/x-asm
|
||||
asp=text/asp
|
||||
asx=application/x-mplayer2
|
||||
au=audio/basic
|
||||
avi=video/x-msvideo
|
||||
avs=video/avs-video
|
||||
bcpio=application/x-bcpio
|
||||
bin=application/mac-binary
|
||||
bmp=image/bmp
|
||||
boo=application/book
|
||||
book=application/book
|
||||
boz=application/x-bzip2
|
||||
bsh=application/x-bsh
|
||||
bz2=application/x-bzip2
|
||||
bz=application/x-bzip
|
||||
c++=text/plain
|
||||
c=text/x-c
|
||||
cab=application/vnd.ms-cab-compressed
|
||||
cat=application/vndms-pkiseccat
|
||||
cc=text/x-c
|
||||
ccad=application/clariscad
|
||||
cco=application/x-cocoa
|
||||
cdf=application/cdf
|
||||
cer=application/pkix-cert
|
||||
cha=application/x-chat
|
||||
chat=application/x-chat
|
||||
chrt=application/vnd.kde.kchart
|
||||
class=application/java
|
||||
# ? class=application/java-vm
|
||||
com=text/plain
|
||||
conf=text/plain
|
||||
cpio=application/x-cpio
|
||||
cpp=text/x-c
|
||||
cpt=application/mac-compactpro
|
||||
crl=application/pkcs-crl
|
||||
crt=application/pkix-cert
|
||||
crx=application/x-chrome-extension
|
||||
csh=text/x-scriptcsh
|
||||
css=text/css
|
||||
csv=text/csv
|
||||
cxx=text/plain
|
||||
dar=application/x-dar
|
||||
dcr=application/x-director
|
||||
deb=application/x-debian-package
|
||||
deepv=application/x-deepv
|
||||
def=text/plain
|
||||
der=application/x-x509-ca-cert
|
||||
dif=video/x-dv
|
||||
dir=application/x-director
|
||||
divx=video/divx
|
||||
dl=video/dl
|
||||
dmg=application/x-apple-diskimage
|
||||
doc=application/msword
|
||||
dot=application/msword
|
||||
dp=application/commonground
|
||||
drw=application/drafting
|
||||
dump=application/octet-stream
|
||||
dv=video/x-dv
|
||||
dvi=application/x-dvi
|
||||
dwf=drawing/x-dwf=(old)
|
||||
dwg=application/acad
|
||||
dxf=application/dxf
|
||||
dxr=application/x-director
|
||||
el=text/x-scriptelisp
|
||||
elc=application/x-bytecodeelisp=(compiled=elisp)
|
||||
eml=message/rfc822
|
||||
env=application/x-envoy
|
||||
eps=application/postscript
|
||||
es=application/x-esrehber
|
||||
etx=text/x-setext
|
||||
evy=application/envoy
|
||||
exe=application/octet-stream
|
||||
f77=text/x-fortran
|
||||
f90=text/x-fortran
|
||||
f=text/x-fortran
|
||||
fdf=application/vndfdf
|
||||
fif=application/fractals
|
||||
fli=video/fli
|
||||
flo=image/florian
|
||||
flv=video/x-flv
|
||||
flx=text/vndfmiflexstor
|
||||
fmf=video/x-atomic3d-feature
|
||||
for=text/x-fortran
|
||||
fpx=image/vndfpx
|
||||
frl=application/freeloader
|
||||
funk=audio/make
|
||||
g3=image/g3fax
|
||||
g=text/plain
|
||||
gif=image/gif
|
||||
gl=video/gl
|
||||
gsd=audio/x-gsm
|
||||
gsm=audio/x-gsm
|
||||
gsp=application/x-gsp
|
||||
gss=application/x-gss
|
||||
gtar=application/x-gtar
|
||||
gz=application/x-compressed
|
||||
gzip=application/x-gzip
|
||||
h=text/x-h
|
||||
hdf=application/x-hdf
|
||||
help=application/x-helpfile
|
||||
hgl=application/vndhp-hpgl
|
||||
hh=text/x-h
|
||||
hlb=text/x-script
|
||||
hlp=application/hlp
|
||||
hpg=application/vndhp-hpgl
|
||||
hpgl=application/vndhp-hpgl
|
||||
hqx=application/binhex
|
||||
hta=application/hta
|
||||
htc=text/x-component
|
||||
htm=text/html
|
||||
html=text/html
|
||||
htmls=text/html
|
||||
htt=text/webviewhtml
|
||||
htx=text/html
|
||||
ice=x-conference/x-cooltalk
|
||||
ico=image/x-icon
|
||||
ics=text/calendar
|
||||
icz=text/calendar
|
||||
idc=text/plain
|
||||
ief=image/ief
|
||||
iefs=image/ief
|
||||
iges=application/iges
|
||||
igs=application/iges
|
||||
ima=application/x-ima
|
||||
imap=application/x-httpd-imap
|
||||
inf=application/inf
|
||||
ins=application/x-internett-signup
|
||||
ip=application/x-ip2
|
||||
isu=video/x-isvideo
|
||||
it=audio/it
|
||||
iv=application/x-inventor
|
||||
ivr=i-world/i-vrml
|
||||
ivy=application/x-livescreen
|
||||
jam=audio/x-jam
|
||||
jav=text/x-java-source
|
||||
java=text/x-java-source
|
||||
jcm=application/x-java-commerce
|
||||
jfif-tbnl=image/jpeg
|
||||
jfif=image/jpeg
|
||||
jnlp=application/x-java-jnlp-file
|
||||
jpe=image/jpeg
|
||||
jpeg=image/jpeg
|
||||
jpg=image/jpeg
|
||||
jps=image/x-jps
|
||||
js=application/javascript
|
||||
json=application/json
|
||||
jut=image/jutvision
|
||||
kar=audio/midi
|
||||
karbon=application/vnd.kde.karbon
|
||||
kfo=application/vnd.kde.kformula
|
||||
flw=application/vnd.kde.kivio
|
||||
kml=application/vnd.google-earth.kml+xml
|
||||
kmz=application/vnd.google-earth.kmz
|
||||
kon=application/vnd.kde.kontour
|
||||
kpr=application/vnd.kde.kpresenter
|
||||
kpt=application/vnd.kde.kpresenter
|
||||
ksp=application/vnd.kde.kspread
|
||||
kwd=application/vnd.kde.kword
|
||||
kwt=application/vnd.kde.kword
|
||||
ksh=text/x-scriptksh
|
||||
la=audio/nspaudio
|
||||
lam=audio/x-liveaudio
|
||||
latex=application/x-latex
|
||||
lha=application/lha
|
||||
lhx=application/octet-stream
|
||||
list=text/plain
|
||||
lma=audio/nspaudio
|
||||
log=text/plain
|
||||
lsp=text/x-scriptlisp
|
||||
lst=text/plain
|
||||
lsx=text/x-la-asf
|
||||
ltx=application/x-latex
|
||||
lzh=application/octet-stream
|
||||
lzx=application/lzx
|
||||
m1v=video/mpeg
|
||||
m2a=audio/mpeg
|
||||
m2v=video/mpeg
|
||||
m3u=audio/x-mpegurl
|
||||
m=text/x-m
|
||||
man=application/x-troff-man
|
||||
manifest=text/cache-manifest
|
||||
map=application/x-navimap
|
||||
mar=text/plain
|
||||
mbd=application/mbedlet
|
||||
mc$=application/x-magic-cap-package-10
|
||||
mcd=application/mcad
|
||||
mcf=text/mcf
|
||||
mcp=application/netmc
|
||||
me=application/x-troff-me
|
||||
mht=message/rfc822
|
||||
mhtml=message/rfc822
|
||||
mid=application/x-midi
|
||||
midi=application/x-midi
|
||||
mif=application/x-frame
|
||||
mime=message/rfc822
|
||||
mjf=audio/x-vndaudioexplosionmjuicemediafile
|
||||
mjpg=video/x-motion-jpeg
|
||||
mm=application/base64
|
||||
mme=application/base64
|
||||
mod=audio/mod
|
||||
moov=video/quicktime
|
||||
mov=video/quicktime
|
||||
movie=video/x-sgi-movie
|
||||
mp2=audio/mpeg
|
||||
mp3=audio/mpeg3
|
||||
mp4=video/mp4
|
||||
mpa=audio/mpeg
|
||||
mpc=application/x-project
|
||||
mpe=video/mpeg
|
||||
mpeg=video/mpeg
|
||||
mpg=video/mpeg
|
||||
mpga=audio/mpeg
|
||||
mpp=application/vndms-project
|
||||
mpt=application/x-project
|
||||
mpv=application/x-project
|
||||
mpx=application/x-project
|
||||
mrc=application/marc
|
||||
ms=application/x-troff-ms
|
||||
mv=video/x-sgi-movie
|
||||
my=audio/make
|
||||
mzz=application/x-vndaudioexplosionmzz
|
||||
nap=image/naplps
|
||||
naplps=image/naplps
|
||||
nc=application/x-netcdf
|
||||
ncm=application/vndnokiaconfiguration-message
|
||||
nif=image/x-niff
|
||||
niff=image/x-niff
|
||||
nix=application/x-mix-transfer
|
||||
nsc=application/x-conference
|
||||
nvd=application/x-navidoc
|
||||
o=application/octet-stream
|
||||
oda=application/oda
|
||||
odb=application/vnd.oasis.opendocument.database
|
||||
odc=application/vnd.oasis.opendocument.chart
|
||||
odf=application/vnd.oasis.opendocument.formula
|
||||
odg=application/vnd.oasis.opendocument.graphics
|
||||
odi=application/vnd.oasis.opendocument.image
|
||||
odm=application/vnd.oasis.opendocument.text-master
|
||||
odp=application/vnd.oasis.opendocument.presentation
|
||||
ods=application/vnd.oasis.opendocument.spreadsheet
|
||||
odt=application/vnd.oasis.opendocument.text
|
||||
oga=audio/ogg
|
||||
ogg=audio/ogg
|
||||
ogv=video/ogg
|
||||
omc=application/x-omc
|
||||
omcd=application/x-omcdatamaker
|
||||
omcr=application/x-omcregerator
|
||||
otc=application/vnd.oasis.opendocument.chart-template
|
||||
otf=application/vnd.oasis.opendocument.formula-template
|
||||
otg=application/vnd.oasis.opendocument.graphics-template
|
||||
oth=application/vnd.oasis.opendocument.text-web
|
||||
oti=application/vnd.oasis.opendocument.image-template
|
||||
otm=application/vnd.oasis.opendocument.text-master
|
||||
otp=application/vnd.oasis.opendocument.presentation-template
|
||||
ots=application/vnd.oasis.opendocument.spreadsheet-template
|
||||
ott=application/vnd.oasis.opendocument.text-template
|
||||
p10=application/pkcs10
|
||||
p12=application/pkcs-12
|
||||
p7a=application/x-pkcs7-signature
|
||||
p7c=application/pkcs7-mime
|
||||
p7m=application/pkcs7-mime
|
||||
p7r=application/x-pkcs7-certreqresp
|
||||
p7s=application/pkcs7-signature
|
||||
p=text/x-pascal
|
||||
part=application/pro_eng
|
||||
pas=text/pascal
|
||||
pbm=image/x-portable-bitmap
|
||||
pcl=application/vndhp-pcl
|
||||
pct=image/x-pict
|
||||
pcx=image/x-pcx
|
||||
pdb=chemical/x-pdb
|
||||
pdf=application/pdf
|
||||
pfunk=audio/make
|
||||
pgm=image/x-portable-graymap
|
||||
pic=image/pict
|
||||
pict=image/pict
|
||||
pkg=application/x-newton-compatible-pkg
|
||||
pko=application/vndms-pkipko
|
||||
pl=text/x-scriptperl
|
||||
plx=application/x-pixclscript
|
||||
pm4=application/x-pagemaker
|
||||
pm5=application/x-pagemaker
|
||||
pm=text/x-scriptperl-module
|
||||
png=image/png
|
||||
pnm=application/x-portable-anymap
|
||||
pot=application/mspowerpoint
|
||||
pov=model/x-pov
|
||||
ppa=application/vndms-powerpoint
|
||||
ppm=image/x-portable-pixmap
|
||||
pps=application/mspowerpoint
|
||||
ppt=application/mspowerpoint
|
||||
ppz=application/mspowerpoint
|
||||
pre=application/x-freelance
|
||||
prt=application/pro_eng
|
||||
ps=application/postscript
|
||||
psd=application/octet-stream
|
||||
pvu=paleovu/x-pv
|
||||
pwz=application/vndms-powerpoint
|
||||
py=text/x-scriptphyton
|
||||
pyc=applicaiton/x-bytecodepython
|
||||
qcp=audio/vndqcelp
|
||||
qd3=x-world/x-3dmf
|
||||
qd3d=x-world/x-3dmf
|
||||
qif=image/x-quicktime
|
||||
qt=video/quicktime
|
||||
qtc=video/x-qtc
|
||||
qti=image/x-quicktime
|
||||
qtif=image/x-quicktime
|
||||
ra=audio/x-pn-realaudio
|
||||
ram=audio/x-pn-realaudio
|
||||
rar=application/x-rar-compressed
|
||||
ras=application/x-cmu-raster
|
||||
rast=image/cmu-raster
|
||||
rexx=text/x-scriptrexx
|
||||
rf=image/vndrn-realflash
|
||||
rgb=image/x-rgb
|
||||
rm=application/vndrn-realmedia
|
||||
rmi=audio/mid
|
||||
rmm=audio/x-pn-realaudio
|
||||
rmp=audio/x-pn-realaudio
|
||||
rng=application/ringing-tones
|
||||
rnx=application/vndrn-realplayer
|
||||
roff=application/x-troff
|
||||
rp=image/vndrn-realpix
|
||||
rpm=audio/x-pn-realaudio-plugin
|
||||
rt=text/vndrn-realtext
|
||||
rtf=text/richtext
|
||||
rtx=text/richtext
|
||||
rv=video/vndrn-realvideo
|
||||
s=text/x-asm
|
||||
s3m=audio/s3m
|
||||
s7z=application/x-7z-compressed
|
||||
saveme=application/octet-stream
|
||||
sbk=application/x-tbook
|
||||
scm=text/x-scriptscheme
|
||||
sdml=text/plain
|
||||
sdp=application/sdp
|
||||
sdr=application/sounder
|
||||
sea=application/sea
|
||||
set=application/set
|
||||
sgm=text/x-sgml
|
||||
sgml=text/x-sgml
|
||||
sh=text/x-scriptsh
|
||||
shar=application/x-bsh
|
||||
shtml=text/x-server-parsed-html
|
||||
sid=audio/x-psid
|
||||
skd=application/x-koan
|
||||
skm=application/x-koan
|
||||
skp=application/x-koan
|
||||
skt=application/x-koan
|
||||
sit=application/x-stuffit
|
||||
sitx=application/x-stuffitx
|
||||
sl=application/x-seelogo
|
||||
smi=application/smil
|
||||
smil=application/smil
|
||||
snd=audio/basic
|
||||
sol=application/solids
|
||||
spc=text/x-speech
|
||||
spl=application/futuresplash
|
||||
spr=application/x-sprite
|
||||
sprite=application/x-sprite
|
||||
spx=audio/ogg
|
||||
src=application/x-wais-source
|
||||
ssi=text/x-server-parsed-html
|
||||
ssm=application/streamingmedia
|
||||
sst=application/vndms-pkicertstore
|
||||
step=application/step
|
||||
stl=application/sla
|
||||
stp=application/step
|
||||
sv4cpio=application/x-sv4cpio
|
||||
sv4crc=application/x-sv4crc
|
||||
svf=image/vnddwg
|
||||
svg=image/svg+xml
|
||||
svr=application/x-world
|
||||
swf=application/x-shockwave-flash
|
||||
t=application/x-troff
|
||||
talk=text/x-speech
|
||||
tar=application/x-tar
|
||||
tbk=application/toolbook
|
||||
tcl=text/x-scripttcl
|
||||
tcsh=text/x-scripttcsh
|
||||
tex=application/x-tex
|
||||
texi=application/x-texinfo
|
||||
texinfo=application/x-texinfo
|
||||
text=text/plain
|
||||
tgz=application/gnutar
|
||||
tif=image/tiff
|
||||
tiff=image/tiff
|
||||
tr=application/x-troff
|
||||
tsi=audio/tsp-audio
|
||||
tsp=application/dsptype
|
||||
tsv=text/tab-separated-values
|
||||
turbot=image/florian
|
||||
txt=text/plain
|
||||
uil=text/x-uil
|
||||
uni=text/uri-list
|
||||
unis=text/uri-list
|
||||
unv=application/i-deas
|
||||
uri=text/uri-list
|
||||
uris=text/uri-list
|
||||
ustar=application/x-ustar
|
||||
uu=text/x-uuencode
|
||||
uue=text/x-uuencode
|
||||
vcd=application/x-cdlink
|
||||
vcf=text/x-vcard
|
||||
vcard=text/x-vcard
|
||||
vcs=text/x-vcalendar
|
||||
vda=application/vda
|
||||
vdo=video/vdo
|
||||
vew=application/groupwise
|
||||
viv=video/vivo
|
||||
vivo=video/vivo
|
||||
vmd=application/vocaltec-media-desc
|
||||
vmf=application/vocaltec-media-file
|
||||
voc=audio/voc
|
||||
vos=video/vosaic
|
||||
vox=audio/voxware
|
||||
vqe=audio/x-twinvq-plugin
|
||||
vqf=audio/x-twinvq
|
||||
vql=audio/x-twinvq-plugin
|
||||
vrml=application/x-vrml
|
||||
vrt=x-world/x-vrt
|
||||
vsd=application/x-visio
|
||||
vst=application/x-visio
|
||||
vsw=application/x-visio
|
||||
w60=application/wordperfect60
|
||||
w61=application/wordperfect61
|
||||
w6w=application/msword
|
||||
wav=audio/wav
|
||||
wb1=application/x-qpro
|
||||
wbmp=image/vnd.wap.wbmp
|
||||
web=application/vndxara
|
||||
wiz=application/msword
|
||||
wk1=application/x-123
|
||||
wmf=windows/metafile
|
||||
wml=text/vnd.wap.wml
|
||||
wmlc=application/vnd.wap.wmlc
|
||||
wmls=text/vnd.wap.wmlscript
|
||||
wmlsc=application/vnd.wap.wmlscriptc
|
||||
word=application/msword
|
||||
wp5=application/wordperfect
|
||||
wp6=application/wordperfect
|
||||
wp=application/wordperfect
|
||||
wpd=application/wordperfect
|
||||
wq1=application/x-lotus
|
||||
wri=application/mswrite
|
||||
wrl=application/x-world
|
||||
wrz=model/vrml
|
||||
wsc=text/scriplet
|
||||
wsrc=application/x-wais-source
|
||||
wtk=application/x-wintalk
|
||||
x-png=image/png
|
||||
xbm=image/x-xbitmap
|
||||
xdr=video/x-amt-demorun
|
||||
xgz=xgl/drawing
|
||||
xif=image/vndxiff
|
||||
xl=application/excel
|
||||
xla=application/excel
|
||||
xlb=application/excel
|
||||
xlc=application/excel
|
||||
xld=application/excel
|
||||
xlk=application/excel
|
||||
xll=application/excel
|
||||
xlm=application/excel
|
||||
xls=application/excel
|
||||
xlt=application/excel
|
||||
xlv=application/excel
|
||||
xlw=application/excel
|
||||
xm=audio/xm
|
||||
xml=text/xml
|
||||
xmz=xgl/movie
|
||||
xpix=application/x-vndls-xpix
|
||||
xpm=image/x-xpixmap
|
||||
xsr=video/x-amt-showrun
|
||||
xwd=image/x-xwd
|
||||
xyz=chemical/x-pdb
|
||||
z=application/x-compress
|
||||
zip=application/zip
|
||||
zoo=application/octet-stream
|
||||
zsh=text/x-scriptzsh
|
||||
# Office 2007 mess - http://wdg.uncc.edu/Microsoft_Office_2007_MIME_Types_for_Apache_and_IIS
|
||||
docx=application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
||||
docm=application/vnd.ms-word.document.macroEnabled.12
|
||||
dotx=application/vnd.openxmlformats-officedocument.wordprocessingml.template
|
||||
dotm=application/vnd.ms-word.template.macroEnabled.12
|
||||
xlsx=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
xlsm=application/vnd.ms-excel.sheet.macroEnabled.12
|
||||
xltx=application/vnd.openxmlformats-officedocument.spreadsheetml.template
|
||||
xltm=application/vnd.ms-excel.template.macroEnabled.12
|
||||
xlsb=application/vnd.ms-excel.sheet.binary.macroEnabled.12
|
||||
xlam=application/vnd.ms-excel.addin.macroEnabled.12
|
||||
pptx=application/vnd.openxmlformats-officedocument.presentationml.presentation
|
||||
pptm=application/vnd.ms-powerpoint.presentation.macroEnabled.12
|
||||
ppsx=application/vnd.openxmlformats-officedocument.presentationml.slideshow
|
||||
ppsm=application/vnd.ms-powerpoint.slideshow.macroEnabled.12
|
||||
potx=application/vnd.openxmlformats-officedocument.presentationml.template
|
||||
potm=application/vnd.ms-powerpoint.template.macroEnabled.12
|
||||
ppam=application/vnd.ms-powerpoint.addin.macroEnabled.12
|
||||
sldx=application/vnd.openxmlformats-officedocument.presentationml.slide
|
||||
sldm=application/vnd.ms-powerpoint.slide.macroEnabled.12
|
||||
thmx=application/vnd.ms-officetheme
|
||||
onetoc=application/onenote
|
||||
onetoc2=application/onenote
|
||||
onetmp=application/onenote
|
||||
onepkg=application/onenote
|
||||
# koffice
|
||||
|
||||
# iWork
|
||||
key=application/x-iwork-keynote-sffkey
|
||||
kth=application/x-iwork-keynote-sffkth
|
||||
nmbtemplate=application/x-iwork-numbers-sfftemplate
|
||||
numbers=application/x-iwork-numbers-sffnumbers
|
||||
pages=application/x-iwork-pages-sffpages
|
||||
template=application/x-iwork-pages-sfftemplate
|
||||
|
||||
# Extensions for Mozilla apps (Firefox and friends)
|
||||
xpi=application/x-xpinstall
|
||||
|
||||
# Opera extensions
|
||||
oex=application/x-opera-extension
|
||||
@@ -1,16 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Forbidden</title>
|
||||
</head>
|
||||
<body>
|
||||
{{with .Error}}
|
||||
<h1>
|
||||
{{.Title}}
|
||||
</h1>
|
||||
<p>
|
||||
{{.Description}}
|
||||
</p>
|
||||
{{end}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"title": "{{js .Error.Title}}",
|
||||
"description": "{{js .Error.Description}}"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{{.Error.Title}}
|
||||
|
||||
{{.Error.Description}}
|
||||
@@ -1 +0,0 @@
|
||||
<forbidden>{{.Error.Description}}</forbidden>
|
||||
@@ -1,63 +0,0 @@
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Helvetica, Arial, Sans;
|
||||
background: #EEEEEE;
|
||||
}
|
||||
.block {
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
#header h1 {
|
||||
font-weight: normal;
|
||||
font-size: 28px;
|
||||
margin: 0;
|
||||
}
|
||||
#more {
|
||||
color: #666;
|
||||
font-size: 80%;
|
||||
border: none;
|
||||
}
|
||||
#header {
|
||||
background: #FFFFCC;
|
||||
}
|
||||
#header p {
|
||||
color: #333;
|
||||
}
|
||||
#routes {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
#routes h2 {
|
||||
font-weight: normal;
|
||||
font-size: 18px;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
#routes ol {
|
||||
|
||||
}
|
||||
#routes li {
|
||||
font-size: 14px;
|
||||
font-family: monospace;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="header" class="block">
|
||||
{{with .Error}}
|
||||
<h1>
|
||||
{{.Title}}
|
||||
</h1>
|
||||
<p>
|
||||
{{.Description}}
|
||||
</p>
|
||||
{{end}}
|
||||
</div>
|
||||
<div id="routes" class="block">
|
||||
<h2>These routes have been tried, in this order :</h2>
|
||||
<ol>
|
||||
{{range .Router.Routes}}
|
||||
<li>{{pad .Method 10}}{{pad .Path 50}}{{.Action}}</li>
|
||||
{{end}}
|
||||
</ol>
|
||||
</div>
|
||||
@@ -1,26 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Not found</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{{if .DevMode}}
|
||||
|
||||
{{template "errors/404-dev.html" .}}
|
||||
|
||||
{{else}}
|
||||
|
||||
{{with .Error}}
|
||||
<h1>
|
||||
{{.Title}}
|
||||
</h1>
|
||||
<p>
|
||||
{{.Description}}
|
||||
</p>
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"title": "{{js .Error.Title}}",
|
||||
"description": "{{js .Error.Description}}"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{{.Error.Title}}
|
||||
|
||||
{{.Error.Description}}
|
||||
@@ -1 +0,0 @@
|
||||
<notfound>{{.Error.Description}}</notfound>
|
||||
@@ -1,118 +0,0 @@
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Helvetica, Arial, Sans;
|
||||
background: #EEEEEE;
|
||||
}
|
||||
.block {
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
#header h1 {
|
||||
font-weight: normal;
|
||||
font-size: 28px;
|
||||
margin: 0;
|
||||
}
|
||||
#more {
|
||||
color: #666;
|
||||
font-size: 80%;
|
||||
border: none;
|
||||
}
|
||||
#header {
|
||||
background: #fcd2da;
|
||||
}
|
||||
#header p {
|
||||
color: #333;
|
||||
}
|
||||
#source {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
#source h2 {
|
||||
font-weight: normal;
|
||||
font-size: 18px;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
#source .lineNumber {
|
||||
float: left;
|
||||
display: block;
|
||||
width: 40px;
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
font-size: 14px;
|
||||
font-family: monospace;
|
||||
background: #333;
|
||||
color: #fff;
|
||||
}
|
||||
#source .line {
|
||||
clear: both;
|
||||
color: #333;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
#source pre {
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
#source .error {
|
||||
color: #c00 !important;
|
||||
}
|
||||
#source .error .lineNumber {
|
||||
background: #c00;
|
||||
}
|
||||
#source a {
|
||||
text-decoration: none;
|
||||
}
|
||||
#source a:hover * {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
#source a:hover pre {
|
||||
background: #FAFFCF !important;
|
||||
}
|
||||
#source em {
|
||||
font-style: normal;
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
}
|
||||
#source strong {
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
{{with .Error}}
|
||||
<div id="header" class="block">
|
||||
<h1>
|
||||
{{.Title}}
|
||||
</h1>
|
||||
<p>
|
||||
{{if .SourceType}}
|
||||
The {{.SourceType}} <strong>{{.Path}}</strong> does not compile: <strong>{{.Description}}</strong>
|
||||
{{else}}
|
||||
{{.Description}}
|
||||
{{end}}
|
||||
</p>
|
||||
</div>
|
||||
{{if .Path}}
|
||||
<div id="source" class="block">
|
||||
<h2>In {{.Path}}
|
||||
{{if .Line}}
|
||||
(around {{if .Line}}line {{.Line}}{{end}}{{if .Column}} column {{.Column}}{{end}})
|
||||
{{end}}
|
||||
</h2>
|
||||
{{range .ContextSource}}
|
||||
<div class="line {{if .IsError}}error{{end}}">
|
||||
<span class="lineNumber">{{.Line}}:</span>
|
||||
<pre>{{.Source}}</pre>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .MetaError}}
|
||||
<div id="source" class="block">
|
||||
<h2>Additionally, an error occurred while handling this error.</h2>
|
||||
<div class="line error">
|
||||
{{.MetaError}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -1,16 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Application error</title>
|
||||
</head>
|
||||
<body>
|
||||
{{if .DevMode}}
|
||||
{{template "errors/500-dev.html" .}}
|
||||
{{else}}
|
||||
<h1>Oops, an error occured</h1>
|
||||
<p>
|
||||
This exception has been logged.
|
||||
</p>
|
||||
{{end}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"title": "{{js .Error.Title}}",
|
||||
"description": "{{js .Error.Description}}"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{{.Error.Title}}
|
||||
{{.Error.Description}}
|
||||
|
||||
{{if eq .RunMode "dev"}}
|
||||
{{with .Error}}
|
||||
{{if .Path}}
|
||||
----------
|
||||
In {{.Path}} {{if .Line}}(around line {{.Line}}){{end}}
|
||||
|
||||
{{range .ContextSource}}
|
||||
{{if .IsError}}>{{else}} {{end}} {{.Line}}: {{.Source}}{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -1,4 +0,0 @@
|
||||
<error>
|
||||
<title>{{.Error.Title}}</title>
|
||||
<description>{{.Error.Description}}</description>
|
||||
</error>
|
||||
@@ -1,7 +1,17 @@
|
||||
# Revel build section
|
||||
# This section contains values that are not reloadable
|
||||
################################################################################
|
||||
|
||||
# Comma delimited list of folders that are included with the package, or build commands
|
||||
# If you want to not include folders within these ones prefix the folder with a . to make it hidden
|
||||
package.folders = conf, public, messages, mongodb_backup, app/views
|
||||
|
||||
|
||||
#------------------------
|
||||
# leanote config
|
||||
#------------------------
|
||||
|
||||
http.addr=0.0.0.0 # listen on all ip addresses
|
||||
http.port=9000
|
||||
|
||||
site.url=http://localhost:9000 # or http://x.com:8080, http://www.xx.com:9000
|
||||
@@ -28,7 +38,6 @@ app.secret=V85ZzBeTnzpsHyjQX4zukbQ8qqtju9y2aDM55VWxAH9Qop19poekx3xkcDVvrD0y #
|
||||
# for dev
|
||||
#--------------------------------
|
||||
app.name=leanote
|
||||
http.addr=
|
||||
http.ssl=false
|
||||
cookie.httponly=false
|
||||
cookie.prefix=LEANOTE
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
# Revel build section
|
||||
# This section contains values that are not reloadable
|
||||
################################################################################
|
||||
|
||||
# Comma delimited list of folders that are included with the package, or build commands
|
||||
# If you want to not include folders within these ones prefix the folder with a . to make it hidden
|
||||
package.folders = conf, public, messages, mongodb_backup, app/views
|
||||
|
||||
|
||||
#------------------------
|
||||
# leanote config
|
||||
#------------------------
|
||||
|
||||
http.addr=0.0.0.0 # listen on all ip addresses
|
||||
http.port=9000
|
||||
|
||||
site.url=http://localhost:9000 # or http://x.com:8080, http://www.xx.com:9000
|
||||
@@ -29,7 +38,6 @@ app.secret=V85ZzBeTnzpsHyjQX4zukbQ8qqtju9y2aDM55VWxAH9Qop19poekx3xkcDVvrD0y
|
||||
# for dev
|
||||
#--------------------------------
|
||||
app.name=leanote
|
||||
http.addr=
|
||||
http.ssl=false
|
||||
cookie.httponly=false
|
||||
cookie.prefix=LEANOTE
|
||||
|
||||
@@ -129,6 +129,14 @@ GET /upload/*filepath Static.Serve("public/upload")
|
||||
* /member MemberIndex.Index
|
||||
* /member/index MemberIndex.Index
|
||||
|
||||
# 不知道为什么, group就是不行 member/blog可以
|
||||
* /member/group/index MemberGroup.Index
|
||||
* /member/group/addGroup MemberGroup.AddGroup
|
||||
* /member/group/updateGroupTitle MemberGroup.UpdateGroupTitle
|
||||
* /member/group/deleteGroup MemberGroup.DeleteGroup
|
||||
* /member/group/addUser MemberGroup.AddUser
|
||||
* /member/group/deleteUser MemberGroup.DeleteUser
|
||||
|
||||
# common
|
||||
* /:controller/:action :controller.:action
|
||||
* /api/:controller/:action :controller.:action
|
||||
|
||||
31
go.mod
Normal file
31
go.mod
Normal file
@@ -0,0 +1,31 @@
|
||||
module github.com/leanote/leanote
|
||||
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/PuerkitoBio/goquery v1.6.1
|
||||
github.com/agtorre/gocolorize v1.0.0
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/garyburd/redigo v1.6.2 // indirect
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/inconshreveable/log15 v0.0.0-20201112154412-8562bdadbbac // indirect
|
||||
github.com/jessevdk/go-flags v1.4.0
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/revel/cmd v1.0.3
|
||||
github.com/revel/config v1.0.0 // indirect
|
||||
github.com/revel/log15 v2.11.20+incompatible // indirect
|
||||
github.com/revel/modules v1.0.0
|
||||
github.com/revel/pathtree v0.0.0-20140121041023-41257a1839e9 // indirect
|
||||
github.com/revel/revel v1.0.0
|
||||
github.com/robfig/config v0.0.0-20141207224736-0f78529c8c7e
|
||||
github.com/twinj/uuid v1.0.0 // indirect
|
||||
github.com/xeonx/timeago v1.0.0-rc4 // indirect
|
||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79
|
||||
golang.org/x/net v0.0.0-20210324205630-d1beb07c2056 // indirect
|
||||
golang.org/x/tools v0.0.0-20200219054238-753a1d49df85
|
||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/stack.v0 v0.0.0-20141108040640-9b43fcefddd0 // indirect
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user