mirror of
https://github.com/corda/corda.git
synced 2025-02-02 09:18:13 +00:00
Improved the presentation of several fields.
This commit is contained in:
parent
3172b19b68
commit
7f8c3738b4
@ -16,6 +16,8 @@
|
|||||||
"angular": "^1.5.6",
|
"angular": "^1.5.6",
|
||||||
"jquery": "^3.0.0",
|
"jquery": "^3.0.0",
|
||||||
"angular-route": "^1.5.7",
|
"angular-route": "^1.5.7",
|
||||||
"lodash": "^4.13.1"
|
"lodash": "^4.13.1",
|
||||||
|
"angular-fcsa-number": "^1.5.3",
|
||||||
|
"jquery.maskedinput": "^1.4.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
<script src="semantic/semantic.js"></script>
|
<script src="semantic/semantic.js"></script>
|
||||||
<script src="bower_components/angular/angular.js"></script>
|
<script src="bower_components/angular/angular.js"></script>
|
||||||
<script src="bower_components/angular-route/angular-route.js"></script>
|
<script src="bower_components/angular-route/angular-route.js"></script>
|
||||||
|
<script src="bower_components/angular-fcsa-number/src/fcsaNumber.js"></script>
|
||||||
|
<script src="bower_components/jquery.maskedinput/dist/jquery.maskedinput.js"></script>
|
||||||
<script src="js/app.js"></script>
|
<script src="js/app.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body ng-controller="HomeController">
|
<body ng-controller="HomeController">
|
||||||
|
@ -21,13 +21,10 @@ let fixedLegModel = {
|
|||||||
effectiveDateAdjustment: null,
|
effectiveDateAdjustment: null,
|
||||||
terminationDate: new Date(2026, 3, 11),
|
terminationDate: new Date(2026, 3, 11),
|
||||||
terminationDateAdjustment: null,
|
terminationDateAdjustment: null,
|
||||||
fixedRate: {
|
fixedRate: "1.676",
|
||||||
ratioUnit: {
|
dayCountBasis: "30/360",
|
||||||
value: "0.01676"
|
//dayCountBasisDay: "D30",
|
||||||
}
|
//dayCountBasisYear: "Y360",
|
||||||
},
|
|
||||||
dayCountBasisDay: "D30",
|
|
||||||
dayCountBasisYear: "Y360",
|
|
||||||
rollConvention: "ModifiedFollowing",
|
rollConvention: "ModifiedFollowing",
|
||||||
dayInMonth: 10,
|
dayInMonth: 10,
|
||||||
paymentRule: "InArrears",
|
paymentRule: "InArrears",
|
||||||
@ -47,8 +44,9 @@ let floatingLegModel = {
|
|||||||
effectiveDateAdjustment: null,
|
effectiveDateAdjustment: null,
|
||||||
terminationDate: new Date(2026, 3, 11),
|
terminationDate: new Date(2026, 3, 11),
|
||||||
terminationDateAdjustment: null,
|
terminationDateAdjustment: null,
|
||||||
dayCountBasisDay: "D30",
|
dayCountBasis: "30/360",
|
||||||
dayCountBasisYear: "Y360",
|
//dayCountBasisDay: "D30",
|
||||||
|
//dayCountBasisYear: "Y360",
|
||||||
rollConvention: "ModifiedFollowing",
|
rollConvention: "ModifiedFollowing",
|
||||||
fixingRollConvention: "ModifiedFollowing",
|
fixingRollConvention: "ModifiedFollowing",
|
||||||
dayInMonth: 10,
|
dayInMonth: 10,
|
||||||
@ -78,19 +76,24 @@ let calculationModel = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Todo: Finish this model to solve the problem of the dates being in two different formats
|
let fixedRateViewModel = {
|
||||||
/*let commonModel = function() {
|
ratioUnit: {
|
||||||
this.baseCurrency = "EUR";
|
value: 0.01 // %
|
||||||
this.eligibleCurrency = "EUR";
|
}
|
||||||
this.eligibleCreditSupport: "Cash in an Eligible Currency";
|
}
|
||||||
this.independentAmounts = {
|
|
||||||
|
let commonViewModel = {
|
||||||
|
baseCurrency: "EUR",
|
||||||
|
eligibleCurrency: "EUR",
|
||||||
|
eligibleCreditSupport: "Cash in an Eligible Currency",
|
||||||
|
independentAmounts: {
|
||||||
quantity: 0,
|
quantity: 0,
|
||||||
token: "EUR"
|
token: "EUR"
|
||||||
};
|
},
|
||||||
this.threshold = {
|
threshold: {
|
||||||
quantity: 0,
|
quantity: 0,
|
||||||
token: "EUR"
|
token: "EUR"
|
||||||
};
|
},
|
||||||
minimumTransferAmount: {
|
minimumTransferAmount: {
|
||||||
quantity: 25000000,
|
quantity: 25000000,
|
||||||
token: "EUR"
|
token: "EUR"
|
||||||
@ -101,7 +104,7 @@ let calculationModel = {
|
|||||||
},
|
},
|
||||||
valuationDate: "Every Local Business Day",
|
valuationDate: "Every Local Business Day",
|
||||||
notificationTime: "2:00pm London",
|
notificationTime: "2:00pm London",
|
||||||
resolutionTime: "2:00pm London time on the first LocalBusiness Day following the date on which the notice is given ",
|
resolutionTime: "2:00pm London time on the first LocalBusiness Day following the date on which the notice is give",
|
||||||
interestRate: {
|
interestRate: {
|
||||||
oracle: "Rates Service Provider",
|
oracle: "Rates Service Provider",
|
||||||
tenor: {
|
tenor: {
|
||||||
@ -114,50 +117,50 @@ let calculationModel = {
|
|||||||
exposure: {},
|
exposure: {},
|
||||||
localBusinessDay: [ "London" , "NewYork" ],
|
localBusinessDay: [ "London" , "NewYork" ],
|
||||||
dailyInterestAmount: "(CashAmount * InterestRate ) / (fixedLeg.notional.token.currencyCode.equals('GBP')) ? 365 : 360",
|
dailyInterestAmount: "(CashAmount * InterestRate ) / (fixedLeg.notional.token.currencyCode.equals('GBP')) ? 365 : 360",
|
||||||
tradeID: tradeId,
|
|
||||||
hashLegalDocs: "put hash here"
|
hashLegalDocs: "put hash here"
|
||||||
};*/
|
};
|
||||||
|
|
||||||
let commonModel = {
|
let dealViewModel = {
|
||||||
"baseCurrency": "EUR",
|
fixedLeg: fixedLegModel,
|
||||||
"eligibleCurrency": "EUR",
|
floatingLeg: floatingLegModel,
|
||||||
"eligibleCreditSupport": "Cash in an Eligible Currency",
|
common: commonViewModel,
|
||||||
"independentAmounts": {
|
notary: "Bank A"
|
||||||
"quantity": 0,
|
};
|
||||||
"token": "EUR"
|
|
||||||
},
|
|
||||||
"threshold": {
|
|
||||||
"quantity": 0,
|
|
||||||
"token": "EUR"
|
|
||||||
},
|
|
||||||
"minimumTransferAmount": {
|
|
||||||
"quantity": 25000000,
|
|
||||||
"token": "EUR"
|
|
||||||
},
|
|
||||||
"rounding": {
|
|
||||||
"quantity": 1000000,
|
|
||||||
"token": "EUR"
|
|
||||||
},
|
|
||||||
"valuationDate": "Every Local Business Day",
|
|
||||||
"notificationTime": "2:00pm London",
|
|
||||||
"resolutionTime": "2:00pm London time on the first LocalBusiness Day following the date on which the notice is give",
|
|
||||||
"interestRate": {
|
|
||||||
"oracle": "Rates Service Provider",
|
|
||||||
"tenor": {
|
|
||||||
"name": "6M"
|
|
||||||
},
|
|
||||||
"ratioUnit": null,
|
|
||||||
"name": "EONIA"
|
|
||||||
},
|
|
||||||
"addressForTransfers": "",
|
|
||||||
"exposure": {},
|
|
||||||
"localBusinessDay": [ "London" , "NewYork" ],
|
|
||||||
"dailyInterestAmount": "(CashAmount * InterestRate ) / (fixedLeg.notional.token.currencyCode.equals('GBP')) ? 365 : 360",
|
|
||||||
"tradeID": "tradeXXX",
|
|
||||||
"hashLegalDocs": "put hash here"
|
|
||||||
};
|
|
||||||
|
|
||||||
let irsViewer = angular.module('irsViewer', ['ngRoute'])
|
let Deal = function(dealViewModel) {
|
||||||
|
let now = new Date();
|
||||||
|
let tradeId = `T${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDate()}.${now.getUTCHours()}:${now.getUTCMinutes()}:${now.getUTCSeconds()}:${now.getUTCMilliseconds()}`
|
||||||
|
|
||||||
|
this.toJson = () => {
|
||||||
|
let fixedLeg = {};
|
||||||
|
let floatingLeg = {};
|
||||||
|
let common = {};
|
||||||
|
_.assign(fixedLeg, dealViewModel.fixedLeg);
|
||||||
|
_.assign(floatingLeg, dealViewModel.floatingLeg);
|
||||||
|
_.assign(common, dealViewModel.common);
|
||||||
|
|
||||||
|
fixedRateViewModel.fixedRate = Number(fixedLeg.fixedRate) / 100;
|
||||||
|
_.assign(fixedLeg.fixedRate, fixedRateViewModel);
|
||||||
|
|
||||||
|
common.tradeID = tradeId;
|
||||||
|
fixedLeg.effectiveDate = formatDateForNode(fixedLeg.effectiveDate);
|
||||||
|
fixedLeg.terminationDate = formatDateForNode(fixedLeg.terminationDate);
|
||||||
|
floatingLeg.effectiveDate = formatDateForNode(floatingLeg.effectiveDate);
|
||||||
|
floatingLeg.terminationDate = formatDateForNode(floatingLeg.terminationDate);
|
||||||
|
|
||||||
|
let json = {
|
||||||
|
fixedLeg: fixedLeg,
|
||||||
|
floatingLeg: floatingLeg,
|
||||||
|
calculation: calculationModel,
|
||||||
|
common: common,
|
||||||
|
notary: dealViewModel.notary
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let irsViewer = angular.module('irsViewer', ['ngRoute', 'fcsa-number'])
|
||||||
.config(($routeProvider, $locationProvider) => {
|
.config(($routeProvider, $locationProvider) => {
|
||||||
$routeProvider
|
$routeProvider
|
||||||
.when('/', {
|
.when('/', {
|
||||||
@ -260,20 +263,11 @@ let nodeService = irsViewer.factory('nodeService', ($http) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.newDeal = () => {
|
this.newDeal = () => {
|
||||||
let now = new Date();
|
return dealViewModel;
|
||||||
let tradeId = `T${now.getUTCFullYear()}-${now.getUTCMonth()}-${now.getUTCDate()}.${now.getUTCHours()}:${now.getUTCMinutes()}:${now.getUTCSeconds()}:${now.getUTCMilliseconds()}`
|
|
||||||
|
|
||||||
return {
|
|
||||||
fixedLeg: fixedLegModel,
|
|
||||||
floatingLeg: floatingLegModel,
|
|
||||||
calculation: calculationModel,
|
|
||||||
common: commonModel,
|
|
||||||
notary: "Bank A"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.createDeal = (deal) => {
|
this.createDeal = (deal) => {
|
||||||
return load('create-deal', $http.post('http://localhost:31338/api/irs/deals', deal))
|
return load('create-deal', $http.post('http://localhost:31338/api/irs/deals', deal.toJson()))
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
return deal.tradeId;
|
return deal.tradeId;
|
||||||
}, (resp) => {
|
}, (resp) => {
|
||||||
@ -288,17 +282,6 @@ function initSemanticUi() {
|
|||||||
$('.ui.dropdown').dropdown();
|
$('.ui.dropdown').dropdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareDeal(deal) {
|
|
||||||
let newDeal = Object.assign({}, deal);
|
|
||||||
|
|
||||||
newDeal.fixedLeg.effectiveDate = formatDateForNode(newDeal.fixedLeg.effectiveDate);
|
|
||||||
newDeal.fixedLeg.terminationDate = formatDateForNode(newDeal.fixedLeg.terminationDate);
|
|
||||||
newDeal.floatingLeg.effectiveDate = formatDateForNode(newDeal.floatingLeg.effectiveDate);
|
|
||||||
newDeal.floatingLeg.terminationDate = formatDateForNode(newDeal.floatingLeg.terminationDate);
|
|
||||||
|
|
||||||
return newDeal;
|
|
||||||
}
|
|
||||||
|
|
||||||
irsViewer.controller('HomeController', function HomeController($http, $scope, nodeService) {
|
irsViewer.controller('HomeController', function HomeController($http, $scope, nodeService) {
|
||||||
let handleHttpFail = (resp) => {
|
let handleHttpFail = (resp) => {
|
||||||
console.log(resp.data)
|
console.log(resp.data)
|
||||||
@ -330,9 +313,10 @@ irsViewer.controller('CreateDealController', function CreateDealController($http
|
|||||||
$scope.isLoading = nodeService.isLoading;
|
$scope.isLoading = nodeService.isLoading;
|
||||||
$scope.deal = nodeService.newDeal();
|
$scope.deal = nodeService.newDeal();
|
||||||
$scope.createDeal = () => {
|
$scope.createDeal = () => {
|
||||||
nodeService.createDeal(prepareDeal($scope.deal))
|
nodeService.createDeal(new Deal($scope.deal))
|
||||||
.then((tradeId) => $location.path('#/deal/' + tradeId), (resp) => {
|
.then((tradeId) => $location.path('#/deal/' + tradeId), (resp) => {
|
||||||
$scope.formError = resp.data;
|
$scope.formError = resp.data;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
$('input.percent').mask("9.999999%", {placeholder: "", autoclear: false});
|
||||||
});
|
});
|
@ -16,7 +16,7 @@
|
|||||||
<label>Notional</label>
|
<label>Notional</label>
|
||||||
<div class="ui grid">
|
<div class="ui grid">
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<input type="text" name="quantity" ng-model="deal.fixedLeg.notional.quantity"/>
|
<input type="text" name="quantity" ng-model="deal.fixedLeg.notional.quantity" fcsa-number/>
|
||||||
</div>
|
</div>
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<select class="ui dropdown fluid" name="token" ng-model="deal.fixedLeg.notional.token">
|
<select class="ui dropdown fluid" name="token" ng-model="deal.fixedLeg.notional.token">
|
||||||
@ -41,7 +41,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Effective Date</label>
|
<label>Effective Date</label>
|
||||||
<input type="date" name="effectiveDate" ng-model="deal.fixedLeg.effectiveDateAccess" ng-model-options="{ getterSetter: true }"/>
|
<input type="date" name="effectiveDate" ng-model="deal.fixedLeg.effectiveDate""/>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Termination Date</label>
|
<label>Termination Date</label>
|
||||||
@ -49,11 +49,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Day Count Basis</label>
|
<label>Day Count Basis</label>
|
||||||
<input type="text" name="dayCountBasisDay" ng-model="deal.fixedLeg.dayCountBasisDay"/>
|
<div class="ui selection dropdown">
|
||||||
</div>
|
<input type="hidden" ng-model="deal.fixedLeg.dayCountBasis" />
|
||||||
<div class="field">
|
<div class="default text">{{deal.fixedLeg.dayCountBasis}}</div>
|
||||||
<label>Day Bound Basis Year</label>
|
<div class="menu">
|
||||||
<input type="text" name="dayCountBasisYear" ng-model="deal.fixedLeg.dayCountBasisYear"/>
|
<div class="item">1/1</div>
|
||||||
|
<div class="item">30/360</div>
|
||||||
|
<div class="item">30E/360</div>
|
||||||
|
<div class="item">30E/360 (IDSA)</div>
|
||||||
|
<div class="item">30E+/360 ISDO</div>
|
||||||
|
<div class="item">ACT/360</div>
|
||||||
|
<div class="item">ACT/365 Fixed</div>
|
||||||
|
<div class="item">ACT/365 L</div>
|
||||||
|
<div class="item">ACT/365 A/1</div>
|
||||||
|
<div class="item">NL/365</div>
|
||||||
|
<div class="item">ACT/ACT ISDA</div>
|
||||||
|
<div class="item">ACT/ACT ICMA</div>
|
||||||
|
<div class="item">Business/252</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Roll Convention</label>
|
<label>Roll Convention</label>
|
||||||
@ -91,8 +105,8 @@
|
|||||||
<input type="text" name="paymentCalendar" ng-model="deal.fixedLeg.paymentCalendar"/>
|
<input type="text" name="paymentCalendar" ng-model="deal.fixedLeg.paymentCalendar"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Fixed Rate Ratio Unit</label>
|
<label>Fixed Rate</label>
|
||||||
<input type="text" name="value" ng-model="deal.fixedLeg.fixedRate.ratioUnit.value"/>
|
<input type="text" name="value" class="percent" ng-model="deal.fixedLeg.fixedRate"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Interest Period Adjustment</label>
|
<label>Interest Period Adjustment</label>
|
||||||
@ -116,7 +130,7 @@
|
|||||||
<label>Notional</label>
|
<label>Notional</label>
|
||||||
<div class="ui grid">
|
<div class="ui grid">
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<input type="text" name="quantity" ng-model="deal.floatingLeg.notional.quantity"/>
|
<input type="text" name="quantity" ng-model="deal.floatingLeg.notional.quantity" fcsa-number/>
|
||||||
</div>
|
</div>
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<select class="ui dropdown fluid" name="token" ng-model="deal.floatingLeg.notional.token">
|
<select class="ui dropdown fluid" name="token" ng-model="deal.floatingLeg.notional.token">
|
||||||
@ -148,12 +162,26 @@
|
|||||||
<input type="date" name="terminationDate" ng-model="deal.floatingLeg.terminationDate"/>
|
<input type="date" name="terminationDate" ng-model="deal.floatingLeg.terminationDate"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Day Count Basis Day</label>
|
<label>Day Count Basis</label>
|
||||||
<input type="text" name="dayCountBasisDay" ng-model="deal.floatingLeg.dayCountBasisDay"/>
|
<div class="ui selection dropdown">
|
||||||
</div>
|
<input type="hidden" ng-model="deal.floatingLeg.dayCountBasis" />
|
||||||
<div class="field">
|
<div class="default text">{{deal.floatingLeg.dayCountBasis}}</div>
|
||||||
<label>Day Count Basis Year</label>
|
<div class="menu">
|
||||||
<input type="text" name="dayCountBasisYear" ng-model="deal.floatingLeg.dayCountBasisYear"/>
|
<div class="item">1/1</div>
|
||||||
|
<div class="item">30/360</div>
|
||||||
|
<div class="item">30E/360</div>
|
||||||
|
<div class="item">30E/360 (IDSA)</div>
|
||||||
|
<div class="item">30E+/360 ISDO</div>
|
||||||
|
<div class="item">ACT/360</div>
|
||||||
|
<div class="item">ACT/365 Fixed</div>
|
||||||
|
<div class="item">ACT/365 L</div>
|
||||||
|
<div class="item">ACT/365 A/1</div>
|
||||||
|
<div class="item">NL/365</div>
|
||||||
|
<div class="item">ACT/ACT ISDA</div>
|
||||||
|
<div class="item">ACT/ACT ICMA</div>
|
||||||
|
<div class="item">Business/252</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Roll Convention</label>
|
<label>Roll Convention</label>
|
||||||
@ -277,7 +305,7 @@
|
|||||||
<label>Independent Amounts</label>
|
<label>Independent Amounts</label>
|
||||||
<div class="ui grid">
|
<div class="ui grid">
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<input type="text" name="quantity" ng-model="deal.common.independentAmounts.quantity"/>
|
<input type="text" name="quantity" ng-model="deal.common.independentAmounts.quantity" fcsa-number />
|
||||||
</div>
|
</div>
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<select class="ui dropdown fluid" name="token" ng-model="deal.common.independentAmounts.token">
|
<select class="ui dropdown fluid" name="token" ng-model="deal.common.independentAmounts.token">
|
||||||
@ -292,7 +320,7 @@
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="ui grid">
|
<div class="ui grid">
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<input type="text" name="quantity" ng-model="deal.common.threshold.quantity"/>
|
<input type="text" name="quantity" ng-model="deal.common.threshold.quantity" fcsa-number />
|
||||||
</div>
|
</div>
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<select class="ui dropdown fluid" name="token" ng-model="deal.common.threshold.token">
|
<select class="ui dropdown fluid" name="token" ng-model="deal.common.threshold.token">
|
||||||
@ -308,7 +336,7 @@
|
|||||||
<label>Minimum Transfer Amount</label>
|
<label>Minimum Transfer Amount</label>
|
||||||
<div class="ui grid">
|
<div class="ui grid">
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<input type="text" name="quantity" ng-model="deal.common.minimumTransferAmount.quantity"/>
|
<input type="text" name="quantity" ng-model="deal.common.minimumTransferAmount.quantity" fcsa-number />
|
||||||
</div>
|
</div>
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<select class="ui dropdown fluid" name="token" ng-model="deal.common.minimumTransferAmount.token">
|
<select class="ui dropdown fluid" name="token" ng-model="deal.common.minimumTransferAmount.token">
|
||||||
@ -323,7 +351,7 @@
|
|||||||
<label>Rounding</label>
|
<label>Rounding</label>
|
||||||
<div class="ui grid">
|
<div class="ui grid">
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<input type="text" name="quantity" ng-model="deal.common.rounding.quantity"/>
|
<input type="text" name="quantity" ng-model="deal.common.rounding.quantity" fcsa-number/>
|
||||||
</div>
|
</div>
|
||||||
<div class="eight wide column">
|
<div class="eight wide column">
|
||||||
<select class="ui dropdown fluid" name="token" ng-model="deal.common.rounding.token">
|
<select class="ui dropdown fluid" name="token" ng-model="deal.common.rounding.token">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user