private void AllTransactionsToGui(DateTime?from, DateTime?to) { lbAllBoughtItems.DisplayMember = "Text"; if (Configuration.Instance.UserBaseProfile.IsValid()) { Result <List <Transaction> > transactionsResult = blendleParser.FetchAllTransactions(); if (transactionsResult.Succeeded && transactionsResult.Data != null) { bool validInput = false; Func <Transaction, bool> transactionFilter = (t) => true; //if and selection is made if (from != null && to != null && to.Value > from.Value) { transactionFilter = (t) => t.CreatedAtLocal >= from.Value && t.CreatedAtLocal <= to.Value; validInput = true; } List <Transaction> filteredTransactions = transactionsResult.Data.Where(transactionFilter).ToList(); lbAllBoughtItems.Items.Clear(); foreach (var transaction in filteredTransactions) { if (transaction.Embedded.Item != null) { if (transaction.Embedded.Item.IsValid()) { BA_Body headLine = transaction.Embedded.Item.Embedded.TaManifest.Body.FirstOrDefault(b => b.BodyContentType == BodyContentType.Hl1); if (headLine != null) { lbAllBoughtItems.Items.Add(new ComboboxItem(GeneralUtils.StripHTML(headLine.content), transaction)); } } } else if (transaction.Embedded.PayItem != null) { } } if (validInput == false) { AttachFromToHandlers(false); List <DateTime> dateList = filteredTransactions.Select(t => t.CreatedAt).ToList(); dtpAllBoughtItemsFilterFrom.Value = dateList.Min(d => d); dtpAllBoughtItemsFilterTo.Value = dateList.Max(d => d); AttachFromToHandlers(true); } } } }
//based on: webpack:///./src/js/app/helpers/itemContent.js --> getImagePositions() //the one before needs to be a paragraph and the current item cannot be an image or streamer public static List <int> AvaliableImagePositions(this List <BA_Body> bodyPositions) { List <int> avaliableImagePositions = new List <int>(); for (var i = 1; i < bodyPositions.Count; i++) { BA_Body current = bodyPositions[i]; BA_Body oneBefore = bodyPositions[i - 1]; if (oneBefore.BodyContentType == BodyContentType.P && current.BodyContentType != BodyContentType.Image && current.BodyContentType != BodyContentType.Streamer) { avaliableImagePositions.Add(bodyPositions.IndexOf(current)); } } return(avaliableImagePositions); }
public Result CreatePdfFromItems(List <BlendleItem> items, string fullCoverImagePath, string fullOutputPath, int mainFontSize = 25) { Result result = new Result(); if (items != null && items.Any() == false) { result.Message = "Invalid month issues!"; result.Succeeded = false; return(result); } List <Tuple <string, int> > tocItems = new List <Tuple <string, int> >(); //Initialize PDF writer PdfWriter writer = new PdfWriter(fullOutputPath); //Initialize PDF document PdfDocument pdf = new PdfDocument(writer); // Initialize document Document document = new Document(pdf, defaultPageSize); document.SetMargins(60, 75, 60, 75); //ration: * 1.25 int locationToStartTOC = 1; //Add cover if (fullCoverImagePath.IsNullOrEmpty() == false && File.Exists(fullCoverImagePath)) { locationToStartTOC = 2; var documentWidth = defaultPageSize.GetWidth(); var documentHeight = defaultPageSize.GetHeight(); var leftMargin = document.GetLeftMargin(); var righttMargin = document.GetRightMargin(); var topMargin = document.GetTopMargin(); var bottomMargin = document.GetBottomMargin(); iText.Layout.Element.Image coverImage = new Image(ImageDataFactory.Create(fullCoverImagePath)); //coverImage.ScaleToFit(documentWidth - leftMargin - righttMargin, documentHeight - topMargin - bottomMargin); coverImage.ScaleToFit(documentWidth, documentHeight); coverImage.SetAutoScale(true); Paragraph coverParagraph = new Paragraph().SetMargins(0, 0, 0, 0).Add(coverImage); document.Add(coverParagraph); document.Add(new AreaBreak()); } //loop through each article foreach (BlendleItem item in items) { if (item.IsValid()) { int bodyCounter = 0; //the order of the bodies is always right var bodyItemList = item._embedded.content.body ?? new List <BA_Body>(); List <int> avaliableImagePositions = bodyItemList.AvaliableImagePositions(); List <CustomImageItem> imagesToPlace = new List <CustomImageItem>(); //these are the separated sub articles, whitin the main issue //the will be placed after the normal body var itemItemList = item._embedded.content._embedded?.items ?? new List <BA_Item>(); var bodyItemsToInsertAfter = new List <Tuple <BA_Body, BA_Body> >(); //if there are normal images, then they are the same as the media set images #region non mediaset images (the ones whitout index) if (item.HasNonMediaSetImages()) { var images = item._embedded.content.images; foreach (var iImage in images) { if (iImage != null && iImage.IsValid()) { var image = iImage.GetBestImage(); if (image.IsValid()) { string imageFullPath = image.GetFullPath(item.BaseLocationPath); if (File.Exists(imageFullPath)) { imagesToPlace.Add(new CustomImageItem() { href = image.href, path = imageFullPath, height = image.height, width = image.width, featured = iImage.featured, }); } } } } } #endregion non mediaset images (the ones whitout index) //if both streams exist, they contain the same images #region mediaset images else if (item.HasMediaSetImages()) { //reorder so we can insert it from the highest first, so the postitions will be right var mediaSets = item._embedded.content._embedded.mediasets.OrderByDescending(ms => ms.position); var first = mediaSets.First(); foreach (var imageContainer in mediaSets) { if (imageContainer != null && imageContainer.IsValid()) { var image = imageContainer._embedded.GetBestImage(); if (image.IsValid()) { string imageFullPath = image.GetFullPath(item.BaseLocationPath); if (File.Exists(imageFullPath)) { //position can be null, to hard to follow the exact placement in the blendle code //webpack:///./src/js/app/helpers/itemContent.js if (imageContainer.position == null) { //bodyItemList.Insert(random.Next(0, bodyItemList.Count-1), imageBodyItem); //insert after random item imagesToPlace.Add(new CustomImageItem() { href = image._links.file.href, path = imageFullPath, height = image.height, width = image.width, //can only be one featured featured = imagesToPlace.FirstOrDefault(i => i.featured) == null && first == imageContainer, }); } //if the placement is known, we can place it else if (imageContainer.position <= bodyItemList.Count) { var imageBodyItem = new BA_Body() { content = imageFullPath, type = BodyContentType.Image.ToString(), }; //insert after pre determined item bodyItemsToInsertAfter.Add(new Tuple <BA_Body, BA_Body>(bodyItemList[imageContainer.position.Value], imageBodyItem)); } } } } } } #endregion mediaset images #region calculates the position of the images //the issue leading image in the beginning var featuredImage = imagesToPlace.FirstOrDefault(i => i.featured); if (featuredImage != null) { int posToPlace = random.Next(0, bodyItemList.Count - 1); //featured images are the header image //logic how to place: webpack:///./src/js/app/helpers/itemContent.js --> getFeaturedImagePosition() //get first p and ph item, then get the smallest position var firstP = bodyItemList.FirstOrDefault(i => i.BodyContentType == BodyContentType.P); var firstPH = bodyItemList.FirstOrDefault(i => i.BodyContentType == BodyContentType.Ph); int firstPIndex = firstP != null?bodyItemList.IndexOf(firstP) : bodyItemList.Count - 1; int firstPHIndex = firstPH != null?bodyItemList.IndexOf(firstPH) : bodyItemList.Count - 1; int lowestNumber = GeneralUtils.Lowest(firstPIndex, firstPHIndex); //if they are both not there, use the random number if (lowestNumber != (bodyItemList.Count - 1)) { posToPlace = lowestNumber; //if the featured image takes a place in the avaliable positions, remove that one from that list if (avaliableImagePositions.Contains(posToPlace)) { avaliableImagePositions.Remove(posToPlace); } } bodyItemsToInsertAfter.Add(new Tuple <BA_Body, BA_Body>(bodyItemList[posToPlace], new BA_Body() { content = featuredImage.path, type = BodyContentType.Image.ToString(), })); } //not not featured images that are unpositioned List <CustomImageItem> unpositionedImages = imagesToPlace.Where(i => i.featured == false).ToList(); //get the loop information for the placement Tuple <int, int> loopInformation = GetLoopInformation(avaliableImagePositions.Count, unpositionedImages.Count()); for (var i = 0; i < unpositionedImages.Count; i++) { CustomImageItem customImageItem = unpositionedImages[i]; int spot = ((loopInformation.Item1 * i) + loopInformation.Item2); bodyItemsToInsertAfter.Add(new Tuple <BA_Body, BA_Body>(bodyItemList[avaliableImagePositions[spot]], new BA_Body() { content = customImageItem.path, type = BodyContentType.Image.ToString(), })); } #endregion calculates the position of the images #region streamers //insert streamers, the text parts in an article that are fat and add some exta if (item._embedded.content.streamers != null && item._embedded.content.streamers.Any()) { foreach (var streamer in item._embedded.content.streamers) { var streamerBodyItem = new BA_Body() { content = streamer.content, type = BodyContentType.Streamer.ToString(), }; if (streamer.position == null) { //insert after random item bodyItemsToInsertAfter.Add(new Tuple <BA_Body, BA_Body>(bodyItemList[random.Next(0, bodyItemList.Count - 1)], streamerBodyItem)); } else if (streamer.position <= bodyItemList.Count) { //insert after pre determined item bodyItemsToInsertAfter.Add(new Tuple <BA_Body, BA_Body>(bodyItemList[streamer.position.Value], streamerBodyItem)); } } } //now we can insert all the items after another from the last to the first, so the exact locations keep preserved foreach (var bodyItemToInsertAfter in bodyItemsToInsertAfter) { //insert them in the list at the valid order bodyItemList.Insert(bodyItemList.IndexOf(bodyItemToInsertAfter.Item1), bodyItemToInsertAfter.Item2); } //insert the body items in the pdf document if (bodyItemList.Any()) { ParseBodiesListResult parsedBodyListResult = ParseBodiesList(ref document, bodyItemList, mainFontSize, true); if (parsedBodyListResult.TOCItems != null && parsedBodyListResult.TOCItems.Any()) { tocItems.AddRange(parsedBodyListResult.TOCItems); } } #endregion streamers #region items (sub article parts) if (itemItemList.Any()) { //resets the body item list bodyItemList.Clear(); //after the body, an nested part of the article can be there foreach (var itemItem in itemItemList) { bodyItemList = itemItem.body; //the image needs to be on top of the sub article, after the title, normally 1 image //example: https://blendle.com/item/bnl-psychologie-20170914-09043b6a400 foreach (BA_Image2 itemItemImage in itemItem.images) { if (itemItemImage._links != null) { var image = itemItemImage._links.GetBestImage(); if (image.IsValid()) { string imageFullPath = image.GetFullPath(item.BaseLocationPath); if (File.Exists(imageFullPath)) { var imageBodyItem = new BA_Body() { content = imageFullPath, type = BodyContentType.Image.ToString(), }; bodyItemList.Insert(1, imageBodyItem); } } } } ParseBodiesListResult parsedBodyListResult = ParseBodiesList(ref document, bodyItemList, mainFontSize, false); if (parsedBodyListResult.TOCItems != null && parsedBodyListResult.TOCItems.Any()) { tocItems.AddRange(parsedBodyListResult.TOCItems); } } } #endregion items (sub article parts) } //new page document.Add(new AreaBreak()); } //adds the TOC AddTOC(ref pdf, tocItems, locationToStartTOC); //Close document document.Close(); result.Succeeded = true; return(result); }