Skip to content

Commit 1863af5

Browse files
committed
refactor: rewrite series sales block to react
Fix #1329
1 parent 3bd115e commit 1863af5

File tree

3 files changed

+254
-63
lines changed

3 files changed

+254
-63
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
//
2+
// IMPORTANT:
3+
// You must update ResourceUrl.RESOURCES_VERSION each time whenever you're modified this file!
4+
//
5+
6+
class SeriesSalesList extends React.PureComponent {
7+
8+
constructor(props) {
9+
super(props);
10+
this.state = {
11+
sales: [],
12+
hasServerError: false,
13+
};
14+
this.loadSales = this.loadSales.bind(this);
15+
}
16+
17+
componentDidMount(){
18+
this.loadSales()
19+
}
20+
21+
loadSales() {
22+
this.setState({
23+
hasServerError: false,
24+
sales: []
25+
});
26+
27+
axios.get(this.props.url)
28+
.then(response => {
29+
const data = response.data;
30+
this.setState({ sales: data });
31+
32+
})
33+
.catch(error => {
34+
console.error(error);
35+
this.setState({ hasServerError: true });
36+
});
37+
}
38+
39+
render() {
40+
return (
41+
<SeriesSalesListView
42+
l10n={this.props.l10n}
43+
hasServerError={this.state.hasServerError}
44+
sales={this.state.sales}
45+
/>
46+
)
47+
}
48+
}
49+
50+
class SeriesSalesListView extends React.PureComponent {
51+
render() {
52+
const { hasServerError, l10n, sales } = this.props;
53+
54+
return (
55+
<div className="row">
56+
<div className="col-sm-12">
57+
<h5>{ l10n['t_who_selling_series'] || 'Who was selling/buying this series' }</h5>
58+
<div className="row">
59+
<div id="loading-series-sales-failed-msg"
60+
className={ `alert alert-danger text-center col-sm-8 col-sm-offset-2 ${hasServerError ? '' : 'hidden'}` }>
61+
{ l10n['t_server_error'] || 'Server error' }
62+
</div>
63+
</div>
64+
<ul>
65+
{ sales.map((sale, index) => (
66+
<SeriesSaleItem
67+
key={sale.id}
68+
l10n={this.props.l10n}
69+
sale={sale}
70+
index={index + 1}
71+
/>
72+
))}
73+
</ul>
74+
</div>
75+
</div>
76+
)
77+
}
78+
}
79+
80+
class SeriesSaleItem extends React.PureComponent {
81+
render() {
82+
const { sale, index, l10n } = this.props;
83+
const hasBuyer = !!sale.buyerName;
84+
const hasCondition = !!sale.condition;
85+
86+
return (
87+
<li id={ `series-sale-${index}-info` }>
88+
<a href={sale.sellerUrl} id={ `series-sale-${index}-seller` } rel="nofollow">{sale.sellerName}</a>
89+
{' '}
90+
{ hasBuyer
91+
? (l10n['t_sold_to'] || 'sold to')
92+
: (l10n['t_was_selling'] || 'was selling for')
93+
}
94+
{' '}
95+
{ hasBuyer && (<ParticipantLink url={sale.buyerUrl} name={sale.buyerName} />) }
96+
{' '}
97+
{ hasBuyer && (l10n['t_sold_for'] || 'for') }
98+
{' '}
99+
<TransactionLink
100+
index={index}
101+
url={sale.transactionUrl}
102+
firstPrice={sale.firstPrice}
103+
firstCurrency={sale.firstCurrency}
104+
secondPrice={sale.secondPrice}
105+
secondCurrency={sale.secondCurrency}
106+
/>
107+
{' '}
108+
{ hasCondition && <span>{`(${sale.condition})`}</span> }
109+
</li>
110+
)
111+
}
112+
}
113+
114+
class ParticipantLink extends React.PureComponent {
115+
render() {
116+
const { name, url } = this.props;
117+
return (
118+
<a href={url} rel="nofollow">{ name }</a>
119+
)
120+
}
121+
}
122+
123+
class TransactionLink extends React.PureComponent {
124+
render() {
125+
const { index, url, firstPrice, firstCurrency, secondPrice, secondCurrency} = this.props;
126+
const hasSecondPrice = !!secondPrice;
127+
return (
128+
<a href={url} id={ `series-sale-${index}-transaction` } rel="nofollow">
129+
{ `${firstPrice}\u00A0${firstCurrency}` }
130+
{ hasSecondPrice && `(${secondPrice}\u00A0${secondCurrency})` }
131+
</a>
132+
)
133+
}
134+
}

