-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ce0cf17
commit 6d0de1b
Showing
223 changed files
with
4,200 additions
and
27 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{{#if this.contextPanel.currentContextRegistry}} | ||
{{#let this.contextPanel.currentContext this.contextPanel.currentContextRegistry this.contextPanel.currentContextComponentArguments as |model registry dynamicArgs|}} | ||
{{component registry.component context=model dynamicArgs=dynamicArgs onPressCancel=this.contextPanel.clear options=this.contextPanel.contextOptions}} | ||
{{/let}} | ||
{{/if}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import Component from '@glimmer/component'; | ||
import { inject as service } from '@ember/service'; | ||
|
||
export default class ContextPanelComponent extends Component { | ||
@service contextPanel; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
<Overlay | ||
@onLoad={{this.setOverlayContext}} | ||
@position="right" | ||
@noBackdrop={{true}} | ||
@fullHeight={{true}} | ||
@isResizeble={{or this.isResizable @isResizable}} | ||
@width={{or this.width @width "600px"}} | ||
> | ||
<Overlay::Header @hideLeftSection={{true}} @actionsWrapperClass="flex-1 flex-col py-3" class="h-auto-i min-h-[127px]"> | ||
<div class="flex flex-row items-center justify-between w-full mb-4"> | ||
<div class="flex flex-1 space-x-2"> | ||
{{#if this.product.id}} | ||
<Button @type="default" @icon="id-card" @helpText="View product details" @onClick={{this.onViewDetails}} /> | ||
{{/if}} | ||
</div> | ||
<div class="flex flex-1 justify-end"> | ||
<div class="mr-2"> | ||
<Button @icon={{if this.product.id "save" "check"}} @type="primary" @text={{if this.product.id "Save Product" "Create Product"}} @onClick={{this.save}} /> | ||
</div> | ||
<Button @type="default" @icon="times" @helpText={{if this.product.id "Cancel edit product" "Cancel new product"}} @onClick={{this.onPressCancel}} /> | ||
</div> | ||
</div> | ||
<div class="flex flex-row justify-between w-full"> | ||
<div class="flex flex-col flex-1 w-3/4"> | ||
<div class="flex flex-row"> | ||
<div class="w-14"> | ||
<div class="w-12 h-12 flex items-center justify-start relative hover:bg-gray-100 transition-all rounded-lg overflow-hidden"> | ||
<img src={{this.product.photo_url}} alt={{this.product.name}} height="48" width="48" class="h-12 w-12 rounded-lg shadow-sm" /> | ||
<Attach::Tooltip @class="clean" @animation="scale" @placement="top"> | ||
<InputInfo @text={{this.product.public_id}} /> | ||
</Attach::Tooltip> | ||
<div class="absolute inset-0 flex items-center justify-center opacity-0 hover:opacity-100 transition-opacity bg-gray-600 bg-opacity-50 rounded-lg"> | ||
<UploadButton | ||
@name="photos" | ||
@accept="image/*" | ||
@onFileAdded={{this.onUploadNewPhoto}} | ||
@icon="upload" | ||
@hideButtonText={{true}} | ||
@labelClass="upload-avatar-label-overlay" | ||
class="w-12 btn-reset" | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="flex flex-col"> | ||
<h1 class="text-gray-900 dark:text-white text-2xl"> | ||
{{#if this.product.id}} | ||
{{this.product.name}} | ||
{{else}} | ||
{{#if this.product.name}} | ||
{{this.product.name}} | ||
{{else}} | ||
<span>New Product</span> | ||
{{/if}} | ||
{{/if}} | ||
</h1> | ||
<div class="-mt-1"> | ||
<div class="flex flex-row items-center"> | ||
<span class="text-sm dark:text-blue-400 text-blue-600">{{n-a this.product.title (smart-humanize this.product.type)}}</span> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="flex justify-end w-1/4"> | ||
<Badge @status={{this.product.status}} @type="info" @hideStatusDot={{true}} /> | ||
</div> | ||
</div> | ||
</Overlay::Header> | ||
|
||
<Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 pt-4" @increaseInnerBodyHeightBy={{700}} /> | ||
</Overlay> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
import Component from '@glimmer/component'; | ||
import { tracked } from '@glimmer/tracking'; | ||
import { inject as service } from '@ember/service'; | ||
import { action } from '@ember/object'; | ||
import contextComponentCallback from '../utils/context-component-callback'; | ||
import applyContextComponentArguments from '../utils/apply-context-component-arguments'; | ||
|
||
export default class ProductFormPanelComponent extends Component { | ||
/** | ||
* @service store | ||
*/ | ||
@service store; | ||
|
||
/** | ||
* @service fetch | ||
*/ | ||
@service fetch; | ||
|
||
/** | ||
* @service currentUser | ||
*/ | ||
@service currentUser; | ||
|
||
/** | ||
* @service notifications | ||
*/ | ||
@service notifications; | ||
|
||
/** | ||
* @service hostRouter | ||
*/ | ||
@service hostRouter; | ||
|
||
/** | ||
* @service loader | ||
*/ | ||
@service loader; | ||
|
||
/** | ||
* @service contextPanel | ||
*/ | ||
@service contextPanel; | ||
|
||
/** | ||
* Overlay context. | ||
* @type {any} | ||
*/ | ||
@tracked context; | ||
|
||
/** | ||
* Indicates whether the component is in a loading state. | ||
* @type {boolean} | ||
*/ | ||
@tracked isLoading = false; | ||
|
||
/** | ||
* All possible product types. | ||
* | ||
* @var {String} | ||
*/ | ||
@tracked productTypeOptions = ['product', 'customer']; | ||
|
||
/** | ||
* All possible product status options. | ||
* | ||
* @var {String} | ||
*/ | ||
@tracked productStatusOptions = ['pending', 'active', 'do-not-product', 'prospective', 'archived']; | ||
|
||
/** | ||
* Constructs the component and applies initial state. | ||
*/ | ||
constructor() { | ||
super(...arguments); | ||
this.product = this.args.product; | ||
applyContextComponentArguments(this); | ||
} | ||
|
||
/** | ||
* Sets the overlay context. | ||
* | ||
* @action | ||
* @param {OverlayContextObject} overlayContext | ||
*/ | ||
@action setOverlayContext(overlayContext) { | ||
this.context = overlayContext; | ||
contextComponentCallback(this, 'onLoad', ...arguments); | ||
} | ||
|
||
/** | ||
* Saves the product changes. | ||
* | ||
* @action | ||
* @returns {Promise<any>} | ||
*/ | ||
@action save() { | ||
const { product } = this; | ||
|
||
this.loader.showLoader('.next-content-overlay-panel-container', { loadingMessage: 'Saving product...', preserveTargetPosition: true }); | ||
this.isLoading = true; | ||
|
||
contextComponentCallback(this, 'onBeforeSave', product); | ||
|
||
try { | ||
return product | ||
.save() | ||
.then((product) => { | ||
this.notifications.success(`product (${product.name}) saved successfully.`); | ||
contextComponentCallback(this, 'onAfterSave', product); | ||
}) | ||
.catch((error) => { | ||
this.notifications.serverError(error); | ||
}) | ||
.finally(() => { | ||
this.loader.removeLoader('.next-content-overlay-panel-container '); | ||
this.isLoading = false; | ||
}); | ||
} catch (error) { | ||
this.loader.removeLoader('.next-content-overlay-panel-container '); | ||
this.isLoading = false; | ||
} | ||
} | ||
|
||
/** | ||
* Uploads a new photo for the driver. | ||
* | ||
* @param {File} file | ||
* @memberof DriverFormPanelComponent | ||
*/ | ||
@action onUploadNewPhoto(file) { | ||
this.fetch.uploadFile.perform( | ||
file, | ||
{ | ||
path: `uploads/${this.currentUser.companyId}/drivers/${this.product.id}`, | ||
subject_uuid: this.product.id, | ||
subject_type: `product`, | ||
type: `product_photo`, | ||
}, | ||
(uploadedFile) => { | ||
this.product.setProperties({ | ||
photo_uuid: uploadedFile.id, | ||
photo_url: uploadedFile.url, | ||
photo: uploadedFile, | ||
}); | ||
} | ||
); | ||
} | ||
|
||
/** | ||
* View the details of the product. | ||
* | ||
* @action | ||
*/ | ||
@action onViewDetails() { | ||
const isActionOverrided = contextComponentCallback(this, 'onViewDetails', this.product); | ||
|
||
if (!isActionOverrided) { | ||
this.contextPanel.focus(this.product, 'viewing'); | ||
} | ||
} | ||
|
||
/** | ||
* Handles cancel button press. | ||
* | ||
* @action | ||
* @returns {any} | ||
*/ | ||
@action onPressCancel() { | ||
return contextComponentCallback(this, 'onPressCancel', this.product); | ||
} | ||
|
||
/** | ||
* Uploads a file to the server for the product. | ||
* | ||
* @param {File} file | ||
*/ | ||
uploadProductPhoto(file) { | ||
this.fetch.uploadFile.perform( | ||
file, | ||
{ | ||
path: `uploads/${this.product.company_uuid}/products/${this.product.slug}`, | ||
subject_uuid: this.product.id, | ||
subject_type: 'product', | ||
type: 'product_photo', | ||
}, | ||
(uploadedFile) => { | ||
this.product.setProperties({ | ||
photo_uuid: uploadedFile.id, | ||
photo_url: uploadedFile.url, | ||
photo: uploadedFile, | ||
}); | ||
} | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<Overlay | ||
@onLoad={{this.setOverlayContext}} | ||
@position="right" | ||
@noBackdrop={{true}} | ||
@fullHeight={{true}} | ||
@isResizable={{or this.isResizable @isResizable}} | ||
@width={{or this.width @width "600px"}} | ||
> | ||
<Overlay::Header @hideLeftSection={{true}} @actionsWrapperClass="flex-1 flex-col py-3" class="h-auto-i min-h-[127px]"> | ||
<div class="flex flex-row items-center justify-between w-full mb-4"> | ||
<div class="flex flex-1 space-x-2"> | ||
<Button @type="default" @icon="pen" @helpText="Edit product" @onClick={{this.onEdit}} /> | ||
</div> | ||
<div class="flex flex-1 justify-end"> | ||
<Button @type="default" @icon="times" @helpText={{if this.product.id "Cancel edit product" "Cancel new product"}} @onClick={{this.onPressCancel}} /> | ||
</div> | ||
</div> | ||
<div class="flex flex-row justify-between w-full"> | ||
<div class="flex flex-col flex-1 w-3/4"> | ||
<div class="flex flex-row"> | ||
<div class="w-14 flex items-center justify-start"> | ||
<Image | ||
src={{this.product.photo_url}} | ||
@fallbackSrc={{config "defaultValues.productImage"}} | ||
alt={{this.product.name}} | ||
height="48" | ||
width="48" | ||
class="h-12 w-12 rounded-lg shadow-sm" | ||
/> | ||
<Attach::Tooltip @class="clean" @animation="scale" @placement="top"> | ||
<InputInfo @text={{this.product.public_id}} /> | ||
</Attach::Tooltip> | ||
</div> | ||
<div class="flex flex-col"> | ||
<h1 class="text-gray-900 dark:text-white text-2xl">{{this.product.name}}</h1> | ||
<div class="-mt-1"> | ||
<div class="flex flex-row items-center"> | ||
<span class="text-sm dark:text-blue-400 text-blue-600">{{smart-humanize this.product.type}}</span> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="flex justify-end w-1/4"> | ||
<Badge @status={{this.product.public_id}} @type="info" @hideStatusDot={{true}} /> | ||
</div> | ||
</div> | ||
</Overlay::Header> | ||
<Overlay::Body class="no-padding" @increaseInnerBodyHeightBy={{1000}}> | ||
<div class="section-header-actions w-full overflow-x-scroll lg:overflow-x-auto"> | ||
<div class="ui-tabs mt-4"> | ||
<nav> | ||
{{#each this.tabs as |tab|}} | ||
<a href="javascript:;" class="ui-tab {{if (eq this.tab.slug tab.slug) 'active'}}" {{on "click" (fn this.onTabChanged tab.slug)}}> | ||
<FaIcon @icon={{tab.icon}} class="mr-1" /> | ||
<span>{{tab.title}}</span> | ||
</a> | ||
{{/each}} | ||
</nav> | ||
</div> | ||
</div> | ||
<div class="tab-content tab-{{this.tab.slug}}"> | ||
{{component this.tab.component product=this.product tabOptions=this.tab options=this.tab.componentParams}} | ||
</div> | ||
</Overlay::Body> | ||
</Overlay> |
Oops, something went wrong.