Conditional classname and text (Rails) - css

I'm pretty new to Rails and trying some basic stuff like conditional classes.
On the 'show' view I have an element that changes styling depending on the stock availability, but also the text changes accordingly.
People keep saying the controller should be as small as possible, but placing this conditional in the view also feels dirty. Is this really the best way?
Current controller:
def show
#tyre = Tyres::Tyre.find_by_id(params[:id])
if #tyre.in_stock
#availability = I18n.t("products.filter.other.in_stock")
#availability_class = 'i-check-circle color--success'
else
#availability = I18n.t("products.filter.other.not_in_stock")
#availability_class = 'i-cross-circle color--important'
end
end
Edit:
Controller:
def show
#tyre = Tyres::Tyre.find_by_id(params[:id])
if #tyre.in_stock
#availability_append = ".in_stock"
else
#availability_append = ".not_in_stock"
end
#availability = I18n.t("products.filter.other#{#availability_append}")
end
View:
.xs-12.description__status
%i{class: (#tyre.in_stock? ? 'i-check-circle color--success' : 'i-cross-circle color--important')}
= #availability

You can clean your controller tyres_controller.rb (i suppose) method,
def show
#tyre = Tyre.find(params[:id]) # I believe you have a model named 'tyre'
end
Then, there will be a file named tyres_helper.rb in your myproject/app/helpers/. Put the following code there,
def tyre_availability(tyre) # it'll return an array with two values, first one is class name, second one is localized value
if tyre.in_stock
return 'i-check-circle color--success', I18n.t("products.filter.other.in_stock")
else
return 'i-cross-circle color--important', I18n.t("products.filter.other.not_in_stock")
end
end
and, in the view you can use,
.xs-12.description__status
%i{:class => tyre_availability(#tyre)[0]}
= tyre_availability(#tyre)[1]

Related

X++ assign Enum Value to a table column

I am trying to pull the Enum chosen from a dialog and assign the label to a table's column.
For example: Dialog opens and allows you to choose from:
Surface
OutOfSpec
Other
These are 0,1,2 respectively.
The user chooses OutOfSpec (the label for this is Out Of Spec), I want to put this enum's Name, or the label, into a table. The column I'm inserting into is set to be a str.
Here's the code I've tried, without success:
SysDictEnum dictEnum = new SysDictEnum(enumNum(SDILF_ScrapReasons));
reason = dialog.addField(enumStr(SDILF_ScrapReasons),"Scrap Reason");
dialog.run();
if (!dialog.closedOk())
{
info(reason.value());
return;
}
ttsBegin;
// For now, this will strip off the order ID from the summary fields.
// No longer removing the Order ID
batchAttr = PdsBatchAttributes::find(itemId, invDim.inventBatchId, "OrderId");
orders = SDILF_BreakdownOrders::find(batchAttr.PdsBatchAttribValue, true);
if (orders)
{
orders.BoxProduced -= 1;
orders.update();
}
// Adding a batch attribute that will include the reason for scrapping
select forUpdate batchAttr;
batchAttr.PdsBatchAttribId = "ScrapReason";
//batchAttr.PdsBatchAttribValue = any2str(dictEnum.index2Value(reason.value()));
batchAttr.PdsBatchAttribValue = enum2str(reason.value());
batchAttr.InventBatchId = invDim.inventBatchId;
batchAttr.ItemId = itemId;
batchAttr.insert();
Obviously this is not the whole code, but it should be enough to give the issue that I'm trying to solve.
I'm sure there is a way to get the int value and use that to assign the label, I've just not been able to figure it out yet.
EDIT
To add some more information about what I am trying to accomplish. We make our finished goods, sometimes they are out of spec or damaged when this happens we then have to scrap that finished good. When we do this we want to keep track of why it is being scrapped, but we don't want just a bunch of random reasons. I used an enum to limit the reasons. When the operator clicks the button to scrap something they will get a dialog screen pop-up that allows them to select a reason for scrapping. The code will then, eventually, put that assigned reason on that finished items batch attributes so that we can track it later in a report and have a list of all the finished goods that were scrapped and why they were scrapped.
I'm not entirely sure of your question, but I think you're just missing one of the index2[...] calls or you're not getting the return value from your dialog correctly. Just create the below as a new job, run it, make a selection of Open Order and click ok.
I don't know the difference between index2Label and index2Name.
static void Job67(Args _args)
{
Dialog dialog = new dialog();
SysDictEnum dictEnum = new SysDictEnum(enumNum(SalesStatus));
DialogField reason;
SalesStatus salesStatusUserSelection;
str label, name, symbol;
int value;
reason = dialog.addField(enumStr(SalesStatus), "SalesStatus");
dialog.run();
if (dialog.closedOk())
{
salesStatusUserSelection = reason.value();
// Label
label = dictEnum.index2Label(salesStatusUserSelection);
// Name
name = dictEnum.index2Name(salesStatusUserSelection);
// Symbol
symbol = dictEnum.index2Symbol(salesStatusUserSelection);
// Value
value = dictEnum.index2Value(salesStatusUserSelection);
info(strFmt("Label: %1; Name: %2; Symbol: %3; Value: %4", label, name, symbol, value));
}
}

Python dictionary not adding new keys

I have checked a few of the posts having the same issue and it tells me how to do it but it is not working.
My code:
class Product:
def __init__(self,price,prod_id,quantity):
self.price = price
self.prod_id = prod_id
self.quantity = quantity
self.shop_inventory = {}
self.amount = {}
class Inventory(Product):
def update_stock(self):
self.shop_inventory[self.prod_id] = self.quantity
self.amount[self.prod_id] = self.price
def return_stock_item(self):
look_up = input("What item would you like to check? ")
item = self.shop_inventory[look_up.lower()]
price = self.amount[look_up.lower()]
return f"{look_up.capitalize()}: There are {item} in stock and cost ${price} each."
def display_stock(self):
return self.amount.items()
To set the values Ive been using
stock = Inventory(2.34,'apple',5)
stock.update_stock()
It's part of a class and everything else in the class is working right. Just this one function is not working. I have tried this method as well as the update() method and neither are adding new key values. It is only over writing the same first spot. I have an item check in the class for all the dictionary items and it always only returns one [key][value] no matter how many times I change the key name.
Thank you for any help.

How to build a simple widget or app in jupyter notebook/lab to interactively extract a substring from text?

I want iterate over a list of string, output the string as plain text in jupyter lab then interactively highlight a substring to get easily the start index of the substring and the length. The goal is to do a quick annotation of text and get the coordinates of the substring.
Is it easy or even possible to do something like this with jupyter notebook (lab)? If then How?
I had a look at ipywidgets but couldn't find something for this use case.
Here's an example with the RangeSlider:
import ipywidgets
input_string = 'averylongstring'
widg = ipywidgets.IntRangeSlider(
value = [0, len(input_string)],
min=0, max=len(input_string)
)
output_widg = ipywidgets.Text()
display(widg)
display(output_widg)
def chomp_string(widg):
start,end = tuple(widg['new'])
output_widg.value = input_string[start: end]
widg.observe(chomp_string, names='value')
You can implement this using jp_proxy_widgets. See the following screenshot:
Note that there are warnings about compatibility for selection protocols -- I only tested this on Chrome on a Mac. Also I don't know why the indices are off by one
(select_callback(startOffset+1, endOffset+1);)
Please see https://github.com/AaronWatters/jp_proxy_widget for more information
Edit: Here is the pastable text as requested:
import jp_proxy_widget
select_widget = jp_proxy_widget.JSProxyWidget()
txt = """
Never gonna give you up.
Never gonna let you down.
Never gonna run around and
desert you.
"""
selected_text = None
def select_callback(startOffset, endOffset):
global selected_text
selected_text = txt[startOffset: endOffset]
print ("Selected", startOffset, endOffset, repr(selected_text))
select_widget.js_init("""
// (Javascript) Add a text area.
element.empty()
$("<h3>please select text:</h3>").appendTo(element);
var textarea = $('<textarea cols="50" rows="5">' + txt + "</textarea>").appendTo(element);
// Attach a select handler that calls back to select_callback.
var select_handler = function(event) {;
var target = event.target;
var startOffset = target.selectionStart;
var endOffset = target.selectionEnd;
select_callback(startOffset+1, endOffset+1);
};
textarea[0].addEventListener('select', select_handler);
""", txt=txt, select_callback=select_callback)
# display the widget
select_widget.debugging_display()

D365 New Button creates price line with empty line

After adding logic about creating price for object in grid it's always created "one line more" which is empty.
So, if there is need to be created two lines, it will be created 3 lines and that one addition will be empty.
Is there something what I missing in code?
[Control("CommandButton")]
class AreaActionPaneNew
{
void clicked()
{
PMCParameters contractParameters = PMCParameters::find();
PMETmpRentalObjectArea groupedAreaList; // Group by area_type and cost_type
PMERentalObjectPrice priceList;
date workingDate = currWorkingDate.dateValue();
;
super();
// Get grouped area values. Values are summed up by area_type and ancost_type
groupedAreaList = PMERentalObjectAreaCl::getRentalAreaPrCostType(pmeRentalobject.RentalObjectId, userSetting.validFrom(), userSetting.validTo() , workingDate);
ttsbegin;
while select groupedAreaList
{
select forupdate firstonly priceList
where priceList.RentalObjectId == pmeRentalObject.RentalObjectId &&
priceList.RentalCostType == groupedAreaList.RentalCostTypeId &&
priceList.AreaType == groupedAreaList.Areatype && priceList.ValidFrom == pmeRentalObject.ValidFrom;
if (!priceList)
priceList.initValue();
priceList.RentalObjectId = pmeRentalObject.RentalObjectId;
priceList.RentalCostType = groupedAreaList.RentalCostTypeId;
priceList.ValidFrom = pmeRentalobject.ValidFrom;
priceList.AreaType = groupedAreaList.Areatype;
priceList.Amount = groupedAreaList.Price;
priceList.Area = groupedAreaList.AreaValue;
priceList.Quantity = groupedAreaList.RentalQty;
if (!priceList)
priceList.Period = contractParameters.ReportPeriod;
if (priceList)
priceList.update();
else
priceList.insert();
}
ttscommit;
pmeRentalObjectPrice_ds.research();
}
}
The code looks like it only updates/inserts without creating a blank line.
From your attribute, you are using a Command Button (see here), which may have an associated command, such as New, which effectively pushes Ctrl+N, and would explain why you have a blank line.
The simplest way to check is just create a regular Button and override the clicked method, then copy/paste your code and push both buttons and see if they have different behavior.
Check the Command property on the button and see if there's something there. Try commenting out the super(); call.
You should perhaps consider just a Button or a Menu Item Button with an associated object.

Django CMS - Copy relations in custom plugin not working

I have a problem with copy_relations after publishing a page.
I have a plugin with additional model. This model has ForeignKey to my plugin.
class InfContactForm(CMSPlugin):
name = models.CharField(max_length=50)
def copy_relations(self, oldinstance):
self.inf_contact_form.all().delete()
for inf_contact_form in oldinstance.inf_contact_form.all():
inf_contact_form.pk = None
inf_contact_form.plugin = self
inf_contact_form.save()
class InfContactFormAgreement(models.Model):
inf_contact_form = models.ForeignKey(InfContactForm, related_name="inf_contact_form")
agreement = HTMLField(blank=True, null=True)
The "InfContactFormAgreement" model is then used as stacked inline in "InfContactForm" plugin form.
Like it is written in docs, there is also copy_relations() method but when the page is published, nothing happens. When I get back again to edit mode InfContactFormAgreement is doubled every time I do it.
Here is also my cms_plugins.py file:
class PluginInfContactForm(CMSPluginBase):
render_template = '_contact_form.html'
name = name1
model = InfContactForm
require_parent = False
inlines = [AgreementStackedInline, ]
def render(self, context, instance, placeholder):
context['instance'] = instance
context = super(PluginInfContactForm, self).render(context, instance, placeholder)
agreements = instance.inf_contact_form.all()
context.update({
'agreements': agreements,
})
return context
plugin_pool.register_plugin(PluginInfContactForm)
Thank you for any advice.
instead of:
inf_contact_form.plugin = self
you should use:
inf_contact_form.inf_contact_form = self
and the resulting code should look like this:
def copy_relations(self, oldinstance):
self.inf_contact_form.all().delete()
for inf_contact_form in oldinstance.inf_contact_form.all():
inf_contact_form.pk = None
inf_contact_form.inf_contact_form = self
inf_contact_form.save()
regards
I had a similar situation, the only difference being that my many-to-many relationship was not in a plugin, but an extension (PageExtension).
In my case, #Dariusz solution did not work, and I had to update the implicit "inbetween" model that exists between the Extension model and the Associated model.
My solution (the key being the "through"):
class Extension(PageExtension):
tags_regions = models.ManyToManyField(Region, related_name="articles", blank=True)
def copy_relations(self, oldinstance):
for region_tag in oldinstance.tags_regions.through.objects.filter(extension=oldinstance):
region_tag.extension = self
region_tag.save()

Resources