src/main/java/ru/mystamps/web/feature/site/ResourceUrl.java

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public final class ResourceUrl {
4949
private static final String CATALOG_PRICE_FORM_JS = "/public/js/" + RESOURCES_VERSION + "/components/AddCatalogPriceForm.js";
5050
private static final String CATALOG_NUMBERS_FORM_JS = "/public/js/" + RESOURCES_VERSION + "/components/AddCatalogNumbersForm.js";
5151
private static final String RELEASE_YEAR_FORM_JS = "/public/js/" + RESOURCES_VERSION + "/components/AddReleaseYearForm.js";
52+
private static final String SERIES_SALES_LIST_JS = "/public/js/" + RESOURCES_VERSION + "/components/SeriesSalesList.js";
53+
5254
private static final String BOOTSTRAP_LANGUAGE = "https://cdn.jsdelivr.net/gh/usrz/bootstrap-languages@3ac2a3d2b27ac43a471cd99e79d378a03b2c6b5f/languages.min.css";
5355
private static final String FAVICON_ICO = "/favicon.ico";
5456

@@ -88,6 +90,8 @@ public static void exposeResourcesToView(Map<String, String> resources, String h
8890
put(resources, host, "CATALOG_PRICE_FORM_JS", CATALOG_PRICE_FORM_JS);
8991
put(resources, host, "CATALOG_NUMBERS_FORM_JS", CATALOG_NUMBERS_FORM_JS);
9092
put(resources, host, "RELEASE_YEAR_FORM_JS", RELEASE_YEAR_FORM_JS);
93+
put(resources, host, "SERIES_SALES_LIST_JS", SERIES_SALES_LIST_JS);
94+
9195
}
9296

9397
// see also MvcConfig.addResourceHandlers()

src/main/webapp/WEB-INF/views/series/info.html

+116-63
Original file line numberDiff line numberDiff line change
@@ -559,69 +559,7 @@ <h5 class="text-center" th:text="#{t_similar_series}">
559559
/*/-->
560560
</div>
561561

562-
<div class="row" th:if="${not #lists.isEmpty(purchasesAndSales)}" sec:authorize="hasAuthority('VIEW_SERIES_SALES')">
563-
<div class="col-sm-12">
564-
<h5 th:text="#{t_who_selling_series}">Who was selling/buying this series</h5>
565-
<ul th:remove="all-but-first">
566-
<li id="series-sale-1-info"
567-
th:id="|series-sale-${iter.count}-info|"
568-
th:each="transaction,iter : ${purchasesAndSales}"
569-
th:with="firstPrice=${#numbers.formatDecimal(transaction.firstPrice, 0, 'DEFAULT', 2, 'DEFAULT') + '&nbsp;' + transaction.firstCurrency},
570-
optionalSecondPrice=${transaction.secondPrice != null ? ('&nbsp;' + '(' + #numbers.formatDecimal(transaction.secondPrice, 0, 'DEFAULT', 2, 'DEFAULT') + '&nbsp;' + transaction.secondCurrency + ')') : ''}">
571-
<!--/*/
572-
<span th:if="${transaction.date != null}" th:remove="tag" th:text="${#dates.format(transaction.date, 'dd.MM.yyyy')}"></span>
573-
/*/-->
574-
<a href="http://example.com/james-alan-hetfield"
575-
id="series-sale-1-seller"
576-
rel="nofollow"
577-
th:id="|series-sale-${iter.count}-seller|"
578-
th:remove="${transaction.sellerUrl == null} ? tag"
579-
th:href="${transaction.sellerUrl}"
580-
th:text="${transaction.sellerName}">James Alan Hetfield</a>
581-
<span th:if="${transaction.buyerName == null}" th:remove="tag" th:text="#{t_was_selling_for}">was selling for</span>
582-
<!--/*/
583-
<th:block th:if="${transaction.buyerName != null}">
584-
<span th:text="#{t_sold_to}" th:remove="tag">sold to</span>
585-
<a href="http://example.com/eicca-toppinen" rel="nofollow" th:remove="${transaction.buyerUrl == null} ? tag" th:href="${transaction.buyerUrl}" th:text="${transaction.buyerName}">Eicca Toppinen</a>
586-
<span th:text="#{t_sold_for}" th:remove="tag">for</span>
587-
</th:block>
588-
/*/-->
589-
<a href="http://example.com/james-alan-hetfield/selling-stamps"
590-
id="series-sale-1-transaction"
591-
rel="nofollow"
592-
th:id="|series-sale-${iter.count}-transaction|"
593-
th:remove="${transaction.transactionUrl == null} ? tag"
594-
th:href="${transaction.transactionUrl}"
595-
th:text="${firstPrice + optionalSecondPrice}">100 USD</a>
596-
<!--/*/
597-
<th:block th:if="${transaction.condition != null}" th:switch="${transaction.condition.toString()}">
598-
<span th:text="|(${#strings.unCapitalize('__#{t_cancelled}__')})|" th:case=" 'CANCELLED' ">cancelled</span>
599-
/*/-->
600-
<span th:text="|(${transaction.condition})|" th:case="*">(MNH)</span>
601-
<!--/*/
602-
</th:block>
603-
/*/-->
604-
</li>
605-
<li id="series-sale-2-info">
606-
<a href="http://example.com/james-alan-hetfield" id="series-sale-2-seller" rel="nofollow">James Alan Hetfield</a> was selling for <a href="http://example.com/james-alan-hetfield/selling-stamps" id="series-sale-2-transaction" rel="nofollow">100 USD (650 RUB)</a>
607-
</li>
608-
<li id="series-sale-3-info">
609-
02.02.2002 <a href="http://example.com/tommy-lee-jones" id="series-sale-3-seller" rel="nofollow">Tommy Lee Jones</a> was selling for <a href="http://example.com/tommy-lee-jones/selling-stamps" id="series-sale-3-transaction" rel="nofollow">200 USD</a>
610-
(cancelled)
611-
</li>
612-
<li id="series-sale-4-info">
613-
02.02.2002 <a href="http://example.com/tommy-lee-jones" id="series-sale-4-seller" rel="nofollow">Tommy Lee Jones</a> was selling for <a href="http://example.com/tommy-lee-jones/selling-stamps" id="series-sale-4-transaction" rel="nofollow">200 USD (1300 RUB)</a>
614-
</li>
615-
<li id="series-sale-5-info">
616-
03.03.2003 <a href="http://example.com/eicca-toppinen" id="series-sale-5-seller" rel="nofollow">Eicca Toppinen</a> sold to <a href="http://example.com/kurt-cobain" rel="nofollow">Kurt Cobain</a> for <a href="http://example.com/eicca-toppinen/selling-stamps" id="series-sale-5-transaction" rel="nofollow">300 USD</a>
617-
(MVLH)
618-
</li>
619-
<li id="series-sale-6-info">
620-
03.03.2003 <a href="http://example.com/eicca-toppinen" id="series-sale-6-seller" rel="nofollow">Eicca Toppinen</a> sold to Michael Jackson for <a href="http://example.com/eicca-toppinen/selling-stamps" id="series-sale-6-transaction" rel="nofollow">300 USD (1560 RUB)</a>
621-
</li>
622-
</ul>
623-
</div>
624-
</div>
562+
<div id="series-sales-list" sec:authorize="hasAuthority('VIEW_SERIES_SALES')"></div>
625563

626564
<div class="row" sec:authorize="hasAuthority('ADD_SERIES_SALES')">
627565
<div class="col-sm-12">
@@ -999,6 +937,106 @@ <h5 th:text="#{t_add_info_who_selling_series}">Add info about selling/buying thi
999937

1000938
responseCount++;
1001939

940+
return new Promise(function delayExecution(resolve) {
941+
setTimeout(resolve, 500 /* 0.5 second */);
942+
943+
}).then(function returnResponse() {
944+
return stubResponse.status == 500 ? Promise.reject(stubResponse) : Promise.resolve(stubResponse);
945+
});
946+
},
947+
get: function (url) {
948+
var possibleOutcomes = [ 'success'];
949+
var outcome = possibleOutcomes[responseCount % possibleOutcomes.length];
950+
var possibleResponses = {
951+
'/series/100': {
952+
'success': {
953+
status: 200,
954+
data: [
955+
{
956+
id: 1,
957+
sellerName: 'James Alan Hetfield',
958+
sellerUrl: 'http://example.com/james-alan-hetfield',
959+
buyerName: 'Eicca Toppinen',
960+
buyerUrl: 'http://example.com/eicca-toppinen',
961+
transactionUrl: 'http://example.com/james-alan-hetfield/selling-stamps',
962+
firstPrice: 100,
963+
firstCurrency: 'USD',
964+
condition: 'cancelled'
965+
},
966+
{
967+
id: 2,
968+
sellerName: 'James Alan Hetfield',
969+
sellerUrl: 'http://example.com/james-alan-hetfield',
970+
transactionUrl: 'http://example.com/james-alan-hetfield/selling-stamps',
971+
firstPrice: 100,
972+
firstCurrency: 'USD',
973+
secondPrice: 650,
974+
secondCurrency: 'RUB'
975+
},
976+
{
977+
id: 3,
978+
date: '02.02.2002',
979+
sellerName: 'Tommy Lee Jones',
980+
sellerUrl: 'http://example.com/tommy-lee-jones',
981+
transactionUrl: 'http://example.com/tommy-lee-jones/selling-stamps',
982+
firstPrice: 200,
983+
firstCurrency: 'USD',
984+
condition: 'MNH'
985+
},
986+
{
987+
id: 4,
988+
date: '02.02.2002',
989+
sellerName: 'Tommy Lee Jones',
990+
sellerUrl: 'http://example.com/tommy-lee-jones',
991+
transactionUrl: 'http://example.com/tommy-lee-jones/selling-stamps',
992+
firstPrice: 200,
993+
firstCurrency: 'USD',
994+
secondPrice: 1300,
995+
secondCurrency: 'RUB',
996+
},
997+
{
998+
id: 5,
999+
date: '03.02.2002',
1000+
sellerName: 'Eicca Toppinen',
1001+
sellerUrl: 'http://example.com/eicca-toppinen',
1002+
transactionUrl: 'http://example.com/tommy-lee-jones/selling-stamps',
1003+
firstPrice: 300,
1004+
firstCurrency: 'USD',
1005+
secondPrice: 1560,
1006+
secondCurrency: 'RUB',
1007+
},
1008+
{
1009+
id: 6,
1010+
date: '03.02.2002',
1011+
sellerName: 'Eicca Toppinen',
1012+
sellerUrl: 'http://example.com/eicca-toppinen',
1013+
buyerName: 'Kurt Cobain',
1014+
buyerUrl: 'http://example.com/kurt-cobain',
1015+
transactionUrl: 'http://example.com/tommy-lee-jones/selling-stamps',
1016+
firstPrice: 300,
1017+
firstCurrency: 'USD',
1018+
secondPrice: 1560,
1019+
secondCurrency: 'RUB',
1020+
}
1021+
]
1022+
}
1023+
}
1024+
};
1025+
var stubResponse;
1026+
1027+
switch (outcome) {
1028+
case 'success':
1029+
stubResponse = possibleResponses[url][outcome];
1030+
break;
1031+
default:
1032+
stubResponse = {
1033+
status: 500,
1034+
statusText: 'Fake Server Error'
1035+
};
1036+
}
1037+
1038+
responseCount++;
1039+
10021040
return new Promise(function delayExecution(resolve) {
10031041
setTimeout(resolve, 500 /* 0.5 second */);
10041042

@@ -1019,6 +1057,8 @@ <h5 th:text="#{t_add_info_who_selling_series}">Add info about selling/buying thi
10191057
<script src="../../../../../../target/classes/js/components/AddReleaseYearForm.js" th:src="${RELEASE_YEAR_FORM_JS}"></script>
10201058
<script src="../../../../../../target/classes/js/components/AddCatalogPriceForm.js" th:src="${CATALOG_PRICE_FORM_JS}"></script>
10211059
<script src="../../../../../../target/classes/js/components/AddCatalogNumbersForm.js" th:src="${CATALOG_NUMBERS_FORM_JS}"></script>
1060+
<script src="../../../../../../target/classes/js/components/SeriesSalesList.js" th:src="${SERIES_SALES_LIST_JS}"></script>
1061+
10221062

10231063
<script th:inline="javascript">
10241064
/*[+
@@ -1057,6 +1097,12 @@ <h5 th:text="#{t_add_info_who_selling_series}">Add info about selling/buying thi
10571097
't_add': [[ #{t_add} ]]
10581098
}
10591099
};
1100+
var seriesSalesListProps = {
1101+
'url': [[ '__@{${INFO_SERIES_PAGE}(id=${series.id})}__' ]],
1102+
'l10n': {
1103+
't_server_error': [[ #{t_server_error} ]],
1104+
}
1105+
};
10601106
+]*/
10611107

10621108
/*[- */
@@ -1074,10 +1120,17 @@ <h5 th:text="#{t_add_info_who_selling_series}">Add info about selling/buying thi
10741120
'url': '/series/100',
10751121
'l10n': {}
10761122
};
1123+
1124+
var seriesSalesListProps = {
1125+
'url': '/series/100',
1126+
'l10n': {}
1127+
};
10771128
/* -]*/
10781129

10791130
renderComponent(AddCatalogPriceForm, addCatalogPriceProps, 'add-catalog-price');
10801131
renderComponent(AddCatalogNumbersForm, addCatalogNumbersProps, 'add-catalog-numbers');
1132+
renderComponent(SeriesSalesList, seriesSalesListProps, 'series-sales-list');
1133+
10811134

10821135
/*[# th:if="${series.releaseYear == null}"]*/
10831136
/*[+

0 commit comments

Comments
 (0)