Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
26e7a3da
Commit
26e7a3da
authored
Dec 22, 2005
by
Andreas Jung
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
removed the ZopeTutorial
parent
9b8ecc03
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
4 additions
and
1843 deletions
+4
-1843
doc/CHANGES.txt
doc/CHANGES.txt
+2
-0
lib/python/App/dtml/zope_quick_start.dtml
lib/python/App/dtml/zope_quick_start.dtml
+2
-13
lib/python/Products/ZopeTutorial/CHANGES.txt
lib/python/Products/ZopeTutorial/CHANGES.txt
+0
-119
lib/python/Products/ZopeTutorial/TutorialTopic.py
lib/python/Products/ZopeTutorial/TutorialTopic.py
+0
-244
lib/python/Products/ZopeTutorial/__init__.py
lib/python/Products/ZopeTutorial/__init__.py
+0
-127
lib/python/Products/ZopeTutorial/dtml/glossaryView.dtml
lib/python/Products/ZopeTutorial/dtml/glossaryView.dtml
+0
-40
lib/python/Products/ZopeTutorial/dtml/lessonView.dtml
lib/python/Products/ZopeTutorial/dtml/lessonView.dtml
+0
-39
lib/python/Products/ZopeTutorial/dtml/tutorialAdd.dtml
lib/python/Products/ZopeTutorial/dtml/tutorialAdd.dtml
+0
-45
lib/python/Products/ZopeTutorial/dtml/tutorialNav.dtml
lib/python/Products/ZopeTutorial/dtml/tutorialNav.dtml
+0
-34
lib/python/Products/ZopeTutorial/glossary.stx
lib/python/Products/ZopeTutorial/glossary.stx
+0
-255
lib/python/Products/ZopeTutorial/tutorial.stx
lib/python/Products/ZopeTutorial/tutorial.stx
+0
-926
lib/python/Products/ZopeTutorial/version.txt
lib/python/Products/ZopeTutorial/version.txt
+0
-1
No files found.
doc/CHANGES.txt
View file @
26e7a3da
...
@@ -26,6 +26,8 @@ Zope Changes
...
@@ -26,6 +26,8 @@ Zope Changes
Features added
Features added
- removed ZopeTutorial (Elvis is now really dead)
- ZClasses are deprecated and should no longer be used.
- ZClasses are deprecated and should no longer be used.
- ZGadyFlyDA/Gadfly is deprecated
- ZGadyFlyDA/Gadfly is deprecated
...
...
lib/python/App/dtml/zope_quick_start.dtml
View file @
26e7a3da
...
@@ -67,17 +67,6 @@ web applications.
...
@@ -67,17 +67,6 @@ web applications.
</p>
</p>
</li>
</li>
<li>
<p>
There is a built-in interactive
<strong>
Zope Tutorial
</strong>
which
gets you started with some simple tasks using the Zope managment
interface. To use the tutorial, go to any Folder and select
<em>
Zope Tutorial
</em>
from the add list and click the
<em>
Add
</em>
button. Provide a name for the tutorial and click
<em>
Add
</em>
to
begin working with the tutorial.
</p>
</li>
<li>
<li>
<p>
<p>
<a
href=
"manage_importObject?file=Examples.zexp&set_owner:int=1"
>
Import
</a>
<a
href=
"manage_importObject?file=Examples.zexp&set_owner:int=1"
>
Import
</a>
...
@@ -90,8 +79,8 @@ applications that you can copy and modify.
...
@@ -90,8 +79,8 @@ applications that you can copy and modify.
<li>
<li>
<p>
<p>
Go to the main
<a
href=
"http://www.zope.org/Documentation/"
target=
"_new"
>
Go to the main
<a
href=
"http://www.zope.org/Documentation/"
target=
"_new"
>
Documentation Overview
</a>
on
Zope.org. Here you will find pointers to
Documentation Overview
</a>
on
<a
href=
"http://www.zope.org"
target=
"_new"
>
Zope.org
</a>
.
official and community contributed documentation.
Here you will find pointers to
official and community contributed documentation.
</p>
</p>
</li>
</li>
...
...
lib/python/Products/ZopeTutorial/CHANGES.txt
deleted
100644 → 0
View file @
9b8ecc03
Zope Tutorial 1.2
Bug Fixes
* Fix niglet in step 7.
Zope Tutorial 1.1
Features
* Updates lessions to use ZPT in place of DTML. This required
extensive reworking in some lessons.
* Update the examples .zexp file.
* Updated likes to the Zope book to refer to the current online
version.
* Updated the glossary.
* Added a ZPT reference link feature for the glossary.
Zope Tutorial 1.0a6
Bug Fixes
* Rearranged things a bit for 2.2 release.
* Improved missing cookie behavior.
* Improved descriptions of management screen navigation.
* Many typos and nits fixed in lessons and examples.
Known Limitations
* Requires Zope 2.1.6 or higher.
* Works better with HTTP cookies.
Zope Tutorial 1.0a5
Features
* Changed the way examples are installed. Now the examples are
installed by adding a Zope object. This resolves a lot of security
issues.
* Added some preliminary API docs, and an API documentation
infrastructure.
Bug Fixes
* Miscellaneous restructuring and fixing.
Known Limitations
* Requires Zope 2.1.6 or higher.
* Requires HTTP cookies.
Zope Tutorial 1.0a4
Features
* Added an introduction.
* Improved installation location and verification.
Bug Fixes
* More information about how to navigate between management
screens.
* Many typos fixed thanks to Karl Ulbrich.
Known Bugs
* Requires Zope 2.1.6 or higher.
Zope Tutorial 1.0a3
Features
* Glossary greatly improved and linked into lessons.
Bug Fixes
* Install now correctly sets up gadfly database.
* Some DTML typos fixed thanks to Didier Georgieff.
Known Bugs
* Requires Zope 2.1.6 or higher.
Zope Tutorial 1.0a2
Features
* Improved PRE formatting. Examples now look nice.
* Improved examples navigation, no longer requires Javascript.
* Added more information to the glossary.
* Added feedback link.
Bug Fixes
* Grammar and typo fixes.
Known Bugs
* Requires Zope 2.1.6 or higher.
Zope Tutorial 1.0a1
Initial preview release.
\ No newline at end of file
lib/python/Products/ZopeTutorial/TutorialTopic.py
deleted
100644 → 0
View file @
9b8ecc03
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
import
OFS.Folder
from
HelpSys.HelpTopic
import
TextTopic
from
Globals
import
HTML
,
DTMLFile
,
MessageDialog
from
cgi
import
escape
import
DateTime
import
DocumentTemplate
import
StructuredText
import
re
pre_pat
=
re
.
compile
(
r'<PRE>(.+?)</PRE>'
,
re
.
IGNORECASE
|
re
.
DOTALL
)
tutorialExamplesFile
=
'ZopeTutorialExamples.zexp'
class
TutorialTopic
(
TextTopic
):
"""
A Tutorial Help Topic
"""
def
__init__
(
self
,
id
,
title
,
text
):
self
.
id
=
id
self
.
title
=
title
text
=
str
(
StructuredText
.
HTML
(
text
))
self
.
obj
=
HTML
(
pre_pat
.
sub
(
clean_pre
,
text
))
index_html
=
DTMLFile
(
'dtml/lessonView'
,
globals
())
def
checkInstallation
(
self
,
REQUEST
):
"""
Returns false if the tutorial examples are not correctly
installed. Also sets the 'hide_next' variable in the request
if the examples are not installed.
"""
ok
=
0
if
REQUEST
.
has_key
(
'tutorialExamplesURL'
):
url
=
REQUEST
[
'tutorialExamplesURL'
]
base
=
REQUEST
[
'BASE1'
]
if
url
.
index
(
base
)
==
0
:
url
=
url
[
len
(
base
):]
try
:
self
.
getPhysicalRoot
().
unrestrictedTraverse
(
url
)
ok
=
1
except
:
pass
if
not
ok
:
REQUEST
.
set
(
'hide_next'
,
1
)
return
ok
def
lessonURL
(
self
,
id
,
REQUEST
):
"""
URL of the examples for a lesson
"""
try
:
return
'%s/lesson%d'
%
(
REQUEST
[
'tutorialExamplesURL'
],
id
)
except
KeyError
:
return
""
def
tutorialShowLesson
(
self
,
id
,
REQUEST
):
"""
Navigate management frame to a given lesson's screen.
"""
url
=
self
.
lessonURL
(
id
,
REQUEST
)
if
not
url
or
not
self
.
checkInstallation
(
REQUEST
):
REQUEST
.
set
(
'hide_next'
,
0
)
return
"""
\
<p class="warning">
Zope cannot find the tutorial examples.
You should install the tutorial examples before
continuing. Choose "Zope Tutorial" from the product
add list in the Zope management screen to install
the examples.
</p>
<p class="warning">
If you have already installed the tutorial, you can either
follow along manually, or reinstall the tutorial examples.
Note: make sure that you have cookies turned on in your browser.
</p>
"""
return
"""
\
<SCRIPT LANGUAGE="javascript">
<!--
window.open("%s/manage_main", "manage_main");
//-->
</SCRIPT>
<p class="information">
<a href="%s/manage_main" target="manage_main"
onClick="javascript:window.open('%s/manage_main', 'manage_main').focus()"
>Show lesson examples</a> in another window.
</p>"""
%
(
url
.
replace
(
'"'
,
'
\
\
"'
),
escape
(
url
,
1
),
escape
(
url
,
1
).
replace
(
"'"
,
"
\
\
'"
))
tutorialNavigation
=
DTMLFile
(
'dtml/tutorialNav'
,
globals
())
class
GlossaryTopic
(
TutorialTopic
):
"""
A Tutorial Glossary Help Topic
"""
def
__init__
(
self
,
id
,
title
,
text
):
self
.
id
=
id
self
.
title
=
title
self
.
obj
=
HTML
(
text
)
index_html
=
DTMLFile
(
'dtml/glossaryView'
,
globals
())
def
formatted_content
(
self
,
REQUEST
):
"""
Custom stx formatting for tutorial topics
"""
text
=
self
.
obj
(
self
,
REQUEST
)
text
=
str
(
StructuredText
.
HTML
(
text
))
pre_pat
.
sub
(
clean_pre
,
text
)
return
text
def
apiLink
(
self
,
klass
,
REQUEST
):
"""
Returns the URL to a API documentation for a given class.
"""
names
=
klass
.
split
(
'.'
)
url
=
"%s/Control_Panel/Products/%s/Help/%s.py#%s"
%
(
REQUEST
[
'SCRIPT_NAME'
],
names
[
0
],
names
[
1
],
names
[
2
])
return
'<a href="%s">API Documentation</a>'
%
url
def
dtmlLink
(
self
,
tag
,
REQUEST
):
"""
Returns the URL to a DTML Reference page for a given tag.
"""
url
=
"%s/Control_Panel/Products/OFSP/Help/dtml-%s.stx"
%
(
REQUEST
[
'SCRIPT_NAME'
],
tag
)
return
'<a href="%s">DTML Reference</a>'
%
url
def
zptLink
(
self
,
tag
,
REQUEST
):
"""
Returns the URL to a ZPT Reference page for a given topic.
"""
url
=
"%s/Control_Panel/Products/PageTemplates/Help/%s.stx"
%
(
REQUEST
[
'SCRIPT_NAME'
],
tag
)
return
'<a href="%s">ZPT Reference</a>'
%
url
addTutorialForm
=
DTMLFile
(
'dtml/tutorialAdd'
,
globals
())
def
addTutorial
(
self
,
id
,
REQUEST
=
None
,
RESPONSE
=
None
):
"""
Install tutorial examples.
"""
id
=
str
(
id
)
ob
=
OFS
.
Folder
.
Folder
()
ob
.
id
=
id
ob
.
title
=
'Zope Tutorial Examples'
id
=
self
.
_setObject
(
id
,
ob
)
folder
=
getattr
(
self
,
id
)
# make sure that Gadfly is initialized
try
:
from
Products.ZGadflyDA.DA
import
data_sources
data_sources
()
except
:
raise
'Bad Request'
,
'The ZGadflyDA product must be installed!'
# work around old Zope bug in importing
try
:
folder
.
manage_importObject
(
tutorialExamplesFile
)
except
:
folder
.
_p_jar
=
self
.
Destination
().
_p_jar
folder
.
manage_importObject
(
tutorialExamplesFile
)
# acquire REQUEST if necessary
if
REQUEST
is
None
:
REQUEST
=
self
.
REQUEST
# Set local roles on examples
changeOwner
(
folder
,
REQUEST
[
'AUTHENTICATED_USER'
])
# Run lesson setup methods -- call Setup.setup methods in lesson folders
examples
=
folder
.
examples
for
lesson
in
examples
.
objectValues
():
if
hasattr
(
lesson
,
'Setup'
):
lesson
.
Setup
.
setup
(
lesson
.
Setup
,
REQUEST
)
if
RESPONSE
is
not
None
:
e
=
(
DateTime
.
DateTime
(
'GMT'
)
+
365
).
rfc822
()
RESPONSE
.
setCookie
(
'tutorialExamplesURL'
,
folder
.
absolute_url
()
+
'/examples'
,
path
=
'/'
,
expires
=
e
)
RESPONSE
.
redirect
(
folder
.
absolute_url
()
+
'/examples'
)
def
changeOwner
(
obj
,
owner
):
"""
Recursively changes the Owner of an object and all its subobjects.
"""
for
user
,
roles
in
obj
.
get_local_roles
():
if
'Owner'
in
roles
:
obj
.
manage_delLocalRoles
([
user
])
break
obj
.
manage_setLocalRoles
(
owner
.
getId
(),
[
'Owner'
])
for
subobj
in
obj
.
objectValues
():
changeOwner
(
subobj
,
owner
)
def
clean_pre
(
match
):
"""
Reformat a pre tag to get rid of extra indentation
and extra blank lines.
"""
lines
=
match
.
group
(
1
).
split
(
'
\
n
'
)
nlines
=
[]
min_indent
=
None
for
line
in
lines
:
indent
=
len
(
line
)
-
len
(
line
.
lstrip
())
if
min_indent
is
None
or
indent
<
min_indent
:
if
line
.
strip
():
min_indent
=
indent
for
line
in
lines
:
nlines
.
append
(
line
[
min_indent
:])
while
1
:
if
not
nlines
[
0
].
strip
():
nlines
.
pop
(
0
)
else
:
break
while
1
:
if
not
nlines
[
-
1
].
strip
():
nlines
.
pop
()
else
:
break
return
"<PRE>%s</PRE>"
%
'
\
n
'
.
join
(
nlines
)
lib/python/Products/ZopeTutorial/__init__.py
deleted
100644 → 0
View file @
9b8ecc03
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
import
TutorialTopic
import
App.Common
import
os.path
import
os
import
stat
from
DateTime
import
DateTime
from
urllib
import
quote_plus
from
cgi
import
escape
import
re
from
HelpSys
import
APIHelpTopic
def
initialize
(
context
):
# abuse registerClass to get a tutorial constructor
# in the product add list
context
.
registerClass
(
None
,
meta_type
=
'Zope Tutorial'
,
constructors
=
(
TutorialTopic
.
addTutorialForm
,
TutorialTopic
.
addTutorial
),
)
from
App.Product
import
doInstall
if
not
doInstall
():
return
# create tutorial help topics
lesson_path
=
os
.
path
.
join
(
App
.
Common
.
package_home
(
globals
()),
'tutorial.stx'
)
glossary_path
=
os
.
path
.
join
(
App
.
Common
.
package_home
(
globals
()),
'glossary.stx'
)
help
=
context
.
getProductHelp
()
# test to see if nothing has changed since last registration
if
help
.
lastRegistered
is
not
None
and
\
help
.
lastRegistered
>=
DateTime
(
os
.
stat
(
lesson_path
)[
stat
.
ST_MTIME
]):
return
help
.
lastRegistered
=
DateTime
()
# delete old help topics
for
id
in
help
.
objectIds
(
'Help Topic'
):
help
.
_delObject
(
id
)
# create glossary
text
=
open
(
glossary_path
).
read
()
text
=
term_pat
.
sub
(
defineTerm
,
text
)
glossary
=
TutorialTopic
.
GlossaryTopic
(
'tutorialGlossary'
,
'Zope Tutorial Glossary'
,
text
)
context
.
registerHelpTopic
(
'tutorialGlossary'
,
glossary
)
# create lessons
f
=
open
(
lesson_path
)
lines
=
[]
id
=
0
while
1
:
line
=
f
.
readline
()
if
(
line
.
strip
()
and
line
.
find
(
' '
)
!=
0
)
or
line
==
''
:
# new topic
if
lines
:
id
=
id
+
1
topic_id
=
'topic_%02d'
%
id
text
=
''
.
join
(
lines
[
1
:])
text
=
term_pat
.
sub
(
glossaryTerm
,
text
)
topic
=
TutorialTopic
.
TutorialTopic
(
topic_id
,
lines
[
0
].
strip
(),
spacestrip
(
text
))
context
.
registerHelpTopic
(
topic_id
,
topic
)
lines
=
[
line
]
else
:
lines
.
append
(
line
)
if
line
==
''
:
break
f
.
close
()
def
spacestrip
(
txt
):
""" dedent text by 2 spaces !
We need this to workaround a nasty bug in STXNG.
STXNG creates empty <pre>..</pre> when then text start
if a level > 1. This fix is lame. The problem should be fixed
inside STXNG
"""
l
=
[]
for
x
in
txt
.
split
(
"
\
n
"
):
if
len
(
x
)
>
2
and
x
[:
2
]
==
' '
:
l
.
append
(
x
[
2
:])
else
:
l
.
append
(
x
)
return
'
\
n
'
.
join
(
l
)
# Glossary functions
# ----------------
term_pat
=
re
.
compile
(
'
\
[(.*?)
\
]'
)
terms
=
[]
def
glossaryTerm
(
match
):
"""
A linked glossary term
"""
name
=
match
.
group
(
1
)
if
name
in
terms
:
return
"""<a href="../tutorialGlossary#%s">%s</a>"""
%
\
(
quote_plus
(
name
),
escape
(
name
))
return
"""[%s]"""
%
name
def
defineTerm
(
match
):
"""
Define a glossary term
"""
name
=
match
.
group
(
1
)
terms
.
append
(
name
)
return
"""<a name="%s"></a>
\
n
\
n
<strong>%s</strong>"""
%
\
(
quote_plus
(
name
),
escape
(
name
))
lib/python/Products/ZopeTutorial/dtml/glossaryView.dtml
deleted
100644 → 0
View file @
9b8ecc03
<dtml-var standard_html_header>
<style type="text/css">
PRE {
background-color : #FFFFAA;
border : thin solid;
white-space : pre;
padding-bottom : 10pt;
padding-left : 10pt;
padding-right : 10pt;
padding-top : 10pt;
}
.feedback {
font-size: 9pt;
}
.warning {
font-size: 9pt;
font-weight: bold;
color: red;
}
.information {
font-size: 9pt;
font-weight: bold;
}
</style>
<h2>&dtml-title;</h2>
<dtml-var expr="formatted_content(REQUEST)">
<p class="feedback">Comments on this lesson?
<a href="mailto:zdp@zope.org?subject=&dtml.url_quote_plus-title;">Email feedback</a>.
</p>
<dtml-var standard_html_footer>
lib/python/Products/ZopeTutorial/dtml/lessonView.dtml
deleted
100644 → 0
View file @
9b8ecc03
<dtml-var standard_html_header>
<style type="text/css">
PRE {
background-color : #FFFFAA;
border : thin solid;
white-space : pre;
padding-bottom : 10pt;
padding-left : 10pt;
padding-right : 10pt;
padding-top : 10pt;
}
.feedback {
font-size: 9pt;
}
.warning {
font-size: 9pt;
font-weight: bold;
color: red;
}
.information {
font-size: 9pt;
font-weight: bold;
}
</style>
<h2>&dtml-title;</h2>
<dtml-var obj>
<hr>
<dtml-var tutorialNavigation>
<dtml-var standard_html_footer>
lib/python/Products/ZopeTutorial/dtml/tutorialAdd.dtml
deleted
100644 → 0
View file @
9b8ecc03
<dtml-var manage_page_header>
<dtml-var "manage_form_title(this(), _,
form_title='Add Zope Tutorial',
)">
<p class="form-help">
This tutorial show you the basics of using Zope. You will
learn how to create and manage Zope resources by builting
a web site devoted to tracking Elvis sightings. Each lesson
includes working examples in Zope that allow you to learn
by hands on experimentation.
</p>
<p class="form-help">
The tutorial assumes that you are familiar with basic Internet
technologies such as <a href="http://www.w3.org/MarkUp/Guide/">HTML</a>,
URLs, and web browers.
</p>
<form action="addTutorial" method="post">
<table cellspacing="0" cellpadding="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Id
</div>
</td>
<td align="left" valign="top">
<input type="text" name="id" size="40" value="" />
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value=" Add " />
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
lib/python/Products/ZopeTutorial/dtml/tutorialNav.dtml
deleted
100644 → 0
View file @
9b8ecc03
<dtml-unless "id=='tutorialGlossary'">
<dtml-call "REQUEST.set('ids', aq_parent.objectIds())">
<dtml-call "ids.remove('tutorialGlossary')">
<dtml-call "REQUEST.set('i', ids.index(id))">
<table width="100%" border="0" padding="0" spacing="0">
<tr valign="top"><td width="50%" align="right">
<dtml-if "i > 0">
<form action="../<dtml-var "ids[i-1]" url_quote>">
<div class="form-element">
<input class="form-element" type="submit" value=" < Back ">
</div>
</form>
</dtml-if>
</td>
<td width="50%">
<dtml-unless hide_next>
<dtml-if "i < _.len(ids) -1 ">
<form action="../<dtml-var "ids[i+1]" url_quote>">
<div class="form-element">
<input class="form-element" type="submit" value=" Next > ">
</div>
</form>
</dtml-if>
</dtml-unless>
</td></tr></table>
</dtml-unless>
lib/python/Products/ZopeTutorial/glossary.stx
deleted
100644 → 0
View file @
9b8ecc03
This diff is collapsed.
Click to expand it.
lib/python/Products/ZopeTutorial/tutorial.stx
deleted
100644 → 0
View file @
9b8ecc03
This diff is collapsed.
Click to expand it.
lib/python/Products/ZopeTutorial/version.txt
deleted
100644 → 0
View file @
9b8ecc03
Zope Tutorial 1.2
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment