Showing
7 changed files
with
172 additions
and
70 deletions
| ... | @@ -196,6 +196,44 @@ app:defaultRange | ... | @@ -196,6 +196,44 @@ app:defaultRange |
| 196 | spin:private "true"^^xsd:boolean ; | 196 | spin:private "true"^^xsd:boolean ; |
| 197 | spin:returnType rdfs:Resource . | 197 | spin:returnType rdfs:Resource . |
| 198 | 198 | ||
| 199 | +app:globalRange | ||
| 200 | + rdf:type spin:Function ; | ||
| 201 | + rdfs:comment "Gets the global range (rdfs:range) of a property. If none is provided, it will walk up super-properties."^^xsd:string ; | ||
| 202 | + rdfs:label "global range"^^xsd:string ; | ||
| 203 | + rdfs:subClassOf app:Functions ; | ||
| 204 | + spin:body | ||
| 205 | + [ rdf:type sp:Select ; | ||
| 206 | + sp:resultVariables ([ sp:varName "range"^^xsd:string | ||
| 207 | + ]) ; | ||
| 208 | + sp:where ([ rdf:type sp:TriplePath ; | ||
| 209 | + sp:object | ||
| 210 | + [ sp:varName "p"^^xsd:string | ||
| 211 | + ] ; | ||
| 212 | + sp:path [ rdf:type sp:ModPath ; | ||
| 213 | + sp:modMax -2 ; | ||
| 214 | + sp:modMin 0 ; | ||
| 215 | + sp:subPath rdfs:subPropertyOf | ||
| 216 | + ] ; | ||
| 217 | + sp:subject | ||
| 218 | + [ sp:varName "property"^^xsd:string | ||
| 219 | + ] | ||
| 220 | + ] [ sp:object | ||
| 221 | + [ sp:varName "range"^^xsd:string | ||
| 222 | + ] ; | ||
| 223 | + sp:predicate rdfs:range ; | ||
| 224 | + sp:subject | ||
| 225 | + [ sp:varName "p"^^xsd:string | ||
| 226 | + ] | ||
| 227 | + ]) | ||
| 228 | + ] ; | ||
| 229 | + spin:constraint | ||
| 230 | + [ rdf:type spl:Argument ; | ||
| 231 | + rdfs:comment "The property to get the range of."^^xsd:string ; | ||
| 232 | + spl:predicate arg:property ; | ||
| 233 | + spl:valueType rdf:Property | ||
| 234 | + ] ; | ||
| 235 | + spin:returnType rdfs:Class . | ||
| 236 | + | ||
| 199 | app:googleMapsAPIKey | 237 | app:googleMapsAPIKey |
| 200 | rdf:type spin:Function ; | 238 | rdf:type spin:Function ; |
| 201 | rdfs:comment "Gets the currently registered Google Maps API key."^^xsd:string ; | 239 | rdfs:comment "Gets the currently registered Google Maps API key."^^xsd:string ; |
| ... | @@ -744,7 +782,7 @@ app:localRange | ... | @@ -744,7 +782,7 @@ app:localRange |
| 744 | sp:where ([ rdf:type sp:Bind ; | 782 | sp:where ([ rdf:type sp:Bind ; |
| 745 | sp:expression | 783 | sp:expression |
| 746 | [ rdf:type app:resourceType ; | 784 | [ rdf:type app:resourceType ; |
| 747 | - arg:subject | 785 | + arg:resource |
| 748 | [ sp:varName "subject"^^xsd:string | 786 | [ sp:varName "subject"^^xsd:string |
| 749 | ] | 787 | ] |
| 750 | ] ; | 788 | ] ; |
| ... | @@ -763,11 +801,6 @@ app:localRange | ... | @@ -763,11 +801,6 @@ app:localRange |
| 763 | arg:property | 801 | arg:property |
| 764 | [ sp:varName "predicate"^^xsd:string | 802 | [ sp:varName "predicate"^^xsd:string |
| 765 | ] | 803 | ] |
| 766 | - ] ; | ||
| 767 | - sp:arg3 [ rdf:type app:defaultRange ; | ||
| 768 | - arg:property | ||
| 769 | - [ sp:varName "predicate"^^xsd:string | ||
| 770 | - ] | ||
| 771 | ] | 804 | ] |
| 772 | ] ; | 805 | ] ; |
| 773 | sp:variable | 806 | sp:variable |
| ... | @@ -821,7 +854,7 @@ app:localRange | ... | @@ -821,7 +854,7 @@ app:localRange |
| 821 | 854 | ||
| 822 | app:localRangeAtClass | 855 | app:localRangeAtClass |
| 823 | rdf:type spin:Function ; | 856 | rdf:type spin:Function ; |
| 824 | - rdfs:comment "Checks (in that order) for declared owl:allValuesFrom restrictions in superclasses, rdfs:range at the property and then spl:valueType in SPIN constraints (spl:Argument and spl:Attribute)."^^xsd:string ; | 857 | + rdfs:comment "Checks (in that order) for declared owl:allValuesFrom restrictions in superclasses, rdfs:range at the property and then spl:valueType in SPIN constraints (spl:Argument and spl:Attribute). It falls back to app:defaultRange if nothing else is found."^^xsd:string ; |
| 825 | rdfs:label "local range at class"^^xsd:string ; | 858 | rdfs:label "local range at class"^^xsd:string ; |
| 826 | rdfs:subClassOf app:Functions ; | 859 | rdfs:subClassOf app:Functions ; |
| 827 | spin:body | 860 | spin:body |
| ... | @@ -835,10 +868,10 @@ app:localRangeAtClass | ... | @@ -835,10 +868,10 @@ app:localRangeAtClass |
| 835 | sp:arg4 [ sp:varName "property"^^xsd:string | 868 | sp:arg4 [ sp:varName "property"^^xsd:string |
| 836 | ] | 869 | ] |
| 837 | ] ; | 870 | ] ; |
| 838 | - sp:arg2 [ rdf:type spl:object ; | 871 | + sp:arg2 [ rdf:type app:globalRange ; |
| 839 | - sp:arg1 [ sp:varName "property"^^xsd:string | 872 | + arg:property |
| 840 | - ] ; | 873 | + [ sp:varName "property"^^xsd:string |
| 841 | - sp:arg2 rdfs:range | 874 | + ] |
| 842 | ] ; | 875 | ] ; |
| 843 | sp:arg3 [ rdf:type spif:walkObjects ; | 876 | sp:arg3 [ rdf:type spif:walkObjects ; |
| 844 | sp:arg1 [ sp:varName "class"^^xsd:string | 877 | sp:arg1 [ sp:varName "class"^^xsd:string |
| ... | @@ -847,6 +880,11 @@ app:localRangeAtClass | ... | @@ -847,6 +880,11 @@ app:localRangeAtClass |
| 847 | sp:arg3 app:splValueTypeFunctor ; | 880 | sp:arg3 app:splValueTypeFunctor ; |
| 848 | sp:arg4 [ sp:varName "property"^^xsd:string | 881 | sp:arg4 [ sp:varName "property"^^xsd:string |
| 849 | ] | 882 | ] |
| 883 | + ] ; | ||
| 884 | + sp:arg4 [ rdf:type app:defaultRange ; | ||
| 885 | + arg:property | ||
| 886 | + [ sp:varName "property"^^xsd:string | ||
| 887 | + ] | ||
| 850 | ] | 888 | ] |
| 851 | ]) ; | 889 | ]) ; |
| 852 | sp:where () | 890 | sp:where () | ... | ... |
This diff is collapsed. Click to expand it.
| 1 | @CHARSET "UTF-8"; | 1 | @CHARSET "UTF-8"; |
| 2 | 2 | ||
| 3 | body { | 3 | body { |
| 4 | - font-family: sans-serif; | 4 | + font-family: Arial, Helvetica, sans-serif; |
| 5 | } | 5 | } |
| 6 | 6 | ||
| 7 | .appAddRowButton { | 7 | .appAddRowButton { |
| ... | @@ -18,8 +18,8 @@ body { | ... | @@ -18,8 +18,8 @@ body { |
| 18 | .appAutoComplete { | 18 | .appAutoComplete { |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | -.appBaseFont, .appObjectWidget { | 21 | +.appBaseFont, .appObjectWidget, .appLabeledObjectsLabelTD { |
| 22 | - font-size: 14px; | 22 | + font-size: 12px; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | .appErrorIndicator { | 25 | .appErrorIndicator { |
| ... | @@ -47,7 +47,6 @@ body { | ... | @@ -47,7 +47,6 @@ body { |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | .appLabeledObjectsLabelTD { | 49 | .appLabeledObjectsLabelTD { |
| 50 | - font-size: 14px; | ||
| 51 | font-weight: bold; | 50 | font-weight: bold; |
| 52 | padding-bottom: 0px; | 51 | padding-bottom: 0px; |
| 53 | padding-left: 0px; | 52 | padding-left: 0px; |
| ... | @@ -100,7 +99,6 @@ body { | ... | @@ -100,7 +99,6 @@ body { |
| 100 | padding-top: 5px; | 99 | padding-top: 5px; |
| 101 | } | 100 | } |
| 102 | 101 | ||
| 103 | - | ||
| 104 | .appEditorHiddenField { | 102 | .appEditorHiddenField { |
| 105 | } | 103 | } |
| 106 | 104 | ||
| ... | @@ -120,8 +118,14 @@ body { | ... | @@ -120,8 +118,14 @@ body { |
| 120 | } | 118 | } |
| 121 | 119 | ||
| 122 | .appFormFooter { | 120 | .appFormFooter { |
| 123 | - padding: 4px; | 121 | + border-top-width: 1px; |
| 124 | - margin-top: 8px; | 122 | + border-top-style: solid; |
| 123 | + border-top-color: #b0b0b0; | ||
| 124 | + background-color: #f0f0f0; | ||
| 125 | + padding-top: 2px; | ||
| 126 | + padding-left: 4px; | ||
| 127 | + padding-right: 4px; | ||
| 128 | + padding-bottom: 4px; | ||
| 125 | } | 129 | } |
| 126 | 130 | ||
| 127 | .appFormHeaderLink { | 131 | .appFormHeaderLink { |
| ... | @@ -145,8 +149,10 @@ a:active.appFormHeaderLink { | ... | @@ -145,8 +149,10 @@ a:active.appFormHeaderLink { |
| 145 | } | 149 | } |
| 146 | 150 | ||
| 147 | .appHeader { | 151 | .appHeader { |
| 148 | - background-color: darkGray; | 152 | + background-color: #303030; |
| 149 | color: white; | 153 | color: white; |
| 154 | + font-size: 15px; | ||
| 155 | + font-weight: bold; | ||
| 150 | padding-left: 4px; | 156 | padding-left: 4px; |
| 151 | padding-top: 2px; | 157 | padding-top: 2px; |
| 152 | padding-bottom: 2px; | 158 | padding-bottom: 2px; |
| ... | @@ -242,14 +248,15 @@ td.appPropertyWidgetObjectTD { | ... | @@ -242,14 +248,15 @@ td.appPropertyWidgetObjectTD { |
| 242 | font-size: 11px; | 248 | font-size: 11px; |
| 243 | } | 249 | } |
| 244 | 250 | ||
| 245 | -.ui-layout-north { | 251 | +.ui-layout-content { |
| 246 | padding: 0 !important; | 252 | padding: 0 !important; |
| 247 | -} | 253 | +} |
| 248 | 254 | ||
| 249 | -.ui-layout-west { | 255 | +.ui-layout-north, .ui-layout-south, .ui-layout-west, .ui-layout-east, .ui-layout-center { |
| 256 | + border: 0px !important; | ||
| 250 | padding: 0 !important; | 257 | padding: 0 !important; |
| 251 | } | 258 | } |
| 252 | 259 | ||
| 253 | -.ui-layout-center { | 260 | +.jstree { |
| 254 | - padding: 0 !important; | 261 | + font-size: 12px !important; |
| 255 | } | 262 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -174,8 +174,26 @@ function appLoad(id, args) { | ... | @@ -174,8 +174,26 @@ function appLoad(id, args) { |
| 174 | var p = jQuery.param(c); | 174 | var p = jQuery.param(c); |
| 175 | url = p + "&" + base; | 175 | url = p + "&" + base; |
| 176 | } | 176 | } |
| 177 | + url += '&_snippet=true'; | ||
| 177 | appInsertLoadingIndicator(e); | 178 | appInsertLoadingIndicator(e); |
| 178 | - e.load(uispinServlet, url); | 179 | + // TODO: Error handling may not work yet |
| 180 | + e.load(uispinServlet, url, function() { | ||
| 181 | + appLoadPostProcess(e, 'north'); | ||
| 182 | + appLoadPostProcess(e, 'east'); | ||
| 183 | + appLoadPostProcess(e, 'south'); | ||
| 184 | + appLoadPostProcess(e, 'west'); | ||
| 185 | + appLoadPostProcess(e, 'center'); | ||
| 186 | + }); | ||
| 187 | +} | ||
| 188 | + | ||
| 189 | + | ||
| 190 | +// Private function to make sure that the scrollbars are | ||
| 191 | +// updated if a ui:loadable has been loaded into a layout pane | ||
| 192 | +function appLoadPostProcess(e, pane) { | ||
| 193 | + // TODO: Test if this also works for panes that don't have a ui-layout-content | ||
| 194 | + if(e.hasClass('ui-layout-' + pane)) { | ||
| 195 | + e.parent().layout().initContent(pane); | ||
| 196 | + } | ||
| 179 | } | 197 | } |
| 180 | 198 | ||
| 181 | 199 | ||
| ... | @@ -221,6 +239,13 @@ function appLoadForm(formId, mode, resourceURI, resourceTypeURI, queryGraphURI) | ... | @@ -221,6 +239,13 @@ function appLoadForm(formId, mode, resourceURI, resourceTypeURI, queryGraphURI) |
| 221 | * @param onSelect the value for onSelect of the generated grid | 239 | * @param onSelect the value for onSelect of the generated grid |
| 222 | */ | 240 | */ |
| 223 | function appLoadSearchResultsGrid(formId, targetId, onSelect) { | 241 | function appLoadSearchResultsGrid(formId, targetId, onSelect) { |
| 242 | + | ||
| 243 | + // TODO: jQuery's serialize method has problems with attributes such as | ||
| 244 | + // _base="<http://example.org/>" - it will convert those to something | ||
| 245 | + // like _base=<http://example.org></http:>. There may be other problems | ||
| 246 | + // with special characters etc, but the specific bug above can be | ||
| 247 | + // worked around by not having URIs end with '/'. | ||
| 248 | + | ||
| 224 | var params = $('#' + formId).serialize(); | 249 | var params = $('#' + formId).serialize(); |
| 225 | var escaped = '¶ms=' + escape(params); | 250 | var escaped = '¶ms=' + escape(params); |
| 226 | if(onSelect) { | 251 | if(onSelect) { | ... | ... |
| ... | @@ -53,13 +53,24 @@ | ... | @@ -53,13 +53,24 @@ |
| 53 | {= ?onSelect } | 53 | {= ?onSelect } |
| 54 | }, | 54 | }, |
| 55 | </ui:if> | 55 | </ui:if> |
| 56 | + autoWidth: true, | ||
| 57 | + height: '100%', | ||
| 56 | rowNum: 10, | 58 | rowNum: 10, |
| 57 | rowList:[5,10,20], | 59 | rowList:[5,10,20], |
| 58 | pager: '#{= ?pagerId }', | 60 | pager: '#{= ?pagerId }', |
| 59 | - viewrecords: true, | 61 | + shrinkToFit: false, |
| 60 | - sortorder: "asc", | 62 | + sortorder: 'asc', |
| 61 | - height: "100%", | 63 | + viewrecords: true |
| 62 | - width: "100%" | 64 | + //width: '100%' |
| 63 | - }).jqGrid('navGrid', '#{= ?pagerId }', { add:false, edit:false, del:false}); | 65 | + }).jqGrid('navGrid', '#{= ?pagerId }', { |
| 66 | + add:false, | ||
| 67 | + del:false, | ||
| 68 | + edit:false, | ||
| 69 | + search: false | ||
| 70 | + }); | ||
| 71 | + | ||
| 72 | + $("#{= ?tableId }").parent().resize(function() { | ||
| 73 | + alert('Resized'); | ||
| 74 | + }); | ||
| 64 | </script> | 75 | </script> |
| 65 | </ui:group> | 76 | </ui:group> |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
appschema.org/skapp.ui.ttl
deleted
100644 → 0
This diff is collapsed. Click to expand it.
| ... | @@ -26,52 +26,56 @@ log:LogBrowser | ... | @@ -26,52 +26,56 @@ log:LogBrowser |
| 26 | rdfs:subClassOf ui:Element ; | 26 | rdfs:subClassOf ui:Element ; |
| 27 | ui:prototype | 27 | ui:prototype |
| 28 | [ rdf:type html:Div ; | 28 | [ rdf:type html:Div ; |
| 29 | - html:style "width:900px"^^xsd:string ; | 29 | + html:id "logBrowserMainPanel"^^xsd:string ; |
| 30 | + html:style "width:880px; height: 500px; border-width: 1px; border-style: solid; border-color: black;"^^xsd:string ; | ||
| 30 | ui:child | 31 | ui:child |
| 31 | - [ rdf:type app:VSplitLayout ; | 32 | + [ rdf:type html:Div ; |
| 32 | - arg:height "500px"^^xsd:string ; | 33 | + html:class "ui-layout-north"^^xsd:string ; |
| 33 | - arg:topHeight "30%"^^xsd:string ; | 34 | + html:id "logBrowserNorthPanel"^^xsd:string ; |
| 35 | + html:style "height: 120px"^^xsd:string ; | ||
| 34 | ui:child | 36 | ui:child |
| 35 | [ rdf:type ui:setContext ; | 37 | [ rdf:type ui:setContext ; |
| 36 | ui:child | 38 | ui:child |
| 37 | - [ rdf:type app:HSplitLayout ; | 39 | + [ rdf:type html:Div ; |
| 38 | - arg:height "200px"^^xsd:string ; | 40 | + html:class "ui-layout-west"^^xsd:string ; |
| 41 | + ui:child | ||
| 42 | + [ rdf:type app:Header ; | ||
| 43 | + arg:label "Event Type"^^xsd:string ; | ||
| 44 | + ui:childIndex 0 | ||
| 45 | + ] ; | ||
| 39 | ui:child | 46 | ui:child |
| 40 | [ rdf:type html:Div ; | 47 | [ rdf:type html:Div ; |
| 41 | - ui:child | 48 | + html:class "ui-layout-content"^^xsd:string ; |
| 42 | - [ rdf:type app:Header ; | ||
| 43 | - arg:label "Event Type"^^xsd:string ; | ||
| 44 | - ui:childIndex 0 | ||
| 45 | - ] ; | ||
| 46 | ui:child | 49 | ui:child |
| 47 | [ rdf:type app:Tree ; | 50 | [ rdf:type app:Tree ; |
| 48 | arg:dataProvider log:LogEventClassTreeDataProvider ; | 51 | arg:dataProvider log:LogEventClassTreeDataProvider ; |
| 49 | arg:id "classTree"^^xsd:string ; | 52 | arg:id "classTree"^^xsd:string ; |
| 50 | arg:onSelect "appLoadWithResource('form', 'resourceType', resource)"^^xsd:string ; | 53 | arg:onSelect "appLoadWithResource('form', 'resourceType', resource)"^^xsd:string ; |
| 51 | - ui:childIndex 1 | 54 | + ui:childIndex 0 |
| 52 | ] ; | 55 | ] ; |
| 53 | - ui:childIndex 0 | 56 | + ui:childIndex 1 |
| 54 | ] ; | 57 | ] ; |
| 58 | + ui:childIndex 0 | ||
| 59 | + ] ; | ||
| 60 | + ui:child | ||
| 61 | + [ rdf:type ui:loadable ; | ||
| 62 | + html:class "ui-layout-center"^^xsd:string ; | ||
| 55 | ui:child | 63 | ui:child |
| 56 | - [ rdf:type ui:loadable ; | 64 | + [ rdf:type app:SearchForm ; |
| 57 | - ui:child | 65 | + arg:formId "searchForm"^^xsd:string ; |
| 58 | - [ rdf:type app:SearchForm ; | 66 | + arg:noBorder "true"^^xsd:boolean ; |
| 59 | - arg:formId "searchForm"^^xsd:string ; | 67 | + arg:queryGraph <http://www.reportinghub.no/graph/logging> ; |
| 60 | - arg:noBorder "true"^^xsd:boolean ; | 68 | + arg:resourceType |
| 61 | - arg:queryGraph <http://www.reportinghub.no/graph/logging> ; | 69 | + [ rdf:type sp:coalesce ; |
| 62 | - arg:resourceType | 70 | + sp:arg1 [ sp:varName "resourceType"^^xsd:string |
| 63 | - [ rdf:type sp:coalesce ; | ||
| 64 | - sp:arg1 [ sp:varName "resourceType"^^xsd:string | ||
| 65 | - ] ; | ||
| 66 | - sp:arg2 log:LogEvent | ||
| 67 | ] ; | 71 | ] ; |
| 68 | - arg:resultsId "results"^^xsd:string ; | 72 | + sp:arg2 log:LogEvent |
| 69 | - ui:childIndex 0 | ||
| 70 | ] ; | 73 | ] ; |
| 71 | - ui:childIndex 1 ; | 74 | + arg:resultsId "results"^^xsd:string ; |
| 72 | - ui:loadId "form"^^xsd:string | 75 | + ui:childIndex 0 |
| 73 | ] ; | 76 | ] ; |
| 74 | - ui:childIndex 0 | 77 | + ui:childIndex 1 ; |
| 78 | + ui:loadId "form"^^xsd:string | ||
| 75 | ] ; | 79 | ] ; |
| 76 | ui:childIndex 0 ; | 80 | ui:childIndex 0 ; |
| 77 | ui:queryGraph | 81 | ui:queryGraph |
| ... | @@ -79,21 +83,38 @@ log:LogBrowser | ... | @@ -79,21 +83,38 @@ log:LogBrowser |
| 79 | sp:arg1 <http://www.reportinghub.no/system/schema/logging> | 83 | sp:arg1 <http://www.reportinghub.no/system/schema/logging> |
| 80 | ] | 84 | ] |
| 81 | ] ; | 85 | ] ; |
| 86 | + ui:childIndex 0 | ||
| 87 | + ] ; | ||
| 88 | + ui:child | ||
| 89 | + [ rdf:type html:Div ; | ||
| 90 | + html:class "ui-layout-center"^^xsd:string ; | ||
| 91 | + html:style "height: 300px"^^xsd:string ; | ||
| 92 | + ui:child | ||
| 93 | + [ rdf:type app:Header ; | ||
| 94 | + arg:label "Matching Events"^^xsd:string ; | ||
| 95 | + ui:childIndex 0 | ||
| 96 | + ] ; | ||
| 82 | ui:child | 97 | ui:child |
| 83 | [ rdf:type html:Div ; | 98 | [ rdf:type html:Div ; |
| 84 | - ui:child | 99 | + html:class "ui-layout-content"^^xsd:string ; |
| 85 | - [ rdf:type app:Header ; | 100 | + html:id "results"^^xsd:string ; |
| 86 | - arg:label "Matching Events"^^xsd:string ; | ||
| 87 | - ui:childIndex 0 | ||
| 88 | - ] ; | ||
| 89 | - ui:child | ||
| 90 | - [ rdf:type html:Div ; | ||
| 91 | - html:id "results"^^xsd:string ; | ||
| 92 | - ui:childIndex 1 | ||
| 93 | - ] ; | ||
| 94 | ui:childIndex 1 | 101 | ui:childIndex 1 |
| 95 | ] ; | 102 | ] ; |
| 96 | - ui:childIndex 0 | 103 | + ui:childIndex 1 |
| 104 | + ] ; | ||
| 105 | + ui:child | ||
| 106 | + [ rdf:type html:Script ; | ||
| 107 | + ui:child | ||
| 108 | + [ rdf:type ui:TextNode ; | ||
| 109 | + ui:childIndex 0 ; | ||
| 110 | + ui:text """$('#logBrowserMainPanel').layout({ | ||
| 111 | + applyDefaultStyles: true | ||
| 112 | + }); | ||
| 113 | + $('#logBrowserNorthPanel').layout({ | ||
| 114 | + applyDefaultStyles: true | ||
| 115 | + });"""^^xsd:string | ||
| 116 | + ] ; | ||
| 117 | + ui:childIndex 2 | ||
| 97 | ] | 118 | ] |
| 98 | ] . | 119 | ] . |
| 99 | 120 | ... | ... |
-
Please register or login to post a comment