Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
Joona Romppanen
/
Moya Info Tools
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit e0d96526
authored
Jun 07, 2017
by
Joona Romppanen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Changed app exit to global hotkey hook. Cleaned up form1 and added loggr
1 parent
f78ff2de
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
128 additions
and
100 deletions
MoyaAdmin/MoyaAdminUI/MoyaAdminLib/MoyaAdminLib.csproj
MoyaSignup/Form1.cs
MoyaSignup/Logger.cs
MoyaSignup/MoyaSignup.csproj
MoyaSignup/UserLoginControl.cs
MoyaAdmin/MoyaAdminUI/MoyaAdminLib/MoyaAdminLib.csproj
View file @
e0d9652
...
@@ -20,7 +20,7 @@
...
@@ -20,7 +20,7 @@
<DebugSymbols>true</DebugSymbols>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>
full
</DebugType>
<DebugType>
pdbonly
</DebugType>
<PlatformTarget>x86</PlatformTarget>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
...
...
MoyaSignup/Form1.cs
View file @
e0d9652
using
System
;
using
System
;
using
System.Collections.Generic
;
using
System.Diagnostics
;
using
System.ComponentModel
;
using
System.Runtime.InteropServices
;
using
System.Data
;
using
System.Drawing
;
using
System.Linq
;
using
System.Text
;
using
System.Windows.Forms
;
using
System.Windows.Forms
;
using
WebCam
;
using
ImageFilters
;
using
System.IO
;
using
MoyaAdminLib
;
using
MoyaAdminLib
;
using
System.Diagnostic
s
;
using
MoyaSignup.Propertie
s
;
using
ThermoPrinterLibrary
;
using
ThermoPrinterLibrary
;
namespace
MoyaSignup
namespace
MoyaSignup
{
{
public
partial
class
Form1
:
Form
public
partial
class
Form1
:
Form
{
{
ThermoPrinter
thermoPrinter
;
[
DllImport
(
"user32.dll"
)]
public
static
extern
bool
RegisterHotKey
(
IntPtr
hWnd
,
int
id
,
int
fsModifiers
,
int
vlc
);
[
DllImport
(
"user32.dll"
)]
public
static
extern
bool
UnregisterHotKey
(
IntPtr
hWnd
,
int
id
);
private
const
int
ShutdownHotkey
=
1
;
private
ThermoPrinter
_thermoPrinter
;
public
bool
AllowShutdown
{
get
;
set
;
}
//public delegate void ThermoPrinterEvent(ThermoPrinter.Models model);
//public delegate void ThermoPrinterEvent(ThermoPrinter.Models model);
//public event ThermoPrinterEvent SetPrinter;
//public event ThermoPrinterEvent SetPrinter;
public
Form1
()
public
Form1
()
{
{
RestClient
.
ApiApplicationKey
=
Properties
.
Settings
.
Default
.
ApiApplicationKey
;
RestClient
.
ApiApplicationKey
=
Settings
.
Default
.
ApiApplicationKey
;
RestClient
.
ApiPass
=
Properties
.
Settings
.
Default
.
ApiPass
;
RestClient
.
ApiPass
=
Settings
.
Default
.
ApiPass
;
RestClient
.
ApiUser
=
Properties
.
Settings
.
Default
.
ApiUser
;
RestClient
.
ApiUser
=
Settings
.
Default
.
ApiUser
;
RestClient
.
ApiURL
=
Properties
.
Settings
.
Default
.
ApiURL
;
RestClient
.
ApiURL
=
Settings
.
Default
.
ApiURL
;
InitializeComponent
();
InitializeComponent
();
RegisterHotKey
(
Handle
,
ShutdownHotkey
,
3
,
(
int
)
Keys
.
S
);
}
}
protected
override
void
WndProc
(
ref
Message
m
)
{
if
(
m
.
Msg
==
0x0312
&&
m
.
WParam
.
ToInt32
()
==
ShutdownHotkey
)
{
AllowShutdown
=
true
;
Application
.
Exit
();
}
base
.
WndProc
(
ref
m
);
}
enum
Language
enum
Language
{
{
Finnish
=
0
,
Finnish
=
0
,
English
=
1
,
English
=
1
}
}
// Language currentLanguage = Language.English;
// Language currentLanguage = Language.English;
...
@@ -62,18 +76,18 @@ namespace MoyaSignup
...
@@ -62,18 +76,18 @@ namespace MoyaSignup
public
void
SetPrinter
(
ThermoPrinter
.
Models
model
)
public
void
SetPrinter
(
ThermoPrinter
.
Models
model
)
{
{
thermoPrinter
=
new
ThermoPrinter
(
model
);
_
thermoPrinter
=
new
ThermoPrinter
(
model
);
try
try
{
{
thermoPrinter
.
Start
(
Properties
.
Settings
.
Default
.
printerPort
);
_thermoPrinter
.
Start
(
Settings
.
Default
.
printerPort
);
thermoPrinter
.
SetBarcodeWidth
(
ThermoPrinter
.
BarcodeWidths
.
Small
);
_
thermoPrinter
.
SetBarcodeWidth
(
ThermoPrinter
.
BarcodeWidths
.
Small
);
thermoPrinter
.
SetCharacterAlignment
(
ThermoPrinter
.
CharacterAlignments
.
Center
);
_
thermoPrinter
.
SetCharacterAlignment
(
ThermoPrinter
.
CharacterAlignments
.
Center
);
thermoPrinter
.
SetPositionHRI
(
ThermoPrinter
.
HRIPrintingPositions
.
Below
);
_
thermoPrinter
.
SetPositionHRI
(
ThermoPrinter
.
HRIPrintingPositions
.
Below
);
}
}
catch
catch
{
{
thermoPrinter
=
null
;
_
thermoPrinter
=
null
;
}
}
}
}
...
@@ -86,40 +100,20 @@ namespace MoyaSignup
...
@@ -86,40 +100,20 @@ namespace MoyaSignup
}*/
}*/
if
(
Debugger
.
IsAttached
)
if
(
Debugger
.
IsAttached
)
this
.
WindowState
=
FormWindowState
.
Normal
;
WindowState
=
FormWindowState
.
Normal
;
ApiSettings
form
=
new
ApiSettings
();
var
form
=
new
ApiSettings
();
form
.
ShowDialog
();
form
.
ShowDialog
();
if
(
Properties
.
Settings
.
Default
.
printerPort
!=
null
&&
Properties
.
Settings
.
Default
.
ThermoPrinter
>
0
)
if
(
Settings
.
Default
.
printerPort
!=
null
&&
Settings
.
Default
.
ThermoPrinter
>
0
)
{
{
ThermoPrinter
.
Models
model
=
(
ThermoPrinter
.
Models
)
Properties
.
Settings
.
Default
.
ThermoPrinter
;
var
model
=
(
ThermoPrinter
.
Models
)
Settings
.
Default
.
ThermoPrinter
;
SetPrinter
(
model
);
SetPrinter
(
model
);
}
}
userLoginControl1
.
SetPrinter
+=
SetPrinter
;
userLoginControl1
.
SetPrinter
+=
SetPrinter
;
}
bool
pictureTaken
;
private
void
btnFinnish_Click
(
object
sender
,
EventArgs
e
)
{
}
}
private
void
btnEnglish_Click
(
object
sender
,
EventArgs
e
)
{
}
bool
checkSaveSafety
()
{
return
true
;
}
/*
/*
private void btnSave_Click(object sender, EventArgs e)
private void btnSave_Click(object sender, EventArgs e)
{
{
...
@@ -145,12 +139,6 @@ namespace MoyaSignup
...
@@ -145,12 +139,6 @@ namespace MoyaSignup
this.Cursor = Cursors.Default;
this.Cursor = Cursors.Default;
}*/
}*/
bool
allowShutdown
;
public
bool
AllowShutdown
{
get
{
return
allowShutdown
;
}
set
{
allowShutdown
=
value
;
}
}
/*
/*
private void txtName_TextChanged(object sender, EventArgs e)
private void txtName_TextChanged(object sender, EventArgs e)
{
{
...
@@ -159,54 +147,57 @@ namespace MoyaSignup
...
@@ -159,54 +147,57 @@ namespace MoyaSignup
private
void
Form1_FormClosing
(
object
sender
,
FormClosingEventArgs
e
)
private
void
Form1_FormClosing
(
object
sender
,
FormClosingEventArgs
e
)
{
{
if
(!
a
llowShutdown
)
if
(!
A
llowShutdown
)
{
{
e
.
Cancel
=
true
;
e
.
Cancel
=
true
;
}
}
else
else
{
{
if
(
thermoPrinter
!=
null
)
_thermoPrinter
?.
Stop
();
thermoPrinter
.
Stop
();
}
}
}
}
private
void
Form1_Deactivate
(
object
sender
,
EventArgs
e
)
private
void
Form1_Deactivate
(
object
sender
,
EventArgs
e
)
{
{
if
(!
allowShutdown
)
if
(!
AllowShutdown
)
this
.
Activate
();
{
Activate
();
}
else
{
UnregisterHotKey
(
Handle
,
ShutdownHotkey
);
}
}
}
private
void
Form1_KeyUp
(
object
sender
,
KeyEventArgs
e
)
private
void
Form1_KeyUp
(
object
sender
,
KeyEventArgs
e
)
{
{
if
(
e
.
Alt
&&
e
.
Control
&&
e
.
KeyCode
==
Keys
.
S
)
/*
if (e.Alt && e.Control && e.KeyCode == Keys.S)
{
{
a
llowShutdown
=
true
;
A
llowShutdown = true;
Application.Exit();
Application.Exit();
return;
return;
}
else
if
(
e
.
Alt
&&
e
.
KeyCode
==
Keys
.
F5
)
}
if (e.Alt && e.KeyCode == Keys.F5)
{
{
//userDetailsEditor1.SetPrinter(ThermoPrinterLibrary.ThermoPrinter.Models.IDP3210);
//userDetailsEditor1.SetPrinter(ThermoPrinterLibrary.ThermoPrinter.Models.IDP3210);
//MessageBox.Show("Printteri: IDP3210");
//MessageBox.Show("Printteri: IDP3210");
}*/
}
}
}
private
void
Form1_KeyDown
(
object
sender
,
KeyEventArgs
e
)
private
void
Form1_KeyDown
(
object
sender
,
KeyEventArgs
e
)
{
{
if
(
e
.
Alt
&&
e
.
Control
&&
e
.
KeyCode
==
Keys
.
S
)
if
(
e
.
Alt
&&
e
.
Control
&&
e
.
KeyCode
==
Keys
.
S
)
{
{
allowShutdown
=
true
;
AllowShutdown
=
true
;
this
.
Close
();
Close
();
return
;
}
}
}
}
private
void
Form1_MouseClick
(
object
sender
,
MouseEventArgs
e
)
private
void
Form1_MouseClick
(
object
sender
,
MouseEventArgs
e
)
{
/*
{
/*
if (e.Button == MouseButtons.Right)
if (e.Button == MouseButtons.Right)
{
{
allowShutdown = true;
allowShutdown = true;
...
@@ -214,12 +205,11 @@ namespace MoyaSignup
...
@@ -214,12 +205,11 @@ namespace MoyaSignup
return;
return;
}*/
}*/
}
}
private
void
button1_Click
(
object
sender
,
EventArgs
e
)
private
void
button1_Click
(
object
sender
,
EventArgs
e
)
{
{
a
llowShutdown
=
true
;
A
llowShutdown
=
true
;
Application
.
Exit
();
Application
.
Exit
();
}
}
...
@@ -227,7 +217,7 @@ namespace MoyaSignup
...
@@ -227,7 +217,7 @@ namespace MoyaSignup
{
{
userLoginControl1
.
Visible
=
false
;
userLoginControl1
.
Visible
=
false
;
userDetailsEditor1
.
LoadUser
(
userLoginControl1
.
CurrentUser
);
userDetailsEditor1
.
LoadUser
(
userLoginControl1
.
CurrentUser
);
userDetailsEditor1
.
ThermoPrinter
=
thermoPrinter
;
userDetailsEditor1
.
ThermoPrinter
=
_
thermoPrinter
;
userLoginControl1
.
Clear
();
userLoginControl1
.
Clear
();
userDetailsEditor1
.
Visible
=
true
;
userDetailsEditor1
.
Visible
=
true
;
//userLoginControl1.CurrentUser;
//userLoginControl1.CurrentUser;
...
@@ -235,7 +225,6 @@ namespace MoyaSignup
...
@@ -235,7 +225,6 @@ namespace MoyaSignup
private
void
userDetailsEditor1_Load
(
object
sender
,
EventArgs
e
)
private
void
userDetailsEditor1_Load
(
object
sender
,
EventArgs
e
)
{
{
}
}
private
void
userDetailsEditor1_CloseView
(
object
sender
,
EventArgs
e
)
private
void
userDetailsEditor1_CloseView
(
object
sender
,
EventArgs
e
)
...
@@ -243,7 +232,5 @@ namespace MoyaSignup
...
@@ -243,7 +232,5 @@ namespace MoyaSignup
userDetailsEditor1
.
Visible
=
false
;
userDetailsEditor1
.
Visible
=
false
;
userLoginControl1
.
Visible
=
true
;
userLoginControl1
.
Visible
=
true
;
}
}
}
}
}
}
\ No newline at end of file
MoyaSignup/Logger.cs
0 → 100644
View file @
e0d9652
using
System
;
using
System.IO
;
namespace
MoyaSignup
{
public
enum
LogLevel
{
Debug
,
Info
,
Error
}
public
static
class
Logger
{
private
static
readonly
StreamWriter
LogWriter
;
static
Logger
()
{
LogWriter
=
File
.
AppendText
(
"log.txt"
);
}
public
static
void
Log
(
LogLevel
level
,
string
message
)
{
LogWriter
.
Write
(
"[{0}] [{1}] {2}"
,
string
.
Format
(
"{0} {1}"
,
DateTime
.
UtcNow
.
ToLongTimeString
(),
DateTime
.
UtcNow
.
ToLongDateString
()),
level
,
message
+
'\n'
);
LogWriter
.
Flush
();
}
public
static
void
Debug
(
string
message
)
=>
Log
(
LogLevel
.
Debug
,
message
);
public
static
void
Info
(
string
message
)
=>
Log
(
LogLevel
.
Info
,
message
);
public
static
void
Error
(
string
message
)
=>
Log
(
LogLevel
.
Error
,
message
);
public
static
void
Error
(
string
message
,
Exception
ex
)
=>
Log
(
LogLevel
.
Error
,
message
+
":\n"
+
ex
);
}
}
\ No newline at end of file
MoyaSignup/MoyaSignup.csproj
View file @
e0d9652
...
@@ -50,11 +50,12 @@
...
@@ -50,11 +50,12 @@
</DefineConstants>
</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<Optimize>true</Optimize>
<DebugType>
none
</DebugType>
<DebugType>
pdbonly
</DebugType>
<PlatformTarget>x86</PlatformTarget>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<UseVSHostingProcess>false</UseVSHostingProcess>
<UseVSHostingProcess>false</UseVSHostingProcess>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
</PropertyGroup>
<ItemGroup>
<ItemGroup>
<Reference Include="AutoUpdateLib">
<Reference Include="AutoUpdateLib">
...
@@ -114,6 +115,7 @@
...
@@ -114,6 +115,7 @@
<DependentUpon>Form1.cs</DependentUpon>
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
</Compile>
<Compile Include="HeartBeatMonitor.cs" />
<Compile Include="HeartBeatMonitor.cs" />
<Compile Include="Logger.cs" />
<Compile Include="mjpeg\ByteArrayUtils.cs" />
<Compile Include="mjpeg\ByteArrayUtils.cs" />
<Compile Include="mjpeg\MJPEGConfiguration.cs" />
<Compile Include="mjpeg\MJPEGConfiguration.cs" />
<Compile Include="mjpeg\MJPEGSource.cs" />
<Compile Include="mjpeg\MJPEGSource.cs" />
...
...
MoyaSignup/UserLoginControl.cs
View file @
e0d9652
...
@@ -61,27 +61,19 @@ namespace MoyaSignup
...
@@ -61,27 +61,19 @@ namespace MoyaSignup
private
static
bool
IsValidEmail
(
string
email
)
private
static
bool
IsValidEmail
(
string
email
)
{
{
if
(!
email
.
Contains
(
"@"
)
||
!
email
.
Contains
(
"."
))
if
(!
email
.
Contains
(
"@"
)
||
!
email
.
Contains
(
"."
))
{
return
false
;
return
false
;
}
var
parts
=
email
.
Split
(
new
[]
{
"@"
},
StringSplitOptions
.
RemoveEmptyEntries
);
var
parts
=
email
.
Split
(
new
[]
{
"@"
},
StringSplitOptions
.
RemoveEmptyEntries
);
if
(
parts
.
Length
==
2
)
if
(
parts
.
Length
==
2
)
{
{
if
(!
parts
[
1
].
Contains
(
"."
))
if
(!
parts
[
1
].
Contains
(
"."
))
{
return
false
;
return
false
;
}
var
domainparts
=
parts
[
1
].
Split
(
new
[]
{
"."
},
StringSplitOptions
.
RemoveEmptyEntries
);
var
domainparts
=
parts
[
1
].
Split
(
new
[]
{
"."
},
StringSplitOptions
.
RemoveEmptyEntries
);
if
(
domainparts
.
Length
<
2
)
if
(
domainparts
.
Length
<
2
)
{
return
false
;
return
false
;
}
var
ltd
=
domainparts
[
domainparts
.
Length
-
1
];
var
ltd
=
domainparts
[
domainparts
.
Length
-
1
];
if
(
ltd
.
Length
<
2
)
if
(
ltd
.
Length
<
2
)
{
return
false
;
return
false
;
}
}
}
else
else
{
{
...
@@ -104,6 +96,7 @@ namespace MoyaSignup
...
@@ -104,6 +96,7 @@ namespace MoyaSignup
var
client
=
new
RestClient
();
var
client
=
new
RestClient
();
try
try
{
{
throw
new
MoyaApiException
(
"test"
,
HttpStatusCode
.
Ambiguous
,
new
WebException
());
var
json
=
client
.
MakeRequest
(
"user"
,
"email="
+
txtEmail
.
Text
);
var
json
=
client
.
MakeRequest
(
"user"
,
"email="
+
txtEmail
.
Text
);
var
ser
=
new
JavaScriptSerializer
();
var
ser
=
new
JavaScriptSerializer
();
var
euser
=
ser
.
Deserialize
<
Eventuser
>(
json
);
var
euser
=
ser
.
Deserialize
<
Eventuser
>(
json
);
...
@@ -126,6 +119,9 @@ namespace MoyaSignup
...
@@ -126,6 +119,9 @@ namespace MoyaSignup
}
}
else
else
{
{
timer1
.
Stop
();
Logger
.
Error
(
"Connection to MoyaApi failed"
,
ex
);
MessageBox
.
Show
(
MessageBox
.
Show
(
"Yhteys taustajärjestelmään epäonnistui. Ota yhteys infoon."
,
"Yhteys taustajärjestelmään epäonnistui. Ota yhteys infoon."
,
"Järjestelmävirhe"
,
"Järjestelmävirhe"
,
...
@@ -136,11 +132,8 @@ namespace MoyaSignup
...
@@ -136,11 +132,8 @@ namespace MoyaSignup
}
}
catch
(
Exception
ex
)
catch
(
Exception
ex
)
{
{
using
(
var
eventLog
=
new
EventLog
(
"Application"
))
timer1
.
Stop
();
{
Logger
.
Error
(
"Unexpected exception"
,
ex
);
eventLog
.
Source
=
"MoyaSignup"
;
eventLog
.
WriteEntry
(
string
.
Format
(
"Odottamaton virhe:\n{0}"
,
ex
.
StackTrace
),
EventLogEntryType
.
Error
,
666
);
}
MessageBox
.
Show
(
MessageBox
.
Show
(
"Odottamaton virhe. Ota yhteys infoon."
,
"Odottamaton virhe. Ota yhteys infoon."
,
...
@@ -149,6 +142,7 @@ namespace MoyaSignup
...
@@ -149,6 +142,7 @@ namespace MoyaSignup
MessageBoxIcon
.
Error
MessageBoxIcon
.
Error
);
);
}
}
timer1
.
Stop
();
timer1
.
Stop
();
}
}
...
@@ -181,7 +175,9 @@ namespace MoyaSignup
...
@@ -181,7 +175,9 @@ namespace MoyaSignup
LoginOk
?.
Invoke
(
this
,
null
);
LoginOk
?.
Invoke
(
this
,
null
);
}
}
else
else
{
WrongPass
();
WrongPass
();
}
}
}
catch
(
Exception
)
catch
(
Exception
)
{
{
...
@@ -230,7 +226,7 @@ namespace MoyaSignup
...
@@ -230,7 +226,7 @@ namespace MoyaSignup
private
void
UserLoginControl_KeyUp
(
object
sender
,
KeyEventArgs
e
)
private
void
UserLoginControl_KeyUp
(
object
sender
,
KeyEventArgs
e
)
{
{
if
(
e
.
Alt
&&
e
.
Control
&&
e
.
KeyCode
==
Keys
.
S
)
/*
if (e.Alt && e.Control && e.KeyCode == Keys.S)
{
{
Application.Exit();
Application.Exit();
return;
return;
...
@@ -240,12 +236,12 @@ namespace MoyaSignup
...
@@ -240,12 +236,12 @@ namespace MoyaSignup
{
{
//userDetailsEditor1.SetPrinter(ThermoPrinterLibrary.ThermoPrinter.Models.IDP3210);
//userDetailsEditor1.SetPrinter(ThermoPrinterLibrary.ThermoPrinter.Models.IDP3210);
//MessageBox.Show("Printteri: IDP3210");
//MessageBox.Show("Printteri: IDP3210");
}
}
*/
}
}
private
void
TxtEmail_KeyUp
(
object
sender
,
KeyEventArgs
e
)
private
void
TxtEmail_KeyUp
(
object
sender
,
KeyEventArgs
e
)
{
{
if
(
e
.
Alt
&&
e
.
Control
&&
e
.
KeyCode
==
Keys
.
S
)
/*
if (e.Alt && e.Control && e.KeyCode == Keys.S)
{
{
Program.form1.AllowShutdown = true;
Program.form1.AllowShutdown = true;
Application.Exit();
Application.Exit();
...
@@ -255,7 +251,7 @@ namespace MoyaSignup
...
@@ -255,7 +251,7 @@ namespace MoyaSignup
{
{
//userDetailsEditor1.SetPrinter(ThermoPrinterLibrary.ThermoPrinter.Models.IDP3210);
//userDetailsEditor1.SetPrinter(ThermoPrinterLibrary.ThermoPrinter.Models.IDP3210);
//MessageBox.Show("Printteri: IDP3210");
//MessageBox.Show("Printteri: IDP3210");
}
}
*/
}
}
}
}
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
Attach a file
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 post a comment