SwiftUI: How to dynamically adjust ForEach elements? - core-data

I have a List() containing rows of expenses (from CoreData). Like this:
ForEach(expenses) { expense in
ExpenseRow(e:expense, cv: self)
}
Here’s the struct ExpenseRow:
struct ExpenseRow: View {
var e: ExpenseEntry
var cv: ContentView
var body: some View {
NavigationLink {
NewExpenseCard(existingExpense:e)
} label: {
HStack{
Text(e.amount.description.abs() ?? " ")
.foregroundColor(e.amount < 0 ? .green : Color(UIColor.label))
Text(e.note ?? "")
.font(.system(size: 14))
.lineLimit(1)
Spacer()
Text(shortDateString(date: e.timestamp!))
.padding(.all, 5)
.font(.body)
.opacity(0.5)
.cornerRadius(5)
}
}
}
}
So each row is an HStack of amount - note - date.
The date portion of the list now looks like this:
Jan 1
Jan 1
Jan 2
Instead, I’d like a date only to be shown if it hasn’t been displayed previously, to avoid duplicate dates being shown. Like this:
Jan 1
Jan 2
But I can’t find any way of doing this. I tried a state variable to track the last displayed date (Jan 1) and then only display the next one if it differs from this, but that leads to an infinite loop where Swift keeps going through the rows forever trying to update them.
How can I do this properly?

Related

Populate Suitelet Sublist from a Saved Search with Formulas in the Search

#bknights posted an good answer to another question around populating a sublist in a suitelet.
However, my question follows on from that when using bk's code:
function getJoinedName(col) {
var join = col.getJoin();
return join ? col.getName() + '__' + join : col.getName();
}
searchResults[0].getAllColumns().forEach(function(col) {
sublist.addField(getJoinedName(col), 'text', col.getLabel());
nlapiLogExecution('DEBUG', 'Column Label', col.getLabel());
});
var resolvedJoins = searchResults.map(function(sr) {
var ret = {
id: sr.getId()
};
sr.getAllColumns().forEach(function(col) {
ret[getJoinedName(col)] = sr.getText(col) || sr.getValue(col);
});
return ret;
});
sublist.setLineItemValues(resolvedJoins);
The above works with a standard search with no formulae... How can we do this when I have multiple search columns which are formulae?
Using API1.0
In your search definition add a label to all formula columns. Then your column keys can be derived like:
function getJoinedName(col) {
if(col.getName().indexOf('formula') === 0 && col.getLabel()){
return 'lbl_'+ col.getLabel().toLowerCase();
}
var join = col.getJoin();
return join ? col.getName() + '__' + join : col.getName();
}
You can just get all the columns of the search result. columns = result[0].getColumns(). The reference the column where the formula column is. So if you look in the UI and it is the third from the top, you can get the value using result[0].getValue(columns[2])
This solution is dependent on the order of rows not changing.
Also if your saved search has labels for the Formulas, you can just use the labels as the field id.

Which method ideal to query Cloudant for latest doc having same value for a field and again filter on that result?

I am very new to NoSQL. My usecase is related to this.... Many users post messages and we store it in cloudant as different documents
{
id:random,
userid:xxx,
timestamp: 1449216912282,
msg: "Hi..."
}
I want to find out users who have not posted anything for last 5 days - Additionally I want to know if they have posted anything between last five and 10 days. If they have, then send a reminder mail to user to be active.
Which option would be better - views, search, cloudant query? Assume we will be having 1000s of posts per hour
I though of creating view - map(userid,timestamp) reduce as _stats and get max timestamp of each user. Then iterating through this list - we get users who did not post in last 5 days.
Other option was to use search index, get all userids between required timestamps. Compare both lists in application.
Is there any way to do it in a single query without overloading the application? Would Changing data format or creating appropriate index or view help?
If your data looked like this:
{
"_id": "abcdefghijklmon1234",
"userid" : "user1",
"timestamp": 1449739485035,
"msg": "Hi"
}
You could create a MapReduce view that created an index with a key consisting of [ 2015, 50, "user1" ], where "2015" is the year, "50" is the week number and "user1" is the document's userid. This can be achieved with a Map function like this:
function (doc) {
var getWeek = function(t) {
var date = new Date(t);
date.setHours(0, 0, 0, 0);
date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
var week1 = new Date(date.getFullYear(), 0, 4);
return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
};
if (typeof doc.timestamp == "number") {
var d = new Date(doc.timestamp);
var weeknum = getWeek(d.getTime());
var year = d.getFullYear();
emit( [ year, weeknum, doc.userid], null);
}
}
with a reduce of "_count". This allows queries such as ?startkey=[2015,49]&endkey=[2015,50]&group_level=3 to get a list of users who DID post last week. The list of users who didn't are the users who don't appear in the above list.
This isn't a solution to your problem in terms of "in the last 5 days", but uses week numbers instead.

Google Visualization - StringFilter - Searching w. OR

