diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea00021..77a7652 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-## [Unreleased]
+## [1.4.0]
+
+### Added
+
+- Support for WooComerce:
+ - New tab in Settings to generate authentication token.
+ - Display of WooCommerce credentials for configuration.
+- New service to interact with WooCommerce-related API endpoints.
+- A "Return To Shop" button added to ZGo Invoice component
## [1.3.2] - 2022-10-11
diff --git a/angular.json b/angular.json
index 9839d4f..2ded65f 100644
--- a/angular.json
+++ b/angular.json
@@ -39,8 +39,8 @@
"budgets": [
{
"type": "initial",
- "maximumWarning": "500kb",
- "maximumError": "1mb"
+ "maximumWarning": "5mb",
+ "maximumError": "10mb"
},
{
"type": "anyComponentStyle",
diff --git a/package.json b/package.json
index bbbe622..3b16603 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "zgo",
- "version": "1.3.2",
+ "version": "1.4.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
diff --git a/src/app/invoice/invoice.component.html b/src/app/invoice/invoice.component.html
index d682959..23f8302 100644
--- a/src/app/invoice/invoice.component.html
+++ b/src/app/invoice/invoice.component.html
@@ -116,13 +116,35 @@
background-color: lightgray;"
mat-raised-button
(click)="copyAmount()">Copy Amount
-
+
+ mat-raised-button
+ (click)="copyMemo()" *ngIf="!isWCOrder">Copy Memo
+
+
+
+
+
diff --git a/src/app/invoice/invoice.component.ts b/src/app/invoice/invoice.component.ts
index a702b43..dbe710d 100644
--- a/src/app/invoice/invoice.component.ts
+++ b/src/app/invoice/invoice.component.ts
@@ -4,7 +4,7 @@ import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { ReceiptService } from '../receipt.service';
import { Order} from '../order/order.model';
import { Observable } from 'rxjs';
-import { faCheck, faHourglass } from '@fortawesome/free-solid-svg-icons';
+import { faCheck, faHourglass, faArrowUpRightFromSquare } from '@fortawesome/free-solid-svg-icons';
import { NotifierService } from '../notifier.service';
@@ -17,21 +17,22 @@ var Buffer = require('buffer/').Buffer;
templateUrl: './invoice.component.html',
styleUrls: ['./invoice.component.css']
})
+
export class InvoiceComponent implements OnInit {
faCheck = faCheck;
faHourglass = faHourglass;
+ faArrowUpRightFromSquare = faArrowUpRightFromSquare;
orderId;
public orderUpdate: Observable;
public nameUpdate: Observable;
name: string = '';
error: boolean = false;
codeString: string = 'Test';
-
+ public isWCOrder : boolean = false;
zcashUrl: SafeUrl = '';
-
-
+ externalURL: string = '';
order:Order = {
- _id: '',
+ _id: '',
address: '',
session: '',
timestamp: '',
@@ -55,11 +56,12 @@ export class InvoiceComponent implements OnInit {
constructor(
private _ActiveRoute:ActivatedRoute,
private router: Router,
- private sanitizer: DomSanitizer,
+ private sanitizer: DomSanitizer,
public receiptService: ReceiptService,
- private notifierService : NotifierService
+ private notifierService : NotifierService
) {
this.orderId = this._ActiveRoute.snapshot.paramMap.get("orderId");
+ console.log('constructor - orderId -> ' + this.orderId);
this.orderUpdate = receiptService.orderUpdate;
this.nameUpdate = receiptService.nameUpdate;
receiptService.getOrderById(this.orderId!).subscribe(response => {
@@ -83,9 +85,11 @@ export class InvoiceComponent implements OnInit {
});
this.orderUpdate.subscribe(order => {
this.order = order;
- this.codeString = `zcash:${this.order.address}?amount=${this.order.totalZec.toFixed(8)}&memo=${URLSafeBase64.encode(Buffer.from('ZGo Order::'.concat(this.orderId!)))}`;
- this.zcashUrl = this.sanitizer.bypassSecurityTrustUrl(this.codeString);
-
+ if ( order.session.substring(0,1) == 'W') {
+ this.isWCOrder = true;
+ }
+ this.codeString = `zcash:${this.order.address}?amount=${this.order.totalZec.toFixed(8)}&memo=${URLSafeBase64.encode(Buffer.from('ZGo Order::'.concat(this.orderId!)))}`;
+ this.zcashUrl = this.sanitizer.bypassSecurityTrustUrl(this.codeString);
});
this.nameUpdate.subscribe(name => {
this.name = name;
@@ -93,6 +97,25 @@ export class InvoiceComponent implements OnInit {
}
ngOnInit(): void {
+ }
+
+ backToShop() {
+ if ( this.isWCOrder ) {
+// console.log('External Invoice -> ' + this.order.externalInvoice );
+ const b64URL:string = this.order.externalInvoice.substring(0,this.order.externalInvoice.indexOf("-"));
+// console.log('encodedURL -> ' + b64URL );
+ const shopURL: string = Buffer.from(b64URL, 'base64').toString();
+ const tmp_orderid = this.order.externalInvoice.substring(this.order.externalInvoice.indexOf('-')+1);
+ const wc_order_key = tmp_orderid.substring(tmp_orderid.indexOf('-')+1);
+ const wc_orderid = tmp_orderid.substring(0,tmp_orderid.indexOf('-'));
+// console.log('wc_order_id -> ' + wc_orderid);
+// console.log('wc_order_key -> ' + wc_order_key);
+// console.log('new URL -> ' + shopURL + '/checkout/order-received/' + wc_orderid + '/?key=' + wc_order_key);
+ if ( shopURL ) {
+// console.log('Opening URL....' + shopURL);
+ window.open( shopURL + '/checkout/order-received/' + wc_orderid + '/?key=' + wc_order_key,"_blank");
+ }
+ }
}
getIconStyle(order : Order) {
@@ -102,7 +125,7 @@ export class InvoiceComponent implements OnInit {
}
- copyAddress() {
+ copyAddress() {
if (!navigator.clipboard) {
// alert("Copy functionality not supported");
this.notifierService
@@ -115,8 +138,9 @@ export class InvoiceComponent implements OnInit {
.showNotification("Error copying address","Close","error");
// console.error("Error", err);
}
- }
- copyAmount() {
+ }
+
+ copyAmount() {
if (!navigator.clipboard) {
// alert("Copy functionality not supported");
this.notifierService
@@ -129,9 +153,9 @@ export class InvoiceComponent implements OnInit {
.showNotification("Error while copying ammount","Close","error");
// console.error("Error", err);
}
- }
+ }
- copyMemo() {
+ copyMemo() {
if (!navigator.clipboard) {
// alert("Copy functionality not supported");
this.notifierService
@@ -144,6 +168,6 @@ export class InvoiceComponent implements OnInit {
.showNotification("Error while copying Memo","Close","error");
// console.error("Error", err);
}
- }
+ }
}
diff --git a/src/app/settings/settings.component.css b/src/app/settings/settings.component.css
index 777aca3..2779c59 100644
--- a/src/app/settings/settings.component.css
+++ b/src/app/settings/settings.component.css
@@ -45,4 +45,15 @@
color: dodgerblue;
}
+.small {
+ font-size: 12px;
+ background: #dddddd;
+}
+.heading {
+ padding-top: 10px;
+}
+
+.toolbar {
+ padding: 12px;
+}
diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html
index f829bdc..f44700b 100644
--- a/src/app/settings/settings.component.html
+++ b/src/app/settings/settings.component.html
@@ -77,98 +77,187 @@
-
-
-
+
+
+
+
+
+
+
+
+ {{ linkMsg }}
+
+
+
+
+
+
+ Payment Service URL:
+ |
+ |
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+
+ Account Code
+
+
+
+
+
+
+
+
+
+
+
-
-
-
- {{ linkMsg }}
-
-
-
-
-
+
+
+
+
+
+
+
+
- Payment Service URL:
- |
- |
+ Owner: |
-
-
-
- |
-
-
-
-
- Account Code
-
-
-
+
+
+
+
+
+
+ |
+
+
+ Token: |
+
+
+
+
+
+
+ |
+
+
+
+
+
+ |
+
+
+ URL: |
+
+
+
+
+
+
+ |
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts
index bdbe35f..0ea9ee6 100644
--- a/src/app/settings/settings.component.ts
+++ b/src/app/settings/settings.component.ts
@@ -5,6 +5,7 @@ import { UntypedFormBuilder, Validators, UntypedFormGroup, FormControl } from '@
import { Observable } from 'rxjs';
import { Owner } from '../owner.model';
import { XeroService } from '../xero.service';
+import { WoocommerceService } from '../woocommerce.service';
import { NotifierService } from '../notifier.service';
import { faCopy } from '@fortawesome/free-solid-svg-icons';
@@ -56,6 +57,13 @@ export class SettingsComponent implements OnInit {
xeroLink: string = '';
localToken: string = '';
clientId: string = '';
+ wooOwner: string = '';
+ wooToken: string = '';
+ wooUrl: string = '';
+ wooOwnerUpdate: Observable;
+ wooTokenUpdate: Observable;
+ wooUrlUpdate: Observable;
+
clientIdUpdate: Observable;
accCodeUpdate: Observable;
linked2Xero : boolean = false;
@@ -65,6 +73,7 @@ export class SettingsComponent implements OnInit {
private notifierService : NotifierService,
private fb: UntypedFormBuilder,
public xeroService: XeroService,
+ public wooService: WoocommerceService,
private dialogRef: MatDialogRef,
@Inject(MAT_DIALOG_DATA) public data: Owner) {
this.useZats = data.zats;
@@ -102,6 +111,19 @@ export class SettingsComponent implements OnInit {
console.log("xeroAccCod -> [" + this.xeroAccCod + "]");
this.accCodForm.get('xAcc')!.setValue(this.xeroAccCod);
});
+ this.wooOwnerUpdate = wooService.ownerUpdate;
+ this.wooTokenUpdate = wooService.tokenUpdate;
+ this.wooUrlUpdate = wooService.siteurlUpdate;
+ wooService.getWooToken(this.owner._id!);
+ this.wooOwnerUpdate.subscribe(owData => {
+ this.wooOwner = owData;
+ });
+ this.wooTokenUpdate.subscribe(tkData => {
+ this.wooToken = tkData;
+ });
+ this.wooUrlUpdate.subscribe(uData => {
+ this.wooUrl = uData;
+ });
}
ngOnInit() {
@@ -128,7 +150,7 @@ export class SettingsComponent implements OnInit {
closeIntegration() {
if ( (this.xeroAccCod == '') && (this.linked2Xero) )
this.notifierService
- .showNotification("Payment confirmation disabled!!","Close",'warning');
+ .showNotification("Xero Payment confirmation disabled!!","Close",'warning');
this.dialogRef.close();
}
@@ -179,6 +201,45 @@ export class SettingsComponent implements OnInit {
}
}
+ copyWooOwner(){
+ try {
+ navigator.clipboard.writeText(this.wooOwner);
+ this.notifierService.showNotification("Owner ID copied to clipboard", "Close", "success");
+ } catch (err) {
+ this.notifierService.showNotification("Copying not available in your browser", "Close", "error");
+ }
+ }
+
+ copyWooToken(){
+ try {
+ navigator.clipboard.writeText(this.wooToken);
+ this.notifierService.showNotification("WooCommerce Token copied to clipboard", "Close", "success");
+ } catch (err) {
+ this.notifierService.showNotification("Copying not available in your browser", "Close", "error");
+ }
+ }
+
+ generateWooToken(){
+ this.wooService.createWooToken(this.owner._id!).subscribe(responseData => {
+ if (responseData.status == 202) {
+ this.notifierService.showNotification("WooCommerce Token generated!", "Close", "success");
+ this.wooService.getWooToken(this.owner._id!);
+ this.wooOwnerUpdate.subscribe(owData => {
+ this.wooOwner = owData;
+ });
+ this.wooTokenUpdate.subscribe(tkData => {
+ this.wooToken = tkData;
+ });
+ this.wooUrlUpdate.subscribe(uData => {
+ this.wooUrl = uData;
+ });
+ close();
+ } else {
+ this.notifierService.showNotification("WooCommerce Token generation failed.", "Close", "error");
+ }
+ });
+ }
+
saveAccCod() {
this.xeroAccCod = this.accCodForm.value.xAcc;
diff --git a/src/app/woocommerce.service.spec.ts b/src/app/woocommerce.service.spec.ts
new file mode 100644
index 0000000..500c1f1
--- /dev/null
+++ b/src/app/woocommerce.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { WoocommerceService } from './woocommerce.service';
+
+describe('WoocommerceService', () => {
+ let service: WoocommerceService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(WoocommerceService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/woocommerce.service.ts b/src/app/woocommerce.service.ts
new file mode 100644
index 0000000..a25c13d
--- /dev/null
+++ b/src/app/woocommerce.service.ts
@@ -0,0 +1,65 @@
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Observable } from 'rxjs';
+import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
+
+import { ConfigData } from './configdata';
+
+var Buffer = require('buffer/').Buffer;
+
+@Injectable({
+ providedIn: 'root'
+})
+export class WoocommerceService {
+ beUrl = ConfigData.Be_URL;
+ private reqHeaders: HttpHeaders;
+ private ownerId: string = '';
+ private token: string = '';
+ private siteurl: string = '';
+ private _ownerIdUpdated: BehaviorSubject = new BehaviorSubject(this.ownerId);
+ private _tokenUpdated: BehaviorSubject = new BehaviorSubject(this.token);
+ private _siteurlUpdated: BehaviorSubject = new BehaviorSubject(this.siteurl);
+ public readonly ownerUpdate: Observable = this._ownerIdUpdated.asObservable();
+ public readonly tokenUpdate: Observable = this._tokenUpdated.asObservable();
+ public readonly siteurlUpdate: Observable = this._siteurlUpdated.asObservable();
+
+ constructor(
+ private http: HttpClient
+ ) {
+ var auth = 'Basic ' + Buffer.from(ConfigData.UsrPwd).toString('base64');
+ this.reqHeaders = new HttpHeaders().set('Authorization', auth);
+ this._ownerIdUpdated.next(Object.assign({}, this).ownerId);
+ this._tokenUpdated.next(Object.assign({}, this).token);
+ this._siteurlUpdated.next(Object.assign({}, this).siteurl);
+ }
+
+ getWooToken(ownerId: string) {
+ const params = new HttpParams().append('ownerid', ownerId);
+ let obs = this.http.get<{ownerid: string, token: string, siteurl: string}>(this.beUrl + 'api/wootoken', {headers: this.reqHeaders, params: params, observe: 'response'});
+ obs.subscribe(tokenResponse => {
+ if (tokenResponse.status == 200) {
+ this.ownerId = tokenResponse.body!.ownerid;
+ this.token = tokenResponse.body!.token;
+ this.siteurl = tokenResponse.body!.siteurl;
+ this._ownerIdUpdated.next(Object.assign({}, this).ownerId);
+ this._tokenUpdated.next(Object.assign({}, this).token);
+ this._siteurlUpdated.next(Object.assign({}, this).siteurl);
+ } else {
+ console.log('No WooCommerce token found');
+ }
+ });
+ return obs;
+ }
+
+ createWooToken(ownerId: string) {
+ const params = new HttpParams().append('ownerid', ownerId);
+ let obs = this.http.post(this.beUrl+'api/wootoken', {}, {headers: this.reqHeaders, params: params, observe: 'response'});
+ obs.subscribe(responseData => {
+ if (responseData.status == 202) {
+ console.log('WooToken created.');
+ } else {
+ console.log('WooToken creation failed.');
+ }
+ });
+ return obs;
+ }
+}