Merge branch 'master' of github.com:Microsoft/TouchDevelop

This commit is contained in:
Jonathan Protzenko 2015-04-01 15:33:20 -07:00
Родитель 924cc93a00 6a4f3e31d5
Коммит 3b69672c11
4 изменённых файлов: 244 добавлений и 19 удалений

Просмотреть файл

@ -2165,6 +2165,7 @@ module TDev.AST {
public htmlColor()
{
if (Cloud.isRestricted()) return "#85BB65"
if (!this.color) return ScriptIcons.stableColorFromName(this.getName());
else return "#" + this.color.replace("#", "").slice(-6);
}

Просмотреть файл

@ -225,6 +225,13 @@ module TDev {
resolved?: string;
}
export interface JsonAbuseReport extends JsonPubOnPub
{
text:string; // report text
resolution:string;
publicationuserid:string;
}
export interface JsonReview extends JsonPubOnPub
{
ispositive: boolean;
@ -306,6 +313,16 @@ module TDev {
sources: JsonVideoSource[];
}
export interface CanDeleteResponse {
publicationkind: string;
publicationname: string;
publicationuserid: string;
candelete:boolean;
candeletekind:boolean;
canmanage:boolean;
hasabusereports:boolean;
}
export class MdComments
{
public userid:string;

Просмотреть файл

@ -1214,7 +1214,8 @@ module TDev { export module Browser {
else if (e.kind == "art") return this.getArtInfoById(e.id);
else if (e.kind == "group") return this.getGroupInfoById(e.id);
else if (e.kind == "document") return this.getDocumentInfo(e);
else if (e.kind == "release") return this.getReleaseInfoById(e.id);
else if (e.kind == "release") return this.getSpecificInfoById(e.id, ReleaseInfo)
else if (e.kind == "abusereport") return this.getSpecificInfoById(e.id, AbuseReportInfo)
else return null;
}
@ -1649,6 +1650,17 @@ module TDev { export module Browser {
return si;
}
public getArtInfoById(id:string)
{
var si = <ArtInfo>this.getLocation(id);
if (!si) {
si = new ArtInfo(this);
si.loadFromWeb(id);
this.saveLocation(si);
}
return si;
}
public getScriptInfoById(id:string)
{
var si = <ScriptInfo>this.getLocation(id);
@ -1736,23 +1748,12 @@ module TDev { export module Browser {
return si;
}
public getReleaseInfoById(id:string)
public getSpecificInfoById(id:string, cl:any)
{
var si = <ReleaseInfo>this.getLocation(id);
var si = this.getLocation(id);
if (!si) {
si = new ReleaseInfo(this);
si.loadFromWeb(id);
this.saveLocation(si);
}
return si;
}
public getArtInfoById(id:string)
{
var si = <ArtInfo>this.getLocation(id);
if (!si) {
si = new ArtInfo(this);
si.loadFromWeb(id);
si = new cl(this);
(<any>si).loadFromWeb(id);
this.saveLocation(si);
}
return si;
@ -2733,6 +2734,12 @@ module TDev { export module Browser {
{
if (!big || !this.getPublicationId()) return null;
if (Cloud.lite) {
return div("sdReportAbuse", HTML.mkImg("svg:SmilieSad,#000,clip=100"), lf("report/delete")).withClick(() => {
AbuseReportInfo.abuseOrDelete(this.getPublicationId())
});
}
return div("sdReportAbuse", HTML.mkImg("svg:SmilieSad,#000,clip=100"), lf("report abuse")).withClick(() => {
window.open(Cloud.getServiceUrl() + "/user/report/" + this.getPublicationId())
});
@ -4253,6 +4260,26 @@ module TDev { export module Browser {
}
}
export class AbuseReportsTab
extends ListTab
{
constructor(par:BrowserPage) {
super(par, "/abusereports")
this.isEmpty = true;
}
public getId() { return "abusereports"; }
public getName() { return lf("abuse reports"); }
public bgIcon() { return "svg:fa-flag"; }
public noneText() { return lf("no abuse reports!"); }
public hideOnEmpty() { return true }
public tabBox(cc:JsonIdObject):HTMLElement
{
return AbuseReportInfo.box(<JsonAbuseReport>cc)
}
}
export class ScriptHeartsTab
extends ListTab
{
@ -4405,6 +4432,10 @@ module TDev { export module Browser {
case "leaderboardscore": // this one should not happen anymore
return div(null, lab(lf("scored {0}", (<any>c).score), this.browser().getCreatorInfo(c).mkSmallBox()),
lab(lf("in"), this.browser().getReferencedPubInfo(<JsonPubOnPub>c).mkSmallBox()));
case "abusereport":
return div(null, lab(lf("abuse report")),
lab(lf("on"), this.browser().getReferencedPubInfo(<JsonPubOnPub>c).mkSmallBox()));
// missing: tag, crash buckets
default:
debugger;
@ -4649,6 +4680,7 @@ module TDev { export module Browser {
// new CommentsTab(this),
, new ScriptsTab(this, lf("no scripts using this art"))
// new SubscribersTab(this)
, new AbuseReportsTab(this)
];
}
@ -5375,7 +5407,7 @@ module TDev { export module Browser {
if (big && !isTopic) facebook.setChildren(this.facebookLike())
if (abuseDiv && this.publicId && this.jsonScript.userid == Cloud.getUserId()) {
if (!Cloud.isRestricted() && abuseDiv && this.publicId && this.jsonScript.userid == Cloud.getUserId()) {
updateHideButton();
}
@ -5507,6 +5539,7 @@ module TDev { export module Browser {
new ScriptHeartsTab(this),
new TagsTab(this),
new InsightsTab(this),
new AbuseReportsTab(this),
];
return r;
}
@ -5595,6 +5628,8 @@ module TDev { export module Browser {
});
}
if (Cloud.isRestricted()) return
// group mode?
if(!st.collabSessionId) {
uninstall.appendChild(HTML.mkButton(lf("edit with group"), () => {
@ -7206,7 +7241,12 @@ module TDev { export module Browser {
return d.mkBox().withClick(() => {
m.dismiss()
Cloud.postPrivateApiAsync(c.id + "/resetpassword", { password: p })
.then(() => ModalDialog.info(lf("password is reset"), p))
.then(() => {
var m = ModalDialog.info(lf("password is reset"), lf("new password:"))
var inp = HTML.mkTextInput("text", "")
inp.value = p
m.add(div(null, inp))
})
.done()
})
})
@ -7632,6 +7672,172 @@ module TDev { export module Browser {
}
}
export class AbuseReportInfo
extends BrowserPage
{
constructor(par:Host) {
super(par)
}
public persistentId() { return "abusereport:" + this.publicId; }
//public getTitle() { return "report " + this.publicId; }
public getId() { return "abusereport"; }
public getName() { return lf("abuse report"); }
public loadFromWeb(id:string)
{
this.publicId = id;
}
public mkBoxCore(big:boolean)
{
var icon = div("sdIcon");
icon.style.background = "#aaa";
var textBlock = div("sdCommentBlockInner");
var author = div("sdCommentAuthor");
var hd = div("sdCommentBlock", textBlock, author);
var addInfoInner = div("sdAddInfoInner", "/" + this.publicId);
var pubId = div("sdAddInfoOuter", addInfoInner);
var res = div("sdHeaderOuter", div("sdHeader", icon, div("sdHeaderInner", hd, pubId)));
if (big)
res.className += " sdBigHeader";
return this.withUpdate(res, (u:JsonAbuseReport) => {
if (u.resolution == "ignored") {
icon.setChildren(HTML.mkImg("svg:fa-check-square-o,white"))
icon.style.background = "#308919";
} else if (u.resolution == "deleted") {
icon.setChildren(HTML.mkImg("svg:fa-trash,white"))
icon.style.background = "#308919";
} else {
icon.setChildren(HTML.mkImg("svg:fa-flag,white"))
icon.style.background = "#e72a2a";
}
textBlock.setChildren([ u.text ]);
author.setChildren(["-- ", u.username]);
addInfoInner.setChildren([Util.timeSince(u.time) + " on " + u.publicationname]);
});
}
static box(c:JsonAbuseReport)
{
var b = TheHost;
var uid = b.getCreatorInfo(c);
var textDiv = div('sdSmallerTextBox', c.text);
var r = div("sdCmt sdCmtTop " + (c.resolution == "ignored" ? "disabledItem" : ""), uid.thumbnail(),
div("sdCmtTopic",
span("sdBold", c.username),
c.resolution ? div("sdCmtResolved", c.resolution) : null
//" on ", div("sdCmtScriptName", c.publicationname).withClick(() => b.loadDetails(b.getReferencedPubInfo(c)))
),
textDiv,
div("sdCmtMeta", [
Util.timeSince(c.time),
span("sdCmtId", " :: /" + c.id),
//div("sdCmtBtns", delBtn),
]));
r.withClick(() => {
})
return r;
}
public mkSmallBox():HTMLElement
{
return this.mkBoxCore(false).withClick(() =>
TheApiCacheMgr.getAsync(this.publicId, true).done(resp => AbuseReportInfo.abuseOrDelete(resp.publicationid, this.publicId)));
}
public initTab()
{
this.withUpdate(this.tabContent, (c:JsonAbuseReport) => {
this.tabContent.setChildren([
ScriptInfo.labeledBox(lf("report on"), this.browser().getReferencedPubInfo(c).mkSmallBox()),
AbuseReportInfo.box(c) ]);
});
}
public mkBigBox():HTMLElement { return null; }
public mkTabsCore():BrowserTab[] { return [this]; }
static abuseOrDelete(pubid:string, abuseid:string = "")
{
Cloud.getPrivateApiAsync(pubid + "/candelete")
.then((resp:CanDeleteResponse) => {
var b = TheHost
var godelete = () => {
ModalDialog.ask(lf("Are you sure you want to delete '{0}'? No undo.", resp.publicationname),
lf("delete"),
() => {
Cloud.deletePrivateApiAsync(pubid)
.then(() => HTML.showProgressNotification(lf("gone.")))
.done()
// TODO show it's gone in the UI
})
}
var viewreports = () => {
m.dismiss()
var inf = b.getAnyInfoByEtag({ id: pubid, kind: resp.publicationkind, ETag: "" });
b.loadDetails(inf, "abusereports")
}
var goignore = () => {
m.dismiss()
Cloud.postPrivateApiAsync(abuseid, { resolution: "ignored" })
.then(() => HTML.showProgressNotification(lf("ignored.")))
.done()
}
if (!abuseid && resp.publicationuserid == Cloud.getUserId()) {
godelete()
} else {
var m = new ModalDialog()
var inp = HTML.mkTextInput("text", lf("Reason (eg., bad language, bullying, etc)"))
var err = div(null)
if (abuseid) {
m.add([
div("wall-dialog-header", lf("resolve report about '{0}'", resp.publicationname)),
])
} else {
m.add([
div("wall-dialog-header", lf("report abuse about '{0}'", resp.publicationname)),
div("", inp),
err,
div("wall-dialog-body", resp.hasabusereports ? lf("There are already abuse report(s).") :
lf("No abuse reports so far.")),
])
}
m.add(
div("wall-dialog-buttons", [
HTML.mkButton(lf("cancel"), () => m.dismiss()),
resp.hasabusereports && HTML.mkButton(lf("view reports"), viewreports),
!abuseid && HTML.mkButton(lf("report"), () => {
if (inp.value.trim().length < 5)
err.setChildren(lf("Need some reason."))
else {
m.dismiss()
Cloud.postPrivateApiAsync(pubid + "/abusereports", { text: inp.value })
.then(() => HTML.showProgressNotification(lf("reported.")))
.done()
}
}),
abuseid && resp.canmanage && HTML.mkButton(lf("ignore report"), goignore),
resp.candelete && HTML.mkButton(lf("delete publication"), godelete),
]))
m.show()
}
})
.done()
}
}
export class CommentInfo
extends BrowserPage
{
@ -7727,7 +7933,7 @@ module TDev { export module Browser {
private _comments:CommentsTab;
public mkTabsCore():BrowserTab[] { return [this]; }
public mkTabsCore():BrowserTab[] { return [this, new AbuseReportsTab(this)]; }
public bugCompareTo(other:CommentInfo, order:string) {
var j0:JsonComment = TheApiCacheMgr.getCached(this.publicId)

Просмотреть файл

@ -167,6 +167,7 @@ export module SVG {
"bell": "M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5 t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z",
"wrench": "M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z",
"fast-backward": "M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z",
"flag": "M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z",
};
export function svgBoilerPlate(viewPort:string, svg:string, iconName = "")