I have stringfilters bind to my table of data.
What i would like to get from the stringfilter is to be able to search like you would do with queries.
There is a colomn with names - a name for each row - for example - "Steve","Monica","Andreas","Michael","Steve","Andreas",...
I want to have both rows with Monica and Steve from the StringFilter.
I would like to be able to search like this
Steve+Monica
or
"Steve"+"Monica"
or
"Steve","Monica"
This is one of my stringfilters:
var stringFilter1 = new google.visualization.ControlWrapper({
controlType: 'StringFilter',
containerId: 'string_filter_div_1',
options: {
filterColumnIndex: 0, matchType : 'any'
}
});
I had a similar problem, and I ended up creating my own function for filtering my rows. I made an example with the function that you describe, but I'm not sure it's the best or the right way, but it works.
One flaw is that you need to type in the names exactly as they are entered, the whole name and with capital letters.
Fiddle, try to add multiple names separated with a "+" (and no spaces).
The function I added looks like this:
function redrawChart(filterString) {
var filterWords = filterString.split("+")
var rows = []
for(i = 0; i < filterWords.length; i++) {
rows = rows.concat(data.getFilteredRows([{value:filterWords[i], column:0}]))
}
return rows
}
And the listener that listens for updates in your string input looks like:
google.visualization.events.addListener(control, 'statechange', function () {
if (control.getState().value == '') {
realChart.setView({'rows': null})
}else{
realChart.setView({'rows': redrawChart(control.getState().value)})
}
realChart.draw();
});
Probably not a complete solution, but maybe some new ideas and directions to your own thoughts.

SharePoint 2010 - Need suggestion

I have one datasheet like mentioned below
WorkWeek Person1 Person2
WW1 X Y
WW2 Z A
WW3 X Z
Where A,X,Y & Z are members of the sharepoint group.
Required I want display a webpart like this
WW1
Image1 Image2
X Y
Next Week the webpart should get updated like this dynamically.
WW2
Image3 Image4
Z A
Where this requirement is possible, If possible then pls suggest how to accomplish this.
I can provide you some Logic which may help you to accomplish this requirement.
Create one Visual web part with the user control which has html as per your requirement,
To get the data from the datasheet use the Code to read the data from Data sheet
When you want to display the data for the First week create one varible and maintain it to identify the sequence of week to get from datasheet.
First time When you access the datasheet set this varibale with your week of year number.
Condition the reading of datasheet with this variable like IF variable is null then assign it the week no of year.,
Check this variable next time you come to this logic that If variable is less than the week no current week no of year then take datasheet last you get + 1 means Datasheet 2 and so on
..
Sorry for bad english
variable : one for DaasheetNo, WeekNo,CurrentWeekNo
assign datasheetNo = Sheet1
If(WeekNo== Null)
{
first time getdata from DaasheetNo (First Sheet)
}
else if(WeekNo < CurrentWeekNo)
{
Get data from datasheetNo +1
}
Hope it helps you
This is called weekly update Webpart in SharePoint.
My Idea:
you can set one CurrentDate value like DateTime.Today to Current Web properties.also set one more properties which WorkWeek users. now check
SPWeb web = SPContext.Current.Web;
if (string.isnullorEmpty(web.Properties["CurrentDate"]))
{
web.Properties["CurrentDate"] = DateTime.Today.Tostring();
// do the stuff for displying data.
}
else
{
if(IFChangeNeeded())
{
// do the stuff for displying data.
}
else
{
web.Properties["CurrentDate"] = DateTime.Today.Tostring();
// do the stuff for displying data.
}
}
IfChangeNeeded() is function which return bool value. this function check that employee need to change on this week.
public bool IFChangeNeeded()
{
DateTime PropDate = Convert.ToDateTime(web.Properties["CurrentDate"]);
DateTime TDate = DateTime.Today;
if(WeekNo(TDate) == WeekNo(PropDate)) // WeekNo is function return weekno from current date.
{
return true;
}
else
{
return false;
}
}

get the values larger than zero only

I'm using C# and I get data from database like this:
da.SelectCommand = new SqlCommand("SELECT name,company,startdate,enddate,DATEDIFF(day,GETDATE(),enddate) AS days FROM Person", cn);
ds.Clear();
da.Fill(ds);
dgvViolation.DataSource = ds.Tables[0];
and the data will dispaly in datagridview like this :
name company startdate enddate days
---------------------------------------
john IBM 12/2/2012 20/2/2012 5
steven IBM 1/2/2012 12/2/2012 -3
I need the datagridview to display the positive values that appear in the days columns only. How do I do this?
Change the query to
"SELECT name,company,startdate,enddate,DATEDIFF(day,GETDATE(),enddate) AS days FROM Person WHERE days > 0"
Why don't you just change your SQL command to return the values above 0?
But if you want to do it with all the data returned, you can use the RowDataBound event of the gridview, something like this:
protected void gridview_RowDataBound(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
if (e.Row.RowType == System.Web.UI.WebControls.DataControlRowType.DataRow)
{
//look at the value of the days column and use e.Row.Style["Display"] = "none"; to hide it.
}
}

Resources