Active 'who is online' implemented; last activity of user implemented

main
Inga 🏳‍🌈 14 years ago
parent 05cb92e8ee
commit b94a29b8d8
  1. 2
      Builder/IISMainHandler/build.txt
  2. 22
      Common/dataobjects/Account.cs
  3. 71
      Common/dataobjects/Session.cs
  4. 6
      Core/DB/Diapasone.cs
  5. 2
      IISMainHandler/WebContext.cs
  6. 5
      IISMainHandler/handlers/response/UserInfoHandler.cs
  7. 29
      IISMainHandler/handlers/response/WhoIsOnlineHandler.cs
  8. 2
      templates/Full/UserInfo.xslt
  9. 59
      templates/Full/WhoIsOnline.xslt

@ -20,6 +20,8 @@ namespace FLocal.Common.dataobjects {
public const string FIELD_NAME = "Name";
public const string FIELD_IPADDRESS = "IpAddress";
public const string FIELD_REGISTRATIONEMAIL = "RegistrationEmail";
public const string FIELD_ISSTATUSHIDDEN = "IsStatusHidden";
public const string FIELD_ISDETAILEDSTATUSHIDDEN = "IsDetailedStatusHidden";
public static readonly TableSpec instance = new TableSpec();
public string name { get { return TABLE; } }
public string idName { get { return FIELD_ID; } }
@ -65,11 +67,29 @@ namespace FLocal.Common.dataobjects {
}
}
private bool _isStatusHidden;
public bool isStatusHidden {
get {
this.LoadIfNotLoaded();
return this._isStatusHidden;
}
}
private bool _isDetailedStatusHidden;
public bool isDetailedStatusHidden {
get {
this.LoadIfNotLoaded();
return this._isDetailedStatusHidden;
}
}
protected override void doFromHash(Dictionary<string, string> data) {
this._userId = int.Parse(data[TableSpec.FIELD_USERID]);
this._passwordHash = data[TableSpec.FIELD_PASSWORDHASH];
this._needsMigration = Util.string2bool(data[TableSpec.FIELD_NEEDSMIGRATION]);
this._name = data[TableSpec.FIELD_NAME];
this._isStatusHidden = Util.string2bool(data[TableSpec.FIELD_ISSTATUSHIDDEN]);
this._isDetailedStatusHidden = Util.string2bool(data[TableSpec.FIELD_ISDETAILEDSTATUSHIDDEN]);
}
public XElement exportToXml(UserContext context) {
@ -205,6 +225,8 @@ namespace FLocal.Common.dataobjects {
{ Account.TableSpec.FIELD_USERID, new ReferenceFieldValue(userInsert) },
{ Account.TableSpec.FIELD_IPADDRESS, new ScalarFieldValue(ip) },
{ Account.TableSpec.FIELD_REGISTRATIONEMAIL, new ScalarFieldValue(registrationEmail) },
{ Account.TableSpec.FIELD_ISSTATUSHIDDEN, new ScalarFieldValue("0") },
{ Account.TableSpec.FIELD_ISDETAILEDSTATUSHIDDEN, new ScalarFieldValue("0") },
}
);
var indicatorInsert = new InsertChange(

@ -48,6 +48,8 @@ namespace FLocal.Common.dataobjects {
public const string FIELD_SESSIONKEY = "SessionKey";
public const string FIELD_ACCOUNTID = "AccountId";
public const string FIELD_LASTACTIVITY = "LastActivity";
public const string FIELD_LASTURL = "LastUrl";
public const string FIELD_ISDELETED = "IsDeleted";
public static readonly TableSpec instance = new TableSpec();
public string name { get { return TABLE; } }
public string idName { get { return FIELD_ID; } }
@ -85,13 +87,31 @@ namespace FLocal.Common.dataobjects {
}
}
private string _lastUrl;
public string lastUrl {
get {
this.LoadIfNotLoaded();
return this._lastUrl;
}
}
private bool _isDeleted;
public bool isDeleted {
get {
this.LoadIfNotLoaded();
return this._isDeleted;
}
}
protected override void doFromHash(Dictionary<string, string> data) {
this._sessionKey = data[TableSpec.FIELD_SESSIONKEY];
this._lastActivity = new DateTime(long.Parse(data[TableSpec.FIELD_LASTACTIVITY]));
this._accountId = int.Parse(data[TableSpec.FIELD_ACCOUNTID]);
this._lastUrl = data[TableSpec.FIELD_LASTURL];
this._isDeleted = Util.string2bool(data[TableSpec.FIELD_ISDELETED]);
}
public void updateLastActivity() {
public void updateLastActivity(string lastUrl) {
if(DateTime.Now.Subtract(this.lastActivity).TotalSeconds < 30) return; //to partially remove db load
try {
Config.Transactional(transaction => {
@ -100,7 +120,8 @@ namespace FLocal.Common.dataobjects {
TableSpec.instance,
this.id.ToString(),
new Dictionary<string,string>() {
{ TableSpec.FIELD_LASTACTIVITY, DateTime.Now.ToUTCString() }
{ TableSpec.FIELD_LASTACTIVITY, DateTime.Now.ToUTCString() },
{ TableSpec.FIELD_LASTURL, (lastUrl != null) ? lastUrl : this.lastUrl },
}
);
});
@ -128,6 +149,8 @@ namespace FLocal.Common.dataobjects {
{ TableSpec.FIELD_SESSIONKEY, key },
{ TableSpec.FIELD_ACCOUNTID, account.id.ToString() },
{ TableSpec.FIELD_LASTACTIVITY, DateTime.Now.ToUTCString() },
{ TableSpec.FIELD_LASTURL, "" },
{ TableSpec.FIELD_ISDELETED, "0" },
}
);
});
@ -135,8 +158,20 @@ namespace FLocal.Common.dataobjects {
}
public void delete() {
Config.Transactional(transaction => Config.instance.mainConnection.delete(transaction, TableSpec.instance, this.id.ToString()));
this.deleteFromRegistry();
try {
Config.Transactional(transaction => {
Config.instance.mainConnection.update(
transaction,
TableSpec.instance,
this.id.ToString(),
new Dictionary<string,string>() {
{ TableSpec.FIELD_ISDELETED, "1" },
}
);
});
} finally {
this.ReLoad();
}
}
public XElement exportToXml(UserContext context) {
@ -149,7 +184,33 @@ namespace FLocal.Common.dataobjects {
}
public static Session LoadByKey(string sessionKey) {
return LoadById(SessionKey.Parse(sessionKey));
Session result = LoadById(SessionKey.Parse(sessionKey));
if(result.isDeleted) throw new NotFoundInDBException(TableSpec.instance, sessionKey);
return result;
}
public static Session GetLastSession(Account account) {
var ids = Config.instance.mainConnection.LoadIdsByConditions(
TableSpec.instance,
new ComparisonCondition(
TableSpec.instance.getColumnSpec(TableSpec.FIELD_ACCOUNTID),
ComparisonType.EQUAL,
account.id.ToString()
),
Diapasone.first,
new JoinSpec[0],
new SortSpec[] {
new SortSpec(
TableSpec.instance.getColumnSpec(TableSpec.FIELD_LASTACTIVITY),
false
)
}
);
if(ids.Count < 1) {
throw new NotFoundInDBException(TableSpec.instance.getColumnSpec(TableSpec.FIELD_ACCOUNTID), account.id.ToString());
}
return Session.LoadById(SessionKey.Parse(ids[0]));
}
}

@ -24,5 +24,11 @@ namespace FLocal.Core.DB {
}
}
public static Diapasone first {
get {
return new Diapasone(0, 1);
}
}
}
}

