Take a break and relax
Workrave is a free program that assists in the recovery and prevention of Repetitive Strain Injury (RSI). It monitors your keyboard and mouse usage and using this information, it frequently alerts you to take microbreaks, rest breaks and restricts you to your daily computer usage.
TypeScript 3.1 RC منتشر شد
ادغام قالب admin در reactjs
Integrate Admin Template in ReactJS is today’s leading topic. If you are working on Web Application then admin panel template is neccessary for any application. You need to download the ADMINLTE template from its original website: AdminLTE
تا اینجای کار ساخت کامپوننتها را با React.createClass که تفاوتی با توسعه (ارث بری) از کلاس React.Component ندارد، انجام دادهایم. اما ساخت کامپوننتها به صورت یک تابع هم مزیتهایی را دارد. اول از همه باید بدانیم که ساخت کامپوننت توسط تابع، بدون وضعیت خواهد بود که به آن Stateless میگویند. به دلیل نداشتن وضعیت، کامپوننتهای تابعی را کمی بهتر میشود برای استفاده مجدد به کار برد. در کامپوننتهای غیر تابعی که Stateful هستند به دلیل احتمال وابستگی وضعیت کامپوننت به خارج از کلاس، مانند مثال قسمت چهارم که کامپوننت در انتظار کلیک یک دکمه خاص توسط کاربر بود، مدیریت استفاده مجدد ازکامپوننت چالش برانگیز خواهد شد.
اعتبارسنجی دادههای ورودی
برای مدیریت بهتر کامپوننتها جهت استفاده مجدد از آنها بهتر است ورودیهای کامپوننت را اعتبارسنجی کنیم. این ورودیها چه برای استفاده داخلی کامپوننت، یا جهت مشخص کردن وضعیت آن، بر رفتار کامپوننت تاثیر زیادی دارند. React مجموعهای از اعتبار سنجیها را دارد که میشود به کامپوننت اضافه کرد. باید توجه داشته باشیم که پیامهای خطای این اعتبارسنجیها فقط در حالت Development Mode قابل استفاده هستند. به زبان ساده اگر از react.min.js استفاده کنید، پیامهای خطا را نخواهید دید. باید فایلها را به نوع react.js تبدیل کنید. اعتبارسنجی React در زمان توسعه و برای توسعه دهندگان استفاده میشود.
مثال نوشیدنیها در قسمت چهارم میتوانست نام نوشیدنی و قیمت آن را نمایش دهد و همچنین میتوانستیم به لیست نوشیدنیها، موردی را اضافه کنیم. اگر ورودی قیمت، اعتبارسنجی نشود، میتوان رشتهای را بجای عدد به عنوان قیمت به کامپوننت ارسال کرد. نحوه اعتبارسنجی قیمت نوشیدنیها به صورت زیر است.
const MenuItem = props => ( <li className="list-group-item"> <span className="badge">{props.price}</span> <p>{props.item}</p> </li> ) MenuItem.propTypes = { price: React.PropTypes.number };
شیء propTypes را به کامپوننت اضافه کردهایم و در تنظیمات آن میتوانیم برای هر پارامتر ورودی یکی از اعضای PropTypes از React را که مناسب حال پارامتر است، انتخاب کنیم. در مثال بالا مشخص کردهایم که ورودی price باید عدد باشد و اگر مثلا رشتهای را بجای عدد ارسال کنیم، پیام خطای زیر را در Console خواهیم داشت.
Warning: Failed prop type: Invalid prop `price` of type `string` supplied to `MenuItem`, expected `number`. in MenuItem (created by Menu) in Menu
یا میتوانستیم از React.PropTypes.number.isRequired استفاده کنیم تا درج مقداری برای این ورودی الزامی باشد. اگر اعتبارسنجیهای React کافی نبودند میتوانیم اعتبارسنجیهای سفارشی خودمان را ایجاد کنیم. در مثال زیر میخواهیم ورودی price بیشتر از 15000 نباشد.
MenuItem.propTypes = { price: (props, price)=>{ if(props[price] > 15000){ return new Error("Too expensive!"); } } };
let MenuItem = React.createClass({ propTypes: { price: React.PropTypes.number } }); class MenuItem extends React.Component{ static propTypes = { price: React.PropTypes.number }; }
نوعهای دیگر برای اعتبارسنجی شامل موارد زیر هستند و البته مرجع تمام اعتبارسنجیهای React را میتوانید در اینجا بررسی کنید.
- React.PropTypes.array
- React.PropTypes.bool
- React.PropTypes.number
- React.PropTypes.object
- React.PropTypes.string
مقدار پیشفرض دادههای ورودی
یکی از امکانات مفید دیگر برای مدیریت مقدارهای ورودی، مشخص کردن مقدار پیشفرضی برای یک پارامتر است. برای مثال اگر برای قیمت یک نوشیدنی مقداری وارد نشد، یک حداقل قیمت برای آن در نظر بگیریم، هر چند که ایده و روشی اشتباه است!
MenuItem.defaultProps = { price: 1000 };
همانطور که میبینید روش کار مشابه با اعتبارسنجی است و برای مشخص کردن مقدار پیشفرض برای React.creatClass از متد getDefaultProps که عضوی از React است، استفاده میکنیم.
let MenuItem = React.createClass({ getDefaultProps() { return { price: 200 } }, render() { return ( <li className="list-group-item"> <span className="badge">{this.props.price}</span> <p>{this.props.item}</p> </li> ); } });
حمله به بدهیهای فنی
Technical Debt is a metaphor for shortcuts and hacks in software that make it more difficult to change and maintain than it could be with an optimal design. Many applications have accumulated a large amount of technical debt, and figuring out how to deal with it is a fairly common challenge for many developers
کانورتور عمومی برای مقادیر در WPF
نکتهای که در اینجا مدنظر است، دسترسی به عدد جمع آخر گزارش و سپس بر اساس آن، ساخت دو ستون اضافی ذیل جدول اصلی گزارش است که موارد مالیات، عوارض، جمع کل و مبلغ به حروف را نسبت به مثالهای قبلی، اضافهتر دارد.
در ادامه کدهای کامل این مثال را مشاهده میکنید. همچنین این کد و کلاسهای وابسته به آن مانند User و TransparentTemplate به سورسهای کتابخانه PdfReport نیز اضافه شدهاند.
using System; using System.Collections.Generic; using iTextSharp.text; using iTextSharp.text.pdf; using PdfReportSamples.Models; using PdfReportSamples.Templates; using PdfRpt.Core.Contracts; using PdfRpt.Core.Helper; using PdfRpt.FluentInterface; namespace PdfReportSamples.Tax { public class TaxPdfReport { public IPdfReportData CreatePdfReport() { return new PdfReport().DocumentPreferences(doc => { doc.RunDirection(PdfRunDirection.RightToLeft); doc.Orientation(PageOrientation.Portrait); doc.PageSize(PdfPageSize.A4); doc.DocumentMetadata(new DocumentMetadata { Author = "Vahid", Application = "PdfRpt", Keywords = "Test", Subject = "Test Rpt", Title = "Test" }); }) .DefaultFonts(fonts => { fonts.Path(AppPath.ApplicationPath + "\\fonts\\irsans.ttf", Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\verdana.ttf"); }) .PagesFooter(footer => { footer.DefaultFooter(DateTime.Now.ToString("MM/dd/yyyy")); }) .PagesHeader(header => { header.DefaultHeader(defaultHeader => { defaultHeader.ImagePath(AppPath.ApplicationPath + "\\Images\\01.png"); defaultHeader.Message("گزارش جدید ما"); }); }) .MainTableTemplate(template => { template.CustomTemplate(new TransparentTemplate()); }) .MainTablePreferences(table => { table.ColumnsWidthsType(TableColumnWidthType.Relative); }) .MainTableDataSource(dataSource => { var listOfRows = new List<User>(); for (int i = 0; i < 7; i++) { listOfRows.Add(new User { Id = i, LastName = "نام خانوادگی " + i, Name = "نام " + i, Balance = i + 1000 }); } dataSource.StronglyTypedList<User>(listOfRows); }) .MainTableSummarySettings(summarySettings => { summarySettings.OverallSummarySettings("جمع کل"); summarySettings.PreviousPageSummarySettings("نقل از صفحه قبل"); summarySettings.PageSummarySettings("جمع صفحه"); }) .MainTableColumns(columns => { columns.AddColumn(column => { column.PropertyName("rowNo"); column.IsRowNumber(true); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.IsVisible(true); column.Order(0); column.Width(1); column.HeaderCell("ردیف"); }); columns.AddColumn(column => { column.PropertyName<User>(x => x.Id); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.IsVisible(true); column.Order(1); column.Width(2); column.HeaderCell("شماره"); }); columns.AddColumn(column => { column.PropertyName<User>(x => x.Name); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.IsVisible(true); column.Order(2); column.Width(3); column.HeaderCell("نام"); }); columns.AddColumn(column => { column.PropertyName<User>(x => x.LastName); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.IsVisible(true); column.Order(3); column.Width(3); column.HeaderCell("نام خانوادگی"); }); columns.AddColumn(column => { column.PropertyName<User>(x => x.Balance); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.IsVisible(true); column.Order(4); column.Width(2); column.HeaderCell("موجودی"); column.ColumnItemsTemplate(template => { template.TextBlock(); template.DisplayFormatFormula(obj => obj == null ? string.Empty : string.Format("{0:n0}", obj)); }); column.AggregateFunction(aggregateFunction => { aggregateFunction.NumericAggregateFunction(AggregateFunction.Sum); aggregateFunction.DisplayFormatFormula(obj => obj == null ? string.Empty : string.Format("{0:n0}", obj)); }); }); }) .MainTableEvents(events => { events.DataSourceIsEmpty(message: "There is no data available to display."); events.MainTableAdded(args => { var balanceData = args.LastOverallAggregateValueOf<User>(u => u.Balance); var balance = double.Parse(balanceData, System.Globalization.NumberStyles.AllowThousands); var others = Math.Round(balance * 1.8 / 100); var tax = Math.Round(balance * 2.2 / 100); var total = balance + tax + others; var taxTable = new PdfPTable(args.Table); // Create a clone of the MainTable's structure taxTable.AddSimpleRow( null /* null = empty cell */, null, null, (data, cellProperties) => { data.Value = "مالیات"; cellProperties.PdfFont = args.PdfFont; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }, (data, cellProperties) => { data.Value = string.Format("{0:n0}", tax); cellProperties.PdfFont = args.PdfFont; cellProperties.BorderColor = BaseColor.LIGHT_GRAY; cellProperties.ShowBorder = true; }); taxTable.AddSimpleRow( null, null, null, (data, cellProperties) => { data.Value = "عوارض"; cellProperties.PdfFont = args.PdfFont; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }, (data, cellProperties) => { data.Value = string.Format("{0:n0}", others); cellProperties.PdfFont = args.PdfFont; cellProperties.BorderColor = BaseColor.LIGHT_GRAY; cellProperties.ShowBorder = true; }); taxTable.AddSimpleRow( null, null, null, (data, cellProperties) => { data.Value = "جمع کل"; cellProperties.PdfFont = args.PdfFont; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }, (data, cellProperties) => { data.Value = string.Format("{0:n0}", total); cellProperties.PdfFont = args.PdfFont; cellProperties.BorderColor = BaseColor.LIGHT_GRAY; cellProperties.ShowBorder = true; }); taxTable.AddSimpleRow( null, null, null, (data, cellProperties) => { data.Value = "قابل پرداخت"; cellProperties.PdfFont = args.PdfFont; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }, (data, cellProperties) => { data.Value = total.NumberToText(Language.Persian) + " ریال"; cellProperties.PdfFont = args.PdfFont; cellProperties.BorderColor = BaseColor.LIGHT_GRAY; cellProperties.ShowBorder = true; cellProperties.PdfFontStyle = DocumentFontStyle.Bold; }); args.PdfDoc.Add(taxTable); }); }) .Export(export => { export.ToExcel(); }) .Generate(data => data.AsPdfFile(AppPath.ApplicationPath + "\\Pdf\\TaxReportSample.pdf")); } } }
تنها تفاوت این مثال با مثالهای قبلی، کدهای مرتبط با متد events.MainTableAdded میباشند.
توسط متد args.LastOverallAggregateValueOf، میتوان به مقدار نهایی متد تجمعی تعریف شده برای یک ستون خاص دسترسی یافت:
var balanceData = args.LastOverallAggregateValueOf<User>(u => u.Balance); var balance = double.Parse(balanceData, System.Globalization.NumberStyles.AllowThousands);
var others = Math.Round(balance * 1.8 / 100); var tax = Math.Round(balance * 2.2 / 100); var total = balance + tax + others;
var taxTable = new PdfPTable(args.Table);
taxTable.AddSimpleRow( null /* null = empty cell */, null, null, (data, cellProperties) => { data.Value = "مالیات"; cellProperties.PdfFont = args.PdfFont; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }, (data, cellProperties) => { data.Value = string.Format("{0:n0}", tax); cellProperties.PdfFont = args.PdfFont; cellProperties.BorderColor = BaseColor.LIGHT_GRAY; cellProperties.ShowBorder = true; });
با مقدار دهی data، مقدار مورد نظر در آن سلول ثبت میگردد. با مقدار دهی خواص cellProperties، نوع قلم، جهت قرارگیری و سایر تنظیماتی را که ملاحظه میکنید، میتوان اعمال کرد.
و در آخر لازم است که این جدول جدید را به شیء Document اضافه کنیم تا نمایش داده شود:
args.PdfDoc.Add(taxTable);
یک نکته:
متد NumberToText جزئی از کتابخانه PdfReport (تعریف شده در فضای نام PdfRpt.Core.Helper) است و برای نمایش رقم به حروف میتواند مورد استفاده قرار گیرد:
total.NumberToText(Language.Persian)
<div condition="Model.Approved"> <p> This website has <strong surround="em">@Model.Approved</strong> been approved yet. Visit www.contoso.com for more information. </p> </div> <div condition="!User.Identity.IsAuthenticated">I'm not a valid user</div> <div condition="User.Identity.IsAuthenticated">I can use the system</div>