aboutsummaryrefslogtreecommitdiffstats
path: root/97suifangqa/apps/indicator
diff options
context:
space:
mode:
authorAlvin Li <liweitianux@gmail.com>2013-08-18 00:52:06 +0800
committerAlvin Li <liweitianux@gmail.com>2013-08-18 00:52:06 +0800
commit9d07e8a26657542c98535abb7812d83a98839918 (patch)
tree6d5b039e7c01082a280fcefb7cc4fe3ca806e521 /97suifangqa/apps/indicator
parent0cdba05f09201b6db129ebaa787e960be9ecb851 (diff)
download97dev-9d07e8a26657542c98535abb7812d83a98839918.tar.bz2
* improved 'indicator.views.follow_indicator()',
renamed to 'indicator_fanduf()' due to name conflict * finished 'search' function for page indicator NewDeleteIndex.html * added 'apps/utils/search_tools.py': some tools to process search results * renamed 'sciblog/templatetags/tools.py' to 'get_range.py' * added 'format_data()' to indicator.tools': to format data of record/confine, make it properly display in html page; * 'indicator/javascripts/new_delete_index.js': added global 'var added_indexes_id' to track the already added indexes * added 'indicator/templatetags/divisible_by.py' filter to check if a number can be extactly divide by another number; * fixed the 'index_card_fir/index_card_sec' problem of 'act_card_container' of page 'SheetDefault.html' * indicator/static/css/new_delete_index.css: added 'index_search_error' and 'index_error' * fixed 'unit.dump' problems in 'indicator.models' * 'indicator.tools': o added 'RI_TYPES', 'RI_WEIGHTS' o added 'type' in the return value of 'calc_indicator_weight()' and 'recommend_indicator()' * added field 'followedHistories' in 'indicator.models.UserIndicator' * moved 'follow_indicator()' and 'unfollow_indicator()' from 'indicator.views' to 'indicator.tools' TODO: * highcharts: draw chart for indicator records; * add/edit data, and submit (page format design) * followed indicator submit buttion
Diffstat (limited to '97suifangqa/apps/indicator')
-rw-r--r--97suifangqa/apps/indicator/fixtures/initial_data.json203
-rw-r--r--97suifangqa/apps/indicator/models.py30
-rw-r--r--97suifangqa/apps/indicator/search_indexes.py4
-rw-r--r--97suifangqa/apps/indicator/static/css/new_delete_index.css12
-rw-r--r--97suifangqa/apps/indicator/static/css/sheet_default.css9
-rw-r--r--97suifangqa/apps/indicator/static/javascripts/delete_card_tip.js26
-rw-r--r--97suifangqa/apps/indicator/static/javascripts/load_card.js107
-rw-r--r--97suifangqa/apps/indicator/static/javascripts/new_delete_index.js26
-rw-r--r--97suifangqa/apps/indicator/templates/indicator/NewDeleteIndex.html110
-rw-r--r--97suifangqa/apps/indicator/templates/indicator/SheetDefault.html361
-rw-r--r--97suifangqa/apps/indicator/templates/indicator/index.html2
-rw-r--r--97suifangqa/apps/indicator/templates/indicator/popup/DeleteCardTip.html4
-rw-r--r--97suifangqa/apps/indicator/templatetags/divisible_by.py30
-rw-r--r--97suifangqa/apps/indicator/tools.py204
-rw-r--r--97suifangqa/apps/indicator/urls.py12
-rw-r--r--97suifangqa/apps/indicator/views.py302
16 files changed, 968 insertions, 474 deletions
diff --git a/97suifangqa/apps/indicator/fixtures/initial_data.json b/97suifangqa/apps/indicator/fixtures/initial_data.json
index 25d6c73..07aeaaa 100644
--- a/97suifangqa/apps/indicator/fixtures/initial_data.json
+++ b/97suifangqa/apps/indicator/fixtures/initial_data.json
@@ -1,24 +1,79 @@
[
{
- "pk": 1,
+ "pk": 4,
+ "model": "indicator.indicatorcategory",
+ "fields": {
+ "pinyin": "gan-chuan-ci",
+ "englishName": "Liver Puncture",
+ "addByUser": 1,
+ "name": "\u809d\u7a7f\u523a",
+ "description": "\u809d\u7a7f\u523a"
+ }
+ },
+ {
+ "pk": 3,
+ "model": "indicator.indicatorcategory",
+ "fields": {
+ "pinyin": "gan-gong-neng",
+ "englishName": "Liver Function",
+ "addByUser": 1,
+ "name": "\u809d\u529f\u80fd",
+ "description": "\u809d\u529f\u80fd"
+ }
+ },
+ {
+ "pk": 5,
+ "model": "indicator.indicatorcategory",
+ "fields": {
+ "pinyin": "lei-bie-5",
+ "englishName": "category5",
+ "addByUser": 1,
+ "name": "\u7c7b\u522b5",
+ "description": "\u7c7b\u522b5\r\n\u6d4b\u8bd5"
+ }
+ },
+ {
+ "pk": 6,
"model": "indicator.indicatorcategory",
"fields": {
- "pinyin": "lei-bie-1",
- "englishName": "category1",
+ "pinyin": "lei-bie-6",
+ "englishName": "category6",
"addByUser": 1,
- "name": "\u7c7b\u522b1",
- "description": "\u6307\u6807\u7c7b\u522b1\r\n\r\n\u4fee\u65391\uff08\u6d4b\u8bd5\uff09"
+ "name": "\u7c7b\u522b6",
+ "description": "\u7c7b\u522b6\r\n\r\n\u6d4b\u8bd5"
+ }
+ },
+ {
+ "pk": 7,
+ "model": "indicator.indicatorcategory",
+ "fields": {
+ "pinyin": "lei-bie-7",
+ "englishName": "category7",
+ "addByUser": 1,
+ "name": "\u7c7b\u522b7",
+ "description": "\u7c7b\u522b7\r\n\r\n\u6d4b\u8bd5"
}
},
{
"pk": 2,
"model": "indicator.indicatorcategory",
"fields": {
- "pinyin": "lei-bie-2",
- "englishName": "category2",
+ "pinyin": "liang-dui-ban",
+ "englishName": "TODO",
"addByUser": 1,
- "name": "\u7c7b\u522b2",
- "description": "\u7c7b\u522b2\r\n\r\nadd_edit_category() \u6dfb\u52a0"
+ "name": "\u4e24\u5bf9\u534a",
+ "description": "\u4e59\u809d\u4e24\u5bf9\u534a"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "indicator.indicatorcategory",
+ "fields": {
+ "pinyin": "xie-chang-gui",
+ "englishName": "Blood Routine",
+ "addByUser": 1,
+ "name": "\u8840\u5e38\u89c4",
+ "description": "\u8840\u5e38\u89c4"
}
},
{
@@ -27,14 +82,30 @@
"fields": {
"addByUser": 1,
"name": "\u6d4b\u8bd51",
- "dataType": "FL",
+ "dataType": "PM",
"pinyin": "ce-shi-1",
"helpText": "\u5e2e\u52a9 help",
"englishName": "test1",
"categories": [
+ 2
+ ],
+ "description": "forms \u6d4b\u8bd51\r\npm type"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "indicator.indicator",
+ "fields": {
+ "addByUser": 1,
+ "name": "\u5b9a1",
+ "dataType": "FL",
+ "pinyin": "ding-1",
+ "helpText": "\u6d6e\u70b9\u578b",
+ "englishName": "indicator1",
+ "categories": [
1
],
- "description": "forms \u6d4b\u8bd51"
+ "description": "\u5b9a\u503c1\r\n\r\n\u6d6e\u70b9\u578b\u6570\u636e"
}
},
{
@@ -42,12 +113,13 @@
"model": "indicator.indicator",
"fields": {
"addByUser": 1,
- "name": "\u5b9a\u503c1",
+ "name": "\u5b9a\u503c2",
"dataType": "FL",
- "pinyin": "ding-zhi-1",
+ "pinyin": "ding-zhi-2",
"helpText": "\u6d6e\u70b9\u5b9a\u503c",
- "englishName": "float1",
+ "englishName": "float2",
"categories": [
+ 2,
1
],
"description": "float type"
@@ -71,28 +143,24 @@
},
{
"pk": 1,
- "model": "indicator.indicator",
+ "model": "indicator.userindicator",
"fields": {
- "addByUser": 1,
- "name": "\u6307\u68071",
- "dataType": "FL",
- "pinyin": "zhi-biao-1",
- "helpText": "\u6d6e\u70b9\u578b",
- "englishName": "indicator1",
- "categories": [
- 1
+ "followedIndicators": [
+ 3,
+ 1,
+ 2
],
- "description": "\u6307\u68071\r\n\r\n\u6d6e\u70b9\u578b\u6570\u636e"
+ "followedHistories": [],
+ "user": 1
}
},
{
- "pk": 1,
+ "pk": 2,
"model": "indicator.userindicator",
"fields": {
- "followedIndicators": [
- 4
- ],
- "user": 1
+ "followedIndicators": [],
+ "followedHistories": [],
+ "user": 2
}
},
{
@@ -101,8 +169,8 @@
"fields": {
"indicator": 1,
"notes": "\u6307\u68071\r\n\u7b2c1\u6761\u8bb0\u5f55",
- "created_at": "2013-08-05T15:48:00.035",
- "updated_at": "2013-08-05T15:50:00.326",
+ "created_at": "2013-08-05T15:48:00.035Z",
+ "updated_at": "2013-08-05T15:50:00.326Z",
"value": "250",
"val_min": null,
"user": 1,
@@ -116,23 +184,39 @@
"model": "indicator.indicatorrecord",
"fields": {
"indicator": 1,
- "notes": "test\r\n\u8bb0\u5f55",
- "created_at": "2013-08-09T10:53:15.927",
- "updated_at": "2013-08-10T00:30:09.336",
+ "notes": "\r\n\u8bb0\u5f55",
+ "created_at": "2013-08-09T10:53:15.927Z",
+ "updated_at": "2013-08-16T16:23:33.798Z",
"value": "50",
"val_min": null,
- "user": 2,
+ "user": 1,
"date": "2013-08-09",
"val_max": null,
"unit": 1
}
},
{
+ "pk": 3,
+ "model": "indicator.indicatorrecord",
+ "fields": {
+ "indicator": 3,
+ "notes": "pm type\r\nrecord 1",
+ "created_at": "2013-08-16T16:07:00.547Z",
+ "updated_at": "2013-08-16T16:07:00.547Z",
+ "value": "+",
+ "val_min": null,
+ "user": 1,
+ "date": "2013-08-17",
+ "val_max": null,
+ "unit": null
+ }
+ },
+ {
"pk": 1,
"model": "indicator.recordhistory",
"fields": {
"val_min_bak": null,
- "created_at": "2013-08-05T16:07:01.832",
+ "created_at": "2013-08-05T16:07:01.832Z",
"indicatorRecord": 1,
"reason": "\u6d4b\u8bd5\r\nadmin\u754c\u9762\u76f4\u63a5\u4fee\u6539",
"unit_bak": 1,
@@ -147,7 +231,7 @@
"model": "indicator.recordhistory",
"fields": {
"val_min_bak": null,
- "created_at": "2013-08-10T11:40:23.170",
+ "created_at": "2013-08-10T11:40:23.170Z",
"indicatorRecord": 1,
"reason": "\u6d4b\u8bd5\u4fee\u6539",
"unit_bak": 1,
@@ -228,15 +312,30 @@
"pk": 2,
"model": "indicator.innateconfine",
"fields": {
- "math_max": 800.0,
+ "math_max": 80000.0,
"indicator": 2,
- "human_max": 500.0,
+ "human_max": 50000.0,
"description": "\u6307\u6807\r\n\r\n\u6570\u636e\u7c7b\u578b\uff1a\u8303\u56f4\u578b\r\n\r\n\u6570\u636e\u8303\u56f4",
"val_norm": "",
"addByUser": 1,
- "human_min": 50.0,
+ "human_min": 10000.0,
"unit": 3,
- "math_min": 0.0
+ "math_min": 5000.0
+ }
+ },
+ {
+ "pk": 3,
+ "model": "indicator.innateconfine",
+ "fields": {
+ "math_max": null,
+ "indicator": 3,
+ "human_max": null,
+ "description": "pm type",
+ "val_norm": "+",
+ "addByUser": 1,
+ "human_min": null,
+ "unit": null,
+ "math_min": null
}
},
{
@@ -245,8 +344,8 @@
"fields": {
"indicator": 1,
"weight": 5.9,
- "created_at": "2013-08-10T22:40:00.035",
- "updated_at": "2013-08-10T22:40:00.326",
+ "created_at": "2013-08-10T22:40:00.035Z",
+ "updated_at": "2013-08-10T22:40:00.326Z",
"blog": null,
"annotation": 2,
"objectType": "AN"
@@ -258,8 +357,8 @@
"fields": {
"indicator": 1,
"weight": 8.0,
- "created_at": "2013-08-11T00:56:08.080",
- "updated_at": "2013-08-11T00:56:08.080",
+ "created_at": "2013-08-11T00:56:08.080Z",
+ "updated_at": "2013-08-11T00:56:08.080Z",
"blog": null,
"annotation": 1,
"objectType": "AN"
@@ -271,8 +370,8 @@
"fields": {
"indicator": 2,
"weight": 8.3,
- "created_at": "2013-08-10T22:50:00.035",
- "updated_at": "2013-08-10T22:50:00.326",
+ "created_at": "2013-08-10T22:50:00.035Z",
+ "updated_at": "2013-08-10T22:50:00.326Z",
"blog": 3,
"annotation": null,
"objectType": "BL"
@@ -284,8 +383,8 @@
"fields": {
"indicator": 1,
"weight": 4.0,
- "created_at": "2013-08-11T00:56:49.463",
- "updated_at": "2013-08-11T00:56:49.463",
+ "created_at": "2013-08-11T00:56:49.463Z",
+ "updated_at": "2013-08-11T00:56:49.463Z",
"blog": 1,
"annotation": null,
"objectType": "BL"
@@ -297,11 +396,11 @@
"fields": {
"indicator": 1,
"weight": 6.0,
- "created_at": "2013-08-11T00:57:23.067",
- "updated_at": "2013-08-11T00:57:23.067",
+ "created_at": "2013-08-11T00:57:23.067Z",
+ "updated_at": "2013-08-11T00:57:23.067Z",
"blog": 3,
"annotation": null,
"objectType": "BL"
}
}
-] \ No newline at end of file
+]
diff --git a/97suifangqa/apps/indicator/models.py b/97suifangqa/apps/indicator/models.py
index 615398f..18c699c 100644
--- a/97suifangqa/apps/indicator/models.py
+++ b/97suifangqa/apps/indicator/models.py
@@ -247,7 +247,11 @@ class UserIndicator(models.Model): # {{{
related_name="user_indicator")
followedIndicators = models.ManyToManyField(Indicator,
verbose_name=u"关注的指标",
- related_name="user_indicators",
+ related_name="followed_indicators",
+ null=True, blank=True)
+ followedHistories = models.ManyToManyField(Indicator,
+ verbose_name=u"历史关注指标",
+ related_name="followed_histories",
null=True, blank=True)
class Meta:
@@ -658,6 +662,12 @@ class IndicatorRecord(models.Model): # {{{
# }}}
def dump(self, **kwargs):
+ # check if the indicator needs unit
+ if self.unit:
+ unit_id = self.unit.id
+ else:
+ unit_id = None
+ # dump
dump_data = {
'id': self.id,
'indicator_id': self.indicator.id,
@@ -665,7 +675,7 @@ class IndicatorRecord(models.Model): # {{{
'created_at': self.created_at.isoformat(),
'updated_at': self.updated_at.isoformat(),
'date': self.date.isoformat(),
- 'unit_id': self.unit.id,
+ 'unit_id': unit_id,
'value': self.value,
'val_max': self.val_max,
'val_min': self.val_min,
@@ -724,13 +734,19 @@ class RecordHistory(models.Model): # {{{
super(RecordHistory, self).save(**kwargs)
def dump(self, **kwargs):
+ # check 'unit_bak'
+ if self.unit_bak:
+ unit_bak_id = self.unit_bak.id
+ else:
+ unit_bak_id = None
+ # dump
dump_data = {
'id': self.id,
'indicatorRecord_id': self.indicatorRecord.id,
'created_at': self.created_at.isoformat(),
'reason': self.reason,
'date_bak': self.date_bak.isoformat(),
- 'unit_bak_id': self.unit_bak.id,
+ 'unit_bak_id': unit_bak_id,
'value_bak': self.value_bak,
'val_max_bak': self.val_max_bak,
'val_min_bak': self.val_min_bak,
@@ -930,10 +946,16 @@ class InnateConfine(models.Model): # {{{
# }}}
def dump(self, **kwargs):
+ # check unit, if the indicator not need unit, then return {}
+ if self.unit:
+ unit_dump = self.unit.dump()
+ else:
+ unit_dump = {}
+ # dump
dump_data = {
'id': self.id,
'indicator_id': self.indicator.id,
- 'unit': self.unit.dump(),
+ 'unit': unit_dump,
'val_norm': self.val_norm,
'human_max': self.human_max,
'human_min': self.human_min,
diff --git a/97suifangqa/apps/indicator/search_indexes.py b/97suifangqa/apps/indicator/search_indexes.py
index 67d5723..f225b2c 100644
--- a/97suifangqa/apps/indicator/search_indexes.py
+++ b/97suifangqa/apps/indicator/search_indexes.py
@@ -12,6 +12,8 @@ class IndicatorCategoryIndex(indexes.SearchIndex, indexes.Indexable):
search index for 'Indicator'
"""
text = indexes.CharField(document=True, use_template=True)
+ # pinyin: for ordering the search result
+ pinyin = indexes.CharField(model_attr='pinyin')
addByUser = indexes.CharField(model_attr='addByUser')
def get_model(self):
@@ -31,6 +33,8 @@ class IndicatorIndex(indexes.SearchIndex, indexes.Indexable):
search index for 'Indicator'
"""
text = indexes.CharField(document=True, use_template=True)
+ # pinyin: for ordering the search result
+ pinyin = indexes.CharField(model_attr='pinyin')
addByUser = indexes.CharField(model_attr='addByUser')
dataType = indexes.CharField(model_attr='dataType')
categories_id = indexes.MultiValueField()
diff --git a/97suifangqa/apps/indicator/static/css/new_delete_index.css b/97suifangqa/apps/indicator/static/css/new_delete_index.css
index 0eb41d1..b5b161a 100644
--- a/97suifangqa/apps/indicator/static/css/new_delete_index.css
+++ b/97suifangqa/apps/indicator/static/css/new_delete_index.css
@@ -160,6 +160,18 @@
width: 185px;
}
+.index_search_error {
+ margin-top: 3px;
+}
+.index_search_error .index_error {
+ float: left;
+ font-size: 14px;
+ height: 20px;
+ line-height: 20px;
+ color: #4A4A4A;
+ font-weight: bold;
+}
+
.all_condition .index_all_title {
font-weight: bold;
font-size: 19px;
diff --git a/97suifangqa/apps/indicator/static/css/sheet_default.css b/97suifangqa/apps/indicator/static/css/sheet_default.css
index aca021c..15d1a98 100644
--- a/97suifangqa/apps/indicator/static/css/sheet_default.css
+++ b/97suifangqa/apps/indicator/static/css/sheet_default.css
@@ -153,6 +153,9 @@
.index_card .refer_range .refer_text {
margin-right: 5px;
}
+.index_card .refer_range .refer_value {
+ margin-right: 5px;
+}
.index_card .edit_data, .index_card .editing_data {
height: 25px;
margin-top: 7px;
@@ -216,6 +219,10 @@
margin-top: 1px;
cursor: pointer;
}
+.index_card .editing_data .data_unit {
+ float: left;
+ margin-right: 8px;
+}
.index_card .editing_data .cancel_edit_icon {
float: right;
background:url(../images/cancel_edit.png) no-repeat;
@@ -356,4 +363,4 @@
}
.move_div_2_left {
float: left;
-} \ No newline at end of file
+}
diff --git a/97suifangqa/apps/indicator/static/javascripts/delete_card_tip.js b/97suifangqa/apps/indicator/static/javascripts/delete_card_tip.js
index 099a216..9365d46 100644
--- a/97suifangqa/apps/indicator/static/javascripts/delete_card_tip.js
+++ b/97suifangqa/apps/indicator/static/javascripts/delete_card_tip.js
@@ -1,4 +1,7 @@
+// global js var: card_2_delete_id (type: string)
+
$(document).ready(function(){
+// console.log(parent.card_2_delete_id); //要取消关注的 卡片id 的获取方法
//点大叉、继续关注按钮,关闭弹层页面
$(".delete_card_tip_close, .action_confirm_ignore").bind("click", function(){
parent.TB_remove();
@@ -7,12 +10,23 @@ $(document).ready(function(){
//取消关注,关闭弹层页面
$(".action_confirm_cancel").bind("click", function(){
- //TODO
- //底层数据层取消关注(ajax)
- //console.log(parent.card_2_delete_id); //要取消关注的 卡片id 的获取方法
+ // ajax process to unfollow the indicator
+ // indicator_id -> parseInt(parent.card_2_delete_id)
+ // 底层数据层取消关注(ajax)
+ var date = new Date();
+ var time = date.getTime();
+ $.ajax({
+ type: 'get',
+ url: parent.indicator_url + 'ajax/unfollow_indicator',
+ data: 'indicator_id='+parent.card_2_delete_id+'&time='+time,
+ success: function(data) {
+ if (data == 'success') {
+ parent.delete_card();
+ parent.TB_remove();
+ }
+ },
+ });
- parent.delete_card();
- parent.TB_remove();
return false;
});
-}); \ No newline at end of file
+});
diff --git a/97suifangqa/apps/indicator/static/javascripts/load_card.js b/97suifangqa/apps/indicator/static/javascripts/load_card.js
index 4db48a4..160273b 100644
--- a/97suifangqa/apps/indicator/static/javascripts/load_card.js
+++ b/97suifangqa/apps/indicator/static/javascripts/load_card.js
@@ -1,26 +1,61 @@
var detail_chart;
-$(document).ready(function(){
- var startDate = '2013-07-13';
- startDate = new Date(startDate.replace(/-/g,"/"));
- var start_date_UTC_time = startDate.getTime() - startDate.getTimezoneOffset() * 60 * 1000;
- var chart3 = new Highcharts.Chart({
+
+// set global options for hightcharts {{{
+$(function() {
+ Highcharts.setOptions ({
chart: {
- renderTo: 'chart_3',
type: 'area',
marginLeft: 15,
height: 223,
spacingTop: 10,
- spacingBottom: 0,
- overflow: false,
- zIndex: 5
+ spacingBottom: 0
+ //overflow: false,
+ //zIndex: 5
},
+ colors: ['#31B6AD'],
credits: {
enabled: false
},
+ legend: {
+ enabled: false
+ },
+ plotOptions: {
+ series: {
+ fillOpacity: 0.12,
+ lineWidth: 1,
+ marker: {
+ enabled: true, //false false的时候就不会突出显示点
+ lineColor: '#31B6AD',
+ lineWidth: 1,
+ radius: 3, // 点的大小
+ fillColor: '#FFFFFF' // 设置点中间填充的颜色
+ },
+ shadow: false
+ //threshold: null
+ }
+ },
+ //series: [{
+ // data: [6.0, 5.9, 5.5, 4.5, 6.2, 6.5, 5.2, 6.0,
+ // 5.9, 5.5, 4.5, 6.2, 6.5, 5.2, 6.0, 5.9,
+ // 5.5, 4.5, 6.2, 6.5],
+ // pointStart: start_date_UTC_time,
+ // pointInterval: 1 * 24 * 3600 * 1000 // one day
+ //}],
title: {
- text: ' '
+ text: null
+ },
+ tooltip: {
+ //formatter: function() {
+ // return '<span style="color:#969696;font-weight:bold;">' + Highcharts.dateFormat('%b %e', this.x) + '</span>' +'<br />' + '<span style="color:#464646;font-weight:bold;">' + this.y + 'mmol/L' + '</span>' + '<br />' + 'click for more info';
+ //},
+ // positioner: function (boxWidth, boxHeight, point) {
+ // return { x: point.plotX+80, y: point.plotY-20 };
+ // },
+ style: {
+ padding: '7px'
+ },
+ borderColor: '#EAEAEA'
},
- colors: ['#31B6AD'],
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
@@ -34,13 +69,13 @@ $(document).ready(function(){
step: 2,
maxStaggerLines: 1
},
- tickInterval: (4 * 24 * 3600 * 1000),
+ tickInterval: (4 * 24 * 3600 * 1000), // 4 days
tickColor: '#FFFFFF'
},
yAxis: {
- title: {
- text: ''
- },
+ //title: {
+ // text: ''
+ //},
allowDecimals: false,
endOnTick: false,
tickInterval: 1,
@@ -50,36 +85,31 @@ $(document).ready(function(){
gridLineWidth: 1,
minPadding: 0.3,
maxPadding: 1.2
+ }
+ });
+});
+// }}}
+
+$(document).ready(function(){
+ var startDate = '2013-07-13';
+ startDate = new Date(startDate.replace(/-/g,"/"));
+ var start_date_UTC_time = startDate.getTime() - startDate.getTimezoneOffset() * 60 * 1000;
+ var chart3 = new Highcharts.Chart({
+ chart: {
+ renderTo: 'chart_3'
},
- legend: {
- enabled: false
+ yAxis: {
+ title: {
+ text: ''
+ }
},
tooltip: {
formatter: function() {
return '<span style="color:#969696;font-weight:bold;">' + Highcharts.dateFormat('%b %e', this.x) + '</span>' +'<br />' + '<span style="color:#464646;font-weight:bold;">' + this.y + 'mmol/L' + '</span>' + '<br />' + 'click for more info';
- },
+ }
// positioner: function (boxWidth, boxHeight, point) {
// return { x: point.plotX+80, y: point.plotY-20 };
// },
- style: {
- padding: '7px'
- },
- borderColor: '#EAEAEA'
- },
- plotOptions: {
- series: {
- marker: {
- enabled: true, //false false的时候就不会突出显示点
- lineColor: '#31B6AD',
- lineWidth: 1,
- radius: 3, // 点的大小
- fillColor: '#FFFFFF' // 设置点中间填充的颜色
- },
- fillOpacity: 0.12,
- lineWidth: 1,
- threshold: null,
- shadow: false
- }
},
series: [{
data: [6.0, 5.9, 5.5, 4.5, 6.2, 6.5, 5.2, 6.0, 5.9, 5.5, 4.5, 6.2, 6.5, 5.2, 6.0, 5.9, 5.5, 4.5, 6.2, 6.5],
@@ -254,7 +284,8 @@ function redraw_chart(detail_chart, start, end){
url: indicator_url + 'ajax/get_card_data_chart',
data: 'card_detail_id='+card_detail_id+'&start='+start+'&end='+end+'&time='+time,
dataType: 'json',
- success: function(dataJson) { //每一天都要有数据,否则x轴刻度时间对不上
+ success: function(dataJson) {
+ //每一天都要有数据,否则x轴刻度时间对不上
var startDateLogFormat = new Date(start.replace(/-/g,"/"));
var start_date_log_UTC_time = startDateLogFormat.getTime() - startDateLogFormat.getTimezoneOffset() * 60 * 1000;
var pointStart = start_date_log_UTC_time;
diff --git a/97suifangqa/apps/indicator/static/javascripts/new_delete_index.js b/97suifangqa/apps/indicator/static/javascripts/new_delete_index.js
index 2c05d7f..8beed99 100644
--- a/97suifangqa/apps/indicator/static/javascripts/new_delete_index.js
+++ b/97suifangqa/apps/indicator/static/javascripts/new_delete_index.js
@@ -1,3 +1,6 @@
+// track the indexes already added(/followed)
+var added_indexes_id = new Array();
+
$(document).ready(function(){
$("#search_btn").bind("click", function(){
var kw = $("#search_kw").val();
@@ -10,6 +13,11 @@ $(document).ready(function(){
$(".right>.index_line").each(function(){
classHover($(this), "minus");
});
+ // save the "index_id's of added (type: string)
+ $(".right>.index_line").each(function(){
+ var index_id = $(this).attr("index_id");
+ added_indexes_id.push(index_id);
+ });
$(".add>.icon").live("click", function(){
var add_icon = $(this);
var index_id = add_icon.closest(".index_line").attr("index_id");
@@ -21,12 +29,16 @@ $(document).ready(function(){
data: 'index_id='+index_id+'&act=add'+'&time='+time,
success: function(data){
if(data == 'success'){
- var obj = add_icon.parent();
- var objClone = obj.clone();
- objClone.removeClass("add")
- objClone.children(".index_category").remove();
- $(".right").append(objClone);
- classHover(objClone, "minus");
+ // check if the index exists?
+ if (added_indexes_id.indexOf(index_id) == -1) {
+ var obj = add_icon.parent();
+ var objClone = obj.clone();
+ objClone.removeClass("add")
+ objClone.children(".index_category").remove();
+ $(".right").append(objClone);
+ classHover(objClone, "minus");
+ added_indexes_id.push(index_id);
+ }
}
}
});
@@ -45,6 +57,8 @@ $(document).ready(function(){
success: function(data){
var obj = minus_icon.parent();
obj.remove();
+ rm_index = added_indexes_id.indexOf(index_id);
+ added_indexes_id.splice(rm_index, 1);
}
});
diff --git a/97suifangqa/apps/indicator/templates/indicator/NewDeleteIndex.html b/97suifangqa/apps/indicator/templates/indicator/NewDeleteIndex.html
index c2a219a..f4e9a18 100644
--- a/97suifangqa/apps/indicator/templates/indicator/NewDeleteIndex.html
+++ b/97suifangqa/apps/indicator/templates/indicator/NewDeleteIndex.html
@@ -52,19 +52,8 @@
<div style="clear: both;"></div>
</div>
<div class="index_navigation">
- <!-- 根据url的参数tab,给对应div的class加 selected 样式 -->
- <!--
- <div class="index_type selected" id="index_all"><a href="?tab=all">所有指标</a></div>
- <div class="index_type"><a href="?tab=1">血常规</a></div>
- <div class="index_type"><a href="?tab=2">两对半</a></div>
- <div class="index_type"><a href="?tab=3">肝功能</a></div>
- <div class="index_type"><a href="?tab=4">肝穿刺</a></div>
- <div class="index_type"><a href="?tab=5">血常规</a></div>
- <div class="index_type"><a href="?tab=6">两对半</a></div>
- <div class="index_type"><a href="?tab=7">肝功能</a></div>
- -->
<!-- 所有指标 -->
- <div class="index_type {% if selected_catid == "all" %}selected{% endif %}">
+ <div class="index_type {% if page_condition == "all" %}selected{% endif %}">
<a href="?tab=all">所有指标</a>
</div>
<!-- 指标类别,页面只能容纳 7 个 -->
@@ -146,6 +135,7 @@
<div style="clear:both;"></div>
</div>
<!-- list of indicators of the category -->
+ {% if page_condition == "category" %}
<div class="index_lines left">
{% for ind in indicators %}
<div class="index_line" index_id="{{ ind.id }}">
@@ -156,6 +146,7 @@
</div>
{% endfor %}
</div> <!-- end: index_lines left -->
+ {% endif %} {# end: page_condition == "category" #}
</div> <!-- end: category_condition -->
<!-- 搜索后左边的展示 -->
@@ -164,36 +155,42 @@
<div class="search_condition" style="display: {% if page_condition == "search" %}block{% else %}none{% endif %};">
<div class="index_title_container">
<div class="index_title">搜索指标</div>
- <div class="example_sheet">仿真化验单</div>
+ <div class="example_sheet"></div>
<div style="clear:both;"></div>
</div>
<!-- list of indicators returned by search -->
+ {% if page_condition == "search" %}
<div class="index_lines left">
{# 'indicators': list made up by the dumps of indicator #}
- {% for ind in indicators %}
- <!-- TODO -->
- <div class="index_line" index_id="{{ ind|dict_get:"id" }}">
- <div class="index_name">{{ ind|dict_get:"name" }}</div>
- <div class="index_category">
- <a href="?tab={{ ind|dict_get:"categories_id"|first }}">{{ ind|dict_get:"categories_name"|first }}</a>
+ {# check if search keyword empty & if search result empty #}
+ {% if search_kw_empty %}
+ {# search keyword empty #}
+ <div class="index_search_error">
+ <div class="index_error">您未输入搜索关键词</div>
+ <div class="icon"></div>
+ <div style="clear:both"></div>
</div>
- <div class="icon"></div>
- <div style="clear:both"></div>
- </div>
- {% endfor %}
- <div class="index_line" index_id="2">
- <div class="index_name">乙肝病毒S蛋白定量</div>
- <div class="index_category">血常规</div>
- <div class="icon"></div>
- <div style="clear:both"></div>
- </div>
- <div class="index_line" index_id="3">
- <div class="index_name">乙肝病毒表面抗体</div>
- <div class="index_category">血常规</div>
- <div class="icon"></div>
- <div style="clear:both"></div>
- </div>
+ {% elif search_result_empty %}
+ {# search result empty #}
+ <div class="index_search_error">
+ <div class="index_error">未搜索到符合的结果</div>
+ <div class="icon"></div>
+ <div style="clear:both"></div>
+ </div>
+ {% else %}
+ {% for ind in indicators %}
+ <div class="index_line" index_id="{{ ind|dict_get:"id" }}">
+ <div class="index_name">{{ ind|dict_get:"name" }}</div>
+ <div class="index_category">
+ <a href="?tab={{ ind|dict_get:"categories_id"|first }}">{{ ind|dict_get:"categories_name"|first }}</a>
+ </div>
+ <div class="icon"></div>
+ <div style="clear:both"></div>
+ </div>
+ {% endfor %}
+ {% endif %}
</div> <!-- end: index_lines left -->
+ {% endif %} {# end: page_condition == "search" #}
</div> <!-- end: search_condition -->
</div> <!-- end: index_container -->
@@ -219,49 +216,6 @@
<div style="clear:both"></div>
</div>
{% endfor %}
-
- {% comment %}{# vim: {{{ #}
- <div class="index_line" index_id="1">
- <div class="index_name">V-谷丙氨酰转氨酶</div>
- <div class="icon"></div>
- <div style="clear:both"></div>
- </div>
- <div class="index_line" index_id="2">
- <div class="index_name">总胆红素</div>
- <div class="icon"></div>
- <div style="clear:both"></div>
- </div>
- <div class="index_line" index_id="3">
- <div class="index_name">乙肝病毒表面抗原</div>
- <div class="icon"></div>
- <div style="clear:both"></div>
- </div>
- <div class="index_line" index_id="4">
- <div class="index_name">乙肝病毒表面抗体</div>
- <div class="icon"></div>
- <div style="clear:both"></div>
- </div>
- <div class="index_line" index_id="5">
- <div class="index_name">乙肝病毒e抗体</div>
- <div class="icon"></div>
- <div style="clear:both"></div>
- </div>
- <div class="index_line" index_id="6">
- <div class="index_name">乙肝病毒核算定量(PCR)</div>
- <div class="icon"></div>
- <div style="clear:both"></div>
- </div>
- <div class="index_line" index_id="7">
- <div class="index_name">乙肝病毒基因型C型</div>
- <div class="icon"></div>
- <div style="clear:both"></div>
- </div>
- <div class="index_line" index_id="8">
- <div class="index_name">乙肝病毒型混合型</div>
- <div class="icon"></div>
- <div style="clear:both"></div>
- </div>
- {% endcomment %}{# vim: }}} #}
</div> <!-- end: index_lines right -->
</div>
diff --git a/97suifangqa/apps/indicator/templates/indicator/SheetDefault.html b/97suifangqa/apps/indicator/templates/indicator/SheetDefault.html
index 56d0e6a..88a8d82 100644
--- a/97suifangqa/apps/indicator/templates/indicator/SheetDefault.html
+++ b/97suifangqa/apps/indicator/templates/indicator/SheetDefault.html
@@ -1,5 +1,7 @@
{% extends "base.html" %}
{% load static from staticfiles %}
+{% load dict_get %}
+{% load divisible_by %}
{% block title %}
指标状态 | 随访工具 | 97 随访
@@ -33,200 +35,183 @@
var static_url = "{{ STATIC_URL }}";
var indicator_url = "/indicator/";
</script>
+
+ <!-- Highcharts related, draw records chart -->
+ <script>
+ {% for ind in indicators %}
+ {% if not ind|dict_get:"record_empty" %} {# indicator has records #}
+ var chart_{{ ind|dict_get:"id" }};
+ {% endif %}
+ {% endfor %}
+ </script>
{% endblock %}
{% block page %}
- <!--
- <iframe align="left" width="420" height="720" src="SideBar.html" style="position:fixed;left:0;top:0" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
- -->
<iframe align="left" width="420" height="720" src="{% url indicator_sidebar %}" style="position:fixed;left:0;top:0" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
- <div id="right_container">
- <div id="index_status_container">
- <div class="index_title">指标状态</div>
- <!-- 这里需要后端读取cookie,来判断用户是否已经点击大叉。若否,则显示;若是,则隐藏 -->
- <div class="index_sub_title">
- <div class="content">以下可能是您感兴趣的指标,您可以点击卡片右上角“X”,取消关注。</div>
- <div class="close_icon" id="index_title_closed_icon"></div>
- </div>
-
- <!-- 左边的卡片加一个class "index_card_fir", 右边的卡片加一个class "index_card_sec" -->
- <!-- 卡片div的id为 "index_card_卡片id",方便后续操作 -->
- <div class="index_card index_card_fir" id="index_card_1">
- <div class="card_title">乙肝病毒核算定量 (PCR)1</div>
- <div class="refer_range">
- <span class="refer_text">参考范围</span>
- <span>100 x 10^4 拷贝 /mL</span>
- </div>
- <div class="edit_data">
- <div class="last_edit_data" style="display:none;"><span class="data_fir">0</span> x 10^<span class="data_sec">0</span> 拷贝 /mL</div>
- <img src="{% static "images/pen.png" %}" class="small_edit_icon">
- <img class="explain_icon" src="{% static "images/nodata.png" %}">
- </div>
- <div class="editing_data">
- <div class="input_container">
- <input class="edit_input_main" type="text" value="98" /> x 10^
- <input class="edit_input_sub" type="text" value="4" />
- </div>
- <div class="add_minus_icon">
- <div class="add_icon"></div>
- <div class="minus_icon"></div>
- </div>
- 拷贝 /mL
- <div class="confirm_edit_icon"></div>
- <div class="cancel_edit_icon"></div>
- </div>
- <div class="edit_icon_container">
- <div class="edit_icon"></div>
- <div class="curve_icon"></div>
- <div style="clear:both;"></div>
- </div>
- <div class="edit_text">点击右上角的按钮可以编辑数据</div>
- <div class="card_bottom">
- <!--
- <div class="understand_index"><a class="thickbox" href="popup/IndexDesc.html?TB_iframe=true&no1_title&transfer_params&height=351&width=630&card_id=1">了解该指标</a></div>
- -->
- <div class="understand_index"><a class="thickbox" href="{% url indicator_indexdesc %}?TB_iframe=true&no1_title&transfer_params&height=351&width=630&card_id=1">了解该指标</a></div>
- <div class="simulation_sheet"><a href="{% static "images/demo_sheet.png" %}" class="thickbox">仿真化验单</a></div>
- <div class="detail_history"><a href="javascript:void(0)">详细历史记录</a></div>
- <div style="clear:both;"></div>
- </div>
- <!-- thickbox插件,方便父级页面与子级弹出层的MVC隔离,方便子级弹出层的复杂需求,如:搜索、分页… -->
- <!-- height参数为弹出层页面高度+2,width参数为弹出层页面宽度+2,card_id参数为卡片id -->
- <!--
- <a class="card_delete_icon card_delete thickbox" href="popup/DeleteCardTip.html?TB_iframe=true&no1_title&transfer_params&height=166&width=630&card_id=1"></a>
- -->
- <a class="card_delete_icon card_delete thickbox" href="{% url indicator_deletecardtip %}?TB_iframe=true&no1_title&transfer_params&height=166&width=630&card_id=1"></a>
- </div>
-
- <!-- 右边的卡片 -->
- <div class="index_card index_card_sec" id="index_card_2">
- <div class="card_title">乙肝病毒核算定量 (PCR)2</div>
- <div class="refer_range">
- <span class="refer_text">参考范围</span>
- <span>100 x 10^4 拷贝 /mL</span>
- </div>
- <div class="edit_data">
- <div class="last_edit_data" style="display:none;"><span class="data_fir">0</span> x 10^<span class="data_sec">0</span> 拷贝 /mL</div>
- <img src="{% static "images/pen.png" %}" class="small_edit_icon">
- <img class="explain_icon" src="{% static "images/nodata.png" %}">
- </div>
- <div class="editing_data">
- <div class="input_container">
- <input class="edit_input_main" type="text" value="98" /> x 10^
- <input class="edit_input_sub" type="text" value="4" />
- </div>
- <div class="add_minus_icon">
- <div class="add_icon"></div>
- <div class="minus_icon"></div>
- </div>
- 拷贝 /mL
- <div class="confirm_edit_icon"></div>
- <div class="cancel_edit_icon"></div>
- </div>
- <div class="edit_icon_container">
- <div class="edit_icon"></div>
- <div class="curve_icon"></div>
- <div style="clear:both;"></div>
- </div>
- <div class="edit_text">点击右上角的按钮可以编辑数据</div>
- <div class="card_bottom">
- <!--
- <div class="understand_index"><a class="thickbox" href="popup/IndexDesc.html?TB_iframe=true&no1_title&transfer_params&height=351&width=630&card_id=2">了解该指标</a></div>
- -->
- <div class="understand_index"><a class="thickbox" href="{% url indicator_indexdesc %}?TB_iframe=true&no1_title&transfer_params&height=351&width=630&card_id=2">了解该指标</a></div>
- <div class="simulation_sheet"><a href="{% static "images/demo_sheet.png" %}" class="thickbox">仿真化验单</a></div>
- <div class="detail_history"><a href="javascript:void(0)">详细历史记录</a></div>
- <div style="clear:both;"></div>
- </div>
- <!--
- <a class="card_delete_icon card_delete thickbox" href="popup/DeleteCardTip.html?TB_iframe=true&no1_title&transfer_params&height=166&width=630&card_id=2"></a>
- -->
- <a class="card_delete_icon card_delete thickbox" href="{% url indicator_deletecardtip %}?TB_iframe=true&no1_title&transfer_params&height=166&width=630&card_id=2"></a>
- </div>
-
- <div class="index_card index_card_fir" id="index_card_3">
- <div class="card_title">乙肝病毒核算定量 (PCR)3</div>
- <div class="refer_range">
- <span class="refer_text">参考范围</span>
- <span>100 x 10^4 拷贝 /mL</span>
- </div>
- <div class="edit_data">
- <div class="last_edit_data"><span class="data_fir">98</span> x 10^<span class="data_sec">4</span> 拷贝 /mL</div>
- <img src="{% static "images/pen.png" %}" class="small_edit_icon">
- <img src="{% static "images/last_edit_data.png" %}" class="explain_icon">
- </div>
- <div class="editing_data">
- <div class="input_container">
- <input class="edit_input_main" type="text" value="" autocomplete="off" /> x 10^
- <input class="edit_input_sub" type="text" value="" autocomplete="off" />
- </div>
- <div class="add_minus_icon">
- <div class="add_icon"></div>
- <div class="minus_icon"></div>
- </div>
- 拷贝 /mL
- <div class="confirm_edit_icon"></div>
- <div class="cancel_edit_icon"></div>
- </div>
- <div class="refresh_data">
- <div class="refresh_text">这是2013-07-01 化验单上的记录</div>
- <div class="refresh_icon"></div>
- <div style="clear:both;"></div>
- </div>
- <div class="select_date">
- <input class="datepicker" type="text" autocomplete="off" />
- </div>
- <div id="chart_3" class="chart"></div>
- <div class="card_bottom">
- <!--
- <div class="understand_index"><a class="thickbox" href="popup/IndexDesc.html?TB_iframe=true&no1_title&transfer_params&height=351&width=630&card_id=3">了解该指标</a></div>
- -->
- <div class="understand_index"><a class="thickbox" href="{% url indicator_indexdesc %}?TB_iframe=true&no1_title&transfer_params&height=351&width=630&card_id=3">了解该指标</a></div>
- <div class="simulation_sheet"><a href="{% static "images/demo_sheet.png" %}" class="thickbox">仿真化验单</a></div>
- <div class="detail_history"><a href="javascript:void(0)">详细历史记录</a></div>
- <div style="clear:both;"></div>
- </div>
- <!--
- <a class="card_delete_icon card_delete thickbox" href="popup/DeleteCardTip.html?TB_iframe=true&no1_title&transfer_params&height=166&width=630&card_id=3"></a>
- -->
- <a class="card_delete_icon card_delete thickbox" href="{% url indicator_deletecardtip %}?TB_iframe=true&no1_title&transfer_params&height=166&width=630&card_id=3"></a>
- </div>
-
- <div class="detail_card_info">
- <div class="card_title">乙肝病毒核算定量 (PCR)4<input class="collapse_btn" type="button" value="收 起" /></div>
- <div class="search_data_div">
- <input class="recent_one_week shift_week" start_date="2013-08-04" end_date="2013-08-10" type="button" value="最近1周" />
- <input class="recent_two_week shift_week unselected" start_date="2013-07-28" end_date="2013-08-10" type="button" value="最近2周" />
- <div class="datepicker_container end_date_container">
- <label>截至日期</label>
- <input class="datepicker end_date" id="search_end_date" type="text" value="" />
- </div>
- <div class="datepicker_container">
- <label class="start_label">起始日期</label>
- <input class="datepicker start_date" id="search_start_date" type="text" value="" />
- </div>
- <div style="clear:both;"></div>
- </div>
- <div id="detail_chart"></div>
- <div class="table_div">
- <table width="100%">
- <tr class="first_line">
- <td width="122px">日期</td>
- <td width="124px">时间</td>
- <td width="312px">记录</td>
- </tr>
- </table>
- </div>
- <div class="see_more"><input class="see_more_btn" type="button" value="浏览更多记录" /></div>
- </div>
-
- <div class="act_card_container index_card_sec">
+
+ <div id="right_container">
+ <div id="index_status_container">
+ <div class="index_title">指标状态</div>
+
+ <!-- 这里需要后端读取cookie,来判断用户是否已经点击大叉。
+ 若否,则显示;若是,则隐藏
+ -->
+ <div class="index_sub_title">
+ <div class="content">以下可能是您感兴趣的指标,您可以点击卡片右上角“X”,取消关注。</div>
+ <div class="close_icon" id="index_title_closed_icon"></div>
+ </div>
+
+ <!-- 左边的卡片加一个class "index_card_fir",
+ 右边的卡片加一个class "index_card_sec"
+ -->
+ <!-- 卡片div的id为 "index_card_卡片id",方便后续操作 -->
+ {% for ind in indicators %}
+ <div class="index_card {% cycle 'index_card_fir' 'index_card_sec' %}" id="index_card_{{ ind|dict_get:"id" }}">
+ <div class="card_title">{{ ind|dict_get:"name" }}</div>
+ <div class="refer_range">
+ <span class="refer_text">{{ ind|dict_get:"ref_text" }}</span>
+ <span class="refer_value">{{ ind|dict_get:"ref_value"|safe }}</span>
+ <span class="data_unit">{{ ind|dict_get:"std_unit_symbol" }}</span>
+ </div>
+ {% if ind|dict_get:"record_empty" %} {# vim: {{{ #}
+ {# if no record, then hide 'last_edit_data' #}
+ <!-- "record_empty": True -->
+ <div class="edit_data">
+ <div class="last_edit_data" style="display: none;">
+ <span class="last_data">Null</span>
+ <span class="data_unit">{{ ind|dict_get:"std_unit_symbol" }}</span>
+ </div>
+ <img class="small_edit_icon" src="{% static "images/pen.png" %}" />
+ <img class="explain_icon" src="{% static "images/nodata.png" %}" />
+ </div> <!-- end: edit_data -->
+ <div class="editing_data">
+ <div class="input_container">
+ <input class="edit_input_main" type="text" value="0" />
+ x 10^
+ <input class="edit_input_sub" type="text" value="0" />
+ </div>
+ <div class="add_minus_icon">
+ <div class="add_icon"></div>
+ <div class="minus_icon"></div>
+ </div>
+ <div class="data_unit">{{ ind|dict_get:"std_unit_symbol" }}</div>
+ <div class="confirm_edit_icon"></div>
+ <div class="cancel_edit_icon"></div>
+ </div> <!-- end: editing_data -->
+ <!-- hints to get started, display when has no record -->
+ <div class="edit_icon_container">
+ <div class="edit_icon"></div>
+ <div class="curve_icon"></div>
+ <div style="clear:both;"></div>
+ </div>
+ <div class="edit_text">点击右上角的按钮开始添加数据</div>
+ {# vim: }}} #}
+ {% else %} {# record_empty == False; vim: {{{ #}
+ {# indicator has records #}
+ <!-- "record_empty": False -->
+ <div class="edit_data">
+ <div class="last_edit_data" style="display: block;">
+ <span class="last_data">{{ ind|dict_get:"last_record"|dict_get:"value_str" }}</span>
+ <span class="data_unit">{{ ind|dict_get:"std_unit_symbol" }}</span>
+ </div>
+ <img class="small_edit_icon" src="{% static "images/pen.png" %}" />
+ <img class="explain_icon" src="{% static "images/last_edit_data.png" %}" />
+ </div> <!-- end: edit_data -->
+ <div class="editing_data">
+ <div class="input_container">
+ <input class="edit_input_main" type="text" value="" autocomplete="off" />
+ x 10^
+ <input class="edit_input_sub" type="text" value="" autocomplete="off" />
+ </div>
+ <div class="add_minus_icon">
+ <div class="add_icon"></div>
+ <div class="minus_icon"></div>
+ </div>
+ <div class="data_unit">{{ ind|dict_get:"std_unit_symbol" }}</div>
+ <div class="confirm_edit_icon"></div>
+ <div class="cancel_edit_icon"></div>
+ </div> <!-- end: editing_data -->
+ <div class="refresh_data">
+ <div class="refresh_text">
+ 记录日期: {{ ind|dict_get:"last_record"|dict_get:"date" }}
+ </div>
+ <div class="refresh_icon"></div>
+ <div style="clear:both;"></div>
+ </div>
+ <div class="select_date">
+ <input class="datepicker" type="text" autocomplete="off" />
+ </div>
+ <!-- chart rendered by Highcharts -->
+ <div id="chart_{{ ind|dict_get:"id" }}" class="chart"></div>
+ {% endif %} {# end: record_empty; vim: }}} #}
+
+ <div class="card_bottom">
+ <div class="understand_index"><a class="thickbox" href="{% url indicator_indexdesc %}?TB_iframe=true&no1_title&transfer_params&height=351&width=630&card_id={{ ind|dict_get:"id" }}">了解该指标</a></div>
+ <!-- TODO -->
+ <div class="simulation_sheet"><a href="{% static "images/demo_sheet.png" %}" class="thickbox">仿真化验单</a></div>
+ <div class="detail_history">
+ <a href="javascript:void(0)">详细历史记录</a>
+ </div>
+ <div style="clear:both;"></div>
+ </div>
+
+ {% comment %}
+ thickbox插件:
+ 方便父级页面与子级弹出层的MVC隔离,
+ 方便子级弹出层的复杂需求,如:搜索、分页…
+ height参数为弹出层页面高度+2,
+ width参数为弹出层页面宽度+2,
+ card_id参数为 "卡片id"
+ {% endcomment %}
+ <a class="card_delete_icon card_delete thickbox" href="{% url indicator_deletecardtip %}?TB_iframe=true&no1_title&transfer_params&height=166&width=630&card_id={{ ind|dict_get:"id" }}"></a>
+ </div> <!-- end: index_card -->
+ {% endfor %} {# end: indicators #}
+
+ <!-- detail card info -->
+ <div class="detail_card_info">
+ <div class="card_title">乙肝病毒核算定量 (PCR)4<input class="collapse_btn" type="button" value="收 起" /></div>
+ <div class="search_data_div">
+ <input class="recent_one_week shift_week" start_date="2013-08-04" end_date="2013-08-10" type="button" value="最近1周" />
+ <input class="recent_two_week shift_week unselected" start_date="2013-07-28" end_date="2013-08-10" type="button" value="最近2周" />
+ <div class="datepicker_container end_date_container">
+ <label>截止日期</label>
+ <input class="datepicker end_date" id="search_end_date" type="text" value="" />
+ </div>
+ <div class="datepicker_container">
+ <label class="start_label">起始日期</label>
+ <input class="datepicker start_date" id="search_start_date" type="text" value="" />
+ </div>
+ <div style="clear:both;"></div>
+ </div>
+ <div id="detail_chart"></div>
+ <div class="table_div">
+ <table width="100%">
+ <tr class="first_line">
+ <td width="122px">日期</td>
+ <td width="124px">时间</td>
+ <td width="312px">记录</td>
+ </tr>
+ </table>
+ </div>
+ <div class="see_more">
+ <input class="see_more_btn" type="button" value="浏览更多记录" />
+ </div>
+ </div> <!-- end: detail card info -->
+
+ <!-- goto follow/unfollow indicator -->
+ {% if indicators|length|divisible_by:"2" %}
+ {# number of followed indicators: even #}
+ <div class="act_card_container index_card_fir">
+ {% else %}
+ <div class="act_card_container index_card_sec">
+ {% endif %}
<div class="act_card">
- <a href="{% url follow_indicator %}">添加或删除关注指标</a>
+ <a href="{% url indicator_fanduf %}">添加或删除关注指标</a>
</div>
- </div>
- </div>
- </div>
+ </div> <!-- end: follow/unfollow indicator -->
+
+ </div>
+ </div>
{% endblock page %}
{# vim: set ts=2 sw=2 tw=0 fenc=utf-8 ft=htmldjango.html: #}
diff --git a/97suifangqa/apps/indicator/templates/indicator/index.html b/97suifangqa/apps/indicator/templates/indicator/index.html
index 7c280f7..408ce67 100644
--- a/97suifangqa/apps/indicator/templates/indicator/index.html
+++ b/97suifangqa/apps/indicator/templates/indicator/index.html
@@ -8,7 +8,7 @@
{% block body %}
<ul>
<li><a href="{% url indicator_status %}">指标状态</a></li>
- <li><a href="{% url follow_indicator %}">关注指标</a></li>
+ <li><a href="{% url indicator_fanduf %}">关注指标</a></li>
</ul>
{% endblock %}
diff --git a/97suifangqa/apps/indicator/templates/indicator/popup/DeleteCardTip.html b/97suifangqa/apps/indicator/templates/indicator/popup/DeleteCardTip.html
index 7424930..c978f8a 100644
--- a/97suifangqa/apps/indicator/templates/indicator/popup/DeleteCardTip.html
+++ b/97suifangqa/apps/indicator/templates/indicator/popup/DeleteCardTip.html
@@ -24,7 +24,9 @@
<div class="delete_card_tip_title">提示</div>
<div class="delete_card_tip_close"></div>
</div>
- <div class="delete_card_tip_content">取消关注指标后,该指标卡片将从本页面消失,您确定需要取消关注?</div>
+ <div class="delete_card_tip_content">
+ 取消关注指标后,该指标卡片将从本页面消失,您确定需要取消关注?
+ </div>
<div class="delete_card_tip_action">
<a class="action_confirm_cancel">取消关注</a>
<a class="action_confirm_ignore">继续关注</a>
diff --git a/97suifangqa/apps/indicator/templatetags/divisible_by.py b/97suifangqa/apps/indicator/templatetags/divisible_by.py
new file mode 100644
index 0000000..96638e7
--- /dev/null
+++ b/97suifangqa/apps/indicator/templatetags/divisible_by.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+
+from django import template
+
+register = template.Library()
+
+@register.filter
+def divisible_by(dividend, divisor):
+ """
+ if 'dividend' can be *exactly* divided by 'divisor',
+ return True;
+ else, return False.
+
+ input parameters:
+ dividend: <type 'int'>
+ divisor: <class 'django.utils.safestring.SafeUnicode'>
+ """
+ if not isinstance(dividend, int):
+ raise ValueError(u'Error: dividend="%s" not int type' % dividend)
+ try:
+ divisor = int(divisor)
+ except ValueError, TypeError:
+ raise ValueError(u'Error: divisor="%s" cannot convert to int'
+ % divisor)
+ #
+ if dividend % divisor == 0:
+ return True
+ else:
+ return False
+
diff --git a/97suifangqa/apps/indicator/tools.py b/97suifangqa/apps/indicator/tools.py
index 663ec4f..a472db5 100644
--- a/97suifangqa/apps/indicator/tools.py
+++ b/97suifangqa/apps/indicator/tools.py
@@ -5,13 +5,52 @@ utils for apps/indicator
"""
from django.contrib.auth.models import User
+from django.shortcuts import get_object_or_404
from indicator import models as im
from sciblog import models as sciblogm
+import re
import datetime
+# follow_indicator {{{
+def follow_indicator(user_id, indicator_id):
+ """
+ 用户关注指标
+ """
+ try:
+ user = get_object_or_404(User, id=user_id)
+ indicator = im.Indicator.objects.get(id=indicator_id)
+ ui, created = im.UserIndicator.objects.get_or_create(user=user)
+ ui.followedIndicators.add(indicator)
+ # to remove the indicator from 'followedHistories' if exists
+ if indicator in ui.followedHistories.all():
+ ui.followedHistories.remove(indicator)
+ return True
+ except:
+ return False
+# }}}
+
+
+# unfollow_indicator {{{
+def unfollow_indicator(user_id, indicator_id):
+ """
+ 用户取消关注指标
+ """
+ try:
+ user = get_object_or_404(User, id=user_id)
+ indicator = im.Indicator.objects.get(id=indicator_id)
+ ui, created = im.UserIndicator.objects.get_or_create(user=user)
+ ui.followedIndicators.remove(indicator)
+ # add indicator to 'followedHistories'
+ ui.followedHistories.add(indicator)
+ return True
+ except:
+ return False
+# }}}
+
+
# get_indicator {{{
def get_indicator(category_id="all", startswith="all"):
"""
@@ -102,7 +141,8 @@ def get_unfollowed_indicator(user_id, category_id="all", startswith="all"):
u = User.objects.get(id=user_id)
ui, created = im.UserIndicator.objects.get_or_create(user=u)
_idict = {}
- iqueryset = im.Indicator.objects.exclude(user_indicators=ui)
+ # XXX: if 'exclude(followed_indicators=ui)' OK??
+ iqueryset = im.Indicator.objects.exclude(followed_indicators=ui)
if not category_id == 'all':
try:
cid = int(category_id)
@@ -192,25 +232,41 @@ def get_record_std(**kwargs):
# }}}
+# types of recommended indicators, and weights {{{
+RI_TYPES = {
+ 'ANNOTATION_COLLECTED': u'ANN_CL',
+ 'BLOG_CATCHED': u'BLG_CT',
+ 'BLOG_COLLECTED': u'BLG_CL',
+ 'OTHER': u'OTHER',
+ 'ERROR': u'ERROR', # no 'RelatedIndicator' data
+}
+RI_WEIGHTS = {
+ RI_TYPES['ANNOTATION_COLLECTED']: 4.0,
+ RI_TYPES['BLOG_CATCHED']: 3.0,
+ RI_TYPES['BLOG_COLLECTED']: 2.0,
+ RI_TYPES['OTHER']: 1.0,
+ RI_TYPES['ERROR']: 0.0,
+}
+# }}}
+
+
# calc_indicator_weight {{{
def calc_indicator_weight(user_id, indicator_id):
"""
calculate the weight of given indicator
used by 'recommend_indicator'
+
+ return format:
+ {'weight': w, 'type': t}
"""
- ### XXX: weight_type: how to store the weights into database ###
- weight_annotation = 4.0
- weight_blog_catched = 3.0
- weight_blog_collected = 2.0
- weight_other = 1.0
- ################################################################
# weight = weight_type * relatedindicator.weight
user = User.objects.get(id=user_id)
ri_qs = im.RelatedIndicator.objects.filter(indicator__id=indicator_id)
if not ri_qs:
- # queryset empty
+ # queryset empty: no 'RelatedIndicator' for this indicator
+ type = RI_TYPES['ERROR']
w = 0.0
- return w
+ return {'weight': w, 'type': type}
# queryset not empty
annotation_ri_qs = ri_qs.filter(annotation__collected_by=user)
blogcatch_ri_qs = ri_qs.filter(blog__catched_by=user)
@@ -218,26 +274,32 @@ def calc_indicator_weight(user_id, indicator_id):
weights = []
if annotation_ri_qs:
# related to annotations collected by user
+ type = RI_TYPES['ANNOTATION_COLLECTED']
for ri in annotation_ri_qs:
- w = weight_annotation * ri.weight
- weights.append(w)
+ w = RI_WEIGHTS[type] * ri.weight
+ weights.append({'weight': w, 'type': type})
elif blogcatch_ri_qs:
# related to blogs catched by user
+ type = RI_TYPES['BLOG_CATCHED']
for ri in blogcatch_ri_qs:
- w = weight_blog_catched * ri.weight
- weights.append(w)
+ w = RI_WEIGHTS[type] * ri.weight
+ weights.append({'weight': w, 'type': type})
elif blogcollect_ri_qs:
- # related to blogs catched by user
+ # related to blogs collected by user
+ type = RI_TYPES['BLOG_COLLECTED']
for ri in blogcollect_ri_qs:
- w = weight_blog_collected * ri.weight
- weights.append(w)
+ w = RI_WEIGHTS[type] * ri.weight
+ weights.append({'weight': w, 'type': type})
else:
# other type, use 'ri_qs' here
+ type = RI_TYPES['OTHER']
for ri in ri_qs:
- w = weight_other * ri.weight
- weights.append(w)
+ w = RI_WEIGHTS[type] * ri.weight
+ weights.append({'weight': w, 'type': type})
+ # sort results
+ weights_sorted = sorted(weights, key = lambda item: item['weight'])
# return final result
- return max(weights)
+ return weights_sorted[-1]
# }}}
@@ -247,22 +309,25 @@ def recommend_indicator(user_id, number):
recommend unfollowed indicator for user,
based on his/her readings and collections.
- return a list with the id's of recommended indicators
-
- TODO:
- performance test
+ return a list of recommended indicators in format:
+ [ {'id': id, 'weight': w, 'type': t}, ... ]
"""
user_id = int(user_id)
number = int(number)
# get unfollowed indicators
u = User.objects.get(id=user_id)
ui, created = im.UserIndicator.objects.get_or_create(user=u)
- uf_ind_qs = im.Indicator.objects.exclude(user_indicators=ui)
+ # XXX: if 'exclude(followed_indicators=ui)' OK??
+ uf_ind_qs = im.Indicator.objects.exclude(followed_indicators=ui)
# calc weight for each unfollowed indicator
weights = []
for ind in uf_ind_qs:
- w = calc_indicator_weight(user_id, ind.id)
- weights.append({'id': ind.id, 'weight': w})
+ wdict = calc_indicator_weight(user_id, ind.id)
+ weights.append({
+ 'id': ind.id,
+ 'weight': wdict.get('weight'),
+ 'type': wdict.get('type'),
+ })
# sort 'weights' dict list by key 'weight'
weights_sorted = sorted(weights, key=lambda item: item['weight'])
weights_sorted.reverse()
@@ -271,3 +336,90 @@ def recommend_indicator(user_id, number):
# }}}
+# format_data {{{
+def format_data(indicator_obj, value=None, val_max=None, val_min=None):
+ """
+ format given data according to the dataType of given Indicator,
+ make it proper for django templates
+ e.g.:
+ if number very big, then display in 'exponent notation'
+
+ used in '.views.indicator_status()'
+ """
+ # threshold to show a float number in scientific notation
+ float_threshold = 9999.9
+ # float display format: fixed point, exponent notation
+ fix_fmt = '{:,.1f}' # comma as a thousands separator
+ exp_fmt = '{:.2e}'
+ # regex to process exponent notation
+ rep = re.compile(r'^(?P<sign>[-+]?)(?P<num>\d\.\d+)[eE]\+?(?P<expminus>-?)0*(?P<exp>[1-9]+)$')
+ # range symbol (range: low $symbol$ high)
+ range_sym = '&sim;'
+ # default return value
+ value_str = u''
+
+ # check given 'indicator_obj'
+ ind = indicator_obj
+ if not isinstance(ind, im.Indicator):
+ print u'Error: given indicator_obj NOT a instance of Indicator'
+ raise ValueError(u'Given indicator_obj NOT a instance of Indicator')
+ # get dataType
+ dataType = ind.dataType
+
+ if value is not None:
+ # a) record float data; b) record integer/pm data;
+ # c) confine integer/pm data.
+ if dataType == ind.INTEGER_TYPE:
+ # TODO: process 'integer type' data
+ value_str = u'INTEGER: %s' % value
+ elif dataType == ind.PM_TYPE:
+ if value == u'+':
+ value_str = u'阳性(+)'
+ else:
+ value_str = u'阳性(-)'
+ elif dataType in [ind.FLOAT_TYPE, ind.FLOAT_RANGE_TYPE]:
+ # process float number
+ value = float(value)
+ if value <= float_threshold:
+ value_str = fix_fmt.format(value)
+ else:
+ value_expstr = exp_fmt.format(value)
+ # convert to html exponent format
+ m = rep.match(value_expstr)
+ value_str = "%s%s&times;10<sup>%s%s</sup>" % (
+ m.group('sign'), m.group('num'),
+ m.group('expminus'), m.group('exp'))
+ else:
+ # unknown XXX
+ pass
+ elif (val_max is not None) and (val_min is not None):
+ # a) record range data; b) confine range.
+ # val_max
+ if val_max <= float_threshold:
+ val_max_str = fix_fmt.format(val_max)
+ else:
+ val_max_expstr = exp_fmt.format(val_max)
+ # convert to html exponent format
+ m = rep.match(val_max_expstr)
+ val_max_str = "%s%s&times;10<sup>%s%s</sup>" % (
+ m.group('sign'), m.group('num'),
+ m.group('expminus'), m.group('exp'))
+ # val_min
+ if val_min <= float_threshold:
+ val_min_str = fix_fmt.format(val_min)
+ else:
+ val_min_expstr = exp_fmt.format(val_min)
+ # convert to html exponent format
+ m = rep.match(val_min_expstr)
+ val_min_str = "%s%s&times;10<sup>%s%s</sup>" % (
+ m.group('sign'), m.group('num'),
+ m.group('expminus'), m.group('exp'))
+ # value_str
+ value_str = u'%s %s %s' % (val_min_str, range_sym, val_max_str)
+ else:
+ # other type??
+ pass
+
+ return value_str
+# }}}
+
diff --git a/97suifangqa/apps/indicator/urls.py b/97suifangqa/apps/indicator/urls.py
index 5818616..93f3c7b 100644
--- a/97suifangqa/apps/indicator/urls.py
+++ b/97suifangqa/apps/indicator/urls.py
@@ -51,10 +51,10 @@ urlpatterns += patterns('indicator.views',
url(r'^status/$',
'indicator_status',
name='indicator_status'),
- # follow_indicator, 关注指标
- url(r'^follow/$',
- 'follow_indicator',
- name='follow_indicator'),
+ # indicator_fanduf, 关注指标
+ url(r'^follow_and_unfollow/$',
+ 'indicator_fanduf',
+ name='indicator_fanduf'),
## indicator: popup
# DeleteCardTip
url(r'^popup/deletecardtip/$',
@@ -94,6 +94,10 @@ urlpatterns += patterns('indicator.views',
url(r'^ajax/get_card_data_table/$',
'ajax_get_card_data_table',
name='indicator_ajax_getcarddatatable'),
+ # unfollow_indicator
+ url(r'^ajax/unfollow_indicator/$',
+ 'ajax_unfollow_indicator',
+ name='indicator_ajax_unfollowindicator'),
)
urlpatterns += patterns('indicator.views',
diff --git a/97suifangqa/apps/indicator/views.py b/97suifangqa/apps/indicator/views.py
index f222d10..dc7b902 100644
--- a/97suifangqa/apps/indicator/views.py
+++ b/97suifangqa/apps/indicator/views.py
@@ -11,10 +11,16 @@ from django.shortcuts import render, get_object_or_404
# CRSF
from django.template import RequestContext
+# haystack search
+from haystack.query import SearchQuerySet
+
from indicator import models as im
from indicator.forms import *
from indicator.tools import *
+# apps/utils
+from utils.search_tools import objects_of_sqs
+
import re
import datetime
@@ -51,40 +57,6 @@ def recommend_indicator_view(request, **kwargs):
return HttpResponse("%s" % ilist)
-# follow_indicator {{{
-@login_required
-def follow_indicator(request, indicator_id):
- """
- 用户关注指标
- """
- try:
- indicator = im.Indicator.objects.get(pk=int(indicator_id))
- ui, created = im.UserIndicator.objects.get_or_create(
- user=request.user)
- ui.followedIndicators.add(indicator)
- return { 'success': True }
- except:
- return { 'success': False }
-# }}}
-
-
-# unfollow_indicator {{{
-@login_required
-def unfollow_indicator(request, indicator_id):
- """
- 用户取消关注指标
- """
- try:
- indicator = im.Indicator.objects.get(pk=int(indicator_id))
- ui, created = im.UserIndicator.objects.get_or_create(
- user=request.user)
- ui.followedIndicators.remove(indicator)
- return { 'success': True }
- except:
- return { 'success': False }
-# }}}
-
-
# get_record_view {{{
@login_required
def get_record_view(request, indicator_id, date_range, **kwargs):
@@ -445,15 +417,126 @@ def indicator_status(request):
"""
status page for indicator
add/edit/view indicator data
+
+ TODO:
+ * when to recommend indicators
+ * how to deal with non-standard units
"""
template = 'indicator/SheetDefault.html'
- return render(request, template)
+ letters = map(chr, range(ord('a'), ord('z')+1))
+ # indicators
+ indicators = []
+ followed_indicators = []
+ r_indicators = []
+
+ # get followed indicator, P[inyin] dict format
+ followed_indicators_pdict = get_followed_indicator(request.user.id)
+ # convert to list
+ for l in letters:
+ followed_indicators += followed_indicators_pdict[l]
+
+ ## TODO: when to recommend indicators for user ??
+ if not followed_indicators:
+ # if no followed indicators yet, then recommend 2 indicators
+ r_indicators_unsort = [
+ im.Indicator.objects.get(id=ri['id']).dump()
+ for ri in recommend_indicator(request.user.id, 2)
+ ]
+ r_indicators= sorted(r_indicators_unsort,
+ key = lambda item: item['pinyin'])
+
+ # recommended indicators behind followed ones
+ indicators = followed_indicators + r_indicators
+
+ # process 'indicators' list, to add following keys: # {{{
+ # ref_text:
+ # ref_value:
+ # std_unit_symbol:
+ # record_empty: bool, if has no record, then True
+ for ind in indicators:
+ ind_obj = get_object_or_404(im.Indicator, id=ind['id'])
+ # check if 'indicator.is_ready()'
+ if not ind_obj.is_ready():
+ raise ValueError(u"Indicator id=%s is NOT ready yet!"
+ % ind_obj.id)
+ # the indicator is ready
+ dataType = ind_obj.dataType
+ confine = ind_obj.get_confine()
+ ## set 'ref_text', 'ref_value', 'std_unit_*'
+ if dataType in [ind_obj.FLOAT_TYPE, ind_obj.RANGE_TYPE,
+ ind_obj.FLOAT_RANGE_TYPE]:
+ ind['ref_text'] = u"参考范围"
+ # ref_value
+ human_max = confine.get('human_max')
+ human_min = confine.get('human_min')
+ ind['ref_value'] = format_data(ind_obj,
+ val_max=human_max, val_min=human_min)
+ # set 'std_unit_*'
+ ind['std_unit_name'] = confine.get('unit').get('name')
+ ind['std_unit_symbol'] = confine.get('unit').get('symbol')
+ elif dataType in [ind_obj.INTEGER_TYPE, ind_obj.PM_TYPE]:
+ ind['ref_text'] = u"参考值"
+ # ref_value
+ val_norm = confine.get('val_norm')
+ ind['ref_value'] = format_data(ind_obj, value=val_norm)
+ # std_unit
+ ind['std_unit_name'] = u""
+ ind['std_unit_symbol'] = u""
+ else:
+ ind['ref_text'] = u"参考"
+ ind['ref_value'] = None
+ ind['std_unit_name'] = None
+ ind['std_unit_symbol'] = None
+ ## check record of indicator
+ records = ind_obj.indicator_records.filter(user=request.user).\
+ order_by('-date', '-updated_at')
+ if records:
+ ind['record_empty'] = False
+ # last record of the indicator
+ last_record = records[0]
+ if dataType in [ind_obj.INTEGER_TYPE, ind_obj.PM_TYPE,
+ ind_obj.FLOAT_TYPE]:
+ value_str = format_data(ind_obj, value=last_record.value)
+ elif dataType == ind_obj.RANGE_TYPE:
+ value_str = format_data(ind_obj,
+ val_max=last_record.val_max,
+ val_min=last_record.val_min)
+ elif dataType == ind_obj.FLOAT_RANGE_TYPE:
+ value = last_record.value
+ val_max = last_record.val_max
+ val_min = last_record.val_min
+ if value is not None:
+ value_str = format_data(ind_obj, value=value)
+ elif (val_max is not None) and (val_min is not None):
+ value_str = format_data(ind_obj,
+ val_max=val_max, val_min=val_min)
+ else:
+ value_str = u''
+ else:
+ # unknow
+ value_str = u''
+ # save to dict
+ ind['last_record'] = {
+ 'date': last_record.date.isoformat(),
+ 'value_str': value_str,
+ }
+ else:
+ ind['record_empty'] = True
+ ind['last_record'] = {}
+ # }}}
+
+ data = {
+ 'indicators': indicators,
+ }
+ # render template
+ #raise ValueError
+ return render(request, template, data)
# }}}
# indicator/NewDeleteIndex.html {{{
@login_required
-def follow_indicator(request):
+def indicator_fanduf(request):
"""
follow/unfollow indicator
@@ -471,23 +554,23 @@ def follow_indicator(request):
# set default value for 'selected_cat*'
selected_catid = None
selected_category = None
- # get indicators, P[inyin] dict format
- indicators_pdict = get_indicator()
- # get followed indicator, P[inyin] dict format
- followed_indicators_pdict = get_followed_indicator(request.user.id)
- # convert to list
- followed_indicators = []
- for l in letters:
- followed_indicators += followed_indicators_pdict[l]
+ # default parameters
+ indicators = None
+ search_kw_empty = False
+ search_result_empty = False
# get/post views
if request.method == 'GET':
- if request.GET.get('tab'):
+ # default page_condition: "all"
+ selected_catid = "all"
+ page_condition = "all"
+ # page_condition: "category"
+ # select category / search indicator
+ if 'tab' in request.GET:
# tab: selected category, default "all"
selected_catid = request.GET.get('tab')
- if selected_catid == "all":
+ if selected_catid == "all" or selected_catid == "":
page_condition = "all"
- indicators = indicators_pdict
else:
selected_catid = int(selected_catid)
selected_category = get_object_or_404(
@@ -496,25 +579,50 @@ def follow_indicator(request):
# get indicators of the category
indicators = selected_category.indicators.\
all().order_by('pinyin')
- elif request.GET.get('kw'):
+ # page_condition: "search"
+ # can override the above 'category' if 'tab' & 'kw' both exist
+ if 'kw' in request.GET:
# kw: search keyword to find indicator
search_kw = request.GET.get('kw')
page_condition = "search"
- # TODO
- indicators = []
- else:
- # default page_condition: "all"
- selected_catid = "all"
- page_condition = "all"
- indicators = indicators_pdict
+ selected_catid = None
+ # check search keyword
+ if search_kw == "":
+ search_kw_empty = True
+ else:
+ # search
+ # TODO: howto order_by() by 'pinyin'
+ sqs = SearchQuerySet().models(im.Indicator).\
+ filter(content=search_kw)
+ if sqs:
+ # search result not empty
+ inds_unsort = [ind.dump()
+ for ind in objects_of_sqs(sqs)]
+ indicators = sorted(inds_unsort,
+ key = lambda item: item['pinyin'])
+ else:
+ search_result_empty = True
elif request.method == 'POST':
- # do post process
+ # posted data of followed indicators
# TODO
- pass
+ post = request.POST
+ raise ValueError(u"TODO")
else:
# XXX
raise Http404
+ # all indicators
+ if page_condition == "all":
+ # get indicators, P[inyin] dict format
+ indicators = get_indicator()
+
+ # get followed indicator, P[inyin] dict format
+ followed_indicators_pdict = get_followed_indicator(request.user.id)
+ # convert to list
+ followed_indicators = []
+ for l in letters:
+ followed_indicators += followed_indicators_pdict[l]
+
data = {
'page_condition': page_condition,
'categories': categories,
@@ -523,6 +631,8 @@ def follow_indicator(request):
'letters': letters,
'indicators': indicators,
'followed_indicators': followed_indicators,
+ 'search_kw_empty': search_kw_empty,
+ 'search_result_empty': search_result_empty,
}
# render page
return render(request, template, data)
@@ -537,7 +647,7 @@ def indicator_deletecardtip(request):
prompted tip for deleting a card
"""
template = 'indicator/popup/DeleteCardTip.html'
- return render_to_response(template)
+ return render(request, template)
# }}}
@@ -548,7 +658,7 @@ def indicator_edithistorydata(request):
popup page to edit history data for an indicator
"""
template = 'indicator/popup/EditHistoryData.html'
- return render_to_response(template)
+ return render(request, template)
# }}}
@@ -559,30 +669,52 @@ def indicator_indexdesc(request):
description for an indicator
"""
template = 'indicator/popup/IndexDesc.html'
- return render_to_response(template)
+ return render(request, template)
# }}}
###########################################################
###### ajax ######
+# ajax_act_index {{{
@login_required
def ajax_act_index(request):
"""
index action (add/minus)
follow/unfollow indicator
-
- TODO:
- * howto relate 'index_id' to 'indicator_id'?
- * howto implement follow/unfollow indicator function?
"""
- if request.is_ajax():
- result = 'success'
- else:
- result = 'fail'
- #raise Http404
+ # default 'fail'
+ result = 'fail'
+ #if request.is_ajax():
+ if True:
+ # check index_id -> indicator_id
+ if request.GET.get('index_id') is not None:
+ index_id = request.GET.get('index_id')
+ try:
+ indicator_id = int(index_id)
+ except ValueError:
+ print u'Error: Given index_id="%s" cannot convert to integer' % indicator_id
+ result = 'fail'
+ return HttpResponse(result)
+ # check 'act': add/minus -> action: follow/unfollow
+ if request.GET.get('act') is not None:
+ action = request.GET.get('act')
+ if action == "add":
+ # follow
+ if follow_indicator(request.user.id, indicator_id):
+ result = 'success'
+ elif action == "minus":
+ # unfollow
+ if unfollow_indicator(request.user.id, indicator_id):
+ result = 'success'
+ else:
+ raise ValueError(u'Error: Given act="%s" unknown' % action)
+ result = 'fail'
+
return HttpResponse(result)
+# }}}
+# ajax_close_sub_title {{{
def ajax_close_sub_title(request):
"""
close the small prompt banner above the indicator cards
@@ -595,8 +727,10 @@ def ajax_close_sub_title(request):
result = 'fail'
#raise Http404
return HttpResponse(result)
+# }}}
+# ajax_edit_history_data {{{
@login_required
def ajax_edit_history_data(request):
"""
@@ -609,8 +743,10 @@ def ajax_edit_history_data(request):
result = 'fail'
#raise Http404
return HttpResponse(result)
+# }}}
+# ajax_get_card_data_chart {{{
@login_required
def ajax_get_card_data_chart(request):
"""
@@ -634,8 +770,10 @@ def ajax_get_card_data_chart(request):
#raise Http404
return HttpResponse(json.dumps(result),
mimetype='application/json')
+# }}}
+# ajax_get_card_data_table {{{
@login_required
def ajax_get_card_data_table(request):
"""
@@ -665,6 +803,32 @@ def ajax_get_card_data_table(request):
result = ''
#raise Http404
return HttpResponse(result)
+# }}}
+
+
+# ajax_unfollow_indicator {{{
+@login_required
+def ajax_unfollow_indicator(request):
+ """
+ respone to the ajax request from 'delete_card_tip.js'
+ unfollow the specified indicator: GET.indicator_id
+ """
+ # default 'fail'
+ result = 'fail'
+ if request.is_ajax():
+ if request.GET.get('indicator_id') is not None:
+ indicator_id = request.GET.get('indicator_id')
+ try:
+ indicator_id = int(indicator_id)
+ except ValueError:
+ print u'Error: Given indicator_id="%s" cannot convert to integer' % indicator_id
+ result = 'fail'
+ if unfollow_indicator(request.user.id, indicator_id):
+ result = 'success'
+
+ # return result
+ return HttpResponse(result)
+# }}}
###########################################################