Merge branch 'master' of github.com:Microsoft/TouchDevelop
This commit is contained in:
Коммит
3b69672c11
|
@ -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);
|
||||
}
|
||||
|
|
17
ast/help.ts
17
ast/help.ts
|
@ -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 = "")
|
||||
|
|
Загрузка…
Ссылка в новой задаче