Initial Commit on git.saherelm.ir ...

This commit is contained in:
2026-08-20 15:42:40 +03:30
commit fac270d301
779 changed files with 79360 additions and 0 deletions
@@ -0,0 +1,89 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XCardComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Sample -->
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<!-- Component -->
<x-card
[showHeader]="true"
[isInPage]="true"
[showFooter]="true"
[showContent]="true"
[showActions]="true"
[color]="ColorNames.Tertiary"
[title]="resourceProvider(ResourceIDs.app_name)"
[subTitle]="resourceProvider(ResourceIDs.company)"
>
<div header>
{{resourceProvider(ResourceIDs.header)}}
</div>
<div content>
{{resourceProvider(ResourceIDs.temp_label)}}
</div>
<div actions>
{{resourceProvider(ResourceIDs.actions)}}
</div>
<div footer>
{{resourceProvider(ResourceIDs.footer)}}
</div>
</x-card>
<x-markdown
[mode]="'preview'"
[content]="sample2"
[hasToolbar]="false"
[wrapWithCard]="true"
[isInPage]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<x-card
[showHeader]="true"
[isInPage]="true"
[showContent]="true"
[color]="ColorNames.Medium"
[imageUrl]="'/assets/image/logo.png'"
[avatarUrl]="'/assets/image/logo.png'"
[title]="resourceProvider(ResourceIDs.app_name)"
[subTitle]="resourceProvider(ResourceIDs.company)"
>
<div content>
{{resourceProvider(ResourceIDs.temp_label)}}
</div>
</x-card>
</v-page>
@@ -0,0 +1,3 @@
.content-container {
margin: 24px;
}
+135
View File
@@ -0,0 +1,135 @@
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, XColor, isNullOrEmptyString } from 'x-framework-core';
@Component({
selector: 'app-card',
templateUrl: './card.page.html',
styleUrls: ['./card.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class CardPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.card;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.card_description);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت نمایش یک جزء از اجزای تشکیل دهنده یک صفحه بکار میرود.
این مولفه می تواند بسته به ابعاد مختلف صفحه واکنش نشان دهد و خود را مطابق کند.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component use to present a part of a page.
this component can adapt itself based on screen size.
`;
//
readonly sample1 =
'```html' +
`
<x-card
[showHeader]="true"
[isPageCard]="true"
[showFooter]="true"
[showContent]="true"
[showActions]="true"
[color]="ColorNames.Tertiary"
[title]="resourceProvider(
ResourceIDs.app_name)"
[subTitle]="resourceProvider(
ResourceIDs.company)"
>
<div header>
{{resourceProvider(
ResourceIDs.header)}}
</div>
<div content>
{{resourceProvider(
ResourceIDs.temp_label)}}
</div>
<div actions>
{{resourceProvider(
ResourceIDs.actions)}}
</div>
<div footer>
{{resourceProvider(
ResourceIDs.footer)}}
</div>
</x-card>
` +
'```';
readonly sample2 =
'```html' +
`
<x-card
[showHeader]="true"
[isPageCard]="true"
[showContent]="true"
[color]="ColorNames.Medium"
[imageUrl]="
\'/assets/image/logo.png\'"
[avatarUrl]="
\'/assets/image/logo.png\'"
[title]="resourceProvider(
ResourceIDs.app_name)"
[subTitle]="resourceProvider(
ResourceIDs.company)"
>
<div content>
{{resourceProvider(
ResourceIDs.temp_label)}}
</div>
</x-card>
` +
'```';
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
}
@@ -0,0 +1,49 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XCounterComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- <x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown> -->
<!-- ColorPicker -->
<x-color-picker
[isInPage]="true"
[wrapWithCard]="true"
[selectedColor]="'#fff500'"
[showCopyToClipboard]="true"
[presetColors]="presetColors"
[outputFormat]="outputFormat"
[cursorColor]="'tertiary-tint'"
[presetColorsLable]="presetColorsLable"
[representColorFormats]="representFormats"
(colorSelected)="handleColorSelected($event)"
></x-color-picker>
</v-page>
@@ -0,0 +1,107 @@
import {
XColorPickerOutputFormat,
XColorPickerOutputFormatIdentifier,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XColor, XResourceIDs, isNullOrEmptyString } from 'x-framework-core';
@Component({
selector: 'app-color-picker',
templateUrl: './color-picker.page.html',
styleUrls: ['./color-picker.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class ColorPickerPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.color_picker;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(
AppResourceIDs.color_picker_description
);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
`;
readonly contentEn = `
# ${this.toolbarTitle}
`;
//
readonly sample1 =
'```html' +
`
` +
'```';
//
readonly presetColorsLable = 'PresetColors';
//
readonly presetColors = [
'#fff',
'#000',
'#2889e9',
'#e920e9',
'#fff500',
'rgb(236,64,64)',
];
readonly outputFormat = XColorPickerOutputFormat.XHEX;
readonly representFormats: XColorPickerOutputFormatIdentifier[] = [
XColorPickerOutputFormat.XHEX,
XColorPickerOutputFormat.XRGBA,
// XColorPickerOutputFormat.XHSLA,
];
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//#endregion
handleColorSelected(color: string) {
console.log('Color Selected From ColorPicker Component: ', color);
}
}
@@ -0,0 +1,171 @@
import { NgModule } from '@angular/core';
import { FabPage } from './fab/fab.page';
import { MapPage } from './map/map.page';
import { FormPage } from './form/form.page';
import { GridPage } from './grid/grid.page';
import { ListPage } from './list/list.page';
import { IconPage } from './icon/icon.page';
import { CardPage } from './card/card.page';
import { PagePage } from './page/page.page';
import { TabsPage } from './tabs/tabs.page';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { TablePage } from './table/table.page';
import { SliderPage } from './slider/slider.page';
import { CounterPage } from './counter/counter.page';
import { StepperPage } from './stepper/stepper.page';
import { MarkdownPage } from './markdown/markdown.page';
import { ViewsModule } from 'src/app/views/views.module';
import { ColorPickerPage } from './color-picker/color-picker.page';
import { IntroductionPage } from './introduction/introduction.page';
import { TabNavigatorPage } from './tab-navigator/tab-navigator.page';
import { BaseRoutes, ComponentsRoutes } from 'src/app/config/page.config';
import { FileComponentsPage } from './file-components/file-components.page';
import { ExpandableListPage } from './expandable-list/expandable-list.page';
import { ModelPresenterPage } from './model-presenter/model-presenter.page';
import { DescriptionListPage } from './description-list/description-list.page';
import { SmallComponentsPage } from './small-components/small-components.page';
import { ExpandablePanelPage } from './expandable-panel/expandable-panel.page';
import { SampleModalComponent } from './small-components/sample-modal/sample-modal.component';
import { TreePage } from './tree/tree.page';
@NgModule({
imports: [
ViewsModule,
CommonModule,
RouterModule.forChild([
{
path: BaseRoutes.Default,
redirectTo: ComponentsRoutes.Introduction,
pathMatch: 'full',
},
{
path: ComponentsRoutes.Introduction,
component: IntroductionPage,
},
{
path: ComponentsRoutes.SmallComponents,
component: SmallComponentsPage,
},
{
path: ComponentsRoutes.Card,
component: CardPage,
},
{
path: ComponentsRoutes.Icon,
component: IconPage,
},
{
path: ComponentsRoutes.Counter,
component: CounterPage,
},
{
path: ComponentsRoutes.ColorPicker,
component: ColorPickerPage,
},
{
path: ComponentsRoutes.Fab,
component: FabPage,
},
{
path: ComponentsRoutes.FileComponents,
component: FileComponentsPage,
},
{
path: ComponentsRoutes.Form,
component: FormPage,
},
{
path: ComponentsRoutes.Grid,
component: GridPage,
},
{
path: ComponentsRoutes.List,
component: ListPage,
},
{
path: ComponentsRoutes.Map,
component: MapPage,
},
{
path: ComponentsRoutes.MarkDown,
component: MarkdownPage,
},
{
path: ComponentsRoutes.Tree,
component: TreePage,
},
{
path: ComponentsRoutes.DescriptionList,
component: DescriptionListPage,
},
{
path: ComponentsRoutes.ExpandableList,
component: ExpandableListPage,
},
{
path: ComponentsRoutes.ExpandablePanel,
component: ExpandablePanelPage,
},
{
path: ComponentsRoutes.ModelPresenter,
component: ModelPresenterPage,
},
{
path: ComponentsRoutes.Slider,
component: SliderPage,
},
{
path: ComponentsRoutes.Stepper,
component: StepperPage,
},
{
path: ComponentsRoutes.Tabs,
component: TabsPage,
},
{
path: ComponentsRoutes.Table,
component: TablePage,
},
{
path: ComponentsRoutes.Page,
component: PagePage,
},
{
path: ComponentsRoutes.TabNavigator,
component: TabNavigatorPage,
},
]),
],
declarations: [
FabPage,
MapPage,
CardPage,
IconPage,
FormPage,
GridPage,
PagePage,
ListPage,
TabsPage,
TreePage,
TablePage,
SliderPage,
StepperPage,
CounterPage,
MarkdownPage,
ColorPickerPage,
IntroductionPage,
TabNavigatorPage,
ExpandableListPage,
FileComponentsPage,
ModelPresenterPage,
SmallComponentsPage,
ExpandablePanelPage,
DescriptionListPage,
//
SampleModalComponent,
],
entryComponents: [SampleModalComponent],
})
export class ComponentsPageModule {}
@@ -0,0 +1,108 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XCounterComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample2"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
></x-markdown>
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample3"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
></x-markdown>
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample4"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
></x-markdown>
<!-- Counter -->
<x-counter
#counter
[stopValue]="0"
[isInPage]="true"
[startValue]="180"
[autoStart]="true"
[currentValue]="150"
[wrapWithCard]="true"
[cardShowActions]="true"
[cssClass]="'ion-text-center'"
[type]="CounterTypes.CountDown"
[displayPattern]="getCounterMessage"
(counterStop)="handleCounterStop($event)"
(counterTtick)="handleCounterTick($event)"
(counterStart)="handleCounterStart($event)"
>
<div actions>
<x-slotter [layout]="SlotLayout.HORIZONTAL">
<x-slot [name]="SlotNames.START" [cssClass]="'ion-text-start'">
<x-button
(clicked)="counter.start()"
[title]="ResourceIDs.start"
[color]="ColorNames.Tertiary"
></x-button>
</x-slot>
<x-slot [name]="SlotNames.CENTER" [cssClass]="'ion-text-center'">
<x-button
(clicked)="counter.pause()"
[title]="ResourceIDs.pause"
[color]="ColorNames.Warning"
></x-button>
</x-slot>
<x-slot [name]="SlotNames.END" [cssClass]="'ion-text-end'">
<x-button
[title]="ResourceIDs.reset"
[color]="ColorNames.Danger"
(clicked)="counter.startValue = 180; counter.stopValue= 0; counter.currentValue = 0; counter.start()"
></x-button>
</x-slot>
</x-slotter>
</div>
</x-counter>
</v-page>
@@ -0,0 +1,3 @@
.content-container {
margin: 24px;
}
@@ -0,0 +1,193 @@
import {
XColor,
toTimeFormat,
XResourceIDs,
toPersianNumbers,
isNullOrEmptyString,
} from 'x-framework-core';
import {
XSlotName,
XSlotLayout,
XCounterType,
XCounterTick,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
@Component({
selector: 'app-counter',
templateUrl: './counter.page.html',
styleUrls: ['./counter.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class CounterPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.counter;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.counter_description);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
// Counter Types ...
readonly CounterTypes = Object.assign({}, XCounterType);
//
// Slotter ...
readonly SlotNames = Object.assign({}, XSlotName);
readonly SlotLayout = Object.assign({}, XSlotLayout);
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه در مواردی که قصد داریم مدت زمان معینی را برای ادامه یا انجام کاری در نظر بگیریم مورد استفاده قرار می گیرد.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used when we need to wait specific time for continue or doing an action.
`;
//
readonly sample1 =
'```html' +
`
<x-counter
#counter
[stopValue]="0"
[startValue]="180"
[currentValue]="150"
[type]="CounterTypes
.CountDown"
[displayPattern]="
getCounterMessage"
(counterStop)="
handleCounterStop($event)"
(counterTtick)="
handleCounterTick($event)"
(counterStart)="
handleCounterStart($event)"
></x-counter>
` +
'```';
//
readonly sample2 =
'```html' +
`
<x-button
(click)="counter.start()"
[title]="ResourceIDs.start"
[color]="ColorNames.Tertiary"
></x-button>
` +
'```';
//
readonly sample3 =
'```html' +
`
<x-button
(click)="counter.pause()"
[title]="ResourceIDs.pause"
[color]="ColorNames.Warning"
></x-button>
` +
'```';
//
readonly sample4 =
'```html' +
`
<x-button
[title]="ResourceIDs.reset"
[color]="ColorNames.Danger"
(click)="
counter.startValue = 180;
counter.stopValue= 0;
counter.currentValue = 0;
counter.start()"
></x-button>
` +
'```';
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
getCounterMessage(start: number, stop: number, current: number): string {
//
let steps = stop - start;
if (steps < 0) {
steps *= -1;
}
//
const ellapsed = steps - current;
const remained = steps - ellapsed;
//
const minutes = Math.trunc(remained / 60);
const seconds = remained - minutes * 60;
//
const message = `${toTimeFormat(minutes)}:${toTimeFormat(seconds)}`;
//
const locale = this.managerService.currentLocale;
//
if (locale === 'fa-IR') {
return toPersianNumbers(message);
} else {
return message;
}
}
//#endregion
//
//#region UI Handlers ...
handleCounterStop(event: XCounterTick) {}
handleCounterStart(event: XCounterTick) {}
handleCounterTick(event: XCounterTick) {}
//#endregion
}
@@ -0,0 +1,45 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XDescriptionListComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Sample -->
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<!-- Component -->
<x-description-list
[model]="item"
[isInPage]="true"
[isLegacy]="true"
[wrapWithCard]="true"
></x-description-list>
<!-- [hiddenModelKeys]="['gender', 'mobile']" -->
</v-page>
@@ -0,0 +1,3 @@
.content-container {
margin: 24px;
}
@@ -0,0 +1,100 @@
import { Component } from '@angular/core';
import { XResourceIDs, isNullOrEmptyString } from 'x-framework-core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
export interface ItemType {
first_name: string;
last_name: string;
gender: string;
mobile: string;
email: string;
}
@Component({
selector: 'app-description-list',
templateUrl: './description-list.page.html',
styleUrls: ['./description-list.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class DescriptionListPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.description_list;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(
AppResourceIDs.description_list_description
);
toolbarShowSubTitle = true;
//#endregion
//
item: ItemType = {
first_name: 'Hadi',
last_name: 'Khazaee Asl',
gender: 'male',
mobile: '09121694056',
email: 'hadi_khazaee_asl@yahoo.com',
};
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت نمایش یک مدل داده ای در غالبی ساختار یافته بکار میرود
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used to show a data model in an structural template
`;
//
readonly sample1 =
'```html' +
`
<x-description-list
[model]="item"
[isInPage]="true"
[wrapWithCard]="true"
[hiddenModelKeys]="['gender', 'mobile']"
>
</x-description-list>
` +
'```';
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
}
@@ -0,0 +1,64 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XExpandableListComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample2"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
></x-markdown>
<x-expandable-list
[isInPage]="true"
[items]="listItems"
[wrapWithCard]="true"
[closeSiblings]="true"
[supportRouting]="false"
[showChildDetailIcon]="true"
[showParentDetailIcon]="true"
[startupState]="'expand-all'"
[disableParentRouting]="false"
[dividerColor]="ColorNames.Danger"
[childColor]="ColorNames.Secondary"
[parentColor]="ColorNames.Tertiary"
[highlightColor]="ColorNames.Success"
[parentActiveColor]="ColorNames.Danger"
[childActiveColor]="ColorNames.Warning"
(itemSelected)="handleItemSelected($event)"
>
</x-expandable-list>
</v-page>
@@ -0,0 +1,173 @@
import {
XColor,
random,
XResourceIDs,
isNullOrEmptyString,
} from 'x-framework-core';
import { Component } from '@angular/core';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { XIconNames, XExpandableListItem } from 'x-framework-components';
@Component({
selector: 'app-expandable-list',
templateUrl: './expandable-list.page.html',
styleUrls: ['./expandable-list.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class ExpandableListPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.expandable_list;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(
AppResourceIDs.expandable_list_description
);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
tempList = Array.from(Array(5).keys());
tempChilds = Array.from(Array(2).keys());
listItems: XExpandableListItem<string>[] = this.tempList.map((i) => {
//
const li: XExpandableListItem<string> = {
...this.toListItem(i),
childs:
random(0, 1) === 0
? undefined
: this.tempChilds.map((c) => {
//
const cLi: XExpandableListItem<string> = {
...this.toListItem(c, i.toString()),
};
//
return cLi;
}),
};
//
return li;
});
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
از این مولفه در مواقعی استفاده می شود که قصد داریم مجموعه هایی از اطلاعات را در گروه های مختلف دسته بندی کرده و نمایش دهیم.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used to show a collection of data sets in a grouped structure.
`;
//
readonly sample1 =
'```html' +
`
<x-expandable-list
[items]="listItems"
[closeSiblings]="true"
[supportRouting]="false"
[showChildDetailIcon]="true"
[showParentDetailIcon]="true"
[startupState]="'expand-all'"
[disableParentRouting]="false"
[dividerColor]="ColorNames.Danger"
[childColor]="ColorNames.Secondary"
[parentColor]="ColorNames.Tertiary"
[highlightColor]="ColorNames.Success"
[parentActiveColor]="ColorNames.Danger"
[childActiveColor]="ColorNames.Warning"
(itemSelected)="handleItemSelected($event)"
>
</x-expandable-list>
` +
'```';
//
readonly sample2 =
'```typescript' +
`
async handleItemSelected(item: XExpandableListItem<any>) {
//
if (!item) {
return;
}
//
await this.managerService.notificationService.presentSuccessNotification({
message: \`item \${item.id} Selected ...\`,
dissmissable: true,
});
}
` +
'```';
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//#endregion
async handleItemSelected(item: XExpandableListItem<any>) {
//
if (!item) {
return;
}
//
await this.managerService.notificationService.presentSuccessNotification({
message: `item ${item.id} Selected ...`,
dissmissable: true,
});
}
private toListItem(data: any, prefix?: string) {
return {
id: `${prefix ? prefix + '_' : ''}${data}`,
data: `Item ${prefix ? prefix + '_' : ''}${data}`,
opened: random(0, 1) === 0 ? true : false,
title: `Title ${prefix ? prefix + '_' : ''}${data}`,
description: `Description ${prefix ? prefix + '_' : ''}${data}`,
} as XExpandableListItem<any>;
}
}
@@ -0,0 +1,93 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/modules/XExpandablePanelModule.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Sample -->
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
>
</x-markdown>
<!-- Component -->
<x-expandable-panel
[isInPage]="true"
[isAccordion]="true"
[selected]="'First'"
[wrapWithCard]="true"
[headerColor]="ColorNames.Tertiary"
[hideDescriptionOnSmallScreens]="false"
[headerHighlightColor]="ColorNames.Warning"
>
<x-panel [id]="'First'" [hasNext]="true" [hasCustomActions]="true">
<div x-panel-title>
Title 1
</div>
<div x-panel-description>
Description 1
</div>
Content 1
<div actions>
Custom Actions 1
</div>
</x-panel>
<x-panel
[id]="'Second'"
[hasNext]="true"
[hasPrev]="true"
[hasReset]="true"
>
<div x-panel-title>
Title 2
</div>
<div x-panel-description>
Description 2
</div>
Content 2
</x-panel>
<x-panel [id]="'Third'" [hasPrev]="true" [hasReset]="true">
<div x-panel-title>
Title 3
</div>
<div x-panel-description>
Description 3
</div>
Content 3
</x-panel>
</x-expandable-panel>
</v-page>
@@ -0,0 +1,130 @@
import { Component } from '@angular/core';
import { XIconNames } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, isNullOrEmptyString, XColor } from 'x-framework-core';
@Component({
selector: 'app-expandable-panel',
templateUrl: './expandable-panel.page.html',
styleUrls: ['./expandable-panel.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class ExpandablePanelPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.expandable_panel;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(
AppResourceIDs.expandable_panel_description
);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت گروه بندی محتوای قابل ارائه در یک نمایه بکار می رود.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used to Grouped representable contents in a View.
`;
//
readonly sample1 =
'```html' +
`
<x-expandable-panel
[isAccordion]="true"
[selected]="'First'"
[headerColor]="ColorNames.Tertiary"
[headerHighlightColor]="ColorNames.Warning"
>
<x-panel [id]="'First'" [hasNext]="true" [hasCustomActions]="true">
<div x-panel-title>
Title 1
</div>
<div x-panel-description>
Description 1
</div>
Content 1
<div actions>
Custom Actions 1
</div>
</x-panel>
<x-panel [id]="'Second'" [hasNext]="true" [hasPrev]="true" [hasReset]="true">
<div x-panel-title>
Title 2
</div>
<div x-panel-description>
Description 2
</div>
Content 2
</x-panel>
<x-panel [id]="'Third'" [hasPrev]="true" [hasReset]="true">
<div x-panel-title>
Title 3
</div>
<div x-panel-description>
Description 3
</div>
Content 3
</x-panel>
</x-expandable-panel>
` +
'```';
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//#endregion
}
+187
View File
@@ -0,0 +1,187 @@
<v-page
[actions]="actions"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XFabComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<x-card
[isInPage]="true"
[showHeader]="true"
[showActions]="true"
[color]="ColorNames.Light"
[title]="resourceProvider(ResourceIDs.sample)"
>
<x-markdown
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[cssClass]="'code-block'"
></x-markdown>
<x-markdown
[mode]="'preview'"
[content]="sample2"
[hasToolbar]="false"
[cssClass]="'code-block'"
></x-markdown>
</x-card>
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<x-fab
[item]="{
id: 'fab_1',
fixed: true,
icon: IconNames.menu_vertical,
size: FabButtonSizes.REGULAR,
color: ColorNames.Tertiary,
vertical: FabVerticalSlots.CENTER,
horizontal: FabHorizontalSlots.CENTER,
childs: [
{
id: 'fab_child_1',
index: 0,
icon: IconNames.phone,
side: FabButtonSides.TOP,
size: FabButtonSizes.MINI,
color: ColorNames.Success,
tooltip: ResourceIDs.temp_label,
handler: fabHandler
},
{
id: 'fab_child_2',
index: 1,
icon: IconNames.mail,
side: FabButtonSides.BOTTOM,
size: FabButtonSizes.MINI,
color: ColorNames.Primary,
tooltip: ResourceIDs.temp_label,
handler: fabHandler
},
{
id: 'fab_child_3',
index: 2,
icon: IconNames.share,
side: FabButtonSides.START,
size: FabButtonSizes.MINI,
color: ColorNames.Medium,
tooltip: ResourceIDs.temp_label,
handler: fabHandler
},
{
id: 'fab_child_3_1',
index: 3,
icon: IconNames.avatars,
side: FabButtonSides.START,
size: FabButtonSizes.MINI,
color: ColorNames.Secondary,
tooltip: ResourceIDs.temp_label,
handler: fabHandler
},
{
id: 'fab_child_4',
index: 4,
icon: IconNames.web,
side: FabButtonSides.END,
size: FabButtonSizes.MINI,
color: ColorNames.Danger,
tooltip: ResourceIDs.temp_label,
handler: fabHandler
}
]
}"
></x-fab>
</x-card>
<!-- Descriptions -->
<x-card
[isInPage]="true"
[showActions]="true"
[showHeader]="true"
[color]="ColorNames.Light"
[title]="resourceProvider(ResourceIDs.descriptions)"
>
<!-- Descriptions -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('descriptions')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="./assets/docs/x-framework-components/components/XPageComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Cards -->
<ng-container *ngFor="let id of ids">
<ng-container
*ngTemplateOutlet="contentRef; context: {$implicit: id}"
></ng-container>
</ng-container>
</v-page>
<!-- Template Content -->
<ng-template #contentRef let-id>
<x-card
[showHeader]="true"
[isInPage]="true"
[showActions]="true"
[title]="'Title ' + id"
[subTitle]="'SubTitle ' + id"
class="v-card v-no-marigin-card"
[avatarUrl]="'/assets/icon/favicon.png'"
>
<!-- Content -->
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quisquam
inventore, optio obcaecati, harum temporibus accusamus voluptatem,
sapiente corporis expedita ipsum quos enim odio adipisci! At praesentium
hic quaerat ad mollitia.
</p>
<!-- Actions -->
<div actions>
<!-- Like -->
<x-button [type]="ButtonTypes.Icon">
<x-icon [name]="IconNames.liked" [color]="ColorNames.Danger"></x-icon>
</x-button>
<!-- Share -->
<x-button [type]="ButtonTypes.Icon">
<x-icon [name]="IconNames.share" [color]="ColorNames.Tertiary"></x-icon>
</x-button>
</div>
</x-card>
</ng-template>
+229
View File
@@ -0,0 +1,229 @@
import {
XFabItem,
XIconNames,
XButtonType,
XFabButtonSize,
XFabButtonSide,
XFabVerticalSlot,
XFabHorizontalSlot,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, XColor, isNullOrEmptyString } from 'x-framework-core';
@Component({
selector: 'app-fab',
templateUrl: './fab.page.html',
styleUrls: ['./fab.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class FabPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
toolbarShowSubTitle = true;
titleRes = AppResourceIDs.fab;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.fab_description);
//
ids = Array.from(Array(25).keys());
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
readonly ButtonTypes = Object.assign({}, XButtonType);
//
readonly FabButtonSizes = Object.assign({}, XFabButtonSize);
readonly FabButtonSides = Object.assign({}, XFabButtonSide);
readonly FabVerticalSlots = Object.assign({}, XFabVerticalSlot);
readonly FabHorizontalSlots = Object.assign({}, XFabHorizontalSlot);
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت ارائه مجموعه ای از فعالیت های مرتبط با یکدیگر در موارد لزوم مورد استفاده قرار می گیرد.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this components usually used for present a group of related actions together in where we want.
`;
//
readonly sample1 =
'```html' +
`
<x-fab
[item]="{
id: 'fab_1',
fixed: true,
icon: IconNames.menu_vertical,
size: FabButtonSizes.REGULAR,
color: ColorNames.Tertiary,
vertical: FabVerticalSlots.CENTER,
horizontal: FabHorizontalSlots.CENTER,
childs: [
{
id: 'fab_child_1',
index: 0,
icon: IconNames.phone,
side: FabButtonSides.TOP,
size: FabButtonSizes.MINI,
color: ColorNames.Success,
tooltip: ResourceIDs.temp_label,
handler: fabHandler
},
{
id: 'fab_child_2',
index: 1,
icon: IconNames.mail,
side: FabButtonSides.BOTTOM,
size: FabButtonSizes.MINI,
color: ColorNames.Primary,
tooltip: ResourceIDs.temp_label,
handler: fabHandler
},
{
id: 'fab_child_3',
index: 2,
icon: IconNames.share,
side: FabButtonSides.START,
size: FabButtonSizes.MINI,
color: ColorNames.Medium,
tooltip: ResourceIDs.temp_label,
handler: fabHandler
},
{
id: 'fab_child_3_1',
index: 3,
icon: IconNames.avatars,
side: FabButtonSides.START,
size: FabButtonSizes.MINI,
color: ColorNames.Secondary,
tooltip: ResourceIDs.temp_label,
handler: fabHandler
},
{
id: 'fab_child_4',
index: 4,
icon: IconNames.web,
side: FabButtonSides.END,
size: FabButtonSizes.MINI,
color: ColorNames.Danger,
tooltip: ResourceIDs.temp_label,
handler: fabHandler
}
]
}"
></x-fab>
` +
'```';
//
readonly sample2 =
'```typescript' +
`
fabHandler = async (id?: string) => {
await this.handleNotifyFab(id);
};
` +
'```';
//
readonly descriptionsFa = `
در ادامه نمونه ای از بکارگیری دکمه های شناور ارائه می گردد که در مولفه صفحه و بعنوان یکی از اجزاء آن ارائه شده است.
برای آشنایی بیشتر می توانید به مستندات مولفه صفحه مراجعه کنید.
`;
readonly descriptionsEn = `
in the following example you will see an implementation of Fab component which provides as a part of Page component.
for more information you can see Page component documentations.
`;
//
actions: XFabItem = {
//
id: 'edit_profile',
//
fixed: true,
//
color: XColor.Warning,
//
icon: XIconNames.edit,
//
tooltip: AppResourceIDs.temp_label,
//
vertical: XFabVerticalSlot.BOTTOM,
horizontal: XFabHorizontalSlot.END,
//
disabled: this.uiDisabled,
//
handler: async (id?: string) => {
await this.handleNotifyFab(id);
},
};
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
fabHandler = async (id?: string) => {
await this.handleNotifyFab(id);
};
//#endregion
//
//#region UI Handlers ...
async handleNotifyFab(id?: string) {
await this.managerService.notificationService.presentInfoNotification({
message: `Clicked Fab Id: ${id}`,
dissmissable: true,
});
}
//#endregion
}
@@ -0,0 +1,290 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[wrapWithCard]="true"
[isInPage]="true"
[content]="getContent('content')"
></x-markdown>
<!-- Expandable Panel -->
<x-expandable-panel
[isInPage]="true"
[isAccordion]="true"
[wrapWithCard]="true"
[selected]="'thumbnail'"
[headerColor]="ColorNames.Tertiary"
[headerHighlightColor]="ColorNames.Dark"
>
<!-- Thumbnail -->
<x-panel [id]="'thumbnail'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>
{{ resourceProvider(ResourceIDs.thumbnail_component) }}
</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.thumbnail_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('thumbnailContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="thumbnailSample1"
></x-markdown>
<x-thumbnail [identifier]="fileUrl" [type]="ThumbnailTypes.CUSTOM">
</x-thumbnail>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="thumbnailSample2"
></x-markdown>
<x-thumbnail [identifier]="fileUrl" [type]="ThumbnailTypes.GENERAL">
</x-thumbnail>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XThumbnailComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- File Drop Area -->
<x-panel [id]="'file_drop_area'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>
{{ resourceProvider(ResourceIDs.file_drop_area) }}
</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.file_drop_area_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('fileDropAreaContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="fileDropAreaSample1"
></x-markdown>
<!-- File Drop Area -->
<x-file-drop-area
[supportsMultipleFiles]="true"
(filesChangeEmiter)="handleFilesChanged($event)"
></x-file-drop-area>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XFileDropAreaComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- Image Cropper -->
<x-panel [id]="'iamge_cropper'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.image_cropper) }}</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.image_cropper_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('imageCropperContent')"
></x-markdown>
<!--
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="imageCropperSample1"
></x-markdown>
-->
<!-- <div class="container"> -->
<!-- File Upload Input -->
<!-- <input
hidden
#fileInput
type="file"
multiple="false"
(change)="handleFilesSelected()"
[disabled]="isLoading || uiDisabled"
/>
<x-button
(click)="selectFile()"
[type]="ButtonTypes.Raised"
[color]="ColorNames.Primary"
[title]="resourceProvider(ResourceIDs.select) + ' ' + resourceProvider(ResourceIDs.avatar)"
>
</x-button> -->
<!-- Wrapper of Thumbnail -->
<!-- <div *ngIf="file" class="thumbnail-wrapper">
<x-slotter
[hasCenterSlot]="false"
[layout]="SlotLayout.HORIZONTAL"
[startTopSlotCssClass]="'ion-text-start'"
[endBottomSlotCssClass]="['ion-text-center']"
>
<x-slot [name]="SlotNames.START">
<div>
<x-thumbnail
class="x-thumb"
[identifier]="file"
[loading]="isLoading"
[cssClass]="'thumbnail'"
[uiDisabled]="uiDisabled"
[type]="ThumbnailTypes.CUSTOM"
>
</x-thumbnail>
</div>
</x-slot>
<x-slot [name]="SlotNames.END">
<div class="avatar-actions ion-text-end">
<div>
<x-button
*ngIf="croppableImage()"
[type]="ButtonTypes.Icon"
(click)="handleLoadCropper()"
[color]="ColorNames.Secondary"
[matTooltip]="resourceProvider(ResourceIDs.crop)"
>
<x-icon [name]="IconNames.crop"></x-icon>
</x-button>
<x-button
[type]="ButtonTypes.Icon"
(click)="handleClearFile()"
[color]="ColorNames.Warning"
[matTooltip]="resourceProvider(ResourceIDs.clear)"
>
<x-icon
[name]="IconNames.clear"
[color]="ColorNames.Light"
></x-icon>
</x-button>
</div>
</div>
</x-slot>
</x-slotter>
</div> -->
<!-- </div> -->
<x-avatar-upload
[showFileDropArea]="true"
[color]="ColorNames.Dark"
[fileDropAreaColor]="ColorNames.Dark"
placeHolderAvatar="/assets/image/default-user-image.png"
>
</x-avatar-upload>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/modules/XImageCropperModule.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- File Upload -->
<x-panel [id]="'file_upload'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.file_upload) }}</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.file_upload_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('fileUploadContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="fileUploadSample1"
></x-markdown>
<!-- Sample -->
<x-file-upload
[showEmpty]="true"
[color]="'dark-tint'"
[showActionBar]="true"
[listShowToolbar]="true"
[emptyHasRefresh]="false"
[listEnableReordering]="true"
[emptyColor]="ColorNames.Dark"
[fileDropAreaColor]="'dark-tint'"
[actionBarColor]="ColorNames.Dark"
[searchBarColor]="ColorNames.Dark"
[emptyMessageColor]="ColorNames.Dark"
[emptyForegroundMessageColor]="false"
(fileChange)="handleFileChanged($event)"
[maxAllowedSize]="config.maxAllowedSize"
[maxAllowedFiles]="config.maxUploadFiles"
[showFileDropArea]="isNotMobileUi$ | async"
[searchBarSearchInputColor]="ColorNames.Dark"
[minAllowedFileSize]="config.minAllowedFileSize"
[maxAllowedFileSize]="config.maxAllowedFileSize"
(actionBarActionFired)="handleActionFired($event)"
></x-file-upload>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/modules/XFileUploadModule.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
</x-expandable-panel>
</v-page>
@@ -0,0 +1,56 @@
//
$size: 32px !important;
$thumbSize: 64px !important;
.thumbnail-wrapper {
margin-top: 6px;
height: $thumbSize;
}
x-thumbnail {
--thumbnail-size: #{$size};
}
// :host ::ng-deep .thumbnail,
// :host ::ng-deep .x-item {
// width: $size;
// min-width: $size;
// max-width: $size;
// height: $size;
// min-height: $size;
// max-height: $size;
// }
:host ::ng-deep .thumbnail {
img {
border-radius: 50% !important;
}
}
.avatar-actions {
//
@extend .thumbnail-wrapper;
//
display: flex;
align-items: center;
flex-direction: row;
//
* {
flex: auto;
margin: {
top: auto;
bottom: auto;
}
//
* {
margin: {
left: 3px;
right: 3px;
}
}
}
}
@@ -0,0 +1,654 @@
import {
Inject,
NgZone,
Component,
ViewChild,
Renderer2,
ElementRef,
ChangeDetectorRef,
} from '@angular/core';
import {
XColor,
toArray,
isArray,
hasChild,
getArrayOf,
XResourceIDs,
XExceptionIDs,
isExtensionOk,
XDialogResult,
XOneOrManyType,
getImageDimensions,
isNullOrEmptyString,
} from 'x-framework-core';
import {
XSlotName,
XIconNames,
XSlotLayout,
XFileStatus,
XButtonType,
XThumbnailType,
XPageContainer,
XPopoverService,
XImageCropperService,
XActionBarActionFiredModel,
} from 'x-framework-components';
import { MenuController } from '@ionic/angular';
import { X_CONFIG } from 'src/app/config/x-config';
import { XConfig } from 'src/app/config/app-config';
import { ViewportRuler } from '@angular/cdk/overlay';
import { XManagerService } from 'x-framework-services';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
@Component({
selector: 'app-file-components',
templateUrl: './file-components.page.html',
styleUrls: ['./file-components.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class FileComponentsPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.file_components;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(
AppResourceIDs.file_components_description
);
toolbarShowSubTitle = true;
//#endregion
//
//#region image cropper props ...
readonly SlotNames = Object.assign({}, XSlotName);
readonly SlotLayout = Object.assign({}, XSlotLayout);
readonly ButtonTypes = Object.assign({}, XButtonType);
//
@ViewChild('fileInput', { static: false })
private fileInputRef!: ElementRef;
//
//#region Selected File ...
private SELECTED_FILE: File;
set file(v: File) {
//
this.SELECTED_FILE = v;
//
if (!v) {
return;
}
//
getImageDimensions(v).then((dimension) => {
if (dimension) {
//
this.selectedFileWidth = dimension.width;
this.selectedFileHeight = dimension.height;
//
this.detectChanges();
}
});
}
get file() {
return this.SELECTED_FILE;
}
//
selectedFileWidth = 0;
selectedFileHeight = 0;
//
preparedMaxAllowedFileSize = this.config.maxProfileImageSize;
preparedAllowedExtensions = this.config.allowedImageExtensions;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.resourceProvider(this.ResourceIDs.file_components)}
در این کتابخانه مجموعه ای از مولفه ها جهت سهولت کار با فایل ها ارائه شده است که در ادامه به بررسی هر یک بتفصیل پرداخته خواهد شد:
`;
readonly contentEn = `
# ${this.resourceProvider(this.ResourceIDs.file_components)}
this framework provides several components to make working with files so easy. in the following section they will be documented:
`;
//
// Thumbnail ...
readonly ThumbnailTypes = Object.assign({}, XThumbnailType);
readonly thumbnailContentFa = `
این مولفه جهت نمایش تصاویر بند انگشتی و یا تعیین نوع فایل در حالت عمومی کاربرد دارد.
`;
readonly thumbnailContentEn = `
this component used to show a thumbnail of an image or file general types.
`;
readonly fileUrl = this.managerService.getFullUrl('/assets/icon/favicon.png');
readonly thumbnailSample1 =
'```html' +
`
<x-thumbnail
[identifier]="fileUrl"
[type]="ThumbnailTypes.CUSTOM"
>
</x-thumbnail>
` +
'```';
readonly thumbnailSample2 =
'```html' +
`
<x-thumbnail
[identifier]="fileUrl"
[type]="ThumbnailTypes.GENERAL"
>
</x-thumbnail>
` +
'```';
//
// File Drop Area ...
readonly fileDropAreaContentFa = `
این مولفه جهت فراهم کردن فضایی برای کشیدن فایل ها و رها کردن آن ها در فضای مناسب مورد استفاده قرار می گیرد.
`;
readonly fileDropAreaContentEn = `
this component use to provide an area for dropping file(s)
`;
//
readonly fileDropAreaSample1 =
'```html' +
`
<x-file-drop-area
[wrapWithCard]="true"
[isPageFileDropArea]="true"
[supportsMultipleFiles]="true"
(filesChangeEmiter)="
handleFilesChanged($event)"
></x-file-drop-area>
` +
'```';
readonly imageCropperContentFa = `
این مولفه جهت فراهم کردن امکانات بریدن تصاویر کاربرد دارد که مهمترین مورد کاربرد آن در تصاویر پروفایل است.
`;
readonly imageCropperContentEn = `
this component use to provide a way to cropping images before upload them, usually used for avatars.
`;
//
readonly imageCropperSample1 =
'```html' +
`
<div class="container">
<input
hidden
#fileInput
type="file"
multiple="false"
(change)="
handleFilesSelected()"
[disabled]="
isLoading || uiDisabled"
/>
<x-button
(click)="selectFile()"
[type]="ButtonTypes.Raised"
[color]="ColorNames.Primary"
[title]="
resourceProvider(
ResourceIDs.select)
+ \' \' +
resourceProvider(
ResourceIDs.avatar)"
>
</x-button>
<div
*ngIf="file"
class="thumbnail-wrapper"
>
<x-slotter
[hasCenterSlot]="false"
[layout]="
SlotLayout.HORIZONTAL"
[startTopSlotCssClass]="
\'ion-text-start\'"
[endBottomSlotCssClass]="
\'ion-text-center\'"
>
<x-slot
[name]="SlotNames.START">
<div>
<x-thumbnail
class="x-thumb"
[identifier]="file"
[loading]="isLoading"
[cssClass]="\'thumbnail\'"
[uiDisabled]="uiDisabled"
[type]="
ThumbnailTypes.CUSTOM"
>
</x-thumbnail>
</div>
</x-slot>
<x-slot [name]="SlotNames.END">
<div
class="
avatar-actions
ion-text-end">
<div>
<x-button
*ngIf="
croppableImage()"
[type]="
ButtonTypes.Icon"
(click)="
handleLoadCropper()"
[color]="
ColorNames.Secondary"
[matTooltip]="
resourceProvider(
ResourceIDs.crop)"
>
<x-icon
[name]="
IconNames.crop">
</x-icon>
</x-button>
<x-button
[type]="
ButtonTypes.Icon"
(click)="
handleClearFile()"
[color]="
ColorNames.Warning"
[matTooltip]="
resourceProvider(
ResourceIDs.clear)"
>
<x-icon
[name]="
IconNames.clear"
[color]="
ColorNames.Light"
></x-icon>
</x-button>
</div>
</div>
</x-slot>
</x-slotter>
</div>
</div>
` +
'```';
//
// File Upload ...
readonly fileUploadContentFa = `
از این مولفه جهت مدیریت بارگزاری فایل ها استفاده می شود
`;
readonly fileUploadContentEn = `
use this component to manage how files uploaded.
`;
readonly fileUploadSample1 =
'```html' +
`
<x-file-upload
[canDrop]="
isNotMobileUi$ | async"
(fileChange)="
handleFileChanged($event)"
[maxAllowedSize]="
config.maxAllowedSize"
[maxAllowedFiles]="
config.maxUploadFiles"
[minAllowedFileSize]="
config.minAllowedFileSize"
[maxAllowedFileSize]="
config.maxAllowedFileSize"
></x-file-upload>
` +
'```';
//
//#region Constructor ...
constructor(
public zone: NgZone,
public element: ElementRef,
public renderer: Renderer2,
public ruler: ViewportRuler,
public menuController: MenuController,
public managerService: XManagerService,
public changeDetector: ChangeDetectorRef,
@Inject(X_CONFIG) public config: XConfig,
public imageCropperService: XImageCropperService,
protected popoverService: XPopoverService,
protected propertyProvider: XPageContainer,
) {
super(
zone,
config,
element,
renderer,
ruler,
menuController,
managerService,
changeDetector,
popoverService,
propertyProvider
);
}
//#endregion
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
croppableImage() {
return (
this.file &&
this.selectedFileWidth > 0 &&
this.selectedFileHeight > 0 &&
this.selectedFileWidth >= this.config.minAllowedImageSize &&
this.selectedFileHeight >= this.config.minAllowedImageSize
);
}
//#endregion
//
//#region UI Handlers ...
//
async handleFilesChanged(files: File | File[]) {
//
console.log('files changed: ', files);
//
await this.managerService.notificationService.presentInfoNotification({
message: `Selected File(s): ${toArray(files).length}`,
dissmissable: true,
});
}
//
handleFilesSelected() {
//
if (!this.fileInputRef) {
return;
}
//
const fileInput = this.fileInputRef.nativeElement;
if (!fileInput || !fileInput.files) {
return;
}
//
const files = getArrayOf<File>(fileInput.files);
//
if (!files || files.length === 0) {
return;
}
//
const file = files[0];
if (!file) {
return;
}
//
fileInput.value = null;
//
this.handleFileDropped(files);
}
//
async handleFileDropped(files: File | File[]) {
//
if (!files) {
return;
}
//
this.loading = true;
//
let file: File;
if (!isArray(files) && files instanceof File) {
file = files as File;
} else {
//
const filesArr = files as File[];
if (hasChild(filesArr)) {
file = filesArr[0];
}
}
//
this.loading = false;
//
if (!file) {
return;
}
//
const status = this.getFileStatus(file);
if (status !== XFileStatus.OK) {
this.loading = false;
this.handleFileStatus(status);
return;
}
//
this.file = file;
}
//
handleLoadCropper() {
this.imageCropperService.showCropper(this.file);
//
const s = this.applyTakeUntilWrapper(
this.imageCropperService.onResult.asObservable()
).subscribe((res) => {
//
if (res.result === XDialogResult.Ok && res.file) {
//
this.file = null;
setTimeout(() => {
this.file = res.file;
}, 100);
}
//
s.unsubscribe();
});
}
//
handleClearFile() {
//
this.file = null;
this.selectedFileWidth = 0;
this.selectedFileHeight = 0;
}
selectFile() {
//
if (!this.fileInputRef || !this.fileInputRef.nativeElement) {
return;
}
//
this.fileInputRef.nativeElement.click();
}
//
// File Upload ...
async handleFileChanged(files: XOneOrManyType<File>) {
console.log('files: ', files);
}
//
async handleActionFired(event: XActionBarActionFiredModel) {
//
const name = event.action;
await this.managerService.notificationService.presentXNotification({
message: `Action Fired: ${name}`,
dissmissable: true,
opt: {
color: XColor.Dark,
},
});
}
//#endregion
//
//#region Private ...
//
//#region File Selection Policies ...
private isExtensionOk(file: File) {
//
if (!file) {
return false;
}
//
if (!hasChild(this.preparedAllowedExtensions)) {
return true;
}
//
const result = isExtensionOk(file, this.preparedAllowedExtensions);
return result;
}
private isMaxAllowedFileSizeOk(file: File) {
//
const result =
this.preparedMaxAllowedFileSize && this.preparedMaxAllowedFileSize > 0
? file.size <= this.preparedMaxAllowedFileSize
: true;
//
return result;
}
private getFileStatus(file: File) {
//
// Check Not Empty File ...
if (!file || file.size === 0) {
return XFileStatus.EMPTY;
}
//
// Check File Extension Validation ...
if (!this.isExtensionOk(file)) {
return XFileStatus.NOT_ALLOWED_TYPE;
}
//
// Check File Size Ok ...
if (!this.isMaxAllowedFileSizeOk(file)) {
return XFileStatus.SIZE_EXCEEDED;
}
//
// Everythings Ok ...
return XFileStatus.OK;
}
private handleFileStatus(status: XFileStatus) {
//
let exception: XExceptionIDs = null;
switch (status) {
//
case XFileStatus.EMPTY:
exception = this.ExceptionIDs.EmptyFile;
break;
//
case XFileStatus.NOT_ALLOWED_TYPE:
exception = this.ExceptionIDs.InavlidFile;
break;
//
case XFileStatus.SIZE_EXCEEDED:
exception = this.ExceptionIDs.MaxFileSizeExceeded;
break;
//
case XFileStatus.MAX_ALLOWED_SIZE_REACHED:
exception = this.ExceptionIDs.MaxFilesSizeExceeded;
break;
//
case XFileStatus.MAX_ALLOWED_FILES_REACHED:
exception = this.ExceptionIDs.MaxAllowedFilesExceeded;
break;
}
//
if (exception) {
this.managerService.notificationService.presentErrorNotification({
exception,
dissmissable: true,
});
}
}
//#endregion
//#endregion
}
@@ -0,0 +1,99 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XFormComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<!-- Form Control Center -->
<x-form
[isInPage]="true"
[wrapWithCard]="true"
*ngIf="showFormControlCenter"
[cardTitle]="'Form Controller'"
[formConfig]="xFormControlConfig"
[actionProvider]="controlFormActionProvider"
(valueChanged)="handleFormControlCenterValueChanged($event)"
>
</x-form>
<!-- Form Elements Multiple Actions -->
<x-card [isInPage]="true">
<x-slotter [layout]="SlotLayouts.HORIZONTAL">
<!-- Start -->
<x-slot [name]="SlotNames.START" [cssClass]="'ion-text-center'">
<x-button
[type]="ButtonTypes.Raised"
[color]="ColorNames.Primary"
[title]="'Show All Form Fileds'"
(clicked)="handleShowAllFormFileds()"
></x-button>
</x-slot>
<!-- Center -->
<x-slot [name]="SlotNames.CENTER"> </x-slot>
<!-- End -->
<x-slot [name]="SlotNames.END" [cssClass]="'ion-text-center'">
<x-button
[type]="ButtonTypes.Raised"
[color]="ColorNames.Danger"
[title]="'Remove All Form Fileds'"
(clicked)="handleClearAllFormFileds()"
></x-button>
</x-slot>
</x-slotter>
</x-card>
<!-- Form -->
<x-form
[isInPage]="true"
*ngIf="xFormConfig"
[wrapWithCard]="true"
[formConfig]="xFormConfig"
[cardTitle]="'Sample Form'"
[actionProvider]="formActionProvider"
[applyStatusOnControls]="applyStatusOnControls"
(valueChanged)="handleFormValueChanged($event)"
[regularColor]="formRegularColor"
[validColor]="formValidColor"
[hintColor]="formHintColor"
[invalidColor]="formInvalidColor"
[activeColor]="formActiveColor"
[pendingColor]="formPendingColor"
[disabledColor]="formDisabledColor"
[accentColor]="formAccentColor"
[fillColor]="formFillColor"
[disabledFillColor]="formDisabledFillColor"
></x-form>
</v-page>
<ng-template #nameAutoCompleteRef let-item> {{ item.data }} </ng-template>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,77 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XGridComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Samples -->
<x-markdown
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[isInPage]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<x-grid
[isInPage]="true"
[wrapWithCard]="true"
[items]="templGridItems"
[selectableItems]="true"
[itemTemplate]="gridItemRef"
[type]="GridPresentTypes.AsFlex"
(itemSelected)="handleGridItemSelected($event)"
>
</x-grid>
<x-markdown
[mode]="'preview'"
[content]="sample2"
[hasToolbar]="false"
[wrapWithCard]="true"
[isInPage]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<x-grid
[cols]="4"
[isInPage]="true"
[wrapWithCard]="true"
[items]="templGridItems"
[selectableItems]="true"
[itemTemplate]="gridItemRef"
[type]="GridPresentTypes.AsGrid"
(itemSelected)="handleGridItemSelected($event)"
>
</x-grid>
</v-page>
<!-- Grid Item Template -->
<ng-template #gridItemRef let-item>
<div>
{{ item.data }}
<!-- <span>{{ item.data }}</span> -->
</div>
</ng-template>
+160
View File
@@ -0,0 +1,160 @@
import {
XGridItem,
XIconNames,
XGridPresentType,
defaultGridOptions,
XStaggedGridOptions,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, isNullOrEmptyString, XColor } from 'x-framework-core';
@Component({
selector: 'app-grid',
templateUrl: './grid.page.html',
styleUrls: ['./grid.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class GridPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.grid;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.grid_description);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه نمایش مجموعه ای از عناصر مرتبط با هم بکار می رود.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used to show a collection of related items.
`;
//
readonly sample0 =
'```typescript' +
`
gridOption: XStaggedGridOptions = {
...defaultGridOptions,
};
tempList = Array.from(Array(25).keys());
templGridItems: XGridItem<string>[] = this.tempList.map((i) => {
//
const li: XGridItem<string> = {
data: \`Item \${i.toString()}\`,
};
//
return li;
});
` +
'```';
//
readonly sample1 =
'```html' +
`
<x-grid
[isPageGrid]="true"
[wrapWithCard]="true"
[items]="templGridItems"
[selectableItems]="true"
[itemTemplate]="gridItemRef"
[type]="GridPresentTypes.AsFlex"
(itemSelected)="
handleGridItemSelected($event)"
>
</x-grid>
` +
'```';
readonly sample2 =
'```html' +
`
<x-grid
[cols]="4"
[isPageGrid]="true"
[wrapWithCard]="true"
[items]="templGridItems"
[selectableItems]="true"
[itemTemplate]="gridItemRef"
[type]="GridPresentTypes.AsGrid"
(itemSelected)="
handleGridItemSelected($event)"
>
</x-grid>
` +
'```';
//
readonly GridPresentTypes = Object.assign({}, XGridPresentType);
//
gridOption: XStaggedGridOptions = {
...defaultGridOptions,
};
tempList = Array.from(Array(25).keys());
templGridItems: XGridItem<string>[] = this.tempList.map((i) => {
//
const li: XGridItem<string> = {
data: `Item ${i.toString()}`,
};
//
return li;
});
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//
handleGridItemSelected(item: XGridItem<string>) {
console.log('handleGridItemSelected: ', item.data);
}
//#endregion
}
@@ -0,0 +1,100 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Sample -->
<x-markdown
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[cssClass]="'code-block'"
></x-markdown>
<x-icon
[foregroundColor]="true"
[name]="IconNames.blockchain"
[color]="ColorNames.Success"
>
</x-icon>
<!-- Sample -->
<x-markdown
[mode]="'preview'"
[content]="sample2"
[hasToolbar]="false"
[cssClass]="'code-block'"
></x-markdown>
<x-icon
[clickable]="true"
[name]="IconNames.blockchain"
[foregroundColor]="false"
[color]="ColorNames.Dark"
(clicked)="managerService.notificationService.presentInfoNotification({
message: 'icon clicked ...',
dissmissable: true
})"
>
</x-icon>
<br />
<br />
<x-form
[fillColor]="ColorNames.Dark"
[formConfig]="iconListFormConfig"
[regularColor]="ColorNames.Light"
></x-form>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XIconComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Icon List -->
<x-card
[isInPage]="true"
*ngIf="showIconList"
[title]="resourceProvider(ResourceIDs.icon_list)"
>
<!-- Icons List -->
<x-list
#listPresenter
[showToolbar]="true"
[stickyToolbar]="true"
[showSearchBar]="true"
[showActionBar]="false"
[clickableItems]="true"
[items]="iconListItems"
[itemTemplate]="iconTemplate"
[searchBarColor]="ColorNames.Dark"
(itemSelected)="handleIconSelected($event)"
[searchBarSearchInputColor]="ColorNames.Dark"
>
</x-list>
</x-card>
</v-page>
<!-- Icon Template Ref -->
<ng-template #iconTemplate let-item>
<div class="cb-inherit ion-text-center">
<x-icon [name]="item.data" [color]="ColorNames.Tertiary"></x-icon>
{{ item.data }}
</div>
</ng-template>
+237
View File
@@ -0,0 +1,237 @@
import {
XSpinner,
hasChild,
XResourceIDs,
isNullOrEmptyString,
XColorWithBrightness,
} from 'x-framework-core';
import {
XIconNames,
XListItem,
XFormConfig,
XFormControlType,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
interface IconsListPresentation {
show: boolean;
}
@Component({
selector: 'app-icon',
templateUrl: './icon.page.html',
styleUrls: ['./icon.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class IconPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.icon;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.icon_description);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
// Color Names ...
readonly ColorNames = Object.assign({}, XColorWithBrightness);
//
// Spinner Names ...
readonly SpinnerNames = Object.assign({}, XSpinner);
//
IconNames = Object.assign({}, XIconNames);
iconList = Object.keys(this.IconNames);
iconListItems: XListItem<string>[] = [];
//#endregion
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت نمایش شمایل های مختلف بکار میرود.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this Component used for show an icon.
`;
readonly sample1 =
'```html' +
`
<x-icon
[foregroundColor]="true"
[name]="IconNames.business"
[color]="ColorNames.Success"
>
</x-icon>
` +
'```';
readonly sample2 =
'```html' +
`
<x-icon
[clickable]="true"
[name]="IconNames.home"
[foregroundColor]="false"
[color]="ColorNames.Dark"
(clicked)="managerService
.notificationService
.presentInfoNotification({
message: 'icon clicked ...',
dissmissable: true
})"
>
</x-icon>
` +
'```';
//
showIconList = false;
iconListFormConfig: XFormConfig<IconsListPresentation> = {
name: 'IconListForm',
controls: [
{
index: 5,
propName: 'show',
type: {
type: XFormControlType.CheckBox,
config: {
checkedChanged: async (checked: boolean) => {
//
if (!hasChild(this.iconListItems)) {
//
const loading = await this.managerService.dialogService.presentLoading(
{
message: this.resourceProvider(
AppResourceIDs.default_loading
),
spinner: this.SpinnerNames.LinesSmall,
}
);
//
await this.prepareIconListItems();
//
await loading.dismiss();
}
//
this.showIconList = checked;
},
},
},
appearance: {
label: `${this.resourceProvider(
this.ResourceIDs.show
)} ${this.resourceProvider(this.ResourceIDs.icon_list)}`,
},
},
],
};
//
//#region LifeCycle ...
//#endregion
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
canShowIconList() {
return hasChild(this.iconListItems);
}
//#endregion
//
//#region UI Handlers ...
async handleIconSelected(item: XListItem<string>) {
//
// text: this.resourceProvider(XResourceIDs.dismiss),
const iconText = `&lt;x-icon name='${item.data}'&gt;&lt;/x-icon&gt;`;
const iconCode = `<x-icon name='${item.data}'></x-icon>`;
await this.managerService.notificationService.presentInfoNotification({
message: iconText,
dissmissable: true,
opt: {
duration: 4000,
buttons: [
{
icon: this.IconNames.clipboard,
side: 'end',
role: 'set',
handler: () => {
//
console.log(iconCode);
const isSaved = this.managerService.saveToClipboard(iconCode);
if (isSaved) {
this.managerService.notificationService.presentDefaultSuccessNotification();
}
},
},
{
icon: this.IconNames.close,
side: 'end',
role: 'cancel',
},
],
},
});
}
//#endregion
//
//#region Private ...
private async prepareIconListItems() {
//
this.iconListItems = this.iconList.map((i) => {
//
const li: XListItem<string> = {
data: i,
};
//
return li;
});
this.detectChanges();
}
//#endregion
}
@@ -0,0 +1,25 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/index.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
</v-page>
@@ -0,0 +1,85 @@
import {
XResourceIDs,
isNullOrEmptyString,
XColorWithBrightness,
} from 'x-framework-core';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
@Component({
selector: 'app-components-introduction',
templateUrl: './introduction.page.html',
styleUrls: ['./introduction.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class IntroductionPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.components_introduction;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(
AppResourceIDs.components_introduction_description
);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
// Color Names ...
readonly ColorNames = Object.assign({}, XColorWithBrightness);
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این واحد در زمره اصلی ترین اجزاء چارچوب ایفای نقش می کند و شامل کلیه مولفه های بصری قابل استفاده در طراحی و پیاده سازی برنامه های کاربردی است.
شناخت عمیق کلیه اجزاء این واحد در تسریع فرآیند توسعه بسیار لازم و ضروری است.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this module is one of most important modules of xFramework and contains all provided UI Components which used to design and develop Applications.
getting deep dive into all components of this module is very usefull to make easier the Design and Develop proccess of Applications.
`;
//#endregion
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
}
@@ -0,0 +1,73 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Samples -->
<x-markdown
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[cssClass]="'code-block'"
></x-markdown>
<x-markdown
[mode]="'preview'"
[content]="sample2"
[hasToolbar]="false"
[cssClass]="'code-block'"
></x-markdown>
<x-markdown
[mode]="'preview'"
[content]="sample3"
[hasToolbar]="false"
[cssClass]="'code-block'"
></x-markdown>
<!-- List Presenter -->
<x-list
#listPresenter
[showToolbar]="true"
[stickyToolbar]="true"
[showActionBar]="true"
[showSearchBar]="true"
[showDivider]="false"
[clickableItems]="true"
[selectableItems]="true"
[items]="templListItems"
[enableReordering]="true"
[itemTemplate]="listItemRef"
[color]="ColorNames.Tertiary"
(refresh)="handleRefreshList()"
[actionBarColor]="ColorNames.Dark"
[searchBarColor]="ColorNames.Dark"
[actionBarHideActions]="hideActions"
(removeItems)="handleRemoveItems($event)"
[searchBarSearchInputColor]="ColorNames.Dark"
>
</x-list>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/modules/XListModule.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
</v-page>
<!-- List Item Template -->
<ng-template #listItemRef let-item>
<span>{{item.data}}</span>
</ng-template>
+343
View File
@@ -0,0 +1,343 @@
import {
XColor,
XResourceIDs,
isNullOrEmptyString,
XBaseRangeRequestDto,
XStandardType,
XOneOrManyType,
} from 'x-framework-core';
import { Component } from '@angular/core';
import { XListItem, XIconNames } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
@Component({
selector: 'app-list',
templateUrl: './list.page.html',
styleUrls: ['./list.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class ListPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.list;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.list_description);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت نمایش فهرستی از موارد و فراهم کردن ابزار مدیریت آن بکار می رود.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used to provide a way to show items in a list and manage items.
`;
//
readonly sample1 =
'```typescript' +
`
tempList = Array
.from(Array(25).keys());
templListItems: XListItem<string>[] =
this.tempList.map((i) => {
const li: XListItem<string> = {
data: \`Item \${i.toString()}\`,
slideOptions: [
{
id: 'remove',
icon: this.IconNames.remove,
color: this.ColorNames.Danger,
onlyIcon: true,
slot: 'end',
handler: () => {
//
this.managerService
.notificationService
.presentDangerNotification({
message: \`remove: \${i}\`,
dissmissable: true,
});
},
},
{
id: 'edit',
icon: this.IconNames.edit,
color: this.ColorNames.Warning,
onlyIcon: true,
slot: 'start',
handler: () => {
//
this.managerService
.notificationService
.presentInfoNotification({
message: \`edit: \${i}\`,
dissmissable: true,
});
},
},
],
};
return li;
});
` +
'```';
//
readonly sample2 =
'```html' +
`
<x-list
#listPresenter
[showToolbar]="true"
[stickyToolbar]="true"
[showActionBar]="true"
[showSearchBar]="true"
[showDivider]="false"
[clickableItems]="true"
[selectableItems]="true"
[items]="templListItems"
[enableReordering]="true"
[itemTemplate]="listItemRef"
[color]="ColorNames.Tertiary"
(refresh)="handleRefreshList()"
[actionBarColor]="ColorNames.Dark"
[searchBarColor]="ColorNames.Dark"
[searchBarInputColor]="ColorNames.Dark"
(removeItems)="handleRemoveItems($event)"
>
</x-list>
` +
'```';
readonly sample3 =
'```typescript' +
`
handleRefreshList() {
this.prepareListItems();
}
handleRemoveItems(request:
XBaseRangeRequestDto<string>) {
//
this.templListItems = this
.templListItems.filter(
(li) => !request.items
.includes(li.data)
);
}
private prepareListItems() {
this.templListItems = this
.tempList.map((i) => {
//
const li: XListItem<string> = {
data: \`Item $\{i.toString()}\`,
slideOptions: [
{
id: 'remove',
icon: this.IconNames.remove,
color: this.ColorNames.Danger,
onlyIcon: true,
slot: 'end',
handler: () => {
//
this.managerService
.notificationService
.presentDangerNotification({
message: \`remove: \${i}\`,
dissmissable: true,
});
},
},
{
id: 'edit',
icon: this.IconNames.edit,
color: this.ColorNames.Warning,
onlyIcon: true,
slot: 'start',
handler: () => {
//
this.managerService
.notificationService
.presentInfoNotification({
message: \`edit: \${i}\`,
dissmissable: true,
});
},
},
],
};
//
return li;
});
}
` +
'```';
//
tempList = Array.from(Array(25).keys());
templListItems: XListItem<string>[] = this.tempList.map((i) => {
//
const li: XListItem<string> = {
data: `Item ${i.toString()}`,
slideOptions: [
{
id: 'remove',
icon: this.IconNames.remove,
color: this.ColorNames.Danger,
onlyIcon: true,
slot: 'end',
handler: () => {
//
this.managerService.dialogService.presentAreYouSureYesNoDialog(
() => {
this.handleRemoveItems({ items: [li.data] });
}
);
},
},
{
id: 'edit',
icon: this.IconNames.edit,
color: this.ColorNames.Warning,
onlyIcon: true,
slot: 'start',
handler: () => {
//
this.managerService.notificationService.presentInfoNotification({
message: `edit: ${i}`,
dissmissable: true,
});
},
},
],
};
//
return li;
});
//
hideActions: XStandardType<XOneOrManyType<string>> = []; // [DefaultActionBarItemIds.Remove];
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//#endregion
//
//#region UI Handlers ...
//
handleRefreshList() {
this.prepareListItems();
}
//
handleRemoveItems(request: XBaseRangeRequestDto<string>) {
//
this.templListItems = this.templListItems.filter(
(li) => !request.items.includes(li.data)
);
//
this.managerService.notificationService.presentSuccessNotification({
message: `${request.items.length} item(s) removed ...`,
dissmissable: true,
});
}
//#endregion
//
//#region Private ...
//
private prepareListItems() {
this.templListItems = this.tempList.map((i) => {
//
const li: XListItem<string> = {
data: `Item ${i.toString()}`,
slideOptions: [
{
id: 'remove',
icon: this.IconNames.remove,
color: this.ColorNames.Danger,
onlyIcon: true,
slot: 'end',
handler: () => {
//
this.managerService.notificationService.presentDangerNotification(
{
message: `remove: ${i}`,
dissmissable: true,
}
);
},
},
{
id: 'edit',
icon: this.IconNames.edit,
color: this.ColorNames.Warning,
onlyIcon: true,
slot: 'start',
handler: () => {
//
this.managerService.notificationService.presentInfoNotification({
message: `edit: ${i}`,
dissmissable: true,
});
},
},
],
};
//
return li;
});
}
//#endregion
}
+102
View File
@@ -0,0 +1,102 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- <x-markdown
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[cssClass]="'code-block'"
></x-markdown> -->
<!-- Map -->
<x-map
#xMap
[zoom]="14"
[isInPage]="true"
[canSelect]="false"
[wrapWithCard]="false"
[latitude]="35.814738589583044"
[longitude]="50.97853161365292"
[actionProvider]="mapActionProvider"
[searchBarColor]="ColorNames.Primary"
[searchBarSearchInputColor]="ColorNames.Primary"
></x-map>
<!-- Center -->
<x-button
[title]="'Set Center'"
[type]="ButtonTypes.Icon"
[icon]="IconNames.map"
(clicked)="handleSetCenter()"
></x-button>
<!-- Zoom -->
<x-button
[title]="'Set Zoom'"
[type]="ButtonTypes.Icon"
[icon]="IconNames.search"
(clicked)="handleSetZoom()"
></x-button>
<!-- AddMarker -->
<x-button
[title]="'Add Marker'"
[type]="ButtonTypes.Icon"
[icon]="IconNames.add"
(clicked)="handleAddMarker()"
></x-button>
<!-- ClearMarker -->
<x-button
[title]="'Clear Marker'"
[type]="ButtonTypes.Icon"
[icon]="IconNames.clear"
(clicked)="handleClearMarker()"
></x-button>
<!-- GoMarkedPlace -->
<x-button
[title]="'Go Marked Place'"
[type]="ButtonTypes.Icon"
[icon]="IconNames.refresh"
(clicked)="handleGoMarkedPlace()"
></x-button>
<!-- Locate -->
<x-button
[title]="'Locate'"
[type]="ButtonTypes.Icon"
[icon]="IconNames.locate"
(clicked)="handleLocate()"
></x-button>
<!-- MapDialog -->
<x-button
[title]="'Map Dialog'"
[icon]="IconNames.map"
[type]="ButtonTypes.Raised"
(clicked)="handleMapDialog()"
></x-button>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XMapComponent.html"
>{{resourceProvider(AppResourceIDs.documentation)}}</a
>
</div>
</x-card>
</v-page>
@@ -0,0 +1,3 @@
x-map {
--map-height: 500px;
}
+272
View File
@@ -0,0 +1,272 @@
import {
Inject,
NgZone,
Component,
Renderer2,
ElementRef,
ChangeDetectorRef,
} from '@angular/core';
import { Subject } from 'rxjs';
import {
XIconNames,
XMapAction,
XButtonType,
XMapLocation,
XMapComponent,
XPageContainer,
XMapActionModel,
XPopoverService,
XMapDialogService,
} from 'x-framework-components';
import { MenuController } from '@ionic/angular';
import { X_CONFIG } from 'src/app/config/x-config';
import { XConfig } from 'src/app/config/app-config';
import { ViewportRuler } from '@angular/cdk/overlay';
import { XManagerService } from 'x-framework-services';
import { XDialogResult, isNullOrEmptyString } from 'x-framework-core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
@Component({
selector: 'app-map',
templateUrl: './map.page.html',
styleUrls: ['./map.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class MapPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.map;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.map_description);
toolbarShowSubTitle = true;
//#endregion
//
readonly IconNames = Object.assign({}, XIconNames);
readonly ButtonTypes = Object.assign({}, XButtonType);
readonly mapActionProvider = new Subject<XMapActionModel>();
//#endregion
//
//#region Constructor ...
public constructor(
public zone: NgZone,
@Inject(X_CONFIG)
public config: XConfig,
public element: ElementRef,
public renderer: Renderer2,
public ruler: ViewportRuler,
public menuController: MenuController,
public managerService: XManagerService,
public changeDetector: ChangeDetectorRef,
protected popoverService: XPopoverService,
protected propertyProvider: XPageContainer,
public mapDialogService: XMapDialogService
) {
super(
zone,
config,
element,
renderer,
ruler,
menuController,
managerService,
changeDetector,
popoverService,
propertyProvider
);
}
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت نمایش نقشه و مکان یابی بکار می رود
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used to show map and locating map.
`;
//
readonly sample1 =
'```html' +
`
<x-map
[zoom]="8"
[showZoom]="true"
[latitude]="35.84"
[showRotate]="true"
[showLocate]="true"
[longitude]="50.9391"
[showSearchBar]="true"
[showZoomSlider]="false"
[locateAfterInit]="true"
[showClearMarker]="true"
[showGoMarkedPlace]="true"
style="--map-height: 300px;"
[searchBarColor]="
ColorNames.Tertiary"
[searchResultListColor]="
ColorNames.Primary"
></x-map>
` +
'```';
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//#endregion
//
//#region UI Handlers ...
async handleSetZoom(map?: XMapComponent) {
//
if (map) {
//
await map.setZoom(12);
return;
}
//
this.mapActionProvider.next({
action: XMapAction.SetZoom,
payload: 12,
});
}
async handleSetCenter(map?: XMapComponent) {
//
if (map) {
//
await map.setCenter(35, 35, 6);
return;
}
//
this.mapActionProvider.next({
action: XMapAction.SetCenter,
payload: {
zoom: '6',
latitude: '35',
longitude: '35',
} as XMapLocation,
});
}
async handleAddMarker(map?: XMapComponent) {
//
if (map) {
//
await map.addMarker(35, 35);
return;
}
//
this.mapActionProvider.next({
action: XMapAction.AddMarker,
payload: {
latitude: '35',
longitude: '35',
} as XMapLocation,
});
}
async handleClearMarker(map?: XMapComponent) {
//
if (map) {
//
await map.clearMarker();
return;
}
//
this.mapActionProvider.next({
action: XMapAction.ClearMarker,
});
}
async handleGoMarkedPlace(map?: XMapComponent) {
//
if (map) {
//
await map.goMarkedPlace();
return;
}
//
this.mapActionProvider.next({
action: XMapAction.GoMarkedPlace,
});
}
async handleLocate(map?: XMapComponent) {
//
if (map) {
//
await map.locate();
return;
}
//
this.mapActionProvider.next({
action: XMapAction.Locate,
});
}
async handleMapDialog() {
//
this.mapDialogService.openDialog({
latitude: 35.814738589583044,
longitude: 50.97853161365292,
zoom: 14,
});
//
const resSubscription = this.mapDialogService.onResult.subscribe(
(result) => {
//
if (!result || result.result !== XDialogResult.Ok) {
//
console.log('empty result');
resSubscription.unsubscribe();
return;
}
//
console.log('selected Location: ', result.payload);
resSubscription.unsubscribe();
}
);
}
//#endregion
}
@@ -0,0 +1,65 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[hasToolbar]="false"
[mode]="MarkdownModes.PREVIEW"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XMarkdownComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Samples -->
<x-markdown
[isInPage]="true"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[mode]="MarkdownModes.PREVIEW"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<!-- Components -->
<x-markdown
[isInPage]="true"
[wrapWithCard]="true"
[mode]="MarkdownModes.BOTH"
[(content)]="sampleContent1"
[toolbarColor]="ColorNames.Dark"
></x-markdown>
<!-- Samples -->
<x-markdown
[isInPage]="true"
[content]="sample2"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[mode]="MarkdownModes.PREVIEW"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<!-- Components -->
<x-markdown
[isInPage]="true"
[hasToolbar]="false"
[wrapWithCard]="true"
[content]="sampleContent2"
[mode]="MarkdownModes.PREVIEW"
></x-markdown>
</v-page>
@@ -0,0 +1,117 @@
import { Component } from '@angular/core';
import { XIconNames } from 'x-framework-components';
import { XMarkdownMode } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, isNullOrEmptyString, XColor } from 'x-framework-core';
@Component({
selector: 'app-markdown',
templateUrl: './markdown.page.html',
styleUrls: ['./markdown.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class MarkdownPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.markdown;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.markdown_description);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
readonly MarkdownModes = Object.assign({}, XMarkdownMode);
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت دریافت و نمایش اطلاعات مبتنی بر شیوه نشانه گذاری داده ها موسوم به مارک داون (MarkDown) کاربرد دارد.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used to get and show MarkDown based Data's.
`;
//
readonly sample1 =
'```html' +
`
<x-markdown
[mode]="MarkdownModes.BOTH"
[(content)]="sampleContent1"
[toolbarColor]="ColorNames.Dark"
></x-markdown>
` +
'```';
readonly sample2 =
'```html' +
`
<x-markdown
[hasToolbar]="false"
[content]="sampleContent2"
[mode]="MarkdownModes.PREVIEW"
></x-markdown>
` +
'```';
//
sampleContent1 = `
## Todo example
- Variable binding
- Code refactor
- Write more unit tests
- Module configuration for markdown settings
- Module configuration for prismjs settings
`;
readonly sampleContent2 = `
## Todo example
this is only a preview sample of markdown.
`;
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//#endregion
}
@@ -0,0 +1,142 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[hasToolbar]="false"
[mode]="MarkdownModes.PREVIEW"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XModelPresenter.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Samples -->
<x-markdown
[isInPage]="true"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[mode]="MarkdownModes.PREVIEW"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<!-- Samples -->
<x-markdown
[isInPage]="true"
[content]="sample2"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[mode]="MarkdownModes.PREVIEW"
></x-markdown>
<!-- Samples -->
<x-markdown
[isInPage]="true"
[content]="sample3"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[mode]="MarkdownModes.PREVIEW"
></x-markdown>
<!-- Samples -->
<x-markdown
[isInPage]="true"
[content]="sample4"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[mode]="MarkdownModes.PREVIEW"
></x-markdown>
<!-- Samples -->
<x-markdown
[isInPage]="true"
[content]="sample5"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[mode]="MarkdownModes.PREVIEW"
></x-markdown>
<!-- Components -->
<x-model-presenter
class="v-card"
[isInPage]="true"
[model]="dataModel"
[wrapWithCard]="true"
[color]="ColorNames.Light"
[cardTitle]="'Object Editor'"
[cardColor]="ColorNames.Light"
[valueColor]="ColorNames.Dark"
[startupState]="'collapse-all'"
[headerColor]="ColorNames.Light"
[actionProvider]="actionProvider"
[hiddenModelKeys]="hiddenModelKeys"
[modelKeyProvider]="modelKeyProvider"
[labelColor]="ColorNames.TertiaryShade"
[availableModelKeys]="availableModelKeys"
[sortOrderModelKeys]="sortOrederModelKeys"
[propertyActionTemplate]="propertyActionRef"
[hiddenLabelModelKeys]="hiddenLabelModelKeys"
(onModelChanged)="handleModelChanged($event)"
[headerHighlightColor]="ColorNames.WarningTint"
></x-model-presenter>
</v-page>
<!-- Property Action Template -->
<ng-template
#propertyActionRef
let-key="key"
let-prefix="prefix"
let-value="value"
>
<!-- is Small Screen -->
<ng-container *ngIf="isMobileUi$ | async">
<!-- Property Selector -->
<x-icon
[clickable]="true"
[foregroundColor]="true"
[color]="ColorNames.Dark"
[name]="IconNames.menu_vertical"
(clicked)="handlePropertyActionMenuClicked(key, prefix, value)"
></x-icon>
</ng-container>
<!-- is Big Screen -->
<ng-container *ngIf="isNotMobileUi$ | async">
<!-- Property Selector -->
<x-icon
[clickable]="true"
[foregroundColor]="true"
[name]="IconNames.edit"
(clicked)="handlePropertyEdit(key, prefix, value)"
[color]="(notNullOrUndefinedValue(value) | async) ? ColorNames.Tertiary : ColorNames.Danger"
></x-icon>
<!-- Property Clear -->
<x-icon
[clickable]="true"
[foregroundColor]="true"
[name]="IconNames.clear"
[color]="ColorNames.Danger"
[uiDisabled]="nullOrUndefinedValue(value) | async"
(clicked)="handlePropertyClear(key, prefix, value)"
></x-icon>
</ng-container>
</ng-template>
@@ -0,0 +1,804 @@
import {
nameof,
assign,
XParam,
isFunction,
XResourceIDs,
XModelProperty,
XModalButtonRole,
XModelKeyProvider,
isNullOrUndefined,
isNullOrEmptyString,
} from 'x-framework-core';
import { Subject } from 'rxjs';
import {
XListItem,
XIconNames,
XPopoverComponent,
XListItemSlideOption,
XModelPresenterAction,
XModelPresenterActionModel,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { XMarkdownMode } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
export interface DataMODEL {
firstName: string;
lastName: string;
email: string;
contacts: Array<{
type: 'mobile' | 'phone';
title: string;
number: string;
}>;
checkList: {
todo1: boolean;
todo2: boolean;
todo3: boolean;
todo4: Array<{
action: string;
dueData: Date;
}>;
};
}
@Component({
selector: 'app-model-presenter',
templateUrl: './model-presenter.page.html',
styleUrls: ['./model-presenter.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class ModelPresenterPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.model_presenter;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(
AppResourceIDs.model_presenter_description
);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
readonly MarkdownModes = Object.assign({}, XMarkdownMode);
//
//#region Model Presenter ...
dataModel: DataMODEL = {
firstName: 'Hadi',
lastName: 'Khazaee Asl',
email: 'hadi_khazaee_asl@yahoo.com',
contacts: [
{
type: 'mobile',
title: 'Personal',
number: '09121694056',
},
{
type: 'phone',
title: 'saherelm office',
number: '02632757987',
},
],
checkList: {
todo1: true,
todo2: false,
todo3: true,
todo4: [
{
action: 'start',
dueData: new Date(),
},
{
action: 'end',
dueData: new Date(),
},
],
},
};
actionProvider = new Subject<XModelPresenterActionModel>();
availableModelKeys: string[] = [
nameof<DataMODEL>('lastName'),
nameof<DataMODEL>('firstName'),
nameof<DataMODEL>('email'),
nameof<DataMODEL>('contacts'),
nameof<DataMODEL>('checkList'),
//
// Contacts ...
// `${nameof<DataMODEL>('contacts')}.type`,
`${nameof<DataMODEL>('contacts')}.title`,
// `${nameof<DataMODEL>('contacts')}.number`,
//
// Checklist ...
`${nameof<DataMODEL>('checkList')}.todo1`,
`${nameof<DataMODEL>('checkList')}.todo2`,
`${nameof<DataMODEL>('checkList')}.todo3`,
`${nameof<DataMODEL>('checkList')}.todo4`,
//
`${nameof<DataMODEL>('checkList')}.todo4.action`,
`${nameof<DataMODEL>('checkList')}.todo4.dueData`,
];
hiddenModelKeys: string[] = [`${nameof<DataMODEL>('contacts')}.type`];
hiddenLabelModelKeys: string[] = [`${nameof<DataMODEL>('contacts')}.number`];
//
sortOrederModelKeys: string[] = [
nameof<DataMODEL>('firstName'),
nameof<DataMODEL>('lastName'),
nameof<DataMODEL>('email'),
nameof<DataMODEL>('contacts'),
nameof<DataMODEL>('checkList'),
//
// Contacts ...
`${nameof<DataMODEL>('contacts')}.number`,
`${nameof<DataMODEL>('contacts')}.title`,
//
// Checklist ...
`${nameof<DataMODEL>('checkList')}.todo4.dueData`,
`${nameof<DataMODEL>('checkList')}.todo4.action`,
];
//
modelKeyProvider: XModelKeyProvider<any> = (key) => {
//
let result = key as string;
//
switch (key) {
//
case nameof<DataMODEL>('firstName'):
result = this.resourceProvider(this.AppResourceIDs.first_name);
break;
//
case nameof<DataMODEL>('lastName'):
result = this.resourceProvider(this.AppResourceIDs.last_name);
break;
//
case nameof<DataMODEL>('contacts'):
result = this.resourceProvider(this.AppResourceIDs.content);
break;
//
default:
result = key as string;
break;
}
//
return result;
};
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت نمایش و ویرایش یک شی یا مدل در نمایی ساختار یافته بکار می رود.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used to view and edit data models in an structural view.
`;
//
readonly sample1 =
'```html' +
`
<x-model-presenter
class="v-card"
[isInPage]="true"
[model]="dataModel"
[wrapWithCard]="true"
[color]="ColorNames.Light"
[cardTitle]="'Object Editor'"
[cardColor]="ColorNames.Light"
[valueColor]="ColorNames.Dark"
[startupState]="'collapse-all'"
[headerColor]="ColorNames.Light"
[actionProvider]="actionProvider"
[hiddenModelKeys]="hiddenModelKeys"
[modelKeyProvider]="modelKeyProvider"
[labelColor]="ColorNames.TertiaryShade"
[availableModelKeys]="availableModelKeys"
[sortOrderModelKeys]="sortOrederModelKeys"
[propertyActionTemplate]="propertyActionRef"
[hiddenLabelModelKeys]="hiddenLabelModelKeys"
(onModelChanged)="handleModelChanged($event)"
[headerHighlightColor]="ColorNames.WarningTint"
></x-model-presenter>
` +
'```';
readonly sample2 =
'```html' +
`
<!-- Property Action Template -->
<ng-template
#propertyActionRef
let-key="key"
let-prefix="prefix"
let-value="value"
>
<!-- is Small Screen -->
<ng-container *ngIf="isMobileUi$ | async">
<!-- Property Selector -->
<x-icon
[clickable]="true"
[foregroundColor]="true"
[color]="ColorNames.Dark"
[name]="IconNames.menu_vertical"
(clicked)="handlePropertyActionMenuClicked(key, prefix, value)"
></x-icon>
</ng-container>
<!-- is Big Screen -->
<ng-container *ngIf="isNotMobileUi$ | async">
<!-- Property Selector -->
<x-icon
[clickable]="true"
[foregroundColor]="true"
[name]="IconNames.edit"
(clicked)="handlePropertyEdit(key, prefix, value)"
[color]="(notNullOrUndefinedValue(value) | async) ? ColorNames.Tertiary : ColorNames.Danger"
></x-icon>
<!-- Property Clear -->
<x-icon
[clickable]="true"
[foregroundColor]="true"
[name]="IconNames.clear"
[color]="ColorNames.Danger"
[uiDisabled]="nullOrUndefinedValue(value) | async"
(clicked)="handlePropertyClear(key, prefix, value)"
></x-icon>
</ng-container>
</ng-template>
` +
'```';
readonly sample3 =
'```javascript' +
`
export interface DataMODEL {
firstName: string;
lastName: string;
email: string;
contacts: Array<{
type: 'mobile' | 'phone';
title: string;
number: string;
}>;
checkList: {
todo1: boolean;
todo2: boolean;
todo3: boolean;
todo4: Array<{
action: string;
dueData: Date;
}>;
};
}
` +
'```';
readonly sample4 =
'```javascript' +
`
dataModel: DataMODEL = {
firstName: 'Hadi',
lastName: 'Khazaee Asl',
email: 'hadi_khazaee_asl@yahoo.com',
contacts: [
{
type: 'mobile',
title: 'Personal',
number: '09121694056',
},
{
type: 'phone',
title: 'saherelm office',
number: '02632757987',
},
],
checkList: {
todo1: true,
todo2: false,
todo3: true,
todo4: [
{
action: 'start',
dueData: new Date(),
},
{
action: 'end',
dueData: new Date(),
},
],
},
};
actionProvider = new Subject<XModelPresenterActionModel>();
availableModelKeys: string[] = [
nameof<DataMODEL>('lastName'),
nameof<DataMODEL>('firstName'),
nameof<DataMODEL>('email'),
nameof<DataMODEL>('contacts'),
nameof<DataMODEL>('checkList'),
//
// Contacts ...
\`\${nameof<DataMODEL>('contacts')}.type\`,
\`\${nameof<DataMODEL>('contacts')}.title\`,
\`\${nameof<DataMODEL>('contacts')}.number\`,
//
// Checklist ...
\`\${nameof<DataMODEL>('checkList')}.todo1\`,
\`\${nameof<DataMODEL>('checkList')}.todo2\`,
\`\${nameof<DataMODEL>('checkList')}.todo3\`,
\`\${nameof<DataMODEL>('checkList')}.todo4\`,
//
\`\${nameof<DataMODEL>('checkList')}.todo4.action\`,
\`\${nameof<DataMODEL>('checkList')}.todo4.dueData\`,
];
hiddenModelKeys: string[] = [\`\${nameof<DataMODEL>('contacts')}.type\`];
hiddenLabelModelKeys: string[] = [\`\${nameof<DataMODEL>('contacts')}.number\`];
//
sortOrederModelKeys: string[] = [
nameof<DataMODEL>('firstName'),
nameof<DataMODEL>('lastName'),
nameof<DataMODEL>('email'),
nameof<DataMODEL>('contacts'),
nameof<DataMODEL>('checkList'),
//
// Contacts ...
\`\${nameof<DataMODEL>('contacts')}.number\`,
\`\${nameof<DataMODEL>('contacts')}.title\`,
//
// Checklist ...
\`\${nameof<DataMODEL>('checkList')}.todo4.dueData\`,
\`\${nameof<DataMODEL>('checkList')}.todo4.action\`,
];
//
modelKeyProvider: XModelPresenterModelKeyProvider<any> = (key) => {
//
let result = key as string;
//
switch (key) {
//
case nameof<DataMODEL>('firstName'):
result = this.resourceProvider(this.AppResourceIDs.first_name);
break;
//
case nameof<DataMODEL>('lastName'):
result = this.resourceProvider(this.AppResourceIDs.last_name);
break;
//
case nameof<DataMODEL>('contacts'):
result = this.resourceProvider(this.AppResourceIDs.content);
break;
//
default:
result = key as string;
break;
}
//
return result;
};
` +
'```';
readonly sample5 =
'```javascript' +
`
async handlePropertyActionMenuClicked(
key: string,
prefix: string,
value: any
) {
//
if (isNullOrEmptyString(key)) {
return;
}
//
const onlyIcon = false;
const slideOptions: XListItemSlideOption[] = [];
//
// Edit ...
slideOptions.push({
id: 'property_edit',
icon: this.IconNames.edit,
title: this.ResourceIDs.edit,
color: isNullOrUndefined(value)
? this.ColorNames.Danger
: this.ColorNames.Tertiary,
slot: 'start',
onlyIcon,
handler: async () => {
await this.handlePropertyEdit(key, prefix, value);
},
});
//
// Clear ...
slideOptions.push({
id: 'property_clear',
icon: this.IconNames.clear,
title: this.ResourceIDs.clear,
color: this.ColorNames.Danger,
slot: 'start',
disabled: isNullOrUndefined(value),
onlyIcon,
handler: async () => {
await this.handlePropertyClear(key, prefix, value);
},
});
//
// Menu Items ...
const item: XListItem<any> = {
data: '',
slideOptions,
};
//
const popOver = await this.managerService.dialogService.presentPopover({
component: XPopoverComponent,
componentProps: assign({}, { key: XParam.Item, value: item }),
translucent: true,
showBackdrop: true,
event,
});
//
const { data } = await popOver.onWillDismiss();
if (!data || !data.id || !data.data) {
return;
}
//
const optionId = data.id.toString() as string;
const option =
item && item.slideOptions
? item.slideOptions.find((so) => so.id === optionId)
: null;
if (!option) {
return;
}
//
const handler = option.handler;
if (!handler || !isFunction(handler)) {
return;
}
//
// Run Handler ...
await handler();
}
async handlePropertyEdit(key: string, prefix: string, value: any) {
//
if (isNullOrEmptyString(key)) {
return;
}
//
await this.managerService.dialogService.presentAlert({
header: 'Change Value:',
message: 'Enter new Value:',
inputs: [
{
type: 'text',
name: 'value',
label: 'Value',
placeholder: isNullOrUndefined(value) ? '' : \`\${value.toString()}\`,
},
],
buttons: [
{
text: 'Change',
role: XModalButtonRole.Selected,
cssClass: ['btn-selected'],
handler: async (value) => {
//
let newValue = '';
if (value && value.value) {
newValue = value.value;
}
//
console.log('new value to set: ', newValue);
//
this.actionProvider.next({
action: XModelPresenterAction.SetProperty,
payload: {
key: key,
value: newValue,
keyPrefix: prefix,
} as XModelPresenterProperty,
});
},
},
{
text: 'Cancel',
role: XModalButtonRole.Cancel,
cssClass: ['btn-cancel'],
},
],
});
}
async handlePropertyClear(key: string, prefix: string, value: any) {
//
if (isNullOrEmptyString(key) || isNullOrUndefined(value)) {
return;
}
//
await this.managerService.dialogService.presentAreYouSureYesNoDialog(() => {
//
this.actionProvider.next({
action: XModelPresenterAction.ClearProperty,
payload: {
key,
keyPrefix: prefix,
} as XModelPresenterProperty,
});
});
}
async handleModelChanged(event: any) {
console.log('handle model changed: ', event);
}
` +
'```';
// readonly sample3 =
// '```html' +
// `
// ` +
// '```';
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//#endregion
//
//#region UI Handlers ...
//
//#region Model Presenter Handlers ...
async handlePropertyActionMenuClicked(
key: string,
prefix: string,
value: any
) {
//
if (isNullOrEmptyString(key)) {
return;
}
//
const onlyIcon = false;
const slideOptions: XListItemSlideOption[] = [];
//
// Edit ...
slideOptions.push({
id: 'property_edit',
icon: this.IconNames.edit,
title: this.ResourceIDs.edit,
color: isNullOrUndefined(value)
? this.ColorNames.Danger
: this.ColorNames.Tertiary,
slot: 'start',
onlyIcon,
handler: async () => {
await this.handlePropertyEdit(key, prefix, value);
},
});
//
// Clear ...
slideOptions.push({
id: 'property_clear',
icon: this.IconNames.clear,
title: this.ResourceIDs.clear,
color: this.ColorNames.Danger,
slot: 'start',
disabled: isNullOrUndefined(value),
onlyIcon,
handler: async () => {
await this.handlePropertyClear(key, prefix, value);
},
});
//
// Menu Items ...
const item: XListItem<any> = {
data: '',
slideOptions,
};
//
const popOver = await this.managerService.dialogService.presentPopover({
component: XPopoverComponent,
componentProps: assign({}, { key: XParam.Item, value: item }),
translucent: true,
showBackdrop: true,
event,
});
//
const { data } = await popOver.onWillDismiss();
if (!data || !data.id || !data.data) {
return;
}
//
const optionId = data.id.toString() as string;
const option =
item && item.slideOptions
? item.slideOptions.find((so) => so.id === optionId)
: null;
if (!option) {
return;
}
//
const handler = option.handler;
if (!handler || !isFunction(handler)) {
return;
}
//
// Run Handler ...
await handler();
}
async handlePropertyEdit(key: string, prefix: string, value: any) {
//
if (isNullOrEmptyString(key)) {
return;
}
//
await this.managerService.dialogService.presentAlert({
header: 'Change Value:',
message: 'Enter new Value:',
inputs: [
{
type: 'text',
name: 'value',
label: 'Value',
placeholder: isNullOrUndefined(value) ? '' : `${value.toString()}`,
},
],
buttons: [
{
text: 'Change',
role: XModalButtonRole.Selected,
cssClass: ['btn-selected'],
handler: async (value) => {
//
let newValue = '';
if (value && value.value) {
newValue = value.value;
}
//
console.log('new value to set: ', newValue);
//
this.actionProvider.next({
action: XModelPresenterAction.SetProperty,
payload: {
prefix,
key: key,
value: newValue,
} as XModelProperty,
});
},
},
{
text: 'Cancel',
role: XModalButtonRole.Cancel,
cssClass: ['btn-cancel'],
},
],
});
}
async handlePropertyClear(key: string, prefix: string, value: any) {
//
if (isNullOrEmptyString(key) || isNullOrUndefined(value)) {
return;
}
//
await this.managerService.dialogService.presentAreYouSureYesNoDialog(() => {
//
this.actionProvider.next({
action: XModelPresenterAction.ClearProperty,
payload: {
key,
prefix,
} as XModelProperty,
});
});
}
async handleModelChanged(event: any) {
console.log('handle model changed: ', event);
}
//#endregion
//#endregion
}
@@ -0,0 +1,33 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Sample -->
<x-markdown
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[cssClass]="'code-block'"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/modules/XPageModule.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
</v-page>
+124
View File
@@ -0,0 +1,124 @@
import { Component } from '@angular/core';
import { XIconNames } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, isNullOrEmptyString, XColor } from 'x-framework-core';
@Component({
selector: 'app-page',
templateUrl: './page.page.html',
styleUrls: ['./page.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class PagePage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.page;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.page_description);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه یکی از پرکاربرد ترین مولفه های ارائه شده توسط این چارچوب است و برای ارائه یک صفحه مجزا در یک برنامه کاربردی کاربرد دارد.
یک صفحه از ترکیب چهار مولفه مجزا تشکیل میگردد، که عبارتند از:
- **XToolbarComponent**:
این مولفه میتواند در ناحیه فوقانی یک صفحه قرار بگیرد و امکانات مختلفی را فراهم کند.
- **XFooterComponent**:
این مولفه میتواند در ناحیه تحتانی یک صفحه قرار بگیرد.
- **XNavigatorComponent**:
این مولفه می تواند در ناحیه کناری صفحه قرار گرفته و گزینه های مختلفی را بعنوان نوار پیمایش در صفحات مختلف را ارئه کند.
- **XPageComponent**:
این مولفه از هر سه مولفه فوق استفاده می کند و امکانات لازم جهت چینش اجزاء مختلف در صفحه و مدیریت نحوه نمایش آن را فراهم می کند.
صفحه حاضر و تمام صفحاتی که در این مستند مرور کرده اید با بهره گیری از این مولفه ایجاد شده اند.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this is a most common component's of this Framework and used to provide an stand alone Page in an Application.
a page presented by combining 4 unique components, which are:
- **XToolbarComponent**:
this component can show in top area of a page and provide several options.
- **XFooterComponent**:
this component can show in bottom area of a page.
- **XNavigatorComponent**:
this component can show in side area of a page and provide several options as a navigation bar.
- **XPageComponent**:
this component use all of 3 above components and provide options to manage their usage and how to looks like a page.
this page and all pages you explored until now created useing this Component.
`;
//
readonly sample1 =
'```html' +
`
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
...
>
<!-- Content -->
...
</v-page>
` +
'```';
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//#endregion
}
@@ -0,0 +1,85 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/modules/XSliderModule.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Sample -->
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<!-- Component -->
<x-slider
[isInPage]="true"
[options]="{
lazy: true,
zoom: true,
autoplay: true,
initialSlide: 0,
grabCursor: true,
autoHeight: true,
slidesPerView: 1,
loadPrevNext: true,
preventClicks: false,
speed: 400,
pagination: true
}"
[wrapWithCard]="true"
[animation]="SliderAnimations.Coverflow"
(onSlideChange)="handleOnSlideChange($event)"
>
<x-slide>
<ng-container *ngTemplateOutlet="slideRef"></ng-container>
</x-slide>
<x-slide>
<ng-container *ngTemplateOutlet="slideRef"></ng-container>
</x-slide>
<x-slide>
<ng-container *ngTemplateOutlet="slideRef"></ng-container>
</x-slide>
<x-slide>
<ng-container *ngTemplateOutlet="slideRef"></ng-container>
</x-slide>
<x-slide>
<ng-container *ngTemplateOutlet="slideRef"></ng-container>
</x-slide>
</x-slider>
</v-page>
<ng-template #slideRef>
<div class="slide-content">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Quas eum odit
labore magnam accusantium assumenda error voluptatem ad cumque velit? Eos
expedita minus doloremque error iste nam commodi aspernatur repellendus.
</div>
</ng-template>
@@ -0,0 +1,10 @@
.slide-content {
direction: ltr;
text-align: justify;
padding: {
top: 24px;
bottom: 24px;
left: 16px;
right: 16px;
}
}
@@ -0,0 +1,139 @@
import { Component } from '@angular/core';
import { XIconNames } from 'x-framework-components';
import { XSliderAnimation } from 'x-framework-components';
import { XResourceIDs, isNullOrEmptyString } from 'x-framework-core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
@Component({
selector: 'app-slider',
templateUrl: './slider.page.html',
styleUrls: ['./slider.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class SliderPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.slider;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.slider_description);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
readonly SliderAnimations = Object.assign({}, XSliderAnimation);
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت نمایش محتوا بصورت کادر های لغزنده بکار می رود.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this Component used to provide Slideable Content's.
`;
//
readonly sample1 =
'```html' +
`
<x-slider
[options]="{
lazy: true,
zoom: true,
autoplay: true,
initialSlide: 0,
grabCursor: true,
autoHeight: true,
slidesPerView: 1,
loadPrevNext: true,
preventClicks: false,
speed: 400,
pagination: true
}"
[animation]="SliderAnimations.Cube"
>
<x-slide>
<ng-container
*ngTemplateOutlet="slideRef">
</ng-container>
</x-slide>
<x-slide>
<ng-container
*ngTemplateOutlet="slideRef">
</ng-container>
</x-slide>
<x-slide>
<ng-container
*ngTemplateOutlet="slideRef">
</ng-container>
</x-slide>
<x-slide>
<ng-container
*ngTemplateOutlet="slideRef">
</ng-container>
</x-slide>
<x-slide>
<ng-container
*ngTemplateOutlet="slideRef">
</ng-container>
</x-slide>
</x-slider>
` +
'```';
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//#endregion
//
//#region UI Handlers ...
handleOnSlideChange(index: number) {
console.log('handleOnSlideChange: ', index);
}
//#endregion
}
@@ -0,0 +1,8 @@
<div>
<h3>Sample Modal Component</h3>
<p>this is sample modal component content ...</p>
<span>Binded Context: {{ context }}</span>
<x-button (click)="handleClosePopup()">CLOSE</x-button>
</div>
@@ -0,0 +1,42 @@
import { Component, Input } from '@angular/core';
import { ModalController, PopoverController } from '@ionic/angular';
export enum XModalContext {
Modal = 'modal',
PopOver = 'pop_over',
}
@Component({
selector: 'app-sample-modal',
templateUrl: './sample-modal.component.html',
styleUrls: ['./sample-modal.component.scss'],
})
export class SampleModalComponent {
@Input()
context: XModalContext;
constructor(
private modalController: ModalController,
private popOverController: PopoverController
) {}
handleClosePopup() {
//
if (!this.context) {
return;
}
//
switch (this.context) {
//
case XModalContext.Modal:
this.modalController.dismiss();
break;
//
case XModalContext.PopOver:
this.popOverController.dismiss();
break;
}
}
}
@@ -0,0 +1,711 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[hasToolbar]="false"
[wrapWithCard]="true"
[content]="getContent('content')"
></x-markdown>
<!-- Expandable Panel -->
<x-expandable-panel
[isInPage]="true"
[isAccordion]="true"
[wrapWithCard]="true"
[selected]="'Button'"
[headerColor]="'tertiary'"
[headerHighlightColor]="'dark'"
>
<!-- Button -->
<x-panel [id]="'Button'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.button) }}</div>
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('buttonContent')"
></x-markdown>
<!-- Sample1 -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="buttonSample1"
></x-markdown>
<x-button
[type]="ButtonTypes.Raised"
[color]="ColorNames.Primary"
class="ion-margin-horizontal"
(click)="handleButtonClicked()"
[title]="ResourceIDs.temp_label"
></x-button>
<!-- Sample2 -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="buttonSample2"
></x-markdown>
<x-button
[foregroundColor]="true"
[type]="ButtonTypes.Raised"
class="ion-margin-horizontal"
[color]="ColorNames.Secondary"
(click)="handleButtonClicked()"
[title]="ResourceIDs.temp_label"
></x-button>
<!-- Sample3 -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="buttonSample3"
></x-markdown>
<x-button
[type]="ButtonTypes.Icon"
[color]="ColorNames.Tertiary"
class="ion-margin-horizontal"
(click)="handleButtonClicked()"
>
<x-icon [name]="'list'" [color]="'light'"></x-icon>
</x-button>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XButtonComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- ActionBar -->
<x-panel [id]="'ActionBar'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.action_bar) }}</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.action_bar_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('actionBarContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="actionBarSample1"
></x-markdown>
<x-action-bar
[color]="ColorNames.Dark"
[actions]="actionBarItems"
(actionFired)="handleActionFired($event)"
></x-action-bar>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XActionBarComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- SearchBar -->
<x-panel [id]="'SearchBar'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.search_bar) }}</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.search_bar_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('searchBarContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="searchBarSample1"
></x-markdown>
<x-search-bar
value="test"
[color]="ColorNames.Dark"
[enterKeyHint]="'search'"
[searchInputColor]="'dark-tint'"
(queryChange)="handleQueryChanged($event)"
>
</x-search-bar>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XSearchBarComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- Alert -->
<x-panel [id]="'Alert'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.alert) }}</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.alert_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('alertContent')"
></x-markdown>
<!-- Sample1 -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="alertSample1"
></x-markdown>
<x-button
[type]="ButtonTypes.Raised"
[title]="ResourceIDs.alert"
(click)="handleShowAlert()"
[color]="ColorNames.Primary"
class="ion-margin-horizontal"
></x-button>
<!-- Sample2 -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="alertSample2"
></x-markdown>
<x-button
[type]="ButtonTypes.Raised"
[title]="ResourceIDs.alert"
(click)="handleShowNativeAlert()"
[color]="ColorNames.Tertiary"
class="ion-margin-horizontal"
></x-button>
<br />
<br />
<!-- Propt Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('promptContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="promptSample1"
></x-markdown>
<x-button
[type]="ButtonTypes.Raised"
[title]="ResourceIDs.prompt"
(click)="handleShowPrompt()"
[color]="ColorNames.Tertiary"
class="ion-margin-horizontal"
></x-button>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="promptSample2"
></x-markdown>
<x-button
[type]="ButtonTypes.Raised"
[title]="ResourceIDs.prompt"
(click)="handleShowNativePrompt()"
[color]="ColorNames.Primary"
class="ion-margin-horizontal"
></x-button>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="promptSample3"
></x-markdown>
<x-button
[type]="ButtonTypes.Raised"
[title]="ResourceIDs.prompt"
[color]="ColorNames.Primary"
class="ion-margin-horizontal"
(click)="handleShowActionModal()"
></x-button>
<br />
<br />
<!-- Modal -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('modalContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="modalSample1"
></x-markdown>
<x-button
[type]="ButtonTypes.Raised"
[title]="ResourceIDs.alert"
[color]="ColorNames.Primary"
class="ion-margin-horizontal"
(click)="handleShowModal()"
></x-button>
<br />
<br />
<!-- PopOver -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('popOverContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="popOverSample1"
></x-markdown>
<x-button
[type]="ButtonTypes.Raised"
[title]="ResourceIDs.alert"
[color]="ColorNames.Primary"
class="ion-margin-horizontal"
(click)="handleShowPopOver($event)"
></x-button>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-services/injectables/XDialogService.html#presentAlert"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- Notification -->
<x-panel [id]="'Notification'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.notification) }}</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.notification_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('notificationContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="notificationSample1"
></x-markdown>
<x-button
[type]="ButtonTypes.Raised"
[color]="ColorNames.Danger"
class="ion-margin-horizontal"
(click)="handleShowNotification()"
[title]="ResourceIDs.notification"
></x-button>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-services/injectables/XNotificationService.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- Spinner -->
<x-panel [id]="'Spinner'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.spinner) }}</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.spinner_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('spinnerContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="spinnerSample1"
></x-markdown>
<!-- Bubbles -->
<x-spinner
[color]="ColorNames.Primary"
[name]="SpinnerNames.Bubbles"
></x-spinner>
<!-- Circles -->
<x-spinner
[name]="SpinnerNames.Circles"
[color]="ColorNames.Secondary"
></x-spinner>
<!-- Tertiary -->
<x-spinner
[color]="ColorNames.Tertiary"
[name]="SpinnerNames.Circular"
></x-spinner>
<!-- Dark -->
<x-spinner
[color]="ColorNames.Dark"
[name]="SpinnerNames.Crescent"
></x-spinner>
<!-- Warning -->
<x-spinner
[color]="ColorNames.Warning"
[name]="SpinnerNames.Dots"
></x-spinner>
<!-- Danger -->
<x-spinner
[color]="ColorNames.Danger"
[name]="SpinnerNames.Lines"
></x-spinner>
<!-- Success -->
<x-spinner
[color]="ColorNames.Success"
[name]="SpinnerNames.LinesSmall"
></x-spinner>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XSpinnerComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- Loading -->
<x-panel [id]="'Loading'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.loading) }}</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.loading_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('loadingContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="loadingSample1"
></x-markdown>
<x-button
[type]="ButtonTypes.Raised"
class="ion-margin-horizontal"
[color]="ColorNames.Secondary"
(click)="handleShowLoading()"
[title]="ResourceIDs.loading"
></x-button>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-services/injectables/XDialogService.html#presentLoading"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- Color -->
<x-panel [id]="'color'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.color) }}</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.color_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('colorContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="colorSample1"
></x-markdown>
<!-- Component -->
<x-color [value]="{ key: 'black', value: '#000000' }"></x-color>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XColorComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- Picker -->
<x-panel [id]="'Picker'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.picker) }}</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.picker_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('pickerContent')"
></x-markdown>
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="pickerSample1"
></x-markdown>
<x-button
[type]="ButtonTypes.Raised"
class="ion-margin-horizontal"
[color]="ColorNames.Primary"
(click)="handleShowSelect()"
[title]="ResourceIDs.picker"
></x-button>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-services/injectables/XDialogService.html#presentPicker"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- Slotter -->
<x-panel [id]="'Slotter'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>{{ resourceProvider(ResourceIDs.slotter) }}</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.slotter_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('slotterContent')"
></x-markdown>
<br />
<br />
<h4>{{ resourceProvider(ResourceIDs.horizontal) }}</h4>
<!-- Sample 1 -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="slotterSample1"
></x-markdown>
<br />
<br />
<x-slotter [layout]="SlotLayout.HORIZONTAL">
<x-slot [name]="SlotNames.START" [cssClass]="'ion-text-start'">
Start
</x-slot>
<x-slot [name]="SlotNames.CENTER" [cssClass]="'ion-text-center'">
Center
</x-slot>
<x-slot [name]="SlotNames.END" [cssClass]="'ion-text-end'">
End
</x-slot>
</x-slotter>
<br />
<br />
<!-- Vertical -->
<h4>{{resourceProvider(ResourceIDs.vertical)}}</h4>
<!-- Sample 1 -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[cssClass]="'code-block'"
[content]="slotterSample2"
></x-markdown>
<br />
<br />
<x-slotter [layout]="SlotLayout.VERTICAL">
<x-slot [name]="SlotNames.TOP" [cssClass]="'ion-text-center'">
Top
</x-slot>
<x-slot [name]="SlotNames.CENTER" [cssClass]="'ion-text-center'">
Center
</x-slot>
<x-slot [name]="SlotNames.BOTTOM" [cssClass]="'ion-text-center'">
Bottom
</x-slot>
</x-slotter>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/modules/XSlotterModule.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
<!-- Empty -->
<x-panel [id]="'Empty'" [hasCustomActions]="true">
<!-- Title and Description -->
<div x-panel-title>
{{ resourceProvider(ResourceIDs.empty_component) }}
</div>
<!-- <div x-panel-description>
{{ resourceProvider(ResourceIDs.empty_component_description) }}
</div> -->
<br />
<!-- Description -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('emptyContent')"
></x-markdown>
<!-- Sample -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="emptySample1"
[cssClass]="'code-block'"
></x-markdown>
<x-empty
[hasRefresh]="true"
[foregroundColor]="false"
[color]="ColorNames.Dark"
(refresh)="handleRefreshEmpty()"
[foregroundMessageColor]="false"
[messageColor]="ColorNames.Dark"
[refreshButtonColor]="ColorNames.Dark"
[foregroundRefreshButtonColor]="false"
></x-empty>
<!-- Actions -->
<div x-panel-actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XEmptyComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-panel>
</x-expandable-panel>
</v-page>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,70 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Stepper Type -->
<x-form [formConfig]="stepperPresentationTypeFormConfig"></x-form>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/modules/XStepperModule.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Sample -->
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<!-- Stepper -->
<x-stepper
class="v-card"
[isInPage]="true"
[showLabel]="true"
[wrapWithCard]="true"
[cardTitle]="'Stepper'"
[type]="currentStepperType"
[iconColor]="ColorNames.Dark"
[titleColor]="ColorNames.DangerShade"
(onReset)="handleResetStepper($event)"
>
<!-- Step 1 -->
<x-step [hasNext]="true" [disableNext]="xFormStepOne.status !== 'VALID'">
<div x-step-label>Step ONe</div>
<x-form #xFormStepOne [formConfig]="stepOneModelConfig"></x-form>
</x-step>
<!-- Step 2 -->
<x-step
[hasPrev]="true"
[hasReset]="true"
[disableReset]="xFormStepTwo.status !== 'VALID'"
>
<div x-step-label>Step TWo</div>
<x-form #xFormStepTwo [formConfig]="stepTwoModelConfig"></x-form>
</x-step>
</x-stepper>
</v-page>
@@ -0,0 +1,322 @@
import {
XIconNames,
XFormConfig,
XStepperType,
XFormComponent,
XFormControlType,
XStepperTypeIdentifier,
XFormSelectControlOption,
XFormStatusChangeEventModel,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { Validators } from '@angular/forms';
import { XResourceIDs, isNullOrEmptyString } from 'x-framework-core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
interface StepOne {
id: number;
name: string;
family: string;
}
interface StepTwo {
id: number;
userName: string;
password: string;
}
interface StepperPresentationType {
type: XStepperTypeIdentifier;
}
@Component({
selector: 'app-stepper',
templateUrl: './stepper.page.html',
styleUrls: ['./stepper.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class StepperPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.stepper;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.stepper_description);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
از این مولفه جهت دریافت یا نمایش اطلاعات در گام های مختلف از کاربر استفاده می گردد.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used to get or show data to user in several steps.
`;
//
readonly sample1 =
'```html' +
`
<!-- Stepper -->
<x-stepper
isInPage="true"
showLabel="true"
wrapWithCard="true"
[type]="currentStepperType"
>
<!-- Step 1 -->
<x-step [hasNext]="true" [disableNext]="xFormStepOne.status !== 'VALID'">
<div x-step-label>
Step ONe
</div>
<x-form #xFormStepOne [formConfig]="stepOneModelConfig"></x-form>
</x-step>
<!-- Step 2 -->
<x-step
[hasPrev]="true"
[hasReset]="true"
[disableReset]="xFormStepTwo.status !== 'VALID'"
>
<div x-step-label>
Step TWo
</div>
<x-form #xFormStepTwo [formConfig]="stepTwoModelConfig"></x-form>
</x-step>
</x-stepper>
` +
'```';
//
currentStepperType: XStepperTypeIdentifier;
stepperPresentationTypes = [
`${XStepperType.VERTICAL}`,
`${XStepperType.HORIZONTAL}`,
];
stepperPresentationTypeFormConfig: XFormConfig<StepperPresentationType> = {
name: 'Steper_Present_Type',
model: {
type: XStepperType.HORIZONTAL,
},
controls: [
//
// Id ...
{
index: 0,
propName: 'type',
type: {
type: XFormControlType.Select,
config: {
multiple: false,
options: this.stepperPresentationTypes.map((k) => {
return {
value: k,
viewValue: this.resourceProvider(k),
} as XFormSelectControlOption<XStepperTypeIdentifier>;
}),
},
},
appearance: {
label: this.ResourceIDs.type,
},
eventHandlers: {
valueChanged: (model) => {
//
if (!model || !model.value) {
return;
}
//
const type = model.value as XStepperTypeIdentifier;
if (!type) {
return;
}
//
this.currentStepperType = type;
this.detectChanges();
},
},
},
],
};
//
stepOneModelConfig: XFormConfig<StepOne> = {
name: 'StepOneForm',
controls: [
//
// Id ...
{
index: 0,
propName: 'id',
type: {
type: XFormControlType.Number,
},
appearance: {
label: this.ResourceIDs.id,
},
validators: {
validators: [Validators.required],
},
},
//
// Name ...
{
index: 1,
propName: 'name',
type: {
type: XFormControlType.Text,
},
appearance: {
label: this.ResourceIDs.first_name,
},
validators: {
validators: [Validators.required],
},
},
//
// Family ...
{
index: 2,
propName: 'family',
type: {
type: XFormControlType.Text,
},
appearance: {
label: this.ResourceIDs.last_name,
},
validators: {
validators: [Validators.required],
},
},
],
};
//
stepTwoModelConfig: XFormConfig<StepTwo> = {
name: 'StepTwoForm',
controls: [
//
// Id ...
{
index: 0,
propName: 'id',
type: {
type: XFormControlType.Number,
},
appearance: {
label: this.ResourceIDs.id,
},
validators: {
validators: [Validators.required],
},
},
//
// Username ...
{
index: 1,
propName: 'userName',
type: {
type: XFormControlType.Text,
},
appearance: {
label: this.ResourceIDs.username,
},
validators: {
validators: [Validators.required],
},
},
//
// Password ...
{
index: 2,
propName: 'password',
type: {
type: XFormControlType.Password,
},
appearance: {
label: this.ResourceIDs.password,
},
validators: {
validators: [Validators.required],
},
},
],
};
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
handleFormOneStatusChanged(
event: XFormStatusChangeEventModel,
form: XFormComponent
) {
console.log('status changed: ', event, form.isStatusValid);
}
handleResetStepper(id: string) {
//
console.log('stepper resetted at: ', id);
//
this.stepOneModelConfig = {
...this.stepOneModelConfig,
model: null,
};
//
this.stepTwoModelConfig = {
...this.stepTwoModelConfig,
model: null,
};
//
this.detectChanges();
}
//#endregion
}
@@ -0,0 +1,38 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Sample -->
<x-markdown
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[cssClass]="'code-block'"
></x-markdown>
<!-- Link to ... -->
<a [href]="tabsHref" target="_blank"
>{{ resourceProvider(ResourceIDs.preview) }}</a
>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XTabNavigatorComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
</v-page>
@@ -0,0 +1,95 @@
import { Component } from '@angular/core';
import { Pages } from 'src/app/config/page.config';
import { XIconNames } from 'x-framework-components';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XColor, XResourceIDs, isNullOrEmptyString } from 'x-framework-core';
@Component({
selector: 'app-tab-navigator',
templateUrl: './tab-navigator.page.html',
styleUrls: ['./tab-navigator.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class TabNavigatorPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.tab_navigator;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(
AppResourceIDs.tab_navigator_description
);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه زمانی کاربرد دارد که قصد داریم صفحاتی را در غالب نمایه ای مبتنی بر برگه ها دسته بندی کرده و نمایش دهیم.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used to group Pages in a Tabbed template and show them.
`;
//
readonly sample1 =
'```html' +
`
<x-tab-navigator
[items]="tabItems"
[color]="ColorNames.Dark"
[iconColor]="ColorNames.Danger"
[highlightColor]="ColorNames.Light"
[selectedColor]="ColorNames.SecondaryShade"
></x-tab-navigator>
` +
'```';
//
tabsHref = Pages.TabsNav.baseRoute;
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//#endregion
}
@@ -0,0 +1,67 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XTableComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Samples -->
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
></x-markdown>
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample2"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
></x-markdown>
<x-table
[isInPage]="true"
[showHeader]="true"
[wrapWithCard]="true"
[showSearchBar]="true"
[showPaginator]="true"
[showActionBar]="true"
[selectableRows]="true"
[color]="ColorNames.Medium"
[properties]="tempTableProps"
[headerColor]="ColorNames.Dark"
[actionBarColor]="ColorNames.DarkShade"
[searchBarColor]="ColorNames.DarkShade"
[paginatorColor]="ColorNames.DarkShade"
(removeItems)="handleRemoveItems($event)"
(rowSelected)="handleRowSelected($event)"
[searchBarPosition]="TableItemPositions.TOP"
[actionBarPosition]="TableItemPositions.TOP"
[paginatorPosition]="TableItemPositions.BOTTOM"
(rowSelectionChanged)="handleRowSelectionChanged($event)"
>
</x-table>
</v-page>
@@ -0,0 +1,805 @@
import {
XResourceIDs,
isNullOrEmptyString,
XColorWithBrightness,
} from 'x-framework-core';
import {
XIconNames,
XTableConfig,
XTableItemPosition,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
interface Temp {
id?: string;
name: string;
family: string;
phoneNumber: string;
value: string;
slided: boolean;
checked: boolean;
level: number;
person: string;
dob: Date;
}
@Component({
selector: 'app-table',
templateUrl: './table.page.html',
styleUrls: ['./table.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class TablePage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.table;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.table_description);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
readonly ColorNames = Object.assign({}, XColorWithBrightness);
//#endregion
//
//#region Data Preparation For Table ...
//
readonly TableItemPositions = Object.assign({}, XTableItemPosition);
//
tempItems: Partial<Temp>[] = [
{
id: '71f14439-262f-44bf-8dc8-ee85929c349c',
name: 'Deidre',
family: 'Thomas',
phoneNumber: '+98 (864) 472-3812',
},
{
id: 'caa22853-dd2d-4669-8b63-b1fe4a38ea07',
name: 'Hubbard',
family: 'Preston',
phoneNumber: '+98 (899) 452-3720',
},
{
id: 'ccb62dc4-a06b-412d-800d-02d18f54a0e0',
name: 'Cooley',
family: 'Nixon',
phoneNumber: '+98 (926) 459-2360',
},
{
id: '6a946279-fe01-4e17-bb2c-a1931780ce9d',
name: 'Becky',
family: 'Wallace',
phoneNumber: '+98 (914) 519-3589',
},
{
id: '8601242a-f2ff-465f-8275-5b991b4a8ade',
name: 'Kidd',
family: 'Shelton',
phoneNumber: '+98 (848) 570-3661',
},
{
id: '1f4bd5e8-d7be-460d-9bfb-f0738957bc4b',
name: 'Caitlin',
family: 'Camacho',
phoneNumber: '+98 (959) 453-2722',
},
{
id: '18a874dc-1f3d-4cdc-a3c7-69d2f417e18e',
name: 'Estes',
family: 'Rivera',
phoneNumber: '+98 (917) 436-3237',
},
{
id: '5a5f2a8e-d20e-4fe9-ae6f-84dde7602e9f',
name: 'Ines',
family: 'Powell',
phoneNumber: '+98 (917) 539-3108',
},
{
id: '663c8403-e525-4b51-b262-e876e97d4532',
name: 'Carrillo',
family: 'Acevedo',
phoneNumber: '+98 (828) 556-3742',
},
{
id: '7e6d0bb6-4180-4329-96cc-364a9a534a04',
name: 'Ina',
family: 'Wilkinson',
phoneNumber: '+98 (933) 560-3834',
},
{
id: '19c21deb-f8b7-40c7-a0bb-da203193c114',
name: 'Mercer',
family: 'Adkins',
phoneNumber: '+98 (981) 480-3459',
},
{
id: 'c2e4de31-d406-4611-9dbe-cd7bdefdc5bc',
name: 'Donaldson',
family: 'Vega',
phoneNumber: '+98 (986) 554-2571',
},
{
id: 'cf846f56-b381-447b-96a1-0d7c29736f4f',
name: 'Natalie',
family: 'Cantu',
phoneNumber: '+98 (857) 445-2595',
},
{
id: 'c5252e01-8a26-44f1-846d-28c8810b10b8',
name: 'Christa',
family: 'Higgins',
phoneNumber: '+98 (983) 498-3785',
},
{
id: 'e7e5b97a-67f8-4bff-8c8c-b68cf6a24b2f',
name: 'Kelley',
family: 'Pitts',
phoneNumber: '+98 (948) 588-3437',
},
{
id: '9db9d0ab-a2c4-4edb-8d0b-e664c86c4e55',
name: 'Shelby',
family: 'Macdonald',
phoneNumber: '+98 (882) 401-2642',
},
{
id: '41305b10-aa7a-415d-a819-5e6ab05e0a49',
name: 'Preston',
family: 'Patton',
phoneNumber: '+98 (923) 509-3278',
},
{
id: '35acdcfe-7015-4a27-a5de-0f5c701a9152',
name: 'Allen',
family: 'Flores',
phoneNumber: '+98 (957) 587-3471',
},
{
id: '31f568b8-272a-43c5-bb7a-bf25c2fa6da9',
name: 'Margaret',
family: 'Neal',
phoneNumber: '+98 (870) 480-3528',
},
{
id: '5ef4be35-3d02-45f7-9c25-bf828b4a3845',
name: 'Kirkland',
family: 'Hewitt',
phoneNumber: '+98 (958) 466-2957',
},
{
id: 'e581d671-5d35-4c21-af77-71f881f8d764',
name: 'Herminia',
family: 'Silva',
phoneNumber: '+98 (925) 546-3981',
},
{
id: '4242bc21-945e-4cbe-b73c-bacc0c8b2013',
name: 'Galloway',
family: 'Tyler',
phoneNumber: '+98 (971) 468-2144',
},
{
id: '58f91369-8718-4c01-aff8-8a5d65527948',
name: 'Hull',
family: 'Rojas',
phoneNumber: '+98 (950) 439-3702',
},
{
id: 'e6d25e18-f272-4ac3-b7f6-54c8bae985b5',
name: 'Sandoval',
family: 'Norton',
phoneNumber: '+98 (920) 439-2511',
},
{
id: 'bff9bdad-2947-4fd9-a18a-92388e32aa0b',
name: 'Alba',
family: 'Collins',
phoneNumber: '+98 (957) 445-2714',
},
{
id: '8272763a-6a67-41da-924e-0f417fb259da',
name: 'Montoya',
family: 'Stein',
phoneNumber: '+98 (889) 585-3578',
},
{
id: '29a6ff2c-746e-4214-b28f-073ac201ea96',
name: 'Grant',
family: 'Gilliam',
phoneNumber: '+98 (814) 562-3575',
},
{
id: '416cb3f4-30ae-4874-a7c3-ffd401cf6c3f',
name: 'Meadows',
family: 'Mcknight',
phoneNumber: '+98 (994) 589-2830',
},
{
id: 'd061721e-ca9c-4054-9aa1-1196a51a0256',
name: 'Harris',
family: 'Rhodes',
phoneNumber: '+98 (853) 489-2436',
},
{
id: 'd01323d5-5126-4c8a-ad89-0298acf4d82d',
name: 'Frieda',
family: 'Hayden',
phoneNumber: '+98 (930) 436-2770',
},
{
id: '34225f99-0986-4294-95f2-3c8961b15036',
name: 'Rasmussen',
family: 'Ross',
phoneNumber: '+98 (821) 599-2812',
},
{
id: '6f7a24d4-8b82-45c4-8b5b-a3053c5a7023',
name: 'Mitzi',
family: 'Gregory',
phoneNumber: '+98 (838) 404-3840',
},
{
id: 'acba244a-12b5-4291-beb2-66a64127121d',
name: 'Washington',
family: 'Cruz',
phoneNumber: '+98 (975) 465-2025',
},
{
id: '2c70c776-80dd-4be9-b32f-6af7d6cea5b0',
name: 'Jewell',
family: 'Rios',
phoneNumber: '+98 (909) 453-3851',
},
{
id: '5f98d7a6-c98b-4dc7-bf90-4df04074b57e',
name: 'Heath',
family: 'Bush',
phoneNumber: '+98 (976) 516-3200',
},
{
id: 'bc51bdc5-47f6-45b4-8c51-6d86324b90d2',
name: 'Laura',
family: 'Edwards',
phoneNumber: '+98 (966) 546-3720',
},
{
id: 'f1f47337-cc3f-49e4-acb7-5989f5eb1a30',
name: 'Harriett',
family: 'Sanders',
phoneNumber: '+98 (816) 579-3042',
},
{
id: '2fce8cd5-398c-4d73-8151-3d0fb375ff49',
name: 'Milagros',
family: 'Vazquez',
phoneNumber: '+98 (941) 437-2907',
},
{
id: 'b725ce24-b08d-4c8e-95ec-5926804ccde3',
name: 'Sheila',
family: 'Aguilar',
phoneNumber: '+98 (855) 509-3995',
},
{
id: 'f7d64d31-43d2-416f-ba19-397b407afeba',
name: 'Eunice',
family: 'Langley',
phoneNumber: '+98 (959) 564-2615',
},
{
id: '6f73fd66-2931-4f1f-9cd1-95803724ff38',
name: 'Valerie',
family: 'House',
phoneNumber: '+98 (985) 550-3203',
},
{
id: '17fab0f9-f37d-4ed0-8656-98b9f9c65333',
name: 'Carmella',
family: 'Young',
phoneNumber: '+98 (964) 548-3625',
},
{
id: '7e9e3057-34df-4727-8a7e-750e876a7ca8',
name: 'Brittany',
family: 'Pennington',
phoneNumber: '+98 (840) 499-3543',
},
{
id: '4ca1aebb-8d6f-4c62-9633-353abf1cab06',
name: 'Polly',
family: 'Roberts',
phoneNumber: '+98 (821) 554-2791',
},
{
id: '147c9f63-800a-4600-94dd-7fa39e233cd7',
name: 'Estrada',
family: 'Tate',
phoneNumber: '+98 (844) 586-3191',
},
{
id: 'decca57e-7d69-4152-99f0-3a56262db788',
name: 'Aimee',
family: 'Morrow',
phoneNumber: '+98 (920) 522-2471',
},
{
id: '1b7d57b2-0169-4949-a1e9-42137085dcda',
name: 'Elinor',
family: 'Gill',
phoneNumber: '+98 (981) 525-3212',
},
{
id: 'db3e2d62-d8cf-4809-9226-49a34a4fbea1',
name: 'Velasquez',
family: 'Taylor',
phoneNumber: '+98 (879) 440-2756',
},
{
id: 'a3f6bda0-0975-4e4e-8bcd-1a9be84777ac',
name: 'Hardin',
family: 'Rowe',
phoneNumber: '+98 (945) 564-3793',
},
{
id: '17c0c061-3215-429d-9172-be3d8ca69119',
name: 'Miranda',
family: 'Hendrix',
phoneNumber: '+98 (804) 519-2572',
},
{
id: '634862e6-09bf-41c3-8553-c8807aab2b22',
name: 'Kristin',
family: 'Mcgowan',
phoneNumber: '+98 (974) 533-3607',
},
{
id: '4214933e-a57c-495c-8c32-ddb9960556f6',
name: 'Ila',
family: 'Gutierrez',
phoneNumber: '+98 (814) 546-2444',
},
{
id: '74f62419-a4eb-414f-9a84-d82dfd117917',
name: 'Sophie',
family: 'Pena',
phoneNumber: '+98 (962) 458-3451',
},
{
id: 'c3cc6ff3-d0ef-45fb-b6a7-b499ff13fedf',
name: 'Sara',
family: 'Burton',
phoneNumber: '+98 (937) 516-2702',
},
{
id: '969ca3e7-78ad-4fbe-b413-0e12021d07b9',
name: 'Valeria',
family: 'Spence',
phoneNumber: '+98 (968) 403-2227',
},
{
id: 'e73ba5bb-adb7-423e-a6e9-22be1501987c',
name: 'Stefanie',
family: 'Erickson',
phoneNumber: '+98 (950) 545-2095',
},
{
id: '83ae1198-c533-43dd-ae1a-85bc5f503293',
name: 'Bean',
family: 'Newman',
phoneNumber: '+98 (824) 504-2755',
},
{
id: 'a2f3949a-7d24-4c42-ac6d-573c11c903fd',
name: 'Tracie',
family: 'Keith',
phoneNumber: '+98 (981) 499-3453',
},
{
id: '7f52c00e-4ccb-4458-ad0c-bb7d9ff759a4',
name: 'Cardenas',
family: 'Trevino',
phoneNumber: '+98 (942) 476-2939',
},
{
id: '48f9d38e-9211-420f-968e-098f7a3dfeaf',
name: 'Yolanda',
family: 'Hamilton',
phoneNumber: '+98 (936) 418-3047',
},
{
id: '0f739ca9-1a2a-41f1-b703-9ddc98e7b328',
name: 'Mendoza',
family: 'Cunningham',
phoneNumber: '+98 (980) 547-3912',
},
{
id: '3e3e68cc-053a-4811-9987-7c700fcc32ee',
name: 'Singleton',
family: 'Harmon',
phoneNumber: '+98 (975) 564-3890',
},
{
id: 'd7d6e72b-5a63-440d-bdf0-125bd9d8d4dd',
name: 'Witt',
family: 'Huffman',
phoneNumber: '+98 (867) 475-3332',
},
{
id: '46c951e3-ab31-44ca-b5eb-2f988dd57562',
name: 'James',
family: 'Mccullough',
phoneNumber: '+98 (895) 507-2233',
},
{
id: '9b7b2396-5758-44be-9d5d-4eef04742a53',
name: 'Stevenson',
family: 'Robles',
phoneNumber: '+98 (847) 587-3623',
},
{
id: 'a0db4093-ec6b-41ed-8ca5-a9b43ee302b7',
name: 'Mcknight',
family: 'Perry',
phoneNumber: '+98 (881) 443-2991',
},
{
id: '1ad02420-9ac0-4250-940c-fc0ea24964a8',
name: 'Flowers',
family: 'Emerson',
phoneNumber: '+98 (933) 514-3019',
},
{
id: 'b2ffa8f4-4f95-4b9d-a219-780d5f4dbd69',
name: 'Karin',
family: 'James',
phoneNumber: '+98 (958) 486-2623',
},
{
id: 'd87e51b3-80db-4e7c-b0d0-9f39c633b70a',
name: 'Marisol',
family: 'William',
phoneNumber: '+98 (961) 533-3778',
},
{
id: '1ce985cc-f810-4972-8e9b-59dfb67b161c',
name: 'Emilia',
family: 'Black',
phoneNumber: '+98 (984) 592-2589',
},
{
id: '4b5be713-cb7e-46cb-b72b-e8c4f644693a',
name: 'Irene',
family: 'Miles',
phoneNumber: '+98 (950) 431-2351',
},
{
id: 'c1ff3dfd-21b4-4824-aeef-d3b6a36ba3ab',
name: 'Tonia',
family: 'Serrano',
phoneNumber: '+98 (955) 511-2933',
},
{
id: '97eec6ce-ccb0-4050-b413-96a0a4afce7a',
name: 'Thelma',
family: 'Odom',
phoneNumber: '+98 (844) 524-2142',
},
{
id: 'e9111905-fc22-4e35-a3a6-4a4c0b6bc0c0',
name: 'Kerry',
family: 'Rose',
phoneNumber: '+98 (947) 581-2952',
},
{
id: '9129d569-5acd-43b7-8eac-de7a9f4f7336',
name: 'Mcgee',
family: 'Hernandez',
phoneNumber: '+98 (865) 521-3785',
},
{
id: '221e68ec-0462-4418-88c9-d433f1d60ae1',
name: 'Shepard',
family: 'Santiago',
phoneNumber: '+98 (892) 446-3690',
},
{
id: '429b8bcc-028d-4989-89d9-5519dc6fec0f',
name: 'Emily',
family: 'French',
phoneNumber: '+98 (836) 537-3964',
},
{
id: 'c750ebd9-9aa0-426f-b668-5702500f7178',
name: 'Clements',
family: 'Carson',
phoneNumber: '+98 (916) 460-3168',
},
{
id: '2f75f87c-65f9-479b-bec4-5c83fbbfb96a',
name: 'Gibbs',
family: 'Burch',
phoneNumber: '+98 (950) 543-2339',
},
{
id: '6dbf72ff-5761-4c0b-9781-93cd4606fd4b',
name: 'Pearson',
family: 'Petersen',
phoneNumber: '+98 (889) 591-2938',
},
{
id: '8944a741-1f18-4d30-8536-a306ab1b5b8f',
name: 'Stout',
family: 'Castillo',
phoneNumber: '+98 (938) 578-3360',
},
{
id: 'aca707ac-97fe-4f7f-8665-ab34d863bc3a',
name: 'Leonard',
family: 'Finch',
phoneNumber: '+98 (821) 441-3242',
},
{
id: '43cc621c-17fb-4196-a28e-658f1fc4752e',
name: 'Nelson',
family: 'Kirkland',
phoneNumber: '+98 (869) 431-2288',
},
{
id: '63292aab-ddc3-4dd8-851a-6430c85f3ad3',
name: 'Olson',
family: 'Sherman',
phoneNumber: '+98 (865) 446-3664',
},
{
id: '40f28107-6a4d-4c1c-a506-a8dc4d65c6e4',
name: 'Bray',
family: 'Hansen',
phoneNumber: '+98 (808) 532-3820',
},
{
id: '02ab1c0b-654f-4277-92dd-1a0219bda442',
name: 'Antonia',
family: 'Bell',
phoneNumber: '+98 (802) 572-3045',
},
{
id: '15019624-9683-4977-a2d8-dc47e434f086',
name: 'Cecile',
family: 'Maxwell',
phoneNumber: '+98 (804) 452-2908',
},
];
//
tempTableProps: XTableConfig<Partial<Temp>> = {
items: [...this.tempItems],
columns: [
{
name: 'name',
title: 'Name',
sortable: true,
description: 'Name of Person',
},
{
name: 'family',
title: 'Family',
sortable: true,
description: 'LastName of Person',
// hidden: this.managerService.isMobileUi$
},
{
name: 'phoneNumber',
title: 'Phone Number',
description: 'Phone Number of Person',
// hidden: this.managerService.isMobileUi$
},
{
customColumn: true,
name: 'Actions',
title: 'Actions',
description: 'row Action',
},
],
};
//#endregion
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت نمایش داده های مرتبط بصورت جدول بکار می رود.
`;
readonly contentEn = `
# ${this.toolbarTitle}
this Component used to show a collection of related Data in a Table.
`;
//
readonly sample1 =
'```typescript' +
`
//
interface Temp {
id?: string;
name: string;
family: string;
phoneNumber: string;
value: string;
slided: boolean;
checked: boolean;
level: number;
person: string;
dob: Date;
}
//
tempTableProps: XTableProps<Partial<Temp>> = {
items: [
{
id: '
71f14439-262f-44bf-8dc8-ee85929c349c',
name: 'Deidre',
family: 'Thomas',
phoneNumber: '+98 (864) 472-3812'
},
{
id: '
caa22853-dd2d-4669-8b63-b1fe4a38ea07',
name: 'Hubbard',
family: 'Preston',
phoneNumber: '+98 (899) 452-3720'
},
{
id: '
ccb62dc4-a06b-412d-800d-02d18f54a0e0',
name: 'Cooley',
family: 'Nixon',
phoneNumber: '+98 (926) 459-2360'
},
{
...
},
...
],
columns: [
{
name: 'name',
title: 'Name',
sortable: true,
description: 'Name of Person'
},
{
name: 'family',
title: 'Family',
sortable: true,
description: 'LastName of Person'
},
{
name: 'phoneNumber',
title: 'Phone Number',
description: 'Phone Number of Person'
},
{
customColumn: true,
name: 'Actions',
title: 'Actions',
description: 'row Action'
}
]
};
` +
'```';
//
readonly sample2 =
'```html' +
`
<x-table
[showHeader]="true"
[showSearchBar]="true"
[showPaginator]="true"
[showActionBar]="true"
[selectableRows]="true"
[color]="ColorNames.Medium"
[properties]="tempTableProps"
[headerColor]="ColorNames.Dark"
[actionBarColor]="ColorNames.Primary"
[searchBarColor]="ColorNames.Primary"
[paginatorColor]="ColorNames.Primary"
(rowSelected)="handleRowSelected($event)"
[searchBarPosition]="
TableItemPositions.TOP"
[actionBarPosition]="
TableItemPositions.TOP"
[paginatorPosition]="
TableItemPositions.BOTTOM"
(rowSelectionChanged)="
handleRowSelectionChanged($event)"
>
</x-table>
` +
'```';
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//
handleRowSelected(row: any) {
console.log('handleRowSelected: ', row);
}
//
handleRowSelectionChanged(selectedRows: any[]) {
console.log('handleRowSelectionChanged: ', selectedRows);
}
//
async handleRemoveItems(items: Partial<Temp>[]) {
//
console.log('Remove Items: ', items);
if (!this.hasChild(items)) {
return;
}
//
const removedItems = this.tempItems.filter((i) => !items.includes(i));
console.log('num of items before remove: ', this.tempItems.length);
console.log('num of items after remove: ', removedItems.length);
//
const newTableProps = {
...this.tempTableProps,
items: [...removedItems],
};
//
this.tempTableProps = {
...newTableProps,
};
//
this.detectChanges();
}
//#endregion
}
@@ -0,0 +1,104 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Content -->
<x-markdown
[mode]="'preview'"
[hasToolbar]="false"
[content]="getContent('content')"
></x-markdown>
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/modules/XTabsModule.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- Samples -->
<x-markdown
[isInPage]="true"
[mode]="'preview'"
[content]="sample1"
[hasToolbar]="false"
[wrapWithCard]="true"
[cssClass]="'code-block'"
[cardTitle]="resourceProvider(ResourceIDs.sample)"
></x-markdown>
<!-- Components -->
<x-tabs
#xTabs
[isInPage]="true"
[swipable]="true"
[loopTabs]="false"
[selectedIndex]="1"
[wrapWithCard]="true"
[dynamicHeight]="false"
[color]="ColorNames.Dark"
[alignTabs]="TabAligns.STRETCH"
[activeTabColor]="ColorNames.Medium"
[tabPaginatorColor]="ColorNames.Dark"
[tabIndicatorColor]="ColorNames.Warning"
[headerPosition]="TabsHeaderPositions.BELOW"
>
<x-tab>
<div x-tab-label>
Tab 1
</div>
<div class="tab-wrapper" [xColor]="ColorNames.Danger">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis similique
reiciendis vero vel. Et, in nemo. Sapiente doloremque provident ex
dolore, expedita totam ipsam architecto vero mollitia magni. Corporis,
dolore.
</div>
</x-tab>
<x-tab>
<div x-tab-label>
Tab 2
</div>
<div class="tab-wrapper" [xColor]="ColorNames.Secondary">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis similique
reiciendis vero vel. Et, in nemo. Sapiente doloremque provident ex
dolore, expedita totam ipsam architecto vero mollitia magni. Corporis,
dolore.
</div>
</x-tab>
<x-tab>
<div x-tab-label>
Tab 3
</div>
<div class="tab-wrapper" [xColor]="ColorNames.Warning">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis similique
reiciendis vero vel. Et, in nemo. Sapiente doloremque provident ex
dolore, expedita totam ipsam architecto vero mollitia magni. Corporis,
dolore.
</div>
</x-tab>
<x-tab>
<div x-tab-label>
Tab 4
</div>
<div class="tab-wrapper" [xColor]="color">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Omnis similique
reiciendis vero vel. Et, in nemo. Sapiente doloremque provident ex
dolore, expedita totam ipsam architecto vero mollitia magni. Corporis,
dolore.
</div>
</x-tab>
</x-tabs>
</v-page>
@@ -0,0 +1,8 @@
.tab-wrapper {
padding: {
top: 24px;
left: 6px;
right: 6px;
bottom: 24px;
};
}
+176
View File
@@ -0,0 +1,176 @@
import {
XTabAlign,
XIconNames,
XTabsHeaderPosition,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { VPageComponent } from '../../../views/v-page/v-page.component';
import { AppResourceIDs } from 'src/app/config/app.localization.config';
import { XResourceIDs, isNullOrEmptyString, XColor } from 'x-framework-core';
@Component({
selector: 'app-tabs',
templateUrl: './tabs.page.html',
styleUrls: ['./tabs.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class TabsPage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = AppResourceIDs.tabs;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(AppResourceIDs.tabs_description);
toolbarShowSubTitle = true;
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
//#endregion
//
readonly TabAligns = Object.assign({}, XTabAlign);
readonly TabsHeaderPositions = Object.assign({}, XTabsHeaderPosition);
//
// Content ...
readonly contentFa = `
# ${this.toolbarTitle}
این مولفه جهت نمایش محتواهای مختلف در غالب برگه ها و دسته بندی آن ها بکار می رود
`;
readonly contentEn = `
# ${this.toolbarTitle}
this component used to group several contents and show them in tabs area.
`;
//
readonly sample1 =
'```html' +
`
<x-tabs
#xTabs
[startIndex]="1"
[swipable]="true"
[loopTabs]="false"
[dynamicHeight]="false"
[color]="ColorNames.Dark"
[alignTabs]="TabAligns.START"
[headerPosition]="
TabsHeaderPositions.BELOW"
>
<x-tab>
<div x-tab-label>
Tab 1
</div>
<div
class="tab-wrapper"
[xColor]="ColorNames.Danger"
>
Lorem ipsum dolor sit amet
consectetur adipisicing elit.
Omnis similique reiciendis vero
vel. Et, in nemo. Sapiente
doloremque provident ex dolore,
expedita totam ipsam architecto
vero mollitia magni. Corporis, dolore.
</div>
</x-tab>
<x-tab>
<div x-tab-label>
Tab 2
</div>
<div
class="tab-wrapper"
[xColor]="ColorNames.Secondary"
>
Lorem ipsum dolor sit amet
consectetur adipisicing elit.
Omnis similique reiciendis vero
vel. Et, in nemo. Sapiente
doloremque provident ex dolore,
expedita totam ipsam architecto
vero mollitia magni. Corporis, dolore.
</div>
</x-tab>
<x-tab>
<div x-tab-label>
Tab 3
</div>
<div
class="tab-wrapper"
[xColor]="ColorNames.Warning"
>
Lorem ipsum dolor sit amet
consectetur adipisicing elit.
Omnis similique reiciendis vero
vel. Et, in nemo. Sapiente
doloremque provident ex dolore,
expedita totam ipsam architecto
vero mollitia magni. Corporis, dolore.
</div>
</x-tab>
<x-tab>
<div x-tab-label>
Tab 4
</div>
<div
class="tab-wrapper"
[xColor]="color"
>
Lorem ipsum dolor sit amet
consectetur adipisicing elit.
Omnis similique reiciendis vero
vel. Et, in nemo. Sapiente
doloremque provident ex dolore,
expedita totam ipsam architecto
vero mollitia magni. Corporis, dolore.
</div>
</x-tab>
</x-tabs>
` +
'```';
//
//#region UI Providers ...
//
// Provide content based on current locale ...
getContent(title: string) {
//
if (isNullOrEmptyString(title)) {
return '';
}
//
const currentLocale = this.managerService.currentLocale;
//
const varName =
title +
(currentLocale === 'en-US'
? 'En'
: currentLocale === 'fa-IR'
? 'Fa'
: '');
const result = this[`${varName}`];
//
return result || '';
}
//#endregion
}
@@ -0,0 +1,69 @@
<v-page
[hasSide]="true"
[toolbarTitle]="toolbarTitle"
[toolbarSubTitle]="toolbarSubTitle"
[toolbarShowSubTitle]="toolbarShowSubTitle"
>
<!-- Content -->
<x-card [isInPage]="true" [showActions]="true" [color]="ColorNames.Light">
<!-- Actions -->
<div actions>
<a
target="_blank"
href="https://docs.x-framework.ir/x-framework-components/components/XTreeComponent.html"
>{{resourceProvider(ResourceIDs.documentation)}}</a
>
</div>
</x-card>
<!-- TODO: Complete this ... -->
<x-button
[type]="ButtonTypes.Raised"
[title]="'Expand All'"
(clicked)="handleTreeExpandAll()"
></x-button>
<x-button
[type]="ButtonTypes.Raised"
[title]="'Collapse All'"
(clicked)="handleTreeCollapseAll()"
></x-button>
<x-button
[type]="ButtonTypes.Raised"
[title]="'Expand'"
(clicked)="handleTreeExpand(1)"
></x-button>
<x-button
[type]="ButtonTypes.Raised"
[title]="'Collapse'"
(clicked)="handleTreeCollapse(1)"
></x-button>
<!-- Tree -->
<x-tree
[isInPage]="true"
[nodes]="treeNodes"
[wrapWithCard]="true"
[nodeTemplate]="todoItemRef"
[actionProvider]="treeActionProvider"
[toggleIconColor]="ColorNames.SuccessShade"
(onNodeToggle)="handleTreeNodeToggled($event)"
></x-tree>
</v-page>
<!-- ToDo Item Template -->
<ng-template #todoItemRef let-data let-nodeId="nodeId">
<!-- Title -->
<div class="v-todo-title">{{ nodeId }}</div>
<!-- Body -->
<ng-container *ngIf="(data | xAs : XProgrammingTech) as data">
<div class="v-todo-description">
<div>Name: {{ data.name }}</div>
<div>Description: {{ data.description }}</div>
</div>
</ng-container>
</ng-template>
@@ -0,0 +1,3 @@
:host(::ng-deep.mat-tree-node) {
align-items: baseline !important;
}
+301
View File
@@ -0,0 +1,301 @@
import { Subject } from 'rxjs';
import {
XTreeNode,
XIconNames,
XButtonType,
XTreeAction,
XTreeNodeToggle,
XTreeActionModel,
} from 'x-framework-components';
import { Component } from '@angular/core';
import { XResourceIDs } from 'x-framework-core';
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
interface ProgrammingTech {
name: string;
description: string;
}
@Component({
selector: 'app-tree',
templateUrl: './tree.page.html',
styleUrls: ['./tree.page.scss'],
})
// tslint:disable-next-line:component-class-suffix
export class TreePage extends VPageComponent {
//
//#region Props ...
//
//#region Page Props ...
titleRes = this.AppResourceIDs.tree;
toolbarTitle = this.resourceProvider(this.titleRes);
toolbarSubTitle = this.resourceProvider(this.AppResourceIDs.tree_description);
toolbarShowSubTitle = true;
//
treeActionProvider = new Subject<XTreeActionModel>();
//#endregion
//
// Prepare All Resource IDs ...
readonly ResourceIDs = Object.assign(
Object.assign({}, XResourceIDs),
this.AppResourceIDs
) as any;
//
readonly IconNames = Object.assign({}, XIconNames);
readonly ButtonTypes = Object.assign({}, XButtonType);
//#endregion
//
XProgrammingTech: ProgrammingTech;
treeNodes = this.getTreeNodes();
//
// TODO: Complete this ...
handleTreeNodeToggled(event: XTreeNodeToggle) {
console.log('handleTreeNodeToggled: ', event);
}
handleTreeExpand(id: number) {
console.log('handleTreeExpand: ', id);
//
this.treeActionProvider.next({
action: XTreeAction.Expand,
payload: id,
});
}
handleTreeCollapse(id: number) {
console.log('handleTreeCollapse: ', id);
//
this.treeActionProvider.next({
action: XTreeAction.Collapse,
payload: id,
});
}
handleTreeExpandAll() {
console.log('handleTreeExpandAll');
//
this.treeActionProvider.next({
action: XTreeAction.ExpandAll,
});
}
handleTreeCollapseAll() {
console.log('handleTreeCollapseAll');
//
this.treeActionProvider.next({
action: XTreeAction.CollapseAll,
});
}
//
//#region XTree ...
private getTreeNodes() {
return [
//
// Frontend ...
{
id: '1',
tooltip: 'Frontend Development Technologies',
data: {
name: 'Frontend',
description: 'Frontend Development Technologies',
},
childs: [
//
// Angular ...
{
id: '1/1',
tooltip: 'Angular Framework',
data: {
name: 'Angular',
description: 'Angular Framework',
},
childs: [
//
// Components ...
{
id: '1/1/1',
data: {
name: 'Components',
description:
"Components is an important part of Angular's building blocks, since it is on top of Component based architecture",
},
childs: [],
} as XTreeNode<ProgrammingTech>,
],
} as XTreeNode<ProgrammingTech>,
//
// React ...
{
id: '1/2',
data: {
name: 'React',
description:
'a Collection of Web tools to create Web client apps',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
//
// Vue ...
{
id: '1/3',
data: {
name: 'Vue',
description: 'a Frontend Development Frameworks',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
],
} as XTreeNode<ProgrammingTech>,
//
// Desktop ...
{
id: '2',
data: {
name: 'Desktop',
description: 'Desktop Development Technologies',
},
childs: [
//
// .Net ...
{
id: '2/1',
data: {
name: '.Net',
description: 'a collction of languages for creating Desktop Apps',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
//
// Electron ...
{
id: '2/2',
data: {
name: 'Electron',
description:
'a collection of tools to Convert a Web app into Desktop Apps',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
],
} as XTreeNode<ProgrammingTech>,
//
// Mobile ...
{
id: '3',
data: {
name: 'Mobile',
description: 'Mobile Development Technologies',
},
childs: [
//
// J2ME ...
{
id: '3/1',
data: {
name: 'J2ME',
description:
'Java Mobile edition, using JAVA language to creating java based Mobile Applications',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
//
// CBuilder ...
{
id: '3/2',
data: {
name: 'CBuilder',
description:
'using c++ to creating Symbian based Mobile Applications',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
//
// Android SDK ...
{
id: '3/3',
data: {
name: 'Android',
description:
'using Android SDK to create Android OS based Mobile Applications by help of Java/Kotlin',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
//
// Swift ...
{
id: '3/4',
data: {
name: 'Swift',
description: 'create iOs based Mobile Applications',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
],
} as XTreeNode<ProgrammingTech>,
//
// Backend ...
{
id: '4',
data: {
name: 'Backend',
description: 'Backend Development Technologies',
},
childs: [
//
// Php ...
{
id: '4/1',
data: {
name: 'Php',
description: 'one of most popular backend development languages',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
//
// Python ...
{
id: '4/2',
data: {
name: 'Python',
description: 'a multi usage language to develop applications',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
//
// NodeJS ...
{
id: '4/3',
data: {
name: 'Node JS',
description:
'a chrome engin based tool to create multi purpose applications',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
//
// .Net Core ...
{
id: '4/4',
data: {
name: '.net core',
description:
'a lightweigt, fast and cross platform version of .Net which provided by Microsoft to Develop Applications',
},
childs: [],
} as XTreeNode<ProgrammingTech>,
],
} as XTreeNode<ProgrammingTech>,
];
}
//#endregion
}