@ -92,7 +92,7 @@ namespace FLocal.IISHandler {
var session = Session.LoadByKey(sessionCookie.Value);
var tmp = session.account;
sessionCookie.Expires = DateTime.Now.AddDays(3);
session.updateLastActivity();
session.updateLastActivity(this.httprequest.RequestType == "GET" ? this.httprequest.Path : null);
this.httpresponse.AppendCookie(sessionCookie);
this.session = session;
} catch(NotFoundInDBException) {

@ -37,9 +37,14 @@ namespace FLocal.IISHandler.handlers.response {
} catch(NotFoundInDBException) {
}
}
Session lastSession = null;
if(account != null && !account.isDetailedStatusHidden) {
lastSession = Session.GetLastSession(account);
}
return new XElement[] {
user.exportToXmlForViewing(context),
(account == null) ? null : new XElement("accountId", account.id.ToString()), //for PM history, PM send etc
(lastSession == null) ? null : new XElement("lastActivity", lastSession.lastActivity.ToXml())
};
}

@ -16,7 +16,7 @@ namespace FLocal.IISHandler.handlers.response {
override protected string templateName {
get {
return "UserList.xslt";
return "WhoIsOnline.xslt";
}
}
@ -25,16 +25,31 @@ namespace FLocal.IISHandler.handlers.response {
IEnumerable<Session> sessions =
from stringId in Config.instance.mainConnection.LoadIdsByConditions(
Session.TableSpec.instance,
new Core.DB.conditions.ComparisonCondition(
Session.TableSpec.instance.getColumnSpec(Session.TableSpec.FIELD_LASTACTIVITY),
Core.DB.conditions.ComparisonType.GREATEROREQUAL,
DateTime.Now.Subtract(Config.instance.ActivityThreshold).ToUTCString()
new ComplexCondition(
ConditionsJoinType.AND,
new ComparisonCondition(
Session.TableSpec.instance.getColumnSpec(Session.TableSpec.FIELD_LASTACTIVITY),
Core.DB.conditions.ComparisonType.GREATEROREQUAL,
DateTime.Now.Subtract(Config.instance.ActivityThreshold).ToUTCString()
),
new ComparisonCondition(
Session.TableSpec.instance.getColumnSpec(Session.TableSpec.FIELD_ISDELETED),
Core.DB.conditions.ComparisonType.EQUAL,
"0"
)
),
pageOuter
) select Session.LoadByKey(stringId);
return new XElement[] {
new XElement("users",
from session in sessions select session.account.user.exportToXmlForViewing(context)
new XElement("users",
from session in sessions
let account = session.account
where !account.isStatusHidden
select account.user.exportToXmlForViewing(
context,
new XElement("lastActivity", session.lastActivity.ToXml()),
!account.isDetailedStatusHidden ? new XElement("lastUrl", session.lastUrl) : null
)
)
};
}

@ -144,7 +144,7 @@
<xsl:text>Ïîñëåäíèé ðàç îíëàéí</xsl:text>
</td>
<td>
<xsl:text>Not implemented</xsl:text>
<xsl:apply-templates select="lastActivity" mode="dateTime"/>
</td>
</tr>
<tr>

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="Windows-1251"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:import href="elems\Main.xslt"/>
<xsl:template name="specificTitle">Ïîëüçîâàòåëè</xsl:template>
<xsl:template name="specific">
<table width="95%" align="center" cellpadding="1" cellspacing="1" class="tablesurround">
<tr>
<td>
<table cellpadding="3" cellspacing="1" width="100%" class="tableborders">
<tr class="tdheader">
<td align="left" width="15%" nowrap="nowrap">
<a>
<xsl:text>Ïîëüçîâàòåëü</xsl:text>
</a>
</td>
<td align="left" width="15%" nowrap="nowrap">
<a>
<xsl:text>Ïîñëåäíÿÿ àêòèâíîñòü</xsl:text>
</a>
</td>
<td align="left" width="70%" nowrap="nowrap">
<a>
<xsl:text>Ïîñëåäíÿÿ ïîñåù¸ííàÿ ñòðàíèöà</xsl:text>
</a>
</td>
</tr>
<xsl:apply-templates select="users/user"/>
</table>
</td>
</tr>
</table>
</xsl:template>
<xsl:template match="users/user">
<tr>
<xsl:choose>
<xsl:when test="position() mod 2 = 0">
<xsl:attribute name="class">lighttable</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="class">darktable</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<td>
<xsl:apply-templates select="current()" mode="userLink"/>
</td>
<td>
<xsl:apply-templates select="lastActivity" mode="dateTime"/>
</td>
<td>
<a>
<xsl:attribute name="href"><xsl:value-of select="lastUrl"/></xsl:attribute>
<xsl:value-of select="lastUrl"/>
</a>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
Loading…
Cancel
Save